From: Rafał Długołęcki Date: Sat, 13 Feb 2016 03:20:30 +0000 (+0100) Subject: Add missing files. Add API for client apps. X-Git-Url: https://git.dlugolecki.net.pl/?a=commitdiff_plain;h=b654badeb78cb3852a62fcad541f3294f9f0c73c;p=wsti_pai.git Add missing files. Add API for client apps. --- diff --git a/1.DefaultUserRoles.sql b/1.DefaultUserRoles.sql new file mode 100644 index 0000000..06d7171 --- /dev/null +++ b/1.DefaultUserRoles.sql @@ -0,0 +1 @@ +INSERT INTO dbo.UserRoles VALUES (1, 'user'), (2, 'admin'); \ No newline at end of file diff --git a/2.DefaultUsers.sql b/2.DefaultUsers.sql new file mode 100644 index 0000000..9823c31 --- /dev/null +++ b/2.DefaultUsers.sql @@ -0,0 +1,4 @@ +SET IDENTITY_INSERT dbo.Users ON; +INSERT INTO dbo.Users (id, login, password, role_id) +VALUES (1, 'user', 'user', 1), (2, 'admin', 'admin', 2); +SET IDENTITY_INSERT dbo.Users OFF; \ No newline at end of file diff --git a/3.DefaultTaskStatuses.sql b/3.DefaultTaskStatuses.sql new file mode 100644 index 0000000..ffc0803 --- /dev/null +++ b/3.DefaultTaskStatuses.sql @@ -0,0 +1,9 @@ +SET IDENTITY_INSERT dbo.TaskStatuses ON; +INSERT INTO + dbo.TaskStatuses (id, status) +VALUES + (1, 'Todo'), + (2, 'In progress'), + (3, 'Done') +; +SET IDENTITY_INSERT dbo.TaskStatuses OFF; \ No newline at end of file diff --git a/4.DefaultProjects.sql b/4.DefaultProjects.sql new file mode 100644 index 0000000..bd7c924 --- /dev/null +++ b/4.DefaultProjects.sql @@ -0,0 +1,10 @@ +SET IDENTITY_INSERT dbo.Projects ON; +INSERT INTO dbo.Projects (id, user_id, name, description, created_at, updated_at) +VALUES +(1, 2, 'Projekt admina', 'To jest projekt admina', '2016-02-12 00:00:00', '2016-02-12 00:00:00'), +(2, 1, 'Projekt usera', 'To jest projekt usera', '2016-02-12 00:00:00', '2016-02-12 00:00:00'), +(3, 1, 'Inny projekt usera', 'Prace nad projektem badawczym', '2016-02-12 00:00:00', '2016-02-12 00:00:00'), +(4, 2, 'Kolejny projekt usera', 'Jakiś projekt Open Source', '2016-02-12 00:00:00', '2016-02-12 00:00:00'), +(5, 2, 'Testowy projekt admina', 'Ważny projekt', '2016-02-12 00:00:00', '2016-02-12 00:00:00') +; +SET IDENTITY_INSERT dbo.Projects OFF; \ No newline at end of file diff --git a/5.DefaultProjectTasks.sql b/5.DefaultProjectTasks.sql new file mode 100644 index 0000000..87e9ef9 --- /dev/null +++ b/5.DefaultProjectTasks.sql @@ -0,0 +1,26 @@ +SET IDENTITY_INSERT dbo.ProjectTasks ON; +INSERT INTO dbo.ProjectTasks (id, project_id, name, description, created_at, updated_at, task_status_id, user_id) +VALUES +(1, 1, 'Inicjalizacja bazy danych', 'Wymagana jest inicjalizacja bazy danych, zadanie polega na przygotowaniu struktury pod stronę', '2016-02-12 00:01:00', '2016-02-12 00:01:00', 3, 1), +(2, 1, 'Wprowadznie treści do bazy', 'Treści będą wykorzystywane przy instalacjach aplikacji', '2016-02-12 00:05:00', '2016-02-12 00:05:00', 3, 1), +(3, 1, 'Opracowanie testów aplikacji', 'Aplikacja ma mieć testy jednostkowe umożliwiające znalezienie błędów na wczesnym etapie prac', '2016-02-12 00:10:00', '2016-02-12 00:10:00', 1, 1), +(4, 1, 'Przetestowanie aplikacji', 'Przed wydaniem produkcyjnym aplikacja ma być przetestowana', '2016-02-12 00:29:00', '2016-02-12 00:29:00', 1, 1), +(5, 1, 'Stworzenie frontendu dla bazy danych', 'Kod strony pisany ma być w języku do tego ustalonym', '2016-02-12 00:35:00', '2016-02-12 00:35:00', 1, 2), + + +(6, 2, 'Mockup projektu', 'Przygotowanie mockupu', '2016-02-12 00:00:00', '2016-02-12 00:00:00', 2, 1), +(7, 2, 'Projekt graficzny', 'Przygotowanie projektu graficznego przez grafika', '2016-02-12 00:01:00', '2016-02-12 00:01:00', 1, 1), +(8, 2, 'Akceptacja klienta', 'Akceptacja projektu graficznego przez klienta', '2016-02-12 00:05:00', '2016-02-12 00:05:00', 3, 2), +(9, 2, 'Implementacja', 'Implementacja projektu graficznego w kod', '2016-02-12 00:10:00', '2016-02-12 00:10:00', 3, 1), +(10, 2, 'Wdrożenie', 'Wdrożenie aplikacji u klienta', '2016-02-12 00:29:00', '2016-02-12 00:29:00', 1, 1), +(11, 2, 'Szkolenie', 'Szkolenie klienta', '2016-02-12 00:35:00', '2016-02-12 00:35:00', 1, 2), + + + +(12, 3, 'Inny projekt usera', 'Prace nad projektem badawczym', '2016-02-12 00:00:00', '2016-02-12 00:00:00', 1, 1), +(13, 4, 'Kolejny projekt usera', 'Jakiś projekt Open Source', '2016-02-12 00:00:00', '2016-02-12 00:00:00', 2, 1), +(14, 5, 'Testowy projekt admina', 'Ważny projekt', '2016-02-12 00:00:00', '2016-02-12 00:00:00', 2, 2) + + +; +SET IDENTITY_INSERT dbo.ProjectTasks OFF; \ No newline at end of file diff --git a/Projects/App_Start/WebApiConfig.cs b/Projects/App_Start/WebApiConfig.cs new file mode 100644 index 0000000..c05dbf3 --- /dev/null +++ b/Projects/App_Start/WebApiConfig.cs @@ -0,0 +1,32 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Web.Http; +using System.Web.Http.Filters; + +namespace Projects +{ + public static class WebApiConfig + { + public static void Register(HttpConfiguration config) + { + config.MapHttpAttributeRoutes(); + + config.Routes.MapHttpRoute( + name: "DefaultApi", + routeTemplate: "api/{controller}/{id}", + defaults: new { id = RouteParameter.Optional } + ); + } + } + public class AllowCrossSiteJsonAttribute : ActionFilterAttribute + { + public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext) + { + if (actionExecutedContext.Response != null) + actionExecutedContext.Response.Headers.Add("Access-Control-Allow-Origin", "*"); + + base.OnActionExecuted(actionExecutedContext); + } + } +} diff --git a/Projects/Controllers/api/ActivityController.cs b/Projects/Controllers/api/ActivityController.cs new file mode 100644 index 0000000..0766226 --- /dev/null +++ b/Projects/Controllers/api/ActivityController.cs @@ -0,0 +1,63 @@ +using Newtonsoft.Json; +using Projects.Models; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Net; +using System.Net.Http; +using System.Net.Http.Headers; +using System.Threading.Tasks; +using System.Web.Http; + +namespace Projects.Controllers.api +{ + [AllowCrossSiteJson] + public class ActivityController : ApiController + { + private ProjectsDBEntities db = new ProjectsDBEntities(); + + // GET: api/Activity + public HttpResponseMessage GetActivity() + { + var results = (from pt in db.ProjectTasks + join ts in db.TaskStatuses on pt.task_status_id equals ts.id + where ts.status == "Done" + group pt.User by pt.User.id into g + join u in db.Users on g.Key equals u.id + select new ActivityResult { user = u.login, count = g.Count() }) + .ToList(); + return new HttpResponseMessage() { + Content = new JsonContent(results) + }; + + } + } + public class JsonContent : HttpContent + { + + private readonly MemoryStream _Stream = new MemoryStream(); + public JsonContent(object value) + { + + Headers.ContentType = new MediaTypeHeaderValue("application/json"); + var jw = new JsonTextWriter(new StreamWriter(_Stream)); + jw.Formatting = Formatting.Indented; + var serializer = new JsonSerializer(); + serializer.Serialize(jw, value); + jw.Flush(); + _Stream.Position = 0; + + } + protected override Task SerializeToStreamAsync(Stream stream, TransportContext context) + { + return _Stream.CopyToAsync(stream); + } + + protected override bool TryComputeLength(out long length) + { + length = _Stream.Length; + return true; + } + } +} diff --git a/Projects/Controllers/api/ProjectTasksController.cs b/Projects/Controllers/api/ProjectTasksController.cs new file mode 100644 index 0000000..fd45ba2 --- /dev/null +++ b/Projects/Controllers/api/ProjectTasksController.cs @@ -0,0 +1,122 @@ +using System; +using System.Collections.Generic; +using System.Data; +using System.Data.Entity; +using System.Data.Entity.Infrastructure; +using System.Linq; +using System.Net; +using System.Net.Http; +using System.Threading.Tasks; +using System.Web.Http; +using System.Web.Http.Description; +using Projects.Models; + +namespace Projects.Controllers.api +{ + [AllowCrossSiteJson] + public class ProjectTasksController : ApiController + { + private ProjectsDBEntities db = new ProjectsDBEntities(); + + // GET: api/ProjectTasks + public IQueryable GetProjectTasks() + { + db.Configuration.ProxyCreationEnabled = false; + db.Configuration.LazyLoadingEnabled = false; + return db.ProjectTasks; + } + + // GET: api/ProjectTasks/5 + [ResponseType(typeof(ProjectTask))] + public async Task GetProjectTask(int id) + { + ProjectTask projectTask = await db.ProjectTasks.FindAsync(id); + if (projectTask == null) + { + return NotFound(); + } + + return Ok(projectTask); + } + + // PUT: api/ProjectTasks/5 + [ResponseType(typeof(void))] + public async Task PutProjectTask(int id, ProjectTask projectTask) + { + if (!ModelState.IsValid) + { + return BadRequest(ModelState); + } + + if (id != projectTask.id) + { + return BadRequest(); + } + + db.Entry(projectTask).State = EntityState.Modified; + + try + { + await db.SaveChangesAsync(); + } + catch (DbUpdateConcurrencyException) + { + if (!ProjectTaskExists(id)) + { + return NotFound(); + } + else + { + throw; + } + } + + return StatusCode(HttpStatusCode.NoContent); + } + + // POST: api/ProjectTasks + [ResponseType(typeof(ProjectTask))] + public async Task PostProjectTask(ProjectTask projectTask) + { + if (!ModelState.IsValid) + { + return BadRequest(ModelState); + } + + db.ProjectTasks.Add(projectTask); + await db.SaveChangesAsync(); + + return CreatedAtRoute("DefaultApi", new { id = projectTask.id }, projectTask); + } + + // DELETE: api/ProjectTasks/5 + [ResponseType(typeof(ProjectTask))] + public async Task DeleteProjectTask(int id) + { + ProjectTask projectTask = await db.ProjectTasks.FindAsync(id); + if (projectTask == null) + { + return NotFound(); + } + + db.ProjectTasks.Remove(projectTask); + await db.SaveChangesAsync(); + + return Ok(projectTask); + } + + protected override void Dispose(bool disposing) + { + if (disposing) + { + db.Dispose(); + } + base.Dispose(disposing); + } + + private bool ProjectTaskExists(int id) + { + return db.ProjectTasks.Count(e => e.id == id) > 0; + } + } +} \ No newline at end of file diff --git a/Projects/Controllers/api/ProjectsController.cs b/Projects/Controllers/api/ProjectsController.cs new file mode 100644 index 0000000..b1b3406 --- /dev/null +++ b/Projects/Controllers/api/ProjectsController.cs @@ -0,0 +1,122 @@ +using System; +using System.Collections.Generic; +using System.Data; +using System.Data.Entity; +using System.Data.Entity.Infrastructure; +using System.Linq; +using System.Net; +using System.Net.Http; +using System.Threading.Tasks; +using System.Web.Http; +using System.Web.Http.Description; +using Projects.Models; + +namespace Projects.Controllers.api +{ + [AllowCrossSiteJson] + public class ProjectsController : ApiController + { + private ProjectsDBEntities db = new ProjectsDBEntities(); + + // GET: api/Projects + public IQueryable GetProjects() + { + db.Configuration.ProxyCreationEnabled = false; + db.Configuration.LazyLoadingEnabled = false; + return db.Projects; + } + + // GET: api/Projects/5 + [ResponseType(typeof(Project))] + public async Task GetProject(int id) + { + Project project = await db.Projects.FindAsync(id); + if (project == null) + { + return NotFound(); + } + + return Ok(project); + } + + // PUT: api/Projects/5 + [ResponseType(typeof(void))] + public async Task PutProject(int id, Project project) + { + if (!ModelState.IsValid) + { + return BadRequest(ModelState); + } + + if (id != project.id) + { + return BadRequest(); + } + + db.Entry(project).State = EntityState.Modified; + + try + { + await db.SaveChangesAsync(); + } + catch (DbUpdateConcurrencyException) + { + if (!ProjectExists(id)) + { + return NotFound(); + } + else + { + throw; + } + } + + return StatusCode(HttpStatusCode.NoContent); + } + + // POST: api/Projects + [ResponseType(typeof(Project))] + public async Task PostProject(Project project) + { + if (!ModelState.IsValid) + { + return BadRequest(ModelState); + } + + db.Projects.Add(project); + await db.SaveChangesAsync(); + + return CreatedAtRoute("DefaultApi", new { id = project.id }, project); + } + + // DELETE: api/Projects/5 + [ResponseType(typeof(Project))] + public async Task DeleteProject(int id) + { + Project project = await db.Projects.FindAsync(id); + if (project == null) + { + return NotFound(); + } + + db.Projects.Remove(project); + await db.SaveChangesAsync(); + + return Ok(project); + } + + protected override void Dispose(bool disposing) + { + if (disposing) + { + db.Dispose(); + } + base.Dispose(disposing); + } + + private bool ProjectExists(int id) + { + return db.Projects.Count(e => e.id == id) > 0; + } + } +} \ No newline at end of file diff --git a/Projects/Global.asax.cs b/Projects/Global.asax.cs index 61f3d92..bb16001 100644 --- a/Projects/Global.asax.cs +++ b/Projects/Global.asax.cs @@ -7,6 +7,8 @@ using System.Web.Mvc; using System.Web.Optimization; using System.Web.Routing; using System.Web.Security; +using System.Web.Http; +using System.Web.Routing; namespace Projects { @@ -14,10 +16,21 @@ namespace Projects { protected void Application_Start() { + GlobalConfiguration.Configure(WebApiConfig.Register); + AreaRegistration.RegisterAllAreas(); FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); RouteConfig.RegisterRoutes(RouteTable.Routes); BundleConfig.RegisterBundles(BundleTable.Bundles); + + var formatters = GlobalConfiguration.Configuration.Formatters; + formatters.Remove(formatters.XmlFormatter); + + /* JSON formatting */ + var json = formatters.JsonFormatter; + json.SerializerSettings.PreserveReferencesHandling = Newtonsoft.Json.PreserveReferencesHandling.None; + json.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore; + json.SerializerSettings.Formatting = Newtonsoft.Json.Formatting.Indented; } protected void Application_PostAuthenticateRequest(Object sender, EventArgs e) diff --git a/Projects/Models/Metadata.cs b/Projects/Models/Metadata.cs index a5bac9c..ed7b886 100644 --- a/Projects/Models/Metadata.cs +++ b/Projects/Models/Metadata.cs @@ -1,8 +1,11 @@ -using System; +using Newtonsoft.Json; +using System; +using System.Collections.Generic; using System.ComponentModel.DataAnnotations; namespace Projects.Models { + [JsonObject(IsReference = true)] public class ProjectMetadata { [StringLength(50)] @@ -22,6 +25,7 @@ namespace Projects.Models public Nullable user_id; } + [JsonObject(IsReference = true)] public class ProjectTaskMetadata { [StringLength(50)] @@ -41,6 +45,7 @@ namespace Projects.Models public Nullable user_id; } + [JsonObject(IsReference = true)] public class UserMetadata { [Display(Name = "Nazwa użytkownika")] @@ -50,6 +55,7 @@ namespace Projects.Models public string password; } + [JsonObject(IsReference = true)] public class TaskStatusMetadata { [Display(Name = "Status")] diff --git a/Projects/Projects.csproj b/Projects/Projects.csproj index 08f2500..ca57e87 100644 --- a/Projects/Projects.csproj +++ b/Projects/Projects.csproj @@ -77,17 +77,45 @@ True + + ..\packages\Microsoft.Data.Edm.5.6.0\lib\net40\Microsoft.Data.Edm.dll + True + + + ..\packages\Microsoft.Data.OData.5.6.0\lib\net40\Microsoft.Data.OData.dll + True + + + ..\packages\Microsoft.AspNet.WebApi.Client.5.2.3\lib\net45\System.Net.Http.Formatting.dll + True + + + ..\packages\System.Spatial.5.6.0\lib\net40\System.Spatial.dll + True + + + ..\packages\Microsoft.AspNet.WebApi.Core.5.2.3\lib\net45\System.Web.Http.dll + True + + + ..\packages\Microsoft.AspNet.WebApi.OData.5.3.1\lib\net45\System.Web.Http.OData.dll + True + + + ..\packages\Microsoft.AspNet.WebApi.WebHost.5.2.3\lib\net45\System.Web.Http.WebHost.dll + True + @@ -195,8 +223,12 @@ + + + + diff --git a/Projects/Views/Activity/Index.cshtml b/Projects/Views/Activity/Index.cshtml new file mode 100644 index 0000000..b5e121c --- /dev/null +++ b/Projects/Views/Activity/Index.cshtml @@ -0,0 +1,24 @@ + +@{ + ViewBag.Title = "Aktywność użytkowników"; +} + +

