Николай Загумённов

Николай Загумённов

С нами с 19 сентября 2013; Место в рейтинге пользователей: #59
Николай Загумённов
09 июня 2016, 01:31
+1
Может быть msPromoCode подойдет
Николай Загумённов
08 июня 2016, 23:50
4
+2
Спасибо Паше за помощь. Открыл для себя Ext.ComponentMgr.onAvailable.

Вот такой плагин получился и не надо создавать никаких comments2.grid.js.
<?php
switch ($modx->event->name) {
    case 'OnBeforeManagerPageInit':
        
        if ($action['namespace'] == 'tickets' && $action['controller'] == 'index') {
            $modx->controller->addHtml("<script type='text/javascript'>
                Ext.ComponentMgr.onAvailable('tickets-home-tabs', function() {
                    // Тут можно переопределять все что угодно
                });
            </script>");
        }
        break;
}
Николай Загумённов
08 июня 2016, 16:52
0
В Tickets скрипты админки вызываются в контролере.
Николай Загумённов
07 июня 2016, 22:47
0
Потому что проверяю. Я уж подумал, что есть разница в месте расположении файла и проверил переместив его в другое место))
Николай Загумённов
07 июня 2016, 16:59
-1
Интересно? а можно ли как-то переопределить гриду в тикетс?
Как ни пробую вставлять свой файл comments2.grid.js он все время расположен выше файлов тикетс. Как я понял, чтобы переопределение работало надо, чтобы свой файл подключался ниже файлов тикетс.
Николай Загумённов
06 июня 2016, 14:49
+3
О круто) забыл что есть модификатор split
Обожаю феном=)
Николай Загумённов
06 июня 2016, 14:14
2
+1
Попробывал сделать так:
{$_modx->runSnippet('!TicketComments', [
    'showLog' => 1,
	'class' => 'TicketComment',
    	'loadModels' => 'UserFiles',
    	'leftJoin' => '{
        "Thumbs": {
            	"class": "UserFile",
            	"on": "Thumbs.list = TicketComment.id AND Thumbs.properties LIKE \'%w\":120,\"h\":90%\'"
        	}
    	}',
    	'select' => '{
        	"TicketComment": "*",
	        "Thumbs": "GROUP_CONCAT(Thumbs.url) as thumbs"
    	}',
    	'groupby' => 'TicketComment.id',
])}
В плейсхолдере thumbs получаю строку с картикками через запятую. Теперь осталось только сделать сниппет который будет обрабатывать эту строку.
Когда оставляю коментарий картинки не подгружаются сразу, надо обновить страницу, чтобы пути появились под комментом.
Как можно сделать чтобы они подгружались сразу?
P.S. Спасибо за GROUP_CONCAT()
Николай Загумённов
31 мая 2016, 00:39
+1
Там параметр есть data-sorting=«1», он по умолчанию отсутствует в чанке формы. Он отвечает за сортировку.
Николай Загумённов
30 мая 2016, 10:18
0
Большое спасибо за такой развернутый комментарий. Я почему-то всё время хотел использовать поле parent для привязки файлов к комменту. Думал про поле list, но смущало что этих листов будет потом очень много, но сейчас понимаю, что это не так критично нежели если id пользователя совпадет с id комментария.
Про замену тэга form на div действительно забыл упомянуть, важный момент без которого работать не будет.
Николай Загумённов
28 мая 2016, 23:40
4
+3
Выяснил, что можно использовать для этих целей UserFiles.
Надо только добавить плагин, который буде срабатывать после сохранения комментария (событие — OnCommentSave). Вообще очень много открыл для себя с этими плагинами =) В таблице компонента меняю поле parent на id созданного комментария.
<?php
// TicketCommentSave
switch ($modx->event->name) {
    case 'OnCommentSave':
        // $modx->log(1, print_r(array_keys($scriptProperties), 1));
        if ($mode == 'new') {
        	// >> Подключаем UserFiles
			$corePath = $modx->getOption('userfiles_core_path', null, $modx->getOption('core_path', null, MODX_CORE_PATH) . 'components/userfiles/');
			$UserFiles = $modx->getService('UserFiles', 'UserFiles', $corePath . 'model/userfiles/', array('core_path' => $corePath));
			// << Подключаем UserFiles
			
			$user_id = $modx->user->id; // id Авторизованного пользователя
			
			$files = $modx->getCollection('UserFile', array('parent' => $user_id));
			foreach ($files as $file) {
				$file->set('parent', $id);
				$file->save();
				if ($children = $file->getMany('Children')) {
					foreach ($children as $child) {
						$child->remove();
					}
					$file->generateThumbnails();
				}
			}
        }
    break;
}
В чанке формы добавления комментария надо добавить сам сниппет ufForm:
[[!ufForm?
	&class=`modUser`
	&list=`comment`
	&dropzone=`{"maxFilesize":2,"maxFiles":5,"acceptedFiles":".jpg, .jpeg, .gif, .png","template":"edit"}`
]]
В чанке одного комментария(tpl.Tickets.comment.one.auth) добавить:
Должна быть включена поддержка fenom в настройках pdotools.
{$_modx->runSnippet('!pdoResources', [
	'limit' 			=> 10,
	'showLog'			=> 1,
	'class' 			=> 'UserFile',
	'loadModels' 		=> 'UserFiles',
	'sortby' 			=> '{"rank":"ASC"}',
	'tpl' 				=> '@INLINE <div class="item pull-left>
						        <a href="{$url}" rel="fancybox"><img src="{$thumb}" alt=""></a>
						    </div>',
	'where' 			=> '{
						        "UserFile.parent": ' ~ $id ~ ',
						        "UserFile.createdby": '~ $createdby ~'
						        
						    }',
	'leftJoin' 			=> '{
								"Thumb": {
									"class": "UserFile",
									"on": "Thumb.parent = UserFile.id AND Thumb.properties LIKE \'%w\":120,\"h\":90%\'"
								}
						    }',
	'select' 			=> '{
								"UserFile": "url",
								"Thumb": "Thumb.url as thumb"
						    }',
])}
Будет работать только для авторизованных пользователей, так как их id мы заполняем в parent таблицы компонента UserFiles.
Николай Загумённов
28 мая 2016, 22:56
7
+2
Я использовал компонент tvSuperSelect.
Чтобы с фронта добавлять тэги добавил плагин, который заполняет ТВ поле и таблицу компонента значениями:
<?php
// tvssTagsSave
$tvss = $modx->getService('tvsuperselect', 'tvsuperselect', $modx->getOption('core_path').'components/tvsuperselect/model/tvsuperselect/');
if (!($tvss instanceof tvSuperSelect)) {
    return '';
}

