Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implementing a button for Presence in the 2de kamer #891

Merged
merged 18 commits into from
Jan 19, 2025
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
15 changes: 15 additions & 0 deletions app/abilities/study-room-presence.js
Original file line number Diff line number Diff line change
@@ -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');

Check warning on line 5 in app/abilities/study-room-presence.js

View check run for this annotation

Codecov / codecov/patch

app/abilities/study-room-presence.js#L5

Added line #L5 was not covered by tests
}

get canCreate() {
return this.session.hasPermission('study-room-presence.create');

Check warning on line 9 in app/abilities/study-room-presence.js

View check run for this annotation

Codecov / codecov/patch

app/abilities/study-room-presence.js#L9

Added line #L9 was not covered by tests
}

get canDestroy() {
return this.session.hasPermission('study-room-presence.destroy');

Check warning on line 13 in app/abilities/study-room-presence.js

View check run for this annotation

Codecov / codecov/patch

app/abilities/study-room-presence.js#L13

Added line #L13 was not covered by tests
}
}
1 change: 1 addition & 0 deletions app/components/index/authenticated.hbs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<EmberWormhole @to='navbar-wormhole'>
<PageActionsButtons @pageActions={{pageActions}}>
<Tools::StudyRoomPresence />
<Tools::BoardRoomPresence />
</PageActionsButtons>
</EmberWormhole>
Expand Down
2 changes: 1 addition & 1 deletion app/components/tools/board-room-presence.hbs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<div class='board-room-presence-dropdown page-action'>
<div class='room-presence-dropdown page-action'>
<BsButton @type='primary'>
<FaIcon @icon='mug-saucer' />
<span class='d-none d-md-inline'>Bestuurskamer</span>
Expand Down
136 changes: 136 additions & 0 deletions app/components/tools/study-room-presence.hbs
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please also write this template in octane style. Some quick rules (without regard for whether you followed these or not):

  • use angle bracket syntax for inserting components
  • refer to controller properties/functions with this. i.e. this.property or this.someFunction
  • refer to arguments passed to this component using @. So, if the parent component has passed an argument called someArgument, then we can refer to it in this template with @someArgument.
  • do not use the action helper anymore. see Refactor: {{action}} helper usage #635 and Refactor: {{action}} helper usage, the sequel #896 for examples of what to write instead.

please thoroughly familiarize yourself with #429 and the tutorials/guides/resources mentioned there.

Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
<div class='room-presence-dropdown page-action'>
<BsButton @type='primary'>
<FaIcon @icon='book' />
<span class='d-none d-md-inline'>2de kamer</span>
<span class='status-dot label-{{this.overallStatus}}'></span>

