Advertisement
Guest User

Untitled

a guest
May 24th, 2017
78
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.77 KB | None | 0 0
  1. <template>
  2. <div class="my-app">
  3. <h1>CTI OMNI</h1>
  4. <b-alert class="form col-md-7 col-md-offset-3" variant="danger" dismissible :show="showDismissibleAlert" @dismissed="showDismissibleAlert=false">
  5. {{errorMessage}}
  6. </b-alert>
  7.  
  8. <div class="form col-md-4 col-md-offset-4" v-if="enterName">
  9. <label for="username">Введите ваше имя:</label>
  10. <br>
  11. <input id="username" type="text" class="form-control" v-model="username" v-on:keyup.enter="connectToChat">
  12. <br>
  13. <div v-if="selectedRole.label === 'Оператор'">
  14. <label for="password">Введите ваш пароль:</label><br>
  15. <input id="password" type="password" v-model="password" class="form-control" v-on:keyup.enter="connectToChat">
  16. </div>
  17. <br>
  18. <label for="selectedRole">Ваша роль:</label><br>
  19. <select id="selectedRole" v-model="selectedRole.label" class="form-control">
  20. <option v-for="role in roles">{{ role.label }}</option>
  21. </select>
  22. <br>
  23. <br>
  24. <div v-if="selectedRole.label === 'Клиент'">
  25. <button class="btn btn-primary col-md-6 col-md-offset-3" v-on:click="connectToChat">Войти в чат</button>
  26. </div>
  27. <div v-else>
  28. <button class="btn btn-danger col-md-6 col-md-offset-3" v-on:click="login">Войти в АРМ оператора</button>
  29. </div>
  30. <br>
  31. <br>
  32. </div>
  33. <div id="main-container" v-else>
  34. <div id="users-list">
  35. <h3>Пользователи онлайн:</h3>
  36. <ul>
  37. <transition-group name="user-appear">
  38. <li v-for="user in users" v-bind:key="user.user">
  39. <a @click="enterToPrivate">{{user.user}} ({{user.online_at}})</a>
  40. </li>
  41. </transition-group>
  42. </ul>
  43. </div>
  44. <div id="messages-list" ref="scrollbar">
  45. <ul>
  46. <transition-group name="message-appear">
  47. <li v-for="message in messages" v-bind:key="message">
  48. <div class="message-metadata">
  49. <span class="username">{{message.username}}</span>
  50. <span class="received-at">{{message.received_at}}</span>
  51. </div>
  52. {{message.body}}
  53. </li>
  54. </transition-group>
  55. </ul>
  56. </div>
  57. <div id="your-message">
  58. <input type="text" placeholder="What do you have to say?" v-model="message" v-on:keyup.enter="sendMessage">
  59. </div>
  60. </div>
  61. </div>
  62. </template>
  63.  
  64. <script>
  65. import {
  66. Socket,
  67. Presence
  68. } from "phoenix"
  69.  
  70. import gql from 'graphql-tag'
  71.  
  72. export default {
  73. data() {
  74. return {
  75. socket: null,
  76. channel: null,
  77. messages: [],
  78. message: "",
  79. username: "e.batogov@cti.ru",
  80. password: "qweasd123",
  81. showDismissibleAlert: false,
  82. errorMessage: "",
  83. token: "",
  84. userId: "",
  85. enterName: true,
  86. hello: '',
  87. roles: [{
  88. id: "customer",
  89. label: "Клиент"
  90. },
  91. {
  92. id: "operator",
  93. label: "Оператор"
  94. }
  95. ],
  96. selectedRole: {
  97. id: "operator",
  98. label: "Оператор"
  99. },
  100. users: [],
  101. remoteUsers: ""
  102. }
  103. },
  104. methods: {
  105. login() {
  106. this.$apollo.mutate({
  107. mutation: gql `
  108. mutation UserLogin($username: String!, $password: String!) {
  109. login(email: $username, password: $password) {
  110. userId
  111. token
  112. }
  113. }`,
  114. variables: {
  115. username: this.username,
  116. password: this.password
  117. }
  118. }).then((data) => {
  119. this.enterName = false;
  120. this.token = data.data.login.token;
  121. this.userId = data.data.login.userId;
  122.  
  123. }).catch((error) => {
  124. this.enterName = true;
  125. this.showDismissibleAlert = true;
  126. this.errorMessage = "Ошибка входа в систему. Проверьте имя и пароль";
  127. })
  128.  
  129. let presences = {}
  130. this.enterName = false;
  131. this.messages = [];
  132. this.socket = new Socket("/socket", {
  133. params: {
  134. username: this.username
  135. }
  136. }),
  137. this.socket.connect();
  138.  
  139. this.channel = this.socket.channel(`room:${this.userId}`, {
  140. guardian_token: this.token
  141. });
  142. this.channel.on("new_msg", payload => {
  143. payload.received_at = new Date(payload.received_at * 1000).toLocaleString();
  144. this.messages.push(payload);
  145. });
  146. this.channel.on("presence_state", state => {
  147. presences = Presence.syncState(presences, state)
  148. this.assignUsers(presences)
  149. })
  150. this.channel.on("presence_diff", diff => {
  151. presences = Presence.syncDiff(presences, diff)
  152. this.assignUsers(presences)
  153. })
  154. this.channel.join()
  155. .receive("ok", response => {
  156. console.log("Joined successfully", response)
  157. })
  158. .receive("error", response => {
  159. console.log("Unable to join", response)
  160. })
  161.  
  162. },
  163. sendMessage() {
  164. this.channel.push("new_msg", {
  165. body: this.message
  166. })
  167. this.message = ''
  168. },
  169. connectToChat() {
  170. let presences = {}
  171. this.enterName = false
  172. this.socket = new Socket("/socket", {
  173. params: {
  174. username: this.username
  175. }
  176. }),
  177. this.socket.connect()
  178. this.channel = this.socket.channel("room:lobby", {});
  179. this.channel.on("new_msg", payload => {
  180. payload.received_at = new Date(payload.received_at * 1000).toLocaleString();
  181. this.messages.push(payload);
  182. this.$nextTick(() => {
  183. var chatArea = this.$refs.scrollbar.$el;
  184. chatArea.scrollTop = chatArea.scrollHeight
  185. })
  186. });
  187. this.channel.on("presence_state", state => {
  188. presences = Presence.syncState(presences, state)
  189. this.assignUsers(presences)
  190. })
  191. this.channel.on("presence_diff", diff => {
  192. presences = Presence.syncDiff(presences, diff)
  193. this.assignUsers(presences)
  194. })
  195. this.channel.join()
  196. .receive("ok", response => {
  197. console.log("Joined successfully", response)
  198. })
  199. .receive("error", response => {
  200. console.log("Unable to join", response)
  201. })
  202. },
  203. assignUsers(presences) {
  204. let formatTimestamp = (timestamp) => {
  205. timestamp = parseInt(timestamp)
  206. let date = new Date(timestamp)
  207. return date.toLocaleTimeString()
  208. }
  209. this.users = Presence.list(presences, (user, {
  210. metas: metas
  211. }) => {
  212. return {
  213. user: user,
  214. online_at: formatTimestamp(metas[0].online_at)
  215. }
  216. })
  217. }
  218. }
  219. }
  220. </script>
  221. <style lang="sass">
  222. .my-app {
  223. h1 {
  224. text-align: center;
  225. }
  226. #main-container {
  227. position: absolute;
  228. top: 0;
  229. bottom: 0;
  230. left: 0;
  231. right: 0;
  232. display: flex;
  233. overflow: hidden;
  234. }
  235. #users-list {
  236. background-color: #008bdf;
  237. width: 250px;
  238. height: 100vh;
  239. overflow-y: scroll;
  240. h3 {
  241. font-size: 0.9em;
  242. margin-left: 10px;
  243. color: rgba(255, 255, 255, 0.7);
  244. }
  245. ul {
  246. list-style: none;
  247. padding-left: 20px;
  248. color: rgba(255, 255, 255, 0.9);
  249. li {
  250. &.user-appear-enter-active,
  251. &.user-appear-leave-active {
  252. transition: all 0.2s;
  253. }
  254. &.user-appear-enter,
  255. &.user-appear-leave-active {
  256. opacity: 0;
  257. transform: translateX(-15px);
  258. }
  259. }
  260. }
  261. }
  262. #messages-list {
  263. padding-top: 20px;
  264. padding-left: 20px;
  265. overflow-y: scroll;
  266. overflow: auto ;
  267. flex: 1;
  268. ul {
  269. list-style: none;
  270. padding: 0;
  271. li {
  272. padding: 5px 0;
  273. &.message-appear-enter-active,
  274. &.message-appear-leave-active {
  275. transition: all 0.2s;
  276. }
  277. &.message-appear-enter,
  278. &.message-appear-leave-active {
  279. opacity: 0;
  280. transform: translateY(20px);
  281. }
  282. .message-metadata {
  283. .username {
  284. font-weight: bold;
  285. }
  286. .received-at {
  287. color: rgba(0, 0, 0, 0.4);
  288. margin-left: 5px;
  289. font-size: 0.9em;
  290. }
  291. }
  292. }
  293. }
  294. }
  295. #your-message {
  296. position: fixed;
  297. bottom: 0;
  298. left: 250px;
  299. right: 0;
  300. background: rgba(255, 255, 255, 0.95);
  301. padding: 15px;
  302. input {
  303. width: 100%;
  304. padding: 5px 8px;
  305. border-radius: 3px;
  306. outline: 0;
  307. border: 1px solid #ddd;
  308. }
  309. }
  310. }
  311. </style>
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement