Формулировка проблемы: Необходимо реализовать возможность перещения файлов и папок внутри дерева файлов проекта.
Связанные задачи: 0147.
Используется: Проекты -> Детали проекта.
Необходимо добавить возможность выбора нескольких файлов или папок в деталях проекта, для выбора которых используются зажатая кнопка "Ctrl" и кнопка "Shift" (реализованные также, как в хранилище). При выборе нескольких файлов или папок в контекстном меню отобразить только пункты меню, применимые к группе файлов и папок. Таковыми являются пункты "Перместить" и "Удалить" для файлов и папок, а также пункт "Скачать", если выделены только файлы.
Пункты меню "Переместить" и "Удалить" должны быть не активны, в случае, если у пользователя нет прав записи и в случае, если пользователь захватил в мультивыбор виртуальные папки.
При выборе только нескольких файлов (и только их) необходимо также оставить пункт меню "Скачать", реализованный также, как в хранилище. Т.е. группу файлов необходимо сохранять в архиве (функция также доступна при наличии прав чтения).
Пункт меню "Удалить" для выбранных объектов должен работать также, как в хранилище а именно: необходимо выводить пользователю диалоговое окно с сообщением:
Удалить выбранные объекты (%количество_удаляемых_объектов)?
с кнопками:
"ОК" - выполнить удаление всех выделенных объектов;
"Отмена" - вернуть пользователя в детали проекта, оставить выделение на выбранных объектах.
Решение: необходимо добавить к контекстному меню физической папки и файла в дереве файлов проекта пункт "Переместить". Расположить этот пункт и у файлов, и у папок перед пунктом "Удалить".
Пункт меню не должен отображаться у виртуальных папок. У физических папок и файлов при нажатии на пункт меню необходимо проверять наличие прав записи.
В случае отсутствия у пользователя прав на запись мероприятия, в котором находятся перемещаемые объекты необходимо делать недоступным пункт меню "Переместить".
Для владельца
проекта необходимо добавить пункт
меню для содержимого папки "Корзина".
При нажатии на пункт меню "Переместить" открыть диалоговое окно "Выбор папки" с деревом файлов проекта, кнопкой "Готово", иконкой "Домой" и иконокой "+". Размер диалогового окна фиксирован и реализован также, как и для перемещения файлов в хранилище. Если список папок не умещается в окно необходимо отображать вертикальный скролл. Если название папки не умещается в окно необходимо обрезать название и выводить его с помощью тултипа при наведении на обрезанное название.
Замечание
Описанное поведение будет реализовано после пересмотра существующих пункта меню "Удалить" и кнопки "Создать" в деталях проекта, т.к. эти функции всегда доступны для использования в корневой папке на данный момент.
Необходимо добавить возможность перемещения из корневой папки проекта в случае наличия только прав на чтение проекта, в связи с указанным выше замечанием.
Определим Корневой элемент
. Назовем виртуальную
папку Корневым элементом
, если:
У пользователя есть право чтения данного элемента.
Данный элемент является прямым предком мероприятия, для которого у пользователя есть право записи.
Выше в иерархии нет элемента, для которого у пользователя есть право записи.
Примечание
Корневым элементом может являться папка проекта, в случае отсутствия мероприятия, удовлетворяющего выше указанным требованиям.
Примечание
В случае нахождения пользователя в корневом элементе директории необходимо делать неактивными кнопку "Создать новую папку" и кнопку "Готово" диалогового окна "Выберите папку назначения".
Примечание
Корневой элемент
- это по сути максимальный элемент, содержащий доступную для пользователя структуру файлов и папок.
Правила отображения дерева файлов проекта:
Иконки папок должны соотвествовать иконкам, отображаемых в деталях проекта. У виртуальных папок - синие иконки, у физических - желтые, у корзины - иконка корзины.
Отображать папку "Корзина" только для владельца проекта.
При наличии у пользователя прав на запись проекта в дереве файлов диалогового окна отобразить все папки проекта, включая виртуальные. Для перемещения будет доступна любая папка проекта (виртуальная или физическая).
При наличии у пользователя прав только на чтение проекта в
дереве файлов диалогового окна необходимо найти
корневой элемент
и отобразить мероприятия,
находящиеся на самом высоком уровне иерархии, для которых у
пользователя есть права на запись.
При наличии у пользователя прав на запись мероприятия в дереве файлов данного проекта отобразить полностью файловую структуру соответствующей виртуальной папки, исключая все виртуальные подпапки, для которых у пользователя нет прав записи.
При наличии у пользователя прав на запись мероприятия отобразить соответствующую текущую виртуальную папку, используя следующие правила:
При наличии у пользователя прав на запись мероприятия, стоящего выше в иерархии, отобразить текущую виртуальную папку в подпапке этого мероприятия (вкладывать текущее мероприятие в ближайшего предка). Соответственно, при наличии вложенных друг в друга мероприятий, для которых у пользователя есть права на запись, отобразить всю соответствующую структуру папок, удовлетворяя сформулированное требование.
При отсутствии у пользователя прав на запись мероприятия, стоящего выше в иерархии, отобразить только структуру папок текущего мероприятия.
При наличии у пользователя прав на запись мероприятия, стоящего ниже в иерархии, отобразить это мероприятие, как виртуальную подпапку текущего мероприятия (вкладывать в текущее мероприятие ближайшее дочернее мероприятие).
Не отображать файлы внутри папок в дереве файлов диалогового окна.
Не отображать перемещаемую папку (и все папки, захваченные в мультивыбор при перемещении) в дереве файлов диалогового окна.
Правила сортировки папок:
Отображать сперва виртуальные подпапки текущей открытой папки, отсортированные по структурному номеру (также, как в деталях проекта).
Отображать во вторую очередь физические подпапки текущей открытой папки, отсортированные по возрастанию названия папки.
Отображать папку "Корзина" в последнюю очередь (только для владельца проекта и только в папке проекта).
Пример:
Пусть имеется проект и у пользователя есть права только на чтение проекта. Пусть проект имеет следующую структуру:
Мероприятие_1 - чтение;
Мероприятие_1.1 - чтение;
Мероприятие_1.1.1 - запись;
Мероприятие_2 - чтение;
Мероприятие_2.1 - запись;
Тогда необходимо отобразить диалоговое окно выбора папки назначения со следующей структурой:
Корневой элемент
- иконка "Дом",
чтение;
Мероприятие_1.1.1 - запись;
Мероприятие_2.1 - запись;
Также добавить в диалоговое окно "Выберите папку назначения" иконку "+". При нажатии на данную иконку открывать диалоговое окно "Введите имя папки" с полем ввода названия и кнопкой "Готово".
Запретить пользователю вводить пустое название. Подсвечивать поле ввода красным в случае пустого названия. Если пользователь нажмет на кнопку "Готово" с пустым названием вывести ошибку:
Пустое название папки
.
Вернуть пользователя в диалоговое окно для ввода названия.
В случае совпадения введенного названия с названием другой папки текущей директории при нажатии на кнопку "Готово" необходимо вывести предупреждение
Папка не создана
* Элемент с таким названием уже существует.
и вновь перенаправить пользователя на написание названия папки. При этом старое название, не прошедшее валидацию, необходимо выделить.
Не нужно сравнивать название новой папки с названиями виртуальных папок, лежащих в текущей директории. Т.е. оставить пользователю возможность создать папку с названием, повторяющим название виртуальной папки.
При успешном создании папки открыть эту папку в диалоговом окне "Выберите папку назначения" и добавить ее в дерево файлов проекта в диалоговом окне (и в деталях проекта соответственно).
При открытии диалогового окна "Выбор папки"
по умолчанию
необходимо:
Если пользователь является владельцем проекта отобразить файловую структуру, начиная с папки проекта. Привязать иконку "Дом" к папке проекта. Отобразить папку "Корзина".
Если пользователь не является владельцем проекта, но имеет права на запись проекта отобразить файловую структуру, начиная с папки проекта. Привязать иконку "Дом" к папке проекта. Не отображать папку "Корзина".
Во всех остальных случаях необходимо найти
корневой элемент
и отобразить файловую
структуру начиная с папки корневого элемента. Привязать иконку
"Дом" к папке корневого элемента.
Место назначения перемещения определяется из текущей
открытой
папки в дереве файлов проекта
диалогового окна "Выберите папку назначения". Для
владельца в качестве места назначения доступна папка
"Корзина".
В случае, если место назначения перемещения совпадет с местом, откуда перемещаются объекты, необходимо выводить ошибку:
Выбранная директория совпадает с текущей.
и оставить пользователя в диалоговом окне "Выбор папки".
Процесс перемещения и валидация
Будем считать, что перемещается группа папок и файлов. Создадим очередь перемещения, в которой разместим перемещаемые папки и файлы в следующем порядке:
Разместим в первую очередь папки по возрастанию имен.
Разместим во вторую очередь файлы по возрастанию имен.
Необходимо последовательно перемещать папки и файлы из очереди перемещения в папку назначения. Для каждой отдельной операции перемещения проводить валидацию на совпадение имен.
В случае нахождения совпадающей по имени папки или файла необходимо для каждой отдельной операции перемещения выводить диалоговые окна "Не удалось переместить папку" и "Не удалось переместить файл" соответственно.
В случае закрытия диалогового окна "Выбор папки" необходимо сохранить прежнее расположени файла и папки.
В случае нажатия кнопки "Готово" начать процесс перемещения, описанный выше.
Диалоговое окно "Не удалось переместить папку"
Диалоговое окно "Не удалось переместить папку" должно содержать следующие элементы:
Надпись "Папка с таким именем уже существует в данной директории";
Редактируемое текстовое поле, в котором должно быть уже введено название текущей перемещаемой папки. В случае изменения текстового поля (ввода другого имени), необходимо переводить флаг "Применить ко всем" и кнопки "Заменить" и "Объединить" в неактивное состояние;
Флаг "Применить ко всем". При отмеченном флаге переводить кнопку "Переименовать" в неактивное состояние.
Кнопка "Переименовать". При нажатии на кнопку необходимо присвоить текущей папке имя, введенное в редактируемое текстовое поле, а затем вновь попытаться переместить папку.
Кнопка "Объединить". При нажатии на кнопку необходимо перенести файлы и папки из текущей папки в папку, вызвавшую конфликт. При этом необходимо удалить текущую папку в случае успешного объединения. Рекурсивно проводить валидацию для подпапок и файлов текущей папки до полного исчерпывания конфликта. Если для какого-либо внутреннего конфликта были выбраны варианты "Пропустить" или "Отмена", то необходимо оставить текущую папку со всей структурой папок, позволяющих достичь пропущенных или отмененных файлов и папок, в ходе разрешения конфликта.
Кнопка "Пропустить". При нажатии на кнопку не перемещать папку в место назначения. Перейти к следующему элементу из очереди перемещения.
Кнопка "Заменить". При нажатии на кнопку необходимо заменить папку, вызвывшую конфликт на текущую папку.
Кнопка "Отмена". При нажатии на кнопку прерывать процесс перемещения. При этом все отдельные операции, выполненные до возникновения конфликта, должны быть реализованы. Остальные папки и файлы (включая текущую) из очереди перемещения должны остаться в своей искомой директории. Вернуть пользователя в исходную рабочую область проектов (закрыть диалоговое окно "Выбор папки").
Диалоговое окно "Не удалось переместить файл"
Диалоговое окно "Не удалось переместить файл" должно содержать следующие элементы:
Надпись "Файл с таким именем уже существует в данной директории";
Редактируемое текстовое поле, в котором должно быть уже введено название текущего перемещаемого файла. В случае изменения текстового поля (ввода другого имени), необходимо переводить флаг "Применить ко всем" и кнопку "Заменить" в неактивное состояние. Редактироваться должно только фактическое название файла (не редактировать расширение файла);
Флаг "Применить ко всем". При отмеченном флаге переводить кнопку "Переименовать" в неактивное состояние.
Кнопка "Переименовать". При нажатии на кнопку необходимо присвоить текущему файлу имя, введенное в редактируемое текстовое поле, а затем вновь попытаться переместить файл.
Кнопка "Пропустить". При нажатии на кнопку не перемещать файл в место назначения. Перейти к следующему элементу из очереди перемещения.
Кнопка "Заменить". При нажатии на кнопку необходимо заменить файл, вызвывший конфликт на текущий файл.
Кнопка "Отмена". При нажатии на кнопку прерывать процесс перемещения. При этом все отдельные операции, выполненные до возникновения конфликта, должны быть реализованы. Остальные папки и файлы (включая текущий) из очереди перемещения должны остаться в своей искомой директории. Вернуть пользователя в исходную рабочую область проектов (закрыть диалоговое окно "Выбор папки").
После определения действия из диалогового окна "Не удалось переместить папку" или "Не удалось переместить файл"необходимо продолжить процесс перемещения группы папок и файлов, перейдя к следующему объекту перемещения в очереди. В случае если флаг "Применить ко всем" был отмечен на каком-либо конфликте, необходимо применять выбранную операцию для всех оставшихся элементов из очереди перемещения.
Примеры использования
Требования: Проект_1 со следующей структурой:
Мероприятие_1
Мероприятие_1.1
Мероприятие_2
Мероприятие_2.1
Мероприятие_2.1.1
И со следующей структурой папок:
Мероприятие_1 (виртуальная папка, чтение)
Файл_0
Папка_0
Мероприятие_1.1 (виртуальная папка, запись)
Папка_1
Файл_1
Мероприятие_2(виртуальная папка, запись)
Папка_2
Мероприятие_2.1 (виртуальная папка, чтение)
Файл_2
Мероприятие_2.1.1 (виртуальная папка, запись)
Папка_1
Папка_3
Наличие у Сотрудника_1 прав на "Проект_1" - чтение. Права на мероприятия указаны выше в скобках у каждого мероприятия.
Авторизоваться с логином и паролем Сотрудника_1 в модуле "Проекты".
Открыть "Проект_1" и нажать на кнопку "Детали" - отобразятся папки "Мероприятие_1" и "Мероприятие_2".
Выделить Папку_3 из Мероприятия_2.1.1 и перенести ее в Мероприятие_2 - папка будет перемещена.
Выделить Папку_1 из Мероприятия_2.1.1 и перенести ее в папку Мероприятие_1.1 с заменой - папка будет перемещена, заменив при этом Папку_1 из Мероприятия_1.1.
Выделить Файл_1 из Мероприятия_1.1 и перенести ее в новую созданную в открывшемся диалоговом окне Новую_папку_1 в Мероприятии_2.