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;
|
user-select: none;
|
||||||
padding: 0.8rem 1rem;
|
padding: 0.8rem 1rem;
|
||||||
gap: 0.8rem;
|
gap: 0.8rem;
|
||||||
|
color: inherit;
|
||||||
}
|
}
|
||||||
.intern-card input {
|
.intern-card input {
|
||||||
height: 1.3em;
|
height: 1.3em;
|
||||||
@ -1284,7 +1285,7 @@ ul {
|
|||||||
flex: 1;
|
flex: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#intern_info__initials {
|
#intern_profile__initials {
|
||||||
position: relative;
|
position: relative;
|
||||||
height: 4rem;
|
height: 4rem;
|
||||||
width: 4rem;
|
width: 4rem;
|
||||||
@ -1292,12 +1293,12 @@ ul {
|
|||||||
color: var(--color);
|
color: var(--color);
|
||||||
}
|
}
|
||||||
|
|
||||||
#intern_info__name {
|
#intern_profile__name {
|
||||||
font-size: 1.5rem;
|
font-size: 1.5rem;
|
||||||
padding: 0.4rem 0.5rem;
|
padding: 0.4rem 0.5rem;
|
||||||
border-radius: 0.5rem;
|
border-radius: 0.5rem;
|
||||||
}
|
}
|
||||||
#intern_info__name[contenteditable=true] {
|
#intern_profile__name[contenteditable=true] {
|
||||||
background-color: rgba(var(--text-color), 0.1);
|
background-color: rgba(var(--text-color), 0.1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1379,33 +1380,39 @@ ul {
|
|||||||
color: var(--nice-blue);
|
color: var(--nice-blue);
|
||||||
}
|
}
|
||||||
|
|
||||||
#intern_info__wrapper {
|
#intern_profile {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
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;
|
flex: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.intern_info__task {
|
.intern_profile__task {
|
||||||
display: grid;
|
display: grid;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
gap: 0.3rem;
|
gap: 0.3rem;
|
||||||
margin-top: 1rem;
|
margin-top: 1rem;
|
||||||
padding: 0.5rem;
|
padding: 1rem;
|
||||||
border-radius: 0.5rem;
|
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;
|
grid-template-columns: minmax(0, 1fr) auto;
|
||||||
}
|
}
|
||||||
.intern_info__task h4 {
|
.intern_profile__task h4 {
|
||||||
grid-column: 1/-1;
|
grid-column: 1/-1;
|
||||||
}
|
}
|
||||||
.intern_info__task p {
|
.intern_profile__task p {
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
.intern_info__task time {
|
.intern_profile__task time {
|
||||||
font-size: 0.9rem;
|
font-size: 0.9rem;
|
||||||
color: rgba(var(--text-color), 0.8);
|
color: rgba(var(--text-color), 0.8);
|
||||||
}
|
}
|
||||||
@ -1853,16 +1860,6 @@ ul {
|
|||||||
margin-top: 0.2rem;
|
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 {
|
.temp-task {
|
||||||
padding: 1rem;
|
padding: 1rem;
|
||||||
background-color: rgba(var(--foreground-color), 1);
|
background-color: rgba(var(--foreground-color), 1);
|
||||||
@ -2223,6 +2220,13 @@ input[type=date]:focus {
|
|||||||
width: min(48rem, 100%);
|
width: min(48rem, 100%);
|
||||||
margin: 0 auto;
|
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) {
|
@media only screen and (min-width: 1280px) {
|
||||||
#main_page {
|
#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;
|
user-select: none;
|
||||||
padding: 0.8rem 1rem;
|
padding: 0.8rem 1rem;
|
||||||
gap: 0.8rem;
|
gap: 0.8rem;
|
||||||
|
color: inherit;
|
||||||
input {
|
input {
|
||||||
height: 1.3em;
|
height: 1.3em;
|
||||||
width: 1.3em;
|
width: 1.3em;
|
||||||
@ -1256,14 +1257,14 @@ ul {
|
|||||||
.container-header h4 {
|
.container-header h4 {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
}
|
}
|
||||||
#intern_info__initials {
|
#intern_profile__initials {
|
||||||
position: relative;
|
position: relative;
|
||||||
height: 4rem;
|
height: 4rem;
|
||||||
width: 4rem;
|
width: 4rem;
|
||||||
font-size: 1.3rem;
|
font-size: 1.3rem;
|
||||||
color: var(--color);
|
color: var(--color);
|
||||||
}
|
}
|
||||||
#intern_info__name {
|
#intern_profile__name {
|
||||||
font-size: 1.5rem;
|
font-size: 1.5rem;
|
||||||
padding: 0.4rem 0.5rem;
|
padding: 0.4rem 0.5rem;
|
||||||
border-radius: 0.5rem;
|
border-radius: 0.5rem;
|
||||||
@ -1348,23 +1349,29 @@ ul {
|
|||||||
color: var(--nice-blue);
|
color: var(--nice-blue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#intern_info__wrapper {
|
#intern_profile {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
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;
|
flex: 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.intern_info__task {
|
.intern_profile__task {
|
||||||
display: grid;
|
display: grid;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
gap: 0.3rem;
|
gap: 0.3rem;
|
||||||
margin-top: 1rem;
|
margin-top: 1rem;
|
||||||
padding: 0.5rem;
|
padding: 1rem;
|
||||||
border-radius: 0.5rem;
|
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;
|
grid-template-columns: minmax(0, 1fr) auto;
|
||||||
h4 {
|
h4 {
|
||||||
grid-column: 1/-1;
|
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 {
|
.temp-task {
|
||||||
padding: 1rem;
|
padding: 1rem;
|
||||||
background-color: rgba(var(--foreground-color), 1);
|
background-color: rgba(var(--foreground-color), 1);
|
||||||
@ -2174,6 +2172,14 @@ input[type="date"] {
|
|||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#intern_profile {
|
||||||
|
&__left {
|
||||||
|
position: sticky;
|
||||||
|
top: 1rem;
|
||||||
|
align-self: flex-start;
|
||||||
|
padding: 1.5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media only screen and (min-width: 1280px) {
|
@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>
|
<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>
|
<h4 class="empty-state">No task requests</h4>
|
||||||
</section>
|
</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">
|
<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">
|
<div id="all_interns_page__header" class="grid gap-0-5">
|
||||||
<h2>Interns</h2>
|
<h2>Interns</h2>
|
||||||
@ -563,19 +564,6 @@
|
|||||||
</main>
|
</main>
|
||||||
</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">
|
<sm-popup id="intern_list_popup">
|
||||||
<header slot="header" class="popup__header">
|
<header slot="header" class="popup__header">
|
||||||
<button class="popup__header__close" onclick="closePopup()">
|
<button class="popup__header__close" onclick="closePopup()">
|
||||||
@ -1224,6 +1212,9 @@
|
|||||||
case 'all_interns_page':
|
case 'all_interns_page':
|
||||||
renderAllInterns()
|
renderAllInterns()
|
||||||
break;
|
break;
|
||||||
|
case 'intern_profile':
|
||||||
|
render.internProfile(params?.id)
|
||||||
|
break;
|
||||||
case 'project_explorer':
|
case 'project_explorer':
|
||||||
let breadcrumbs = []
|
let breadcrumbs = []
|
||||||
if (subPageId1) {
|
if (subPageId1) {
|
||||||
@ -1917,7 +1908,8 @@
|
|||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
},
|
},
|
||||||
internCard(internFloId, { selectable = false } = {}) {
|
internCard(internFloId, options = {}) {
|
||||||
|
const { selectable } = options
|
||||||
const internName = RIBC.getInternList()[internFloId]
|
const internName = RIBC.getInternList()[internFloId]
|
||||||
const internPoints = RIBC.getInternRating(internFloId)
|
const internPoints = RIBC.getInternRating(internFloId)
|
||||||
const splitName = internName.split(' ')
|
const splitName = internName.split(' ')
|
||||||
@ -1925,9 +1917,10 @@
|
|||||||
if (splitName.length > 1) {
|
if (splitName.length > 1) {
|
||||||
initials += splitName[splitName.length - 1][0]
|
initials += splitName[splitName.length - 1][0]
|
||||||
}
|
}
|
||||||
return html`
|
if (selectable) {
|
||||||
<label class="intern-card align-center interact" .dataset=${{ internFloId }} onclick=${selectable ? false : showInternInfo} title="Intern Information">
|
return html`
|
||||||
${selectable ? html`<input type="checkbox" class="intern-card__checkbox" value=${internFloId}>` : ''}
|
<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__initials" style=${`--color: var(${getInternColor(internFloId)})`}>${initials}</div>
|
||||||
<div class="intern-card__name">${internName}</div>
|
<div class="intern-card__name">${internName}</div>
|
||||||
<div class="intern-card__score-wrapper flex align-center">
|
<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>
|
<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>
|
</div>
|
||||||
</label>`;
|
</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() {
|
adminInterns() {
|
||||||
const addInternButton = html`<button class="button button--colored" onclick="openPopup('add_intern_popup')">
|
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('')]}`)
|
renderElem(getRef('admin_page__intern_list'), html`${[addInternButton, filterInterns('')]}`)
|
||||||
},
|
},
|
||||||
internUpdateCard(update) {
|
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}`
|
let topic = `${RIBC.getProjectDetails(projectCode).projectName} / ${RIBC.getTaskDetails(projectCode, branch, task).title}`
|
||||||
const internName = RIBC.getInternList()[floID]
|
const internName = RIBC.getInternList()[floID]
|
||||||
let replyButton
|
let replyButton
|
||||||
if (userType === "admin" && !note) {
|
let saveButton
|
||||||
replyButton = html`<button class="button button--small init-update-replay margin-left-auto">Reply</button>`
|
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
|
let providedLink
|
||||||
if (link) {
|
if (link) {
|
||||||
@ -1971,8 +1979,8 @@
|
|||||||
<h4 class="update__topic">${topic}</h4>
|
<h4 class="update__topic">${topic}</h4>
|
||||||
<p class="update__message ws-pre-line wrap-around">${description}</p>
|
<p class="update__message ws-pre-line wrap-around">${description}</p>
|
||||||
${providedLink}
|
${providedLink}
|
||||||
${replyButton}
|
|
||||||
${adminReply}
|
${adminReply}
|
||||||
|
${saveButton || replyButton ? html`<div class="flex align-center gap-0-3">${saveButton}${replyButton}</div>` : ''}
|
||||||
</li>`;
|
</li>`;
|
||||||
},
|
},
|
||||||
branchButton(obj = {}) {
|
branchButton(obj = {}) {
|
||||||
@ -1997,14 +2005,33 @@
|
|||||||
</span>
|
</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)
|
const { completedTasks } = RIBC.getInternRecord(internId)
|
||||||
if (getObjLength(completedTasks) === 0) return false
|
if (getObjLength(completedTasks) === 0) return false
|
||||||
return Object.keys(completedTasks).map(task => {
|
return Object.keys(completedTasks).map(task => {
|
||||||
const { points, completionDate } = completedTasks[task];
|
const { points, completionDate } = completedTasks[task];
|
||||||
const { title } = RIBC.getAllTasks()[task];
|
const { title } = RIBC.getAllTasks()[task];
|
||||||
return html`
|
return html`
|
||||||
<div class="intern_info__task">
|
<div class="intern_profile__task">
|
||||||
<h4>${title}</h4>
|
<h4>${title}</h4>
|
||||||
<time>${getFormattedTime(completionDate, 'date-only')}</time>
|
<time>${getFormattedTime(completionDate, 'date-only')}</time>
|
||||||
<p class="flex align-center gap-0-3">
|
<p class="flex align-center gap-0-3">
|
||||||
@ -2197,13 +2224,94 @@
|
|||||||
<h4 class="task__title">${title}</h4>
|
<h4 class="task__title">${title}</h4>
|
||||||
${linkifyDescription}
|
${linkifyDescription}
|
||||||
</div>
|
</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>
|
<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
|
Post an update
|
||||||
</button>
|
</button>
|
||||||
</li>
|
</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) {
|
dashProject(projectCode) {
|
||||||
const { projectName } = RIBC.getProjectDetails(projectCode)
|
const { projectName } = RIBC.getProjectDetails(projectCode)
|
||||||
const projectMap = RIBC.getProjectMap(projectCode)
|
const projectMap = RIBC.getProjectMap(projectCode)
|
||||||
@ -2620,85 +2728,6 @@
|
|||||||
return days;
|
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
|
// opens a popup containing various project information
|
||||||
function showProjectInfo(projectCode) {
|
function showProjectInfo(projectCode) {
|
||||||
const { projectName, projectDescription } = RIBC.getProjectDetails(projectCode);
|
const { projectName, projectDescription } = RIBC.getProjectDetails(projectCode);
|
||||||
@ -3156,22 +3185,22 @@
|
|||||||
|
|
||||||
function toggleInternNameEditing(e) {
|
function toggleInternNameEditing(e) {
|
||||||
const button = e.target.closest('button');
|
const button = e.target.closest('button');
|
||||||
if (getRef('intern_info__name').isContentEditable) {
|
if (getRef('intern_profile__name').isContentEditable) {
|
||||||
const floId = getRef('intern_info__flo_id').value;
|
const floId = getRef('intern_profile__flo_id').value;
|
||||||
const newName = getRef('intern_info__name').textContent.trim();
|
const newName = getRef('intern_profile__name').textContent.trim();
|
||||||
if (newName !== '' && floGlobals.tempEditableContent !== newName) {
|
if (newName !== '' && floGlobals.tempEditableContent !== newName) {
|
||||||
RIBC.admin.renameIntern(floId, newName)
|
RIBC.admin.renameIntern(floId, newName)
|
||||||
const highPerformingInterns = Object.keys(RIBC.getInternList()).sort((a, b) => RIBC.getInternRating(b) - RIBC.getInternRating(a));
|
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))}`)
|
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')
|
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';
|
button.textContent = 'Edit';
|
||||||
document.getSelection().collapseToEnd()
|
document.getSelection().collapseToEnd()
|
||||||
floGlobals.tempEditableContent = '';
|
floGlobals.tempEditableContent = '';
|
||||||
adminDataChanged();
|
adminDataChanged();
|
||||||
} else {
|
} else {
|
||||||
makeEditable(getRef('intern_info__name'))
|
makeEditable(getRef('intern_profile__name'))
|
||||||
button.textContent = 'Done'
|
button.textContent = 'Done'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3233,7 +3262,7 @@
|
|||||||
}
|
}
|
||||||
delegate(getRef('all_updates_list'), 'click', '.init-update-replay', (e) => {
|
delegate(getRef('all_updates_list'), 'click', '.init-update-replay', (e) => {
|
||||||
const vectorClock = e.delegateTarget.closest('.intern-update').dataset.vectorClock;
|
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-form class="update-replay grid gap-0-5">
|
||||||
<sm-textarea placeholder="Enter your reply here" class="update-reply-textarea" rows="4" required></sm-textarea>
|
<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">
|
<div class="flex align-center gap-0-3 margin-left-auto">
|
||||||
@ -3244,9 +3273,22 @@
|
|||||||
</div>
|
</div>
|
||||||
</sm-form>
|
</sm-form>
|
||||||
`)
|
`)
|
||||||
e.delegateTarget.classList.add('hidden')
|
e.delegateTarget.parentNode.classList.add('hidden')
|
||||||
e.target.closest('.intern-update').querySelector('.update-reply-textarea').focusIn()
|
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) {
|
function cancelUpdateReply(replayBox) {
|
||||||
replayBox.previousElementSibling.classList.remove('hidden')
|
replayBox.previousElementSibling.classList.remove('hidden')
|
||||||
@ -3385,9 +3427,6 @@
|
|||||||
case 'rate_participants_popup':
|
case 'rate_participants_popup':
|
||||||
renderElem(getRef('rating_wrapper'), html``)
|
renderElem(getRef('rating_wrapper'), html``)
|
||||||
break;
|
break;
|
||||||
case 'intern_info_popup':
|
|
||||||
renderElem(getRef('intern_info__wrapper'), html``)
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
if (popupStack.items.length === 0) {
|
if (popupStack.items.length === 0) {
|
||||||
getRef('main_page').removeAttribute('inert')
|
getRef('main_page').removeAttribute('inert')
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
(function(EXPORTS) { //compactIDB v2.1.0
|
(function (EXPORTS) { //compactIDB v2.1.0
|
||||||
/* Compact IndexedDB operations */
|
/* Compact IndexedDB operations */
|
||||||
'use strict';
|
'use strict';
|
||||||
const compactIDB = EXPORTS;
|
const compactIDB = EXPORTS;
|
||||||
@ -59,7 +59,7 @@
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
compactIDB.initDB = function(dbName, objectStores = {}) {
|
compactIDB.initDB = function (dbName, objectStores = {}) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
if (!(objectStores instanceof Object))
|
if (!(objectStores instanceof Object))
|
||||||
return reject('ObjectStores must be an object or array')
|
return reject('ObjectStores must be an object or array')
|
||||||
@ -87,14 +87,14 @@
|
|||||||
resolve("Initiated IndexedDB");
|
resolve("Initiated IndexedDB");
|
||||||
else
|
else
|
||||||
upgradeDB(dbName, a_obs, d_obs)
|
upgradeDB(dbName, a_obs, d_obs)
|
||||||
.then(result => resolve(result))
|
.then(result => resolve(result))
|
||||||
.catch(error => reject(error))
|
.catch(error => reject(error))
|
||||||
db.close();
|
db.close();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const openDB = compactIDB.openDB = function(dbName = defaultDB) {
|
const openDB = compactIDB.openDB = function (dbName = defaultDB) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
var idb = indexedDB.open(dbName);
|
var idb = indexedDB.open(dbName);
|
||||||
idb.onerror = (event) => reject("Error in opening IndexedDB");
|
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) => {
|
return new Promise((resolve, reject) => {
|
||||||
var deleteReq = indexedDB.deleteDatabase(dbName);;
|
var deleteReq = indexedDB.deleteDatabase(dbName);;
|
||||||
deleteReq.onerror = (event) => reject("Error deleting database!");
|
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) => {
|
return new Promise((resolve, reject) => {
|
||||||
openDB(dbName).then(db => {
|
openDB(dbName).then(db => {
|
||||||
var obs = db.transaction(obsName, "readwrite").objectStore(obsName);
|
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) => {
|
return new Promise((resolve, reject) => {
|
||||||
openDB(dbName).then(db => {
|
openDB(dbName).then(db => {
|
||||||
var obs = db.transaction(obsName, "readwrite").objectStore(obsName);
|
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) => {
|
return new Promise((resolve, reject) => {
|
||||||
openDB(dbName).then(db => {
|
openDB(dbName).then(db => {
|
||||||
var obs = db.transaction(obsName, "readwrite").objectStore(obsName);
|
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) => {
|
return new Promise((resolve, reject) => {
|
||||||
openDB(dbName).then(db => {
|
openDB(dbName).then(db => {
|
||||||
var obs = db.transaction(obsName, "readwrite").objectStore(obsName);
|
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) => {
|
return new Promise((resolve, reject) => {
|
||||||
openDB(dbName).then(db => {
|
openDB(dbName).then(db => {
|
||||||
var obs = db.transaction(obsName, "readonly").objectStore(obsName);
|
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) => {
|
return new Promise((resolve, reject) => {
|
||||||
openDB(dbName).then(db => {
|
openDB(dbName).then(db => {
|
||||||
var obs = db.transaction(obsName, "readonly").objectStore(obsName);
|
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.lowerKey = options.atKey || options.lowerKey || 0
|
||||||
options.upperKey = options.atKey || options.upperKey || false
|
options.upperKey = options.atKey || options.upperKey || false
|
||||||
options.patternEval = options.patternEval || ((k, v) => {
|
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*/
|
/* FLO Blockchain Operator to send/receive data from blockchain using API calls*/
|
||||||
'use strict';
|
'use strict';
|
||||||
const floBlockchainAPI = EXPORTS;
|
const floBlockchainAPI = EXPORTS;
|
||||||
@ -102,7 +102,7 @@
|
|||||||
});
|
});
|
||||||
|
|
||||||
//Promised function to get data from API
|
//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) => {
|
return new Promise((resolve, reject) => {
|
||||||
//console.log(apicall);
|
//console.log(apicall);
|
||||||
fetch_api(apicall)
|
fetch_api(apicall)
|
||||||
@ -112,7 +112,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Get balance for the given Address
|
//Get balance for the given Address
|
||||||
const getBalance = floBlockchainAPI.getBalance = function(addr) {
|
const getBalance = floBlockchainAPI.getBalance = function (addr) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
promisedAPI(`api/addr/${addr}/balance`)
|
promisedAPI(`api/addr/${addr}/balance`)
|
||||||
.then(balance => resolve(parseFloat(balance)))
|
.then(balance => resolve(parseFloat(balance)))
|
||||||
@ -121,7 +121,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Send Tx to blockchain
|
//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) => {
|
return new Promise((resolve, reject) => {
|
||||||
if (!floCrypto.validateASCII(floData))
|
if (!floCrypto.validateASCII(floData))
|
||||||
return reject("Invalid FLO_Data: only printable ASCII characters are allowed");
|
return reject("Invalid FLO_Data: only printable ASCII characters are allowed");
|
||||||
@ -187,7 +187,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Write Data into blockchain
|
//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,
|
let strict_utxo = options.strict_utxo === false ? false : true,
|
||||||
sendAmt = isNaN(options.sendAmt) ? DEFAULT.sendAmt : options.sendAmt;
|
sendAmt = isNaN(options.sendAmt) ? DEFAULT.sendAmt : options.sendAmt;
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
@ -200,7 +200,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
//merge all UTXOs of a given floID into a single UTXO
|
//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) => {
|
return new Promise((resolve, reject) => {
|
||||||
if (!floCrypto.validateFloID(floID))
|
if (!floCrypto.validateFloID(floID))
|
||||||
return reject(`Invalid floID`);
|
return reject(`Invalid floID`);
|
||||||
@ -234,7 +234,7 @@
|
|||||||
* @param {boolean} preserveRatio (optional) preserve ratio or equal contribution
|
* @param {boolean} preserveRatio (optional) preserve ratio or equal contribution
|
||||||
* @return {Promise}
|
* @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) => {
|
return new Promise((resolve, reject) => {
|
||||||
if (!Array.isArray(senderPrivKeys))
|
if (!Array.isArray(senderPrivKeys))
|
||||||
return reject("Invalid senderPrivKeys: SenderPrivKeys must be Array");
|
return reject("Invalid senderPrivKeys: SenderPrivKeys must be Array");
|
||||||
@ -266,7 +266,7 @@
|
|||||||
* @param {string} floData FLO data of the txn
|
* @param {string} floData FLO data of the txn
|
||||||
* @return {Promise}
|
* @return {Promise}
|
||||||
*/
|
*/
|
||||||
const sendTxMultiple = floBlockchainAPI.sendTxMultiple = function(senderPrivKeys, receivers, floData = '') {
|
const sendTxMultiple = floBlockchainAPI.sendTxMultiple = function (senderPrivKeys, receivers, floData = '') {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
if (!floCrypto.validateASCII(floData))
|
if (!floCrypto.validateASCII(floData))
|
||||||
return reject("Invalid FLO_Data: only printable ASCII characters are allowed");
|
return reject("Invalid FLO_Data: only printable ASCII characters are allowed");
|
||||||
@ -421,7 +421,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Broadcast signed Tx in blockchain using API
|
//Broadcast signed Tx in blockchain using API
|
||||||
const broadcastTx = floBlockchainAPI.broadcastTx = function(signedTxHash) {
|
const broadcastTx = floBlockchainAPI.broadcastTx = function (signedTxHash) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
if (signedTxHash.length < 1)
|
if (signedTxHash.length < 1)
|
||||||
return reject("Empty Signature");
|
return reject("Empty Signature");
|
||||||
@ -441,7 +441,7 @@
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
floBlockchainAPI.getTx = function(txid) {
|
floBlockchainAPI.getTx = function (txid) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
promisedAPI(`api/tx/${txid}`)
|
promisedAPI(`api/tx/${txid}`)
|
||||||
.then(response => resolve(response))
|
.then(response => resolve(response))
|
||||||
@ -450,7 +450,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Read Txs of Address between from and to
|
//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) => {
|
return new Promise((resolve, reject) => {
|
||||||
promisedAPI(`api/addrs/${addr}/txs?from=${from}&to=${to}`)
|
promisedAPI(`api/addrs/${addr}/txs?from=${from}&to=${to}`)
|
||||||
.then(response => resolve(response))
|
.then(response => resolve(response))
|
||||||
@ -459,7 +459,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Read All Txs of Address (newest first)
|
//Read All Txs of Address (newest first)
|
||||||
floBlockchainAPI.readAllTxs = function(addr) {
|
floBlockchainAPI.readAllTxs = function (addr) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
promisedAPI(`api/addrs/${addr}/txs?from=0&to=1`).then(response => {
|
promisedAPI(`api/addrs/${addr}/txs?from=0&to=1`).then(response => {
|
||||||
promisedAPI(`api/addrs/${addr}/txs?from=0&to=${response.totalItems}0`)
|
promisedAPI(`api/addrs/${addr}/txs?from=0&to=${response.totalItems}0`)
|
||||||
@ -481,7 +481,7 @@
|
|||||||
sender : flo-id(s) of sender
|
sender : flo-id(s) of sender
|
||||||
receiver : flo-id(s) of receiver
|
receiver : flo-id(s) of receiver
|
||||||
*/
|
*/
|
||||||
floBlockchainAPI.readData = function(addr, options = {}) {
|
floBlockchainAPI.readData = function (addr, options = {}) {
|
||||||
options.limit = options.limit || 0;
|
options.limit = options.limit || 0;
|
||||||
options.ignoreOld = options.ignoreOld || 0;
|
options.ignoreOld = options.ignoreOld || 0;
|
||||||
if (typeof options.sender === "string") options.sender = [options.sender];
|
if (typeof options.sender === "string") options.sender = [options.sender];
|
||||||
@ -489,7 +489,7 @@
|
|||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
promisedAPI(`api/addrs/${addr}/txs?from=0&to=1`).then(response => {
|
promisedAPI(`api/addrs/${addr}/txs?from=0&to=1`).then(response => {
|
||||||
var newItems = response.totalItems - options.ignoreOld;
|
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)
|
if (options.limit <= 0)
|
||||||
options.limit = response.items.length;
|
options.limit = response.items.length;
|
||||||
var filteredData = [];
|
var filteredData = [];
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
(function(EXPORTS) { //floCrypto v2.3.3d
|
(function (EXPORTS) { //floCrypto v2.3.3d
|
||||||
/* FLO Crypto Operators */
|
/* FLO Crypto Operators */
|
||||||
'use strict';
|
'use strict';
|
||||||
const floCrypto = EXPORTS;
|
const floCrypto = EXPORTS;
|
||||||
@ -78,14 +78,14 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
//generate a random Interger within range
|
//generate a random Interger within range
|
||||||
floCrypto.randInt = function(min, max) {
|
floCrypto.randInt = function (min, max) {
|
||||||
min = Math.ceil(min);
|
min = Math.ceil(min);
|
||||||
max = Math.floor(max);
|
max = Math.floor(max);
|
||||||
return Math.floor(securedMathRandom() * (max - min + 1)) + min;
|
return Math.floor(securedMathRandom() * (max - min + 1)) + min;
|
||||||
}
|
}
|
||||||
|
|
||||||
//generate a random String within length (options : alphaNumeric chars only)
|
//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 result = '';
|
||||||
var characters = alphaNumeric ? 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789' :
|
var characters = alphaNumeric ? 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789' :
|
||||||
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_+-./*?@#&$<>=[]{}():';
|
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_+-./*?@#&$<>=[]{}():';
|
||||||
@ -95,7 +95,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Encrypt Data using public-key
|
//Encrypt Data using public-key
|
||||||
floCrypto.encryptData = function(data, receiverPublicKeyHex) {
|
floCrypto.encryptData = function (data, receiverPublicKeyHex) {
|
||||||
var senderECKeyData = getSenderPublicKeyString();
|
var senderECKeyData = getSenderPublicKeyString();
|
||||||
var senderDerivedKey = deriveSharedKeySender(receiverPublicKeyHex, senderECKeyData.privateKey);
|
var senderDerivedKey = deriveSharedKeySender(receiverPublicKeyHex, senderECKeyData.privateKey);
|
||||||
let senderKey = senderDerivedKey.XValue + senderDerivedKey.YValue;
|
let senderKey = senderDerivedKey.XValue + senderDerivedKey.YValue;
|
||||||
@ -107,7 +107,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Decrypt Data using private-key
|
//Decrypt Data using private-key
|
||||||
floCrypto.decryptData = function(data, privateKeyHex) {
|
floCrypto.decryptData = function (data, privateKeyHex) {
|
||||||
var receiverECKeyData = {};
|
var receiverECKeyData = {};
|
||||||
if (typeof privateKeyHex !== "string") throw new Error("No private key found.");
|
if (typeof privateKeyHex !== "string") throw new Error("No private key found.");
|
||||||
let privateKey = wifToDecimal(privateKeyHex, true);
|
let privateKey = wifToDecimal(privateKeyHex, true);
|
||||||
@ -120,7 +120,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Sign data using private-key
|
//Sign data using private-key
|
||||||
floCrypto.signData = function(data, privateKeyHex) {
|
floCrypto.signData = function (data, privateKeyHex) {
|
||||||
var key = new Bitcoin.ECKey(privateKeyHex);
|
var key = new Bitcoin.ECKey(privateKeyHex);
|
||||||
var messageHash = Crypto.SHA256(data);
|
var messageHash = Crypto.SHA256(data);
|
||||||
var messageSign = Bitcoin.ECDSA.sign(messageHash, key.priv);
|
var messageSign = Bitcoin.ECDSA.sign(messageHash, key.priv);
|
||||||
@ -129,7 +129,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Verify signatue of the data using public-key
|
//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 msgHash = Crypto.SHA256(data);
|
||||||
var sigBytes = Crypto.util.hexToBytes(signatureHex);
|
var sigBytes = Crypto.util.hexToBytes(signatureHex);
|
||||||
var publicKeyPoint = ecparams.getCurve().decodePointHex(publicKeyHex);
|
var publicKeyPoint = ecparams.getCurve().decodePointHex(publicKeyHex);
|
||||||
@ -138,7 +138,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Generates a new flo ID and returns private-key, public-key and floID
|
//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);
|
var key = new Bitcoin.ECKey(false);
|
||||||
key.setCompressed(true);
|
key.setCompressed(true);
|
||||||
return {
|
return {
|
||||||
@ -168,7 +168,7 @@
|
|||||||
});
|
});
|
||||||
|
|
||||||
//Returns public-key from private-key
|
//Returns public-key from private-key
|
||||||
floCrypto.getPubKeyHex = function(privateKeyHex) {
|
floCrypto.getPubKeyHex = function (privateKeyHex) {
|
||||||
if (!privateKeyHex)
|
if (!privateKeyHex)
|
||||||
return null;
|
return null;
|
||||||
var key = new Bitcoin.ECKey(privateKeyHex);
|
var key = new Bitcoin.ECKey(privateKeyHex);
|
||||||
@ -179,7 +179,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Returns flo-ID from public-key or private-key
|
//Returns flo-ID from public-key or private-key
|
||||||
floCrypto.getFloID = function(keyHex) {
|
floCrypto.getFloID = function (keyHex) {
|
||||||
if (!keyHex)
|
if (!keyHex)
|
||||||
return null;
|
return null;
|
||||||
try {
|
try {
|
||||||
@ -192,7 +192,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
floCrypto.getAddress = function(privateKeyHex, strict = false) {
|
floCrypto.getAddress = function (privateKeyHex, strict = false) {
|
||||||
if (!privateKeyHex)
|
if (!privateKeyHex)
|
||||||
return;
|
return;
|
||||||
var key = new Bitcoin.ECKey(privateKeyHex);
|
var key = new Bitcoin.ECKey(privateKeyHex);
|
||||||
@ -212,7 +212,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Verify the private-key for the given public-key or flo-ID
|
//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)
|
if (!privateKeyHex || !pubKey_floID)
|
||||||
return false;
|
return false;
|
||||||
try {
|
try {
|
||||||
@ -232,7 +232,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Check if the given flo-id is valid or not
|
//Check if the given flo-id is valid or not
|
||||||
floCrypto.validateFloID = function(floID) {
|
floCrypto.validateFloID = function (floID) {
|
||||||
if (!floID)
|
if (!floID)
|
||||||
return false;
|
return false;
|
||||||
try {
|
try {
|
||||||
@ -244,7 +244,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Check if the given address (any blockchain) is valid or not
|
//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);
|
let raw = decodeAddress(address);
|
||||||
if (!raw)
|
if (!raw)
|
||||||
return false;
|
return false;
|
||||||
@ -267,7 +267,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Check the public-key for the address (any blockchain)
|
//Check the public-key for the address (any blockchain)
|
||||||
floCrypto.verifyPubKey = function(pubKeyHex, address) {
|
floCrypto.verifyPubKey = function (pubKeyHex, address) {
|
||||||
let raw = decodeAddress(address),
|
let raw = decodeAddress(address),
|
||||||
pub_hash = Crypto.util.bytesToHex(ripemd160(Crypto.SHA256(Crypto.util.hexToBytes(pubKeyHex), {
|
pub_hash = Crypto.util.bytesToHex(ripemd160(Crypto.SHA256(Crypto.util.hexToBytes(pubKeyHex), {
|
||||||
asBytes: true
|
asBytes: true
|
||||||
@ -276,7 +276,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Convert the given address (any blockchain) to equivalent floID
|
//Convert the given address (any blockchain) to equivalent floID
|
||||||
floCrypto.toFloID = function(address) {
|
floCrypto.toFloID = function (address) {
|
||||||
if (!address)
|
if (!address)
|
||||||
return;
|
return;
|
||||||
let raw = decodeAddress(address);
|
let raw = decodeAddress(address);
|
||||||
@ -292,7 +292,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Checks if the given addresses (any blockchain) are same (w.r.t keys)
|
//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)
|
if (!addr1 || !addr2)
|
||||||
return;
|
return;
|
||||||
let raw1 = decodeAddress(addr1),
|
let raw1 = decodeAddress(addr1),
|
||||||
@ -303,7 +303,7 @@
|
|||||||
return raw1.hex === raw2.hex;
|
return raw1.hex === raw2.hex;
|
||||||
}
|
}
|
||||||
|
|
||||||
const decodeAddress = floCrypto.decodeAddr = function(address) {
|
const decodeAddress = floCrypto.decodeAddr = function (address) {
|
||||||
if (!address)
|
if (!address)
|
||||||
return;
|
return;
|
||||||
else if (address.length == 33 || address.length == 34) { //legacy encoding
|
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
|
//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 {
|
try {
|
||||||
if (str.length > 0) {
|
if (str.length > 0) {
|
||||||
var strHex = shamirSecretShare.str2hex(str);
|
var strHex = shamirSecretShare.str2hex(str);
|
||||||
@ -352,7 +352,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Returns the retrived secret by combining the shamirs shares
|
//Returns the retrived secret by combining the shamirs shares
|
||||||
const retrieveShamirSecret = floCrypto.retrieveShamirSecret = function(sharesArray) {
|
const retrieveShamirSecret = floCrypto.retrieveShamirSecret = function (sharesArray) {
|
||||||
try {
|
try {
|
||||||
if (sharesArray.length > 0) {
|
if (sharesArray.length > 0) {
|
||||||
var comb = shamirSecretShare.combine(sharesArray.slice(0, sharesArray.length));
|
var comb = shamirSecretShare.combine(sharesArray.slice(0, sharesArray.length));
|
||||||
@ -366,7 +366,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Verifies the shares and str
|
//Verifies the shares and str
|
||||||
floCrypto.verifyShamirsSecret = function(sharesArray, str) {
|
floCrypto.verifyShamirsSecret = function (sharesArray, str) {
|
||||||
if (!str)
|
if (!str)
|
||||||
return null;
|
return null;
|
||||||
else if (retrieveShamirSecret(sharesArray) === str)
|
else if (retrieveShamirSecret(sharesArray) === str)
|
||||||
@ -375,7 +375,7 @@
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const validateASCII = floCrypto.validateASCII = function(string, bool = true) {
|
const validateASCII = floCrypto.validateASCII = function (string, bool = true) {
|
||||||
if (typeof string !== "string")
|
if (typeof string !== "string")
|
||||||
return null;
|
return null;
|
||||||
if (bool) {
|
if (bool) {
|
||||||
@ -393,8 +393,8 @@
|
|||||||
if (x < 32 || x > 127)
|
if (x < 32 || x > 127)
|
||||||
if (x in invalids)
|
if (x in invalids)
|
||||||
invalids[string[i]].push(i)
|
invalids[string[i]].push(i)
|
||||||
else
|
else
|
||||||
invalids[string[i]] = [i];
|
invalids[string[i]] = [i];
|
||||||
}
|
}
|
||||||
if (Object.keys(invalids).length)
|
if (Object.keys(invalids).length)
|
||||||
return invalids;
|
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);
|
let chars = validateASCII(string, false);
|
||||||
if (chars === true)
|
if (chars === true)
|
||||||
return string;
|
return string;
|
||||||
@ -414,9 +414,9 @@
|
|||||||
ascii_alternatives.split('\n').forEach(a => refAlt[a[0]] = a.slice(2));
|
ascii_alternatives.split('\n').forEach(a => refAlt[a[0]] = a.slice(2));
|
||||||
mode = mode.toLowerCase();
|
mode = mode.toLowerCase();
|
||||||
if (mode === "hard-unicode")
|
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")
|
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")
|
else if (mode === "hard-remove")
|
||||||
convertor = c => "";
|
convertor = c => "";
|
||||||
else if (mode === "soft-remove")
|
else if (mode === "soft-remove")
|
||||||
@ -428,7 +428,7 @@
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
floCrypto.revertUnicode = function(string) {
|
floCrypto.revertUnicode = function (string) {
|
||||||
return string.replace(/\\u[\dA-F]{4}/gi,
|
return string.replace(/\\u[\dA-F]{4}/gi,
|
||||||
m => String.fromCharCode(parseInt(m.replace(/\\u/g, ''), 16)));
|
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*/
|
/* General functions for FLO Dapps*/
|
||||||
'use strict';
|
'use strict';
|
||||||
const floDapps = EXPORTS;
|
const floDapps = EXPORTS;
|
||||||
@ -454,7 +454,7 @@
|
|||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
floDapps.launchStartUp = function() {
|
floDapps.launchStartUp = function () {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
initIndexedDB().then(log => {
|
initIndexedDB().then(log => {
|
||||||
console.log(log)
|
console.log(log)
|
||||||
@ -497,7 +497,7 @@
|
|||||||
|
|
||||||
floDapps.setAppObjectStores = appObs => initIndexedDB.appObs = appObs;
|
floDapps.setAppObjectStores = appObs => initIndexedDB.appObs = appObs;
|
||||||
|
|
||||||
floDapps.storeContact = function(floID, name) {
|
floDapps.storeContact = function (floID, name) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
if (!floCrypto.validateAddr(floID))
|
if (!floCrypto.validateAddr(floID))
|
||||||
return reject("Invalid floID!")
|
return reject("Invalid floID!")
|
||||||
@ -508,7 +508,7 @@
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
floDapps.storePubKey = function(floID, pubKey) {
|
floDapps.storePubKey = function (floID, pubKey) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
if (floID in user.pubKeys)
|
if (floID in user.pubKeys)
|
||||||
return resolve("pubKey already stored")
|
return resolve("pubKey already stored")
|
||||||
@ -523,7 +523,7 @@
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
floDapps.sendMessage = function(floID, message) {
|
floDapps.sendMessage = function (floID, message) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
let options = {
|
let options = {
|
||||||
receiverID: floID,
|
receiverID: floID,
|
||||||
@ -538,7 +538,7 @@
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
floDapps.requestInbox = function(callback) {
|
floDapps.requestInbox = function (callback) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
let lastVC = Object.keys(user.messages).sort().pop()
|
let lastVC = Object.keys(user.messages).sort().pop()
|
||||||
let options = {
|
let options = {
|
||||||
@ -552,7 +552,7 @@
|
|||||||
try {
|
try {
|
||||||
if (d[v].message instanceof Object && "secret" in d[v].message)
|
if (d[v].message instanceof Object && "secret" in d[v].message)
|
||||||
d[v].message = floCrypto.decryptData(d[v].message, privKey)
|
d[v].message = floCrypto.decryptData(d[v].message, privKey)
|
||||||
} catch (error) {}
|
} catch (error) { }
|
||||||
compactIDB.writeData("messages", d[v], v, user.db_name)
|
compactIDB.writeData("messages", d[v], v, user.db_name)
|
||||||
user.messages[v] = d[v]
|
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) => {
|
return new Promise((resolve, reject) => {
|
||||||
if (!Array.isArray(addList) || !addList.length) addList = undefined;
|
if (!Array.isArray(addList) || !addList.length) addList = undefined;
|
||||||
if (!Array.isArray(rmList) || !rmList.length) rmList = undefined;
|
if (!Array.isArray(rmList) || !rmList.length) rmList = undefined;
|
||||||
@ -584,12 +584,12 @@
|
|||||||
reject('Access Denied for Admin privilege')
|
reject('Access Denied for Admin privilege')
|
||||||
else
|
else
|
||||||
floBlockchainAPI.writeData(floID, JSON.stringify(floData), adminPrivKey)
|
floBlockchainAPI.writeData(floID, JSON.stringify(floData), adminPrivKey)
|
||||||
.then(result => resolve(['Updated App Configuration', result]))
|
.then(result => resolve(['Updated App Configuration', result]))
|
||||||
.catch(error => reject(error))
|
.catch(error => reject(error))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const clearCredentials = floDapps.clearCredentials = function() {
|
const clearCredentials = floDapps.clearCredentials = function () {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
compactIDB.clearData('credentials', DEFAULT.application).then(result => {
|
compactIDB.clearData('credentials', DEFAULT.application).then(result => {
|
||||||
localStorage.removeItem(`${DEFAULT.application}#privKey`);
|
localStorage.removeItem(`${DEFAULT.application}#privKey`);
|
||||||
@ -599,7 +599,7 @@
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
floDapps.deleteUserData = function(credentials = false) {
|
floDapps.deleteUserData = function (credentials = false) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
let p = []
|
let p = []
|
||||||
p.push(compactIDB.deleteDB(user.db_name))
|
p.push(compactIDB.deleteDB(user.db_name))
|
||||||
@ -611,7 +611,7 @@
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
floDapps.deleteAppData = function() {
|
floDapps.deleteAppData = function () {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
compactIDB.deleteDB(DEFAULT.application).then(result => {
|
compactIDB.deleteDB(DEFAULT.application).then(result => {
|
||||||
localStorage.removeItem(`${DEFAULT.application}#privKey`)
|
localStorage.removeItem(`${DEFAULT.application}#privKey`)
|
||||||
@ -623,7 +623,7 @@
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
floDapps.securePrivKey = function(pwd) {
|
floDapps.securePrivKey = function (pwd) {
|
||||||
return new Promise(async (resolve, reject) => {
|
return new Promise(async (resolve, reject) => {
|
||||||
let indexArr = localStorage.getItem(`${DEFAULT.application}#privKey`)
|
let indexArr = localStorage.getItem(`${DEFAULT.application}#privKey`)
|
||||||
if (!indexArr)
|
if (!indexArr)
|
||||||
@ -643,8 +643,8 @@
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
floDapps.verifyPin = function(pin = null) {
|
floDapps.verifyPin = function (pin = null) {
|
||||||
const readSharesFromIDB = function(indexArr) {
|
const readSharesFromIDB = function (indexArr) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
var promises = []
|
var promises = []
|
||||||
for (var i = 0; i < indexArr.length; i++)
|
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)
|
var fk = floCloudAPI.util.filterKey(type, options)
|
||||||
vectorClock = vectorClock || getNextGeneralData[fk] || '0';
|
vectorClock = vectorClock || getNextGeneralData[fk] || '0';
|
||||||
var filteredResult = {}
|
var filteredResult = {}
|
||||||
@ -716,10 +716,10 @@
|
|||||||
let tmp = floCrypto.decryptData(data.message, key)
|
let tmp = floCrypto.decryptData(data.message, key)
|
||||||
data.message = JSON.parse(tmp)
|
data.message = JSON.parse(tmp)
|
||||||
break;
|
break;
|
||||||
} catch (error) {}
|
} catch (error) { }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (error) {}
|
} catch (error) { }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
getNextGeneralData[fk] = Object.keys(filteredResult).sort().pop();
|
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,
|
floID: data.senderID,
|
||||||
update: data.message,
|
update: data.message,
|
||||||
time: data.vectorClock.split('_')[0],
|
time: data.vectorClock.split('_')[0],
|
||||||
note: data.note
|
note: data.note,
|
||||||
|
tag: data.tag
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
internUpdates = internUpdates.filter(data => data.floID in _.internList)
|
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