UNPKG

5.96 kBJavaScriptView Raw
1/**
2 * @copyright Copyright (c) 2019 Maxim Khorin <maksimovichu@gmail.com>
3 */
4'use strict';
5
6const Base = require('../base/Base');
7
8module.exports = class ActionView extends Base {
9
10 static getConstants () {
11 return {
12 POS_HEAD: 'head',
13 POS_BODY_END: 'bodyEnd',
14
15 ArrayHelper: require('../helper/ArrayHelper'),
16 CommonHelper: require('../helper/CommonHelper'),
17 EscapeHelper: require('../helper/EscapeHelper'),
18 MongoHelper: require('../helper/MongoHelper'),
19 ObjectHelper: require('../helper/ObjectHelper'),
20 StringHelper: require('../helper/StringHelper')
21 };
22 }
23
24 constructor (config) {
25 super({
26 widgets: {},
27 data: {},
28 ...config
29 });
30 }
31
32 get (name) {
33 return this.theme.getTemplate(name, this.controller.language);
34 }
35
36 getInternalTemplate (name) {
37 return this.get(this.controller.getViewFileName(name));
38 }
39
40 getParentTemplate (name) {
41 return this.theme.getParentTemplate(name, this.controller.language);
42 }
43
44 getViewOwnTemplate (name) {
45 return this.theme.getViewOwnTemplate(name, this.controller.language);
46 }
47
48 getViewOwnTemplateWithOrigin (name) {
49 return this.theme.getViewOwnTemplateWithOrigin(name, this.controller.language);
50 }
51
52 getViewModelClass (name) {
53 return this.theme.getModel(name, this.controller.language);
54 }
55
56 getViewOwnModel (name) {
57 return this.theme.getViewOwnModel(name, this.controller.language);
58 }
59
60 getViewOwnModelWithOrigin (name) {
61 return this.theme.getViewOwnModelWithOrigin(name, this.controller.language);
62 }
63
64 createViewModel (name, config = {}) {
65 const Class = this.getViewModelClass(name);
66 if (Class) {
67 config.view = this;
68 return new Class(config);
69 }
70 }
71
72 log () {
73 CommonHelper.log(this.controller, this.constructor.name, ...arguments);
74 }
75
76 // RENDER
77
78 async render (template, params) {
79 params = this.getRenderParams(params);
80 let content = await this.renderTemplate(this.get(template), params);
81 content = await this.renderWidgets(content, params);
82 return this._asset ? this._asset.render(content) : content;
83 }
84
85 renderTemplate (template, params) {
86 const app = this.controller.res.app;
87 return PromiseHelper.promise(app.render.bind(app, template, params));
88 }
89
90 getRenderParams (params) {
91 params = {
92 _module: this.module,
93 _controller: this.controller,
94 _view: this,
95 _layout: this.controller.VIEW_LAYOUT || this.module.VIEW_LAYOUT,
96 _baseUrl: this.module.app.baseUrl,
97 _format: this.controller.format.bind(this.controller),
98 _t: this.controller.translate.bind(this.controller),
99 _url: this.controller.createUrl.bind(this.controller),
100 _data: null,
101 ...params
102 };
103 params._data = new DataMap(params._data);
104 return params;
105 }
106
107 createHead () {
108 return this.createAssetPosition(this.POS_HEAD);
109 }
110
111 createBodyEnd () {
112 return this.createAssetPosition(this.POS_BODY_END);
113 }
114
115 // ASSET
116
117 addAsset (data) {
118 if (this.getAsset()) {
119 this._asset.add(data);
120 }
121 }
122
123 createAssetPosition (pos) {
124 return this.getAsset() ? this._asset.createPosition(pos) : '';
125 }
126
127 getAsset () {
128 if (this._asset !== undefined) {
129 return this._asset;
130 }
131 const manager = this.module.get('asset');
132 if (manager) {
133 this._asset = manager.createViewAsset();
134 } else {
135 this._asset = null;
136 this.log('error', 'Asset component not found');
137 }
138 return this._asset;
139 }
140
141 // WIDGET
142
143 placeWidget (name, params) {
144 if (!this.widgets.hasOwnProperty(name)) {
145 this.widgets[name] = params || {};
146 }
147 return `#{${name}}`;
148 }
149
150 async renderWidgets (content, renderParams) {
151 const names = Object.keys(this.widgets);
152 if (names.length === 0) {
153 return content;
154 }
155 for (const name of names) {
156 await this.renderWidget(name, renderParams);
157 }
158 return this.insertWidgetContent(content);
159 }
160
161 renderWidget (name, params) {
162 const widget = this.createWidget(name, this.widgets[name]);
163 if (!widget) {
164 return delete this.widgets[name];
165 }
166 this.widgets[name] = widget;
167 return widget.execute(params);
168 }
169
170 createWidget (id, params) {
171 const key = params && params.id || id;
172 const config = this.getWidgetConfig(key);
173 if (!config) {
174 return this.log('error', `Widget configuration not found: ${key}`);
175 }
176 return ClassHelper.spawn({id, ...config, ...params, view: this});
177 }
178
179 getWidgetConfig (key) {
180 if (!this._widgetConfigMap) {
181 this._widgetConfigMap = this.module.getConfig('widgets') || {};
182 }
183 return this._widgetConfigMap.hasOwnProperty(key) ? this._widgetConfigMap[key] : null;
184 }
185
186 insertWidgetContent (content) {
187 const names = Object.keys(this.widgets).join('|');
188 return names.length
189 ? content.replace(new RegExp(`#{(${names})}`, 'g'), (match, name) => this.widgets[name].content)
190 : content;
191 }
192};
193module.exports.init();
194
195const ClassHelper = require('../helper/ClassHelper');
196const CommonHelper = require('../helper/CommonHelper');
197const PromiseHelper = require('../helper/PromiseHelper');
198const DataMap = require('../base/DataMap');
\No newline at end of file