Reworked folders on disk
|
@ -0,0 +1,33 @@
|
||||||
|
root = true
|
||||||
|
|
||||||
|
[*]
|
||||||
|
end_of_line = crlf
|
||||||
|
tab_width = 4
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
insert_final_newline = true
|
||||||
|
|
||||||
|
[*.xml]
|
||||||
|
indent_style = tab
|
||||||
|
|
||||||
|
[*.xaml]
|
||||||
|
indent_style = tab
|
||||||
|
|
||||||
|
[{*.cs, *.ts}]
|
||||||
|
indent_style = tab
|
||||||
|
|
||||||
|
[*.json]
|
||||||
|
indent_style = tab
|
||||||
|
|
||||||
|
[*.*proj]
|
||||||
|
indent_style = tab
|
||||||
|
tab_width = 2
|
||||||
|
indent_size = 2
|
||||||
|
|
||||||
|
[*.js]
|
||||||
|
indent_style = space
|
||||||
|
|
||||||
|
[*.yml]
|
||||||
|
indent_style = space
|
||||||
|
|
||||||
|
[*.md]
|
||||||
|
indent_style = space
|
|
@ -25,8 +25,7 @@ bld/
|
||||||
# Visual Studio 2015 cache/options directory
|
# Visual Studio 2015 cache/options directory
|
||||||
.vs/
|
.vs/
|
||||||
# Uncomment if you have tasks that create the project's static files in wwwroot
|
# Uncomment if you have tasks that create the project's static files in wwwroot
|
||||||
#wwwroot/
|
wwwroot
|
||||||
**/wwwroot/playground
|
|
||||||
|
|
||||||
# MSTest test Results
|
# MSTest test Results
|
||||||
[Tt]est[Rr]esult*/
|
[Tt]est[Rr]esult*/
|
||||||
|
@ -153,7 +152,7 @@ publish/
|
||||||
PublishScripts/
|
PublishScripts/
|
||||||
|
|
||||||
# NuGet Packages
|
# NuGet Packages
|
||||||
#*.nupkg
|
*.nupkg
|
||||||
# The packages folder can be ignored because of Package Restore
|
# The packages folder can be ignored because of Package Restore
|
||||||
**/packages/*
|
**/packages/*
|
||||||
# except build/, which is used as an MSBuild target.
|
# except build/, which is used as an MSBuild target.
|
||||||
|
|
Двоичные данные
NugetPackages/universalimageloader.1.9.5.8565.nupkg
|
@ -1,23 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Diagnostics;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
using Uno.UI.Demo.AspnetShell.Models;
|
|
||||||
|
|
||||||
namespace Uno.UI.Demo.AspnetShell.Controllers
|
|
||||||
{
|
|
||||||
public class HomeController : Controller
|
|
||||||
{
|
|
||||||
public IActionResult Index()
|
|
||||||
{
|
|
||||||
return View();
|
|
||||||
}
|
|
||||||
|
|
||||||
public IActionResult Error()
|
|
||||||
{
|
|
||||||
return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,11 +0,0 @@
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace Uno.UI.Demo.AspnetShell.Models
|
|
||||||
{
|
|
||||||
public class ErrorViewModel
|
|
||||||
{
|
|
||||||
public string RequestId { get; set; }
|
|
||||||
|
|
||||||
public bool ShowRequestId => !string.IsNullOrEmpty(RequestId);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,25 +0,0 @@
|
||||||
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 Uno.UI.Demo.AspnetShell
|
|
||||||
{
|
|
||||||
public class Program
|
|
||||||
{
|
|
||||||
public static void Main(string[] args)
|
|
||||||
{
|
|
||||||
BuildWebHost(args).Run();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IWebHost BuildWebHost(string[] args) =>
|
|
||||||
WebHost.CreateDefaultBuilder(args)
|
|
||||||
.UseStartup<Startup>()
|
|
||||||
.Build();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1 +0,0 @@
|
||||||
<a href="Playground/index.html">Playground...</a>
|
|
|
@ -1,22 +0,0 @@
|
||||||
@model ErrorViewModel
|
|
||||||
@{
|
|
||||||
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>
|
|
|
@ -1,29 +0,0 @@
|
||||||
@using System.Reflection
|
|
||||||
@using Microsoft.DotNet.PlatformAbstractions
|
|
||||||
@{
|
|
||||||
var version = typeof(Program)
|
|
||||||
.GetTypeInfo()
|
|
||||||
.Assembly
|
|
||||||
.GetCustomAttribute<AssemblyFileVersionAttribute>()
|
|
||||||
?.Version
|
|
||||||
?? "0.0-dev";
|
|
||||||
}
|
|
||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8" />
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
||||||
<title>@ViewData["Title"]Uno</title>
|
|
||||||
|
|
||||||
<link rel="icon" type="image/png" href="~/images/favicon16.png" sizes="16x16">
|
|
||||||
<link rel="icon" type="image/png" href="~/images/favicon24.png" sizes="24x24">
|
|
||||||
<link rel="icon" type="image/png" href="~/images/favicon32.png" sizes="32x32">
|
|
||||||
<link rel="icon" type="image/png" href="~/images/favicon48.png" sizes="48x48">
|
|
||||||
<link rel="icon" type="image/png" href="~/images/favicon256.png" sizes="256x256">
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
@RenderBody()
|
|
||||||
|
|
||||||
@RenderSection("Scripts", required: false)
|
|
||||||
</body>
|
|
||||||
</html>
|
|
|
@ -1,18 +0,0 @@
|
||||||
<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.14.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-Fnqn3nxp3506LP/7Y3j/25BlWeA3PXTyT1l78LjECcPaKCV12TsZP7yyMxOe/G/k">
|
|
||||||
</script>
|
|
||||||
<script src="https://ajax.aspnetcdn.com/ajax/jquery.validation.unobtrusive/3.2.6/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-JrXK+k53HACyavUKOsL+NkmSesD2P+73eDMrbTtTk0h4RmOF8hF8apPlkp26JlyH">
|
|
||||||
</script>
|
|
||||||
</environment>
|
|
|
@ -1,3 +0,0 @@
|
||||||
@using Uno.UI.Demo.AspnetShell
|
|
||||||
@using Uno.UI.Demo.AspnetShell.Models
|
|
||||||
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
|
|
|
@ -1,3 +0,0 @@
|
||||||
@{
|
|
||||||
Layout = "_Layout";
|
|
||||||
}
|
|
Двоичные данные
Uno.UI.Demo.AspnetShell/wwwroot/favicon.ico
До Ширина: | Высота: | Размер: 1.1 KiB |
|
@ -1 +0,0 @@
|
||||||
google-site-verification: googlebbe0bf0f35d3c279.html
|
|
Двоичные данные
Uno.UI.Demo.AspnetShell/wwwroot/images/favicon16.png
До Ширина: | Высота: | Размер: 477 B |
Двоичные данные
Uno.UI.Demo.AspnetShell/wwwroot/images/favicon24.png
До Ширина: | Высота: | Размер: 802 B |
Двоичные данные
Uno.UI.Demo.AspnetShell/wwwroot/images/favicon256.png
До Ширина: | Высота: | Размер: 16 KiB |
Двоичные данные
Uno.UI.Demo.AspnetShell/wwwroot/images/favicon32.png
До Ширина: | Высота: | Размер: 1.1 KiB |
Двоичные данные
Uno.UI.Demo.AspnetShell/wwwroot/images/favicon48.png
До Ширина: | Высота: | Размер: 1.9 KiB |
|
@ -1,113 +0,0 @@
|
||||||
<UserControl x:Class="Uno.UI.Demo.Samples.Animations"
|
|
||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
|
||||||
xmlns:local="using:Uno.UI.Demo.Samples"
|
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
|
||||||
mc:Ignorable="">
|
|
||||||
<ScrollViewer>
|
|
||||||
<StackPanel Style="{StaticResource SamplePanelStyle}">
|
|
||||||
<VisualStateManager.VisualStateGroups>
|
|
||||||
<VisualStateGroup x:Name="AnimationTests">
|
|
||||||
<VisualState x:Name="Animated">
|
|
||||||
<Storyboard>
|
|
||||||
<!-- Animation 1 -->
|
|
||||||
<DoubleAnimation Storyboard.TargetProperty="Angle"
|
|
||||||
Storyboard.TargetName="RotateTransform1"
|
|
||||||
From="0"
|
|
||||||
To="360"
|
|
||||||
Duration="0:0:3" />
|
|
||||||
<DoubleAnimation Storyboard.TargetProperty="Opacity"
|
|
||||||
Storyboard.TargetName="Rectangle1"
|
|
||||||
To="0"
|
|
||||||
Duration="0:0:2" />
|
|
||||||
<!-- Animation 2 -->
|
|
||||||
<DoubleAnimation Storyboard.TargetProperty="ScaleX"
|
|
||||||
Storyboard.TargetName="ScaleTransform1"
|
|
||||||
To="0.5"
|
|
||||||
Duration="0:0:2">
|
|
||||||
<DoubleAnimation.EasingFunction>
|
|
||||||
<BounceEase Bounces="2"
|
|
||||||
Bounciness="3" />
|
|
||||||
</DoubleAnimation.EasingFunction>
|
|
||||||
</DoubleAnimation>
|
|
||||||
<DoubleAnimation Storyboard.TargetProperty="ScaleY"
|
|
||||||
Storyboard.TargetName="ScaleTransform1"
|
|
||||||
To="0.5"
|
|
||||||
Duration="0:0:2">
|
|
||||||
<DoubleAnimation.EasingFunction>
|
|
||||||
<BounceEase Bounces="2"
|
|
||||||
Bounciness="3" />
|
|
||||||
</DoubleAnimation.EasingFunction>
|
|
||||||
</DoubleAnimation>
|
|
||||||
<!-- Animation 3 -->
|
|
||||||
<DoubleAnimation Storyboard.TargetProperty="Y"
|
|
||||||
Storyboard.TargetName="TranslateTransform1"
|
|
||||||
From="0"
|
|
||||||
To="150"
|
|
||||||
Duration="0:0:2">
|
|
||||||
<DoubleAnimation.EasingFunction>
|
|
||||||
<BounceEase Bounces="2"
|
|
||||||
Bounciness="3" />
|
|
||||||
</DoubleAnimation.EasingFunction>
|
|
||||||
</DoubleAnimation>
|
|
||||||
<DoubleAnimation Storyboard.TargetProperty="X"
|
|
||||||
Storyboard.TargetName="TranslateTransform2"
|
|
||||||
From="0"
|
|
||||||
To="150"
|
|
||||||
Duration="0:0:2">
|
|
||||||
<DoubleAnimation.EasingFunction>
|
|
||||||
<CubicEase EasingMode="EaseInOut" />
|
|
||||||
</DoubleAnimation.EasingFunction>
|
|
||||||
</DoubleAnimation>
|
|
||||||
</Storyboard>
|
|
||||||
</VisualState>
|
|
||||||
<VisualState x:Name="NotAnimated" />
|
|
||||||
</VisualStateGroup>
|
|
||||||
</VisualStateManager.VisualStateGroups>
|
|
||||||
|
|
||||||
<TextBlock Style="{StaticResource SampleSectionTextBlockStyle}"
|
|
||||||
TextWrapping="Wrap"
|
|
||||||
Text="Animations using VisualStates, DoubleAnimations, EasingFunctions and RenderTransforms" />
|
|
||||||
|
|
||||||
<Button Content="Click me!"
|
|
||||||
Click="Button_Click" />
|
|
||||||
|
|
||||||
<Rectangle Fill="{StaticResource Color13Brush}"
|
|
||||||
Width="100"
|
|
||||||
Height="100"
|
|
||||||
x:Name="Rectangle1"
|
|
||||||
Opacity="1">
|
|
||||||
<Rectangle.RenderTransform>
|
|
||||||
<RotateTransform CenterX="50"
|
|
||||||
CenterY="50"
|
|
||||||
x:Name="RotateTransform1" />
|
|
||||||
</Rectangle.RenderTransform>
|
|
||||||
</Rectangle>
|
|
||||||
<Rectangle Fill="{StaticResource Color16Brush}"
|
|
||||||
Width="100"
|
|
||||||
Height="100">
|
|
||||||
<Rectangle.RenderTransform>
|
|
||||||
<ScaleTransform CenterX="50"
|
|
||||||
CenterY="50"
|
|
||||||
x:Name="ScaleTransform1" />
|
|
||||||
|
|
||||||
</Rectangle.RenderTransform>
|
|
||||||
</Rectangle>
|
|
||||||
|
|
||||||
<Rectangle Fill="{StaticResource Color15Brush}"
|
|
||||||
Width="100"
|
|
||||||
Height="100">
|
|
||||||
<Rectangle.RenderTransform>
|
|
||||||
<TranslateTransform x:Name="TranslateTransform1" />
|
|
||||||
</Rectangle.RenderTransform>
|
|
||||||
</Rectangle>
|
|
||||||
<Rectangle Fill="{StaticResource Color14Brush}"
|
|
||||||
Width="100"
|
|
||||||
Height="100">
|
|
||||||
<Rectangle.RenderTransform>
|
|
||||||
<TranslateTransform x:Name="TranslateTransform2" />
|
|
||||||
</Rectangle.RenderTransform>
|
|
||||||
</Rectangle>
|
|
||||||
</StackPanel>
|
|
||||||
</ScrollViewer>
|
|
||||||
</UserControl>
|
|
|
@ -1,17 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
|
||||||
<PropertyGroup Label="Globals">
|
|
||||||
<ProjectGuid>6279c845-92f8-4333-ab99-3d213163593c</ProjectGuid>
|
|
||||||
<MinimumVisualStudioVersion>14.0</MinimumVisualStudioVersion>
|
|
||||||
</PropertyGroup>
|
|
||||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
|
||||||
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.Common.Default.props" />
|
|
||||||
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.Common.props" />
|
|
||||||
<PropertyGroup />
|
|
||||||
<Import Project="Uno.UI.Demo.Shared.projitems" Label="Shared" />
|
|
||||||
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.CSharp.targets" />
|
|
||||||
<ItemGroup>
|
|
||||||
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="1.1.1" />
|
|
||||||
<PackageReference Include="Microsoft.Extensions.Logging.Filter" Version="1.1.1" />
|
|
||||||
</ItemGroup>
|
|
||||||
</Project>
|
|
|
@ -1,49 +0,0 @@
|
||||||
var Uno;
|
|
||||||
(function (Uno) {
|
|
||||||
var UI;
|
|
||||||
(function (UI) {
|
|
||||||
var Demo;
|
|
||||||
(function (Demo) {
|
|
||||||
var Analytics = /** @class */ (function () {
|
|
||||||
function Analytics() {
|
|
||||||
}
|
|
||||||
Analytics.reportPageView = function (screenName, appName) {
|
|
||||||
if (appName === void 0) { appName = "Uno.UI.Demo.Playground"; }
|
|
||||||
if (Analytics.init(screenName, appName)) {
|
|
||||||
return "ok";
|
|
||||||
}
|
|
||||||
var gtag = window.gtag;
|
|
||||||
if (gtag) {
|
|
||||||
gtag("event", "screen_view", {
|
|
||||||
screen_name: screenName,
|
|
||||||
app_name: appName
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
console.error("Google Analytics not present, can't report page view for " + screenName + ".");
|
|
||||||
}
|
|
||||||
return "ok";
|
|
||||||
};
|
|
||||||
Analytics.init = function (screenName, appName) {
|
|
||||||
if (Analytics.isLoaded) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
var script = "\n\twindow.dataLayer = window.dataLayer || [];\n\tfunction gtag() { dataLayer.push(arguments); }\n\tgtag('js', new Date());\n\tgtag('config', 'UA-26688675-3');\n\tgtag(\"event\", \"screen_view\", {screen_name: \"" + screenName + "\", app_name: \"" + appName + "\"});";
|
|
||||||
var script1 = document.createElement("script");
|
|
||||||
script1.type = "text/javascript";
|
|
||||||
script1.src = "https://www.googletagmanager.com/gtag/js?id=UA-26688675-3";
|
|
||||||
document.body.appendChild(script1);
|
|
||||||
var script2 = document.createElement("script");
|
|
||||||
script2.type = "text/javascript";
|
|
||||||
script2.innerText = script;
|
|
||||||
document.body.appendChild(script2);
|
|
||||||
Analytics.isLoaded = true;
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
Analytics.isLoaded = false;
|
|
||||||
return Analytics;
|
|
||||||
}());
|
|
||||||
Demo.Analytics = Analytics;
|
|
||||||
})(Demo = UI.Demo || (UI.Demo = {}));
|
|
||||||
})(UI = Uno.UI || (Uno.UI = {}));
|
|
||||||
})(Uno || (Uno = {}));
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
assembly-versioning-scheme: MajorMinorPatch
|
||||||
|
mode: ContinuousDeployment
|
||||||
|
next-version: 1.3.0
|
||||||
|
continuous-delivery-fallback-tag: ""
|
||||||
|
branches:
|
||||||
|
master:
|
||||||
|
tag: dev
|
||||||
|
stable:
|
||||||
|
tag:
|
||||||
|
dev/.*?/(.*?):
|
||||||
|
tag: dev.{BranchName}
|
||||||
|
projects/(.*?):
|
||||||
|
tag: proj-{BranchName}
|
||||||
|
ignore:
|
||||||
|
sha: []
|
14
nuget.config
|
@ -1,14 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<configuration>
|
|
||||||
<activePackageSource>
|
|
||||||
<add key="All" value="(Aggregate source)" />
|
|
||||||
</activePackageSource>
|
|
||||||
<packageSources>
|
|
||||||
<add key="LocalCache" value=".\NugetPackages" />
|
|
||||||
<add key="api.nuget.org" value="https://api.nuget.org/v3/index.json" />
|
|
||||||
<add key="Microsoft and .NET" value="https://www.nuget.org/api/v2/curated-feeds/microsoftdotnet/" />
|
|
||||||
</packageSources>
|
|
||||||
<disabledPackageSources>
|
|
||||||
<add key="Microsoft and .NET" value="true" />
|
|
||||||
</disabledPackageSources>
|
|
||||||
</configuration>
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>netstandard2.0</TargetFramework>
|
||||||
|
<GetVersion>false</GetVersion>
|
||||||
|
<UpdateAssemblyInfo>false</UpdateAssemblyInfo>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="..\.vsts-ci.yml" Link=".vsts-ci.yml" />
|
||||||
|
<None Include="build.proj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="GitVersionTask" Version="3.6.5" />
|
||||||
|
<PackageReference Include="MSBuildTasks" Version="1.5.0.235" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
|
@ -0,0 +1 @@
|
||||||
|
Uno Gallery
|
|
@ -0,0 +1,34 @@
|
||||||
|
<Project DefaultTargets="UpdateVersion">
|
||||||
|
<Import Project="obj\Build.csproj.nuget.g.props" Condition="Exists('obj\Build.csproj.nuget.g.props')" />
|
||||||
|
<Import Project="obj\Build.csproj.nuget.g.targets" Condition="Exists('obj\Build.csproj.nuget.g.targets')" />
|
||||||
|
|
||||||
|
<Target Name="UpdateVersion" DependsOnTargets="GetVersion">
|
||||||
|
|
||||||
|
<Message Text="Updating versions" />
|
||||||
|
|
||||||
|
<XmlUpdate XmlFileName="..\Uno.Playground.iOS\Info.plist"
|
||||||
|
XPath="//plist/dict/key[text() = 'CFBundleShortVersionString']/following-sibling::string[1]"
|
||||||
|
Value="$(GITVERSION_MAJOR).$(GITVERSION_MINOR)" />
|
||||||
|
|
||||||
|
<XmlUpdate XmlFileName="..\Uno.Playground.iOS\Info.plist"
|
||||||
|
XPath="//plist/dict/key[text() = 'CFBundleVersion']/following-sibling::string[1]"
|
||||||
|
Value="$(GITVERSION_COMMITSSINCEVERSIONSOURCE)" />
|
||||||
|
|
||||||
|
<XmlUpdate
|
||||||
|
XmlFileName="..\Uno.Playground.Droid\Properties\AndroidManifest.xml"
|
||||||
|
XPath="/manifest/@android:versionCode"
|
||||||
|
Value="$(GITVERSION_COMMITSSINCEVERSIONSOURCE)"
|
||||||
|
Namespace="http://schemas.android.com/apk/res/android"
|
||||||
|
Prefix="android" />
|
||||||
|
|
||||||
|
<XmlUpdate
|
||||||
|
XmlFileName="..\Uno.Playground.UWP\package.appxmanifest"
|
||||||
|
XPath="/x:Package/x:Identity/@Version"
|
||||||
|
Value="$(GITVERSION_MAJOR).$(GITVERSION_MINOR).$(GITVERSION_COMMITSSINCEVERSIONSOURCE).0"
|
||||||
|
Namespace="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
|
||||||
|
Prefix="x"/>
|
||||||
|
|
||||||
|
<Message Text="Assm: Ver $(GITVERSION_MAJOR).$(GITVERSION_MINOR).$(GITVERSION_COMMITSSINCEVERSIONSOURCE)" />
|
||||||
|
</Target>
|
||||||
|
|
||||||
|
</Project>
|
|
@ -0,0 +1,8 @@
|
||||||
|
namespace Uno.UI.Demo.Api
|
||||||
|
{
|
||||||
|
internal static class Constants
|
||||||
|
{
|
||||||
|
internal const string SamplesTableName = "Samples";
|
||||||
|
internal const string DefaultCategoryIdForSaving = "default";
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.ServiceModel.Channels;
|
||||||
|
using System.Web;
|
||||||
|
|
||||||
|
namespace Uno.UI.Demo.AspnetShell.Helpers
|
||||||
|
{
|
||||||
|
public static class HttpRequestMessageExtensions
|
||||||
|
{
|
||||||
|
public static string GetClientIp(this HttpRequestMessage request)
|
||||||
|
{
|
||||||
|
if (request.Properties.ContainsKey("MS_HttpContext"))
|
||||||
|
{
|
||||||
|
return ((HttpContextWrapper)request.Properties["MS_HttpContext"]).Request.UserHostAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (request.Properties.ContainsKey(RemoteEndpointMessageProperty.Name))
|
||||||
|
{
|
||||||
|
RemoteEndpointMessageProperty prop;
|
||||||
|
prop = (RemoteEndpointMessageProperty)request.Properties[RemoteEndpointMessageProperty.Name];
|
||||||
|
return prop.Address;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,39 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.WindowsAzure.Storage.Table;
|
||||||
|
|
||||||
|
namespace Uno.UI.Demo.Api.Helpers
|
||||||
|
{
|
||||||
|
public static class TableQueryExtensions
|
||||||
|
{
|
||||||
|
public static TableQuery<T> SelectColumn<T>(
|
||||||
|
this TableQuery<T> tableQuery,
|
||||||
|
string column)
|
||||||
|
where T : ITableEntity, new()
|
||||||
|
{
|
||||||
|
if (tableQuery.SelectColumns == null)
|
||||||
|
{
|
||||||
|
tableQuery.SelectColumns = new List<string>();
|
||||||
|
}
|
||||||
|
|
||||||
|
tableQuery.SelectColumns.Add(column);
|
||||||
|
|
||||||
|
return tableQuery;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Task<TableQuerySegment<T>> ExecuteQuery<T>(
|
||||||
|
this CloudTable cloudTable,
|
||||||
|
TableQuery<T> query,
|
||||||
|
CancellationToken ct)
|
||||||
|
where T : ITableEntity, new()
|
||||||
|
{
|
||||||
|
return cloudTable.ExecuteQuerySegmentedAsync(
|
||||||
|
query,
|
||||||
|
token: null,
|
||||||
|
requestOptions: null,
|
||||||
|
operationContext: null,
|
||||||
|
cancellationToken: ct);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,52 @@
|
||||||
|
using Microsoft.WindowsAzure.Storage.Table;
|
||||||
|
|
||||||
|
namespace Uno.UI.Demo.Api.Models
|
||||||
|
{
|
||||||
|
public class Sample : TableEntity
|
||||||
|
{
|
||||||
|
public Sample()
|
||||||
|
{
|
||||||
|
PartitionKey = nameof(Sample);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Sample(string id) : this()
|
||||||
|
{
|
||||||
|
RowKey = id;
|
||||||
|
ETag = "*";
|
||||||
|
}
|
||||||
|
|
||||||
|
[IgnoreProperty]
|
||||||
|
public string Id => RowKey;
|
||||||
|
|
||||||
|
public string Category { get; set; }
|
||||||
|
|
||||||
|
public string Title { get; set; }
|
||||||
|
|
||||||
|
public string Description { get; set; }
|
||||||
|
|
||||||
|
public string Xaml { get; set; }
|
||||||
|
|
||||||
|
public string Data { get; set; }
|
||||||
|
|
||||||
|
[IgnoreProperty]
|
||||||
|
public string[] ParsedKeywords
|
||||||
|
{
|
||||||
|
get => Keywords?.Split(';') ?? new string[] {};
|
||||||
|
set => Keywords = value == null ? "" : string.Join(";", value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Keywords { get; set; }
|
||||||
|
|
||||||
|
public string IpAddress { get; set; }
|
||||||
|
|
||||||
|
public string App { get; set; }
|
||||||
|
|
||||||
|
public string UserAgent { get; set; }
|
||||||
|
|
||||||
|
public long ListingOrder { get; set; } = 0;
|
||||||
|
|
||||||
|
public string PathData { get; set; }
|
||||||
|
|
||||||
|
public string AccentPathData { get; set; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
using Microsoft.WindowsAzure.Storage.Table;
|
||||||
|
|
||||||
|
namespace Uno.UI.Demo.Api.Models
|
||||||
|
{
|
||||||
|
public class SampleCategory : TableEntity
|
||||||
|
{
|
||||||
|
public SampleCategory()
|
||||||
|
{
|
||||||
|
PartitionKey = nameof(SampleCategory);
|
||||||
|
}
|
||||||
|
|
||||||
|
public SampleCategory(string id) : this()
|
||||||
|
{
|
||||||
|
RowKey = id;
|
||||||
|
ETag = "*";
|
||||||
|
}
|
||||||
|
|
||||||
|
[IgnoreProperty]
|
||||||
|
public string Id => RowKey;
|
||||||
|
|
||||||
|
public string Title { get; set; }
|
||||||
|
|
||||||
|
public long ListingOrder { get; set; } = 0;
|
||||||
|
|
||||||
|
public string PathData { get; set; }
|
||||||
|
|
||||||
|
public string AccentPathData { get; set; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,64 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Runtime.Serialization;
|
||||||
|
|
||||||
|
namespace Uno.UI.Demo.Api.Models
|
||||||
|
{
|
||||||
|
public class SampleCategoryViewModel
|
||||||
|
{
|
||||||
|
private readonly SampleCategory _category;
|
||||||
|
|
||||||
|
public SampleCategoryViewModel(SampleCategory category, IEnumerable<Sample> samples)
|
||||||
|
{
|
||||||
|
_category = category;
|
||||||
|
Samples = samples
|
||||||
|
.Where(s => s.Category.Equals(category.Id))
|
||||||
|
.Select(s => new SampleViewModel(s)).ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
public string CategoryId => _category.Id;
|
||||||
|
|
||||||
|
public string Title => _category.Title;
|
||||||
|
|
||||||
|
public string DefaultIconPath => _category.PathData;
|
||||||
|
|
||||||
|
public string DefaultIconAccentPath => _category.AccentPathData;
|
||||||
|
|
||||||
|
public SampleViewModel[] Samples { get; }
|
||||||
|
|
||||||
|
[IgnoreDataMember]
|
||||||
|
public int SamplesHash
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
var sum = 0;
|
||||||
|
foreach (var s in Samples)
|
||||||
|
{
|
||||||
|
unchecked
|
||||||
|
{
|
||||||
|
sum += GetEtagHash(s.Etag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return sum;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int GetEtagHash(string s)
|
||||||
|
{
|
||||||
|
unchecked
|
||||||
|
{
|
||||||
|
var r = 0;
|
||||||
|
|
||||||
|
foreach (var c in s)
|
||||||
|
{
|
||||||
|
r += c;
|
||||||
|
}
|
||||||
|
|
||||||
|
return r;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
namespace Uno.UI.Demo.Api.Models
|
||||||
|
{
|
||||||
|
public class SampleDetailViewModel
|
||||||
|
{
|
||||||
|
private readonly Sample _sample;
|
||||||
|
|
||||||
|
public SampleDetailViewModel(Sample sample)
|
||||||
|
{
|
||||||
|
_sample = sample;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Id => _sample.Id;
|
||||||
|
|
||||||
|
public string Title => _sample.Title ?? "";
|
||||||
|
|
||||||
|
public string Description => _sample.Description ?? "";
|
||||||
|
|
||||||
|
public string Category => _sample.Category;
|
||||||
|
|
||||||
|
public string Xaml => _sample.Xaml ?? "";
|
||||||
|
|
||||||
|
public string Data => _sample.Data ?? "";
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
namespace Uno.UI.Demo.Api.Models
|
||||||
|
{
|
||||||
|
public class SampleSaveRequest
|
||||||
|
{
|
||||||
|
public string App { get; set; }
|
||||||
|
public string Category { get; set; }
|
||||||
|
public string Title { get; set; }
|
||||||
|
public string Xaml { get; set; }
|
||||||
|
public string Data { get; set; }
|
||||||
|
public string PathData { get; set; }
|
||||||
|
public string AccentPathData { get; set; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
using System.Runtime.Serialization;
|
||||||
|
|
||||||
|
namespace Uno.UI.Demo.Api.Models
|
||||||
|
{
|
||||||
|
public partial class SampleViewModel
|
||||||
|
{
|
||||||
|
private readonly Sample _sample;
|
||||||
|
|
||||||
|
public SampleViewModel(Sample sample)
|
||||||
|
{
|
||||||
|
_sample = sample;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Id => _sample.Id;
|
||||||
|
|
||||||
|
public string Title => _sample.Title ?? "(no title)";
|
||||||
|
|
||||||
|
public string Description => _sample.Description ?? "";
|
||||||
|
|
||||||
|
public string[] Keywords => _sample.ParsedKeywords ?? new string[] { };
|
||||||
|
|
||||||
|
public string IconPath => _sample.PathData;
|
||||||
|
|
||||||
|
public string IconAccentPath => _sample.AccentPathData;
|
||||||
|
|
||||||
|
[IgnoreDataMember]
|
||||||
|
public string Etag => _sample.ETag;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
using System.Linq;
|
||||||
|
using System.Net;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.Azure.WebJobs;
|
||||||
|
using Microsoft.Azure.WebJobs.Extensions.Http;
|
||||||
|
using Microsoft.Azure.WebJobs.Host;
|
||||||
|
using Microsoft.WindowsAzure.Storage.Table;
|
||||||
|
using Microsoft.WindowsAzure.Storage.Table.Queryable;
|
||||||
|
using Uno.UI.Demo.Api.Helpers;
|
||||||
|
using Uno.UI.Demo.Api.Models;
|
||||||
|
|
||||||
|
namespace Uno.UI.Demo.Api
|
||||||
|
{
|
||||||
|
public static class SampleGet
|
||||||
|
{
|
||||||
|
[FunctionName("SampleGet")]
|
||||||
|
public static async Task<HttpResponseMessage> Run(
|
||||||
|
[HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "samples/{id}")]
|
||||||
|
HttpRequestMessage req,
|
||||||
|
[Table(Constants.SamplesTableName)] CloudTable table,
|
||||||
|
TraceWriter log,
|
||||||
|
string id,
|
||||||
|
CancellationToken ct)
|
||||||
|
{
|
||||||
|
var sampleQuery = table
|
||||||
|
.CreateQuery<Sample>()
|
||||||
|
.Where(smpl => smpl.PartitionKey.Equals(nameof(Sample)) && smpl.RowKey.Equals(id))
|
||||||
|
.AsTableQuery();
|
||||||
|
|
||||||
|
var queryResult = await table.ExecuteQuery(sampleQuery, ct);
|
||||||
|
|
||||||
|
var sample = queryResult.Select(s => new SampleDetailViewModel(s)).FirstOrDefault();
|
||||||
|
|
||||||
|
return sample == null
|
||||||
|
? req.CreateErrorResponse(HttpStatusCode.NotFound, "Sample not found")
|
||||||
|
: req.CreateResponse(HttpStatusCode.OK, sample);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,80 @@
|
||||||
|
using System;
|
||||||
|
using System.Net;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Web.Http;
|
||||||
|
using Microsoft.Azure.WebJobs;
|
||||||
|
using Microsoft.Azure.WebJobs.Extensions.Http;
|
||||||
|
using Microsoft.Azure.WebJobs.Host;
|
||||||
|
using Microsoft.WindowsAzure.Storage.Table;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Uno.UI.Demo.Api.Models;
|
||||||
|
using Uno.UI.Demo.AspnetShell.Helpers;
|
||||||
|
|
||||||
|
namespace Uno.UI.Demo.Api
|
||||||
|
{
|
||||||
|
public static class SamplePost
|
||||||
|
{
|
||||||
|
[FunctionName("SamplePost")]
|
||||||
|
public static async Task<HttpResponseMessage> Run(
|
||||||
|
[HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = "samples")]
|
||||||
|
HttpRequestMessage req,
|
||||||
|
[Table(Constants.SamplesTableName)] CloudTable table,
|
||||||
|
TraceWriter log,
|
||||||
|
CancellationToken ct)
|
||||||
|
{
|
||||||
|
var saveRequest =
|
||||||
|
JsonConvert.DeserializeObject<SampleSaveRequest>(await req.Content.ReadAsStringAsync());
|
||||||
|
|
||||||
|
if (saveRequest == null)
|
||||||
|
{
|
||||||
|
return req.CreateErrorResponse(HttpStatusCode.BadRequest, "Request payload required.");
|
||||||
|
}
|
||||||
|
|
||||||
|
var id = Guid.NewGuid().ToString("N").Substring(24); // 8 characters is enough
|
||||||
|
|
||||||
|
if (saveRequest.Xaml == null || saveRequest.Xaml.Length < 5)
|
||||||
|
{
|
||||||
|
return req.CreateErrorResponse(HttpStatusCode.BadRequest, "Xaml required.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (saveRequest.Xaml.Length > 512 * 1024)
|
||||||
|
{
|
||||||
|
return req.CreateErrorResponse(HttpStatusCode.RequestEntityTooLarge, "Xaml too big.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (saveRequest.Data != null && saveRequest.Data.Length > 16 * 1024)
|
||||||
|
{
|
||||||
|
return req.CreateErrorResponse(HttpStatusCode.RequestEntityTooLarge, "Data too big.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (saveRequest.Title != null && saveRequest.Title.Length > 255)
|
||||||
|
{
|
||||||
|
return req.CreateErrorResponse(HttpStatusCode.RequestEntityTooLarge, "Title too big.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (saveRequest.App != null && saveRequest.App.Length > 255)
|
||||||
|
{
|
||||||
|
return req.CreateErrorResponse(HttpStatusCode.RequestEntityTooLarge, "App name too big.");
|
||||||
|
}
|
||||||
|
|
||||||
|
var sample = new Sample(id)
|
||||||
|
{
|
||||||
|
Data = saveRequest.Data,
|
||||||
|
Xaml = saveRequest.Xaml,
|
||||||
|
Category = Constants.DefaultCategoryIdForSaving,
|
||||||
|
Title = saveRequest.Title,
|
||||||
|
IpAddress = req.GetClientIp(),
|
||||||
|
UserAgent = req.Headers.UserAgent.ToString(),
|
||||||
|
App = saveRequest.App
|
||||||
|
};
|
||||||
|
|
||||||
|
var operation = new TableBatchOperation();
|
||||||
|
operation.Insert(sample);
|
||||||
|
await table.ExecuteBatchAsync(operation, null, null, ct);
|
||||||
|
|
||||||
|
return req.CreateResponse(HttpStatusCode.OK, id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,129 @@
|
||||||
|
using System.Linq;
|
||||||
|
using System.Net;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.Azure.WebJobs;
|
||||||
|
using Microsoft.Azure.WebJobs.Extensions.Http;
|
||||||
|
using Microsoft.Azure.WebJobs.Host;
|
||||||
|
using Microsoft.WindowsAzure.Storage.Table;
|
||||||
|
using Microsoft.WindowsAzure.Storage.Table.Queryable;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Uno.UI.Demo.Api.Helpers;
|
||||||
|
using Uno.UI.Demo.Api.Models;
|
||||||
|
using Uno.UI.Demo.AspnetShell.Helpers;
|
||||||
|
|
||||||
|
namespace Uno.UI.Demo.Api
|
||||||
|
{
|
||||||
|
public static class SampleSave
|
||||||
|
{
|
||||||
|
[FunctionName("SampleSave")]
|
||||||
|
public static async Task<HttpResponseMessage> Run(
|
||||||
|
[HttpTrigger(AuthorizationLevel.Admin, "put", Route = "samples/{id}")]
|
||||||
|
HttpRequestMessage req,
|
||||||
|
[Table(Constants.SamplesTableName)] CloudTable table,
|
||||||
|
string id,
|
||||||
|
TraceWriter log,
|
||||||
|
CancellationToken ct)
|
||||||
|
{
|
||||||
|
var clientIp = req.GetClientIp();
|
||||||
|
|
||||||
|
var saveRequest =
|
||||||
|
JsonConvert.DeserializeObject<SampleSaveRequest>(await req.Content.ReadAsStringAsync());
|
||||||
|
|
||||||
|
|
||||||
|
var existingQuery = table
|
||||||
|
.CreateQuery<Sample>()
|
||||||
|
.Where(smpl => smpl.PartitionKey.Equals(nameof(Sample)) && smpl.RowKey.Equals(id))
|
||||||
|
.AsTableQuery();
|
||||||
|
|
||||||
|
var existing = (await table.ExecuteQuery(existingQuery, ct)).FirstOrDefault();
|
||||||
|
var sample = existing ?? new Sample(id);
|
||||||
|
|
||||||
|
var exists = existing != null;
|
||||||
|
|
||||||
|
if (saveRequest == null)
|
||||||
|
{
|
||||||
|
return req.CreateErrorResponse(HttpStatusCode.BadRequest, "Request payload required.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!exists && (saveRequest.Xaml == null || saveRequest.Xaml.Length < 5))
|
||||||
|
{
|
||||||
|
return req.CreateErrorResponse(HttpStatusCode.BadRequest, "Xaml required.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (saveRequest.Xaml != null && saveRequest.Xaml.Length > 512 * 1024)
|
||||||
|
{
|
||||||
|
return req.CreateErrorResponse(HttpStatusCode.RequestEntityTooLarge, "Xaml too big.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (saveRequest.Data != null && saveRequest.Data.Length > 16 * 1024)
|
||||||
|
{
|
||||||
|
return req.CreateErrorResponse(HttpStatusCode.RequestEntityTooLarge, "Data too big.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (saveRequest.Title != null && saveRequest.Title.Length > 255)
|
||||||
|
{
|
||||||
|
return req.CreateErrorResponse(HttpStatusCode.RequestEntityTooLarge, "Title too big.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (saveRequest.App != null && saveRequest.App.Length > 255)
|
||||||
|
{
|
||||||
|
return req.CreateErrorResponse(HttpStatusCode.RequestEntityTooLarge, "App name too big.");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(saveRequest.Data))
|
||||||
|
{
|
||||||
|
sample.Data = saveRequest.Data;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(saveRequest.Xaml))
|
||||||
|
{
|
||||||
|
sample.Xaml = saveRequest.Xaml;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(sample.Category) || !string.IsNullOrWhiteSpace(saveRequest.Category))
|
||||||
|
{
|
||||||
|
sample.Category = saveRequest.Category ?? Constants.DefaultCategoryIdForSaving;
|
||||||
|
}
|
||||||
|
if (!string.IsNullOrWhiteSpace(saveRequest.Title))
|
||||||
|
{
|
||||||
|
sample.Title = saveRequest.Title;
|
||||||
|
}
|
||||||
|
if (string.IsNullOrWhiteSpace(sample.IpAddress))
|
||||||
|
{
|
||||||
|
sample.IpAddress = clientIp;
|
||||||
|
}
|
||||||
|
if (string.IsNullOrWhiteSpace(sample.UserAgent))
|
||||||
|
{
|
||||||
|
sample.UserAgent = req.Headers.UserAgent.ToString();
|
||||||
|
}
|
||||||
|
if (!string.IsNullOrWhiteSpace(saveRequest.App))
|
||||||
|
{
|
||||||
|
sample.App = saveRequest.App;
|
||||||
|
}
|
||||||
|
if (!string.IsNullOrWhiteSpace(saveRequest.PathData))
|
||||||
|
{
|
||||||
|
sample.PathData = saveRequest.PathData;
|
||||||
|
}
|
||||||
|
if (!string.IsNullOrWhiteSpace(saveRequest.AccentPathData))
|
||||||
|
{
|
||||||
|
sample.AccentPathData = saveRequest.AccentPathData;
|
||||||
|
}
|
||||||
|
|
||||||
|
var operation = new TableBatchOperation();
|
||||||
|
if (existing == null)
|
||||||
|
{
|
||||||
|
operation.Insert(sample);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
operation.Merge(sample);
|
||||||
|
}
|
||||||
|
await table.ExecuteBatchAsync(operation, null, null, ct);
|
||||||
|
|
||||||
|
return req.CreateResponse(HttpStatusCode.OK, id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,97 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Net;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Net.Http.Headers;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.Azure.WebJobs;
|
||||||
|
using Microsoft.Azure.WebJobs.Extensions.Http;
|
||||||
|
using Microsoft.Azure.WebJobs.Host;
|
||||||
|
using Microsoft.WindowsAzure.Storage.Table;
|
||||||
|
using Microsoft.WindowsAzure.Storage.Table.Queryable;
|
||||||
|
using Uno.UI.Demo.Api.Helpers;
|
||||||
|
using Uno.UI.Demo.Api.Models;
|
||||||
|
|
||||||
|
namespace Uno.UI.Demo.Api
|
||||||
|
{
|
||||||
|
public static class SamplesGet
|
||||||
|
{
|
||||||
|
[FunctionName("SamplesGet")]
|
||||||
|
public static async Task<HttpResponseMessage> Run(
|
||||||
|
[HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "samples")]
|
||||||
|
HttpRequestMessage req,
|
||||||
|
[Table(Constants.SamplesTableName)] CloudTable table,
|
||||||
|
TraceWriter log,
|
||||||
|
CancellationToken ct)
|
||||||
|
{
|
||||||
|
|
||||||
|
var categoriesQuery = table
|
||||||
|
.CreateQuery<SampleCategory>()
|
||||||
|
.Where(cat => cat.PartitionKey.Equals(nameof(SampleCategory)) && !cat.RowKey.Equals(Constants.DefaultCategoryIdForSaving))
|
||||||
|
.AsTableQuery()
|
||||||
|
.SelectColumn(nameof(SampleCategory.Title));
|
||||||
|
|
||||||
|
var categories = (await table.ExecuteQuery(categoriesQuery, ct))
|
||||||
|
.OrderBy(cat => cat.ListingOrder)
|
||||||
|
.ThenBy(cat => cat.Title)
|
||||||
|
.ThenBy(cat => cat.Id)
|
||||||
|
.ToArray();
|
||||||
|
|
||||||
|
var result = new List<SampleCategoryViewModel>(categories.Length);
|
||||||
|
|
||||||
|
var etagSb = new StringBuilder();
|
||||||
|
|
||||||
|
etagSb.Append('"');
|
||||||
|
|
||||||
|
foreach (var category in categories)
|
||||||
|
{
|
||||||
|
var samplesQuery = table
|
||||||
|
.CreateQuery<Sample>()
|
||||||
|
.Where(smpl => smpl.PartitionKey.Equals(nameof(Sample)) && smpl.Category.Equals(category.Id))
|
||||||
|
.AsTableQuery()
|
||||||
|
.SelectColumn(nameof(Sample.Category))
|
||||||
|
.SelectColumn(nameof(Sample.Title))
|
||||||
|
.SelectColumn(nameof(Sample.Description))
|
||||||
|
.SelectColumn(nameof(Sample.Keywords));
|
||||||
|
|
||||||
|
var samples = (await table.ExecuteQuery(samplesQuery, ct))
|
||||||
|
.OrderBy(cat => cat.ListingOrder)
|
||||||
|
.ThenBy(cat => cat.Title)
|
||||||
|
.ThenBy(cat => cat.Id)
|
||||||
|
.ToArray();
|
||||||
|
|
||||||
|
var categoryVm = new SampleCategoryViewModel(category, samples);
|
||||||
|
result.Add(categoryVm);
|
||||||
|
etagSb.Append(categoryVm.SamplesHash.ToString("X"));
|
||||||
|
}
|
||||||
|
|
||||||
|
etagSb.Append('"');
|
||||||
|
|
||||||
|
var etag = etagSb.ToString();
|
||||||
|
|
||||||
|
if (req.Headers.IfMatch.Any(im => im.Tag.Equals(etag, StringComparison.OrdinalIgnoreCase)))
|
||||||
|
{
|
||||||
|
return req.CreateResponse(HttpStatusCode.NotModified);
|
||||||
|
}
|
||||||
|
|
||||||
|
var response = req.CreateResponse(HttpStatusCode.OK, result.ToArray());
|
||||||
|
response.Headers.CacheControl =
|
||||||
|
new CacheControlHeaderValue
|
||||||
|
{
|
||||||
|
NoCache = false,
|
||||||
|
Private = false,
|
||||||
|
MaxAge = TimeSpan.FromHours(0.5),
|
||||||
|
MustRevalidate = false,
|
||||||
|
NoStore = false,
|
||||||
|
NoTransform = true,
|
||||||
|
MaxStale = true
|
||||||
|
};
|
||||||
|
response.Headers.ETag = new EntityTagHeaderValue(etag, false);
|
||||||
|
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net461</TargetFramework>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.NET.Sdk.Functions" Version="1.0.13" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Reference Include="Microsoft.CSharp" />
|
||||||
|
<Reference Include="System.ServiceModel" />
|
||||||
|
<Reference Include="System.Web" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Update="host.json">
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
<None Update="local.settings.json">
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
<CopyToPublishDirectory>Never</CopyToPublishDirectory>
|
||||||
|
</None>
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
|
@ -0,0 +1,2 @@
|
||||||
|
{
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
wwwroot/*
|
||||||
|
|
||||||
|
!wwwroot/*.ico
|
||||||
|
!wwwroot/google*
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
using Microsoft.AspNetCore;
|
||||||
|
using Microsoft.AspNetCore.Hosting;
|
||||||
|
|
||||||
|
namespace Uno.UI.Demo.AspnetShell
|
||||||
|
{
|
||||||
|
public class Program
|
||||||
|
{
|
||||||
|
public static void Main(string[] args)
|
||||||
|
{
|
||||||
|
BuildWebHost(args).Run();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IWebHost BuildWebHost(string[] args) =>
|
||||||
|
WebHost.CreateDefaultBuilder(args)
|
||||||
|
.UseStartup<Startup>()
|
||||||
|
.Build();
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,6 +2,7 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.Builder;
|
using Microsoft.AspNetCore.Builder;
|
||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Hosting;
|
||||||
|
@ -10,15 +11,11 @@ using Microsoft.AspNetCore.Rewrite;
|
||||||
using Microsoft.AspNetCore.StaticFiles;
|
using Microsoft.AspNetCore.StaticFiles;
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.WindowsAzure.Storage.Auth;
|
|
||||||
using Microsoft.WindowsAzure.Storage.Table;
|
|
||||||
|
|
||||||
namespace Uno.UI.Demo.AspnetShell
|
namespace Uno.UI.Demo.AspnetShell
|
||||||
{
|
{
|
||||||
public class Startup
|
public class Startup
|
||||||
{
|
{
|
||||||
private const string PlaygroundHost = "playground.platform.uno";
|
|
||||||
|
|
||||||
public Startup(IConfiguration configuration)
|
public Startup(IConfiguration configuration)
|
||||||
{
|
{
|
||||||
Configuration = configuration;
|
Configuration = configuration;
|
||||||
|
@ -29,7 +26,10 @@ namespace Uno.UI.Demo.AspnetShell
|
||||||
// This method gets called by the runtime. Use this method to add services to the container.
|
// This method gets called by the runtime. Use this method to add services to the container.
|
||||||
public void ConfigureServices(IServiceCollection services)
|
public void ConfigureServices(IServiceCollection services)
|
||||||
{
|
{
|
||||||
services.AddMvc();
|
services.AddResponseCompression(c =>
|
||||||
|
{
|
||||||
|
c.EnableForHttps = true;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
|
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
|
||||||
|
@ -42,28 +42,23 @@ namespace Uno.UI.Demo.AspnetShell
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
app.UseExceptionHandler("/Home/Error");
|
app.UseExceptionHandler("/error.html");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
app.UseResponseCompression();
|
||||||
|
|
||||||
// Static content
|
// Static content
|
||||||
|
app.UseDefaultFiles();
|
||||||
app.UseStaticFiles(new StaticFileOptions
|
app.UseStaticFiles(new StaticFileOptions
|
||||||
{
|
{
|
||||||
ContentTypeProvider = CreateContentTypeProvider(),
|
ContentTypeProvider = CreateContentTypeProvider(),
|
||||||
OnPrepareResponse = ConfigureCacheControl,
|
OnPrepareResponse = ConfigureCacheControl
|
||||||
});
|
|
||||||
|
|
||||||
// MVC (dynamic) content
|
|
||||||
app.UseMvc(routes =>
|
|
||||||
{
|
|
||||||
routes.MapRoute(
|
|
||||||
name: "default",
|
|
||||||
template: "{controller=Home}/{action=Index}/{id?}");
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void ConfigureCacheControl(StaticFileResponseContext ctx)
|
private static void ConfigureCacheControl(StaticFileResponseContext ctx)
|
||||||
{
|
{
|
||||||
if (ctx.File.Name.EndsWith(".dll", StringComparison.OrdinalIgnoreCase))
|
if (ctx.File.Name.EndsWith(".clr", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
// Cache managed files for a year, based on this update:
|
// Cache managed files for a year, based on this update:
|
||||||
// https://github.com/nventive/Uno.Wasm.Bootstrap/commit/f4859452c715c54ac40b968a303a242b0399d59a
|
// https://github.com/nventive/Uno.Wasm.Bootstrap/commit/f4859452c715c54ac40b968a303a242b0399d59a
|
||||||
|
@ -73,9 +68,14 @@ namespace Uno.UI.Demo.AspnetShell
|
||||||
|
|
||||||
private FileExtensionContentTypeProvider CreateContentTypeProvider()
|
private FileExtensionContentTypeProvider CreateContentTypeProvider()
|
||||||
{
|
{
|
||||||
var provider = new FileExtensionContentTypeProvider();
|
var provider = new FileExtensionContentTypeProvider
|
||||||
provider.Mappings[".wasm"] = "application/wasm";
|
{
|
||||||
provider.Mappings[".dll"] = "application/octet-stream";
|
Mappings =
|
||||||
|
{
|
||||||
|
[".wasm"] = "application/wasm",
|
||||||
|
[".clr"] = "application/octet-stream"
|
||||||
|
}
|
||||||
|
};
|
||||||
return provider;
|
return provider;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,9 +1,16 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>netcoreapp2.0</TargetFramework>
|
<TargetFramework>netcoreapp2.0</TargetFramework>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Remove="wwwroot\playground\**" />
|
||||||
|
<Content Remove="wwwroot\playground\**" />
|
||||||
|
<EmbeddedResource Remove="wwwroot\playground\**" />
|
||||||
|
<None Remove="wwwroot\playground\**" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.7" />
|
<PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.7" />
|
||||||
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="2.0.3" />
|
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="2.0.3" />
|
||||||
|
@ -13,8 +20,4 @@
|
||||||
<DotNetCliToolReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Tools" Version="2.0.3" />
|
<DotNetCliToolReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Tools" Version="2.0.3" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<Folder Include="wwwroot\playground\" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
</Project>
|
</Project>
|
До Ширина: | Высота: | Размер: 16 KiB После Ширина: | Высота: | Размер: 16 KiB |
До Ширина: | Высота: | Размер: 36 KiB После Ширина: | Высота: | Размер: 36 KiB |
До Ширина: | Высота: | Размер: 58 KiB После Ширина: | Высота: | Размер: 58 KiB |
До Ширина: | Высота: | Размер: 4.7 KiB После Ширина: | Высота: | Размер: 4.7 KiB |
До Ширина: | Высота: | Размер: 3.6 KiB После Ширина: | Высота: | Размер: 3.6 KiB |
До Ширина: | Высота: | Размер: 4.7 KiB После Ширина: | Высота: | Размер: 4.7 KiB |
До Ширина: | Высота: | Размер: 2.9 KiB После Ширина: | Высота: | Размер: 2.9 KiB |
До Ширина: | Высота: | Размер: 2.3 KiB После Ширина: | Высота: | Размер: 2.3 KiB |
До Ширина: | Высота: | Размер: 2.9 KiB После Ширина: | Высота: | Размер: 2.9 KiB |
До Ширина: | Высота: | Размер: 6.5 KiB После Ширина: | Высота: | Размер: 6.5 KiB |
До Ширина: | Высота: | Размер: 5.0 KiB После Ширина: | Высота: | Размер: 5.0 KiB |
До Ширина: | Высота: | Размер: 6.5 KiB После Ширина: | Высота: | Размер: 6.5 KiB |
До Ширина: | Высота: | Размер: 10 KiB После Ширина: | Высота: | Размер: 10 KiB |
До Ширина: | Высота: | Размер: 7.9 KiB После Ширина: | Высота: | Размер: 7.9 KiB |
До Ширина: | Высота: | Размер: 10 KiB После Ширина: | Высота: | Размер: 10 KiB |
До Ширина: | Высота: | Размер: 14 KiB После Ширина: | Высота: | Размер: 14 KiB |
До Ширина: | Высота: | Размер: 12 KiB После Ширина: | Высота: | Размер: 12 KiB |
До Ширина: | Высота: | Размер: 14 KiB После Ширина: | Высота: | Размер: 14 KiB |
|
@ -89,7 +89,7 @@
|
||||||
<Version>1.22.0-dev.23</Version>
|
<Version>1.22.0-dev.23</Version>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="Uno.UI">
|
<PackageReference Include="Uno.UI">
|
||||||
<Version>1.29.1-aobfwasm.2834</Version>
|
<Version>1.30.1-aobfwasm.2873</Version>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="1.1.1" />
|
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="1.1.1" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Logging.Filter" Version="1.1.1" />
|
<PackageReference Include="Microsoft.Extensions.Logging.Filter" Version="1.1.1" />
|
До Ширина: | Высота: | Размер: 448 B После Ширина: | Высота: | Размер: 448 B |
До Ширина: | Высота: | Размер: 169 B После Ширина: | Высота: | Размер: 169 B |
До Ширина: | Высота: | Размер: 94 B После Ширина: | Высота: | Размер: 94 B |
До Ширина: | Высота: | Размер: 390 B После Ширина: | Высота: | Размер: 390 B |
До Ширина: | Высота: | Размер: 500 B После Ширина: | Высота: | Размер: 500 B |