Attendee.vue 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. <template>
  2. <md-list-item class="attendee-list-item md-double-line" :key="attendee._id">
  3. <md-icon>person</md-icon>
  4. <div v-if="!edit" class="md-list-text-container">
  5. <span>{{ attendee.name }}</span>
  6. <vue-markdown v-if="attendee.notes" ref="attendeeNotes" @click.native="toggleNotes()" class="attendee-notes" :source="attendee.notes" :break="false"></vue-markdown>
  7. </div>
  8. <div v-if="edit">
  9. <md-input-container md-inline>
  10. <md-input @keyup.enter.native="updateAttendee()" @keydown.esc.native="edit = false" v-model="attendee.name" ref="updateAttendeeName" />
  11. </md-input-container>
  12. <div class="notes-editor-list-item">
  13. <md-input-container md-inline>
  14. <label>notes</label>
  15. <md-input @keyup.enter.native="updateAttendee()" @keydown.esc.native="edit = false" v-model="attendee.notes" />
  16. </md-input-container>
  17. </div>
  18. </div>
  19. <md-menu v-if="isAuthorized(attendee.created_by) && !edit" md-align-trigger>
  20. <md-button class="md-icon-button" md-menu-trigger>
  21. <md-icon>more_vert</md-icon>
  22. </md-button>
  23. <md-menu-content>
  24. <md-menu-item @click.native="editAttendee()">
  25. <span>edit</span>
  26. <md-icon>edit</md-icon>
  27. </md-menu-item>
  28. <md-menu-item @click.native="deleteAttendee()">
  29. <span>delete</span>
  30. <md-icon>delete</md-icon>
  31. </md-menu-item>
  32. </md-menu-content>
  33. </md-menu>
  34. <ibt-dialog ref="dialogObj" />
  35. </md-list-item>
  36. </template>
  37. <script>
  38. import IbtDialog from './IbtDialog.vue';
  39. import VueMarkdown from 'vue-markdown';
  40. export default {
  41. props: {attendee: {default: {}}},
  42. data: function () {
  43. return {
  44. edit: false,
  45. expandedNote: false
  46. }
  47. },
  48. computed: {
  49. loggedInUser() {
  50. return this.$store.state.loggedInUser;
  51. },
  52. settings() {
  53. return this.$store.state.settings || {};
  54. }
  55. },
  56. beforeCreate: function() {
  57. this.attendeesUrl = this.$resource('attendees{/id}');
  58. },
  59. methods: {
  60. isAuthorized(ownerID) {
  61. return (!ownerID && !this.$store.state.settings.protectUnregistered) || this.$store.state.loggedInUser.isAdmin || (this.$store.state.loggedInUser._id && this.$store.state.loggedInUser._id == ownerID);
  62. },
  63. editAttendee() {
  64. this.edit = true;
  65. // FIXME: it's so wrong it hurts, but any other attempt to set the focus
  66. // failed, being called too early. Also, I don't know how I can access
  67. // Vue.nextTick from here.
  68. var that = this;
  69. setTimeout(function() { that.$refs.updateAttendeeName.$el.focus(); }, 400);
  70. },
  71. updateAttendee() {
  72. this.attendeesUrl.update({id: this.attendee._id}, this.attendee).then((response) => {
  73. return response.json();
  74. }, (response) => {
  75. this.$refs.dialogObj.show({text: 'unable to update the attendee'});
  76. }).then((json) => {
  77. this.edit = false;
  78. this.$emit('updated');
  79. });
  80. },
  81. deleteAttendee() {
  82. this.attendeesUrl.delete({id: this.attendee._id}).then((response) => {
  83. return response.json();
  84. }, (response) => {
  85. this.$refs.dialogObj.show({text: 'unable to delete the attendee'});
  86. }).then((json) => {
  87. this.$emit('updated');
  88. });
  89. },
  90. toggleNotes() {
  91. if (!this.expandedNote) {
  92. $(this.$refs.attendeeNotes.$el).find('p').css('text-overflow', 'initial');
  93. $(this.$refs.attendeeNotes.$el).find('p').css('white-space', 'initial');
  94. this.expandedNote = true;
  95. } else {
  96. $(this.$refs.attendeeNotes.$el).find('p').css('text-overflow', 'ellipsis');
  97. $(this.$refs.attendeeNotes.$el).find('p').css('white-space', 'nowrap');
  98. this.expandedNote = false;
  99. }
  100. }
  101. },
  102. components: { IbtDialog, VueMarkdown }
  103. };
  104. </script>
  105. <style scoped>
  106. .attendee-list-item {
  107. min-width: 250px;
  108. }
  109. .attendee-notes {
  110. font-style: italic !important;
  111. }
  112. .notes-editor-list-item {
  113. margin-bottom: 0px !important;
  114. padding-left: 16px;
  115. }
  116. .notes-editor-list-item ul {
  117. padding-top: 0px !important;
  118. padding-bottom: 0px !important;
  119. }
  120. .notes-editor-list-item .md-theme-default.md-list {
  121. background-color: transparent;
  122. }
  123. .notes-editor-list-item button:hover {
  124. background-color: transparent !important;
  125. }
  126. .attendee-notes > p {
  127. margin: 0px;
  128. font-style: italic;
  129. margin: 0px;
  130. text-overflow: ellipsis;
  131. max-width: 400px;
  132. overflow: hidden;
  133. white-space: nowrap;
  134. color: rgba(0, 0, 0, 0.54);
  135. }
  136. </style>
  137. <style>
  138. .md-list-item .md-list-item-holder>.md-icon:first-child {
  139. margin-right: 16px;
  140. }
  141. .attendee-list-item .md-list-item-container {
  142. padding-left: 0px;
  143. padding-right: 0px;
  144. }
  145. </style>