release/9.30 - Commerce Sample Update
This commit is contained in:
Родитель
02c8e5632a
Коммит
e49e747e81
|
@ -1,350 +1,123 @@
|
|||
## Ignore Visual Studio temporary files, build results, and
|
||||
## files generated by popular Visual Studio add-ons.
|
||||
##
|
||||
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
|
||||
|
||||
# User-specific files
|
||||
*.rsuser
|
||||
*.suo
|
||||
_ReSharper*
|
||||
[Bb]in
|
||||
obj
|
||||
objd
|
||||
bin
|
||||
bld
|
||||
pkg
|
||||
/schemas/
|
||||
out/
|
||||
target/
|
||||
tmp/
|
||||
.vs
|
||||
App_Data
|
||||
*.user
|
||||
*.userosscache
|
||||
*.sln.docstates
|
||||
|
||||
# User-specific files (MonoDevelop/Xamarin Studio)
|
||||
*.userprefs
|
||||
|
||||
# Mono auto generated files
|
||||
mono_crash.*
|
||||
|
||||
# Build results
|
||||
[Dd]ebug/
|
||||
[Dd]ebugPublic/
|
||||
[Rr]elease/
|
||||
[Rr]eleases/
|
||||
x64/
|
||||
x86/
|
||||
[Aa][Rr][Mm]/
|
||||
[Aa][Rr][Mm]64/
|
||||
bld/
|
||||
[Bb]in/
|
||||
[Oo]bj/
|
||||
[Ll]og/
|
||||
[Ll]ogs/
|
||||
|
||||
# Visual Studio 2015/2017 cache/options directory
|
||||
*.sln.cache
|
||||
*.suo
|
||||
TestResults
|
||||
[Tt]humbs.db
|
||||
buildd.*
|
||||
build.(err|log|wrn|trc|prf|evt|dbb)
|
||||
*.log
|
||||
*.bak
|
||||
OACRTemp/
|
||||
build_logs/
|
||||
lock
|
||||
/public/inc/bldver.*
|
||||
/public/inc/sources.ver
|
||||
.vs/
|
||||
# Uncomment if you have tasks that create the project's static files in wwwroot
|
||||
#wwwroot/
|
||||
/Symbols
|
||||
/drop
|
||||
/.corext/.pkg/
|
||||
/.corext/gen/
|
||||
/.corext/cache
|
||||
versionsmk.inc
|
||||
Logs
|
||||
|
||||
# Visual Studio 2017 auto generated files
|
||||
Generated\ Files/
|
||||
# Weird MSBuild output folders
|
||||
[0-9]
|
||||
|
||||
# MSTest test Results
|
||||
[Tt]est[Rr]esult*/
|
||||
[Bb]uild[Ll]og.*
|
||||
# msbuild logs
|
||||
msbuild.log
|
||||
msbuild.err
|
||||
msbuild.wrn
|
||||
|
||||
# NUnit
|
||||
*.VisualState.xml
|
||||
TestResult.xml
|
||||
nunit-*.xml
|
||||
# bad tlb/chm generators in nmake tree
|
||||
*.tlb
|
||||
*.chm
|
||||
# The following file is a part of the sdk and must be an exception to the above rule, meaning it will be included.
|
||||
!CommerceRuntimeMessages.chm
|
||||
|
||||
# Build Results of an ATL Project
|
||||
[Dd]ebugPS/
|
||||
[Rr]eleasePS/
|
||||
dlldata.c
|
||||
# dumb silverlight
|
||||
ClientBin/
|
||||
|
||||
# Benchmark Results
|
||||
BenchmarkDotNet.Artifacts/
|
||||
# dumb azure
|
||||
*.build.csdef
|
||||
csx/
|
||||
|
||||
# .NET Core
|
||||
project.lock.json
|
||||
project.fragment.lock.json
|
||||
artifacts/
|
||||
# Generated C# files
|
||||
*.g.cs
|
||||
!src/SampleExtensions/ShoppingApp/**/*.g.cs
|
||||
*.projhash
|
||||
*.projhash.userData
|
||||
*.projhash.userData.assemblies
|
||||
*.slnhash
|
||||
*.slnhash.userData
|
||||
*.slnhash.userData.assemblies
|
||||
|
||||
# Ignore other generated file types, too
|
||||
*.g.ts
|
||||
*.g.xml
|
||||
|
||||
# StyleCop
|
||||
StyleCopReport.xml
|
||||
StyleCop.Cache
|
||||
|
||||
# Files built by Visual Studio
|
||||
*_i.c
|
||||
*_p.c
|
||||
*_h.h
|
||||
*.ilk
|
||||
*.meta
|
||||
*.obj
|
||||
*.iobj
|
||||
*.pch
|
||||
*.pdb
|
||||
*.ipdb
|
||||
*.pgc
|
||||
*.pgd
|
||||
# Configs and transient build assets
|
||||
.config/.inc/bldver.cpp
|
||||
.config/.inc/bldver.cs
|
||||
.config/.inc/bldver.h
|
||||
.config/.inc/bldver.vb
|
||||
.config/.inc/sources.ver
|
||||
.config/.inc/version.htm
|
||||
.config/.inc/version.sql
|
||||
.config/.inc/version.json
|
||||
.config/.inc/version.txt
|
||||
.gen/
|
||||
build/.gen_oacr/
|
||||
build/oacr_exclude.ini
|
||||
*.tslint
|
||||
*.d.ts
|
||||
*.map
|
||||
*.generated
|
||||
*.rsp
|
||||
*.sbr
|
||||
*.tlb
|
||||
*.tli
|
||||
*.tlh
|
||||
*.tmp
|
||||
*.tmp_proj
|
||||
*_wpftmp.csproj
|
||||
*.log
|
||||
*.vspscc
|
||||
*.vssscc
|
||||
.builds
|
||||
*.pidb
|
||||
*.svclog
|
||||
*.scc
|
||||
*.js
|
||||
/src/OnlineStore/Ecommerce.Sdk.Controls/Common/Scripts.js
|
||||
|
||||
# Chutzpah Test files
|
||||
_Chutzpah*
|
||||
# Build and development artifiacts
|
||||
/VersionGeneration
|
||||
tslint.out
|
||||
TypeScripttslintFileListArgs.txt
|
||||
/.config/dev.packages.props
|
||||
/src/Provisioning/ProvisioningDatabase/ProvisioningDatabase.refactorlog
|
||||
.packages
|
||||
phantomjs-license.txt
|
||||
|
||||
# Visual C++ cache files
|
||||
ipch/
|
||||
*.aps
|
||||
*.ncb
|
||||
*.opendb
|
||||
*.opensdf
|
||||
*.sdf
|
||||
*.cachefile
|
||||
*.VC.db
|
||||
*.VC.VC.opendb
|
||||
|
||||
# Visual Studio profiler
|
||||
*.psess
|
||||
*.vsp
|
||||
*.vspx
|
||||
*.sap
|
||||
|
||||
# Visual Studio Trace Files
|
||||
*.e2e
|
||||
|
||||
# TFS 2012 Local Workspace
|
||||
$tf/
|
||||
|
||||
# Guidance Automation Toolkit
|
||||
*.gpState
|
||||
|
||||
# ReSharper is a .NET coding add-in
|
||||
_ReSharper*/
|
||||
*.[Rr]e[Ss]harper
|
||||
*.DotSettings.user
|
||||
|
||||
# TeamCity is a build add-in
|
||||
_TeamCity*
|
||||
|
||||
# DotCover is a Code Coverage Tool
|
||||
*.dotCover
|
||||
|
||||
# AxoCover is a Code Coverage Tool
|
||||
.axoCover/*
|
||||
!.axoCover/settings.json
|
||||
|
||||
# Visual Studio code coverage results
|
||||
*.coverage
|
||||
*.coveragexml
|
||||
|
||||
# NCrunch
|
||||
_NCrunch_*
|
||||
.*crunch*.local.xml
|
||||
nCrunchTemp_*
|
||||
|
||||
# MightyMoose
|
||||
*.mm.*
|
||||
AutoTest.Net/
|
||||
|
||||
# Web workbench (sass)
|
||||
.sass-cache/
|
||||
|
||||
# Installshield output folder
|
||||
[Ee]xpress/
|
||||
|
||||
# DocProject is a documentation generator add-in
|
||||
DocProject/buildhelp/
|
||||
DocProject/Help/*.HxT
|
||||
DocProject/Help/*.HxC
|
||||
DocProject/Help/*.hhc
|
||||
DocProject/Help/*.hhk
|
||||
DocProject/Help/*.hhp
|
||||
DocProject/Help/Html2
|
||||
DocProject/Help/html
|
||||
|
||||
# Click-Once directory
|
||||
publish/
|
||||
|
||||
# Publish Web Output
|
||||
*.[Pp]ublish.xml
|
||||
*.azurePubxml
|
||||
# Note: Comment the next line if you want to checkin your web deploy settings,
|
||||
# but database connection strings (with potential passwords) will be unencrypted
|
||||
*.pubxml
|
||||
*.publishproj
|
||||
|
||||
# Microsoft Azure Web App publish settings. Comment the next line if you want to
|
||||
# checkin your Azure Web App publish settings, but sensitive information contained
|
||||
# in these scripts will be unencrypted
|
||||
PublishScripts/
|
||||
|
||||
# NuGet Packages
|
||||
*.nupkg
|
||||
# NuGet Symbol Packages
|
||||
*.snupkg
|
||||
# The packages folder can be ignored because of Package Restore
|
||||
**/[Pp]ackages/*
|
||||
# except build/, which is used as an MSBuild target.
|
||||
!**/[Pp]ackages/build/
|
||||
# Uncomment if necessary however generally it will be regenerated when needed
|
||||
#!**/[Pp]ackages/repositories.config
|
||||
# NuGet v3's project.json files produces more ignorable files
|
||||
*.nuget.props
|
||||
*.nuget.targets
|
||||
|
||||
# Microsoft Azure Build Output
|
||||
csx/
|
||||
*.build.csdef
|
||||
|
||||
# Microsoft Azure Emulator
|
||||
ecf/
|
||||
rcf/
|
||||
|
||||
# Windows Store app package directories and files
|
||||
# POS Build Artifacts
|
||||
AppPackages/
|
||||
BundleArtifacts/
|
||||
Package.StoreAssociation.xml
|
||||
_pkginfo.txt
|
||||
*.appx
|
||||
*.appxbundle
|
||||
*.appxupload
|
||||
bld/
|
||||
schemas/
|
||||
dist/
|
||||
devDependencies/
|
||||
|
||||
# Visual Studio cache files
|
||||
# files ending in .cache can be ignored
|
||||
*.[Cc]ache
|
||||
# but keep track of directories ending in .cache
|
||||
!?*.[Cc]ache/
|
||||
|
||||
# Others
|
||||
ClientBin/
|
||||
~$*
|
||||
*~
|
||||
*.dbmdl
|
||||
*.dbproj.schemaview
|
||||
*.jfm
|
||||
# Certificate files
|
||||
*.pfx
|
||||
*.publishsettings
|
||||
orleans.codegen.cs
|
||||
|
||||
# Including strong name files can present a security risk
|
||||
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
|
||||
#*.snk
|
||||
# Nuget package cache
|
||||
/src/References
|
||||
/ComponentScenarios/Pos/Dependencies/
|
||||
|
||||
# Since there are multiple workflows, uncomment next line to ignore bower_components
|
||||
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
|
||||
#bower_components/
|
||||
# Nuget package creation temps
|
||||
/nu/t
|
||||
|
||||
# RIA/Silverlight projects
|
||||
Generated_Code/
|
||||
|
||||
# Backup & report files from converting an old project file
|
||||
# to a newer Visual Studio version. Backup files are not needed,
|
||||
# because we have git ;-)
|
||||
_UpgradeReport_Files/
|
||||
Backup*/
|
||||
UpgradeLog*.XML
|
||||
UpgradeLog*.htm
|
||||
ServiceFabricBackup/
|
||||
*.rptproj.bak
|
||||
|
||||
# SQL Server files
|
||||
*.mdf
|
||||
*.ldf
|
||||
*.ndf
|
||||
|
||||
# Business Intelligence projects
|
||||
*.rdl.data
|
||||
*.bim.layout
|
||||
*.bim_*.settings
|
||||
*.rptproj.rsuser
|
||||
*- [Bb]ackup.rdl
|
||||
*- [Bb]ackup ([0-9]).rdl
|
||||
*- [Bb]ackup ([0-9][0-9]).rdl
|
||||
|
||||
# Microsoft Fakes
|
||||
FakesAssemblies/
|
||||
|
||||
# GhostDoc plugin setting file
|
||||
*.GhostDoc.xml
|
||||
|
||||
# Node.js Tools for Visual Studio
|
||||
.ntvs_analysis.dat
|
||||
node_modules/
|
||||
|
||||
# Visual Studio 6 build log
|
||||
*.plg
|
||||
|
||||
# Visual Studio 6 workspace options file
|
||||
*.opt
|
||||
|
||||
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
|
||||
*.vbw
|
||||
|
||||
# Visual Studio LightSwitch build output
|
||||
**/*.HTMLClient/GeneratedArtifacts
|
||||
**/*.DesktopClient/GeneratedArtifacts
|
||||
**/*.DesktopClient/ModelManifest.xml
|
||||
**/*.Server/GeneratedArtifacts
|
||||
**/*.Server/ModelManifest.xml
|
||||
_Pvt_Extensions
|
||||
|
||||
# Paket dependency manager
|
||||
.paket/paket.exe
|
||||
paket-files/
|
||||
|
||||
# FAKE - F# Make
|
||||
.fake/
|
||||
|
||||
# CodeRush personal settings
|
||||
.cr/personal
|
||||
|
||||
# Python Tools for Visual Studio (PTVS)
|
||||
__pycache__/
|
||||
*.pyc
|
||||
|
||||
# Cake - Uncomment if you are using it
|
||||
# tools/**
|
||||
# !tools/packages.config
|
||||
|
||||
# Tabs Studio
|
||||
*.tss
|
||||
|
||||
# Telerik's JustMock configuration file
|
||||
*.jmconfig
|
||||
|
||||
# BizTalk build output
|
||||
*.btp.cs
|
||||
*.btm.cs
|
||||
*.odx.cs
|
||||
*.xsd.cs
|
||||
|
||||
# OpenCover UI analysis results
|
||||
OpenCover/
|
||||
|
||||
# Azure Stream Analytics local run output
|
||||
ASALocalRun/
|
||||
|
||||
# MSBuild Binary and Structured Log
|
||||
*.binlog
|
||||
|
||||
# NVidia Nsight GPU debugger configuration file
|
||||
*.nvuser
|
||||
|
||||
# MFractors (Xamarin productivity tool) working folder
|
||||
.mfractor/
|
||||
|
||||
# Local History for Visual Studio
|
||||
.localhistory/
|
||||
|
||||
# BeatPulse healthcheck temp database
|
||||
healthchecksdb
|
||||
|
||||
# Backup folder for Package Reference Convert tool in Visual Studio 2017
|
||||
MigrationBackup/
|
||||
|
||||
# Ionide (cross platform F# VS Code tools) working folder
|
||||
.ionide/
|
||||
# Ignore generated nuget packages
|
||||
*.nupkg
|
|
@ -1,9 +0,0 @@
|
|||
# Microsoft Open Source Code of Conduct
|
||||
|
||||
This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
|
||||
|
||||
Resources:
|
||||
|
||||
- [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/)
|
||||
- [Microsoft Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/)
|
||||
- Contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with questions or concerns
|
|
@ -0,0 +1,11 @@
|
|||
param(
|
||||
[string]$AzureKeyVaultURI,
|
||||
[string]$ApplicationId,
|
||||
[string]$ApplicationSecretValue,
|
||||
[string]$CertificateName,
|
||||
[string]$Timestamp,
|
||||
[string]$Files,
|
||||
[string]$TimestampDigest = "sha256"
|
||||
)
|
||||
|
||||
AzureSignTool.exe sign -kvu "$AzureKeyVaultURI" -kvi "$ApplicationId" -kvs "$ApplicationSecretValue" -kvc "$CertificateName" -tr "$Timestamp" -td "$TimestampDigest" (-split $Files)
|
|
@ -0,0 +1,13 @@
|
|||
param(
|
||||
[string]$RelativePath,
|
||||
[string]$File,
|
||||
[string]$DestinationFullName
|
||||
)
|
||||
|
||||
$searchFile = Get-ChildItem -Path $RelativePath -Filter $File -Recurse
|
||||
if (-NOT $searchFile) {
|
||||
throw "$File file was not found."
|
||||
}
|
||||
else {
|
||||
Copy-Item $searchFile.FullName -Destination "$DestinationFullName"
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
write-host "Executing pre-build scripts"
|
||||
|
||||
# Any additional scripts to be executed during pipeline should be referenced in this file
|
||||
# Link for reference: https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/invoke-expression?view=powershell-7.1
|
||||
|
||||
# Invoke-Expression -Command "C:\ps-test\testscript.ps1"
|
|
@ -0,0 +1,40 @@
|
|||
pr: none
|
||||
trigger: none
|
||||
|
||||
pool:
|
||||
vmImage: 'windows-latest'
|
||||
|
||||
steps:
|
||||
- task: PowerShell@2
|
||||
displayName: 'Pre-Build steps'
|
||||
inputs:
|
||||
targetType: filePath
|
||||
filePath: ./Pipeline/PowershellScripts/Pre-Build.ps1
|
||||
failOnStderr: true
|
||||
|
||||
- task: NuGetToolInstaller@1
|
||||
displayName: 'Use NuGet 5.4.0'
|
||||
inputs:
|
||||
versionSpec: '5.4.0'
|
||||
|
||||
- task: NuGetCommand@2
|
||||
displayName: 'NuGet restore'
|
||||
inputs:
|
||||
feedsToUse: config
|
||||
nugetConfigPath: nuget.config
|
||||
|
||||
- task: VSBuild@1
|
||||
displayName: 'Build solution **\*.sln'
|
||||
inputs:
|
||||
solution: '**\*.sln'
|
||||
|
||||
- task: PowerShell@2
|
||||
displayName: 'Copy CloudScaleUnitExtensionPackage package to artifact directory'
|
||||
inputs:
|
||||
targetType: filePath
|
||||
filePath: ./Pipeline/PowershellScripts/CopyFileToDestination.ps1
|
||||
arguments: '-RelativePath "$(Build.SourcesDirectory)\src\ScaleUnitSample" -File "CloudScaleUnitExtensionPackage.zip" -DestinationFullName "$(Build.ArtifactStagingDirectory)\ScaleUnitPackage_$(Build.BuildNumber).zip"'
|
||||
failOnStderr: true
|
||||
|
||||
- task: PublishBuildArtifacts@1
|
||||
displayName: 'Publish Artifact: drop'
|
10
README.md
10
README.md
|
@ -1,3 +1,13 @@
|
|||
---
|
||||
page_type: sample
|
||||
languages:
|
||||
- csharp
|
||||
products:
|
||||
- Dynamics 365 Commerce
|
||||
name: Extend Headless commerce engine (CRT/RS)
|
||||
description: This repo contains the sample code on how to extend the Dynamics 365 Headless Commerce engine - Retail Server, Commerce runtime and Database.
|
||||
---
|
||||
|
||||
**Download Retail SDK samples and Reference packages from GitHub and NuGet feed:**
|
||||
|
||||
This document explains to how to get Retail SDK samples from GitHub and reference package from the public NuGet feed.
|
||||
|
|
41
SECURITY.md
41
SECURITY.md
|
@ -1,41 +0,0 @@
|
|||
<!-- BEGIN MICROSOFT SECURITY.MD V0.0.5 BLOCK -->
|
||||
|
||||
## Security
|
||||
|
||||
Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/Microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/).
|
||||
|
||||
If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://docs.microsoft.com/en-us/previous-versions/tn-archive/cc751383(v=technet.10)), please report it to us as described below.
|
||||
|
||||
## Reporting Security Issues
|
||||
|
||||
**Please do not report security vulnerabilities through public GitHub issues.**
|
||||
|
||||
Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://msrc.microsoft.com/create-report).
|
||||
|
||||
If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://www.microsoft.com/en-us/msrc/pgp-key-msrc).
|
||||
|
||||
You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://www.microsoft.com/msrc).
|
||||
|
||||
Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue:
|
||||
|
||||
* Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.)
|
||||
* Full paths of source file(s) related to the manifestation of the issue
|
||||
* The location of the affected source code (tag/branch/commit or direct URL)
|
||||
* Any special configuration required to reproduce the issue
|
||||
* Step-by-step instructions to reproduce the issue
|
||||
* Proof-of-concept or exploit code (if possible)
|
||||
* Impact of the issue, including how an attacker might exploit the issue
|
||||
|
||||
This information will help us triage your report more quickly.
|
||||
|
||||
If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://microsoft.com/msrc/bounty) page for more details about our active programs.
|
||||
|
||||
## Preferred Languages
|
||||
|
||||
We prefer all communications to be in English.
|
||||
|
||||
## Policy
|
||||
|
||||
Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://www.microsoft.com/en-us/msrc/cvd).
|
||||
|
||||
<!-- END MICROSOFT SECURITY.MD BLOCK -->
|
|
@ -0,0 +1,11 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration>
|
||||
<packageSources>
|
||||
<clear />
|
||||
<add key="dynamics365-commerce" value="https://pkgs.dev.azure.com/commerce-partner/Registry/_packaging/dynamics365-commerce/nuget/v3/index.json" />
|
||||
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" />
|
||||
</packageSources>
|
||||
<disabledPackageSources>
|
||||
<clear />
|
||||
</disabledPackageSources>
|
||||
</configuration>
|
|
@ -0,0 +1,14 @@
|
|||
<Project>
|
||||
<PropertyGroup>
|
||||
<BuildNumber Condition="'$(BuildNumber)' == ''">0.0</BuildNumber>
|
||||
<MajorVersion>9.30</MajorVersion>
|
||||
<Version>$(MajorVersion).$(BuildNumber)</Version>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<Publisher Condition="'$(Publisher)' == ''">CN=Contoso Ltd.</Publisher>
|
||||
<PublisherDisplayName Condition="'$(PublisherDisplayName)' == ''">Contoso Ltd.</PublisherDisplayName>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<CommerceSdkPackagesVersion>[9.30.21144.7-preview,9.31)</CommerceSdkPackagesVersion>
|
||||
</PropertyGroup>
|
||||
</Project>
|
|
@ -0,0 +1,10 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Import Project="..\CustomizationPackage.props" />
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Dynamics.Commerce.Sdk.ChannelDatabase" Version="$(CommerceSdkPackagesVersion)" />
|
||||
</ItemGroup>
|
||||
</Project>
|
|
@ -0,0 +1,138 @@
|
|||
/**
|
||||
* SAMPLE CODE NOTICE
|
||||
*
|
||||
* THIS SAMPLE CODE IS MADE AVAILABLE AS IS. MICROSOFT MAKES NO WARRANTIES, WHETHER EXPRESS OR IMPLIED,
|
||||
* OF FITNESS FOR A PARTICULAR PURPOSE, OF ACCURACY OR COMPLETENESS OF RESPONSES, OF RESULTS, OR CONDITIONS OF MERCHANTABILITY.
|
||||
* THE ENTIRE RISK OF THE USE OR THE RESULTS FROM THE USE OF THIS SAMPLE CODE REMAINS WITH THE USER.
|
||||
* NO TECHNICAL SUPPORT IS PROVIDED. YOU MAY NOT DISTRIBUTE THIS CODE UNLESS YOU HAVE A LICENSE AGREEMENT WITH MICROSOFT THAT ALLOWS YOU TO DO SO.
|
||||
*/
|
||||
|
||||
-- Create the extension table to store the custom fields.
|
||||
|
||||
IF (SELECT OBJECT_ID('[ext].[CONTOSO_EXAMPLETABLE]')) IS NULL
|
||||
BEGIN
|
||||
CREATE TABLE
|
||||
[ext].[CONTOSO_EXAMPLETABLE]
|
||||
(
|
||||
[EXAMPLEID] BIGINT IDENTITY(1,1) NOT NULL,
|
||||
[EXAMPLEINT] INT NOT NULL DEFAULT ((0)),
|
||||
[EXAMPLESTRING] NVARCHAR(64) NOT NULL DEFAULT (('')),
|
||||
CONSTRAINT [I_EXAMPLETABLE_EXAMPLEID] PRIMARY KEY CLUSTERED
|
||||
(
|
||||
[EXAMPLEID] ASC
|
||||
) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
|
||||
) ON [PRIMARY]
|
||||
|
||||
ALTER TABLE [ext].[CONTOSO_EXAMPLETABLE] WITH CHECK ADD CHECK (([EXAMPLEID]<>(0)))
|
||||
END
|
||||
GO
|
||||
|
||||
GRANT SELECT, INSERT, UPDATE, DELETE ON OBJECT::[ext].[CONTOSO_EXAMPLETABLE] TO [DataSyncUsersRole]
|
||||
GO
|
||||
|
||||
-- Create a stored procedure CRT can use to add entries to the custom table.
|
||||
|
||||
IF OBJECT_ID(N'[ext].[CONTOSO_INSERTEXAMPLE]', N'P') IS NOT NULL
|
||||
DROP PROCEDURE [ext].[CONTOSO_INSERTEXAMPLE]
|
||||
GO
|
||||
|
||||
CREATE PROCEDURE [ext].[CONTOSO_INSERTEXAMPLE]
|
||||
@i_ExampleInt INT,
|
||||
@s_ExampleString NVARCHAR(64)
|
||||
AS
|
||||
BEGIN
|
||||
SET NOCOUNT ON
|
||||
|
||||
INSERT INTO
|
||||
ext.CONTOSO_EXAMPLETABLE
|
||||
(EXAMPLEINT, EXAMPLESTRING)
|
||||
OUTPUT
|
||||
INSERTED.EXAMPLEID
|
||||
VALUES
|
||||
(@i_ExampleInt, @s_ExampleString)
|
||||
END;
|
||||
GO
|
||||
|
||||
GRANT EXECUTE ON [ext].[CONTOSO_INSERTEXAMPLE] TO [UsersRole];
|
||||
GO
|
||||
|
||||
GRANT EXECUTE ON [ext].[CONTOSO_INSERTEXAMPLE] TO [DeployExtensibilityRole];
|
||||
GO
|
||||
|
||||
-- Create the custom view that can query a complete Example Entity.
|
||||
|
||||
IF (SELECT OBJECT_ID('[ext].[CONTOSO_EXAMPLEVIEW]')) IS NOT NULL
|
||||
DROP VIEW [ext].[CONTOSO_EXAMPLEVIEW]
|
||||
GO
|
||||
|
||||
CREATE VIEW [ext].[CONTOSO_EXAMPLEVIEW] AS
|
||||
(
|
||||
SELECT
|
||||
et.EXAMPLEINT,
|
||||
et.EXAMPLESTRING,
|
||||
et.EXAMPLEID
|
||||
FROM
|
||||
[ext].[CONTOSO_EXAMPLETABLE] et
|
||||
)
|
||||
GO
|
||||
|
||||
GRANT SELECT ON OBJECT::[ext].[CONTOSO_EXAMPLEVIEW] TO [UsersRole];
|
||||
GO
|
||||
|
||||
GRANT SELECT ON OBJECT::[ext].[CONTOSO_EXAMPLEVIEW] TO [DeployExtensibilityRole];
|
||||
GO
|
||||
|
||||
-- Create a stored procedure CRT can use to perform updates.
|
||||
|
||||
IF OBJECT_ID(N'[ext].[CONTOSO_UPDATEEXAMPLE]', N'P') IS NOT NULL
|
||||
DROP PROCEDURE [ext].[CONTOSO_UPDATEEXAMPLE]
|
||||
GO
|
||||
|
||||
CREATE PROCEDURE [ext].[CONTOSO_UPDATEEXAMPLE]
|
||||
@bi_Id BIGINT,
|
||||
@i_ExampleInt INT,
|
||||
@s_ExampleString NVARCHAR(64)
|
||||
AS
|
||||
BEGIN
|
||||
SET NOCOUNT ON
|
||||
|
||||
UPDATE
|
||||
ext.CONTOSO_EXAMPLETABLE
|
||||
SET
|
||||
EXAMPLEINT = @i_ExampleInt,
|
||||
EXAMPLESTRING = @s_ExampleString
|
||||
WHERE
|
||||
EXAMPLEID = @bi_Id
|
||||
END;
|
||||
GO
|
||||
|
||||
GRANT EXECUTE ON [ext].[CONTOSO_UPDATEEXAMPLE] TO [UsersRole];
|
||||
GO
|
||||
|
||||
GRANT EXECUTE ON [ext].[CONTOSO_UPDATEEXAMPLE] TO [DeployExtensibilityRole];
|
||||
GO
|
||||
|
||||
-- Create a stored procedure CRT can use to delete Example Entities.
|
||||
|
||||
IF OBJECT_ID(N'[ext].[CONTOSO_DELETEEXAMPLE]', N'P') IS NOT NULL
|
||||
DROP PROCEDURE [ext].CONTOSO_DELETEEXAMPLE
|
||||
GO
|
||||
|
||||
CREATE PROCEDURE [ext].CONTOSO_DELETEEXAMPLE
|
||||
@bi_Id BIGINT
|
||||
AS
|
||||
BEGIN
|
||||
SET NOCOUNT ON
|
||||
|
||||
DELETE FROM
|
||||
ext.CONTOSO_EXAMPLETABLE
|
||||
WHERE
|
||||
EXAMPLEID = @bi_Id
|
||||
END;
|
||||
GO
|
||||
|
||||
GRANT EXECUTE ON [ext].CONTOSO_DELETEEXAMPLE TO [UsersRole];
|
||||
GO
|
||||
|
||||
GRANT EXECUTE ON [ext].CONTOSO_DELETEEXAMPLE TO [DeployExtensibilityRole];
|
||||
GO
|
|
@ -0,0 +1,10 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Import Project="..\CustomizationPackage.props" />
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Dynamics.Commerce.Sdk.Runtime" Version="$(CommerceSdkPackagesVersion)" />
|
||||
</ItemGroup>
|
||||
</Project>
|
|
@ -0,0 +1,63 @@
|
|||
/**
|
||||
* SAMPLE CODE NOTICE
|
||||
*
|
||||
* THIS SAMPLE CODE IS MADE AVAILABLE AS IS. MICROSOFT MAKES NO WARRANTIES, WHETHER EXPRESS OR IMPLIED,
|
||||
* OF FITNESS FOR A PARTICULAR PURPOSE, OF ACCURACY OR COMPLETENESS OF RESPONSES, OF RESULTS, OR CONDITIONS OF MERCHANTABILITY.
|
||||
* THE ENTIRE RISK OF THE USE OR THE RESULTS FROM THE USE OF THIS SAMPLE CODE REMAINS WITH THE USER.
|
||||
* NO TECHNICAL SUPPORT IS PROVIDED. YOU MAY NOT DISTRIBUTE THIS CODE UNLESS YOU HAVE A LICENSE AGREEMENT WITH MICROSOFT THAT ALLOWS YOU TO DO SO.
|
||||
*/
|
||||
|
||||
namespace Contoso.CommerceRuntime.Controllers
|
||||
{
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Dynamics.Commerce.Runtime;
|
||||
using Microsoft.Dynamics.Commerce.Runtime.DataModel;
|
||||
using Microsoft.Dynamics.Commerce.Runtime.Hosting.Contracts;
|
||||
|
||||
/// <summary>
|
||||
/// An extension controller to handle requests to the StoreHours entity set.
|
||||
/// </summary>
|
||||
[RoutePrefix("BoundController")]
|
||||
[BindEntity(typeof(Entities.DataModel.ExampleEntity))]
|
||||
public class BoundController : IController
|
||||
{
|
||||
[HttpGet]
|
||||
[Authorization(CommerceRoles.Anonymous, CommerceRoles.Application, CommerceRoles.Customer, CommerceRoles.Device, CommerceRoles.Employee, CommerceRoles.Storefront)]
|
||||
public async Task<PagedResult<Entities.DataModel.ExampleEntity>> GetAllExampleEntities(IEndpointContext context)
|
||||
{
|
||||
var queryResultSettings = QueryResultSettings.SingleRecord;
|
||||
queryResultSettings.Paging = new PagingInfo(10);
|
||||
|
||||
var request = new Messages.ExampleEntityDataRequest() { QueryResultSettings = queryResultSettings };
|
||||
var response = await context.ExecuteAsync<Messages.ExampleEntityDataResponse>(request).ConfigureAwait(false);
|
||||
return response.ExampleEntities;
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Authorization(CommerceRoles.Customer, CommerceRoles.Device, CommerceRoles.Employee)]
|
||||
public async Task<long> CreateExampleEntity(IEndpointContext context, CommerceRuntime.Entities.DataModel.ExampleEntity entityData)
|
||||
{
|
||||
var request = new Messages.CreateExampleEntityDataRequest(entityData);
|
||||
var response = await context.ExecuteAsync<Messages.CreateExampleEntityDataResponse>(request).ConfigureAwait(false);
|
||||
return response.CreatedId;
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Authorization(CommerceRoles.Customer, CommerceRoles.Device, CommerceRoles.Employee)]
|
||||
public async Task<bool> UpdateExampleEntity(IEndpointContext context, [EntityKey] long key, CommerceRuntime.Entities.DataModel.ExampleEntity updatedEntity)
|
||||
{
|
||||
var request = new Messages.UpdateExampleEntityDataRequest(key, updatedEntity);
|
||||
var response = await context.ExecuteAsync<Messages.UpdateExampleEntityDataResponse>(request).ConfigureAwait(false);
|
||||
return response.Success;
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Authorization(CommerceRoles.Customer, CommerceRoles.Device, CommerceRoles.Employee)]
|
||||
public async Task<bool> DeleteExampleEntity(IEndpointContext context, [EntityKey] long key)
|
||||
{
|
||||
var request = new Messages.DeleteExampleEntityDataRequest(key);
|
||||
var response = await context.ExecuteAsync<Messages.DeleteExampleEntityDataResponse>(request).ConfigureAwait(false);
|
||||
return response.Success;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
/**
|
||||
* SAMPLE CODE NOTICE
|
||||
*
|
||||
* THIS SAMPLE CODE IS MADE AVAILABLE AS IS. MICROSOFT MAKES NO WARRANTIES, WHETHER EXPRESS OR IMPLIED,
|
||||
* OF FITNESS FOR A PARTICULAR PURPOSE, OF ACCURACY OR COMPLETENESS OF RESPONSES, OF RESULTS, OR CONDITIONS OF MERCHANTABILITY.
|
||||
* THE ENTIRE RISK OF THE USE OR THE RESULTS FROM THE USE OF THIS SAMPLE CODE REMAINS WITH THE USER.
|
||||
* NO TECHNICAL SUPPORT IS PROVIDED. YOU MAY NOT DISTRIBUTE THIS CODE UNLESS YOU HAVE A LICENSE AGREEMENT WITH MICROSOFT THAT ALLOWS YOU TO DO SO.
|
||||
*/
|
||||
|
||||
namespace Contoso.CommerceRuntime.Controllers
|
||||
{
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Dynamics.Commerce.Runtime.DataModel;
|
||||
using Microsoft.Dynamics.Commerce.Runtime.Hosting.Contracts;
|
||||
|
||||
/// <summary>
|
||||
/// An extension controller to handle requests to the StoreHours entity set.
|
||||
/// </summary>
|
||||
public class UnboundController : IController
|
||||
{
|
||||
/// <summary>
|
||||
/// A simple GET endpoint to demonstrate GET endpoints on an unbound controller.
|
||||
/// </summary>
|
||||
/// <returns>A simple true value to indicate the endpoint was reached.</returns>
|
||||
[HttpGet]
|
||||
[Authorization(CommerceRoles.Anonymous, CommerceRoles.Application, CommerceRoles.Customer, CommerceRoles.Device, CommerceRoles.Employee, CommerceRoles.Storefront)]
|
||||
public Task<bool> SimplePingGet()
|
||||
{
|
||||
return Task.FromResult(true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A simple POST endpoint to demonstrate POST endpoints on an unbound controller.
|
||||
/// </summary>
|
||||
/// <returns>A simple true value to indicate the endpoint was reached.</returns>
|
||||
[HttpPost]
|
||||
[Authorization(CommerceRoles.Customer, CommerceRoles.Device, CommerceRoles.Employee)]
|
||||
public Task<bool> SimplePingPost()
|
||||
{
|
||||
return Task.FromResult(true);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
/**
|
||||
* SAMPLE CODE NOTICE
|
||||
*
|
||||
* THIS SAMPLE CODE IS MADE AVAILABLE AS IS. MICROSOFT MAKES NO WARRANTIES, WHETHER EXPRESS OR IMPLIED,
|
||||
* OF FITNESS FOR A PARTICULAR PURPOSE, OF ACCURACY OR COMPLETENESS OF RESPONSES, OF RESULTS, OR CONDITIONS OF MERCHANTABILITY.
|
||||
* THE ENTIRE RISK OF THE USE OR THE RESULTS FROM THE USE OF THIS SAMPLE CODE REMAINS WITH THE USER.
|
||||
* NO TECHNICAL SUPPORT IS PROVIDED. YOU MAY NOT DISTRIBUTE THIS CODE UNLESS YOU HAVE A LICENSE AGREEMENT WITH MICROSOFT THAT ALLOWS YOU TO DO SO.
|
||||
*/
|
||||
|
||||
namespace Contoso.CommerceRuntime.Entities.DataModel
|
||||
{
|
||||
using System.Runtime.Serialization;
|
||||
using Microsoft.Dynamics.Commerce.Runtime.ComponentModel.DataAnnotations;
|
||||
using Microsoft.Dynamics.Commerce.Runtime.DataModel;
|
||||
using SystemAnnotations = System.ComponentModel.DataAnnotations;
|
||||
|
||||
/// <summary>
|
||||
/// Defines a simple class that holds information about opening and closing times for a particular day.
|
||||
/// </summary>
|
||||
public class ExampleEntity : CommerceEntity
|
||||
{
|
||||
private const string ExampleIntColumn = "EXAMPLEINT";
|
||||
private const string ExampleStringColumn = "EXAMPLESTRING";
|
||||
private const string IdColumn = "EXAMPLEID";
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ExampleEntity"/> class.
|
||||
/// </summary>
|
||||
public ExampleEntity()
|
||||
: base("Example")
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a property containing an int value.
|
||||
/// </summary>
|
||||
[DataMember]
|
||||
[Column(ExampleIntColumn)]
|
||||
public int IntData
|
||||
{
|
||||
get { return (int)this[ExampleIntColumn]; }
|
||||
set { this[ExampleIntColumn] = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a property containing a string value.
|
||||
/// </summary>
|
||||
[DataMember]
|
||||
[Column(ExampleStringColumn)]
|
||||
public string StringData
|
||||
{
|
||||
get { return (string)this[ExampleStringColumn]; }
|
||||
set { this[ExampleStringColumn] = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the id.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Fields named "Id" are automatically treated as the entity key.
|
||||
/// If a name other than Id is preferred, <see cref="System.ComponentModel.DataAnnotations.KeyAttribute"/>
|
||||
/// can be used like it is here to annotate a given field as the entity key.
|
||||
/// </remarks>
|
||||
[SystemAnnotations.Key]
|
||||
[DataMember]
|
||||
[Column(IdColumn)]
|
||||
public long UnusualEntityId
|
||||
{
|
||||
get { return (long)this[IdColumn]; }
|
||||
set { this[IdColumn] = value; }
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
/**
|
||||
* SAMPLE CODE NOTICE
|
||||
*
|
||||
* THIS SAMPLE CODE IS MADE AVAILABLE AS IS. MICROSOFT MAKES NO WARRANTIES, WHETHER EXPRESS OR IMPLIED,
|
||||
* OF FITNESS FOR A PARTICULAR PURPOSE, OF ACCURACY OR COMPLETENESS OF RESPONSES, OF RESULTS, OR CONDITIONS OF MERCHANTABILITY.
|
||||
* THE ENTIRE RISK OF THE USE OR THE RESULTS FROM THE USE OF THIS SAMPLE CODE REMAINS WITH THE USER.
|
||||
* NO TECHNICAL SUPPORT IS PROVIDED. YOU MAY NOT DISTRIBUTE THIS CODE UNLESS YOU HAVE A LICENSE AGREEMENT WITH MICROSOFT THAT ALLOWS YOU TO DO SO.
|
||||
*/
|
||||
|
||||
namespace Contoso.CommerceRuntime.Messages
|
||||
{
|
||||
using System.Runtime.Serialization;
|
||||
using Contoso.CommerceRuntime.Entities.DataModel;
|
||||
using Microsoft.Dynamics.Commerce.Runtime.Messages;
|
||||
|
||||
/// <summary>
|
||||
/// A simple request class to create an Example Entity in the database.
|
||||
/// </summary>
|
||||
[DataContract]
|
||||
public sealed class CreateExampleEntityDataRequest : Request
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="CreateExampleEntityDataRequest"/> class.
|
||||
/// </summary>
|
||||
/// <param name="entityData">An example entity with its fields populated with the values to be stored.</param>
|
||||
public CreateExampleEntityDataRequest(ExampleEntity entityData)
|
||||
{
|
||||
this.EntityData = entityData;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets an Example Entity instance with its fields set with the values to be stored.
|
||||
/// </summary>
|
||||
[DataMember]
|
||||
public ExampleEntity EntityData { get; private set; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
/**
|
||||
* SAMPLE CODE NOTICE
|
||||
*
|
||||
* THIS SAMPLE CODE IS MADE AVAILABLE AS IS. MICROSOFT MAKES NO WARRANTIES, WHETHER EXPRESS OR IMPLIED,
|
||||
* OF FITNESS FOR A PARTICULAR PURPOSE, OF ACCURACY OR COMPLETENESS OF RESPONSES, OF RESULTS, OR CONDITIONS OF MERCHANTABILITY.
|
||||
* THE ENTIRE RISK OF THE USE OR THE RESULTS FROM THE USE OF THIS SAMPLE CODE REMAINS WITH THE USER.
|
||||
* NO TECHNICAL SUPPORT IS PROVIDED. YOU MAY NOT DISTRIBUTE THIS CODE UNLESS YOU HAVE A LICENSE AGREEMENT WITH MICROSOFT THAT ALLOWS YOU TO DO SO.
|
||||
*/
|
||||
|
||||
namespace Contoso.CommerceRuntime.Messages
|
||||
{
|
||||
using System.Runtime.Serialization;
|
||||
using Microsoft.Dynamics.Commerce.Runtime.Messages;
|
||||
|
||||
/// <summary>
|
||||
/// A simple response class to indicate whether creating a new entity succeeded or not.
|
||||
/// </summary>
|
||||
[DataContract]
|
||||
public sealed class CreateExampleEntityDataResponse : Response
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="CreateExampleEntityDataResponse"/> class.
|
||||
/// </summary>
|
||||
/// <param name="createdId">The ID of the newly saved entity instance, 0 in the event of failure.</param>
|
||||
public CreateExampleEntityDataResponse(long createdId)
|
||||
{
|
||||
this.CreatedId = createdId;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the ID of the newly saved entity instance, or 0 in the event of failure.
|
||||
/// </summary>
|
||||
public long CreatedId { get; private set; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
/**
|
||||
* SAMPLE CODE NOTICE
|
||||
*
|
||||
* THIS SAMPLE CODE IS MADE AVAILABLE AS IS. MICROSOFT MAKES NO WARRANTIES, WHETHER EXPRESS OR IMPLIED,
|
||||
* OF FITNESS FOR A PARTICULAR PURPOSE, OF ACCURACY OR COMPLETENESS OF RESPONSES, OF RESULTS, OR CONDITIONS OF MERCHANTABILITY.
|
||||
* THE ENTIRE RISK OF THE USE OR THE RESULTS FROM THE USE OF THIS SAMPLE CODE REMAINS WITH THE USER.
|
||||
* NO TECHNICAL SUPPORT IS PROVIDED. YOU MAY NOT DISTRIBUTE THIS CODE UNLESS YOU HAVE A LICENSE AGREEMENT WITH MICROSOFT THAT ALLOWS YOU TO DO SO.
|
||||
*/
|
||||
|
||||
namespace Contoso.CommerceRuntime.Messages
|
||||
{
|
||||
using System.Runtime.Serialization;
|
||||
using Microsoft.Dynamics.Commerce.Runtime.Messages;
|
||||
|
||||
/// <summary>
|
||||
/// A simple request used to delete an example entity from the database.
|
||||
/// </summary>
|
||||
[DataContract]
|
||||
public sealed class DeleteExampleEntityDataRequest : Request
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="DeleteExampleEntityDataRequest"/> class.
|
||||
/// </summary>
|
||||
/// <param name="entityKey">A unique key identifying an Example Entity record to delete.</param>
|
||||
public DeleteExampleEntityDataRequest(long entityKey)
|
||||
{
|
||||
this.ExampleEntityKey = entityKey;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the unique ID specifying the Example Entity record to delete.
|
||||
/// </summary>
|
||||
public long ExampleEntityKey { get; private set; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
/**
|
||||
* SAMPLE CODE NOTICE
|
||||
*
|
||||
* THIS SAMPLE CODE IS MADE AVAILABLE AS IS. MICROSOFT MAKES NO WARRANTIES, WHETHER EXPRESS OR IMPLIED,
|
||||
* OF FITNESS FOR A PARTICULAR PURPOSE, OF ACCURACY OR COMPLETENESS OF RESPONSES, OF RESULTS, OR CONDITIONS OF MERCHANTABILITY.
|
||||
* THE ENTIRE RISK OF THE USE OR THE RESULTS FROM THE USE OF THIS SAMPLE CODE REMAINS WITH THE USER.
|
||||
* NO TECHNICAL SUPPORT IS PROVIDED. YOU MAY NOT DISTRIBUTE THIS CODE UNLESS YOU HAVE A LICENSE AGREEMENT WITH MICROSOFT THAT ALLOWS YOU TO DO SO.
|
||||
*/
|
||||
|
||||
namespace Contoso.CommerceRuntime.Messages
|
||||
{
|
||||
using System.Runtime.Serialization;
|
||||
using Microsoft.Dynamics.Commerce.Runtime.Messages;
|
||||
|
||||
/// <summary>
|
||||
/// A simple response class to indicate whether a delete succeeded or not.
|
||||
/// </summary>
|
||||
[DataContract]
|
||||
public sealed class DeleteExampleEntityDataResponse : Response
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a new instance of the <see cref="DeleteExampleEntityDataResponse"/> class.
|
||||
/// </summary>
|
||||
/// <param name="success">Whether the delete succeeded.</param>
|
||||
public DeleteExampleEntityDataResponse(bool success)
|
||||
{
|
||||
this.Success = success;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the delete succeeded.
|
||||
/// </summary>
|
||||
public bool Success { get; private set; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
/**
|
||||
* SAMPLE CODE NOTICE
|
||||
*
|
||||
* THIS SAMPLE CODE IS MADE AVAILABLE AS IS. MICROSOFT MAKES NO WARRANTIES, WHETHER EXPRESS OR IMPLIED,
|
||||
* OF FITNESS FOR A PARTICULAR PURPOSE, OF ACCURACY OR COMPLETENESS OF RESPONSES, OF RESULTS, OR CONDITIONS OF MERCHANTABILITY.
|
||||
* THE ENTIRE RISK OF THE USE OR THE RESULTS FROM THE USE OF THIS SAMPLE CODE REMAINS WITH THE USER.
|
||||
* NO TECHNICAL SUPPORT IS PROVIDED. YOU MAY NOT DISTRIBUTE THIS CODE UNLESS YOU HAVE A LICENSE AGREEMENT WITH MICROSOFT THAT ALLOWS YOU TO DO SO.
|
||||
*/
|
||||
namespace Contoso.CommerceRuntime.Messages
|
||||
{
|
||||
using System.Runtime.Serialization;
|
||||
using Microsoft.Dynamics.Commerce.Runtime.Messages;
|
||||
|
||||
/// <summary>
|
||||
/// A simple request class to get all Example Entities.
|
||||
/// </summary>
|
||||
[DataContract]
|
||||
public sealed class ExampleEntityDataRequest : Request
|
||||
{
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
/**
|
||||
* SAMPLE CODE NOTICE
|
||||
*
|
||||
* THIS SAMPLE CODE IS MADE AVAILABLE AS IS. MICROSOFT MAKES NO WARRANTIES, WHETHER EXPRESS OR IMPLIED,
|
||||
* OF FITNESS FOR A PARTICULAR PURPOSE, OF ACCURACY OR COMPLETENESS OF RESPONSES, OF RESULTS, OR CONDITIONS OF MERCHANTABILITY.
|
||||
* THE ENTIRE RISK OF THE USE OR THE RESULTS FROM THE USE OF THIS SAMPLE CODE REMAINS WITH THE USER.
|
||||
* NO TECHNICAL SUPPORT IS PROVIDED. YOU MAY NOT DISTRIBUTE THIS CODE UNLESS YOU HAVE A LICENSE AGREEMENT WITH MICROSOFT THAT ALLOWS YOU TO DO SO.
|
||||
*/
|
||||
|
||||
namespace Contoso.CommerceRuntime.Messages
|
||||
{
|
||||
using System.Runtime.Serialization;
|
||||
using Contoso.CommerceRuntime.Entities.DataModel;
|
||||
using Microsoft.Dynamics.Commerce.Runtime;
|
||||
using Microsoft.Dynamics.Commerce.Runtime.Messages;
|
||||
|
||||
/// <summary>
|
||||
/// Defines a simple response class that holds a collection of Example Entities.
|
||||
/// </summary>
|
||||
[DataContract]
|
||||
public sealed class ExampleEntityDataResponse : Response
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ExampleEntityDataResponse"/> class.
|
||||
/// </summary>
|
||||
/// <param name="exampleEntities">The collection of Example Entities.</param>
|
||||
public ExampleEntityDataResponse(PagedResult<ExampleEntity> exampleEntities)
|
||||
{
|
||||
this.ExampleEntities = exampleEntities;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the retrieved Example Entities as a paged result.
|
||||
/// </summary>
|
||||
[DataMember]
|
||||
public PagedResult<ExampleEntity> ExampleEntities { get; private set; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
/**
|
||||
* SAMPLE CODE NOTICE
|
||||
*
|
||||
* THIS SAMPLE CODE IS MADE AVAILABLE AS IS. MICROSOFT MAKES NO WARRANTIES, WHETHER EXPRESS OR IMPLIED,
|
||||
* OF FITNESS FOR A PARTICULAR PURPOSE, OF ACCURACY OR COMPLETENESS OF RESPONSES, OF RESULTS, OR CONDITIONS OF MERCHANTABILITY.
|
||||
* THE ENTIRE RISK OF THE USE OR THE RESULTS FROM THE USE OF THIS SAMPLE CODE REMAINS WITH THE USER.
|
||||
* NO TECHNICAL SUPPORT IS PROVIDED. YOU MAY NOT DISTRIBUTE THIS CODE UNLESS YOU HAVE A LICENSE AGREEMENT WITH MICROSOFT THAT ALLOWS YOU TO DO SO.
|
||||
*/
|
||||
|
||||
namespace Contoso.CommerceRuntime.Messages
|
||||
{
|
||||
using System.Runtime.Serialization;
|
||||
using Contoso.CommerceRuntime.Entities.DataModel;
|
||||
using Microsoft.Dynamics.Commerce.Runtime.Messages;
|
||||
|
||||
/// <summary>
|
||||
/// A simple request class to update the values on an example entity.
|
||||
/// </summary>
|
||||
[DataContract]
|
||||
public sealed class UpdateExampleEntityDataRequest : Request
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="UpdateExampleEntityDataRequest"/> class.
|
||||
/// </summary>
|
||||
/// <param name="entityKey">A unique key identifying an Example Entity record to update.</param>
|
||||
/// <param name="updatedEntity">An example entity with update fields.</param>
|
||||
public UpdateExampleEntityDataRequest(long entityKey, ExampleEntity updatedEntity)
|
||||
{
|
||||
this.ExampleEntityKey = entityKey;
|
||||
this.UpdatedExampleEntity = updatedEntity;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the unique ID specifying the Example Entity record to update.
|
||||
/// </summary>
|
||||
public long ExampleEntityKey { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets an Example Entity instance with any updates applied to it.
|
||||
/// </summary>
|
||||
[DataMember]
|
||||
public ExampleEntity UpdatedExampleEntity { get; private set; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
/**
|
||||
* SAMPLE CODE NOTICE
|
||||
*
|
||||
* THIS SAMPLE CODE IS MADE AVAILABLE AS IS. MICROSOFT MAKES NO WARRANTIES, WHETHER EXPRESS OR IMPLIED,
|
||||
* OF FITNESS FOR A PARTICULAR PURPOSE, OF ACCURACY OR COMPLETENESS OF RESPONSES, OF RESULTS, OR CONDITIONS OF MERCHANTABILITY.
|
||||
* THE ENTIRE RISK OF THE USE OR THE RESULTS FROM THE USE OF THIS SAMPLE CODE REMAINS WITH THE USER.
|
||||
* NO TECHNICAL SUPPORT IS PROVIDED. YOU MAY NOT DISTRIBUTE THIS CODE UNLESS YOU HAVE A LICENSE AGREEMENT WITH MICROSOFT THAT ALLOWS YOU TO DO SO.
|
||||
*/
|
||||
|
||||
namespace Contoso.CommerceRuntime.Messages
|
||||
{
|
||||
using System.Runtime.Serialization;
|
||||
using Microsoft.Dynamics.Commerce.Runtime.Messages;
|
||||
|
||||
/// <summary>
|
||||
/// A simple response class to indicate whether an update succeeded or not.
|
||||
/// </summary>
|
||||
[DataContract]
|
||||
public sealed class UpdateExampleEntityDataResponse : Response
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="UpdateExampleEntityDataResponse"/> class.
|
||||
/// </summary>
|
||||
/// <param name="success">Whether the update succeeded.</param>
|
||||
public UpdateExampleEntityDataResponse(bool success)
|
||||
{
|
||||
this.Success = success;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the update succeeded.
|
||||
/// </summary>
|
||||
public bool Success { get; private set; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,174 @@
|
|||
/**
|
||||
* SAMPLE CODE NOTICE
|
||||
*
|
||||
* THIS SAMPLE CODE IS MADE AVAILABLE AS IS. MICROSOFT MAKES NO WARRANTIES, WHETHER EXPRESS OR IMPLIED,
|
||||
* OF FITNESS FOR A PARTICULAR PURPOSE, OF ACCURACY OR COMPLETENESS OF RESPONSES, OF RESULTS, OR CONDITIONS OF MERCHANTABILITY.
|
||||
* THE ENTIRE RISK OF THE USE OR THE RESULTS FROM THE USE OF THIS SAMPLE CODE REMAINS WITH THE USER.
|
||||
* NO TECHNICAL SUPPORT IS PROVIDED. YOU MAY NOT DISTRIBUTE THIS CODE UNLESS YOU HAVE A LICENSE AGREEMENT WITH MICROSOFT THAT ALLOWS YOU TO DO SO.
|
||||
*/
|
||||
|
||||
namespace Contoso.CommerceRuntime.RequestHandlers
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Dynamics.Commerce.Runtime;
|
||||
using Microsoft.Dynamics.Commerce.Runtime.Data;
|
||||
using Microsoft.Dynamics.Commerce.Runtime.Messages;
|
||||
using Contoso.CommerceRuntime.Entities.DataModel;
|
||||
using Contoso.CommerceRuntime.Messages;
|
||||
|
||||
/// <summary>
|
||||
/// Sample service to demonstrate managing a collection of entities.
|
||||
/// </summary>
|
||||
public class ExampleDataService : IRequestHandlerAsync
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the collection of supported request types by this handler.
|
||||
/// </summary>
|
||||
public IEnumerable<Type> SupportedRequestTypes
|
||||
{
|
||||
get
|
||||
{
|
||||
return new[]
|
||||
{
|
||||
typeof(CreateExampleEntityDataRequest),
|
||||
typeof(ExampleEntityDataRequest),
|
||||
typeof(UpdateExampleEntityDataRequest),
|
||||
typeof(DeleteExampleEntityDataRequest),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Entry point to StoreHoursDataService service.
|
||||
/// </summary>
|
||||
/// <param name="request">The request to execute.</param>
|
||||
/// <returns>Result of executing request, or null object for void operations.</returns>
|
||||
public Task<Response> Execute(Request request)
|
||||
{
|
||||
if (request == null)
|
||||
{
|
||||
throw new ArgumentNullException("request");
|
||||
}
|
||||
|
||||
Type reqType = request.GetType();
|
||||
if (reqType == typeof(CreateExampleEntityDataRequest))
|
||||
{
|
||||
return this.CreateExampleEntity((CreateExampleEntityDataRequest)request);
|
||||
}
|
||||
else if (reqType == typeof(ExampleEntityDataRequest))
|
||||
{
|
||||
return this.GetExampleEntities((ExampleEntityDataRequest)request);
|
||||
}
|
||||
else if (reqType == typeof(UpdateExampleEntityDataRequest))
|
||||
{
|
||||
return this.UpdateExampleEntity((UpdateExampleEntityDataRequest)request);
|
||||
}
|
||||
else if (reqType == typeof(DeleteExampleEntityDataRequest))
|
||||
{
|
||||
return this.DeleteExampleEntity((DeleteExampleEntityDataRequest)request);
|
||||
}
|
||||
else
|
||||
{
|
||||
string message = string.Format(CultureInfo.InvariantCulture, "Request '{0}' is not supported.", reqType);
|
||||
throw new NotSupportedException(message);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<Response> CreateExampleEntity(CreateExampleEntityDataRequest request)
|
||||
{
|
||||
ThrowIf.Null(request, nameof(request));
|
||||
ThrowIf.Null(request.EntityData, nameof(request.EntityData));
|
||||
|
||||
long insertedId = 0;
|
||||
using (var databaseContext = new DatabaseContext(request.RequestContext))
|
||||
{
|
||||
ParameterSet parameters = new ParameterSet();
|
||||
parameters["@i_ExampleInt"] = request.EntityData.IntData;
|
||||
parameters["@s_ExampleString"] = request.EntityData.StringData;
|
||||
var result = await databaseContext
|
||||
.ExecuteStoredProcedureAsync<ExampleEntity>("[ext].CONTOSO_INSERTEXAMPLE", parameters, request.QueryResultSettings)
|
||||
.ConfigureAwait(continueOnCapturedContext: false);
|
||||
insertedId = result.Item2.Single().UnusualEntityId;
|
||||
}
|
||||
|
||||
return new CreateExampleEntityDataResponse(insertedId);
|
||||
}
|
||||
|
||||
private async Task<Response> GetExampleEntities(ExampleEntityDataRequest request)
|
||||
{
|
||||
ThrowIf.Null(request, "request");
|
||||
|
||||
using (DatabaseContext databaseContext = new DatabaseContext(request.RequestContext))
|
||||
{
|
||||
var query = new SqlPagedQuery(request.QueryResultSettings)
|
||||
{
|
||||
DatabaseSchema = "ext",
|
||||
Select = new ColumnSet("EXAMPLEINT", "EXAMPLESTRING", "EXAMPLEID"),
|
||||
From = "CONTOSO_EXAMPLEVIEW",
|
||||
OrderBy = "EXAMPLEID",
|
||||
};
|
||||
|
||||
var queryResults =
|
||||
await databaseContext
|
||||
.ReadEntityAsync<Entities.DataModel.ExampleEntity>(query)
|
||||
.ConfigureAwait(continueOnCapturedContext: false);
|
||||
return new ExampleEntityDataResponse(queryResults);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<Response> UpdateExampleEntity(UpdateExampleEntityDataRequest request)
|
||||
{
|
||||
ThrowIf.Null(request, nameof(request));
|
||||
ThrowIf.Null(request.UpdatedExampleEntity, nameof(request.UpdatedExampleEntity));
|
||||
|
||||
if (request.ExampleEntityKey == 0)
|
||||
{
|
||||
throw new DataValidationException(DataValidationErrors.Microsoft_Dynamics_Commerce_Runtime_ValueOutOfRange, $"{nameof(request.ExampleEntityKey)} cannot be 0");
|
||||
}
|
||||
|
||||
bool updateSuccess = false;
|
||||
using (var databaseContext = new DatabaseContext(request.RequestContext))
|
||||
{
|
||||
ParameterSet parameters = new ParameterSet();
|
||||
parameters["@bi_Id"] = request.ExampleEntityKey;
|
||||
parameters["@i_ExampleInt"] = request.UpdatedExampleEntity.IntData;
|
||||
parameters["@s_ExampleString"] = request.UpdatedExampleEntity.StringData;
|
||||
int sprocErrorCode =
|
||||
await databaseContext
|
||||
.ExecuteStoredProcedureNonQueryAsync("[ext].CONTOSO_UPDATEEXAMPLE", parameters, request.QueryResultSettings)
|
||||
.ConfigureAwait(continueOnCapturedContext: false);
|
||||
updateSuccess = (sprocErrorCode == 0);
|
||||
}
|
||||
|
||||
return new UpdateExampleEntityDataResponse(updateSuccess);
|
||||
}
|
||||
|
||||
private async Task<Response> DeleteExampleEntity(DeleteExampleEntityDataRequest request)
|
||||
{
|
||||
ThrowIf.Null(request, nameof(request));
|
||||
|
||||
if (request.ExampleEntityKey == 0)
|
||||
{
|
||||
throw new DataValidationException(DataValidationErrors.Microsoft_Dynamics_Commerce_Runtime_ValueOutOfRange, $"{nameof(request.ExampleEntityKey)} cannot be 0");
|
||||
}
|
||||
|
||||
bool deleteSuccess = false;
|
||||
using (var databaseContext = new DatabaseContext(request.RequestContext))
|
||||
{
|
||||
ParameterSet parameters = new ParameterSet();
|
||||
parameters["@bi_Id"] = request.ExampleEntityKey;
|
||||
int sprocErrorCode =
|
||||
await databaseContext
|
||||
.ExecuteStoredProcedureNonQueryAsync("[ext].CONTOSO_DELETEEXAMPLE", parameters, request.QueryResultSettings)
|
||||
.ConfigureAwait(continueOnCapturedContext: false);
|
||||
deleteSuccess = sprocErrorCode == 0;
|
||||
}
|
||||
|
||||
return new DeleteExampleEntityDataResponse(deleteSuccess);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
/**
|
||||
* SAMPLE CODE NOTICE
|
||||
*
|
||||
* THIS SAMPLE CODE IS MADE AVAILABLE AS IS. MICROSOFT MAKES NO WARRANTIES, WHETHER EXPRESS OR IMPLIED,
|
||||
* OF FITNESS FOR A PARTICULAR PURPOSE, OF ACCURACY OR COMPLETENESS OF RESPONSES, OF RESULTS, OR CONDITIONS OF MERCHANTABILITY.
|
||||
* THE ENTIRE RISK OF THE USE OR THE RESULTS FROM THE USE OF THIS SAMPLE CODE REMAINS WITH THE USER.
|
||||
* NO TECHNICAL SUPPORT IS PROVIDED. YOU MAY NOT DISTRIBUTE THIS CODE UNLESS YOU HAVE A LICENSE AGREEMENT WITH MICROSOFT THAT ALLOWS YOU TO DO SO.
|
||||
*/
|
||||
|
||||
namespace Contoso.CommerceRuntime.Triggers
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.Dynamics.Commerce.Runtime;
|
||||
using Microsoft.Dynamics.Commerce.Runtime.DataModel;
|
||||
using Microsoft.Dynamics.Commerce.Runtime.Messages;
|
||||
|
||||
/// <summary>
|
||||
/// Class that implements a post trigger for the GetCustomerDataRequest request type.
|
||||
/// </summary>
|
||||
public class DefinePosExtensionTrigger : IRequestTrigger
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the supported requests for this trigger.
|
||||
/// </summary>
|
||||
public IEnumerable<Type> SupportedRequestTypes
|
||||
{
|
||||
get
|
||||
{
|
||||
return new[] { typeof(GetExtensionPackageDefinitionsRequest) };
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Post trigger code to retrieve extension properties.
|
||||
/// </summary>
|
||||
/// <param name="request">The request.</param>
|
||||
/// <param name="response">The response.</param>
|
||||
public void OnExecuted(Request request, Response response)
|
||||
{
|
||||
ThrowIf.Null(request, "request");
|
||||
ThrowIf.Null(response, "response");
|
||||
|
||||
var getExtensionsResponse = (GetExtensionPackageDefinitionsResponse)response;
|
||||
var extensionPackageDefinition = new ExtensionPackageDefinition();
|
||||
extensionPackageDefinition.Name = "POS";
|
||||
extensionPackageDefinition.Publisher = "Contoso";
|
||||
extensionPackageDefinition.IsEnabled = true;
|
||||
|
||||
getExtensionsResponse.ExtensionPackageDefinitions.Add(extensionPackageDefinition);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Pre trigger code.
|
||||
/// </summary>
|
||||
/// <param name="request">The request.</param>
|
||||
public void OnExecuting(Request request)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
<Project>
|
||||
<Import Project="..\..\repo.props" />
|
||||
|
||||
<PropertyGroup>
|
||||
<PackagePublisher Condition="'$(PackagePublisher)' == ''">$(Publisher)</PackagePublisher>
|
||||
<PackagePublisherDisplayName Condition="'$(PackagePublisherDisplayName)' == ''">$(PublisherDisplayName)</PackagePublisherDisplayName>
|
||||
<PackageVersion Condition="'$(PackageVersion)' == ''">$(Version)</PackageVersion>
|
||||
<PackageName Condition="'$(PackageName)' == ''">Contoso.Commerce.ScaleUnit</PackageName>
|
||||
<PackageDisplayName Condition="'$(PackageDisplayName)' == ''">Contoso Scale Unit Example Commerce Customization</PackageDisplayName>
|
||||
<PackageDescription Condition="'$(PackageDescription)' == ''">Contoso Scale Unit Example Commerce Customization</PackageDescription>
|
||||
</PropertyGroup>
|
||||
</Project>
|
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<commerceRuntimeExtensions>
|
||||
<composition>
|
||||
<add source="assembly" value="CommerceRuntime" />
|
||||
</composition>
|
||||
</commerceRuntimeExtensions>
|
|
@ -0,0 +1,28 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Import Project="..\CustomizationPackage.props" />
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net461</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Include="Extension.config" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Dynamics.Commerce.Sdk.Installers.ScaleUnit" Version="$(CommerceSdkPackagesVersion)" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\ChannelDatabase\ChannelDatabase.csproj">
|
||||
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\CommerceRuntime\CommerceRuntime.csproj">
|
||||
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\POS\POS.csproj">
|
||||
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
</Project>
|
|
@ -0,0 +1,25 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>Example Create Dialog</title>
|
||||
</head>
|
||||
<body>
|
||||
<div class="ExampleCreateDialog col grow">
|
||||
<div>
|
||||
<div class="h4">Int data:</div>
|
||||
<input type="number" id="intData"></select>
|
||||
<br />
|
||||
<br />
|
||||
<div class="h4">String data:</div>
|
||||
<input type="text" id="stringData"></input>
|
||||
<br />
|
||||
<br />
|
||||
<div class="h4">Extension property string data:</div>
|
||||
<input type="text" id="extensionPropertyStringData"></input>
|
||||
</div>
|
||||
<div class="grow"></div>
|
||||
<div class="row"></div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,88 @@
|
|||
/**
|
||||
* SAMPLE CODE NOTICE
|
||||
*
|
||||
* THIS SAMPLE CODE IS MADE AVAILABLE AS IS. MICROSOFT MAKES NO WARRANTIES, WHETHER EXPRESS OR IMPLIED,
|
||||
* OF FITNESS FOR A PARTICULAR PURPOSE, OF ACCURACY OR COMPLETENESS OF RESPONSES, OF RESULTS, OR CONDITIONS OF MERCHANTABILITY.
|
||||
* THE ENTIRE RISK OF THE USE OR THE RESULTS FROM THE USE OF THIS SAMPLE CODE REMAINS WITH THE USER.
|
||||
* NO TECHNICAL SUPPORT IS PROVIDED. YOU MAY NOT DISTRIBUTE THIS CODE UNLESS YOU HAVE A LICENSE AGREEMENT WITH MICROSOFT THAT ALLOWS YOU TO DO SO.
|
||||
*/
|
||||
|
||||
import * as Dialogs from "PosApi/Create/Dialogs";
|
||||
import { Entities } from "../../../DataService/DataServiceEntities.g";
|
||||
import { ObjectExtensions } from "PosApi/TypeExtensions";
|
||||
|
||||
type DialogResolve = (updatedEntity: Entities.ExampleEntity) => void;
|
||||
type DialogReject = (reason: any) => void;
|
||||
|
||||
export default class ExampleCreateDialog extends Dialogs.ExtensionTemplatedDialogBase {
|
||||
private _resolve: DialogResolve;
|
||||
private _data: Entities.ExampleEntity;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this._data = {
|
||||
UnusualEntityId: -1,
|
||||
IntData: 0,
|
||||
StringData: "",
|
||||
ExtensionProperties: [{
|
||||
Key: "customExtensionProp",
|
||||
Value: {}
|
||||
}]
|
||||
};
|
||||
}
|
||||
|
||||
public onReady(element: HTMLElement): void {
|
||||
let intDataInput: HTMLInputElement = element.querySelector("#intData") as HTMLInputElement;
|
||||
intDataInput.onchange = () => { this._data.IntData = intDataInput.valueAsNumber; };
|
||||
|
||||
let stringDataInput: HTMLInputElement = element.querySelector("#stringData") as HTMLInputElement;
|
||||
stringDataInput.onchange = () => { this._data.StringData = stringDataInput.value; };
|
||||
|
||||
let extensionPropertyStringDataInput: HTMLInputElement = element.querySelector("#extensionPropertyStringData") as HTMLInputElement;
|
||||
extensionPropertyStringDataInput.onchange = () => {
|
||||
this._data.ExtensionProperties[0].Value.StringValue = extensionPropertyStringDataInput.value;
|
||||
};
|
||||
}
|
||||
|
||||
public open(): Promise<Entities.ExampleEntity> {
|
||||
let promise: Promise<Entities.ExampleEntity> = new Promise((resolve: DialogResolve, reject: DialogReject) => {
|
||||
this._resolve = resolve;
|
||||
let option: Dialogs.ITemplatedDialogOptions = {
|
||||
title: "Create Example Entity",
|
||||
button1: {
|
||||
id: "btnCreate",
|
||||
label: this.context.resources.getString("string_2001"),
|
||||
isPrimary: true,
|
||||
onClick: this.btnUpdateClickHandler.bind(this)
|
||||
},
|
||||
button2: {
|
||||
id: "btnCancel",
|
||||
label: this.context.resources.getString("string_2004"),
|
||||
onClick: this.btnCancelClickHandler.bind(this)
|
||||
},
|
||||
onCloseX: () => this.btnCancelClickHandler()
|
||||
};
|
||||
|
||||
this.openDialog(option);
|
||||
});
|
||||
|
||||
return promise;
|
||||
}
|
||||
|
||||
private btnUpdateClickHandler(): boolean {
|
||||
this.resolvePromise(this._data);
|
||||
return true;
|
||||
}
|
||||
|
||||
private btnCancelClickHandler(): boolean {
|
||||
this.resolvePromise(null);
|
||||
return true;
|
||||
}
|
||||
|
||||
private resolvePromise(editResult: Entities.ExampleEntity): void {
|
||||
if (ObjectExtensions.isFunction(this._resolve)) {
|
||||
this._resolve(editResult);
|
||||
this._resolve = null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>Ping Result Dialog</title>
|
||||
</head>
|
||||
<body>
|
||||
<div class="ExampleCreateDialog col grow">
|
||||
<p>
|
||||
<div class="h4">Unbound GET endpoint ping result:</div>
|
||||
<br />
|
||||
<br />
|
||||
<b class="h5" id="UnboundGetResult"></b>
|
||||
</p>
|
||||
<p>
|
||||
<div class="h4">Unbound POST endpoint ping result:</div>
|
||||
<br />
|
||||
<br />
|
||||
<b class="h5" id="UnboundPostResult"></b>
|
||||
</p>
|
||||
<div class="grow"></div>
|
||||
<div class="row"></div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,63 @@
|
|||
/**
|
||||
* SAMPLE CODE NOTICE
|
||||
*
|
||||
* THIS SAMPLE CODE IS MADE AVAILABLE AS IS. MICROSOFT MAKES NO WARRANTIES, WHETHER EXPRESS OR IMPLIED,
|
||||
* OF FITNESS FOR A PARTICULAR PURPOSE, OF ACCURACY OR COMPLETENESS OF RESPONSES, OF RESULTS, OR CONDITIONS OF MERCHANTABILITY.
|
||||
* THE ENTIRE RISK OF THE USE OR THE RESULTS FROM THE USE OF THIS SAMPLE CODE REMAINS WITH THE USER.
|
||||
* NO TECHNICAL SUPPORT IS PROVIDED. YOU MAY NOT DISTRIBUTE THIS CODE UNLESS YOU HAVE A LICENSE AGREEMENT WITH MICROSOFT THAT ALLOWS YOU TO DO SO.
|
||||
*/
|
||||
|
||||
import * as Dialogs from "PosApi/Create/Dialogs";
|
||||
import { ObjectExtensions } from "PosApi/TypeExtensions";
|
||||
|
||||
type DialogResolve = (result: any) => void;
|
||||
type DialogReject = (reason: any) => void;
|
||||
|
||||
export default class PingResultDialog extends Dialogs.ExtensionTemplatedDialogBase {
|
||||
private _resolve: DialogResolve;
|
||||
private _pingUnboundGetResult: boolean;
|
||||
private _pingUnboundPostResult: boolean;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
|
||||
public onReady(element: HTMLElement): void {
|
||||
let getPingResult = element.querySelector("#UnboundGetResult") as HTMLSpanElement;
|
||||
getPingResult.textContent = this._pingUnboundGetResult ? "Success!" : "Failed.";
|
||||
let postPingResult = element.querySelector("#UnboundPostResult") as HTMLSpanElement;
|
||||
postPingResult.textContent = this._pingUnboundPostResult ? "Success!" : "Failed.";
|
||||
}
|
||||
|
||||
public open(pingUnboundGetResult: boolean, pingUnboundPostResult: boolean): Promise<void> {
|
||||
let promise: Promise<void> = new Promise((resolve: DialogResolve, reject: DialogReject) => {
|
||||
this._resolve = resolve;
|
||||
this._pingUnboundGetResult = pingUnboundGetResult;
|
||||
this._pingUnboundPostResult = pingUnboundPostResult;
|
||||
this.openDialog({
|
||||
title: "Ping Test Results",
|
||||
button1: {
|
||||
id: "btnOk",
|
||||
label: this.context.resources.getString("string_2005"),
|
||||
isPrimary: true,
|
||||
onClick: this.closeDialogHandler.bind(this)
|
||||
},
|
||||
onCloseX: () => this.closeDialogHandler()
|
||||
});
|
||||
});
|
||||
|
||||
return promise;
|
||||
}
|
||||
|
||||
private closeDialogHandler(): boolean {
|
||||
this.resolvePromise();
|
||||
return true;
|
||||
}
|
||||
|
||||
private resolvePromise(): void {
|
||||
if (ObjectExtensions.isFunction(this._resolve)) {
|
||||
this._resolve(null);
|
||||
this._resolve = null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>Example Edit Dialog</title>
|
||||
</head>
|
||||
<body>
|
||||
<div class="ExampleEditDialog col grow">
|
||||
<div>
|
||||
<div class="h4">Int data:</div>
|
||||
<input type="number" id="intData"></select>
|
||||
<br />
|
||||
<br />
|
||||
<div class="h4">String data:</div>
|
||||
<input type="text" id="stringData"></input>
|
||||
<br />
|
||||
<br />
|
||||
<div class="h4">Extension property string data:</div>
|
||||
<input type="text" id="extensionPropertyStringData"></input>
|
||||
</div>
|
||||
<div class="grow"></div>
|
||||
<div class="row"></div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,93 @@
|
|||
/**
|
||||
* SAMPLE CODE NOTICE
|
||||
*
|
||||
* THIS SAMPLE CODE IS MADE AVAILABLE AS IS. MICROSOFT MAKES NO WARRANTIES, WHETHER EXPRESS OR IMPLIED,
|
||||
* OF FITNESS FOR A PARTICULAR PURPOSE, OF ACCURACY OR COMPLETENESS OF RESPONSES, OF RESULTS, OR CONDITIONS OF MERCHANTABILITY.
|
||||
* THE ENTIRE RISK OF THE USE OR THE RESULTS FROM THE USE OF THIS SAMPLE CODE REMAINS WITH THE USER.
|
||||
* NO TECHNICAL SUPPORT IS PROVIDED. YOU MAY NOT DISTRIBUTE THIS CODE UNLESS YOU HAVE A LICENSE AGREEMENT WITH MICROSOFT THAT ALLOWS YOU TO DO SO.
|
||||
*/
|
||||
|
||||
import * as Dialogs from "PosApi/Create/Dialogs";
|
||||
import { Entities } from "../../../DataService/DataServiceEntities.g";
|
||||
import { ObjectExtensions } from "PosApi/TypeExtensions";
|
||||
|
||||
type DialogResolve = (updatedEntity: Entities.ExampleEntity) => void;
|
||||
type DialogReject = (reason: any) => void;
|
||||
|
||||
export default class ExampleEditDialog extends Dialogs.ExtensionTemplatedDialogBase {
|
||||
private _resolve: DialogResolve;
|
||||
private _data: Entities.ExampleEntity;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
|
||||
public onReady(element: HTMLElement): void {
|
||||
let intDataInput: HTMLInputElement = element.querySelector("#intData") as HTMLInputElement;
|
||||
intDataInput.value = this._data.IntData.toString();
|
||||
intDataInput.onchange = () => { this._data.IntData = intDataInput.valueAsNumber; };
|
||||
|
||||
let stringDataInput: HTMLInputElement = element.querySelector("#stringData") as HTMLInputElement;
|
||||
stringDataInput.value = this._data.StringData;
|
||||
stringDataInput.onchange = () => { this._data.StringData = stringDataInput.value; };
|
||||
|
||||
let extensionPropertyStringDataInput: HTMLInputElement = element.querySelector("#extensionPropertyStringData") as HTMLInputElement;
|
||||
extensionPropertyStringDataInput.value = this._data.ExtensionProperties.filter(prop => prop.Key == "customExtensionProp").map(prop => prop.Value.StringValue)[0];
|
||||
extensionPropertyStringDataInput.onchange = () => {
|
||||
if (this._data.ExtensionProperties.length > 0) {
|
||||
this._data.ExtensionProperties.filter(prop => prop.Key == "customExtensionProp")[0].Value.StringValue = extensionPropertyStringDataInput.value;
|
||||
} else {
|
||||
this._data.ExtensionProperties = [{
|
||||
Key: "customExtensionProp",
|
||||
Value: {
|
||||
StringValue: extensionPropertyStringDataInput.value
|
||||
}
|
||||
}];
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public open(dataToEdit: Entities.ExampleEntity): Promise<Entities.ExampleEntity> {
|
||||
this._data = dataToEdit;
|
||||
|
||||
let promise: Promise<Entities.ExampleEntity> = new Promise((resolve: DialogResolve, reject: DialogReject) => {
|
||||
this._resolve = resolve;
|
||||
let option: Dialogs.ITemplatedDialogOptions = {
|
||||
title: "Update Example Entity",
|
||||
button1: {
|
||||
id: "btnUpdate",
|
||||
label: this.context.resources.getString("string_2002"),
|
||||
isPrimary: true,
|
||||
onClick: this.btnUpdateClickHandler.bind(this)
|
||||
},
|
||||
button2: {
|
||||
id: "btnCancel",
|
||||
label: this.context.resources.getString("string_2004"),
|
||||
onClick: this.btnCancelClickHandler.bind(this)
|
||||
},
|
||||
onCloseX: () => this.btnCancelClickHandler()
|
||||
};
|
||||
|
||||
this.openDialog(option);
|
||||
});
|
||||
|
||||
return promise;
|
||||
}
|
||||
|
||||
private btnUpdateClickHandler(): boolean {
|
||||
this.resolvePromise(this._data);
|
||||
return true;
|
||||
}
|
||||
|
||||
private btnCancelClickHandler(): boolean {
|
||||
this.resolvePromise(null);
|
||||
return true;
|
||||
}
|
||||
|
||||
private resolvePromise(editResult: Entities.ExampleEntity): void {
|
||||
if (ObjectExtensions.isFunction(this._resolve)) {
|
||||
this._resolve(editResult);
|
||||
this._resolve = null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Import Project="..\CustomizationPackage.props" />
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Dynamics.Commerce.Sdk.Pos" Version="$(CommerceSdkPackagesVersion)" />
|
||||
<PackageReference Include="Microsoft.TypeScript.MSBuild" Version="4.0.*" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\CommerceRuntime\CommerceRuntime.csproj" />
|
||||
</ItemGroup>
|
||||
</Project>
|
|
@ -0,0 +1,38 @@
|
|||
//======================================================================================================
|
||||
//======================================= Store Hour Sample comment. ===================================
|
||||
//======================================================================================================
|
||||
{
|
||||
//======================== View extension titles. ========================
|
||||
"string_0001" : "EXAMPLE VIEW",
|
||||
"_string_0001.comment" : "The Example View's title.",
|
||||
|
||||
//======================== Column names. ========================
|
||||
"string_1001" : "Int data",
|
||||
"_string_1001.comment" : "A column title for the int data on the Example Entity.",
|
||||
|
||||
"string_1002" : "String data",
|
||||
"_string_2.comment" : "A column title for the string data on the Example Entity.",
|
||||
|
||||
"string_1003" : "Extension property string data",
|
||||
"_string_3.comment" : "A column title for the extension property data on the Example Entity.",
|
||||
|
||||
//======================== Dialog button labels. ========================
|
||||
"string_2001" : "Create",
|
||||
"_string_4.comment" : "Create button used on a dialog for making a new entity.",
|
||||
|
||||
"string_2002" : "Update",
|
||||
"_string_5.comment" : "Update button used to commit changes made to an entity in an update dialog.",
|
||||
|
||||
"string_1006" : "Delete",
|
||||
"_string_6.comment" : "Delete button used to delete an entity instance in the list view.",
|
||||
|
||||
"string_2004" : "Cancel",
|
||||
"_string_7.comment" : "Cancel button shared across dialogs.",
|
||||
|
||||
"string_2005" : "OK",
|
||||
"_string_8.comment" : "OK button used to dismiss a dialog.",
|
||||
|
||||
//======================== Command labels. ========================
|
||||
"string_3001" : "Ping Test",
|
||||
"_string_3001.comment" : "A button label used in the app bar, when pressed two unbound endpoints are pinged."
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
/**
|
||||
* SAMPLE CODE NOTICE
|
||||
*
|
||||
* THIS SAMPLE CODE IS MADE AVAILABLE AS IS. MICROSOFT MAKES NO WARRANTIES, WHETHER EXPRESS OR IMPLIED,
|
||||
* OF FITNESS FOR A PARTICULAR PURPOSE, OF ACCURACY OR COMPLETENESS OF RESPONSES, OF RESULTS, OR CONDITIONS OF MERCHANTABILITY.
|
||||
* THE ENTIRE RISK OF THE USE OR THE RESULTS FROM THE USE OF THIS SAMPLE CODE REMAINS WITH THE USER.
|
||||
* NO TECHNICAL SUPPORT IS PROVIDED. YOU MAY NOT DISTRIBUTE THIS CODE UNLESS YOU HAVE A LICENSE AGREEMENT WITH MICROSOFT THAT ALLOWS YOU TO DO SO.
|
||||
*/
|
||||
|
||||
import { IExtensionCommandContext } from "PosApi/Extend/Views/AppBarCommands";
|
||||
import * as SearchView from "PosApi/Extend/Views/SearchView";
|
||||
|
||||
export default class NavigateToExampleViewCommand extends SearchView.ProductSearchExtensionCommandBase {
|
||||
/**
|
||||
* Creates a new instance of the NavigateToExampleViewCommand class.
|
||||
* @param {IExtensionCommandContext<ProductDetailsView.IProductSearchToExtensionCommandMessageTypeMap>} context The command context.
|
||||
* @remarks The command context contains APIs through which a command can communicate with POS.
|
||||
*/
|
||||
constructor(context: IExtensionCommandContext<SearchView.IProductSearchToExtensionCommandMessageTypeMap>) {
|
||||
super(context);
|
||||
|
||||
this.id = "navigateToExampleViewCommand";
|
||||
this.label = "Navigate to Full System Example View";
|
||||
this.extraClass = "iconGo";
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the command.
|
||||
* @param {ProductDetailsView.IProductDetailsExtensionCommandState} state The state used to initialize the command.
|
||||
*/
|
||||
protected init(state: SearchView.IProductSearchExtensionCommandState): void {
|
||||
this.canExecute = true;
|
||||
this.isVisible = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the command.
|
||||
*/
|
||||
protected execute(): void {
|
||||
this.context.navigator.navigate("ExampleView");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>Example View</title>
|
||||
</head>
|
||||
<body>
|
||||
<div class="exampleView height100Percent">
|
||||
<div id="exampleListView" class="pad20 height100Percent">
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,152 @@
|
|||
/**
|
||||
* SAMPLE CODE NOTICE
|
||||
*
|
||||
* THIS SAMPLE CODE IS MADE AVAILABLE AS IS. MICROSOFT MAKES NO WARRANTIES, WHETHER EXPRESS OR IMPLIED,
|
||||
* OF FITNESS FOR A PARTICULAR PURPOSE, OF ACCURACY OR COMPLETENESS OF RESPONSES, OF RESULTS, OR CONDITIONS OF MERCHANTABILITY.
|
||||
* THE ENTIRE RISK OF THE USE OR THE RESULTS FROM THE USE OF THIS SAMPLE CODE REMAINS WITH THE USER.
|
||||
* NO TECHNICAL SUPPORT IS PROVIDED. YOU MAY NOT DISTRIBUTE THIS CODE UNLESS YOU HAVE A LICENSE AGREEMENT WITH MICROSOFT THAT ALLOWS YOU TO DO SO.
|
||||
*/
|
||||
|
||||
import * as Views from "PosApi/Create/Views";
|
||||
import { Entities } from "../DataService/DataServiceEntities.g";
|
||||
import ExampleViewModel from "./ExampleViewModel";
|
||||
import { IDataList, IDataListOptions, DataListInteractionMode } from "PosApi/Consume/Controls";
|
||||
import { ObjectExtensions, ArrayExtensions } from "PosApi/TypeExtensions";
|
||||
|
||||
/**
|
||||
* The controller for ExampleView.
|
||||
*/
|
||||
export default class StoreHoursView extends Views.CustomViewControllerBase {
|
||||
public readonly viewModel: ExampleViewModel;
|
||||
public dataList: IDataList<Entities.ExampleEntity>;
|
||||
|
||||
constructor(context: Views.ICustomViewControllerContext) {
|
||||
let config: Views.ICustomViewControllerConfiguration = {
|
||||
title: context.resources.getString("string_0001"),
|
||||
commandBar: {
|
||||
commands: [
|
||||
{
|
||||
name: "Create",
|
||||
label: context.resources.getString("string_2001"),
|
||||
icon: Views.Icons.Add,
|
||||
isVisible: true,
|
||||
canExecute: true,
|
||||
execute: (args: Views.CustomViewControllerExecuteCommandArgs): void => {
|
||||
this.viewModel.createExampleEntity().then((entityCreated) => {
|
||||
if (entityCreated) {
|
||||
// Re-load the list, since the underlying data was amended
|
||||
this.dataList.data = this.viewModel.loadedData;
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "Edit",
|
||||
label: context.resources.getString("string_2002"),
|
||||
icon: Views.Icons.Edit,
|
||||
isVisible: true,
|
||||
canExecute: false,
|
||||
execute: (args: Views.CustomViewControllerExecuteCommandArgs): void => {
|
||||
this.state.isProcessing = true;
|
||||
this.viewModel.editExampleEntity().then((editsMade) => {
|
||||
if (editsMade) {
|
||||
// Re-load the list since the underlying data changed
|
||||
this.dataList.data = this.viewModel.loadedData;
|
||||
}
|
||||
this.state.isProcessing = false;
|
||||
});
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "Delete",
|
||||
label: context.resources.getString("string_1006"),
|
||||
icon: Views.Icons.Delete,
|
||||
isVisible: true,
|
||||
canExecute: false,
|
||||
execute: (args: Views.CustomViewControllerExecuteCommandArgs): void => {
|
||||
this.state.isProcessing = true;
|
||||
this.viewModel.deleteExampleEntity().then(() => {
|
||||
// Re-load the list, since the data has changed
|
||||
this.dataList.data = this.viewModel.loadedData;
|
||||
this.state.isProcessing = false;
|
||||
});
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "PingTest",
|
||||
label: context.resources.getString("string_3001"),
|
||||
icon: Views.Icons.LightningBolt,
|
||||
isVisible: true,
|
||||
canExecute: true,
|
||||
execute: (args: Views.CustomViewControllerExecuteCommandArgs): void => {
|
||||
this.state.isProcessing = true;
|
||||
this.viewModel.runPingTest().then(() => {
|
||||
this.state.isProcessing = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
};
|
||||
|
||||
super(context, config);
|
||||
|
||||
// Initialize the view model.
|
||||
this.viewModel = new ExampleViewModel(context);
|
||||
}
|
||||
|
||||
public dispose(): void {
|
||||
ObjectExtensions.disposeAllProperties(this);
|
||||
}
|
||||
|
||||
public onReady(element: HTMLElement): void {
|
||||
// DataList
|
||||
let dataListOptions: IDataListOptions<Entities.ExampleEntity> = {
|
||||
interactionMode: DataListInteractionMode.SingleSelect,
|
||||
data: this.viewModel.loadedData,
|
||||
columns: [
|
||||
{
|
||||
title: this.context.resources.getString("string_1001"), // Int data
|
||||
ratio: 40, collapseOrder: 1, minWidth: 100,
|
||||
computeValue: (data: Entities.ExampleEntity): string => data.IntData.toString()
|
||||
},
|
||||
{
|
||||
title: this.context.resources.getString("string_1002"), // String data
|
||||
ratio: 30, collapseOrder: 2, minWidth: 100,
|
||||
computeValue: (data: Entities.ExampleEntity): string => data.StringData
|
||||
},
|
||||
{
|
||||
title: this.context.resources.getString("string_1003"), // Extension property string data
|
||||
ratio: 30, collapseOrder: 3, minWidth: 100,
|
||||
computeValue: (data: Entities.ExampleEntity): string => {
|
||||
return ArrayExtensions.firstOrUndefined(
|
||||
data.ExtensionProperties.filter(prop => prop.Key == "customExtensionProp").map(prop => prop.Value.StringValue)
|
||||
);
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
let dataListRootElem: HTMLDivElement = element.querySelector("#exampleListView") as HTMLDivElement;
|
||||
this.dataList = this.context.controlFactory.create(this.context.logger.getNewCorrelationId(), "DataList", dataListOptions, dataListRootElem);
|
||||
|
||||
this.dataList.addEventListener("SelectionChanged", (eventData: { items: Entities.ExampleEntity[] }) => {
|
||||
this.viewModel.seletionChanged(eventData.items);
|
||||
|
||||
// Update the command states to reflect the current selection state.
|
||||
this.state.commandBar.commands.forEach(
|
||||
command => command.canExecute = (
|
||||
["Create", "PingTest"].some(name => name == command.name) ||
|
||||
this.viewModel.isItemSelected()
|
||||
)
|
||||
);
|
||||
});
|
||||
|
||||
this.state.isProcessing = true;
|
||||
this.viewModel.load().then((): void => {
|
||||
// Initialize the data list with what the view model loaded
|
||||
this.dataList.data = this.viewModel.loadedData;
|
||||
this.state.isProcessing = false;
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,139 @@
|
|||
/**
|
||||
* SAMPLE CODE NOTICE
|
||||
*
|
||||
* THIS SAMPLE CODE IS MADE AVAILABLE AS IS. MICROSOFT MAKES NO WARRANTIES, WHETHER EXPRESS OR IMPLIED,
|
||||
* OF FITNESS FOR A PARTICULAR PURPOSE, OF ACCURACY OR COMPLETENESS OF RESPONSES, OF RESULTS, OR CONDITIONS OF MERCHANTABILITY.
|
||||
* THE ENTIRE RISK OF THE USE OR THE RESULTS FROM THE USE OF THIS SAMPLE CODE REMAINS WITH THE USER.
|
||||
* NO TECHNICAL SUPPORT IS PROVIDED. YOU MAY NOT DISTRIBUTE THIS CODE UNLESS YOU HAVE A LICENSE AGREEMENT WITH MICROSOFT THAT ALLOWS YOU TO DO SO.
|
||||
*/
|
||||
|
||||
import { IExtensionViewControllerContext } from "PosApi/Create/Views";
|
||||
import { Entities } from "../DataService/DataServiceEntities.g";
|
||||
import * as Messages from "../DataService/DataServiceRequests.g";
|
||||
import ExampleCreateDialog from "../Controls/Dialogs/Create/ExampleCreateDialogModule";
|
||||
import ExampleEditDialog from "../Controls/Dialogs/Edit/ExampleEditDialogModule";
|
||||
import PingResultDialog from "../Controls/Dialogs/Display/PingResultDialogModule";
|
||||
import { ObjectExtensions, ArrayExtensions } from "PosApi/TypeExtensions";
|
||||
|
||||
/**
|
||||
* The ViewModel for ExampleView.
|
||||
*/
|
||||
export default class ExampleViewModel {
|
||||
public title: string;
|
||||
public loadedData: Entities.ExampleEntity[];
|
||||
public isItemSelected: () => boolean;
|
||||
private _selectedItem: Entities.ExampleEntity;
|
||||
private _context: IExtensionViewControllerContext;
|
||||
|
||||
constructor(context: IExtensionViewControllerContext) {
|
||||
this._context = context;
|
||||
this.title = context.resources.getString("string_0001");
|
||||
this.loadedData = [];
|
||||
this.isItemSelected = () => !ObjectExtensions.isNullOrUndefined(this._selectedItem);
|
||||
}
|
||||
|
||||
public load(): Promise<void> {
|
||||
return this._context.runtime
|
||||
.executeAsync(new Messages.BoundController.GetAllExampleEntitiesRequest())
|
||||
.then(response => {
|
||||
if (!response.canceled) {
|
||||
this.loadedData = response.data.result;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Handler for list item selection.
|
||||
* @param {Entities.ExampleEntity[]} items
|
||||
*/
|
||||
public seletionChanged(items: Entities.ExampleEntity[]): Promise<void> {
|
||||
this._context.logger.logInformational("Item selected:" + JSON.stringify(items));
|
||||
this._selectedItem = ArrayExtensions.firstOrUndefined(items);
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
public createExampleEntity(): Promise<boolean> {
|
||||
let dialog: ExampleCreateDialog = new ExampleCreateDialog();
|
||||
return dialog
|
||||
.open()
|
||||
.then(newItem => {
|
||||
// No action if the dialog was canceled
|
||||
if (ObjectExtensions.isNullOrUndefined(newItem)) {
|
||||
this._context.logger.logInformational("Create canceled.");
|
||||
return Promise.resolve(false);;
|
||||
}
|
||||
|
||||
this._context.logger.logInformational("Item created with data: " + JSON.stringify(newItem));
|
||||
// Create the entity and reload the loaded data to reflect the change:
|
||||
return this._context.runtime
|
||||
.executeAsync(new Messages.BoundController.CreateExampleEntityRequest(newItem))
|
||||
.then(response => {
|
||||
if (!response.canceled && response.data.result != 0) {
|
||||
this._context.logger.logInformational("Create success for id: " + response.data.result);
|
||||
return this.load().then((): boolean => true); // Load the updated data
|
||||
}
|
||||
this._context.logger.logInformational("Create failed for entity: " + JSON.stringify(newItem));
|
||||
return Promise.resolve(false);
|
||||
});
|
||||
}).catch(reason => {
|
||||
this._context.logger.logError("Error occurred in the create dialog: " + JSON.stringify(reason));
|
||||
return Promise.resolve(false);;
|
||||
});
|
||||
}
|
||||
|
||||
public editExampleEntity(): Promise<boolean> {
|
||||
let dialog: ExampleEditDialog = new ExampleEditDialog();
|
||||
return dialog
|
||||
.open(this._selectedItem)
|
||||
.then(updatedItem => {
|
||||
// No action if the dialog was canceled
|
||||
if (ObjectExtensions.isNullOrUndefined(updatedItem)) {
|
||||
this._context.logger.logInformational("Update canceled for data: " + JSON.stringify(updatedItem));
|
||||
return Promise.resolve(false);
|
||||
}
|
||||
|
||||
this._context.logger.logInformational("Updated data is: " + JSON.stringify(updatedItem));
|
||||
// Perform the update and reload the loaded data to reflect the change:
|
||||
return this._context.runtime
|
||||
.executeAsync(new Messages.BoundController.UpdateExampleEntityRequest(updatedItem.UnusualEntityId, updatedItem))
|
||||
.then(response => {
|
||||
if (!response.canceled && response.data.result) {
|
||||
this._context.logger.logInformational("Update success for id: " + updatedItem.UnusualEntityId);
|
||||
return this.load().then((): boolean => true); // Load the updated data
|
||||
}
|
||||
this._context.logger.logInformational("Update failed for id: " + updatedItem.UnusualEntityId);
|
||||
return Promise.resolve(false);
|
||||
});
|
||||
}).catch(reason => {
|
||||
this._context.logger.logError("Error occurred in the edit dialog: " + JSON.stringify(reason));
|
||||
return Promise.resolve(false);
|
||||
});
|
||||
}
|
||||
|
||||
public deleteExampleEntity(): Promise<void> {
|
||||
// Delete the selected entity and reload the loaded data to reflect the change:
|
||||
return this._context.runtime
|
||||
.executeAsync(new Messages.BoundController.DeleteExampleEntityRequest(this._selectedItem.UnusualEntityId))
|
||||
.then(response => {
|
||||
if (!response.canceled && response.data.result) {
|
||||
this._context.logger.logInformational("Delete success for id: " + this._selectedItem.UnusualEntityId);
|
||||
return this.load(); // Load the updated data
|
||||
}
|
||||
this._context.logger.logInformational("Delete failed for id " + this._selectedItem.UnusualEntityId);
|
||||
return Promise.resolve();
|
||||
});
|
||||
}
|
||||
|
||||
public runPingTest(): Promise<void> {
|
||||
return this._context.runtime
|
||||
.executeAsync(new Messages.StoreOperations.SimplePingGetRequest())
|
||||
.then(pingGetResponse => {
|
||||
return this._context.runtime
|
||||
.executeAsync(new Messages.StoreOperations.SimplePingPostRequest())
|
||||
.then(pingPostResponse => {
|
||||
let pingResultDialog: PingResultDialog = new PingResultDialog();
|
||||
return pingResultDialog.open(pingGetResponse.data.result, pingPostResponse.data.result);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
{
|
||||
"$schema": "./devDependencies/schemas/manifestSchema.json",
|
||||
"name": "Contoso.Pos.FullSystemExample.Sample",
|
||||
"publisher": "Contoso",
|
||||
"version": "1.0.0",
|
||||
"minimumPosVersion": "9.29.0.0",
|
||||
"description": "An extension package that makes use of a Retail Server extension. Also works off-line.",
|
||||
"components": {
|
||||
"resources": {
|
||||
"supportedUICultures": [ "en-US" ],
|
||||
"fallbackUICulture": "en-US",
|
||||
"culturesDirectoryPath": "Resources/Strings",
|
||||
"stringResourcesFileName": "resources.resjson"
|
||||
},
|
||||
"extend": {
|
||||
"views": {
|
||||
"SearchView": {
|
||||
"productAppBarCommands": [
|
||||
{ "modulePath": "ViewExtensions/Search/NavigateToExampleViewCommand" },
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"create": {
|
||||
"templatedDialogs": [
|
||||
{
|
||||
"htmlPath": "Controls/Dialogs/Create/ExampleCreateDialog.html",
|
||||
"modulePath": "Controls/Dialogs/Create/ExampleCreateDialogModule"
|
||||
},
|
||||
{
|
||||
"htmlPath": "Controls/Dialogs/Edit/ExampleEditDialog.html",
|
||||
"modulePath": "Controls/Dialogs/Edit/ExampleEditDialogModule"
|
||||
},
|
||||
{
|
||||
"htmlPath": "Controls/Dialogs/Display/PingResultDialog.html",
|
||||
"modulePath": "Controls/Dialogs/Display/PingResultDialogModule"
|
||||
}
|
||||
],
|
||||
"views": [
|
||||
{
|
||||
"title": "Sample Extension View",
|
||||
"pageName": "ExampleView",
|
||||
"phonePageName": "ExampleView",
|
||||
"viewDirectory": "Views/",
|
||||
"viewControllerPath": "Views/ExampleView"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"extends": "./devDependencies/pos-tsconfig-base.json"
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 15
|
||||
VisualStudioVersion = 15.0.28307.1267
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ChannelDatabase", "ChannelDatabase\ChannelDatabase.csproj", "{A8166D6A-9868-43C8-8732-0D2DD6C9826C}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CommerceRuntime", "CommerceRuntime\CommerceRuntime.csproj", "{59AA9A4E-084B-4DF4-83D2-151759F6944F}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ScaleUnit", "ScaleUnit\ScaleUnit.csproj", "{2888FAB4-68EF-4670-ABFF-20E1DBAA32F4}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "POS", "POS\POS.csproj", "{F69DE011-47C5-46FC-A9E0-88A62650B082}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ScaleUnit.Installer", "Installer\ScaleUnit.Installer.csproj", "{E937C87D-E159-44F0-AD36-DEAA6D72E678}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{A8166D6A-9868-43C8-8732-0D2DD6C9826C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{A8166D6A-9868-43C8-8732-0D2DD6C9826C}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{A8166D6A-9868-43C8-8732-0D2DD6C9826C}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{A8166D6A-9868-43C8-8732-0D2DD6C9826C}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{59AA9A4E-084B-4DF4-83D2-151759F6944F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{59AA9A4E-084B-4DF4-83D2-151759F6944F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{59AA9A4E-084B-4DF4-83D2-151759F6944F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{59AA9A4E-084B-4DF4-83D2-151759F6944F}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{2888FAB4-68EF-4670-ABFF-20E1DBAA32F4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{2888FAB4-68EF-4670-ABFF-20E1DBAA32F4}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{2888FAB4-68EF-4670-ABFF-20E1DBAA32F4}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{2888FAB4-68EF-4670-ABFF-20E1DBAA32F4}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{F69DE011-47C5-46FC-A9E0-88A62650B082}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{F69DE011-47C5-46FC-A9E0-88A62650B082}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{F69DE011-47C5-46FC-A9E0-88A62650B082}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{F69DE011-47C5-46FC-A9E0-88A62650B082}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{E937C87D-E159-44F0-AD36-DEAA6D72E678}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{E937C87D-E159-44F0-AD36-DEAA6D72E678}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{E937C87D-E159-44F0-AD36-DEAA6D72E678}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{E937C87D-E159-44F0-AD36-DEAA6D72E678}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {D8D07A3D-D311-441B-A70E-A959154EE41B}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
|
@ -0,0 +1,23 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk" ToolsVersion="15.0">
|
||||
<Import Project="..\CustomizationPackage.props" />
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\ChannelDatabase\ChannelDatabase.csproj">
|
||||
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\CommerceRuntime\CommerceRuntime.csproj">
|
||||
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\POS\POS.csproj">
|
||||
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Dynamics.Commerce.Sdk.ScaleUnit" Version="$(CommerceSdkPackagesVersion)" />
|
||||
</ItemGroup>
|
||||
</Project>
|
Загрузка…
Ссылка в новой задаче