Всего 125 668 комментариев

Александр Туниеков
28 января 2021, 20:17
0
Блин. comet-server.com уже 2 года работает :-(. Я 2 года назад искал подходящий push-сервис и ничего не находил. Пришлось мутить собственный сервис вебсокет уведомлений.
Илья Уткин
28 января 2021, 19:51
0
Один, изначально нужно было заказчику просто на сайт личные сообщения сделать. Потом там накрутилось фишечек. Года два валялось в недоделанном виде)
Александр Туниеков
28 января 2021, 19:10
+1
И теперь сообщения на сайт можно добавть даже 2 вариантами, если мой компонент пройдет модерацию :-).
Ты один делал компонент или комманда трудилась, если не секрет? У меня вид не айс. я верстку плохо знаю :-(.
Илья Уткин
28 января 2021, 18:53
0
Да, много есть таких вариантов. Это может быть и доска объявлений, и специфический сайт, например — каталог мероприятий. Теперь сообщения можно добавить на любой сайт, где есть пользователи.
Александр Туниеков
28 января 2021, 18:21
0
Переписка между группой пользователей предостовляющим услуги на сайте и группой пользующиюся этими услугами. Например, врачебный сайт: онлайн врачи и пациенты. А владельцы сайта не хотят чтоб они в соцсетях без них общались. Только компонент Ильи, наверно, не преспособлен для такой ситуации. Не вижу разбивку пользователей мессенджера на группы.
Илья Уткин
28 января 2021, 18:14
0
Сейчас сообщения как раз и реализованы на топиках. Когда пользователь пишет первое сообщение, создаётся тред, у нему прикрепляется два пользователя — кто написал и кому написали. Но теоретически можно создать тред и прикрепить к нему даже нескольких пользователей. Тогда это будет групповой чат.
Илья Уткин
28 января 2021, 18:12
0
врядли же кто то пишет соцсети на modx
Есть такие люди)
Сергей
28 января 2021, 17:57
0
Илья, внешний вид — классный. Внутри работает хорошо. Вложения прикрепляет.

Вопрос. А сложно сделать с отдельными топиками?

