Skip to content

Commit ca88a8e

Browse files
Merge branch 'development' into patch-6
2 parents aa8233c + 1e5239d commit ca88a8e

File tree

127 files changed

+4952
-3969
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

127 files changed

+4952
-3969
lines changed

app/adapters/application.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,21 @@ export default JSONAPIAdapter.extend(HasManyQueryAdapterMixin, FastbootAdapter,
5757
return this._super(store, type, query);
5858
},
5959

60+
ajaxOptions(url, type) {
61+
const request = this._super(...arguments);
62+
63+
// The requests with public=true will not be authorized
64+
if (type === 'GET') {
65+
if (request.data.public) {delete request.headers[ENV['ember-simple-auth-token'].authorizationHeaderName]}
66+
67+
if (ENV.noCache === 'true') {
68+
request.data.nocache = true;
69+
}
70+
}
71+
72+
return request;
73+
},
74+
6075
/**
6176
This method is called for every response that the adapter receives from the
6277
API. If the response has a 401 status code it invalidates the session (see

app/components/footer-main.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,6 @@ export default class FooterMain extends Component {
2727
}
2828

2929
async didInsertElement() {
30-
this.set('pages', sortBy(await this.cache.findAll('page'), 'index'));
30+
this.set('pages', sortBy((await this.cache.query('pages', 'page', { public: true })).toArray(), 'index'));
3131
}
3232
}

app/components/forms/wizard/sessions-speakers-step.js

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -139,8 +139,13 @@ export default Component.extend(EventWizardMixin, FormMixin, {
139139
return grouped;
140140
}),
141141

142-
microlocations: computed('data.microlocations.@each.isDeleted', function() {
143-
return this.data.event.microlocations.filterBy('isDeleted', false);
142+
microlocations: computed('data.microlocations.@each.isDeleted', 'data.microlocations.@each.position', function() {
143+
const sortedRooms = this.data.event.microlocations.sortBy('position').filterBy('isDeleted', false);
144+
sortedRooms.forEach((room, idx) => {
145+
room.set('position', idx);
146+
});
147+
148+
return sortedRooms;
144149
}),
145150

146151
complexCustomForms: computed('data.customForms.@each.isComplex', function() {
@@ -183,9 +188,6 @@ export default Component.extend(EventWizardMixin, FormMixin, {
183188
case 'track':
184189
this.data.tracks.addObject(this.store.createRecord('track'));
185190
break;
186-
case 'microlocation':
187-
this.data.microlocations.addObject(this.store.createRecord('microlocation'));
188-
break;
189191
}
190192
},
191193
addCustomField() {
@@ -197,6 +199,27 @@ export default Component.extend(EventWizardMixin, FormMixin, {
197199
removeField(field) {
198200
this.data.customForms.removeObject(field);
199201
},
202+
addRoom(index) {
203+
this.microlocations.forEach(room => {
204+
const pos = room.get('position');
205+
pos > index && room.set('position', pos + 1);
206+
});
207+
this.data.event.microlocations.addObject(this.store.createRecord('microlocation', { position: index + 1 }));
208+
},
209+
removeRoom(room, index) {
210+
room.deleteRecord();
211+
this.microlocations.forEach(item => {
212+
const pos = item.get('position');
213+
pos > index && item.set('position', pos - 1);
214+
});
215+
},
216+
moveRoom(item, direction) {
217+
const idx = item.get('position');
218+
const otherIdx = direction === 'up' ? (idx - 1) : (idx + 1);
219+
const other = this.microlocations.find(item => item.get('position') === otherIdx);
220+
other.set('position', idx);
221+
item.set('position', otherIdx);
222+
},
200223
resetCFS() {
201224
this.set('data.speakersCall.announcement', null);
202225
},

app/components/public/add-to-calender.hbs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@
33
<i class="clock alternate outline icon pt-1"></i>
44
<div class="content">
55
{{#if this.isSingleDay}}
6-
{{general-date @event.startsAt @event.timezone "dddd, MMMM DD, YYYY"}}<br>{{general-date @event.startsAt @event.timezone "h:mm A"}} {{t 'to'}} {{general-date @event.endsAt @event.timezone "h:mm A"}}
6+
{{general-date @event.startsAt "dddd, D MMMM, YYYY" tz=@event.timezone}}<br>{{general-date @event.startsAt "h:mm A" tz=@event.timezone}} {{t 'to'}} {{general-date @event.endsAt "h:mm A" tz=@event.timezone}}
77
{{else}}
8-
{{general-date @event.startsAt @event.timezone "dddd, MMMM DD, YYYY h:mm A"}} {{t 'to'}} {{general-date @event.endsAt @event.timezone "dddd, MMMM DD, YYYY h:mm A"}}
8+
{{general-date @event.startsAt "dddd, D MMMM, YYYY h:mm A" tz=@event.timezone}} {{t 'to'}} {{general-date @event.endsAt "dddd, D MMMM, YYYY h:mm A" tz=@event.timezone}}
99
{{/if}}
1010
({{this.timezone}})
1111
<br>

app/components/public/call-for-speakers.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,11 @@ export default class CallForSpeakers extends Component {
1313
if (this.session.isAuthenticated) {
1414
this.router.transitionTo('public.cfs.new-speaker');
1515
} else {
16+
this.flashMessages.add({
17+
message : 'In order to add Speaker details you need to login',
18+
type : 'info',
19+
preventDuplicates : true
20+
});
1621
this.set('isLoginModalOpen', true);
1722
}
1823
}

app/components/public/session-item.hbs

Lines changed: 52 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,26 @@
1+
{{!-- template-lint-disable no-nested-interactive --}}
12
<UiAccordion class="segment p-0" style={{css background-color=@session.track.color border-color='lightgray'}}>
23
<div class="title p-4" {{action 'hideSpeakerImage'}} role="button" style={{css color=(text-color @session.track.color)}}>
34
<div class="ui">
45
<h3 class="ui header" id="session-id-{{@session.id}}" style={{css color=(text-color @session.track.color)}}>
56
{{@session.title}}
6-
{{#unless @hideSessionLink}}
7-
{{!-- template-lint-disable no-nested-interactive --}}
8-
<a href="{{href-to 'public.session.view' (or @event.identifier @session.event.identifier) @session.id}}" style={{css float='right' color=(text-color @session.track.color 'grey' 'lightgrey')}}><i class="share icon"></i></a>
9-
{{/unless}}
7+
<span style={{css float='right'}}>
8+
{{#if @session.slidesUrl}}
9+
<button class="ui basic {{text-color @session.track.color 'basic' 'inverted'}} button" style={{css color=(text-color @session.track.color 'grey' 'lightgrey')}} {{action this.goToSlides}}>
10+
<i class="icon {{if this.slidesUploaded 'download' 'linkify'}}"></i>
11+
{{if this.slidesUploaded (t 'Download Slides') (t 'Link to Slides')}}
12+
</button>
13+
{{/if}}
14+
{{#if @session.microlocation.hasVideoStream}}
15+
<button class="ui basic {{text-color @session.track.color 'basic' 'inverted'}} button" style={{css color=(text-color @session.track.color 'grey' 'lightgrey')}} {{action this.goToStream}}>
16+
<i class="icon video"></i>
17+
{{t 'Join Video'}}
18+
</button>
19+
{{/if}}
20+
{{#unless @hideSessionLink}}
21+
<a role="button" href="{{href-to 'public.session.view' (or @event.identifier @session.event.identifier) @session.id}}" style={{css color=(text-color @session.track.color 'grey' 'lightgrey')}}><i class="share icon"></i></a>
22+
{{/unless}}
23+
</span>
1024
<div class="sub header" style={{css color=(text-color @session.track.color) opacity=0.6}}>
1125
{{@session.sessionType.name}}
1226
</div>
@@ -19,7 +33,7 @@
1933
<div class="left floated twelve wide column">
2034
{{#if @session.startsAt}}
2135
<div class=""><i class="icon map marker alternate"></i>{{@session.microlocation.name}}</div>
22-
<div class="small text"><i class="wait icon"></i>{{general-date @session.startsAt @timezone}} - {{general-date @session.endsAt @timezone}}</div>
36+
<div class="small text"><i class="wait icon"></i>{{general-date @session.startsAt 'D MMM, YYYY h:mm A (z)' tz=@timezone}}</div>
2337
{{/if}}
2438
</div>
2539
{{else}}
@@ -32,7 +46,7 @@
3246
</div>
3347
<div class="left floated nine wide column">
3448
{{#each @session.speakers as |speaker|}}
35-
{{speaker.name}} ({{speaker.position}}, {{speaker.organisation}})
49+
{{speaker.name}} {{#if speaker.positionOrganisation}}({{speaker.positionOrganisation}}){{/if}}
3650
<br>
3751
{{/each}}
3852
</div>
@@ -41,19 +55,18 @@
4155
<div class="right floated four wide column">
4256
{{#if @session.startsAt}}
4357
<div class=""><i class="icon map marker alternate"></i>{{@session.microlocation.name}}</div>
44-
<div class="small text"><i class="wait icon"></i>{{general-date @session.startsAt @timezone 'hh:mm a / DD-MM-YYYY (z)'}}</div>
58+
<div class="small text"><i class="wait icon"></i>{{general-date @session.startsAt 'D MMM, YYYY h:mm A (z)' tz=@timezone}}</div>
4559
{{/if}}
4660
</div>
4761
{{/if}}
48-
49-
<div class="row">
50-
<div class="column session-description">
51-
{{sanitize @session.shortAbstract}}
52-
</div>
53-
</div>
5462
</div>
5563
</div>
5664
<div class="content pt-0 p-4 rounded-t-none {{if @expanded 'active'}}" style={{css background-color='white' border-radius='0.2rem'}}>
65+
<div class="ui pt-4 row">
66+
<div class="column session-description">
67+
{{sanitize @session.shortAbstract}}
68+
</div>
69+
</div>
5770
{{#if (and @expanded (or @session.slidesUrl @session.videoUrl))}}
5871
<div class="row p-4">
5972
<div class="column" style={{css display='flex' align-items='center' flex-direction='column'}}>
@@ -81,13 +94,39 @@
8194
</div>
8295
</div>
8396
{{/if}}
97+
98+
{{#if @session.microlocation.hasVideoStream}}
99+
<p style="white-space: pre-line;">
100+
<a class="mt-2" href="{{href-to 'public.stream.view' (or @event.identifier @session.event.identifier) @session.microlocation.videoStream.slugName @session.microlocation.videoStream}}" target="_blank" rel="noopener">{{t 'Join Video Channel'}}</a>
101+
{{#if @session.microlocation.videoStream.password}}
102+
<div class="d-flex items-center">
103+
<span>{{t 'Password'}}: </span>
104+
<UiPopup @on="click" @content={{t "Copied to clipboard"}} @position="bottom right" style="white-space: normal;">
105+
<CopyButton @clipboardText={{@session.microlocation.videoStream.password}} class="ui basic segments">
106+
<div class="ui left labeled button">
107+
<div class="ui basic label">
108+
{{@session.microlocation.videoStream.password}}
109+
</div>
110+
<div class="ui icon button">
111+
<i class="copy icon"></i>
112+
</div>
113+
</div>
114+
</CopyButton>
115+
</UiPopup>
116+
</div>
117+
{{/if}}
118+
{{@session.microlocation.videoStream.additionalInformation}}
119+
</p>
120+
{{/if}}
84121

85122
{{#each @session.speakers as |speaker|}}
86123
<img alt="speaker" class="ui tiny avatar image mt-8" src="{{if speaker.thumbnailImageUrl speaker.thumbnailImageUrl (if speaker.photoUrl speaker.photoUrl '/images/placeholders/avatar.png')}}">
87124
<p>
88125
<br>
89126
{{speaker.name}}
90127
<br>
128+
{{speaker.positionOrganisation}}
129+
<br>
91130
{{#if speaker.shortBiography}}
92131
{{sanitize speaker.shortBiography}}
93132
{{else if speaker.longBiography}}

app/components/public/session-item.js

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
11
import { action } from '@ember/object';
22
import Component from '@glimmer/component';
3+
import { inject as service } from '@ember/service';
4+
import { tracked } from '@glimmer/tracking';
35
import { extractYoutubeUrl } from 'open-event-frontend/utils/url';
46

57
export default class SessionItem extends Component {
6-
hideImage = false;
8+
@service router;
9+
10+
@tracked
11+
hideImage = this.args.expanded;
712

813
get youtubeLink() {
914
return extractYoutubeUrl(this.args.session.videoUrl);
@@ -18,11 +23,27 @@ export default class SessionItem extends Component {
1823
return slidesUrl?.indexOf('.pptx') > -1 || slidesUrl?.indexOf('.ppt') > -1;
1924
}
2025

26+
get slidesUploaded() {
27+
const url = this.args.session.slidesUrl;
28+
return url.startsWith('https://open-event-api-dev.herokuapp.com') || url.startsWith('https://api.eventyay.com');
29+
}
30+
2131
@action
2232
hideSpeakerImage() {
2333
this.hideImage = !this.hideImage;
2434
if (!this.args.session.speakers.length) {
2535
this.hideImage = false;
2636
}
2737
}
38+
39+
@action
40+
goToSlides() {
41+
window.open(this.args.session.slidesUrl, '_blank');
42+
}
43+
44+
@action
45+
goToStream() {
46+
const url = this.router.urlFor('public.stream.view', this.args.event?.identifier ?? this.args.session.get('event.identifier'), this.args.session.get('microlocation.videoStream.slugName'), this.args.session.get('microlocation.videoStream.id'));
47+
window.open(url, '_blank');
48+
}
2849
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
<div {{did-insert this.setup}}>
2+
{{@videoStream.name}}
3+
</div>
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
import Component from '@glimmer/component';
2+
import { action } from '@ember/object';
3+
import { inject as service } from '@ember/service';
4+
import VideoStream from 'open-event-frontend/models/video-stream';
5+
import { getScript } from 'open-event-frontend/utils/loader';
6+
import AuthManagerService from 'open-event-frontend/services/auth-manager';
7+
import UrlParser from 'url-parse';
8+
9+
declare global {
10+
interface Window {
11+
JitsiMeetExternalAPI: any;
12+
}
13+
}
14+
15+
interface Args {
16+
videoStream: VideoStream
17+
}
18+
19+
export default class PublicStreamVideoStream extends Component<Args> {
20+
21+
@service
22+
authManager!: AuthManagerService
23+
24+
app: HTMLElement | null = null
25+
26+
getRoomName(parsedUrl: UrlParser): string {
27+
return parsedUrl.pathname.slice(1); // drop leading slash
28+
}
29+
30+
isJitsi(parsedUrl: UrlParser): boolean {
31+
return parsedUrl.host.endsWith('jit.si');
32+
}
33+
34+
@action
35+
async setup(): Promise<void> {
36+
const stream = this.args.videoStream;
37+
38+
const parsedUrl = new UrlParser(stream.url, true);
39+
40+
this.app = (document.querySelector('.ember-application') as HTMLElement);
41+
this.app.innerHTML = '<div class="ui active centered inline loader"></div>';
42+
43+
if (this.isJitsi(parsedUrl)) {
44+
await this.setupJitsi(stream, parsedUrl);
45+
} else {
46+
location.href = stream.url;
47+
}
48+
}
49+
50+
async setupJitsi(stream: VideoStream, parsedUrl: UrlParser): Promise<void> {
51+
const app = (document.querySelector('.ember-application') as HTMLElement);
52+
app.innerHTML = '<div class="ui active centered inline loader"></div>';
53+
await getScript(parsedUrl.origin + '/external_api.js');
54+
const domain = parsedUrl.host;
55+
const options = {
56+
roomName : this.getRoomName(parsedUrl),
57+
parentNode : document.querySelector('.ember-application'),
58+
userInfo : {
59+
email : this.authManager.currentUser.email,
60+
displayName : this.authManager.currentUser.fullName
61+
},
62+
configOverwrite: {
63+
prejoinPageEnabled : false,
64+
startWithAudioMuted : true,
65+
startWithVideoMuted : true
66+
},
67+
interfaceConfigOverwrite: {
68+
HIDE_INVITE_MORE_HEADER: true
69+
}
70+
};
71+
(this.app as HTMLElement).innerHTML = '';
72+
const api = new window.JitsiMeetExternalAPI(domain, options);
73+
74+
api.executeCommand('subject', stream.name);
75+
76+
if (stream.password) {
77+
api.addEventListener('participantRoleChanged', (event: any) => {
78+
if (event.role === 'moderator') {
79+
api.executeCommand('password', stream.password);
80+
}
81+
});
82+
// join a protected channel
83+
api.on('passwordRequired', () => {
84+
api.executeCommand('password', stream.password);
85+
});
86+
}
87+
}
88+
}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{{general-date @record @props.options.timezone @props.options.dateFormat}}
1+
{{general-date @record @props.options.dateFormat tz=@props.options.timezone}}

0 commit comments

Comments
 (0)