@ViewBag.Title

+ + + + + + + + + @foreach (var result in (IEnumerable)ViewBag.results) + { + + + + + } + +
Nazwa użytkownikaIlość ukończonych zadań
@result.user@result.count
+ diff --git a/Projects/Views/Login/Login.cshtml b/Projects/Views/Login/Login.cshtml new file mode 100644 index 0000000..98481b0 --- /dev/null +++ b/Projects/Views/Login/Login.cshtml @@ -0,0 +1,37 @@ +@model Projects.Models.User + +@{ + ViewBag.Title = "Login"; +} + +

@ViewBag.Title

+ + + + +@using (Html.BeginForm()) +{ + @Html.AntiForgeryToken() + + @Html.ValidationSummary(true, "", new { @class = "text-danger" }) +
+ @Html.LabelFor(model => model.login, htmlAttributes: new { @class = "control-label col-md-2" }) +
+ @Html.EditorFor(model => model.login, new { htmlAttributes = new { @class = "form-control" } }) + @Html.ValidationMessageFor(model => model.login, "", new { @class = "text-danger" }) +
+
+
+ @Html.LabelFor(model => model.password, htmlAttributes: new { @class = "control-label col-md-2" }) +
+ @Html.EditorFor(model => model.password, new { htmlAttributes = new { @class = "form-control" } }) + @Html.ValidationMessageFor(model => model.password, "", new { @class = "text-danger" }) +
+
+ +
+
+ +
+
+} \ No newline at end of file diff --git a/Projects/Web.config b/Projects/Web.config index 06973af..97b0fb8 100644 --- a/Projects/Web.config +++ b/Projects/Web.config @@ -34,7 +34,12 @@ - + + + + + + @@ -77,6 +82,14 @@ + + + + + + + + diff --git a/Projects/packages.config b/Projects/packages.config index c598596..f6ce924 100644 --- a/Projects/packages.config +++ b/Projects/packages.config @@ -19,8 +19,15 @@ + + + + + + + @@ -37,5 +44,6 @@ + \ No newline at end of file