Skip to content

Commit c85834d

Browse files
author
Lionel Laské
committed
Merge branch 'dev'
2 parents 4493d80 + 140f95a commit c85834d

File tree

85 files changed

+32173
-15414
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

85 files changed

+32173
-15414
lines changed

.eslintignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ dashboard/public/js/pace.min.js
1616
dashboard/public/js/qrcodegen.js
1717
dashboard/public/js/FileSaver.js
1818
dashboard/public/js/select2.min.js
19+
api/controller/utils/qrCodeUtil.js
1920

2021
docs/
2122

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,5 @@ build/
1212

1313
*.csv
1414
tmp/
15+
16+
.nyc_output/

CHANGELOG.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,22 @@ All notable changes to this project will be documented in this file.
44
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
55
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
66

7+
## [1.5.0] - 2023-02-15
8+
### Added
9+
- Assignments feature: API and Dashboard
10+
- Code coverage
11+
12+
### Changed
13+
- MongoDB minimal version is now 3.2+
14+
- Updated to MongoDB 5.0 in docker image
15+
- Store activities list in database
16+
17+
### Fixed
18+
- Padding from left in language selection menu list #294
19+
- Fix required in sidebar to achieve consistency #348
20+
21+
22+
### Fixed
723
## [1.4.0] - 2021-11-21
824
### Added
925
- Two factor authentication

README.md

Lines changed: 345 additions & 328 deletions
Large diffs are not rendered by default.

api/controller/activities.js

Lines changed: 155 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,18 @@ var fs = require('fs'),
44
path = require('path'),
55
ini = require('ini');
66

7+
var db;
8+
var activitiesCollection;
9+
710
// Load into memory the content of activities directory
8-
var activities;
911
var settingsData;
10-
exports.load = function(settings, callback) {
12+
exports.load = function(settings, database) {
1113

1214
// Get settings
13-
activities = [];
15+
var activitiesFromDir = [];
1416
settingsData = settings;
17+
db = database;
18+
activitiesCollection = settings.collections.activities;
1519
var activitiesDirName = settings.activities.activities_directory_name;
1620
var templateDirName = settings.activities.template_directory_name;
1721
var activityInfoPath = settings.activities.activity_info_path;
@@ -29,6 +33,26 @@ exports.load = function(settings, callback) {
2933
console.log("ERROR: can't find activity path '"+activitiesPath+"'");
3034
throw err;
3135
}
36+
var index = 0;
37+
var mergedActivitiesAtEnd = function() {
38+
// Load activities
39+
loadActivities(function(activitiesFromDB) {
40+
// Sort activities array by index in .INI favorite property
41+
if (!activitiesFromDB) {
42+
activitiesFromDir.sort(function(a0, a1) {
43+
if (a0.index > a1.index) return 1;
44+
else if (a0.index < a1.index) return -1;
45+
else return 0;
46+
});
47+
}
48+
49+
// Merge current with loaded
50+
var merged = mergeActivities(activitiesFromDB, activitiesFromDir);
51+
52+
// Store activities
53+
storeActivities(merged);
54+
});
55+
}
3256
files.forEach(function(file) {
3357
// If it's not the template directory
3458
if (file != templateDirName) {
@@ -58,7 +82,7 @@ exports.load = function(settings, callback) {
5882
}
5983

6084
// Return the activity
61-
activities.push({
85+
activitiesFromDir.push({
6286
"id": info.Activity.bundle_id,
6387
"name": info.Activity.name,
6488
"version": info.Activity.activity_version,
@@ -68,24 +92,26 @@ exports.load = function(settings, callback) {
6892
"activityId": null,
6993
"index": (favorites.indexOf(info.Activity.bundle_id) == -1 ? favoritesLength++ : favorites.indexOf(info.Activity.bundle_id))
7094
});
71-
});
72-
stream.on('end', function() {
73-
// Sort activities array by index in .INI favorite property
74-
activities.sort(function(a0, a1) {
75-
if (a0.index > a1.index) return 1;
76-
else if (a0.index < a1.index) return -1;
77-
else return 0;
78-
});
79-
if (callback) {
80-
callback();
81-
callback = null;
95+
if (++index == files.length) {
96+
mergedActivitiesAtEnd();
8297
}
8398
});
8499
stream.on('error', function() {
85100
console.log("WARNING: can't find info file for '"+activitiesDirName+path.sep + file+"'");
101+
if (++index == files.length) {
102+
mergedActivitiesAtEnd();
103+
}
86104
});
105+
} else {
106+
if (++index == files.length) {
107+
mergedActivitiesAtEnd();
108+
}
87109
}
88110
});
111+
} else {
112+
if (++index == files.length) {
113+
mergedActivitiesAtEnd();
114+
}
89115
}
90116
});
91117
});
@@ -138,10 +164,11 @@ exports.load = function(settings, callback) {
138164
* ]
139165
**/
140166
exports.findAll = function(req, res) {
141-
142-
//process results based on filters and fields
143-
var data = process_results(req, activities);
144-
res.send(data);
167+
loadActivities(function(activities) {
168+
//process results based on filters and fields
169+
var data = process_results(req, activities);
170+
res.send(data);
171+
});
145172
};
146173

