Commit | Line | Data |
---|---|---|
604b951e BA |
1 | <template lang="pug"> |
2 | main | |
3 | input#modalNews.modal(type="checkbox") | |
4 | div#newnewsDiv(role="dialog" data-checkbox="modalNews") | |
5 | .card | |
6 | label.modal-close(for="modalNews") | |
7 | textarea#newsContent( | |
8 | v-model="curnews.content" | |
9 | :placeholder="st.tr['News go here']" | |
10 | @input="adjustHeight" | |
11 | ) | |
12 | button(@click="sendNews()") {{ st.tr["Send"] }} | |
13 | #dialog.text-center {{ st.tr[infoMsg] }} | |
14 | .row | |
15 | .col-sm-12.col-md-10.col-md-offset-1.col-lg-8.col-lg-offset-2 | |
0c76fa56 | 16 | button#writeNews( |
604b951e BA |
17 | v-if="devs.includes(st.user.id)" |
18 | @click="showModalNews" | |
19 | ) | |
20 | | {{ st.tr["Write news"] }} | |
bd76b456 BA |
21 | .news(v-for="n,idx in sortedNewsList" :class="{margintop:idx>0}") |
22 | span.ndt {{ formatDatetime(n.added) }} | |
604b951e BA |
23 | div(v-if="devs.includes(st.user.id)") |
24 | button(@click="editNews(n)") {{ st.tr["Edit"] }} | |
25 | button(@click="deleteNews(n)") {{ st.tr["Delete"] }} | |
bd76b456 | 26 | p(v-html="parseHtml(n.content)") |
604b951e BA |
27 | button(v-if="hasMore" @click="loadMore()") |
28 | | {{ st.tr["Load more"] }} | |
29 | </template> | |
30 | ||
31 | <script> | |
32 | import { store } from "@/store"; | |
33 | import { ajax } from "@/utils/ajax"; | |
34 | import { getDate, getTime } from "@/utils/datetime"; | |
35 | import { processModalClick } from "@/utils/modalClick"; | |
36 | export default { | |
37 | name: "my-news", | |
38 | data: function() { | |
39 | return { | |
40 | devs: [1], //for now the only dev is me | |
41 | st: store.state, | |
42 | cursor: 0, //ID of last showed news | |
43 | hasMore: true, //a priori there could be more news to load | |
44 | curnews: {id:0, content:""}, | |
45 | newsList: [], | |
46 | infoMsg: "", | |
47 | }; | |
48 | }, | |
49 | created: function() { | |
50 | ajax("/news", "GET", {cursor:this.cursor}, (res) => { | |
51 | this.newsList = res.newsList; | |
52 | const L = res.newsList.length; | |
53 | if (L > 0) | |
54 | this.cursor = res.newsList[L-1].id; | |
55 | }); | |
56 | }, | |
57 | mounted: function() { | |
58 | document.getElementById("newnewsDiv").addEventListener("click", processModalClick); | |
59 | }, | |
60 | computed: { | |
61 | sortedNewsList: function() { | |
62 | return this.newsList.sort( (n1,n2) => n1.added - n2.added ); | |
63 | }, | |
64 | }, | |
65 | methods: { | |
66 | formatDatetime: function(dt) { | |
67 | const dtObj = new Date(dt); | |
bd76b456 BA |
68 | const timePart = getTime(dtObj); |
69 | // Show minutes but not seconds: | |
70 | return getDate(dtObj) + " " + timePart.substr(0,timePart.lastIndexOf(":")); | |
604b951e BA |
71 | }, |
72 | parseHtml: function(txt) { | |
73 | return !txt.match(/<[/a-zA-Z]+>/) | |
74 | ? txt.replace(/\n/g, "<br/>") //no HTML tag | |
75 | : txt; | |
76 | }, | |
77 | adjustHeight: function() { | |
78 | const newsContent = document.getElementById("newsContent"); | |
79 | // https://stackoverflow.com/questions/995168/textarea-to-resize-based-on-content-length | |
80 | newsContent.style.height = "1px"; | |
81 | newsContent.style.height = (10+newsContent.scrollHeight)+"px"; | |
82 | }, | |
83 | resetCurnews: function() { | |
84 | this.curnews.id = 0; | |
85 | this.curnews.content = ""; | |
86 | // No need for added and uid fields: never updated | |
87 | }, | |
88 | showModalNews: function() { | |
89 | this.resetCurnews(); | |
90 | doClick('modalNews'); | |
91 | }, | |
92 | sendNews: function() { | |
93 | const edit = this.curnews.id > 0; | |
94 | this.infoMsg = "Processing... Please wait"; | |
95 | ajax( | |
96 | "/news", | |
97 | edit ? "PUT" : "POST", | |
98 | {news: this.curnews}, | |
99 | (res) => { | |
100 | if (edit) | |
101 | { | |
102 | let n = this.newsList.find(n => n.id == this.curnews.id); | |
103 | if (!!n) | |
104 | n.content = this.curnews.content; | |
105 | } | |
106 | else | |
107 | { | |
108 | const newNews = { | |
109 | content:this.curnews.content, | |
110 | added:Date.now(), | |
111 | uid: this.st.user.id, | |
112 | id: res.id | |
113 | }; | |
114 | this.newsList = this.newsList.concat([newNews]); | |
115 | } | |
116 | document.getElementById("modalNews").checked = false; | |
117 | this.infoMsg = ""; | |
118 | this.resetCurnews(); | |
119 | } | |
120 | ); | |
121 | }, | |
122 | editNews: function(n) { | |
123 | this.curnews.content = n.content; | |
124 | this.curnews.id = n.id; | |
125 | // No need for added and uid fields: never updated | |
126 | doClick('modalNews'); | |
127 | }, | |
128 | deleteNews: function(n) { | |
129 | if (confirm(this.st.tr["Are you sure?"])) | |
130 | { | |
131 | this.infoMsg = "Processing... Please wait"; | |
132 | ajax("/news", "DELETE", {id:n.id}, () => { | |
133 | const nIdx = this.newsList.findIndex(nw => nw.id == n.id); | |
134 | this.newsList.splice(nIdx, 1); | |
135 | this.infoMsg = ""; | |
136 | document.getElementById("modalNews").checked = false; | |
137 | }); | |
138 | } | |
139 | }, | |
140 | loadMore: function() { | |
141 | ajax("/news", "GET", {cursor:this.cursor}, (res) => { | |
142 | if (res.newsList.length > 0) | |
143 | { | |
144 | this.newsList = this.newsList.concat(res.newsList); | |
145 | const L = res.newsList.length; | |
146 | if (L > 0) | |
147 | this.cursor = res.newsList[L-1].id; | |
148 | } | |
149 | else | |
150 | this.hasMore = false; | |
151 | }); | |
152 | }, | |
153 | }, | |
154 | }; | |
155 | </script> | |
156 | ||
157 | <style lang="sass" scoped> | |
158 | [type="checkbox"].modal+div .card | |
159 | max-width: 767px | |
160 | max-height: 100% | |
161 | textarea#newsContent | |
bd76b456 | 162 | margin: 0 |
604b951e BA |
163 | width: 100% |
164 | min-height: 200px | |
165 | max-height: 100% | |
166 | #dialog | |
167 | padding: 5px | |
168 | color: blue | |
0c76fa56 BA |
169 | button#writeNews |
170 | margin-top: 0 | |
171 | margin-bottom: 0 | |
bd76b456 BA |
172 | span.ndt |
173 | color: darkblue | |
feae89d3 | 174 | padding: 0 5px 0 var(--universal-margin) |
bd76b456 BA |
175 | .margintop |
176 | margin-top: 25px | |
bd76b456 | 177 | border-top: 1px solid grey |
feae89d3 BA |
178 | .news |
179 | padding-top: 10px | |
bd76b456 BA |
180 | & > div |
181 | display: inline-block | |
182 | @media screen and (max-width: 767px) | |
183 | .margintop | |
184 | margin-top: 10px | |
604b951e | 185 | </style> |