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
Adds sessions layout public event #68
Conversation
Codecov Report
@@ Coverage Diff @@
## development #68 +/- ##
===============================================
+ Coverage 58.83% 59.01% +0.17%
===============================================
Files 129 133 +4
Lines 945 954 +9
===============================================
+ Hits 556 563 +7
- Misses 389 391 +2
Continue to review full report at Codecov.
|
@geekyd Looks good, but I think it would look better if we increase some space between the "Talk" and the image. |
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.
A few functional changes. UI review I'll do it once this is done.
app/controllers/public/sessions.js
Outdated
const { Controller, computed } = Ember; | ||
|
||
export default Controller.extend({ | ||
sessions: [{ shortAbstract: 'An introduction to the event', id: '1', title: 'Welcome to FOSSASIA', startAt: '10:35 AM / 17-03-2017', track: { color: 'green', fontColor: 'green', id: 0, name: 'Track 1' }, microlocation: { id: 0, name: 'Room 1' }, speakers: [{ shortBiography: 'Works for ORG 1', id: 0, city: 'Delhi', name: 'Arnold Singh', speakingExperience: 'GSOC 2015', organisation: 'ORG 1', longBiography: '', photo: { 'iconImageUrl': '' } }] }, |
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.
Like I said in the issue, the startsAt and endsAt fields will be a js Date object. not a string.
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.
@niranjan94 As we are going to use model for getting sessions, it would be better if we use parse the dates in the model.
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.
The model's output is gonna be a js date object. (It will parse the API Response and give a js date output) ... And we shouldn't do the date -> string conversion in the model ... because the string date format we require might vary depending on where the session is being displayed in the UI.
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.
Like for example,
- in this page we may want to display it in a more human readable form like
March 23, 2017 05:30 PM
- In the sessions table we'll display
23/03/2017 05:30 PM
- In the form we may display in another way for it to work with the date picker.
We can't and shouldn't put all of this inside the model.
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.
Okay got it!
app/helpers/underscore-text.js
Outdated
|
||
const { Helper } = Ember; | ||
|
||
export function underscoreText(params) { |
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 remove this helper and use the underscore
helper from ember-cli-string-helpers which is already a part of this project.
@@ -0,0 +1,5 @@ | |||
<div class="ui segment"> | |||
{{#each-in tracks as |track|}} |
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.
I think tabs would look better. And when a user presses on a track, don't scroll to it. Instead filter the whole list to display only that track.
f03e8d6
to
d35dad4
Compare
@niranjan94 Please review. |
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.
Be reactive to data. Let computed properties do a lot of heavy lifting for you.
In your action based implementation, even if I'm on all tracks and keep pressing the all tab, the whole action will keep getting executed and hence the sessionsByTracks
will keep getting computed.
But in the case of computed properties, unless the selected track changes, it'll not get recomputed. You can click on a button how many ever times you want.
And the next thing is, when you have an ID for any data object, never depend on it's name.
app/controllers/public/sessions.js
Outdated
return keys(groupBy(orderBy(this.get('sessions'), 'startAt'), 'track.name')); | ||
}), | ||
actions: { | ||
filterSession(element) { |
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.
Remove this action.
app/controllers/public/sessions.js
Outdated
sessions: [{ shortAbstract: 'An introduction to the event', id: '1', title: 'Welcome to FOSSASIA', startAt: moment(new Date()).format('h:mm a / DD-MM-YYYY'), track: { color: 'green', fontColor: 'green', id: 0, name: 'Track 1' }, microlocation: { id: 2, name: 'Room 1' }, speakers: [{ shortBiography: 'Works for ORG 1', id: 0, city: 'Delhi', name: 'Arnold Singh', speakingExperience: 'GSOC 2015', organisation: 'ORG 1', longBiography: '', photo: { 'iconImageUrl': '' } }] }, | ||
{ shortAbstract: 'Welcome to open source', id: '2', title: 'Introduction to Open source', startAt: moment(new Date().setMinutes(10)).format('h:mm a / DD-MM-YYYY'), track: { color: 'red', fontColor: 'white', id: 0, name: 'Track 2' }, microlocation: { id: 3, name: 'Room 5' }, speakers: [{ shortBiography: '', id: 0, city: 'Delhi', name: 'Tux', speakingExperience: 'Speaker at the high conference', organisation: 'ORG 2', longBiography: '', photo: { 'iconImageUrl': '' } }] } | ||
], | ||
sessionsByTracks: computed('sessions.[]', function() { |
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.
Let this computed function depend on sessions.[]
and selectedTrackId
You don't have to declare selectedTrackId
anywhere. it is by default null. If it is null consider it to be all tracks. Else filter by that track id
app/templates/public/sessions.hbs
Outdated
@@ -1 +1,4 @@ | |||
{{outlet}} | |||
<h2 class="ui header">Sessions</h2> | |||
{{public/session-filter filterSession=(action 'filterSession') tracks=tracks}} |
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.
Change to
{{public/session-filter selectedTrackId=selectedTrackId tracks=tracks}}
Note that you're passing in the selectedTrackId
variable
|
||
actions: { | ||
filter(element, event) { | ||
this.set('selectedTrack', event.target.id); |
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.
Change to
this.set('selectedTrackId', trackId);
selectedTrack: 'all', | ||
|
||
actions: { | ||
filter(element, event) { |
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.
Change to
filter(trackId = null) {
If no trackId is passed it is considered as null
@@ -0,0 +1,10 @@ | |||
<div class="ui secondary menu"> | |||
<a href="#" class="item {{if (eq selectedTrack 'all') 'active'}}" id="all" onclick={{action 'filter' 'All'}}> |
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.
Change to
<a href="#" class="item {{unless selectedTrackId 'active'}}" {{action 'filter'}}>
Here if selectedTrackId
is null it is considered to be all tracks.
And for action you don't have to specify onclick=
And note that we're not passing any argument to the action. hence trackId in the action will be null.
All | ||
</a> | ||
{{#each tracks as |track|}} | ||
<a href="#" class="item {{if (eq selectedTrack (underscore track)) 'active'}}" id="{{underscore track}}" onclick={{action 'filter' track}}> |
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.
Can be changed to
<a href="#" class="item {{if (eq selectedTrackId track.id) 'active'}}" {{action 'filter' track.id}}>
{{track.name}}
</a>
Now from anywhere in that page, all I have to do is change |
@niranjan94 Thank you for the detailed review and proposing a better solution. I have made the required changes. Please review it. |
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.
app/controllers/public/sessions.js
Outdated
} | ||
}), | ||
tracks: computed('sessions.[]', function() { | ||
var allTracks = mapValues(keyBy(orderBy(this.get('sessions'), 'startAt'), 'track.id'), function(v) { |
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.
This can be better written as
chain(this.get('sessions'))
.map('track')
.uniqBy('id')
.orderBy('name')
.value()
chain
is also a lodash method.
That way we don't have to order all the sessions before getting the tracks and we get all contents of the track object.
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.
The output will be an array of track objects.
app/controllers/public/sessions.js
Outdated
{ shortAbstract: 'Welcome to open source', id: '2', title: 'Introduction to Open source', startAt: moment(new Date().setMinutes(10)).format('h:mm a / DD-MM-YYYY'), track: { color: 'red', fontColor: 'white', id: 2, name: 'Track 2' }, microlocation: { id: 3, name: 'Room 5' }, speakers: [{ shortBiography: '', id: 0, city: 'Delhi', name: 'Tux', speakingExperience: 'Speaker at the high conference', organisation: 'ORG 2', longBiography: '', photo: { 'iconImageUrl': '' } }] } | ||
], | ||
sessionsByTracks: computed('sessions.[]', 'selectedTrackId', function() { | ||
var allSessions = mapValues(groupBy(orderBy(this.get('sessions'), 'startAt'), 'track.id'), function(v) { |
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.
This can be written as
Unfiltered:
chain(this.get('sessions'))
.orderBy(['track.name', 'startAt'])
.groupBy('track.name')
.value();
Filtered:
chain(this.get('sessions'))
.filter(['track.id', this.get('selectedTrackId')])
.orderBy(['track.name', 'startAt'])
.groupBy('track.name')
.value();
Ordering and grouping are the operations that usually take up more time. So all filtering should be done before them so that they get as less data as possible.
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.
This will give an output like
{
'Track name': []
}
Where []
is an array of sessions. You can use each-in
in the template to loop through this and get both track name and the sessions.
app/controllers/public/sessions.js
Outdated
const { Controller, computed } = Ember; | ||
|
||
export default Controller.extend({ | ||
sessions: [{ shortAbstract: 'An introduction to the event', id: '1', title: 'Welcome to FOSSASIA', startAt: moment(new Date()).format('h:mm a / DD-MM-YYYY'), track: { color: 'green', fontColor: 'green', id: 1, name: 'Track 1' }, microlocation: { id: 2, name: 'Room 1' }, speakers: [{ shortBiography: 'Works for ORG 1', id: 0, city: 'Delhi', name: 'Arnold Singh', speakingExperience: 'GSOC 2015', organisation: 'ORG 1', longBiography: '', photo: { 'iconImageUrl': '' } }] }, |
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.
Again ... like I said startAt
and endAt
will NOT be a string. It will be a date object. You need to use ember-moment template helpers to display it how you like.
@niranjan94 Please review. |
app/controllers/public/sessions.js
Outdated
var allSessions = chain(this.get('sessions')) | ||
.orderBy(['startAt', 'startAt']) | ||
.groupBy('track.id') | ||
.mapValues(function(v) { |
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.
Why is this needed ?
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.
Since you're anyway only using track name in the view.
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.
Just a groupBy track.name should give you all the info you need+sessions
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.
I'm using the id to map the tracks and not the names anymore. That's the reason we are using this function to map the track id with the sessions.
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.
You're performing unnecessary operations here. With what I suggested here > #68 (comment) you can perform one operation less and yet achieve the same results.
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.
For UI grouping, track name shouldn't be an issue.
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.
We pass tracks to the filter component which stores selectedTrackId
the id of the selected track. We need to update the session-filter according to this information, therefore I have used track id and not track name to populate and bind the sessions under a track id to the id in session-filter.
Now whenever selectedTrackId
changes it filters the sessions of session-list according to the trackid.
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.
@geekyd that's exactly what is being done here too #68 (comment) but with one less operation.
With one or two sessions, a single less operation isn't gonna matter. But with hundreds of session, a single operation, especially ones like mapValues
matter a lot
app/controllers/public/sessions.js
Outdated
], | ||
sessionsByTracks: computed('sessions.[]', 'selectedTrackId', function() { | ||
var allSessions = chain(this.get('sessions')) | ||
.orderBy(['startAt', 'startAt']) |
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.
Duplicate entry
@niranjan94 Removed |
@@ -0,0 +1,8 @@ | |||
{{#each-in sessions as |id trackSession|}} |
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.
call id
as trackName
@@ -0,0 +1,8 @@ | |||
{{#each-in sessions as |id trackSession|}} |
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.
Now. When it is filtered by a track, what is going to come here is an array and not an object. Please handle that too.
TL,DR;
The session-list component should be able to render both an array of sessions and an object (when it is grouped by track)
You can use the is-array
helper available
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.
There is no need to handle this as output of both filter and unfiltered data is always going to be an object and not an array.
The format:
{ track1: Array, track2: Array ...}
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.
Crap. Did not notice that groupBy in the filtered output. We should remove that. No point grouping by track when we are filtering by track.
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.
And one more reason to have array support. If at in future we implement API calls for session filtering, we'll be getting sessions as array in the response.
@niranjan94 Made the changes. Please review. |
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.
{{/each}} | ||
{{else}} | ||
{{#each-in sessions as |track trackSession|}} | ||
<h3 class="ui header" id="{{underscore track}}">{{track}}</h3> |
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.
The ID can be removed
@@ -0,0 +1,15 @@ | |||
<div class="ui session-container"> | |||
{{#if (is-array sessions)}} | |||
<h3 class="ui header" id="{{underscore track}}">{{track}}</h3> |
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.
The ID can be removed
const { Component } = Ember; | ||
|
||
export default Component.extend({ | ||
classNames: ['ui', 'accordion', 'segment'] |
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.
<div class="title"> | ||
<div class="ui"> | ||
<h4 class="ui header">{{session.title}}</h4> | ||
<div class="ui row">Talk</div> |
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.
This should be the session type.
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.
And add this as a subheader to your header for a better UI
<h4 class="ui header">
{{session.title}}
<div class="sub header">
{{session.sessionType.name}}
</div>
</h4>
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.
Also, increase from h4
to h3
</div> | ||
<br> | ||
<div class="ui grid"> | ||
<div class="column twelve wide"> |
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.
<div class="title"> | ||
<div class="ui"> | ||
<h4 class="ui header">{{session.title}}</h4> | ||
<div class="ui row">Talk</div> |
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.
Also, increase from h4
to h3
@niranjan94 Please review. |
</div> | ||
</div> | ||
<div class="ui row"> | ||
<div class="session-description"> |
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.
There should be a column inside the row. So put this inside a div with class column
@niranjan94 Made the changes. Please review. |
<div class="">{{moment-format session.startAt 'hh:mm a / DD-MM-YYYY'}} <i class="wait icon"></i></div> | ||
</div> | ||
</div> | ||
<div class="ui row"> |
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.
Looks like the row is out side the grid ?
Should be something like this.
<div class="ui grid">
<div class="row">
<!-- speaker pics and microlocation/time -->
</div>
<div class="row">
<div class="column">
{{session.shortAbstract}}
</div>
</div>
A row
cannot exist outside a ui grid
@niranjan94 Please review. |
development
branch.Short description of what this resolves:
Adds session layout in public events page
Added components
####Screenshot
Fixes #63
@niranjan94 Please review.