GitLab steht Mittwoch, den 08. Juli, zwischen 09:00 und 13:00 Uhr aufgrund von Wartungsarbeiten nicht zur Verfügung.

Commit cf08eba4 authored by Curtis Adam's avatar Curtis Adam

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

parent 73dee127
......@@ -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();