This commit is contained in:
alexziskind1 2019-04-15 08:48:11 -07:00
Коммит 83464c8c5c
345 изменённых файлов: 66185 добавлений и 0 удалений

261
.gitignore поставляемый Normal file
Просмотреть файл

@ -0,0 +1,261 @@
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
# User-specific files
*.suo
*.user
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/
# Visual Studio 2015 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUNIT
*.VisualState.xml
TestResult.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# DNX
project.lock.json
project.fragment.lock.json
artifacts/
*_i.c
*_p.c
*_i.h
*.ilk
*.meta
*.obj
*.pch
*.pdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# JustCode is a .NET coding add-in
.JustCode
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# TODO: Comment the next line if you want to checkin your web deploy settings
# but database connection strings (with potential passwords) will be unencrypted
#*.pubxml
*.publishproj
# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/
# NuGet Packages
*.nupkg
# The packages folder can be ignored because of Package Restore
**/packages/*
# except build/, which is used as an MSBuild target.
!**/packages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/packages/repositories.config
# NuGet v3's project.json files produces more ignoreable files
*.nuget.props
*.nuget.targets
# Microsoft Azure Build Output
csx/
*.build.csdef
# Microsoft Azure Emulator
ecf/
rcf/
# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!*.[Cc]ache/
# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
node_modules/
orleans.codegen.cs
# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
# SQL Server files
*.mdf
*.ldf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# Paket dependency manager
.paket/paket.exe
paket-files/
# FAKE - F# Make
.fake/
# JetBrains Rider
.idea/
*.sln.iml
# CodeRush
.cr/
# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc

Просмотреть файл

@ -0,0 +1,12 @@
using System;
namespace RPS.Core.Models.Dto
{
public class PtDashboardFilter
{
public int UserId { get; set; }
public DateTime DateStart { get; set; }
public DateTime DateEnd { get; set; }
}
}

Просмотреть файл

@ -0,0 +1,31 @@
using System;
using System.Collections.Generic;
namespace RPS.Core.Models.Dto
{
public class ItemsForMonth
{
public List<PtItem> Closed { get; set; }
public List<PtItem> Open { get; set; }
public ItemsForMonth()
{
Closed = new List<PtItem>();
Open = new List<PtItem>();
}
}
public class PtDashboardFilteredIssues
{
public List<DateTime> Categories { get; set; }
public List<ItemsForMonth> MonthItems { get; set; }
public PtDashboardFilteredIssues()
{
Categories = new List<DateTime>();
MonthItems = new List<ItemsForMonth>();
}
}
}

Просмотреть файл

@ -0,0 +1,8 @@
namespace RPS.Core.Models.Dto
{
public class PtDashboardStatusCounts
{
public int ClosedItemsCount { get; set; }
public int OpenItemsCount { get; set; }
}
}

Просмотреть файл

@ -0,0 +1,9 @@
namespace RPS.Core.Models.Dto
{
public class PtNewComment
{
public string Title { get; set; }
public int ItemId { get; set; }
public int UserId { get; set; }
}
}

Просмотреть файл

@ -0,0 +1,12 @@
using RPS.Core.Models.Enums;
namespace RPS.Core.Models.Dto
{
public class PtNewItem
{
public string Title { get; set; }
public string Description { get; set; }
public ItemTypeEnum TypeStr { get; set; }
public int UserId { get; set; }
}
}

Просмотреть файл

@ -0,0 +1,8 @@
namespace RPS.Core.Models.Dto
{
public class PtNewTask
{
public string Title { get; set; }
public int ItemId { get; set; }
}
}

Просмотреть файл

