diff --git a/plugins/ProductTag/.gitattributes b/plugins/ProductTag/.gitattributes new file mode 100644 index 00000000..c941e526 --- /dev/null +++ b/plugins/ProductTag/.gitattributes @@ -0,0 +1 @@ +**/wwwroot/libs/** linguist-vendored diff --git a/plugins/ProductTag/.gitignore b/plugins/ProductTag/.gitignore new file mode 100644 index 00000000..666ef8a0 --- /dev/null +++ b/plugins/ProductTag/.gitignore @@ -0,0 +1,258 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# User-specific files +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ + +# Visual Studio 2015 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUNIT +*.VisualState.xml +TestResult.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# DNX +project.lock.json +artifacts/ + +*_i.c +*_p.c +*_i.h +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# JustCode is a .NET coding add-in +.JustCode + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# TODO: Comment the next line if you want to checkin your web deploy settings +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# The packages folder can be ignored because of Package Restore +**/packages/* +# except build/, which is used as an MSBuild target. +!**/packages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/packages/repositories.config +# NuGet v3's project.json files produces more ignoreable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.pfx +*.publishsettings +node_modules/ +orleans.codegen.cs + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm + +# SQL Server files +*.mdf +*.ldf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# JetBrains Rider +.idea/ +*.sln.iml + +# ProductTag +host/EasyAbp.EShop.Plugins.ProductTag.IdentityServer/Logs/logs.txt +host/EasyAbp.EShop.Plugins.ProductTag.HttpApi.Host/Logs/logs.txt +host/EasyAbp.EShop.Plugins.ProductTag.Web.Host/Logs/logs.txt +host/EasyAbp.EShop.Plugins.ProductTag.Web.Unified/Logs/logs.txt diff --git a/plugins/ProductTag/EasyAbp.EShop.Plugins.ProductTag.sln b/plugins/ProductTag/EasyAbp.EShop.Plugins.ProductTag.sln new file mode 100644 index 00000000..b43e8329 --- /dev/null +++ b/plugins/ProductTag/EasyAbp.EShop.Plugins.ProductTag.sln @@ -0,0 +1,139 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.29001.49 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EasyAbp.EShop.Plugins.ProductTag.Domain.Shared", "src\EasyAbp.EShop.Plugins.ProductTag.Domain.Shared\EasyAbp.EShop.Plugins.ProductTag.Domain.Shared.csproj", "{D64C1577-4929-4B60-939E-96DE1534891A}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EasyAbp.EShop.Plugins.ProductTag.Domain", "src\EasyAbp.EShop.Plugins.ProductTag.Domain\EasyAbp.EShop.Plugins.ProductTag.Domain.csproj", "{F2840BC7-0188-4606-9126-DADD0F5ABF7A}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EasyAbp.EShop.Plugins.ProductTag.Application.Contracts", "src\EasyAbp.EShop.Plugins.ProductTag.Application.Contracts\EasyAbp.EShop.Plugins.ProductTag.Application.Contracts.csproj", "{BD65D04F-08D5-40C1-8C24-77CA0BACB877}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EasyAbp.EShop.Plugins.ProductTag.Application", "src\EasyAbp.EShop.Plugins.ProductTag.Application\EasyAbp.EShop.Plugins.ProductTag.Application.csproj", "{78040F9E-3501-4A40-82DF-00A597710F35}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{649A3FFA-182F-4E56-9717-E6A9A2BEC545}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{CCD2960C-23CC-4AB4-B84D-60C7AAA52F4D}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "host", "host", "{E400416D-2895-4512-9D17-90681EEC7E0A}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EasyAbp.EShop.Plugins.ProductTag.EntityFrameworkCore", "src\EasyAbp.EShop.Plugins.ProductTag.EntityFrameworkCore\EasyAbp.EShop.Plugins.ProductTag.EntityFrameworkCore.csproj", "{0CE86223-D31D-4315-A1F5-87BA3EE1B844}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EasyAbp.EShop.Plugins.ProductTag.MongoDB", "src\EasyAbp.EShop.Plugins.ProductTag.MongoDB\EasyAbp.EShop.Plugins.ProductTag.MongoDB.csproj", "{F1C58097-4C08-4D88-8976-6B3389391481}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EasyAbp.EShop.Plugins.ProductTag.HttpApi", "src\EasyAbp.EShop.Plugins.ProductTag.HttpApi\EasyAbp.EShop.Plugins.ProductTag.HttpApi.csproj", "{077AA5F8-8B61-420C-A6B5-0150A66FDB34}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EasyAbp.EShop.Plugins.ProductTag.HttpApi.Client", "src\EasyAbp.EShop.Plugins.ProductTag.HttpApi.Client\EasyAbp.EShop.Plugins.ProductTag.HttpApi.Client.csproj", "{36E2735F-CEAB-44C8-A6D1-2CDAFF399751}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EasyAbp.EShop.Plugins.ProductTag.TestBase", "test\EasyAbp.EShop.Plugins.ProductTag.TestBase\EasyAbp.EShop.Plugins.ProductTag.TestBase.csproj", "{C5BB573D-3030-4BCB-88B7-F6A85C32766C}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EasyAbp.EShop.Plugins.ProductTag.EntityFrameworkCore.Tests", "test\EasyAbp.EShop.Plugins.ProductTag.EntityFrameworkCore.Tests\EasyAbp.EShop.Plugins.ProductTag.EntityFrameworkCore.Tests.csproj", "{527F645C-C1FC-406E-8479-81386C8ECF13}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EasyAbp.EShop.Plugins.ProductTag.MongoDB.Tests", "test\EasyAbp.EShop.Plugins.ProductTag.MongoDB.Tests\EasyAbp.EShop.Plugins.ProductTag.MongoDB.Tests.csproj", "{D0AD9179-125C-40B2-A8EE-CD4C1EE24BB6}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EasyAbp.EShop.Plugins.ProductTag.Domain.Tests", "test\EasyAbp.EShop.Plugins.ProductTag.Domain.Tests\EasyAbp.EShop.Plugins.ProductTag.Domain.Tests.csproj", "{E60895E5-79C4-447D-88B7-85CB5BA336A4}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EasyAbp.EShop.Plugins.ProductTag.Application.Tests", "test\EasyAbp.EShop.Plugins.ProductTag.Application.Tests\EasyAbp.EShop.Plugins.ProductTag.Application.Tests.csproj", "{90CB5DC4-C040-45C7-8900-9688B26405BC}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EasyAbp.EShop.Plugins.ProductTag.Web", "src\EasyAbp.EShop.Plugins.ProductTag.Web\EasyAbp.EShop.Plugins.ProductTag.Web.csproj", "{3B7B6317-1B85-4164-8E11-75574F80AE17}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EasyAbp.EShop.Plugins.ProductTag.HttpApi.Client.ConsoleTestApp", "test\EasyAbp.EShop.Plugins.ProductTag.HttpApi.Client.ConsoleTestApp\EasyAbp.EShop.Plugins.ProductTag.HttpApi.Client.ConsoleTestApp.csproj", "{1EDCD6D4-DF3A-4E3B-ABB6-C0D0B373EAB8}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EasyAbp.EShop.Plugins.ProductTag.Host.Shared", "host\EasyAbp.EShop.Plugins.ProductTag.Host.Shared\EasyAbp.EShop.Plugins.ProductTag.Host.Shared.csproj", "{F6AC8D4A-EDD7-4514-8E8A-5BCB019864DB}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {D64C1577-4929-4B60-939E-96DE1534891A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D64C1577-4929-4B60-939E-96DE1534891A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D64C1577-4929-4B60-939E-96DE1534891A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D64C1577-4929-4B60-939E-96DE1534891A}.Release|Any CPU.Build.0 = Release|Any CPU + {F2840BC7-0188-4606-9126-DADD0F5ABF7A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F2840BC7-0188-4606-9126-DADD0F5ABF7A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F2840BC7-0188-4606-9126-DADD0F5ABF7A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F2840BC7-0188-4606-9126-DADD0F5ABF7A}.Release|Any CPU.Build.0 = Release|Any CPU + {BD65D04F-08D5-40C1-8C24-77CA0BACB877}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BD65D04F-08D5-40C1-8C24-77CA0BACB877}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BD65D04F-08D5-40C1-8C24-77CA0BACB877}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BD65D04F-08D5-40C1-8C24-77CA0BACB877}.Release|Any CPU.Build.0 = Release|Any CPU + {78040F9E-3501-4A40-82DF-00A597710F35}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {78040F9E-3501-4A40-82DF-00A597710F35}.Debug|Any CPU.Build.0 = Debug|Any CPU + {78040F9E-3501-4A40-82DF-00A597710F35}.Release|Any CPU.ActiveCfg = Release|Any CPU + {78040F9E-3501-4A40-82DF-00A597710F35}.Release|Any CPU.Build.0 = Release|Any CPU + {0CE86223-D31D-4315-A1F5-87BA3EE1B844}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0CE86223-D31D-4315-A1F5-87BA3EE1B844}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0CE86223-D31D-4315-A1F5-87BA3EE1B844}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0CE86223-D31D-4315-A1F5-87BA3EE1B844}.Release|Any CPU.Build.0 = Release|Any CPU + {F1C58097-4C08-4D88-8976-6B3389391481}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F1C58097-4C08-4D88-8976-6B3389391481}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F1C58097-4C08-4D88-8976-6B3389391481}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F1C58097-4C08-4D88-8976-6B3389391481}.Release|Any CPU.Build.0 = Release|Any CPU + {077AA5F8-8B61-420C-A6B5-0150A66FDB34}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {077AA5F8-8B61-420C-A6B5-0150A66FDB34}.Debug|Any CPU.Build.0 = Debug|Any CPU + {077AA5F8-8B61-420C-A6B5-0150A66FDB34}.Release|Any CPU.ActiveCfg = Release|Any CPU + {077AA5F8-8B61-420C-A6B5-0150A66FDB34}.Release|Any CPU.Build.0 = Release|Any CPU + {36E2735F-CEAB-44C8-A6D1-2CDAFF399751}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {36E2735F-CEAB-44C8-A6D1-2CDAFF399751}.Debug|Any CPU.Build.0 = Debug|Any CPU + {36E2735F-CEAB-44C8-A6D1-2CDAFF399751}.Release|Any CPU.ActiveCfg = Release|Any CPU + {36E2735F-CEAB-44C8-A6D1-2CDAFF399751}.Release|Any CPU.Build.0 = Release|Any CPU + {C5BB573D-3030-4BCB-88B7-F6A85C32766C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C5BB573D-3030-4BCB-88B7-F6A85C32766C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C5BB573D-3030-4BCB-88B7-F6A85C32766C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C5BB573D-3030-4BCB-88B7-F6A85C32766C}.Release|Any CPU.Build.0 = Release|Any CPU + {527F645C-C1FC-406E-8479-81386C8ECF13}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {527F645C-C1FC-406E-8479-81386C8ECF13}.Debug|Any CPU.Build.0 = Debug|Any CPU + {527F645C-C1FC-406E-8479-81386C8ECF13}.Release|Any CPU.ActiveCfg = Release|Any CPU + {527F645C-C1FC-406E-8479-81386C8ECF13}.Release|Any CPU.Build.0 = Release|Any CPU + {D0AD9179-125C-40B2-A8EE-CD4C1EE24BB6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D0AD9179-125C-40B2-A8EE-CD4C1EE24BB6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D0AD9179-125C-40B2-A8EE-CD4C1EE24BB6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D0AD9179-125C-40B2-A8EE-CD4C1EE24BB6}.Release|Any CPU.Build.0 = Release|Any CPU + {E60895E5-79C4-447D-88B7-85CB5BA336A4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E60895E5-79C4-447D-88B7-85CB5BA336A4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E60895E5-79C4-447D-88B7-85CB5BA336A4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E60895E5-79C4-447D-88B7-85CB5BA336A4}.Release|Any CPU.Build.0 = Release|Any CPU + {90CB5DC4-C040-45C7-8900-9688B26405BC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {90CB5DC4-C040-45C7-8900-9688B26405BC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {90CB5DC4-C040-45C7-8900-9688B26405BC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {90CB5DC4-C040-45C7-8900-9688B26405BC}.Release|Any CPU.Build.0 = Release|Any CPU + {3B7B6317-1B85-4164-8E11-75574F80AE17}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3B7B6317-1B85-4164-8E11-75574F80AE17}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3B7B6317-1B85-4164-8E11-75574F80AE17}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3B7B6317-1B85-4164-8E11-75574F80AE17}.Release|Any CPU.Build.0 = Release|Any CPU + {1EDCD6D4-DF3A-4E3B-ABB6-C0D0B373EAB8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1EDCD6D4-DF3A-4E3B-ABB6-C0D0B373EAB8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1EDCD6D4-DF3A-4E3B-ABB6-C0D0B373EAB8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1EDCD6D4-DF3A-4E3B-ABB6-C0D0B373EAB8}.Release|Any CPU.Build.0 = Release|Any CPU + {F6AC8D4A-EDD7-4514-8E8A-5BCB019864DB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F6AC8D4A-EDD7-4514-8E8A-5BCB019864DB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F6AC8D4A-EDD7-4514-8E8A-5BCB019864DB}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F6AC8D4A-EDD7-4514-8E8A-5BCB019864DB}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {D64C1577-4929-4B60-939E-96DE1534891A} = {649A3FFA-182F-4E56-9717-E6A9A2BEC545} + {F2840BC7-0188-4606-9126-DADD0F5ABF7A} = {649A3FFA-182F-4E56-9717-E6A9A2BEC545} + {BD65D04F-08D5-40C1-8C24-77CA0BACB877} = {649A3FFA-182F-4E56-9717-E6A9A2BEC545} + {78040F9E-3501-4A40-82DF-00A597710F35} = {649A3FFA-182F-4E56-9717-E6A9A2BEC545} + {0CE86223-D31D-4315-A1F5-87BA3EE1B844} = {649A3FFA-182F-4E56-9717-E6A9A2BEC545} + {F1C58097-4C08-4D88-8976-6B3389391481} = {649A3FFA-182F-4E56-9717-E6A9A2BEC545} + {077AA5F8-8B61-420C-A6B5-0150A66FDB34} = {649A3FFA-182F-4E56-9717-E6A9A2BEC545} + {36E2735F-CEAB-44C8-A6D1-2CDAFF399751} = {649A3FFA-182F-4E56-9717-E6A9A2BEC545} + {C5BB573D-3030-4BCB-88B7-F6A85C32766C} = {CCD2960C-23CC-4AB4-B84D-60C7AAA52F4D} + {527F645C-C1FC-406E-8479-81386C8ECF13} = {CCD2960C-23CC-4AB4-B84D-60C7AAA52F4D} + {D0AD9179-125C-40B2-A8EE-CD4C1EE24BB6} = {CCD2960C-23CC-4AB4-B84D-60C7AAA52F4D} + {E60895E5-79C4-447D-88B7-85CB5BA336A4} = {CCD2960C-23CC-4AB4-B84D-60C7AAA52F4D} + {90CB5DC4-C040-45C7-8900-9688B26405BC} = {CCD2960C-23CC-4AB4-B84D-60C7AAA52F4D} + {3B7B6317-1B85-4164-8E11-75574F80AE17} = {649A3FFA-182F-4E56-9717-E6A9A2BEC545} + {1EDCD6D4-DF3A-4E3B-ABB6-C0D0B373EAB8} = {CCD2960C-23CC-4AB4-B84D-60C7AAA52F4D} + {F6AC8D4A-EDD7-4514-8E8A-5BCB019864DB} = {E400416D-2895-4512-9D17-90681EEC7E0A} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {4324B3B4-B60B-4E3C-91D8-59576B4E26DD} + EndGlobalSection +EndGlobal diff --git a/plugins/ProductTag/EasyAbp.EShop.Plugins.ProductTag.sln.DotSettings b/plugins/ProductTag/EasyAbp.EShop.Plugins.ProductTag.sln.DotSettings new file mode 100644 index 00000000..cb0b2c91 --- /dev/null +++ b/plugins/ProductTag/EasyAbp.EShop.Plugins.ProductTag.sln.DotSettings @@ -0,0 +1,23 @@ + + True + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + Required + Required + Required + Required + False + True + False + False + True + False + False + SQL + \ No newline at end of file diff --git a/plugins/ProductTag/common.props b/plugins/ProductTag/common.props new file mode 100644 index 00000000..d9519ad8 --- /dev/null +++ b/plugins/ProductTag/common.props @@ -0,0 +1,30 @@ + + + latest + 0.1.0 + $(NoWarn);CS1591 + module + true + EasyAbp Team + An abp application module group that provides basic e-shop service. + https://avatars3.githubusercontent.com/u/58311641?s=128 + https://github.com/EasyAbp/EShop + https://github.com/EasyAbp/EShop + abp module easyabp EShop shopping shop ordering product payment store mall + EasyAbp + MIT + + + + + + + + + + all + runtime; build; native; contentfiles; analyzers + + + + \ No newline at end of file diff --git a/plugins/ProductTag/docker-compose.migrations.yml b/plugins/ProductTag/docker-compose.migrations.yml new file mode 100644 index 00000000..5e7c2ed1 --- /dev/null +++ b/plugins/ProductTag/docker-compose.migrations.yml @@ -0,0 +1,13 @@ +version: '3.4' + +services: + migrations: + build: + context: ../../ + dockerfile: templates/service/database/Dockerfile + depends_on: + - sqlserver + environment: + - IdentityServer_DB=ProductTag_Identity + - ProductTag_DB=ProductTag_ModuleDb + - SA_PASSWORD=yourStrong(!)Password diff --git a/plugins/ProductTag/docker-compose.override.yml b/plugins/ProductTag/docker-compose.override.yml new file mode 100644 index 00000000..d5d2a0e4 --- /dev/null +++ b/plugins/ProductTag/docker-compose.override.yml @@ -0,0 +1,29 @@ +version: '3.4' + +services: + sqlserver: + environment: + - SA_PASSWORD=yourStrong(!)Password + - ACCEPT_EULA=Y + ports: + - "51599:1433" + + identity-server: + environment: + - ASPNETCORE_URLS=http://0.0.0.0:80 + - ConnectionStrings__Default=Server=sqlserver;Database=ProductTag_Identity;Trusted_Connection=True;MultipleActiveResultSets=true;User=sa;Password=yourStrong(!)Password;Integrated Security=false + - ConnectionStrings__SqlServerCache=Server=sqlserver;Database=ProductTag_Cache;Trusted_Connection=True;MultipleActiveResultSets=true;User=sa;Password=yourStrong(!)Password;Integrated Security=false + ports: + - "51600:80" + + product-tag: + environment: + - ASPNETCORE_URLS=http://0.0.0.0:80 + - ConnectionStrings__Default=Server=sqlserver;Database=ProductTag_ModuleDb;Trusted_Connection=True;MultipleActiveResultSets=true;User=sa;Password=yourStrong(!)Password;Integrated Security=false + - ConnectionStrings__AbpSettingManagement=Server=sqlserver;Database=ProductTag_Identity;Trusted_Connection=True;MultipleActiveResultSets=true;User=sa;Password=yourStrong(!)Password;Integrated Security=false + - ConnectionStrings__AbpPermissionManagement=Server=sqlserver;Database=ProductTag_Identity;Trusted_Connection=True;MultipleActiveResultSets=true;User=sa;Password=yourStrong(!)Password;Integrated Security=false + - ConnectionStrings__AbpAuditLogging=Server=sqlserver;Database=ProductTag_Identity;Trusted_Connection=True;MultipleActiveResultSets=true;User=sa;Password=yourStrong(!)Password;Integrated Security=false + - ConnectionStrings__SqlServerCache=Server=sqlserver;Database=ProductTag_Cache;Trusted_Connection=True;MultipleActiveResultSets=true;User=sa;Password=yourStrong(!)Password;Integrated Security=false + - AuthServer__Authority=http://identity-server + ports: + - "51601:80" \ No newline at end of file diff --git a/plugins/ProductTag/docker-compose.yml b/plugins/ProductTag/docker-compose.yml new file mode 100644 index 00000000..54ef5f29 --- /dev/null +++ b/plugins/ProductTag/docker-compose.yml @@ -0,0 +1,25 @@ +version: '3.4' + +services: + sqlserver: + image: mcr.microsoft.com/mssql/server + volumes: + - dbdata:/var/opt/mssql + + identity-server: + build: + context: ../../ + dockerfile: templates/service/host/IdentityServerHost/Dockerfile + depends_on: + - sqlserver + + product-tag: + build: + context: ../../ + dockerfile: templates/service/host/EasyAbp.EShop.Plugins.ProductTag.Host/Dockerfile + depends_on: + - sqlserver + - identity-server + +volumes: + dbdata: \ No newline at end of file diff --git a/plugins/ProductTag/host/EasyAbp.EShop.Plugins.ProductTag.Host.Shared/EasyAbp.EShop.Plugins.ProductTag.Host.Shared.csproj b/plugins/ProductTag/host/EasyAbp.EShop.Plugins.ProductTag.Host.Shared/EasyAbp.EShop.Plugins.ProductTag.Host.Shared.csproj new file mode 100644 index 00000000..d469bb9b --- /dev/null +++ b/plugins/ProductTag/host/EasyAbp.EShop.Plugins.ProductTag.Host.Shared/EasyAbp.EShop.Plugins.ProductTag.Host.Shared.csproj @@ -0,0 +1,10 @@ + + + + + + netstandard2.0 + EasyAbp.EShop.Plugins.ProductTag + + + diff --git a/plugins/ProductTag/host/EasyAbp.EShop.Plugins.ProductTag.Host.Shared/MultiTenancy/MultiTenancyConsts.cs b/plugins/ProductTag/host/EasyAbp.EShop.Plugins.ProductTag.Host.Shared/MultiTenancy/MultiTenancyConsts.cs new file mode 100644 index 00000000..4e271474 --- /dev/null +++ b/plugins/ProductTag/host/EasyAbp.EShop.Plugins.ProductTag.Host.Shared/MultiTenancy/MultiTenancyConsts.cs @@ -0,0 +1,10 @@ +namespace EasyAbp.EShop.Plugins.ProductTag.MultiTenancy +{ + public static class MultiTenancyConsts + { + /* Enable/disable multi-tenancy in a single point + * to test your module with multi-tenancy. + */ + public const bool IsEnabled = false; + } +} diff --git a/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Application.Contracts/EasyAbp.EShop.Plugins.ProductTag.Application.Contracts.csproj b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Application.Contracts/EasyAbp.EShop.Plugins.ProductTag.Application.Contracts.csproj new file mode 100644 index 00000000..b953a1d8 --- /dev/null +++ b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Application.Contracts/EasyAbp.EShop.Plugins.ProductTag.Application.Contracts.csproj @@ -0,0 +1,20 @@ + + + + + + netstandard2.0 + EasyAbp.EShop.Plugins.ProductTag + + + + + + + + + + + + + diff --git a/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Application.Contracts/FodyWeavers.xml b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Application.Contracts/FodyWeavers.xml new file mode 100644 index 00000000..be0de3a9 --- /dev/null +++ b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Application.Contracts/FodyWeavers.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Application.Contracts/FodyWeavers.xsd b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Application.Contracts/FodyWeavers.xsd new file mode 100644 index 00000000..3f3946e2 --- /dev/null +++ b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Application.Contracts/FodyWeavers.xsd @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + 'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed. + + + + + A comma-separated list of error codes that can be safely ignored in assembly verification. + + + + + 'false' to turn off automatic generation of the XML Schema file. + + + + + \ No newline at end of file diff --git a/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Application.Contracts/Permissions/ProductTagPermissionDefinitionProvider.cs b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Application.Contracts/Permissions/ProductTagPermissionDefinitionProvider.cs new file mode 100644 index 00000000..d8d8dfd3 --- /dev/null +++ b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Application.Contracts/Permissions/ProductTagPermissionDefinitionProvider.cs @@ -0,0 +1,25 @@ +using EasyAbp.EShop.Plugins.ProductTag.Localization; +using Volo.Abp.Authorization.Permissions; +using Volo.Abp.Localization; + +namespace EasyAbp.EShop.Plugins.ProductTag.Permissions +{ + public class ProductTagPermissionDefinitionProvider : PermissionDefinitionProvider + { + public override void Define(IPermissionDefinitionContext context) + { + var moduleGroup = context.AddGroup(ProductTagPermissions.GroupName, L("Permission:ProductTag")); + + var tags = moduleGroup.AddPermission(ProductTagPermissions.Tags.Default, L("Permission:Tag")); + tags.AddChild(ProductTagPermissions.Tags.Create, L("Permission:Create")); + tags.AddChild(ProductTagPermissions.Tags.Update, L("Permission:Update")); + tags.AddChild(ProductTagPermissions.Tags.Delete, L("Permission:Delete")); + tags.AddChild(ProductTagPermissions.Tags.CrossStore, L("Permission:CrossStore")); + } + + private static LocalizableString L(string name) + { + return LocalizableString.Create(name); + } + } +} \ No newline at end of file diff --git a/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Application.Contracts/Permissions/ProductTagPermissions.cs b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Application.Contracts/Permissions/ProductTagPermissions.cs new file mode 100644 index 00000000..68707d32 --- /dev/null +++ b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Application.Contracts/Permissions/ProductTagPermissions.cs @@ -0,0 +1,23 @@ +using Volo.Abp.Reflection; + +namespace EasyAbp.EShop.Plugins.ProductTag.Permissions +{ + public class ProductTagPermissions + { + public const string GroupName = "EasyAbp.EShop.ProductTag"; + + public class Tags + { + public const string Default = GroupName + ".Tag"; + public const string Delete = Default + ".Delete"; + public const string Update = Default + ".Update"; + public const string Create = Default + ".Create"; + public const string CrossStore = Default + ".CrossStore"; + } + + public static string[] GetAll() + { + return ReflectionHelper.GetPublicConstantsRecursively(typeof(ProductTagPermissions)); + } + } +} \ No newline at end of file diff --git a/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Application.Contracts/ProductTagApplicationContractsModule.cs b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Application.Contracts/ProductTagApplicationContractsModule.cs new file mode 100644 index 00000000..95a8ca02 --- /dev/null +++ b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Application.Contracts/ProductTagApplicationContractsModule.cs @@ -0,0 +1,18 @@ +using EasyAbp.EShop.Stores; +using Volo.Abp.Application; +using Volo.Abp.Modularity; +using Volo.Abp.Authorization; + +namespace EasyAbp.EShop.Plugins.ProductTag +{ + [DependsOn( + typeof(ProductTagDomainSharedModule), + typeof(AbpDddApplicationContractsModule), + typeof(AbpAuthorizationModule), + typeof(EShopStoresDomainSharedModule) + )] + public class ProductTagApplicationContractsModule : AbpModule + { + + } +} diff --git a/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Application.Contracts/ProductTags/Dtos/CreateUpdateProductTagsDto.cs b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Application.Contracts/ProductTags/Dtos/CreateUpdateProductTagsDto.cs new file mode 100644 index 00000000..323f2e33 --- /dev/null +++ b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Application.Contracts/ProductTags/Dtos/CreateUpdateProductTagsDto.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using Volo.Abp.ObjectExtending; + +namespace EasyAbp.EShop.Plugins.ProductTag.ProductTags.Dtos +{ + public class CreateUpdateProductTagsDto : ExtensibleObject + { + public Guid StoreId { get; set; } + + public Guid ProductId { get; set; } + + public List TagIds { get; set; } + } +} diff --git a/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Application.Contracts/ProductTags/Dtos/GetProductTagListDto.cs b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Application.Contracts/ProductTags/Dtos/GetProductTagListDto.cs new file mode 100644 index 00000000..00c63de1 --- /dev/null +++ b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Application.Contracts/ProductTags/Dtos/GetProductTagListDto.cs @@ -0,0 +1,15 @@ +using System; +using EasyAbp.EShop.Stores.Stores; +using Volo.Abp.Application.Dtos; + +namespace EasyAbp.EShop.Plugins.ProductTag.ProductTags.Dtos +{ + public class GetProductTagListDto : PagedAndSortedResultRequestDto, IMultiStore + { + public Guid StoreId { get; set; } + + public Guid? TagId { get; set; } + + public Guid? ProductId { get; set; } + } +} \ No newline at end of file diff --git a/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Application.Contracts/ProductTags/Dtos/ProductTagDto.cs b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Application.Contracts/ProductTags/Dtos/ProductTagDto.cs new file mode 100644 index 00000000..8083a1d2 --- /dev/null +++ b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Application.Contracts/ProductTags/Dtos/ProductTagDto.cs @@ -0,0 +1,14 @@ +using System; +using Volo.Abp.Application.Dtos; + +namespace EasyAbp.EShop.Plugins.ProductTag.ProductTags.Dtos +{ + public class ProductTagDto : ExtensibleAuditedEntityDto + { + public Guid TagId { get; set; } + + public Guid ProductId { get; set; } + + public int DisplayOrder { get; set; } + } +} \ No newline at end of file diff --git a/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Application.Contracts/ProductTags/Dtos/UpdateProductTagDto.cs b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Application.Contracts/ProductTags/Dtos/UpdateProductTagDto.cs new file mode 100644 index 00000000..194760d0 --- /dev/null +++ b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Application.Contracts/ProductTags/Dtos/UpdateProductTagDto.cs @@ -0,0 +1,14 @@ +using System; +using Volo.Abp.Application.Dtos; + +namespace EasyAbp.EShop.Plugins.ProductTag.ProductTags.Dtos +{ + public class UpdateProductTagDto : ExtensibleEntityDto + { + public Guid TagId { get; set; } + + public Guid ProductId { get; set; } + + public int DisplayOrder { get; set; } + } +} \ No newline at end of file diff --git a/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Application.Contracts/ProductTags/IProductTagAppService.cs b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Application.Contracts/ProductTags/IProductTagAppService.cs new file mode 100644 index 00000000..360a5bbc --- /dev/null +++ b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Application.Contracts/ProductTags/IProductTagAppService.cs @@ -0,0 +1,17 @@ +using EasyAbp.EShop.Plugins.ProductTag.ProductTags.Dtos; +using System; +using System.Threading.Tasks; +using Volo.Abp.Application.Services; + +namespace EasyAbp.EShop.Plugins.ProductTag.ProductTags +{ + public interface IProductTagAppService : + IReadOnlyAppService< + ProductTagDto, + Guid, + GetProductTagListDto>, + IUpdateAppService + { + Task UpdateAsync(CreateUpdateProductTagsDto input); + } +} diff --git a/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Application.Contracts/Tags/Dtos/CreateUpdateTagDto.cs b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Application.Contracts/Tags/Dtos/CreateUpdateTagDto.cs new file mode 100644 index 00000000..714a2cad --- /dev/null +++ b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Application.Contracts/Tags/Dtos/CreateUpdateTagDto.cs @@ -0,0 +1,31 @@ +using System; +using System.ComponentModel; +using System.ComponentModel.DataAnnotations; +using EasyAbp.EShop.Stores.Stores; +using Volo.Abp.Application.Dtos; + +namespace EasyAbp.EShop.Plugins.ProductTag.Tags.Dtos +{ + public class UpdateTagDto : ExtensibleEntityDto + { + [DisplayName("TagParentId")] + public Guid? ParentId { get; set; } + + [Required] + [DisplayName("TagDisplayName")] + public string DisplayName { get; set; } + + [DisplayName("TagDescription")] + public string Description { get; set; } + + [DisplayName("TagMediaResources")] + public string MediaResources { get; set; } + } + + public class CreateTagDto : UpdateTagDto, IMultiStore + { + [Required] + [DisplayName("TagStoreId")] + public Guid StoreId { get; set; } + } +} \ No newline at end of file diff --git a/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Application.Contracts/Tags/Dtos/GetTagListDto.cs b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Application.Contracts/Tags/Dtos/GetTagListDto.cs new file mode 100644 index 00000000..6b397a7f --- /dev/null +++ b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Application.Contracts/Tags/Dtos/GetTagListDto.cs @@ -0,0 +1,15 @@ +using System; +using System.ComponentModel.DataAnnotations; +using EasyAbp.EShop.Stores.Stores; +using Volo.Abp.Application.Dtos; + +namespace EasyAbp.EShop.Plugins.ProductTag.Tags.Dtos +{ + public class GetTagListDto : PagedAndSortedResultRequestDto, IMultiStore + { + [Required] + public Guid StoreId { get; set; } + + public bool ShowHidden { get; set; } + } +} \ No newline at end of file diff --git a/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Application.Contracts/Tags/Dtos/TagDto.cs b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Application.Contracts/Tags/Dtos/TagDto.cs new file mode 100644 index 00000000..934179e1 --- /dev/null +++ b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Application.Contracts/Tags/Dtos/TagDto.cs @@ -0,0 +1,26 @@ +using EasyAbp.EShop.Stores.Stores; +using System; +using System.Collections.Generic; +using Volo.Abp.Application.Dtos; + +namespace EasyAbp.EShop.Plugins.ProductTag.Tags.Dtos +{ + public class TagDto : ExtensibleFullAuditedEntityDto, IMultiStore + { + public Guid StoreId { get; set; } + + public Guid? ParentId { get; set; } + + public string Code { get; set; } + + public int Level { get; set; } + + public string DisplayName { get; set; } + + public string Description { get; set; } + + public string MediaResources { get; set; } + + public ICollection Children { get; set; } + } +} \ No newline at end of file diff --git a/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Application.Contracts/Tags/ITagAppService.cs b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Application.Contracts/Tags/ITagAppService.cs new file mode 100644 index 00000000..33cebd33 --- /dev/null +++ b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Application.Contracts/Tags/ITagAppService.cs @@ -0,0 +1,15 @@ +using System; +using EasyAbp.EShop.Plugins.ProductTag.Tags.Dtos; +using Volo.Abp.Application.Services; + +namespace EasyAbp.EShop.Plugins.ProductTag.Tags +{ + public interface ITagAppService : ICrudAppService< + TagDto, + Guid, + GetTagListDto, + CreateTagDto, + UpdateTagDto> + { + } +} diff --git a/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Application/EasyAbp.EShop.Plugins.ProductTag.Application.csproj b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Application/EasyAbp.EShop.Plugins.ProductTag.Application.csproj new file mode 100644 index 00000000..04ad94cd --- /dev/null +++ b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Application/EasyAbp.EShop.Plugins.ProductTag.Application.csproj @@ -0,0 +1,20 @@ + + + + + + netstandard2.0 + EasyAbp.EShop.Plugins.ProductTag + + + + + + + + + + + + + diff --git a/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Application/FodyWeavers.xml b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Application/FodyWeavers.xml new file mode 100644 index 00000000..be0de3a9 --- /dev/null +++ b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Application/FodyWeavers.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Application/FodyWeavers.xsd b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Application/FodyWeavers.xsd new file mode 100644 index 00000000..3f3946e2 --- /dev/null +++ b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Application/FodyWeavers.xsd @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + 'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed. + + + + + A comma-separated list of error codes that can be safely ignored in assembly verification. + + + + + 'false' to turn off automatic generation of the XML Schema file. + + + + + \ No newline at end of file diff --git a/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Application/ProductTagAppService.cs b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Application/ProductTagAppService.cs new file mode 100644 index 00000000..53b30d75 --- /dev/null +++ b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Application/ProductTagAppService.cs @@ -0,0 +1,14 @@ +using EasyAbp.EShop.Plugins.ProductTag.Localization; +using Volo.Abp.Application.Services; + +namespace EasyAbp.EShop.Plugins.ProductTag +{ + public abstract class ProductTagAppService : ApplicationService + { + protected ProductTagAppService() + { + LocalizationResource = typeof(ProductTagResource); + ObjectMapperContext = typeof(ProductTagApplicationModule); + } + } +} diff --git a/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Application/ProductTagApplicationAutoMapperProfile.cs b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Application/ProductTagApplicationAutoMapperProfile.cs new file mode 100644 index 00000000..e13e925e --- /dev/null +++ b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Application/ProductTagApplicationAutoMapperProfile.cs @@ -0,0 +1,25 @@ +using AutoMapper; +using EasyAbp.EShop.Plugins.ProductTag.ProductTags.Dtos; +using EasyAbp.EShop.Plugins.ProductTag.Tags; +using EasyAbp.EShop.Plugins.ProductTag.Tags.Dtos; + +namespace EasyAbp.EShop.Plugins.ProductTag +{ + public class ProductTagApplicationAutoMapperProfile : Profile + { + public ProductTagApplicationAutoMapperProfile() + { + /* You can configure your AutoMapper mapping configuration here. + * Alternatively, you can split your mapping configurations + * into multiple profile classes for a better organization. */ + CreateMap(MemberList.Source); + CreateMap(MemberList.Source); + CreateMap(); + CreateMap(MemberList.Source); + CreateMap(MemberList.Source); + + CreateMap(); + CreateMap(MemberList.Source); + } + } +} \ No newline at end of file diff --git a/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Application/ProductTagApplicationModule.cs b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Application/ProductTagApplicationModule.cs new file mode 100644 index 00000000..be07ebcd --- /dev/null +++ b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Application/ProductTagApplicationModule.cs @@ -0,0 +1,27 @@ +using EasyAbp.EShop.Products; +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.AutoMapper; +using Volo.Abp.Modularity; +using Volo.Abp.Application; + +namespace EasyAbp.EShop.Plugins.ProductTag +{ + [DependsOn( + typeof(ProductTagDomainModule), + typeof(ProductTagApplicationContractsModule), + typeof(AbpDddApplicationModule), + typeof(AbpAutoMapperModule), + typeof(EShopProductsDomainModule) + )] + public class ProductTagApplicationModule : AbpModule + { + public override void ConfigureServices(ServiceConfigurationContext context) + { + context.Services.AddAutoMapperObjectMapper(); + Configure(options => + { + options.AddMaps(validate: true); + }); + } + } +} diff --git a/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Application/ProductTags/ProductTagAppService.cs b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Application/ProductTags/ProductTagAppService.cs new file mode 100644 index 00000000..f279118c --- /dev/null +++ b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Application/ProductTags/ProductTagAppService.cs @@ -0,0 +1,130 @@ +using EasyAbp.EShop.Plugins.ProductTag.ProductTags.Dtos; +using EasyAbp.EShop.Plugins.ProductTag.Tags; +using EasyAbp.EShop.Products.Permissions; +using EasyAbp.EShop.Products.ProductStores; +using EasyAbp.EShop.Stores.Permissions; +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Linq; +using System.Threading.Tasks; +using EasyAbp.EShop.Products.Products; +using Microsoft.AspNetCore.Authorization; +using Volo.Abp; +using Volo.Abp.Application.Dtos; +using Volo.Abp.Application.Services; +using Volo.Abp.Domain.Repositories; + +namespace EasyAbp.EShop.Plugins.ProductTag.ProductTags +{ + public class ProductTagAppService : ReadOnlyAppService, + IProductTagAppService + { + private readonly IProductTagRepository _repository; + private readonly ITagRepository _tagRepository; + private readonly IProductStoreRepository _productStoreRepository; + + public ProductTagAppService(IProductTagRepository repository, + ITagRepository tagRepository, + IProductStoreRepository productStoreRepository) : base(repository) + { + _repository = repository; + _tagRepository = tagRepository; + _productStoreRepository = productStoreRepository; + } + + protected override string GetListPolicyName { get; set; } = ProductsPermissions.Products.Default; + protected string UpdatePolicyName { get; set; } = ProductsPermissions.Products.Update; + + [RemoteService(false)] + public override Task GetAsync(Guid id) + { + throw new NotSupportedException(); + } + + public override async Task> GetListAsync(GetProductTagListDto input) + { + await CheckGetListPolicyAsync(); + + await AuthorizationService.CheckStoreOwnerAsync(input.StoreId, GetListPolicyName); + + var query = CreateFilteredQuery(input); + + var totalCount = await AsyncExecuter.CountAsync(query); + + query = ApplySorting(query, input); + query = ApplyPaging(query, input); + + var entities = await AsyncExecuter.ToListAsync(query); + + return new PagedResultDto( + totalCount, + entities.Select(MapToGetListOutputDto).ToList()); + } + + protected override IQueryable CreateFilteredQuery(GetProductTagListDto input) + { + var queryable = Repository.AsQueryable(); + + queryable = queryable.Where(x => x.StoreId == input.StoreId); + + if (input.TagId.HasValue) + { + queryable = queryable.Where(x => x.TagId == input.TagId); + } + + if (input.ProductId.HasValue) + { + queryable = queryable.Where(x => x.ProductId == input.ProductId); + } + + return queryable; + } + + public async Task UpdateAsync(Guid id, UpdateProductTagDto input) + { + var entity = await GetEntityByIdAsync(id); + + await AuthorizationService.CheckStoreOwnerAsync(entity.StoreId, UpdatePolicyName); + + MapToEntity(input, entity); + await _repository.UpdateAsync(entity, autoSave: true); + + return MapToGetOutputDto(entity); + } + + public async Task UpdateAsync(CreateUpdateProductTagsDto input) + { + await AuthorizationService.CheckStoreOwnerAsync(input.StoreId, UpdatePolicyName); + + var productStore = await _productStoreRepository.GetAsync(input.ProductId, input.StoreId, false); + + if (!productStore.IsOwner) + { + throw new StoreIsNotProductOwnerException(input.ProductId, input.StoreId); + } + + input.TagIds ??= new List(); + + var storeTags = (await _tagRepository.GetListByAsync(input.StoreId)).Select(x => x.Id); + + var productTags = await _repository.GetListByProductIdAsync(input.ProductId, input.StoreId); + + foreach (var productTag in productTags.Where(x => !input.TagIds.Contains(x.TagId))) + { + await _repository.DeleteAsync(productTag, true); + } + + foreach (var tagId in input.TagIds.Except(productTags.Select(x => x.TagId).Concat(storeTags))) + { + await _repository.InsertAsync( + new ProductTag(GuidGenerator.Create(), CurrentTenant.Id, tagId, input.ProductId), true); + } + } + + protected virtual ProductTag MapToEntity(UpdateProductTagDto input, ProductTag entity) + { + return ObjectMapper.Map(input, entity); + } + } +} diff --git a/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Application/Tags/TagAppService.cs b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Application/Tags/TagAppService.cs new file mode 100644 index 00000000..c819b4ef --- /dev/null +++ b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Application/Tags/TagAppService.cs @@ -0,0 +1,40 @@ +using System; +using System.Linq; +using System.Threading.Tasks; +using EasyAbp.EShop.Plugins.ProductTag.Permissions; +using EasyAbp.EShop.Plugins.ProductTag.Tags.Dtos; +using EasyAbp.EShop.Stores.Stores; +using JetBrains.Annotations; +using Volo.Abp.Application.Dtos; +using Volo.Abp.Linq; + +namespace EasyAbp.EShop.Plugins.ProductTag.Tags +{ + public class TagAppService : MultiStoreCrudAppService, + ITagAppService + { + private readonly IAsyncQueryableExecuter _asyncQueryableExecuter; + protected override string CreatePolicyName { get; set; } = ProductTagPermissions.Tags.Create; + protected override string DeletePolicyName { get; set; } = ProductTagPermissions.Tags.Delete; + protected override string UpdatePolicyName { get; set; } = ProductTagPermissions.Tags.Update; + protected override string GetPolicyName { get; set; } = ProductTagPermissions.Tags.Default; + protected override string GetListPolicyName { get; set; } = ProductTagPermissions.Tags.Default; + + protected override string CrossStorePolicyName { get; set; } = ProductTagPermissions.Tags.CrossStore; + + public TagAppService(ITagRepository repository, + [NotNull] IAsyncQueryableExecuter asyncQueryableExecuter) : base(repository) + { + _asyncQueryableExecuter = asyncQueryableExecuter ?? throw new ArgumentNullException(nameof(asyncQueryableExecuter)); + } + + protected override IQueryable CreateFilteredQuery(GetTagListDto input) + { + var query = base.CreateFilteredQuery(input); + + query = query.Where(x => x.StoreId == input.StoreId); + + return input.ShowHidden ? query : query.Where(x => !x.IsHidden); + } + } +} diff --git a/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Domain.Shared/EasyAbp.EShop.Plugins.ProductTag.Domain.Shared.csproj b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Domain.Shared/EasyAbp.EShop.Plugins.ProductTag.Domain.Shared.csproj new file mode 100644 index 00000000..8e9296cb --- /dev/null +++ b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Domain.Shared/EasyAbp.EShop.Plugins.ProductTag.Domain.Shared.csproj @@ -0,0 +1,24 @@ + + + + + + netstandard2.0 + EasyAbp.EShop.Plugins.ProductTag + true + + + + + + + + + + + + + + + + diff --git a/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Domain.Shared/FodyWeavers.xml b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Domain.Shared/FodyWeavers.xml new file mode 100644 index 00000000..be0de3a9 --- /dev/null +++ b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Domain.Shared/FodyWeavers.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Domain.Shared/FodyWeavers.xsd b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Domain.Shared/FodyWeavers.xsd new file mode 100644 index 00000000..3f3946e2 --- /dev/null +++ b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Domain.Shared/FodyWeavers.xsd @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + 'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed. + + + + + A comma-separated list of error codes that can be safely ignored in assembly verification. + + + + + 'false' to turn off automatic generation of the XML Schema file. + + + + + \ No newline at end of file diff --git a/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Domain.Shared/Localization/ProductTag/cs.json b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Domain.Shared/Localization/ProductTag/cs.json new file mode 100644 index 00000000..5468561d --- /dev/null +++ b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Domain.Shared/Localization/ProductTag/cs.json @@ -0,0 +1,22 @@ +{ + "culture": "cs", + "texts": { + "ManageYourProfile": "Spravovat profil", + "Menu:Tag": "MenuTag", + "Tag": "Tag", + "TagTenantId": "TagTenantId", + "TagStoreId": "TagStoreId", + "TagDisplayName": "TagDisplayName", + "TagDescription": "TagDescription", + "TagMediaResources": "TagMediaResources", + "CreateTag": "CreateTag", + "EditTag": "EditTag", + "TagDeletionConfirmationMessage": "Are you sure to delete the tag {0}?", + "Permission:ProductTag": "ProductTag", + "Permission:Tag": "Tag", + "Permission:Create": "Create", + "Permission:Update": "Update", + "Permission:Delete": "Delete", + "Permission:CrossStore": "CrossStore" + } +} diff --git a/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Domain.Shared/Localization/ProductTag/en.json b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Domain.Shared/Localization/ProductTag/en.json new file mode 100644 index 00000000..88126067 --- /dev/null +++ b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Domain.Shared/Localization/ProductTag/en.json @@ -0,0 +1,23 @@ +{ + "culture": "en", + "texts": { + "ManageYourProfile": "Manage your profile", + "SamplePageMessage": "A sample page for the ProductTag module", + "Menu:Tag": "MenuTag", + "Tag": "Tag", + "TagTenantId": "TagTenantId", + "TagStoreId": "TagStoreId", + "TagDisplayName": "TagDisplayName", + "TagDescription": "TagDescription", + "TagMediaResources": "TagMediaResources", + "CreateTag": "CreateTag", + "EditTag": "EditTag", + "TagDeletionConfirmationMessage": "Are you sure to delete the tag {0}?", + "Permission:ProductTag": "ProductTag", + "Permission:Tag": "Tag", + "Permission:Create": "Create", + "Permission:Update": "Update", + "Permission:Delete": "Delete", + "Permission:CrossStore": "CrossStore" + } +} \ No newline at end of file diff --git a/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Domain.Shared/Localization/ProductTag/pl-PL.json b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Domain.Shared/Localization/ProductTag/pl-PL.json new file mode 100644 index 00000000..2598715f --- /dev/null +++ b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Domain.Shared/Localization/ProductTag/pl-PL.json @@ -0,0 +1,21 @@ +{ + "culture": "pl-PL", + "texts": { + "Menu:Tag": "MenuTag", + "Tag": "Tag", + "TagTenantId": "TagTenantId", + "TagStoreId": "TagStoreId", + "TagDisplayName": "TagDisplayName", + "TagDescription": "TagDescription", + "TagMediaResources": "TagMediaResources", + "CreateTag": "CreateTag", + "EditTag": "EditTag", + "TagDeletionConfirmationMessage": "Are you sure to delete the tag {0}?", + "Permission:ProductTag": "ProductTag", + "Permission:Tag": "Tag", + "Permission:Create": "Create", + "Permission:Update": "Update", + "Permission:Delete": "Delete", + "Permission:CrossStore": "CrossStore" + } +} \ No newline at end of file diff --git a/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Domain.Shared/Localization/ProductTag/pt-BR.json b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Domain.Shared/Localization/ProductTag/pt-BR.json new file mode 100644 index 00000000..95c7cef0 --- /dev/null +++ b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Domain.Shared/Localization/ProductTag/pt-BR.json @@ -0,0 +1,21 @@ +{ + "culture": "pt-BR", + "texts": { + "Menu:Tag": "MenuTag", + "Tag": "Tag", + "TagTenantId": "TagTenantId", + "TagStoreId": "TagStoreId", + "TagDisplayName": "TagDisplayName", + "TagDescription": "TagDescription", + "TagMediaResources": "TagMediaResources", + "CreateTag": "CreateTag", + "EditTag": "EditTag", + "TagDeletionConfirmationMessage": "Are you sure to delete the tag {0}?", + "Permission:ProductTag": "ProductTag", + "Permission:Tag": "Tag", + "Permission:Create": "Create", + "Permission:Update": "Update", + "Permission:Delete": "Delete", + "Permission:CrossStore": "CrossStore" + } +} \ No newline at end of file diff --git a/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Domain.Shared/Localization/ProductTag/sl.json b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Domain.Shared/Localization/ProductTag/sl.json new file mode 100644 index 00000000..51704a4d --- /dev/null +++ b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Domain.Shared/Localization/ProductTag/sl.json @@ -0,0 +1,22 @@ +{ + "culture": "sl", + "texts": { + "ManageYourProfile": "Upravljajte svojim profilom", + "Menu:Tag": "MenuTag", + "Tag": "Tag", + "TagTenantId": "TagTenantId", + "TagStoreId": "TagStoreId", + "TagDisplayName": "TagDisplayName", + "TagDescription": "TagDescription", + "TagMediaResources": "TagMediaResources", + "CreateTag": "CreateTag", + "EditTag": "EditTag", + "TagDeletionConfirmationMessage": "Are you sure to delete the tag {0}?", + "Permission:ProductTag": "ProductTag", + "Permission:Tag": "Tag", + "Permission:Create": "Create", + "Permission:Update": "Update", + "Permission:Delete": "Delete", + "Permission:CrossStore": "CrossStore" + } +} \ No newline at end of file diff --git a/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Domain.Shared/Localization/ProductTag/tr.json b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Domain.Shared/Localization/ProductTag/tr.json new file mode 100644 index 00000000..090722e1 --- /dev/null +++ b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Domain.Shared/Localization/ProductTag/tr.json @@ -0,0 +1,23 @@ +{ + "culture": "tr", + "texts": { + "ManageYourProfile": "Profil yönetimi", + "SamplePageMessage": "ProductTag modulünden örnek bir sayfa", + "Menu:Tag": "MenuTag", + "Tag": "Tag", + "TagTenantId": "TagTenantId", + "TagStoreId": "TagStoreId", + "TagDisplayName": "TagDisplayName", + "TagDescription": "TagDescription", + "TagMediaResources": "TagMediaResources", + "CreateTag": "CreateTag", + "EditTag": "EditTag", + "TagDeletionConfirmationMessage": "Are you sure to delete the tag {0}?", + "Permission:ProductTag": "ProductTag", + "Permission:Tag": "Tag", + "Permission:Create": "Create", + "Permission:Update": "Update", + "Permission:Delete": "Delete", + "Permission:CrossStore": "CrossStore" + } +} \ No newline at end of file diff --git a/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Domain.Shared/Localization/ProductTag/vi.json b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Domain.Shared/Localization/ProductTag/vi.json new file mode 100644 index 00000000..35201fbd --- /dev/null +++ b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Domain.Shared/Localization/ProductTag/vi.json @@ -0,0 +1,21 @@ +{ + "culture": "vi", + "texts": { + "Menu:Tag": "MenuTag", + "Tag": "Tag", + "TagTenantId": "TagTenantId", + "TagStoreId": "TagStoreId", + "TagDisplayName": "TagDisplayName", + "TagDescription": "TagDescription", + "TagMediaResources": "TagMediaResources", + "CreateTag": "CreateTag", + "EditTag": "EditTag", + "TagDeletionConfirmationMessage": "Are you sure to delete the tag {0}?", + "Permission:ProductTag": "ProductTag", + "Permission:Tag": "Tag", + "Permission:Create": "Create", + "Permission:Update": "Update", + "Permission:Delete": "Delete", + "Permission:CrossStore": "CrossStore" + } +} diff --git a/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Domain.Shared/Localization/ProductTag/zh-Hans.json b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Domain.Shared/Localization/ProductTag/zh-Hans.json new file mode 100644 index 00000000..b252ab76 --- /dev/null +++ b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Domain.Shared/Localization/ProductTag/zh-Hans.json @@ -0,0 +1,22 @@ +{ + "culture": "zh-Hans", + "texts": { + "ManageYourProfile": "管理个人资料", + "Menu:Tag": "MenuTag", + "Tag": "Tag", + "TagTenantId": "TagTenantId", + "TagStoreId": "TagStoreId", + "TagDisplayName": "TagDisplayName", + "TagDescription": "TagDescription", + "TagMediaResources": "TagMediaResources", + "CreateTag": "CreateTag", + "EditTag": "EditTag", + "TagDeletionConfirmationMessage": "Are you sure to delete the tag {0}?", + "Permission:ProductTag": "ProductTag", + "Permission:Tag": "Tag", + "Permission:Create": "Create", + "Permission:Update": "Update", + "Permission:Delete": "Delete", + "Permission:CrossStore": "CrossStore" + } +} \ No newline at end of file diff --git a/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Domain.Shared/Localization/ProductTag/zh-Hant.json b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Domain.Shared/Localization/ProductTag/zh-Hant.json new file mode 100644 index 00000000..f5cab7d9 --- /dev/null +++ b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Domain.Shared/Localization/ProductTag/zh-Hant.json @@ -0,0 +1,22 @@ +{ + "culture": "zh-Hant", + "texts": { + "ManageYourProfile": "管理個人資料", + "Menu:Tag": "MenuTag", + "Tag": "Tag", + "TagTenantId": "TagTenantId", + "TagStoreId": "TagStoreId", + "TagDisplayName": "TagDisplayName", + "TagDescription": "TagDescription", + "TagMediaResources": "TagMediaResources", + "CreateTag": "CreateTag", + "EditTag": "EditTag", + "TagDeletionConfirmationMessage": "Are you sure to delete the tag {0}?", + "Permission:ProductTag": "ProductTag", + "Permission:Tag": "Tag", + "Permission:Create": "Create", + "Permission:Update": "Update", + "Permission:Delete": "Delete", + "Permission:CrossStore": "CrossStore" + } +} \ No newline at end of file diff --git a/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Domain.Shared/Localization/ProductTagResource.cs b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Domain.Shared/Localization/ProductTagResource.cs new file mode 100644 index 00000000..8024441c --- /dev/null +++ b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Domain.Shared/Localization/ProductTagResource.cs @@ -0,0 +1,10 @@ +using Volo.Abp.Localization; + +namespace EasyAbp.EShop.Plugins.ProductTag.Localization +{ + [LocalizationResourceName("ProductTag")] + public class ProductTagResource + { + + } +} diff --git a/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Domain.Shared/ProductTagDomainSharedModule.cs b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Domain.Shared/ProductTagDomainSharedModule.cs new file mode 100644 index 00000000..d4b2ba4d --- /dev/null +++ b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Domain.Shared/ProductTagDomainSharedModule.cs @@ -0,0 +1,37 @@ +using Volo.Abp.Modularity; +using Volo.Abp.Localization; +using EasyAbp.EShop.Plugins.ProductTag.Localization; +using Volo.Abp.Localization.ExceptionHandling; +using Volo.Abp.Validation; +using Volo.Abp.Validation.Localization; +using Volo.Abp.VirtualFileSystem; + +namespace EasyAbp.EShop.Plugins.ProductTag +{ + [DependsOn( + typeof(AbpValidationModule) + )] + public class ProductTagDomainSharedModule : AbpModule + { + public override void ConfigureServices(ServiceConfigurationContext context) + { + Configure(options => + { + options.FileSets.AddEmbedded(); + }); + + Configure(options => + { + options.Resources + .Add("en") + .AddBaseTypes(typeof(AbpValidationResource)) + .AddVirtualJson("/Localization/ProductTag"); + }); + + Configure(options => + { + options.MapCodeNamespace("ProductTag", typeof(ProductTagResource)); + }); + } + } +} diff --git a/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Domain.Shared/ProductTagErrorCodes.cs b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Domain.Shared/ProductTagErrorCodes.cs new file mode 100644 index 00000000..ff528d99 --- /dev/null +++ b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Domain.Shared/ProductTagErrorCodes.cs @@ -0,0 +1,7 @@ +namespace EasyAbp.EShop.Plugins.ProductTag +{ + public static class ProductTagErrorCodes + { + //Add your business exception error codes here... + } +} diff --git a/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Domain/EasyAbp.EShop.Plugins.ProductTag.Domain.csproj b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Domain/EasyAbp.EShop.Plugins.ProductTag.Domain.csproj new file mode 100644 index 00000000..c3a84dc7 --- /dev/null +++ b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Domain/EasyAbp.EShop.Plugins.ProductTag.Domain.csproj @@ -0,0 +1,17 @@ + + + + + + netstandard2.0 + EasyAbp.EShop.Plugins.ProductTag + + + + + + + + + + diff --git a/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Domain/FodyWeavers.xml b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Domain/FodyWeavers.xml new file mode 100644 index 00000000..be0de3a9 --- /dev/null +++ b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Domain/FodyWeavers.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Domain/FodyWeavers.xsd b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Domain/FodyWeavers.xsd new file mode 100644 index 00000000..3f3946e2 --- /dev/null +++ b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Domain/FodyWeavers.xsd @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + 'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed. + + + + + A comma-separated list of error codes that can be safely ignored in assembly verification. + + + + + 'false' to turn off automatic generation of the XML Schema file. + + + + + \ No newline at end of file diff --git a/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Domain/ProductTagDbProperties.cs b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Domain/ProductTagDbProperties.cs new file mode 100644 index 00000000..70233f15 --- /dev/null +++ b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Domain/ProductTagDbProperties.cs @@ -0,0 +1,11 @@ +namespace EasyAbp.EShop.Plugins.ProductTag +{ + public static class ProductTagDbProperties + { + public static string DbTablePrefix { get; set; } = "ProductTag"; + + public static string DbSchema { get; set; } = null; + + public const string ConnectionStringName = "ProductTag"; + } +} diff --git a/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Domain/ProductTagDomainModule.cs b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Domain/ProductTagDomainModule.cs new file mode 100644 index 00000000..ad1a21de --- /dev/null +++ b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Domain/ProductTagDomainModule.cs @@ -0,0 +1,16 @@ +using EasyAbp.Abp.Trees; +using EasyAbp.EShop.Stores; +using Volo.Abp.Modularity; + +namespace EasyAbp.EShop.Plugins.ProductTag +{ + [DependsOn( + typeof(ProductTagDomainSharedModule), + typeof(AbpTreesDomainModule), + typeof(EShopStoresDomainSharedModule) + )] + public class ProductTagDomainModule : AbpModule + { + + } +} diff --git a/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Domain/ProductTags/IProductTagRepository.cs b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Domain/ProductTags/IProductTagRepository.cs new file mode 100644 index 00000000..e6d0168c --- /dev/null +++ b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Domain/ProductTags/IProductTagRepository.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using Volo.Abp.Domain.Repositories; + +namespace EasyAbp.EShop.Plugins.ProductTag.ProductTags +{ + public interface IProductTagRepository : IRepository + { + Task> GetListByTagIdAsync(Guid tagId, Guid? storeId = null, CancellationToken cancellationToken = default); + + Task> GetListByProductIdAsync(Guid productId, Guid? storeId = null, CancellationToken cancellationToken = default); + } +} diff --git a/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Domain/ProductTags/ProductTags.cs b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Domain/ProductTags/ProductTags.cs new file mode 100644 index 00000000..570d3449 --- /dev/null +++ b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Domain/ProductTags/ProductTags.cs @@ -0,0 +1,37 @@ +using System; +using Volo.Abp.Domain.Entities.Auditing; +using Volo.Abp.MultiTenancy; + +namespace EasyAbp.EShop.Plugins.ProductTag.ProductTags +{ + public class ProductTag : AuditedAggregateRoot, IMultiTenant + { + public virtual Guid? TenantId { get; protected set; } + + public virtual Guid StoreId { get; set; } + + public virtual Guid TagId { get; protected set; } + + public virtual Guid ProductId { get; protected set; } + + public virtual int DisplayOrder { get; protected set; } + + protected ProductTag() + { + } + + public ProductTag( + Guid id, + Guid? tenantId, + Guid tagId, + Guid productId, + int displayOrder = 0 + ) : base(id) + { + TenantId = tenantId; + TagId = tagId; + ProductId = productId; + DisplayOrder = displayOrder; + } + } +} diff --git a/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Domain/Settings/ProductTagSettingDefinitionProvider.cs b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Domain/Settings/ProductTagSettingDefinitionProvider.cs new file mode 100644 index 00000000..919c64ea --- /dev/null +++ b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Domain/Settings/ProductTagSettingDefinitionProvider.cs @@ -0,0 +1,14 @@ +using Volo.Abp.Settings; + +namespace EasyAbp.EShop.Plugins.ProductTag.Settings +{ + public class ProductTagSettingDefinitionProvider : SettingDefinitionProvider + { + public override void Define(ISettingDefinitionContext context) + { + /* Define module settings here. + * Use names from ProductTagSettings class. + */ + } + } +} \ No newline at end of file diff --git a/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Domain/Settings/ProductTagSettings.cs b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Domain/Settings/ProductTagSettings.cs new file mode 100644 index 00000000..40555821 --- /dev/null +++ b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Domain/Settings/ProductTagSettings.cs @@ -0,0 +1,11 @@ +namespace EasyAbp.EShop.Plugins.ProductTag.Settings +{ + public static class ProductTagSettings + { + public const string GroupName = "ProductTag"; + + /* Add constants for setting names. Example: + * public const string MySettingName = GroupName + ".MySettingName"; + */ + } +} \ No newline at end of file diff --git a/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Domain/Tags/ITagRepository.cs b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Domain/Tags/ITagRepository.cs new file mode 100644 index 00000000..dfb32dfe --- /dev/null +++ b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Domain/Tags/ITagRepository.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using Volo.Abp.Domain.Repositories; + +namespace EasyAbp.EShop.Plugins.ProductTag.Tags +{ + public interface ITagRepository : IRepository + { + Task> GetListByAsync(Guid storeId, bool includeDetails = false, CancellationToken cancellationToken = default); + } +} diff --git a/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Domain/Tags/Tag.cs b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Domain/Tags/Tag.cs new file mode 100644 index 00000000..91ac332b --- /dev/null +++ b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Domain/Tags/Tag.cs @@ -0,0 +1,67 @@ +using System; +using System.Collections.Generic; +using EasyAbp.Abp.Trees; +using EasyAbp.EShop.Stores.Stores; +using JetBrains.Annotations; +using Volo.Abp.Domain.Entities.Auditing; +using Volo.Abp.MultiTenancy; + +namespace EasyAbp.EShop.Plugins.ProductTag.Tags +{ + public class Tag : FullAuditedAggregateRoot, ITree, IMultiTenant, IMultiStore + { + public virtual Guid? TenantId { get; protected set; } + + public virtual Guid StoreId { get; protected set; } + + [CanBeNull] + public virtual string Description { get; protected set; } + + [CanBeNull] + public virtual string MediaResources { get; protected set; } + + public virtual bool IsHidden { get; protected set; } + + #region Properties of ITree + + [NotNull] + public virtual string DisplayName { get; set; } + + [NotNull] + public virtual string Code { get; set; } + + public virtual int Level { get; set; } + + public virtual Guid? ParentId { get; set; } + + public virtual Tag Parent { get; set; } + + public virtual ICollection Children { get; set; } + + #endregion + + protected Tag() + { + } + + public Tag( + Guid id, + Guid? tenantId, + Guid storeId, + Guid? parentId, + string displayName, + string description, + string mediaResources, + bool isHidden + ) : base(id) + { + TenantId = tenantId; + StoreId = storeId; + ParentId = parentId; + DisplayName = displayName; + Description = description; + MediaResources = mediaResources; + IsHidden = isHidden; + } + } +} diff --git a/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.EntityFrameworkCore/EasyAbp.EShop.Plugins.ProductTag.EntityFrameworkCore.csproj b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.EntityFrameworkCore/EasyAbp.EShop.Plugins.ProductTag.EntityFrameworkCore.csproj new file mode 100644 index 00000000..db7d2960 --- /dev/null +++ b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.EntityFrameworkCore/EasyAbp.EShop.Plugins.ProductTag.EntityFrameworkCore.csproj @@ -0,0 +1,16 @@ + + + + + + netstandard2.0 + EasyAbp.EShop.Plugins.ProductTag + + + + + + + + + diff --git a/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.EntityFrameworkCore/EntityFrameworkCore/IProductTagDbContext.cs b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.EntityFrameworkCore/EntityFrameworkCore/IProductTagDbContext.cs new file mode 100644 index 00000000..8d481613 --- /dev/null +++ b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.EntityFrameworkCore/EntityFrameworkCore/IProductTagDbContext.cs @@ -0,0 +1,17 @@ +using EasyAbp.EShop.Plugins.ProductTag.Tags; +using Microsoft.EntityFrameworkCore; +using Volo.Abp.Data; +using Volo.Abp.EntityFrameworkCore; + +namespace EasyAbp.EShop.Plugins.ProductTag.EntityFrameworkCore +{ + [ConnectionStringName(ProductTagDbProperties.ConnectionStringName)] + public interface IProductTagDbContext : IEfCoreDbContext + { + /* Add DbSet for each Aggregate Root here. Example: + * DbSet Questions { get; } + */ + DbSet Tags { get; set; } + DbSet ProductTags { get; set; } + } +} \ No newline at end of file diff --git a/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.EntityFrameworkCore/EntityFrameworkCore/ProductTagDbContext.cs b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.EntityFrameworkCore/EntityFrameworkCore/ProductTagDbContext.cs new file mode 100644 index 00000000..19d93b2f --- /dev/null +++ b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.EntityFrameworkCore/EntityFrameworkCore/ProductTagDbContext.cs @@ -0,0 +1,31 @@ +using EasyAbp.EShop.Plugins.ProductTag.Tags; +using Microsoft.EntityFrameworkCore; +using Volo.Abp.Data; +using Volo.Abp.EntityFrameworkCore; + +namespace EasyAbp.EShop.Plugins.ProductTag.EntityFrameworkCore +{ + [ConnectionStringName(ProductTagDbProperties.ConnectionStringName)] + public class ProductTagDbContext : AbpDbContext, IProductTagDbContext + { + /* Add DbSet for each Aggregate Root here. Example: + * public DbSet Questions { get; set; } + */ + + public DbSet Tags { get; set; } + public DbSet ProductTags { get; set; } + + public ProductTagDbContext(DbContextOptions options) + : base(options) + { + + } + + protected override void OnModelCreating(ModelBuilder builder) + { + base.OnModelCreating(builder); + + builder.ConfigureProductTag(); + } + } +} \ No newline at end of file diff --git a/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.EntityFrameworkCore/EntityFrameworkCore/ProductTagDbContextModelCreatingExtensions.cs b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.EntityFrameworkCore/EntityFrameworkCore/ProductTagDbContextModelCreatingExtensions.cs new file mode 100644 index 00000000..01a377d1 --- /dev/null +++ b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.EntityFrameworkCore/EntityFrameworkCore/ProductTagDbContextModelCreatingExtensions.cs @@ -0,0 +1,66 @@ +using System; +using EasyAbp.EShop.Plugins.ProductTag.Tags; +using Microsoft.EntityFrameworkCore; +using Volo.Abp; +using Volo.Abp.EntityFrameworkCore.Modeling; + +namespace EasyAbp.EShop.Plugins.ProductTag.EntityFrameworkCore +{ + public static class ProductTagDbContextModelCreatingExtensions + { + public static void ConfigureProductTag( + this ModelBuilder builder, + Action optionsAction = null) + { + Check.NotNull(builder, nameof(builder)); + + var options = new ProductTagModelBuilderConfigurationOptions( + ProductTagDbProperties.DbTablePrefix, + ProductTagDbProperties.DbSchema + ); + + optionsAction?.Invoke(options); + + /* Configure all entities here. Example: + + builder.Entity(b => + { + //Configure table & schema name + b.ToTable(options.TablePrefix + "Questions", options.Schema); + + b.ConfigureByConvention(); + + //Properties + b.Property(q => q.Title).IsRequired().HasMaxLength(QuestionConsts.MaxTitleLength); + + //Relations + b.HasMany(question => question.Tags).WithOne().HasForeignKey(qt => qt.QuestionId); + + //Indexes + b.HasIndex(q => q.CreationTime); + }); + */ + + + + builder.Entity(b => + { + b.ToTable(options.TablePrefix + "Tags", options.Schema); + b.ConfigureByConvention(); + /* Configure more properties here */ + + b.HasIndex(x => x.StoreId); + }); + + builder.Entity(b => + { + b.ToTable(options.TablePrefix + "ProductTags", options.Schema); + b.ConfigureByConvention(); + /* Configure more properties here */ + + b.HasIndex(x => x.TagId); + b.HasIndex(x => x.ProductId); + }); + } + } +} \ No newline at end of file diff --git a/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.EntityFrameworkCore/EntityFrameworkCore/ProductTagEntityFrameworkCoreModule.cs b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.EntityFrameworkCore/EntityFrameworkCore/ProductTagEntityFrameworkCoreModule.cs new file mode 100644 index 00000000..6022e551 --- /dev/null +++ b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.EntityFrameworkCore/EntityFrameworkCore/ProductTagEntityFrameworkCoreModule.cs @@ -0,0 +1,29 @@ +using EasyAbp.Abp.Trees.EntityFrameworkCore; +using EasyAbp.EShop.Plugins.ProductTag.ProductTags; +using EasyAbp.EShop.Plugins.ProductTag.Tags; +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.EntityFrameworkCore; +using Volo.Abp.Modularity; + +namespace EasyAbp.EShop.Plugins.ProductTag.EntityFrameworkCore +{ + [DependsOn( + typeof(ProductTagDomainModule), + typeof(AbpEntityFrameworkCoreModule), + typeof(AbpTreesEntityFrameworkCoreModule) + )] + public class ProductTagEntityFrameworkCoreModule : AbpModule + { + public override void ConfigureServices(ServiceConfigurationContext context) + { + context.Services.AddAbpDbContext(options => + { + /* Add custom repositories here. Example: + * options.AddRepository(); + */ + options.AddRepository(); + options.AddRepository(); + }); + } + } +} \ No newline at end of file diff --git a/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.EntityFrameworkCore/EntityFrameworkCore/ProductTagModelBuilderConfigurationOptions.cs b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.EntityFrameworkCore/EntityFrameworkCore/ProductTagModelBuilderConfigurationOptions.cs new file mode 100644 index 00000000..f234aee5 --- /dev/null +++ b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.EntityFrameworkCore/EntityFrameworkCore/ProductTagModelBuilderConfigurationOptions.cs @@ -0,0 +1,18 @@ +using JetBrains.Annotations; +using Volo.Abp.EntityFrameworkCore.Modeling; + +namespace EasyAbp.EShop.Plugins.ProductTag.EntityFrameworkCore +{ + public class ProductTagModelBuilderConfigurationOptions : AbpModelBuilderConfigurationOptions + { + public ProductTagModelBuilderConfigurationOptions( + [NotNull] string tablePrefix = "", + [CanBeNull] string schema = null) + : base( + tablePrefix, + schema) + { + + } + } +} \ No newline at end of file diff --git a/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.EntityFrameworkCore/FodyWeavers.xml b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.EntityFrameworkCore/FodyWeavers.xml new file mode 100644 index 00000000..be0de3a9 --- /dev/null +++ b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.EntityFrameworkCore/FodyWeavers.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.EntityFrameworkCore/FodyWeavers.xsd b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.EntityFrameworkCore/FodyWeavers.xsd new file mode 100644 index 00000000..3f3946e2 --- /dev/null +++ b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.EntityFrameworkCore/FodyWeavers.xsd @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + 'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed. + + + + + A comma-separated list of error codes that can be safely ignored in assembly verification. + + + + + 'false' to turn off automatic generation of the XML Schema file. + + + + + \ No newline at end of file diff --git a/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.EntityFrameworkCore/ProductTags/ProductTagRepository.cs b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.EntityFrameworkCore/ProductTags/ProductTagRepository.cs new file mode 100644 index 00000000..052993ec --- /dev/null +++ b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.EntityFrameworkCore/ProductTags/ProductTagRepository.cs @@ -0,0 +1,43 @@ +using EasyAbp.EShop.Plugins.ProductTag.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Volo.Abp.Domain.Repositories.EntityFrameworkCore; +using Volo.Abp.EntityFrameworkCore; + +namespace EasyAbp.EShop.Plugins.ProductTag.ProductTags +{ + public class ProductTagRepository : EfCoreRepository, IProductTagRepository + { + public ProductTagRepository(IDbContextProvider dbContextProvider) : base(dbContextProvider) + { + } + + public virtual async Task> GetListByTagIdAsync(Guid categoryId, Guid? storeId = null, + CancellationToken cancellationToken = default) + { + var queryable = GetQueryable(); + if (storeId.HasValue) + { + queryable = queryable.Where(x => x.StoreId == storeId.Value); + } + + return await queryable.Where(pc => pc.TagId == categoryId).ToListAsync(cancellationToken); + } + + public virtual async Task> GetListByProductIdAsync(Guid productId, Guid? storeId = null, + CancellationToken cancellationToken = default) + { + var queryable = GetQueryable(); + if (storeId.HasValue) + { + queryable = queryable.Where(x => x.StoreId == storeId.Value); + } + + return await queryable.Where(pc => pc.ProductId == productId).ToListAsync(cancellationToken); + } + } +} diff --git a/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.EntityFrameworkCore/Tags/TagRepository.cs b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.EntityFrameworkCore/Tags/TagRepository.cs new file mode 100644 index 00000000..2e528cab --- /dev/null +++ b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.EntityFrameworkCore/Tags/TagRepository.cs @@ -0,0 +1,32 @@ +using EasyAbp.Abp.Trees; +using EasyAbp.EShop.Plugins.ProductTag.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Volo.Abp.EntityFrameworkCore; + +namespace EasyAbp.EShop.Plugins.ProductTag.Tags +{ + public class TagRepository : EfCoreTreeRepository, ITagRepository + { + public TagRepository(IDbContextProvider dbContextProvider) : base(dbContextProvider) + { + } + + public async Task> GetListByAsync(Guid storeId, bool includeDetails = false, CancellationToken cancellationToken = default) + { + return includeDetails + ? await WithDetails().Where(x => x.StoreId == storeId).ToListAsync(GetCancellationToken(cancellationToken)) + : await GetQueryable().Where(x => x.StoreId == storeId).ToListAsync(GetCancellationToken(cancellationToken)); + } + + [Obsolete("Should use GetListByAsync(Guid storeId, bool includeDetails, CancellationToken cancellationToken)")] + public override Task> GetListAsync(bool includeDetails = false, CancellationToken cancellationToken = new CancellationToken()) + { + return base.GetListAsync(includeDetails, cancellationToken); + } + } +} diff --git a/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.HttpApi.Client/EasyAbp.EShop.Plugins.ProductTag.HttpApi.Client.csproj b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.HttpApi.Client/EasyAbp.EShop.Plugins.ProductTag.HttpApi.Client.csproj new file mode 100644 index 00000000..6d083269 --- /dev/null +++ b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.HttpApi.Client/EasyAbp.EShop.Plugins.ProductTag.HttpApi.Client.csproj @@ -0,0 +1,15 @@ + + + + + + netstandard2.0 + EasyAbp.EShop.Plugins.ProductTag + + + + + + + + diff --git a/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.HttpApi.Client/FodyWeavers.xml b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.HttpApi.Client/FodyWeavers.xml new file mode 100644 index 00000000..be0de3a9 --- /dev/null +++ b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.HttpApi.Client/FodyWeavers.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.HttpApi.Client/FodyWeavers.xsd b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.HttpApi.Client/FodyWeavers.xsd new file mode 100644 index 00000000..3f3946e2 --- /dev/null +++ b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.HttpApi.Client/FodyWeavers.xsd @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + 'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed. + + + + + A comma-separated list of error codes that can be safely ignored in assembly verification. + + + + + 'false' to turn off automatic generation of the XML Schema file. + + + + + \ No newline at end of file diff --git a/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.HttpApi.Client/ProductTagHttpApiClientModule.cs b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.HttpApi.Client/ProductTagHttpApiClientModule.cs new file mode 100644 index 00000000..264a411f --- /dev/null +++ b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.HttpApi.Client/ProductTagHttpApiClientModule.cs @@ -0,0 +1,22 @@ +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.Http.Client; +using Volo.Abp.Modularity; + +namespace EasyAbp.EShop.Plugins.ProductTag +{ + [DependsOn( + typeof(ProductTagApplicationContractsModule), + typeof(AbpHttpClientModule))] + public class ProductTagHttpApiClientModule : AbpModule + { + public const string RemoteServiceName = "ProductTag"; + + public override void ConfigureServices(ServiceConfigurationContext context) + { + context.Services.AddHttpClientProxies( + typeof(ProductTagApplicationContractsModule).Assembly, + RemoteServiceName + ); + } + } +} diff --git a/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.HttpApi/EasyAbp.EShop.Plugins.ProductTag.HttpApi.csproj b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.HttpApi/EasyAbp.EShop.Plugins.ProductTag.HttpApi.csproj new file mode 100644 index 00000000..decfa3db --- /dev/null +++ b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.HttpApi/EasyAbp.EShop.Plugins.ProductTag.HttpApi.csproj @@ -0,0 +1,15 @@ + + + + + + netcoreapp3.1 + EasyAbp.EShop.Plugins.ProductTag + + + + + + + + diff --git a/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.HttpApi/FodyWeavers.xml b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.HttpApi/FodyWeavers.xml new file mode 100644 index 00000000..be0de3a9 --- /dev/null +++ b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.HttpApi/FodyWeavers.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.HttpApi/FodyWeavers.xsd b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.HttpApi/FodyWeavers.xsd new file mode 100644 index 00000000..3f3946e2 --- /dev/null +++ b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.HttpApi/FodyWeavers.xsd @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + 'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed. + + + + + A comma-separated list of error codes that can be safely ignored in assembly verification. + + + + + 'false' to turn off automatic generation of the XML Schema file. + + + + + \ No newline at end of file diff --git a/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.HttpApi/ProductTagBaseController.cs b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.HttpApi/ProductTagBaseController.cs new file mode 100644 index 00000000..3d123e0c --- /dev/null +++ b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.HttpApi/ProductTagBaseController.cs @@ -0,0 +1,13 @@ +using EasyAbp.EShop.Plugins.ProductTag.Localization; +using Volo.Abp.AspNetCore.Mvc; + +namespace EasyAbp.EShop.Plugins.ProductTag +{ + public abstract class ProductTagBaseController : AbpController + { + protected ProductTagBaseController() + { + LocalizationResource = typeof(ProductTagResource); + } + } +} diff --git a/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.HttpApi/ProductTagHttpApiModule.cs b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.HttpApi/ProductTagHttpApiModule.cs new file mode 100644 index 00000000..90825e4d --- /dev/null +++ b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.HttpApi/ProductTagHttpApiModule.cs @@ -0,0 +1,33 @@ +using Localization.Resources.AbpUi; +using EasyAbp.EShop.Plugins.ProductTag.Localization; +using Volo.Abp.AspNetCore.Mvc; +using Volo.Abp.Localization; +using Volo.Abp.Modularity; +using Microsoft.Extensions.DependencyInjection; + +namespace EasyAbp.EShop.Plugins.ProductTag +{ + [DependsOn( + typeof(ProductTagApplicationContractsModule), + typeof(AbpAspNetCoreMvcModule))] + public class ProductTagHttpApiModule : AbpModule + { + public override void PreConfigureServices(ServiceConfigurationContext context) + { + PreConfigure(mvcBuilder => + { + mvcBuilder.AddApplicationPartIfNotExists(typeof(ProductTagHttpApiModule).Assembly); + }); + } + + public override void ConfigureServices(ServiceConfigurationContext context) + { + Configure(options => + { + options.Resources + .Get() + .AddBaseTypes(typeof(AbpUiResource)); + }); + } + } +} diff --git a/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.HttpApi/ProductTags/ProductTagController.cs b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.HttpApi/ProductTags/ProductTagController.cs new file mode 100644 index 00000000..ab622bc1 --- /dev/null +++ b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.HttpApi/ProductTags/ProductTagController.cs @@ -0,0 +1,48 @@ +using EasyAbp.EShop.Plugins.ProductTag.ProductTags.Dtos; +using System; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc; +using Volo.Abp; +using Volo.Abp.Application.Dtos; + +namespace EasyAbp.EShop.Plugins.ProductTag.ProductTags +{ + [RemoteService(Name = "ProductTagService")] + [Route("/api/eShop/products/productTag")] + public class ProductTagController : ProductTagBaseController, IProductTagAppService + { + private readonly IProductTagAppService _service; + + public ProductTagController(IProductTagAppService service) + { + _service = service; + } + + [HttpPut] + public virtual Task UpdateAsync(CreateUpdateProductTagsDto input) + { + return _service.UpdateAsync(input); + } + + [RemoteService(false)] + [NonAction] + public Task GetAsync(Guid id) + { + throw new NotSupportedException(); + } + + [HttpGet] + public Task> GetListAsync(GetProductTagListDto input) + { + return _service.GetListAsync(input); + } + + + [HttpPut] + [Route("{id}")] + public Task UpdateAsync(Guid id, UpdateProductTagDto input) + { + return _service.UpdateAsync(id, input); + } + } +} \ No newline at end of file diff --git a/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.HttpApi/Tags/TagController.cs b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.HttpApi/Tags/TagController.cs new file mode 100644 index 00000000..c9acb3d2 --- /dev/null +++ b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.HttpApi/Tags/TagController.cs @@ -0,0 +1,54 @@ +using System; +using System.Threading.Tasks; +using EasyAbp.EShop.Plugins.ProductTag.Tags.Dtos; +using Microsoft.AspNetCore.Mvc; +using Volo.Abp; +using Volo.Abp.Application.Dtos; + +namespace EasyAbp.EShop.Plugins.ProductTag.Tags +{ + [RemoteService(Name = "TagService")] + [Route("/api/eShop/products/tag")] + public class TagController : ProductTagBaseController, ITagAppService + { + private readonly ITagAppService _service; + + public TagController(ITagAppService service) + { + _service = service; + } + + [HttpGet] + [Route("{id}")] + public Task GetAsync(Guid id) + { + return _service.GetAsync(id); + } + + [HttpGet] + public Task> GetListAsync(GetTagListDto input) + { + return _service.GetListAsync(input); + } + + [HttpPost] + public Task CreateAsync(CreateTagDto input) + { + return _service.CreateAsync(input); + } + + [HttpPut] + [Route("{id}")] + public Task UpdateAsync(Guid id, UpdateTagDto input) + { + return _service.UpdateAsync(id, input); + } + + [HttpDelete] + [Route("{id}")] + public Task DeleteAsync(Guid id) + { + return _service.DeleteAsync(id); + } + } +} \ No newline at end of file diff --git a/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.MongoDB/EasyAbp.EShop.Plugins.ProductTag.MongoDB.csproj b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.MongoDB/EasyAbp.EShop.Plugins.ProductTag.MongoDB.csproj new file mode 100644 index 00000000..951ad0ea --- /dev/null +++ b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.MongoDB/EasyAbp.EShop.Plugins.ProductTag.MongoDB.csproj @@ -0,0 +1,15 @@ + + + + + + netcoreapp3.1 + EasyAbp.EShop.Plugins.ProductTag + + + + + + + + diff --git a/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.MongoDB/FodyWeavers.xml b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.MongoDB/FodyWeavers.xml new file mode 100644 index 00000000..00e1d9a1 --- /dev/null +++ b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.MongoDB/FodyWeavers.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.MongoDB/FodyWeavers.xsd b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.MongoDB/FodyWeavers.xsd new file mode 100644 index 00000000..3f3946e2 --- /dev/null +++ b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.MongoDB/FodyWeavers.xsd @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + 'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed. + + + + + A comma-separated list of error codes that can be safely ignored in assembly verification. + + + + + 'false' to turn off automatic generation of the XML Schema file. + + + + + \ No newline at end of file diff --git a/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.MongoDB/MongoDB/IProductTagMongoDbContext.cs b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.MongoDB/MongoDB/IProductTagMongoDbContext.cs new file mode 100644 index 00000000..c82594b7 --- /dev/null +++ b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.MongoDB/MongoDB/IProductTagMongoDbContext.cs @@ -0,0 +1,13 @@ +using Volo.Abp.Data; +using Volo.Abp.MongoDB; + +namespace EasyAbp.EShop.Plugins.ProductTag.MongoDB +{ + [ConnectionStringName(ProductTagDbProperties.ConnectionStringName)] + public interface IProductTagMongoDbContext : IAbpMongoDbContext + { + /* Define mongo collections here. Example: + * IMongoCollection Questions { get; } + */ + } +} diff --git a/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.MongoDB/MongoDB/ProductTagMongoDbContext.cs b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.MongoDB/MongoDB/ProductTagMongoDbContext.cs new file mode 100644 index 00000000..2bfe8f87 --- /dev/null +++ b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.MongoDB/MongoDB/ProductTagMongoDbContext.cs @@ -0,0 +1,20 @@ +using Volo.Abp.Data; +using Volo.Abp.MongoDB; + +namespace EasyAbp.EShop.Plugins.ProductTag.MongoDB +{ + [ConnectionStringName(ProductTagDbProperties.ConnectionStringName)] + public class ProductTagMongoDbContext : AbpMongoDbContext, IProductTagMongoDbContext + { + /* Add mongo collections here. Example: + * public IMongoCollection Questions => Collection(); + */ + + protected override void CreateModel(IMongoModelBuilder modelBuilder) + { + base.CreateModel(modelBuilder); + + modelBuilder.ConfigureProductTag(); + } + } +} \ No newline at end of file diff --git a/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.MongoDB/MongoDB/ProductTagMongoDbContextExtensions.cs b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.MongoDB/MongoDB/ProductTagMongoDbContextExtensions.cs new file mode 100644 index 00000000..00b88801 --- /dev/null +++ b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.MongoDB/MongoDB/ProductTagMongoDbContextExtensions.cs @@ -0,0 +1,22 @@ +using System; +using Volo.Abp; +using Volo.Abp.MongoDB; + +namespace EasyAbp.EShop.Plugins.ProductTag.MongoDB +{ + public static class ProductTagMongoDbContextExtensions + { + public static void ConfigureProductTag( + this IMongoModelBuilder builder, + Action optionsAction = null) + { + Check.NotNull(builder, nameof(builder)); + + var options = new ProductTagMongoModelBuilderConfigurationOptions( + ProductTagDbProperties.DbTablePrefix + ); + + optionsAction?.Invoke(options); + } + } +} \ No newline at end of file diff --git a/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.MongoDB/MongoDB/ProductTagMongoDbModule.cs b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.MongoDB/MongoDB/ProductTagMongoDbModule.cs new file mode 100644 index 00000000..2b28a721 --- /dev/null +++ b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.MongoDB/MongoDB/ProductTagMongoDbModule.cs @@ -0,0 +1,23 @@ +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.Modularity; +using Volo.Abp.MongoDB; + +namespace EasyAbp.EShop.Plugins.ProductTag.MongoDB +{ + [DependsOn( + typeof(ProductTagDomainModule), + typeof(AbpMongoDbModule) + )] + public class ProductTagMongoDbModule : AbpModule + { + public override void ConfigureServices(ServiceConfigurationContext context) + { + context.Services.AddMongoDbContext(options => + { + /* Add custom repositories here. Example: + * options.AddRepository(); + */ + }); + } + } +} diff --git a/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.MongoDB/MongoDB/ProductTagMongoModelBuilderConfigurationOptions.cs b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.MongoDB/MongoDB/ProductTagMongoModelBuilderConfigurationOptions.cs new file mode 100644 index 00000000..b052723e --- /dev/null +++ b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.MongoDB/MongoDB/ProductTagMongoModelBuilderConfigurationOptions.cs @@ -0,0 +1,14 @@ +using JetBrains.Annotations; +using Volo.Abp.MongoDB; + +namespace EasyAbp.EShop.Plugins.ProductTag.MongoDB +{ + public class ProductTagMongoModelBuilderConfigurationOptions : AbpMongoModelBuilderConfigurationOptions + { + public ProductTagMongoModelBuilderConfigurationOptions( + [NotNull] string collectionPrefix = "") + : base(collectionPrefix) + { + } + } +} \ No newline at end of file diff --git a/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Web/EasyAbp.EShop.Plugins.ProductTag.Web.csproj b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Web/EasyAbp.EShop.Plugins.ProductTag.Web.csproj new file mode 100644 index 00000000..6a8d8589 --- /dev/null +++ b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Web/EasyAbp.EShop.Plugins.ProductTag.Web.csproj @@ -0,0 +1,47 @@ + + + + + + netcoreapp3.1 + $(AssetTargetFallback);portable-net45+win8+wp8+wpa81; + true + Library + EasyAbp.EShop.Plugins.ProductTag.Web + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Web/FodyWeavers.xml b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Web/FodyWeavers.xml new file mode 100644 index 00000000..be0de3a9 --- /dev/null +++ b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Web/FodyWeavers.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Web/FodyWeavers.xsd b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Web/FodyWeavers.xsd new file mode 100644 index 00000000..3f3946e2 --- /dev/null +++ b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Web/FodyWeavers.xsd @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + 'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed. + + + + + A comma-separated list of error codes that can be safely ignored in assembly verification. + + + + + 'false' to turn off automatic generation of the XML Schema file. + + + + + \ No newline at end of file diff --git a/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Web/Menus/ProductTagMenuContributor.cs b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Web/Menus/ProductTagMenuContributor.cs new file mode 100644 index 00000000..23344d33 --- /dev/null +++ b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Web/Menus/ProductTagMenuContributor.cs @@ -0,0 +1,39 @@ +using System.Collections.Generic; +using EasyAbp.EShop.Plugins.ProductTag.Localization; +using EasyAbp.EShop.Plugins.ProductTag.Permissions; +using EasyAbp.EShop.Products.Web.Menus; +using System.Threading.Tasks; +using Volo.Abp.UI.Navigation; + +namespace EasyAbp.EShop.Plugins.ProductTag.Web.Menus +{ + public class ProductTagMenuContributor : IMenuContributor + { + public async Task ConfigureMenuAsync(MenuConfigurationContext context) + { + if (context.Menu.Name == StandardMenus.Main) + { + await ConfigureMainMenu(context); + } + } + + private async Task ConfigureMainMenu(MenuConfigurationContext context) + { + //Add main menu items. + var l = context.GetLocalizer(); + + var eShopMenuItem = context.Menu.Items.GetOrAdd(i => i.Name == ProductsMenus.ModuleGroupPrefix, + () => new ApplicationMenuItem(ProductsMenus.ModuleGroupPrefix, l["Menu:EasyAbpEShop"])); + + var productManagementMenuItem = eShopMenuItem.Items.GetOrAdd(x => x.Name == ProductsMenus.Prefix, + () => new ApplicationMenuItem(ProductsMenus.Prefix, l["Menu:ProductManagement"])); + + if (await context.IsGrantedAsync(ProductTagPermissions.Tags.Default)) + { + productManagementMenuItem.AddItem( + new ApplicationMenuItem(ProductTagMenus.Tag, l["Menu:Tag"], "/EShop/Products/Tags/Tag") + ); + } + } + } +} \ No newline at end of file diff --git a/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Web/Menus/ProductTagMenus.cs b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Web/Menus/ProductTagMenus.cs new file mode 100644 index 00000000..9d59ae47 --- /dev/null +++ b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Web/Menus/ProductTagMenus.cs @@ -0,0 +1,13 @@ +namespace EasyAbp.EShop.Plugins.ProductTag.Web.Menus +{ + public class ProductTagMenus + { + private const string Prefix = "ProductTag"; + + //Add your menu items here... + //public const string Home = Prefix + ".MyNewMenuItem"; + + + public const string Tag = Prefix + ".Tag"; + } +} \ No newline at end of file diff --git a/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Web/Pages/EShop/Products/ProductTag/Index.cshtml b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Web/Pages/EShop/Products/ProductTag/Index.cshtml new file mode 100644 index 00000000..85b85366 --- /dev/null +++ b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Web/Pages/EShop/Products/ProductTag/Index.cshtml @@ -0,0 +1,9 @@ +@page +@using Microsoft.Extensions.Localization +@using EasyAbp.EShop.Plugins.ProductTag.Localization +@model EasyAbp.EShop.Plugins.ProductTag.Web.Pages.EShop.Products.ProductTag.IndexModel +@inject IStringLocalizer L +@{ +} +

