-
Notifications
You must be signed in to change notification settings - Fork 4
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
base: staging
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
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'); | ||
} | ||
|
||
get canCreate() { | ||
return this.session.hasPermission('study-room-presence.create'); | ||
} | ||
|
||
get canDestroy() { | ||
return this.session.hasPermission('study-room-presence.destroy'); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,135 @@ | ||
<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-{{overallStatus}}'></span> | ||
|
||
<BsPopover | ||
{{!-- @triggerEvents='focus' --}} | ||
@placement='bottom' | ||
@title='Aanwezig in de 2de Kamer' | ||
@renderInPlace="{{true}}" | ||
> | ||
{{#each 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' | ||
{{action '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={{action 'setPresenceModalState' 'closed'}} | ||
@onSubmit={{action 'save'}} | ||
@submitText='Beschikbaarheid opslaan' | ||
@submitDisabled={{saveButtonDisabled}} | ||
> | ||
{{#if sortedPresences}} | ||
<table class='table edit-presence'> | ||
<thead> | ||
<tr> | ||
<th>Persoon</th> | ||
<th>Status</th> | ||
<th>Tot</th> | ||
<th></th> | ||
</tr> | ||
</thead> | ||
<tbody> | ||
{{#each 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' | ||
{{action '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 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={{currentUserPresence.status}} | ||
@id="new-user-presence-status" | ||
/> | ||
<label for="new-user-presence-starttime" class="mt-2">Van</label> | ||
<Input::TimeInput | ||
@dateValue={{currentUserPresence.startTime}} | ||
@class='col-xs-12 presence-time-input' | ||
@inputClass='form-control' | ||
@placeholder={{currentUserPresence.startTime}} | ||
@required={{true}} | ||
@id="new-user-presence-starttime" | ||
/> | ||
<label for="new-user-presence-endtime" class="mt-2">Tot</label> | ||
<Input::TimeInput | ||
@dateValue={{currentUserPresence.endTime}} | ||
@class='col-xs-12 presence-time-input' | ||
@inputClass='form-control' | ||
@placeholder={{currentUserPresence.endTime}} | ||
@required={{true}} | ||
@id="new-user-presence-endtime" | ||
/> | ||
{{else}} | ||
<button | ||
class='btn btn-secondary' | ||
{{action 'newPresence'}} | ||
type='button' | ||
> | ||
Nieuw | ||
</button> | ||
{{/if}} | ||
</BasicModal> | ||
</EmberWormhole> | ||
{{/if}} |
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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,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: 'chilling', | ||
label: 'Chillen', | ||
}, | ||
{ | ||
value: 'studying', | ||
label: 'Studeren', | ||
}, | ||
{ | ||
value: 'banaan', | ||
label: 'Banaan', | ||
}, | ||
], | ||
|
||
// 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('chilling')) { | ||
return 'Chillen'; | ||
} else if (currentStatusses.includes('studeren')) { | ||
return 'Studying'; | ||
} | ||
|
||
return 'banaan'; | ||
}), | ||
|
||
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: 'Studying', | ||
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; |
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; | ||
} |
There was a problem hiding this comment.
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):
this.
i.e.this.property
orthis.someFunction
@
. So, if the parent component has passed an argument calledsomeArgument
, then we can refer to it in this template with@someArgument
.{{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.