@ -0,0 +1,16 @@
using RPS.Core.Models.Enums;
namespace RPS.Core.Models.Dto
{
public class PtUpdateItem
{
public int Id { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public int Estimate { get; set; }
public PriorityEnum Priority { get; set; }
public StatusEnum Status { get; set; }
public ItemTypeEnum Type { get; set; }
public int AssigneeId { get; set; }
}
}

Просмотреть файл

@ -0,0 +1,10 @@
namespace RPS.Core.Models.Dto
{
public class PtUpdateTask
{
public int Id { get; set; }
public string Title { get; set; }
public bool Completed { get; set; }
public int ItemId { get; set; }
}
}

Просмотреть файл

@ -0,0 +1,10 @@
namespace RPS.Core.Models.Enums
{
public enum ItemTypeEnum
{
PBI,
Bug,
Chore,
Impediment
}
}

Просмотреть файл

@ -0,0 +1,10 @@
namespace RPS.Core.Models.Enums
{
public enum PriorityEnum
{
Low = 2,
Medium = 4,
High = 8,
Critical = 16
}
}

Просмотреть файл

@ -0,0 +1,10 @@
namespace RPS.Core.Models.Enums
{
public enum StatusEnum
{
Submitted = 2,
Open = 4,
Closed = 8,
ReOpened = 16
}
}

Просмотреть файл

@ -0,0 +1,7 @@
namespace RPS.Core.Models
{
public class PtComment : PtObjectBase
{
public PtUser User { get; set; }
}
}

23
RPS.Core/Models/PtItem.cs Normal file
Просмотреть файл

@ -0,0 +1,23 @@
using System.Collections.Generic;
using RPS.Core.Models.Enums;
namespace RPS.Core.Models
{
public class PtItem : PtObjectBase
{
public string Description { get; set; }
public int Estimate { get; set; }
public PriorityEnum Priority { get; set; }
public StatusEnum Status { get; set; }
public ItemTypeEnum Type { get; set; }
public PtUser Assignee { get; set; }
public List<PtTask> Tasks { get; set; }
public List<PtComment> Comments { get; set; }
public PtItem()
{
Tasks = new List<PtTask>();
Comments = new List<PtComment>();
}
}
}

Просмотреть файл

@ -0,0 +1,13 @@
using System;
namespace RPS.Core.Models
{
public class PtObjectBase
{
public int Id { get; set; }
public string Title { get; set; }
public DateTime DateCreated { get; set; }
public DateTime DateModified { get; set; }
public DateTime? DateDeleted { get; set; }
}
}

11
RPS.Core/Models/PtTask.cs Normal file
Просмотреть файл

@ -0,0 +1,11 @@
using System;
namespace RPS.Core.Models
{
public class PtTask:PtObjectBase
{
public bool Completed { get; set; }
public DateTime DateStart { get; set; }
public DateTime DateEnd { get; set; }
}
}

Просмотреть файл

@ -0,0 +1,8 @@
namespace RPS.Core.Models
{
public class PtUser : PtObjectBase
{
public string FullName { get; set; }
public string Avatar { get; set; }
}
}

12
RPS.Core/RPS.Core.csproj Normal file
Просмотреть файл

@ -0,0 +1,12 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework>
</PropertyGroup>
<ItemGroup>
<Folder Include="Models\Dto\" />
<Folder Include="Models\Enums\" />
</ItemGroup>
</Project>

31398
RPS.Data/GenData/fs-items.json Normal file

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -0,0 +1,149 @@
[
{
"avatar": "images/avatars/me/me.png",
"dateCreated": "2018-05-31T14:36:33.560Z",
"dateModified": "2018-05-31T14:36:33.560Z",
"fullName": "Alex Ziskind",
"id": 21
},
{
"avatar": "images/avatars/females/image-1.png",
"dateCreated": "2019-01-30T13:55:12.528Z",
"dateModified": "2019-01-30T13:55:12.528Z",
"fullName": "Barbara Pfeffer",
"id": 1
},
{
"avatar": "images/avatars/males/image-2.png",
"dateCreated": "2018-05-26T20:49:07.704Z",
"dateModified": "2018-05-26T20:49:07.704Z",
"fullName": "Lysanne Baumbach",
"id": 2
},
{
"avatar": "images/avatars/females/image-3.png",
"dateCreated": "2019-02-23T14:16:47.553Z",
"dateModified": "2019-02-23T14:16:47.553Z",
"fullName": "Brian Upton",
"id": 3
},
{
"avatar": "images/avatars/females/image-4.png",
"dateCreated": "2018-07-05T20:24:45.565Z",
"dateModified": "2018-07-05T20:24:45.565Z",
"fullName": "Carolyn Cronin",
"id": 4
},
{
"avatar": "images/avatars/females/image-5.png",
"dateCreated": "2018-03-23T19:51:11.902Z",
"dateModified": "2018-03-23T19:51:11.902Z",
"fullName": "Waylon Jakubowski",
"id": 5
},
{
"avatar": "images/avatars/females/image-6.png",
"dateCreated": "2018-06-25T07:44:17.800Z",
"dateModified": "2018-06-25T07:44:17.800Z",
"fullName": "Lera Witting",
"id": 6
},
{
"avatar": "images/avatars/females/image-7.png",
"dateCreated": "2018-09-18T13:56:03.825Z",
"dateModified": "2018-09-18T13:56:03.825Z",
"fullName": "Valentin Ledner",
"id": 7
},
{
"avatar": "images/avatars/females/image-8.png",
"dateCreated": "2019-03-01T03:56:59.841Z",
"dateModified": "2019-03-01T03:56:59.841Z",
"fullName": "Israel Gleichner",
"id": 8
},
{
"avatar": "images/avatars/males/image-9.png",
"dateCreated": "2018-12-26T00:09:37.109Z",
"dateModified": "2018-12-26T00:09:37.109Z",
"fullName": "Freeda Watsica",
"id": 9
},
{
"avatar": "images/avatars/males/image-10.png",
"dateCreated": "2018-06-14T03:29:47.253Z",
"dateModified": "2018-06-14T03:29:47.253Z",
"fullName": "Branson Prosacco",
"id": 10
},
{
"avatar": "images/avatars/males/image-11.png",
"dateCreated": "2019-01-18T09:06:15.372Z",
"dateModified": "2019-01-18T09:06:15.372Z",
"fullName": "Emmie Herzog",
"id": 11
},
{
"avatar": "images/avatars/females/image-12.png",
"dateCreated": "2019-01-22T22:12:15.668Z",
"dateModified": "2019-01-22T22:12:15.668Z",
"fullName": "Stephania Rogahn",
"id": 12
},
{
"avatar": "images/avatars/females/image-13.png",
"dateCreated": "2018-08-12T10:09:06.552Z",
"dateModified": "2018-08-12T10:09:06.552Z",
"fullName": "Pat Langosh",
"id": 13
},
{
"avatar": "images/avatars/females/image-14.png",
"dateCreated": "2019-01-19T09:34:38.291Z",
"dateModified": "2019-01-19T09:34:38.291Z",
"fullName": "Reynold Ziemann",
"id": 14
},
{
"avatar": "images/avatars/females/image-15.png",
"dateCreated": "2018-11-14T20:05:10.339Z",
"dateModified": "2018-11-14T20:05:10.339Z",
"fullName": "Arlo Mitchell",
"id": 15
},
{
"avatar": "images/avatars/males/image-16.png",
"dateCreated": "2018-03-25T05:26:54.466Z",
"dateModified": "2018-03-25T05:26:54.466Z",
"fullName": "Velva Renner",
"id": 16
},
{
"avatar": "images/avatars/males/image-17.png",
"dateCreated": "2018-08-13T16:43:18.673Z",
"dateModified": "2018-08-13T16:43:18.673Z",
"fullName": "Noelia Frami",
"id": 17
},
{
"avatar": "images/avatars/females/image-18.png",
"dateCreated": "2018-05-05T01:58:36.413Z",
"dateModified": "2018-05-05T01:58:36.413Z",
"fullName": "Amir Vandervort",
"id": 18
},
{
"avatar": "images/avatars/females/image-19.png",
"dateCreated": "2019-02-21T04:20:11.074Z",
"dateModified": "2019-02-21T04:20:11.074Z",
"fullName": "Phoebe Durgan",
"id": 19
},
{
"avatar": "images/avatars/males/image-20.png",
"dateCreated": "2018-09-30T21:35:39.078Z",
"dateModified": "2018-09-30T21:35:39.078Z",
"fullName": "Orpha Dooley",
"id": 20
}
]

Просмотреть файл

@ -0,0 +1,33 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
namespace RPS.Data.Helpers
{
public class AndSpecification<T> : Specification<T>
{
private readonly Specification<T> _left;
private readonly Specification<T> _right;
public AndSpecification(Specification<T> left, Specification<T> right)
{
_right = right;
_left = left;
}
public override Expression<Func<T, bool>> ToExpression()
{
Expression<Func<T, bool>> leftExpression = _left.ToExpression();
Expression<Func<T, bool>> rightExpression = _right.ToExpression();
BinaryExpression andExpression = Expression.AndAlso(
leftExpression.Body, rightExpression.Body);
return Expression.Lambda<Func<T, bool>>(
andExpression, leftExpression.Parameters.Single());
}
}
}

Просмотреть файл

@ -0,0 +1,28 @@
using RPS.Core.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
namespace RPS.Data.Helpers
{
public class PtItemDateRangeSpecification : Specification<PtItem>
{
private readonly DateTime _start;
private readonly DateTime _end;
public PtItemDateRangeSpecification(DateTime start, DateTime end)
{
_start = start;
_end = end;
}
public override Expression<Func<PtItem, bool>> ToExpression()
{
return item => item.DateCreated >= _start && item.DateCreated <= _end;
}
}
}

Просмотреть файл

@ -0,0 +1,27 @@
using RPS.Core.Models;
using RPS.Core.Models.Enums;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
namespace RPS.Data.Helpers
{
public class PtItemStatusSpecification : Specification<PtItem>
{
private readonly StatusEnum _status;
public PtItemStatusSpecification(StatusEnum status)
{
_status = status;
}
public override Expression<Func<PtItem, bool>> ToExpression()
{
return item => item.Status == _status;
}
}
}

Просмотреть файл

@ -0,0 +1,33 @@
using RPS.Core.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
namespace RPS.Data.Helpers
{
public class PtItemUserIdSpecification : Specification<PtItem>
{
private readonly int _userId;
public PtItemUserIdSpecification(int userId)
{
_userId = userId;
}
public override Expression<Func<PtItem, bool>> ToExpression()
{
if (_userId == 0)
{
return item => true;
}
else
{
return item => item.Assignee.Id == _userId;
}
}
}
}

Просмотреть файл

@ -0,0 +1,25 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
namespace RPS.Data.Helpers
{
public abstract class Specification<T>
{
public abstract Expression<Func<T, bool>> ToExpression();
public bool IsSatisfiedBy(T entity)
{
Func<T, bool> predicate = ToExpression().Compile();
return predicate(entity);
}
public Specification<T> And(Specification<T> specification)
{
return new AndSpecification<T>(this, specification);
}
}
}

Просмотреть файл

@ -0,0 +1,12 @@
using RPS.Core.Models;
using RPS.Core.Models.Dto;
using System.Collections.Generic;
namespace RPS.Data
{
public interface IPtCommentsRepository
{
IEnumerable<PtComment> GetAllForItem(int itemId);
PtComment AddNewComment(PtNewComment newComment);
}
}

Просмотреть файл

@ -0,0 +1,10 @@
using RPS.Core.Models.Dto;
namespace RPS.Data
{
public interface IPtDashboardRepository
{
PtDashboardStatusCounts GetStatusCounts(PtDashboardFilter filter);
PtDashboardFilteredIssues GetFilteredIssues(PtDashboardFilter filter);
}
}

Просмотреть файл

@ -0,0 +1,18 @@
using RPS.Core.Models;
using RPS.Core.Models.Dto;
using System.Collections.Generic;
namespace RPS.Data
{
public interface IPtItemsRepository
{
IEnumerable<PtItem> GetAll();
IEnumerable<PtItem> GetUserItems(int userId);
IEnumerable<PtItem> GetOpenItems();
IEnumerable<PtItem> GetClosedItems();
PtItem GetItemById(int itemId);
PtItem AddNewItem(PtNewItem newItem);
PtItem UpdateItem(PtUpdateItem updateItem);
}
}

Просмотреть файл

@ -0,0 +1,15 @@
using RPS.Core.Models;
using RPS.Core.Models.Dto;
using System.Collections.Generic;
namespace RPS.Data
{
public interface IPtTasksRepository
{
IEnumerable<PtTask> GetAllForItem(int itemId);
PtTask AddNewTask(PtNewTask newTask);
PtTask UpdateTask(PtUpdateTask updateTask);
bool DeleteTask(int id, int itemId);
}
}

Просмотреть файл

@ -0,0 +1,10 @@
using RPS.Core.Models;
using System.Collections.Generic;
namespace RPS.Data
{
public interface IPtUserRepository
{
IEnumerable<PtUser> GetAll();
}
}

Просмотреть файл

@ -0,0 +1,41 @@
using System;
using System.Collections.Generic;
using System.Linq;
using RPS.Core.Models;
using RPS.Core.Models.Dto;
namespace RPS.Data
{
public class PtCommentsRepository : IPtCommentsRepository
{
private PtInMemoryContext context;
public PtCommentsRepository(PtInMemoryContext context)
{
this.context = context;
}
public PtComment AddNewComment(PtNewComment newComment)
{
var item = context.PtItems.Single(i => i.Id == newComment.ItemId);
PtComment comment = new PtComment
{
Id = item.Comments.Max(t => t.Id) + 1,
Title = newComment.Title,
DateCreated = DateTime.Now,
DateModified = DateTime.Now,
User = context.PtUsers.Find(u => u.Id == newComment.UserId)
};
item.Comments.Insert(0, comment);
return comment;
}
public IEnumerable<PtComment> GetAllForItem(int itemId)
{
var item = context.PtItems.Single(i => i.Id == itemId);
return item.Comments.Where(t => !t.DateDeleted.HasValue);
}
}
}

Просмотреть файл

@ -0,0 +1,110 @@
using System;
using System.Collections.Generic;
using System.Linq;
using RPS.Core.Models;
using RPS.Core.Models.Dto;
using RPS.Core.Models.Enums;
using RPS.Data.Helpers;
namespace RPS.Data
{
public class PtDashboardRepository : IPtDashboardRepository
{
private PtInMemoryContext context;
public PtDashboardRepository(PtInMemoryContext context)
{
this.context = context;
}
public PtDashboardFilteredIssues GetFilteredIssues(PtDashboardFilter filter)
{
var openItemSpec = new PtItemStatusSpecification(StatusEnum.Open);
var closedItemSpec = new PtItemStatusSpecification(StatusEnum.Closed);
var userIdSpec = new PtItemUserIdSpecification(filter.UserId);
var dateRangeSpec = new PtItemDateRangeSpecification(filter.DateStart, filter.DateEnd);
//var items = Find(userIdSpec.And(dateRangeSpec));
var itemsForUserAndDates = context.PtItems
.Where(userIdSpec.ToExpression().Compile())
.Where(dateRangeSpec.ToExpression().Compile());
var minDate = itemsForUserAndDates.Min(i => i.DateCreated);
var maxDate = itemsForUserAndDates.Max(i => i.DateCreated);
var categories = GetDates(minDate, maxDate);
var itemsByMonth = categories.Select(c => {
return itemsForUserAndDates.Where(i => {
var dc = i.DateCreated;
return dc.Month == c.Month && dc.Year == c.Year;
});
});
var categorizedAndDivided = itemsByMonth.Select(c => {
var openItemsForMonth = c.Where(openItemSpec.ToExpression().Compile()).ToList();
var closedItemsForMonth = c.Where(closedItemSpec.ToExpression().Compile()).ToList();
return new ItemsForMonth
{
Open = openItemsForMonth,
Closed = closedItemsForMonth
};
});
var issues = new PtDashboardFilteredIssues
{
Categories = categories,
MonthItems = categorizedAndDivided.ToList()
};
return issues;
}
public PtDashboardStatusCounts GetStatusCounts(PtDashboardFilter filter)
{
var openItemSpec = new PtItemStatusSpecification(StatusEnum.Open);
var closedItemSpec = new PtItemStatusSpecification(StatusEnum.Closed);
var userIdSpec = new PtItemUserIdSpecification(filter.UserId);
var dateRangeSpec = new PtItemDateRangeSpecification(filter.DateStart, filter.DateEnd);
var itemsForUserAndDates = context.PtItems
.Where(userIdSpec.ToExpression().Compile())
.Where(dateRangeSpec.ToExpression().Compile());
//var openItems = Find(openItemSpec.And(userIdSpec).And(dateRangeSpec)).ToList();
//var closedItems = Find(closedItemSpec.And(userIdSpec).And(dateRangeSpec)).ToList();
var openItems = itemsForUserAndDates.Where(openItemSpec.ToExpression().Compile()).ToList();
var closedItems = itemsForUserAndDates.Where(closedItemSpec.ToExpression().Compile()).ToList();
return new PtDashboardStatusCounts
{
OpenItemsCount = openItems.Count,
ClosedItemsCount = closedItems.Count
};
}
private IReadOnlyList<PtItem> Find(Specification<PtItem> specification)
{
return context.PtItems.Where(specification.ToExpression().Compile()).ToList();
}
private List<DateTime> GetDates(DateTime min, DateTime max)
{
List<DateTime> months = new List<DateTime>();
while (min <= max)
{
months.Add(new DateTime(min.Year, min.Month, 1));
min = min.AddMonths(1);
}
return months;
}
}
}

Просмотреть файл

@ -0,0 +1,45 @@
using Newtonsoft.Json;
using RPS.Core.Models;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
namespace RPS.Data
{
public class PtInMemoryContext
{
string resourceNameItems = "RPS.Data.GenData.fs-items.json";
string resourceNameUsers = "RPS.Data.GenData.fs-users.json";
List<PtItem> items;
List<PtUser> users;
public List<PtItem> PtItems { get { return items; } }
public List<PtUser> PtUsers { get { return users; } }
public PtInMemoryContext()
{
var assembly = Assembly.GetExecutingAssembly();
string contentsItems = "[]";
using (Stream stream = assembly.GetManifestResourceStream(resourceNameItems))
using (StreamReader file = new StreamReader(stream))
{
contentsItems = file.ReadToEnd();
}
items = JsonConvert.DeserializeObject<List<PtItem>>(contentsItems);
string contentsUsers = "[]";
using (Stream stream = assembly.GetManifestResourceStream(resourceNameUsers))
using (StreamReader file = new StreamReader(stream))
{
contentsUsers = file.ReadToEnd();
}
users = JsonConvert.DeserializeObject<List<PtUser>>(contentsUsers);
}
}
}

Просмотреть файл

@ -0,0 +1,99 @@
using RPS.Core.Models;
using RPS.Core.Models.Enums;
using System.Collections.Generic;
using System.Linq;
using RPS.Core.Models.Dto;
using System;
namespace RPS.Data
{
public class PtItemsRepository : IPtItemsRepository
{
private PtInMemoryContext context;
public PtItemsRepository(PtInMemoryContext context)
{
this.context = context;
}
public IEnumerable<PtItem> GetAll()
{
return context.PtItems;
}
public IEnumerable<PtItem> GetClosedItems()
{
return context.PtItems.Where(i => i.Status == StatusEnum.Closed &&
i.DateDeleted == null);
}
public PtItem GetItemById(int itemId)
{
var item = context.PtItems.SingleOrDefault(i => i.Id == itemId);
item.Tasks = item.Tasks.Where(t => !t.DateDeleted.HasValue).ToList();
return item;
}
public IEnumerable<PtItem> GetOpenItems()
{
return context.PtItems.Where(i => (i.Status == StatusEnum.Open ||
i.Status == StatusEnum.ReOpened) &&
i.DateDeleted == null);
}
public IEnumerable<PtItem> GetUserItems(int userId)
{
return context.PtItems.Where(i => i.Assignee.Id == userId &&
i.DateDeleted == null);
}
public PtItem AddNewItem(PtNewItem newItem)
{
var item1 = new PtItem
{
Id = context.PtItems.Max(i=>i.Id) + 1,
Title = newItem.Title,
Description = newItem.Description,
Type = newItem.TypeStr,
Assignee = context.PtUsers.Find(u=>u.Id == newItem.UserId),
Estimate = 0,
Priority = PriorityEnum.Medium,
Status = StatusEnum.Open,
Tasks = new List<PtTask>(),
Comments = new List<PtComment>(),
DateCreated = DateTime.Now,
DateModified = DateTime.Now
};
context.PtItems.Insert(0, item1);
return item1;
}
public PtItem UpdateItem(PtUpdateItem updateItem)
{
var idx = context.PtItems.FindIndex(i => i.Id == updateItem.Id);
var oldItem = context.PtItems.Find(i => i.Id == updateItem.Id);
var uItem = new PtItem
{
Id = updateItem.Id,
Title = updateItem.Title,
Description = updateItem.Description,
Type = updateItem.Type,
Assignee = context.PtUsers.Find(u => u.Id == updateItem.AssigneeId),
Estimate = updateItem.Estimate,
Priority = updateItem.Priority,
Status = updateItem.Status,
Tasks = oldItem.Tasks,
Comments = oldItem.Comments,
DateCreated = oldItem.DateCreated,
DateModified = DateTime.Now
};
context.PtItems[idx] = uItem;
return uItem;
}
}
}

Просмотреть файл

@ -0,0 +1,79 @@
using System;
using System.Collections.Generic;
using System.Linq;
using RPS.Core.Models;
using RPS.Core.Models.Dto;
namespace RPS.Data
{
public class PtTasksRepository : IPtTasksRepository
{
private PtInMemoryContext context;
public PtTasksRepository(PtInMemoryContext context)
{
this.context = context;
}
public PtTask AddNewTask(PtNewTask newTask)
{
var item = context.PtItems.Single(i => i.Id == newTask.ItemId);
PtTask task = new PtTask
{
Id = item.Tasks.Max(t=>t.Id) + 1,
Title = newTask.Title,
Completed = false,
DateCreated = DateTime.Now,
DateModified = DateTime.Now
};
item.Tasks.Insert(0, task);
return task;
}
public bool DeleteTask(int id, int itemId)
{
var item = context.PtItems.SingleOrDefault(i => i.Id == itemId);
if (item != null)
{
var task = item.Tasks.Single(t => t.Id == id);
task.DateDeleted = DateTime.Now;
return true;
}
else
{
return false;
}
}
public IEnumerable<PtTask> GetAllForItem(int itemId)
{
var item = context.PtItems.Single(i => i.Id == itemId);
return item.Tasks.Where(t => !t.DateDeleted.HasValue);
}
public PtTask UpdateTask(PtUpdateTask updateTask)
{
var item = context.PtItems.Single(i => i.Id == updateTask.ItemId);
var oldTask = item.Tasks.Single(t => t.Id == updateTask.Id);
var idx = item.Tasks.FindIndex(t => t.Id == updateTask.Id);
PtTask uTask = new PtTask
{
Id = oldTask.Id,
Title = updateTask.Title,
Completed = updateTask.Completed,
DateCreated = oldTask.DateCreated,
DateModified = DateTime.Now,
DateEnd = oldTask.DateEnd,
DateStart = oldTask.DateStart
};
item.Tasks[idx] = uTask;
return uTask;
}
}
}

Просмотреть файл

@ -0,0 +1,20 @@
using RPS.Core.Models;
using System.Collections.Generic;
namespace RPS.Data
{
public class PtUserRepository : IPtUserRepository
{
private PtInMemoryContext context;
public PtUserRepository(PtInMemoryContext context)
{
this.context = context;
}
public IEnumerable<PtUser> GetAll()
{
return context.PtUsers;
}
}
}

20
RPS.Data/RPS.Data.csproj Normal file
Просмотреть файл

@ -0,0 +1,20 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework>
</PropertyGroup>
<ItemGroup>
<Folder Include="GenData\" />
<Folder Include="Helpers\" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="12.0.1" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\RPS.Core\RPS.Core.csproj" />
</ItemGroup>
</Project>

Просмотреть файл

@ -0,0 +1,8 @@
@page
@model core_test.Pages.BacklogModel
@{
ViewData["Title"] = "Backlog";
}
<h2>Backlog</h2>

Просмотреть файл

@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
namespace core_test.Pages
{
public class BacklogModel : PageModel
{
public void OnGet()
{
}
}
}

Просмотреть файл

@ -0,0 +1,7 @@
@page
@model core_test.Pages.DashboardModel
@{
ViewData["Title"] = "Dashboard";
}
<h2>Dashboard</h2>

Просмотреть файл

@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
namespace core_test.Pages
{
public class DashboardModel : PageModel
{
public void OnGet()
{
}
}
}

Просмотреть файл

@ -0,0 +1,23 @@
@page
@model ErrorModel
@{
ViewData["Title"] = "Error";
}
<h1 class="text-danger">Error.</h1>
<h2 class="text-danger">An error occurred while processing your request.</h2>
@if (Model.ShowRequestId)
{
<p>
<strong>Request ID:</strong> <code>@Model.RequestId</code>
</p>
}
<h3>Development Mode</h3>
<p>
Swapping to <strong>Development</strong> environment will display more detailed information about the error that occurred.
</p>
<p>
<strong>Development environment should not be enabled in deployed applications</strong>, as it can result in sensitive information from exceptions being displayed to end users. For local debugging, development environment can be enabled by setting the <strong>ASPNETCORE_ENVIRONMENT</strong> environment variable to <strong>Development</strong>, and restarting the application.
</p>

Просмотреть файл

@ -0,0 +1,23 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
namespace RPS.Web.Pages
{
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
public class ErrorModel : PageModel
{
public string RequestId { get; set; }
public bool ShowRequestId => !string.IsNullOrEmpty(RequestId);
public void OnGet()
{
RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier;
}
}
}

Просмотреть файл

@ -0,0 +1,41 @@
@using Microsoft.AspNetCore.Http.Features
@{
var consentFeature = Context.Features.Get<ITrackingConsentFeature>();
var showBanner = !consentFeature?.CanTrack ?? false;
var cookieString = consentFeature?.CreateConsentCookie();
}
@if (showBanner)
{
<nav id="cookieConsent" class="navbar navbar-default navbar-fixed-top" role="alert">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#cookieConsent .navbar-collapse">
<span class="sr-only">Toggle cookie consent banner</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<span class="navbar-brand"><span class="glyphicon glyphicon-info-sign" aria-hidden="true"></span></span>
</div>
<div class="collapse navbar-collapse">
<p class="navbar-text">
Use this space to summarize your privacy and cookie use policy.
</p>
<div class="navbar-right">
<a asp-page="/Privacy" class="btn btn-info navbar-btn">Learn More</a>
<button type="button" class="btn btn-default navbar-btn" data-cookie-string="@cookieString">Accept</button>
</div>
</div>
</div>
</nav>
<script>
(function () {
document.querySelector("#cookieConsent button[data-cookie-string]").addEventListener("click", function (el) {
document.cookie = el.target.dataset.cookieString;
document.querySelector("#cookieConsent").classList.add("hidden");
}, false);
})();
</script>
}

Просмотреть файл

@ -0,0 +1,192 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>@ViewData["Title"] - RPS</title>
<link href="~/lib/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet" />
<link href="~/css/site.css" rel="stylesheet" />
<script src="~/lib/jquery/dist/jquery.min.js"></script>
</head>
<body>
<div class="navbar navbar-dark fixed-top bg-dark flex-md-nowrap p-0 shadow">
<a class="navbar-brand col-sm-3 col-md-2 mr-0">
<img src="~/images/rpslogo.png" class="logo">
</a>
<nav class="my-2 my-md-0 mr-md-3">
<a class="p-2 text-light" href="/Dashboard">Dashboard</a>
<a class="p-2 text-light" href="/Backlog">Backlog</a>
</nav>
</div>
<div class="container-fluid">
<div class="row">
<nav class="col-md-2 d-none d-md-block bg-light sidebar">
<div class="sidebar-sticky">
<ul class="nav flex-column">
<li class="nav-item">
<a class="nav-link active" routerLink="/dashboard">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"
fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
stroke-linejoin="round" class="feather feather-home">
<path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"></path>
<polyline points="9 22 9 12 15 12 15 22"></polyline>
</svg>
Dashboard <span class="sr-only">(current)</span>
</a>
</li>
<li class="nav-item">
<a class="nav-link" routerLink="/backlog/my">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"
fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
stroke-linejoin="round" class="feather feather-layers">
<polygon points="12 2 2 7 12 12 22 7 12 2"></polygon>
<polyline points="2 17 12 22 22 17"></polyline>
<polyline points="2 12 12 17 22 12"></polyline>
</svg>
My Items
</a>
</li>
<li class="nav-item">
<a class="nav-link" routerLink="/backlog/open">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"
fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
stroke-linejoin="round" class="feather feather-file">
<path d="M13 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V9z"></path>
<polyline points="13 2 13 9 20 9"></polyline>
</svg>
Open Items
</a>
</li>
<li class="nav-item">
<a class="nav-link" routerLink="/backlog/closed">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"
fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
stroke-linejoin="round" class="feather feather-shopping-cart">
<circle cx="9" cy="21" r="1"></circle>
<circle cx="20" cy="21" r="1"></circle>
<path d="M1 1h4l2.68 13.39a2 2 0 0 0 2 1.61h9.72a2 2 0 0 0 2-1.61L23 6H6"></path>
</svg>
Done Items
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"
fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
stroke-linejoin="round" class="feather feather-users">
<path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"></path>
<circle cx="9" cy="7" r="4"></circle>
<path d="M23 21v-2a4 4 0 0 0-3-3.87"></path>
<path d="M16 3.13a4 4 0 0 1 0 7.75"></path>
</svg>
Users
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"
fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
stroke-linejoin="round" class="feather feather-bar-chart-2">
<line x1="18" y1="20" x2="18" y2="10"></line>
<line x1="12" y1="20" x2="12" y2="4"></line>
<line x1="6" y1="20" x2="6" y2="14"></line>
</svg>
Reports
</a>
</li>
</ul>
<h6 class="sidebar-heading d-flex justify-content-between align-items-center px-3 mt-4 mb-1 text-muted">
<span>Saved reports</span>
<a class="d-flex align-items-center text-muted" href="#">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"
fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
stroke-linejoin="round" class="feather feather-plus-circle">
<circle cx="12" cy="12" r="10"></circle>
<line x1="12" y1="8" x2="12" y2="16"></line>
<line x1="8" y1="12" x2="16" y2="12"></line>
</svg>
</a>
</h6>
<ul class="nav flex-column mb-2">
<li class="nav-item">
<a class="nav-link" href="#">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"
fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
stroke-linejoin="round" class="feather feather-file-text">
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
<polyline points="14 2 14 8 20 8"></polyline>
<line x1="16" y1="13" x2="8" y2="13"></line>
<line x1="16" y1="17" x2="8" y2="17"></line>
<polyline points="10 9 9 9 8 9"></polyline>
</svg>
Current month
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"
fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
stroke-linejoin="round" class="feather feather-file-text">
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
<polyline points="14 2 14 8 20 8"></polyline>
<line x1="16" y1="13" x2="8" y2="13"></line>
<line x1="16" y1="17" x2="8" y2="17"></line>
<polyline points="10 9 9 9 8 9"></polyline>
</svg>
Last quarter
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"
fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
stroke-linejoin="round" class="feather feather-file-text">
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
<polyline points="14 2 14 8 20 8"></polyline>
<line x1="16" y1="13" x2="8" y2="13"></line>
<line x1="16" y1="17" x2="8" y2="17"></line>
<polyline points="10 9 9 9 8 9"></polyline>
</svg>
Social engagement
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"
fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
stroke-linejoin="round" class="feather feather-file-text">
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
<polyline points="14 2 14 8 20 8"></polyline>
<line x1="16" y1="13" x2="8" y2="13"></line>
<line x1="16" y1="17" x2="8" y2="17"></line>
<polyline points="10 9 9 9 8 9"></polyline>
</svg>
Year-end sale
</a>
</li>
</ul>
</div>
</nav>
<main role="main" class="col-md-9 ml-sm-auto col-lg-10 px-4">
@RenderBody()
</main>
</div>
<footer>
<p>&copy; 2019 - RPS</p>
</footer>
</div>
</body>
</html>

Просмотреть файл

@ -0,0 +1,18 @@
<environment include="Development">
<script src="~/lib/jquery-validation/dist/jquery.validate.js"></script>
<script src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js"></script>
</environment>
<environment exclude="Development">
<script src="https://ajax.aspnetcdn.com/ajax/jquery.validate/1.17.0/jquery.validate.min.js"
asp-fallback-src="~/lib/jquery-validation/dist/jquery.validate.min.js"
asp-fallback-test="window.jQuery && window.jQuery.validator"
crossorigin="anonymous"
integrity="sha384-rZfj/ogBloos6wzLGpPkkOr/gpkBNLZ6b6yLy4o+ok+t/SAKlL5mvXLr0OXNi1Hp">
</script>
<script src="https://ajax.aspnetcdn.com/ajax/jquery.validation.unobtrusive/3.2.9/jquery.validate.unobtrusive.min.js"
asp-fallback-src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js"
asp-fallback-test="window.jQuery && window.jQuery.validator && window.jQuery.validator.unobtrusive"
crossorigin="anonymous"
integrity="sha384-ifv0TYDWxBHzvAk2Z0n8R434FL1Rlv/Av18DXE43N/1rvHyOG4izKst0f2iSLdds">
</script>
</environment>

Просмотреть файл

@ -0,0 +1,3 @@
@using RPS.Web
@namespace RPS.Web.Pages
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

Просмотреть файл

@ -0,0 +1,3 @@
@{
Layout = "_Layout";
}

24
RPS.Web/Program.cs Normal file
Просмотреть файл

@ -0,0 +1,24 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
namespace RPS.Web
{
public class Program
{
public static void Main(string[] args)
{
CreateWebHostBuilder(args).Build().Run();
}
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>();
}
}

Просмотреть файл

@ -0,0 +1,27 @@
{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:59008",
"sslPort": 44374
}
},
"profiles": {
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"RPS.Web": {
"commandName": "Project",
"launchBrowser": true,
"applicationUrl": "https://localhost:5001;http://localhost:5000",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}

13
RPS.Web/RPS.Web.csproj Normal file
Просмотреть файл

@ -0,0 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.App" />
<PackageReference Include="Microsoft.AspNetCore.Razor.Design" Version="2.1.2" PrivateAssets="All" />
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="2.1.1" />
</ItemGroup>
</Project>

63
RPS.Web/Startup.cs Normal file
Просмотреть файл

@ -0,0 +1,63 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.HttpsPolicy;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
namespace RPS.Web
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.Configure<CookiePolicyOptions>(options =>
{
// This lambda determines whether user consent for non-essential cookies is needed for a given request.
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});
services.AddMvc()
.SetCompatibilityVersion(CompatibilityVersion.Version_2_1)
.AddRazorPagesOptions(options =>
{
options.Conventions.AddPageRoute("/Dashboard", "");
});
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseCookiePolicy();
app.UseMvc();
}
}
}

