Feature updates
-- added option to save an update from intern -- added UI to see assigned tasks in intern profile
This commit is contained in:
parent
4ddeb8ce73
commit
c196d31d1b
48
css/main.css
48
css/main.css
@ -1152,6 +1152,7 @@ ul {
|
||||
user-select: none;
|
||||
padding: 0.8rem 1rem;
|
||||
gap: 0.8rem;
|
||||
color: inherit;
|
||||
}
|
||||
.intern-card input {
|
||||
height: 1.3em;
|
||||
@ -1284,7 +1285,7 @@ ul {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
#intern_info__initials {
|
||||
#intern_profile__initials {
|
||||
position: relative;
|
||||
height: 4rem;
|
||||
width: 4rem;
|
||||
@ -1292,12 +1293,12 @@ ul {
|
||||
color: var(--color);
|
||||
}
|
||||
|
||||
#intern_info__name {
|
||||
#intern_profile__name {
|
||||
font-size: 1.5rem;
|
||||
padding: 0.4rem 0.5rem;
|
||||
border-radius: 0.5rem;
|
||||
}
|
||||
#intern_info__name[contenteditable=true] {
|
||||
#intern_profile__name[contenteditable=true] {
|
||||
background-color: rgba(var(--text-color), 0.1);
|
||||
}
|
||||
|
||||
@ -1379,33 +1380,39 @@ ul {
|
||||
color: var(--nice-blue);
|
||||
}
|
||||
|
||||
#intern_info__wrapper {
|
||||
#intern_profile {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 1rem;
|
||||
gap: 1.5rem;
|
||||
}
|
||||
#intern_info__wrapper > * {
|
||||
#intern_profile__left {
|
||||
width: min(26rem, 100%);
|
||||
border-radius: 0.5rem;
|
||||
background-color: rgba(var(--foreground-color), 1);
|
||||
padding: 1rem;
|
||||
}
|
||||
#intern_profile__right {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.intern_info__task {
|
||||
.intern_profile__task {
|
||||
display: grid;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
gap: 0.3rem;
|
||||
margin-top: 1rem;
|
||||
padding: 0.5rem;
|
||||
padding: 1rem;
|
||||
border-radius: 0.5rem;
|
||||
background-color: rgba(var(--text-color), 0.06);
|
||||
background-color: rgba(var(--foreground-color), 1);
|
||||
grid-template-columns: minmax(0, 1fr) auto;
|
||||
}
|
||||
.intern_info__task h4 {
|
||||
.intern_profile__task h4 {
|
||||
grid-column: 1/-1;
|
||||
}
|
||||
.intern_info__task p {
|
||||
.intern_profile__task p {
|
||||
font-weight: 500;
|
||||
}
|
||||
.intern_info__task time {
|
||||
.intern_profile__task time {
|
||||
font-size: 0.9rem;
|
||||
color: rgba(var(--text-color), 0.8);
|
||||
}
|
||||
@ -1853,16 +1860,6 @@ ul {
|
||||
margin-top: 0.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);
|
||||
@ -2223,6 +2220,13 @@ input[type=date]:focus {
|
||||
width: min(48rem, 100%);
|
||||
margin: 0 auto;
|
||||
}
|
||||
#intern_profile__left {
|
||||
position: -webkit-sticky;
|
||||
position: sticky;
|
||||
top: 1rem;
|
||||
align-self: flex-start;
|
||||
padding: 1.5rem;
|
||||
}
|
||||
}
|
||||
@media only screen and (min-width: 1280px) {
|
||||
#main_page {
|
||||
|
||||
2
css/main.min.css
vendored
2
css/main.min.css
vendored
File diff suppressed because one or more lines are too long
@ -1129,6 +1129,7 @@ ul {
|
||||
user-select: none;
|
||||
padding: 0.8rem 1rem;
|
||||
gap: 0.8rem;
|
||||
color: inherit;
|
||||
input {
|
||||
height: 1.3em;
|
||||
width: 1.3em;
|
||||
@ -1256,14 +1257,14 @@ ul {
|
||||
.container-header h4 {
|
||||
flex: 1;
|
||||
}
|
||||
#intern_info__initials {
|
||||
#intern_profile__initials {
|
||||
position: relative;
|
||||
height: 4rem;
|
||||
width: 4rem;
|
||||
font-size: 1.3rem;
|
||||
color: var(--color);
|
||||
}
|
||||
#intern_info__name {
|
||||
#intern_profile__name {
|
||||
font-size: 1.5rem;
|
||||
padding: 0.4rem 0.5rem;
|
||||
border-radius: 0.5rem;
|
||||
@ -1348,23 +1349,29 @@ ul {
|
||||
color: var(--nice-blue);
|
||||
}
|
||||
}
|
||||
#intern_info__wrapper {
|
||||
#intern_profile {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 1rem;
|
||||
& > * {
|
||||
gap: 1.5rem;
|
||||
&__left {
|
||||
width: min(26rem, 100%);
|
||||
border-radius: 0.5rem;
|
||||
background-color: rgba(var(--foreground-color), 1);
|
||||
padding: 1rem;
|
||||
}
|
||||
&__right {
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
.intern_info__task {
|
||||
.intern_profile__task {
|
||||
display: grid;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
gap: 0.3rem;
|
||||
margin-top: 1rem;
|
||||
padding: 0.5rem;
|
||||
padding: 1rem;
|
||||
border-radius: 0.5rem;
|
||||
background-color: rgba(var(--text-color), 0.06);
|
||||
background-color: rgba(var(--foreground-color), 1);
|
||||
grid-template-columns: minmax(0, 1fr) auto;
|
||||
h4 {
|
||||
grid-column: 1/-1;
|
||||
@ -1794,15 +1801,6 @@ ul {
|
||||
}
|
||||
}
|
||||
|
||||
.send-update-button,
|
||||
.init-update-replay {
|
||||
color: var(--accent-color);
|
||||
background-color: rgba(var(--text-color), 0.04);
|
||||
.icon {
|
||||
fill: var(--accent-color);
|
||||
}
|
||||
}
|
||||
|
||||
.temp-task {
|
||||
padding: 1rem;
|
||||
background-color: rgba(var(--foreground-color), 1);
|
||||
@ -2174,6 +2172,14 @@ input[type="date"] {
|
||||
margin: 0 auto;
|
||||
}
|
||||
}
|
||||
#intern_profile {
|
||||
&__left {
|
||||
position: sticky;
|
||||
top: 1rem;
|
||||
align-self: flex-start;
|
||||
padding: 1.5rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (min-width: 1280px) {
|
||||
|
||||
265
index.html
265
index.html
@ -517,6 +517,7 @@
|
||||
<ul id="task_requests_list" class="grid gap-0-5 observe-empty-state margin-top-1"></ul>
|
||||
<h4 class="empty-state">No task requests</h4>
|
||||
</section>
|
||||
<section id="intern_profile" class="inner-page hidden flex align-start"></section>
|
||||
<section id="all_interns_page" class="inner-page hidden flex flex-direction-column align-start">
|
||||
<div id="all_interns_page__header" class="grid gap-0-5">
|
||||
<h2>Interns</h2>
|
||||
@ -563,19 +564,6 @@
|
||||
</main>
|
||||
</main>
|
||||
|
||||
<sm-popup id="intern_info_popup">
|
||||
<header slot="header" class="popup__header">
|
||||
<button class="popup__header__close" onclick="closePopup()">
|
||||
<svg class="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
|
||||
<path fill="none" d="M0 0h24v24H0z" />
|
||||
<path
|
||||
d="M12 10.586l4.95-4.95 1.414 1.414-4.95 4.95 4.95 4.95-1.414 1.414-4.95-4.95-4.95 4.95-1.414-1.414 4.95-4.95-4.95-4.95L7.05 5.636z" />
|
||||
</svg>
|
||||
</button>
|
||||
</header>
|
||||
<section id="intern_info__wrapper" class="grid gap-1"></section>
|
||||
</sm-popup>
|
||||
|
||||
<sm-popup id="intern_list_popup">
|
||||
<header slot="header" class="popup__header">
|
||||
<button class="popup__header__close" onclick="closePopup()">
|
||||
@ -1224,6 +1212,9 @@
|
||||
case 'all_interns_page':
|
||||
renderAllInterns()
|
||||
break;
|
||||
case 'intern_profile':
|
||||
render.internProfile(params?.id)
|
||||
break;
|
||||
case 'project_explorer':
|
||||
let breadcrumbs = []
|
||||
if (subPageId1) {
|
||||
@ -1917,7 +1908,8 @@
|
||||
</div>
|
||||
`;
|
||||
},
|
||||
internCard(internFloId, { selectable = false } = {}) {
|
||||
internCard(internFloId, options = {}) {
|
||||
const { selectable } = options
|
||||
const internName = RIBC.getInternList()[internFloId]
|
||||
const internPoints = RIBC.getInternRating(internFloId)
|
||||
const splitName = internName.split(' ')
|
||||
@ -1925,9 +1917,10 @@
|
||||
if (splitName.length > 1) {
|
||||
initials += splitName[splitName.length - 1][0]
|
||||
}
|
||||
return html`
|
||||
<label class="intern-card align-center interact" .dataset=${{ internFloId }} onclick=${selectable ? false : showInternInfo} title="Intern Information">
|
||||
${selectable ? html`<input type="checkbox" class="intern-card__checkbox" value=${internFloId}>` : ''}
|
||||
if (selectable) {
|
||||
return html`
|
||||
<label class="intern-card align-center interact" .dataset=${{ internFloId }} title="Intern Information">
|
||||
<input type="checkbox" class="intern-card__checkbox" value=${internFloId}>
|
||||
<div class="intern-card__initials" style=${`--color: var(${getInternColor(internFloId)})`}>${initials}</div>
|
||||
<div class="intern-card__name">${internName}</div>
|
||||
<div class="intern-card__score-wrapper flex align-center">
|
||||
@ -1935,6 +1928,17 @@
|
||||
<svg class="icon icon--star" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"> <path fill="none" d="M0 0h24v24H0z" /> <path d="M12 18.26l-7.053 3.948 1.575-7.928L.587 8.792l8.027-.952L12 .5l3.386 7.34 8.027.952-5.935 5.488 1.575 7.928z" /> </svg>
|
||||
</div>
|
||||
</label>`;
|
||||
} else {
|
||||
return html`
|
||||
<a class="intern-card align-center interact" href=${`#/intern_profile?id=${internFloId}`} title="Intern Information">
|
||||
<div class="intern-card__initials" style=${`--color: var(${getInternColor(internFloId)})`}>${initials}</div>
|
||||
<div class="intern-card__name">${internName}</div>
|
||||
<div class="intern-card__score-wrapper flex align-center">
|
||||
<b class="intern-card__score">${internPoints}</b>
|
||||
<svg class="icon icon--star" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"> <path fill="none" d="M0 0h24v24H0z" /> <path d="M12 18.26l-7.053 3.948 1.575-7.928L.587 8.792l8.027-.952L12 .5l3.386 7.34 8.027.952-5.935 5.488 1.575 7.928z" /> </svg>
|
||||
</div>
|
||||
</a>`;
|
||||
}
|
||||
},
|
||||
adminInterns() {
|
||||
const addInternButton = html`<button class="button button--colored" onclick="openPopup('add_intern_popup')">
|
||||
@ -1944,12 +1948,16 @@
|
||||
renderElem(getRef('admin_page__intern_list'), html`${[addInternButton, filterInterns('')]}`)
|
||||
},
|
||||
internUpdateCard(update) {
|
||||
const { floID, time, note, update: { projectCode, branch, task, description, link } } = update
|
||||
const { floID, time, note, update: { projectCode, branch, task, description, link }, tag } = update
|
||||
let topic = `${RIBC.getProjectDetails(projectCode).projectName} / ${RIBC.getTaskDetails(projectCode, branch, task).title}`
|
||||
const internName = RIBC.getInternList()[floID]
|
||||
let replyButton
|
||||
if (userType === "admin" && !note) {
|
||||
replyButton = html`<button class="button button--small init-update-replay margin-left-auto">Reply</button>`
|
||||
let saveButton
|
||||
if (userType === "admin") {
|
||||
if (!note)
|
||||
replyButton = html`<button class="button button--small button--colored init-update-replay">Reply</button>`
|
||||
if (!tag)
|
||||
saveButton = html`<button class="button button--small button--colored save-update margin-left-auto">Save</button>`
|
||||
}
|
||||
let providedLink
|
||||
if (link) {
|
||||
@ -1971,8 +1979,8 @@
|
||||
<h4 class="update__topic">${topic}</h4>
|
||||
<p class="update__message ws-pre-line wrap-around">${description}</p>
|
||||
${providedLink}
|
||||
${replyButton}
|
||||
${adminReply}
|
||||
${saveButton || replyButton ? html`<div class="flex align-center gap-0-3">${saveButton}${replyButton}</div>` : ''}
|
||||
</li>`;
|
||||
},
|
||||
branchButton(obj = {}) {
|
||||
@ -1997,14 +2005,33 @@
|
||||
</span>
|
||||
`
|
||||
},
|
||||
internSpecificTasks(internId) {
|
||||
assignedInternTasks(internId) {
|
||||
const { assignedTasks, completedTasks } = RIBC.getInternRecord(internId)
|
||||
if (getObjLength(assignedTasks) === 0) return false
|
||||
const assignedTasksList = [];
|
||||
for (const task in assignedTasks) {
|
||||
if (completedTasks[task]) continue;
|
||||
const { points, assignedOn } = assignedTasks[task];
|
||||
const { title } = RIBC.getAllTasks()[task];
|
||||
assignedTasksList.push(html`
|
||||
<div class="intern_profile__task">
|
||||
<h4>${title}</h4>
|
||||
<time>${getFormattedTime(assignedOn, 'date-only')}</time>
|
||||
<p class="flex align-center gap-0-3">
|
||||
${points}
|
||||
<svg class="icon icon--star" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"> <path fill="none" d="M0 0h24v24H0z"></path> <path d="M12 18.26l-7.053 3.948 1.575-7.928L.587 8.792l8.027-.952L12 .5l3.386 7.34 8.027.952-5.935 5.488 1.575 7.928z"></path> </svg>
|
||||
</p>
|
||||
</div>`)
|
||||
}
|
||||
},
|
||||
completedInternTasks(internId) {
|
||||
const { completedTasks } = RIBC.getInternRecord(internId)
|
||||
if (getObjLength(completedTasks) === 0) return false
|
||||
return Object.keys(completedTasks).map(task => {
|
||||
const { points, completionDate } = completedTasks[task];
|
||||
const { title } = RIBC.getAllTasks()[task];
|
||||
return html`
|
||||
<div class="intern_info__task">
|
||||
<div class="intern_profile__task">
|
||||
<h4>${title}</h4>
|
||||
<time>${getFormattedTime(completionDate, 'date-only')}</time>
|
||||
<p class="flex align-center gap-0-3">
|
||||
@ -2197,13 +2224,94 @@
|
||||
<h4 class="task__title">${title}</h4>
|
||||
${linkifyDescription}
|
||||
</div>
|
||||
<button class="send-update-button button--small margin-left-auto" onclick=${initTaskUpdate}>
|
||||
<button class="send-update-button button--small button--colored margin-left-auto" onclick=${initTaskUpdate}>
|
||||
<svg class="icon margin-right-0-5" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path fill="none" d="M0 0h24v24H0z"/><path d="M1.946 9.315c-.522-.174-.527-.455.01-.634l19.087-6.362c.529-.176.832.12.684.638l-5.454 19.086c-.15.529-.455.547-.679.045L12 14l6-8-8 6-8.054-2.685z"/></svg>
|
||||
Post an update
|
||||
</button>
|
||||
</li>
|
||||
`;
|
||||
},
|
||||
internProfile(internFloId) {
|
||||
const { joined, completedTasks = {}, active = true } = RIBC.getInternRecord(internFloId) || {}
|
||||
const internName = RIBC.getInternList()[internFloId]
|
||||
const rating = RIBC.getInternRating(internFloId)
|
||||
let completedTasksCount = 0;
|
||||
let totalPoints = 0
|
||||
for (const task in completedTasks) {
|
||||
completedTasksCount++
|
||||
totalPoints += completedTasks[task].points
|
||||
}
|
||||
const splitName = internName.split(' ')
|
||||
let initials = splitName[0][0]
|
||||
if (splitName.length > 1) {
|
||||
initials += splitName[splitName.length - 1][0]
|
||||
}
|
||||
renderElem(getRef('intern_profile'), html`
|
||||
<div id="intern_profile__left">
|
||||
<div class="flex flex-direction-column align-items-center gap-1-5">
|
||||
<div id="intern_profile__initials" class="intern-card__initials" style=${`--color: var(${getInternColor(internFloId)})`}>${initials}</div>
|
||||
<div class="flex flex-direction-column align-items-center gap-0-5">
|
||||
<div class="flex align-center gap-0-5">
|
||||
<h3 id="intern_profile__name" class="text-center">${internName}</h3>
|
||||
${userType === "admin" ? html`<button id="edit_intern_name" class="button button--small button--colored" onclick=${toggleInternNameEditing}>Edit</button> ` : ''}
|
||||
</div>
|
||||
<sm-copy id="intern_profile__flo_id" value=${internFloId}></sm-copy>
|
||||
</div>
|
||||
${joined ? html`<p>Joined on ${getFormattedTime(joined, 'date-only')}</p>` : ''}
|
||||
</div>
|
||||
<div id="stats_wrapper">
|
||||
<div id="intern_rating" class="stat">
|
||||
<div class="stat__display">
|
||||
<svg class="stat__circle" viewBox="0 0 128 128" fill="none" xmlns="http://www.w3.org/2000/svg"> <circle cx="64" cy="64" r="63.5"/> </svg>
|
||||
<span class="stat__count">${rating}%</h4>
|
||||
</div>
|
||||
<p>Rating</p>
|
||||
</div>
|
||||
<div id="intern_complete_tasks" class="stat">
|
||||
<div class="stat__display">
|
||||
<svg class="stat__circle" viewBox="0 0 128 128" fill="none" xmlns="http://www.w3.org/2000/svg"> <circle cx="64" cy="64" r="63.5"/> </svg>
|
||||
<span class="stat__count">${completedTasksCount}</h4>
|
||||
</div>
|
||||
<p>Task completed</p>
|
||||
</div>
|
||||
<div id="intern_points" class="stat">
|
||||
<div class="stat__display">
|
||||
<svg class="stat__circle" viewBox="0 0 128 128" fill="none" xmlns="http://www.w3.org/2000/svg"> <circle cx="64" cy="64" r="63.5"/> </svg>
|
||||
<span class="stat__count">${totalPoints}</h4>
|
||||
</div>
|
||||
<p>Points earned</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="intern_profile__right" class="flex flex-direction-column gap-1-5">
|
||||
<div class="flex align-center space-between gap-1">
|
||||
<h3>Tasks</h3>
|
||||
<a href=${`#/updates_page?projectCode=all&internId=${internFloId}`} class="button button--small button--colored">See updates</a>
|
||||
</div>
|
||||
<div>
|
||||
<h4>Assigned</h4>
|
||||
<div>
|
||||
${render.assignedInternTasks(internFloId) || html`<p>No currently assigned tasks</p>`}
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<h4>Completed</h4>
|
||||
<div>
|
||||
${render.completedInternTasks(internFloId) || html`<p>No tasks completed yet</p>`}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`)
|
||||
let color = '--green';
|
||||
if (rating < 50) {
|
||||
color = '--danger-color'
|
||||
} else if (rating < 80) {
|
||||
color = '--orange'
|
||||
}
|
||||
setTimeout(() => {
|
||||
getRef('intern_rating').style = `--progress: ${400 - (rating * 4)}; --rating-color:var(${color})`;
|
||||
}, 100);
|
||||
},
|
||||
dashProject(projectCode) {
|
||||
const { projectName } = RIBC.getProjectDetails(projectCode)
|
||||
const projectMap = RIBC.getProjectMap(projectCode)
|
||||
@ -2620,85 +2728,6 @@
|
||||
return days;
|
||||
}
|
||||
|
||||
|
||||
// opens a popup containing various intern information
|
||||
function showInternInfo(e) {
|
||||
const internFloId = e.target.closest('.intern-card').dataset.internFloId;
|
||||
const { joined, completedTasks = {}, active = true } = RIBC.getInternRecord(internFloId) || {}
|
||||
const internName = RIBC.getInternList()[internFloId]
|
||||
const rating = RIBC.getInternRating(internFloId)
|
||||
let completedTasksCount = 0;
|
||||
let totalPoints = 0
|
||||
for (const task in completedTasks) {
|
||||
completedTasksCount++
|
||||
totalPoints += completedTasks[task].points
|
||||
}
|
||||
const splitName = internName.split(' ')
|
||||
let initials = splitName[0][0]
|
||||
if (splitName.length > 1) {
|
||||
initials += splitName[splitName.length - 1][0]
|
||||
}
|
||||
renderElem(getRef('intern_info__wrapper'), html`
|
||||
<div id="intern_info__left">
|
||||
<div class="flex flex-direction-column align-items-center gap-1-5">
|
||||
<div id="intern_info__initials" class="intern-card__initials" style=${`--color: var(${getInternColor(internFloId)})`}>${initials}</div>
|
||||
<div class="flex flex-direction-column align-items-center gap-0-5">
|
||||
<div class="flex align-center gap-0-5">
|
||||
<h3 id="intern_info__name" class="text-center">${internName}</h3>
|
||||
${userType === "admin" ? html`<button id="edit_intern_name" class="button button--small button--colored" onclick=${toggleInternNameEditing}>Edit</button> ` : ''}
|
||||
</div>
|
||||
<sm-copy id="intern_info__flo_id" value=${internFloId}></sm-copy>
|
||||
</div>
|
||||
${joined ? html`<p>Joined on ${getFormattedTime(joined, 'date-only')}</p>` : ''}
|
||||
</div>
|
||||
<div id="stats_wrapper">
|
||||
<div id="intern_rating" class="stat">
|
||||
<div class="stat__display">
|
||||
<svg class="stat__circle" viewBox="0 0 128 128" fill="none" xmlns="http://www.w3.org/2000/svg"> <circle cx="64" cy="64" r="63.5"/> </svg>
|
||||
<span class="stat__count">${rating}%</h4>
|
||||
</div>
|
||||
<p>Rating</p>
|
||||
</div>
|
||||
<div id="intern_complete_tasks" class="stat">
|
||||
<div class="stat__display">
|
||||
<svg class="stat__circle" viewBox="0 0 128 128" fill="none" xmlns="http://www.w3.org/2000/svg"> <circle cx="64" cy="64" r="63.5"/> </svg>
|
||||
<span class="stat__count">${completedTasksCount}</h4>
|
||||
</div>
|
||||
<p>Task completed</p>
|
||||
</div>
|
||||
<div id="intern_points" class="stat">
|
||||
<div class="stat__display">
|
||||
<svg class="stat__circle" viewBox="0 0 128 128" fill="none" xmlns="http://www.w3.org/2000/svg"> <circle cx="64" cy="64" r="63.5"/> </svg>
|
||||
<span class="stat__count">${totalPoints}</h4>
|
||||
</div>
|
||||
<p>Points earned</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="intern_info__right">
|
||||
<div id="intern_info__tasks">
|
||||
<div class="flex align-center space-between gap-1">
|
||||
<h3>Tasks completed</h3>
|
||||
<a href=${`#/updates_page?projectCode=all&internId=${internFloId}`} class="button button--small button--colored">See updates</a>
|
||||
</div>
|
||||
<div id="intern_info__tasks_list">
|
||||
${render.internSpecificTasks(internFloId) || html`<p>No tasks completed yet</p>`}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`)
|
||||
openPopup('intern_info_popup');
|
||||
let color = '--green';
|
||||
if (rating < 50) {
|
||||
color = '--danger-color'
|
||||
} else if (rating < 80) {
|
||||
color = '--orange'
|
||||
}
|
||||
setTimeout(() => {
|
||||
getRef('intern_rating').style = `--progress: ${400 - (rating * 4)}; --rating-color:var(${color})`;
|
||||
}, 100);
|
||||
}
|
||||
|
||||
// opens a popup containing various project information
|
||||
function showProjectInfo(projectCode) {
|
||||
const { projectName, projectDescription } = RIBC.getProjectDetails(projectCode);
|
||||
@ -3156,22 +3185,22 @@
|
||||
|
||||
function toggleInternNameEditing(e) {
|
||||
const button = e.target.closest('button');
|
||||
if (getRef('intern_info__name').isContentEditable) {
|
||||
const floId = getRef('intern_info__flo_id').value;
|
||||
const newName = getRef('intern_info__name').textContent.trim();
|
||||
if (getRef('intern_profile__name').isContentEditable) {
|
||||
const floId = getRef('intern_profile__flo_id').value;
|
||||
const newName = getRef('intern_profile__name').textContent.trim();
|
||||
if (newName !== '' && floGlobals.tempEditableContent !== newName) {
|
||||
RIBC.admin.renameIntern(floId, newName)
|
||||
const highPerformingInterns = Object.keys(RIBC.getInternList()).sort((a, b) => RIBC.getInternRating(b) - RIBC.getInternRating(a));
|
||||
renderElem(getRef('top_interns'), html`${highPerformingInterns.slice(0, 8).map(floId => render.internCard(floId))}`)
|
||||
notify('Intern name updated locally, please commit changes to make them permanent.', 'success')
|
||||
}
|
||||
getRef('intern_info__name').contentEditable = false;
|
||||
getRef('intern_profile__name').contentEditable = false;
|
||||
button.textContent = 'Edit';
|
||||
document.getSelection().collapseToEnd()
|
||||
floGlobals.tempEditableContent = '';
|
||||
adminDataChanged();
|
||||
} else {
|
||||
makeEditable(getRef('intern_info__name'))
|
||||
makeEditable(getRef('intern_profile__name'))
|
||||
button.textContent = 'Done'
|
||||
}
|
||||
}
|
||||
@ -3233,7 +3262,7 @@
|
||||
}
|
||||
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.parentNode.after(html.node`
|
||||
<sm-form class="update-replay grid gap-0-5">
|
||||
<sm-textarea placeholder="Enter your reply here" class="update-reply-textarea" rows="4" required></sm-textarea>
|
||||
<div class="flex align-center gap-0-3 margin-left-auto">
|
||||
@ -3244,9 +3273,22 @@
|
||||
</div>
|
||||
</sm-form>
|
||||
`)
|
||||
e.delegateTarget.classList.add('hidden')
|
||||
e.delegateTarget.parentNode.classList.add('hidden')
|
||||
e.target.closest('.intern-update').querySelector('.update-reply-textarea').focusIn()
|
||||
})
|
||||
delegate(getRef('all_updates_list'), 'click', '.save-update', (e) => {
|
||||
const vectorClock = e.delegateTarget.closest('.intern-update').dataset.vectorClock;
|
||||
getConfirmation('Are you sure you want to save this update?', { confirmText: 'Save' }).then((res) => {
|
||||
if (res) {
|
||||
floCloudAPI.tagApplicationData(vectorClock, 'saved').then(() => {
|
||||
notify('Update saved', 'success')
|
||||
e.delegateTarget.remove()
|
||||
}).catch(() => {
|
||||
notify('Failed to save update', 'error')
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
function cancelUpdateReply(replayBox) {
|
||||
replayBox.previousElementSibling.classList.remove('hidden')
|
||||
@ -3385,9 +3427,6 @@
|
||||
case 'rate_participants_popup':
|
||||
renderElem(getRef('rating_wrapper'), html``)
|
||||
break;
|
||||
case 'intern_info_popup':
|
||||
renderElem(getRef('intern_info__wrapper'), html``)
|
||||
break;
|
||||
}
|
||||
if (popupStack.items.length === 0) {
|
||||
getRef('main_page').removeAttribute('inert')
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
(function(EXPORTS) { //compactIDB v2.1.0
|
||||
(function (EXPORTS) { //compactIDB v2.1.0
|
||||
/* Compact IndexedDB operations */
|
||||
'use strict';
|
||||
const compactIDB = EXPORTS;
|
||||
@ -59,7 +59,7 @@
|
||||
})
|
||||
}
|
||||
|
||||
compactIDB.initDB = function(dbName, objectStores = {}) {
|
||||
compactIDB.initDB = function (dbName, objectStores = {}) {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!(objectStores instanceof Object))
|
||||
return reject('ObjectStores must be an object or array')
|
||||
@ -87,14 +87,14 @@
|
||||
resolve("Initiated IndexedDB");
|
||||
else
|
||||
upgradeDB(dbName, a_obs, d_obs)
|
||||
.then(result => resolve(result))
|
||||
.catch(error => reject(error))
|
||||
.then(result => resolve(result))
|
||||
.catch(error => reject(error))
|
||||
db.close();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
const openDB = compactIDB.openDB = function(dbName = defaultDB) {
|
||||
const openDB = compactIDB.openDB = function (dbName = defaultDB) {
|
||||
return new Promise((resolve, reject) => {
|
||||
var idb = indexedDB.open(dbName);
|
||||
idb.onerror = (event) => reject("Error in opening IndexedDB");
|
||||
@ -106,7 +106,7 @@
|
||||
});
|
||||
}
|
||||
|
||||
const deleteDB = compactIDB.deleteDB = function(dbName = defaultDB) {
|
||||
const deleteDB = compactIDB.deleteDB = function (dbName = defaultDB) {
|
||||
return new Promise((resolve, reject) => {
|
||||
var deleteReq = indexedDB.deleteDatabase(dbName);;
|
||||
deleteReq.onerror = (event) => reject("Error deleting database!");
|
||||
@ -114,7 +114,7 @@
|
||||
});
|
||||
}
|
||||
|
||||
compactIDB.writeData = function(obsName, data, key = false, dbName = defaultDB) {
|
||||
compactIDB.writeData = function (obsName, data, key = false, dbName = defaultDB) {
|
||||
return new Promise((resolve, reject) => {
|
||||
openDB(dbName).then(db => {
|
||||
var obs = db.transaction(obsName, "readwrite").objectStore(obsName);
|
||||
@ -128,7 +128,7 @@
|
||||
});
|
||||
}
|
||||
|
||||
compactIDB.addData = function(obsName, data, key = false, dbName = defaultDB) {
|
||||
compactIDB.addData = function (obsName, data, key = false, dbName = defaultDB) {
|
||||
return new Promise((resolve, reject) => {
|
||||
openDB(dbName).then(db => {
|
||||
var obs = db.transaction(obsName, "readwrite").objectStore(obsName);
|
||||
@ -142,7 +142,7 @@
|
||||
});
|
||||
}
|
||||
|
||||
compactIDB.removeData = function(obsName, key, dbName = defaultDB) {
|
||||
compactIDB.removeData = function (obsName, key, dbName = defaultDB) {
|
||||
return new Promise((resolve, reject) => {
|
||||
openDB(dbName).then(db => {
|
||||
var obs = db.transaction(obsName, "readwrite").objectStore(obsName);
|
||||
@ -156,7 +156,7 @@
|
||||
});
|
||||
}
|
||||
|
||||
compactIDB.clearData = function(obsName, dbName = defaultDB) {
|
||||
compactIDB.clearData = function (obsName, dbName = defaultDB) {
|
||||
return new Promise((resolve, reject) => {
|
||||
openDB(dbName).then(db => {
|
||||
var obs = db.transaction(obsName, "readwrite").objectStore(obsName);
|
||||
@ -168,7 +168,7 @@
|
||||
});
|
||||
}
|
||||
|
||||
compactIDB.readData = function(obsName, key, dbName = defaultDB) {
|
||||
compactIDB.readData = function (obsName, key, dbName = defaultDB) {
|
||||
return new Promise((resolve, reject) => {
|
||||
openDB(dbName).then(db => {
|
||||
var obs = db.transaction(obsName, "readonly").objectStore(obsName);
|
||||
@ -182,7 +182,7 @@
|
||||
});
|
||||
}
|
||||
|
||||
compactIDB.readAllData = function(obsName, dbName = defaultDB) {
|
||||
compactIDB.readAllData = function (obsName, dbName = defaultDB) {
|
||||
return new Promise((resolve, reject) => {
|
||||
openDB(dbName).then(db => {
|
||||
var obs = db.transaction(obsName, "readonly").objectStore(obsName);
|
||||
@ -223,7 +223,7 @@
|
||||
})
|
||||
}*/
|
||||
|
||||
compactIDB.searchData = function(obsName, options = {}, dbName = defaultDB) {
|
||||
compactIDB.searchData = function (obsName, options = {}, dbName = defaultDB) {
|
||||
options.lowerKey = options.atKey || options.lowerKey || 0
|
||||
options.upperKey = options.atKey || options.upperKey || false
|
||||
options.patternEval = options.patternEval || ((k, v) => {
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
(function(EXPORTS) { //floBlockchainAPI v2.3.3b
|
||||
(function (EXPORTS) { //floBlockchainAPI v2.3.3b
|
||||
/* FLO Blockchain Operator to send/receive data from blockchain using API calls*/
|
||||
'use strict';
|
||||
const floBlockchainAPI = EXPORTS;
|
||||
@ -102,7 +102,7 @@
|
||||
});
|
||||
|
||||
//Promised function to get data from API
|
||||
const promisedAPI = floBlockchainAPI.promisedAPI = floBlockchainAPI.fetch = function(apicall) {
|
||||
const promisedAPI = floBlockchainAPI.promisedAPI = floBlockchainAPI.fetch = function (apicall) {
|
||||
return new Promise((resolve, reject) => {
|
||||
//console.log(apicall);
|
||||
fetch_api(apicall)
|
||||
@ -112,7 +112,7 @@
|
||||
}
|
||||
|
||||
//Get balance for the given Address
|
||||
const getBalance = floBlockchainAPI.getBalance = function(addr) {
|
||||
const getBalance = floBlockchainAPI.getBalance = function (addr) {
|
||||
return new Promise((resolve, reject) => {
|
||||
promisedAPI(`api/addr/${addr}/balance`)
|
||||
.then(balance => resolve(parseFloat(balance)))
|
||||
@ -121,7 +121,7 @@
|
||||
}
|
||||
|
||||
//Send Tx to blockchain
|
||||
const sendTx = floBlockchainAPI.sendTx = function(senderAddr, receiverAddr, sendAmt, privKey, floData = '', strict_utxo = true) {
|
||||
const sendTx = floBlockchainAPI.sendTx = function (senderAddr, receiverAddr, sendAmt, privKey, floData = '', strict_utxo = true) {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!floCrypto.validateASCII(floData))
|
||||
return reject("Invalid FLO_Data: only printable ASCII characters are allowed");
|
||||
@ -187,7 +187,7 @@
|
||||
}
|
||||
|
||||
//Write Data into blockchain
|
||||
floBlockchainAPI.writeData = function(senderAddr, data, privKey, receiverAddr = DEFAULT.receiverID, options = {}) {
|
||||
floBlockchainAPI.writeData = function (senderAddr, data, privKey, receiverAddr = DEFAULT.receiverID, options = {}) {
|
||||
let strict_utxo = options.strict_utxo === false ? false : true,
|
||||
sendAmt = isNaN(options.sendAmt) ? DEFAULT.sendAmt : options.sendAmt;
|
||||
return new Promise((resolve, reject) => {
|
||||
@ -200,7 +200,7 @@
|
||||
}
|
||||
|
||||
//merge all UTXOs of a given floID into a single UTXO
|
||||
floBlockchainAPI.mergeUTXOs = function(floID, privKey, floData = '') {
|
||||
floBlockchainAPI.mergeUTXOs = function (floID, privKey, floData = '') {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!floCrypto.validateFloID(floID))
|
||||
return reject(`Invalid floID`);
|
||||
@ -234,7 +234,7 @@
|
||||
* @param {boolean} preserveRatio (optional) preserve ratio or equal contribution
|
||||
* @return {Promise}
|
||||
*/
|
||||
floBlockchainAPI.writeDataMultiple = function(senderPrivKeys, data, receivers = [DEFAULT.receiverID], preserveRatio = true) {
|
||||
floBlockchainAPI.writeDataMultiple = function (senderPrivKeys, data, receivers = [DEFAULT.receiverID], preserveRatio = true) {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!Array.isArray(senderPrivKeys))
|
||||
return reject("Invalid senderPrivKeys: SenderPrivKeys must be Array");
|
||||
@ -266,7 +266,7 @@
|
||||
* @param {string} floData FLO data of the txn
|
||||
* @return {Promise}
|
||||
*/
|
||||
const sendTxMultiple = floBlockchainAPI.sendTxMultiple = function(senderPrivKeys, receivers, floData = '') {
|
||||
const sendTxMultiple = floBlockchainAPI.sendTxMultiple = function (senderPrivKeys, receivers, floData = '') {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!floCrypto.validateASCII(floData))
|
||||
return reject("Invalid FLO_Data: only printable ASCII characters are allowed");
|
||||
@ -421,7 +421,7 @@
|
||||
}
|
||||
|
||||
//Broadcast signed Tx in blockchain using API
|
||||
const broadcastTx = floBlockchainAPI.broadcastTx = function(signedTxHash) {
|
||||
const broadcastTx = floBlockchainAPI.broadcastTx = function (signedTxHash) {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (signedTxHash.length < 1)
|
||||
return reject("Empty Signature");
|
||||
@ -441,7 +441,7 @@
|
||||
})
|
||||
}
|
||||
|
||||
floBlockchainAPI.getTx = function(txid) {
|
||||
floBlockchainAPI.getTx = function (txid) {
|
||||
return new Promise((resolve, reject) => {
|
||||
promisedAPI(`api/tx/${txid}`)
|
||||
.then(response => resolve(response))
|
||||
@ -450,7 +450,7 @@
|
||||
}
|
||||
|
||||
//Read Txs of Address between from and to
|
||||
const readTxs = floBlockchainAPI.readTxs = function(addr, from, to) {
|
||||
const readTxs = floBlockchainAPI.readTxs = function (addr, from, to) {
|
||||
return new Promise((resolve, reject) => {
|
||||
promisedAPI(`api/addrs/${addr}/txs?from=${from}&to=${to}`)
|
||||
.then(response => resolve(response))
|
||||
@ -459,7 +459,7 @@
|
||||
}
|
||||
|
||||
//Read All Txs of Address (newest first)
|
||||
floBlockchainAPI.readAllTxs = function(addr) {
|
||||
floBlockchainAPI.readAllTxs = function (addr) {
|
||||
return new Promise((resolve, reject) => {
|
||||
promisedAPI(`api/addrs/${addr}/txs?from=0&to=1`).then(response => {
|
||||
promisedAPI(`api/addrs/${addr}/txs?from=0&to=${response.totalItems}0`)
|
||||
@ -481,7 +481,7 @@
|
||||
sender : flo-id(s) of sender
|
||||
receiver : flo-id(s) of receiver
|
||||
*/
|
||||
floBlockchainAPI.readData = function(addr, options = {}) {
|
||||
floBlockchainAPI.readData = function (addr, options = {}) {
|
||||
options.limit = options.limit || 0;
|
||||
options.ignoreOld = options.ignoreOld || 0;
|
||||
if (typeof options.sender === "string") options.sender = [options.sender];
|
||||
@ -489,7 +489,7 @@
|
||||
return new Promise((resolve, reject) => {
|
||||
promisedAPI(`api/addrs/${addr}/txs?from=0&to=1`).then(response => {
|
||||
var newItems = response.totalItems - options.ignoreOld;
|
||||
promisedAPI(`api/addrs/${addr}/txs?from=0&to=${newItems*2}`).then(response => {
|
||||
promisedAPI(`api/addrs/${addr}/txs?from=0&to=${newItems * 2}`).then(response => {
|
||||
if (options.limit <= 0)
|
||||
options.limit = response.items.length;
|
||||
var filteredData = [];
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
(function(EXPORTS) { //floCrypto v2.3.3d
|
||||
(function (EXPORTS) { //floCrypto v2.3.3d
|
||||
/* FLO Crypto Operators */
|
||||
'use strict';
|
||||
const floCrypto = EXPORTS;
|
||||
@ -78,14 +78,14 @@
|
||||
}
|
||||
|
||||
//generate a random Interger within range
|
||||
floCrypto.randInt = function(min, max) {
|
||||
floCrypto.randInt = function (min, max) {
|
||||
min = Math.ceil(min);
|
||||
max = Math.floor(max);
|
||||
return Math.floor(securedMathRandom() * (max - min + 1)) + min;
|
||||
}
|
||||
|
||||
//generate a random String within length (options : alphaNumeric chars only)
|
||||
floCrypto.randString = function(length, alphaNumeric = true) {
|
||||
floCrypto.randString = function (length, alphaNumeric = true) {
|
||||
var result = '';
|
||||
var characters = alphaNumeric ? 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789' :
|
||||
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_+-./*?@#&$<>=[]{}():';
|
||||
@ -95,7 +95,7 @@
|
||||
}
|
||||
|
||||
//Encrypt Data using public-key
|
||||
floCrypto.encryptData = function(data, receiverPublicKeyHex) {
|
||||
floCrypto.encryptData = function (data, receiverPublicKeyHex) {
|
||||
var senderECKeyData = getSenderPublicKeyString();
|
||||
var senderDerivedKey = deriveSharedKeySender(receiverPublicKeyHex, senderECKeyData.privateKey);
|
||||
let senderKey = senderDerivedKey.XValue + senderDerivedKey.YValue;
|
||||
@ -107,7 +107,7 @@
|
||||
}
|
||||
|
||||
//Decrypt Data using private-key
|
||||
floCrypto.decryptData = function(data, privateKeyHex) {
|
||||
floCrypto.decryptData = function (data, privateKeyHex) {
|
||||
var receiverECKeyData = {};
|
||||
if (typeof privateKeyHex !== "string") throw new Error("No private key found.");
|
||||
let privateKey = wifToDecimal(privateKeyHex, true);
|
||||
@ -120,7 +120,7 @@
|
||||
}
|
||||
|
||||
//Sign data using private-key
|
||||
floCrypto.signData = function(data, privateKeyHex) {
|
||||
floCrypto.signData = function (data, privateKeyHex) {
|
||||
var key = new Bitcoin.ECKey(privateKeyHex);
|
||||
var messageHash = Crypto.SHA256(data);
|
||||
var messageSign = Bitcoin.ECDSA.sign(messageHash, key.priv);
|
||||
@ -129,7 +129,7 @@
|
||||
}
|
||||
|
||||
//Verify signatue of the data using public-key
|
||||
floCrypto.verifySign = function(data, signatureHex, publicKeyHex) {
|
||||
floCrypto.verifySign = function (data, signatureHex, publicKeyHex) {
|
||||
var msgHash = Crypto.SHA256(data);
|
||||
var sigBytes = Crypto.util.hexToBytes(signatureHex);
|
||||
var publicKeyPoint = ecparams.getCurve().decodePointHex(publicKeyHex);
|
||||
@ -138,7 +138,7 @@
|
||||
}
|
||||
|
||||
//Generates a new flo ID and returns private-key, public-key and floID
|
||||
const generateNewID = floCrypto.generateNewID = function() {
|
||||
const generateNewID = floCrypto.generateNewID = function () {
|
||||
var key = new Bitcoin.ECKey(false);
|
||||
key.setCompressed(true);
|
||||
return {
|
||||
@ -168,7 +168,7 @@
|
||||
});
|
||||
|
||||
//Returns public-key from private-key
|
||||
floCrypto.getPubKeyHex = function(privateKeyHex) {
|
||||
floCrypto.getPubKeyHex = function (privateKeyHex) {
|
||||
if (!privateKeyHex)
|
||||
return null;
|
||||
var key = new Bitcoin.ECKey(privateKeyHex);
|
||||
@ -179,7 +179,7 @@
|
||||
}
|
||||
|
||||
//Returns flo-ID from public-key or private-key
|
||||
floCrypto.getFloID = function(keyHex) {
|
||||
floCrypto.getFloID = function (keyHex) {
|
||||
if (!keyHex)
|
||||
return null;
|
||||
try {
|
||||
@ -192,7 +192,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
floCrypto.getAddress = function(privateKeyHex, strict = false) {
|
||||
floCrypto.getAddress = function (privateKeyHex, strict = false) {
|
||||
if (!privateKeyHex)
|
||||
return;
|
||||
var key = new Bitcoin.ECKey(privateKeyHex);
|
||||
@ -212,7 +212,7 @@
|
||||
}
|
||||
|
||||
//Verify the private-key for the given public-key or flo-ID
|
||||
floCrypto.verifyPrivKey = function(privateKeyHex, pubKey_floID, isfloID = true) {
|
||||
floCrypto.verifyPrivKey = function (privateKeyHex, pubKey_floID, isfloID = true) {
|
||||
if (!privateKeyHex || !pubKey_floID)
|
||||
return false;
|
||||
try {
|
||||
@ -232,7 +232,7 @@
|
||||
}
|
||||
|
||||
//Check if the given flo-id is valid or not
|
||||
floCrypto.validateFloID = function(floID) {
|
||||
floCrypto.validateFloID = function (floID) {
|
||||
if (!floID)
|
||||
return false;
|
||||
try {
|
||||
@ -244,7 +244,7 @@
|
||||
}
|
||||
|
||||
//Check if the given address (any blockchain) is valid or not
|
||||
floCrypto.validateAddr = function(address, std = true, bech = true) {
|
||||
floCrypto.validateAddr = function (address, std = true, bech = true) {
|
||||
let raw = decodeAddress(address);
|
||||
if (!raw)
|
||||
return false;
|
||||
@ -267,7 +267,7 @@
|
||||
}
|
||||
|
||||
//Check the public-key for the address (any blockchain)
|
||||
floCrypto.verifyPubKey = function(pubKeyHex, address) {
|
||||
floCrypto.verifyPubKey = function (pubKeyHex, address) {
|
||||
let raw = decodeAddress(address),
|
||||
pub_hash = Crypto.util.bytesToHex(ripemd160(Crypto.SHA256(Crypto.util.hexToBytes(pubKeyHex), {
|
||||
asBytes: true
|
||||
@ -276,7 +276,7 @@
|
||||
}
|
||||
|
||||
//Convert the given address (any blockchain) to equivalent floID
|
||||
floCrypto.toFloID = function(address) {
|
||||
floCrypto.toFloID = function (address) {
|
||||
if (!address)
|
||||
return;
|
||||
let raw = decodeAddress(address);
|
||||
@ -292,7 +292,7 @@
|
||||
}
|
||||
|
||||
//Checks if the given addresses (any blockchain) are same (w.r.t keys)
|
||||
floCrypto.isSameAddr = function(addr1, addr2) {
|
||||
floCrypto.isSameAddr = function (addr1, addr2) {
|
||||
if (!addr1 || !addr2)
|
||||
return;
|
||||
let raw1 = decodeAddress(addr1),
|
||||
@ -303,7 +303,7 @@
|
||||
return raw1.hex === raw2.hex;
|
||||
}
|
||||
|
||||
const decodeAddress = floCrypto.decodeAddr = function(address) {
|
||||
const decodeAddress = floCrypto.decodeAddr = function (address) {
|
||||
if (!address)
|
||||
return;
|
||||
else if (address.length == 33 || address.length == 34) { //legacy encoding
|
||||
@ -338,7 +338,7 @@
|
||||
}
|
||||
|
||||
//Split the str using shamir's Secret and Returns the shares
|
||||
floCrypto.createShamirsSecretShares = function(str, total_shares, threshold_limit) {
|
||||
floCrypto.createShamirsSecretShares = function (str, total_shares, threshold_limit) {
|
||||
try {
|
||||
if (str.length > 0) {
|
||||
var strHex = shamirSecretShare.str2hex(str);
|
||||
@ -352,7 +352,7 @@
|
||||
}
|
||||
|
||||
//Returns the retrived secret by combining the shamirs shares
|
||||
const retrieveShamirSecret = floCrypto.retrieveShamirSecret = function(sharesArray) {
|
||||
const retrieveShamirSecret = floCrypto.retrieveShamirSecret = function (sharesArray) {
|
||||
try {
|
||||
if (sharesArray.length > 0) {
|
||||
var comb = shamirSecretShare.combine(sharesArray.slice(0, sharesArray.length));
|
||||
@ -366,7 +366,7 @@
|
||||
}
|
||||
|
||||
//Verifies the shares and str
|
||||
floCrypto.verifyShamirsSecret = function(sharesArray, str) {
|
||||
floCrypto.verifyShamirsSecret = function (sharesArray, str) {
|
||||
if (!str)
|
||||
return null;
|
||||
else if (retrieveShamirSecret(sharesArray) === str)
|
||||
@ -375,7 +375,7 @@
|
||||
return false;
|
||||
}
|
||||
|
||||
const validateASCII = floCrypto.validateASCII = function(string, bool = true) {
|
||||
const validateASCII = floCrypto.validateASCII = function (string, bool = true) {
|
||||
if (typeof string !== "string")
|
||||
return null;
|
||||
if (bool) {
|
||||
@ -393,8 +393,8 @@
|
||||
if (x < 32 || x > 127)
|
||||
if (x in invalids)
|
||||
invalids[string[i]].push(i)
|
||||
else
|
||||
invalids[string[i]] = [i];
|
||||
else
|
||||
invalids[string[i]] = [i];
|
||||
}
|
||||
if (Object.keys(invalids).length)
|
||||
return invalids;
|
||||
@ -403,7 +403,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
floCrypto.convertToASCII = function(string, mode = 'soft-remove') {
|
||||
floCrypto.convertToASCII = function (string, mode = 'soft-remove') {
|
||||
let chars = validateASCII(string, false);
|
||||
if (chars === true)
|
||||
return string;
|
||||
@ -414,9 +414,9 @@
|
||||
ascii_alternatives.split('\n').forEach(a => refAlt[a[0]] = a.slice(2));
|
||||
mode = mode.toLowerCase();
|
||||
if (mode === "hard-unicode")
|
||||
convertor = (c) => `\\u${('000'+c.charCodeAt().toString(16)).slice(-4)}`;
|
||||
convertor = (c) => `\\u${('000' + c.charCodeAt().toString(16)).slice(-4)}`;
|
||||
else if (mode === "soft-unicode")
|
||||
convertor = (c) => refAlt[c] || `\\u${('000'+c.charCodeAt().toString(16)).slice(-4)}`;
|
||||
convertor = (c) => refAlt[c] || `\\u${('000' + c.charCodeAt().toString(16)).slice(-4)}`;
|
||||
else if (mode === "hard-remove")
|
||||
convertor = c => "";
|
||||
else if (mode === "soft-remove")
|
||||
@ -428,7 +428,7 @@
|
||||
return result;
|
||||
}
|
||||
|
||||
floCrypto.revertUnicode = function(string) {
|
||||
floCrypto.revertUnicode = function (string) {
|
||||
return string.replace(/\\u[\dA-F]{4}/gi,
|
||||
m => String.fromCharCode(parseInt(m.replace(/\\u/g, ''), 16)));
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
(function(EXPORTS) { //floDapps v2.3.2d
|
||||
(function (EXPORTS) { //floDapps v2.3.2d
|
||||
/* General functions for FLO Dapps*/
|
||||
'use strict';
|
||||
const floDapps = EXPORTS;
|
||||
@ -454,7 +454,7 @@
|
||||
})
|
||||
});
|
||||
|
||||
floDapps.launchStartUp = function() {
|
||||
floDapps.launchStartUp = function () {
|
||||
return new Promise((resolve, reject) => {
|
||||
initIndexedDB().then(log => {
|
||||
console.log(log)
|
||||
@ -497,7 +497,7 @@
|
||||
|
||||
floDapps.setAppObjectStores = appObs => initIndexedDB.appObs = appObs;
|
||||
|
||||
floDapps.storeContact = function(floID, name) {
|
||||
floDapps.storeContact = function (floID, name) {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!floCrypto.validateAddr(floID))
|
||||
return reject("Invalid floID!")
|
||||
@ -508,7 +508,7 @@
|
||||
});
|
||||
}
|
||||
|
||||
floDapps.storePubKey = function(floID, pubKey) {
|
||||
floDapps.storePubKey = function (floID, pubKey) {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (floID in user.pubKeys)
|
||||
return resolve("pubKey already stored")
|
||||
@ -523,7 +523,7 @@
|
||||
});
|
||||
}
|
||||
|
||||
floDapps.sendMessage = function(floID, message) {
|
||||
floDapps.sendMessage = function (floID, message) {
|
||||
return new Promise((resolve, reject) => {
|
||||
let options = {
|
||||
receiverID: floID,
|
||||
@ -538,7 +538,7 @@
|
||||
})
|
||||
}
|
||||
|
||||
floDapps.requestInbox = function(callback) {
|
||||
floDapps.requestInbox = function (callback) {
|
||||
return new Promise((resolve, reject) => {
|
||||
let lastVC = Object.keys(user.messages).sort().pop()
|
||||
let options = {
|
||||
@ -552,7 +552,7 @@
|
||||
try {
|
||||
if (d[v].message instanceof Object && "secret" in d[v].message)
|
||||
d[v].message = floCrypto.decryptData(d[v].message, privKey)
|
||||
} catch (error) {}
|
||||
} catch (error) { }
|
||||
compactIDB.writeData("messages", d[v], v, user.db_name)
|
||||
user.messages[v] = d[v]
|
||||
}
|
||||
@ -565,7 +565,7 @@
|
||||
})
|
||||
}
|
||||
|
||||
floDapps.manageAppConfig = function(adminPrivKey, addList, rmList, settings) {
|
||||
floDapps.manageAppConfig = function (adminPrivKey, addList, rmList, settings) {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!Array.isArray(addList) || !addList.length) addList = undefined;
|
||||
if (!Array.isArray(rmList) || !rmList.length) rmList = undefined;
|
||||
@ -584,12 +584,12 @@
|
||||
reject('Access Denied for Admin privilege')
|
||||
else
|
||||
floBlockchainAPI.writeData(floID, JSON.stringify(floData), adminPrivKey)
|
||||
.then(result => resolve(['Updated App Configuration', result]))
|
||||
.catch(error => reject(error))
|
||||
.then(result => resolve(['Updated App Configuration', result]))
|
||||
.catch(error => reject(error))
|
||||
})
|
||||
}
|
||||
|
||||
const clearCredentials = floDapps.clearCredentials = function() {
|
||||
const clearCredentials = floDapps.clearCredentials = function () {
|
||||
return new Promise((resolve, reject) => {
|
||||
compactIDB.clearData('credentials', DEFAULT.application).then(result => {
|
||||
localStorage.removeItem(`${DEFAULT.application}#privKey`);
|
||||
@ -599,7 +599,7 @@
|
||||
})
|
||||
}
|
||||
|
||||
floDapps.deleteUserData = function(credentials = false) {
|
||||
floDapps.deleteUserData = function (credentials = false) {
|
||||
return new Promise((resolve, reject) => {
|
||||
let p = []
|
||||
p.push(compactIDB.deleteDB(user.db_name))
|
||||
@ -611,7 +611,7 @@
|
||||
})
|
||||
}
|
||||
|
||||
floDapps.deleteAppData = function() {
|
||||
floDapps.deleteAppData = function () {
|
||||
return new Promise((resolve, reject) => {
|
||||
compactIDB.deleteDB(DEFAULT.application).then(result => {
|
||||
localStorage.removeItem(`${DEFAULT.application}#privKey`)
|
||||
@ -623,7 +623,7 @@
|
||||
})
|
||||
}
|
||||
|
||||
floDapps.securePrivKey = function(pwd) {
|
||||
floDapps.securePrivKey = function (pwd) {
|
||||
return new Promise(async (resolve, reject) => {
|
||||
let indexArr = localStorage.getItem(`${DEFAULT.application}#privKey`)
|
||||
if (!indexArr)
|
||||
@ -643,8 +643,8 @@
|
||||
})
|
||||
}
|
||||
|
||||
floDapps.verifyPin = function(pin = null) {
|
||||
const readSharesFromIDB = function(indexArr) {
|
||||
floDapps.verifyPin = function (pin = null) {
|
||||
const readSharesFromIDB = function (indexArr) {
|
||||
return new Promise((resolve, reject) => {
|
||||
var promises = []
|
||||
for (var i = 0; i < indexArr.length; i++)
|
||||
@ -687,7 +687,7 @@
|
||||
})
|
||||
}
|
||||
|
||||
const getNextGeneralData = floDapps.getNextGeneralData = function(type, vectorClock = null, options = {}) {
|
||||
const getNextGeneralData = floDapps.getNextGeneralData = function (type, vectorClock = null, options = {}) {
|
||||
var fk = floCloudAPI.util.filterKey(type, options)
|
||||
vectorClock = vectorClock || getNextGeneralData[fk] || '0';
|
||||
var filteredResult = {}
|
||||
@ -716,10 +716,10 @@
|
||||
let tmp = floCrypto.decryptData(data.message, key)
|
||||
data.message = JSON.parse(tmp)
|
||||
break;
|
||||
} catch (error) {}
|
||||
} catch (error) { }
|
||||
}
|
||||
}
|
||||
} catch (error) {}
|
||||
} catch (error) { }
|
||||
}
|
||||
}
|
||||
getNextGeneralData[fk] = Object.keys(filteredResult).sort().pop();
|
||||
|
||||
1184
scripts/lib.js
1184
scripts/lib.js
File diff suppressed because it is too large
Load Diff
@ -71,7 +71,8 @@
|
||||
floID: data.senderID,
|
||||
update: data.message,
|
||||
time: data.vectorClock.split('_')[0],
|
||||
note: data.note
|
||||
note: data.note,
|
||||
tag: data.tag
|
||||
}
|
||||
})
|
||||
internUpdates = internUpdates.filter(data => data.floID in _.internList)
|
||||
|
||||
2
scripts/ribc.min.js
vendored
2
scripts/ribc.min.js
vendored
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue
Block a user