Skip to content

persehoney/itmo-cs-t3-web-2022

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

21 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

itmo-cs-t3-web-2022

Homework solutions from Web Development course by Mike Mirzayanov at CS, ITMO university

Lections-2022

practice-2 (верстка)

Скачайте архив https://assets.codeforces.com/files/6e78d88da1176e86/2d/codeforces-layout.7z

  1. ✅ Ваша задача заменить соответствующий элемент в базовой верстки содержимим html-файла из 2-1-codeforces-layout-search и дописать в css-файл набор таких правил, чтобы результат выглядел в точности как изображение (скриншот) из 2-1-codeforces-layout-search. Вносить какие-либо другие изменения в html-документ нельзя. Для позиционирования .search используйте либо float: right либо position: absolute. Для самого input используйте свойство background, чтобы установить картинку внутри него. Конечно, вам понадобятся дополнительные базовые свойства для отступов, границ, размера шрифта и так далее.

  2. ✅ Ваша задача заменить соответствующий элемент в базовой верстки содержимим html-файла из 2-2-codeforces-layout-datatable и дописать в css-файл набор таких правил, чтобы результат выглядел в точности как изображение (скриншот) из 2-2-codeforces-layout-datatable. Вносить какие-либо другие изменения в html-документ нельзя. Для схлопывания бордюров между ячейками таблицы прочитайте о свойстве border-collapse. Для раскрашивания строк через одну используйте селектор с псевдо-классом nth-child(2n-1). Для выравнивания текста по центу используйте свойство text-align. Конечно, вам понадобятся дополнительные базовые свойства для отступов, границ, размера шрифта и так далее.

  3. ✅ Ваша задача заменить соответствующий элемент в базовой верстки содержимим html-файла из 2-3-codeforces-layout-blog и дописать в css-файл набор таких правил, чтобы результат выглядел в точности как изображение (скриншот) из 2-3-codeforces-layout-blog. Вносить какие-либо другие изменения в html-документ нельзя. Для отображения картинки для вложений используйте свойство background с указанием url для элемента списка. Для выравнивания текста и изображений можно использовать position: relative и/или line-height. Возможно, вам понадобится псевдо-класс :last-child для удаления отступа у последнего абзаца теста блога. Конечно, вам понадобятся дополнительные базовые свойства для отступов, границ, размера шрифта и так далее.

  4. ✅ Ваша задача заменить соответствующий элемент в базовой верстки содержимим html-файла из 2-4-codeforces-layout-login-form и дописать в css-файл набор таких правил, чтобы результат выглядел в точности как изображение (скриншот) из 2-4-codeforces-layout-login-form. Вносить какие-либо другие изменения в html-документ нельзя.

practice-3 (servlet API)