ProductTag

+

@L["SamplePageMessage"]

diff --git a/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Web/Pages/EShop/Products/ProductTag/Index.cshtml.cs b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Web/Pages/EShop/Products/ProductTag/Index.cshtml.cs new file mode 100644 index 00000000..c4fc906c --- /dev/null +++ b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Web/Pages/EShop/Products/ProductTag/Index.cshtml.cs @@ -0,0 +1,9 @@ +namespace EasyAbp.EShop.Plugins.ProductTag.Web.Pages.EShop.Products.ProductTag +{ + public class IndexModel : ProductTagPageModel + { + public void OnGet() + { + } + } +} \ No newline at end of file diff --git a/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Web/Pages/EShop/Products/ProductTag/_ViewImports.cshtml b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Web/Pages/EShop/Products/ProductTag/_ViewImports.cshtml new file mode 100644 index 00000000..c1da1f5f --- /dev/null +++ b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Web/Pages/EShop/Products/ProductTag/_ViewImports.cshtml @@ -0,0 +1,4 @@ +@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers +@addTagHelper *, Volo.Abp.AspNetCore.Mvc.UI +@addTagHelper *, Volo.Abp.AspNetCore.Mvc.UI.Bootstrap +@addTagHelper *, Volo.Abp.AspNetCore.Mvc.UI.Bundling \ No newline at end of file diff --git a/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Web/Pages/EShop/Products/Tags/Tag/CreateModal.cshtml b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Web/Pages/EShop/Products/Tags/Tag/CreateModal.cshtml new file mode 100644 index 00000000..07cc44da --- /dev/null +++ b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Web/Pages/EShop/Products/Tags/Tag/CreateModal.cshtml @@ -0,0 +1,18 @@ +@page +@using EasyAbp.EShop.Plugins.ProductTag.Localization +@using Microsoft.AspNetCore.Mvc.Localization +@using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Modal; +@inject IHtmlLocalizer L +@model EasyAbp.EShop.Plugins.ProductTag.Web.Pages.EShop.Products.Tags.Tag.CreateModalModel +@{ + Layout = null; +} + + + + + + + + + \ No newline at end of file diff --git a/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Web/Pages/EShop/Products/Tags/Tag/CreateModal.cshtml.cs b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Web/Pages/EShop/Products/Tags/Tag/CreateModal.cshtml.cs new file mode 100644 index 00000000..134cb57e --- /dev/null +++ b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Web/Pages/EShop/Products/Tags/Tag/CreateModal.cshtml.cs @@ -0,0 +1,26 @@ +using System.Threading.Tasks; +using EasyAbp.EShop.Plugins.ProductTag.Tags; +using EasyAbp.EShop.Plugins.ProductTag.Tags.Dtos; +using Microsoft.AspNetCore.Mvc; + +namespace EasyAbp.EShop.Plugins.ProductTag.Web.Pages.EShop.Products.Tags.Tag +{ + public class CreateModalModel : ProductTagPageModel + { + [BindProperty] + public CreateTagDto ViewModel { get; set; } + + private readonly ITagAppService _service; + + public CreateModalModel(ITagAppService service) + { + _service = service; + } + + public virtual async Task OnPostAsync() + { + await _service.CreateAsync(ViewModel); + return NoContent(); + } + } +} \ No newline at end of file diff --git a/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Web/Pages/EShop/Products/Tags/Tag/EditModal.cshtml b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Web/Pages/EShop/Products/Tags/Tag/EditModal.cshtml new file mode 100644 index 00000000..ffb257f8 --- /dev/null +++ b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Web/Pages/EShop/Products/Tags/Tag/EditModal.cshtml @@ -0,0 +1,19 @@ +@page +@using EasyAbp.EShop.Plugins.ProductTag.Localization +@using Microsoft.AspNetCore.Mvc.Localization +@using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Modal; +@inject IHtmlLocalizer L +@model EasyAbp.EShop.Plugins.ProductTag.Web.Pages.EShop.Products.Tags.Tag.EditModalModel +@{ + Layout = null; +} + + + + + + + + + + diff --git a/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Web/Pages/EShop/Products/Tags/Tag/EditModal.cshtml.cs b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Web/Pages/EShop/Products/Tags/Tag/EditModal.cshtml.cs new file mode 100644 index 00000000..61595422 --- /dev/null +++ b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Web/Pages/EShop/Products/Tags/Tag/EditModal.cshtml.cs @@ -0,0 +1,37 @@ +using System; +using System.Threading.Tasks; +using EasyAbp.EShop.Plugins.ProductTag.Tags; +using EasyAbp.EShop.Plugins.ProductTag.Tags.Dtos; +using Microsoft.AspNetCore.Mvc; + +namespace EasyAbp.EShop.Plugins.ProductTag.Web.Pages.EShop.Products.Tags.Tag +{ + public class EditModalModel : ProductTagPageModel + { + [HiddenInput] + [BindProperty(SupportsGet = true)] + public Guid Id { get; set; } + + [BindProperty] + public UpdateTagDto ViewModel { get; set; } + + private readonly ITagAppService _service; + + public EditModalModel(ITagAppService service) + { + _service = service; + } + + public virtual async Task OnGetAsync() + { + var dto = await _service.GetAsync(Id); + ViewModel = ObjectMapper.Map(dto); + } + + public virtual async Task OnPostAsync() + { + await _service.UpdateAsync(Id, ViewModel); + return NoContent(); + } + } +} \ No newline at end of file diff --git a/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Web/Pages/EShop/Products/Tags/Tag/Index.cshtml b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Web/Pages/EShop/Products/Tags/Tag/Index.cshtml new file mode 100644 index 00000000..4de9187d --- /dev/null +++ b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Web/Pages/EShop/Products/Tags/Tag/Index.cshtml @@ -0,0 +1,61 @@ +@page +@using EasyAbp.EShop.Plugins.ProductTag.Localization +@using EasyAbp.EShop.Plugins.ProductTag.Web.Menus +@using Microsoft.AspNetCore.Mvc.Localization +@using Volo.Abp.AspNetCore.Mvc.UI.Layout +@model EasyAbp.EShop.Plugins.ProductTag.Web.Pages.EShop.Products.Tags.Tag.IndexModel +@inject IPageLayout PageLayout +@inject IHtmlLocalizer L +@{ + PageLayout.Content.Title = L["Tag"].Value; + PageLayout.Content.BreadCrumb.Add(L["Menu:Tag"].Value); + PageLayout.Content.MenuItemName = ProductTagMenus.Tag; +} + +@section scripts +{ + +} +@section styles +{ + +} + + + + + + + @L["Tag"] - @Model.StoreName + + + + + + + + + + + @L["Actions"] + Id + @*@L["TagStoreId"]*@ + @L["TagDescription"] + @L["TagMediaResources"] + @*@L["TagIsHidden"]*@ + @L["TagDisplayName"] + @*@L["TagCode"]*@ + @*@L["TagLevel"]*@ + @L["TagParentId"] + @*@L["TagParent"] + @L["TagChildren"]*@ + + + + + \ No newline at end of file diff --git a/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Web/Pages/EShop/Products/Tags/Tag/Index.cshtml.cs b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Web/Pages/EShop/Products/Tags/Tag/Index.cshtml.cs new file mode 100644 index 00000000..ec5a07d9 --- /dev/null +++ b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Web/Pages/EShop/Products/Tags/Tag/Index.cshtml.cs @@ -0,0 +1,51 @@ +using EasyAbp.EShop.Stores.StoreOwners; +using EasyAbp.EShop.Stores.StoreOwners.Dtos; +using EasyAbp.EShop.Stores.Stores; +using Microsoft.AspNetCore.Mvc; +using System; +using System.Linq; +using System.Threading.Tasks; + +namespace EasyAbp.EShop.Plugins.ProductTag.Web.Pages.EShop.Products.Tags.Tag +{ + public class IndexModel : ProductTagPageModel + { + private readonly IStoreAppService _storeAppService; + private readonly IStoreOwnerAppService _storeOwnerAppService; + + [BindProperty(SupportsGet = true)] + public Guid? StoreId { get; set; } + + public string StoreName { get; set; } + + public IndexModel(IStoreAppService storeAppService, + IStoreOwnerAppService storeOwnerAppService) + { + _storeAppService = storeAppService; + _storeOwnerAppService = storeOwnerAppService; + } + + public virtual async Task OnGetAsync() + { + //TODO: Need to handle: when StoreId is empty, and current user owns multiple store + if (!StoreId.HasValue && CurrentUser.Id.HasValue) + { + var storeOwners = await _storeOwnerAppService.GetListAsync(new GetStoreOwnerListDto + { + OwnerId = CurrentUser.Id.Value, + }); + + StoreId = storeOwners.Items.FirstOrDefault()?.StoreId; + } + + //show default store + if (!StoreId.HasValue) + { + var defaultStore = await _storeAppService.GetDefaultAsync(); + StoreId = defaultStore.Id; + } + + StoreName = (await _storeAppService.GetAsync(StoreId.Value)).Name; + } + } +} diff --git a/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Web/Pages/EShop/Products/Tags/Tag/index.css b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Web/Pages/EShop/Products/Tags/Tag/index.css new file mode 100644 index 00000000..e69de29b diff --git a/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Web/Pages/EShop/Products/Tags/Tag/index.js b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Web/Pages/EShop/Products/Tags/Tag/index.js new file mode 100644 index 00000000..1617ed57 --- /dev/null +++ b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Web/Pages/EShop/Products/Tags/Tag/index.js @@ -0,0 +1,80 @@ +$(function () { + + var l = abp.localization.getResource('Products'); + + var service = easyAbp.eShop.products.tags.tag; + var createModal = new abp.ModalManager(abp.appPath + 'EShop/Products/Tags/Tag/CreateModal'); + var editModal = new abp.ModalManager(abp.appPath + 'EShop/Products/Tags/Tag/EditModal'); + + var dataTable = $('#TagTable').DataTable(abp.libs.datatables.normalizeConfiguration({ + processing: true, + serverSide: true, + paging: true, + searching: false, + autoWidth: false, + scrollCollapse: true, + order: [[1, "asc"]], + ajax: abp.libs.datatables.createAjax(service.getList, function () { + return { storeId: storeId, showHidden: true } + }), + columnDefs: [ + { + rowAction: { + items: + [ + { + text: l('Product'), + action: function (data) { + document.location.href = document.location.origin + + '/EShop/Products/Products/Product?StoreId=' + storeId + '&TagId=' + data.record.id; + } + }, + { + text: l('Edit'), + action: function (data) { + editModal.open({ id: data.record.id }); + } + }, + { + text: l('Delete'), + confirmMessage: function (data) { + return l('TagDeletionConfirmationMessage', data.record.id); + }, + action: function (data) { + service.delete(data.record.id) + .then(function () { + abp.notify.info(l('SuccessfullyDeleted')); + dataTable.ajax.reload(); + }); + } + } + ] + } + }, + { data: "id"}, + //{ data: "storeId" }, + { data: "description" }, + { data: "mediaResources" }, + //{ data: "isHidden" }, + { data: "displayName" }, + //{ data: "code" }, + //{ data: "level" }, + { data: "parentId" }, + //{ data: "parent" }, + //{ data: "children" }, + ] + })); + + createModal.onResult(function () { + dataTable.ajax.reload(); + }); + + editModal.onResult(function () { + dataTable.ajax.reload(); + }); + + $('#NewTagButton').click(function (e) { + e.preventDefault(); + createModal.open(); + }); +}); \ No newline at end of file diff --git a/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Web/Pages/ProductTagPageModel.cs b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Web/Pages/ProductTagPageModel.cs new file mode 100644 index 00000000..7cb25b39 --- /dev/null +++ b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Web/Pages/ProductTagPageModel.cs @@ -0,0 +1,16 @@ +using EasyAbp.EShop.Plugins.ProductTag.Localization; +using Volo.Abp.AspNetCore.Mvc.UI.RazorPages; + +namespace EasyAbp.EShop.Plugins.ProductTag.Web.Pages +{ + /* Inherit your PageModel classes from this class. + */ + public abstract class ProductTagPageModel : AbpPageModel + { + protected ProductTagPageModel() + { + LocalizationResourceType = typeof(ProductTagResource); + ObjectMapperContext = typeof(ProductTagWebModule); + } + } +} \ No newline at end of file diff --git a/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Web/ProductTagWebAutoMapperProfile.cs b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Web/ProductTagWebAutoMapperProfile.cs new file mode 100644 index 00000000..e6196b15 --- /dev/null +++ b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Web/ProductTagWebAutoMapperProfile.cs @@ -0,0 +1,18 @@ +using AutoMapper; +using EasyAbp.EShop.Plugins.ProductTag.Tags.Dtos; + +namespace EasyAbp.EShop.Plugins.ProductTag.Web +{ + public class ProductTagWebAutoMapperProfile : Profile + { + public ProductTagWebAutoMapperProfile() + { + /* You can configure your AutoMapper mapping configuration here. + * Alternatively, you can split your mapping configurations + * into multiple profile classes for a better organization. */ + + CreateMap(); + CreateMap(); + } + } +} \ No newline at end of file diff --git a/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Web/ProductTagWebModule.cs b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Web/ProductTagWebModule.cs new file mode 100644 index 00000000..79dbc117 --- /dev/null +++ b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Web/ProductTagWebModule.cs @@ -0,0 +1,58 @@ +using EasyAbp.EShop.Plugins.ProductTag.Localization; +using EasyAbp.EShop.Plugins.ProductTag.Web.Menus; +using Microsoft.AspNetCore.Mvc.RazorPages; +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.AspNetCore.Mvc.Localization; +using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared; +using Volo.Abp.AutoMapper; +using Volo.Abp.Modularity; +using Volo.Abp.UI.Navigation; +using Volo.Abp.VirtualFileSystem; + +namespace EasyAbp.EShop.Plugins.ProductTag.Web +{ + [DependsOn( + typeof(ProductTagHttpApiModule), + typeof(AbpAspNetCoreMvcUiThemeSharedModule), + typeof(AbpAutoMapperModule) + )] + public class ProductTagWebModule : AbpModule + { + public override void PreConfigureServices(ServiceConfigurationContext context) + { + context.Services.PreConfigure(options => + { + options.AddAssemblyResource(typeof(ProductTagResource), typeof(ProductTagWebModule).Assembly); + }); + + PreConfigure(mvcBuilder => + { + mvcBuilder.AddApplicationPartIfNotExists(typeof(ProductTagWebModule).Assembly); + }); + } + + public override void ConfigureServices(ServiceConfigurationContext context) + { + Configure(options => + { + options.MenuContributors.Add(new ProductTagMenuContributor()); + }); + + Configure(options => + { + options.FileSets.AddEmbedded(); + }); + + context.Services.AddAutoMapperObjectMapper(); + Configure(options => + { + options.AddMaps(validate: true); + }); + + Configure(options => + { + //Configure authorization. + }); + } + } +} diff --git a/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Web/Properties/launchSettings.json b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Web/Properties/launchSettings.json new file mode 100644 index 00000000..0f428ebe --- /dev/null +++ b/plugins/ProductTag/src/EasyAbp.EShop.Plugins.ProductTag.Web/Properties/launchSettings.json @@ -0,0 +1,27 @@ +{ + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:1625/", + "sslPort": 44392 + } + }, + "profiles": { + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "EasyAbp.EShop.Plugins.ProductTag.Web": { + "commandName": "Project", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "applicationUrl": "https://localhost:5001;http://localhost:5000" + } + } +} \ No newline at end of file diff --git a/plugins/ProductTag/test/EasyAbp.EShop.Plugins.ProductTag.Application.Tests/EasyAbp.EShop.Plugins.ProductTag.Application.Tests.csproj b/plugins/ProductTag/test/EasyAbp.EShop.Plugins.ProductTag.Application.Tests/EasyAbp.EShop.Plugins.ProductTag.Application.Tests.csproj new file mode 100644 index 00000000..0d0e5054 --- /dev/null +++ b/plugins/ProductTag/test/EasyAbp.EShop.Plugins.ProductTag.Application.Tests/EasyAbp.EShop.Plugins.ProductTag.Application.Tests.csproj @@ -0,0 +1,16 @@ + + + + + + netcoreapp3.1 + EasyAbp.EShop.Plugins.ProductTag + + + + + + + + + diff --git a/plugins/ProductTag/test/EasyAbp.EShop.Plugins.ProductTag.Application.Tests/ProductTagApplicationTestBase.cs b/plugins/ProductTag/test/EasyAbp.EShop.Plugins.ProductTag.Application.Tests/ProductTagApplicationTestBase.cs new file mode 100644 index 00000000..aa019db8 --- /dev/null +++ b/plugins/ProductTag/test/EasyAbp.EShop.Plugins.ProductTag.Application.Tests/ProductTagApplicationTestBase.cs @@ -0,0 +1,10 @@ +namespace EasyAbp.EShop.Plugins.ProductTag +{ + /* Inherit from this class for your application layer tests. + * See SampleAppService_Tests for example. + */ + public abstract class ProductTagApplicationTestBase : ProductTagTestBase + { + + } +} \ No newline at end of file diff --git a/plugins/ProductTag/test/EasyAbp.EShop.Plugins.ProductTag.Application.Tests/ProductTagApplicationTestModule.cs b/plugins/ProductTag/test/EasyAbp.EShop.Plugins.ProductTag.Application.Tests/ProductTagApplicationTestModule.cs new file mode 100644 index 00000000..662e0188 --- /dev/null +++ b/plugins/ProductTag/test/EasyAbp.EShop.Plugins.ProductTag.Application.Tests/ProductTagApplicationTestModule.cs @@ -0,0 +1,13 @@ +using Volo.Abp.Modularity; + +namespace EasyAbp.EShop.Plugins.ProductTag +{ + [DependsOn( + typeof(ProductTagApplicationModule), + typeof(ProductTagDomainTestModule) + )] + public class ProductTagApplicationTestModule : AbpModule + { + + } +} diff --git a/plugins/ProductTag/test/EasyAbp.EShop.Plugins.ProductTag.Application.Tests/Samples/SampleAppService_Tests.cs b/plugins/ProductTag/test/EasyAbp.EShop.Plugins.ProductTag.Application.Tests/Samples/SampleAppService_Tests.cs new file mode 100644 index 00000000..6e5f4666 --- /dev/null +++ b/plugins/ProductTag/test/EasyAbp.EShop.Plugins.ProductTag.Application.Tests/Samples/SampleAppService_Tests.cs @@ -0,0 +1,30 @@ +using System.Threading.Tasks; +using Shouldly; +using Xunit; + +namespace EasyAbp.EShop.Plugins.ProductTag.Samples +{ + public class SampleAppService_Tests : ProductTagApplicationTestBase + { + private readonly ISampleAppService _sampleAppService; + + public SampleAppService_Tests() + { + _sampleAppService = GetRequiredService(); + } + + [Fact] + public async Task GetAsync() + { + var result = await _sampleAppService.GetAsync(); + result.Value.ShouldBe(42); + } + + [Fact] + public async Task GetAuthorizedAsync() + { + var result = await _sampleAppService.GetAuthorizedAsync(); + result.Value.ShouldBe(42); + } + } +} diff --git a/plugins/ProductTag/test/EasyAbp.EShop.Plugins.ProductTag.Domain.Tests/EasyAbp.EShop.Plugins.ProductTag.Domain.Tests.csproj b/plugins/ProductTag/test/EasyAbp.EShop.Plugins.ProductTag.Domain.Tests/EasyAbp.EShop.Plugins.ProductTag.Domain.Tests.csproj new file mode 100644 index 00000000..5ced1389 --- /dev/null +++ b/plugins/ProductTag/test/EasyAbp.EShop.Plugins.ProductTag.Domain.Tests/EasyAbp.EShop.Plugins.ProductTag.Domain.Tests.csproj @@ -0,0 +1,15 @@ + + + + + + netcoreapp3.1 + EasyAbp.EShop.Plugins.ProductTag + + + + + + + + diff --git a/plugins/ProductTag/test/EasyAbp.EShop.Plugins.ProductTag.Domain.Tests/ProductTagDomainTestBase.cs b/plugins/ProductTag/test/EasyAbp.EShop.Plugins.ProductTag.Domain.Tests/ProductTagDomainTestBase.cs new file mode 100644 index 00000000..9ea5f5aa --- /dev/null +++ b/plugins/ProductTag/test/EasyAbp.EShop.Plugins.ProductTag.Domain.Tests/ProductTagDomainTestBase.cs @@ -0,0 +1,10 @@ +namespace EasyAbp.EShop.Plugins.ProductTag +{ + /* Inherit from this class for your domain layer tests. + * See SampleManager_Tests for example. + */ + public abstract class ProductTagDomainTestBase : ProductTagTestBase + { + + } +} \ No newline at end of file diff --git a/plugins/ProductTag/test/EasyAbp.EShop.Plugins.ProductTag.Domain.Tests/ProductTagDomainTestModule.cs b/plugins/ProductTag/test/EasyAbp.EShop.Plugins.ProductTag.Domain.Tests/ProductTagDomainTestModule.cs new file mode 100644 index 00000000..a287e7b9 --- /dev/null +++ b/plugins/ProductTag/test/EasyAbp.EShop.Plugins.ProductTag.Domain.Tests/ProductTagDomainTestModule.cs @@ -0,0 +1,17 @@ +using EasyAbp.EShop.Plugins.ProductTag.EntityFrameworkCore; +using Volo.Abp.Modularity; + +namespace EasyAbp.EShop.Plugins.ProductTag +{ + /* Domain tests are configured to use the EF Core provider. + * You can switch to MongoDB, however your domain tests should be + * database independent anyway. + */ + [DependsOn( + typeof(ProductTagEntityFrameworkCoreTestModule) + )] + public class ProductTagDomainTestModule : AbpModule + { + + } +} diff --git a/plugins/ProductTag/test/EasyAbp.EShop.Plugins.ProductTag.Domain.Tests/Samples/SampleManager_Tests.cs b/plugins/ProductTag/test/EasyAbp.EShop.Plugins.ProductTag.Domain.Tests/Samples/SampleManager_Tests.cs new file mode 100644 index 00000000..529935d2 --- /dev/null +++ b/plugins/ProductTag/test/EasyAbp.EShop.Plugins.ProductTag.Domain.Tests/Samples/SampleManager_Tests.cs @@ -0,0 +1,21 @@ +using System.Threading.Tasks; +using Xunit; + +namespace EasyAbp.EShop.Plugins.ProductTag.Samples +{ + public class SampleManager_Tests : ProductTagDomainTestBase + { + //private readonly SampleManager _sampleManager; + + public SampleManager_Tests() + { + //_sampleManager = GetRequiredService(); + } + + [Fact] + public async Task Method1Async() + { + + } + } +} diff --git a/plugins/ProductTag/test/EasyAbp.EShop.Plugins.ProductTag.EntityFrameworkCore.Tests/EasyAbp.EShop.Plugins.ProductTag.EntityFrameworkCore.Tests.csproj b/plugins/ProductTag/test/EasyAbp.EShop.Plugins.ProductTag.EntityFrameworkCore.Tests/EasyAbp.EShop.Plugins.ProductTag.EntityFrameworkCore.Tests.csproj new file mode 100644 index 00000000..ae7e53ba --- /dev/null +++ b/plugins/ProductTag/test/EasyAbp.EShop.Plugins.ProductTag.EntityFrameworkCore.Tests/EasyAbp.EShop.Plugins.ProductTag.EntityFrameworkCore.Tests.csproj @@ -0,0 +1,18 @@ + + + + + + netcoreapp3.1 + EasyAbp.EShop.Plugins.ProductTag + + + + + + + + + + + diff --git a/plugins/ProductTag/test/EasyAbp.EShop.Plugins.ProductTag.EntityFrameworkCore.Tests/EntityFrameworkCore/ProductTagEntityFrameworkCoreTestBase.cs b/plugins/ProductTag/test/EasyAbp.EShop.Plugins.ProductTag.EntityFrameworkCore.Tests/EntityFrameworkCore/ProductTagEntityFrameworkCoreTestBase.cs new file mode 100644 index 00000000..daa009b6 --- /dev/null +++ b/plugins/ProductTag/test/EasyAbp.EShop.Plugins.ProductTag.EntityFrameworkCore.Tests/EntityFrameworkCore/ProductTagEntityFrameworkCoreTestBase.cs @@ -0,0 +1,10 @@ +namespace EasyAbp.EShop.Plugins.ProductTag.EntityFrameworkCore +{ + /* This class can be used as a base class for EF Core integration tests, + * while SampleRepository_Tests uses a different approach. + */ + public abstract class ProductTagEntityFrameworkCoreTestBase : ProductTagTestBase + { + + } +} \ No newline at end of file diff --git a/plugins/ProductTag/test/EasyAbp.EShop.Plugins.ProductTag.EntityFrameworkCore.Tests/EntityFrameworkCore/ProductTagEntityFrameworkCoreTestModule.cs b/plugins/ProductTag/test/EasyAbp.EShop.Plugins.ProductTag.EntityFrameworkCore.Tests/EntityFrameworkCore/ProductTagEntityFrameworkCoreTestModule.cs new file mode 100644 index 00000000..388da505 --- /dev/null +++ b/plugins/ProductTag/test/EasyAbp.EShop.Plugins.ProductTag.EntityFrameworkCore.Tests/EntityFrameworkCore/ProductTagEntityFrameworkCoreTestModule.cs @@ -0,0 +1,43 @@ +using Microsoft.Data.Sqlite; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Storage; +using Volo.Abp.EntityFrameworkCore; +using Volo.Abp.EntityFrameworkCore.Sqlite; +using Volo.Abp.Modularity; + +namespace EasyAbp.EShop.Plugins.ProductTag.EntityFrameworkCore +{ + [DependsOn( + typeof(ProductTagTestBaseModule), + typeof(ProductTagEntityFrameworkCoreModule), + typeof(AbpEntityFrameworkCoreSqliteModule) + )] + public class ProductTagEntityFrameworkCoreTestModule : AbpModule + { + public override void ConfigureServices(ServiceConfigurationContext context) + { + var sqliteConnection = CreateDatabaseAndGetConnection(); + + Configure(options => + { + options.Configure(abpDbContextConfigurationContext => + { + abpDbContextConfigurationContext.DbContextOptions.UseSqlite(sqliteConnection); + }); + }); + } + + private static SqliteConnection CreateDatabaseAndGetConnection() + { + var connection = new SqliteConnection("Data Source=:memory:"); + connection.Open(); + + new ProductTagDbContext( + new DbContextOptionsBuilder().UseSqlite(connection).Options + ).GetService().CreateTables(); + + return connection; + } + } +} diff --git a/plugins/ProductTag/test/EasyAbp.EShop.Plugins.ProductTag.EntityFrameworkCore.Tests/EntityFrameworkCore/Samples/SampleRepository_Tests.cs b/plugins/ProductTag/test/EasyAbp.EShop.Plugins.ProductTag.EntityFrameworkCore.Tests/EntityFrameworkCore/Samples/SampleRepository_Tests.cs new file mode 100644 index 00000000..4b161b23 --- /dev/null +++ b/plugins/ProductTag/test/EasyAbp.EShop.Plugins.ProductTag.EntityFrameworkCore.Tests/EntityFrameworkCore/Samples/SampleRepository_Tests.cs @@ -0,0 +1,12 @@ +using EasyAbp.EShop.Plugins.ProductTag.Samples; + +namespace EasyAbp.EShop.Plugins.ProductTag.EntityFrameworkCore.Samples +{ + public class SampleRepository_Tests : SampleRepository_Tests + { + /* Don't write custom repository tests here, instead write to + * the base class. + * One exception can be some specific tests related to EF core. + */ + } +} diff --git a/plugins/ProductTag/test/EasyAbp.EShop.Plugins.ProductTag.HttpApi.Client.ConsoleTestApp/ClientDemoService.cs b/plugins/ProductTag/test/EasyAbp.EShop.Plugins.ProductTag.HttpApi.Client.ConsoleTestApp/ClientDemoService.cs new file mode 100644 index 00000000..cffdd8fb --- /dev/null +++ b/plugins/ProductTag/test/EasyAbp.EShop.Plugins.ProductTag.HttpApi.Client.ConsoleTestApp/ClientDemoService.cs @@ -0,0 +1,156 @@ +using System; +using System.Net.Http; +using System.Threading.Tasks; +using IdentityModel.Client; +using Microsoft.Extensions.Configuration; +using EasyAbp.EShop.Plugins.ProductTag.Samples; +using Volo.Abp.DependencyInjection; +using Volo.Abp.IdentityModel; + +namespace EasyAbp.EShop.Plugins.ProductTag +{ + public class ClientDemoService : ITransientDependency + { + private readonly ISampleAppService _sampleAppService; + private readonly IIdentityModelAuthenticationService _authenticationService; + private readonly IConfiguration _configuration; + + public ClientDemoService( + ISampleAppService sampleAppService, + IIdentityModelAuthenticationService authenticationService, + IConfiguration configuration) + { + _sampleAppService = sampleAppService; + _authenticationService = authenticationService; + _configuration = configuration; + } + + public async Task RunAsync() + { + await TestWithDynamicProxiesAsync(); + await TestWithHttpClientAndIdentityModelAuthenticationServiceAsync(); + await TestAllManuallyAsync(); + } + + /* Shows how to perform an HTTP request to the API using ABP's dynamic c# proxy + * feature. It is just simple as calling a local service method. + * Authorization and HTTP request details are handled by the ABP framework. + */ + private async Task TestWithDynamicProxiesAsync() + { + Console.WriteLine(); + Console.WriteLine($"***** {nameof(TestWithDynamicProxiesAsync)} *****"); + + var result = await _sampleAppService.GetAsync(); + Console.WriteLine("Result: " + result.Value); + + result = await _sampleAppService.GetAuthorizedAsync(); + Console.WriteLine("Result (authorized): " + result.Value); + } + + /* Shows how to use HttpClient to perform a request to the HTTP API. + * It uses ABP's IIdentityModelAuthenticationService to simplify obtaining access tokens. + */ + private async Task TestWithHttpClientAndIdentityModelAuthenticationServiceAsync() + { + Console.WriteLine(); + Console.WriteLine($"***** {nameof(TestWithHttpClientAndIdentityModelAuthenticationServiceAsync)} *****"); + + //Get access token using ABP's IIdentityModelAuthenticationService + + var accessToken = await _authenticationService.GetAccessTokenAsync( + new IdentityClientConfiguration( + _configuration["IdentityClients:Default:Authority"], + _configuration["IdentityClients:Default:Scope"], + _configuration["IdentityClients:Default:ClientId"], + _configuration["IdentityClients:Default:ClientSecret"], + _configuration["IdentityClients:Default:GrantType"], + _configuration["IdentityClients:Default:UserName"], + _configuration["IdentityClients:Default:UserPassword"] + ) + ); + + //Perform the actual HTTP request + + using (var httpClient = new HttpClient()) + { + httpClient.SetBearerToken(accessToken); + + var url = _configuration["RemoteServices:ProductTag:BaseUrl"] + + "api/ProductTag/sample/authorized"; + + var responseMessage = await httpClient.GetAsync(url); + if (responseMessage.IsSuccessStatusCode) + { + var responseString = await responseMessage.Content.ReadAsStringAsync(); + Console.WriteLine("Result: " + responseString); + } + else + { + throw new Exception("Remote server returns error code: " + responseMessage.StatusCode); + } + } + } + + /* Shows how to use HttpClient to perform a request to the HTTP API. + * It obtains access token using IdentityServer's API. See its documentation: + * https://identityserver4.readthedocs.io/en/latest/quickstarts/2_resource_owner_passwords.html + */ + private async Task TestAllManuallyAsync() + { + Console.WriteLine(); + Console.WriteLine($"***** {nameof(TestAllManuallyAsync)} *****"); + + //Obtain access token from the IDS4 server + + // discover endpoints from metadata + var client = new HttpClient(); + var disco = await client.GetDiscoveryDocumentAsync(_configuration["IdentityClients:Default:Authority"]); + if (disco.IsError) + { + Console.WriteLine(disco.Error); + return; + } + + // request token + var tokenResponse = await client.RequestPasswordTokenAsync(new PasswordTokenRequest + { + Address = disco.TokenEndpoint, + ClientId = _configuration["IdentityClients:Default:ClientId"], + ClientSecret = _configuration["IdentityClients:Default:ClientSecret"], + UserName = _configuration["IdentityClients:Default:UserName"], + Password = _configuration["IdentityClients:Default:UserPassword"], + Scope = _configuration["IdentityClients:Default:Scope"] + }); + + if (tokenResponse.IsError) + { + Console.WriteLine(tokenResponse.Error); + return; + } + + Console.WriteLine(tokenResponse.Json); + + //Perform the actual HTTP request + + using (var httpClient = new HttpClient()) + { + httpClient.SetBearerToken(tokenResponse.AccessToken); + + var url = _configuration["RemoteServices:ProductTag:BaseUrl"] + + "api/ProductTag/sample/authorized"; + + var responseMessage = await httpClient.GetAsync(url); + if (responseMessage.IsSuccessStatusCode) + { + var responseString = await responseMessage.Content.ReadAsStringAsync(); + Console.WriteLine("Result: " + responseString); + } + else + { + throw new Exception("Remote server returns error code: " + responseMessage.StatusCode); + } + } + } + } +} \ No newline at end of file diff --git a/plugins/ProductTag/test/EasyAbp.EShop.Plugins.ProductTag.HttpApi.Client.ConsoleTestApp/ConsoleTestAppHostedService.cs b/plugins/ProductTag/test/EasyAbp.EShop.Plugins.ProductTag.HttpApi.Client.ConsoleTestApp/ConsoleTestAppHostedService.cs new file mode 100644 index 00000000..06b96ffe --- /dev/null +++ b/plugins/ProductTag/test/EasyAbp.EShop.Plugins.ProductTag.HttpApi.Client.ConsoleTestApp/ConsoleTestAppHostedService.cs @@ -0,0 +1,26 @@ +using Microsoft.Extensions.Hosting; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp; + +namespace EasyAbp.EShop.Plugins.ProductTag.HttpApi.Client.ConsoleTestApp +{ + public class ConsoleTestAppHostedService : IHostedService + { + public async Task StartAsync(CancellationToken cancellationToken) + { + using (var application = AbpApplicationFactory.Create()) + { + application.Initialize(); + + var demo = application.ServiceProvider.GetRequiredService(); + await demo.RunAsync(); + + application.Shutdown(); + } + } + + public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask; + } +} diff --git a/plugins/ProductTag/test/EasyAbp.EShop.Plugins.ProductTag.HttpApi.Client.ConsoleTestApp/EasyAbp.EShop.Plugins.ProductTag.HttpApi.Client.ConsoleTestApp.csproj b/plugins/ProductTag/test/EasyAbp.EShop.Plugins.ProductTag.HttpApi.Client.ConsoleTestApp/EasyAbp.EShop.Plugins.ProductTag.HttpApi.Client.ConsoleTestApp.csproj new file mode 100644 index 00000000..99cf34c2 --- /dev/null +++ b/plugins/ProductTag/test/EasyAbp.EShop.Plugins.ProductTag.HttpApi.Client.ConsoleTestApp/EasyAbp.EShop.Plugins.ProductTag.HttpApi.Client.ConsoleTestApp.csproj @@ -0,0 +1,26 @@ + + + + Exe + netcoreapp3.1 + EasyAbp.EShop.Plugins.ProductTag + + + + + + + + + + + PreserveNewest + Always + + + + + + + + diff --git a/plugins/ProductTag/test/EasyAbp.EShop.Plugins.ProductTag.HttpApi.Client.ConsoleTestApp/ProductTagConsoleApiClientModule.cs b/plugins/ProductTag/test/EasyAbp.EShop.Plugins.ProductTag.HttpApi.Client.ConsoleTestApp/ProductTagConsoleApiClientModule.cs new file mode 100644 index 00000000..00c5cb52 --- /dev/null +++ b/plugins/ProductTag/test/EasyAbp.EShop.Plugins.ProductTag.HttpApi.Client.ConsoleTestApp/ProductTagConsoleApiClientModule.cs @@ -0,0 +1,14 @@ +using Volo.Abp.Http.Client.IdentityModel; +using Volo.Abp.Modularity; + +namespace EasyAbp.EShop.Plugins.ProductTag +{ + [DependsOn( + typeof(ProductTagHttpApiClientModule), + typeof(AbpHttpClientIdentityModelModule) + )] + public class ProductTagConsoleApiClientModule : AbpModule + { + + } +} diff --git a/plugins/ProductTag/test/EasyAbp.EShop.Plugins.ProductTag.HttpApi.Client.ConsoleTestApp/Program.cs b/plugins/ProductTag/test/EasyAbp.EShop.Plugins.ProductTag.HttpApi.Client.ConsoleTestApp/Program.cs new file mode 100644 index 00000000..282fb945 --- /dev/null +++ b/plugins/ProductTag/test/EasyAbp.EShop.Plugins.ProductTag.HttpApi.Client.ConsoleTestApp/Program.cs @@ -0,0 +1,21 @@ +using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; + +namespace EasyAbp.EShop.Plugins.ProductTag.HttpApi.Client.ConsoleTestApp +{ + class Program + { + static async Task Main(string[] args) + { + await CreateHostBuilder(args).RunConsoleAsync(); + } + + public static IHostBuilder CreateHostBuilder(string[] args) => + Host.CreateDefaultBuilder(args) + .ConfigureServices((hostContext, services) => + { + services.AddHostedService(); + }); + } +} diff --git a/plugins/ProductTag/test/EasyAbp.EShop.Plugins.ProductTag.HttpApi.Client.ConsoleTestApp/appsettings.json b/plugins/ProductTag/test/EasyAbp.EShop.Plugins.ProductTag.HttpApi.Client.ConsoleTestApp/appsettings.json new file mode 100644 index 00000000..220d40f5 --- /dev/null +++ b/plugins/ProductTag/test/EasyAbp.EShop.Plugins.ProductTag.HttpApi.Client.ConsoleTestApp/appsettings.json @@ -0,0 +1,21 @@ +{ + "RemoteServices": { + "Default": { + "BaseUrl": "https://localhost:44362/" + }, + "ProductTag": { + "BaseUrl": "https://localhost:44375/" + } + }, + "IdentityClients": { + "Default": { + "GrantType": "password", + "ClientId": "ProductTag_ConsoleTestApp", + "ClientSecret": "1q2w3e*", + "UserName": "admin", + "UserPassword": "1q2w3E*", + "Authority": "https://localhost:44362/", + "Scope": "ProductTag" + } + } +} \ No newline at end of file diff --git a/plugins/ProductTag/test/EasyAbp.EShop.Plugins.ProductTag.MongoDB.Tests/EasyAbp.EShop.Plugins.ProductTag.MongoDB.Tests.csproj b/plugins/ProductTag/test/EasyAbp.EShop.Plugins.ProductTag.MongoDB.Tests/EasyAbp.EShop.Plugins.ProductTag.MongoDB.Tests.csproj new file mode 100644 index 00000000..d0f972bf --- /dev/null +++ b/plugins/ProductTag/test/EasyAbp.EShop.Plugins.ProductTag.MongoDB.Tests/EasyAbp.EShop.Plugins.ProductTag.MongoDB.Tests.csproj @@ -0,0 +1,17 @@ + + + + + + netcoreapp3.1 + EasyAbp.EShop.Plugins.ProductTag + + + + + + + + + + diff --git a/plugins/ProductTag/test/EasyAbp.EShop.Plugins.ProductTag.MongoDB.Tests/MongoDB/MongoDbFixture.cs b/plugins/ProductTag/test/EasyAbp.EShop.Plugins.ProductTag.MongoDB.Tests/MongoDB/MongoDbFixture.cs new file mode 100644 index 00000000..7e1890b4 --- /dev/null +++ b/plugins/ProductTag/test/EasyAbp.EShop.Plugins.ProductTag.MongoDB.Tests/MongoDB/MongoDbFixture.cs @@ -0,0 +1,22 @@ +using System; +using Mongo2Go; + +namespace EasyAbp.EShop.Plugins.ProductTag.MongoDB +{ + public class MongoDbFixture : IDisposable + { + private static readonly MongoDbRunner MongoDbRunner; + public static readonly string ConnectionString; + + static MongoDbFixture() + { + MongoDbRunner = MongoDbRunner.Start(); + ConnectionString = MongoDbRunner.ConnectionString; + } + + public void Dispose() + { + MongoDbRunner?.Dispose(); + } + } +} diff --git a/plugins/ProductTag/test/EasyAbp.EShop.Plugins.ProductTag.MongoDB.Tests/MongoDB/MongoTestCollection.cs b/plugins/ProductTag/test/EasyAbp.EShop.Plugins.ProductTag.MongoDB.Tests/MongoDB/MongoTestCollection.cs new file mode 100644 index 00000000..5021a6fe --- /dev/null +++ b/plugins/ProductTag/test/EasyAbp.EShop.Plugins.ProductTag.MongoDB.Tests/MongoDB/MongoTestCollection.cs @@ -0,0 +1,10 @@ +using Xunit; + +namespace EasyAbp.EShop.Plugins.ProductTag.MongoDB +{ + [CollectionDefinition(Name)] + public class MongoTestCollection : ICollectionFixture + { + public const string Name = "MongoDB Collection"; + } +} \ No newline at end of file diff --git a/plugins/ProductTag/test/EasyAbp.EShop.Plugins.ProductTag.MongoDB.Tests/MongoDB/ProductTagMongoDbTestBase.cs b/plugins/ProductTag/test/EasyAbp.EShop.Plugins.ProductTag.MongoDB.Tests/MongoDB/ProductTagMongoDbTestBase.cs new file mode 100644 index 00000000..b4814cc2 --- /dev/null +++ b/plugins/ProductTag/test/EasyAbp.EShop.Plugins.ProductTag.MongoDB.Tests/MongoDB/ProductTagMongoDbTestBase.cs @@ -0,0 +1,10 @@ +namespace EasyAbp.EShop.Plugins.ProductTag.MongoDB +{ + /* This class can be used as a base class for MongoDB integration tests, + * while SampleRepository_Tests uses a different approach. + */ + public abstract class ProductTagMongoDbTestBase : ProductTagTestBase + { + + } +} \ No newline at end of file diff --git a/plugins/ProductTag/test/EasyAbp.EShop.Plugins.ProductTag.MongoDB.Tests/MongoDB/ProductTagMongoDbTestModule.cs b/plugins/ProductTag/test/EasyAbp.EShop.Plugins.ProductTag.MongoDB.Tests/MongoDB/ProductTagMongoDbTestModule.cs new file mode 100644 index 00000000..f77a5e40 --- /dev/null +++ b/plugins/ProductTag/test/EasyAbp.EShop.Plugins.ProductTag.MongoDB.Tests/MongoDB/ProductTagMongoDbTestModule.cs @@ -0,0 +1,25 @@ +using System; +using Volo.Abp.Data; +using Volo.Abp.Modularity; + +namespace EasyAbp.EShop.Plugins.ProductTag.MongoDB +{ + [DependsOn( + typeof(ProductTagTestBaseModule), + typeof(ProductTagMongoDbModule) + )] + public class ProductTagMongoDbTestModule : AbpModule + { + public override void ConfigureServices(ServiceConfigurationContext context) + { + var connectionString = MongoDbFixture.ConnectionString.EnsureEndsWith('/') + + "Db_" + + Guid.NewGuid().ToString("N"); + + Configure(options => + { + options.ConnectionStrings.Default = connectionString; + }); + } + } +} \ No newline at end of file diff --git a/plugins/ProductTag/test/EasyAbp.EShop.Plugins.ProductTag.MongoDB.Tests/MongoDB/Samples/SampleRepository_Tests.cs b/plugins/ProductTag/test/EasyAbp.EShop.Plugins.ProductTag.MongoDB.Tests/MongoDB/Samples/SampleRepository_Tests.cs new file mode 100644 index 00000000..0c1e9333 --- /dev/null +++ b/plugins/ProductTag/test/EasyAbp.EShop.Plugins.ProductTag.MongoDB.Tests/MongoDB/Samples/SampleRepository_Tests.cs @@ -0,0 +1,14 @@ +using EasyAbp.EShop.Plugins.ProductTag.Samples; +using Xunit; + +namespace EasyAbp.EShop.Plugins.ProductTag.MongoDB.Samples +{ + [Collection(MongoTestCollection.Name)] + public class SampleRepository_Tests : SampleRepository_Tests + { + /* Don't write custom repository tests here, instead write to + * the base class. + * One exception can be some specific tests related to MongoDB. + */ + } +} diff --git a/plugins/ProductTag/test/EasyAbp.EShop.Plugins.ProductTag.TestBase/EasyAbp.EShop.Plugins.ProductTag.TestBase.csproj b/plugins/ProductTag/test/EasyAbp.EShop.Plugins.ProductTag.TestBase/EasyAbp.EShop.Plugins.ProductTag.TestBase.csproj new file mode 100644 index 00000000..d8c26cfe --- /dev/null +++ b/plugins/ProductTag/test/EasyAbp.EShop.Plugins.ProductTag.TestBase/EasyAbp.EShop.Plugins.ProductTag.TestBase.csproj @@ -0,0 +1,23 @@ + + + + + + netcoreapp3.1 + EasyAbp.EShop.Plugins.ProductTag + + + + + + + + + + + + + + + + diff --git a/plugins/ProductTag/test/EasyAbp.EShop.Plugins.ProductTag.TestBase/ProductTagDataSeedContributor.cs b/plugins/ProductTag/test/EasyAbp.EShop.Plugins.ProductTag.TestBase/ProductTagDataSeedContributor.cs new file mode 100644 index 00000000..5ee6714a --- /dev/null +++ b/plugins/ProductTag/test/EasyAbp.EShop.Plugins.ProductTag.TestBase/ProductTagDataSeedContributor.cs @@ -0,0 +1,27 @@ +using System.Threading.Tasks; +using Volo.Abp.Data; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Guids; + +namespace EasyAbp.EShop.Plugins.ProductTag +{ + public class ProductTagDataSeedContributor : IDataSeedContributor, ITransientDependency + { + private readonly IGuidGenerator _guidGenerator; + + public ProductTagDataSeedContributor( + IGuidGenerator guidGenerator) + { + _guidGenerator = guidGenerator; + } + + public Task SeedAsync(DataSeedContext context) + { + /* Instead of returning the Task.CompletedTask, you can insert your test data + * at this point! + */ + + return Task.CompletedTask; + } + } +} \ No newline at end of file diff --git a/plugins/ProductTag/test/EasyAbp.EShop.Plugins.ProductTag.TestBase/ProductTagTestBase.cs b/plugins/ProductTag/test/EasyAbp.EShop.Plugins.ProductTag.TestBase/ProductTagTestBase.cs new file mode 100644 index 00000000..ffc27da7 --- /dev/null +++ b/plugins/ProductTag/test/EasyAbp.EShop.Plugins.ProductTag.TestBase/ProductTagTestBase.cs @@ -0,0 +1,60 @@ +using System; +using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp; +using Volo.Abp.Modularity; +using Volo.Abp.Uow; +using Volo.Abp.Testing; + +namespace EasyAbp.EShop.Plugins.ProductTag +{ + /* All test classes are derived from this class, directly or indirectly. */ + public abstract class ProductTagTestBase : AbpIntegratedTest + where TStartupModule : IAbpModule + { + protected override void SetAbpApplicationCreationOptions(AbpApplicationCreationOptions options) + { + options.UseAutofac(); + } + + protected virtual Task WithUnitOfWorkAsync(Func func) + { + return WithUnitOfWorkAsync(new AbpUnitOfWorkOptions(), func); + } + + protected virtual async Task WithUnitOfWorkAsync(AbpUnitOfWorkOptions options, Func action) + { + using (var scope = ServiceProvider.CreateScope()) + { + var uowManager = scope.ServiceProvider.GetRequiredService(); + + using (var uow = uowManager.Begin(options)) + { + await action(); + + await uow.CompleteAsync(); + } + } + } + + protected virtual Task WithUnitOfWorkAsync(Func> func) + { + return WithUnitOfWorkAsync(new AbpUnitOfWorkOptions(), func); + } + + protected virtual async Task WithUnitOfWorkAsync(AbpUnitOfWorkOptions options, Func> func) + { + using (var scope = ServiceProvider.CreateScope()) + { + var uowManager = scope.ServiceProvider.GetRequiredService(); + + using (var uow = uowManager.Begin(options)) + { + var result = await func(); + await uow.CompleteAsync(); + return result; + } + } + } + } +} diff --git a/plugins/ProductTag/test/EasyAbp.EShop.Plugins.ProductTag.TestBase/ProductTagTestBaseModule.cs b/plugins/ProductTag/test/EasyAbp.EShop.Plugins.ProductTag.TestBase/ProductTagTestBaseModule.cs new file mode 100644 index 00000000..f7c7e7a6 --- /dev/null +++ b/plugins/ProductTag/test/EasyAbp.EShop.Plugins.ProductTag.TestBase/ProductTagTestBaseModule.cs @@ -0,0 +1,42 @@ +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp; +using Volo.Abp.Authorization; +using Volo.Abp.Autofac; +using Volo.Abp.Data; +using Volo.Abp.Modularity; +using Volo.Abp.Threading; + +namespace EasyAbp.EShop.Plugins.ProductTag +{ + [DependsOn( + typeof(AbpAutofacModule), + typeof(AbpTestBaseModule), + typeof(AbpAuthorizationModule), + typeof(ProductTagDomainModule) + )] + public class ProductTagTestBaseModule : AbpModule + { + public override void ConfigureServices(ServiceConfigurationContext context) + { + context.Services.AddAlwaysAllowAuthorization(); + } + + public override void OnApplicationInitialization(ApplicationInitializationContext context) + { + SeedTestData(context); + } + + private static void SeedTestData(ApplicationInitializationContext context) + { + AsyncHelper.RunSync(async () => + { + using (var scope = context.ServiceProvider.CreateScope()) + { + await scope.ServiceProvider + .GetRequiredService() + .SeedAsync(); + } + }); + } + } +} diff --git a/plugins/ProductTag/test/EasyAbp.EShop.Plugins.ProductTag.TestBase/Samples/SampleRepository_Tests.cs b/plugins/ProductTag/test/EasyAbp.EShop.Plugins.ProductTag.TestBase/Samples/SampleRepository_Tests.cs new file mode 100644 index 00000000..f2eeae67 --- /dev/null +++ b/plugins/ProductTag/test/EasyAbp.EShop.Plugins.ProductTag.TestBase/Samples/SampleRepository_Tests.cs @@ -0,0 +1,27 @@ +using System.Threading.Tasks; +using Volo.Abp.Modularity; +using Xunit; + +namespace EasyAbp.EShop.Plugins.ProductTag.Samples +{ + /* Write your custom repository tests like that, in this project, as abstract classes. + * Then inherit these abstract classes from EF Core & MongoDB test projects. + * In this way, both database providers are tests with the same set tests. + */ + public abstract class SampleRepository_Tests : ProductTagTestBase + where TStartupModule : IAbpModule + { + //private readonly ISampleRepository _sampleRepository; + + protected SampleRepository_Tests() + { + //_sampleRepository = GetRequiredService(); + } + + [Fact] + public async Task Method1Async() + { + + } + } +} diff --git a/plugins/ProductTag/test/EasyAbp.EShop.Plugins.ProductTag.TestBase/Security/FakeCurrentPrincipalAccessor.cs b/plugins/ProductTag/test/EasyAbp.EShop.Plugins.ProductTag.TestBase/Security/FakeCurrentPrincipalAccessor.cs new file mode 100644 index 00000000..25bd2a26 --- /dev/null +++ b/plugins/ProductTag/test/EasyAbp.EShop.Plugins.ProductTag.TestBase/Security/FakeCurrentPrincipalAccessor.cs @@ -0,0 +1,43 @@ +using System.Collections.Generic; +using System.Security.Claims; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Security.Claims; + +namespace EasyAbp.EShop.Plugins.ProductTag.Security +{ + [Dependency(ReplaceServices = true)] + public class FakeCurrentPrincipalAccessor : ThreadCurrentPrincipalAccessor + { + protected override ClaimsPrincipal GetClaimsPrincipal() + { + return GetPrincipal(); + } + + private ClaimsPrincipal _principal; + + private ClaimsPrincipal GetPrincipal() + { + if (_principal == null) + { + lock (this) + { + if (_principal == null) + { + _principal = new ClaimsPrincipal( + new ClaimsIdentity( + new List + { + new Claim(AbpClaimTypes.UserId,"2e701e62-0953-4dd3-910b-dc6cc93ccb0d"), + new Claim(AbpClaimTypes.UserName,"admin"), + new Claim(AbpClaimTypes.Email,"admin@abp.io") + } + ) + ); + } + } + } + + return _principal; + } + } +}