Просмотреть файл

@ -0,0 +1,9 @@
{
"Logging": {
"LogLevel": {
"Default": "Debug",
"System": "Information",
"Microsoft": "Information"
}
}
}

8
RPS.Web/appsettings.json Normal file
Просмотреть файл

@ -0,0 +1,8 @@
{
"Logging": {
"LogLevel": {
"Default": "Warning"
}
},
"AllowedHosts": "*"
}

Просмотреть файл

@ -0,0 +1,27 @@
.backlog-icon {
height: 20px;
}
.li-indicator {
height: 58px;
width: 10px;
text-align: left;
}
.li-indicator div {
width: 5px;
height: 58px;
}
.li-info-wrapper {
margin-left: 5px;
}
.li-title {
font-size: 14px;
color: #4b5833;
}
.pt-table-row {
cursor: pointer;
}

Просмотреть файл

@ -0,0 +1,12 @@
.comp-label strong {
font-size: 4em;
line-height: 1;
font-weight: 200;
display: block;
}
.comp-label small {
font-size: .7em;
text-transform: uppercase;
display: block;
}

Просмотреть файл

@ -0,0 +1,12 @@
.backlog-icon {
height: 20px;
}
.chitchat-item {
margin-top: 20px;
}
.chitchat-text {
color: #495057;
font-size: .9em;
}

