init project
This commit is contained in:
commit
e1a9562b22
1346 changed files with 1138526 additions and 0 deletions
5
.gitignore
vendored
Normal file
5
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
configs/**/data/**
|
||||||
|
|
||||||
|
**/node_modules
|
||||||
|
**/.DS_Store
|
||||||
|
files/
|
||||||
700
My_workflow.json
Normal file
700
My_workflow.json
Normal file
File diff suppressed because one or more lines are too long
4
api/.dockerignore
Normal file
4
api/.dockerignore
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
**/bin
|
||||||
|
**/obj
|
||||||
|
bin/
|
||||||
|
obj/
|
||||||
147
api/.editorconfig
Normal file
147
api/.editorconfig
Normal file
|
|
@ -0,0 +1,147 @@
|
||||||
|
# To learn more about .editorconfig see https://aka.ms/editorconfigdocs
|
||||||
|
###############################
|
||||||
|
# Core EditorConfig Options #
|
||||||
|
###############################
|
||||||
|
root = true
|
||||||
|
# All files
|
||||||
|
[*]
|
||||||
|
indent_style = space
|
||||||
|
end_of_line = crlf
|
||||||
|
|
||||||
|
# XML project files
|
||||||
|
[*.{csproj,vbproj,vcxproj,vcxproj.filters,proj,projitems,shproj}]
|
||||||
|
indent_size = 2
|
||||||
|
|
||||||
|
# XML config files
|
||||||
|
[*.{props,targets,ruleset,config,nuspec,resx,vsixmanifest,vsct}]
|
||||||
|
indent_size = 2
|
||||||
|
|
||||||
|
# Code files
|
||||||
|
[*.{cs,csx,vb,vbx}]
|
||||||
|
indent_size = 4
|
||||||
|
insert_final_newline = true
|
||||||
|
charset = utf-8-bom
|
||||||
|
###############################
|
||||||
|
# .NET Coding Conventions #
|
||||||
|
###############################
|
||||||
|
[*.{cs,vb}]
|
||||||
|
# Organize usings
|
||||||
|
dotnet_sort_system_directives_first = true
|
||||||
|
# this. preferences
|
||||||
|
dotnet_style_qualification_for_field = false:silent
|
||||||
|
dotnet_style_qualification_for_property = false:silent
|
||||||
|
dotnet_style_qualification_for_method = false:silent
|
||||||
|
dotnet_style_qualification_for_event = false:silent
|
||||||
|
# Language keywords vs BCL types preferences
|
||||||
|
dotnet_style_predefined_type_for_locals_parameters_members = true:silent
|
||||||
|
dotnet_style_predefined_type_for_member_access = true:silent
|
||||||
|
# Parentheses preferences
|
||||||
|
dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:silent
|
||||||
|
dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:silent
|
||||||
|
dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:silent
|
||||||
|
dotnet_style_parentheses_in_other_operators = never_if_unnecessary:silent
|
||||||
|
# Modifier preferences
|
||||||
|
dotnet_style_require_accessibility_modifiers = for_non_interface_members:silent
|
||||||
|
dotnet_style_readonly_field = true:suggestion
|
||||||
|
# Expression-level preferences
|
||||||
|
dotnet_style_object_initializer = true:suggestion
|
||||||
|
dotnet_style_collection_initializer = true:suggestion
|
||||||
|
dotnet_style_explicit_tuple_names = true:suggestion
|
||||||
|
dotnet_style_null_propagation = true:suggestion
|
||||||
|
dotnet_style_coalesce_expression = true:suggestion
|
||||||
|
dotnet_style_prefer_is_null_check_over_reference_equality_method = true:silent
|
||||||
|
dotnet_style_prefer_inferred_tuple_names = true:suggestion
|
||||||
|
dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion
|
||||||
|
dotnet_style_prefer_auto_properties = true:silent
|
||||||
|
dotnet_style_prefer_conditional_expression_over_assignment = true:silent
|
||||||
|
dotnet_style_prefer_conditional_expression_over_return = true:silent
|
||||||
|
###############################
|
||||||
|
# Naming Conventions #
|
||||||
|
###############################
|
||||||
|
# Style Definitions
|
||||||
|
dotnet_naming_style.pascal_case_style.capitalization = pascal_case
|
||||||
|
# Use PascalCase for constant fields
|
||||||
|
dotnet_naming_rule.constant_fields_should_be_pascal_case.severity = suggestion
|
||||||
|
dotnet_naming_rule.constant_fields_should_be_pascal_case.symbols = constant_fields
|
||||||
|
dotnet_naming_rule.constant_fields_should_be_pascal_case.style = pascal_case_style
|
||||||
|
dotnet_naming_symbols.constant_fields.applicable_kinds = field
|
||||||
|
dotnet_naming_symbols.constant_fields.applicable_accessibilities = *
|
||||||
|
dotnet_naming_symbols.constant_fields.required_modifiers = const
|
||||||
|
dotnet_style_operator_placement_when_wrapping = beginning_of_line
|
||||||
|
tab_width = 4
|
||||||
|
end_of_line = crlf
|
||||||
|
dotnet_style_prefer_simplified_boolean_expressions = true:suggestion
|
||||||
|
dotnet_style_prefer_compound_assignment = true:suggestion
|
||||||
|
dotnet_style_prefer_simplified_interpolation = true:suggestion
|
||||||
|
dotnet_style_namespace_match_folder = true:suggestion
|
||||||
|
###############################
|
||||||
|
# C# Coding Conventions #
|
||||||
|
###############################
|
||||||
|
[*.cs]
|
||||||
|
# var preferences
|
||||||
|
csharp_style_var_for_built_in_types = true:silent
|
||||||
|
csharp_style_var_when_type_is_apparent = true:silent
|
||||||
|
csharp_style_var_elsewhere = true:silent
|
||||||
|
# Expression-bodied members
|
||||||
|
csharp_style_expression_bodied_methods = false:silent
|
||||||
|
csharp_style_expression_bodied_constructors = false:silent
|
||||||
|
csharp_style_expression_bodied_operators = false:silent
|
||||||
|
csharp_style_expression_bodied_properties = true:silent
|
||||||
|
csharp_style_expression_bodied_indexers = true:silent
|
||||||
|
csharp_style_expression_bodied_accessors = true:silent
|
||||||
|
# Pattern matching preferences
|
||||||
|
csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion
|
||||||
|
csharp_style_pattern_matching_over_as_with_null_check = true:suggestion
|
||||||
|
# Null-checking preferences
|
||||||
|
csharp_style_throw_expression = true:suggestion
|
||||||
|
csharp_style_conditional_delegate_call = true:suggestion
|
||||||
|
# Modifier preferences
|
||||||
|
csharp_preferred_modifier_order = public,private,protected,internal,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,volatile,async:suggestion
|
||||||
|
# Expression-level preferences
|
||||||
|
csharp_prefer_braces = true:silent
|
||||||
|
csharp_style_deconstructed_variable_declaration = true:suggestion
|
||||||
|
csharp_prefer_simple_default_expression = true:suggestion
|
||||||
|
csharp_style_pattern_local_over_anonymous_function = true:suggestion
|
||||||
|
csharp_style_inlined_variable_declaration = true:suggestion
|
||||||
|
###############################
|
||||||
|
# C# Formatting Rules #
|
||||||
|
###############################
|
||||||
|
# New line preferences
|
||||||
|
csharp_new_line_before_open_brace = all
|
||||||
|
csharp_new_line_before_else = true
|
||||||
|
csharp_new_line_before_catch = true
|
||||||
|
csharp_new_line_before_finally = true
|
||||||
|
csharp_new_line_before_members_in_object_initializers = true
|
||||||
|
csharp_new_line_before_members_in_anonymous_types = true
|
||||||
|
csharp_new_line_between_query_expression_clauses = true
|
||||||
|
# Indentation preferences
|
||||||
|
csharp_indent_case_contents = true
|
||||||
|
csharp_indent_switch_labels = true
|
||||||
|
csharp_indent_labels = flush_left
|
||||||
|
# Space preferences
|
||||||
|
csharp_space_after_cast = false
|
||||||
|
csharp_space_after_keywords_in_control_flow_statements = true
|
||||||
|
csharp_space_between_method_call_parameter_list_parentheses = false
|
||||||
|
csharp_space_between_method_declaration_parameter_list_parentheses = false
|
||||||
|
csharp_space_between_parentheses = false
|
||||||
|
csharp_space_before_colon_in_inheritance_clause = true
|
||||||
|
csharp_space_after_colon_in_inheritance_clause = true
|
||||||
|
csharp_space_around_binary_operators = before_and_after
|
||||||
|
csharp_space_between_method_declaration_empty_parameter_list_parentheses = false
|
||||||
|
csharp_space_between_method_call_name_and_opening_parenthesis = false
|
||||||
|
csharp_space_between_method_call_empty_parameter_list_parentheses = false
|
||||||
|
# Wrapping preferences
|
||||||
|
csharp_preserve_single_line_statements = true
|
||||||
|
csharp_preserve_single_line_blocks = true
|
||||||
|
csharp_using_directive_placement = outside_namespace:silent
|
||||||
|
csharp_prefer_simple_using_statement = true:suggestion
|
||||||
|
csharp_style_namespace_declarations = block_scoped:silent
|
||||||
|
csharp_style_prefer_method_group_conversion = true:silent
|
||||||
|
csharp_style_expression_bodied_lambdas = true:silent
|
||||||
|
csharp_style_expression_bodied_local_functions = false:silent
|
||||||
|
###############################
|
||||||
|
# VB Coding Conventions #
|
||||||
|
###############################
|
||||||
|
[*.vb]
|
||||||
|
# Modifier preferences
|
||||||
|
visual_basic_preferred_modifier_order = Partial,Default,Private,Protected,Public,Friend,NotOverridable,Overridable,MustOverride,Overloads,Overrides,MustInherit,NotInheritable,Static,Shared,Shadows,ReadOnly,WriteOnly,Dim,Const,WithEvents,Widening,Narrowing,Custom,Async:suggestion
|
||||||
1
api/.gitattributes
vendored
Normal file
1
api/.gitattributes
vendored
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
**/wwwroot/libs/** linguist-vendored
|
||||||
266
api/.gitignore
vendored
Normal file
266
api/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,266 @@
|
||||||
|
## 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
|
||||||
|
|
||||||
|
# Platform
|
||||||
|
src/Kurs.Platform.Web/Logs/*
|
||||||
|
src/Kurs.Platform.Web.Host/Logs/*
|
||||||
|
src/Kurs.Platform.AuthServer/Logs/*
|
||||||
|
src/Kurs.Platform.HttpApi.Host/Logs/*
|
||||||
|
src/Kurs.Platform.HttpApi.Host/Logs/*
|
||||||
|
src/Kurs.Platform.DbMigrator/Logs/*
|
||||||
|
src/Kurs.Platform.Blazor.Server/Logs/*
|
||||||
|
src/Kurs.Platform.Blazor.Server.Tiered/Logs/*
|
||||||
|
|
||||||
|
# Use abp install-libs to restore.
|
||||||
|
**/wwwroot/libs/*
|
||||||
|
*appsettings.development.json
|
||||||
5
api/.prettierrc
Normal file
5
api/.prettierrc
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"singleQuote": true,
|
||||||
|
"useTabs": false,
|
||||||
|
"tabWidth": 4
|
||||||
|
}
|
||||||
46
api/Kurs.Platform.DbMigrator.Dockerfile
Normal file
46
api/Kurs.Platform.DbMigrator.Dockerfile
Normal file
|
|
@ -0,0 +1,46 @@
|
||||||
|
FROM mcr.microsoft.com/dotnet/sdk:9.0-alpine AS build
|
||||||
|
ENV DOTNET_NUGET_SIGNATURE_VERIFICATION=false
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
COPY "modules/Kurs.Languages/Kurs.Languages.Application.Contracts/Kurs.Languages.Application.Contracts.csproj" "modules/Kurs.Languages/Kurs.Languages.Application.Contracts/"
|
||||||
|
COPY "modules/Kurs.Languages/Kurs.Languages.Domain/Kurs.Languages.Domain.csproj" "modules/Kurs.Languages/Kurs.Languages.Domain/"
|
||||||
|
COPY "modules/Kurs.Languages/Kurs.Languages.Domain.Shared/Kurs.Languages.Domain.Shared.csproj" "modules/Kurs.Languages/Kurs.Languages.Domain.Shared/"
|
||||||
|
COPY "modules/Kurs.Languages/Kurs.Languages.EntityFrameworkCore/Kurs.Languages.EntityFrameworkCore.csproj" "modules/Kurs.Languages/Kurs.Languages.EntityFrameworkCore/"
|
||||||
|
COPY "modules/Kurs.MailQueue/Kurs.MailQueue.csproj" "modules/Kurs.MailQueue/"
|
||||||
|
COPY "modules/Kurs.Notifications/Kurs.Notifications.Application.Contracts/Kurs.Notifications.Application.Contracts.csproj" "modules/Kurs.Notifications/Kurs.Notifications.Application.Contracts/"
|
||||||
|
COPY "modules/Kurs.Notifications/Kurs.Notifications.Domain/Kurs.Notifications.Domain.csproj" "modules/Kurs.Notifications/Kurs.Notifications.Domain/"
|
||||||
|
COPY "modules/Kurs.Notifications/Kurs.Notifications.Domain.Shared/Kurs.Notifications.Domain.Shared.csproj" "modules/Kurs.Notifications/Kurs.Notifications.Domain.Shared/"
|
||||||
|
COPY "modules/Kurs.Notifications/Kurs.Notifications.EntityFrameworkCore/Kurs.Notifications.EntityFrameworkCore.csproj" "modules/Kurs.Notifications/Kurs.Notifications.EntityFrameworkCore/"
|
||||||
|
COPY "modules/Kurs.Sender/Kurs.Sender.csproj" "modules/Kurs.Sender/"
|
||||||
|
COPY "modules/Kurs.Settings/Kurs.Settings.Application.Contracts/Kurs.Settings.Application.Contracts.csproj" "modules/Kurs.Settings/Kurs.Settings.Application.Contracts/"
|
||||||
|
COPY "modules/Kurs.Settings/Kurs.Settings.Domain/Kurs.Settings.Domain.csproj" "modules/Kurs.Settings/Kurs.Settings.Domain/"
|
||||||
|
COPY "modules/Kurs.Settings/Kurs.Settings.Domain.Shared/Kurs.Settings.Domain.Shared.csproj" "modules/Kurs.Settings/Kurs.Settings.Domain.Shared/"
|
||||||
|
COPY "modules/Kurs.Settings/Kurs.Settings.EntityFrameworkCore/Kurs.Settings.EntityFrameworkCore.csproj" "modules/Kurs.Settings/Kurs.Settings.EntityFrameworkCore/"
|
||||||
|
COPY "src/Kurs.Platform.Application.Contracts/Kurs.Platform.Application.Contracts.csproj" "src/Kurs.Platform.Application.Contracts/"
|
||||||
|
COPY "src/Kurs.Platform.DbMigrator/Kurs.Platform.DbMigrator.csproj" "src/Kurs.Platform.DbMigrator/"
|
||||||
|
COPY "src/Kurs.Platform.Domain/Kurs.Platform.Domain.csproj" "src/Kurs.Platform.Domain/"
|
||||||
|
COPY "src/Kurs.Platform.Domain.Shared/Kurs.Platform.Domain.Shared.csproj" "src/Kurs.Platform.Domain.Shared/"
|
||||||
|
COPY "src/Kurs.Platform.EntityFrameworkCore/Kurs.Platform.EntityFrameworkCore.csproj" "src/Kurs.Platform.EntityFrameworkCore/"
|
||||||
|
RUN dotnet restore "src/Kurs.Platform.DbMigrator/Kurs.Platform.DbMigrator.csproj"
|
||||||
|
|
||||||
|
COPY . .
|
||||||
|
RUN dotnet publish "src/Kurs.Platform.DbMigrator/Kurs.Platform.DbMigrator.csproj" -c Release -o /app/publish --no-restore
|
||||||
|
|
||||||
|
FROM mcr.microsoft.com/dotnet/aspnet:9.0-alpine AS final
|
||||||
|
ENV DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=false \
|
||||||
|
LC_ALL=tr_TR.UTF-8 \
|
||||||
|
LANG=tr_TR.UTF-8
|
||||||
|
|
||||||
|
# icu'lar dotnet culture icin gerekli
|
||||||
|
# lib'ler wkhtmltopdf icin gerekli
|
||||||
|
RUN apk update
|
||||||
|
RUN apk add --no-cache \
|
||||||
|
icu-data-full \
|
||||||
|
icu-libs \
|
||||||
|
libgdiplus \
|
||||||
|
libc6-compat \
|
||||||
|
libc-dev
|
||||||
|
|
||||||
|
WORKDIR /srv/app
|
||||||
|
COPY --from=build /app/publish .
|
||||||
|
ENTRYPOINT ["./Kurs.Platform.DbMigrator"]
|
||||||
75
api/Kurs.Platform.HttpApi.Host.Dockerfile
Normal file
75
api/Kurs.Platform.HttpApi.Host.Dockerfile
Normal file
|
|
@ -0,0 +1,75 @@
|
||||||
|
FROM mcr.microsoft.com/dotnet/sdk:9.0-alpine AS build
|
||||||
|
ENV DOTNET_NUGET_SIGNATURE_VERIFICATION=false
|
||||||
|
WORKDIR /app
|
||||||
|
RUN apk update && apk upgrade
|
||||||
|
RUN apk add nodejs~=22 npm~=10
|
||||||
|
|
||||||
|
RUN dotnet tool install -g Volo.Abp.Cli
|
||||||
|
ENV PATH="/root/.dotnet/tools:${PATH}"
|
||||||
|
COPY "src/Kurs.Platform.HttpApi.Host/Kurs.Platform.HttpApi.Host.csproj" "src/Kurs.Platform.HttpApi.Host/"
|
||||||
|
COPY "src/Kurs.Platform.HttpApi.Host/package.json" "src/Kurs.Platform.HttpApi.Host/"
|
||||||
|
COPY "src/Kurs.Platform.HttpApi.Host/package-lock.json" "src/Kurs.Platform.HttpApi.Host/"
|
||||||
|
WORKDIR /app/src/Kurs.Platform.HttpApi.Host
|
||||||
|
RUN abp install-libs
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
COPY "modules/Kurs.Languages/Kurs.Languages.Application/Kurs.Languages.Application.csproj" "modules/Kurs.Languages/Kurs.Languages.Application/"
|
||||||
|
COPY "modules/Kurs.Languages/Kurs.Languages.Application.Contracts/Kurs.Languages.Application.Contracts.csproj" "modules/Kurs.Languages/Kurs.Languages.Application.Contracts/"
|
||||||
|
COPY "modules/Kurs.Languages/Kurs.Languages.Domain/Kurs.Languages.Domain.csproj" "modules/Kurs.Languages/Kurs.Languages.Domain/"
|
||||||
|
COPY "modules/Kurs.Languages/Kurs.Languages.Domain.Shared/Kurs.Languages.Domain.Shared.csproj" "modules/Kurs.Languages/Kurs.Languages.Domain.Shared/"
|
||||||
|
COPY "modules/Kurs.Languages/Kurs.Languages.EntityFrameworkCore/Kurs.Languages.EntityFrameworkCore.csproj" "modules/Kurs.Languages/Kurs.Languages.EntityFrameworkCore/"
|
||||||
|
COPY "modules/Kurs.MailQueue/Kurs.MailQueue.csproj" "modules/Kurs.MailQueue/"
|
||||||
|
COPY "modules/Kurs.Notifications/Kurs.Notifications.Application/Kurs.Notifications.Application.csproj" "modules/Kurs.Notifications/Kurs.Notifications.Application/"
|
||||||
|
COPY "modules/Kurs.Notifications/Kurs.Notifications.Application.Contracts/Kurs.Notifications.Application.Contracts.csproj" "modules/Kurs.Notifications/Kurs.Notifications.Application.Contracts/"
|
||||||
|
COPY "modules/Kurs.Notifications/Kurs.Notifications.Domain/Kurs.Notifications.Domain.csproj" "modules/Kurs.Notifications/Kurs.Notifications.Domain/"
|
||||||
|
COPY "modules/Kurs.Notifications/Kurs.Notifications.Domain.Shared/Kurs.Notifications.Domain.Shared.csproj" "modules/Kurs.Notifications/Kurs.Notifications.Domain.Shared/"
|
||||||
|
COPY "modules/Kurs.Notifications/Kurs.Notifications.EntityFrameworkCore/Kurs.Notifications.EntityFrameworkCore.csproj" "modules/Kurs.Notifications/Kurs.Notifications.EntityFrameworkCore/"
|
||||||
|
COPY "modules/Kurs.Sender/Kurs.Sender.csproj" "modules/Kurs.Sender/"
|
||||||
|
COPY "modules/Kurs.Settings/Kurs.Settings.Application/Kurs.Settings.Application.csproj" "modules/Kurs.Settings/Kurs.Settings.Application/"
|
||||||
|
COPY "modules/Kurs.Settings/Kurs.Settings.Application.Contracts/Kurs.Settings.Application.Contracts.csproj" "modules/Kurs.Settings/Kurs.Settings.Application.Contracts/"
|
||||||
|
COPY "modules/Kurs.Settings/Kurs.Settings.Domain/Kurs.Settings.Domain.csproj" "modules/Kurs.Settings/Kurs.Settings.Domain/"
|
||||||
|
COPY "modules/Kurs.Settings/Kurs.Settings.Domain.Shared/Kurs.Settings.Domain.Shared.csproj" "modules/Kurs.Settings/Kurs.Settings.Domain.Shared/"
|
||||||
|
COPY "modules/Kurs.Settings/Kurs.Settings.EntityFrameworkCore/Kurs.Settings.EntityFrameworkCore.csproj" "modules/Kurs.Settings/Kurs.Settings.EntityFrameworkCore/"
|
||||||
|
COPY "src/Kurs.Platform.Application/Kurs.Platform.Application.csproj" "src/Kurs.Platform.Application/"
|
||||||
|
COPY "src/Kurs.Platform.Application.Contracts/Kurs.Platform.Application.Contracts.csproj" "src/Kurs.Platform.Application.Contracts/"
|
||||||
|
COPY "src/Kurs.Platform.Domain/Kurs.Platform.Domain.csproj" "src/Kurs.Platform.Domain/"
|
||||||
|
COPY "src/Kurs.Platform.Domain.Shared/Kurs.Platform.Domain.Shared.csproj" "src/Kurs.Platform.Domain.Shared/"
|
||||||
|
COPY "src/Kurs.Platform.EntityFrameworkCore/Kurs.Platform.EntityFrameworkCore.csproj" "src/Kurs.Platform.EntityFrameworkCore/"
|
||||||
|
COPY "src/Kurs.Platform.HttpApi/Kurs.Platform.HttpApi.csproj" "src/Kurs.Platform.HttpApi/"
|
||||||
|
COPY "src/Kurs.Platform.HttpApi.Client/Kurs.Platform.HttpApi.Client.csproj" "src/Kurs.Platform.HttpApi.Client/"
|
||||||
|
COPY "src/Kurs.Platform.HttpApi.Host/Kurs.Platform.HttpApi.Host.csproj" "src/Kurs.Platform.HttpApi.Host/"
|
||||||
|
COPY "test/Kurs.Platform.EntityFrameworkCore.Tests/Kurs.Platform.EntityFrameworkCore.Tests.csproj" "test/Kurs.Platform.EntityFrameworkCore.Tests/"
|
||||||
|
COPY "test/Kurs.Platform.TestBase/Kurs.Platform.TestBase.csproj" "test/Kurs.Platform.TestBase/"
|
||||||
|
RUN dotnet restore "src/Kurs.Platform.HttpApi.Host/Kurs.Platform.HttpApi.Host.csproj"
|
||||||
|
|
||||||
|
COPY . .
|
||||||
|
RUN mkdir -p publish
|
||||||
|
RUN dotnet publish "src/Kurs.Platform.HttpApi.Host/Kurs.Platform.HttpApi.Host.csproj" -c Release -o /app/publish --no-restore
|
||||||
|
|
||||||
|
FROM mcr.microsoft.com/dotnet/aspnet:9.0-alpine AS final
|
||||||
|
ENV DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=false \
|
||||||
|
LC_ALL=tr_TR.UTF-8 \
|
||||||
|
LANG=tr_TR.UTF-8
|
||||||
|
|
||||||
|
# icu'lar dotnet culture icin gerekli
|
||||||
|
# lib'ler wkhtmltopdf icin gerekli
|
||||||
|
RUN apk update
|
||||||
|
RUN apk add --no-cache \
|
||||||
|
icu-data-full \
|
||||||
|
icu-libs \
|
||||||
|
libgdiplus \
|
||||||
|
libc6-compat \
|
||||||
|
libc-dev
|
||||||
|
|
||||||
|
# OpenSSL default TLSv3 desteklediği için MSSQL 2012'ye bağlanmıyor. Bunu çözmek için gerekli
|
||||||
|
RUN sed -i 's/\[openssl_init\]/# [openssl_init]/' /etc/ssl/openssl.cnf
|
||||||
|
RUN printf "\n\n[openssl_init]\nssl_conf = ssl_sect" >> /etc/ssl/openssl.cnf
|
||||||
|
RUN printf "\n\n[ssl_sect]\nsystem_default = ssl_default_sect" >> /etc/ssl/openssl.cnf
|
||||||
|
RUN printf "\n\n[ssl_default_sect]\nMinProtocol = TLSv1\nCipherString = DEFAULT@SECLEVEL=0\n" >> /etc/ssl/openssl.cnf
|
||||||
|
|
||||||
|
EXPOSE 80
|
||||||
|
EXPOSE 443
|
||||||
|
|
||||||
|
WORKDIR /srv/app
|
||||||
|
COPY --from=build /app/publish .
|
||||||
|
ENTRYPOINT ["./Kurs.Platform.HttpApi.Host"]
|
||||||
243
api/Kurs.Platform.sln
Normal file
243
api/Kurs.Platform.sln
Normal file
|
|
@ -0,0 +1,243 @@
|
||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
|
# Visual Studio Version 17
|
||||||
|
VisualStudioVersion = 17.4.33213.308
|
||||||
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Kurs.Platform.Domain", "src\Kurs.Platform.Domain\Kurs.Platform.Domain.csproj", "{554AD327-6DBA-4F8F-96F8-81CE7A0C863F}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Kurs.Platform.Application", "src\Kurs.Platform.Application\Kurs.Platform.Application.csproj", "{1A94A50E-06DC-43C1-80B5-B662820EC3EB}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Kurs.Platform.EntityFrameworkCore", "src\Kurs.Platform.EntityFrameworkCore\Kurs.Platform.EntityFrameworkCore.csproj", "{C956DD76-69C8-4A9C-83EA-D17DF83340FD}"
|
||||||
|
EndProject
|
||||||
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{CA9AC87F-097E-4F15-8393-4BC07735A5B0}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Kurs.Platform.Domain.Shared", "src\Kurs.Platform.Domain.Shared\Kurs.Platform.Domain.Shared.csproj", "{42F719ED-8413-4895-B5B4-5AB56079BC66}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Kurs.Platform.Application.Contracts", "src\Kurs.Platform.Application.Contracts\Kurs.Platform.Application.Contracts.csproj", "{520659C8-C734-4298-A3DA-B539DB9DFC0B}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Kurs.Platform.HttpApi", "src\Kurs.Platform.HttpApi\Kurs.Platform.HttpApi.csproj", "{4164BDF7-F527-4E85-9CE6-E3C2D7426A27}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Kurs.Platform.HttpApi.Client", "src\Kurs.Platform.HttpApi.Client\Kurs.Platform.HttpApi.Client.csproj", "{3B5A0094-670D-4BB1-BFDD-61B88A8773DC}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Kurs.Platform.DbMigrator", "src\Kurs.Platform.DbMigrator\Kurs.Platform.DbMigrator.csproj", "{AA94D832-1CCC-4715-95A9-A483F23A1A5D}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Kurs.Platform.HttpApi.Host", "src\Kurs.Platform.HttpApi.Host\Kurs.Platform.HttpApi.Host.csproj", "{748584B1-BA69-4F6A-81AA-F4BDE6BCE29D}"
|
||||||
|
EndProject
|
||||||
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "modules", "modules", "{03E1C8DA-035E-4882-AF81-F392139FCF38}"
|
||||||
|
EndProject
|
||||||
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Kurs.Sender", "Kurs.Sender", "{4D886EEF-D4CF-4879-A10D-249D762E4ED9}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Kurs.Sender", "modules\Kurs.Sender\Kurs.Sender.csproj", "{21B52B6A-FC09-4EDA-8A73-9516726BF50B}"
|
||||||
|
EndProject
|
||||||
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Kurs.Languages", "Kurs.Languages", "{3B18248C-EE9C-43ED-9025-D3A78986EA7D}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Kurs.Languages.Application", "modules\Kurs.Languages\Kurs.Languages.Application\Kurs.Languages.Application.csproj", "{E9D256F2-B12F-4A90-8CF6-B52724716A94}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Kurs.Languages.Application.Contracts", "modules\Kurs.Languages\Kurs.Languages.Application.Contracts\Kurs.Languages.Application.Contracts.csproj", "{F1EC497F-D361-4927-AFE6-156A0F7D8A1C}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Kurs.Languages.Domain", "modules\Kurs.Languages\Kurs.Languages.Domain\Kurs.Languages.Domain.csproj", "{9020ECD8-81D6-4604-A379-260796918C28}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Kurs.Languages.Domain.Shared", "modules\Kurs.Languages\Kurs.Languages.Domain.Shared\Kurs.Languages.Domain.Shared.csproj", "{A3933E06-9DFE-480D-85C4-66F28F076164}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Kurs.Languages.EntityFrameworkCore", "modules\Kurs.Languages\Kurs.Languages.EntityFrameworkCore\Kurs.Languages.EntityFrameworkCore.csproj", "{556AC2C2-9765-4B3D-8F38-9EAF3DA61AC5}"
|
||||||
|
EndProject
|
||||||
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Kurs.Settings", "Kurs.Settings", "{4D880243-0276-49A9-9FF2-FAD8BA727F74}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Kurs.Settings.Application", "modules\Kurs.Settings\Kurs.Settings.Application\Kurs.Settings.Application.csproj", "{5F288ACC-A9CF-470B-BB68-B1C8B102CDDD}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Kurs.Settings.Application.Contracts", "modules\Kurs.Settings\Kurs.Settings.Application.Contracts\Kurs.Settings.Application.Contracts.csproj", "{A926F04F-631B-4A05-853C-6C76555BF26A}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Kurs.Settings.Domain", "modules\Kurs.Settings\Kurs.Settings.Domain\Kurs.Settings.Domain.csproj", "{E14E0128-D4FF-462D-B684-7238EA876D69}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Kurs.Settings.Domain.Shared", "modules\Kurs.Settings\Kurs.Settings.Domain.Shared\Kurs.Settings.Domain.Shared.csproj", "{DBFD0F4B-5592-4E34-8624-04F7540E34B9}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Kurs.Settings.EntityFrameworkCore", "modules\Kurs.Settings\Kurs.Settings.EntityFrameworkCore\Kurs.Settings.EntityFrameworkCore.csproj", "{C2F5630E-A6E2-48D5-B182-5FE9278D3E37}"
|
||||||
|
EndProject
|
||||||
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{62A235F3-B95E-4CB4-B59E-AAE30A0E6C5B}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Kurs.Platform.TestBase", "test\Kurs.Platform.TestBase\Kurs.Platform.TestBase.csproj", "{3E13749E-82D1-434B-B867-F7B094B66065}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Kurs.Platform.EntityFrameworkCore.Tests", "test\Kurs.Platform.EntityFrameworkCore.Tests\Kurs.Platform.EntityFrameworkCore.Tests.csproj", "{620D9F08-EB9F-469F-806A-64E915437154}"
|
||||||
|
EndProject
|
||||||
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Kurs.MailQueue", "Kurs.MailQueue", "{70BCE3C5-D122-4EF8-97EC-DB804AEE92D5}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Kurs.MailQueue", "modules\Kurs.MailQueue\Kurs.MailQueue.csproj", "{088B3139-68D3-4A5F-B159-0C8FE94CD969}"
|
||||||
|
EndProject
|
||||||
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Kurs.Notifications", "Kurs.Notifications", "{41A473FE-2537-4223-8CF3-A4A2A4A4F41E}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Kurs.Notifications.Application", "modules\Kurs.Notifications\Kurs.Notifications.Application\Kurs.Notifications.Application.csproj", "{A972109D-D974-4BB2-BA01-72BD845ACBBA}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Kurs.Notifications.Application.Contracts", "modules\Kurs.Notifications\Kurs.Notifications.Application.Contracts\Kurs.Notifications.Application.Contracts.csproj", "{297B7268-DEF3-4669-98DF-78FA08619EDF}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Kurs.Notifications.Domain", "modules\Kurs.Notifications\Kurs.Notifications.Domain\Kurs.Notifications.Domain.csproj", "{631092C7-B59D-4EA7-92D0-5E181AB4F9F6}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Kurs.Notifications.Domain.Shared", "modules\Kurs.Notifications\Kurs.Notifications.Domain.Shared\Kurs.Notifications.Domain.Shared.csproj", "{23659070-58F7-403B-8973-B2E20B5E9BE1}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Kurs.Notifications.EntityFrameworkCore", "modules\Kurs.Notifications\Kurs.Notifications.EntityFrameworkCore\Kurs.Notifications.EntityFrameworkCore.csproj", "{D9E0D333-60F3-493F-A5B2-5758ACA42A17}"
|
||||||
|
EndProject
|
||||||
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{722BAAEF-70B8-4381-A8AD-7F2C205D2D0A}"
|
||||||
|
ProjectSection(SolutionItems) = preProject
|
||||||
|
README.md = README.md
|
||||||
|
EndProjectSection
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
Release|Any CPU = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{554AD327-6DBA-4F8F-96F8-81CE7A0C863F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{554AD327-6DBA-4F8F-96F8-81CE7A0C863F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{554AD327-6DBA-4F8F-96F8-81CE7A0C863F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{554AD327-6DBA-4F8F-96F8-81CE7A0C863F}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{1A94A50E-06DC-43C1-80B5-B662820EC3EB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{1A94A50E-06DC-43C1-80B5-B662820EC3EB}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{1A94A50E-06DC-43C1-80B5-B662820EC3EB}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{1A94A50E-06DC-43C1-80B5-B662820EC3EB}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{C956DD76-69C8-4A9C-83EA-D17DF83340FD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{C956DD76-69C8-4A9C-83EA-D17DF83340FD}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{C956DD76-69C8-4A9C-83EA-D17DF83340FD}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{C956DD76-69C8-4A9C-83EA-D17DF83340FD}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{42F719ED-8413-4895-B5B4-5AB56079BC66}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{42F719ED-8413-4895-B5B4-5AB56079BC66}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{42F719ED-8413-4895-B5B4-5AB56079BC66}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{42F719ED-8413-4895-B5B4-5AB56079BC66}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{520659C8-C734-4298-A3DA-B539DB9DFC0B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{520659C8-C734-4298-A3DA-B539DB9DFC0B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{520659C8-C734-4298-A3DA-B539DB9DFC0B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{520659C8-C734-4298-A3DA-B539DB9DFC0B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{4164BDF7-F527-4E85-9CE6-E3C2D7426A27}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{4164BDF7-F527-4E85-9CE6-E3C2D7426A27}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{4164BDF7-F527-4E85-9CE6-E3C2D7426A27}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{4164BDF7-F527-4E85-9CE6-E3C2D7426A27}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{3B5A0094-670D-4BB1-BFDD-61B88A8773DC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{3B5A0094-670D-4BB1-BFDD-61B88A8773DC}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{3B5A0094-670D-4BB1-BFDD-61B88A8773DC}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{3B5A0094-670D-4BB1-BFDD-61B88A8773DC}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{AA94D832-1CCC-4715-95A9-A483F23A1A5D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{AA94D832-1CCC-4715-95A9-A483F23A1A5D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{AA94D832-1CCC-4715-95A9-A483F23A1A5D}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{AA94D832-1CCC-4715-95A9-A483F23A1A5D}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{748584B1-BA69-4F6A-81AA-F4BDE6BCE29D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{748584B1-BA69-4F6A-81AA-F4BDE6BCE29D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{748584B1-BA69-4F6A-81AA-F4BDE6BCE29D}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{748584B1-BA69-4F6A-81AA-F4BDE6BCE29D}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{21B52B6A-FC09-4EDA-8A73-9516726BF50B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{21B52B6A-FC09-4EDA-8A73-9516726BF50B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{21B52B6A-FC09-4EDA-8A73-9516726BF50B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{21B52B6A-FC09-4EDA-8A73-9516726BF50B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{E9D256F2-B12F-4A90-8CF6-B52724716A94}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{E9D256F2-B12F-4A90-8CF6-B52724716A94}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{E9D256F2-B12F-4A90-8CF6-B52724716A94}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{E9D256F2-B12F-4A90-8CF6-B52724716A94}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{F1EC497F-D361-4927-AFE6-156A0F7D8A1C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{F1EC497F-D361-4927-AFE6-156A0F7D8A1C}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{F1EC497F-D361-4927-AFE6-156A0F7D8A1C}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{F1EC497F-D361-4927-AFE6-156A0F7D8A1C}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{9020ECD8-81D6-4604-A379-260796918C28}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{9020ECD8-81D6-4604-A379-260796918C28}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{9020ECD8-81D6-4604-A379-260796918C28}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{9020ECD8-81D6-4604-A379-260796918C28}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{A3933E06-9DFE-480D-85C4-66F28F076164}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{A3933E06-9DFE-480D-85C4-66F28F076164}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{A3933E06-9DFE-480D-85C4-66F28F076164}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{A3933E06-9DFE-480D-85C4-66F28F076164}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{556AC2C2-9765-4B3D-8F38-9EAF3DA61AC5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{556AC2C2-9765-4B3D-8F38-9EAF3DA61AC5}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{556AC2C2-9765-4B3D-8F38-9EAF3DA61AC5}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{556AC2C2-9765-4B3D-8F38-9EAF3DA61AC5}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{5F288ACC-A9CF-470B-BB68-B1C8B102CDDD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{5F288ACC-A9CF-470B-BB68-B1C8B102CDDD}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{5F288ACC-A9CF-470B-BB68-B1C8B102CDDD}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{5F288ACC-A9CF-470B-BB68-B1C8B102CDDD}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{A926F04F-631B-4A05-853C-6C76555BF26A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{A926F04F-631B-4A05-853C-6C76555BF26A}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{A926F04F-631B-4A05-853C-6C76555BF26A}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{A926F04F-631B-4A05-853C-6C76555BF26A}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{E14E0128-D4FF-462D-B684-7238EA876D69}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{E14E0128-D4FF-462D-B684-7238EA876D69}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{E14E0128-D4FF-462D-B684-7238EA876D69}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{E14E0128-D4FF-462D-B684-7238EA876D69}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{DBFD0F4B-5592-4E34-8624-04F7540E34B9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{DBFD0F4B-5592-4E34-8624-04F7540E34B9}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{DBFD0F4B-5592-4E34-8624-04F7540E34B9}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{DBFD0F4B-5592-4E34-8624-04F7540E34B9}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{C2F5630E-A6E2-48D5-B182-5FE9278D3E37}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{C2F5630E-A6E2-48D5-B182-5FE9278D3E37}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{C2F5630E-A6E2-48D5-B182-5FE9278D3E37}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{C2F5630E-A6E2-48D5-B182-5FE9278D3E37}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{3E13749E-82D1-434B-B867-F7B094B66065}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{3E13749E-82D1-434B-B867-F7B094B66065}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{3E13749E-82D1-434B-B867-F7B094B66065}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{3E13749E-82D1-434B-B867-F7B094B66065}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{620D9F08-EB9F-469F-806A-64E915437154}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{620D9F08-EB9F-469F-806A-64E915437154}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{620D9F08-EB9F-469F-806A-64E915437154}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{620D9F08-EB9F-469F-806A-64E915437154}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{088B3139-68D3-4A5F-B159-0C8FE94CD969}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{088B3139-68D3-4A5F-B159-0C8FE94CD969}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{088B3139-68D3-4A5F-B159-0C8FE94CD969}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{088B3139-68D3-4A5F-B159-0C8FE94CD969}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{A972109D-D974-4BB2-BA01-72BD845ACBBA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{A972109D-D974-4BB2-BA01-72BD845ACBBA}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{A972109D-D974-4BB2-BA01-72BD845ACBBA}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{A972109D-D974-4BB2-BA01-72BD845ACBBA}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{297B7268-DEF3-4669-98DF-78FA08619EDF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{297B7268-DEF3-4669-98DF-78FA08619EDF}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{297B7268-DEF3-4669-98DF-78FA08619EDF}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{297B7268-DEF3-4669-98DF-78FA08619EDF}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{631092C7-B59D-4EA7-92D0-5E181AB4F9F6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{631092C7-B59D-4EA7-92D0-5E181AB4F9F6}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{631092C7-B59D-4EA7-92D0-5E181AB4F9F6}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{631092C7-B59D-4EA7-92D0-5E181AB4F9F6}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{23659070-58F7-403B-8973-B2E20B5E9BE1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{23659070-58F7-403B-8973-B2E20B5E9BE1}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{23659070-58F7-403B-8973-B2E20B5E9BE1}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{23659070-58F7-403B-8973-B2E20B5E9BE1}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{D9E0D333-60F3-493F-A5B2-5758ACA42A17}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{D9E0D333-60F3-493F-A5B2-5758ACA42A17}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{D9E0D333-60F3-493F-A5B2-5758ACA42A17}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{D9E0D333-60F3-493F-A5B2-5758ACA42A17}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(NestedProjects) = preSolution
|
||||||
|
{554AD327-6DBA-4F8F-96F8-81CE7A0C863F} = {CA9AC87F-097E-4F15-8393-4BC07735A5B0}
|
||||||
|
{1A94A50E-06DC-43C1-80B5-B662820EC3EB} = {CA9AC87F-097E-4F15-8393-4BC07735A5B0}
|
||||||
|
{C956DD76-69C8-4A9C-83EA-D17DF83340FD} = {CA9AC87F-097E-4F15-8393-4BC07735A5B0}
|
||||||
|
{42F719ED-8413-4895-B5B4-5AB56079BC66} = {CA9AC87F-097E-4F15-8393-4BC07735A5B0}
|
||||||
|
{520659C8-C734-4298-A3DA-B539DB9DFC0B} = {CA9AC87F-097E-4F15-8393-4BC07735A5B0}
|
||||||
|
{4164BDF7-F527-4E85-9CE6-E3C2D7426A27} = {CA9AC87F-097E-4F15-8393-4BC07735A5B0}
|
||||||
|
{3B5A0094-670D-4BB1-BFDD-61B88A8773DC} = {CA9AC87F-097E-4F15-8393-4BC07735A5B0}
|
||||||
|
{AA94D832-1CCC-4715-95A9-A483F23A1A5D} = {CA9AC87F-097E-4F15-8393-4BC07735A5B0}
|
||||||
|
{748584B1-BA69-4F6A-81AA-F4BDE6BCE29D} = {CA9AC87F-097E-4F15-8393-4BC07735A5B0}
|
||||||
|
{4D886EEF-D4CF-4879-A10D-249D762E4ED9} = {03E1C8DA-035E-4882-AF81-F392139FCF38}
|
||||||
|
{21B52B6A-FC09-4EDA-8A73-9516726BF50B} = {4D886EEF-D4CF-4879-A10D-249D762E4ED9}
|
||||||
|
{3B18248C-EE9C-43ED-9025-D3A78986EA7D} = {03E1C8DA-035E-4882-AF81-F392139FCF38}
|
||||||
|
{E9D256F2-B12F-4A90-8CF6-B52724716A94} = {3B18248C-EE9C-43ED-9025-D3A78986EA7D}
|
||||||
|
{F1EC497F-D361-4927-AFE6-156A0F7D8A1C} = {3B18248C-EE9C-43ED-9025-D3A78986EA7D}
|
||||||
|
{9020ECD8-81D6-4604-A379-260796918C28} = {3B18248C-EE9C-43ED-9025-D3A78986EA7D}
|
||||||
|
{A3933E06-9DFE-480D-85C4-66F28F076164} = {3B18248C-EE9C-43ED-9025-D3A78986EA7D}
|
||||||
|
{556AC2C2-9765-4B3D-8F38-9EAF3DA61AC5} = {3B18248C-EE9C-43ED-9025-D3A78986EA7D}
|
||||||
|
{4D880243-0276-49A9-9FF2-FAD8BA727F74} = {03E1C8DA-035E-4882-AF81-F392139FCF38}
|
||||||
|
{5F288ACC-A9CF-470B-BB68-B1C8B102CDDD} = {4D880243-0276-49A9-9FF2-FAD8BA727F74}
|
||||||
|
{A926F04F-631B-4A05-853C-6C76555BF26A} = {4D880243-0276-49A9-9FF2-FAD8BA727F74}
|
||||||
|
{E14E0128-D4FF-462D-B684-7238EA876D69} = {4D880243-0276-49A9-9FF2-FAD8BA727F74}
|
||||||
|
{DBFD0F4B-5592-4E34-8624-04F7540E34B9} = {4D880243-0276-49A9-9FF2-FAD8BA727F74}
|
||||||
|
{C2F5630E-A6E2-48D5-B182-5FE9278D3E37} = {4D880243-0276-49A9-9FF2-FAD8BA727F74}
|
||||||
|
{3E13749E-82D1-434B-B867-F7B094B66065} = {62A235F3-B95E-4CB4-B59E-AAE30A0E6C5B}
|
||||||
|
{620D9F08-EB9F-469F-806A-64E915437154} = {62A235F3-B95E-4CB4-B59E-AAE30A0E6C5B}
|
||||||
|
{70BCE3C5-D122-4EF8-97EC-DB804AEE92D5} = {03E1C8DA-035E-4882-AF81-F392139FCF38}
|
||||||
|
{088B3139-68D3-4A5F-B159-0C8FE94CD969} = {70BCE3C5-D122-4EF8-97EC-DB804AEE92D5}
|
||||||
|
{41A473FE-2537-4223-8CF3-A4A2A4A4F41E} = {03E1C8DA-035E-4882-AF81-F392139FCF38}
|
||||||
|
{A972109D-D974-4BB2-BA01-72BD845ACBBA} = {41A473FE-2537-4223-8CF3-A4A2A4A4F41E}
|
||||||
|
{297B7268-DEF3-4669-98DF-78FA08619EDF} = {41A473FE-2537-4223-8CF3-A4A2A4A4F41E}
|
||||||
|
{631092C7-B59D-4EA7-92D0-5E181AB4F9F6} = {41A473FE-2537-4223-8CF3-A4A2A4A4F41E}
|
||||||
|
{23659070-58F7-403B-8973-B2E20B5E9BE1} = {41A473FE-2537-4223-8CF3-A4A2A4A4F41E}
|
||||||
|
{D9E0D333-60F3-493F-A5B2-5758ACA42A17} = {41A473FE-2537-4223-8CF3-A4A2A4A4F41E}
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
|
SolutionGuid = {28315BFD-90E7-4E14-A2EA-F3D23AF4126F}
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
||||||
23
api/Kurs.Platform.sln.DotSettings
Normal file
23
api/Kurs.Platform.sln.DotSettings
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
|
||||||
|
<s:Boolean x:Key="/Default/CodeEditing/Intellisense/CodeCompletion/IntelliSenseCompletingCharacters/CSharpCompletingCharacters/UpgradedFromVSSettings/@EntryValue">True</s:Boolean>
|
||||||
|
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=EnforceDoWhileStatementBraces/@EntryIndexedValue">WARNING</s:String>
|
||||||
|
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=EnforceFixedStatementBraces/@EntryIndexedValue">WARNING</s:String>
|
||||||
|
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=EnforceForeachStatementBraces/@EntryIndexedValue">WARNING</s:String>
|
||||||
|
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=EnforceForStatementBraces/@EntryIndexedValue">WARNING</s:String>
|
||||||
|
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=EnforceIfStatementBraces/@EntryIndexedValue">WARNING</s:String>
|
||||||
|
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=EnforceLockStatementBraces/@EntryIndexedValue">WARNING</s:String>
|
||||||
|
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=EnforceUsingStatementBraces/@EntryIndexedValue">WARNING</s:String>
|
||||||
|
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=EnforceWhileStatementBraces/@EntryIndexedValue">WARNING</s:String>
|
||||||
|
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/BRACES_FOR_FOR/@EntryValue">Required</s:String>
|
||||||
|
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/BRACES_FOR_FOREACH/@EntryValue">Required</s:String>
|
||||||
|
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/BRACES_FOR_IFELSE/@EntryValue">Required</s:String>
|
||||||
|
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/BRACES_FOR_WHILE/@EntryValue">Required</s:String>
|
||||||
|
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/BRACES_REDUNDANT/@EntryValue">False</s:Boolean>
|
||||||
|
<s:Boolean x:Key="/Default/CodeStyle/Generate/=Implementations/@KeyIndexDefined">True</s:Boolean>
|
||||||
|
<s:String x:Key="/Default/CodeStyle/Generate/=Implementations/Options/=Async/@EntryIndexedValue">False</s:String>
|
||||||
|
<s:String x:Key="/Default/CodeStyle/Generate/=Implementations/Options/=Mutable/@EntryIndexedValue">False</s:String>
|
||||||
|
<s:Boolean x:Key="/Default/CodeStyle/Generate/=Overrides/@KeyIndexDefined">True</s:Boolean>
|
||||||
|
<s:String x:Key="/Default/CodeStyle/Generate/=Overrides/Options/=Async/@EntryIndexedValue">False</s:String>
|
||||||
|
<s:String x:Key="/Default/CodeStyle/Generate/=Overrides/Options/=Mutable/@EntryIndexedValue">False</s:String>
|
||||||
|
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=SQL/@EntryIndexedValue">SQL</s:String>
|
||||||
|
</wpf:ResourceDictionary>
|
||||||
5
api/NuGet.Config
Normal file
5
api/NuGet.Config
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<configuration>
|
||||||
|
<packageSources>
|
||||||
|
</packageSources>
|
||||||
|
</configuration>
|
||||||
110
api/README.md
Normal file
110
api/README.md
Normal file
|
|
@ -0,0 +1,110 @@
|
||||||
|
# Yeni Modul Ekleme
|
||||||
|
|
||||||
|
`abp new Kurs.Notification -t module --no-ui -m none --database-provider ef --version 7.2.2 --old`
|
||||||
|
|
||||||
|
# Code Format
|
||||||
|
|
||||||
|
`dotnet format --include .\modules\Kurs.Notification\ --folder`
|
||||||
|
|
||||||
|
# Migrations
|
||||||
|
|
||||||
|
- Yeni migration ekleme
|
||||||
|
`EntityFrameworkCore projesine gir`
|
||||||
|
`dotnet ef migrations add ""`
|
||||||
|
`dotnet ef database update`
|
||||||
|
|
||||||
|
- Son migrationi siler ve snapshot revert eder
|
||||||
|
`dotnet ef migrations remove`
|
||||||
|
`dotnet ef database update "20240822114716_ABP_822"`
|
||||||
|
|
||||||
|
# Public Api
|
||||||
|
|
||||||
|
```
|
||||||
|
Token İsteği Örnek:
|
||||||
|
POST /connect/token HTTP/1.1
|
||||||
|
Host: localhost:44344
|
||||||
|
Content-Type: application/x-www-form-urlencoded
|
||||||
|
|
||||||
|
username=sedat%40kadifeteks.com
|
||||||
|
&password=...
|
||||||
|
&grant_type=password
|
||||||
|
&client_id=Platform_PublicApi
|
||||||
|
&scope=offline_access%20Platform
|
||||||
|
```
|
||||||
|
|
||||||
|
## Whatsapp Ayarları
|
||||||
|
|
||||||
|
- Normal facebook üyeliği yapılır.
|
||||||
|
- https://developers.facebook.com/ sitesinden yeni developer üyeliği oluşturulur. Developer üyeliği seçilir.
|
||||||
|
- CreateApp butonu ile yeni uygulama oluşturulur. Uygulama adı belirlenir. 'Sozsoft Messenger'
|
||||||
|
- AppType olarak İşletme seçilir ve App oluşturulur.
|
||||||
|
- Add Products kısmında WhatsApp seçilir ve Business Account oluşturulur.
|
||||||
|
- 3 noktadan (menüden) WhatsApp Manager sayfasına gidilir. Manage Templates seçilir, istenirse yeni template oluşturulur. 'hello_world'
|
||||||
|
- WhatsApp Manager üzerinde menüden Settings -> Users -> System Users eklenir. Kullanıcı adı 'admin' ve Role ise 'Admin' seçilir.
|
||||||
|
- Eklenen 'admin' kullanıcısında 'Assign Assets' seçilir ve full yetki verilir.
|
||||||
|
- admin kullanıcısı üzerinden 'Generate Token' seçilir ve aşağıdaki yetkiler verilir.
|
||||||
|
|
||||||
|
```
|
||||||
|
- whatsapp_business_management'
|
||||||
|
- 'whatsapp_business_messaging'
|
||||||
|
```
|
||||||
|
|
||||||
|
- WhatsApp -> API Setup kısmından "From" kısmında yeni telefon numarası eklenir.
|
||||||
|
- WhatsApp -> API Setup kısmından Generate Access Token oluşturulur.
|
||||||
|
|
||||||
|
- token: EAASM83pDJf0BO0ZCYBr3Fx4SES0ox8XiZCgP3FIteprYpwawZCkGYjpMlKk4OZCWgRNZC2Ttofgf8amMf929ZBuDcgYIOsXkPMGBNmVxm2czipzq63LmtbYfyCWsKVy0q1jtay0nRoeDuO2FKhqCfLLtNn9cSWjINVLcz26ptK8a2Oko83cZBzrNsp3cpIECnzqRfEjHdEz1U73y3ZB1MZBOhHilax7yZALf4ZA1Tmk
|
||||||
|
- WhatsApp telefon numarasını Register etmek için aşağıdaki postman Curl gönderilir.
|
||||||
|
|
||||||
|
```
|
||||||
|
curl --location 'https://graph.facebook.com/v21.0/521106361082067/register' \
|
||||||
|
--header 'Content-Type: application/json' \
|
||||||
|
--header 'Authorization: Bearer <access token>' \
|
||||||
|
--data '{
|
||||||
|
"messaging_product": "whatsapp",
|
||||||
|
"pin": "238567"
|
||||||
|
}'
|
||||||
|
```
|
||||||
|
|
||||||
|
- Message göndermek için url : https://graph.facebook.com/v21.0/521106361082067/messages
|
||||||
|
|
||||||
|
```
|
||||||
|
{
|
||||||
|
"messaging_product": "whatsapp",
|
||||||
|
"to": "{+gönderilecek gsm numarası}",
|
||||||
|
"type": "template",
|
||||||
|
"template": {
|
||||||
|
"name": "{message_template_name}",
|
||||||
|
"language": {
|
||||||
|
"code": "en"
|
||||||
|
},
|
||||||
|
"components": [
|
||||||
|
{
|
||||||
|
"type": "body",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"type": "text",
|
||||||
|
"text": "Test mesajı"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
# ABP Update
|
||||||
|
- https://abp.io/docs/latest/release-info/upgrading
|
||||||
|
- https://abp.io/docs/9.0/release-info/migration-guides/abp-9-0
|
||||||
|
- https://learn.microsoft.com/en-us/aspnet/core/migration/80-90?view=aspnetcore-9.0&tabs=visual-studio-code
|
||||||
|
- Adımlar:
|
||||||
|
- abp cli güncellenir dotnet tool update --global Volo.Abp.Cli
|
||||||
|
- abp update ile sln içindeki referanslar update edilir
|
||||||
|
- modules/ klasörü *.csproj içinde ara&düzenle ile update edilir (örn. 8.3.4 -> 9.0.2)
|
||||||
|
- .net sürümü arttıysa Microsoft'un dotnet upgrade dokümanı takip edilir
|
||||||
|
- Yeni dotnet sdk kurulumu yapılır (örn dotnet 9 sdk)
|
||||||
|
- ef tools güncellenir (dotnet tool update --global dotnet-ef)
|
||||||
|
- Dockerfile dosyalarındaki base imajlar yeni dotnet sürümüne güncellenir
|
||||||
|
- Abp upgrade dokümanı takip edilir
|
||||||
|
- Proje build olmuyorsa hatalar çözülür
|
||||||
|
- Yeni migration eklenir (varsa). Migration boş çıkıyorsa kaldırılır. (Örn dotnet ef migrations add Abp902 ve dotnet ef migrations remove)
|
||||||
|
- Migration boş değilse çalıştırılır (dotnet ef database update)
|
||||||
19
api/common.props
Normal file
19
api/common.props
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
<Project>
|
||||||
|
<PropertyGroup>
|
||||||
|
<LangVersion>latest</LangVersion>
|
||||||
|
<Version>1.0.0</Version>
|
||||||
|
<NoWarn>$(NoWarn);CS1591</NoWarn>
|
||||||
|
<AbpProjectType>app</AbpProjectType>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<Target Name="NoWarnOnRazorViewImportedTypeConflicts" BeforeTargets="RazorCoreCompile">
|
||||||
|
<PropertyGroup>
|
||||||
|
<NoWarn>$(NoWarn);0436</NoWarn>
|
||||||
|
</PropertyGroup>
|
||||||
|
</Target>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Content Remove="$(UserProfile)\.nuget\packages\*\*\contentFiles\any\*\*.abppkg*.json" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
6
api/global.json
Normal file
6
api/global.json
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
{
|
||||||
|
"sdk": {
|
||||||
|
"version": "9.0.101",
|
||||||
|
"rollForward": "latestMajor"
|
||||||
|
}
|
||||||
|
}
|
||||||
1
api/migrate-database.ps1
Normal file
1
api/migrate-database.ps1
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
dotnet run --project src/Kurs.Platform.DbMigrator
|
||||||
|
|
@ -0,0 +1,24 @@
|
||||||
|
using System;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using Volo.Abp.Application.Dtos;
|
||||||
|
|
||||||
|
namespace Kurs.Languages;
|
||||||
|
|
||||||
|
public class LanguageDto : FullAuditedEntityDto<Guid>
|
||||||
|
{
|
||||||
|
[Required]
|
||||||
|
public string CultureName { get; set; }
|
||||||
|
|
||||||
|
[Required]
|
||||||
|
public string UiCultureName { get; set; }
|
||||||
|
|
||||||
|
[Required]
|
||||||
|
public string DisplayName { get; set; }
|
||||||
|
|
||||||
|
[Required]
|
||||||
|
public bool IsEnabled { get; set; }
|
||||||
|
|
||||||
|
/// <summary> multiple select icin test amacli olarak eklendi
|
||||||
|
/// </summary>
|
||||||
|
public string MultipleCultures { get; set; }
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
using System;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using Volo.Abp.Application.Dtos;
|
||||||
|
|
||||||
|
namespace Kurs.Languages;
|
||||||
|
|
||||||
|
public class LanguageKeyDto : FullAuditedEntityDto<Guid>
|
||||||
|
{
|
||||||
|
[Required]
|
||||||
|
public string Key { get; set; }
|
||||||
|
|
||||||
|
[Required]
|
||||||
|
public string ResourceName { get; set; }
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
|
namespace Kurs.Languages;
|
||||||
|
|
||||||
|
public class LanguageTextCreateUpdateDto
|
||||||
|
{
|
||||||
|
[Required]
|
||||||
|
public string CultureName { get; set; }
|
||||||
|
|
||||||
|
[Required]
|
||||||
|
public string Key { get; set; }
|
||||||
|
|
||||||
|
[Required]
|
||||||
|
public string Value { get; set; }
|
||||||
|
|
||||||
|
[Required]
|
||||||
|
public string ResourceName { get; set; }
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
using System;
|
||||||
|
using Volo.Abp.Application.Dtos;
|
||||||
|
|
||||||
|
namespace Kurs.Languages;
|
||||||
|
|
||||||
|
public class LanguageTextDto : FullAuditedEntityDto<Guid>
|
||||||
|
{
|
||||||
|
public string CultureName { get; set; }
|
||||||
|
public string ResourceName { get; set; }
|
||||||
|
public string Key { get; set; }
|
||||||
|
public string Value { get; set; }
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
|
namespace Kurs.Languages;
|
||||||
|
|
||||||
|
public class LanguageTextFilteredDto
|
||||||
|
{
|
||||||
|
[Required]
|
||||||
|
public string CultureName { get; set; }
|
||||||
|
|
||||||
|
[Required]
|
||||||
|
public string ResourceName { get; set; }
|
||||||
|
|
||||||
|
[Required]
|
||||||
|
public string Key { get; set; }
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
using System;
|
||||||
|
using Volo.Abp.Application.Dtos;
|
||||||
|
|
||||||
|
namespace Kurs.Languages;
|
||||||
|
|
||||||
|
public class LanguageTextTranslatedDto : FullAuditedEntityDto<Guid>
|
||||||
|
{
|
||||||
|
public string BaseCultureName { get; set; }
|
||||||
|
public string BaseValue { get; set; }
|
||||||
|
public string TargetCultureName { get; set; }
|
||||||
|
public string TargetValue { get; set; }
|
||||||
|
public string ResourceName { get; set; }
|
||||||
|
public string Key { get; set; }
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using Volo.Abp.Application.Dtos;
|
||||||
|
|
||||||
|
namespace Kurs.Languages;
|
||||||
|
|
||||||
|
public class LanguageTextTranslatedRequestDto : PagedAndSortedResultRequestDto
|
||||||
|
{
|
||||||
|
[Required]
|
||||||
|
public string BaseCultureName { get; set; }
|
||||||
|
|
||||||
|
[Required]
|
||||||
|
public string TargetCultureName { get; set; }
|
||||||
|
|
||||||
|
public string ResourceName { get; set; }
|
||||||
|
|
||||||
|
public string Key { get; set; }
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
|
||||||
|
<ConfigureAwait ContinueOnCapturedContext="false" />
|
||||||
|
</Weavers>
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
||||||
|
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. -->
|
||||||
|
<xs:element name="Weavers">
|
||||||
|
<xs:complexType>
|
||||||
|
<xs:all>
|
||||||
|
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1">
|
||||||
|
<xs:complexType>
|
||||||
|
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" />
|
||||||
|
</xs:complexType>
|
||||||
|
</xs:element>
|
||||||
|
</xs:all>
|
||||||
|
<xs:attribute name="VerifyAssembly" type="xs:boolean">
|
||||||
|
<xs:annotation>
|
||||||
|
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation>
|
||||||
|
</xs:annotation>
|
||||||
|
</xs:attribute>
|
||||||
|
<xs:attribute name="VerifyIgnoreCodes" type="xs:string">
|
||||||
|
<xs:annotation>
|
||||||
|
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation>
|
||||||
|
</xs:annotation>
|
||||||
|
</xs:attribute>
|
||||||
|
<xs:attribute name="GenerateXsd" type="xs:boolean">
|
||||||
|
<xs:annotation>
|
||||||
|
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation>
|
||||||
|
</xs:annotation>
|
||||||
|
</xs:attribute>
|
||||||
|
</xs:complexType>
|
||||||
|
</xs:element>
|
||||||
|
</xs:schema>
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Volo.Abp.Application.Dtos;
|
||||||
|
using Volo.Abp.Application.Services;
|
||||||
|
|
||||||
|
namespace Kurs.Languages;
|
||||||
|
|
||||||
|
public interface ILanguageAppService : ICrudAppService<
|
||||||
|
LanguageDto,
|
||||||
|
Guid,
|
||||||
|
PagedAndSortedResultRequestDto>
|
||||||
|
{
|
||||||
|
Task<LanguageDto> GetLanguageByCultureNameAsync(string CultureName);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
using System;
|
||||||
|
using Volo.Abp.Application.Dtos;
|
||||||
|
using Volo.Abp.Application.Services;
|
||||||
|
|
||||||
|
namespace Kurs.Languages;
|
||||||
|
|
||||||
|
public interface ILanguageKeyAppService : ICrudAppService<
|
||||||
|
LanguageKeyDto,
|
||||||
|
Guid,
|
||||||
|
PagedAndSortedResultRequestDto>
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Volo.Abp;
|
||||||
|
|
||||||
|
namespace Kurs.Languages;
|
||||||
|
|
||||||
|
[IntegrationService]
|
||||||
|
public interface ILanguageKeyIntegrationService
|
||||||
|
{
|
||||||
|
Task CreateKeysForSettingsAsync(
|
||||||
|
string NameKey,
|
||||||
|
string DescriptionKey,
|
||||||
|
string MainGroupKey,
|
||||||
|
string SubGroupKey
|
||||||
|
);
|
||||||
|
|
||||||
|
Task DeleteKeysForSettingsAsync(
|
||||||
|
string NameKey,
|
||||||
|
string DescriptionKey,
|
||||||
|
string MainGroupKey,
|
||||||
|
string SubGroupKey);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Volo.Abp.Application.Dtos;
|
||||||
|
using Volo.Abp.Application.Services;
|
||||||
|
|
||||||
|
namespace Kurs.Languages;
|
||||||
|
|
||||||
|
public interface ILanguageTextAppService : ICrudAppService<
|
||||||
|
LanguageTextDto,
|
||||||
|
Guid,
|
||||||
|
PagedAndSortedResultRequestDto,
|
||||||
|
LanguageTextCreateUpdateDto>
|
||||||
|
{
|
||||||
|
Task<PagedResultDto<LanguageTextTranslatedDto>> GetLanguageTextTranslatedAsync(LanguageTextTranslatedRequestDto input);
|
||||||
|
Task<LanguageTextDto> GetLanguageTextAsync(LanguageTextFilteredDto input);
|
||||||
|
Task UpdateLanguageTextAsync(LanguageTextCreateUpdateDto input);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
{
|
||||||
|
"role": "lib.application-contracts"
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<Import Project="..\common.props" />
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net9.0</TargetFramework>
|
||||||
|
<RootNamespace>Kurs.Languages</RootNamespace>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Volo.Abp.Ddd.Application.Contracts" Version="9.0.2" />
|
||||||
|
<PackageReference Include="Volo.Abp.Authorization" Version="9.0.2" />
|
||||||
|
<ProjectReference Include="..\Kurs.Languages.Domain.Shared\Kurs.Languages.Domain.Shared.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
using Volo.Abp.Application;
|
||||||
|
using Volo.Abp.Modularity;
|
||||||
|
using Volo.Abp.Authorization;
|
||||||
|
|
||||||
|
namespace Kurs.Languages;
|
||||||
|
|
||||||
|
[DependsOn(
|
||||||
|
typeof(LanguagesDomainSharedModule),
|
||||||
|
typeof(AbpDddApplicationContractsModule),
|
||||||
|
typeof(AbpAuthorizationModule)
|
||||||
|
)]
|
||||||
|
public class LanguagesApplicationContractsModule : AbpModule
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
namespace Kurs.Languages;
|
||||||
|
|
||||||
|
public class LanguagesRemoteServiceConsts
|
||||||
|
{
|
||||||
|
public const string RemoteServiceName = "Languages";
|
||||||
|
|
||||||
|
public const string ModuleName = "languages";
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
using Kurs.Languages.Localization;
|
||||||
|
using Volo.Abp.Authorization.Permissions;
|
||||||
|
using Volo.Abp.Localization;
|
||||||
|
|
||||||
|
namespace Kurs.Languages.Permissions;
|
||||||
|
|
||||||
|
public class LanguagesPermissionDefinitionProvider : PermissionDefinitionProvider
|
||||||
|
{
|
||||||
|
public override void Define(IPermissionDefinitionContext context)
|
||||||
|
{
|
||||||
|
var myGroup = context.AddGroup(LanguagesPermissions.GroupName, L("Permission:Languages"));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static LocalizableString L(string name)
|
||||||
|
{
|
||||||
|
return LocalizableString.Create<LanguagesResource>(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
using Volo.Abp.Reflection;
|
||||||
|
|
||||||
|
namespace Kurs.Languages.Permissions;
|
||||||
|
|
||||||
|
public class LanguagesPermissions
|
||||||
|
{
|
||||||
|
public const string GroupName = "Languages";
|
||||||
|
|
||||||
|
public static string[] GetAll()
|
||||||
|
{
|
||||||
|
return ReflectionHelper.GetPublicConstantsRecursively(typeof(LanguagesPermissions));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
|
||||||
|
<ConfigureAwait ContinueOnCapturedContext="false" />
|
||||||
|
</Weavers>
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
||||||
|
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. -->
|
||||||
|
<xs:element name="Weavers">
|
||||||
|
<xs:complexType>
|
||||||
|
<xs:all>
|
||||||
|
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1">
|
||||||
|
<xs:complexType>
|
||||||
|
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" />
|
||||||
|
</xs:complexType>
|
||||||
|
</xs:element>
|
||||||
|
</xs:all>
|
||||||
|
<xs:attribute name="VerifyAssembly" type="xs:boolean">
|
||||||
|
<xs:annotation>
|
||||||
|
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation>
|
||||||
|
</xs:annotation>
|
||||||
|
</xs:attribute>
|
||||||
|
<xs:attribute name="VerifyIgnoreCodes" type="xs:string">
|
||||||
|
<xs:annotation>
|
||||||
|
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation>
|
||||||
|
</xs:annotation>
|
||||||
|
</xs:attribute>
|
||||||
|
<xs:attribute name="GenerateXsd" type="xs:boolean">
|
||||||
|
<xs:annotation>
|
||||||
|
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation>
|
||||||
|
</xs:annotation>
|
||||||
|
</xs:attribute>
|
||||||
|
</xs:complexType>
|
||||||
|
</xs:element>
|
||||||
|
</xs:schema>
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
{
|
||||||
|
"role": "lib.application"
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<Import Project="..\common.props" />
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net9.0</TargetFramework>
|
||||||
|
<RootNamespace>Kurs.Languages</RootNamespace>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Volo.Abp.AutoMapper" Version="9.0.2" />
|
||||||
|
<PackageReference Include="Volo.Abp.Ddd.Application" Version="9.0.2" />
|
||||||
|
<PackageReference Include="Volo.Abp.EntityFrameworkCore" Version="9.0.2" />
|
||||||
|
<ProjectReference Include="..\Kurs.Languages.Application.Contracts\Kurs.Languages.Application.Contracts.csproj" />
|
||||||
|
<ProjectReference Include="..\Kurs.Languages.Domain\Kurs.Languages.Domain.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
|
|
@ -0,0 +1,53 @@
|
||||||
|
using Kurs.Languages.Entities;
|
||||||
|
using Kurs.Languages.Localization;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Volo.Abp.Application.Dtos;
|
||||||
|
using Volo.Abp.Application.Services;
|
||||||
|
using Volo.Abp.Domain.Entities;
|
||||||
|
using Volo.Abp.Domain.Repositories;
|
||||||
|
using Volo.Abp.Validation;
|
||||||
|
|
||||||
|
namespace Kurs.Languages;
|
||||||
|
|
||||||
|
public class LanguageAppService : CrudAppService<
|
||||||
|
Language,
|
||||||
|
LanguageDto,
|
||||||
|
Guid,
|
||||||
|
PagedAndSortedResultRequestDto>,
|
||||||
|
ILanguageAppService
|
||||||
|
{
|
||||||
|
public LanguageAppService(IRepository<Language, Guid> repository) : base(repository)
|
||||||
|
{
|
||||||
|
LocalizationResource = typeof(LanguagesResource);
|
||||||
|
ObjectMapperContext = typeof(LanguagesApplicationModule);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task<LanguageDto> CreateAsync(LanguageDto input)
|
||||||
|
{
|
||||||
|
var recordExists = await Repository.AnyAsync(a => a.CultureName == input.CultureName);
|
||||||
|
if (recordExists)
|
||||||
|
{
|
||||||
|
var validationErrors = new ValidationResult(
|
||||||
|
L["Error:UniqueControl"],
|
||||||
|
new string[] { "CultureName" }
|
||||||
|
);
|
||||||
|
throw new AbpValidationException(new List<ValidationResult> { validationErrors });
|
||||||
|
}
|
||||||
|
|
||||||
|
return await base.CreateAsync(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<LanguageDto> GetLanguageByCultureNameAsync(string CultureName)
|
||||||
|
{
|
||||||
|
var item = await Repository.FirstOrDefaultAsync(a => a.CultureName == CultureName);
|
||||||
|
if (item is null)
|
||||||
|
{
|
||||||
|
throw new EntityNotFoundException(L["RecordNotFound"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ObjectMapper.Map<Language, LanguageDto>(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,48 @@
|
||||||
|
using Kurs.Languages.Entities;
|
||||||
|
using Kurs.Languages.Localization;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Volo.Abp.Application.Dtos;
|
||||||
|
using Volo.Abp.Application.Services;
|
||||||
|
using Volo.Abp.Domain.Repositories;
|
||||||
|
using Volo.Abp.Validation;
|
||||||
|
|
||||||
|
namespace Kurs.Languages;
|
||||||
|
|
||||||
|
public class LanguageKeyAppService : CrudAppService<
|
||||||
|
LanguageKey,
|
||||||
|
LanguageKeyDto,
|
||||||
|
Guid,
|
||||||
|
PagedAndSortedResultRequestDto>,
|
||||||
|
ILanguageKeyAppService
|
||||||
|
{
|
||||||
|
private readonly IRepository<LanguageKey, Guid> _repository;
|
||||||
|
|
||||||
|
public LanguageKeyAppService(
|
||||||
|
IRepository<LanguageKey, Guid> repository
|
||||||
|
) : base(repository)
|
||||||
|
{
|
||||||
|
LocalizationResource = typeof(LanguagesResource);
|
||||||
|
ObjectMapperContext = typeof(LanguagesApplicationModule);
|
||||||
|
_repository = repository;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task<LanguageKeyDto> CreateAsync(LanguageKeyDto input)
|
||||||
|
{
|
||||||
|
var recordExists = await _repository.AnyAsync(
|
||||||
|
a => a.ResourceName == input.ResourceName
|
||||||
|
&& a.Key == input.Key);
|
||||||
|
if (recordExists)
|
||||||
|
{
|
||||||
|
var validationErrors = new ValidationResult(
|
||||||
|
L["Error:UniqueControl"],
|
||||||
|
new string[] { "ResourceName", "Key" }
|
||||||
|
);
|
||||||
|
throw new AbpValidationException(new List<ValidationResult> { validationErrors });
|
||||||
|
}
|
||||||
|
|
||||||
|
return await base.CreateAsync(input);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,63 @@
|
||||||
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Kurs.Languages.Entities;
|
||||||
|
using Volo.Abp;
|
||||||
|
using Volo.Abp.DependencyInjection;
|
||||||
|
using Volo.Abp.Domain.Repositories;
|
||||||
|
|
||||||
|
namespace Kurs.Languages;
|
||||||
|
|
||||||
|
[IntegrationService]
|
||||||
|
public class LanguageKeyIntegrationService : ILanguageKeyIntegrationService, ITransientDependency
|
||||||
|
{
|
||||||
|
private readonly IRepository<LanguageKey, Guid> _repository;
|
||||||
|
|
||||||
|
public LanguageKeyIntegrationService(IRepository<LanguageKey, Guid> repository)
|
||||||
|
{
|
||||||
|
_repository = repository;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task CreateKeysForSettingsAsync(
|
||||||
|
string NameKey,
|
||||||
|
string DescriptionKey,
|
||||||
|
string MainGroupKey,
|
||||||
|
string SubGroupKey
|
||||||
|
)
|
||||||
|
{
|
||||||
|
//NameKey
|
||||||
|
if (!await _repository.AnyAsync(a => a.Key == NameKey && a.ResourceName == LanguagesConsts.AppName))
|
||||||
|
{
|
||||||
|
await _repository.InsertAsync(new LanguageKey { Key = NameKey, ResourceName = LanguagesConsts.AppName });
|
||||||
|
}
|
||||||
|
|
||||||
|
//DescriptionKey
|
||||||
|
if (!await _repository.AnyAsync(a => a.Key == DescriptionKey && a.ResourceName == LanguagesConsts.AppName))
|
||||||
|
{
|
||||||
|
await _repository.InsertAsync(new LanguageKey { Key = DescriptionKey, ResourceName = LanguagesConsts.AppName });
|
||||||
|
}
|
||||||
|
|
||||||
|
//MainGroupKey
|
||||||
|
if (!await _repository.AnyAsync(a => a.Key == MainGroupKey && a.ResourceName == LanguagesConsts.AppName))
|
||||||
|
{
|
||||||
|
await _repository.InsertAsync(new LanguageKey { Key = MainGroupKey, ResourceName = LanguagesConsts.AppName });
|
||||||
|
}
|
||||||
|
|
||||||
|
//SubGroupKey
|
||||||
|
if (!await _repository.AnyAsync(a => a.Key == SubGroupKey && a.ResourceName == LanguagesConsts.AppName))
|
||||||
|
{
|
||||||
|
await _repository.InsertAsync(new LanguageKey { Key = SubGroupKey, ResourceName = LanguagesConsts.AppName });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task DeleteKeysForSettingsAsync(
|
||||||
|
string NameKey,
|
||||||
|
string DescriptionKey,
|
||||||
|
string MainGroupKey,
|
||||||
|
string SubGroupKey)
|
||||||
|
{
|
||||||
|
await _repository.DeleteAsync(a => a.Key == NameKey && a.ResourceName == LanguagesConsts.AppName);
|
||||||
|
await _repository.DeleteAsync(a => a.Key == DescriptionKey && a.ResourceName == LanguagesConsts.AppName);
|
||||||
|
await _repository.DeleteAsync(a => a.Key == MainGroupKey && a.ResourceName == LanguagesConsts.AppName);
|
||||||
|
await _repository.DeleteAsync(a => a.Key == SubGroupKey && a.ResourceName == LanguagesConsts.AppName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,164 @@
|
||||||
|
using Kurs.Languages.Entities;
|
||||||
|
using Kurs.Languages.Localization;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Linq.Dynamic.Core;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Volo.Abp;
|
||||||
|
using Volo.Abp.Application.Dtos;
|
||||||
|
using Volo.Abp.Application.Services;
|
||||||
|
using Volo.Abp.Auditing;
|
||||||
|
using Volo.Abp.Domain.Repositories;
|
||||||
|
using Volo.Abp.Validation;
|
||||||
|
|
||||||
|
namespace Kurs.Languages;
|
||||||
|
|
||||||
|
public class LanguageTextAppService : CrudAppService<
|
||||||
|
LanguageText,
|
||||||
|
LanguageTextDto,
|
||||||
|
Guid,
|
||||||
|
PagedAndSortedResultRequestDto,
|
||||||
|
LanguageTextCreateUpdateDto>,
|
||||||
|
ILanguageTextAppService
|
||||||
|
{
|
||||||
|
private readonly IRepository<LanguageText, Guid> _repositoryText;
|
||||||
|
private readonly IRepository<LanguageKey, Guid> _repositoryKey;
|
||||||
|
|
||||||
|
public LanguageTextAppService(
|
||||||
|
IRepository<LanguageText, Guid> repositoryText,
|
||||||
|
IRepository<LanguageKey, Guid> repositoryKey
|
||||||
|
)
|
||||||
|
: base(repositoryText)
|
||||||
|
{
|
||||||
|
LocalizationResource = typeof(LanguagesResource);
|
||||||
|
ObjectMapperContext = typeof(LanguagesApplicationModule);
|
||||||
|
_repositoryText = repositoryText;
|
||||||
|
_repositoryKey = repositoryKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task<LanguageTextDto> CreateAsync(LanguageTextCreateUpdateDto input)
|
||||||
|
{
|
||||||
|
var recordExists = await _repositoryText.AnyAsync(
|
||||||
|
a => a.CultureName == input.CultureName &&
|
||||||
|
a.Key == input.Key &&
|
||||||
|
a.ResourceName == input.ResourceName);
|
||||||
|
if (recordExists)
|
||||||
|
{
|
||||||
|
var validationErrors = new ValidationResult(
|
||||||
|
L["Error:UniqueControl"],
|
||||||
|
new string[] { "CultureName", "Key", "ResourceName" }
|
||||||
|
);
|
||||||
|
throw new AbpValidationException(new List<ValidationResult> { validationErrors });
|
||||||
|
}
|
||||||
|
|
||||||
|
return await base.CreateAsync(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task UpdateLanguageTextAsync(LanguageTextCreateUpdateDto input)
|
||||||
|
{
|
||||||
|
var entity = await _repositoryText.GetAsync(
|
||||||
|
a => a.CultureName == input.CultureName &&
|
||||||
|
a.ResourceName == input.ResourceName &&
|
||||||
|
a.Key == input.Key);
|
||||||
|
if (entity != null)
|
||||||
|
{
|
||||||
|
entity.Value = input.Value;
|
||||||
|
|
||||||
|
await _repositoryText.UpdateAsync(entity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<PagedResultDto<LanguageTextTranslatedDto>> GetLanguageTextTranslatedAsync(LanguageTextTranslatedRequestDto input)
|
||||||
|
{
|
||||||
|
var query = await _repositoryKey.GetQueryableAsync();
|
||||||
|
query = query
|
||||||
|
.WhereIf(!input.ResourceName.IsNullOrEmpty(), a => a.ResourceName == input.ResourceName)
|
||||||
|
.WhereIf(!input.Key.IsNullOrEmpty(), a => a.Key == input.Key);
|
||||||
|
var totalCount = await query.CountAsync();
|
||||||
|
query = ApplySorting(query, input);
|
||||||
|
query = ApplyPaging(query, input);
|
||||||
|
var keys = await query.ToListAsync();
|
||||||
|
|
||||||
|
var dtoLanguageTextTranslate = ObjectMapper.Map<List<LanguageKey>, List<LanguageTextTranslatedDto>>(keys);
|
||||||
|
|
||||||
|
var dtoBaseCulturesValue = await _repositoryText.GetListAsync(a => a.CultureName == input.BaseCultureName);
|
||||||
|
var dtoTargetCulturesValue = await _repositoryText.GetListAsync(a => a.CultureName == input.TargetCultureName);
|
||||||
|
|
||||||
|
dtoLanguageTextTranslate.ForEach(dto =>
|
||||||
|
{
|
||||||
|
var baseEntity = dtoBaseCulturesValue.FirstOrDefault(a => a.Key == dto.Key && a.ResourceName == dto.ResourceName);
|
||||||
|
|
||||||
|
dto.BaseCultureName = input.BaseCultureName;
|
||||||
|
dto.BaseValue = baseEntity?.Value;
|
||||||
|
|
||||||
|
var targetEntity = dtoTargetCulturesValue.FirstOrDefault(a => a.Key == dto.Key && a.ResourceName == dto.ResourceName);
|
||||||
|
|
||||||
|
dto.TargetCultureName = input.TargetCultureName;
|
||||||
|
dto.TargetValue = targetEntity?.Value;
|
||||||
|
});
|
||||||
|
|
||||||
|
return new PagedResultDto<LanguageTextTranslatedDto>(totalCount, dtoLanguageTextTranslate);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<LanguageTextDto> GetLanguageTextAsync(LanguageTextFilteredDto input)
|
||||||
|
{
|
||||||
|
var entity = await _repositoryText.FirstOrDefaultAsync(a =>
|
||||||
|
a.CultureName == input.CultureName &&
|
||||||
|
a.ResourceName == input.ResourceName &&
|
||||||
|
a.Key == input.Key);
|
||||||
|
|
||||||
|
return ObjectMapper.Map<LanguageText, LanguageTextDto>(entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual IQueryable<LanguageKey> ApplySorting(IQueryable<LanguageKey> query, LanguageTextTranslatedRequestDto input)
|
||||||
|
{
|
||||||
|
//Try to sort query if available
|
||||||
|
if (input is ISortedResultRequest sortInput)
|
||||||
|
{
|
||||||
|
if (!sortInput.Sorting.IsNullOrWhiteSpace())
|
||||||
|
{
|
||||||
|
return query.OrderBy(sortInput.Sorting);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//IQueryable.Task requires sorting, so we should sort if Take will be used.
|
||||||
|
if (input is ILimitedResultRequest)
|
||||||
|
{
|
||||||
|
return ApplyDefaultSorting(query);
|
||||||
|
}
|
||||||
|
|
||||||
|
//No sorting
|
||||||
|
return query;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual IQueryable<LanguageKey> ApplyDefaultSorting(IQueryable<LanguageKey> query)
|
||||||
|
{
|
||||||
|
if (typeof(LanguageKey).IsAssignableTo<IHasCreationTime>())
|
||||||
|
{
|
||||||
|
return query.OrderByDescending(e => ((IHasCreationTime)e).CreationTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new AbpException("No sorting specified but this query requires sorting. Override the ApplyDefaultSorting method for your application service derived from AbstractKeyReadOnlyAppService!");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual IQueryable<LanguageKey> ApplyPaging(IQueryable<LanguageKey> query, LanguageTextTranslatedRequestDto input)
|
||||||
|
{
|
||||||
|
//Try to use paging if available
|
||||||
|
if (input is IPagedResultRequest pagedInput)
|
||||||
|
{
|
||||||
|
return query.PageBy(pagedInput);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Try to limit query result if available
|
||||||
|
if (input is ILimitedResultRequest limitedInput)
|
||||||
|
{
|
||||||
|
return query.Take(limitedInput.MaxResultCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
//No paging
|
||||||
|
return query;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
using Kurs.Languages.Localization;
|
||||||
|
using Volo.Abp.Application.Services;
|
||||||
|
|
||||||
|
namespace Kurs.Languages;
|
||||||
|
|
||||||
|
public abstract class LanguagesAppService : ApplicationService
|
||||||
|
{
|
||||||
|
protected LanguagesAppService()
|
||||||
|
{
|
||||||
|
LocalizationResource = typeof(LanguagesResource);
|
||||||
|
ObjectMapperContext = typeof(LanguagesApplicationModule);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
using AutoMapper;
|
||||||
|
using Kurs.Languages.Entities;
|
||||||
|
using Volo.Abp.AutoMapper;
|
||||||
|
using Volo.Abp.Localization;
|
||||||
|
|
||||||
|
namespace Kurs.Languages;
|
||||||
|
|
||||||
|
public class LanguagesApplicationAutoMapperProfile : Profile
|
||||||
|
{
|
||||||
|
public LanguagesApplicationAutoMapperProfile()
|
||||||
|
{
|
||||||
|
CreateMap<Language, LanguageInfo>();
|
||||||
|
CreateMap<Language, LanguageDto>();
|
||||||
|
CreateMap<LanguageKey, LanguageKeyDto>();
|
||||||
|
CreateMap<LanguageText, LanguageTextDto>();
|
||||||
|
CreateMap<LanguageText, LanguageTextEto>();
|
||||||
|
CreateMap<LanguageTextCreateUpdateDto, LanguageText>()
|
||||||
|
.IgnoreAllPropertiesWithAnInaccessibleSetter()
|
||||||
|
.IgnoreFullAuditedObjectProperties();
|
||||||
|
CreateMap<LanguageKey, LanguageTextTranslatedDto>()
|
||||||
|
.ForMember(d => d.Key, o => o.MapFrom(s => s.Key))
|
||||||
|
.ForMember(d => d.ResourceName, o => o.MapFrom(s => s.ResourceName))
|
||||||
|
.ForAllMembers(o => o.Ignore());
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Volo.Abp.Application;
|
||||||
|
using Volo.Abp.AutoMapper;
|
||||||
|
using Volo.Abp.Modularity;
|
||||||
|
|
||||||
|
namespace Kurs.Languages;
|
||||||
|
|
||||||
|
[DependsOn(
|
||||||
|
typeof(LanguagesDomainModule),
|
||||||
|
typeof(LanguagesApplicationContractsModule),
|
||||||
|
typeof(AbpDddApplicationModule),
|
||||||
|
typeof(AbpAutoMapperModule)
|
||||||
|
)]
|
||||||
|
public class LanguagesApplicationModule : AbpModule
|
||||||
|
{
|
||||||
|
public override void ConfigureServices(ServiceConfigurationContext context)
|
||||||
|
{
|
||||||
|
context.Services.AddAutoMapperObjectMapper<LanguagesApplicationModule>();
|
||||||
|
|
||||||
|
Configure<AbpAutoMapperOptions>(options =>
|
||||||
|
{
|
||||||
|
options.AddMaps<LanguagesApplicationModule>(validate: true);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
|
||||||
|
<ConfigureAwait ContinueOnCapturedContext="false" />
|
||||||
|
</Weavers>
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
||||||
|
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. -->
|
||||||
|
<xs:element name="Weavers">
|
||||||
|
<xs:complexType>
|
||||||
|
<xs:all>
|
||||||
|
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1">
|
||||||
|
<xs:complexType>
|
||||||
|
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" />
|
||||||
|
</xs:complexType>
|
||||||
|
</xs:element>
|
||||||
|
</xs:all>
|
||||||
|
<xs:attribute name="VerifyAssembly" type="xs:boolean">
|
||||||
|
<xs:annotation>
|
||||||
|
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation>
|
||||||
|
</xs:annotation>
|
||||||
|
</xs:attribute>
|
||||||
|
<xs:attribute name="VerifyIgnoreCodes" type="xs:string">
|
||||||
|
<xs:annotation>
|
||||||
|
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation>
|
||||||
|
</xs:annotation>
|
||||||
|
</xs:attribute>
|
||||||
|
<xs:attribute name="GenerateXsd" type="xs:boolean">
|
||||||
|
<xs:annotation>
|
||||||
|
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation>
|
||||||
|
</xs:annotation>
|
||||||
|
</xs:attribute>
|
||||||
|
</xs:complexType>
|
||||||
|
</xs:element>
|
||||||
|
</xs:schema>
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
{
|
||||||
|
"role": "lib.domain-shared"
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<Import Project="..\common.props" />
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net9.0</TargetFramework>
|
||||||
|
<GenerateEmbeddedFilesManifest>true</GenerateEmbeddedFilesManifest>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Volo.Abp.Ddd.Domain.Shared" Version="9.0.2" />
|
||||||
|
<PackageReference Include="Volo.Abp.Validation" Version="9.0.2" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.Extensions.FileProviders.Embedded" Version="9.0.0" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
namespace Kurs.Languages;
|
||||||
|
|
||||||
|
public static class LanguagesConsts
|
||||||
|
{
|
||||||
|
public const string AppName = "Languages";
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,34 @@
|
||||||
|
using Kurs.Languages.Localization;
|
||||||
|
using Volo.Abp.Domain;
|
||||||
|
using Volo.Abp.Localization;
|
||||||
|
using Volo.Abp.Localization.ExceptionHandling;
|
||||||
|
using Volo.Abp.Modularity;
|
||||||
|
using Volo.Abp.Validation;
|
||||||
|
using Volo.Abp.VirtualFileSystem;
|
||||||
|
|
||||||
|
namespace Kurs.Languages;
|
||||||
|
|
||||||
|
[DependsOn(
|
||||||
|
typeof(AbpValidationModule),
|
||||||
|
typeof(AbpDddDomainSharedModule)
|
||||||
|
)]
|
||||||
|
public class LanguagesDomainSharedModule : AbpModule
|
||||||
|
{
|
||||||
|
public override void ConfigureServices(ServiceConfigurationContext context)
|
||||||
|
{
|
||||||
|
Configure<AbpVirtualFileSystemOptions>(options =>
|
||||||
|
{
|
||||||
|
options.FileSets.AddEmbedded<LanguagesDomainSharedModule>();
|
||||||
|
});
|
||||||
|
|
||||||
|
Configure<AbpLocalizationOptions>(options =>
|
||||||
|
{
|
||||||
|
options.Resources.Add<LanguagesResource>("en");
|
||||||
|
});
|
||||||
|
|
||||||
|
Configure<AbpExceptionLocalizationOptions>(options =>
|
||||||
|
{
|
||||||
|
options.MapCodeNamespace("Languages", typeof(LanguagesResource));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
namespace Kurs.Languages;
|
||||||
|
|
||||||
|
public static class LanguagesErrorCodes
|
||||||
|
{
|
||||||
|
//Add your business exception error codes here...
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,44 @@
|
||||||
|
namespace Kurs.Languages.Languages
|
||||||
|
{
|
||||||
|
public static class LanguageCodes
|
||||||
|
{
|
||||||
|
public const string Ar = "ar";
|
||||||
|
public const string Cs = "cs";
|
||||||
|
public const string De = "de-DE";
|
||||||
|
public const string En = "en";
|
||||||
|
public const string Es = "es";
|
||||||
|
public const string Fi = "fi";
|
||||||
|
public const string Fr = "fr";
|
||||||
|
public const string Hi = "hi";
|
||||||
|
public const string Hr = "hr";
|
||||||
|
public const string Hu = "hu";
|
||||||
|
public const string It = "it";
|
||||||
|
public const string Pt = "pt-BR";
|
||||||
|
public const string Ru = "ru";
|
||||||
|
public const string Sk = "sk";
|
||||||
|
public const string Sl = "sl";
|
||||||
|
public const string Tr = "tr";
|
||||||
|
public const string Zh = "zh-Hans";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class LanguageNames
|
||||||
|
{
|
||||||
|
public const string Ar = "العربية";
|
||||||
|
public const string Cs = "Čeština";
|
||||||
|
public const string De = "Deutsch";
|
||||||
|
public const string En = "English";
|
||||||
|
public const string Es = "Español";
|
||||||
|
public const string Fi = "Finnish";
|
||||||
|
public const string Fr = "Français";
|
||||||
|
public const string Hi = "Hindi";
|
||||||
|
public const string Hr = "Croatian";
|
||||||
|
public const string Hu = "Magyar";
|
||||||
|
public const string It = "Italiano";
|
||||||
|
public const string Pt = "Português";
|
||||||
|
public const string Ru = "Русский";
|
||||||
|
public const string Sk = "Slovak";
|
||||||
|
public const string Sl = "Slovenščina";
|
||||||
|
public const string Tr = "Türkçe";
|
||||||
|
public const string Zh = "繁體中文";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
using Volo.Abp.Localization;
|
||||||
|
|
||||||
|
namespace Kurs.Languages.Localization;
|
||||||
|
|
||||||
|
[LocalizationResourceName(LanguagesConsts.AppName)]
|
||||||
|
public class LanguagesResource
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
using System;
|
||||||
|
using Volo.Abp.Domain.Entities.Auditing;
|
||||||
|
|
||||||
|
namespace Kurs.Languages.Entities;
|
||||||
|
|
||||||
|
public class Language : FullAuditedEntity<Guid>
|
||||||
|
{
|
||||||
|
public string CultureName { get; set; }
|
||||||
|
public string UiCultureName { get; set; }
|
||||||
|
public string DisplayName { get; set; }
|
||||||
|
public bool IsEnabled { get; set; }
|
||||||
|
public string TwoLetterISOLanguageName { get; set; }
|
||||||
|
/// <summary> multiple select icin test amacli olarak eklendi
|
||||||
|
/// </summary>
|
||||||
|
public string MultipleCultures { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Volo.Abp.Domain.Entities.Auditing;
|
||||||
|
|
||||||
|
namespace Kurs.Languages.Entities;
|
||||||
|
|
||||||
|
public class LanguageKey : FullAuditedEntity<Guid>
|
||||||
|
{
|
||||||
|
public string Key { get; set; }
|
||||||
|
public string ResourceName { get; set; }
|
||||||
|
|
||||||
|
public ICollection<LanguageText> Texts { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
using System;
|
||||||
|
using Volo.Abp.Domain.Entities.Auditing;
|
||||||
|
|
||||||
|
namespace Kurs.Languages.Entities;
|
||||||
|
|
||||||
|
public class LanguageText : FullAuditedEntity<Guid>
|
||||||
|
{
|
||||||
|
public string CultureName { get; set; }
|
||||||
|
public string? Key { get; set; }
|
||||||
|
public string Value { get; set; }
|
||||||
|
public string? ResourceName { get; set; }
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
|
||||||
|
<ConfigureAwait ContinueOnCapturedContext="false" />
|
||||||
|
</Weavers>
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
||||||
|
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. -->
|
||||||
|
<xs:element name="Weavers">
|
||||||
|
<xs:complexType>
|
||||||
|
<xs:all>
|
||||||
|
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1">
|
||||||
|
<xs:complexType>
|
||||||
|
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" />
|
||||||
|
</xs:complexType>
|
||||||
|
</xs:element>
|
||||||
|
</xs:all>
|
||||||
|
<xs:attribute name="VerifyAssembly" type="xs:boolean">
|
||||||
|
<xs:annotation>
|
||||||
|
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation>
|
||||||
|
</xs:annotation>
|
||||||
|
</xs:attribute>
|
||||||
|
<xs:attribute name="VerifyIgnoreCodes" type="xs:string">
|
||||||
|
<xs:annotation>
|
||||||
|
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation>
|
||||||
|
</xs:annotation>
|
||||||
|
</xs:attribute>
|
||||||
|
<xs:attribute name="GenerateXsd" type="xs:boolean">
|
||||||
|
<xs:annotation>
|
||||||
|
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation>
|
||||||
|
</xs:annotation>
|
||||||
|
</xs:attribute>
|
||||||
|
</xs:complexType>
|
||||||
|
</xs:element>
|
||||||
|
</xs:schema>
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
{
|
||||||
|
"role": "lib.domain"
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<Import Project="..\common.props" />
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net9.0</TargetFramework>
|
||||||
|
<RootNamespace>Kurs.Languages</RootNamespace>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Volo.Abp.Caching.StackExchangeRedis" Version="9.0.2" />
|
||||||
|
<PackageReference Include="Volo.Abp.Ddd.Domain" Version="9.0.2" />
|
||||||
|
<ProjectReference Include="..\Kurs.Languages.Domain.Shared\Kurs.Languages.Domain.Shared.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Volo.Abp.Localization;
|
||||||
|
|
||||||
|
namespace Kurs.Languages;
|
||||||
|
|
||||||
|
public class LanguageListCacheItem
|
||||||
|
{
|
||||||
|
public IReadOnlyList<LanguageInfo> Languages { get; set; }
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Kurs.Languages;
|
||||||
|
|
||||||
|
public class LanguageTextCacheItem : object
|
||||||
|
{
|
||||||
|
public Dictionary<string, string> Dictionary { get; set; }
|
||||||
|
|
||||||
|
public LanguageTextCacheItem()
|
||||||
|
{ }
|
||||||
|
|
||||||
|
public static string CalculateCacheKey(string resourceName, string cultureName)
|
||||||
|
{
|
||||||
|
// .en.Kurs.Dynamics
|
||||||
|
return $".{cultureName}.{resourceName}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Kurs.Languages.Entities;
|
||||||
|
using Volo.Abp.Caching;
|
||||||
|
using Volo.Abp.DependencyInjection;
|
||||||
|
using Volo.Abp.Domain.Entities.Events;
|
||||||
|
using Volo.Abp.EventBus;
|
||||||
|
|
||||||
|
namespace Kurs.Languages;
|
||||||
|
|
||||||
|
public class LanguageTextCacheItemInvalidator :
|
||||||
|
ILocalEventHandler<EntityChangedEventData<LanguageText>>,
|
||||||
|
ITransientDependency
|
||||||
|
{
|
||||||
|
private readonly IDistributedCache<LanguageTextCacheItem> cache;
|
||||||
|
|
||||||
|
public LanguageTextCacheItemInvalidator(IDistributedCache<LanguageTextCacheItem> cache)
|
||||||
|
{
|
||||||
|
this.cache = cache;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task HandleEventAsync(EntityChangedEventData<LanguageText> eventData)
|
||||||
|
{
|
||||||
|
//distributedCacheOptions.Value.KeyPrefix
|
||||||
|
var key = LanguageTextCacheItem.CalculateCacheKey(eventData.Entity.ResourceName, eventData.Entity.CultureName);
|
||||||
|
await cache.RemoveAsync(key);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,77 @@
|
||||||
|
using Kurs.Languages.Entities;
|
||||||
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Volo.Abp.Caching;
|
||||||
|
using Volo.Abp.DependencyInjection;
|
||||||
|
using Volo.Abp.Domain.Entities.Events.Distributed;
|
||||||
|
using Volo.Abp.Domain.Repositories;
|
||||||
|
using Volo.Abp.EventBus.Distributed;
|
||||||
|
|
||||||
|
namespace Kurs.Languages;
|
||||||
|
|
||||||
|
public class LanguageTextCacheItemInvalidatorDistributed :
|
||||||
|
IDistributedEventHandler<EntityCreatedEto<LanguageTextEto>>,
|
||||||
|
IDistributedEventHandler<EntityUpdatedEto<LanguageTextEto>>,
|
||||||
|
IDistributedEventHandler<EntityDeletedEto<LanguageTextEto>>,
|
||||||
|
ITransientDependency
|
||||||
|
{
|
||||||
|
private readonly IRepository<LanguageText, Guid> languageTextRepository;
|
||||||
|
private readonly IDistributedCache<LanguageTextCacheItem> cache;
|
||||||
|
|
||||||
|
public LanguageTextCacheItemInvalidatorDistributed(
|
||||||
|
IRepository<LanguageText, Guid> languageTextRepository,
|
||||||
|
IDistributedCache<LanguageTextCacheItem> cache)
|
||||||
|
{
|
||||||
|
this.languageTextRepository = languageTextRepository;
|
||||||
|
this.cache = cache;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task HandleEventAsync(EntityCreatedEto<LanguageTextEto> eventData)
|
||||||
|
{
|
||||||
|
await InvalidateCacheAsync(eventData.Entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task HandleEventAsync(EntityUpdatedEto<LanguageTextEto> eventData)
|
||||||
|
{
|
||||||
|
await InvalidateCacheAsync(eventData.Entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task HandleEventAsync(EntityDeletedEto<LanguageTextEto> eventData)
|
||||||
|
{
|
||||||
|
await InvalidateCacheAsync(eventData.Entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task InvalidateCacheAsync(LanguageTextEto eventData)
|
||||||
|
{
|
||||||
|
var key = LanguageTextCacheItem.CalculateCacheKey(eventData.ResourceName, eventData.CultureName);
|
||||||
|
await cache.RemoveAsync(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class LanguageTextEto
|
||||||
|
{
|
||||||
|
public string CultureName { get; set; }
|
||||||
|
public string ResourceName { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// For distributed event bus
|
||||||
|
//private void ConfigureDistributedEventBus()
|
||||||
|
//{
|
||||||
|
// Configure<AbpDistributedEntityEventOptions>(options =>
|
||||||
|
// {
|
||||||
|
// //Enable for all entities
|
||||||
|
// //options.AutoEventSelectors.AddAll();
|
||||||
|
|
||||||
|
// //Enable for a single entity
|
||||||
|
// options.AutoEventSelectors.Add<LanguageText>();
|
||||||
|
// options.EtoMappings.Add<LanguageText, LanguageTextEto>();
|
||||||
|
|
||||||
|
// //Enable for all entities in a namespace (and child namespaces)
|
||||||
|
// //options.AutoEventSelectors.AddNamespace("MyProject.Products");
|
||||||
|
|
||||||
|
// //Custom predicate expression that should return true to select a type
|
||||||
|
// //options.AutoEventSelectors.Add(type => type.Namespace.StartsWith("MyProject."));
|
||||||
|
// });
|
||||||
|
//}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
namespace Kurs.Languages;
|
||||||
|
|
||||||
|
public static class LanguagesDbProperties
|
||||||
|
{
|
||||||
|
public static string DbTablePrefix { get; set; } = "P";
|
||||||
|
|
||||||
|
public static string? DbSchema { get; set; } = null;
|
||||||
|
|
||||||
|
public const string ConnectionStringName = "Languages";
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,24 @@
|
||||||
|
using Kurs.Languages.Localization;
|
||||||
|
using Volo.Abp.Caching.StackExchangeRedis;
|
||||||
|
using Volo.Abp.Domain;
|
||||||
|
using Volo.Abp.Localization;
|
||||||
|
using Volo.Abp.Modularity;
|
||||||
|
|
||||||
|
namespace Kurs.Languages;
|
||||||
|
|
||||||
|
[DependsOn(
|
||||||
|
typeof(AbpDddDomainModule),
|
||||||
|
typeof(AbpLocalizationModule),
|
||||||
|
typeof(AbpCachingStackExchangeRedisModule),
|
||||||
|
typeof(LanguagesDomainSharedModule)
|
||||||
|
)]
|
||||||
|
public class LanguagesDomainModule : AbpModule
|
||||||
|
{
|
||||||
|
public override void ConfigureServices(ServiceConfigurationContext context)
|
||||||
|
{
|
||||||
|
Configure<AbpLocalizationOptions>(options =>
|
||||||
|
{
|
||||||
|
options.GlobalContributors.Add<DatabaseLocalizationResourceContributor>();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,45 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Kurs.Languages.Entities;
|
||||||
|
using Volo.Abp.Caching;
|
||||||
|
using Volo.Abp.DependencyInjection;
|
||||||
|
using Volo.Abp.Domain.Repositories;
|
||||||
|
using Volo.Abp.Localization;
|
||||||
|
|
||||||
|
namespace Kurs.Languages.Localization;
|
||||||
|
|
||||||
|
[Dependency(ReplaceServices = true)]
|
||||||
|
public class DatabaseLanguageProvider : ILanguageProvider, ITransientDependency
|
||||||
|
{
|
||||||
|
private readonly IReadOnlyBasicRepository<Language, Guid> languageRepository;
|
||||||
|
private readonly IDistributedCache<LanguageListCacheItem> cache;
|
||||||
|
|
||||||
|
public const string CacheKey = "Languages";
|
||||||
|
|
||||||
|
public DatabaseLanguageProvider(
|
||||||
|
IReadOnlyBasicRepository<Language, Guid> languageRepository,
|
||||||
|
IDistributedCache<LanguageListCacheItem> cache)
|
||||||
|
{
|
||||||
|
this.languageRepository = languageRepository;
|
||||||
|
this.cache = cache;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<IReadOnlyList<LanguageInfo>> GetLanguagesAsync()
|
||||||
|
{
|
||||||
|
var langs = await cache.GetOrAddAsync(CacheKey, GetLanguagesFromDB);
|
||||||
|
return langs.Languages;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<LanguageListCacheItem> GetLanguagesFromDB()
|
||||||
|
{
|
||||||
|
var langs = await languageRepository.GetListAsync();
|
||||||
|
return new LanguageListCacheItem
|
||||||
|
{
|
||||||
|
Languages = langs.OrderBy(o => o.DisplayName)
|
||||||
|
.Select(a => new LanguageInfo(a.CultureName, a.UiCultureName, a.DisplayName))
|
||||||
|
.ToList()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,45 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.Extensions.Localization;
|
||||||
|
using Volo.Abp.Localization;
|
||||||
|
|
||||||
|
namespace Kurs.Languages.Localization;
|
||||||
|
|
||||||
|
public class DatabaseLocalizationResourceContributor : ILocalizationResourceContributor
|
||||||
|
{
|
||||||
|
private LocalizationResourceBase _resource;
|
||||||
|
private IDatabaseResourceLocalizer _databaseResourceLocalizer;
|
||||||
|
private ILanguageProvider _languageProvider;
|
||||||
|
|
||||||
|
public bool IsDynamic => false;
|
||||||
|
|
||||||
|
public void Initialize(LocalizationResourceInitializationContext context)
|
||||||
|
{
|
||||||
|
_resource = context.Resource;
|
||||||
|
_databaseResourceLocalizer = context.ServiceProvider.GetRequiredService<IDatabaseResourceLocalizer>();
|
||||||
|
_languageProvider = context.ServiceProvider.GetRequiredService<ILanguageProvider>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public LocalizedString GetOrNull(string cultureName, string name)
|
||||||
|
{
|
||||||
|
return _databaseResourceLocalizer.GetOrNull(_resource, cultureName, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task FillAsync(string cultureName, Dictionary<string, LocalizedString> dictionary)
|
||||||
|
{
|
||||||
|
await _databaseResourceLocalizer.FillAsync(_resource, cultureName, dictionary);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Fill(string cultureName, Dictionary<string, LocalizedString> dictionary)
|
||||||
|
{
|
||||||
|
_databaseResourceLocalizer.Fill(_resource, cultureName, dictionary);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<IEnumerable<string>> GetSupportedCulturesAsync()
|
||||||
|
{
|
||||||
|
var langs = await _languageProvider.GetLanguagesAsync();
|
||||||
|
return langs.Select(a => a.CultureName).ToList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,89 @@
|
||||||
|
using Kurs.Languages.Entities;
|
||||||
|
using Microsoft.Extensions.Localization;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Volo.Abp.Caching;
|
||||||
|
using Volo.Abp.DependencyInjection;
|
||||||
|
using Volo.Abp.Domain.Repositories;
|
||||||
|
using Volo.Abp.Localization;
|
||||||
|
using Volo.Abp.Threading;
|
||||||
|
|
||||||
|
namespace Kurs.Languages.Localization;
|
||||||
|
|
||||||
|
public class DatabaseResourceLocalizer : IDatabaseResourceLocalizer, ISingletonDependency
|
||||||
|
{
|
||||||
|
private readonly IRepository<LanguageText, Guid> languageTextRepository;
|
||||||
|
private readonly IDistributedCache<LanguageTextCacheItem> cache;
|
||||||
|
|
||||||
|
public DatabaseResourceLocalizer(
|
||||||
|
IRepository<LanguageText, Guid> languageTextRepository,
|
||||||
|
IDistributedCache<LanguageTextCacheItem> cache)
|
||||||
|
{
|
||||||
|
this.languageTextRepository = languageTextRepository;
|
||||||
|
this.cache = cache;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LocalizedString GetOrNull(LocalizationResourceBase resource, string cultureName, string name)
|
||||||
|
{
|
||||||
|
var item = GetCacheItem(resource, cultureName);
|
||||||
|
var value = item.Dictionary?.GetOrDefault(name);
|
||||||
|
if (item == null || value == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return new LocalizedString(name, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected LanguageTextCacheItem GetCacheItem(LocalizationResourceBase resource, string cultureName)
|
||||||
|
{
|
||||||
|
// culture, resource, key
|
||||||
|
var key = LanguageTextCacheItem.CalculateCacheKey(resource.ResourceName, cultureName);
|
||||||
|
return cache.GetOrAdd(key, () => CreateCacheItem(resource, cultureName));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Fill(LocalizationResourceBase resource, string cultureName, Dictionary<string, LocalizedString> dictionary)
|
||||||
|
{
|
||||||
|
var item = GetCacheItem(resource, cultureName);
|
||||||
|
|
||||||
|
foreach (var kvp in item.Dictionary)
|
||||||
|
{
|
||||||
|
dictionary[kvp.Key] = new LocalizedString(kvp.Key, kvp.Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual LanguageTextCacheItem CreateCacheItem(LocalizationResourceBase resource, string cultureName)
|
||||||
|
{
|
||||||
|
//TODO VT'den textleri alip cache'e dolduran kismi yazalim
|
||||||
|
//TODO:SÖ
|
||||||
|
var task = languageTextRepository.GetListAsync(a => a.ResourceName == resource.ResourceName && a.CultureName == cultureName);
|
||||||
|
var texts = AsyncHelper.RunSync(() => task);
|
||||||
|
|
||||||
|
return new LanguageTextCacheItem
|
||||||
|
{
|
||||||
|
Dictionary = texts.ToDictionary(a => a.Key, a => a.Value)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task FillAsync(LocalizationResourceBase resource, string cultureName, Dictionary<string, LocalizedString> dictionary)
|
||||||
|
{
|
||||||
|
var key = LanguageTextCacheItem.CalculateCacheKey(resource.ResourceName, cultureName);
|
||||||
|
var item = await cache.GetOrAddAsync(key, () => CreateCacheItemAsync(resource, cultureName));
|
||||||
|
|
||||||
|
foreach (var kvp in item.Dictionary)
|
||||||
|
{
|
||||||
|
dictionary[kvp.Key] = new LocalizedString(kvp.Key, kvp.Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual async Task<LanguageTextCacheItem> CreateCacheItemAsync(LocalizationResourceBase resource, string cultureName)
|
||||||
|
{
|
||||||
|
var texts = await languageTextRepository.GetListAsync(a => a.ResourceName == resource.ResourceName && a.CultureName == cultureName);
|
||||||
|
|
||||||
|
return new LanguageTextCacheItem
|
||||||
|
{
|
||||||
|
Dictionary = texts.ToDictionary(a => a.Key, a => a.Value)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
using Microsoft.Extensions.Localization;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Volo.Abp.Localization;
|
||||||
|
|
||||||
|
namespace Kurs.Languages.Localization;
|
||||||
|
|
||||||
|
public interface IDatabaseResourceLocalizer
|
||||||
|
{
|
||||||
|
void Fill(LocalizationResourceBase resource, string cultureName, Dictionary<string, LocalizedString> dictionary);
|
||||||
|
Task FillAsync(LocalizationResourceBase resource, string cultureName, Dictionary<string, LocalizedString> dictionary);
|
||||||
|
LocalizedString GetOrNull(LocalizationResourceBase resource, string cultureName, string name);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
using Volo.Abp.Data;
|
||||||
|
using Volo.Abp.EntityFrameworkCore;
|
||||||
|
|
||||||
|
namespace Kurs.Languages.EntityFrameworkCore;
|
||||||
|
|
||||||
|
[ConnectionStringName(LanguagesDbProperties.ConnectionStringName)]
|
||||||
|
public interface ILanguagesDbContext : IEfCoreDbContext
|
||||||
|
{
|
||||||
|
/* Add DbSet for each Aggregate Root here. Example:
|
||||||
|
* DbSet<Question> Questions { get; }
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
using Kurs.Languages.Entities;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Volo.Abp.Data;
|
||||||
|
using Volo.Abp.EntityFrameworkCore;
|
||||||
|
|
||||||
|
namespace Kurs.Languages.EntityFrameworkCore;
|
||||||
|
|
||||||
|
[ConnectionStringName(LanguagesDbProperties.ConnectionStringName)]
|
||||||
|
public class LanguagesDbContext : AbpDbContext<LanguagesDbContext>, ILanguagesDbContext
|
||||||
|
{
|
||||||
|
public DbSet<Language> Languages { get; set; }
|
||||||
|
public DbSet<LanguageKey> LanguageKeys { get; set; }
|
||||||
|
public DbSet<LanguageText> LanguageTexts { get; set; }
|
||||||
|
|
||||||
|
public LanguagesDbContext(DbContextOptions<LanguagesDbContext> options)
|
||||||
|
: base(options)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnModelCreating(ModelBuilder builder)
|
||||||
|
{
|
||||||
|
base.OnModelCreating(builder);
|
||||||
|
|
||||||
|
builder.ConfigureLanguages();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,50 @@
|
||||||
|
using Kurs.Languages.Entities;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Volo.Abp;
|
||||||
|
using Volo.Abp.EntityFrameworkCore.Modeling;
|
||||||
|
|
||||||
|
namespace Kurs.Languages.EntityFrameworkCore;
|
||||||
|
|
||||||
|
public static class LanguagesDbContextModelCreatingExtensions
|
||||||
|
{
|
||||||
|
public static void ConfigureLanguages(
|
||||||
|
this ModelBuilder builder)
|
||||||
|
{
|
||||||
|
Check.NotNull(builder, nameof(builder));
|
||||||
|
|
||||||
|
builder.Entity<Language>(b =>
|
||||||
|
{
|
||||||
|
b.ToTable(LanguagesDbProperties.DbTablePrefix + nameof(Language), LanguagesDbProperties.DbSchema);
|
||||||
|
b.ConfigureByConvention();
|
||||||
|
|
||||||
|
b.Property(a => a.CultureName).HasMaxLength(10).IsRequired();
|
||||||
|
b.Property(a => a.UiCultureName).HasMaxLength(10).IsRequired();
|
||||||
|
b.Property(a => a.DisplayName).HasMaxLength(50).IsRequired();
|
||||||
|
});
|
||||||
|
|
||||||
|
builder.Entity<LanguageKey>(b =>
|
||||||
|
{
|
||||||
|
b.ToTable(LanguagesDbProperties.DbTablePrefix + nameof(LanguageKey), LanguagesDbProperties.DbSchema);
|
||||||
|
b.ConfigureByConvention();
|
||||||
|
|
||||||
|
b.HasKey(a => new { a.ResourceName, a.Key });
|
||||||
|
b.HasMany(a => a.Texts).WithOne()
|
||||||
|
.HasForeignKey(a => new { a.ResourceName, a.Key })
|
||||||
|
.OnDelete(DeleteBehavior.SetNull);
|
||||||
|
|
||||||
|
b.Property(a => a.Key).HasMaxLength(100).IsRequired();
|
||||||
|
b.Property(a => a.ResourceName).HasMaxLength(50).IsRequired();
|
||||||
|
});
|
||||||
|
|
||||||
|
builder.Entity<LanguageText>(b =>
|
||||||
|
{
|
||||||
|
b.ToTable(LanguagesDbProperties.DbTablePrefix + nameof(LanguageText), LanguagesDbProperties.DbSchema);
|
||||||
|
b.ConfigureByConvention();
|
||||||
|
|
||||||
|
b.Property(a => a.CultureName).HasMaxLength(10).IsRequired();
|
||||||
|
b.Property(a => a.ResourceName).HasMaxLength(50);
|
||||||
|
b.Property(a => a.Key).HasMaxLength(100);
|
||||||
|
b.Property(a => a.Value).HasMaxLength(250).IsRequired();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Volo.Abp.EntityFrameworkCore;
|
||||||
|
using Volo.Abp.Modularity;
|
||||||
|
|
||||||
|
namespace Kurs.Languages.EntityFrameworkCore;
|
||||||
|
|
||||||
|
[DependsOn(
|
||||||
|
typeof(LanguagesDomainModule),
|
||||||
|
typeof(AbpEntityFrameworkCoreModule)
|
||||||
|
)]
|
||||||
|
public class LanguagesEntityFrameworkCoreModule : AbpModule
|
||||||
|
{
|
||||||
|
public override void ConfigureServices(ServiceConfigurationContext context)
|
||||||
|
{
|
||||||
|
context.Services.AddAbpDbContext<LanguagesDbContext>(options =>
|
||||||
|
{
|
||||||
|
/* Add custom repositories here. Example:
|
||||||
|
* options.AddRepository<Question, EfCoreQuestionRepository>();
|
||||||
|
*/
|
||||||
|
options.AddDefaultRepositories(includeAllEntities: true);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
|
||||||
|
<ConfigureAwait ContinueOnCapturedContext="false" />
|
||||||
|
</Weavers>
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
||||||
|
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. -->
|
||||||
|
<xs:element name="Weavers">
|
||||||
|
<xs:complexType>
|
||||||
|
<xs:all>
|
||||||
|
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1">
|
||||||
|
<xs:complexType>
|
||||||
|
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" />
|
||||||
|
</xs:complexType>
|
||||||
|
</xs:element>
|
||||||
|
</xs:all>
|
||||||
|
<xs:attribute name="VerifyAssembly" type="xs:boolean">
|
||||||
|
<xs:annotation>
|
||||||
|
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation>
|
||||||
|
</xs:annotation>
|
||||||
|
</xs:attribute>
|
||||||
|
<xs:attribute name="VerifyIgnoreCodes" type="xs:string">
|
||||||
|
<xs:annotation>
|
||||||
|
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation>
|
||||||
|
</xs:annotation>
|
||||||
|
</xs:attribute>
|
||||||
|
<xs:attribute name="GenerateXsd" type="xs:boolean">
|
||||||
|
<xs:annotation>
|
||||||
|
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation>
|
||||||
|
</xs:annotation>
|
||||||
|
</xs:attribute>
|
||||||
|
</xs:complexType>
|
||||||
|
</xs:element>
|
||||||
|
</xs:schema>
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
{
|
||||||
|
"role": "lib.ef"
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<Import Project="..\common.props" />
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net9.0</TargetFramework>
|
||||||
|
<RootNamespace>Kurs.Languages</RootNamespace>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Volo.Abp.EntityFrameworkCore" Version="9.0.2" />
|
||||||
|
<ProjectReference Include="..\Kurs.Languages.Domain\Kurs.Languages.Domain.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
24
api/modules/Kurs.Languages/common.props
Normal file
24
api/modules/Kurs.Languages/common.props
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
<Project>
|
||||||
|
<PropertyGroup>
|
||||||
|
<LangVersion>latest</LangVersion>
|
||||||
|
<Version>0.1.0</Version>
|
||||||
|
<NoWarn>$(NoWarn);CS1591</NoWarn>
|
||||||
|
<AbpProjectType>module</AbpProjectType>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="ConfigureAwait.Fody" Version="3.3.1" PrivateAssets="All" />
|
||||||
|
<PackageReference Include="Fody" Version="6.5.3">
|
||||||
|
<PrivateAssets>All</PrivateAssets>
|
||||||
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
|
||||||
|
</PackageReference>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
|
||||||
|
<Target Name="NoWarnOnRazorViewImportedTypeConflicts" BeforeTargets="RazorCoreCompile">
|
||||||
|
<PropertyGroup>
|
||||||
|
<NoWarn>$(NoWarn);0436</NoWarn>
|
||||||
|
</PropertyGroup>
|
||||||
|
</Target>
|
||||||
|
|
||||||
|
</Project>
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
using Kurs.MailQueue.Domain.Shared;
|
||||||
|
using Volo.Abp.Application.Services;
|
||||||
|
|
||||||
|
namespace Kurs.MailQueue.Application;
|
||||||
|
|
||||||
|
public abstract class MailQueueAppService : ApplicationService
|
||||||
|
{
|
||||||
|
protected MailQueueAppService()
|
||||||
|
{
|
||||||
|
LocalizationResource = typeof(KursMailQueueResource);
|
||||||
|
ObjectMapperContext = typeof(KursMailQueueModule);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
using AutoMapper;
|
||||||
|
|
||||||
|
namespace Kurs.MailQueue.Application;
|
||||||
|
|
||||||
|
public class MailQueueAutoMapperProfile : Profile
|
||||||
|
{
|
||||||
|
public MailQueueAutoMapperProfile()
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
using Volo.Abp.Localization;
|
||||||
|
|
||||||
|
namespace Kurs.MailQueue.Domain.Shared;
|
||||||
|
|
||||||
|
[LocalizationResourceName(MailQueueConsts.AppName)]
|
||||||
|
public class KursMailQueueResource
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
namespace Kurs.MailQueue.Domain.Shared;
|
||||||
|
|
||||||
|
public static class MailQueueConsts
|
||||||
|
{
|
||||||
|
public const string AppName = "MailQueue";
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
namespace Kurs.MailQueue.Domain.Shared;
|
||||||
|
|
||||||
|
public class MailQueueWorkerOptions
|
||||||
|
{
|
||||||
|
public string MailType { get; set; } // Template Tipi
|
||||||
|
public string MailSubject { get; set; } // Mail konusu
|
||||||
|
public string MailTemplate { get; set; } // Render edilecek html template
|
||||||
|
public string Tablo { get; set; } // Bu maildeki tablolar örn. {0:MT3_GECIKEN_SIPARIS:IN:Order Delay Notification:0:}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,34 @@
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
|
using Volo.Abp.Domain.Entities.Auditing;
|
||||||
|
|
||||||
|
namespace Kurs.MailQueue.Domain.Entities;
|
||||||
|
|
||||||
|
public class BackgroundWorker_MailQueue : FullAuditedEntity<Guid>
|
||||||
|
{
|
||||||
|
public Guid TemplateId { get; set; }
|
||||||
|
[Required]
|
||||||
|
[StringLength(100)]
|
||||||
|
public string From { get; set; }
|
||||||
|
[Required]
|
||||||
|
[StringLength(100)]
|
||||||
|
public string To { get; set; }
|
||||||
|
[StringLength(8000)]
|
||||||
|
public string MailParameter { get; set; } //{0:KURYE=FEDEX&ABWNO=777705877048}
|
||||||
|
[StringLength(100)]
|
||||||
|
public string Table { get; set; }
|
||||||
|
[StringLength(500)]
|
||||||
|
public string TableParameter { get; set; }
|
||||||
|
[StringLength(100)]
|
||||||
|
public string Attachment { get; set; }
|
||||||
|
[StringLength(500)]
|
||||||
|
public string AttachmentParameter { get; set; }
|
||||||
|
public bool SendStatus { get; set; } // Mail gönderildi mi, vs
|
||||||
|
// [Column(TypeName = "datetime")]
|
||||||
|
public DateTime? SendTime { get; set; } // Gönderim zamanı
|
||||||
|
[StringLength(100)]
|
||||||
|
public string AwsMessageId { get; set; } // AWS'ten gelen response
|
||||||
|
[StringLength(100)]
|
||||||
|
public string RelatedRecordId { get; set; } // İlgili kaydın ID'si
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
|
using Volo.Abp.Domain.Entities.Auditing;
|
||||||
|
|
||||||
|
namespace Kurs.MailQueue.Domain.Entities;
|
||||||
|
|
||||||
|
public partial class BackgroundWorker_MailQueueEvents : FullAuditedEntity<Guid>
|
||||||
|
{
|
||||||
|
[Required]
|
||||||
|
[StringLength(100)]
|
||||||
|
public string AwsMessageId { get; set; }
|
||||||
|
// [Column(TypeName = "datetime")]
|
||||||
|
public DateTime? EventDate { get; set; }
|
||||||
|
[StringLength(20)]
|
||||||
|
public string Event { get; set; }
|
||||||
|
[StringLength(100)]
|
||||||
|
public string MailAddress { get; set; }
|
||||||
|
public string ResponseDescription { get; set; }
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,33 @@
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Volo.Abp.Domain.Entities;
|
||||||
|
|
||||||
|
namespace Kurs.MailQueue.Domain.Entities;
|
||||||
|
|
||||||
|
[Index(nameof(TableName), nameof(Order), Name = "IX_MailQueueTableFormat", IsUnique = true)]
|
||||||
|
public partial class BackgroundWorker_MailQueueTableFormat : Entity<int>
|
||||||
|
{
|
||||||
|
[Required]
|
||||||
|
[StringLength(100)]
|
||||||
|
public string TableName { get; set; }
|
||||||
|
public short Order { get; set; }
|
||||||
|
[StringLength(50)]
|
||||||
|
public string ColumnName { get; set; }
|
||||||
|
[StringLength(50)]
|
||||||
|
public string Caption { get; set; }
|
||||||
|
[StringLength(1000)]
|
||||||
|
public string HeaderCss { get; set; }
|
||||||
|
[StringLength(1000)]
|
||||||
|
public string Css { get; set; }
|
||||||
|
[StringLength(1000)]
|
||||||
|
public string FooterCss { get; set; }
|
||||||
|
[StringLength(50)]
|
||||||
|
public string DataType { get; set; }
|
||||||
|
[StringLength(50)]
|
||||||
|
public string DataFormat { get; set; }
|
||||||
|
public bool IsHidden { get; set; }
|
||||||
|
public bool IsProtected { get; set; } // Excel'deki sutun korumali mi olacak?
|
||||||
|
[StringLength(50)]
|
||||||
|
public string SubTotal { get; set; }
|
||||||
|
public int Width { get; set; }
|
||||||
|
}
|
||||||
42
api/modules/Kurs.MailQueue/Domain/LogManager.cs
Normal file
42
api/modules/Kurs.MailQueue/Domain/LogManager.cs
Normal file
|
|
@ -0,0 +1,42 @@
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Volo.Abp.Domain.Services;
|
||||||
|
|
||||||
|
namespace Kurs.MailQueue.Domain;
|
||||||
|
|
||||||
|
public interface ILogManager : IDomainService
|
||||||
|
{
|
||||||
|
void Log(
|
||||||
|
LogLevel logTipi,
|
||||||
|
string logDetayi,
|
||||||
|
string kategori = null,
|
||||||
|
string kayitTipi = null,
|
||||||
|
Guid? kayitId = null,
|
||||||
|
string jobId = null);
|
||||||
|
void LogInformation(string logDetayi, string kategori = null, string kayitTipi = null, Guid? kayitId = null, string jobId = null);
|
||||||
|
void LogError(string logDetayi, string kategori = null, string kayitTipi = null, Guid? kayitId = null, string jobId = null);
|
||||||
|
void LogWarning(string logDetayi, string kategori = null, string kayitTipi = null, Guid? kayitId = null, string jobId = null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class NullLogManager : DomainService, ILogManager
|
||||||
|
{
|
||||||
|
public NullLogManager()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Log(
|
||||||
|
LogLevel logTipi,
|
||||||
|
string logDetayi,
|
||||||
|
string kategori = null,
|
||||||
|
string kayitTipi = null,
|
||||||
|
Guid? kayitId = null,
|
||||||
|
string jobId = null)
|
||||||
|
{
|
||||||
|
Logger.Log(logTipi, logDetayi);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void LogInformation(string logDetayi, string kategori = null, string kayitTipi = null, Guid? kayitId = null, string jobId = null) => Log(LogLevel.Information, logDetayi, kategori, kayitTipi, kayitId, jobId);
|
||||||
|
public void LogError(string logDetayi, string kategori = null, string kayitTipi = null, Guid? kayitId = null, string jobId = null) => Log(LogLevel.Error, logDetayi, kategori, kayitTipi, kayitId, jobId);
|
||||||
|
public void LogWarning(string logDetayi, string kategori = null, string kayitTipi = null, Guid? kayitId = null, string jobId = null) => Log(LogLevel.Warning, logDetayi, kategori, kayitTipi, kayitId, jobId);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,63 @@
|
||||||
|
using Kurs.MailQueue.MailGeneration.Models;
|
||||||
|
using Volo.Abp.DependencyInjection;
|
||||||
|
|
||||||
|
namespace Kurs.MailQueue.Domain.MailGeneration;
|
||||||
|
|
||||||
|
public interface IAttachmentExtractor
|
||||||
|
{
|
||||||
|
IList<AttachmentModel> Extract(string attachment, string attachmentParametre);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class AttachmentExtractor : IAttachmentExtractor, ITransientDependency
|
||||||
|
{
|
||||||
|
protected readonly IParameterExtractor ParameterExtractor;
|
||||||
|
|
||||||
|
public AttachmentExtractor(
|
||||||
|
IParameterExtractor parameterExtractor)
|
||||||
|
{
|
||||||
|
ParameterExtractor = parameterExtractor;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IList<AttachmentModel> Extract(string attachment, string attachmentParametre)
|
||||||
|
{
|
||||||
|
var result = new List<AttachmentModel>();
|
||||||
|
|
||||||
|
if (attachment.IsNullOrWhiteSpace())
|
||||||
|
return result;
|
||||||
|
|
||||||
|
var parameters = ParameterExtractor.Extract(attachmentParametre);
|
||||||
|
/*
|
||||||
|
Dict<
|
||||||
|
0, Dict<
|
||||||
|
Tarih, 1232
|
||||||
|
No 4334
|
||||||
|
>
|
||||||
|
1, Dict<
|
||||||
|
QUERY, ghghg
|
||||||
|
QUERYSQL select ffddf
|
||||||
|
*/
|
||||||
|
//Attachment:
|
||||||
|
//{0:MRP:rpt_DepoCikisCekiListesi:PDF:MailEkteGozukecekAd};{1:CRM:rpt_DepoCikisCekiListesiCarpet:XLS:MailEkteGozukecekAd}
|
||||||
|
//AttachmentParametre:
|
||||||
|
//Filtre değerleri olabilir {0:Tarih=1232&No=4334};{1:Tarih=213}
|
||||||
|
//Veya query olabilir {0:QUERY=…&QUERYSQL=..};{1:QUERY=…&QUERYSQL=..}
|
||||||
|
foreach (var item in attachment.Split("};{"))
|
||||||
|
{
|
||||||
|
var keyValue = item.Trim('{').Trim('}').Split(":");
|
||||||
|
if (keyValue.Length == 5)
|
||||||
|
{
|
||||||
|
result.Add(new AttachmentModel
|
||||||
|
{
|
||||||
|
Index = keyValue[0],
|
||||||
|
DbAdi = keyValue[1],
|
||||||
|
RaporAdi = keyValue[2],
|
||||||
|
ExportDosyaTipi = keyValue[3],
|
||||||
|
Filtreler = parameters.GetOrDefault(keyValue[0]),
|
||||||
|
MailEkAdi = keyValue[4]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,43 @@
|
||||||
|
using Volo.Abp.DependencyInjection;
|
||||||
|
|
||||||
|
namespace Kurs.MailQueue.Domain.MailGeneration;
|
||||||
|
|
||||||
|
public interface ICssExtractor
|
||||||
|
{
|
||||||
|
Dictionary<string, string> Extract(string text);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class CssExtractor : ICssExtractor, ITransientDependency
|
||||||
|
{
|
||||||
|
//color: #FFF;background-color:#000;
|
||||||
|
// color=#FFF
|
||||||
|
// background-color=#000
|
||||||
|
public Dictionary<string, string> Extract(string text)
|
||||||
|
{
|
||||||
|
if (text.IsNullOrWhiteSpace())
|
||||||
|
return null;
|
||||||
|
var values = new Dictionary<string, string>();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
foreach (var css in text.Split(";", StringSplitOptions.RemoveEmptyEntries))
|
||||||
|
{
|
||||||
|
var rule = css.Split(":", StringSplitOptions.RemoveEmptyEntries);
|
||||||
|
if (rule.Length == 2)
|
||||||
|
{
|
||||||
|
var key = rule[0].Trim();
|
||||||
|
var value = rule[1].Trim();
|
||||||
|
if (values.ContainsKey(key))
|
||||||
|
values.Add(key, value);
|
||||||
|
else
|
||||||
|
values[key] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
return values;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,79 @@
|
||||||
|
using Volo.Abp.DependencyInjection;
|
||||||
|
|
||||||
|
namespace Kurs.MailQueue.Domain.MailGeneration;
|
||||||
|
|
||||||
|
public interface IParameterExtractor
|
||||||
|
{
|
||||||
|
Dictionary<string, Dictionary<string, string>> Extract(string text);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ParameterExtractor : IParameterExtractor, ITransientDependency
|
||||||
|
{
|
||||||
|
//{0:FISID=xyz&TARIH=12321};{1:FISID=abc&TARIH=32121}
|
||||||
|
// [0]=> FISID=xyz,TARIH=12321
|
||||||
|
// [1]=> FISID=abc,TARIH=32121
|
||||||
|
public Dictionary<string, Dictionary<string, string>> Extract(string text)
|
||||||
|
{
|
||||||
|
return ExtractPart(text)
|
||||||
|
.Select(a => ExtractParameters(a))
|
||||||
|
.Where(a => a.HasValue)
|
||||||
|
.Select(a => a.Value)
|
||||||
|
.ToDictionary(x => x.Key, x => x.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
0=>{FISID=xyz&TARIH=12321}
|
||||||
|
0.0=>FISID=xyz
|
||||||
|
0.1=>TARIH=12321
|
||||||
|
1=>{FISID=xyz&TARIH=12321}
|
||||||
|
1.0=>FISID=xyz
|
||||||
|
1.1=>TARIH=12321
|
||||||
|
*/
|
||||||
|
|
||||||
|
//{0:FISID=xyz&TARIH=12321};{1:FISID=xyz&TARIH=12321}
|
||||||
|
// [0] => 0:FISID=xyz&TARIH=12321, [1] => 1:FISID=xyz&TARIH=12321
|
||||||
|
//{x=1};{y=2};{z=3}
|
||||||
|
// [0] => x=1, [1] => y=2, [2] => z=3
|
||||||
|
private List<string> ExtractPart(string text)
|
||||||
|
{
|
||||||
|
return text?
|
||||||
|
.Split("};{")
|
||||||
|
.Select(a => a.Trim('{').Trim('}'))
|
||||||
|
.ToList() ?? new List<string>();
|
||||||
|
}
|
||||||
|
|
||||||
|
//2:FISID=xyz&TARIH=12321
|
||||||
|
// 2 => List([0] => FISID=xyz, [1] => TARIH=12321)
|
||||||
|
private KeyValuePair<string, Dictionary<string, string>>? ExtractParameters(string text)
|
||||||
|
{
|
||||||
|
if (text.IsNullOrWhiteSpace())
|
||||||
|
return null;
|
||||||
|
|
||||||
|
var index = "0";
|
||||||
|
if (text.Contains(":"))
|
||||||
|
{
|
||||||
|
index = text.Substring(0, text.IndexOf(':'));
|
||||||
|
text = text.Substring(text.IndexOf(':') + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
var values = text
|
||||||
|
.Split("&")?
|
||||||
|
.Select(a => ExtractKeyValue(a))
|
||||||
|
.Where(a => a.HasValue)
|
||||||
|
.Select(a => a.Value)
|
||||||
|
.ToDictionary(x => x.Key, x => x.Value);
|
||||||
|
|
||||||
|
return new KeyValuePair<string, Dictionary<string, string>>(index, values);
|
||||||
|
}
|
||||||
|
|
||||||
|
//x=1
|
||||||
|
// [x] => 1
|
||||||
|
private KeyValuePair<string, string>? ExtractKeyValue(string text)
|
||||||
|
{
|
||||||
|
var keyValue = text?.Split("=");
|
||||||
|
if (keyValue != null && keyValue.Length == 2)
|
||||||
|
return new KeyValuePair<string, string>(keyValue[0], keyValue[1]);
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,48 @@
|
||||||
|
using Kurs.MailQueue.MailGeneration.Models;
|
||||||
|
using Volo.Abp.DependencyInjection;
|
||||||
|
|
||||||
|
namespace Kurs.MailQueue.Domain.MailGeneration;
|
||||||
|
|
||||||
|
public interface ITableExtractor
|
||||||
|
{
|
||||||
|
IList<MailTemplateTableModel> Extract(string text, string parameters);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class TableExtractor : ITableExtractor, ITransientDependency
|
||||||
|
{
|
||||||
|
public IParameterExtractor ParameterExtractor { get; }
|
||||||
|
|
||||||
|
public TableExtractor(IParameterExtractor parameterExtractor)
|
||||||
|
{
|
||||||
|
ParameterExtractor = parameterExtractor;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IList<MailTemplateTableModel> Extract(string text, string parameters)
|
||||||
|
{
|
||||||
|
var result = new List<MailTemplateTableModel>();
|
||||||
|
|
||||||
|
if (text.IsNullOrWhiteSpace())
|
||||||
|
return result;
|
||||||
|
|
||||||
|
var parametreler = ParameterExtractor.Extract(parameters);
|
||||||
|
|
||||||
|
//{0:MT3_GECIKEN_SIPARIS:IN:DosyaAdi;0:};{1:MT7_SIPARIS_DURUM:PDF:DosyaAdi.pdf:0:BRU,3,1}
|
||||||
|
foreach (var item in text.Split("};{"))
|
||||||
|
{
|
||||||
|
var keyValue = item.Trim('{').Trim('}').Split(":");
|
||||||
|
if (keyValue.Length == 6)
|
||||||
|
result.Add(new MailTemplateTableModel
|
||||||
|
{
|
||||||
|
Index = keyValue[0],
|
||||||
|
TabloAdi = keyValue[1],
|
||||||
|
DosyaTipi = keyValue[2],
|
||||||
|
MailEkAdi = keyValue[3],
|
||||||
|
Korumalimi = keyValue[4],
|
||||||
|
DosyaAciklama = keyValue[5],
|
||||||
|
Parametreler = parametreler.GetOrDefault(keyValue[0])
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,226 @@
|
||||||
|
using Kurs.MailQueue.FileGeneration;
|
||||||
|
using Kurs.MailQueue.MailGeneration.Models;
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
|
using Volo.Abp.DependencyInjection;
|
||||||
|
using Volo.Abp.Guids;
|
||||||
|
using Volo.Abp.TextTemplating;
|
||||||
|
|
||||||
|
namespace Kurs.MailQueue.Domain.MailGeneration;
|
||||||
|
|
||||||
|
public interface IAttachmentGenerator
|
||||||
|
{
|
||||||
|
Task<Dictionary<string, string>> GenerateAsync(
|
||||||
|
Guid kuyrukId,
|
||||||
|
string attachment,
|
||||||
|
string attachmentParametre,
|
||||||
|
string jobId = null);
|
||||||
|
|
||||||
|
Task<Dictionary<string, string>> GenerateAsync(List<MailTemplateTableModel> tables, Guid? kuyrukId = null, string jobId = null);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public class AttachmentGenerator : IAttachmentGenerator, ITransientDependency
|
||||||
|
{
|
||||||
|
public IParameterExtractor ParameterExtractor { get; }
|
||||||
|
public IAttachmentExtractor AttachmentExtractor { get; }
|
||||||
|
public ITemplateRenderer TemplateRenderer { get; }
|
||||||
|
public IGuidGenerator GuidGenerator { get; }
|
||||||
|
public IServiceProvider ServiceProvider { get; }
|
||||||
|
protected ILogManager LogManager { get; }
|
||||||
|
private readonly IConfiguration Configuration;
|
||||||
|
|
||||||
|
public AttachmentGenerator(
|
||||||
|
IAttachmentExtractor attachmentExtractor,
|
||||||
|
ITemplateRenderer templateRenderer,
|
||||||
|
IGuidGenerator guidGenerator,
|
||||||
|
IServiceProvider serviceProvider,
|
||||||
|
ILogManager logManager,
|
||||||
|
IConfiguration configuration
|
||||||
|
)
|
||||||
|
{
|
||||||
|
AttachmentExtractor = attachmentExtractor;
|
||||||
|
TemplateRenderer = templateRenderer;
|
||||||
|
GuidGenerator = guidGenerator;
|
||||||
|
ServiceProvider = serviceProvider;
|
||||||
|
LogManager = logManager;
|
||||||
|
Configuration = configuration;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Verilen parametreler (attachment parametreleri) ile KIM raporlari ile istenilen formatta dosya uretir
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="attachment">Export edilecek olan attachmentlar</param>
|
||||||
|
/// <param name="attachmentParametre">Her attachment için parametreler</param>
|
||||||
|
/// <returns>Uretilen ekleri Key: MailEkAdi, Value: Base64 encode edilmis dosya olan dictionary olarak döner</returns>
|
||||||
|
public async Task<Dictionary<string, string>> GenerateAsync(
|
||||||
|
Guid kuyrukId,
|
||||||
|
string attachment,
|
||||||
|
string attachmentParametre,
|
||||||
|
string jobId)
|
||||||
|
{
|
||||||
|
var result = new Dictionary<string, string>();
|
||||||
|
var models = AttachmentExtractor.Extract(attachment, attachmentParametre);
|
||||||
|
var attachmentFolder = $"{kuyrukId}-{jobId}";
|
||||||
|
foreach (var item in models)
|
||||||
|
{
|
||||||
|
var file = GenerateAttachment(item, attachmentFolder);
|
||||||
|
if (file.IsNullOrEmpty())
|
||||||
|
{
|
||||||
|
LogManager.LogError($"Attachment oluşturulamadı. Index: {item.Index}", "ATTACHMENT", "KUYRUK", kuyrukId, jobId);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var base64 = await ConvertFileToBase64Async(file);
|
||||||
|
var key = item.MailEkAdi;
|
||||||
|
if (result.ContainsKey(key))
|
||||||
|
{
|
||||||
|
key = result.Count + "-" + item.MailEkAdi;
|
||||||
|
}
|
||||||
|
result.Add(key, base64);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Verilan tablo modeli ile istenilen dosya tipinde (PDF, XLS, TXT) ek üretir
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="tables">Tablo modeli listesi</param>
|
||||||
|
/// <returns>Uretilen ekleri Key: MailEkAdi, Value: Base64 encode edilmis dosya olan dictionary olarak döner</returns>
|
||||||
|
public async Task<Dictionary<string, string>> GenerateAsync(List<MailTemplateTableModel> tables, Guid? kuyrukId = null, string jobId = null)
|
||||||
|
{
|
||||||
|
var attachments = new Dictionary<string, string>();
|
||||||
|
foreach (var table in tables.Where(a => a.DosyaTipi != "IN"))
|
||||||
|
{
|
||||||
|
IFileGenerator fileGenerator = null;
|
||||||
|
switch (table.DosyaTipi)
|
||||||
|
{
|
||||||
|
case "PDF":
|
||||||
|
fileGenerator = (IFileGenerator)ServiceProvider.GetService(typeof(PDFFileGenerator));
|
||||||
|
break;
|
||||||
|
case "XLS":
|
||||||
|
fileGenerator = (IFileGenerator)ServiceProvider.GetService(typeof(XLSFileGenerator));
|
||||||
|
break;
|
||||||
|
case "TXT":
|
||||||
|
fileGenerator = (IFileGenerator)ServiceProvider.GetService(typeof(TXTFileGenerator));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (fileGenerator == null)
|
||||||
|
{
|
||||||
|
LogManager.LogError($"File Generator oluşturulamadı. Index: {table.Index}, Dosya Tipi: {table.DosyaTipi}", "ATTACHMENT-TABLO", "KUYRUK", kuyrukId, jobId);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var attachment = await fileGenerator.Generate(table);
|
||||||
|
if (kuyrukId.HasValue)
|
||||||
|
{
|
||||||
|
LogToFile(kuyrukId.Value, attachment, table.MailEkAdi);
|
||||||
|
}
|
||||||
|
var base64 = Convert.ToBase64String(attachment);
|
||||||
|
attachments.Add(table.MailEkAdi, base64);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
LogManager.LogError($"Dosya oluşturulamadı. Index: {table.Index}. {ex}", "ATTACHMENT-TABLO", "KUYRUK", kuyrukId, jobId);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return attachments;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string GenerateAttachment(AttachmentModel model, string attachmentFolder)
|
||||||
|
{
|
||||||
|
if (model.Filtreler.IsNullOrEmpty() || model.RaporAdi.IsNullOrWhiteSpace())
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
|
||||||
|
// if (model.Filtreler.ContainsKey("QUERY") && model.Filtreler.ContainsKey("QUERYSQL"))
|
||||||
|
// {
|
||||||
|
// /*
|
||||||
|
//Parametrelerden asagidaki sekilde gelen queryleri en alttaki formata donusturuyoruz
|
||||||
|
//params
|
||||||
|
//0 =>
|
||||||
|
// QUERY -> qryDepo_Cikis_CekiListesi_Detayli
|
||||||
|
// QUERYSQL -> Ksp_Depo_Cikis_CekiListesi_Detayli 252993
|
||||||
|
// QUERY2 -> qryDepo_Cikis_CekiListesi_Sub
|
||||||
|
// QUERY2SQL -> KSp_Depo_Cikis_CekiListesi_Sub 252993
|
||||||
|
|
||||||
|
//SQL olan keyvalue'lari cikar ve sadece querylerde foreach yap
|
||||||
|
// QUERY -> qryDepo_Cikis_CekiListesi_Detayli
|
||||||
|
// dict.add(item.Value, params[item.Key + "SQL"].Value)
|
||||||
|
// QUERY2 -> qryDepo_Cikis_CekiListesi_Sub
|
||||||
|
// dict.add(item.Value, params[item.Key + "SQL"].Value)
|
||||||
|
|
||||||
|
//Bunlari yeni dict'e ekle
|
||||||
|
//dict
|
||||||
|
//qryDepo_Cikis_CekiListesi_Detayli -> Ksp_Depo_Cikis_CekiListesi_Detayli 252993
|
||||||
|
//qryDepo_Cikis_CekiListesi_Sub -> KSp_Depo_Cikis_CekiListesi_Sub 252993
|
||||||
|
// */
|
||||||
|
// //dict -> key (name), value (sql)
|
||||||
|
// var queries = model.Filtreler
|
||||||
|
// .Where(a => a.Key.StartsWith("QUERY"))
|
||||||
|
// .Where(a => !a.Key.EndsWith("SQL"))
|
||||||
|
// .Where(a => !a.Value.IsNullOrWhiteSpace())
|
||||||
|
// .ToDictionary(x => x.Value, x => model.Filtreler.GetValueOrDefault(x.Key + "SQL"));
|
||||||
|
|
||||||
|
// return MsAccessReportManager.GenerateAccessReport(
|
||||||
|
// model.DbAdi,
|
||||||
|
// model.Index,
|
||||||
|
// model.RaporAdi,
|
||||||
|
// model.ExportDosyaTipi,
|
||||||
|
// queries,
|
||||||
|
// attachmentFolder);
|
||||||
|
// }
|
||||||
|
// else
|
||||||
|
// {
|
||||||
|
// return MsAccessReportManager.GenerateAccessReport(
|
||||||
|
// model.DbAdi,
|
||||||
|
// model.Index,
|
||||||
|
// model.RaporAdi,
|
||||||
|
// string.Join(" AND ", model.Filtreler.Select(a => $"{a.Key}={a.Value}")),
|
||||||
|
// model.ExportDosyaTipi,
|
||||||
|
// attachmentFolder);
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<string> ConvertFileToBase64Async(string filePath)
|
||||||
|
{
|
||||||
|
var bytes = await File.ReadAllBytesAsync(filePath);
|
||||||
|
return Convert.ToBase64String(bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void LogToFile(Guid id, byte[] content, string fileName)
|
||||||
|
{
|
||||||
|
if (!Configuration.GetValue<bool>("App:LogMailToFile"))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var path = Configuration.GetValue<string>("App:AttachmentsPath");
|
||||||
|
if (path.IsNullOrWhiteSpace())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
path = Path.Combine(path, id.ToString());
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (!Directory.Exists(path))
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory(path);
|
||||||
|
}
|
||||||
|
File.WriteAllBytes(Path.Combine(path, fileName), content);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
LogManager.LogError($"Dosya diske kaydedilemedi. Yol:{path}, Dosya: {fileName}", "ATTACHMENT-TABLO", "KUYRUK", id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,103 @@
|
||||||
|
using Kurs.MailQueue.MailGeneration.Models;
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
|
using Volo.Abp.DependencyInjection;
|
||||||
|
using Volo.Abp.TextTemplating;
|
||||||
|
|
||||||
|
namespace Kurs.MailQueue.Domain.MailGeneration;
|
||||||
|
|
||||||
|
public interface IMailBodyGenerator
|
||||||
|
{
|
||||||
|
Task<string> GenerateAsync(
|
||||||
|
string templateName,
|
||||||
|
string mailParametreleri,
|
||||||
|
Guid kuyrukId,
|
||||||
|
Dictionary<string, MailTemplateTableModel> tablolar,
|
||||||
|
string jobId = null
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class MailBodyGenerator : IMailBodyGenerator, ITransientDependency
|
||||||
|
{
|
||||||
|
private readonly IConfiguration configuration;
|
||||||
|
|
||||||
|
public IParameterExtractor ParameterExtractor { get; }
|
||||||
|
public ITemplateRenderer TemplateRenderer { get; }
|
||||||
|
protected ILogManager LogManager { get; }
|
||||||
|
|
||||||
|
public MailBodyGenerator(
|
||||||
|
IParameterExtractor parameterExtractor,
|
||||||
|
ITemplateRenderer templateRenderer,
|
||||||
|
IConfiguration configuration,
|
||||||
|
ILogManager logManager)
|
||||||
|
{
|
||||||
|
ParameterExtractor = parameterExtractor;
|
||||||
|
TemplateRenderer = templateRenderer;
|
||||||
|
this.configuration = configuration;
|
||||||
|
LogManager = logManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Verilen parametreler ile mail body render eder
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="templateName">Render edilecek olan template adı</param>
|
||||||
|
/// <param name="mailParametreleri">Dinamik parametreler</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public async Task<string> GenerateAsync(
|
||||||
|
string templateName,
|
||||||
|
string mailParametreleri,
|
||||||
|
Guid kuyrukId,
|
||||||
|
Dictionary<string, MailTemplateTableModel> tablolar,
|
||||||
|
string jobId = null
|
||||||
|
)
|
||||||
|
{
|
||||||
|
var parametreler = ParameterExtractor.Extract(mailParametreleri);
|
||||||
|
//Mail icin 0: ile baslayan tek bir parametre grubu oldugu icin, onu aliyoruz
|
||||||
|
var model = new MailTemplateModel
|
||||||
|
{
|
||||||
|
MailParametreleri = parametreler.GetOrDefault("0"),
|
||||||
|
Tablolar = tablolar
|
||||||
|
};
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var result = await TemplateRenderer.RenderAsync(templateName, model);
|
||||||
|
LogToFile(kuyrukId, result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
LogManager.LogError($"Template Render Başarısız: {templateName}", "MAILBODY", "KUYRUK", kuyrukId, jobId);
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void LogToFile(Guid id, string content)
|
||||||
|
{
|
||||||
|
if (!configuration.GetValue<bool>("App:LogMailToFile"))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var path = configuration.GetValue<string>("App:AttachmentsPath");
|
||||||
|
if (path.IsNullOrWhiteSpace())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
path = Path.Combine(path, id.ToString());
|
||||||
|
var date = DateTime.Now.ToString("yyyy-MM-dd-HH-mm-ss");
|
||||||
|
var dosyaAdi = $"mail-{id}-{date}.html ";
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (!Directory.Exists(path))
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
File.AppendAllText(Path.Combine(path, dosyaAdi), content);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
LogManager.LogError($"Mail diske kaydedilemedi. Yol:{path}: Dosya {dosyaAdi}", "MAILBODY", "KUYRUK", id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,104 @@
|
||||||
|
using System.Data;
|
||||||
|
using Kurs.MailQueue.Domain.Entities;
|
||||||
|
using Kurs.MailQueue.EntityFrameworkCore;
|
||||||
|
using Kurs.MailQueue.MailGeneration.Models;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Volo.Abp.DependencyInjection;
|
||||||
|
using Volo.Abp.Domain.Repositories;
|
||||||
|
using Volo.Abp.TextTemplating;
|
||||||
|
|
||||||
|
namespace Kurs.MailQueue.Domain.MailGeneration;
|
||||||
|
|
||||||
|
public interface ITableGenerator
|
||||||
|
{
|
||||||
|
Task<Dictionary<string, MailTemplateTableModel>>
|
||||||
|
GenerateAsync(
|
||||||
|
string tabloTemplate,
|
||||||
|
string tabloParametreleri,
|
||||||
|
Guid kuyrukId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class TableGenerator : ITableGenerator, ITransientDependency
|
||||||
|
{
|
||||||
|
public ITableExtractor TableExtractor { get; }
|
||||||
|
public ITemplateRenderer TemplateRenderer { get; }
|
||||||
|
public IRepository<BackgroundWorker_MailQueueTableFormat> RepositoryTablo { get; }
|
||||||
|
public IQueryRepository QueryHelper { get; }
|
||||||
|
public ICssExtractor CssExtractor { get; }
|
||||||
|
|
||||||
|
public TableGenerator(
|
||||||
|
ITableExtractor tableExtractor,
|
||||||
|
ITemplateRenderer templateRenderer,
|
||||||
|
IRepository<BackgroundWorker_MailQueueTableFormat> repositoryTablo,
|
||||||
|
IQueryRepository queryHelper,
|
||||||
|
ICssExtractor cssExtractor
|
||||||
|
)
|
||||||
|
{
|
||||||
|
TableExtractor = tableExtractor;
|
||||||
|
TemplateRenderer = templateRenderer;
|
||||||
|
RepositoryTablo = repositoryTablo;
|
||||||
|
QueryHelper = queryHelper;
|
||||||
|
CssExtractor = cssExtractor;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Verilen parametreler ile tablo render eder
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="templateName">Render edilecek olan template adı</param>
|
||||||
|
/// <param name="mailParametreleri">Dinamik parametreler</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public async Task<Dictionary<string, MailTemplateTableModel>> GenerateAsync(string tabloTemplate, string tabloParametreleri, Guid kuyrukId)
|
||||||
|
{
|
||||||
|
var tablolar = TableExtractor.Extract(tabloTemplate, tabloParametreleri);
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
foreach (var tablo in tablolar)
|
||||||
|
{
|
||||||
|
var query = await RepositoryTablo.GetQueryableAsync();
|
||||||
|
var sutunlar = await query.Where(a => a.TableName == tablo.TabloAdi)
|
||||||
|
.OrderBy(o => o.Order)
|
||||||
|
.ToListAsync();
|
||||||
|
|
||||||
|
var table = await QueryHelper.QueryAsync(tablo.TabloAdi, tablo.Parametreler);
|
||||||
|
|
||||||
|
tablo.TabloSutunlari = sutunlar
|
||||||
|
.Select(a => new MailTemplateTableColumnModel
|
||||||
|
{
|
||||||
|
SiraNo = a.Order,
|
||||||
|
SutunAdi = a.ColumnName,
|
||||||
|
SutunBaslik = a.Caption,
|
||||||
|
BaslikCss = CssExtractor.Extract(a.HeaderCss),
|
||||||
|
Css = CssExtractor.Extract(a.Css),
|
||||||
|
AltBilgiCss = CssExtractor.Extract(a.FooterCss),
|
||||||
|
VeriTipi = a.DataType,
|
||||||
|
VeriFormati = a.DataFormat,
|
||||||
|
Gizlimi = a.IsHidden,
|
||||||
|
Korumalimi = a.IsProtected,
|
||||||
|
AltToplam = a.SubTotal,
|
||||||
|
Genislik = a.Width
|
||||||
|
})
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
var degerler = new List<Dictionary<string, object>>();
|
||||||
|
foreach (var row in table.AsEnumerable())
|
||||||
|
{
|
||||||
|
var dict = new Dictionary<string, object>();
|
||||||
|
for (int j = 0; j < table.Columns.Count; j++)
|
||||||
|
{
|
||||||
|
var column = table.Columns[j];
|
||||||
|
dict.Add(
|
||||||
|
column.ColumnName,
|
||||||
|
row[column.ColumnName]);
|
||||||
|
}
|
||||||
|
degerler.Add(dict);
|
||||||
|
}
|
||||||
|
tablo.TabloDegerleri = degerler;
|
||||||
|
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return tablolar.ToDictionary(
|
||||||
|
x => $"{x.DosyaTipi}{x.Index}",
|
||||||
|
x => x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
namespace Kurs.MailQueue.MailGeneration.Models;
|
||||||
|
|
||||||
|
public class AttachmentModel
|
||||||
|
{
|
||||||
|
public string Index { get; set; }
|
||||||
|
public string DbAdi { get; set; } //MRP.mdb, CRM.mdb
|
||||||
|
public string RaporAdi { get; set; }
|
||||||
|
public string ExportDosyaTipi { get; set; } //PDF, TXT, XLS, ..
|
||||||
|
public Dictionary<string, string> Filtreler { get; set; }
|
||||||
|
public string MailEkAdi { get; set; }
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
namespace Kurs.MailQueue.MailGeneration.Models;
|
||||||
|
|
||||||
|
public class MailTemplateModel
|
||||||
|
{
|
||||||
|
public Dictionary<string, string> MailParametreleri { get; set; }
|
||||||
|
public Dictionary<string, MailTemplateTableModel> Tablolar { get; set; }
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
namespace Kurs.MailQueue.MailGeneration.Models;
|
||||||
|
|
||||||
|
public class MailTemplateTableColumnModel
|
||||||
|
{
|
||||||
|
public int SiraNo { get; set; }
|
||||||
|
public string SutunAdi { get; set; }
|
||||||
|
public string SutunBaslik { get; set; }
|
||||||
|
public Dictionary<string, string> BaslikCss { get; set; }
|
||||||
|
public Dictionary<string, string> Css { get; set; }
|
||||||
|
public Dictionary<string, string> AltBilgiCss { get; set; }
|
||||||
|
public string VeriTipi { get; set; }
|
||||||
|
public string VeriFormati { get; set; }
|
||||||
|
public bool Gizlimi { get; set; }
|
||||||
|
public bool Korumalimi { get; set; }
|
||||||
|
public string AltToplam { get; set; }
|
||||||
|
public int Genislik { get; set; }
|
||||||
|
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue