Commit 8589b5467308f8579fe99887b259701849099115
1 parent
022d2aadaa
Exists in
master
Nilai maksimal dan indikator grafik
Showing 3 changed files with 136 additions and 6 deletions Side-by-side Diff
lib/control-panel/routers/main.js
... | ... | @@ -22,11 +22,21 @@ async function pageIndex(req, res) { |
22 | 22 | limitedList[i].value = value; |
23 | 23 | } |
24 | 24 | |
25 | + const products = limitedList.map((item) => item.product); | |
26 | + const maxValuesArray = await redisUtil.getMaxValuesForIndicator(products, xid); | |
27 | + const maxValues = {}; | |
28 | + const productCount = products.length; | |
29 | + for (let i = 0; i < productCount; i += 1) { | |
30 | + const product = products[i]; | |
31 | + maxValues[product] = Number(maxValuesArray[i]) || 0; | |
32 | + } | |
33 | + | |
25 | 34 | res.render( |
26 | 35 | 'main.njk', |
27 | 36 | { |
28 | 37 | pageTitle: 'Produk dan Limit', |
29 | 38 | limitedList, |
39 | + maxValues, | |
30 | 40 | }, |
31 | 41 | ); |
32 | 42 | } |
... | ... | @@ -86,6 +96,25 @@ async function pageAddProductQuota(req, res) { |
86 | 96 | res.redirect(req.baseUrl); |
87 | 97 | } |
88 | 98 | |
99 | +async function pageEditMaxValueForIndicator(req, res) { | |
100 | + const { xid } = res.locals; | |
101 | + const { product, maxValue } = req.body; | |
102 | + | |
103 | + try { | |
104 | + logger.info(`${MODULE_NAME}: Saving max value`, { | |
105 | + xid, product, maxValue, | |
106 | + }); | |
107 | + | |
108 | + await redisUtil.setMaxValueForIndicator(product, Number(maxValue), xid); | |
109 | + } catch (e) { | |
110 | + logger.warn(`${MODULE_NAME}: Exception on saving max value for indicator`, { | |
111 | + xid, product, maxValue, eCode: e.code, eMessage: e.message, | |
112 | + }); | |
113 | + } | |
114 | + | |
115 | + res.redirect(req.baseUrl); | |
116 | +} | |
117 | + | |
89 | 118 | router.use((req, res, next) => { |
90 | 119 | res.locals.baseUrl = req.baseUrl; |
91 | 120 | next(); |
... | ... | @@ -98,3 +127,5 @@ router.get('/delete/:suplier/:product', pageDelete); |
98 | 127 | |
99 | 128 | router.post('/edit-product', express.urlencoded({ extended: false }), pageEditProductSubmit); |
100 | 129 | router.post('/add-quota', express.urlencoded({ extended: false }), pageAddProductQuota); |
130 | + | |
131 | +router.post('/edit-max-value-for-indicator', express.urlencoded({ extended: false }), pageEditMaxValueForIndicator); |
lib/control-panel/views/main.njk
... | ... | @@ -5,18 +5,34 @@ |
5 | 5 | <table class="table"> |
6 | 6 | <thead> |
7 | 7 | <tr> |
8 | - <th>Produk</th> | |
9 | - <th class="text-right">Sisa Kuota</th> | |
10 | - <th> </th> | |
8 | + <th style="white-space: nowrap; width: 1%;">Produk</th> | |
9 | + <th class="text-right">Sisa</th> | |
10 | + <th style="white-space: nowrap; width: 1%;"> </th> | |
11 | 11 | </tr> |
12 | 12 | </thead> |
13 | 13 | <tbody> |
14 | 14 | {% for item in limitedList %} |
15 | 15 | <tr> |
16 | - <td><strong>{{ item.product }}</strong></td> | |
17 | - <td class="text-right">{{ item.value }}</td> | |
16 | + <td style="white-space: nowrap; width: 1%;"> | |
17 | + <strong>{{ item.product }}</strong> | |
18 | + </td> | |
19 | + | |
20 | + <td class="text-right"> | |
21 | + {% set maxValue = maxValues[item.product] %} | |
22 | + {% if maxValue %} | |
23 | + <div class="progress"> | |
24 | + <div class="progress-bar" role="progressbar" style="width: {{ 100 * item.value / (maxValue or item.value) }}%;" aria-valuenow="25" aria-valuemin="0" aria-valuemax="{{ maxValue }}"></div> | |
25 | + </div> | |
26 | + <br> | |
27 | + {% endif %} | |
18 | 28 | |
19 | - <td> | |
29 | + <a href="#" title="klik untuk edit nilai maksimal pada grafik indikator" data-toggle="modal" data-target="#editMaxValueModal" data-product="{{ item.product }}" data-maxvalue="{{ item.value }}"> | |
30 | + {{ item.value }} | |
31 | + {% if maxValue %} dari {{ maxValue }} {% endif %} | |
32 | + </a> | |
33 | + </td> | |
34 | + | |
35 | + <td style="white-space: nowrap; width: 1%;"> | |
20 | 36 | <button type="button" class="btn btn-primary btn-sm" data-toggle="modal" data-target="#editQuotaModal" data-product="{{ item.product }}"> |
21 | 37 | Edit |
22 | 38 | </button> |
... | ... | @@ -117,6 +133,34 @@ |
117 | 133 | </div> |
118 | 134 | </form> |
119 | 135 | |
136 | +<form method="POST" action="{{ baseUrl }}/edit-max-value-for-indicator"> | |
137 | +<div class="modal fade" id="editMaxValueModal" tabindex="-1" role="dialog" aria-labelledby="editMaxValueModalLabel" aria-hidden="true"> | |
138 | + <div class="modal-dialog"> | |
139 | + <div class="modal-content"> | |
140 | + <div class="modal-header"> | |
141 | + <h5 class="modal-title" id="editMaxValueModalLabel">Edit nilai maksimal pada indikator</h5> | |
142 | + <button type="button" class="close" data-dismiss="modal" aria-label="Close"> | |
143 | + <span aria-hidden="true">×</span> | |
144 | + </button> | |
145 | + </div> | |
146 | + <div class="modal-body"> | |
147 | + <input type="hidden" name="product" id="inputProduct"> | |
148 | + <div class="form-group"> | |
149 | + <label for="raiseValue">Nilai maksimal</label> | |
150 | + <input name="maxValue" type="number" class="form-control" id="maxValue" aria-describedby="maxValueHelp" required> | |
151 | + <small id="maxValueHelp" class="form-text text-muted">Masukkan nilai maksimal (untuk tampilan grafik).</small> | |
152 | + </div> | |
153 | + </div> | |
154 | + | |
155 | + <div class="modal-footer"> | |
156 | + <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button> | |
157 | + <input type="submit" class="btn btn-primary" value="Simpan"> | |
158 | + </div> | |
159 | + </div> | |
160 | + </div> | |
161 | +</div> | |
162 | +</form> | |
163 | + | |
120 | 164 | {% endblock %} |
121 | 165 | |
122 | 166 | {% block postScriptOnBody %} |
... | ... | @@ -139,6 +183,17 @@ $('#addQuotaModal').on('show.bs.modal', function (event) { |
139 | 183 | modal.find('.modal-title').text(`Tambah Kuota ${product}`); |
140 | 184 | modal.find('.modal-body #inputProduct').val(product); |
141 | 185 | }); |
186 | + | |
187 | +$('#editMaxValueModal').on('show.bs.modal', function (event) { | |
188 | + var button = $(event.relatedTarget); | |
189 | + var product = button.data('product'); | |
190 | + var maxvalue = button.data('maxvalue'); | |
191 | + | |
192 | + var modal = $(this) | |
193 | + modal.find('.modal-title').text(`Edit nilai maksimal ${product}`); | |
194 | + modal.find('.modal-body #inputProduct').val(product); | |
195 | + modal.find('.modal-body #maxValue').val(maxvalue); | |
196 | +}); | |
142 | 197 | </script> |
143 | 198 | |
144 | 199 | {% endblock %} |
145 | 200 | \ No newline at end of file |
lib/redis-util.js
... | ... | @@ -240,3 +240,47 @@ const limitedList = (xid) => new Promise((resolve, reject) => { |
240 | 240 | }); |
241 | 241 | }); |
242 | 242 | exports.limitedList = limitedList; |
243 | + | |
244 | +const setMaxValueForIndicator = (product, val, xid) => new Promise((resolve) => { | |
245 | + if (!(product || '').trim()) { | |
246 | + logger.warn(`${MODULE_NAME}: Skip saving max value for empty product`, { | |
247 | + xid, product, val, | |
248 | + }); | |
249 | + resolve(); | |
250 | + return; | |
251 | + } | |
252 | + | |
253 | + const keyword = `${composeKeyword(product)}_MAX_VALUE`; | |
254 | + logger.info(`${MODULE_NAME}: Saving max value`, { | |
255 | + xid, product, val, keyword, | |
256 | + }); | |
257 | + | |
258 | + redisClient.set(keyword, Number(val), 'EX', DEFAULT_TTL, (err) => { | |
259 | + if (err) { | |
260 | + logger.warn(`9E4965F4 ${MODULE_NAME}: Error on set max value on redis`, { | |
261 | + xid, product, val, eCode: err.code, eMessage: err.message, | |
262 | + }); | |
263 | + resolve(); | |
264 | + return; | |
265 | + } | |
266 | + | |
267 | + resolve(val); | |
268 | + }); | |
269 | +}); | |
270 | +exports.setMaxValueForIndicator = setMaxValueForIndicator; | |
271 | + | |
272 | +const getMaxValuesForIndicator = (products, xid) => new Promise((resolve, reject) => { | |
273 | + const keywords = products.map((item) => `${composeKeyword(item)}_MAX_VALUE`); | |
274 | + redisClient.mget(...keywords, (err, reply) => { | |
275 | + if (err) { | |
276 | + logger.warn(`63BE7706 ${MODULE_NAME}: Error on getting max values on redis`, { | |
277 | + xid, eCode: err.code, eMessage: err.message, | |
278 | + }); | |
279 | + reject(err); | |
280 | + return; | |
281 | + } | |
282 | + | |
283 | + resolve(reply); | |
284 | + }); | |
285 | +}); | |
286 | +exports.getMaxValuesForIndicator = getMaxValuesForIndicator; |