Просмотреть файл

@ -0,0 +1,167 @@

.logo {
width: 100px;
}
.feather {
width: 16px;
height: 16px;
vertical-align: text-bottom;
}
/*
* Sidebar
*/
.sidebar {
position: fixed;
top: 0;
bottom: 0;
left: 0;
z-index: 100; /* Behind the navbar */
padding: 67px 0 0; /* Height of navbar */
box-shadow: inset -1px 0 0 rgba(0, 0, 0, .1);
}
.sidebar-sticky {
position: relative;
top: 0;
height: calc(100vh - 67px);
padding-top: .5rem;
overflow-x: hidden;
overflow-y: auto; /* Scrollable contents if viewport is shorter than content. */
}
@supports ((position: -webkit-sticky) or (position: sticky)) {
.sidebar-sticky {
position: -webkit-sticky;
position: sticky;
}
}
.sidebar .nav-link {
font-weight: 500;
color: #333;
}
.sidebar .nav-link .feather {
margin-right: 4px;
color: #999;
}
.sidebar .nav-link.active {
color: #007bff;
}
.sidebar .nav-link:hover .feather,
.sidebar .nav-link.active .feather {
color: inherit;
}
.sidebar-heading {
font-size: .75rem;
text-transform: uppercase;
}
/*
* Content
*/
[role="main"] {
padding-top: 133px; /* Space for fixed navbar */
}
@media (min-width: 768px) {
[role="main"] {
padding-top: 67px; /* Space for fixed navbar */
}
}
/*
* Navbar
*/
.navbar-brand {
padding-top: .75rem;
padding-bottom: .75rem;
font-size: 1rem;
background-color: rgba(0, 0, 0, .25);
box-shadow: inset -1px 0 0 rgba(0, 0, 0, .25);
}
.navbar .form-control {
padding: .75rem 1rem;
border-width: 0;
border-radius: 0;
}
.form-control-dark {
color: #fff;
background-color: rgba(255, 255, 255, .1);
border-color: rgba(255, 255, 255, .1);
}
.form-control-dark:focus {
border-color: transparent;
box-shadow: 0 0 0 3px rgba(255, 255, 255, .25);
}
.li-avatar {
background-color: #eeeeee;
width: 40px;
height: 40px;
}
.li-estimate {
font-size: 10px;
font-weight: bold;
color: #555a97;
}
.li-date {
font-size: 12px;
color: #555a97;
margin-left: 10px;
}
.indicator-pbi {
background-color: #527FD7;
}
.indicator-bug {
background-color: #D75252;
}
.indicator-chore {
background-color: #666666;
}
.indicator-impediment {
background-color: #D7C152;
}
.priority-critical {
color: #fff;
background-color: #820101;
}
.priority-high {
color: #fff;
background-color: #b27100;
}
.priority-medium {
color: #fff;
background-color: #0c6d00;
}
.priority-low {
color: #fff;
background-color: #002b6d;
}
.modal-body {
max-height: 400px;
overflow: scroll;
}

