amazon-chime-sdk-rails 1.0.0 → 1.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/workflows/build.yml +57 -0
- data/.gitignore +7 -1
- data/CHANGELOG.md +31 -0
- data/Dockerfile +15 -0
- data/Gemfile +5 -3
- data/README.md +132 -1005
- data/config/spring.rb +2 -0
- 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 +25 -0
- data/lib/chime_sdk/controller/meetings.rb +3 -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 +20 -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')) %>
|