= Финална имплементација на случаи на употреба = На следната табела се прикажани финалните кориснички сценарија: || '''ID''' || '''Use Case Scenario''' || '''Actor''' || || 14 || Најава преку OAuth2 (Google, Microsoft, GitHub) || Корисник || || 15 || Поставување на предлог теми за проект || Ментор || || 16 || Доделување теми на студент || Ментор || || 17 || Контакт со ментор (променет) || Студент || И дополнително се имплементирани E-mail нотификации, поврзани со inbox на самиот сајт. ---- = Корисник = == Најава преку OAuth2 == Кога прв пат ќе ја отвори страната, корисникот е редиректиран кон страната за најава. Долу, има дополнителни три копчиња за најава со Google, Microsoft и GitHub. [[Image(најава.png)]] Да го земеме како пример Google. Корисникот ја одбира опцијата за најава со Google и е редиректиран кон најавата поставена од Google: [[Image(најава2.png)]] Откако ќе го одбере својот Google профил и успешно помине најавата, тогаш корисникот може да продолжи со регистрација. Тука се пополуваат полињата како име, презиме и мејл: [[Image(најава3.png)]] Сега што останува е корисникот да пополни биографија, предмети, интереси, доколку е студент тогаш индекс, година, семестар, итн. Но тие се опционални, и регистрацијата преку Google е завршена. Сега, секогаш кога корисникот сака да се најави на Најди Ментор, може преку својот Google профил. {{{ var googleId = System.Configuration.ConfigurationManager.AppSettings["GoogleClientId"]; var googleSecret = System.Configuration.ConfigurationManager.AppSettings["GoogleClientSecret"]; if (!string.IsNullOrWhiteSpace(googleId) && !string.IsNullOrWhiteSpace(googleSecret)) { app.UseGoogleAuthentication(new GoogleOAuth2AuthenticationOptions { ClientId = googleId, ClientSecret = googleSecret, CallbackPath = new PathString("/signin-google"), CookieManager = cookieManager }); } }}} {{{ // POST: /Account/ExternalLogin [HttpPost] [AllowAnonymous] [ValidateAntiForgeryToken] public ActionResult ExternalLogin(string provider, string returnUrl) { // Request a redirect to the external login provider var redirectUrl = Url.Action("ExternalLoginCallback", "Account", new { ReturnUrl = returnUrl }); return new ChallengeResult(provider, redirectUrl); } // POST: /Account/ExternalLoginConfirmation [HttpPost] [AllowAnonymous] [ValidateAntiForgeryToken] public async Task ExternalLoginConfirmation(WebApplication1.Models.ExternalLoginConfirmationViewModel model, string returnUrl) { if (User.Identity.IsAuthenticated) { return RedirectToAction("Index", "Manage"); } if (!ModelState.IsValid) { return View(model); } // Obtain external login info again var info = await AuthenticationManager.GetExternalLoginInfoAsync(); if (info == null) { ModelState.AddModelError("", "Не можам да ги вчитам информации за надворешната најава."); return View(model); } ApplicationUser user; if (model.UserType == "Student") { user = new Student { UserName = model.Email, Email = model.Email, Name = model.Name, Surname = model.Surname, Biography = model.Biography, Index = model.Index, Major = model.Major, Cycle = model.Cycle, Semester = model.Semester }; } else // Mentor { user = new Mentor { UserName = model.Email, Email = model.Email, Name = model.Name, Surname = model.Surname, Biography = model.Biography, Timeslots = model.Timeslots, TypesOfProject = model.TypesOfProject, Available = model.Available, ImageURL = null }; } // Create user var result = await UserManager.CreateAsync(user); if (!result.Succeeded) { AddErrors(result); return View(model); } // Add the external login result = await UserManager.AddLoginAsync(user.Id, info.Login); if (!result.Succeeded) { AddErrors(result); return View(model); } if (model.UserType == "Student") { var student = db.Users .OfType() .Include(s => s.Subjects) .Include(s => s.Topics) .SingleOrDefault(u => u.Id == user.Id); if (student != null) { // clear any placeholder (should be empty for a brand new user) and add incoming items student.Subjects.Clear(); student.Topics.Clear(); foreach (var subjName in model.Subjects ?? Enumerable.Empty()) student.Subjects.Add(new Subject { Name = subjName, UserId = student.Id }); foreach (var topicName in model.Topics ?? Enumerable.Empty()) student.Topics.Add(new Topic { Name = topicName, UserId = student.Id }); db.SaveChanges(); } } else // Mentor { var mentor = db.Users .OfType() .Include(m => m.Subjects) .Include(m => m.Topics) .SingleOrDefault(u => u.Id == user.Id); if (mentor != null) { mentor.Subjects.Clear(); mentor.Topics.Clear(); foreach (var subjName in model.Subjects ?? Enumerable.Empty()) mentor.Subjects.Add(new Subject { Name = subjName, UserId = mentor.Id }); foreach (var topicName in model.Topics ?? Enumerable.Empty()) mentor.Topics.Add(new Topic { Name = topicName, UserId = mentor.Id }); db.SaveChanges(); } } [HttpPost] [ValidateAntiForgeryToken] public ActionResult LinkLogin(string provider) { // Request redirect to external login provider to link to current user return new ChallengeResult(provider, Url.Action("LinkLoginCallback", "Account"), User.Identity.GetUserId()); } [AllowAnonymous] public async Task LinkLoginCallback() { var loginInfo = await AuthenticationManager.GetExternalLoginInfoAsync(XsrfKey, User.Identity.GetUserId()); if (loginInfo == null) { return RedirectToAction("Manage", new { Message = ManageMessageId.Error }); } var result = await UserManager.AddLoginAsync(User.Identity.GetUserId(), loginInfo.Login); if (result.Succeeded) { return RedirectToAction("Manage", new { Message = ManageMessageId.AddLoginSuccess }); } return RedirectToAction("Manage", new { Message = ManageMessageId.Error }); } }}} = Ментор = == Поставување на предлог теми за проект == Менторот може да постави предлог теми за проект на својот профил. Најпрво треба да го отвори прозорецот за уредување на својот профил и да го најде следното поле: [[Image(теми.png)]] Откако ќе додаде тема, ќе може да ја уреди, избрише или додели на некој студент, притоа студентот мора да стапил во контакт со менторот претходно на самата страна и да има договор помеѓу студентот и менторот за таа тема. Доколку темата е доделена, менторот може да ја одземе. == Доделување теми на студент == Менторот може да додели тема на студент преку dropdown кое е пополнето со сите студенти кои го контактирале менторот: [[Image(доделитема.png)]] Секој корисник може да ги види предлог темите на менторот на неговиот профил. Може да види наслов, опис, доколку се доделени или не. Ако е менторот, или пак студентот на кој е доделена темата, тогаш има посебно поле „Доделена на студент:“ [[Image(темипрофил.png)]] [[Image(темипрофил2.png)]] = Студент = == Контакт со ментор (променет) == Контактирање на ментор од страна на студент останува исто, само е додадено поле за избор на предлог тема, која студентот може да ја избере но е опционална. Студентот стиска на копчето за контакт кај профилот на менторот и се отвара следниот прозорец: [[Image(контакт.png)]] По испраќање на контакт барање на менторот, менторот добива нотификација како и претходно, само што сега е излистана и темата која ја одбрал студентот. Ова е со цел да знае професорот на кого да ја додели темата понатаму, но тоа мора да го направи преку својот профил, во случај да има повеќе заинтересирани студенти. [[Image(контактнотиф.png)]] = Нотификации преку E-mail = Воведени се нотификација преку E-mail. освен што стигаат во постоечкиот Inbox, сега сите нотификации стигаат и преку E-mail на корисникот. Пример: [[Image(нотиф.png)]] [[Image(нотиф2.png)]]