Merge remote-tracking branch 'refs/remotes/Microsoft/master'
|
After Width: | Height: | Size: 27 KiB |
@@ -1,4 +1,4 @@
|
||||
# Contoso Retail Data Warehose
|
||||
# Contoso Retail Data Warehouse
|
||||
|
||||
Loads data from a public Azure Storage Blob into the Contoso Retail Data Warehouse schema in Azure SQL Data Warehouse.
|
||||
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
<configuration>
|
||||
<runtime>
|
||||
<gcServer enabled="true"/>
|
||||
</runtime>
|
||||
</configuration>
|
||||
@@ -59,4 +59,4 @@ GO
|
||||
INNER JOIN Person.Person AS p ON h.CustomerID = p.BusinessEntityID
|
||||
INNER JOIN Production.Product AS pr ON d.ProductID = pr.ProductID
|
||||
) SELECT * FROM Prices;
|
||||
GO
|
||||
GO
|
||||
@@ -58,4 +58,4 @@ GO
|
||||
INNER JOIN Person.Person AS p ON h.CustomerID = p.BusinessEntityID
|
||||
INNER JOIN Production.Product AS pr ON d.ProductID = pr.ProductID
|
||||
) SELECT * FROM Prices;
|
||||
GO
|
||||
GO
|
||||
@@ -30,7 +30,7 @@ GO
|
||||
|
||||
-- Get Actual Execution Plan
|
||||
|
||||
-- Execute the stored procedure first with parameter value ‘WA’ – which will select 1% of data.
|
||||
-- Execute the stored procedure first with parameter value ‘WA’ – which will select 1% of data.
|
||||
DBCC FREEPROCCACHE
|
||||
GO
|
||||
EXEC CustomersByState 'WA'
|
||||
@@ -49,4 +49,4 @@ it is split into sub-partitions, which are also processed separately.
|
||||
This splitting process continues until each partition fits into available memory
|
||||
or until the maximum recursion level is reached.
|
||||
In this case it stopped at level 1.
|
||||
*/
|
||||
*/
|
||||
@@ -18,4 +18,4 @@ GO
|
||||
In SELECT node properties:
|
||||
MaxQueryMemory for maximum query memory grant under RG MAX_MEMORY_PERCENT hint
|
||||
MaxCompileMemory for maximum query optimizer memory in KB during compile under RG
|
||||
*/
|
||||
*/
|
||||
@@ -18,4 +18,4 @@ GO
|
||||
/*
|
||||
Observe the type of Spill = 1
|
||||
Means one pass over the data was enough to complete the sort in the Worktable
|
||||
*/
|
||||
*/
|
||||
@@ -8,4 +8,5 @@ obj/*
|
||||
*.lock.json
|
||||
Properties/PublishProfiles/*
|
||||
appsettings.Development.json
|
||||
appsettings.Production.json
|
||||
appsettings.Production.json
|
||||
*.ndjson
|
||||
@@ -28,17 +28,21 @@ namespace ProductCatalog.Controllers
|
||||
[HttpGet("login")]
|
||||
public void Login(string id)
|
||||
{
|
||||
try
|
||||
if(id=="0")
|
||||
ControllerContext.HttpContext.Session.Remove("CompanyID");
|
||||
else
|
||||
ControllerContext.HttpContext.Session.SetString("CompanyID", id);
|
||||
string referer;
|
||||
switch (Request.Query["page"])
|
||||
{
|
||||
if(id=="0")
|
||||
ControllerContext.HttpContext.Session.Remove("CompanyID");
|
||||
else
|
||||
ControllerContext.HttpContext.Session.SetString("CompanyID", id);
|
||||
Response.Redirect("/index.html");
|
||||
} catch (Exception ex)
|
||||
{
|
||||
Response.WriteAsync(ex.Message);
|
||||
case "index": referer = "/index.html"; break;
|
||||
case "report1": referer = "/report-pie.html"; break;
|
||||
case "report2": referer = "/report-multibar.html"; break;
|
||||
case "dashboard": referer = "/dashboard.html"; break;
|
||||
case "temporal": referer = "/temporal.html"; break;
|
||||
default: referer = "/index.html"; break;
|
||||
}
|
||||
Response.Redirect(referer);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using ProductCatalog.Models;
|
||||
using System;
|
||||
using System.Linq;
|
||||
|
||||
namespace ProductCatalog.Controllers
|
||||
{
|
||||
public class ProductCatalogController : Controller
|
||||
{
|
||||
private ProductCatalogContext _context;
|
||||
|
||||
public ProductCatalogController (ProductCatalogContext context)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public IActionResult Index()
|
||||
{
|
||||
ViewData["page"] = "index";
|
||||
return View(_context.Products.AsEnumerable());
|
||||
}
|
||||
|
||||
// POST api/ProductCatalog/Add
|
||||
public IActionResult Add(Product p)
|
||||
{
|
||||
try
|
||||
{
|
||||
_context.Products.Add(p);
|
||||
_context.SaveChanges();
|
||||
return Redirect("/ProductCatalog/Index");
|
||||
} catch (Exception)
|
||||
{
|
||||
return Redirect("/ProductCatalog/Index");
|
||||
}
|
||||
}
|
||||
|
||||
public IActionResult Report1()
|
||||
{
|
||||
ViewData["page"] = "report1";
|
||||
return View();
|
||||
}
|
||||
|
||||
public IActionResult Report2()
|
||||
{
|
||||
ViewData["page"] = "report2";
|
||||
return View();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,9 @@
|
||||
using Belgrade.SqlClient;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System;
|
||||
using System.Data.SqlClient;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
// For more information on enabling Web API for empty projects, visit http://go.microsoft.com/fwlink/?LinkID=397860
|
||||
@@ -16,18 +16,28 @@ namespace ProductCatalog.Controllers
|
||||
IQueryPipe sqlQuery = null;
|
||||
ICommand sqlCmd = null;
|
||||
private readonly string EMPTY_PRODUCTS_ARRAY = "{\"data\":[]}";
|
||||
private readonly byte[] EMPTY_PRODUCTS_ARRAY_GZIPPED = new byte[] {0x1F,0x8B,0x08,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0xAB,0x66,0x50,0x62,0x48,0x61,0x48,0x64,0x28,0x01,0x62,0x25,0x06,0x2B,0x86,0x68,0x86,0x58,0x86,0x5A,0x06,0x00,0xB3,0x4C,0x62,0xB2,0x16,0x00,0x00,0x00};
|
||||
private readonly byte[] EMPTY_PRODUCTS_ARRAY_GZIPPED = new byte[] { 0x1F, 0x8B, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0xAB, 0x66, 0x50, 0x62, 0x48, 0x61, 0x48, 0x64, 0x28, 0x01, 0x62, 0x25, 0x06, 0x2B, 0x86, 0x68, 0x86, 0x58, 0x86, 0x5A, 0x06, 0x00, 0xB3, 0x4C, 0x62, 0xB2, 0x16, 0x00, 0x00, 0x00 };
|
||||
private readonly ILogger logger;
|
||||
|
||||
public ProductController(IQueryPipe sqlQueryService, ICommand sqlCommandService)
|
||||
public ProductController(IQueryPipe sqlQueryService, ICommand sqlCommandService, ILogger<ProductController> logger)
|
||||
{
|
||||
this.sqlQuery = sqlQueryService;
|
||||
this.sqlCmd = sqlCommandService;
|
||||
this.logger = logger;
|
||||
}
|
||||
|
||||
// GET api/Product
|
||||
public async Task Get()
|
||||
{
|
||||
await sqlQuery.Stream(@"
|
||||
await sqlQuery
|
||||
.OnError(
|
||||
ex =>
|
||||
{
|
||||
logger.LogError("Error while trying to get products: {Error}\n{StackTrace}", ex.Message, ex.StackTrace);
|
||||
this.Response.StatusCode = 500;
|
||||
throw ex;
|
||||
})
|
||||
.Stream(@"
|
||||
select ProductID, Name, Color, Price, Quantity,
|
||||
JSON_VALUE(Data, '$.MadeIn') as MadeIn, JSON_QUERY(Tags) as Tags
|
||||
from Product
|
||||
@@ -64,7 +74,7 @@ FOR JSON PATH, WITHOUT_ARRAY_WRAPPER");
|
||||
cmd.Parameters.AddWithValue("id", id);
|
||||
await sqlQuery.Stream(cmd, Response.Body, "{}");
|
||||
}
|
||||
|
||||
|
||||
// POST api/Product
|
||||
[HttpPost]
|
||||
public async Task Post()
|
||||
@@ -116,7 +126,47 @@ FOR JSON PATH, WITHOUT_ARRAY_WRAPPER");
|
||||
var cmd = new SqlCommand("EXEC RestoreProduct @productid, @date");
|
||||
cmd.Parameters.AddWithValue("@productid", ProductId);
|
||||
cmd.Parameters.AddWithValue("@date", DateModified);
|
||||
this.sqlCmd.ExecuteNonQuery(cmd);
|
||||
this.sqlCmd
|
||||
.OnError(
|
||||
ex =>
|
||||
{
|
||||
logger.LogError("Error while trying to restore product with id {ProductID} from time {DateModified}.\n{Error}\n{StackTrace}", ProductId, DateModified, ex.Message, ex.StackTrace);
|
||||
this.Response.StatusCode = 500;
|
||||
throw ex;
|
||||
})
|
||||
.ExecuteNonQuery(cmd);
|
||||
}
|
||||
|
||||
|
||||
[HttpGet("Report1")]
|
||||
[Produces("application/json")]
|
||||
public async Task Report1()
|
||||
{
|
||||
await sqlQuery
|
||||
.Stream(@"
|
||||
select color as x, sum(quantity) as y
|
||||
from product
|
||||
where color is not null
|
||||
group by color
|
||||
for json path", Response.Body, EMPTY_PRODUCTS_ARRAY);
|
||||
}
|
||||
|
||||
|
||||
[HttpGet("Report2")]
|
||||
[Produces("application/json")]
|
||||
public async Task Report2()
|
||||
{
|
||||
await sqlQuery
|
||||
.Stream(@"
|
||||
select name as [key], [values].x, [values].y
|
||||
from company
|
||||
join (select companyid, color as x, sum(quantity) as y
|
||||
from product
|
||||
where color is not null
|
||||
group by companyid, color
|
||||
) as [values] on company.companyid = [values].companyid
|
||||
order by company.companyid
|
||||
for json auto", Response.Body, EMPTY_PRODUCTS_ARRAY);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Newtonsoft.Json;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace ProductCatalog.Models
|
||||
{
|
||||
[Table("Product")]
|
||||
public class Product
|
||||
{
|
||||
public int ProductId { get; set; }
|
||||
|
||||
public string Name { get; set; }
|
||||
|
||||
public string Color { get; set; }
|
||||
|
||||
public string Size { get; set; }
|
||||
|
||||
public decimal Price { get; set; }
|
||||
|
||||
public int Quantity { get; set; }
|
||||
|
||||
public int CompanyID { get; set; }
|
||||
|
||||
[NotMapped]
|
||||
public string[] Tags
|
||||
{
|
||||
get { return _Tags == null ? null : JsonConvert.DeserializeObject<string[]>(_Tags); }
|
||||
set { _Tags = JsonConvert.SerializeObject(value); }
|
||||
}
|
||||
|
||||
internal string _Tags { get; set; }
|
||||
|
||||
[NotMapped]
|
||||
public Properties Data
|
||||
{
|
||||
get { return (this._Data == null) ? null : JsonConvert.DeserializeObject<Properties>(this._Data); }
|
||||
set { _Data = JsonConvert.SerializeObject(value); }
|
||||
}
|
||||
|
||||
internal string _Data { get; set; }
|
||||
}
|
||||
|
||||
public class Properties
|
||||
{
|
||||
public string Type { get; set; }
|
||||
|
||||
public string MadeIn { get; set; }
|
||||
}
|
||||
|
||||
public class ProductCatalogContext : DbContext
|
||||
{
|
||||
public ProductCatalogContext(DbContextOptions<ProductCatalogContext> options)
|
||||
: base(options)
|
||||
{ }
|
||||
|
||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||
{
|
||||
modelBuilder.Entity<Product>()
|
||||
.Property(x => x.ProductId)
|
||||
.HasDefaultValueSql("NEXT VALUE FOR ProductId");
|
||||
|
||||
modelBuilder.Entity<Product>()
|
||||
.Property(b => b._Tags).HasColumnName("Tags");
|
||||
|
||||
modelBuilder.Entity<Product>()
|
||||
.Property(b => b._Data).HasColumnName("Data");
|
||||
}
|
||||
|
||||
public DbSet<Product> Products { get; set; }
|
||||
}
|
||||
|
||||
}
|
||||
@@ -7,7 +7,7 @@
|
||||
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.Props" Condition="'$(VSToolsPath)' != ''" />
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>7e230e5a-b0b6-4f56-9561-942fd1817b80</ProjectGuid>
|
||||
<RootNamespace>product_catalog</RootNamespace>
|
||||
<RootNamespace>ProductCatalog</RootNamespace>
|
||||
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">.\obj</BaseIntermediateOutputPath>
|
||||
<OutputPath Condition="'$(OutputPath)'=='' ">.\bin\</OutputPath>
|
||||
<TargetFrameworkVersion>v4.6</TargetFrameworkVersion>
|
||||
@@ -11,7 +11,7 @@
|
||||
"IIS Express": {
|
||||
"commandName": "IISExpress",
|
||||
"launchBrowser": true,
|
||||
"launchUrl": "index.html",
|
||||
"launchUrl": "ProductCatalog/Index",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
@@ -19,7 +19,7 @@
|
||||
"ProductCatalog": {
|
||||
"commandName": "Project",
|
||||
"launchBrowser": true,
|
||||
"launchUrl": "http://localhost:5000/index.html",
|
||||
"launchUrl": "http://localhost:5000/ProductCatalog/Index",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
@@ -1,12 +1,17 @@
|
||||
using Belgrade.SqlClient;
|
||||
using Belgrade.SqlClient.SqlDb;
|
||||
using Belgrade.SqlClient.SqlDb;
|
||||
using Belgrade.SqlClient.SqlDb.Rls;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using ProductCatalog.Models;
|
||||
using Serilog;
|
||||
#if NET46
|
||||
using Serilog.Sinks.MSSqlServer;
|
||||
#endif
|
||||
using System;
|
||||
using System.Data.SqlClient;
|
||||
using System.Linq;
|
||||
@@ -23,6 +28,24 @@ namespace ProductCatalog
|
||||
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
|
||||
.AddEnvironmentVariables();
|
||||
Configuration = builder.Build();
|
||||
#if NETCOREAPP1_0
|
||||
Log.Logger = new LoggerConfiguration()
|
||||
.WriteTo.RollingFile(new Serilog.Formatting.Json.JsonFormatter(), System.IO.Path.Combine(env.ContentRootPath, "log-{Date}.ndjson"))
|
||||
.CreateLogger();
|
||||
#endif
|
||||
#if NET46
|
||||
var columnOptions = new ColumnOptions();
|
||||
// Don't include the Properties XML column.
|
||||
columnOptions.Store.Remove(StandardColumn.Properties);
|
||||
columnOptions.Store.Remove(StandardColumn.MessageTemplate);
|
||||
columnOptions.Store.Remove(StandardColumn.Exception);
|
||||
// Do include the log event data as JSON.
|
||||
columnOptions.Store.Add(StandardColumn.LogEvent);
|
||||
|
||||
Log.Logger = new LoggerConfiguration()
|
||||
.WriteTo.MSSqlServer(Configuration["ConnectionStrings:BelgradeDemo"], "dbo.Logs", columnOptions: columnOptions)
|
||||
.CreateLogger();
|
||||
#endif
|
||||
}
|
||||
|
||||
public IConfigurationRoot Configuration { get; }
|
||||
@@ -30,30 +53,24 @@ namespace ProductCatalog
|
||||
// This method gets called by the runtime. Use this method to add services to the container.
|
||||
public void ConfigureServices(IServiceCollection services)
|
||||
{
|
||||
//string ConnString = Configuration.GetConnectionString("BelgradeDemo");
|
||||
string ConnString = Configuration["ConnectionStrings:BelgradeDemo"];
|
||||
|
||||
|
||||
services.AddDbContext<ProductCatalogContext>(options => options.UseSqlServer(new SqlConnection(ConnString)));
|
||||
|
||||
// Adding data access services/components.
|
||||
services.AddTransient<IQueryPipe>(
|
||||
sp =>
|
||||
{
|
||||
return new QueryPipeSessionContextAdapter(
|
||||
new QueryPipe(new SqlConnection(ConnString)),
|
||||
"CompanyID",
|
||||
() => GetCompanyIdFromSession(sp));
|
||||
});
|
||||
services.AddTransient(
|
||||
sp => new QueryPipe(new SqlConnection(ConnString))
|
||||
.AddRls("CompanyID",() => GetCompanyIdFromSession(sp))
|
||||
);
|
||||
|
||||
services.AddTransient<ICommand>(
|
||||
sp =>
|
||||
{
|
||||
return new CommandSessionContextAdapter(
|
||||
new Command(new SqlConnection(ConnString)),
|
||||
"CompanyID",
|
||||
() => GetCompanyIdFromSession(sp));
|
||||
});
|
||||
services.AddTransient(
|
||||
sp => new Command(new SqlConnection(ConnString))
|
||||
.AddRls("CompanyID", () => GetCompanyIdFromSession(sp))
|
||||
);
|
||||
|
||||
// Add framework services.
|
||||
//// Add framework services.
|
||||
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
|
||||
services.AddLogging();
|
||||
services.AddSession();
|
||||
services.AddMvc();
|
||||
}
|
||||
@@ -63,10 +80,17 @@ namespace ProductCatalog
|
||||
{
|
||||
loggerFactory.AddConsole(Configuration.GetSection("Logging"));
|
||||
loggerFactory.AddDebug();
|
||||
loggerFactory.AddSerilog();
|
||||
|
||||
app.UseSession();
|
||||
app.UseMvc();
|
||||
app.UseStaticFiles();
|
||||
app.UseMvc(routes =>
|
||||
{
|
||||
routes.MapRoute(
|
||||
name: "default",
|
||||
template: "{controller=ProductCatalog}/{action=Index}");
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -0,0 +1,124 @@
|
||||
<div class="container">
|
||||
<div class="clearfix">
|
||||
<h1 class="pull-left">Products<span id="snapshot"></span></h1>
|
||||
<button id="addProduct" type="button" class="btn btn-primary pull-right" data-toggle="modal" data-target="#modalAddProduct">
|
||||
<span class="glyphicon glyphicon-plus"></span> Add
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Bootstrap Modal (ADD) -->
|
||||
<div class="modal fade" id="modalAddProduct" tabindex="-1" role="dialog" aria-labelledby="myModalAddProductLabel">
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||
<h4 class="modal-title" id="myModalAddProductLabel">Add new product</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
|
||||
<!-- Bootstrap form -->
|
||||
<form id="AddProductForm" action="~/ProductCatalog/Add" method="post">
|
||||
<div class="form-group">
|
||||
<label for="Name">Title</label>
|
||||
<input type="text" class="form-control" name="Name" placeholder="Title">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="Color">Color</label>
|
||||
<select class="form-control" name="Color">
|
||||
<option value="">N/A</option>
|
||||
<option value="White">White</option>
|
||||
<option value="Silver">Silver</option>
|
||||
<option value="Magenta">Magenta</option>
|
||||
<option value="Red">Red</option>
|
||||
<option value="Multi">Multi</option>
|
||||
<option value="Black">Black</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="Price" class="field-label">Price</label>
|
||||
<input type="text" name="Price" class="form-control">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="Data.MadeIn" class="field-label">Made In</label>
|
||||
<input type="text" name="Data.MadeIn" class="form-control">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="Tags[]">Tags</label>
|
||||
<select class="form-control" name="Tags[]" multiple>
|
||||
<option value="sales">Sales</option>
|
||||
<option value="promo">Promo</option>
|
||||
<option value="new">New</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="Company">Company</label>
|
||||
<select class="form-control" name="CompanyID" id="CompanyList"></select>
|
||||
</div>
|
||||
|
||||
<!-- Allow form submission with keyboard without duplicating the dialog button -->
|
||||
<input type="submit" tabindex="-1" style="position:absolute; top:-1000px">
|
||||
|
||||
</form>
|
||||
<!-- End Bootstrap form -->
|
||||
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button id="cancelAddButton" type="reset" class="btn btn-link" data-dismiss="modal">Close</button>
|
||||
<button id="submitAddButton2" type="submit" class="btn btn-primary"><span class="glyphicon glyphicon-floppy-save"></span> Save</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- End Bootstrap modal -->
|
||||
<!-- JQuery DataTable -->
|
||||
<table id="example" class="table table-striped table-bordered" cellspacing="0" width="100%">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Product</th>
|
||||
<th>Color</th>
|
||||
<th>Price</th>
|
||||
<th>Quantity</th>
|
||||
<th>Made in</th>
|
||||
<th>Tags</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach (var product in Model)
|
||||
{
|
||||
<tr>
|
||||
<td>@product.Name</td>
|
||||
<td>@product.Color</td>
|
||||
<td>@product.Price</td>
|
||||
<td>@product.Quantity</td>
|
||||
<td>@(product.Data == null ? string.Empty : product.Data.MadeIn)</td>
|
||||
<td>@(product.Tags==null ? string.Empty : string.Join(", ", product.Tags))</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
<!-- End JQuery DataTable -->
|
||||
</div>
|
||||
|
||||
@section styles {
|
||||
<link href="~/media/css/jquery-ui/jquery-ui.css" rel="stylesheet" />
|
||||
<link href="~/media/css/dataTables.bootstrap.css" rel="stylesheet" />
|
||||
<link href="~/media/css/toastr.min.css" rel="stylesheet" />
|
||||
<link href="~/media/css/products.css" rel="stylesheet" />
|
||||
}
|
||||
|
||||
@section scripts {
|
||||
<script src="~/media/js/lib/jquery-ui.js"></script>
|
||||
<script src="~/media/js/lib/jquery.dataTables.js"></script>
|
||||
<script src="~/media/js/lib/jquery.dataTables.Bootstrap.js"></script>
|
||||
<script src="~/media/js/lib/jquery.html-template.js"></script>
|
||||
<script src="~/media/js/lib/jquery.serializejson.js"></script>
|
||||
<script src="~/media/js/lib/toastr.min.js"></script>
|
||||
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function () {
|
||||
$('#example').DataTable();
|
||||
});
|
||||
</script>
|
||||
|
||||
<script src="~/media/js/products-crud.js"></script>
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
<div class="testBlock"><svg id="test1"></svg></div>
|
||||
<div class="testBlock"><svg id="test2"></svg></div>
|
||||
|
||||
@section styles {
|
||||
<link href="~/media/js/lib/nvd3/nv.d3.min.css" rel="stylesheet" />
|
||||
<style>
|
||||
text {
|
||||
font: 12px sans-serif;
|
||||
}
|
||||
|
||||
.testBlock {
|
||||
display: block;
|
||||
float: left;
|
||||
height: 300px;
|
||||
width: 300px;
|
||||
}
|
||||
|
||||
html, body {
|
||||
margin: 0px;
|
||||
padding: 0px;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
}
|
||||
|
||||
@section scripts {
|
||||
<script src="~/media/js/lib/nvd3/d3.min.js" charset="utf-8"></script>
|
||||
<script src="~/media/js/lib/nvd3/nv.d3.min.js"></script>
|
||||
<script>
|
||||
$.ajax('/data/nvd3-pie.js', { "dataType": "json" })
|
||||
//$.ajax('/api/Product/Report1', { "dataType": "json" })
|
||||
.done(function (testdata) {
|
||||
|
||||
var width = 300;
|
||||
var height = 300;
|
||||
|
||||
nv.addGraph(function () {
|
||||
var chart = nv.models.pie()
|
||||
.width(width)
|
||||
.height(height)
|
||||
.labelType(function (d, i, values) {
|
||||
return values.key + ':' + values.value;
|
||||
})
|
||||
;
|
||||
|
||||
d3.select("#test1")
|
||||
.datum([testdata])
|
||||
.transition().duration(1200)
|
||||
.attr('width', width)
|
||||
.attr('height', height)
|
||||
.call(chart);
|
||||
|
||||
return chart;
|
||||
});
|
||||
|
||||
nv.addGraph(function () {
|
||||
var chart = nv.models.pie()
|
||||
.x(function (d) { return d.x; })
|
||||
.y(function (d) { return d.y; })
|
||||
.width(width)
|
||||
.height(height)
|
||||
.labelType('percent')
|
||||
.valueFormat(d3.format('%'))
|
||||
.donut(true);
|
||||
|
||||
d3.select("#test2")
|
||||
.datum([testdata])
|
||||
.transition().duration(1200)
|
||||
.attr('width', width)
|
||||
.attr('height', height)
|
||||
.call(chart);
|
||||
|
||||
return chart;
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
</script>
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
<div id="chart1">
|
||||
<svg></svg>
|
||||
</div>
|
||||
|
||||
|
||||
@section styles {
|
||||
<link href="~/media/js/lib/nvd3/nv.d3.min.css" rel="stylesheet" />
|
||||
<style>
|
||||
text {
|
||||
font: 12px sans-serif;
|
||||
}
|
||||
|
||||
svg {
|
||||
display: block;
|
||||
}
|
||||
|
||||
html, body, #chart1, svg {
|
||||
margin: 0px;
|
||||
padding: 0px;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
|
||||
}
|
||||
|
||||
@section scripts {
|
||||
<script src="~/media/js/lib/nvd3/d3.min.js" charset="utf-8"></script>
|
||||
<script src="~/media/js/lib/nvd3/nv.d3.min.js"></script>
|
||||
<script>
|
||||
$.ajax('/data/nvd3-multibar.js', { "dataType": "json" })
|
||||
//$.ajax('/api/Product/Report2', { "dataType": "json" })
|
||||
.done(function (exampleData) {
|
||||
|
||||
nv.addGraph(function () {
|
||||
var chart = nv.models.multiBarChart()
|
||||
.height(400)
|
||||
.reduceXTicks(true) //If 'false', every single x-axis tick label will be rendered.
|
||||
.rotateLabels(0) //Angle to rotate x-axis labels.
|
||||
.showControls(false) //Allow user to switch between 'Grouped' and 'Stacked' mode.
|
||||
.groupSpacing(0.1) //Distance between each group of bars.
|
||||
;
|
||||
|
||||
chart.yAxis
|
||||
.tickFormat(d3.format(',.1f'));
|
||||
|
||||
d3.select('#chart1 svg')
|
||||
.datum(exampleData)
|
||||
.call(chart);
|
||||
|
||||
nv.utils.windowResize(chart.update);
|
||||
|
||||
return chart;
|
||||
});
|
||||
});
|
||||
</script>
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
|
||||
<link rel="shortcut icon" type="image/ico" href="/favicon.ico">
|
||||
<meta name="viewport" content="initial-scale=1.0, maximum-scale=2.0">
|
||||
|
||||
<title>Product Catalog</title>
|
||||
<link href="~/media/css/Bootstrap.css" rel="stylesheet" />
|
||||
@RenderSection("styles", required: false)
|
||||
</head>
|
||||
<body id='@ViewData["page"]'>
|
||||
|
||||
<!-- Static navbar -->
|
||||
<nav class="navbar navbar-default">
|
||||
<div class="container-fluid">
|
||||
<div class="navbar-header">
|
||||
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
|
||||
<span class="sr-only">Toggle navigation</span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
</button>
|
||||
<a class="navbar-brand" href="/index.html">Product Catalog Demo</a>
|
||||
</div>
|
||||
<div id="navbar" class="navbar-collapse collapse">
|
||||
<ul class="nav navbar-nav">
|
||||
<li class="index"><a href="~/ProductCatalog/Index">Product list</a></li>
|
||||
</ul>
|
||||
<ul class="nav navbar-nav pull-right">
|
||||
<li class="dropdown pull-right">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Current user: <span class="UserGreeting">Admin</span><span class="caret"></span></a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a href='/api/Company/login?id=0&page=@ViewData["page"]' class="user-role">Admin</a></li>
|
||||
<li><a href='/api/Company/login?id=1&page=@ViewData["page"]' class="user-role">A Datum Corporation</a></li>
|
||||
<li><a href='/api/Company/login?id=2&page=@ViewData["page"]' class="user-role">Contoso, Ltd.</a></li>
|
||||
<li><a href='/api/Company/login?id=3&page=@ViewData["page"]' class="user-role">Consolidated Messenger</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div><!--/.nav-collapse -->
|
||||
</div><!--/.container-fluid -->
|
||||
</nav>
|
||||
<!-- End Static navbar -->
|
||||
|
||||
@RenderBody()
|
||||
|
||||
<script src="~/media/js/lib/jquery.js"></script>
|
||||
<script>$("li." + $("body")[0].id).addClass("active");</script>
|
||||
<script src="~/media/js/lib/Bootstrap.js"></script>
|
||||
<script src="~/media/js/rls.js"></script>
|
||||
|
||||
@RenderSection("scripts", required: false)
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,3 @@
|
||||
@{
|
||||
Layout = "_Layout";
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
{
|
||||
"Logging": {
|
||||
"IncludeScopes": false,
|
||||
"IncludeScopes": false,
|
||||
"LogLevel": {
|
||||
"Default": "Debug",
|
||||
"System": "Information",
|
||||
@@ -8,6 +8,6 @@
|
||||
}
|
||||
},
|
||||
"ConnectionStrings": {
|
||||
"BelgradeDemo": "Server=.;Database=ProductCatalog;Integrated Security=true"
|
||||
"BelgradeDemo": "Server=.\\SQLEXPRESS;Database=ProductCatalog;Integrated Security=true"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,17 +1,22 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"Belgrade.Sql.Client": "0.6.0",
|
||||
"Belgrade.Sql.Client": "0.6.2",
|
||||
"Microsoft.AspNetCore.Mvc": "1.0.0",
|
||||
"Microsoft.AspNetCore.Server.IISIntegration": "1.0.0",
|
||||
"Microsoft.AspNetCore.Server.Kestrel": "1.0.0",
|
||||
"Microsoft.AspNetCore.Session": "1.0.0",
|
||||
"Microsoft.AspNetCore.StaticFiles": "1.0.0",
|
||||
"Microsoft.EntityFrameworkCore.SqlServer": "1.0.1",
|
||||
"Microsoft.Extensions.Configuration.EnvironmentVariables": "1.0.0",
|
||||
"Microsoft.Extensions.Configuration.FileExtensions": "1.0.0",
|
||||
"Microsoft.Extensions.Configuration.Json": "1.0.0",
|
||||
"Microsoft.Extensions.Logging": "1.0.0",
|
||||
"Microsoft.Extensions.Logging.Console": "1.0.0",
|
||||
"Microsoft.Extensions.Logging.Debug": "1.0.0",
|
||||
"Serilog": "2.3.0",
|
||||
"Serilog.Extensions.Logging": "1.3.1",
|
||||
"Serilog.Sinks.PeriodicBatching": "2.1.0",
|
||||
"Serilog.Sinks.RollingFile": "3.3.0",
|
||||
"System.Data.SqlClient": "4.1.0"
|
||||
},
|
||||
|
||||
@@ -33,6 +38,7 @@
|
||||
},
|
||||
"net46": {
|
||||
"dependencies": {
|
||||
"Serilog.Sinks.MSSqlServer": "4.2.0"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -35,7 +35,7 @@ CREATE TABLE Product (
|
||||
GO
|
||||
|
||||
DECLARE @products NVARCHAR(MAX) =
|
||||
N'[{"ProductID":15,"Name":"Adjustable Race","Color":"Magenta","Size":"62","Price":100.0000,"Quantity":75,"CompanyID":1,"Data":{"Type":"Part","MadeIn":"China"},"DateModified":"2016-02-11T21:27:32"},{"ProductID":16,"Name":"Bearing Ball","Color":"Magenta","Size":"62","Price":15.9900,"Quantity":90,"CompanyID":2,"Data":{"ManufacturingCost":11.672700,"Type":"Part","MadeIn":"China"},"Tags":["promo"],"DateModified":"2016-02-11T21:27:32"},{"ProductID":17,"Name":"BB Ball Bearing","Color":"Magenta","Size":"62","Price":28.9900,"Quantity":80,"CompanyID":3,"Data":{"ManufacturingCost":21.162700,"Type":"Part","MadeIn":"China"},"DateModified":"2016-02-11T21:27:32"},{"ProductID":18,"Name":"Blade","Color":"Magenta","Size":"62","Price":18.0000,"Quantity":45,"CompanyID":4,"Data":{},"Tags":["new"],"DateModified":"2016-02-11T21:27:32"},{"ProductID":19,"Name":"Sport-100 Helmet, Red","Color":"Red","Size":"72","Price":41.9900,"Quantity":38,"CompanyID":3,"Data":{"ManufacturingCost":30.652700,"Type":"Еquipment","MadeIn":"China"},"Tags":["promo"],"DateModified":"2016-02-11T21:27:32"},{"ProductID":20,"Name":"Sport-100 Helmet, Black","Color":"Black","Size":"72","Price":31.4900,"Quantity":60,"CompanyID":1,"Data":{"ManufacturingCost":22.987700,"Type":"Еquipment","MadeIn":"China"},"Tags":["new","promo"],"DateModified":"2016-02-11T21:27:32"},{"ProductID":21,"Name":"Mountain Bike Socks, M","Color":"White","Size":"M","Price":560.9900,"Quantity":30,"CompanyID":2,"Data":{"Type":"Clothes"},"Tags":["sales","promo"],"DateModified":"2016-02-11T21:27:32"},{"ProductID":22,"Name":"Mountain Bike Socks, L","Color":"White","Size":"L","Price":120.9900,"Quantity":20,"CompanyID":3,"Data":{"ManufacturingCost":88.322700,"Type":"Clothes"},"Tags":["sales","promo"],"DateModified":"2016-02-11T21:27:32"},{"ProductID":23,"Name":"Long-Sleeve Logo Jersey, XL","Color":"Multi","Size":"XL","Price":44.9900,"Quantity":60,"CompanyID":4,"Data":{"ManufacturingCost":32.842700,"Type":"Clothes"},"Tags":["sales","promo"],"DateModified":"2016-02-11T21:27:32"},{"ProductID":24,"Name":"Road-650 Black, 52","Color":"Black","Size":"52","Price":704.6900,"Quantity":70,"CompanyID":5,"Data":{"Type":"Bike","MadeIn":"UK"},"DateModified":"2016-02-11T21:27:32"},{"ProductID":25,"Name":"Mountain-100 Silver, 38","Color":"Silver","Size":"38","Price":359.9900,"Quantity":45,"CompanyID":1,"Data":{"ManufacturingCost":262.792700,"Type":"Bike","MadeIn":"UK"},"Tags":["promo"],"DateModified":"2016-02-11T21:27:32"},{"ProductID":26,"Name":"Road-250 Black, 48","Color":"Black","Size":"48","Price":299.0200,"Quantity":25,"CompanyID":2,"Data":{"ManufacturingCost":218.284600,"Type":"Bike","MadeIn":"UK"},"Tags":["new","promo"],"DateModified":"2016-02-11T21:27:32"},{"ProductID":27,"Name":"ML Bottom Bracket","Price":101.2400,"Quantity":50,"CompanyID":3,"Data":{"Type":"Part","MadeIn":"China"},"DateModified":"2016-02-11T21:27:32"},{"ProductID":28,"Name":"HL Bottom Bracket","Price":121.4900,"Quantity":65,"CompanyID":4,"Data":{"ManufacturingCost":88.687700,"Type":"Part","MadeIn":"China"},"DateModified":"2016-02-11T21:27:32"}]'
|
||||
N'[{"ProductID":15,"Name":"Adjustable Race","Color":"Magenta","Size":"62","Price":100.0000,"Quantity":75,"CompanyID":1,"Data":{"Type":"Part","MadeIn":"China"},"DateModified":"2016-02-11T21:27:32"},{"ProductID":16,"Name":"Bearing Ball","Color":"Magenta","Size":"62","Price":15.9900,"Quantity":90,"CompanyID":2,"Data":{"ManufacturingCost":11.672700,"Type":"Part","MadeIn":"China"},"Tags":["promo"],"DateModified":"2016-02-11T21:27:32"},{"ProductID":17,"Name":"BB Ball Bearing","Color":"Magenta","Size":"62","Price":28.9900,"Quantity":80,"CompanyID":3,"Data":{"ManufacturingCost":21.162700,"Type":"Part","MadeIn":"China"},"DateModified":"2016-02-11T21:27:32"},{"ProductID":18,"Name":"Blade","Color":"Silver","Size":"62","Price":18.0000,"Quantity":45,"CompanyID":1,"Data":{},"Tags":["new"],"DateModified":"2016-02-11T21:27:32"},{"ProductID":19,"Name":"Sport-100 Helmet, Red","Color":"Black","Size":"72","Price":41.9900,"Quantity":38,"CompanyID":3,"Data":{"ManufacturingCost":30.652700,"Type":"Еquipment","MadeIn":"China"},"Tags":["promo"],"DateModified":"2016-02-11T21:27:32"},{"ProductID":20,"Name":"Sport-100 Helmet, Black","Color":"Black","Size":"72","Price":31.4900,"Quantity":60,"CompanyID":1,"Data":{"ManufacturingCost":22.987700,"Type":"Еquipment","MadeIn":"China"},"Tags":["new","promo"],"DateModified":"2016-02-11T21:27:32"},{"ProductID":21,"Name":"Mountain Bike Socks, M","Color":"White","Size":"M","Price":560.9900,"Quantity":30,"CompanyID":2,"Data":{"Type":"Clothes"},"Tags":["sales","promo"],"DateModified":"2016-02-11T21:27:32"},{"ProductID":22,"Name":"Mountain Bike Socks, L","Color":"White","Size":"L","Price":120.9900,"Quantity":20,"CompanyID":3,"Data":{"ManufacturingCost":88.322700,"Type":"Clothes"},"Tags":["sales","promo"],"DateModified":"2016-02-11T21:27:32"},{"ProductID":23,"Name":"Long-Sleeve Logo Jersey, XL","Color":"White","Size":"XL","Price":44.9900,"Quantity":60,"CompanyID":1,"Data":{"ManufacturingCost":32.842700,"Type":"Clothes"},"Tags":["sales","promo"],"DateModified":"2016-02-11T21:27:32"},{"ProductID":24,"Name":"Road-650 Black, 52","Color":"Black","Size":"52","Price":704.6900,"Quantity":70,"CompanyID":1,"Data":{"Type":"Bike","MadeIn":"UK"},"DateModified":"2016-02-11T21:27:32"},{"ProductID":25,"Name":"Mountain-100 Silver, 38","Color":"White","Size":"38","Price":359.9900,"Quantity":45,"CompanyID":1,"Data":{"ManufacturingCost":262.792700,"Type":"Bike","MadeIn":"UK"},"Tags":["promo"],"DateModified":"2016-02-11T21:27:32"},{"ProductID":26,"Name":"Road-250 Black, 48","Color":"Black","Size":"48","Price":299.0200,"Quantity":25,"CompanyID":2,"Data":{"ManufacturingCost":218.284600,"Type":"Bike","MadeIn":"UK"},"Tags":["new","promo"],"DateModified":"2016-02-11T21:27:32"},{"ProductID":27,"Name":"ML Bottom Bracket","Color":"Silver","Size":"36","Price":101.2400,"Quantity":50,"CompanyID":3,"Data":{"Type":"Part","MadeIn":"China"},"DateModified":"2016-02-11T21:27:32"},{"ProductID":28,"Name":"HL Bottom Bracket","Color":"Silver","Size":"36","Price":121.4900,"Quantity":65,"CompanyID":2,"Data":{"ManufacturingCost":88.687700,"Type":"Part","MadeIn":"China"},"DateModified":"2016-02-11T21:27:32"}]'
|
||||
INSERT INTO Product (ProductID, Name, Color, Size, Price, Quantity, CompanyID, Data, Tags, DateModified)
|
||||
SELECT ProductID, Name, Color, Size, Price, Quantity, CompanyID, Data, Tags, DateModified
|
||||
FROM OPENJSON (@products) WITH(
|
||||
@@ -53,6 +53,7 @@ CREATE TABLE Company (
|
||||
CompanyID int PRIMARY KEY DEFAULT (NEXT VALUE FOR CompanyId),
|
||||
Name nvarchar(50) NOT NULL,
|
||||
Address nvarchar(100) NULL,
|
||||
Contact nvarchar(100) NULL,
|
||||
Email nvarchar(50) NULL,
|
||||
Phone nvarchar(50) NULL,
|
||||
Postcode nvarchar(20) NULL,
|
||||
@@ -60,11 +61,11 @@ CREATE TABLE Company (
|
||||
GO
|
||||
|
||||
declare @companies nvarchar(max) =
|
||||
N'[{"CompanyID":1,"Name":"A Datum Corporation","Email":"msavic@datum.com","Address":"Suite 10, 183838 Southwest Boulevard, Surrey","Phone":"(381) 555-7639","Postcode":"46077"},{"CompanyID":2,"Name":"Contoso, Ltd.","Email":"zmisic@contoso.com","Address":"Unit 2, 2934 Night Road, Jolimont","Phone":"(360) 555-4901","Postcode":"98253"},{"CompanyID":3,"Name":"Consolidated Messenger","Email":"rputnik@consolidated-messanger.com","Address":"894 Market Day Street, West Mont","Phone":"(415) 555-1105","Postcode":"94101"}]'
|
||||
INSERT INTO Company (CompanyID, Name, Address, Email, Phone, Postcode)
|
||||
SELECT CompanyID, Name, Address, Email, Phone, Postcode
|
||||
N'[{"CompanyID":1,"Name":"A Datum Corporation","Email":"msavic@datum.com","Address":"Suite 10, 183838 Southwest Boulevard, Surrey","Contact":"Milunka Savic","Phone":"(381) 555-7639","Postcode":"46077"},{"CompanyID":2,"Name":"Contoso, Ltd.","Email":"zmisic@contoso.com","Address":"Unit 2, 2934 Night Road, Jolimont","Contact":"Zivojin Misic","Phone":"(360) 555-4901","Postcode":"98253"},{"CompanyID":3,"Name":"Consolidated Messenger","Contact":"Radomir Putnik","Email":"rputnik@consolidated-messanger.com","Address":"894 Market Day Street, West Mont","Phone":"(415) 555-1105","Postcode":"94101"}]'
|
||||
INSERT INTO Company (CompanyID, Name, Address, Email, Phone, Postcode, Contact)
|
||||
SELECT CompanyID, Name, Address, Email, Phone, Postcode, Contact
|
||||
FROM OPENJSON (@companies)
|
||||
WITH(CompanyID int, Name nvarchar(50), Address nvarchar(100), Email nvarchar(50), Phone nvarchar(50), Postcode nvarchar(20))
|
||||
WITH(CompanyID int, Name nvarchar(50), Address nvarchar(100), Email nvarchar(50), Phone nvarchar(50), Postcode nvarchar(20),Contact nvarchar(100))
|
||||
GO
|
||||
|
||||
DROP PROCEDURE IF EXISTS [dbo].[InsertProductFromJson]
|
||||
@@ -112,3 +113,15 @@ AS BEGIN
|
||||
|
||||
END
|
||||
GO
|
||||
DROP TABLE IF EXISTS Logs;
|
||||
GO
|
||||
CREATE TABLE Logs (
|
||||
Id int IDENTITY PRIMARY KEY,
|
||||
Message nvarchar(max) NULL,
|
||||
MessageTemplate nvarchar(max) NULL,
|
||||
Level nvarchar(128) NULL,
|
||||
TimeStamp datetimeoffset(7) NOT NULL,
|
||||
Exception nvarchar(max) NULL,
|
||||
Properties xml NULL,
|
||||
LogEvent nvarchar(max) NULL
|
||||
);
|
||||
@@ -0,0 +1,67 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<link href="media/css/Bootstrap.css" rel="stylesheet" />
|
||||
<link href="media/js/lib/nvd3/nv.d3.min.css" rel="stylesheet" />
|
||||
<script src="media/js/lib/jquery.js"></script>
|
||||
<script src="media/js/lib/jquery.html-template.js"></script>
|
||||
<script src="media/js/lib/nvd3/d3.min.js"></script>
|
||||
<script src="media/js/lib/nvd3/nv.d3.min.js"></script>
|
||||
<script src="media/js/lib/Bootstrap.js"></script>
|
||||
<script src="media/js/rls.js"></script>
|
||||
<script src="media/js/dashboard.js"></script>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<!-- Static navbar -->
|
||||
<nav class="navbar navbar-default">
|
||||
<div class="container-fluid">
|
||||
<div class="navbar-header">
|
||||
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
|
||||
<span class="sr-only">Toggle navigation</span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
</button>
|
||||
<a class="navbar-brand" href="/ProductCatalog/Index">Product Catalog Demo</a>
|
||||
</div>
|
||||
<div id="navbar" class="navbar-collapse collapse">
|
||||
<ul class="nav navbar-nav">
|
||||
<li><a href="index.html">Product List</a></li>
|
||||
<li class="active"><a href="#">Dashboard</a></li>
|
||||
<li><a href="temporal.html">Product History</a></li>
|
||||
</ul>
|
||||
<ul class="nav navbar-nav pull-right">
|
||||
<li class="dropdown pull-right">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Current user: <span class="UserGreeting">Admin</span><span class="caret"></span></a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a href="/api/Company/login?id=0&page=dashboard" class="user-role">Admin</a></li>
|
||||
<li><a href="/api/Company/login?id=1&page=dashboard" class="user-role">A Datum Corporation</a></li>
|
||||
<li><a href="/api/Company/login?id=2&page=dashboard" class="user-role">Contoso, Ltd.</a></li>
|
||||
<li><a href="/api/Company/login?id=3&page=dashboard" class="user-role">Consolidated Messenger</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div><!--/.nav-collapse -->
|
||||
</div><!--/.container-fluid -->
|
||||
</nav>
|
||||
<!-- End Static navbar -->
|
||||
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<div class="col-xs-3">
|
||||
<svg id="pie1"></svg>
|
||||
</div>
|
||||
<div class="col-xs-3">
|
||||
<svg id="pie2"></svg>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-xs-12">
|
||||
<svg id="chart1"></svg>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,104 @@
|
||||
{
|
||||
"data": [{
|
||||
"ProductID": 15,
|
||||
"Name": "Adjustable Race",
|
||||
"Color": "Magenta",
|
||||
"Price": 100.0000,
|
||||
"Quantity": 75,
|
||||
"MadeIn": "China"
|
||||
}, {
|
||||
"ProductID": 16,
|
||||
"Name": "Bearing Ball",
|
||||
"Color": "Magenta",
|
||||
"Price": 15.9900,
|
||||
"Quantity": 90,
|
||||
"MadeIn": "China",
|
||||
"Tags": ["promo"]
|
||||
}, {
|
||||
"ProductID": 17,
|
||||
"Name": "BB Ball Bearing",
|
||||
"Color": "Magenta",
|
||||
"Price": 28.9900,
|
||||
"Quantity": 80,
|
||||
"MadeIn": "China"
|
||||
}, {
|
||||
"ProductID": 18,
|
||||
"Name": "Blade",
|
||||
"Color": "Magenta",
|
||||
"Price": 18.0000,
|
||||
"Quantity": 45,
|
||||
"Tags": ["new"]
|
||||
}, {
|
||||
"ProductID": 19,
|
||||
"Name": "Sport-100 Helmet, Red",
|
||||
"Color": "Red",
|
||||
"Price": 41.9900,
|
||||
"Quantity": 38,
|
||||
"MadeIn": "China",
|
||||
"Tags": ["promo"]
|
||||
}, {
|
||||
"ProductID": 20,
|
||||
"Name": "Sport-100 Helmet, Black",
|
||||
"Color": "Black",
|
||||
"Price": 31.4900,
|
||||
"Quantity": 60,
|
||||
"MadeIn": "China",
|
||||
"Tags": ["new", "promo"]
|
||||
}, {
|
||||
"ProductID": 21,
|
||||
"Name": "Mountain Bike Socks, M",
|
||||
"Color": "White",
|
||||
"Price": 560.9900,
|
||||
"Quantity": 30,
|
||||
"Tags": ["sales", "promo"]
|
||||
}, {
|
||||
"ProductID": 22,
|
||||
"Name": "Mountain Bike Socks, L",
|
||||
"Color": "White",
|
||||
"Price": 120.9900,
|
||||
"Quantity": 20,
|
||||
"Tags": ["sales", "promo"]
|
||||
}, {
|
||||
"ProductID": 23,
|
||||
"Name": "Long-Sleeve Logo Jersey, XL",
|
||||
"Color": "Multi",
|
||||
"Price": 44.9900,
|
||||
"Quantity": 60,
|
||||
"Tags": ["sales", "promo"]
|
||||
}, {
|
||||
"ProductID": 24,
|
||||
"Name": "Road-650 Black, 52",
|
||||
"Color": "Black",
|
||||
"Price": 704.6900,
|
||||
"Quantity": 70,
|
||||
"MadeIn": "UK"
|
||||
}, {
|
||||
"ProductID": 25,
|
||||
"Name": "Mountain-100 Silver, 38",
|
||||
"Color": "Silver",
|
||||
"Price": 359.9900,
|
||||
"Quantity": 45,
|
||||
"MadeIn": "UK",
|
||||
"Tags": ["promo"]
|
||||
}, {
|
||||
"ProductID": 26,
|
||||
"Name": "Road-250 Black, 48",
|
||||
"Color": "Black",
|
||||
"Price": 299.0200,
|
||||
"Quantity": 25,
|
||||
"MadeIn": "UK",
|
||||
"Tags": ["new", "promo"]
|
||||
}, {
|
||||
"ProductID": 27,
|
||||
"Name": "ML Bottom Bracket",
|
||||
"Price": 101.2400,
|
||||
"Quantity": 50,
|
||||
"MadeIn": "China"
|
||||
}, {
|
||||
"ProductID": 28,
|
||||
"Name": "HL Bottom Bracket",
|
||||
"Price": 121.4900,
|
||||
"Quantity": 65,
|
||||
"MadeIn": "China"
|
||||
}]
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
[
|
||||
{
|
||||
"key": "A Datum Corporation",
|
||||
"values": [
|
||||
{ "x": "Black", "y": 31.4900 },
|
||||
{ "x": "Magenta", "y": 100.0000 },
|
||||
{ "x": "Silver", "y": 359.9900 }
|
||||
]
|
||||
},
|
||||
{
|
||||
"key": "Consolidated Messenger",
|
||||
"values": [
|
||||
{ "x": "Magenta", "y": 28.9900 },
|
||||
{ "x": "Red", "y": 41.9900 },
|
||||
{ "x": "White", "y": 120.9900 }
|
||||
]
|
||||
}, {
|
||||
"key": "Contoso, Ltd.",
|
||||
"values": [
|
||||
{ "x": "White", "y": 560.9900 },
|
||||
{ "x": "Magenta", "y": 15.9900 },
|
||||
{ "x": "Black", "y": 299.0200 }
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,9 @@
|
||||
[
|
||||
{ "x": "Red", "y": 5 },
|
||||
{ "x": "Silver", "y": 2 },
|
||||
{ "x": "Black", "y": 9 },
|
||||
{ "x": "Red", "y": 7 },
|
||||
{ "x": "Magenta", "y": 4 },
|
||||
{ "x": "White", "y": 3 },
|
||||
{ "x": "Blue", "y": 0.5 }
|
||||
]
|
||||
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
@@ -23,9 +23,9 @@
|
||||
<script src="media/js/lib/jquery.serializejson.js"></script>
|
||||
<script src="media/js/lib/toastr.min.js"></script>
|
||||
|
||||
<script src="media/js/products.js"></script>
|
||||
<script src="media/js/products-temporal.js"></script>
|
||||
|
||||
<script type="text/javascript" src="media/js/products.js"></script>
|
||||
<script src="media/js/products-crud.js"></script>
|
||||
<script src="media/js/rls.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<!-- Static navbar -->
|
||||
@@ -38,20 +38,22 @@
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
</button>
|
||||
<a class="navbar-brand" href="#">Product Catalog Demo</a>
|
||||
<a class="navbar-brand" href="/ProductCatalog/Index">Product Catalog Demo</a>
|
||||
</div>
|
||||
<div id="navbar" class="navbar-collapse collapse">
|
||||
<ul class="nav navbar-nav">
|
||||
<li class="active"><a href="#">Products</a></li>
|
||||
<li class="active"><a href="#">Product List</a></li>
|
||||
<li><a href="dashboard.html">Dashboard</a></li>
|
||||
<li><a href="temporal.html">Product History</a></li>
|
||||
</ul>
|
||||
<ul class="nav navbar-nav pull-right">
|
||||
<li class="dropdown pull-right">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Current user: <span class="UserGreeting">Admin</span><span class="caret"></span></a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a href="/api/Company/login?id=0" class="user-role">Admin</a></li>
|
||||
<li><a href="/api/Company/login?id=1" class="user-role">A Datum Corporation</a></li>
|
||||
<li><a href="/api/Company/login?id=2" class="user-role">Contoso, Ltd.</a></li>
|
||||
<li><a href="/api/Company/login?id=3" class="user-role">Consolidated Messenger</a></li>
|
||||
<li><a href="/api/Company/login?id=0&page=index" class="user-role">Admin</a></li>
|
||||
<li><a href="/api/Company/login?id=1&page=index" class="user-role">A Datum Corporation</a></li>
|
||||
<li><a href="/api/Company/login?id=2&page=index" class="user-role">Contoso, Ltd.</a></li>
|
||||
<li><a href="/api/Company/login?id=3&page=index" class="user-role">Consolidated Messenger</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
@@ -193,7 +195,6 @@
|
||||
<table id="example" class="table table-striped table-bordered" cellspacing="0" width="100%">
|
||||
<thead>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th>Product</th>
|
||||
<th>Color</th>
|
||||
<th>Price</th>
|
||||
@@ -202,7 +203,6 @@
|
||||
<th>Tags</th>
|
||||
<th>Edit</th>
|
||||
<th>Delete</th>
|
||||
<th>Restore</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody></tbody>
|
||||
|
Before Width: | Height: | Size: 106 KiB After Width: | Height: | Size: 106 KiB |
|
Before Width: | Height: | Size: 335 B After Width: | Height: | Size: 335 B |
|
Before Width: | Height: | Size: 207 B After Width: | Height: | Size: 207 B |
|
Before Width: | Height: | Size: 262 B After Width: | Height: | Size: 262 B |
|
Before Width: | Height: | Size: 262 B After Width: | Height: | Size: 262 B |
|
Before Width: | Height: | Size: 332 B After Width: | Height: | Size: 332 B |
|
Before Width: | Height: | Size: 280 B After Width: | Height: | Size: 280 B |
|
Before Width: | Height: | Size: 6.8 KiB After Width: | Height: | Size: 6.8 KiB |
|
Before Width: | Height: | Size: 4.4 KiB After Width: | Height: | Size: 4.4 KiB |
|
Before Width: | Height: | Size: 6.8 KiB After Width: | Height: | Size: 6.8 KiB |
|
Before Width: | Height: | Size: 6.8 KiB After Width: | Height: | Size: 6.8 KiB |
|
Before Width: | Height: | Size: 4.4 KiB After Width: | Height: | Size: 4.4 KiB |
|
Before Width: | Height: | Size: 686 B After Width: | Height: | Size: 686 B |
|
Before Width: | Height: | Size: 709 B After Width: | Height: | Size: 709 B |
|
Before Width: | Height: | Size: 894 B After Width: | Height: | Size: 894 B |
|
Before Width: | Height: | Size: 160 B After Width: | Height: | Size: 160 B |
|
Before Width: | Height: | Size: 148 B After Width: | Height: | Size: 148 B |
|
Before Width: | Height: | Size: 201 B After Width: | Height: | Size: 201 B |
|
Before Width: | Height: | Size: 158 B After Width: | Height: | Size: 158 B |
|
Before Width: | Height: | Size: 146 B After Width: | Height: | Size: 146 B |
@@ -0,0 +1,76 @@
|
||||
$(function () {
|
||||
|
||||
//$.ajax('data/nvd3-pie.js', { "dataType": "json" })
|
||||
$.ajax('api/Product/report1', { "dataType": "json" })
|
||||
.done(function (testdata) {
|
||||
|
||||
var width = 300;
|
||||
var height = 300;
|
||||
|
||||
nv.addGraph(function () {
|
||||
var chart =
|
||||
nv.models
|
||||
.pie()
|
||||
.width(width)
|
||||
.height(height)
|
||||
.labelType(function (d, i, values) {
|
||||
return values.key + ':' + values.value;
|
||||
});
|
||||
|
||||
d3.select("#pie1")
|
||||
.datum([testdata])
|
||||
.transition().duration(1200)
|
||||
.attr('width', width)
|
||||
.attr('height', height)
|
||||
.call(chart);
|
||||
|
||||
return chart;
|
||||
});
|
||||
|
||||
nv.addGraph(function () {
|
||||
var chart = nv.models.pie()
|
||||
.x(function (d) { return d.key; })
|
||||
.y(function (d) { return d.y; })
|
||||
.width(width)
|
||||
.height(height)
|
||||
.labelType('percent')
|
||||
.valueFormat(d3.format('%'))
|
||||
.donut(true);
|
||||
|
||||
d3.select("#pie2")
|
||||
.datum([testdata])
|
||||
.transition().duration(1200)
|
||||
.attr('width', width)
|
||||
.attr('height', height)
|
||||
.call(chart);
|
||||
|
||||
return chart;
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
//$.ajax('data/nvd3-multibar.js', { "dataType": "json" })
|
||||
$.ajax('api/Product/report2', { "dataType": "json" })
|
||||
.done(function (exampleData) {
|
||||
|
||||
nv.addGraph(function () {
|
||||
var chart = nv.models.multiBarChart()
|
||||
.reduceXTicks(true) //If 'false', every single x-axis tick label will be rendered.
|
||||
.rotateLabels(0) //Angle to rotate x-axis labels.
|
||||
.showControls(false) //Allow user to switch between 'Grouped' and 'Stacked' mode.
|
||||
.groupSpacing(0.1) //Distance between each group of bars.
|
||||
;
|
||||
|
||||
chart.yAxis
|
||||
.tickFormat(d3.format(',.1f'));
|
||||
|
||||
d3.select('svg#chart1')
|
||||
.datum(exampleData)
|
||||
.call(chart);
|
||||
|
||||
nv.utils.windowResize(chart.update);
|
||||
|
||||
return chart;
|
||||
});
|
||||
});
|
||||
});
|
||||