147174
/**
@@ -191,21 +218,95 @@ exports.findAll = function(req, res) {
191218
* }
192219
**/
193220
exports.findById = function(req, res) {
221+
loadActivities(function(activities) {
222+
//process results based on filters and fields
223+
var data = process_results(req, activities);
224+
225+
//find by id
226+
var id = req.params.id;
227+
for (var i = 0; i < data.length; i++) {
228+
var activity = data[i];
229+
if (activity.id == id) {
230+
res.send(activity);
231+
return;
232+
}
233+
}
234+
res.send();
235+
})
236+
};
237+
238+
// Store activities in database
239+
function storeActivities(activitiesList) {
240+
db.collection(activitiesCollection, function(err, collection) {
241+
collection.replaceOne(
242+
{},
243+
{
244+
activities: activitiesList
245+
},
246+
{
247+
upsert: true
248+
},
249+
function(err, result) {
250+
if (err) {
251+
console.log(err);
252+
return;
253+
}
254+
}
255+
);
256+
});
257+
}
258+
259+
// Load activities in database
260+
function loadActivities(callback) {
261+
db.collection(activitiesCollection, function(err, collection) {
262+
collection.findOne(
263+
{},
264+
function(err, activities) {
265+
if (err) {
266+
console.log(err);
267+
callback(null)
268+
return;
269+
}
270+
callback(activities?activities.activities:null);
271+
}
272+
);
273+
});
274+
}
194275

195-
//process results based on filters and fields
196-
var data = process_results(req, activities);
276+
// Merge activities list
277+
function mergeActivities(list1, list2) {
278+
// No merge
279+
if (!list1) {
280+
return list2;
281+
}
197282

198-
//find by id
199-
var id = req.params.id;
200-
for (var i = 0; i < data.length; i++) {
201-
var activity = data[i];
202-
if (activity.id == id) {
203-
res.send(activity);
204-
return;
283+
// Keep only in list 1 elements in list 2
284+
let merged = [];
285+
for (let i = 0 ; i < list1.length ; i++) {
286+
let activity = list1[i];
287+
let found = false;
288+
for (let j = 0 ; !found && j < list2.length ; j++) {
289+
found = (activity.id == list2[j].id);
290+
}
291+
if (found) {
292+
merged.push(list1[i]);
205293
}
206294
}
207-
res.send();
208-
};
295+
296+
// Add in list 1 new elements in list 2
297+
for (let i = 0 ; i < list2.length ; i++) {
298+
let activity = list2[i];
299+
let found = false;
300+
for (let j = 0 ; !found && j < list1.length ; j++) {
301+
found = (activity.id == list1[j].id);
302+
}
303+
if (!found) {
304+
merged.push(activity);
305+
}
306+
}
307+
308+
return merged;
309+
}
209310

210311
//private function for filtering and sorting
211312
function addOptions(field, params, options, default_val) {
@@ -294,9 +395,9 @@ function process_results(req, activities) {
294395

295396

296397
/**
297-
* @api {post} api/v1/activities Update details of activities
398+
* @api {post} api/v1/activities Update favorites activities
298399
* @apiName UpdateActivities
299-
* @apiDescription Update about details of the activities. Only admin can perform this action.
400+
* @apiDescription Update list of favorites activities. Only admin can perform this action.
300401
* @apiGroup Activities
301402
* @apiVersion 1.0.0
302403
*
@@ -331,26 +432,35 @@ function process_results(req, activities) {
331432
* ]
332433
**/
333434
exports.updateActivities = function(req, res) {
334-
335-
//do changes
336-
var locales = settingsData.locales;
337-
if (req.body.favorites) {
338-
settingsData.activities.favorites = req.body.favorites;
339-
settingsData.locales = {};
340-
} else {
435+
// No favorite provided
436+
if (!req.body.favorites) {
341437
return res.status(401).send({
342438
'error': 'Invalid favorites variable',
343439
'code': 9
344440
});
345441
}
442+
var favorites = req.body.favorites.split(',');
443+
var favoritesLength = favorites.length;
444+
445+
// Load activities
446+
loadActivities(function(activities) {
447+
// Compute new index depending of position in favorite string
448+
for (var i = 0 ; i < activities.length ; i++) {
449+
var activity = activities[i];
450+
var isFavorite = (favorites.indexOf(activity.id) != -1);
451+
activity.index = (!isFavorite ? favoritesLength++ : favorites.indexOf(activity.id));
452+
activity.favorite = isFavorite;
453+
}
346454

347-
// write it back to ini
348-
var file = "./env/" + (process.env.NODE_ENV ? process.env.NODE_ENV : 'sugarizer') + ".ini";
349-
fs.writeFileSync(file, ini.stringify(settingsData));
350-
settingsData.locales = locales;
455+
// Sort by index
456+
activities.sort(function(a0, a1) {
457+
if (a0.index > a1.index) return 1;
458+
else if (a0.index < a1.index) return -1;
459+
else return 0;
460+
});
351461

352-
//update activities list and return
353-
exports.load(settingsData, function() {
462+
// Store activities
463+
storeActivities(activities);
354464
res.send(activities);
355465
});
356466
};

0 commit comments

Comments
 (0)