Двоичные данные
RPS.Web/wwwroot/favicon.ico Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 31 KiB

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Двоичные данные
RPS.Web/wwwroot/images/avatars/females/image-1.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 75 KiB

Двоичные данные
RPS.Web/wwwroot/images/avatars/females/image-10.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 58 KiB

Двоичные данные
RPS.Web/wwwroot/images/avatars/females/image-100.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 70 KiB

Двоичные данные
RPS.Web/wwwroot/images/avatars/females/image-101.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 63 KiB

Двоичные данные
RPS.Web/wwwroot/images/avatars/females/image-102.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 66 KiB

Двоичные данные
RPS.Web/wwwroot/images/avatars/females/image-103.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 73 KiB

Двоичные данные
RPS.Web/wwwroot/images/avatars/females/image-104.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 73 KiB

Двоичные данные
RPS.Web/wwwroot/images/avatars/females/image-105.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 61 KiB

Двоичные данные
RPS.Web/wwwroot/images/avatars/females/image-106.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 76 KiB

Двоичные данные
RPS.Web/wwwroot/images/avatars/females/image-107.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 62 KiB

Двоичные данные
RPS.Web/wwwroot/images/avatars/females/image-108.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 64 KiB

Двоичные данные
RPS.Web/wwwroot/images/avatars/females/image-109.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 66 KiB

