PageSourceSearch

https://shvmiskra.ru/nassets/e8dff584/js/conversation_controls.js?v=1765633899

js shvmiskra.ru collected 2026-10-08 16:18:42 UTC 9,514 bytes, 308 lines download raw bytes

1jQuery.widget( 'gc.conversationControls', {
2	activeTab: "templates",
3	noAnimate: true,
4	tabsContents: {},
5	_create: function () {
6		if ( ! window.userInfo.isTeacher ) {
7			return;
8		}
9
10
11		this.commentsContainer = this.options.commentsContainer;
12
13		let $el = this.element;
14		let self = this;
15		setTimeout( function() {
16			self.noAnimate = false;
17		}, 500 );
18
19		//let $collapsedContent = $('<div class="expand-link"><div class="expand-link-border"></div> <div class="expand-link-title"></div> </div>').appendTo( $el );
20
21		let $tabs = this.tabs = $('<div class="conversation-controls-tabs"/>');
22		$tabs.appendTo( $el );
23
24		//$('<div data-tab="templates" class="tab">Шаблоны</div>').appendTo( $tabs );
25		$('<div data-tab="notes" class="tab">' + Yii.t('common', 'Добавить заметку') + '</div>').appendTo( $tabs );
26
27		this.element.parents('.conversation-widget').addClass('with-controls')
28
29		$tabs.find('.tab').click( function() {
30			if ( $(this).hasClass('active')) {
31				self.selectTab(null)
32			}
33			else {
34				self.selectTab($(this).data('tab'))
35			}
36		});
37
38		this.tabContentBlock = $('<div class="tab-content conversation-control-tab text-right">');
39		this.tabContentBlock.hide();
40		this.parentBlock = $el.parents('.gc-comment-form');
41		this.tabContentBlock.prependTo( this.parentBlock );
42
43
44		this.setHistory( this.options.history );
45
46		//$collapsedContent.show();
47		//this.collapsedContent = $collapsedContent;
48
49		/*(
50		$collapsedContent.find('.expand-link-title').click( function() {
51			gcSetCookie('conversationControlsExpanded', 1);
52
53			$collapsedContent.hide();
54			self.showContent();
55		});
56
57
58		if ( gcGetCookie('conversationControlsExpanded') == "1" ) {
59			this.showContent();
60		}
61		 */
62
63
64	},
65	selectTab: function( tab ) {
66		this.tabContentBlock.show();
67		this.activeTab = tab;
68
69
70		this.tabs.find('.tab').removeClass('active');
71		this.tabs.find('.tab[data-tab="' + tab + '"]').addClass('active');
72		let content = null;
73		if ( this.activeTab == "templates" ) {
74			 content = this.createTemplatesContent();
75		}
76		else if ( this.activeTab == "notes" ) {
77			content = this.createNotesContent();
78		}
79
80
81		this.tabContentBlock.hide();
82		this.tabContentBlock.empty();
83		if ( this.activeTab ) {
84			content.appendTo(this.tabContentBlock);
85			this.tabContentBlock.show('fade');
86		}
87		if ( this.activeTab == "notes") {
88			this.parentBlock.find('.new-comment').hide();
89		}
90		else {
91			this.parentBlock.find('.new-comment').show();
92		}
93		if ( content ) {
94			content.find('.main-input').focus();
95		}
96
97
98
99
100		let self = this;
101		self.doScroll();
102
103	},
104	doScroll: function() {
105		let $div = $('.conversation-widget .comments-container');
106		if ( this.noAnimate ) {
107			$div.prop({scrollTop: $div.prop("scrollHeight")});
108		}
109		else {
110			$div.animate({scrollTop: $div.prop("scrollHeight")}, 300);
111		}
112	},
113	createContentBlock: function() {
114		let self = this;
115
116		let $expandedContent = $('<div class="expanded-content"></div>').appendTo( this.element );
117
118		return $expandedContent;
119	},
120	setHistory: function(history) {
121		let $comments = this.commentsContainer.find('.gc-comment');
122		let somethingChanged = false;
123		for ( let row of history ) {
124			let itemId = 'actionHistory' + row.id;
125			if( $('#' + itemId ).length > 0 ) {
126				continue;
127			}
128			let $historyHtml = $('<div class="history-action ' + row.history_class + '"><div class="line"></div><div class="inner-html">' + row.by_user + " &bullet; " + row.created_at + " &bullet;  " + row.title + '</div> </div> </div>');
129			$historyHtml.data('id', row.id)
130			let needClick = false;
131			$('<div id="actionHistory' + row.id + '" class="date-info">' +  + '</div>').appendTo( $historyHtml );
132			if ( row.html && row.html.length > 0  ) {
133				$historyHtml.data('text', row.text );
134				let $item = $('<div class="inner-html-data"><div class="inner-html-content">' + row.html + '</div></div>');
135				$item.appendTo( $historyHtml );
136				needClick = true;
137			}
138			let doBreak = false;
139			let $lastComment = null;
140			$comments.each(function (index, commentEl) {
141				if ( doBreak ) {
142					return;
143				}
144				let $commentEl = $(commentEl);
145				let commentTimestamp = $commentEl.data('timestamp');
146				if ( commentTimestamp > row.timestamp ) {
147					$historyHtml.insertBefore( $commentEl );
148					somethingChanged = true;
149					doBreak = true;
150				}
151				$lastComment = $commentEl;
152			});
153			if ( ! doBreak ) {
154				$historyHtml.appendTo(this.commentsContainer.find('> .comments'));
155				somethingChanged = true;
156			}
157			if ( needClick ) {
158				$historyHtml.find('.inner-html-content').dblclick( function() {
159					let $viewContent = $(this);
160					let $parentContainer = $(this).parents('.inner-html-data');
161
162					$viewContent.hide();
163
164					let $editCont = $("<div/>")
165					$editCont.appendTo( $parentContainer );
166					let $historyActionCont = $editCont.parents('.history-action');
167
168					let $textarea = $('<textarea style="min-height: 40px; margin-bottom: 10px;" class="form-control"/>');
169					$textarea.val( $historyActionCont.data('text') );
170					$textarea.height( 100 );
171					//$textarea.autosize();
172
173					$textarea.appendTo( $editCont );
174
175
176					$('<button class="btn btn-success">Save</button>').click( function() {
177						let text = $textarea.val();
178						let id = $historyActionCont.data('id');
179						ajaxCall("/pl/tasks/resp/edit-note?actionHistoryId=" + id, { text: text }, {}, function( response ) {
180							if ( response.data.deleted ) {
181								$editCont.parents('.history-action').detach();
182							}
183							else {
184								$editCont.detach();
185								$viewContent.html(response.data.html).show();
186								$historyActionCont.data('text', response.data.text);
187							}
188						} );
189
190					}).appendTo( $editCont );
191					$('<button class="btn btn-link">Cancel</button>').click( function() {
192						$editCont.detach();
193						$viewContent.show();
194					}).appendTo( $editCont );
195
196
197				})
198			}
199		}
200		if ( somethingChanged ) {
201			//this.doScroll();
202		}
203	},
204	doSearchTemplates: function( string, $searchList ) {
205		//$searchList.html('<span class="/public/img/loading.gif"/> Поиск');
206		let searchResults = this.searchResults = {};
207
208		let showItems = function(items) {
209			$searchList.empty();
210			$searchList.hide();
211			if ( items.length == 0 ) {
212				$searchList.html( '<div class="info">Поиск ничего не дал</div>').show('fade')
213			}
214			for (let item of items) {
215				let $itemEl = $("<li> <span class='fa fa-list'></span> " + item.title + "</li>").appendTo($searchList);
216
217				$itemEl.click(function () {
218					let questionDialog = new SkillQuestionDialog();
219					questionDialog.open(item.id, window.accountUserId, function (text) {
220						$('.gc-comment-form .new-comment-textarea').val(text);
221						$('.gc-comment-form .new-comment-textarea').css('min-height', 100).focus();
222					});
223				});
224				$searchList.show('fade');
225
226			}
227		};
228		if ( searchResults[string]) {
229			showItems(searchResults[string]);
230		}
231		else {
232			ajaxCall("/pl/notifications/skill-question/search-templates", {string: string}, {method: "get"}, function( response ) {
233				searchResults[string] = response.data.items;
234				showItems( searchResults[string] );
235			});
236		}
237
238	},
239	createTemplatesContent: function() {
240		let self = this;
241
242		let $result = $("<div class='content-block'>");
243
244		let $searchInput = $('<input class="main-input form-control" size="40" placeholder="Поиск по шаблонам ответов">');
245		$searchInput.appendTo($result);
246		let $searchList = $("<ul class='search-list'>").appendTo($result);
247
248		let currentTimeout = null;
249
250		$searchInput.keyup(function () {
251			clearTimeout(currentTimeout);
252			let string = $(this).val();
253			if ( ! string ) string = "";
254			string = string.trim();
255			if (string.length > 2 ) {
256				$searchList.html('<div class="info"><img src="/public/img/loading.gif"/> Поиск</div>');
257				if ( !self.searchResults[string] ) {
258					currentTimeout = setTimeout(function () {
259						self.doSearchTemplates(string, $searchList);
260					}, 200);
261				}
262				else {
263					self.doSearchTemplates(string, $searchList);
264				}
265			}
266			else if (string && string.length > 0) {
267				$searchList.html('<div class="info">Введите как минимум 3 символа</div>');
268			}
269			else {
270				self.doSearchTemplates( "", $searchList );
271			}
272		});
273
274		self.doSearchTemplates( "", $searchList );
275
276		return $result;
277	},
278	createNotesContent: function() {
279		let self = this;
280		let $result = $("<div class='content-block'><textarea rows=2 class='form-control main-input' style='margin-bottom: 5px; background: lightyellow' placeholder='" +
281			Yii.t('common', 'Оставить пометку, которая видна только сотрудникам') +
282			"'></textarea></div>");
283		$result.find('textarea').autosize();
284		$result.find('textarea').css('minHeight', 40);
285		$result.find('textarea').keyup(function(event) {
286			if( event.keyCode == 13 && ( event.ctrlKey )  ) {
287				$button.click();
288			}
289		});
290
291		let $button = $('<button class="btn btn-success">' + Yii.t('common', 'Добавить') + '</button>').appendTo( $result );
292		$button.click( function() {
293			let text = $result.find('textarea').val();
294			ajaxCall("/pl/tasks/resp/note?id=" + self.options.responsibilityId, { text: text }, {}, function( response ) {
295				self.setHistory( response.data.history );
296				$result.find('textarea').val("");
297				self.selectTab(null)
298			} );
299		});
300
301		let $buttonCancel = $('<button class="btn btn-link">' + Yii.t('common', 'Отмена') + '</button>').appendTo( $result );
302		$buttonCancel.click( function() {
303			self.selectTab(null)
304		});
305
306		return $result;
307	}
308});

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.