<BsPopover
@placement='bottom'
@title='Aanwezig in de 2de Kamer'
@renderInPlace="{{true}}"
>
{{#each this.sortedPresences as |presence|}}
<div class='py-1'>
<div class='d-block'>
<LinkTo @route='users.user' @model={{presence.user.id}}>
<small><b>{{presence.user.fullNameWithNickname}}</b></small>
</LinkTo>
</div>
<span class='presence-label label-{{presence.status}}'>
{{t (concat 'component.tools.studyRoomPresence.' presence.status)}}
van
{{moment-format presence.startTime 'HH:mm'}}
tot
{{moment-format presence.endTime 'HH:mm'}}
</span>
</div>
{{else}}
<div>Er is niemand aanwezig</div>
{{/each}}

{{#if (can 'create study-room-presences')}}
<span class='d-flex'>
<button
class='btn btn-secondary mb-2 mt-3 update-presence-button'
{{on 'click' (fn this.setPresenceModalState 'open') }}
type='button'
>
Aanwezigheid updaten
</button>
</span>
{{/if}}
</BsPopover>
</BsButton>
</div>

{{#if presenceModalIsOpen}}
<EmberWormhole @to='ember-wormhole-destination'>
<BasicModal
@title='2de kamer beschikbaarheid opgeven'
@closeModal={{fn this.setPresenceModalState 'closed'}}
@onSubmit={{this.save}}
@submitText='Beschikbaarheid opslaan'
@submitDisabled={{saveButtonDisabled}}
>
{{#if this.sortedPresences}}
<table class='table edit-presence'>
<thead>
<tr>
<th>Persoon</th>
<th>Status</th>
<th>Tot</th>
<th></th>
</tr>
</thead>
<tbody>
{{#each this.sortedPresences as |presence|}}
<tr class="edit-presence-row">
<td>{{presence.user.fullNameWithNickname}}</td>
<td>
{{t
(concat 'component.tools.studyRoomPresence.' presence.status)
}}
</td>
<td> {{moment-format presence.endTime 'HH:mm'}} </td>
<td>
{{#if (can 'destroy study-room-presences')}}
<button
class='btn btn-danger delete-presence-button float-end'
aria-hidden='true'
{{on 'click' this.deletePresence}}
type='button'
>
<FaIcon @icon='trash' @size="xs" />
</button>
{{/if}}
</td>
</tr>
{{/each}}
</tbody>
</table>
{{else}}
<div class='alert alert-info'>Er zijn geen alphanen aanwezig</div>
{{/if}}

{{#if (can 'create study-room-presences')}}
{{#if this.currentUserPresence}}
<label for="new-user-presence-status">Status</label>
<Input::SelectInput
@class='form-control col-xs-12 presence-select'
@required={{true}}
@options={{statusOptions}}
@placeholder={{Status}}
@value={{this.currentUserPresence.status}}
@id="new-user-presence-status"
/>
<label for="new-user-presence-starttime" class="mt-2">Van</label>
<Input::TimeInput
@dateValue={{this.currentUserPresence.startTime}}
@class='col-xs-12 presence-time-input'
@inputClass='form-control'
@placeholder={{this.currentUserPresence.startTime}}
@required={{true}}
@id="new-user-presence-starttime"
/>
<label for="new-user-presence-endtime" class="mt-2">Tot</label>
<Input::TimeInput
@dateValue={{this.currentUserPresence.endTime}}
@class='col-xs-12 presence-time-input'
@inputClass='form-control'
@placeholder={{this.currentUserPresence.endTime}}
@required={{true}}
@id="new-user-presence-endtime"
/>
{{else}}
<button
class='btn btn-secondary'
{{on 'click' this.newPresence}}
type='button'
>
Nieuw
</button>
{{/if}}
{{/if}}
</BasicModal>
</EmberWormhole>
{{/if}}
127 changes: 127 additions & 0 deletions app/components/tools/study-room-presence.js
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this component is written in the old style, please follow the new octane component style. There are a lot of examples that use glimmer components already

specifically, you can take example from https://github.com/csvalpha/amber-ui/pull/635/files#diff-b264f9e9a3db1a61c4d3c4c38a3c454a93a33286c5d2b1e820513bc9d4986084 where I've rewritten the board-room-presence component

Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
import { dropTask, restartableTask, timeout } from 'ember-concurrency';
import Component from '@glimmer/component';
import { action } from '@ember/object';
import moment from 'moment';
import { inject as service } from '@ember/service';
import { tracked } from '@glimmer/tracking';
import Ember from 'ember';

export default class BoardRoomPresence extends Component {
@service session;
@service store;
@service abilities;

@tracked presenceModalIsOpen = false;
@tracked model = [];
@tracked newCurrentUserPresence = null;

statusOptions = [

Check warning on line 18 in app/components/tools/study-room-presence.js

View check run for this annotation

Codecov / codecov/patch

app/components/tools/study-room-presence.js#L16-L18

Added lines #L16 - L18 were not covered by tests
{
value: 'chilling',

Check warning on line 20 in app/components/tools/study-room-presence.js

View check run for this annotation

Codecov / codecov/patch

app/components/tools/study-room-presence.js#L20

Added line #L20 was not covered by tests
label: 'Chillen',
},
{
value: 'studying',
label: 'Studeren',
},
{
value: 'vergaderen',
label: 'Vergaderen',
},
];

@dropTask({ cancelOn: 'didInsertElement' }) *poll() {
while (!Ember.testing) {
yield this.fetchData.perform();
yield timeout(1000 * 30); // Wait 30 seconds
}
}

Check warning on line 38 in app/components/tools/study-room-presence.js

View check run for this annotation

Codecov / codecov/patch

app/components/tools/study-room-presence.js#L36-L38

Added lines #L36 - L38 were not covered by tests

@restartableTask *fetchData() {
/* eslint-disable camelcase */
this.model = yield this.store.query('study-room-presence', {
filter: { current_and_future: true },
});

Check warning on line 44 in app/components/tools/study-room-presence.js

View check run for this annotation

Codecov / codecov/patch

app/components/tools/study-room-presence.js#L44

Added line #L44 was not covered by tests
/* eslint-enable camelcase */
}

constructor() {
super(...arguments);
this.poll.perform();
}

Check warning on line 52 in app/components/tools/study-room-presence.js

View check run for this annotation

Codecov / codecov/patch

app/components/tools/study-room-presence.js#L51-L52

Added lines #L51 - L52 were not covered by tests
get currentUserPresence() {
if (this.newCurrentUserPresence) {
return this.newCurrentUserPresence;
}
return (

Check warning on line 57 in app/components/tools/study-room-presence.js

View check run for this annotation

Codecov / codecov/patch

app/components/tools/study-room-presence.js#L56-L57

Added lines #L56 - L57 were not covered by tests
this.model.filter((presence) => presence.user.get('isCurrentUser'))[0] ||
null
);

Check warning on line 60 in app/components/tools/study-room-presence.js

View check run for this annotation

Codecov / codecov/patch

app/components/tools/study-room-presence.js#L59-L60

Added lines #L59 - L60 were not covered by tests
}

set currentUserPresence(presence) {
this.newCurrentUserPresence = presence;
}

Check warning on line 66 in app/components/tools/study-room-presence.js

View check run for this annotation

Codecov / codecov/patch

app/components/tools/study-room-presence.js#L66

Added line #L66 was not covered by tests
get sortedPresences() {
return this.model.sortBy('endTime');
}

Check warning on line 70 in app/components/tools/study-room-presence.js

View check run for this annotation

Codecov / codecov/patch

app/components/tools/study-room-presence.js#L70

Added line #L70 was not covered by tests
get overallStatus() {
const currentStatusses = this.model
.filter((presence) => {
return moment().isBetween(

Check warning on line 74 in app/components/tools/study-room-presence.js

View check run for this annotation

Codecov / codecov/patch

app/components/tools/study-room-presence.js#L74

Added line #L74 was not covered by tests
moment(presence.get('startTime')),
moment(presence.get('endTime')),

Check warning on line 76 in app/components/tools/study-room-presence.js

View check run for this annotation

Codecov / codecov/patch

app/components/tools/study-room-presence.js#L76

Added line #L76 was not covered by tests
'minute',
'[)'
);
})
.mapBy('status');

if (currentStatusses.includes('chilling')) {
return 'Chillen';
}

Check warning on line 86 in app/components/tools/study-room-presence.js

View check run for this annotation

Codecov / codecov/patch

app/components/tools/study-room-presence.js#L85-L86

Added lines #L85 - L86 were not covered by tests
if (currentStatusses.includes('studeren')) {
return 'Studying';
}

Check warning on line 90 in app/components/tools/study-room-presence.js

View check run for this annotation

Codecov / codecov/patch

app/components/tools/study-room-presence.js#L89-L90

Added lines #L89 - L90 were not covered by tests
return 'Vergaderen';
}

Check warning on line 93 in app/components/tools/study-room-presence.js

View check run for this annotation

Codecov / codecov/patch

app/components/tools/study-room-presence.js#L93

Added line #L93 was not covered by tests
get saveButtonDisabled() {
return this.currentUserPresence === null;
}

Check warning on line 97 in app/components/tools/study-room-presence.js

View check run for this annotation

Codecov / codecov/patch

app/components/tools/study-room-presence.js#L97

Added line #L97 was not covered by tests
@action
setPresenceModalState(state) {
this.presenceModalIsOpen = state === 'open';
}

Check warning on line 102 in app/components/tools/study-room-presence.js

View check run for this annotation

Codecov / codecov/patch

app/components/tools/study-room-presence.js#L102

Added line #L102 was not covered by tests
@action
deletePresence() {
this.currentUserPresence.destroyRecord().then(() => {
this.currentUserPresence = null;
});
}

Check warning on line 108 in app/components/tools/study-room-presence.js

View check run for this annotation

Codecov / codecov/patch

app/components/tools/study-room-presence.js#L107-L108

Added lines #L107 - L108 were not covered by tests

@action
newPresence() {
this.currentUserPresence = this.store.createRecord('study-room-presence', {
startTime: moment().startOf('minute').toDate(),
endTime: moment().startOf('minute').add(1, 'hours').toDate(),

Check warning on line 114 in app/components/tools/study-room-presence.js

View check run for this annotation

Codecov / codecov/patch

app/components/tools/study-room-presence.js#L114

Added line #L114 was not covered by tests
status: 'present',
user: this.session.currentUser,
});
}

@action
save() {
const presence = this.currentUserPresence;
const fetch = this.fetchData;
presence.save().then(() => fetch.perform());
this.presenceModalIsOpen = false;
}
}

Check warning on line 127 in app/components/tools/study-room-presence.js

View check run for this annotation

Codecov / codecov/patch

app/components/tools/study-room-presence.js#L124-L127

Added lines #L124 - L127 were not covered by tests
11 changes: 11 additions & 0 deletions app/models/study-room-presence.js
Original file line number Diff line number Diff line change
@@ -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;
}
2 changes: 1 addition & 1 deletion app/styles/app.scss
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
font-weight: bold;
}

.board-room-presence-dropdown {
.room-presence-dropdown {
color: $white;
}

Expand All @@ -26,6 +26,18 @@
background-color: $brand-danger;
}

.label-chilling {
background-color: $brand-success;
}

.label-studying {
background-color: $brand-warning;
}

.label-vergaderen {
background-color: $brand-success;
}

.edit-presence {
.edit-presence-row {
margin: 5px;
Expand Down
1 change: 1 addition & 0 deletions mirage/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -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');
Expand Down
1 change: 1 addition & 0 deletions mirage/scenarios/default.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export default function (server) {
'article',
'article_comment',
'board_room_presence',
'study_room_presence',
'group',
'membership',
'photo_album',
Expand Down
4 changes: 4 additions & 0 deletions translations/en.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,10 @@ component:
present: Present
busy: Busy
absent: Absent
studyRoomPresence:
chilling: Chilling
studying: Studying
vergaderen: In a meeting
userComment:
anonymous: Anonymous user
mixin:
Expand Down
4 changes: 4 additions & 0 deletions translations/nl.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,10 @@ component:
present: Aanwezig
busy: Bezig
absent: Afwezig
studyRoomPresence:
chilling: Chillen
studying: Studeren
vergaderen: In een vergadering
userComment:
anonymous: Anonieme gebruiker
mixin:
Expand Down
Loading