Added aggregate feature

This commit is contained in:
sairaj mote 2023-05-11 22:04:56 +05:30
parent 40560c5824
commit b3181e66d8
5 changed files with 174 additions and 89 deletions

File diff suppressed because one or more lines are too long

View File

@ -264,22 +264,31 @@ sm-option {
font-size: 0.9rem; font-size: 0.9rem;
--border-radius: 0.3rem; --border-radius: 0.3rem;
} }
sm-option::part(option) {
grid-template-columns: none;
}
strip-select { sm-chips {
--gap: 0; --gap: 0;
background-color: rgba(var(--text-color), 0.06); background-color: rgba(var(--text-color), 0.06);
border-radius: 0.3rem; border-radius: 0.3rem;
padding: 0.3rem; padding: 0.3rem;
} }
strip-option { sm-chip {
position: relative; position: relative;
font-size: 0.8rem; font-size: 0.9rem;
--border-radius: 0.2rem; --border-radius: 0.3rem;
--padding: 0.5rem 0.8rem;
--background: rgba(var(--text-color), 0.06);
-webkit-user-select: none; -webkit-user-select: none;
-moz-user-select: none; -moz-user-select: none;
user-select: none; user-select: none;
} }
sm-chip[selected] {
--background: var(--accent-color);
color: rgba(var(--background-color), 1);
}
sm-button { sm-button {
--border-radius: 0.3rem; --border-radius: 0.3rem;
@ -310,8 +319,6 @@ ul {
overflow-wrap: break-word; overflow-wrap: break-word;
word-wrap: break-word; word-wrap: break-word;
word-break: break-word; word-break: break-word;
-webkit-hyphens: auto;
hyphens: auto;
} }
.full-bleed { .full-bleed {
@ -322,8 +329,8 @@ ul {
text-transform: uppercase; text-transform: uppercase;
} }
.capitalize { .capitalize::first-letter {
text-transform: capitalize; text-transform: uppercase;
} }
.sticky { .sticky {
@ -1065,14 +1072,14 @@ th.ascending::after {
content: " ▲"; content: " ▲";
} }
#group_by::part(popup) { #sheet_processing_popup::part(popup) {
min-height: 80vh; min-height: 80vh;
} }
#group_by sm-select:last-of-type { #sheet_processing_popup sm-select:last-of-type {
margin-left: 0.5rem; margin-left: 0.5rem;
} }
#group_by th, #sheet_processing_popup th,
#group_by td { #sheet_processing_popup td {
padding: 1rem; padding: 1rem;
} }
@ -1313,7 +1320,7 @@ th.ascending::after {
} }
@media screen and (max-width: 640px) { @media screen and (max-width: 640px) {
#group_by_view { #processed_sheet_view {
overflow: auto; overflow: auto;
max-width: calc(100vw - 3rem); max-width: calc(100vw - 3rem);
} }
@ -1375,8 +1382,11 @@ th.ascending::after {
position: relative; position: relative;
transform: none; transform: none;
} }
#group_by::part(popup) { #sheet_processing_popup {
width: 80vw; --width: 36rem;
}
#sheet_processing_popup[data-mode=group] {
--width: 80vw;
} }
#save_button { #save_button {
margin: 1rem auto; margin: 1rem auto;

2
css/main.min.css vendored

File diff suppressed because one or more lines are too long

View File

@ -261,20 +261,29 @@ sm-select {
sm-option { sm-option {
font-size: 0.9rem; font-size: 0.9rem;
--border-radius: 0.3rem; --border-radius: 0.3rem;
&::part(option) {
grid-template-columns: none;
}
} }
strip-select { sm-chips {
--gap: 0; --gap: 0;
background-color: rgba(var(--text-color), 0.06); background-color: rgba(var(--text-color), 0.06);
border-radius: 0.3rem; border-radius: 0.3rem;
padding: 0.3rem; padding: 0.3rem;
} }
strip-option { sm-chip {
position: relative; position: relative;
font-size: 0.8rem; font-size: 0.9rem;
--border-radius: 0.2rem; --border-radius: 0.3rem;
--padding: 0.5rem 0.8rem;
--background: rgba(var(--text-color), 0.06);
user-select: none; user-select: none;
&[selected] {
--background: var(--accent-color);
color: rgba(var(--background-color), 1);
}
} }
sm-button { sm-button {
@ -313,7 +322,6 @@ ul {
overflow-wrap: break-word; overflow-wrap: break-word;
word-wrap: break-word; word-wrap: break-word;
word-break: break-word; word-break: break-word;
hyphens: auto;
} }
.full-bleed { .full-bleed {
@ -325,7 +333,9 @@ ul {
} }
.capitalize { .capitalize {
text-transform: capitalize; &::first-letter {
text-transform: uppercase;
}
} }
.sticky { .sticky {
@ -1040,7 +1050,7 @@ th.ascending::after {
content: " \25B2"; content: " \25B2";
} }
#group_by { #sheet_processing_popup {
&::part(popup) { &::part(popup) {
min-height: 80vh; min-height: 80vh;
} }
@ -1262,7 +1272,7 @@ th.ascending::after {
} }
@media screen and (max-width: 640px) { @media screen and (max-width: 640px) {
#group_by_view { #processed_sheet_view {
overflow: auto; overflow: auto;
max-width: calc(100vw - 3rem); max-width: calc(100vw - 3rem);
} }
@ -1326,9 +1336,10 @@ th.ascending::after {
position: relative; position: relative;
transform: none; transform: none;
} }
#group_by { #sheet_processing_popup {
&::part(popup) { --width: 36rem;
width: 80vw; &[data-mode="group"] {
--width: 80vw;
} }
} }
#save_button { #save_button {

View File

@ -8,7 +8,9 @@
<link rel="stylesheet" href="css/main.min.css"> <link rel="stylesheet" href="css/main.min.css">
<link rel="preconnect" href="https://fonts.googleapis.com"> <link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap" rel="stylesheet"> <link
href="https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,400;0,500;0,700;1,400;1,500;1,700&display=swap"
rel="stylesheet">
<script src="https://unpkg.com/uhtml@3.0.1/es.js"></script> <script src="https://unpkg.com/uhtml@3.0.1/es.js"></script>
<script id="floGlobals"> <script id="floGlobals">
/* Constants for FLO blockchain operations !!Make sure to add this at begining!! */ /* Constants for FLO blockchain operations !!Make sure to add this at begining!! */
@ -97,10 +99,10 @@
<sm-notifications id="notification_drawer"></sm-notifications> <sm-notifications id="notification_drawer"></sm-notifications>
<sm-popup id="confirmation_popup"> <sm-popup id="confirmation_popup">
<h4 id="confirm_title"></h4> <h4 id="confirm_title"></h4>
<p id="confirm_message"></p> <p id="confirm_message" class="breakable"></p>
<div class="flex align-center"> <div class="flex align-center gap-0-5 margin-left-auto">
<sm-button variant="no-outline" class="cancel-button">Cancel</sm-button> <button class="button cancel-button">Cancel</button>
<sm-button variant="no-outline" class="confirm-button">OK</button> <button class="button button--primary confirm-button">OK</button>
</div> </div>
</sm-popup> </sm-popup>
<!-- Loading screen--> <!-- Loading screen-->
@ -123,10 +125,10 @@
<p>Open &bull; Distributed &bull; Reliable</p> <p>Open &bull; Distributed &bull; Reliable</p>
</div> </div>
<div class="sign-in-box flex flex-direction-column gap-2"> <div class="sign-in-box flex flex-direction-column gap-2">
<strip-select id="entry_type_selector" class="align-self-start"> <sm-chips id="entry_type_selector" class="align-self-start">
<strip-option value="sign-in" selected>Sign in</strip-option> <sm-chip value="sign-in" selected>Sign in</sm-chip>
<strip-option value="sign-up">Sign up</strip-option> <sm-chip value="sign-up">Sign up</sm-chip>
</strip-select> </sm-chips>
<div id="user_entry"> <div id="user_entry">
<div> <div>
<h3>Welcome back</h3> <h3>Welcome back</h3>
@ -221,8 +223,12 @@
</svg> </svg>
Sheets Sheets
</a> </a>
<button class="button button--small margin-left-auto" onclick="openPopup('group_by')">Group <div id="sheet_processing_options" class="flex gap-0-5 margin-left-auto hidden">
by</button> <button class="button button--small" onclick="initSheetProcessing('group')">Group
by</button>
<button class="button button--small" onclick="initSheetProcessing('aggregate')">Aggregate
by</button>
</div>
</div> </div>
<div class="flex align-center"> <div class="flex align-center">
<button onclick="toggleSideBar()"> <button onclick="toggleSideBar()">
@ -366,7 +372,7 @@
</sm-popup> </sm-popup>
<!-- Group by popup --> <!-- Group by popup -->
<sm-popup id="group_by"> <sm-popup id="sheet_processing_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()">
<svg class="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"> <svg class="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
@ -375,19 +381,19 @@
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" /> 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> </svg>
</button> </button>
<h3 id="group_by_title"> </h3> <h3 id="sheet_processing_title"> </h3>
</header> </header>
<div class="flex align-center" id="group_by_menu"> <div class="flex align-center" id="group_by_menu">
<sm-select id="first_select"> <sm-select id="process_by_method_selector">
<sm-option value="count">Count</sm-option> <sm-option value="count">Count</sm-option>
<sm-option value="total" selected>Total</sm-option> <sm-option value="total" selected>Total</sm-option>
<sm-option value="avg">Avg</sm-option> <sm-option value="avg">Avg</sm-option>
<sm-option value="max">Max</sm-option> <sm-option value="max">Max</sm-option>
<sm-option value="min">Min</sm-option> <sm-option value="min">Min</sm-option>
</sm-select> </sm-select>
<sm-select id="second_select"></sm-select> <sm-select id="process_by_attribute_selector"></sm-select>
</div> </div>
<div class="table-container" id="group_by_view"></div> <div id="processed_sheet_view" class="grid"></div>
</sm-popup> </sm-popup>
<script src="components.js"></script> <script src="components.js"></script>
<script> <script>
@ -464,43 +470,51 @@
}, wait); }, wait);
}; };
} }
let zIndex = 50 let zIndex = 50
// function required for popups or modals to appear // function required for popups or modals to appear
function openPopup(popupId, pinned) { function openPopup(popupId, pinned) {
zIndex++ zIndex++
getRef(popupId).setAttribute('style', `z-index: ${zIndex}`) getRef(popupId).setAttribute('style', `z-index: ${zIndex}`)
getRef(popupId).show({ pinned }) return getRef(popupId).show({ pinned })
return getRef(popupId);
} }
// hides the popup or modal // hides the popup or modal
function closePopup() { function closePopup(options = {}) {
if (popupStack.peek() === undefined) if (popupStack.peek() === undefined)
return; return;
popupStack.peek().popup.hide() popupStack.peek().popup.hide(options)
} }
// displays a popup for asking permission. Use this instead of JS confirm // displays a popup for asking permission. Use this instead of JS confirm
const getConfirmation = (title, options = {}) => { const getConfirmation = (title, options = {}) => {
return new Promise(resolve => { return new Promise(resolve => {
const { message = '', cancelText = 'Cancel', confirmText = 'OK' } = options const { message = '', cancelText = 'Cancel', confirmText = 'OK', danger = false } = options
openPopup('confirmation_popup', true)
getRef('confirm_title').innerText = title; getRef('confirm_title').innerText = title;
getRef('confirm_message').innerText = message; getRef('confirm_message').innerText = message;
const cancelButton = getRef('confirmation_popup').querySelector('.cancel-button'); const cancelButton = getRef('confirmation_popup').querySelector('.cancel-button');
const confirmButton = getRef('confirmation_popup').querySelector('.confirm-button') const confirmButton = getRef('confirmation_popup').querySelector('.confirm-button')
confirmButton.textContent = confirmText confirmButton.textContent = confirmText
cancelButton.textContent = cancelText cancelButton.textContent = cancelText
if (danger)
confirmButton.classList.add('button--danger')
else
confirmButton.classList.remove('button--danger')
const { opened, closed } = openPopup('confirmation_popup')
confirmButton.onclick = () => { confirmButton.onclick = () => {
closePopup() closePopup({ payload: true })
resolve(true);
} }
cancelButton.onclick = () => { cancelButton.onclick = () => {
closePopup() closePopup()
resolve(false);
} }
closed.then((payload) => {
confirmButton.onclick = null
cancelButton.onclick = null
if (payload)
resolve(true)
else
resolve(false)
})
}) })
} }
@ -770,10 +784,9 @@
} }
document.addEventListener('popupopened', e => { document.addEventListener('popupopened', e => {
let popup = e.detail.popup switch (e.target.id) {
switch (popup.id) { case 'sheet_processing_popup':
case 'group_by': renderProcessedSheet()
renderGroup()
break; break;
case 'profile_popup': case 'profile_popup':
renderElem(getRef('profile_popup__content'), render.profile()) renderElem(getRef('profile_popup__content'), render.profile())
@ -781,14 +794,13 @@
} }
}) })
document.addEventListener('popupclosed', e => { document.addEventListener('popupclosed', e => {
let popup = e.detail.popup switch (e.target.id) {
switch (popup.id) {
case 'new_sheet_popup': case 'new_sheet_popup':
getRef('columns_container').innerHTML = '' getRef('columns_container').innerHTML = ''
getRef('editors_container').innerHTML = '' getRef('editors_container').innerHTML = ''
break; break;
case 'group_by': case 'sheet_processing_popup':
renderElem(getRef("group_by_view"), html``) renderElem(getRef("processed_sheet_view"), html``)
break; break;
} }
}) })
@ -1105,24 +1117,74 @@
} }
}).catch(error => notify(`Save Unsuccessful [${error}]`, error)) }).catch(error => notify(`Save Unsuccessful [${error}]`, error))
}) })
function initSheetProcessing(type) {
floGlobals.sheetProcessingMode = type
switch (type) {
case 'group':
getRef('sheet_processing_title').textContent = `Group ${floGlobals.currentSheet.title} by`
break;
case 'aggregate':
getRef('sheet_processing_title').textContent = `Aggregate ${floGlobals.currentSheet.title} by`
break;
default:
break;
}
getRef('sheet_processing_popup').dataset.mode = type
openPopup('sheet_processing_popup')
}
getRef('first_select').addEventListener("change", renderGroup) getRef('process_by_method_selector').addEventListener("change", renderProcessedSheet)
getRef('second_select').addEventListener("change", renderGroup) getRef('process_by_attribute_selector').addEventListener("change", renderProcessedSheet)
function renderGroup() { function renderProcessedSheet() {
try { try {
const type = getRef('first_select').value const type = getRef('process_by_method_selector').value
const column = getRef('second_select').value const column = getRef('process_by_attribute_selector').value
const { sheetId, sheet } = floGlobals.currentSheet const { sheetId, sheet } = floGlobals.currentSheet
if (type === 'count') { switch (floGlobals.sheetProcessingMode) {
getRef('second_select').classList.add("hidden") case 'group':
let data = logSheet.groupBy.count(sheetId, sheet) if (type === 'count') {
renderGroupByView("count", data) getRef('process_by_attribute_selector').classList.add("hidden")
} else { let data = logSheet.groupBy.count(sheetId, sheet)
getRef('second_select').classList.remove("hidden") renderGroupByView("count", data)
let data = logSheet.groupBy[type](sheetId, sheet, column); } else {
renderGroupByView(`${type}(${column})`, data) getRef('process_by_attribute_selector').classList.remove("hidden")
let data = logSheet.groupBy[type](sheetId, sheet, column);
renderGroupByView(`${type}(${column})`, data)
}
break;
case 'aggregate':
let data = logSheet.aggBy[type](sheetId, sheet, column);
if (type === 'count') {
getRef('process_by_attribute_selector').classList.add("hidden")
} else {
getRef('process_by_attribute_selector').classList.remove("hidden")
}
if (data) {
if (type === 'count') {
renderElem(getRef('processed_sheet_view'), html`
<div class="grid gap-0-5 text-center" style="padding: 3rem 0;">
<h1>${data}</h1>
Total entries
</div>
`)
} else {
renderElem(getRef('processed_sheet_view'), html`
<div class="grid gap-0-5 text-center" style="padding: 3rem 0;">
<h1>${data}</h1>
<div class="capitalize">${type} ${column}</div>
</div>
`)
}
} else {
renderElem(getRef('processed_sheet_view'), html`
<h4 style="padding: 1.5rem 0;">${column} doesn't have numeric values</h4>
`)
}
break;
default:
break;
} }
} catch (error) { } catch (error) {
notify(error, "error") notify(error, "error")
@ -1252,6 +1314,7 @@
getRef('sheet_type').classList.add('placeholder') getRef('sheet_type').classList.add('placeholder')
getRef('sheet_description').classList.add('placeholder') getRef('sheet_description').classList.add('placeholder')
getRef('sheet_container__header').classList.add('hidden') getRef('sheet_container__header').classList.add('hidden')
getRef('sheet_processing_options').classList.add('hidden')
showPage('sheet_view') showPage('sheet_view')
logSheet.refreshLogs(sheetId).then(result => { logSheet.refreshLogs(sheetId).then(result => {
getRef('sheet_container').classList.remove('placeholder') getRef('sheet_container').classList.remove('placeholder')
@ -1363,9 +1426,9 @@
} }
getRef('sheet_container__body').append(frag) getRef('sheet_container__body').append(frag)
if (!onlyRenderTable) { if (!onlyRenderTable) {
getRef('group_by_title').textContent = `Group ${title} by`;
//Add options for groupBy //Add options for groupBy
renderElem(getRef('second_select'), html`${attributes.map(attr => html`<sm-option value="${attr}">${attr}</sm-option>`)}`) renderElem(getRef('process_by_attribute_selector'), html`${attributes.map(attr => html`<sm-option value="${attr}" class="wrap-around">${attr}</sm-option>`)}`)
getRef('sheet_processing_options').classList.remove('hidden')
} }
} }
@ -1388,7 +1451,7 @@
}) })
function renderGroupByView(groupName, groupData) { function renderGroupByView(groupName, groupData) {
renderElem(getRef("group_by_view"), html` renderElem(getRef("processed_sheet_view"), html`
<table class="margin-top-1"> <table class="margin-top-1">
<thead> <thead>
<tr> <tr>