switch ($modx->event->name) {

    case 'OnDocFormSave':
        if (is_object($resource) && is_array($resource->_fields)) {
            $data = $resource->_fields;
            $resource_id = $data['id'];
            // $modx->log(1, print_r($data, 1));

            $flds = $tv_values = array();
            foreach ($data as $key => $value) {
                if ($key == 'tags')  {
                    $tv_id = 1;

                    $array = array_diff($value, array(''));
                    if (!empty($array)) {
                        $flds[] = array(
                            'resource_id' => $resource_id,
                            'tv_id' => $tv_id,
                            'data' => $array,
                        );

                        $tv_values[$tv_id] = $modx->toJSON($array);
                    }
                }
            }
             // пишем в таблицу пакета
            if (!empty($flds)) {
                // $modx->log(1, print_r($flds, 1));

                $table = $modx->getTableName('tvssOption');

                foreach ($flds as $fld) {
                    $sql = 'DELETE FROM '.$table.' WHERE `resource_id` = '.$fld['resource_id'].' AND `tv_id` = '.$fld['tv_id'];
                    $stmt = $modx->prepare($sql);
                    $stmt->execute();
                    $stmt->closeCursor();

                    $values = array();
                    foreach ($fld['data'] as $value) {
                        if (!empty($value)) {
                            $values[] = '('.$fld['resource_id'].',"'.$fld['tv_id'].'","'.addslashes($value).'")';
                        }
                    }

                    if (!empty($values)) {
                        $sql = 'INSERT INTO '.$table.' (`resource_id`,`tv_id`,`value`) VALUES '.implode(',', $values);
                        $stmt = $modx->prepare($sql);
                        $stmt->execute();
                        $stmt->closeCursor();
                    }
                }
            }

            // пишем в таблицу modTemplateVarResource
            if (!empty($tv_values)) {
                //$modx->log(1, print_r($tv_values, 1));

                foreach ($tv_values as $tv_id => $values) {
                    if (!$tv_obj = $modx->getObject('modTemplateVarResource', array(
                        'tmplvarid' => $tv_id,
                        'contentid' => $resource_id,
                    ))) {
                        $tv_obj = $modx->newObject('modTemplateVarResource');
                    }

                    $tv_obj->fromArray(array(
                        'tmplvarid' => $tv_id,
                        'contentid' => $resource_id,
                        'value' => $values,
                    ));
                    $tv_obj->save();
                    // $modx->log(1, print_r($tv_obj->toArray(), 1));

                    unset($tv_obj);
                }
            }
        }
    break;
}
Чтобы выводить во фронте поле добавил сниппет:
<?php
// tvssTagsOptions
/* @var pdoFetch $pdoFetch */
$fqn = $modx->getOption('pdoFetch.class', null, 'pdotools.pdofetch', true);
$path = $modx->getOption('pdotools_class_path', null, MODX_CORE_PATH.'components/pdotools/model/', true);
if ($pdoClass = $modx->loadClass($fqn, $path, false, true)) {
    $pdoFetch = new $pdoClass($modx, $scriptProperties);
} else {
    return false;
}
$pdoFetch->addTime('pdoTools loaded');

