Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,14 @@

import ai.elimu.dao.StoryBookLearningEventDao;
import ai.elimu.model.analytics.StoryBookLearningEvent;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
Expand All @@ -26,6 +33,36 @@ public String handleRequest(Model model) {

List<StoryBookLearningEvent> storyBookLearningEvents = storyBookLearningEventDao.readAllOrderedByTime();
model.addAttribute("storyBookLearningEvents", storyBookLearningEvents);

// Prepare data for chart in UI
List<String> monthList = new ArrayList<>();
List<Integer> eventCountList = new ArrayList<>();
if (!storyBookLearningEvents.isEmpty()) {
// Group event count by month (e.g. "Aug-2024", "Sep-2024")
Map<String, Integer> eventCountByMonthMap = new HashMap<>();
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("MMM-yyyy");
for (StoryBookLearningEvent event : storyBookLearningEvents) {
String eventMonth = simpleDateFormat.format(event.getTimestamp().getTime());
eventCountByMonthMap.put(eventMonth, eventCountByMonthMap.getOrDefault(eventMonth, 0) + 1);
}

// Iterate each month from 4 years ago until now
Calendar calendar4YearsAgo = Calendar.getInstance();
calendar4YearsAgo.add(Calendar.YEAR, -4);
Calendar calendarNow = Calendar.getInstance();
Calendar month = calendar4YearsAgo;
while (!month.after(calendarNow)) {
String monthAsString = simpleDateFormat.format(month.getTime());
monthList.add(monthAsString);

eventCountList.add(eventCountByMonthMap.getOrDefault(monthAsString, 0));

// Increase the date by 1 month
month.add(Calendar.MONTH, 1);
}
}
model.addAttribute("monthList", monthList);
model.addAttribute("eventCountList", eventCountList);

return "analytics/storybook-learning-event/list";
}
Expand Down
124 changes: 21 additions & 103 deletions src/main/webapp/WEB-INF/jsp/analytics/layout.jsp
Original file line number Diff line number Diff line change
Expand Up @@ -45,111 +45,29 @@
</div>

<nav class="deep-purple lighten-1">
<div class="nav-wrapper container">
<a id="logo-container" href="<spring:url value='/' />" class="brand-logo">
<img src="<spring:url value='/static/img/logo-text-256x77.png' />" alt="elimu.ai" />
</a>
<sec:authorize access="!hasAnyRole('ROLE_ADMIN','ROLE_CONTRIBUTOR')">
<ul class="right hide-on-med-and-down">
<li><a href="<spring:url value='/sign-on' />"><fmt:message key="sign.on" /></a></li>
</ul>
<div class="row nav-wrapper">
<div class="col s1">
<ul id="nav-mobile" class="side-nav">
<li><a href="<spring:url value='/sign-on' />"><fmt:message key="sign.on" /></a></li>
</ul>
</sec:authorize>
<sec:authorize access="hasAnyRole('ROLE_ADMIN','ROLE_CONTRIBUTOR')">
<ul class="right">
<a href="<spring:url value='/content' />">
<div class="chip">
<c:choose>
<c:when test="${not empty contributor.imageUrl}">
<img src="${contributor.imageUrl}" />
</c:when>
<c:when test="${not empty contributor.providerIdWeb3}">
<img src="https://effigy.im/a/<c:out value="${contributor.providerIdWeb3}" />.png" />
</c:when>
<c:otherwise>
<img src="<spring:url value='/static/img/placeholder.png' />" />
</c:otherwise>
</c:choose>
<c:choose>
<c:when test="${not empty contributor.firstName}">
<c:out value="${contributor.firstName}" />&nbsp;<c:out value="${contributor.lastName}" />
</c:when>
<c:when test="${not empty contributor.providerIdWeb3}">
${fn:substring(contributor.providerIdWeb3, 0, 6)}...${fn:substring(contributor.providerIdWeb3, 38, 42)}
</c:when>
</c:choose>
</div>
</a>
</ul>
</sec:authorize>