Скачайте архив https://assets.codeforces.com/files/943c97ce9320d0ea9/hw3.zip. Откройте содержимое как проект в IDEA, выбрав pom.xml при открытии проекта. (Использовать IDEA не обязательно, но крайне рекомендуется). Запустите результат в Tomcat по порту 8080. Убедитесь, что страница http://localhost:8080/index.html отображается.

  1. ✅ В настоящий момент, если делать правки в статике прям в IDEA, то по F5 ресурсы не обновляются. Модифицируйте StaticServlet таким образом, чтобы он сначала смотрел в нужную подпапку src вашего проекта, и если файл найден, то возвращал его. В getServletContext().getRealPath("/static" + uri) пусть сервлет смотрит во вторую очередь, если не получилось найти файл в соответствующей подпапке в src. Убедитесь что проходят все три теста из TestsA.

  2. ✅ Часто стараются сократить количество ресурсов, подгружаемых с HTML-страниц. Обратите внимание, что index.html пытается загрузить странный ресурс с путём css/r.css+css/g.css+css/b.css. Пока у него не получается это сделать. Ваша задача добавить в StaticServlet функциональность, чтобы можно было в рамках одного запроса загружать множество статических файлов. Файлы в пути будут соединены символом плюс. Определяйте MIME-тип ответа на основании первого из запрошенных файлов. В ответе вы должны просто конкатенировать запрошенные файлы. После правильной реализации на странице http://localhost:8080/index.html будут отображены три цветных блока. Убедитесь что проходят все тесты из TestsB.

  3. ❌ Ваша задача добиться работоспособности страницы http://localhost:8080/messages.html Для этой страницы написан фронтенд, всё что осталось реализовать — один сервлет для обработки запросов. Должны корректно обрабатываться следующие запросы (все запросы передаются методом POST, возвращают результат в JSON):

  • /message/auth: ожидается опциональный параметр user, если он задан, то сохранить в сессию имя текущего пользователя (то, что пришло в параметре user), в любом случае вернуть имя пользователя (нового, если был только что установлен) или пустую строку, если не авторизован;

  • /message/findAll: вернуть все сообщения в виде массива пар с ключами user и text (например, «[{"user":"mike","text":"test"},{"user":"lena","text":"hi"}]»). Сообщения надо возвращать в правильном порядке.

  • /message/add: ожидается параметр text, добавить сообщение от имени текущего пользователя (взять из сессии) с текстом text.

    Для вывода результата всюду используйте JSON. Не забудьте установить у ответа Content-Type в значение "application/json". Для простого форматирования объекта в JSON рекомендуется использовать библиотеку Gson. Для этого добавьте зависимость в pom.xml от артефакта groupId=com.google.code.gson, artifactId=gson, version=2.9.1 и используйте код типа такого:

String json = new Gson().toJson(objectToConvert);
response.getWriter().print(json);
response.getWriter().flush();
  1. ❌ Ваша задача написать фильтр CaptchaFilter, который будет перехватывать все GET-запросы, если в текущей сессии не отмечено, что пройдена каптча. В таком случае фильтр должен загадать случайное число от 100 до 999, записать это в сессию (ожидаемый ответ) и простейшую форму с картинкой и полем для ввода ответа. Картинку по тексту можно сгененировать с помощью кода, который приложен в проекте (ImageUtils.java). Пользователь отправляет форму, фильтр ловит ответ и если ответ совпал с ожидаемым, то помечает в сессии, что каптча пройдена и больше не перехватывает запросы. Иначе перезагадывает число и опять показывает форму. Таким образом, вы должны написать один фильтр CaptchaFilter и добавить его в web.xml для перехвата всех запросов.

practice-4

Cкачайте учебный проект по ссылке https://assets.codeforces.com/files/69565a5324cd/hw4.zip Откройте его в IDEA как maven-проект, запустите в локальном Tomcat, используя корневой контекст /.

Убедитесь в работоспособности. Должны отображаться страницы, похожие на Codeforces. На странице /index должен отображаться список пользователей. По клику можно перейти на страницу пользователя.

Прочитайте исходный код проекта.

  1. ✅ Улучшите страницу профиля пользователя /user?handle=?. Результат должен быть похож на такой:

4.1

