amazon-chime-sdk-rails 1.0.0 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/build.yml +69 -0
- data/.gitignore +7 -1
- data/CHANGELOG.md +19 -0
- data/Dockerfile +15 -0
- data/Gemfile +5 -3
- data/README.md +132 -1005
- data/docs/Develop_Rails_API_Application.md +569 -0
- data/docs/Develop_Rails_View_Application.md +441 -0
- data/gemfiles/Gemfile.rails-5.0 +1 -1
- data/gemfiles/Gemfile.rails-5.1 +0 -1
- data/gemfiles/Gemfile.rails-5.2 +0 -1
- data/gemfiles/Gemfile.rails-6.0 +0 -1
- data/gemfiles/Gemfile.rails-6.1 +24 -0
- data/gemfiles/Gemfile.rails-7.0 +30 -0
- data/lib/chime_sdk/controller/meetings.rb +4 -3
- data/lib/chime_sdk/version.rb +1 -1
- data/lib/generators/chime_sdk/js_generator.rb +72 -9
- data/lib/generators/templates/controllers/meetings_controller.rb +1 -1
- data/spec/generators/js_generator_spec.rb +66 -6
- data/spec/rails_app/app/assets/config/manifest.js +1 -0
- data/spec/rails_app/app/assets/javascripts/application.js +3 -0
- data/spec/rails_app/app/controllers/api/public/meeting_attendees_controller.rb +11 -0
- data/spec/rails_app/app/controllers/api/public/meetings_controller.rb +15 -0
- data/spec/rails_app/app/controllers/meetings_controller.rb +1 -1
- data/spec/rails_app/app/views/layouts/_header.html.erb +1 -5
- data/spec/rails_app/app/views/layouts/application.html.erb +1 -2
- data/spec/rails_app/app/views/meetings/show.html.erb +22 -2
- data/spec/rails_app/config/application.rb +11 -2
- data/spec/rails_app/config/initializers/devise_token_auth.rb +1 -1
- data/spec/rails_app/config/routes.rb +10 -3
- data/spec/rails_app/db/seeds.rb +1 -1
- data/spec/requests/meetings_spec.rb +1 -1
- data/templates/amazon-chime-sdk-policy.yml +49 -0
- metadata +19 -57
- data/.travis.yml +0 -47
- data/spec/rails_app/app/controllers/spa_controller.rb +0 -6
- data/spec/rails_app/app/javascript/App.vue +0 -50
- data/spec/rails_app/app/javascript/channels/consumer.js +0 -6
- data/spec/rails_app/app/javascript/channels/index.js +0 -5
- data/spec/rails_app/app/javascript/components/DeviseTokenAuth.vue +0 -84
- data/spec/rails_app/app/javascript/components/meetings/Index.vue +0 -100
- data/spec/rails_app/app/javascript/components/meetings/Meeting.vue +0 -178
- data/spec/rails_app/app/javascript/components/rooms/Index.vue +0 -53
- data/spec/rails_app/app/javascript/components/rooms/Show.vue +0 -91
- data/spec/rails_app/app/javascript/packs/application.js +0 -17
- data/spec/rails_app/app/javascript/packs/spa.js +0 -14
- data/spec/rails_app/app/javascript/router/index.js +0 -74
- data/spec/rails_app/app/javascript/store/index.js +0 -37
- data/spec/rails_app/app/views/spa/index.html.erb +0 -1
- data/spec/rails_app/babel.config.js +0 -72
- data/spec/rails_app/bin/webpack +0 -18
- data/spec/rails_app/bin/webpack-dev-server +0 -18
- data/spec/rails_app/config/webpack/development.js +0 -5
- data/spec/rails_app/config/webpack/environment.js +0 -7
- data/spec/rails_app/config/webpack/loaders/vue.js +0 -6
- data/spec/rails_app/config/webpack/production.js +0 -5
- data/spec/rails_app/config/webpack/test.js +0 -5
- data/spec/rails_app/config/webpacker.yml +0 -97
- data/spec/rails_app/package.json +0 -23
- data/spec/rails_app/postcss.config.js +0 -12
@@ -1,84 +0,0 @@
|
|
1
|
-
<template>
|
2
|
-
<div id="login">
|
3
|
-
<h2>Log in</h2>
|
4
|
-
<form class="new_user" @submit.prevent="login">
|
5
|
-
<div class="field">
|
6
|
-
<label for="user_email">Email</label><br />
|
7
|
-
<input v-model="loginParams.email" autofocus="autofocus" autocomplete="email" type="email" value="" name="user[email]" id="user_email" />
|
8
|
-
</div>
|
9
|
-
<div class="field">
|
10
|
-
<label for="user_password">Password</label><br />
|
11
|
-
<input v-model="loginParams.password" autocomplete="current-password" type="password" name="user[password]" id="user_password" />
|
12
|
-
</div>
|
13
|
-
<div class="actions">
|
14
|
-
<input type="submit" name="commit" value="Log in" data-disable-with="Log in" />
|
15
|
-
</div>
|
16
|
-
</form>
|
17
|
-
|
18
|
-
<a href="/users/sign_up">(Sign up)</a><br />
|
19
|
-
</div>
|
20
|
-
</template>
|
21
|
-
|
22
|
-
<script>
|
23
|
-
import axios from 'axios'
|
24
|
-
|
25
|
-
export default {
|
26
|
-
name: 'DeviseTokenAuth',
|
27
|
-
props: {
|
28
|
-
isLogout: {
|
29
|
-
type: Boolean,
|
30
|
-
default: false
|
31
|
-
}
|
32
|
-
},
|
33
|
-
data () {
|
34
|
-
return {
|
35
|
-
loginParams: {
|
36
|
-
email: "",
|
37
|
-
password: ""
|
38
|
-
}
|
39
|
-
}
|
40
|
-
},
|
41
|
-
mounted () {
|
42
|
-
if (this.isLogout) {
|
43
|
-
this.logout();
|
44
|
-
}
|
45
|
-
},
|
46
|
-
methods: {
|
47
|
-
login () {
|
48
|
-
axios
|
49
|
-
.post('/auth/sign_in', { email: this.loginParams.email, password: this.loginParams.password })
|
50
|
-
.then(response => {
|
51
|
-
if (response.status == 200) {
|
52
|
-
let authHeaders = {};
|
53
|
-
for (let authHeader of ['access-token', 'client', 'uid']) {
|
54
|
-
authHeaders[authHeader] = response.headers[authHeader];
|
55
|
-
axios.defaults.headers.common[authHeader] = authHeaders[authHeader];
|
56
|
-
}
|
57
|
-
this.$store.commit('signIn', { user: response.data.data, authHeaders: authHeaders });
|
58
|
-
if (this.$route.query.redirect) {
|
59
|
-
this.$router.push(this.$route.query.redirect);
|
60
|
-
} else {
|
61
|
-
this.$router.push('/');
|
62
|
-
}
|
63
|
-
}
|
64
|
-
})
|
65
|
-
.catch (error => {
|
66
|
-
console.log("Authentication failed");
|
67
|
-
if (error.response.status == 401) {
|
68
|
-
this.$router.go({path: this.$router.currentRoute.path});
|
69
|
-
}
|
70
|
-
})
|
71
|
-
},
|
72
|
-
logout () {
|
73
|
-
for (var authHeader of Object.keys(this.$store.getters.authHeaders)) {
|
74
|
-
delete axios.defaults.headers.common[authHeader];
|
75
|
-
}
|
76
|
-
this.$store.commit('signOut');
|
77
|
-
this.$router.push('/');
|
78
|
-
}
|
79
|
-
}
|
80
|
-
}
|
81
|
-
</script>
|
82
|
-
|
83
|
-
<style scoped>
|
84
|
-
</style>
|
@@ -1,100 +0,0 @@
|
|
1
|
-
<template>
|
2
|
-
<div>
|
3
|
-
<p id="notice">{{ notice }}</p>
|
4
|
-
|
5
|
-
<h1>Meetings by Amazon Chime SDK</h1>
|
6
|
-
|
7
|
-
<table>
|
8
|
-
<thead>
|
9
|
-
<tr>
|
10
|
-
<th>Meeting ID</th>
|
11
|
-
<th>External Meeting ID</th>
|
12
|
-
<th>Media Region</th>
|
13
|
-
<th colspan="1"></th>
|
14
|
-
</tr>
|
15
|
-
</thead>
|
16
|
-
|
17
|
-
<tbody>
|
18
|
-
<tr v-for="meeting in meetings" :key="`${meeting.Meeting.MeetingId}`">
|
19
|
-
<td><router-link v-bind:to="{ name: 'Meeting', params: { room_id: room_id, meeting_id: meeting.Meeting.MeetingId } }">{{ meeting.Meeting.MeetingId }}</router-link></td>
|
20
|
-
<td>{{ meeting.Meeting.ExternalMeetingId }}</td>
|
21
|
-
<td>{{ meeting.Meeting.MediaRegion }}</td>
|
22
|
-
<td><a href="#" v-on:click="delete_meeting(meeting.Meeting.MeetingId, 'Are you sure?')" data-remote="true">Destroy</a></td>
|
23
|
-
</tr>
|
24
|
-
</tbody>
|
25
|
-
</table>
|
26
|
-
|
27
|
-
<p><a href="#" v-on:click="create_meeting(room_id)" data-remote="true">Create Meeting</a></p>
|
28
|
-
<p><router-link v-bind:to="{ name: 'Room', params: { room_id: room_id } }">Back to Room</router-link></p>
|
29
|
-
</div>
|
30
|
-
</template>
|
31
|
-
|
32
|
-
<script>
|
33
|
-
import axios from 'axios'
|
34
|
-
|
35
|
-
export default {
|
36
|
-
name: 'Meetings',
|
37
|
-
props: {
|
38
|
-
room_id: {
|
39
|
-
required: true
|
40
|
-
},
|
41
|
-
message: String
|
42
|
-
},
|
43
|
-
data () {
|
44
|
-
return {
|
45
|
-
meetings: [],
|
46
|
-
notice: this.message
|
47
|
-
}
|
48
|
-
},
|
49
|
-
mounted () {
|
50
|
-
axios
|
51
|
-
.get(`/rooms/${this.room_id}/meetings`)
|
52
|
-
.then(response => {
|
53
|
-
this.meetings = response.data.meetings;
|
54
|
-
})
|
55
|
-
.catch(error => {
|
56
|
-
if (error.response.status == 403) {
|
57
|
-
this.$router.push({ name: 'Room', params: { room_id: this.room_id, message: error.response.data.notice } });
|
58
|
-
}
|
59
|
-
this.notice = error;
|
60
|
-
})
|
61
|
-
},
|
62
|
-
methods: {
|
63
|
-
create_meeting (room_id) {
|
64
|
-
axios
|
65
|
-
.post(`/rooms/${this.room_id}/meetings`)
|
66
|
-
.then(response => {
|
67
|
-
if (response.status == 201) {
|
68
|
-
let meeting_id = response.data.Meeting.MeetingId;
|
69
|
-
this.$router.push({ name: 'Meeting', params: { room_id: this.room_id, meeting_id: meeting_id, message: `Meeting <${meeting_id}> was successfully created.` } });
|
70
|
-
}
|
71
|
-
})
|
72
|
-
.catch (error => {
|
73
|
-
if (error.response.status == 403) {
|
74
|
-
this.notice = error.response.data.notice;
|
75
|
-
} else {
|
76
|
-
this.notice = error;
|
77
|
-
}
|
78
|
-
})
|
79
|
-
},
|
80
|
-
delete_meeting(meeting_id, confirmation) {
|
81
|
-
if (confirm(confirmation)) {
|
82
|
-
axios
|
83
|
-
.delete(`/rooms/${this.room_id}/meetings/${meeting_id}`)
|
84
|
-
.then(response => {
|
85
|
-
if (response.status == 204) {
|
86
|
-
this.notice = `Meeting <${meeting_id}> was successfully destroyed.`;
|
87
|
-
}
|
88
|
-
})
|
89
|
-
.catch (error => {
|
90
|
-
console.log(error.response);
|
91
|
-
this.notice = error;
|
92
|
-
})
|
93
|
-
}
|
94
|
-
}
|
95
|
-
}
|
96
|
-
}
|
97
|
-
</script>
|
98
|
-
|
99
|
-
<style scoped>
|
100
|
-
</style>
|
@@ -1,178 +0,0 @@
|
|
1
|
-
<template>
|
2
|
-
<div>
|
3
|
-
<p id="notice">{{ notice }}</p>
|
4
|
-
|
5
|
-
<h1>Meeting by Amazon Chime SDK</h1>
|
6
|
-
|
7
|
-
<p><router-link v-bind:to="{ name: 'Meetings', params: { room_id: room_id } }">Show Meetings</router-link></p>
|
8
|
-
|
9
|
-
<div v-if="meeting">
|
10
|
-
<strong>Meeting</strong>
|
11
|
-
<p>
|
12
|
-
Meeting ID : <router-link v-bind:to="{ name: 'Meeting', params: { room_id: room_id, meeting_id: meeting.Meeting.MeetingId } }">{{ meeting.Meeting.MeetingId }}</router-link><br>
|
13
|
-
External Meeting ID : {{ meeting.Meeting.ExternalMeetingId }}<br>
|
14
|
-
Media Region : {{ meeting.Meeting.MediaRegion }}
|
15
|
-
</p>
|
16
|
-
</div>
|
17
|
-
|
18
|
-
<div v-if="attendee">
|
19
|
-
<strong>Attendee</strong>
|
20
|
-
<p>
|
21
|
-
Attendee ID : <a v-bind:href="`/rooms/${room_id}/meetings/${meeting.Meeting.MeetingId}/attendees/${attendee.Attendee.AttendeeId}`">{{ attendee.Attendee.AttendeeId }}</a><br>
|
22
|
-
External User ID : {{ attendee.Attendee.ExternalUserId }}<br>
|
23
|
-
Application Attendee Name : {{ attendee.Attendee.ApplicationMetadata.User.name }}
|
24
|
-
</p>
|
25
|
-
|
26
|
-
<div id="status">
|
27
|
-
<strong>Status</strong>
|
28
|
-
<div v-if="meetingOnline">
|
29
|
-
<div id="meeting-status">
|
30
|
-
<p>Meeting : Online <input type="button" value="Leave a meeting" v-on:click="leave()"></p>
|
31
|
-
<div id="audio-status">
|
32
|
-
<div v-if="meetingMuted">
|
33
|
-
<p>Audio : Muted <input type="button" value="Unmute" v-on:click="unmute()"></p>
|
34
|
-
</div>
|
35
|
-
<div v-else>
|
36
|
-
<p>Audio : Active <input type="button" value="Mute" v-on:click="mute()"></p>
|
37
|
-
</div>
|
38
|
-
</div>
|
39
|
-
</div>
|
40
|
-
<div id="attendee-status">
|
41
|
-
<strong>Present Attendees</strong>
|
42
|
-
<ul>
|
43
|
-
<li v-for="attendeeName in presentAttendees" :key="attendeeName">{{ attendeeName }}</li>
|
44
|
-
</ul>
|
45
|
-
</div>
|
46
|
-
</div>
|
47
|
-
<div v-else>
|
48
|
-
<div id="meeting-status">
|
49
|
-
<p>Meeting : Offline <input type="button" value="Join a meeting" v-on:click="join()"></p>
|
50
|
-
</div>
|
51
|
-
</div>
|
52
|
-
</div>
|
53
|
-
|
54
|
-
<audio id="audio"></audio>
|
55
|
-
</div>
|
56
|
-
</div>
|
57
|
-
</template>
|
58
|
-
|
59
|
-
<script>
|
60
|
-
import axios from 'axios'
|
61
|
-
import {
|
62
|
-
ConsoleLogger,
|
63
|
-
DefaultDeviceController,
|
64
|
-
DefaultMeetingSession,
|
65
|
-
LogLevel,
|
66
|
-
MeetingSessionConfiguration
|
67
|
-
} from 'amazon-chime-sdk-js'
|
68
|
-
|
69
|
-
export default {
|
70
|
-
name: 'Meeting',
|
71
|
-
props: {
|
72
|
-
room_id: {
|
73
|
-
required: true
|
74
|
-
},
|
75
|
-
meeting_id: {
|
76
|
-
required: true
|
77
|
-
},
|
78
|
-
message: String
|
79
|
-
},
|
80
|
-
data () {
|
81
|
-
return {
|
82
|
-
meeting: null,
|
83
|
-
attendee: null,
|
84
|
-
notice: this.message,
|
85
|
-
meetingOnline: false,
|
86
|
-
meetingMuted: false,
|
87
|
-
presentAttendees: []
|
88
|
-
}
|
89
|
-
},
|
90
|
-
mounted () {
|
91
|
-
axios
|
92
|
-
.get(`/rooms/${this.room_id}/meetings/${this.meeting_id}`)
|
93
|
-
.then(response => {
|
94
|
-
this.meeting = { Meeting: response.data.Meeting };
|
95
|
-
this.attendee = { Attendee: response.data.Attendee };
|
96
|
-
|
97
|
-
const logger = new ConsoleLogger('ChimeMeetingLogs', LogLevel.INFO);
|
98
|
-
const deviceController = new DefaultDeviceController(logger);
|
99
|
-
const configuration = new MeetingSessionConfiguration(this.meeting, this.attendee);
|
100
|
-
this.meetingSession = new DefaultMeetingSession(configuration, logger, deviceController);
|
101
|
-
})
|
102
|
-
.catch(error => {
|
103
|
-
if (error.response.status == 404) {
|
104
|
-
this.$router.push({ name: 'Meetings', params: { room_id: this.room_id, message: `${error.response.data.error.message}: ${error.response.data.error.type}` } });
|
105
|
-
} else {
|
106
|
-
this.notice = error;
|
107
|
-
}
|
108
|
-
})
|
109
|
-
},
|
110
|
-
methods: {
|
111
|
-
// Customize this function to extract attendee name to show
|
112
|
-
showApplicationUserName(attendee) {
|
113
|
-
// return attendee.Attendee.AttendeeId;
|
114
|
-
return `${attendee.Attendee.ApplicationMetadata.User.name} (${attendee.Attendee.AttendeeId})`;
|
115
|
-
},
|
116
|
-
async join() {
|
117
|
-
try {
|
118
|
-
const audioInputDevices = await this.meetingSession.audioVideo.listAudioInputDevices();
|
119
|
-
const audioOutputDevices = await this.meetingSession.audioVideo.listAudioOutputDevices();
|
120
|
-
await this.meetingSession.audioVideo.chooseAudioInputDevice(audioInputDevices[0].deviceId);
|
121
|
-
await this.meetingSession.audioVideo.chooseAudioOutputDevice(audioOutputDevices[0].deviceId);
|
122
|
-
} catch (error) {
|
123
|
-
// handle error - unable to acquire audio device perhaps due to permissions blocking
|
124
|
-
console.log(error);
|
125
|
-
}
|
126
|
-
const audioOutputElement = document.getElementById('audio');
|
127
|
-
this.meetingSession.audioVideo.bindAudioElement(audioOutputElement);
|
128
|
-
this.meetingSession.audioVideo.start();
|
129
|
-
this.meetingOnline = true;
|
130
|
-
this.parepareAttendeeStatus();
|
131
|
-
},
|
132
|
-
leave() {
|
133
|
-
this.meetingSession.audioVideo.stop();
|
134
|
-
this.meetingOnline = false;
|
135
|
-
this.meetingMuted = false;
|
136
|
-
this.presentAttendees = [];
|
137
|
-
},
|
138
|
-
mute() {
|
139
|
-
this.meetingSession.audioVideo.realtimeMuteLocalAudio();
|
140
|
-
this.meetingMuted = true;
|
141
|
-
},
|
142
|
-
unmute() {
|
143
|
-
const unmuted = this.meetingSession.audioVideo.realtimeUnmuteLocalAudio();
|
144
|
-
if (unmuted) {
|
145
|
-
this.meetingMuted = false;
|
146
|
-
} else {
|
147
|
-
console.log('You cannot unmute yourself');
|
148
|
-
}
|
149
|
-
},
|
150
|
-
parepareAttendeeStatus() {
|
151
|
-
this.presentAttendeeMap = {};
|
152
|
-
const callback = (presentAttendeeId, present) => {
|
153
|
-
if (present) {
|
154
|
-
axios
|
155
|
-
.get(`/rooms/${this.room_id}/meetings/${this.meeting_id}/attendees/${presentAttendeeId}`)
|
156
|
-
.then(response => {
|
157
|
-
this.presentAttendeeMap[presentAttendeeId] = response.data;
|
158
|
-
this.updateAttendeeStatus(this.presentAttendeeMap);
|
159
|
-
})
|
160
|
-
.catch(error => {
|
161
|
-
console.log(error);
|
162
|
-
});
|
163
|
-
} else {
|
164
|
-
delete this.presentAttendeeMap[presentAttendeeId]
|
165
|
-
this.updateAttendeeStatus(this.presentAttendeeMap);
|
166
|
-
}
|
167
|
-
};
|
168
|
-
this.meetingSession.audioVideo.realtimeSubscribeToAttendeeIdPresence(callback);
|
169
|
-
},
|
170
|
-
updateAttendeeStatus(presentAttendeeMap) {
|
171
|
-
this.presentAttendees = Object.values(presentAttendeeMap).map(attendee => this.showApplicationUserName(attendee));
|
172
|
-
}
|
173
|
-
}
|
174
|
-
}
|
175
|
-
</script>
|
176
|
-
|
177
|
-
<style scoped>
|
178
|
-
</style>
|
@@ -1,53 +0,0 @@
|
|
1
|
-
<template>
|
2
|
-
<div>
|
3
|
-
<p id="notice">{{ notice }}</p>
|
4
|
-
|
5
|
-
<h1>Rooms</h1>
|
6
|
-
|
7
|
-
<table>
|
8
|
-
<thead>
|
9
|
-
<tr>
|
10
|
-
<th>Name</th>
|
11
|
-
<th colspan="3"></th>
|
12
|
-
</tr>
|
13
|
-
</thead>
|
14
|
-
|
15
|
-
<tbody>
|
16
|
-
<tr v-for="room in rooms" :key="`${room.id}`">
|
17
|
-
<td>{{ room.name }}</td>
|
18
|
-
<td><router-link v-bind:to="{ name: 'Room', params: { room_id: room.id } }">Show</router-link></td>
|
19
|
-
<td><a v-bind:href="`/rooms/${room.id}/edit`">(Edit)</a></td>
|
20
|
-
<td><a v-bind:href="`/rooms/${room.id}`" data-method="delete" data-confirm="Are you sure?" rel="nofollow">(Destroy)</a></td>
|
21
|
-
</tr>
|
22
|
-
</tbody>
|
23
|
-
</table>
|
24
|
-
|
25
|
-
<br>
|
26
|
-
|
27
|
-
<a href="/rooms/new">(New Room)</a>
|
28
|
-
</div>
|
29
|
-
</template>
|
30
|
-
|
31
|
-
<script>
|
32
|
-
import axios from 'axios'
|
33
|
-
|
34
|
-
export default {
|
35
|
-
name: 'Rooms',
|
36
|
-
data () {
|
37
|
-
return {
|
38
|
-
rooms: [],
|
39
|
-
notice: null
|
40
|
-
}
|
41
|
-
},
|
42
|
-
mounted () {
|
43
|
-
axios
|
44
|
-
.get('/rooms')
|
45
|
-
.then(response => {
|
46
|
-
this.rooms = response.data;
|
47
|
-
})
|
48
|
-
}
|
49
|
-
}
|
50
|
-
</script>
|
51
|
-
|
52
|
-
<style scoped>
|
53
|
-
</style>
|
@@ -1,91 +0,0 @@
|
|
1
|
-
<template>
|
2
|
-
<div v-if="room">
|
3
|
-
<p id="notice">{{ notice }}</p>
|
4
|
-
|
5
|
-
<p>
|
6
|
-
<strong>Name:</strong>
|
7
|
-
{{ room.name }}
|
8
|
-
</p>
|
9
|
-
|
10
|
-
<p>
|
11
|
-
<strong>Private Meeting:</strong>
|
12
|
-
<p><router-link v-bind:to="{ name: 'Meetings', params: { room_id: room.id } }">Show Meetings</router-link></p>
|
13
|
-
<p><a href="#" v-on:click="create_meeting(room)" data-remote="true">Create Meeting</a></p>
|
14
|
-
</p>
|
15
|
-
|
16
|
-
<p>
|
17
|
-
<strong>Members:</strong>
|
18
|
-
<div>
|
19
|
-
<table>
|
20
|
-
<tbody>
|
21
|
-
<tr v-for="member in room.members" :key="`${member.name}`">
|
22
|
-
<td>{{ member.name }}</td>
|
23
|
-
</tr>
|
24
|
-
</tbody>
|
25
|
-
</table>
|
26
|
-
</div>
|
27
|
-
</p>
|
28
|
-
|
29
|
-
<p>
|
30
|
-
<strong>Manage members:</strong>
|
31
|
-
<a v-bind:href="`/rooms/${room.id}`">(Show)</a>
|
32
|
-
</p>
|
33
|
-
|
34
|
-
<br>
|
35
|
-
|
36
|
-
<a v-bind:href="`/rooms/${room.id}/edit`">(Edit)</a>
|
37
|
-
<router-link v-bind:to="{ name: 'Rooms' }">Back</router-link>
|
38
|
-
</div>
|
39
|
-
</template>
|
40
|
-
|
41
|
-
<script>
|
42
|
-
import axios from 'axios'
|
43
|
-
|
44
|
-
export default {
|
45
|
-
name: 'Room',
|
46
|
-
props: {
|
47
|
-
room_id: {
|
48
|
-
required: true
|
49
|
-
},
|
50
|
-
message: String
|
51
|
-
},
|
52
|
-
data () {
|
53
|
-
return {
|
54
|
-
room: null,
|
55
|
-
notice: this.message
|
56
|
-
}
|
57
|
-
},
|
58
|
-
mounted () {
|
59
|
-
axios
|
60
|
-
.get(`/rooms/${this.room_id}`)
|
61
|
-
.then(response => {
|
62
|
-
this.room = response.data;
|
63
|
-
})
|
64
|
-
.catch(error => {
|
65
|
-
this.notice = error;
|
66
|
-
})
|
67
|
-
},
|
68
|
-
methods: {
|
69
|
-
create_meeting (room_id) {
|
70
|
-
axios
|
71
|
-
.post(`/rooms/${this.room_id}/meetings`)
|
72
|
-
.then(response => {
|
73
|
-
if (response.status == 201) {
|
74
|
-
let meeting_id = response.data.Meeting.MeetingId;
|
75
|
-
this.$router.push({ name: 'Meeting', params: { room_id: this.room_id, meeting_id: meeting_id, message: `Meeting <${meeting_id}> was successfully created.` } });
|
76
|
-
}
|
77
|
-
})
|
78
|
-
.catch (error => {
|
79
|
-
if (error.response.status == 403) {
|
80
|
-
this.notice = error.response.data.notice;
|
81
|
-
} else {
|
82
|
-
this.notice = error;
|
83
|
-
}
|
84
|
-
})
|
85
|
-
}
|
86
|
-
}
|
87
|
-
}
|
88
|
-
</script>
|
89
|
-
|
90
|
-
<style scoped>
|
91
|
-
</style>
|
@@ -1,17 +0,0 @@
|
|
1
|
-
// This file is automatically compiled by Webpack, along with any other files
|
2
|
-
// present in this directory. You're encouraged to place your actual application logic in
|
3
|
-
// a relevant structure within app/javascript and only use these pack files to reference
|
4
|
-
// that code so it'll be compiled.
|
5
|
-
|
6
|
-
require("@rails/ujs").start()
|
7
|
-
require("turbolinks").start()
|
8
|
-
require("@rails/activestorage").start()
|
9
|
-
require("channels")
|
10
|
-
|
11
|
-
|
12
|
-
// Uncomment to copy all static images under ../images to the output folder and reference
|
13
|
-
// them with the image_pack_tag helper in views (e.g <%= image_pack_tag 'rails.png' %>)
|
14
|
-
// or the `imagePath` JavaScript helper below.
|
15
|
-
//
|
16
|
-
// const images = require.context('../images', true)
|
17
|
-
// const imagePath = (name) => images(name, true)
|
@@ -1,14 +0,0 @@
|
|
1
|
-
import Vue from 'vue'
|
2
|
-
import App from '../App.vue'
|
3
|
-
import router from '../router'
|
4
|
-
import store from '../store'
|
5
|
-
|
6
|
-
Vue.config.productionTip = false
|
7
|
-
|
8
|
-
document.addEventListener('DOMContentLoaded', () => {
|
9
|
-
new Vue({
|
10
|
-
router,
|
11
|
-
store,
|
12
|
-
render: h => h(App)
|
13
|
-
}).$mount('#app')
|
14
|
-
})
|
@@ -1,74 +0,0 @@
|
|
1
|
-
import Vue from 'vue'
|
2
|
-
import VueRouter from 'vue-router'
|
3
|
-
import store from '../store'
|
4
|
-
import DeviseTokenAuth from '../components/DeviseTokenAuth.vue'
|
5
|
-
import Rooms from '../components/rooms/Index.vue'
|
6
|
-
import Room from '../components/rooms/Show.vue'
|
7
|
-
import Meetings from '../components/meetings/Index.vue'
|
8
|
-
import Meeting from '../components/meetings/Meeting.vue'
|
9
|
-
|
10
|
-
Vue.use(VueRouter)
|
11
|
-
|
12
|
-
const routes = [
|
13
|
-
// Routes for common components
|
14
|
-
{
|
15
|
-
path: '/',
|
16
|
-
name: 'Root',
|
17
|
-
component: Rooms
|
18
|
-
},
|
19
|
-
{
|
20
|
-
path: '/users/sign_in',
|
21
|
-
name: 'SignIn',
|
22
|
-
component: DeviseTokenAuth
|
23
|
-
},
|
24
|
-
{
|
25
|
-
path: '/users/sign_out',
|
26
|
-
name: 'SignOut',
|
27
|
-
component: DeviseTokenAuth,
|
28
|
-
props: { isLogout: true }
|
29
|
-
},
|
30
|
-
|
31
|
-
// Routes for Rooms
|
32
|
-
{
|
33
|
-
path: '/rooms',
|
34
|
-
name: 'Rooms',
|
35
|
-
component: Rooms
|
36
|
-
},
|
37
|
-
{
|
38
|
-
path: '/rooms/:room_id',
|
39
|
-
name: 'Room',
|
40
|
-
component: Room,
|
41
|
-
props: true,
|
42
|
-
meta: { requiresAuth: true }
|
43
|
-
},
|
44
|
-
|
45
|
-
// Routes for Meetings
|
46
|
-
{
|
47
|
-
path: '/rooms/:room_id/meetings',
|
48
|
-
name: 'Meetings',
|
49
|
-
component: Meetings,
|
50
|
-
props: true,
|
51
|
-
meta: { requiresAuth: true }
|
52
|
-
},
|
53
|
-
{
|
54
|
-
path: '/rooms/:room_id/meetings/:meeting_id',
|
55
|
-
name: 'Meeting',
|
56
|
-
component: Meeting,
|
57
|
-
props: true,
|
58
|
-
meta: { requiresAuth: true }
|
59
|
-
}
|
60
|
-
]
|
61
|
-
|
62
|
-
const router = new VueRouter({
|
63
|
-
routes
|
64
|
-
})
|
65
|
-
|
66
|
-
router.beforeEach((to, from, next) => {
|
67
|
-
if (to.matched.some(record => record.meta.requiresAuth) && !store.getters.userSignedIn) {
|
68
|
-
next({ name: 'SignIn', query: { redirect: to.fullPath }});
|
69
|
-
} else {
|
70
|
-
next();
|
71
|
-
}
|
72
|
-
})
|
73
|
-
|
74
|
-
export default router
|
@@ -1,37 +0,0 @@
|
|
1
|
-
import Vue from 'vue'
|
2
|
-
import Vuex from 'vuex'
|
3
|
-
import createPersistedState from "vuex-persistedstate"
|
4
|
-
|
5
|
-
Vue.use(Vuex)
|
6
|
-
|
7
|
-
export default new Vuex.Store({
|
8
|
-
state: {
|
9
|
-
signedInStatus: false,
|
10
|
-
currentUser: null,
|
11
|
-
authHeaders: {}
|
12
|
-
},
|
13
|
-
mutations: {
|
14
|
-
signIn(state, { user, authHeaders }) {
|
15
|
-
state.currentUser = user;
|
16
|
-
state.authHeaders = authHeaders;
|
17
|
-
state.signedInStatus = true;
|
18
|
-
},
|
19
|
-
signOut(state) {
|
20
|
-
state.signedInStatus = false;
|
21
|
-
state.currentUser = null;
|
22
|
-
state.authHeaders = {};
|
23
|
-
}
|
24
|
-
},
|
25
|
-
getters: {
|
26
|
-
userSignedIn(state) {
|
27
|
-
return state.signedInStatus;
|
28
|
-
},
|
29
|
-
currentUser(state) {
|
30
|
-
return state.currentUser;
|
31
|
-
},
|
32
|
-
authHeaders(state) {
|
33
|
-
return state.authHeaders;
|
34
|
-
}
|
35
|
-
},
|
36
|
-
plugins: [createPersistedState({storage: window.sessionStorage})]
|
37
|
-
});
|
@@ -1 +0,0 @@
|
|
1
|
-
<%= content_for(:javascript_pack_tag, javascript_pack_tag('spa', 'data-turbolinks-track': 'reload')) %>
|