TicketForm - количество загружаемых файлов

У меня несколько разделов на тикетах.
В разных формах нужно определить разное количество загружаемых изображений к тикетам, в одних 5 штук, в других 3 например.
И таких разделов немало, то есть нужно решение универсальное и настраиваемое для каждой из форм, а не ограничивать для всех форм на сайте.

Как реализовать такой вот лимит для прикрепляемых пользователем изображений через TicketForm?
Куда копать?
Василий Столейков
12 октября 2015, 09:52
modx.pro
4
2 297
+1
Поблагодарить автора Отправить деньги

Комментарии: 31

Василий Столейков
12 октября 2015, 17:37
0
Неужели нельзя сделать такое ограничение на количество файлов?
    Сергей Шлоков
    13 октября 2015, 06:50
    0
    Как вариант через плагин на onBeforeDocFormSave.
      Василий Столейков
      13 октября 2015, 10:26
      0
      Да нет, тут похоже нужно Javascript задействовать для контроля, ведь загрузчик-то Plupload
      Вот пытаюсь вклинится в его работу, но не хочется трогать файл компонента
      assets/components/tickets/js/web/files.js
      Вот и сижу, ломаю себе голову… ))
        Сергей Шлоков
        13 октября 2015, 10:48
        +1
        Тогда могу предложить такой вариант — создай свой js и подключай его в шаблоне для тикета. А в js просто повесь событие на загрузку. Типа такого
        $(document).on('click', '#ticket-files-select', function(e) {
        	if ($('div.ticket-file-image-wrapper').length == 3) {
        		alert('Больше трех картинок низя!');
        		return false;
        	}
        });
        Не тестировал, но идея должна быть понятна.
        П.С. Это для стандартных шаблонов Tickets.
          Василий Столейков
          13 октября 2015, 11:09
          0
          Работает, но тут проблема в мультизагрузке. Мультизагрузкой загрузить можно хоть 100 фоток и отправить…
          www.plupload.com/docs/Options — грызу гранит доков… Думаю как вклиниться в вызов.
            Сергей Шлоков
            13 октября 2015, 11:13
            0
            Отключи мультизагрузку через multi_selection в files.js.
            multi_selection: false,
      Сергей
      13 октября 2015, 11:55
      +1
      У меня получилогсь сделать. Допиливал files.js. Могу кинуть подробно все шаги, мультизагрузка тоже учтена и она работает. ) Но, чувствую, не самый оптимальный способ(т.к. опыт небольшой), но рабочий.
        Василий Столейков
        13 октября 2015, 12:04
        0
        О! Давай!!!
        Я вот тоже мучаю этот файл, впихиваю в FilesAdded проверки.

        А ещё пытаюсь инициализировать отдельно в моих скриптах и перезаписать вызов из files.js, но тоже не получается, ругается что

        Uncaught ReferenceError: Tickets is not defined

        Мучаю этот кусок кода:
        var max = 3; // max number of files
         
        Tickets.Uploader.bind('FilesAdded', function(up, files) {
            if (files.length > max)
                 alert('You are allowed to add only ' + max + ' files.');
         
            uploader.splice(); // reset the queue to zero
        }
        Сергей
        13 октября 2015, 12:12
        0
        Создал дополнительное поле [[*max-photo]]. Прикрепил к ресурсу, на котором будет вызов формы. Форму создал отдельную, на вскйи случай photo.tpl.Tickets.form.create:
        <form class="well create" method="post" action="" id="ticketForm">
        	<div id="ticket-preview-placeholder"></div>
        
        	<input type="hidden" name="tid" value="0" />
        
        	<div class="form-group">
        		<label for="ticket-sections">Выберете альбом</label>
        		<select name="parent" class="form-control" id="ticket-sections">[[+sections]]</select>
        		<span class="error"></span>
        	</div>
        
        	<div class="form-group">
        		<label for="ticket-pagetitle">[[%ticket_pagetitle]]</label>
        		<input type="text" class="form-control" placeholder="[[%ticket_pagetitle]]" name="pagetitle" value="" maxlength="50" id="ticket-pagetitle"/>
        		<span class="error"></span>
        	</div>
        	
            <div class="form-group">
        		<textarea class="form-control" placeholder="[[%ticket_content]]" name="content" id="ticket-editor" rows="10"></textarea>
        		<span class="error"></span>
        	</div>
        
        	<div class="ticket-form-files">
        		[[+files]]
        	</div>
        
        	<div class="form-actions row">
        		<div class="col-md-6">
        			<input type="button" class="btn btn-default preview" value="[[%ticket_preview]]" title="Ctrl + Enter" />
        		</div>
        		<div class="col-md-6 move-right">
        			<!--<input type="button" class="btn btn-primary publish" name="publish" value="[[%ticket_publish]]" title="" />  -->
        			<div id="ajax_hide_limit"><input type="submit" class="btn btn-danger draft" name="draft" value="Отправить на модерацию" title="Ctrl + Shift + Enter" /></div>
        		</div>
        	</div>
        </form>
        
        
           <strong>Количество загруженных фотографий:</strong><div style="display:inline-block;" id="ajax_test_value">[[!temp-count-photo? &id=`[[*id]]` &userId=`[[!+modx.user.id]]`]]</div> из <div style="display:inline-block;" id="ajax_max_value">[[*max-photo]]</div>
        
        <div id="ajax_test_block" ></div>

        Далее…
          Сергей
          13 октября 2015, 12:13
          0
          Вот мой код files.js:
            Сергей
            13 октября 2015, 12:17
            0
            Блеать! тикеткс обновил что-ли… ща, пороюсь
              Василий Столейков
              13 октября 2015, 12:22
              0
              Вот-вот и я о том же… Тикетс обновится и всё полетит. Нужно или

              1. делать копии файлов в случае обновления и следить за их заменой после каждого обновления,
              2. или как-то поймать и переинициализировать Plupload с подсчётом максимального количества.

              Плюс второго варианта в том, что для разных форм можно будет указывать разное количество максимальных файлов.
              Как найдёшь код своего files.js скинь его тоже!
                Сергей
                13 октября 2015, 12:23
                0
                Ок, я ща порпобую сделать откат до субботы, скопирую, и возвращусь)
                Надеюсь, он не пропал)))
                Ну мой как раз тоже и предусматриает это через [[*max-photo]] .)
                  Василий Столейков
                  13 октября 2015, 12:25
                  0
                  А, да. У тебя там ещё есть сниппет [[!temp-count-photo]]
                    Сергей
                    13 октября 2015, 12:27
                    0
                    Да, там просто такая ситуация. Если авторизваонный чувак, закидывает фоты и уходит со страницы, не отправляя… но потом возвращается на страницу с формой. Все загруженные фоты ранее остаются… и если не учитваеть это(алерт тут уже не поможет), то вся история напрасна. Я скрываю кнопку в таком случае «отправить». В ближайшее время постараюсь восстановить.
            Сергей
            13 октября 2015, 12:45
            0
            var form = $('#comment-form');
            if (!form.length) {
            	form = $('#ticketForm');
            }
            
            Tickets.Uploader = new plupload.Uploader({
            	runtimes: 'html5,flash,silverlight,html4',
            
            	browse_button: 'ticket-files-select',
            	//upload_button: document.getElementById('ticket-files-upload'),
            	container: 'ticket-files-container',
            	filelist: 'ticket-files-list',
            	progress: 'ticket-files-progress',
            	progress_bar: 'ticket-files-progress-bar',
            	progress_count: 'ticket-files-progress-count',
            	progress_percent: 'ticket-files-progress-percent',
            	form: form,
            
            	multipart_params: {
            		action: $('#' + this.container).data('action') || 'ticket/file/upload',
            		tid: this.form.find('[name="tid"]').val(),
            		form_key: this.form.find('[name="form_key"]').val(),
            		ctx: TicketsConfig.ctx || 'web'
            	},
            	drop_element: 'ticket-files-list',
            
            	url: TicketsConfig.actionUrl,
            
            	filters: {
            		max_file_size: TicketsConfig.source.size,
            		mime_types: [{
            			title: 'Files',
            			extensions: TicketsConfig.source.extensions
            		}]
            	},
            
            	resize: {
            		width: TicketsConfig.source.width,
            		height: TicketsConfig.source.height
            	},
            
            	flash_swf_url: TicketsConfig.jsUrl + 'web/lib/plupload/js/Moxie.swf',
            	silverlight_xap_url: TicketsConfig.jsUrl + 'web/lib/plupload/js/Moxie.xap',
            
            	init: {
            		Init: function(up) {
            			if (this.runtime == 'html5') {
            				var element = $(this.settings.drop_element);
            				element.addClass('droppable');
            				element.on('dragover', function() {
            					if (!element.hasClass('dragover')) {
            						element.addClass('dragover');
            					}
            				});
            				element.on('dragleave drop', function() {
            					element.removeClass('dragover');
            				});
            			}
            		},
            
            		PostInit: function(up) {},
            
            		FilesAdded: function(up, files) {
            			this.settings.form.find('[type="submit"]').attr('disabled',true);
            			up.start();
            		},
            
            		UploadProgress: function(up, file) {
            			$(up.settings.browse_button).hide();
            			$('#' + up.settings.progress).show();
            			$('#' + up.settings.progress_count).text((up.total.uploaded + 1) + ' / ' + up.files.length);
            			$('#' + up.settings.progress_percent).text(up.total.percent + '%');
            			$('#' + up.settings.progress_bar).css('width', up.total.percent + '%');
            		},
            
            		FileUploaded: function(up, file, response) {
            			response = $.parseJSON(response.response);
            			if (response.success) {
            				// Successfull action
            			/*Моя фича*/
            			var maxPhoto=$("#ajax_max_value").html() 
            			maxPhoto = parseInt(maxPhoto); 
                        var count=$("#ajax_test_value").html()
                        count = parseInt(count);
            			var type="test";
            				$.ajax({
            				 data: {type:type},    
                                type: "POST",
                                url: "/аякс-загрузка-фоток.html",
                                success: function ( data ) {
                                    count++;
                                   $("#ajax_test_value").html(count);
                                   if(count>=maxPhoto){
                                     $("#ticket-files-container").hide();
                                     $("#max-response").show();
                                   }
                                   if(count>maxPhoto){
                                     $("#ajax_hide_limit").hide();
                                     
                                   }
                                   else{
                                     $("#ajax_hide_limit").show();
                                     
                                   }  
                                   /* $("#ajax_test_block").html(count);*/
                                     /*$("#ticket-files-select").hide();*/
                 
                }
             });
                        /*конец моей фичи*/
            				var files = $('#' + up.settings.filelist);
            				var clearfix = files.find('.clearfix');
            				if (clearfix.length != 0) {
            					$(response.data).insertBefore(clearfix);
            				}
            				else {
            					files.append(response.data);
            				}
            
            			}
            			else {
            				Tickets.Message.error(response.message);
            			}
            		},
            
            		UploadComplete: function(up, file, response) {
            			$(up.settings.browse_button).show();
            			$('#' + up.settings.progress).hide();
            			up.total.reset();
            			up.splice();
            			this.settings.form.find('[type="submit"]').attr('disabled',false);
            		},
            
            		Error: function(up, err) {
            			Tickets.Message.error(err.message);
            		}
            	}
            });
            
            Tickets.Uploader.init();
            $(document).on('click', '.ticket-file-delete', function(e) {
                	
            	var deleted = 'deleted';
            	var $this = $(this);
            	var $form = $this.parents('form');
            	var $parent = $this.parents('.ticket-file');
            	var id = $parent.data('id');
            	var form_key = $form.find('[name="form_key"]').val();
            
            	$.post(TicketsConfig.actionUrl, {action: 'ticket/file/delete', id: id, form_key: form_key}, function(response) {
            	    /*Моя фича*/
            			var maxPhoto=$("#ajax_max_value").html() 
            			maxPhoto = parseInt(maxPhoto);
                        var count=$("#ajax_test_value").html()
                        count = parseInt(count);
            			var type="test";
            				$.ajax({
            				 data: {type:type},    
                                type: "POST",
                                url: "/аякс-загрузка-фоток.html",
                                success: function ( data ) {
                                    count--;
                                   $("#ajax_test_value").html(count);
                                   if(count>=maxPhoto){
                                     $("#ticket-files-container").hide();
                                     $("#max-response").show();
                                   }
                                   else {$("#ticket-files-container").show();
                                         $("#max-response").hide();
                                   }
                                   if(count>maxPhoto){
                                     $("#ajax_hide_limit").hide();
                                     
                                   }
                                   else{
                                     $("#ajax_hide_limit").show();
                                     
                                   }  
                                   /* $("#ajax_test_block").html(count);*/
                                     /*$("#ticket-files-select").hide();*/
                 
                }
             });
                        /*конец моей фичи*/
            		if (response.success) {
            			if ($parent.hasClass(deleted)) {
            				$parent.removeClass(deleted)
            			}
            			else {
            				$parent.addClass(deleted)
            			}
            		}
            		else {
            			Tickets.Message.error(response.message);
            		}
            	}, 'json');
            	return false;
            });
            
            $(document).on('click', '.ticket-file-restore', function(e) {
                	
            	var deleted = 'deleted';
            	var $this = $(this);
            	var $form = $this.parents('form');
            	var $parent = $this.parents('.ticket-file');
            	var id = $parent.data('id');
            	var form_key = $form.find('[name="form_key"]').val();
            
            	$.post(TicketsConfig.actionUrl, {action: 'ticket/file/delete', id: id, form_key: form_key}, function(response) {
            	    /*Моя фича*/
            			var maxPhoto=$("#ajax_max_value").html() 
            			maxPhoto = parseInt(maxPhoto); 
                        var count=$("#ajax_test_value").html()
                        count = parseInt(count);
            			var type="test";
            				$.ajax({
            				 data: {type:type},    
                                type: "POST",
                                url: "/аякс-загрузка-фоток.html",
                                success: function ( data ) {
                                    count++;
                                   $("#ajax_test_value").html(count);
                                   if(count>=maxPhoto){
                                    $("#ticket-files-container").hide();
                                     $("#max-response").show();
                                   }
                                   else {$("#ticket-files-container").show();
                                         $("#max-response").hide();
                                   }
                                   if(count>maxPhoto){
                                     $("#ajax_hide_limit").hide();
                                     
                                   }
                                   else{
                                     $("#ajax_hide_limit").show();
                                     
                                   }   
                                   /* $("#ajax_test_block").html(count);*/
                                     /*$("#ticket-files-select").hide();*/
                 
                }
             });
                        /*конец моей фичи*/
            		if (response.success) {
            			if ($parent.hasClass(deleted)) {
            				$parent.removeClass(deleted)
            			}
            			else {
            				$parent.addClass(deleted)
            			}
            		}
            		else {
            			Tickets.Message.error(response.message);
            		}
            	}, 'json');
            	return false;
            });
            
            $(document).on('click', '.ticket-file-insert', function(e) {
            	var $this = $(this);
            	var $parent = $this.parents('.ticket-file');
            	var $text = $('[name="content"]');
            	var template = $parent.find('.ticket-file-template').html();
            	template = template.replace(/^\n/g, '').replace(/\t{2}/g, '').replace(/\t$/g, '');
            
            	$text.focus();
            	$.markItUp({replaceWith: template});
            	return false;
            });
            Это files.js Ща другое распишу…
            Тут учтены в том числе варианты с восстановлением фоток и их удалением в форме.
              Сергей
              13 октября 2015, 12:49
              0
              $(document).ready(function() {
                  var maxPhoto=$("#ajax_max_value").html() 
              			maxPhoto = parseInt(maxPhoto); 
                          var count=$("#ajax_test_value").html()
                          count = parseInt(count);
                          if(count>maxPhoto){
                                       $("#ajax_hide_limit").hide();
                                       
                                     }
                          if(count<=maxPhoto){
                                       $("#ajax_hide_limit").show();
                                       
                                     }           
                
                  })
              Это подключаемый скрипт к странице с формой.
                Сергей
                13 октября 2015, 12:50
                0
                Это
                temp-count-photo:
                <?php
                $userId;
                $modx->getObject('TicketFile');
                return $count = $modx->getCount('TicketFile', array('parent'=>0, 'createdby'=>$userId));
                  Сергей
                  13 октября 2015, 12:58
                  0
                  Сейчас, еще кое-что никак не вспомню…
                    Сергей
                    13 октября 2015, 13:01
                    0
                    Во! Это tpl.Tickets.form.files:
                    <div id="ticket-files-list">
                    	[[+files]]
                    	<div class="clearfix"></div>
                    </div>
                    
                    <div id="ticket-files-container" data-action="ticket/file/upload">
                    	<a id="ticket-files-select" href="javascript:;">[[%ticket_file_select]]</a>
                    	
                    	<div id="ticket-files-progress">
                    		<span id="ticket-files-progress-count">0/0</span>
                    		<span id="ticket-files-progress-percent">0%</span>
                    		<div id="ticket-files-progress-bar"></div>
                    	</div>
                    </div>
                    <span style="display:none;" id="max-response"><strong>Лимит исчерпан</strong></span>
                      Сергей
                      13 октября 2015, 13:01
                      0
                      Вроде все) Учти все id в формах при подключении.
                        Василий Столейков
                        13 октября 2015, 13:05
                        0
                        Спасибо! Сейчас буду разбираться и прикручивать по-тихоньку…
                          Сергей
                          13 октября 2015, 13:06
                          0
                          Пожалуйста. Теперь хоть сам отсюда смогу восстановить, если вдруг чего опять)))
                        Сергей
                        13 октября 2015, 13:05
                        0
                        Получается следующая система. Можно закидывать и мультиаплодно, тогда при превышении укзаанного лимита, скрывается кнопка «отправить». Учитывается ссылки к каждой добавленной фоте «восстановить» и «удалить». И при уходе со страницы и возвращении на нее, количество загруженных фоток ранее учитывается и форма показывает превышение лимита, убирая кнопку «отправить».
                          Сергей
                          13 октября 2015, 13:33
                          0
                          Вот это я уже не помню правда
                          $.ajax({
                          				 data: {type:type},    
                                              type: "POST",
                                              url: "/аякс-загрузка-фоток.html",
                          в files.js для чего посылал, скорее всего там у меня был првоерчный сниппет, который показывал, прокатывал POST или нет у меня на странице. Соотв-но можно без него обойтись.
                            mngatoff
                            06 августа 2017, 01:52
                            3
                            +1
                            а я влез в тикетовый процессор web/upload/file, и в методе process() дописал после проверки на дубли:
                            // Check for files limit
                                    if ($filesLimit = $this->modx->getOption('tickets.max_files_upload')) {
                                    	$checkLimit = $this->modx->newQuery($this->classKey, array('class' => $this->class));
                            	        if (!empty($this->ticket->id)) {
                            	            $checkLimit->andCondition(array('parent:IN' => array(0, $this->ticket->id)));
                            	        } else {
                            	            $checkLimit->andCondition(array('parent' => 0));
                            	        }
                                    	$checkLimit->andCondition(array('createdby' => $this->modx->user->id));
                                    	if ($this->modx->getCount($this->classKey, $checkLimit) >= $filesLimit) {
                                    		@unlink($data['tmp_name']);
                            
                                        	return $this->failure('Вы не можете загрузить больше '.$filesLimit.' файлов');
                                    	}
                                    }
                            и джаваскрипт можно не трогать, и надежнее.
                            Хочется попросить Василия что-то подобное таки включить в релиз, полезная штука.
                            Михаил
                            27 февраля 2018, 15:30
                            0
                            А ни кто не знает как вывести на фронтенде количество загруженных файлов к тикету?
                            Для доски объявлений нужно…
                              Михаил
                              28 марта 2018, 23:07
                              +1
                              оказалось всё просто)
                              <?php
                              $parentId;
                              $modx->getObject('TicketFile');
                              return $count = $modx->getCount('TicketFile', array('parent'=>$parentId));
                              И вывести сниппет так: [[название-сниппета? &parentId=`[[+id]]`]]
                              Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.
                              31