Картинку стоит отображать всем одинаковую (можно взять с https://userpic.codeforces.com/no-title.jpg).

Стрелки должны функционировать и переводить на предыдущего по списку или следующего пользователя (если есть). Если такого нет - то стрелка должна стать серой и перестать быть ссылкой (как на скриншоте выше).

Сделайте, чтобы в эту страницу можно было альтернативно передавать и user_id, то есть чтобы работали ссылки вида /user?user_id=3 Ссылки на стрелочках надо оставлять в старом стиле (по handle). Поменяйте FreemarkerServlet#getData, чтобы если параметр заканчивается на _id и является корректным числом, то он бы складывался в data не как строка, а как число типа long. Это поможет и в других заданиях сократить код.

  1. ✅ Сделайте, чтобы подчеркивался текущий пункт в меню. Подумайте, что надо доложить в data, чтобы была возможность такое сделать. Минимизируйте дублирование кода в шаблонах вокруг menu items.

4.2

  1. ✅ Исправьте FreemarkerServlet, чтобы по заходу на страницу без пути (по-умолчанию) и на страницу / осуществлялся мягкий (временный) редирект на /index. Сделайте, чтобы по переходу по неожиданной ссылке отображалась 404-страница (и статус должен быть 404).

4.3

  1. ✅ Поддержите новый объект предметной области Post. У Post должно быть четыре поля id (long), title (String), text (String) и user_id (long). Создайте в системе по аналогии с User серию постов с разумными содержаниями (модифицируйте DataUtil). Используя вашу разметку из второго ДЗ отобразите на главной список всех постов в обратном порядке (от последнего к первому). Если длина text превышает 350 символов, то обрезайте его и используйте символ многоточия в конце (сокращайте длинные тексты). Страницу со списком пользователей перенесите в отдельную страницу /users. Измените её разметку так, чтобы использовать вёрстку таблицы из второго ДЗ для их отображения. Добавьте в меню пункт USERS.

  2. ✅ В сайдбаре в блоках Information в сайдбаре тоже отображайте тексты постов (тоже не более 350 символов). Фразу Information замените на “Post #?” (его id). По ссылке View all уводите на страницу /post?post_id=?, на которой должен быть уже один не сокращённый пост. Таким образом, посты у вас будут отображаться на двух страницах (/index и /post?post_id=?). Не допускайте copy-paste: они обе должны пользоваться одним макросом отображения одного поста. На странице с одним постом текст поста сокращать не надо (ваш макрос должен поддерживать как сокращенный способ отображения, так и полный). Добавьте в профиль пользователя количество его постов ссылкой на новую страницу /posts?user_id=?, по которой осуществляется переход на список всех постов пользователя. Она должна выглядеть совсем как главная, но фильтровать посты по заданному пользователю. Вам надо снова переиспользовать макрос для отображения постов.

  3. ✅ Добавьте пользователю свойство color (как цвет на Codeforces), которое должно быть enum с одним из значений: {RED, GREEN, BLUE}. Измените userlink, чтобы он отображал пользователей по окрашенному хэндлу (прям как на Codeforces). То есть уберите подчеркивание, поменяйте чуток шрифт, навесьте правильный цвет в зависимости от color. Старый режим тоже сохраните, сделав дополнительный параметр у userlink (назовите его nameOnly). Используйте старый режим для отображения текущего залогинённого пользователя в хедере. В остальных местах теперь отображайте пользователя в новом стиле. Напоминаем, что аутентификация на сайте поддерживается в игрушечном режиме через передачу параметра ?logged_user_id=.

practice-5

Cкачайте учебный проект по ссылке https://assets.codeforces.com/files/69565a5324cd/hw5.zip

Откройте его в IDEA как maven-проект, запустите в локальном Tomcat, используя корневой контекст /.

Убедитесь в работоспособности. Должны отображаться страницы, похожие на Codeforces. На странице http://localhost:8080/ должна отображаться простая приветственная страница.

Прочитайте исходный код проекта (95% этого кода было написано на лекции).

Задания

  1. ✅ Обратите внимание, что в настоящий момент для всех action-методов в страницах требуются два обязательных параметра HttpServletRequest request, Map<String, Object> view. В ряде случаев (часто) достаточно одного из них или они вообще не нужны (например, в HelpPage они на самом деле не нужны вообще, а в текущем IndexPage нужен только view). Измените исходный код FrontServlet так, чтобы в качестве action-метода подыскивался метод просто по названию (нет требования к точной сигнатуре как сейчас). При запуске надо смотретьnn на типы параметров метода (method.getParameterTypes()) и если параметр имеет тип Map.class, то ожидать что это view (передать), тоже самое сделать для HttpServletRequest. Таким образом, в action-методе может быть любой набор параметров типов HttpServletRequest и Map, они могут идти в любом порядке. После этого следует удалить из всех страниц из всех action-методов лишние параметры и убедиться в работоспособности.

  2. ✅ Обратите внимание, что по клику в изображения флагов в заголовке сайта, будет осуществлён переход на текущую страницу, но с доп. параметром lang=язык. В этом задании вам нужно поддержать простейший способ интернационализации страниц. Измените исходный код FrontServlet так, что:

  • при наличии параметра lang в запросе (то есть при указании языка просмотра), его следует запомнить в сессии - таким образом далее просмотр сайта предполагается на этом языке. Это надо делать лишь только, если lang в запросе это две строчные латинских буквы.
  • если в сессии установлен язык и он отличен от en, то при загрузке шаблона для страницы в первую очередь осуществляется попытка загрузить шаблон вида IndexPage_ru.ftlh (то есть вида НазваниеСтраницы_язык.ftlh). Если такой шаблон не существует, то должна быть загружен шаблон без указания языка.
  • обратите внимание, что проект уже содержит IndexPage_ru.ftlh, то есть после реализации решения этой задачи, на главной будет отображаться русская версия этой страницы.
  1. ❌ По адресу http://5d3p.wp.codeforces.com/ (пункт меню tic-tac-toe) расположена простая реализация веб-версии игры крестики-нолики. В данном вам проекте уже есть TicTacToePage.ftlh - верстка этой страницы в виде шаблона Freemarker. А вот файл TicTacToePage.java не содержит соответствующей реализации. Ваша задача дописать код в TicTacToePage.java так, чтобы поведение страницы было в точности такое же как по ссылке http://5d3p.wp.codeforces.com/ Изменять код верстки (файл TicTacToePage.ftlh) нельзя.

practice-6

Скачайте проект с https://assets.codeforces.com/files/69565a5324cd/hw6.zip

Перейдите по http://wp.codeforces.com/phpMyAdmin/ в свою базу данных (ваш логин начинается с латинской u и имеет вид u??, пароль - p??????, были отосланы вам на почту) и накликайте там таблицу User с полями:

  • id (BIGINT до 18 знаков, autoincrement, primary key, not null)
  • login (VARCHAR до 255 знаков, добавьте ключ уникальности unique_User_login, not null)
  • passwordSha (VARCHAR до 255 знаков, not null)
  • creationTime (DATETIME, индекс index_User_creationTime, not null)

Запустите проект (поправьте profile.properties, пересоберите с помощью mvn package), убедитесь, что всё работает - регистрация+вход+выход.

  1. ✅ На форму регистрации добавьте еще одно поле passwordConfirmation и дополнительно валидируйте, что они совпали. То есть после выполнения этого задания на форме регистрации будет три поля: login, password, passwordConfirmation. И появится доп. сообщение об ошибке.

  2. ✅ Добавьте в сущность User новое уникальное поле email. Это потребует изменение таблицы в базе данных, исходного кода репозитория и т.п. После этого добавьте поддержку поля email при регистрации. Следует проверять, что оно уникально, раньше не встречалось и выглядит как email (достаточно проверить, что переданная строка содержит ровно один символ @).

  3. ✅ Сделать, что входить в систему можно по логину или email (а не только по логину, что хочешь, то и вводишь). Не забудьте всюду переименовать поля/параметры из login в loginOrEmail.

  4. ✅ Добавьте в футер информацию об общем кол-ве зарегистрированных пользователей. Для этого сделайте методы findCount в UserRepository/UserService. Добавьте в macro для страницы (commons.ftl) использование переменной шаблона ${userCount}. После этого вам надо как-то во view во всех страницах всегда класть по ключу “userCount” значение userService.findCount(). Для этого сделайте общий базовый класс для всех страниц Page (то есть все страницы будут унаследованы от Page) и пару методов у него:

  • void before(HttpServletRequest request, Map<String, Object> view)

  • void after(HttpServletRequest request, Map<String, Object> view)

    В потомках (всех страницах) можно будет переопределять эти методы (не забывайте вызывать super.before()/super.after()).

    Добавьте в код FrontServlet поиск и запуск before/after-методов до и после запуска action-метода соответственно.

    После этого у базового класса Page в before (или after) следует добавить помещение во view нужного значения userCount и теперь всюду в футере будет нужная информация.

    Перенесите в Page#before из FrontServlet установку аутентифицированного пользователя user. Еще перенесите в Page#before установку message из IndexPage - после этого message можно устанавливать в любую страницу: достаточно положить его в сессию и сделать редирект. Сделайте в page метод setMessage, который будет добавлять в сессию сообщение (не надо будет каждый раз руками писать request.getSession()...). Аналогично, сделайте в Page пару методов setUser/getUser, которые устанавливают в сессию аутентифицированного пользователя и возвращают его из сессии. Обратите внимание, что вам понадобится для этого request, но его вы можете сохранить в поле в Page во время Page#before. Можно в Page добавить пустой метод c названием action, чтобы не писать в каждой странице пустой action (если нужен именно такой).

  1. ✅ Поддержать новую сущность Event - события от пользователя с полями id, userId, type, creationTime. Поле userId надо сделать внешним ключом на User: ALTER TABLE Event ADD CONSTRAINT fk_Event_userId FOREIGN KEY (userId) REFERENCES User (id). Поле type должно быть enum с пока двумя значениями ENTER, LOGOUT. Вставлять записи в таблицу Event на каждый удачный вход/выход. Для этой сущности нужен и класс Event в пакете domain и свой репозиторий EventRepository (там будет лишь один метод save).

  2. ❌ Сделать сущность Talk (id, sourceUserId, targetUserId, text, creationTime) - сообщение от одного пользователя другому. Сделать страницу /talks (только для аутентифицированных, если пользователь не аутентифицирован - отсылайте на IndexPage с соответствующим сообщением). На TalksPage должна быть простая форма с 2 полями "Send Message" и список всех сообщений, где заданный пользователь автор или адресат в порядке от более поздних к более новым. Таким образом, на сайте появится система внутренней переписки. Переписку можно уложить в типичную datatable (колонки: id, от кого, кому, текст, когда), а вот форма должна быть с полем типа select (выпадающий список всех зареганных пользователей) и большим полем типа textarea для сообщения. Форма должна быть сверху, под ней - сообщения в табличке. Не переживайте, если для отображения списка сообщений на каждое сообщение вам понадобиться делать SQL-запрос для поиска отправителя/получателя (просто делайте UserRepository#find(id) и норм). Это учебное задание, в реальной системе за счёт кэширования или более подробных абстракций такой бы проблемы не было.

  3. ❌ Обратите внимание, что сейчас в классах XxxRepositoryImpl очень много похожего кода. Проведите рефакторинг (сами придумайте какой), чтобы уменьшить размер кода, переиспользовав его. Возможно, вам понадобится создавать дополнительные удобные методы в DatabaseUtils или сделайте базовый клас для всех XxxRepositoryImpl назвав его BasicRepositoryImpl и выносить туда общий код.

practice-7

Прочтите:

  1. https://webref.ru/dev/jqfundamentals/javascript-basics - справа в сайдбаре есть меню по разделам
  2. https://jquery.com/ - официальный сайт
  3. https://learn.javascript.ru/ - Дополнительный мастхэв по современному js
  4. https://www.w3schools.com/jquery/default.asp – ещё один хороший сайт

Задания

  1. (это задание показывать преподавателю не надо). Скачайте проект с https://assets.codeforces.com/files/69565a5324cd/hw7.zip. Запустите проект (поправьте profile.properties, пересоберите с помощью mvn package), убедитесь, что всё работает - регистрация+вход+выход. Возмоно, понадобится небольшая адаптация так как вы уже выполнили предыдущее задание и ваша база данных чуток другая. Ознакомьтесь с исходным кодом проекта, в частности обратите внимание на аннотацию @Json и то, как она обрабатывается во FrontServlet. Это вам может помочь (а может и не помочь).

  2. ✅ Переделайте форму входа в систему на использование AJAX.

  3. ✅ Обратите внимание, что использование $.ajax довольно многословно. Сделайте в файле app.js свою функцию ajax (допускается обертка над jquery-методами), которая лучше адаптирована к нашему проекту. Добавьте в неё удобные значения по-умолчанию, автоматическое следование (location.href=...) при использовании redirect (то есть теперь в RegisterPage и EnterPage не надо будет проверять “if (response.redirect) …”). Измените код страниц, чтобы везде пользоваться новой функцией. Убедитесь, то стало меньше кода и он стал чище.

  4. ✅ Создайте сущность Article (статья/пост) с полями id, userId, title, text, creationTime (помним про внешний ключ и прочие нужные индексы) и соответствующие ей ArticleRepository, ArticleRepositoryImpl, ArticleService. По ссылке /article добавьте форму создания статьи (два поля: title типа input и text типа textarea, кнопка Create), которая будет работать посредством AJAX. Добавьте ссылку на создание статьи в меню, если пользователь авторизован.

  5. ✅ На главной странице (IndexPage) добавьте вывод всех статей в обратном хронологическом порядке. Используйте AJAX для асинхронной подгрузке статей (используйте элемент template для задания шаблона статьи). Если вы справились с заданием из 2-го дз про разметку статьи, то используйте разметку/css из того задания.

  6. ❌ Добавьте в Article поле/колонку hidden. Отображайте на главной только нескрытые статьи. Сделайте страницу /myArticles с таблицей своих статей (только id, title и колонка с кнопкой Hide/Show). Пусть таблица загружается без AJAX, просто выводится в шаблоне. Третий столбец должен содержать либо кнопку Hide, либо кнопку Show. При нажатии на кнопку должен уходить AJAX-запрос на изменение поля hidden и при успешном выполнении операции текст на кнопке и ее действие должно актуализироваться. То есть сама страница должна работать без перезагрузок. Не забудьте проверить в бэкенде, что запрос пришел от автора статьи.

  7. ❌ Добавьте пользователю булевское свойство/колонку admin (по умолчанию false). Если страницу /users просматривает админ, то добавьте в таблицу колонку Admin. В этой колонке должен отображаться текущее значение admin пользователя и ссылка либо enable (то есть включить админа, для текущего false), либо disable (то есть выключить админа, для текущего true). По нажатию на такую ссылку в бэкенд должен уходить AJAX-запрос с id пользователя, менять значение admin у этого пользователя, а в обработчике на успех надо перерисовать false<->true и enable<->disable. Иными словами управление добавить/удалить из админов должно происходить без перезагрузки страницы. Не забудьте проверить в бэкенде, что запрос пришел от админа.

practice-8

Скачайте проект с https://assets.codeforces.com/files/69565a5324cd/hw8.zip

Запустите проект (поправьте profile.properties). Используйте базу данных вида uXX. Запуск создаст таблицу user. Добавьте к ней колонку passwordSha, которая по-умолчанию NULL. Убедитесь, что всё работает - регистрация+вход+выход, просмотр пользователей.

  1. ✅ Сделайте небольшую страницу с профилем пользователя по ссылке /user/{id}. Для этого используйте параметр в методе с аннотацией @PathVariable (погуглите, это просто). Просто отобразите id, login и creation на отдельной странице (или надпись “No such user”, если такого нет). Обратите внимание, что сейчас на странице со списком всех пользователей не отображается логотип и иконки языков. Исправьте это.

  2. ✅ Добавьте сущность Notice с тремя полями id, content (используйте аннотацию @Lob), creationTime. Обратите внимание, что Notice не имеет связи с User (пока всё делаем без связей). Добавьте NoticeRepository, NoticeService. В классе Page аналогично с getUser сделайте getNotices (не забудьте аннотацию @ModelAttribute), чтобы все потомки Page добавляли в модель переменную notices. Измените commons.ftlh, чтобы в сайдбаре вместо блока “Pay Attention” была серия подобных блоков, которые отображают все notices. Добавьте несколько notices через базу, убедитесь, что на всех страницах теперь отображаются ваши notices в сайдбаре.

  3. ✅ Добавьте форму добавления Notice. Это должна быть просто одна textarea с кнопкой “Add”. Не забывайте про валидацию.

  4. ✅ Добавьте пользователям колонку/поле disabled, по умолчанию равно false. На страницу /users добавьте колонку с действиями. Там в каждой строчке будет ровно одна кнопка (Disable или Enable в зависимости от текущего статуса). При нажатии кнопки отправляется маленькая форма, которая устанавливает новый статус пользователя. Обратите внимание, что семантика обработки этой формы должна быть “установить заданный статус”, а не “сменить статус на противоположный”. После этого страница перегружается и там уже кнопка для обновленного статуса. Пока не используйте javascript, просто сделайте такие небольшие формы в каждой строке. Добавьте в форму входа сообщение “User is disabled” при попытке входа заблокированного пользователя.

practice-9 (mappings)

Скачайте проект с https://assets.codeforces.com/files/69565a5324cd/hw9.zip

Запустите проект (поправьте profile.properties). Используйте базу данных вида uXX. Запуск создаст таблицу user и другие. Добавьте к user колонку passwordSha, которая по-умолчанию NULL. Убедитесь, что всё работает - регистрация+вход+выход, просмотр пользователей. Создайте нескольких пользователей, дайте им разные права (просто руками добавьте записи в user_role). Полезный справочный ресурс https://en.wikibooks.org/wiki/Java_Persistence/Relationships

  1. ✅ Добавьте сущность простейшую сущность Comment с четырьмя полями id, text (используйте аннотацию @Lob), user, post. Добавьте и List comments в Post. Настройте двунаправленный мэппинг many-to-one и one-to-many для отношения комментарий-пост и однонаправленный мэппинг many-to-one для отношения комментарий-пользователь (то есть коммент знает своего пользователя, а в пользователе комментарии не хранятся). Сделайте простейшую страницу с отображением одного Post и списка его комментариев под ним (по урлу /post/{id}). Перед списком комментариев для залогинённого пользователя добавьте форму добавления нового комментария (просто одна textarea и кнопка). Пусть клик по заголовку одного Post теперь ведёт на страницу индивидуального Post (например, на главной будут все посты с ссылками в заголовках).

  2. ✅ Добавьте сущность Tag (тег). У него есть только id и name. Теги должны находиться с Post в отношении многие-ко-многим. Сделайте однонаправленный мэппинг многие-ко-многим, то есть поле Post#tags. Надо делать по образу и подобию как связаны пользователи и роли. Добавьте руками несколько тегов (записи в таблицу tag) и несколько тегов к posts (записи в таблицу post_tag). Отображайте список тегов при отобраожении поста.

  3. ✅ Добавьте поле Tags в форму создания поста. Считайте, что туда надо ввести список тегов через пробельные символы (whitespaces). Выбрасывайте ошибку валидации, если ввели тег (после разбивания на слова), что не является простым словом из латинских букв. При сохранении нового Post надо сохранить его вместе с тегами (возможно, в таблице tag появятся новые записи, возможно будут использованы старые).

practice-10 (vue.js)

  1. Установите nodejs (отсюда https://nodejs.org/en/, рекомендуется последний LTS 18.12.1). Соглашайтесь на добавление в PATH.
  2. Установите 'npm install -g @vue/cli'. В консоли будет довольно много всего выкачано, настроено.
  3. Сделайте где-либо 'vue create test' (выбрать Vue 2). В консоли будет довольно много всего выкачано, настроено.
  4. Убедитесь, что у вас стоит IDEA с поддержкой Vue.js (смотреть список установленных плагинов) или установите WebStorm.

Скачайте проект с https://assets.codeforces.com/files/69565a5324cd/hw10.zip

Сделайте ‘npm install’ в директории проекта, чтобы выкачать все модули. Создайте конфигурацию запуска (IDEA: Run/Debug Configuration -> Add new configuration -> npm). Command: run, Script: serve.

Запустите приложение. Убедитесь в работоспособности приложения: можно зайти (пароль - любой непустой), выйти, создать пост, изменить текст существующего.

Проверьте работоспособность – аутентификация (по логину из data.js, пароль не проверяется), создание и редактирование постов.

  1. ✅ Для аутентифицированных пользователей выводите в Header не только имя, но и логин. Добавьте в футер вывод статистики: количество зарегистрированных пользователей и количество постов. Обратите внимание, что для этого не нужно передавать в футер сами посты и пользователей, достаточно только их количества.

  2. ✅ Добавьте возможность регистрации. Для этого изучите как устроено добавление поста. Вам надо реализовать аналогичную функциональность - добавить пользователя. В форме регистрации нужно указать login и name. Провалидируйте login (длина от 3 до 16, только строчные латинские буквы, логин уникален). Провалидируйте имя (длина от 1 до 32). После регистрации должно редиректить на страницу со входом. Форма регистрации должна визуально быть очень похожа на форму входа.

  3. ✅ Сделайте страницу со списком пользователей. Страница должна быть доступна и не аутентифицированным пользователям (анонимам). Расположите там просто типичную таблицу (наш datatable) с колонками id, login, name.

  4. ✅ Добавьте на главную (Index) вывод всех постов (по убыванию id). Выводите посты в типичном виде (как article, используйте разметку из предыдущих заданий). Выводите правильное количество комментариев.

  5. ❌ Сделайте отдельную страницу поста. Сделайте туда переход по клику на View all в сайдбаре или по заголовку поста на главной. Выведите на этой странице сам пост и комментарии к нему. Не допускайте копи-пейста при отображении одного поста с пунктом 4.

  6. ❌ На странице поста из предыдущего задания сделайте возможность написания комментариев.

practice-11 (rest)

Скачайте проект с https://assets.codeforces.com/files/69565a5324cd/hw11.zip

Сделайте ‘npm install’ в директории frontend, чтобы выкачать все модули. Запуск приложения frontend надо осуществлять так же, как и в предыдущем домашнем задании.

В директории backend настройте базу данных в backend/profile.properties. Примените скрипт data.sql для добавления данных в БД (у обоих пользователей пароль 12345). Запустите backend, убедитесь в работоспособности приложения: можно зайти, выйти, отображаются посты в сайдбаре.

  1. ✅ Сделайте страницу со списком всех пользователей в системе. Для этого реализуйте endpoint (в бэкенде) GET /api/1/users. Можно воспользоваться кодом из предыдущего ДЗ для реализации на стороне frontend.

  2. ✅ Отобразить на главной (Index) в основной части все посты (желательно переиспользовать код предыдущего дз). Выводите посты в типичном виде (как article, используйте разметку из предыдущих заданий).

  3. ❌ Перенесите во frontend форму регистрации из предыдущего задания и сделайте, чтобы она работала через REST. Надо добавить endpoint: POST /api/1/users. Допустимо, чтобы ошибка валидации от бэкенда прилетала в одно место формы (а не по полям), то есть как и при аутентификации. После успешной регистрации надо автоматически аутентифицировать и перекидывать на Index.

  4. ❌ Поддержите через REST форму создания поста (endpoint: POST /api/1/posts). После успешного создания поста инициируйте перезагрузку (обновление) поля данных posts в App. Это приведет к тому, что новый пост появится в сайдбаре и на главной.

  5. ❌ Добавьте в базу данных и модель поддержку комментариев. Реализуйте отдельную страницу для поста (прям как в предыдущем дз, можете переиспользовать код), она должна отображать один пост и его комментарии (с автором). Переходить на эту страницу надо по ссылке View All в сайдбаре на соответствующем посте и по клику в заголовок поста с Index. В постах на главной поддержать вывод правильного количества комментариев.

About

Web Development course at CS, ITMO university

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published