using EnVisage.Code; using EnVisage.Code.BLL; using EnVisage.Models; using System; using System.Collections.Generic; using System.Net; using System.Web.Mvc; using System.Data; using System.Data.Entity; using System.Linq; namespace EnVisage.Controllers { [Authorize] public class SkillsController : BaseController { [AreaSecurity(area = Areas.Skills, level = AccessLevel.Read)] public ActionResult Index() { string userIdAsText = User.Identity.GetID(); SkillsMatrixPageLoadModel model = GetPageLoadModel(userIdAsText, ApplicationDashboards.None, this.DbContext); model.ReadOnly = !SecurityManager.CheckSecurityObjectPermission(Areas.SkillsMatrix, AccessLevel.Write); // Get Activity Calendar root URL model.ActivityCalendarUrl = this.Url.Action("Index", "CapacityManagement"); // Open in special Skills Matrix page model.OpenerType = ApplicationDashboards.None; return View("Index", model); } public ActionResult ExportToPDF() { PDFExporter exporter = new PDFExporter(); exporter.BrowserWidth = 2560; byte[] pdfBuffer = exporter.ExportPage(Url.Action("LoadMatrix", "Skills", null, this.Request.Url.Scheme), 20, true, Request.Cookies); // send the PDF file to browser FileResult fileResult = new FileContentResult(pdfBuffer, "application/pdf"); fileResult.FileDownloadName = "Prevu-Skills-" + DateTime.Today.Month + "-" + DateTime.Today.Day + ".pdf"; return fileResult; } #region Skills management [HttpPost] [AreaSecurity(area = Areas.Skills, level = AccessLevel.Read)] [ValidateJsonAntiForgeryToken] public ActionResult GetSkillTree(SkillsMatrixQueryModel model) { try { var manager = new SkillGroupManager(DbContext); var items = manager.LoadSkillsTree(); return Json(items); } catch (BLLException blEx) // handle any system specific error { // display error message if required if (blEx.DisplayError) ModelState.AddModelError(string.Empty, blEx.Message); else // if display not requried then display modal form with general error message { LogException(blEx); //SetErrorScript(); ModelState.AddModelError(string.Empty, "Cannot load skills tree. Try again later."); } } catch (Exception exception) // handle any unexpected error { LogException(exception); //SetErrorScript(); ModelState.AddModelError(string.Empty, "Cannot load skills tree. Try again later."); } return new HttpStatusCodeResult(HttpStatusCode.InternalServerError); } [HttpPost] [AreaSecurity(area = Areas.Skills, level = AccessLevel.Write)] [ValidateJsonAntiForgeryToken] public ActionResult SaveSkillTree(EditSkillsModel model) { try { var manager = new SkillGroupManager(DbContext); manager.Save(model); DbContext.SaveChanges(); var items = manager.LoadSkillsTree(); return Json(items); } catch (BLLException blEx) // handle any system specific error { // display error message if required if (blEx.DisplayError) ModelState.AddModelError(string.Empty, blEx.Message); else // if display not requried then display modal form with general error message { LogException(blEx); //SetErrorScript(); ModelState.AddModelError(string.Empty, "Cannot save skills tree. Try again later."); } } catch (Exception exception) // handle any unexpected error { LogException(exception); //SetErrorScript(); ModelState.AddModelError(string.Empty, "Cannot save skills tree. Try again later."); } return new HttpStatusCodeResult(HttpStatusCode.InternalServerError); } #endregion #region Skills matrix /// /// Returns Skills Matrix data /// /// Query params /// /// SA. ENV-1328 [HttpPost] [ValidateJsonAntiForgeryToken] public ActionResult GetSkillsMatrix(SkillsMatrixQueryModel model) { if (!SecurityManager.CheckSecurityObjectPermission(Areas.SkillsMatrix, AccessLevel.Read) && !SecurityManager.CheckSecurityObjectPermission(Areas.RD_ResourceSkills, AccessLevel.Read)) return new HttpStatusCodeResult(HttpStatusCode.Unauthorized); try { // If DatePoint is not specified, data will be extracted for Now DateTime datePoint = DateTime.UtcNow.Date; Guid userId = SecurityManager.GetUserPrincipal(); if (model.DatePoint > 0) datePoint = Utils.ConvertFromUnixDate(model.DatePoint).ToUniversalTime(); var manager = new SkillsMatrixManager(DbContext); bool excludeChartData = (model.Filter != null) && (model.Filter.Resources != null) && (model.Filter.Resources.Count == 1); SkillsMatrixSaveModel data = manager.LoadSkillMatrix(SkillMatrixTimeLayer.Present, model.DataType, datePoint, userId, !excludeChartData, model.Filter); return Json(data); } catch (BLLException blEx) // handle any system specific error { // display error message if required if (blEx.DisplayError) ModelState.AddModelError(string.Empty, blEx.Message); else // if display not requried then display modal form with general error message { LogException(blEx); //SetErrorScript(); ModelState.AddModelError(string.Empty, "Cannot load skills matrix. Try again later."); } } catch (Exception exception) // handle any unexpected error { LogException(exception); //SetErrorScript(); ModelState.AddModelError(string.Empty, "Cannot load skills matrix. Try again later."); } return new HttpStatusCodeResult(HttpStatusCode.InternalServerError); } /// /// Saves Skills Matrix data /// /// Data to save /// /// SA. ENV-1328 [HttpPost] [ValidateJsonAntiForgeryToken] public ActionResult SaveSkillsMatrix(SkillsMatrixSaveModel model) { if (!SecurityManager.CheckSecurityObjectPermission(Areas.SkillsMatrix, AccessLevel.Write) && !SecurityManager.CheckSecurityObjectPermission(Areas.RD_ResourceSkills, AccessLevel.Write)) return new HttpStatusCodeResult(HttpStatusCode.Unauthorized); try { if ((model != null) && (model.Values != null)) { var manager = new SkillsMatrixManager(DbContext); manager.Save(model); DbContext.SaveChanges(); } return new HttpStatusCodeResult(HttpStatusCode.OK); } catch (BLLException blEx) // handle any system specific error { // display error message if required if (blEx.DisplayError) ModelState.AddModelError(string.Empty, blEx.Message); else // if display not requried then display modal form with general error message { LogException(blEx); //SetErrorScript(); ModelState.AddModelError(string.Empty, "Cannot save skill matrix. Try again later."); } } catch (Exception exception) // handle any unexpected error { LogException(exception); //SetErrorScript(); ModelState.AddModelError(string.Empty, "Cannot save skill matrix. Try again later."); } return new HttpStatusCodeResult(HttpStatusCode.InternalServerError); } /// /// Initialized model for opening Skills page. Including filter options /// /// public static SkillsMatrixPageLoadModel GetPageLoadModel(string userIdAsText, ApplicationDashboards openerType, EnVisageEntities dbContext) { if (String.IsNullOrEmpty(userIdAsText)) throw new ArgumentNullException("userIdAsText"); if (dbContext == null) throw new ArgumentNullException("dbContext"); SkillsMatrixPageLoadModel model = new SkillsMatrixPageLoadModel { DataType = Skill2ResourceType.Actual }; Guid userId = Guid.Parse(userIdAsText); List options; #region Teams if (openerType != ApplicationDashboards.ResourceBoard) { TeamManager teamMngr = new TeamManager(dbContext); var availableTeams = teamMngr.GetTeamsByUser(userId); options = (availableTeams.OrderBy(x => x.Name).Select(x => new SelectListItem() { Text = x.Name, Value = x.TeamId.ToString() })).ToList(); model.FilterOptions.Teams = options; } #endregion #region Views if (openerType != ApplicationDashboards.ResourceBoard) { ViewManager viewMngr = new ViewManager(dbContext); IList availableViews = viewMngr.GetViewsByOwner(userId); options = (availableViews.OrderBy(x => x.Name).Select(x => new SelectListItem() { Text = x.Name, Value = x.Id.ToString() })).ToList(); model.FilterOptions.Views = options; } #endregion #region Companies if (openerType != ApplicationDashboards.ResourceBoard) { CompanyManager cmpnyMngr = new CompanyManager(dbContext); // Uncomment below, the only visible to user companies must be displayed by permissions // var availableCompanies = cmpnyMngr.GetCompaniesByUser4Display(userId); var availableCompanies = cmpnyMngr.GetCompaniesByUser(null); options = new List(); SelectListItem listItem; var companiesRootLevel = availableCompanies.Where(x => !x.ParentCompanyId.HasValue || !availableCompanies.Any(z => z.Id.Equals(x.ParentCompanyId.Value))) .OrderBy(x => x.Name).ToList(); foreach (var rootCompany in companiesRootLevel) { listItem = new SelectListItem() { Text = rootCompany.Name, Value = rootCompany.Id.ToString(), Group = null }; options.Add(listItem); // Get child companies var childCompanies = availableCompanies.Where(x => x.ParentCompanyId.HasValue && x.ParentCompanyId.Value.Equals(rootCompany.Id)) .OrderBy(x => x.Name).ToList(); foreach (var childCompany in childCompanies) { listItem = new SelectListItem() { Text = childCompany.Name, Value = childCompany.Id.ToString(), Group = new SelectListGroup() { Name = rootCompany.Name } }; options.Add(listItem); } } model.FilterOptions.Companies = options; } #endregion #region Skill Groups and Skills SkillManager skillMngr = new SkillManager(dbContext); List allSkills = skillMngr.DataTable.ToList(); Dictionary skillGroups = allSkills.Where(x => !x.ParentId.HasValue) .ToDictionary(k => k.Id, v => v.Name); List skillGroupsOrdered = skillGroups.OrderBy(x => x.Value) .Select(x => new SelectListItem() { Value = x.Key.ToString(), Text = x.Value, }).ToList(); model.FilterOptions.Skills = new List(); // SA: When creating Skills tree for Matrix filter in the page, // we transform the tree to an ordered plain list, where Skills immediatelly follow // their parent Skill Group. To make Skills and Groups manipulation easy, // we store the amount of skills and marker of child skills existance to the Group property of // any Skills Group SelectListItem. Where Group.Name contains amount of child skills, and // Group.Disabled=true means the Skill Group has child skills foreach (SelectListItem grp in skillGroupsOrdered) { SelectListItem grpCopy = grp.Clone(); model.FilterOptions.Skills.Add(grpCopy); List grpSkills = allSkills.Where(s => s.ParentId.HasValue && s.ParentId.Value.Equals(new Guid(grpCopy.Value))) .OrderBy(s => s.Name) .Select(s => new SelectListItem() { Value = s.Id.ToString(), Text = s.Name }).ToList(); model.FilterOptions.Skills.AddRange(grpSkills); grpCopy.Group = new SelectListGroup() { Name = grpSkills.Count().ToString(), Disabled = grpSkills.Count() > 0 }; } skillMngr = null; #endregion #region Skill Levels if (openerType != ApplicationDashboards.ResourceBoard) { Dictionary levelsReady = new Dictionary(); Array levelIds = Enum.GetValues(typeof(SkillLevels)); foreach (object levelId in levelIds) { int levelCode = Convert.ToInt32(levelId); string levelName = ((SkillLevels)levelId).ToDisplayValue(); levelsReady.Add(levelCode, levelName); } model.FilterOptions.SkillLevels = levelsReady.OrderBy(x => x.Key).Select(x => new SelectListItem() { Value = x.Key.ToString(), Text = String.Format("{0} - {1}", x.Key.ToString(), x.Value) }).ToList(); } #endregion #region Skill Interests if (openerType != ApplicationDashboards.ResourceBoard) { Dictionary interestesReady = new Dictionary(); Array interestIds = Enum.GetValues(typeof(SkillInterests)); foreach (object interestId in interestIds) { int interestCode = Convert.ToInt32(interestId); string interestName = ((SkillInterests)interestId).ToDisplayValue(); interestesReady.Add(interestCode, interestName); } model.FilterOptions.SkillInterests = interestesReady.OrderBy(x => x.Key).Select(x => new SelectListItem() { Value = x.Key.ToString(), Text = x.Value }).ToList(); } #endregion return model; } #endregion } }