if (!$modx->addPackage('tvsuperselect', MODX_CORE_PATH.'components/tvsuperselect/model/')) {
    return false;
}

$tv			= $modx->getOption('tv', $scriptProperties, ''); // TV name or...
$tvid		= $modx->getOption('tvId', $scriptProperties, ''); // ... TV id
$tvInput	= $modx->getOption('tvInput', $scriptProperties, ''); // TV input name
$res		= $modx->getOption('res', $scriptProperties, 0); // Resource id
$tpl		= $modx->getOption('tpl', $scriptProperties, 'tpl.tvssTagsOptions');

$tv_where = $tv ? array( 'name' => $tv ) : '';
$tv_where = $tv_where ?: ( $tvid? array( 'id' => $tvid ) : '' );
// print_r($tv_where);

if( empty($tv_where) ) { return; }


if( $tv_obj = $modx->getObject('modTemplateVar', $tv_where) )
{
	$value = '';
	if( $res != 0 && $tv_val_obj = $modx->getObject('modTemplateVarResource', array(
			'tmplvarid'	=> $tv_obj->id,
			'contentid'	=> $res,
	))) {
		$value = $tv_val_obj->value;
	}
	$value_arr = $modx->fromJSON($value); // Массив со значениями тэгов конкретного ресурса

	// Массив, который мы передадим в процессор, там его ловить в $scriptProperties
	$processorProps = array(
	    'tv_id' => $tv_obj->id,
	);
	// Массив опций для метода runProcessor
	$otherProps = array(
	    // Здесь указываем где лежат наши процессоры
	    'processors_path' => $modx->getOption('core_path') . 'components/tvsuperselect/processors/'
	);
	// Запускаем
	$response = $modx->runProcessor('mgr/option/getoptions', $processorProps, $otherProps);
	// И возвращаем ответ от процессора

	$options_array = $modx->fromJSON($response->response); // Массив со всеми тэгами

	
	
	if (is_array($options_array['results']) || is_object($options_array['results'])) {
		foreach($options_array['results'] as $v) {
			$selected = '';
			if (is_array($value_arr) || is_object($value_arr)) {
				foreach ($value_arr as $key => $val) {
					if ($v['value'] == $val) {
						$selected = "selected=\"selected\"";
					}
				}
			}
			$options .= "<option ". $selected ." value=\"". $v['value'] ."\">";
			$options .= $v['value'];
			$options .= "</option>";
			$selected = "";
		}
	}
	
	$return = $modx->getChunk($tpl, array(
		'tv_id'			=> $tv_obj->id,
		'tv_name'		=> $tv_obj->name,
		'tv_input_name'	=> $tvInput ?: $tv_obj->name,
		'tv_value'		=> $value,
		'res_id'		=> $res,
		'options'		=> $options
	));
	
	return $return;
}
else {
	return;
}
Чанк tpl.tvssTagsOptions:
<select name="tags[]" multiple="multiple" class="js-tvSuperSelect-tags form-control" id="ticket-tags">
	[[+options]]