<ul class="right">
<script>
/**
* Fetch token balance
*/
async function getBalance(contributorAddress) {
console.info('getBalance');

// Connect to the web3 provider.
const provider = await connect()
window.web3 = new Web3(provider);
console.info('window.web3: ' + window.web3);

var contractAbi = [{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}];
var contractAddress = '0xe29797910d413281d2821d5d9a989262c8121cc2';
var contract = new window.web3.eth.Contract(contractAbi, contractAddress);
var balance = await contract.methods.balanceOf(contributorAddress).call();

return balance;
}
</script>
<c:choose>
<c:when test="${empty contributor.providerIdWeb3}">
<a class="btn tokenButton" href="<spring:url value='/sign-on/web3' />">
<svg style="width: 24px; height: 24px; top: 6px; position: relative; right: 5px;" viewBox="0 0 784.37 1277.39" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xodm="http://www.corel.com/coreldraw/odm/2003">
<g>
<polygon fill="#343434" fill-rule="nonzero" points="392.07,0 383.5,29.11 383.5,873.74 392.07,882.29 784.13,650.54 "/>
<polygon fill="#8C8C8C" fill-rule="nonzero" points="392.07,0 -0,650.54 392.07,882.29 392.07,472.33 "/>
<polygon fill="#3C3C3B" fill-rule="nonzero" points="392.07,956.52 387.24,962.41 387.24,1263.28 392.07,1277.38 784.37,724.89 "/>
<polygon fill="#8C8C8C" fill-rule="nonzero" points="392.07,1277.38 392.07,956.52 -0,724.89 "/>
<polygon fill="#141414" fill-rule="nonzero" points="392.07,882.29 784.13,650.54 392.07,472.33 "/>
<polygon fill="#393939" fill-rule="nonzero" points="0,650.54 392.07,882.29 392.07,472.33 "/>
</g>
</svg>&nbsp;Connect wallet
</a>
</c:when>
<c:otherwise>
<c:set var="etherscanUrl" value="https://etherscan.io" />
<c:if test="${applicationScope.configProperties['env'] != 'PROD'}">
<c:set var="etherscanUrl" value="https://rinkeby.etherscan.io" />
</c:if>
<a class="btn tokenButton" href="${etherscanUrl}/token/0xe29797910d413281d2821d5d9a989262c8121cc2?a=${contributor.providerIdWeb3}" target="_blank">
<code><span id="tokenBalance">0</span> $ELIMU</code>
<li>
<a href="<spring:url value='/analytics' />">
<img style="max-width: 100%; vertical-align: middle; max-height: 60%;" src="<spring:url value='/static/img/logo-text-256x78.png' />" alt="elimu.ai" />
</a>
<script>
$(function() {
var contributorAddress = '${contributor.providerIdWeb3}';
getBalance(contributorAddress).then(function(result) {
console.info('result: ' + result);

var tokenBalance = result / 1000000000000000000;
console.info('tokenBalance: ' + tokenBalance);

var tokenBalanceFormatted = Intl.NumberFormat().format(Math.round(tokenBalance));
console.info('tokenBalanceFormatted ' + tokenBalanceFormatted);

$('#tokenBalance').html(tokenBalanceFormatted);
});
});
</script>
</c:otherwise>
</c:choose>
</ul>

<a href="#" data-activates="nav-mobile" class="button-collapse"><i class="material-icons">menu</i></a>
</li>

<li class="divider"></li>
<li class="grey-text"><b><fmt:message key="learning.events" /></b></li>
<li><a href="<spring:url value='/analytics/letter-learning-event/list' />"><i class="material-icons left">text_format</i><fmt:message key="letters" /></a></li>
<li><a href="<spring:url value='/analytics/word-learning-event/list' />"><i class="material-icons left">sms</i><fmt:message key="words" /></a></li>
<li><a href="<spring:url value='/analytics/storybook-learning-event/list' />"><i class="material-icons left">book</i><fmt:message key="storybooks" /></a></li>
</ul>
<a id="navButton" href="<spring:url value='/analytics' />" data-activates="nav-mobile" class="waves-effect waves-light"><i class="material-icons">dehaze</i></a>
</div>
<div class="col s11">
<a href="<spring:url value='/analytics' />" class="breadcrumb"><fmt:message key="analytics" /></a>
<c:if test="${!fn:contains(pageContext.request.requestURI, '/jsp/analytics/main.jsp')}">
<a class="breadcrumb"><content:gettitle /></a>
</c:if>
</div>
</div>
</nav>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,15 @@
<canvas id="myChart" width="400" height="100"></canvas>
<script>
const labels = [
'January',
'February',
'March',
'April',
'May',
'June',
<c:forEach var="month" items="${monthList}">'${month}',</c:forEach>
];
const data = {
labels: labels,
datasets: [{
label: 'My First dataset',
label: 'Learning events',
backgroundColor: 'rgba(149,117,205, 0.5)',
borderColor: 'rgba(149,117,205, 0.5)',
data: [0, 10, 5, 2, 20, 30, 45],
data: <c:out value="${eventCountList}" />
}]
};
const config = {
Expand Down