Двоичные данные
RPS.Web/wwwroot/images/avatars/females/image-11.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 67 KiB

Двоичные данные
RPS.Web/wwwroot/images/avatars/females/image-110.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 72 KiB

Двоичные данные
RPS.Web/wwwroot/images/avatars/females/image-111.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 62 KiB

Двоичные данные
RPS.Web/wwwroot/images/avatars/females/image-112.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 82 KiB

Двоичные данные
RPS.Web/wwwroot/images/avatars/females/image-113.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 63 KiB

Двоичные данные
RPS.Web/wwwroot/images/avatars/females/image-114.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 61 KiB

Двоичные данные
RPS.Web/wwwroot/images/avatars/females/image-115.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 79 KiB

Двоичные данные
RPS.Web/wwwroot/images/avatars/females/image-116.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 69 KiB

Двоичные данные
RPS.Web/wwwroot/images/avatars/females/image-117.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 69 KiB

Двоичные данные
RPS.Web/wwwroot/images/avatars/females/image-118.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 60 KiB

Двоичные данные
RPS.Web/wwwroot/images/avatars/females/image-119.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 56 KiB

Двоичные данные
RPS.Web/wwwroot/images/avatars/females/image-12.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 78 KiB

Двоичные данные
RPS.Web/wwwroot/images/avatars/females/image-13.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 78 KiB