Пользователь создает топик.
Приходит уведомление админу.
Ведется сообщения до победного.
Артур Шевченко
28 января 2021, 17:36
0
Я переписал код, но он всё равно как-то не так работает
<?php
switch ($modx->event->name) {
    case 'OnDocFormSave':
        $oldValue = $resource->getTVValue('old_value');
        $newValue = $resource->get('menuindex');
        $resource->setTVValue('old_value', $newValue);
        $resource->save();
        $resources = $modx->getIterator('msProduct', array('parent' => $resource->get('parent')));
        
        if($newValue < $oldValue){
            foreach($resources as $res){
                $menuindex = $res->get('menuindex');
               
                if($menuindex >= $newValue && $menuindex < $oldValue && $res->get('id') != $id){
                    $res->set('menuindex', $menuindex + 1);
                    $res->set('old_value', $menuindex + 1);
                }
                
                $res->save();                
            }
        }
        else{
            foreach($resources as $res){
                $menuindex = $res->get('menuindex');
               
                if($menuindex > $newValue && $menuindex <= $oldValue && $res->get('id') != $id){
                    $res->set('menuindex', $menuindex - 1);
                    $res->set('old_value', $menuindex - 1);
                }
                
                $res->save();                
            }    
        }
    break;
}
Александр Мельник
28 января 2021, 17:29
0
А для каких целей может понадобиться чат между пользователями?
Я без иронии, просто не могу себе представить ситуацию, когда посетители сайта должны писать друг другу. Ну врядли же кто то пишет соцсети на modx
Ну разве что задать вопрос менеджеру, а вот больше не могу придумать применений.
Поделитесь для чего используете вы?
Александр Туниеков
28 января 2021, 16:44
0
Блин только публикую свой компонент обмена сообщениями, а тут такой облом :-). 2 месяца коту по хвост :-(.
Артур Шевченко
28 января 2021, 16:11
1
0
Думаю стоить дополнить этот пост раз он есть в поиске. Во-первых на мой взгляд решение не самое лучшее, но достаточно простое, поэтому я его немного переделал для компактности
ПЛАГИН
<?php
switch ($modx->event->name) {
    case 'OnDocFormSave':
        $sql = 'SELECT article FROM modx_msop_modifications WHERE rid= ?';
        $statement = $modx->prepare($sql);
        if ( $statement->execute(array($id)) ) {
            $result = $statement->fetchAll(PDO::FETCH_COLUMN);
        }
        $resource->set('introtext', implode(',',$result));
        $resource->save();
    break;
}
КОД ДЛЯ КОСОЛИ, чтобы обновить товары
<?php
$resources = $modx->getIterator('msProduct');

foreach ($resources as $resource) {
    $id = $resource->get('id');
    $sql = 'SELECT article FROM modx_msop_modifications WHERE rid= ?';
    $statement = $modx->prepare($sql);
    if ( $statement->execute(array($id)) ) {
        $result = $statement->fetchAll(PDO::FETCH_COLUMN);
    }
    $resource->set('introtext', implode(',',$result));
    $resource->save();
}
Михаил
28 января 2021, 14:41
0
Наерное надо убрать, что бы пользователь мог отправлять пустые сообщения
Артур Шевченко
28 января 2021, 13:58
0
Сразу оговорюсь это говнокод, а то придут старшие товарищи и начнут тапками меня закидывать. Использовать на свой страх и риск, но у меня работает.
Ссылка имеет вид domain.ru/smeta?order_id=183
На этой странице вызывается сниппет getOrder
{set $order = '!getOrder' | snippet:[
    'order_id' => $.get.order_id
]}
Сниппет возвращает массив, посмотреть что внутри можно так
{$order | print_r}
Сам сниппет выглядит так
<?php
if(!$order_id){return false;}
$pdoTools = $modx->getService('pdoTools');
$orderFields = array('id','num', 'createdon', 
                    'updatedon', 'cart_cost', 
                    'delivery_cost', 'comment', 
                    'status', 'cost');
$orderProductFields = array('id','product_id', 
                            'name', 'count', 
                            'price', 'cost', 'options');
                        
$addressFields = array('city', 'street',
                        'receiver', 'phone',
                        'comment');
$output = array(
    'meta' => [],
    'address' => [],
    'products' => []
    );

$order = $modx->getObject('msOrder', $order_id);
if($order){        
    //заполняем массив основных данных заказа
    for($i = 0; $i < count($orderFields); $i++){
        $output['meta'][$orderFields[$i]] = $order->get($orderFields[$i]); 
    }
    
    //вычисляем срок выполнения заказа
    $output['meta']['duration'] = ceil($output['meta']['cost'] / $modx->getOption('base_cost'));
            
    //заполняем адрес и дополнительные данные
    $address = $order->getOne('Address');
    $properties = $address->get('properties');
    for($i = 0; $i < count($addressFields); $i++){
        if($addressFields[$i] != 'properties'){
            $output['address'][$addressFields[$i]] = $address->get($addressFields[$i]); 
        }else{
            foreach($properties as $name => $prop){
                $output['address'][$name] = $prop; 
            }
        }
    }
    //заполняем продукты
    $products = $order->getMany('Products');
    if($products){
        foreach($products as $key => $product){
            for($i = 0; $i < count($orderProductFields); $i++){
                $output['products'][$key][$orderProductFields[$i]] = $product->get($orderProductFields[$i]); 
            }
        }  
    }
    
    
    //$modx->log(1, 'OUTPUT getUserOrder ' . print_r($output, 1));
    
    if($tpl){
        return $pdoTools->getChunk($tpl, $output);
    }
    //$modx->log(1, print_r($output,1));
    return $output;
}else{
    return false;
}
После вызова сниппет идёт такой код
{if $order}
<p class="h-6"><span class="text-orange">Номер заказа:</span> {$order['meta']['num']}</p>
<p class="h-6"><span class="text-orange">Дата заказа:</span> {$order['meta']['createdon'] | date: 'd.m.Y H:i:s'}</p>
<p class="h-6"><span class="text-orange">Имя заказчика:</span> {$order['address']['receiver']}</p>
{if $_modx->isAuthenticated('mgr') || $.get.admin}
<p class="h-6"><span class="text-orange">Телефон заказчика:</span> <a class="service-link" href="tel:{$order['address']['phone'] | replace:'-':'' }">{$order['address']['phone'] | replace:'-':'' }</a></p>
{/if}
<p class="h-6"><span class="text-orange">Общая стоимость:</span> <span class="jsTotalOrderCost">{$order['meta']['cost']}</span> руб.</p>
<p class="h-6"><span class="text-orange">Срок выполнения:</span> <span class="jsOrderDuration">{$order['meta']['duration']}</span> дн.</p>
<p class="h-6 mb-0"><span class="text-orange">Перечень включенных в состав услуг 
 <small class="small">(в стоимость услуг входит стоимость платных дополнений)</small></span></p>
    {if $_modx->isAuthenticated('mgr') || $.get.admin}
        <div class="pl-0" id="orderWrap">
        {if $order['products']}    
        {set $i = 1}    
        {foreach $order['products'] as $key => $product}
            {set $description = $product['product_id'] | resource: 'desc'}
            {set $introtext = $product['product_id'] | resource: 'introtext'}
            {set $add_cost = $product['product_id'] | resource: 'add_cost'}
            {set $weight = $product['product_id'] | resource: 'weight'}
            {$_modx->parseChunk('@FILE chunks/shop/editOrderProduct.html', [
                'description' => $product['options']['desc']?:$description,
                'introtexxt' => $introtext,
                'index' => $i,
                'add_cost' => $add_cost,
                'price' => $product['price'],
                'weight' => $weight,
                'count' => $product['count'],
                'name' => $product['options']['name']?:$product['name'],
                'cost' => $product['cost'],
                'id' => $product['id'],
                'options' => $product['options'],
                'order_id' => $.get.order_id,
                'total_cost' => $order['meta']['cost'],
                'product_id' => $product['product_id']
            ])}
            {set $i = $i + 1}
        {/foreach}
        {else}
        <p class="h-6 my-3 text-red">Необходимо добавить услуги!</p>
        {/if}
        </div>
         <p class="h-5 mt-3 mb-3">Найти услугу</p>
        {'!AjaxForm' | snippet: [
            'snippet' => 'searchResources',
            'tpl' => '@FILE chunks/shop/editOrderProductTpl.html',
            'form' => '@FILE chunks/forms/searchForm.html',
            'fieldsForSearch' => 'pagetitle,longtitle,menutitle',
            'validate' => 'query:required:minLength=^3^',
            'placeholderPrefix' =>'find.'
        ]}
        <div id="productList"></div>
        <p class="h-5 mt-3 mb-0">Добавить услугу</p>
        <form class="row py-3 jsProductRow border-gray-bottom jsAddForm">
            <div class="jsCommonFields">
                <input type="hidden" name="weight" value="1">
                <input type="hidden" name="order_id" value="{$.get.order_id}">
                <input type="hidden" name="total_cost" value="{$order['meta']['cost']}">
                <input type="hidden" name="action" value="editOrder">
            </div>
            <input type="hidden" name="product_id" value="130">
            <div class="col-lg-7 col-md-5 col-6 mb-md-0 mb-3 d-flex flex-column justify-content-center align-items-start">
                <label class="label-text par mb-0 w-100">
                    <input type="text" class="input pr-1" name="name" placeholder="{130 | resource: 'pagetitle'}" value="" required>
                </label>
            </div>
            <div class="col-lg-1 col-md-2 col-6 mb-md-0 mb-3 d-flex justify-content-center align-items-center">
                <label class="label-text par mb-0">
                    <input type="number" class="input pr-1" min="1" name="count" value="1">
                </label>
            </div>
            <div class="col-lg-2 col-md-3 col-6 d-flex justify-content-center align-items-center">
                <label class="label-text par mb-0">
                    <input type="text" class="input pr-1" name="price" placeholder="Цена" value="" required>
                </label>
            </div>
            <div class="col-lg-2 col-md-2 col-6 d-flex justify-content-center align-items-center">
                <button class="btn btn-orange btn-cart" type="submit">
                    <i class="fa fa-cart-plus"></i>
                </button>
            </div>
            <div class="col-12 order-5 mt-3">
                <label class="label-text par mb-0">
                    <textarea name="options[desc]" class="textarea w-100" rows="4" placeholder="Описание"></textarea>
                </label>
            </div>
        </form>
    {else}
     <ul class="pl-0">
    {foreach $order['products'] as $key => $product}
        {set $description = $product['product_id'] | resource: 'description'}
        {set $introtext = $product['product_id'] | resource: 'introtext'}
        {set $add_cost = $product['product_id'] | resource: 'add_cost'}
        <li class="row py-3 jsProductRow border-gray-bottom">
            <input type="hidden" name="id" value="{$id}">
            <div class="col-lg-7 col-md-5 col-6 d-flex flex-column justify-content-center align-items-start">
                <span class="par service-link mb-3">{$product['options']['name']?:$product['name']}</span>
                <small class="small">{$product['options']['desc']?:$description}</small>
                {if $add_cost}
                    {if $id == 45}
                    <small class="small text-red">*стоимость шаблона: {$add_cost} руб.</small>
                    {else}
                    <small class="small text-red">*стоимость дополнения: {$add_cost} руб.</small>
                    {/if}
                {/if}
            </div>
            <div class="col-lg-1 col-md-1 col-6 d-flex justify-content-center align-items-center">
                <span class="price text-orange h-6">{$product['count']} шт.</span>
            </div>
            <div class="col-lg-2 col-md-3 col-6 d-flex justify-content-center align-items-center">
                    <span class="text-orange h-6">{$product['price']} руб.</span>
            </div>
            <div class="col-lg-2 col-md-3 col-6 d-flex justify-content-center align-items-center">
                <span class="text-orange h-6">{$product['cost']} руб.</span>
            </div>
        </li>
    {/foreach}
    </ul>
    {/if}
{else}
<p class="h-4 text-center">Заказ с id = {$.get.order_id} не существует в системе</p>
{/if}
<div class="row">
        <div class="col-lg-3 offset-lg-3 col-sm-6 mt-3">
        <div class="btn-wrap">
            <a href="/" class="btn btn-no-bg w-100">На Главную</a>
        </div>
    </div>
    <div class="col-lg-3 col-sm-6 mt-3">
        <div class="btn-wrap">
            <a href="{9 | url}" class="btn btn-no-bg w-100">К Услугам</a>
        </div>
    </div>
</div>
Каждый товар выводится в форму редактирования, а под всеми товарами есть форма добавления нового и форма поиска
editOrderProduct.htm выглядит так
<form class="row py-3 jsProductRow border-gray-bottom jsEditForm" name="product-{$id}" id="product-{$id}">
    <input type="hidden" name="id" value="{$id}">
    <input type="hidden" name="weight" value="{$weight}">
    <input type="hidden" name="order_id" value="{$order_id}">
    <input type="hidden" name="total_cost" value="{$total_cost}">
    <input type="hidden" name="action" value="editOrder">
    <input type="hidden" name="price" value="{$price}">
    <input type="hidden" name="options[addcost]" value="{$add_cost | number: '0': '.': ''}">
    <input type="hidden" name="product_id" value="{$product_id}">
    <div class="col-lg-7 col-md-5 col-6 d-flex flex-column justify-content-center align-items-start">
        <span class="par service-link">{$index}. {$name}</span>
        {if $introtext}
        <small class="small">{$introtext}</small>
        {/if}
        {if $add_cost}
        {if $id == 45}
        <small class="small text-red">*стоимость шаблона: {$add_cost} руб.</small>
        {else}
        <small class="small text-red">*стоимость дополнения: {$add_cost} руб.</small>
        {/if}
        {/if}
    </div>
    <div class="col-lg-1 col-md-1 col-6 d-flex justify-content-center align-items-center">
        <label class="label-text par mb-0">
            <input type="number" class="input pr-1" min="0" name="count" value="{$count}">
        </label>
    </div>
    <div class="col-lg-2 col-md-3 col-6 d-flex justify-content-center align-items-center">
        <span class="text-orange h-6">{$price} руб.</span>
    </div>
    <div class="col-lg-2 col-md-3 col-6 d-flex justify-content-center align-items-center">
        <span class="text-orange h-6">{$cost} руб.</span>
    </div>
    <div class="col-12 order-5 mt-3">
        <label class="label-text par mb-0">
            <textarea name="options[desc]" class="textarea w-100" rows="4" placeholder="Описание">{$description}</textarea>
        </label>
    </div>
</form>
Как отправить запрос на сервер думаю разберётесь, в заметке про поиск это есть. Ну и собственно сам сниппет editOrder
<?php
if(!isset($_POST['order_id'])){
    $modx->log(1,'EditOrder: Не передан идентификатор заказа');
    return false;
}
//$modx->log(1, print_r($_POST,1));
$res = [];
$tpl = '@FILE chunks/shop/editOrderProduct.html';
$order = $modx->getObject('msOrder', $_POST['order_id']);
if(isset($_POST['id'])){
    $product = $modx->getObject('msOrderProduct', $_POST['id']);
    $productCost = $_POST['price'] * $_POST['count'] + $_POST['options']['addcost'];
    $totalWeight = $_POST['weight'] + $order->get('weight') - $product->get('weight');
    $totalCost = $order->get('cost') + $productCost - $product->get('cost')  - $_POST['options']['addcost'];
    if($_POST['count'] > 0){
        $product->set('count', $_POST['count']);
	    $product->set('cost', $_POST['price'] * $_POST['count']);
	    if($_POST['options']['desc']){
	        $options = $product->get('options');
	        $options['desc'] = $_POST['options']['desc'];
	        $product->set('options', $options);
	    }
	    $product->save();
    }else{
        $totalWeight = $_POST['weight'] - $product->get('weight');
        $totalCost = $order->get('cost') - $product->get('cost');
        $product->remove();
        
    }
}else{
    $product = $modx->newObject('msOrderProduct');
    $data = $_POST;
    $data['cost'] = $_POST['price'] * $_POST['count'] + $_POST['options']['addcost'];
    $totalWeight = $_POST['weight'] * $_POST['count'] + $order->get('weight');
    $totalCost = $order->get('cost') + $data['cost'];
    $product->fromArray($data);
    $product->save();
}
	    
$order->set('cost', $totalCost);
$order->set('cart_cost', $totalCost);
$order->set('weight', $totalWeight);
$order->set('updatedon', date('Y-m-d H:i:s'));
$order->save();

if($totalCost){
    $pdoTools = $modx->getService('pdoTools');
    $products = $order->getMany('Products');
    $i = 1;
    foreach($products as $product){
        $options = $product->get('options');
        $resource = $modx->getObject('modResource', $product->get('product_id'));
        $desc = $options['desc']?:$resource->get('description');
        $name = $options['name']?:$product->get('name');
          
        $productData = array(
                'description' => $desc,
                'introtexxt' => $resource->get('introtext'),
                'index' => $i,
                'add_cost' => $resource->get('add_cost'),
                'price' => $product->get('price'),
                'weight' => $product->get('weight'),
                'count' => $product->get('count'),
                'name' => $name,
                'cost' => $product->get('cost') + $resource->get('add_cost'),
                'id' => $product->get('id'),
                'options' => $options,
                'order_id' => $_POST['order_id'],
                'product_id' => $resource->get('id')
            );
        
        if(isset($tpl)){
            $res['orderProducts'] .= $pdoTools->getChunk($tpl, $productData);
        }else{
            $res['orderProducts'][] = $productData;
        }
        $i++;
    }
}
else{
    $res['orderProducts'] = '<p class="h-6 my-3 text-red">Необходимо добавить услуги!</p>';
}       
$res['total_cost'] = $totalCost;
$res['duration'] = ceil($totalCost / $modx->getOption('base_cost'));

return json_encode($res);
Если интересует добавление товаров, то вот сниппет addToOrder
<?php
	    $res = [];
	    $order = $modx->getObject('msOrder', $_POST['order_id']);
	    
	    $product = $modx->newObject('msOrderProduct');
	    $data = $_POST;
	    //$modx->log(1, print_r($_POST,1));
	    $data['cost'] = $_POST['price'] * $_POST['count'];
	    $totalWeight = $_POST['weight'] * $_POST['count'] + $order->get('weight');
	    $totalCost = $order->get('cost') + $data['cost'] + $data['options']['addcost'];
	    $product->fromArray($data);
	    $product->save();
	    
	    $order->set('cost', $totalCost);
	    $order->set('cart_cost', $totalCost);
	    $order->set('weight', $totalWeight);
	    $order->set('updatedon', date('Y-m-d H:i:s'));
	    $order->save();
	    
	    $pdoTools = $modx->getService('pdoTools');
	    $products = $order->getMany('Products');
	    $i = 1;
        foreach($products as $product){
            $options = $product->get('options');
            $resource = $modx->getObject('modResource', $_POST['product_id']);
            $res['orderProducts'] .= $pdoTools->getChunk('@FILE chunks/shop/editOrderProduct.html', array(
                    'description' => $options['desc']?:$resource->get('description'),
                    'introtexxt' => $resource->get('introtext'),
                    'index' => $i,
                    'add_cost' => $resource->get('add_cost'),
                    'price' => $product->get('price'),
                    'weight' => $product->get('weight'),
                    'count' => $product->get('count'),
                    'name' => $options['name']?:$product->get('name'),
                    'cost' => $product->get('cost'),
                    'id' => $product->get('id'),
                    'options' => $options,
                    'order_id' => $_POST['order_id'],
                    'total_cost' => $totalCost,
                    'product_id' => $resource->get('id')
                ));
                $i++;
        }
        $res['total_cost'] = $totalCost;
        $res['duration'] = ceil($totalCost / $modx->getOption('base_cost'));
        $res = json_encode($res);
        return $res;
Николай Савин
28 января 2021, 12:34
+2
Посмотрим что можно оптимизировать в этом моменте. Меня тоже подбешивает такая логика. @Иван Бочкарев Добавь наверное в план.
Alexey
28 января 2021, 12:13
0
Спасибо, как всегда — круто!

Подскажите, а момент с оформлением заказа на другого юзера по номеру телефона планируется пофиксить в будущем?

github.com/Ibochkarev/miniShop2/issues/440