diff --git a/app/abilities/study-room-presence copy.js b/app/abilities/study-room-presence copy.js
new file mode 100644
index 000000000..2ff1bc004
--- /dev/null
+++ b/app/abilities/study-room-presence copy.js
@@ -0,0 +1,15 @@
+import { Ability } from 'ember-can';
+
+export default class StudyRoomPresence extends Ability {
+ get canShow() {
+ return this.session.hasPermission('study-room-presence.read');
+ }
+
+ get canCreate() {
+ return this.session.hasPermission('study-room-presence.create');
+ }
+
+ get canDestroy() {
+ return this.session.hasPermission('study-room-presence.destroy');
+ }
+}
diff --git a/app/components/index/authenticated.hbs b/app/components/index/authenticated.hbs
index 4a82afe64..b3db07a79 100644
--- a/app/components/index/authenticated.hbs
+++ b/app/components/index/authenticated.hbs
@@ -1,6 +1,7 @@
+
diff --git a/app/components/tools/board-room-presence.hbs b/app/components/tools/board-room-presence.hbs
index b70989892..5ac073729 100644
--- a/app/components/tools/board-room-presence.hbs
+++ b/app/components/tools/board-room-presence.hbs
@@ -1,4 +1,4 @@
-
+
Bestuurskamer
diff --git a/app/components/tools/study-room-presence.hbs b/app/components/tools/study-room-presence.hbs
new file mode 100644
index 000000000..dcb1ae323
--- /dev/null
+++ b/app/components/tools/study-room-presence.hbs
@@ -0,0 +1,135 @@
+
+
+
+ 2de kamer
+
+
+
+ {{#each sortedPresences as |presence|}}
+
+
+
+ {{presence.user.fullNameWithNickname}}
+
+
+
+ {{t (concat 'component.tools.studyRoomPresence.' presence.status)}}
+ van
+ {{moment-format presence.startTime 'HH:mm'}}
+ tot
+ {{moment-format presence.endTime 'HH:mm'}}
+
+
+ {{else}}
+ Er is niemand aanwezig
+ {{/each}}
+
+ {{#if (can 'create study-room-presences')}}
+
+
+
+ {{/if}}
+
+
+
+
+{{#if presenceModalIsOpen}}
+
+
+ {{#if sortedPresences}}
+
+
+
+ Persoon |
+ Status |
+ Tot |
+ |
+
+
+
+ {{#each sortedPresences as |presence|}}
+
+ {{presence.user.fullNameWithNickname}} |
+
+ {{t
+ (concat 'component.tools.studyRoomPresence.' presence.status)
+ }}
+ |
+ {{moment-format presence.endTime 'HH:mm'}} |
+
+ {{#if (can 'destroy study-room-presences')}}
+
+ {{/if}}
+ |
+
+ {{/each}}
+
+
+ {{else}}
+ Er zijn geen alphanen aanwezig
+ {{/if}}
+
+ {{#if currentUserPresence}}
+
+
+
+
+
+
+ {{else}}
+
+ {{/if}}
+
+
+{{/if}}
\ No newline at end of file
diff --git a/app/components/tools/study-room-presence.js b/app/components/tools/study-room-presence.js
new file mode 100644
index 000000000..a9276969e
--- /dev/null
+++ b/app/components/tools/study-room-presence.js
@@ -0,0 +1,122 @@
+import { task, timeout } from 'ember-concurrency';
+import Component from '@ember/component';
+import Ember from 'ember';
+import { computed } from '@ember/object';
+import { equal } from '@ember/object/computed';
+import moment from 'moment';
+import { inject as service } from '@ember/service';
+
+const StudyRoomPresence = Component.extend({
+ session: service(),
+ store: service(),
+ abilities: service(),
+ presenceModalIsOpen: false,
+ model: [],
+
+ statusOptions: [
+ {
+ value: 'present',
+ label: 'Aanwezig',
+ },
+ {
+ value: 'busy',
+ label: 'Bezig',
+ },
+ {
+ value: 'absent',
+ label: 'Afwezig',
+ },
+ ],
+
+ // Periodically poll for new studyroom data
+ poll: task(function* () {
+ while (!Ember.testing) {
+ this.fetchData.perform();
+ yield timeout(1000 * 30); // Wait 30 seconds
+ }
+ })
+ .drop()
+ .on('didInsertElement'),
+
+ // Fetch task is separate from polling task, so we can call it individually.
+ fetchData: task(function* () {
+ /* eslint-disable camelcase */
+ const model = yield this.store.query('study-room-presence', {
+ filter: { current_and_future: true },
+ });
+ /* eslint-enable camelcase */
+
+ this.set('model', model);
+ }).restartable(),
+
+ currentUserPresence: computed('model.[]', function () {
+ return (
+ this.model.filter((presence) => presence.get('user.isCurrentUser'))[0] ||
+ null
+ );
+ }),
+
+ sortedPresences: computed('model.[]', function () {
+ return this.model.sortBy('endTime');
+ }),
+
+ overallStatus: computed('model.[]', function () {
+ const currentStatusses = this.model
+ .filter((presence) => {
+ return moment().isBetween(
+ moment(presence.get('startTime')),
+ moment(presence.get('endTime')),
+ 'minute',
+ '[)'
+ );
+ })
+ .mapBy('status');
+
+ if (currentStatusses.includes('present')) {
+ return 'present';
+ } else if (currentStatusses.includes('busy')) {
+ return 'busy';
+ }
+
+ return 'absent';
+ }),
+
+ saveButtonDisabled: equal('currentUserPresence', null),
+
+ actions: {
+ setPresenceModalState(state) {
+ this.set('presenceModalIsOpen', state === 'open');
+ },
+
+ deletePresence() {
+ this.currentUserPresence.destroyRecord().then(() => {
+ this.set('currentUserPresence', null);
+ });
+ },
+
+ newPresence() {
+ if (this.abilities.can('create study-room-presences')) {
+ const newPresenceObject = this.store.createRecord(
+ 'study-room-presence',
+ {
+ startTime: moment().startOf('minute').toDate(),
+ endTime: moment().startOf('minute').add(1, 'hours').toDate(),
+ status: 'present',
+ user: this.session.currentUser,
+ }
+ );
+ this.set('currentUserPresence', newPresenceObject);
+ }
+ },
+
+ save() {
+ const presence = this.currentUserPresence;
+ const fetch = this.fetchData;
+
+ presence.save().then(() => fetch.perform());
+ this.set('presenceModalIsOpen', false);
+ },
+ },
+});
+
+export default studyRoomPresence;
diff --git a/app/models/study-room-presence.js b/app/models/study-room-presence.js
new file mode 100644
index 000000000..5721bbf03
--- /dev/null
+++ b/app/models/study-room-presence.js
@@ -0,0 +1,11 @@
+import Model, { belongsTo, attr } from '@ember-data/model';
+
+export default class StudyRoomPresence extends Model {
+ // Properties
+ @attr startTime;
+ @attr endTime;
+ @attr status;
+
+ // Relations
+ @belongsTo user;
+}
diff --git a/app/styles/app.scss b/app/styles/app.scss
index d1288923e..45ed2c239 100644
--- a/app/styles/app.scss
+++ b/app/styles/app.scss
@@ -33,7 +33,7 @@
@import 'components/quickpost';
@import 'components/sidebar';
@import 'components/social-media-buttons';
-@import 'components/tools/board-room-presence';
+@import 'components/tools/room-presence';
@import 'components/tools/upcoming-birthdays';
@import 'components/tools/upcoming-activities';
@import 'components/tools/forum-tool';
diff --git a/app/styles/components/tools/board-room-presence.scss b/app/styles/components/tools/room-presence.scss
similarity index 94%
rename from app/styles/components/tools/board-room-presence.scss
rename to app/styles/components/tools/room-presence.scss
index 683763d55..57a337521 100644
--- a/app/styles/components/tools/board-room-presence.scss
+++ b/app/styles/components/tools/room-presence.scss
@@ -10,7 +10,7 @@
font-weight: bold;
}
-.board-room-presence-dropdown {
+.room-presence-dropdown {
color: $white;
}
diff --git a/mirage/config.js b/mirage/config.js
index 8241fd8ae..1afd1afa4 100644
--- a/mirage/config.js
+++ b/mirage/config.js
@@ -32,6 +32,7 @@ export default function () {
this.resource('groups');
this.resource('quickpost_messages');
this.resource('board_room_presences');
+ this.resource('study_room_presences');
this.resource('photo_albums');
this.resource('photo_comments');
this.resource('photo_tags');
diff --git a/mirage/scenarios/default.js b/mirage/scenarios/default.js
index db12aec4a..b1e3f3afa 100644
--- a/mirage/scenarios/default.js
+++ b/mirage/scenarios/default.js
@@ -8,6 +8,7 @@ export default function (server) {
'article',
'article_comment',
'board_room_presence',
+ 'study_room_presence',
'group',
'membership',
'photo_album',