</select>
В чанке с формой добавления/редактирования тикетов добавил:
<link href="/js/select2-4.0.2/dist/css/select2.min.css" rel="stylesheet" />
	<script src="/js/select2-4.0.2/dist/js/select2.min.js"></script>
	<script type="text/javascript">
		$(document).ready(function(){
			$(".js-tvSuperSelect-tags").select2({
				tags: true
			});
		});
	</script>
	<div class="form-group">
		<label for="ticket-sections">Тэги</label>
		[[!tvssTagsOptions? &tv=`tags` &res=`0`]]
		// В чанке редактирования [[!tvssTagsOptions? &tv=`tags` &res=`[[+id]]`]]
		<span class="error"></span>
	</div>
Прикрутил к полю тэгов Select2, чтобы тэги было удобно заполнять и все.
Может кому пригодится =)
Николай Загумённов
26 мая 2016, 11:31
1
0
В mFilter2 я попробовал так сортировать по количеству коментов, не знаю на сколько так правильно делать, вроде работает.
[[!mFilter2?
	&parents=`5,6,7,8`
	&class=`Ticket`
	&element=`getTickets`
	&sortAliases=`{ "ticket":"Ticket","vote":"TicketVote" }`
	&sort=`ticket|createdon:desc,vote:desc,comms|comments:desc`
	&limit=`6`
	&tpl=`tpl.Post.row`
	&includeTVs=`item_image`
	&showLog=`1`
	&leftJoin=`{
				"Comms": {
					"class": "TicketThread",
					"on": "Ticket.id = Comms.resource"
				}
			}`
	&select=`{
				"Ticket": "*",
				"Comms": "Comms.comments as comms"
			}`
	&groupby=`Ticket.id`
]]
Николай Загумённов
25 мая 2016, 20:46
0
Можно ли этот компонент использовать для прикрепления изображений к комментариям тикетс?
Николай Загумённов
25 мая 2016, 11:12
3
0
Путь до картинки можно менять не модификаторами во время, а при сохранении тикета, плагином на событие OnDocFormSave.
Заодно проверяет поле content на наличие картинок с таким путём и меняет 0 на id.
Может кому пригодится.
Мне пригодился этот пост. Спасибо за него.

<?php
switch ($modx->event->name) {

    case 'OnDocFormSave':
        if (is_object($resource) && is_array($resource->_fields)) {
            $data = $resource->_fields;
            $resource_id = $data['id'];
            // $modx->log(1, print_r($data, 1));

            $flds = $tv_values = array();
            foreach ($data as $key => $value) {
                if ($key == 'item_image')  {
                    $tv_id = 2; // id твшки с картинкой

                    $value = trim($value);
                    $tv_value = str_replace('assets/images/tickets/0', 'assets/images/tickets/' . $resource_id, $value);
                }
                if ($key == 'content') {
                	$content = str_replace('assets/images/tickets/0', 'assets/images/tickets/' . $resource_id, $value);
                }
            }
            if (!empty($content)) {
            	$res_obj = $modx->getObject('modResource',$resource_id);
            	$res_obj->set('content', $content);
            	$res_obj->save();
            	unset($res_obj);
            }
            // пишем в таблицу modTemplateVarResource
            if (!empty($tv_value)) {
                //$modx->log(1, print_r($tv_values, 1));

                	if (!$tv_obj = $modx->getObject('modTemplateVarResource', array(
                        'tmplvarid' => $tv_id,
                        'contentid' => $resource_id,
                    ))) {
                        $tv_obj = $modx->newObject('modTemplateVarResource');
                    }

                    $tv_obj->fromArray(array(
                        'tmplvarid' => $tv_id,
                        'contentid' => $resource_id,
                        'value' => $tv_value,
                    ));
                    $tv_obj->save();
                    // $modx->log(1, print_r($tv_obj->toArray(), 1));

                    unset($tv_obj);
            }
        }
    break;
}
Николай Загумённов
05 мая 2016, 20:39
+1
Там поле есть оказывается — Закрытый тикет, при редактировании тикета в админке.
Как я понял, пользователям с данной политикой будет доступен просмотр закрытых тикетов.
Николай Загумённов
05 мая 2016, 20:25
0
Что за политика TicketVipPolicy?
A policy for create and update private Tickets — приватные тикеты это какие тикеты?
Прошу прощения если вопрос повторялся=)