Completed
Push — master ( f7bdb9...8d2b6e )
by Andrii
10:42
created

ResourceListViewer::registerJs()   B

Complexity

Conditions 1
Paths 1

Size

Total Lines 122

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 122
rs 8
c 0
b 0
f 0
cc 1
nc 1
nop 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace hipanel\modules\finance\widgets;
4
5
use DateTime;
6
use hipanel\assets\BootstrapDatetimepickerAsset;
7
use hipanel\modules\finance\models\proxy\Resource;
8
use Yii;
9
use yii\helpers\ArrayHelper;
10
use yii\helpers\Json;
11
use yii\web\View;
12
13
class ResourceListViewer extends BaseResourceViewer
14
{
15
    public function run(): string
16
    {
17
        $this->registerJs();
18
        $this->registerCss();
19
20
        return $this->render('ResourceListViewer', [
21
            'dataProvider' => $this->dataProvider,
22
            'originalContext' => $this->originalContext,
23
            'originalSearchModel' => $this->originalSearchModel,
24
            'uiModel' => $this->uiModel,
25
            'configurator' => $this->configurator,
26
            'model' => new Resource(),
27
        ]);
28
    }
29
30
    private function registerJs(): void
31
    {
32
        BootstrapDatetimepickerAsset::register($this->view);
33
        $request = Yii::$app->request;
34
        $ids = Json::encode(ArrayHelper::getColumn($this->dataProvider->getModels(), 'id'));
35
        $csrf_param = $request->csrfParam;
36
        $csrf_token = $request->csrfToken;
37
        $locale = Yii::$app->language;
38
        $cookieName = 'resource_date_' . $this->originalContext->id;
39
        $cookieOptions = Json::encode([
40
            'path' => '/' . $request->getPathInfo(),
41
            'expires' => (new DateTime())->modify('+45 minutes')->format(DateTime::RFC850),
42
            'max-age' => 3600,
43
            'samesite' => 'lax',
44
        ]);
45
        $this->view->registerJs(/** @lang JavaScript */ <<<"JS"
46
(() => {
47
  const ids = {$ids};
48
  const buildRange = momentObj => {
49
    return {
50
      time_from: momentObj ? momentObj.startOf('month').format('YYYY-MM-DD') : '',
51
      time_till: momentObj ? momentObj.endOf('month').format('YYYY-MM-DD') : ''
52
    }
53
  }
54
  const getDate = () => {
55
    const rawDate = getCookie('{$cookieName}');
56
    
57
    return rawDate ? moment(rawDate) : moment();
58
  }
59
  const setDate = momentObj => {
60
    setCookie('{$cookieName}', momentObj, {$cookieOptions});
61
  }
62
  const dateInput = $('input[name="date-range"]');
63
  const {time_from, time_till} = buildRange(getDate());
64
  dateInput.datetimepicker({
65
    date: getDate(),
66
    maxDate: moment(),
67
    locale: '{$locale}',
68
    viewMode: 'months',
69
    format: 'MMMM YYYY'
70
  });
71
  dateInput.datetimepicker().on('dp.update', evt => {
72
    $('td[data-type]').html('<div class="spinner"><div class="rect1"></div><div class="rect2"></div><div class="rect3"></div><div class="rect4"></div><div class="rect5"></div></div>');
73
    const date = evt.viewDate;
74
    setDate(date);
75
    fetchResources(ids, date.startOf('month').format('YYYY-MM-DD'), date.endOf('month').format('YYYY-MM-DD')).catch(err => {
76
      console.log(err);
77
      hipanel.notify.error(err.message);
78
    });
79
  });
80
  
81
  const fetchResources = async (ids, time_from, time_till) =>  {
82
    const formData = new FormData();
83
    formData.append('object_ids', ids);
84
    if (time_from.length !== 0 && time_till.length !== 0) {
85
      formData.append('time_from', time_from);
86
      formData.append('time_till', time_till);
87
    }
88
    formData.append('{$csrf_param}', '{$csrf_token}');
89
    
90
    try {
91
      const response = await fetch('{$this->fetchResourcesUrl}', {
92
        method: 'POST',
93
        body: formData
94
      });
95
      const result = await response.json();
96
      Object.entries(result).forEach(entry => {
97
        const [id, resources] = entry;
98
        Object.entries(resources).forEach(resource => {
99
          const [type, data] = resource;
100
          const cell = document.querySelector('tr[data-key="' + id + '"] > td[data-type="' + type + '"]');
101
          if (!!cell) {
102
            cell.innerHTML = data.amount;
103
          }
104
        });
105
      });
106
      const not_counted = document.createElement('span');
107
      not_counted.classList.add('text-danger');
108
      not_counted.appendChild(document.createTextNode('not counted'));
109
      document.querySelectorAll('tr[data-key] .spinner').forEach(node => {
110
        node.parentNode.replaceChild(not_counted.cloneNode(true), node);
111
      })
112
    } catch (error) {
113
      hipanel.notify.error(error.message);
114
    }
115
  }
116
  
117
  fetchResources(ids, time_from, time_till); // run request
118
  
119
  // Cookies
120
  function getCookie(name) {
121
    let matches = document.cookie.match(new RegExp(
122
      "(?:^|; )" + name.replace(/([\.$?*|{}\(\)\[\]\\\/\+^])/g, '\\$1') + "=([^;]*)"
123
    ));
124
    return matches ? decodeURIComponent(matches[1]) : undefined;
125
  }
126
  function setCookie(name, value, options = {}) {
127
    options = {
128
      ...options
129
    };
130
    if (options.expires instanceof Date) {
131
      options.expires = options.expires.toUTCString();
132
    }
133
    let updatedCookie = encodeURIComponent(name) + "=" + encodeURIComponent(value);
134
    for (let optionKey in options) {
135
      updatedCookie += "; " + optionKey;
136
      let optionValue = options[optionKey];
137
      if (optionValue !== true) {
138
        updatedCookie += "=" + optionValue;
139
      }
140
    }
141
    document.cookie = updatedCookie;
142
  }
143
  function deleteCookie(name) {
144
    setCookie(name, "", {
145
      'max-age': -1
146
    })
147
  }
148
})();
149
JS
150
            , View::POS_READY);
151
    }
152
153
    private function registerCss()
154
    {
155
        $this->view->registerCss(<<<CSS
156
.spinner {
157
  width: 50px;
158
  height: 10px;
159
  text-align: center;
160
  font-size: 10px;
161
  display: inline-block;
162
}
163
164
.spinner > div {
165
  background-color: #b8c7ce;
166
  height: 100%;
167
  width: 6px;
168
  display: inline-block;
169
  margin-right: .1rem;
170
  
171
  -webkit-animation: sk-stretchdelay 1.2s infinite ease-in-out;
172
  animation: sk-stretchdelay 1.2s infinite ease-in-out;
173
}
174
175
.spinner .rect2 {
176
  -webkit-animation-delay: -1.1s;
177
  animation-delay: -1.1s;
178
}
179
180
.spinner .rect3 {
181
  -webkit-animation-delay: -1.0s;
182
  animation-delay: -1.0s;
183
}
184
185
.spinner .rect4 {
186
  -webkit-animation-delay: -0.9s;
187
  animation-delay: -0.9s;
188
}
189
190
.spinner .rect5 {
191
  -webkit-animation-delay: -0.8s;
192
  animation-delay: -0.8s;
193
}
194
195
@-webkit-keyframes sk-stretchdelay {
196
  0%, 40%, 100% { -webkit-transform: scaleY(0.4) }
197
  20% { -webkit-transform: scaleY(1.0) }
198
}
199
200
@keyframes sk-stretchdelay {
201
  0%, 40%, 100% { 
202
    transform: scaleY(0.4);
203
    -webkit-transform: scaleY(0.4);
204
  }  20% { 
205
    transform: scaleY(1.0);
206
    -webkit-transform: scaleY(1.0);
207
  }
208
}
209
CSS
210
        );
211
    }
212
}