Commit 138c65f1 authored by Curtis Adam's avatar Curtis Adam

Add an option to display the pool and repetitorium results as wordcloud

parent c2b06382
......@@ -2,6 +2,7 @@
@import '../imports/ui/main/main.scss';
@import '../imports/ui/impressum/impressum.scss';
@import '../imports/ui/welcome/welcome.scss';
@import '../imports/ui/wordcloud/wordcloud.scss';
@import '../imports/ui/cardsets/cardsets.scss';
@import '../imports/ui/cardset/cardset.scss';
@import '../imports/ui/cardsets/resultItem';
......
......@@ -453,7 +453,11 @@ $themes: (
$sweet_alert_2_icon_info_text: map-get($map, "sweet_alert_2_icon_info_text");
$sweet_alert_2_icon_question_border: map-get($map, "sweet_alert_2_icon_question_border");
$sweet_alert_2_icon_question_text: map-get($map, "sweet_alert_2_icon_question_text");
//wordcloud tooltip
$wordcloud_tooltip_text: map-get($map, "wordcloud_tooltip_text");
$wordcloud_tooltip_backgroud: map-get($map, "wordcloud_tooltip_backgroud");
$wordcloud_tooltip_border: map-get($map, "wordcloud_tooltip_border");
$wordcloud_tooltip_divider: map-get($map, "wordcloud_tooltip_divider");
background-image: $background_image !important;
.star-ratings .current-rating {
......@@ -1157,6 +1161,10 @@ $themes: (
}
}
#cardsetLink {
color: $hyperlink !important;
}
.btn.btn-raised.btn-primary {
background-color: $primary !important;
color: $white !important;
......@@ -2183,6 +2191,10 @@ $themes: (
color: $white !important;
}
#displayModeBtn {
color: $white !important;
}
.btn-demo, .btn-warning, .btn-info, .btn-success, .btn-danger {
background-color: $disabled_background !important;
border-color: $disabled_background !important;
......@@ -2584,5 +2596,15 @@ $themes: (
border-color: $sweet_alert_2_icon_question_border !important;
color: $sweet_alert_2_icon_question_text !important;
}
//wordcloud tooltip
.wordcloud-tooltip {
color: $wordcloud_tooltip_text !important;
background-color: $wordcloud_tooltip_backgroud !important;
border-color: $wordcloud_tooltip_border !important;
hr {
color: $wordcloud_tooltip_divider !important;
}
}
}
}
......@@ -454,6 +454,11 @@
"sweet_alert_2_icon_info_border": $thm_dark_blue,
"sweet_alert_2_icon_info_text": $thm_dark_blue,
"sweet_alert_2_icon_question_border": $thm_gray,
"sweet_alert_2_icon_question_text": $thm_gray
"sweet_alert_2_icon_question_text": $thm_gray,
//wordcloud tooltip
"wordcloud_tooltip_text": $white,
"wordcloud_tooltip_backgroud": $thm_gray,
"wordcloud_tooltip_border": $white,
"wordcloud_tooltip_divider": $white
);
}
......@@ -456,6 +456,11 @@
"sweet_alert_2_icon_info_border": $thm_dark_blue,
"sweet_alert_2_icon_info_text": $thm_dark_blue,
"sweet_alert_2_icon_question_border": $thm_gray,
"sweet_alert_2_icon_question_text": $thm_gray
"sweet_alert_2_icon_question_text": $thm_gray,
//wordcloud tooltip
"wordcloud_tooltip_text": $white,
"wordcloud_tooltip_backgroud": $thm_gray,
"wordcloud_tooltip_border": $white,
"wordcloud_tooltip_divider": $white
);
}
......@@ -42,6 +42,15 @@
"deactivate": ""
}
},
"backend": {
"settings": {
"title": "Zeige Pomodoro statt Wortwolke auf der Landing-Page",
"button": {
"enabled": "Aktiviert",
"disabled": "Deaktiviert"
}
}
},
"form": {
"time": {
"hour": "1 Stunde",
......@@ -902,7 +911,8 @@
"wordcloudEveryting": "Alle",
"from": "Ab",
"noResults": "Keine Karteien oder Repetitorien vorhanden oder keine Ergebnisse für diese Filtereinstellung",
"sort": "Sortieren "
"sort": "Sortieren ",
"displayMode": "Liste | Wolke"
},
"infinite-scroll": {
"remainingCardsets": "__current__ von __total__ Karteien",
......
......@@ -42,6 +42,15 @@
"deactivate": ""
}
},
"backend": {
"settings": {
"title": "Show Pomodoro instead of word cloud on landing page",
"button": {
"enabled": "Enabled",
"disabled": "Disabled"
}
}
},
"form": {
"time": {
"hour": "hour",
......@@ -949,7 +958,8 @@
"wordcloudEveryting": "All",
"from": "From",
"noResults": "No results for this filter setting",
"sort": "Sort: "
"sort": "Sort: ",
"displayMode": "List | Cloud"
},
"infinite-scroll": {
"remainingCardsets": "__current__ of __total__ Cardsets",
......
......@@ -5,6 +5,9 @@ import {check} from "meteor/check";
export const AdminSettings = new Mongo.Collection("adminSettings");
if (Meteor.isServer) {
Meteor.publish('pomodoroLandingPage', function () {
return AdminSettings.find({name: "wordcloudPomodoroSettings"});
});
Meteor.publish('default_db_data', function () {
if (this.userId && !Roles.userIsInRole(this.userId, ["firstLogin", "blocked"])) {
if (Roles.userIsInRole(this.userId, ["admin", "editor"])) {
......@@ -17,6 +20,21 @@ if (Meteor.isServer) {
}
Meteor.methods({
updateWordcloudPomodoroSettings: function (enableWordcloudPomodoro) {
check(enableWordcloudPomodoro, Boolean);
if (!Roles.userIsInRole(this.userId, ["admin", "editor"])) {
throw new Meteor.Error("not-authorized");
}
AdminSettings.upsert({
name: "wordcloudPomodoroSettings"
},
{
$set: {
enabled: enableWordcloudPomodoro
}
});
},
updateMailSettings: function (enableMails) {
check(enableMails, Boolean);
......
......@@ -3,6 +3,7 @@ import {FilterNavigation} from "./filterNavigation";
import {Session} from "meteor/session";
import {Cardsets} from "./cardsets";
import {Route} from "./route";
import {WordcloudCanvas} from "./wordcloudCanvas";
import {Leitner, Wozniak} from "./learned";
let itemIncrementCounter = 6;
......@@ -116,6 +117,9 @@ export let Filter = class Filter {
break;
}
this.resetInfiniteBar();
if (FilterNavigation.isDisplayWordcloudActive(FilterNavigation.getRouteId())) {
WordcloudCanvas.draw();
}
}
static workloadFilter () {
......
import {Route} from "./route.js";
import {Session} from "meteor/session";
//0: Themen-Pool / Pool
//1: Kartei anlegen / My Cardsets
//2: Kurse / Course
//2: Repetitorien / Repetitorium
//3: Lernpensum / Learning
//4: Alle Karteien / All Cardsets
//5: Kartei mischen / Shuffle
let filtersWithResetButton = [0, 1, 2, 3, 4, 5];
let filtersWithDisplayModeButton = [0, 2, 4];
let filtersWithSortButton = [0, 1, 2, 3, 4, 5];
let filtersWithDefaultSortName = [0, 1, 2, 3, 5];
let filtersWithDefaultSortDateUpdated = [4];
......@@ -88,7 +90,15 @@ export let FilterNavigation = class FilterNavigation {
}
static gotSortButton (filterType) {
return filtersWithSortButton.includes(filterType);
if (this.isDisplayWordcloudActive(filterType)) {
return false;
} else {
return filtersWithSortButton.includes(filterType);
}
}
static isDisplayWordcloudActive (filterType) {
return this.gotDisplayModeButton(filterType) && Session.get('filterDisplayWordcloud');
}
static gotDefaultSortName (filterType) {
......@@ -100,11 +110,14 @@ export let FilterNavigation = class FilterNavigation {
return filtersWithDefaultSortDateUpdated.includes(filterType);
}
static gotResetButton (filterType) {
return filtersWithResetButton.includes(filterType);
}
static gotDisplayModeButton (filterType) {
return filtersWithDisplayModeButton.includes(filterType);
}
static getRouteId () {
if (Route.isPool()) {
return 0;
......
......@@ -3,6 +3,8 @@ import {Bonus} from "./bonus.js";
import {Cardsets} from "./cardsets.js";
import {Route} from "./route.js";
import swal from "sweetalert2";
import {WordcloudCanvas} from "./wordcloudCanvas";
import {AdminSettings} from "./adminSettings";
let defaultSettings = {
goal: 2,
......@@ -718,17 +720,24 @@ export let PomodoroTimer = class PomodoroTimer {
}
static showPomodoroFullsize () {
if ($(document).has('#pomoA').length) {
$('#bigClockDiv').addClass('zIndexFirstPrio bigDiv');
$('.pomodoroTimer').detach().appendTo('#bigClockDiv');
if ($(document).has('#pomodoroTimerNormalContainer').length) {
$('.pomodoroTimer').detach().appendTo('#pomodoroTimerOverlay');
isClockInBigmode = true;
$('#pomodoroTimerOverlay').css('display', 'block');
if ($(window).height() > $(window).width()) {
$('#pomodoroTimerOverlay .pomodoroClock').css('height', $(window).width());
} else {
$('#pomodoroTimerOverlay .pomodoroClock').css('height', $(window).height());
}
}
}
static showPomodoroNormal () {
if ($(document).has('#pomoA').length) {
$('#bigClockDiv').removeClass('zIndexFirstPrio bigDiv');
if ($(document).has('#pomodoroTimerNormalContainer').length) {
isClockInBigmode = false;
$('#pomodoroTimerOverlay').css('display', 'none');
$('#pomodoroTimerOverlay .pomodoroClock').css('height', 'unset');
WordcloudCanvas.draw();
this.pomoPosition();
}
}
......@@ -737,20 +746,18 @@ export let PomodoroTimer = class PomodoroTimer {
* PomoSetup for switching from bottom right to middle
*/
static pomoPosition () {
if (!PomodoroTimer.isClockInBigmode()) {
if (!cloudShown) {
$('.pomodoroTimer').detach().appendTo('#pomoA');
$('#pomoB').addClass('zIndexLowPrio');
$('.pomodoroClock').on('click', function () {
PomodoroTimer.clickClock();
});
} else if (cloudShown) {
$('.pomodoroTimer').detach().appendTo('#pomoB');
$('#pomoB').removeClass('zIndexLowPrio');
$('.pomodoroClock').on('click', function () {
PomodoroTimer.clickClock();
});
if (!PomodoroTimer.isClockInBigmode() && !Meteor.userId()) {
if (AdminSettings.findOne({name: "wordcloudPomodoroSettings"}).enabled || !cloudShown) {
$('.pomodoroTimer').detach().appendTo('#pomodoroTimerWordcloudContainer');
$('#pomodoroTimerWordcloudContainer').css('display', 'block');
$('#wordcloud-container').css('display', 'none');
} else {
$('.pomodoroTimer').detach().appendTo('#pomodoroTimerNormalContainer');
$('#pomodoroTimerWordcloudContainer').css('display', 'none');
$('#wordcloud-container').css('display', 'block');
}
} else {
$('#wordcloud-container').css('display', 'block');
}
}
......
import WordCloud from "wordcloud";
import {Cardsets} from "./cardsets.js";
import {Filter} from "./filter.js";
import {Session} from "meteor/session";
import * as fakeWordCloud from "../../public/fakeStatistics/wordcloud";
import {ReactiveVar} from 'meteor/reactive-var';
import {Meteor} from "meteor/meteor";
import {PomodoroTimer} from "./pomodoroTimer";
import {FilterNavigation} from "./filterNavigation";
import {AdminSettings} from "./adminSettings";
let clearCanvas;
let drawOutOfBound;
let gridSize;
let weightFactor;
let rotateRatio;
let fontFamily;
let color;
let backgroundColor;
let wait;
let wordcloudPomodoroSize = 0.6;
export let WordcloudCanvas = class WordcloudCanvas {
static setConfig () {
if (Meteor.userId()) {
clearCanvas = true;
drawOutOfBound = false;
gridSize = 24;
weightFactor = 24;
rotateRatio = 0;
fontFamily = 'Roboto Condensed, Arial Narrow, sans-serif';
color = "random-light";
backgroundColor = 'rgba(255,255,255, 0)';
wait = 50;
} else {
clearCanvas = true;
drawOutOfBound = false;
gridSize = 24;
weightFactor = 24;
rotateRatio = 0;
fontFamily = 'Roboto Condensed, Arial Narrow, sans-serif';
color = "random-light";
backgroundColor = 'rgba(255,255,255, 0)';
wait = 400;
}
}
static draw () {
if (document.getElementById('wordcloud-canvas') !== null) {
this.setCanvasSize();
if ($(window).width() >= 768 && Meteor.userId()) {
PomodoroTimer.setCloudShown(true);
this.setConfig();
let wordcloundContent = this.getContent();
this.setWordcloudTheme();
WordCloud(document.getElementById('wordcloud-canvas'),
{
clearCanvas: clearCanvas,
drawOutOfBound: drawOutOfBound,
list: wordcloundContent,
gridSize: gridSize,
weightFactor: weightFactor,
rotateRatio: rotateRatio,
fontFamily: fontFamily,
color: color,
hover: WordcloudCanvas.wordcloudHover,
click: WordcloudCanvas.wordcloudClick,
backgroundColor: backgroundColor,
wait: wait
});
} else if ($(window).width() >= 768 && !AdminSettings.findOne({name: "wordcloudPomodoroSettings"}).enabled) {
PomodoroTimer.setCloudShown(true);
this.setConfig();
let wordcloundContent = this.getContent();
if (Meteor.settings.public.welcome.fakeStatistics) {
this.setWordcloudTheme();
WordCloud(document.getElementById('wordcloud-canvas'),
{
clearCanvas: clearCanvas,
drawOutOfBound: drawOutOfBound,
list: wordcloundContent,
gridSize: gridSize,
weightFactor: weightFactor,
rotateRatio: rotateRatio,
fontFamily: fontFamily,
color: function (word) {
for (let i = 0; i < wordcloundContent.length; i++) {
if (word === wordcloundContent[i][0]) {
return wordcloundContent[i][3];
}
}
},
backgroundColor: backgroundColor,
wait: wait
});
} else {
this.setWordcloudTheme();
WordCloud(document.getElementById('wordcloud-canvas'),
{
clearCanvas: clearCanvas,
drawOutOfBound: drawOutOfBound,
list: wordcloundContent,
gridSize: gridSize,
weightFactor: weightFactor,
rotateRatio: rotateRatio,
fontFamily: fontFamily,
color: color,
hover: WordcloudCanvas.wordcloudHover,
click: WordcloudCanvas.wordcloudClick,
backgroundColor: backgroundColor,
wait: wait
});
}
} else {
PomodoroTimer.setCloudShown(false);
}
} else {
setTimeout(function () {
WordcloudCanvas.draw();
}, 100);
}
}
static setCanvasSize () {
if (Meteor.userId()) {
document.getElementById('wordcloud-canvas').width = ($('#wordcloud-container').width());
let filterNavigation = $('#filter-nav-wrapper');
document.getElementById('wordcloud-canvas').height = ($(window).height() - (filterNavigation.offset().top + filterNavigation.height()) - 30);
} else {
let newWidth = $('#wordcloud-container').width();
if (newWidth > 1024) {
newWidth = 1024;
}
document.getElementById('wordcloud-canvas').width = newWidth;
let newHeight = $(window).height() - ($('#welcome').outerHeight(true) + $('#welcome-login').outerHeight(true));
if ($(window).width() >= 768 && !AdminSettings.findOne({name: "wordcloudPomodoroSettings"}).enabled) {
document.getElementById('wordcloud-canvas').height = newHeight;
$('.pomodoroClock').css('height', 'unset');
} else {
$('#pomodoroTimerWordcloudContainer .pomodoroClock').css('margin-top', newHeight * ((1 - wordcloudPomodoroSize) / 2));
$('#pomodoroTimerWordcloudContainer .pomodoroClock').css('height', newHeight * wordcloudPomodoroSize);
this.disableWordcloud();
}
}
}
static wordcloudClick (item) {
Session.set('wordcloudItem', item[2]);
$('#wordcloudModal').modal('show');
}
static wordcloudHover (item, dimension) {
if (dimension !== undefined) {
$('#wordcloud-canvas').css('cursor', 'pointer');
} else {
$('#wordcloud-canvas').css('cursor', 'unset');
$('.wordcloud-tooltip').css('display', 'none');
}
}
static enableWordcloud () {
Session.set('filterDisplayWordcloud', true);
this.setWordcloudTheme();
}
static disableWordcloud () {
Session.set('filterDisplayWordcloud', false);
this.setWordcloudTheme();
}
static setWordcloudTheme () {
if (Meteor.userId()) {
if (FilterNavigation.isDisplayWordcloudActive(FilterNavigation.getRouteId())) {
$('html').attr('id', 'theme-wrapper-wordcloud');
} else {
$('html').attr('id', 'theme-wrapper');
}
} else {
$('html').attr('id', 'theme-wrapper-welcome');
}
}
static getContent () {
let cloud = {};
let minimumSize = 1;
let biggestCardsetSize = 1;
let list = [];
if (Meteor.userId()) {
cloud = Cardsets.find(Filter.getFilterQuery()).fetch();
} else {
if (Meteor.settings.public.welcome.fakeStatistics) {
cloud = new ReactiveVar(fakeWordCloud).curValue.default;
} else {
cloud = Cardsets.find({wordcloud: true}, {fields: {name: 1, quantity: 1}}).fetch();
}
}
cloud.forEach(function (cloud) {
if (cloud.quantity > biggestCardsetSize) {
biggestCardsetSize = cloud.quantity;
}
});
cloud.forEach(function (cloud) {
let name = cloud.name;
if (name.length > 30) {
name = name.substring(0, 30) + "";
}
let quantitiy = cloud.quantity / biggestCardsetSize * 5;
quantitiy = (quantitiy > minimumSize ? quantitiy : minimumSize);
list.push([name, Number(quantitiy), cloud._id, cloud.color]);
});
list.sort(function (a, b) {
return (b[0].length * b[1]) - (a[0].length * a[1]);
});
return list;
}
static setDefaultView () {
if ($(window).width() < 768) {
this.disableWordcloud();
} else if (Cardsets.find(Filter.getFilterQuery()).count() > 20) {
this.enableWordcloud();
} else {
this.disableWordcloud();
}
}
};
......@@ -314,6 +314,13 @@ Meteor.startup(function () {
});
}
if (!AdminSettings.findOne({name: "wordcloudPomodoroSettings"})) {
AdminSettings.insert({
name: "wordcloudPomodoroSettings",
enabled: true
});
}
if (!AdminSettings.findOne({name: "testNotifications"})) {
AdminSettings.insert({
name: "testNotifications",
......
......@@ -4,6 +4,26 @@
{{_ "admin.settings"}}
</h1>
</div>
<div class="panel panel-default">
<div class="panel-heading panel-heading-mail">
<h3 class="panel-title">{{_ "pomodoro.backend.settings.title"}}</h3>
</div>
<div class="panel-body panel-body-mail">
<div class="row" style="margin-bottom:10px; margin-left: 5px">
<form>
{{#if isWordcloudPomodoroEnabled}}
<a id="disableWordcloudPomodoro" class="btn btn-raised btn-success">
{{_ "pomodoro.backend.settings.button.enabled"}}</a>
{{else}}
<a id="enableWordcloudPomodoro" class="btn btn-raised btn-danger">
{{_ "pomodoro.backend.settings.button.disabled"}}</a>
{{/if}}
</form>
</div>
</div>
</div>
<div class="panel panel-default">
<div class="panel-heading panel-heading-mail">
......
......@@ -3,8 +3,11 @@ import {AdminSettings} from "../../../api/adminSettings.js";
import "./admin_settings.html";
Template.admin_settings.events({
'click #enableMail': function () {
Meteor.call("updateMailSettings", true);
'click #enableWordcloudPomodoro': function () {
Meteor.call("updateWordcloudPomodoroSettings", true);
},
'click #disableWordcloudPomodoro': function () {
Meteor.call("updateWordcloudPomodoroSettings", false);
},
'click #disableMail': function () {
Meteor.call("updateMailSettings", false);
......@@ -57,6 +60,9 @@ Template.admin_settings.events({
});
Template.admin_settings.helpers({
isWordcloudPomodoroEnabled: function () {
return AdminSettings.findOne({name: "wordcloudPomodoroSettings"}).enabled;
},
isMailEnabled: function () {
return AdminSettings.findOne({name: "mailSettings"}).enabled;
},
......
......@@ -35,7 +35,7 @@
<template name="shuffle">
{{#if canShuffle}}
<div class="col-md-12" id="set-list-region">
<div class="container" id="set-list-region">
<div class="bs-callout bs-callout-info selectionInfo">
{{#if gotShuffledCards}}
<button href="#" id="updateShuffledCardset" class="btn btn-raised btn-success"
......@@ -69,7 +69,7 @@
</template>
<template name="create">
<div class="col-md-12" id="set-list-region">
<div class="container" id="set-list-region">
{{#if isActiveRoute 'create'}}
<button id="newCardSet" type="button"
class="btn btn-raised btn-success saveSet" {{disableIfOffline}} {{disableIfShuffle}}>
......@@ -82,13 +82,17 @@
{{/if}}
{{#if cardsetList 0}}
{{> filterNavigation}}
{{#if cardsetList 1}}
{{#each cardsetList 2}}
{{> cardsetCourseIterationResultRow extendContext 'index' @index}}
{{/each}}
{{> infiniteScroll}}
{{#if displayWordcloud}}
{{> wordcloud}}
{{else}}
{{> noFilterResults}}
{{#if cardsetList 1}}
{{#each cardsetList 2}}
{{> cardsetCourseIterationResultRow extendContext 'index' @index}}
{{/each}}
{{> infiniteScroll}}
{{else}}
{{> noFilterResults}}
{{/if}}
{{/if}}
{{else}}
{{> noResults}}
......@@ -97,7 +101,7 @@
</template>
<template name="repetitorium">
<div class="col-md-12" id="set-list-region">
<div class="container" id="set-list-region">
{{#unless selectingCardsetToLearn}}
{{#if canCreateContent}}
<button id="newRepetitorium" type="button"
......@@ -110,13 +114,17 @@
{{/unless}}
{{#if cardsetList 0}}
{{> filterNavigation}}
{{#if cardsetList 1}}
{{#each cardsetList 2}}
{{> cardsetCourseIterationResultRow extendContext 'index' @index}}
{{/each}}
{{> infiniteScroll}}
{{#if displayWordcloud}}
{{> wordcloud}}
{{else}}
{{> noFilterResults}}
{{#if cardsetList 1}}
{{#each cardsetList 2}}
{{> cardsetCourseIterationResultRow extendContext 'index' @index}}
{{/each}}
{{> infiniteScroll}}
{{else}}
{{> noFilterResults}}
{{/if}}
{{/if}}
{{else}}
{{> noResults}}
......@@ -127,7 +135,7 @@
<template name="learn">
{{> selectModeForm}}
{{> cardsetsConfirmLearnForm}}
<div id="learn-list-region" class="col-md-12">
<div id="learn-list-region" class="container">
<a id="browseCardset" class="btn btn-raised btn-success">{{_
"set-list-learn-empty.browseCardset"}}</a>
<a id="browseShuffledCardset" class="btn btn-raised btn-success">{{_
......
......@@ -12,6 +12,7 @@ import {BertAlertVisuals} from "../../api/bertAlertVisuals";
import {Workload} from "../../api/learned";
import {SweetAlertMessages} from "../../api/sweetAlert";
import {Profile} from "../../api/profile";
import {FilterNavigation} from "../../api/filterNavigation";
Session.setDefault('cardsetId', undefined);
Session.set('moduleActive', true);
......@@ -47,6 +48,9 @@ Template.create.helpers({
},
isProfileComplete: function () {
return Profile.isCompleted();
},
displayWordcloud: function () {
return FilterNavigation.gotDisplayModeButton(FilterNavigation.getRouteId()) && Session.get('filterDisplayWordcloud');
}
});
......@@ -132,6 +136,9 @@ Template.repetitorium.helpers({
},
selectingCardsetToLearn: function () {
return Session.get('selectingCardsetToLearn');
},
displayWordcloud: function () {
return FilterNavigation.gotDisplayModeButton(FilterNavigation.getRouteId()) && Session.get('filterDisplayWordcloud');
}
});