Диплом: Создание современной системы управления с использованием последних трендов геймификации

Внимание! Если размещение файла нарушает Ваши авторские права, то обязательно сообщите нам
52
взаимодействие между участниками команды, поэтому необходимо в
обеспечить возможность проверки корректности работы системы при
совершаемых в отношении друг друга действий пользователей.
Для этого создан компонент LoginComponent, в представлении
которого добавлена форма с полями для заполнения пользователем. Для
уменьшения возможных сложностей и отторжения разработчиков от
использования новой системы нужно сделать этот процесс максимально
простым. Всё, что требуется для регистрации или авторизации – ввод email
и пароля. Всю остальную информацию пользователь, при необходимости,
сможет сам внести впоследствии в своём личном кабинете.
Особенностью компонента является идентичность работы формы как
для регистрации, так и для авторизации. Их отличает друг от друга только
заголовок и надписи на кнопках. Чтобы сменить тип действия,
пользователь может использовать серую кнопку, на которой в случае
процесса регистрации или авторизации написано «уже есть аккаунт» или
«Ещё не зарегистрированы?» соответственно. При нажатии на кнопку не
происходит смена одной формы на другую, меняется только свойство
состояния – type, которое может иметь значение ‘login’ или ‘registration’.
Рис 3.5 Переключение авторизации/регистрации
53
У основной кнопки действия значение зависит от свойства type и
может меняться с «Зарегистрироваться» на «Войти». При нажатии на неё
происходит вызов метода типа action, который выполняет запрос на
сервер. При этом название метода идентично свойству type: если оно равно
login’, то происходит вызов метода login, иначе – registration (рис. 3.5).
Таким образом мы избегаем проверок значения и дублирования кода. Всё
делается через this.$store.dispatch(this.type, this.user).then(() => …).
Помимо этого, мы сразу указываем пришедший токен во внутренних
настройках нашего экземпляра класса axios, который мы встроили в
приложение. Для этого мы укажем свойство, которое будет отправляться
на сервер каждый раз, когда мы будем делать на него запрос:
headers.common['authorization'] = `bearer ${response.data.token}`.
В случае действия ‘registrationмы будем совершать практически те
же действия, за исключением одного, о котором речь пойдёт позже:
получение уведомлений, так как у вновь созданного пользователя не могло
произойти ничего нового в силу отсутствия его аккаунта в системе.
Процесс регистрации и авторизации – это один из тех случаев, когда
мы будем запускать переход на другой роут с помощью программных
действий. Только дождавшись положительного ответа от сервера, мы
направляем пользователя на основной участок его работы с системой:
доску Kanban в случае, если пользователь авторизовался, или личный
кабинет – в случае, если пользователь зарегистрировался.
3.3.3. Формирование команды
Следующим шагом в работе с системой является формирование
команды, которая будет заниматься разработкой программного
обеспечения. Для этого мы должны создать функционал, который будет
предоставлять двусторонние возможности, для удобства пользователей.
54
Во-первых, пользователь, зарегистрировавшись в системе, может сам
отправить запрос на присоединение к команде, которая ему известна. Во-
вторых, руководитель команды может найти пользователя в системе и
отправить запрос на присоединение его к своей команде.
Разработка этого участка начинается с создания компонента
TeamsComponent, который, в зависимости от участия пользователя в
командах, представляет собой либо список этих команд, либо инструкцию
по возможностям присоединения к командам. Помимо этого, в
представлении имеются три кнопки: создания новой команды и поиска
пользователей для менеджеров проектов, и поиска существующих команд,
для прочих участников процесса разработки.
В случае поиска, команд или пользователей, наш функционал схож с
принципом работы в LoginComponent: здесь мы также меняем searchType,
в зависимости от значения которого отправляем запрос на сервер либо по
поиску пользователей (‘users’), либо команд (‘teams’). Представление поля
для ввода и кнопка «Искать» при этом совершенно идентичны. Чтобы
найти нужные сущности, пользователь должен получить информацию о
них через свои источники, никак не связанные с работой нашей системы.
Любым удобным способом либо менеджер может прислать разработчику
название команды, к которой нужно присоединиться пользователю, либо
сам разработчик отправляет менеджеру свой email, чтобы тот нашёл и
присоединил его к команде. При запросе поиска мы отправляем на сервер
GET-запрос с параметрами searchType и name. Получив в ответ от сервера
массив (состоящий, чаще всего, из одного элемента) пользователь может
отправить запрос на присоединение.
Так, если searchType равен ‘users’, то название кнопки действия
будет «Присоединить пользователя к команде», а если ‘teams’, то
«Присоединиться к команде». И в том, и в другом случае на сервер
55
отправляется POST-запрос, который добавляет новое уведомление либо
для разработчика, либо для менеджера команды соответственно. Схема
поиска команд и разработчиков и отправка запросов на добавление в
команду представлена в приложении 2.
Совершение такого действия приводит либо к немедленному
получению пользователем уведомления о соответствующем запросе и
сохранению этого уведомления в БД для последующей отдачи
пользователю, когда он войдёт в систему на случай, если он в данный
момент неактивен. При получении такого уведомления клиентская часть
отправляет на сервер ещё один PATCH-запрос, в котором не передаются
никакие параметры, и вызов которого на сервере означает только одно:
уведомление получено пользователем и его статус необходимо сменить на
неактивный: его можно будет посмотреть в истории уведомлений, но
сигнала о его получении пользователь больше не будет получать при входе
в систему.
Создание команды также является крайне простым действием, как и
в случае с регистрацией, но здесь нужно ввести только одно название, по
которому потом можно будет найти эту команду и работать с ней.
Нажимая кнопку «создать команду», отправляется POST-запрос на сервер,
который создаёт новый экземпляр класса Team в базе данных, при этом
создавший её пользователь автоматически становится первым участником
этой команды, и после получения успешного ответа от сервера мы с
помощью мутации Vuex изменяем состояние списка команд пользователя,
происходит перерендеринг представления, и в списке команд пользователя
отображается ещё одна, новая, команда.
У каждого элемента списка команд есть отдельное меню, в котором
имеются кнопки на активацию, редактирование и удаление команды. При
активации команды мы совершаем вызов мутации, которая обновляет
56
состояние активной команды пользователя, с которой он в дальнейшем
может взаимодействовать. Название и, если имеется, логотип команды
отображаются в верхнем левом углу приложения, и, например, в случае
отправления запроса на добавление в команду, в числе параметров
отправляется id этой команды. После создания новой команды она
автоматически становится активной. Чтобы подчеркнуть её активность, в
списке она дополнительно будет подсвечена.
Редактирование команды открывает её личный кабинет, где можно
указать некоторые подробности и добавить логотип, а также ознакомиться
со статистикой работы участников команды, сравнить их успехи и увидеть
все бейджи достижений и лидерства. Все прочие действия, связанные с
работой команды, как-то: добавление новых проектов, запуск спринтов –
совершаются в отдельных функциональных компонентах. Удаление
команды происходит через отправку DELETE-запроса на сервер и, так же,
обновление мутабельного списка команд в списке через удаление
соответствующего элемента из представленного массива.
3.3.4. Управление уведомлениями
В предыдущих подглавах мы уже несколько раз упоминали о работе
с уведомлениями, и теперь нужно подробнее остановиться на реализации
этого функционала, так как по мере развития нашего приложения этот тип
событий будет приобретать всё большее значение. Для понимания
принципа работы с уведомлениями необходимо получить четкое
представление о том, что такое websockets, и как они работают.
Протокол WebSocket (стандарт RFC 6455) создан для разрешения
задач разных типов и позволяет снять ограничения по обмену данными
между сервером и клиентом. Этот протокол позволяет отправлять любые
данные, на любой адрес, при этом совершенно безопасно и практически
без лишнего трафика. Начало поддержки этой технологии в 2009 году
57
буквально сдвинуло парадигму HTTP: созданный как синхронный
протокол, который построен по чёткой модели «запрос — ответ», стал
полностью асинхронным и, более того, симметричным.
Для того, чтобы открыть соединение, достаточно создать новый
объект WebSocket и указать специальный протокол ws. После этого мы
уже можем подписаться на определённые коллбэки этого объекта, их
четыре: onopen, onclose, onmessage и onerror, которые вызываются при
открытии, закрытии, получении сообщения или ошибке соответственно.
Рис. 3.6 Схема работы websockets на проекте
Для разработки системы уведомлений ключевым коллбэком для нас
будет onmessage, так как именно его получение будет вызывать функцию,
открывающую модальное окно или меняющее состояние компонента
уведомлений. Эта функция начинает свою работу сразу после начала
работы пользователя с системой, так как после авторизации вызывается
action, который и подписывает клиент на слушание поступающих с сервера
сообщений.
58
Наиболее зависимым от этого события компонентом является
NotificationComponent, который является дочерним по отношению к
компоненту основного меню приложения – MenuComponent. После
получения сигнала мы производим мутацию массива уведомлений, и, если
в этом массиве оказываются непрочитанные, добавляем в представление
красный значок с указанием их числа.
Основным блоком компонента уведомлений является контейнер,
содержащий их список. Его видимость определяется результатом проверки
встроенного Vue-атрибута ‘v-if="Х"’, где Х – это булевое свойство
shownList’, которое меняет своё значение на противоположное путём
нажатия пользователем кнопки действия.
Сразу после открытия списка уведомлений на сервер отправляется
PATCH-запрос с массивом id всех ранее непрочитанных уведомлений, с
тем чтобы их свойство read было обновлено на сервере.
3.3.4. Создание и декомпозиция историй
Необходимым функционалом для работы по методологии Agile
является возможность создания пользовательских историй, которые
составляют основу Scrum’а и каждого спринта.
Для этого в основном меню мы добавляем кнопку-ссылку на роут
создания пользовательских историй. На этом экране пользователь видит
список историй, немедленно запрашиваемых на сервере. Автоматизм этого
действия достигается использованием функции так называемого
жизненного цикла каждого компонента Vue: created’, который является
колбэком инициализации компонента. Помимо этого колбека существует
ещё ряд схожих с ним по принципу, вызываемых в разные циклы
существования компонента.
59
Для каждой истории в списке, по аналогии со списком команд,
доступны кнопки-иконки «редактировать» и «удалить». Помимо списка
пользовательских историй, относящихся к активному проекту, на экране
пользователю доступна отдельная кнопка «Создать историю», нажимая
которую, пользователь вызывает метод “createNewStory”, которая
запускает всплывающее окно, содержание которого представлено
компонентом EditStoryComponent. Название компонента обусловлено тем,
что в случае вызова пользователем редактирования истории также будет
запущено всплывающее окно.
Разница заключается только в том, что в случае запуска
редактирования клиент отправляет на сервер GET-запрос с подробностями
соответствующей истории, и вся информация по ней через процесс
мутации заполняется в поля формы редактирования. В случае же создания
новой истории все поля остаются пустыми. Поля формы следующие:
1. Title, тип string – название истории;
2. Description, тип string – подробное описание истории;
3. Complexity, тип number – оценённая сложность истории;
4. Tasks, массив, тип Task – названия относящихся к истории задач.
Поле Tasks формы является представлением массива объектов,
каждый их которых, каждое из которых добавляет в историю новый
экземпляр класс Task, ограниченный при создании только названием и
сложностью. Однако по условиям работы базы данных, каждая задача не
может существовать отдельно, и должна быть обязательно привязана к
какой-то истории. В связи с этим возникает сложность, как нам сохранять
задачи, если при создании истории она ещё не существует в базе данных.
Эту проблему мы решаем с помощью представленного в ES6
функционала обещаний, или Promises, который позволяет дожидаться
60
ответа от сервера и только после этого продолжать выполнение
определённых участков кода.
В нашем случае мы создаем новое обещание перед сохранением
истории на сервер, и после получение успешного ответа создаём ещё одно
обещание, и снова посылаем POST-запрос, теперь уже для сохранения
массива задач, относящихся к только что созданной истории. И уже после
получения успеха о сохранении задач сообщаем пользователю, что
история успешно сохранена.
Рис. 3.7 Схема работы Promises при сохранении новой истории с задачами
В случае, если пользователь работает с уже существующей историей
(что проверяется наличием у объекта свойства id), то при сохранении мы
пропускаем этап обещания для сохранения истории, так как мы можем
сохранять задачи немедленно, присваивая их свойству storyId в базе
данных id редактируемой задачи. Если пользователь внёс изменения в
сложность, название или описание истории, то процесс сохранения
массива задач и истории происходит параллельно и независимо друг от
друга.
61
Дальнейшая декомпозиция, или разбиение истории на подзадачи,
происходит через редактирование каждой созданной задачи. В форме
редактирования истории у списка задач так же, как и везде, у каждого
элемента есть кнопки-иконки на редактирование и удаление. Под списком
задач есть строка с полями ввода названия и сложности, и кнопка
сохранить, при нажатии на которую создаётся новая задача – своего рода
функционал для быстрого создания новой задачи. а также отдельная
кнопка на создание новой подзадачи, которая, как и нажатие кнопки-
иконки редактирование переводит открытое модальное окно на подробное
редактирование или создание отдельной задачи, представленное
компонентом editTaskComponent. Общий вид формы задачи представлен
следующими полями:
1. Title, тип string – название задачи;
2. Complexity, тип number – сложность задачи в стори-поинтах;
3. Description, тип string – описание задачи;
4. AssignedTo, тип User – ответственный за выполнение задачи;
5. CreatedBy (неизменяемое), тип User – создатель задачи;
6. CreatedAt (неизменяемое), тип Date – время создания задачи;
7. storyId, тип number id истории, к которой относится задача;
8. status, тип string – статус задачи для доски канбан;
9. type, тип string – тип задачи (задача, баг, импрув).
После внесения изменений в необходимые поля и нажатия
пользователем кнопки «Сохранить», создается новое обещание и на сервер
отправляется PUT-запрос, который обновляет соответствующую задачу в
базе данных, и после успешного ответа с сервера обещание исполняется, и

Смотрите также:

"Автоматизация обработки заявок ООО "Проектно-Строительная Компания"
"Автоматизация процесса аттестации персонала для ООО "Нэт Бай Нэт Холдинг"
"Анализ интернет-активности конкурентов ( на примере конкурентов "Газпром нефть")
"Бухгалтерский учёт и аудит расчётов с подотчётними лицами в организации на примере ООО "ЛОЦ 10""
«Психологическое сопровождение персонала в организации на примере ООО «Крокус»
Cовершенствование деловой оценки персонала в организации (на примере ООО "Даймонд кейтеринг развитие")
PR как средство продвижения организации (на примере ПАО "Тамбовский завод "Комсомолец им. Н.С. Артемова")
PR-коммуникации в сфере общественного питания (на примере кафе-кондитерской «Cream Cheese»)
SMM как средство повышения эффективности работы учреждений социокультурной сферы (на примере Малого театра)
Value-based education: ценности в системе образования и способы их реализации на уроке английского языка. Опыт Европейских стран