Skip to content

Commit ba8b1c3

Browse files
Hieu Lam - TMAkhangon
andauthored
feature-9075: Reduce complexity of mobile screens and minimize white spaces (#9096)
* feature-9075: Reduce complexity of mobile screens and minimize white spaces * feature-9075: Reduce complexity of mobile screens and minimize white spaces --------- Co-authored-by: Khang On - TMA <[email protected]>
1 parent ad3851f commit ba8b1c3

File tree

6 files changed

+262
-20
lines changed

6 files changed

+262
-20
lines changed
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
<div class="ui list basic segment m-0 pl-0 pr-0 pb-0 add-to-calender-join-video">
2+
{{#if @hasStreams}}
3+
<div class="btn-join-video-mobile">
4+
<button class="{{unless @showVideo 'primary' 'basic'}} ui button no-wrap" {{action this.openPanel}}>
5+
<i class="icon calendar"></i>
6+
{{t 'Join Live Event'}}
7+
</button>
8+
</div>
9+
<div class="btn-add-to-calender-mobile">
10+
<UiDropdown class="ui floating dropdown button w-full text center aligned">
11+
<i class="add to calendar icon"></i>
12+
{{t 'Add to Calendar'}}
13+
<div class="menu">
14+
<button {{action 'openAddToCalendarModal' this.calendarUrls}} class="ui item inverted fluid button">{{t 'Add Event'}}</button>
15+
{{#if (and @event.isSchedulePublished this.showSessions)}}
16+
<button {{action 'openAddToCalendarModal' this.sessionCalendarUrls}} class="ui item inverted fluid button">{{t 'Add Sessions'}}</button>
17+
{{#if this.authManager.currentUser}}
18+
<button {{action 'openAddToCalendarModal' this.mySessionCalendarUrls}} class="ui item inverted fluid button">{{t 'Add My Schedule'}}</button>
19+
{{/if}}
20+
{{/if}}
21+
</div>
22+
</UiDropdown>
23+
</div>
24+
{{else}}
25+
<div class="mt-4">
26+
<UiDropdown class="ui floating dropdown button w-full text center aligned">
27+
<i class="add to calendar icon"></i>
28+
{{t 'Add to Calendar'}}
29+
<div class="menu">
30+
<button {{action 'openAddToCalendarModal' this.calendarUrls}} class="ui item inverted fluid button">{{t 'Add Event'}}</button>
31+
{{#if (and @event.isSchedulePublished this.showSessions)}}
32+
<button {{action 'openAddToCalendarModal' this.sessionCalendarUrls}} class="ui item inverted fluid button">{{t 'Add Sessions'}}</button>
33+
{{#if this.authManager.currentUser}}
34+
<button {{action 'openAddToCalendarModal' this.mySessionCalendarUrls}} class="ui item inverted fluid button">{{t 'Add My Schedule'}}</button>
35+
{{/if}}
36+
{{/if}}
37+
</div>
38+
</UiDropdown>
39+
</div>
40+
{{/if}}
41+
</div>
42+
43+
<Modals::AddToCalendar @isOpen={{this.isAddToCalendarModalOpen}} @calendarUrls={{this.modalUrls}}/>
Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
import Component from '@glimmer/component';
2+
import moment from 'moment-timezone';
3+
import Event from 'open-event-frontend/models/event';
4+
import { inject as service } from '@ember/service';
5+
import { tracked } from '@glimmer/tracking';
6+
import { hasSessions } from 'open-event-frontend/utils/event';
7+
import AuthManagerService from 'open-event-frontend/services/auth-manager';
8+
import VideoStream from 'open-event-frontend/models/video-stream';
9+
import Loader from 'open-event-frontend/services/loader';
10+
import { action } from '@ember/object';
11+
import EventService from 'open-event-frontend/services/event';
12+
13+
interface Args {
14+
videoStream: VideoStream;
15+
event: Event;
16+
hasStreams: boolean;
17+
canAccess: boolean;
18+
showSidePanel: () => void;
19+
location: string
20+
}
21+
22+
23+
export default class AddToCalender extends Component<Args> {
24+
@service
25+
authManager!: AuthManagerService;
26+
27+
@tracked showSessions : any;
28+
29+
@tracked isAddToCalendarModalOpen = false;
30+
31+
@tracked modalUrls : { name: string; url: string; }[] = [];
32+
@service router: any;
33+
@service loader!: Loader;
34+
@service confirm: any;
35+
@service l10n: any;
36+
@service session : any;
37+
@service declare event: EventService;
38+
39+
get description(): string {
40+
const { event } = this.args;
41+
let desc = `Join the event at <a href = "${event.url}">${event.url}</a>\n `;
42+
if (event.description) {
43+
desc = desc + `<section><h3>Event Description </h3>\n${event.description}\n</section>`;
44+
}
45+
if (event.ownerDescription) {
46+
desc = desc + `<section><h3>Organizer Message </h3>\n${event.ownerDescription}\n</section>`;
47+
}
48+
return desc;
49+
}
50+
51+
constructor(owner: null, args: Args) {
52+
super(owner, args);
53+
this.checkSessions();
54+
}
55+
56+
openAddToCalendarModal(calendarUrls: { name: string; url: string; }[]): void {
57+
this.isAddToCalendarModalOpen = true;
58+
this.modalUrls = calendarUrls;
59+
}
60+
61+
async checkSessions(): Promise<void> {
62+
const { event } = this.args;
63+
this.showSessions = this.showSessions ?? await hasSessions(this.loader, event);
64+
}
65+
66+
get startsAt(): moment.Moment {
67+
const { event } = this.args;
68+
return moment(event.startsAt).tz(event.timezone);
69+
}
70+
71+
get endsAt(): moment.Moment {
72+
const { event } = this.args;
73+
return moment(event.endsAt).tz(event.timezone);
74+
}
75+
76+
get calendarLocation(): string {
77+
return this.args.event.online ? this.args.event.url : this.args.location;
78+
}
79+
80+
get googleUrl(): string {
81+
const { event } = this.args;
82+
const startTime = this.startsAt.utc().format('YYYYMMDD[T]HHmmSS[Z]');
83+
const endTime = this.endsAt.utc().format('YYYYMMDD[T]HHmmSS[Z]');
84+
return `https://calendar.google.com/calendar/render?action=TEMPLATE&dates=${startTime}/${endTime}&text=${event.name}&location=${this.calendarLocation}&ctz=${event.timezone}&details=${this.description}`;
85+
}
86+
87+
get yahooUrl(): string {
88+
const { event } = this.args;
89+
const startTime = this.startsAt.format('YYYYMMDD[T]HHmmSS');
90+
const endTime = this.endsAt.format('YYYYMMDD[T]HHmmSS');
91+
return `https://calendar.yahoo.com/?v=60&title=${event.name}&st=${startTime}&et=${endTime}&desc=${this.description.replace(/<[^>]+>/g, '')}&in_loc=${this.calendarLocation}`;
92+
}
93+
94+
get outlookUrl(): string {
95+
const { event } = this.args;
96+
const startTime = this.startsAt.utc().format('YYYY[-]MM[-]DDTHH[:]mm[:]SS[Z]');
97+
const endTime = this.endsAt.utc().format('YYYY[-]MM[-]DDTHH[:]mm[:]SS[Z]');
98+
return `https://outlook.live.com/calendar/0/deeplink/compose?subject=${event.name}&startdt=${startTime}&enddt=${endTime}&body=${(this.description).substring(0, 1000)}&location=${this.calendarLocation}`;
99+
}
100+
101+
get iCalUrl(): string {
102+
const host = this.loader.host();
103+
return host + '/v1/events/' + this.args.event.identifier + '.ics?download';
104+
}
105+
106+
get calendarUrls(): { name: string; url: string; }[] {
107+
return [{ name: 'Google Calendar', url: this.googleUrl }, { name: 'iCal', url: this.iCalUrl }, { name: 'Yahoo', url: this.yahooUrl }, { name: 'Outlook', url: this.outlookUrl }];
108+
}
109+
110+
get sessionGoogleUrl(): string {
111+
const { event } = this.args;
112+
let host = this.loader.host();
113+
host = host.replace('https://', '')
114+
return 'https://calendar.google.com/calendar/render?cid=webcal://' + host + '/v1/events/' + event.identifier + '.ics?include_sessions';
115+
}
116+
117+
get mySessionGoogleUrl(): string {
118+
const { event } = this.args;
119+
let host = this.loader.host();
120+
host = host.replace('https://', '');
121+
return 'https://calendar.google.com/calendar/render?cid=webcal://' + host + '/v1/events/' + event.identifier + encodeURIComponent('.ics?include_sessions&my_schedule&user_id=') + this.authManager.currentUser.id;
122+
}
123+
124+
get mySessioniCalUrl(): string {
125+
const host = this.loader.host();
126+
return host + '/v1/events/' + this.args.event.identifier + '.ics?include_sessions&my_schedule&user_id=' + this.authManager.currentUser.id;
127+
}
128+
129+
get sessioniCalUrl(): string {
130+
const host = this.loader.host();
131+
return host + '/v1/events/' + this.args.event.identifier + '.ics?include_sessions';
132+
}
133+
134+
get sessionCalendarUrls(): { name: string; url: string; }[] {
135+
return [{ name: 'Google Calendar', url: this.sessionGoogleUrl }, { name: 'iCal', url: this.sessioniCalUrl }];
136+
}
137+
138+
get mySessionCalendarUrls(): { name: string; url: string; }[] {
139+
return [{ name: 'Google Calendar', url: this.mySessionGoogleUrl }, { name: 'iCal', url: this.mySessioniCalUrl }];
140+
}
141+
142+
@action
143+
openPanel(): void {
144+
if (this.args.canAccess) {
145+
this.args.showSidePanel?.();
146+
this.router.transitionTo({ queryParams: { side_panel: true } });
147+
} else {
148+
if (this.session.isAuthenticated) {
149+
this.router.transitionTo('public', this.args.event, { queryParams: { video_dialog: true } });
150+
} else {
151+
this.router.transitionTo({ queryParams: { video_dialog: true } });
152+
}
153+
}
154+
}
155+
}

app/components/public/side-menu.js

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -75,9 +75,12 @@ export default class SideMenu extends Component {
7575
@action
7676
scrollToTarget(section) {
7777
this.hideSidebar();
78-
document.querySelector(`#${section}`).scrollIntoView({
79-
behavior: 'smooth'
80-
});
78+
const target = document.querySelector(`#${section}`);
79+
if (target) {
80+
target.scrollIntoView({
81+
behavior: 'smooth'
82+
});
83+
}
8184
this.set('activeMenuSection', section);
8285
this.set('activeSection', null);
8386
document.querySelectorAll('.scroll').forEach(node => {

app/styles/partials/utils.scss

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -253,4 +253,31 @@
253253
.align-bottom {
254254
vertical-align: bottom;
255255
}
256-
256+
257+
.add-to-calender-join-video {
258+
height: 36px;
259+
}
260+
261+
.btn-add-to-calender-mobile {
262+
width: 50%;
263+
float: left;
264+
265+
.button {
266+
border-radius: 0 !important;
267+
}
268+
}
269+
270+
.btn-join-video-mobile {
271+
width: 50%;
272+
float: left;
273+
274+
.button {
275+
border-radius: 0 !important;
276+
}
277+
}
278+
279+
@media screen and (max-width: 767px) {
280+
.ui.stackable.grid > .wide.column {
281+
padding-bottom: 0 !important;
282+
}
283+
}

app/templates/public.hbs

Lines changed: 29 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -41,33 +41,47 @@
4141
</div>
4242
<div class="sixteen wide column content {{if this.smallLead 'with small lead'}}" id="event-contents">
4343
<div class="ui stackable grid">
44-
<div class="three wide column" id="public-event-content">
45-
{{#unless this.device.isMobile}}
44+
{{#unless this.device.isMobile}}
45+
<div class="three wide column" id="public-event-content">
4646
{{#if this.displaySideMenu}}
4747
<div class="ui fluid side-menu">
4848
<Public::SideMenuOuter @event={{this.model}} />
4949
</div>
5050
{{/if}}
51-
{{/unless}}
52-
</div>
51+
</div>
52+
{{/unless}}
5353
{{#unless this.device.isMobile}}
5454
<div class="ten wide column">
5555
{{outlet}}
5656
</div>
5757
{{/unless}}
5858
<div class="three wide column">
5959
{{#if this.displaySideMenu}}
60-
<Public::Stream::JoinVideo
61-
@showVideo={{false}}
62-
@event={{this.model}}
63-
@videoStream={{this.model.videoStream}}
64-
@canAccess={{this.canAccess}}
65-
@hasStreams={{this.hasStreams}}
66-
@sameTab={{this.side_panel}}
67-
@showSidePanel={{action "showSidePanel"}}
68-
class="ui basic segment m-0 p-0" />
69-
<Public::AddToCalender @event={{this.model}} @location={{this.headerLocation}}/>
70-
{{#if (not-eq this.session.currentRouteName 'public.exhibition.view')}}
60+
{{#if this.device.isMobile}}
61+
<Public::AddToCalenderJoinVideo
62+
@event={{this.model}}
63+
@location={{this.headerLocation}}
64+
@showVideo={{false}}
65+
@videoStream={{this.model.videoStream}}
66+
@canAccess={{this.canAccess}}
67+
@hasStreams={{this.hasStreams}}
68+
@sameTab={{this.side_panel}}
69+
@showSidePanel={{action "showSidePanel"}}
70+
class="ui basic segment m-0 p-0 mb-0"
71+
/>
72+
{{else}}
73+
<Public::Stream::JoinVideo
74+
@showVideo={{false}}
75+
@event={{this.model}}
76+
@videoStream={{this.model.videoStream}}
77+
@canAccess={{this.canAccess}}
78+
@hasStreams={{this.hasStreams}}
79+
@sameTab={{this.side_panel}}
80+
@showSidePanel={{action "showSidePanel"}}
81+
class="ui basic segment m-0 p-0" />
82+
<Public::AddToCalender @event={{this.model}} @location={{this.headerLocation}}/>
83+
{{/if}}
84+
{{#if (and (not-eq this.session.currentRouteName 'public.exhibition.view') (not-eq this.session.currentRouteName 'public.coc'))}}
7185
{{#if (not-eq this.router.currentRoute.name 'public.sessions.index')}}
7286
<Public::SocialLinks @externalUrl={{this.model.externalEventUrl}} @socialLinks={{this.model.socialLinks}}/>
7387
{{/if}}

app/utils/file.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ export const humanReadableBytes = (sizeInKb, absolute = true, si = true) => {
1313
do {
1414
bytes /= thresh;
1515
++u;
16-
} while (Math.round(Math.abs(bytes)*100)/100 >= thresh && u < units.length - 1);
16+
} while (Math.round(Math.abs(bytes) * 100) / 100 >= thresh && u < units.length - 1);
1717
return `${bytes.toFixed(absolute ? 0 : 1)} ${units[u]}`;
1818
};
1919

0 commit comments

Comments
 (0)