Commit | Line | Data |
---|---|---|
604b951e BA |
1 | <template lang="pug"> |
2 | main | |
3 | input#modalNews.modal(type="checkbox") | |
910d631b BA |
4 | div#newnewsDiv( |
5 | role="dialog" | |
6 | data-checkbox="modalNews" | |
7 | ) | |
23e1fa07 | 8 | .card#writeNews |
604b951e BA |
9 | label.modal-close(for="modalNews") |
10 | textarea#newsContent( | |
11 | v-model="curnews.content" | |
12 | :placeholder="st.tr['News go here']" | |
13 | @input="adjustHeight" | |
14 | ) | |
15 | button(@click="sendNews()") {{ st.tr["Send"] }} | |
16 | #dialog.text-center {{ st.tr[infoMsg] }} | |
17 | .row | |
18 | .col-sm-12.col-md-10.col-md-offset-1.col-lg-8.col-lg-offset-2 | |
23e1fa07 | 19 | button#writeNewsBtn( |
a9e79351 | 20 | v-if="devTeam" |
604b951e BA |
21 | @click="showModalNews" |
22 | ) | |
23 | | {{ st.tr["Write news"] }} | |
910d631b BA |
24 | .news( |
25 | v-for="n,idx in newsList" | |
d85f259c | 26 | :id="'n' + n.id" |
910d631b BA |
27 | :class="{margintop:idx>0}" |
28 | ) | |
bd76b456 | 29 | span.ndt {{ formatDatetime(n.added) }} |
a9e79351 | 30 | .dev-buttons(v-if="devTeam") |
604b951e BA |
31 | button(@click="editNews(n)") {{ st.tr["Edit"] }} |
32 | button(@click="deleteNews(n)") {{ st.tr["Delete"] }} | |
d85f259c BA |
33 | button(@click="gotoPrevNext(n, 1)") {{ st.tr["Previous_n"] }} |
34 | button(@click="gotoPrevNext(n, -1)") {{ st.tr["Next_n"] }} | |
622e0fa8 | 35 | .news-content(v-html="parseHtml(n.content)") |
b3ef5759 | 36 | button#loadMoreBtn( |
910d631b BA |
37 | v-if="hasMore" |
38 | @click="loadMore()" | |
39 | ) | |
604b951e BA |
40 | | {{ st.tr["Load more"] }} |
41 | </template> | |
42 | ||
43 | <script> | |
44 | import { store } from "@/store"; | |
45 | import { ajax } from "@/utils/ajax"; | |
a9e79351 | 46 | import params from "@/parameters"; |
604b951e BA |
47 | import { getDate, getTime } from "@/utils/datetime"; |
48 | import { processModalClick } from "@/utils/modalClick"; | |
49 | export default { | |
50 | name: "my-news", | |
51 | data: function() { | |
52 | return { | |
604b951e | 53 | st: store.state, |
0234201f BA |
54 | // timestamp of oldest showed news: |
55 | cursor: Number.MAX_SAFE_INTEGER, | |
56 | // hasMore == TRUE: a priori there could be more news to load | |
57 | hasMore: true, | |
6808d7a1 | 58 | curnews: { id: 0, content: "" }, |
604b951e | 59 | newsList: [], |
6808d7a1 | 60 | infoMsg: "" |
604b951e BA |
61 | }; |
62 | }, | |
fe23f977 | 63 | computed: { |
6fbf1743 | 64 | devTeam: function() { |
fe23f977 BA |
65 | return params.devs.includes(this.st.user.id); |
66 | } | |
67 | }, | |
604b951e | 68 | created: function() { |
e57c4de4 BA |
69 | ajax( |
70 | "/news", | |
71 | "GET", | |
72 | { | |
73 | data: { cursor: this.cursor }, | |
74 | success: (res) => { | |
0234201f BA |
75 | // The returned list is sorted from most recent to oldest |
76 | this.newsList = res.newsList; | |
e57c4de4 | 77 | const L = res.newsList.length; |
0234201f | 78 | if (L > 0) this.cursor = res.newsList[L - 1].added; |
68e19a44 | 79 | else this.hasMore = false; |
e57c4de4 BA |
80 | } |
81 | } | |
82 | ); | |
604b951e BA |
83 | }, |
84 | mounted: function() { | |
d9a7a1e4 BA |
85 | // Mark that I've read the news: |
86 | localStorage.setItem("newsRead", Date.now()); | |
87 | if (this.st.user.id > 0) ajax("/newsread", "PUT"); | |
88 | document.getElementById("newsMenu").classList.remove("somenews"); | |
6808d7a1 BA |
89 | document |
90 | .getElementById("newnewsDiv") | |
91 | .addEventListener("click", processModalClick); | |
604b951e BA |
92 | }, |
93 | methods: { | |
94 | formatDatetime: function(dt) { | |
95 | const dtObj = new Date(dt); | |
bd76b456 BA |
96 | const timePart = getTime(dtObj); |
97 | // Show minutes but not seconds: | |
6808d7a1 BA |
98 | return ( |
99 | getDate(dtObj) + " " + timePart.substr(0, timePart.lastIndexOf(":")) | |
100 | ); | |
604b951e BA |
101 | }, |
102 | parseHtml: function(txt) { | |
103 | return !txt.match(/<[/a-zA-Z]+>/) | |
104 | ? txt.replace(/\n/g, "<br/>") //no HTML tag | |
105 | : txt; | |
106 | }, | |
107 | adjustHeight: function() { | |
108 | const newsContent = document.getElementById("newsContent"); | |
2c5d7b20 | 109 | // https://stackoverflow.com/a/995374 |
604b951e | 110 | newsContent.style.height = "1px"; |
6808d7a1 | 111 | newsContent.style.height = 10 + newsContent.scrollHeight + "px"; |
604b951e BA |
112 | }, |
113 | resetCurnews: function() { | |
114 | this.curnews.id = 0; | |
115 | this.curnews.content = ""; | |
116 | // No need for added and uid fields: never updated | |
117 | }, | |
d85f259c BA |
118 | gotoPrevNext: function(n, dir) { |
119 | document.getElementById("n" + n.id)[ | |
120 | (dir < 0 ? "previous" : "next") + "ElementSibling"].scrollIntoView(); | |
121 | }, | |
604b951e BA |
122 | showModalNews: function() { |
123 | this.resetCurnews(); | |
6808d7a1 | 124 | window.doClick("modalNews"); |
604b951e BA |
125 | }, |
126 | sendNews: function() { | |
127 | const edit = this.curnews.id > 0; | |
128 | this.infoMsg = "Processing... Please wait"; | |
e57c4de4 BA |
129 | ajax( |
130 | "/news", | |
131 | edit ? "PUT" : "POST", | |
132 | { | |
133 | data: { news: this.curnews }, | |
134 | success: (res) => { | |
135 | if (edit) { | |
136 | let n = this.newsList.find(n => n.id == this.curnews.id); | |
d85f259c | 137 | if (!!n) n.content = this.curnews.content; |
e57c4de4 BA |
138 | } else { |
139 | const newNews = { | |
140 | content: this.curnews.content, | |
141 | added: Date.now(), | |
142 | uid: this.st.user.id, | |
143 | id: res.id | |
144 | }; | |
145 | this.newsList = [newNews].concat(this.newsList); | |
146 | } | |
147 | document.getElementById("modalNews").checked = false; | |
148 | this.infoMsg = ""; | |
149 | this.resetCurnews(); | |
150 | } | |
604b951e | 151 | } |
e57c4de4 | 152 | ); |
604b951e BA |
153 | }, |
154 | editNews: function(n) { | |
155 | this.curnews.content = n.content; | |
156 | this.curnews.id = n.id; | |
157 | // No need for added and uid fields: never updated | |
6808d7a1 | 158 | window.doClick("modalNews"); |
604b951e BA |
159 | }, |
160 | deleteNews: function(n) { | |
6808d7a1 | 161 | if (confirm(this.st.tr["Are you sure?"])) { |
604b951e | 162 | this.infoMsg = "Processing... Please wait"; |
e57c4de4 BA |
163 | ajax( |
164 | "/news", | |
165 | "DELETE", | |
166 | { | |
167 | data: { id: n.id }, | |
168 | success: () => { | |
169 | const nIdx = this.newsList.findIndex(nw => nw.id == n.id); | |
170 | this.newsList.splice(nIdx, 1); | |
171 | this.infoMsg = ""; | |
172 | document.getElementById("modalNews").checked = false; | |
173 | } | |
174 | } | |
175 | ); | |
604b951e BA |
176 | } |
177 | }, | |
178 | loadMore: function() { | |
e57c4de4 BA |
179 | ajax( |
180 | "/news", | |
181 | "GET", | |
182 | { | |
183 | data: { cursor: this.cursor }, | |
184 | success: (res) => { | |
68e19a44 BA |
185 | const L = res.newsList.length; |
186 | if (L > 0) { | |
e57c4de4 | 187 | this.newsList = this.newsList.concat(res.newsList); |
68e19a44 | 188 | this.cursor = res.newsList[L - 1].added; |
e57c4de4 BA |
189 | } else this.hasMore = false; |
190 | } | |
191 | } | |
192 | ); | |
6808d7a1 BA |
193 | } |
194 | } | |
604b951e BA |
195 | }; |
196 | </script> | |
197 | ||
26d8a01a | 198 | <style lang="sass" scoped> |
604b951e BA |
199 | [type="checkbox"].modal+div .card |
200 | max-width: 767px | |
201 | max-height: 100% | |
910d631b | 202 | |
604b951e | 203 | textarea#newsContent |
bd76b456 | 204 | margin: 0 |
604b951e BA |
205 | width: 100% |
206 | min-height: 200px | |
207 | max-height: 100% | |
910d631b | 208 | |
604b951e BA |
209 | #dialog |
210 | padding: 5px | |
211 | color: blue | |
910d631b | 212 | |
23e1fa07 BA |
213 | #writeNews |
214 | padding-top: 50px | |
215 | ||
b3ef5759 | 216 | button#writeNewsBtn, button#loadMoreBtn |
0c76fa56 BA |
217 | margin-top: 0 |
218 | margin-bottom: 0 | |
910d631b | 219 | |
bd76b456 BA |
220 | span.ndt |
221 | color: darkblue | |
feae89d3 | 222 | padding: 0 5px 0 var(--universal-margin) |
910d631b | 223 | |
26d8a01a BA |
224 | .margintop |
225 | margin-top: 25px | |
226 | border-top: 1px solid grey | |
227 | @media screen and (max-width: 767px) | |
228 | .margintop | |
229 | margin-top: 10px | |
230 | </style> | |
231 | ||
232 | <style lang="sass"> | |
feae89d3 BA |
233 | .news |
234 | padding-top: 10px | |
622e0fa8 | 235 | & > .dev-buttons |
bd76b456 | 236 | display: inline-block |
622e0fa8 | 237 | & > .news-content |
9493b395 BA |
238 | margin: var(--universal-margin) |
239 | & > p | |
240 | margin: 10px 0 | |
241 | & > br | |
242 | display: block | |
243 | margin-top: 10px | |
244 | content: " " | |
604b951e | 245 | </style> |