Двоичные данные
RPS.Web/wwwroot/images/avatars/females/image-14.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 72 KiB

Двоичные данные
RPS.Web/wwwroot/images/avatars/females/image-15.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 79 KiB

Двоичные данные
RPS.Web/wwwroot/images/avatars/females/image-16.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 55 KiB

Двоичные данные
RPS.Web/wwwroot/images/avatars/females/image-17.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 85 KiB

Двоичные данные
RPS.Web/wwwroot/images/avatars/females/image-18.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 61 KiB

Двоичные данные
RPS.Web/wwwroot/images/avatars/females/image-19.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 70 KiB

Двоичные данные
RPS.Web/wwwroot/images/avatars/females/image-2.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 68 KiB

Двоичные данные
RPS.Web/wwwroot/images/avatars/females/image-20.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 77 KiB

Двоичные данные
RPS.Web/wwwroot/images/avatars/females/image-21.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 76 KiB

Двоичные данные
RPS.Web/wwwroot/images/avatars/females/image-22.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 74 KiB

Двоичные данные
RPS.Web/wwwroot/images/avatars/females/image-23.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 66 KiB

Двоичные данные
RPS.Web/wwwroot/images/avatars/females/image-24.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 78 KiB

Двоичные данные
RPS.Web/wwwroot/images/avatars/females/image-25.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 79 KiB

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше