Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8643b6feaa | ||
|
|
551b8469e4 | ||
|
|
1d85f4ccf8 | ||
|
|
cc226d6ce6 | ||
|
|
4996fa7baa | ||
|
|
5215ca95fb | ||
|
|
6d554f190d | ||
|
|
3776aa3f4e | ||
|
|
18fd3950c9 | ||
|
|
cff72f167a | ||
|
|
d3e773fe48 | ||
|
|
8a80499d73 | ||
|
|
5b89d794ca | ||
|
|
227c46827f | ||
|
|
5bd50d1f55 | ||
|
|
a0691c2ccd | ||
|
|
14c70888e4 | ||
|
|
64b2121fa1 | ||
|
|
1ee3dedcf3 | ||
|
|
89f6c5864e | ||
|
|
8851fa938c | ||
|
|
691196ebf1 | ||
|
|
b000f2225c | ||
|
|
2f8d5fa403 | ||
|
|
075990cf8a | ||
|
|
574348a9f2 | ||
|
|
ce7b0e6d1f | ||
|
|
d7170126f0 | ||
|
|
1341d4ebcb |
@@ -1 +1,53 @@
|
|||||||
# RSDO (Razvoj Slovenščine v Digitalnem Okolju) - Concordancer
|
# RSDO (Razvoj Slovenščine v Digitalnem Okolju) - Concordancer
|
||||||
|
This repository contains the source code of the concordancer which is a part of the [Terminology Portal](https://github.com/clarinsi/rsdo_term_portal).
|
||||||
|
|
||||||
|
There are two main parts:
|
||||||
|
- Web application with backend (API interface) written in ASP.NET Core 10 and frontend written in React
|
||||||
|
- System Manager which is written in .NET 10 and is used to initially set up the system
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
Web application requires following external dependencies
|
||||||
|
- OpenSearch v2.3.0 (use docker image: `opensearchproject/opensearch:2.3.0`)
|
||||||
|
- PostgreSQL (use docker image: `postgres`)
|
||||||
|
|
||||||
|
## Building source code
|
||||||
|
### Frontend (React application)
|
||||||
|
To build a frontend application successfully, first, [Node.js](https://nodejs.org/en/) must be installed (at least version 16).
|
||||||
|
Use `npm install` to install all required dependencies, and `npm run build` to build the application.
|
||||||
|
For more info see the [Readme](src/apps/Rsdo.Concordancer.Api/WebApp/README.md) inside the frontend [root](src/apps/Rsdo.Concordancer.Api/WebApp) folder.
|
||||||
|
|
||||||
|
### Backend (ASP.NET Core 10) and System Manager (.NET 10)
|
||||||
|
Open [Rsdo.Concordancer.sln](src/Rsdo.Concordancer.sln) inside of your IDE and build the solution, or use `dotnet build` command to build the solution. All required dependencies will be installed via NuGet packages.
|
||||||
|
|
||||||
|
## Creating docker images
|
||||||
|
There are two Dockerfile's in the source repository for each part. Both images should be compiled within the context of the project root folder.
|
||||||
|
|
||||||
|
### Web application
|
||||||
|
[Dockerfile](src/apps/Rsdo.Concordancer.Api/Dockerfile) for Web Application accepts additional optional argument (WEBAPP_PUBLIC_URL) which is mapped to React [PUBLIC_URL](https://create-react-app.dev/docs/using-the-public-folder/) variable. If the variable is omited, then application should be deployed on a domain root.
|
||||||
|
|
||||||
|
`docker build -t rsdo-concordancer-api -f src/apps/Rsdo.Concordancer.Api/Dockerfile .`
|
||||||
|
|
||||||
|
`docker build --build-arg WEBAPP_PUBLIC_URL=/corpus -t rsdo-concordancer-api -f src/apps/Rsdo.Concordancer.Api/Dockerfile .`
|
||||||
|
|
||||||
|
### System Manager
|
||||||
|
Use following [Dockerfile](src/apps/Rsdo.Concordancer.SystemManager/Dockerfile) to build System Manager.
|
||||||
|
|
||||||
|
`docker build -t rsdo-concordancer-systemmanager -f src/apps/Rsdo.Concordancer.SystemManager/Dockerfile .`
|
||||||
|
|
||||||
|
## Environment variables
|
||||||
|
|
||||||
|
### Web application
|
||||||
|
Web application must be configured with the following Environment variables and values:
|
||||||
|
- `RSDO:Database:MasterConnectionString` holds connection string to the main database; e.g.: `Host=rsdo_db;Username=rsdo;Password=strongpassword;Database=Concordancer`
|
||||||
|
- `RSDO:Elastic:ConnectionString` holds connection string to OpenSearch server; e.g.: `http://rsdo_opensearch:9200`
|
||||||
|
- `RSDO:Tokenizer:ClasslaUrl` holds and url to external service which is used for tokenizing search strings; e.g.: `https://orodja.cjvt.si/oznacevalnik/ajax_api/v1/slv/process`
|
||||||
|
|
||||||
|
### System Manager
|
||||||
|
System manager must be configured with the following Environment variables and values:
|
||||||
|
- `RSDO:Database:MasterConnectionString` holds connection string to the main database; e.g.: `Host=rsdo_db;Username=rsdo;Password=strongpassword;Database=Concordancer`
|
||||||
|
- `RSDO:Elastic:ConnectionString` holds connection string to OpenSearch server; e.g.: `http://rsdo_opensearch:9200`
|
||||||
|
|
||||||
|
## Using System Manager
|
||||||
|
To initialy setup the system, you have to use System Manager and run following commands:
|
||||||
|
1. `dotnet Rsdo.Concordancer.SystemManager.dll createMasterDb --connectionString="Host=rsdo_db;Username=rsdo;Password=strongpassword;Database=postgres"` which will create master database with the name Concordancer. You can select different name with the `--name` option
|
||||||
|
2. `dotnet Rsdo.Concordancer.SystemManager.dll importSloleks --sourceFile=/data/Sloleks2.0.LMF/sloleks_clarin_2.0.xml` which will import Sloleks (which is used for better searching). XML file is not part of this repository, but it can be downloaded from the following [URL](https://www.clarin.si/repository/xmlui/bitstream/handle/11356/1230/Sloleks2.0.LMF.zip?sequence=3&isAllowed=y)
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
docker build --no-cache -t rsdo-concordancer-api -f src/apps/Rsdo.Concordancer.Api/Dockerfile .
|
||||||
|
docker build --no-cache --build-arg WEBAPP_PUBLIC_URL=/korpus -t rsdo-concordancer-api-term-portal -f src/apps/Rsdo.Concordancer.Api/Dockerfile .
|
||||||
|
docker build --no-cache -t rsdo-concordancer-systemmanager -f src/apps/Rsdo.Concordancer.SystemManager/Dockerfile .
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
docker build --no-cache -t rsdo-concordancer-api -f src/apps/Rsdo.Concordancer.Api/Dockerfile .
|
||||||
|
docker build --no-cache --build-arg WEBAPP_PUBLIC_URL=/korpus -t rsdo-concordancer-api-term-portal -f src/apps/Rsdo.Concordancer.Api/Dockerfile .
|
||||||
|
docker build --no-cache -t rsdo-concordancer-systemmanager -f src/apps/Rsdo.Concordancer.SystemManager/Dockerfile .
|
||||||
|
|
||||||
|
docker login ghcr.io
|
||||||
|
|
||||||
|
docker tag rsdo-concordancer-api ghcr.io/clarinsi/rsdo-concordancer-api:latest
|
||||||
|
docker tag rsdo-concordancer-api ghcr.io/clarinsi/rsdo-concordancer-api:v1.0.4
|
||||||
|
docker tag rsdo-concordancer-api ghcr.io/clarinsi/rsdo-concordancer-api:v1.0
|
||||||
|
docker tag rsdo-concordancer-api ghcr.io/clarinsi/rsdo-concordancer-api:v1
|
||||||
|
|
||||||
|
docker tag rsdo-concordancer-api-term-portal ghcr.io/clarinsi/rsdo-concordancer-api-term-portal:latest
|
||||||
|
docker tag rsdo-concordancer-api-term-portal ghcr.io/clarinsi/rsdo-concordancer-api-term-portal:v1.0.4
|
||||||
|
docker tag rsdo-concordancer-api-term-portal ghcr.io/clarinsi/rsdo-concordancer-api-term-portal:v1.0
|
||||||
|
docker tag rsdo-concordancer-api-term-portal ghcr.io/clarinsi/rsdo-concordancer-api-term-portal:v1
|
||||||
|
|
||||||
|
docker tag rsdo-concordancer-systemmanager ghcr.io/clarinsi/rsdo-concordancer-systemmanager:latest
|
||||||
|
docker tag rsdo-concordancer-systemmanager ghcr.io/clarinsi/rsdo-concordancer-systemmanager:v1.0.4
|
||||||
|
docker tag rsdo-concordancer-systemmanager ghcr.io/clarinsi/rsdo-concordancer-systemmanager:v1.0
|
||||||
|
docker tag rsdo-concordancer-systemmanager ghcr.io/clarinsi/rsdo-concordancer-systemmanager:v1
|
||||||
|
|
||||||
|
docker push --all-tags ghcr.io/clarinsi/rsdo-concordancer-api
|
||||||
|
docker push --all-tags ghcr.io/clarinsi/rsdo-concordancer-api-term-portal
|
||||||
|
docker push --all-tags ghcr.io/clarinsi/rsdo-concordancer-systemmanager
|
||||||
Binary file not shown.
+62
-18
@@ -1,7 +1,7 @@
|
|||||||
## Ignore Visual Studio temporary files, build results, and
|
## Ignore Visual Studio temporary files, build results, and
|
||||||
## files generated by popular Visual Studio add-ons.
|
## files generated by popular Visual Studio add-ons.
|
||||||
##
|
##
|
||||||
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
|
## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore
|
||||||
|
|
||||||
# User-specific files
|
# User-specific files
|
||||||
*.rsuser
|
*.rsuser
|
||||||
@@ -9,6 +9,7 @@
|
|||||||
*.user
|
*.user
|
||||||
*.userosscache
|
*.userosscache
|
||||||
*.sln.docstates
|
*.sln.docstates
|
||||||
|
*.env
|
||||||
|
|
||||||
# User-specific files (MonoDevelop/Xamarin Studio)
|
# User-specific files (MonoDevelop/Xamarin Studio)
|
||||||
*.userprefs
|
*.userprefs
|
||||||
@@ -21,17 +22,37 @@ mono_crash.*
|
|||||||
[Dd]ebugPublic/
|
[Dd]ebugPublic/
|
||||||
[Rr]elease/
|
[Rr]elease/
|
||||||
[Rr]eleases/
|
[Rr]eleases/
|
||||||
x64/
|
|
||||||
x86/
|
[Dd]ebug/x64/
|
||||||
|
[Dd]ebugPublic/x64/
|
||||||
|
[Rr]elease/x64/
|
||||||
|
[Rr]eleases/x64/
|
||||||
|
bin/x64/
|
||||||
|
obj/x64/
|
||||||
|
|
||||||
|
[Dd]ebug/x86/
|
||||||
|
[Dd]ebugPublic/x86/
|
||||||
|
[Rr]elease/x86/
|
||||||
|
[Rr]eleases/x86/
|
||||||
|
bin/x86/
|
||||||
|
obj/x86/
|
||||||
|
|
||||||
[Ww][Ii][Nn]32/
|
[Ww][Ii][Nn]32/
|
||||||
[Aa][Rr][Mm]/
|
[Aa][Rr][Mm]/
|
||||||
[Aa][Rr][Mm]64/
|
[Aa][Rr][Mm]64/
|
||||||
|
[Aa][Rr][Mm]64[Ee][Cc]/
|
||||||
bld/
|
bld/
|
||||||
[Bb]in/
|
|
||||||
[Oo]bj/
|
[Oo]bj/
|
||||||
|
[Oo]ut/
|
||||||
[Ll]og/
|
[Ll]og/
|
||||||
[Ll]ogs/
|
[Ll]ogs/
|
||||||
|
|
||||||
|
# Build results on 'Bin' directories
|
||||||
|
**/[Bb]in/*
|
||||||
|
# Uncomment if you have tasks that rely on *.refresh files to move binaries
|
||||||
|
# (https://github.com/github/gitignore/pull/3736)
|
||||||
|
#!**/[Bb]in/*.refresh
|
||||||
|
|
||||||
# Visual Studio 2015/2017 cache/options directory
|
# Visual Studio 2015/2017 cache/options directory
|
||||||
.vs/
|
.vs/
|
||||||
# Uncomment if you have tasks that create the project's static files in wwwroot
|
# Uncomment if you have tasks that create the project's static files in wwwroot
|
||||||
@@ -43,12 +64,16 @@ Generated\ Files/
|
|||||||
# MSTest test Results
|
# MSTest test Results
|
||||||
[Tt]est[Rr]esult*/
|
[Tt]est[Rr]esult*/
|
||||||
[Bb]uild[Ll]og.*
|
[Bb]uild[Ll]og.*
|
||||||
|
*.trx
|
||||||
|
|
||||||
# NUnit
|
# NUnit
|
||||||
*.VisualState.xml
|
*.VisualState.xml
|
||||||
TestResult.xml
|
TestResult.xml
|
||||||
nunit-*.xml
|
nunit-*.xml
|
||||||
|
|
||||||
|
# Approval Tests result files
|
||||||
|
*.received.*
|
||||||
|
|
||||||
# Build Results of an ATL Project
|
# Build Results of an ATL Project
|
||||||
[Dd]ebugPS/
|
[Dd]ebugPS/
|
||||||
[Rr]eleasePS/
|
[Rr]eleasePS/
|
||||||
@@ -61,6 +86,7 @@ BenchmarkDotNet.Artifacts/
|
|||||||
project.lock.json
|
project.lock.json
|
||||||
project.fragment.lock.json
|
project.fragment.lock.json
|
||||||
artifacts/
|
artifacts/
|
||||||
|
.artifacts/
|
||||||
|
|
||||||
# ASP.NET Scaffolding
|
# ASP.NET Scaffolding
|
||||||
ScaffoldingReadMe.txt
|
ScaffoldingReadMe.txt
|
||||||
@@ -75,6 +101,7 @@ StyleCopReport.xml
|
|||||||
*.ilk
|
*.ilk
|
||||||
*.meta
|
*.meta
|
||||||
*.obj
|
*.obj
|
||||||
|
*.idb
|
||||||
*.iobj
|
*.iobj
|
||||||
*.pch
|
*.pch
|
||||||
*.pdb
|
*.pdb
|
||||||
@@ -82,6 +109,8 @@ StyleCopReport.xml
|
|||||||
*.pgc
|
*.pgc
|
||||||
*.pgd
|
*.pgd
|
||||||
*.rsp
|
*.rsp
|
||||||
|
# but not Directory.Build.rsp, as it configures directory-level build defaults
|
||||||
|
!Directory.Build.rsp
|
||||||
*.sbr
|
*.sbr
|
||||||
*.tlb
|
*.tlb
|
||||||
*.tli
|
*.tli
|
||||||
@@ -153,6 +182,7 @@ coverage*.info
|
|||||||
|
|
||||||
# NCrunch
|
# NCrunch
|
||||||
_NCrunch_*
|
_NCrunch_*
|
||||||
|
.NCrunch_*
|
||||||
.*crunch*.local.xml
|
.*crunch*.local.xml
|
||||||
nCrunchTemp_*
|
nCrunchTemp_*
|
||||||
|
|
||||||
@@ -206,9 +236,6 @@ PublishScripts/
|
|||||||
*.nuget.props
|
*.nuget.props
|
||||||
*.nuget.targets
|
*.nuget.targets
|
||||||
|
|
||||||
# Nuget personal access tokens and Credentials
|
|
||||||
nuget.config
|
|
||||||
|
|
||||||
# Microsoft Azure Build Output
|
# Microsoft Azure Build Output
|
||||||
csx/
|
csx/
|
||||||
*.build.csdef
|
*.build.csdef
|
||||||
@@ -297,6 +324,14 @@ node_modules/
|
|||||||
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
|
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
|
||||||
*.vbw
|
*.vbw
|
||||||
|
|
||||||
|
# Visual Studio 6 workspace and project file (working project files containing files to include in project)
|
||||||
|
*.dsw
|
||||||
|
*.dsp
|
||||||
|
|
||||||
|
# Visual Studio 6 technical files
|
||||||
|
*.ncb
|
||||||
|
*.aps
|
||||||
|
|
||||||
# Visual Studio LightSwitch build output
|
# Visual Studio LightSwitch build output
|
||||||
**/*.HTMLClient/GeneratedArtifacts
|
**/*.HTMLClient/GeneratedArtifacts
|
||||||
**/*.DesktopClient/GeneratedArtifacts
|
**/*.DesktopClient/GeneratedArtifacts
|
||||||
@@ -306,22 +341,22 @@ node_modules/
|
|||||||
_Pvt_Extensions
|
_Pvt_Extensions
|
||||||
|
|
||||||
# Paket dependency manager
|
# Paket dependency manager
|
||||||
.paket/paket.exe
|
**/.paket/paket.exe
|
||||||
paket-files/
|
paket-files/
|
||||||
|
|
||||||
# FAKE - F# Make
|
# FAKE - F# Make
|
||||||
.fake/
|
**/.fake/
|
||||||
|
|
||||||
# CodeRush personal settings
|
# CodeRush personal settings
|
||||||
.cr/personal
|
**/.cr/personal
|
||||||
|
|
||||||
# Python Tools for Visual Studio (PTVS)
|
# Python Tools for Visual Studio (PTVS)
|
||||||
__pycache__/
|
**/__pycache__/
|
||||||
*.pyc
|
*.pyc
|
||||||
|
|
||||||
# Cake - Uncomment if you are using it
|
# Cake - Uncomment if you are using it
|
||||||
# tools/**
|
#tools/**
|
||||||
# !tools/packages.config
|
#!tools/packages.config
|
||||||
|
|
||||||
# Tabs Studio
|
# Tabs Studio
|
||||||
*.tss
|
*.tss
|
||||||
@@ -343,15 +378,22 @@ ASALocalRun/
|
|||||||
|
|
||||||
# MSBuild Binary and Structured Log
|
# MSBuild Binary and Structured Log
|
||||||
*.binlog
|
*.binlog
|
||||||
|
MSBuild_Logs/
|
||||||
|
|
||||||
|
# AWS SAM Build and Temporary Artifacts folder
|
||||||
|
.aws-sam
|
||||||
|
|
||||||
# NVidia Nsight GPU debugger configuration file
|
# NVidia Nsight GPU debugger configuration file
|
||||||
*.nvuser
|
*.nvuser
|
||||||
|
|
||||||
# MFractors (Xamarin productivity tool) working folder
|
# MFractors (Xamarin productivity tool) working folder
|
||||||
.mfractor/
|
**/.mfractor/
|
||||||
|
|
||||||
# Local History for Visual Studio
|
# Local History for Visual Studio
|
||||||
.localhistory/
|
**/.localhistory/
|
||||||
|
|
||||||
|
# Visual Studio History (VSHistory) files
|
||||||
|
.vshistory/
|
||||||
|
|
||||||
# BeatPulse healthcheck temp database
|
# BeatPulse healthcheck temp database
|
||||||
healthchecksdb
|
healthchecksdb
|
||||||
@@ -360,7 +402,7 @@ healthchecksdb
|
|||||||
MigrationBackup/
|
MigrationBackup/
|
||||||
|
|
||||||
# Ionide (cross platform F# VS Code tools) working folder
|
# Ionide (cross platform F# VS Code tools) working folder
|
||||||
.ionide/
|
**/.ionide/
|
||||||
|
|
||||||
# Fody - auto-generated XML schema
|
# Fody - auto-generated XML schema
|
||||||
FodyWeavers.xsd
|
FodyWeavers.xsd
|
||||||
@@ -371,11 +413,14 @@ FodyWeavers.xsd
|
|||||||
!.vscode/tasks.json
|
!.vscode/tasks.json
|
||||||
!.vscode/launch.json
|
!.vscode/launch.json
|
||||||
!.vscode/extensions.json
|
!.vscode/extensions.json
|
||||||
*.code-workspace
|
!.vscode/*.code-snippets
|
||||||
|
|
||||||
# Local History for Visual Studio Code
|
# Local History for Visual Studio Code
|
||||||
.history/
|
.history/
|
||||||
|
|
||||||
|
# Built Visual Studio Code Extensions
|
||||||
|
*.vsix
|
||||||
|
|
||||||
# Windows Installer files from build outputs
|
# Windows Installer files from build outputs
|
||||||
*.cab
|
*.cab
|
||||||
*.msi
|
*.msi
|
||||||
@@ -385,4 +430,3 @@ FodyWeavers.xsd
|
|||||||
|
|
||||||
# JetBrains Rider
|
# JetBrains Rider
|
||||||
.idea/
|
.idea/
|
||||||
*.sln.iml
|
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
<Project>
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net10.0</TargetFramework>
|
||||||
|
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||||
|
<EnableNETAnalyzers>true</EnableNETAnalyzers>
|
||||||
|
<AnalysisLevel>10-recommended</AnalysisLevel>
|
||||||
|
<EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>
|
||||||
|
<NoWarn>$(NoWarn);CS1591</NoWarn>
|
||||||
|
<Version>1.0.4</Version>
|
||||||
|
</PropertyGroup>
|
||||||
|
</Project>
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
<Project>
|
||||||
|
<PropertyGroup>
|
||||||
|
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageVersion Include="Autofac" Version="9.1.0" />
|
||||||
|
<PackageVersion Include="Autofac.Extensions.DependencyInjection" Version="11.0.0" />
|
||||||
|
<PackageVersion Include="CommandLineParser" Version="2.9.1" />
|
||||||
|
<PackageVersion Include="coverlet.collector" Version="10.0.1" />
|
||||||
|
<PackageVersion Include="EFCore.NamingConventions" Version="10.0.1" />
|
||||||
|
<PackageVersion Include="FluentMigrator" Version="8.0.1" />
|
||||||
|
<PackageVersion Include="FluentMigrator.Runner" Version="8.0.1" />
|
||||||
|
<PackageVersion Include="FluentMigrator.Runner.Postgres" Version="8.0.1" />
|
||||||
|
<PackageVersion Include="FluentValidation" Version="12.1.1" />
|
||||||
|
<PackageVersion Include="Hangfire" Version="1.8.23" />
|
||||||
|
<PackageVersion Include="Hangfire.Core" Version="1.8.23" />
|
||||||
|
<PackageVersion Include="Hangfire.PostgreSql" Version="1.21.1" />
|
||||||
|
<PackageVersion Include="Microsoft.EntityFrameworkCore" Version="10.0.8" />
|
||||||
|
<PackageVersion Include="Microsoft.Extensions.Caching.Memory" Version="10.0.8" />
|
||||||
|
<PackageVersion Include="Microsoft.Extensions.Configuration" Version="10.0.8" />
|
||||||
|
<PackageVersion Include="Microsoft.Extensions.Configuration.Abstractions" Version="10.0.8" />
|
||||||
|
<PackageVersion Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="10.0.8" />
|
||||||
|
<PackageVersion Include="Microsoft.Extensions.Http" Version="10.0.8" />
|
||||||
|
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="18.6.0" />
|
||||||
|
<PackageVersion Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="10.0.2" />
|
||||||
|
<PackageVersion Include="Newtonsoft.Json" Version="13.0.4" />
|
||||||
|
<PackageVersion Include="Npgsql" Version="10.0.3" />
|
||||||
|
<PackageVersion Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="10.0.2" />
|
||||||
|
<PackageVersion Include="OpenSearch.Client" Version="1.8.0" />
|
||||||
|
<PackageVersion Include="Serilog.AspNetCore" Version="10.0.0" />
|
||||||
|
<PackageVersion Include="Serilog.Expressions" Version="5.0.0" />
|
||||||
|
<PackageVersion Include="Serilog.Settings.Configuration" Version="10.0.0" />
|
||||||
|
<PackageVersion Include="Serilog.Sinks.Console" Version="6.1.1" />
|
||||||
|
<PackageVersion Include="Serilog.Sinks.Email" Version="4.2.1" />
|
||||||
|
<PackageVersion Include="Serilog.Sinks.File" Version="7.0.0" />
|
||||||
|
<PackageVersion Include="Swashbuckle.AspNetCore" Version="10.2.1" />
|
||||||
|
<PackageVersion Include="Swashbuckle.AspNetCore.Annotations" Version="10.2.1" />
|
||||||
|
<PackageVersion Include="xunit" Version="2.9.3" />
|
||||||
|
<PackageVersion Include="xunit.runner.visualstudio" Version="3.1.5" />
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
||||||
@@ -24,6 +24,13 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Rsdo.Concordancer.Data", "c
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Rsdo.Concordancer.SystemManager", "apps\Rsdo.Concordancer.SystemManager\Rsdo.Concordancer.SystemManager.csproj", "{41B26AD1-C0A5-4796-95D0-CB84FB574A83}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Rsdo.Concordancer.SystemManager", "apps\Rsdo.Concordancer.SystemManager\Rsdo.Concordancer.SystemManager.csproj", "{41B26AD1-C0A5-4796-95D0-CB84FB574A83}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{0BC9D8CB-3F46-40F4-B769-E2605F03E0F6}"
|
||||||
|
ProjectSection(SolutionItems) = preProject
|
||||||
|
Directory.Build.props = Directory.Build.props
|
||||||
|
Directory.Packages.props = Directory.Packages.props
|
||||||
|
.gitignore = .gitignore
|
||||||
|
EndProjectSection
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
|||||||
@@ -1,357 +0,0 @@
|
|||||||
<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:String x:Key="/Default/CodeInspection/Browsers/Browsers/@EntryValue">C65+,E16+,FF58+,IE11+</s:String>
|
|
||||||
<s:String x:Key="/Default/CodeInspection/Highlighting/AnalysisEnabled/@EntryValue">VISIBLE_FILES</s:String>
|
|
||||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ArrangeThisQualifier/@EntryIndexedValue">DO_NOT_SHOW</s:String>
|
|
||||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=CSharpWarnings_003A_003ACS1591/@EntryIndexedValue">DO_NOT_SHOW</s:String>
|
|
||||||
<s:String x:Key="/Default/CodeStyle/CodeCleanup/Profiles/=Reformat_0020Code_0020IDE/@EntryIndexedValue"><?xml version="1.0" encoding="utf-16"?><Profile name="Reformat Code IDE"><CSReorderTypeMembers>True</CSReorderTypeMembers><CSCodeStyleAttributes ArrangeTypeAccessModifier="True" ArrangeTypeMemberAccessModifier="True" SortModifiers="True" RemoveRedundantParentheses="False" AddMissingParentheses="True" ArrangeBraces="True" ArrangeAttributes="True" ArrangeArgumentsStyle="False" ArrangeCodeBodyStyle="False" /><CSArrangeQualifiers>True</CSArrangeQualifiers><CSOptimizeUsings><OptimizeUsings>True</OptimizeUsings><EmbraceInRegion>False</EmbraceInRegion><RegionName></RegionName></CSOptimizeUsings><CSReformatCode>True</CSReformatCode><CSFixBuiltinTypeReferences>True</CSFixBuiltinTypeReferences><CSShortenReferences>True</CSShortenReferences><XAMLCollapseEmptyTags>False</XAMLCollapseEmptyTags></Profile></s:String>
|
|
||||||
<s:String x:Key="/Default/CodeStyle/CodeCleanup/Profiles/=StyleCop/@EntryIndexedValue"><?xml version="1.0" encoding="utf-16"?><Profile name="StyleCop"><CSUpdateFileHeader>False</CSUpdateFileHeader><CSArrangeQualifiers>True</CSArrangeQualifiers><CSOptimizeUsings><OptimizeUsings>True</OptimizeUsings><EmbraceInRegion>False</EmbraceInRegion><RegionName></RegionName></CSOptimizeUsings><CSReformatCode>True</CSReformatCode><CSReorderTypeMembers>True</CSReorderTypeMembers></Profile></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:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/ThisQualifier/INSTANCE_MEMBERS_QUALIFY_MEMBERS/@EntryValue">None</s:String>
|
|
||||||
<s:String x:Key="/Default/CodeStyle/CSharpFileLayoutPatterns/Pattern/@EntryValue"><?xml version="1.0" encoding="utf-16"?>
|
|
||||||
<Patterns xmlns="urn:schemas-jetbrains-com:member-reordering-patterns">
|
|
||||||
<TypePattern DisplayName="Non-reorderable types">
|
|
||||||
<TypePattern.Match>
|
|
||||||
<Or>
|
|
||||||
<And>
|
|
||||||
<Kind Is="Interface" />
|
|
||||||
<Or>
|
|
||||||
<HasAttribute Name="System.Runtime.InteropServices.InterfaceTypeAttribute" />
|
|
||||||
<HasAttribute Name="System.Runtime.InteropServices.ComImport" />
|
|
||||||
</Or>
|
|
||||||
</And>
|
|
||||||
<Kind Is="Struct" />
|
|
||||||
<HasAttribute Name="JetBrains.Annotations.NoReorderAttribute" />
|
|
||||||
<HasAttribute Name="JetBrains.Annotations.NoReorder" />
|
|
||||||
</Or>
|
|
||||||
</TypePattern.Match>
|
|
||||||
</TypePattern>
|
|
||||||
<TypePattern DisplayName="xUnit.net Test Classes" RemoveRegions="All">
|
|
||||||
<TypePattern.Match>
|
|
||||||
<And>
|
|
||||||
<Kind Is="Class" />
|
|
||||||
<HasMember>
|
|
||||||
<And>
|
|
||||||
<Kind Is="Method" />
|
|
||||||
<HasAttribute Name="Xunit.FactAttribute" Inherited="True" />
|
|
||||||
</And>
|
|
||||||
</HasMember>
|
|
||||||
</And>
|
|
||||||
</TypePattern.Match>
|
|
||||||
<Entry DisplayName="Setup/Teardown Methods">
|
|
||||||
<Entry.Match>
|
|
||||||
<Or>
|
|
||||||
<Kind Is="Constructor" />
|
|
||||||
<And>
|
|
||||||
<Kind Is="Method" />
|
|
||||||
<ImplementsInterface Name="System.IDisposable" />
|
|
||||||
</And>
|
|
||||||
</Or>
|
|
||||||
</Entry.Match>
|
|
||||||
<Entry.SortBy>
|
|
||||||
<Kind Order="Constructor" />
|
|
||||||
</Entry.SortBy>
|
|
||||||
</Entry>
|
|
||||||
<Entry DisplayName="All other members" />
|
|
||||||
<Entry DisplayName="Test Methods" Priority="100">
|
|
||||||
<Entry.Match>
|
|
||||||
<And>
|
|
||||||
<Kind Is="Method" />
|
|
||||||
<HasAttribute Name="Xunit.FactAttribute" />
|
|
||||||
</And>
|
|
||||||
</Entry.Match>
|
|
||||||
<Entry.SortBy>
|
|
||||||
<Name />
|
|
||||||
</Entry.SortBy>
|
|
||||||
</Entry>
|
|
||||||
</TypePattern>
|
|
||||||
<TypePattern DisplayName="NUnit Test Fixtures" RemoveRegions="All">
|
|
||||||
<TypePattern.Match>
|
|
||||||
<And>
|
|
||||||
<Kind Is="Class" />
|
|
||||||
<HasAttribute Name="NUnit.Framework.TestFixtureAttribute" Inherited="True" />
|
|
||||||
</And>
|
|
||||||
</TypePattern.Match>
|
|
||||||
<Entry DisplayName="Setup/Teardown Methods">
|
|
||||||
<Entry.Match>
|
|
||||||
<And>
|
|
||||||
<Kind Is="Method" />
|
|
||||||
<Or>
|
|
||||||
<HasAttribute Name="NUnit.Framework.SetUpAttribute" Inherited="True" />
|
|
||||||
<HasAttribute Name="NUnit.Framework.TearDownAttribute" Inherited="True" />
|
|
||||||
<HasAttribute Name="NUnit.Framework.FixtureSetUpAttribute" Inherited="True" />
|
|
||||||
<HasAttribute Name="NUnit.Framework.FixtureTearDownAttribute" Inherited="True" />
|
|
||||||
</Or>
|
|
||||||
</And>
|
|
||||||
</Entry.Match>
|
|
||||||
</Entry>
|
|
||||||
<Entry DisplayName="All other members" />
|
|
||||||
<Entry DisplayName="Test Methods" Priority="100">
|
|
||||||
<Entry.Match>
|
|
||||||
<And>
|
|
||||||
<Kind Is="Method" />
|
|
||||||
<HasAttribute Name="NUnit.Framework.TestAttribute" />
|
|
||||||
</And>
|
|
||||||
</Entry.Match>
|
|
||||||
<Entry.SortBy>
|
|
||||||
<Name />
|
|
||||||
</Entry.SortBy>
|
|
||||||
</Entry>
|
|
||||||
</TypePattern>
|
|
||||||
<TypePattern DisplayName="Default Pattern (StyleCop)" RemoveRegions="All">
|
|
||||||
<Entry DisplayName="Constants">
|
|
||||||
<Entry.Match>
|
|
||||||
<Kind Is="Constant" />
|
|
||||||
</Entry.Match>
|
|
||||||
<Entry.SortBy>
|
|
||||||
<Access Order="Public Internal ProtectedInternal Protected Private" />
|
|
||||||
<Name />
|
|
||||||
</Entry.SortBy>
|
|
||||||
</Entry>
|
|
||||||
<Entry DisplayName="Static fields">
|
|
||||||
<Entry.Match>
|
|
||||||
<And>
|
|
||||||
<Kind Is="Field" />
|
|
||||||
<Static />
|
|
||||||
</And>
|
|
||||||
</Entry.Match>
|
|
||||||
<Entry.SortBy>
|
|
||||||
<Access Order="Public Internal ProtectedInternal Protected Private" />
|
|
||||||
<Readonly />
|
|
||||||
<Name />
|
|
||||||
</Entry.SortBy>
|
|
||||||
</Entry>
|
|
||||||
<Entry DisplayName="Fields">
|
|
||||||
<Entry.Match>
|
|
||||||
<Kind Is="Field" />
|
|
||||||
</Entry.Match>
|
|
||||||
<Entry.SortBy>
|
|
||||||
<Access Order="Public Internal ProtectedInternal Protected Private" />
|
|
||||||
<Readonly />
|
|
||||||
<Name />
|
|
||||||
</Entry.SortBy>
|
|
||||||
</Entry>
|
|
||||||
<Entry DisplayName="Constructors and Destructors" Priority="200">
|
|
||||||
<Entry.Match>
|
|
||||||
<Or>
|
|
||||||
<Kind Is="Constructor" />
|
|
||||||
<Kind Is="Destructor" />
|
|
||||||
</Or>
|
|
||||||
</Entry.Match>
|
|
||||||
<Entry.SortBy>
|
|
||||||
<Static />
|
|
||||||
<Kind Order="Constructor Destructor" />
|
|
||||||
<Access Order="Public Internal ProtectedInternal Protected Private" />
|
|
||||||
</Entry.SortBy>
|
|
||||||
</Entry>
|
|
||||||
<Entry DisplayName="Delegates">
|
|
||||||
<Entry.Match>
|
|
||||||
<Kind Is="Delegate" />
|
|
||||||
</Entry.Match>
|
|
||||||
<Entry.SortBy>
|
|
||||||
<Access Order="Public Internal ProtectedInternal Protected Private" />
|
|
||||||
<Static />
|
|
||||||
<Name />
|
|
||||||
</Entry.SortBy>
|
|
||||||
</Entry>
|
|
||||||
<Entry DisplayName="Public events">
|
|
||||||
<Entry.Match>
|
|
||||||
<And>
|
|
||||||
<Kind Is="Event" />
|
|
||||||
<Access Is="Public" />
|
|
||||||
</And>
|
|
||||||
</Entry.Match>
|
|
||||||
<Entry.SortBy>
|
|
||||||
<Access Order="Public" />
|
|
||||||
<Static />
|
|
||||||
<Name />
|
|
||||||
</Entry.SortBy>
|
|
||||||
</Entry>
|
|
||||||
<Entry DisplayName="Interface events">
|
|
||||||
<Entry.Match>
|
|
||||||
<And>
|
|
||||||
<Kind Is="Event" />
|
|
||||||
<ImplementsInterface />
|
|
||||||
</And>
|
|
||||||
</Entry.Match>
|
|
||||||
<Entry.SortBy>
|
|
||||||
<ImplementsInterface Immediate="True" />
|
|
||||||
<Name />
|
|
||||||
</Entry.SortBy>
|
|
||||||
</Entry>
|
|
||||||
<Entry DisplayName="Other events">
|
|
||||||
<Entry.Match>
|
|
||||||
<Kind Is="Event" />
|
|
||||||
</Entry.Match>
|
|
||||||
<Entry.SortBy>
|
|
||||||
<Access Order="Public Internal ProtectedInternal Protected Private" />
|
|
||||||
<Static />
|
|
||||||
<Name />
|
|
||||||
</Entry.SortBy>
|
|
||||||
</Entry>
|
|
||||||
<Entry DisplayName="Enums">
|
|
||||||
<Entry.Match>
|
|
||||||
<Kind Is="Enum" />
|
|
||||||
</Entry.Match>
|
|
||||||
<Entry.SortBy>
|
|
||||||
<Access Order="Public Internal ProtectedInternal Protected Private" />
|
|
||||||
<Name />
|
|
||||||
</Entry.SortBy>
|
|
||||||
</Entry>
|
|
||||||
<Entry DisplayName="Interfaces">
|
|
||||||
<Entry.Match>
|
|
||||||
<Kind Is="Interface" />
|
|
||||||
</Entry.Match>
|
|
||||||
<Entry.SortBy>
|
|
||||||
<Access Order="Public Internal ProtectedInternal Protected Private" />
|
|
||||||
<Name />
|
|
||||||
</Entry.SortBy>
|
|
||||||
</Entry>
|
|
||||||
<Entry DisplayName="Public properties">
|
|
||||||
<Entry.Match>
|
|
||||||
<And>
|
|
||||||
<Kind Is="Property" />
|
|
||||||
<Access Is="Public" />
|
|
||||||
</And>
|
|
||||||
</Entry.Match>
|
|
||||||
<Entry.SortBy>
|
|
||||||
<Static />
|
|
||||||
<Name />
|
|
||||||
</Entry.SortBy>
|
|
||||||
</Entry>
|
|
||||||
<Entry DisplayName="Interface properties">
|
|
||||||
<Entry.Match>
|
|
||||||
<And>
|
|
||||||
<Kind Is="Property" />
|
|
||||||
<ImplementsInterface />
|
|
||||||
</And>
|
|
||||||
</Entry.Match>
|
|
||||||
<Entry.SortBy>
|
|
||||||
<ImplementsInterface Immediate="True" />
|
|
||||||
<Name />
|
|
||||||
</Entry.SortBy>
|
|
||||||
</Entry>
|
|
||||||
<Entry DisplayName="Other properties">
|
|
||||||
<Entry.Match>
|
|
||||||
<Kind Is="Property" />
|
|
||||||
</Entry.Match>
|
|
||||||
<Entry.SortBy>
|
|
||||||
<Access Order="Public Internal ProtectedInternal Protected Private" />
|
|
||||||
<Static />
|
|
||||||
<Name />
|
|
||||||
</Entry.SortBy>
|
|
||||||
</Entry>
|
|
||||||
<Entry DisplayName="Public indexers" Priority="1000">
|
|
||||||
<Entry.Match>
|
|
||||||
<And>
|
|
||||||
<Kind Is="Indexer" />
|
|
||||||
<Access Is="Public" />
|
|
||||||
</And>
|
|
||||||
</Entry.Match>
|
|
||||||
<Entry.SortBy>
|
|
||||||
<Static />
|
|
||||||
<Name />
|
|
||||||
</Entry.SortBy>
|
|
||||||
</Entry>
|
|
||||||
<Entry DisplayName="Interface indexers" Priority="1000">
|
|
||||||
<Entry.Match>
|
|
||||||
<And>
|
|
||||||
<Kind Is="Indexer" />
|
|
||||||
<ImplementsInterface />
|
|
||||||
</And>
|
|
||||||
</Entry.Match>
|
|
||||||
<Entry.SortBy>
|
|
||||||
<ImplementsInterface Immediate="True" />
|
|
||||||
<Name />
|
|
||||||
</Entry.SortBy>
|
|
||||||
</Entry>
|
|
||||||
<Entry DisplayName="Other indexers" Priority="1000">
|
|
||||||
<Entry.Match>
|
|
||||||
<Kind Is="Indexer" />
|
|
||||||
</Entry.Match>
|
|
||||||
<Entry.SortBy>
|
|
||||||
<Access Order="Public Internal ProtectedInternal Protected Private" />
|
|
||||||
<Static />
|
|
||||||
<Name />
|
|
||||||
</Entry.SortBy>
|
|
||||||
</Entry>
|
|
||||||
<Entry DisplayName="Public methods and operators">
|
|
||||||
<Entry.Match>
|
|
||||||
<And>
|
|
||||||
<Or>
|
|
||||||
<Kind Is="Method" />
|
|
||||||
<Kind Is="Operator" />
|
|
||||||
</Or>
|
|
||||||
<Access Is="Public" />
|
|
||||||
</And>
|
|
||||||
</Entry.Match>
|
|
||||||
<Entry.SortBy>
|
|
||||||
<Static />
|
|
||||||
<Name />
|
|
||||||
</Entry.SortBy>
|
|
||||||
</Entry>
|
|
||||||
<Entry DisplayName="Interface methods">
|
|
||||||
<Entry.Match>
|
|
||||||
<And>
|
|
||||||
<Kind Is="Method" />
|
|
||||||
<ImplementsInterface />
|
|
||||||
</And>
|
|
||||||
</Entry.Match>
|
|
||||||
<Entry.SortBy>
|
|
||||||
<ImplementsInterface Immediate="True" />
|
|
||||||
<Name />
|
|
||||||
</Entry.SortBy>
|
|
||||||
</Entry>
|
|
||||||
<Entry DisplayName="Other methods">
|
|
||||||
<Entry.Match>
|
|
||||||
<Kind Is="Method" />
|
|
||||||
</Entry.Match>
|
|
||||||
<Entry.SortBy>
|
|
||||||
<Access Order="Public Internal ProtectedInternal Protected Private" />
|
|
||||||
<Static />
|
|
||||||
<Name />
|
|
||||||
</Entry.SortBy>
|
|
||||||
</Entry>
|
|
||||||
<Entry DisplayName="Operators">
|
|
||||||
<Entry.Match>
|
|
||||||
<Kind Is="Operator" />
|
|
||||||
</Entry.Match>
|
|
||||||
<Entry.SortBy>
|
|
||||||
<Access Order="Public Internal ProtectedInternal Protected Private" />
|
|
||||||
<Static />
|
|
||||||
<Name />
|
|
||||||
</Entry.SortBy>
|
|
||||||
</Entry>
|
|
||||||
<Entry DisplayName="Nested structs" Priority="600">
|
|
||||||
<Entry.Match>
|
|
||||||
<Kind Is="Struct" />
|
|
||||||
</Entry.Match>
|
|
||||||
<Entry.SortBy>
|
|
||||||
<Static />
|
|
||||||
<Access Order="Public Internal ProtectedInternal Protected Private" />
|
|
||||||
<Name />
|
|
||||||
</Entry.SortBy>
|
|
||||||
</Entry>
|
|
||||||
<Entry DisplayName="Nested classes" Priority="700">
|
|
||||||
<Entry.Match>
|
|
||||||
<Kind Is="Class" />
|
|
||||||
</Entry.Match>
|
|
||||||
<Entry.SortBy>
|
|
||||||
<Static />
|
|
||||||
<Access Order="Public Internal ProtectedInternal Protected Private" />
|
|
||||||
<Name />
|
|
||||||
</Entry.SortBy>
|
|
||||||
</Entry>
|
|
||||||
<Entry DisplayName="All other members" />
|
|
||||||
</TypePattern>
|
|
||||||
</Patterns></s:String>
|
|
||||||
<s:String x:Key="/Default/CodeStyle/CSharpUsing/KeepImports/=System/@EntryIndexedValue">System</s:String>
|
|
||||||
<s:String x:Key="/Default/CodeStyle/CSharpUsing/KeepImports/=System_002ELinq/@EntryIndexedValue">System.Linq</s:String>
|
|
||||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=MB/@EntryIndexedValue">MB</s:String>
|
|
||||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=LocalConstants/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></s:String>
|
|
||||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateInstanceFields/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String>
|
|
||||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateStaticFields/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String>
|
|
||||||
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EAlwaysTreatStructAsNotReorderableMigration/@EntryIndexedValue">True</s:Boolean>
|
|
||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Dtos/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
using Microsoft.OpenApi.Models;
|
using Microsoft.OpenApi;
|
||||||
|
|
||||||
namespace Rsdo.Concordancer.Api.Controllers;
|
namespace Rsdo.Concordancer.Api.Controllers;
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,12 @@
|
|||||||
FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS base
|
FROM mcr.microsoft.com/dotnet/aspnet:10.0 AS base
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
EXPOSE 80
|
EXPOSE 80
|
||||||
|
|
||||||
FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build
|
FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build
|
||||||
|
|
||||||
|
# COPY SHARED MSBUILD CONFIGURATION
|
||||||
|
COPY src/Directory.Build.props /src/Directory.Build.props
|
||||||
|
COPY src/Directory.Packages.props /src/Directory.Packages.props
|
||||||
|
|
||||||
# INSTALL NODE.JS
|
# INSTALL NODE.JS
|
||||||
RUN curl -fsSL https://deb.nodesource.com/setup_16.x | bash - \
|
RUN curl -fsSL https://deb.nodesource.com/setup_16.x | bash - \
|
||||||
@@ -10,13 +14,6 @@ RUN curl -fsSL https://deb.nodesource.com/setup_16.x | bash - \
|
|||||||
nodejs \
|
nodejs \
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
# COPY LOCAL NUGET PACKAGES
|
|
||||||
WORKDIR /nuget
|
|
||||||
COPY local-packages/. .
|
|
||||||
|
|
||||||
# ADD LOCAL NUGET SOURCE
|
|
||||||
RUN dotnet nuget add source /nuget
|
|
||||||
|
|
||||||
# RESTORE PACKAGES (with project files only)
|
# RESTORE PACKAGES (with project files only)
|
||||||
WORKDIR /src/apps
|
WORKDIR /src/apps
|
||||||
COPY src/apps/Rsdo.Concordancer.Api/Rsdo.Concordancer.Api.csproj Rsdo.Concordancer.Api/Rsdo.Concordancer.Api.csproj
|
COPY src/apps/Rsdo.Concordancer.Api/Rsdo.Concordancer.Api.csproj Rsdo.Concordancer.Api/Rsdo.Concordancer.Api.csproj
|
||||||
@@ -57,4 +54,4 @@ RUN dotnet publish "Rsdo.Concordancer.Api.csproj" -c Release -o /app/publish
|
|||||||
FROM base AS final
|
FROM base AS final
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
COPY --from=publish /app/publish .
|
COPY --from=publish /app/publish .
|
||||||
ENTRYPOINT ["dotnet", "Rsdo.Concordancer.Api.dll"]
|
ENTRYPOINT ["dotnet", "Rsdo.Concordancer.Api.dll"]
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
|
using MailKit.Security;
|
||||||
using Serilog;
|
using Serilog;
|
||||||
using Serilog.Configuration;
|
using Serilog.Configuration;
|
||||||
using Serilog.Events;
|
using Serilog.Events;
|
||||||
using Serilog.Sinks.Email;
|
|
||||||
|
|
||||||
namespace Rsdo.Concordancer.Api.Framework;
|
namespace Rsdo.Concordancer.Api.Framework;
|
||||||
|
|
||||||
@@ -23,25 +23,25 @@ public static class SerilogExtensions
|
|||||||
int batchPostingLimit = 100,
|
int batchPostingLimit = 100,
|
||||||
string mailSubject = "Log Email")
|
string mailSubject = "Log Email")
|
||||||
{
|
{
|
||||||
var connectionInfo = new EmailConnectionInfo()
|
NetworkCredential credentials = null;
|
||||||
{
|
|
||||||
FromEmail = fromEmail,
|
|
||||||
ToEmail = toEmail,
|
|
||||||
EmailSubject = mailSubject,
|
|
||||||
MailServer = mailServer,
|
|
||||||
Port = port,
|
|
||||||
EnableSsl = enableSsl,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(userName) && !string.IsNullOrEmpty(password))
|
if (!string.IsNullOrEmpty(userName) && !string.IsNullOrEmpty(password))
|
||||||
{
|
{
|
||||||
connectionInfo.NetworkCredentials = new NetworkCredential()
|
credentials = new NetworkCredential()
|
||||||
{
|
{
|
||||||
UserName = userName,
|
UserName = userName,
|
||||||
Password = password,
|
Password = password,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return sinkConfiguration.Email(connectionInfo: connectionInfo, restrictedToMinimumLevel: restrictedToMinimumLevel);
|
return sinkConfiguration.Email(
|
||||||
|
from: fromEmail,
|
||||||
|
to: toEmail,
|
||||||
|
host: mailServer,
|
||||||
|
port: port,
|
||||||
|
connectionSecurity: enableSsl ? SecureSocketOptions.Auto : SecureSocketOptions.None,
|
||||||
|
credentials: credentials,
|
||||||
|
subject: mailSubject,
|
||||||
|
body: outputTemplate,
|
||||||
|
restrictedToMinimumLevel: restrictedToMinimumLevel);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,52 +1,146 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
using Autofac;
|
||||||
using Autofac.Extensions.DependencyInjection;
|
using Autofac.Extensions.DependencyInjection;
|
||||||
using Microsoft.AspNetCore.Hosting;
|
using Hangfire;
|
||||||
using Microsoft.Extensions.Configuration;
|
using Hangfire.PostgreSql;
|
||||||
|
using Microsoft.AspNetCore.Builder;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.Extensions.Hosting;
|
using Microsoft.Extensions.Hosting;
|
||||||
|
using Microsoft.OpenApi;
|
||||||
|
using Rsdo.Concordancer.Api.Controllers;
|
||||||
|
using Rsdo.Concordancer.Api.Framework;
|
||||||
|
using Rsdo.Concordancer.Core.Constants;
|
||||||
|
using Rsdo.Concordancer.Data.CompositionRoot;
|
||||||
|
using Rsdo.Concordancer.Infrastructure.CompositionRoot;
|
||||||
|
using Rsdo.Concordancer.ServiceModel.Shared;
|
||||||
|
using Rsdo.Concordancer.Services.CompositionRoot;
|
||||||
|
using Rsdo.Concordancer.Services.Framework.Cache;
|
||||||
using Serilog;
|
using Serilog;
|
||||||
|
|
||||||
namespace Rsdo.Concordancer.Api;
|
var builder = WebApplication.CreateBuilder(
|
||||||
|
new WebApplicationOptions()
|
||||||
public class Program
|
|
||||||
{
|
|
||||||
public static int Main(string[] args)
|
|
||||||
{
|
{
|
||||||
// Read configuration file
|
Args = args,
|
||||||
var configuration = new ConfigurationBuilder().SetBasePath(Directory.GetCurrentDirectory())
|
WebRootPath = "./WebApp/build",
|
||||||
.AddJsonFile("appsettings.json")
|
});
|
||||||
.AddJsonFile($"appsettings.{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") ?? "Production"}.json", true)
|
|
||||||
.Build();
|
|
||||||
|
|
||||||
// Create logger
|
builder.Host.UseSerilog(
|
||||||
Log.Logger = new LoggerConfiguration().ReadFrom.Configuration(configuration).CreateLogger();
|
(context, _, loggerConfiguration) =>
|
||||||
|
{
|
||||||
|
loggerConfiguration.ReadFrom.Configuration(context.Configuration);
|
||||||
|
});
|
||||||
|
|
||||||
// Run application
|
builder.Host.UseServiceProviderFactory(new AutofacServiceProviderFactory());
|
||||||
try
|
builder.Host.ConfigureContainer<ContainerBuilder>(
|
||||||
{
|
containerBuilder =>
|
||||||
Log.Information("Starting web host");
|
{
|
||||||
CreateHostBuilder(args).Build().Run();
|
containerBuilder.RegisterModule(new ServicesModule());
|
||||||
return 0;
|
containerBuilder.RegisterModule(new InfrastructureModule());
|
||||||
}
|
containerBuilder.RegisterModule(new DataModule());
|
||||||
catch (Exception e)
|
containerBuilder.RegisterBuildCallback(
|
||||||
{
|
(c) =>
|
||||||
Log.Fatal(e, "Host terminated unexpectedly");
|
{
|
||||||
return 1;
|
var warmUps = c.Resolve<IEnumerable<ICacheWarmUp>>();
|
||||||
}
|
foreach (var warmUp in warmUps)
|
||||||
finally
|
|
||||||
{
|
|
||||||
Log.CloseAndFlush();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IHostBuilder CreateHostBuilder(string[] args) =>
|
|
||||||
Host.CreateDefaultBuilder(args)
|
|
||||||
.UseSerilog()
|
|
||||||
.UseServiceProviderFactory(new AutofacServiceProviderFactory())
|
|
||||||
.ConfigureWebHostDefaults(
|
|
||||||
webBuilder =>
|
|
||||||
{
|
{
|
||||||
webBuilder.UseStartup<Startup>();
|
warmUp.WarmUp();
|
||||||
webBuilder.UseWebRoot("./WebApp/build");
|
}
|
||||||
});
|
});
|
||||||
}
|
});
|
||||||
|
|
||||||
|
builder.Services.AddCors(
|
||||||
|
opt =>
|
||||||
|
{
|
||||||
|
opt.AddPolicy(
|
||||||
|
"CorsPolicy",
|
||||||
|
policy =>
|
||||||
|
{
|
||||||
|
policy.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
builder.Services.AddControllers()
|
||||||
|
.AddJsonOptions(
|
||||||
|
opts =>
|
||||||
|
{
|
||||||
|
// Bind strings to enums
|
||||||
|
opts.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter());
|
||||||
|
});
|
||||||
|
|
||||||
|
builder.Services.AddSwaggerGen(
|
||||||
|
c =>
|
||||||
|
{
|
||||||
|
c.SwaggerDoc(
|
||||||
|
ServiceApiInfo.ApiGroupConcordancer,
|
||||||
|
info: new OpenApiInfo()
|
||||||
|
{
|
||||||
|
Title = $"{ServiceApiInfo.ServiceName} Concordancer API",
|
||||||
|
Version = $"v{ServiceApiInfo.ServiceVersion.ToString(3)}",
|
||||||
|
});
|
||||||
|
c.SwaggerDoc(
|
||||||
|
ServiceApiInfo.ApiGroupDashboard,
|
||||||
|
info: new OpenApiInfo()
|
||||||
|
{
|
||||||
|
Title = $"{ServiceApiInfo.ServiceName} Dashboard API",
|
||||||
|
Version = $"v{ServiceApiInfo.ServiceVersion.ToString(3)}",
|
||||||
|
});
|
||||||
|
|
||||||
|
// enable attribute annotations
|
||||||
|
c.EnableAnnotations();
|
||||||
|
|
||||||
|
// include code documentation to the swagger doc
|
||||||
|
foreach (var assembly in new[] { Assembly.GetExecutingAssembly(), typeof(ExecutionResult).Assembly })
|
||||||
|
{
|
||||||
|
var xmlFile = $"{assembly.GetName().Name}.xml";
|
||||||
|
var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
|
||||||
|
c.IncludeXmlComments(xmlPath);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
builder.Services.AddHangfire(
|
||||||
|
x =>
|
||||||
|
{
|
||||||
|
// It would be better to use ConnectionStringProvider, but in this case
|
||||||
|
// we would have to build the container which would (at this point) double singletons.
|
||||||
|
// So we are duplicated code from ConnectionStringProvider
|
||||||
|
var connectionString = builder.Configuration[ConfigurationKey.Database.MasterConnectionString];
|
||||||
|
x.UsePostgreSqlStorage(
|
||||||
|
options =>
|
||||||
|
{
|
||||||
|
options.UseNpgsqlConnection(connectionString);
|
||||||
|
});
|
||||||
|
x.UseMediator();
|
||||||
|
});
|
||||||
|
|
||||||
|
builder.Services.AddHangfireServer();
|
||||||
|
builder.Services.AddHttpClient();
|
||||||
|
|
||||||
|
var app = builder.Build();
|
||||||
|
|
||||||
|
if (app.Environment.IsDevelopment())
|
||||||
|
{
|
||||||
|
app.UseDeveloperExceptionPage();
|
||||||
|
}
|
||||||
|
|
||||||
|
app.UseSwagger();
|
||||||
|
app.UseSwaggerUI(
|
||||||
|
c =>
|
||||||
|
{
|
||||||
|
c.SwaggerEndpoint($"{ServiceApiInfo.ApiGroupConcordancer}/swagger.json", $"{ServiceApiInfo.ServiceName} Concordancer API");
|
||||||
|
c.SwaggerEndpoint($"{ServiceApiInfo.ApiGroupDashboard}/swagger.json", $"{ServiceApiInfo.ServiceName} Dashboard API");
|
||||||
|
});
|
||||||
|
|
||||||
|
app.UseStaticFiles();
|
||||||
|
app.UseRouting();
|
||||||
|
app.UseCors("CorsPolicy");
|
||||||
|
app.UseAuthorization();
|
||||||
|
|
||||||
|
app.MapControllers();
|
||||||
|
app.MapHangfireDashboard("/hangfire");
|
||||||
|
app.MapFallbackToFile("index.html");
|
||||||
|
|
||||||
|
app.Run();
|
||||||
@@ -1,31 +1,25 @@
|
|||||||
{
|
{
|
||||||
"$schema": "http://json.schemastore.org/launchsettings.json",
|
"$schema": "https://json.schemastore.org/launchsettings.json",
|
||||||
"iisSettings": {
|
"profiles": {
|
||||||
"windowsAuthentication": false,
|
"http": {
|
||||||
"anonymousAuthentication": true,
|
"commandName": "Project",
|
||||||
"iisExpress": {
|
"dotnetRunMessages": true,
|
||||||
"applicationUrl": "http://localhost:9184",
|
"launchBrowser": true,
|
||||||
"sslPort": 44312
|
"launchUrl": "swagger/index.html",
|
||||||
|
"applicationUrl": "http://localhost:5000",
|
||||||
|
"environmentVariables": {
|
||||||
|
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"https": {
|
||||||
|
"commandName": "Project",
|
||||||
|
"dotnetRunMessages": true,
|
||||||
|
"launchBrowser": true,
|
||||||
|
"launchUrl": "swagger/index.html",
|
||||||
|
"applicationUrl": "https://localhost:5001;http://localhost:5000",
|
||||||
|
"environmentVariables": {
|
||||||
|
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
"profiles": {
|
|
||||||
"IIS Express": {
|
|
||||||
"commandName": "IISExpress",
|
|
||||||
"launchBrowser": true,
|
|
||||||
"launchUrl": "swagger",
|
|
||||||
"environmentVariables": {
|
|
||||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"Rsdo.Concordancer.Api": {
|
|
||||||
"commandName": "Project",
|
|
||||||
"dotnetRunMessages": "true",
|
|
||||||
"launchBrowser": true,
|
|
||||||
"launchUrl": "swagger",
|
|
||||||
"applicationUrl": "https://localhost:5001;http://localhost:5000",
|
|
||||||
"environmentVariables": {
|
|
||||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,27 +1,19 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||||
|
|
||||||
<PropertyGroup>
|
|
||||||
<TargetFramework>net6.0</TargetFramework>
|
|
||||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
|
||||||
<EnableNETAnalyzers>false</EnableNETAnalyzers>
|
|
||||||
<Version>1.0.1</Version>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Autofac" Version="6.4.0" />
|
<PackageReference Include="Autofac" />
|
||||||
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="8.0.0" />
|
<PackageReference Include="Autofac.Extensions.DependencyInjection" />
|
||||||
<PackageReference Include="Hangfire" Version="1.7.31" />
|
<PackageReference Include="Hangfire" />
|
||||||
<PackageReference Include="Hangfire.PostgreSql" Version="1.9.9" />
|
<PackageReference Include="Hangfire.PostgreSql" />
|
||||||
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="6.0.10" />
|
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" />
|
||||||
<PackageReference Include="Rsdo.StyleCop" Version="1.0.0" />
|
<PackageReference Include="Serilog.AspNetCore" />
|
||||||
<PackageReference Include="Serilog.AspNetCore" Version="6.0.1" />
|
<PackageReference Include="Serilog.Expressions" />
|
||||||
<PackageReference Include="Serilog.Expressions" Version="3.4.1" />
|
<PackageReference Include="Serilog.Settings.Configuration" />
|
||||||
<PackageReference Include="Serilog.Settings.Configuration" Version="3.4.0" />
|
<PackageReference Include="Serilog.Sinks.Console" />
|
||||||
<PackageReference Include="Serilog.Sinks.Console" Version="4.1.0" />
|
<PackageReference Include="Serilog.Sinks.Email" />
|
||||||
<PackageReference Include="Serilog.Sinks.Email" Version="2.4.0" />
|
<PackageReference Include="Serilog.Sinks.File" />
|
||||||
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0" />
|
<PackageReference Include="Swashbuckle.AspNetCore" />
|
||||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" />
|
<PackageReference Include="Swashbuckle.AspNetCore.Annotations" />
|
||||||
<PackageReference Include="Swashbuckle.AspNetCore.Annotations" Version="6.4.0" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -1,150 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Reflection;
|
|
||||||
using System.Text.Json.Serialization;
|
|
||||||
using Autofac;
|
|
||||||
using Hangfire;
|
|
||||||
using Hangfire.PostgreSql;
|
|
||||||
using Microsoft.AspNetCore.Builder;
|
|
||||||
using Microsoft.AspNetCore.Hosting;
|
|
||||||
using Microsoft.Extensions.Configuration;
|
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
|
||||||
using Microsoft.Extensions.Hosting;
|
|
||||||
using Microsoft.OpenApi.Models;
|
|
||||||
using Rsdo.Concordancer.Api.Controllers;
|
|
||||||
using Rsdo.Concordancer.Api.Framework;
|
|
||||||
using Rsdo.Concordancer.Core.Constants;
|
|
||||||
using Rsdo.Concordancer.Data.CompositionRoot;
|
|
||||||
using Rsdo.Concordancer.Infrastructure.CompositionRoot;
|
|
||||||
using Rsdo.Concordancer.ServiceModel.Shared;
|
|
||||||
using Rsdo.Concordancer.Services.CompositionRoot;
|
|
||||||
using Rsdo.Concordancer.Services.Framework.Cache;
|
|
||||||
using Swashbuckle.AspNetCore.SwaggerGen;
|
|
||||||
|
|
||||||
namespace Rsdo.Concordancer.Api;
|
|
||||||
|
|
||||||
public class Startup
|
|
||||||
{
|
|
||||||
public Startup(IConfiguration configuration)
|
|
||||||
{
|
|
||||||
Configuration = configuration;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IConfiguration Configuration { get; }
|
|
||||||
|
|
||||||
// This method gets called by the runtime. Use this method to add services to the container.
|
|
||||||
public void ConfigureServices(IServiceCollection services)
|
|
||||||
{
|
|
||||||
services.AddCors(
|
|
||||||
opt =>
|
|
||||||
{
|
|
||||||
opt.AddPolicy(
|
|
||||||
"CorsPolicy",
|
|
||||||
policy =>
|
|
||||||
{
|
|
||||||
policy.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
services.AddControllers()
|
|
||||||
.AddJsonOptions(
|
|
||||||
opts =>
|
|
||||||
{
|
|
||||||
// Bind strings to enums
|
|
||||||
opts.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter());
|
|
||||||
});
|
|
||||||
services.AddSwaggerGen(
|
|
||||||
c =>
|
|
||||||
{
|
|
||||||
c.SwaggerDoc(
|
|
||||||
ServiceApiInfo.ApiGroupConcordancer,
|
|
||||||
info: new OpenApiInfo()
|
|
||||||
{
|
|
||||||
Title = $"{ServiceApiInfo.ServiceName} Concordancer API",
|
|
||||||
Version = $"v{ServiceApiInfo.ServiceVersion.ToString(3)}",
|
|
||||||
});
|
|
||||||
c.SwaggerDoc(
|
|
||||||
ServiceApiInfo.ApiGroupDashboard,
|
|
||||||
info: new OpenApiInfo()
|
|
||||||
{
|
|
||||||
Title = $"{ServiceApiInfo.ServiceName} Dashboard API",
|
|
||||||
Version = $"v{ServiceApiInfo.ServiceVersion.ToString(3)}",
|
|
||||||
});
|
|
||||||
|
|
||||||
// enable attribute annotations
|
|
||||||
c.EnableAnnotations();
|
|
||||||
|
|
||||||
// include code documentation to the swagger doc
|
|
||||||
ConfigureSwaggerApiDoc(c, Assembly.GetExecutingAssembly(), typeof(ExecutionResult).Assembly);
|
|
||||||
});
|
|
||||||
services.AddHangfire(
|
|
||||||
x =>
|
|
||||||
{
|
|
||||||
// It would be better to use ConnectionStringProvider, but in this case
|
|
||||||
// we would have to build the container which would (at this point) double singletons.
|
|
||||||
// So we are duplicated code from ConnectionStringProvider
|
|
||||||
var connectionString = Configuration[ConfigurationKey.Database.MasterConnectionString];
|
|
||||||
x.UsePostgreSqlStorage(connectionString);
|
|
||||||
x.UseMediator();
|
|
||||||
});
|
|
||||||
services.AddHangfireServer();
|
|
||||||
services.AddHttpClient();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ConfigureSwaggerApiDoc(SwaggerGenOptions options, params Assembly[] assemblies)
|
|
||||||
{
|
|
||||||
foreach (var assembly in assemblies)
|
|
||||||
{
|
|
||||||
var xmlFile = $"{assembly.GetName().Name}.xml";
|
|
||||||
var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
|
|
||||||
options.IncludeXmlComments(xmlPath);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ConfigureContainer(ContainerBuilder builder)
|
|
||||||
{
|
|
||||||
builder.RegisterModule(new ServicesModule());
|
|
||||||
builder.RegisterModule(new InfrastructureModule());
|
|
||||||
builder.RegisterModule(new DataModule());
|
|
||||||
builder.RegisterBuildCallback(
|
|
||||||
(c) =>
|
|
||||||
{
|
|
||||||
var warmUps = c.Resolve<IEnumerable<ICacheWarmUp>>();
|
|
||||||
foreach (var warmUp in warmUps)
|
|
||||||
{
|
|
||||||
warmUp.WarmUp();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
|
|
||||||
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
|
|
||||||
{
|
|
||||||
if (env.IsDevelopment())
|
|
||||||
{
|
|
||||||
app.UseDeveloperExceptionPage();
|
|
||||||
}
|
|
||||||
|
|
||||||
app.UseSwagger();
|
|
||||||
app.UseSwaggerUI(
|
|
||||||
c =>
|
|
||||||
{
|
|
||||||
c.SwaggerEndpoint($"{ServiceApiInfo.ApiGroupConcordancer}/swagger.json", $"{ServiceApiInfo.ServiceName} Concordancer API");
|
|
||||||
c.SwaggerEndpoint($"{ServiceApiInfo.ApiGroupDashboard}/swagger.json", $"{ServiceApiInfo.ServiceName} Dashboard API");
|
|
||||||
});
|
|
||||||
|
|
||||||
app.UseStaticFiles();
|
|
||||||
app.UseRouting();
|
|
||||||
app.UseCors("CorsPolicy");
|
|
||||||
app.UseAuthorization();
|
|
||||||
|
|
||||||
app.UseEndpoints(
|
|
||||||
endpoints =>
|
|
||||||
{
|
|
||||||
endpoints.MapControllers();
|
|
||||||
endpoints.MapHangfireDashboard("/hangfire");
|
|
||||||
endpoints.MapFallbackToFile("index.html");
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
<svg width="8" height="12" viewBox="0 0 8 12" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M6.8297 5.28995L2.5897 1.04995C2.49674 0.95622 2.38613 0.881826 2.26428 0.831057C2.14242 0.780288 2.01171 0.75415 1.8797 0.75415C1.74769 0.75415 1.61698 0.780288 1.49512 0.831057C1.37326 0.881826 1.26266 0.95622 1.1697 1.04995C0.983448 1.23731 0.878906 1.49076 0.878906 1.75495C0.878906 2.01913 0.983448 2.27259 1.1697 2.45995L4.7097 5.99995L1.1697 9.53995C0.983448 9.72731 0.878906 9.98076 0.878906 10.2449C0.878906 10.5091 0.983448 10.7626 1.1697 10.9499C1.26314 11.0426 1.37395 11.116 1.49579 11.1657C1.61763 11.2155 1.74809 11.2407 1.8797 11.2399C2.01131 11.2407 2.14177 11.2155 2.26361 11.1657C2.38544 11.116 2.49626 11.0426 2.5897 10.9499L6.8297 6.70995C6.92343 6.61699 6.99782 6.50638 7.04859 6.38453C7.09936 6.26267 7.1255 6.13196 7.1255 5.99995C7.1255 5.86794 7.09936 5.73723 7.04859 5.61537C6.99782 5.49351 6.92343 5.38291 6.8297 5.28995Z" fill="#848C91"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 977 B |
@@ -0,0 +1,4 @@
|
|||||||
|
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M1.5 3.75C1.5 2.50736 2.50736 1.5 3.75 1.5H14.25C15.4926 1.5 16.5 2.50736 16.5 3.75V14.25C16.5 15.4926 15.4926 16.5 14.25 16.5H3.75C2.50736 16.5 1.5 15.4926 1.5 14.25V3.75Z" fill="#006CB7"/>
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M12.6857 6.21973C12.9786 6.51262 12.9786 6.98749 12.6857 7.28039L8.03033 12.1554C7.73744 12.4483 7.26256 12.4483 6.96967 12.1554L4.71967 9.90539C4.42678 9.61249 4.42678 9.13762 4.71967 8.84473C5.01256 8.55183 5.48744 8.55183 5.78033 8.84473L7.5 10.5644L11.625 6.21973C11.9179 5.92683 12.3928 5.92683 12.6857 6.21973Z" fill="white"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 725 B |
+14
-2
@@ -1,15 +1,27 @@
|
|||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
import useSearch from '../../hooks/use-search';
|
import useSearch from '../../hooks/use-search';
|
||||||
import styles from './ConcordanceAggregationItem.module.scss';
|
import styles from './ConcordanceAggregationItem.module.scss';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
|
import selectIcon from '../../assets/chevron-right.svg';
|
||||||
|
import selectedIcon from '../../assets/square-checkbox-solid.svg';
|
||||||
|
|
||||||
const ConcordanceAggregationItem = (props) => {
|
const ConcordanceAggregationItem = (props) => {
|
||||||
|
const { t } = useTranslation();
|
||||||
const search = useSearch();
|
const search = useSearch();
|
||||||
const isSelected = search.isFiltered('TextIds', props.filterKey) === true;
|
const isSelected = search.isFiltered('TextIds', props.filterKey) === true;
|
||||||
const link = isSelected ? search.getClearFilterLink('TextIds', props.filterKey) : search.getFilterLink('TextIds', props.filterKey);
|
const link = isSelected ? search.getClearFilterLink('TextIds', props.filterKey) : search.getFilterLink('TextIds', props.filterKey);
|
||||||
|
|
||||||
|
let icon;
|
||||||
|
if (isSelected) {
|
||||||
|
icon = <img src={selectedIcon} alt={t('shared.unselect')} />;
|
||||||
|
} else {
|
||||||
|
icon = <img src={selectIcon} alt={t('shared.select')} />;
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<li className={styles.aggregationItem}><Link to={link}>{isSelected && <span>X - </span>}{props.title}<span className='float-end'>{props.count}</span></Link></li>
|
<li className={styles.aggregationItem}><Link to={link}>{icon}<span className={styles.title}>{props.title}</span><span className={styles.count}>{props.count}</span></Link></li>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default ConcordanceAggregationItem;
|
export default ConcordanceAggregationItem;
|
||||||
|
|||||||
+10
-1
@@ -7,6 +7,15 @@
|
|||||||
|
|
||||||
a {
|
a {
|
||||||
color: $text-color;
|
color: $text-color;
|
||||||
|
display: flex;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
|
|
||||||
|
.title {
|
||||||
|
margin-left: 1.2rem;
|
||||||
|
flex-grow: 1;
|
||||||
|
margin-right: 0.8rem;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: clip;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -6,7 +6,7 @@ const ConcordanceAlternateSearchItem = (props) => {
|
|||||||
const search = useSearch();
|
const search = useSearch();
|
||||||
const link = search.getAlternateSearchLink(props.search);
|
const link = search.getAlternateSearchLink(props.search);
|
||||||
return (
|
return (
|
||||||
<li className={styles.alternateSearchItem}><Link to={link}>{props.title}<span className='float-end'>{props.count}</span></Link></li>
|
<li className={styles.alternateSearchItem}><Link to={link}><span className={styles.title}>{props.title}</span><span className={styles.count}>{props.count}</span></Link></li>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
+8
@@ -7,6 +7,14 @@
|
|||||||
|
|
||||||
a {
|
a {
|
||||||
color: $text-color;
|
color: $text-color;
|
||||||
|
display: flex;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
|
|
||||||
|
.title {
|
||||||
|
flex-grow: 1;
|
||||||
|
margin-right: 0.8rem;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: clip;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+6
-18
@@ -1,6 +1,6 @@
|
|||||||
import { useTranslation } from 'react-i18next';
|
import ConcordanceDetailsTextInfo from './ConcordanceDetailsTextInfo';
|
||||||
|
|
||||||
import sytles from './ConcordanceDetailsText.module.scss';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
const ConcordanceDetailsText = (props) => {
|
const ConcordanceDetailsText = (props) => {
|
||||||
// Hooks
|
// Hooks
|
||||||
@@ -8,22 +8,10 @@ const ConcordanceDetailsText = (props) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className={sytles.textInfo}>
|
<ConcordanceDetailsTextInfo title={t('concordance.detailsTextSource')} value={props.source} />
|
||||||
<h5>{t('concordance.detailsTextSource')}</h5>
|
<ConcordanceDetailsTextInfo title={t('concordance.detailsTextYear')} value={props.year} />
|
||||||
<p>{props.source}</p>
|
<ConcordanceDetailsTextInfo title={t('concordance.detailsTextTitle')} value={props.title} />
|
||||||
</div>
|
<ConcordanceDetailsTextInfo title={t('concordance.detailsTextAuthor')} value={props.author} />
|
||||||
<div className={sytles.textInfo}>
|
|
||||||
<h5>{t('concordance.detailsTextYear')}</h5>
|
|
||||||
<p>{props.year}</p>
|
|
||||||
</div>
|
|
||||||
<div className={sytles.textInfo}>
|
|
||||||
<h5>{t('concordance.detailsTextTitle')}</h5>
|
|
||||||
<p>{props.title}</p>
|
|
||||||
</div>
|
|
||||||
<div className={sytles.textInfo}>
|
|
||||||
<h5>{t('concordance.detailsTextAuthor')}</h5>
|
|
||||||
<p>{props.author}</p>
|
|
||||||
</div>
|
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
+15
@@ -0,0 +1,15 @@
|
|||||||
|
import styles from './ConcordanceDetailsTextInfo.module.scss';
|
||||||
|
|
||||||
|
const ConcordanceDetailsTextInfo = (props) => {
|
||||||
|
var title = props.title;
|
||||||
|
var value = props.value;
|
||||||
|
|
||||||
|
if (value) {
|
||||||
|
return (<div className={styles.textInfo}>
|
||||||
|
<h5>{title}</h5>
|
||||||
|
<p>{value}</p>
|
||||||
|
</div>);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ConcordanceDetailsTextInfo;
|
||||||
+3
-1
@@ -17,6 +17,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
p {
|
p {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
text-overflow: clip;
|
||||||
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+2
-2
@@ -6,8 +6,8 @@ const ConcordanceListItem = (props) => {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className={`row ${styles.item}`} onClick={() => { props.toggleDetails(props.index) }}>
|
<div className={`row ${styles.item}`} onClick={() => { props.toggleDetails(props.index) }}>
|
||||||
<div className='col text-end'><ConcordanceTokens tokens={props.item.leftContext} /> </div>
|
<div className={`col ${styles.left}`}><span><ConcordanceTokens tokens={props.item.leftContext} /> </span></div>
|
||||||
<div className='col'><ConcordanceTokens tokens={[props.item.centerContext]} /> <ConcordanceTokens tokens={props.item.rightContext} /></div>
|
<div className={`col ${styles.right}`}><ConcordanceTokens tokens={[props.item.centerContext]} /> <ConcordanceTokens tokens={props.item.rightContext} /></div>
|
||||||
</div>
|
</div>
|
||||||
{props.expanded && <ConcordanceDetails paragraphId={props.item.paragraphId} tokenOrder={props.item.centerContext.tokenOrder} onClose={() => { props.toggleDetails(null) }} />}
|
{props.expanded && <ConcordanceDetails paragraphId={props.item.paragraphId} tokenOrder={props.item.centerContext.tokenOrder} onClose={() => { props.toggleDetails(null) }} />}
|
||||||
</>
|
</>
|
||||||
|
|||||||
+20
@@ -5,4 +5,24 @@
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
margin-bottom: 0.5rem;
|
margin-bottom: 0.5rem;
|
||||||
padding-bottom: 0.5rem;
|
padding-bottom: 0.5rem;
|
||||||
|
|
||||||
|
:global(.col) {
|
||||||
|
|
||||||
|
&.left,
|
||||||
|
&.right {
|
||||||
|
overflow: hidden;
|
||||||
|
white-space: nowrap;
|
||||||
|
text-overflow: clip;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.left {
|
||||||
|
span {
|
||||||
|
display: inline-block;
|
||||||
|
float: right;
|
||||||
|
min-width: 100%;
|
||||||
|
overflow: visible;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -18,7 +18,7 @@ const IndexTopBar = () => {
|
|||||||
<div className={styles.menu}>
|
<div className={styles.menu}>
|
||||||
<div className='container-fluid'>
|
<div className='container-fluid'>
|
||||||
<div className='row align-items-center'>
|
<div className='row align-items-center'>
|
||||||
<div className='col'><img src={logo} alt='Logo' /></div>
|
<div className='col'><a href="https://www.slovenscina.eu"><img src={logo} alt='Logo' /></a></div>
|
||||||
<div className={`col ${styles.links}`}><button type='button' onClick={languageClickHandler}><img src={langIcon} alt={changeLanguageTitle} />{changeLanguageCode}</button></div>
|
<div className={`col ${styles.links}`}><button type='button' onClick={languageClickHandler}><img src={langIcon} alt={changeLanguageTitle} />{changeLanguageCode}</button></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -26,4 +26,4 @@ const IndexTopBar = () => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default IndexTopBar;
|
export default IndexTopBar;
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ const useDownload = (url) => {
|
|||||||
var url = window.URL.createObjectURL(blob);
|
var url = window.URL.createObjectURL(blob);
|
||||||
var a = document.createElement('a');
|
var a = document.createElement('a');
|
||||||
a.href = url;
|
a.href = url;
|
||||||
a.download = "export.csv";
|
a.download = "export.txt";
|
||||||
document.body.appendChild(a); // we need to append the element to the dom -> otherwise it will not work in firefox
|
document.body.appendChild(a); // we need to append the element to the dom -> otherwise it will not work in firefox
|
||||||
a.click();
|
a.click();
|
||||||
a.remove(); //afterwards we remove the element again
|
a.remove(); //afterwards we remove the element again
|
||||||
|
|||||||
@@ -22,7 +22,9 @@ const resources = {
|
|||||||
'searchError': 'Server returned error when searching.',
|
'searchError': 'Server returned error when searching.',
|
||||||
'searchHelp': 'Help',
|
'searchHelp': 'Help',
|
||||||
'searchHistory': 'Search history',
|
'searchHistory': 'Search history',
|
||||||
'searchRecords': 'Showing {{start}}-{{end}} from {{total}} records.'
|
'searchRecords': 'Showing {{start}}-{{end}} from {{total}} records.',
|
||||||
|
'select': 'Select',
|
||||||
|
'unselect': 'Remove selected'
|
||||||
},
|
},
|
||||||
concordance: {
|
concordance: {
|
||||||
'title': 'Search concordances',
|
'title': 'Search concordances',
|
||||||
@@ -63,7 +65,9 @@ const resources = {
|
|||||||
'searchError': 'Strežnik je vrnil napako pri iskanju.',
|
'searchError': 'Strežnik je vrnil napako pri iskanju.',
|
||||||
'searchHelp': 'Pomoč',
|
'searchHelp': 'Pomoč',
|
||||||
'searchHistory': 'Zgodovina iskanj',
|
'searchHistory': 'Zgodovina iskanj',
|
||||||
'searchRecords': 'Prikazujem {{start}}-{{end}} od {{total}} zapisov.'
|
'searchRecords': 'Prikazujem {{start}}-{{end}} od {{total}} zapisov.',
|
||||||
|
'select': 'Izberi',
|
||||||
|
'unselect': 'Odstrani izbrano'
|
||||||
},
|
},
|
||||||
concordance: {
|
concordance: {
|
||||||
'title': 'Iskanje po konkordancah',
|
'title': 'Iskanje po konkordancah',
|
||||||
@@ -96,4 +100,4 @@ i18n
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
export default i18n;
|
export default i18n;
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ const ResultsLayout = (props) => {
|
|||||||
<div className='container-fluid'>
|
<div className='container-fluid'>
|
||||||
<div className='row align-items-center'>
|
<div className='row align-items-center'>
|
||||||
<div className='col-sm-4 col-lg-2 col-xl-2'>
|
<div className='col-sm-4 col-lg-2 col-xl-2'>
|
||||||
<Link to={search.rootUrl}><img src={logo} alt='Logo' /></Link>
|
<a href="https://www.slovenscina.eu"><img src={logo} alt='Logo' /></a>
|
||||||
<ul className={styles.areaButtons}>
|
<ul className={styles.areaButtons}>
|
||||||
<li className={`${styles.areaButton} ${isConcordance ? styles.active : null}`}><Link to={`/${search.corpusId}/concordance`}><img src={isConcordance ? concordanceActiveIcon : concordanceInactiveIcon} alt='Concordance' /></Link></li>
|
<li className={`${styles.areaButton} ${isConcordance ? styles.active : null}`}><Link to={`/${search.corpusId}/concordance`}><img src={isConcordance ? concordanceActiveIcon : concordanceInactiveIcon} alt='Concordance' /></Link></li>
|
||||||
<li className={`${styles.areaButton} ${!isConcordance ? styles.active : null}`}><Link to={`/${search.corpusId}/list`}><img src={!isConcordance ? listActiveIcon : listInactiveIcon} alt='List' /></Link></li>
|
<li className={`${styles.areaButton} ${!isConcordance ? styles.active : null}`}><Link to={`/${search.corpusId}/list`}><img src={!isConcordance ? listActiveIcon : listInactiveIcon} alt='List' /></Link></li>
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ const ConcordanceResults = () => {
|
|||||||
content = <p>{t('shared.noResults')}</p>
|
content = <p>{t('shared.noResults')}</p>
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<ResultsLayout source='concordance'>
|
<ResultsLayout source='concordance' help={<ConcordanceHelp />}>
|
||||||
<div className='row'>
|
<div className='row'>
|
||||||
<div className='col-lg-10 offset-lg-2'>
|
<div className='col-lg-10 offset-lg-2'>
|
||||||
{content}
|
{content}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import ResultsHeader from '../../components/results/ResultsHeader';
|
|||||||
import ResultsPager from '../../components/results/ResultsPager';
|
import ResultsPager from '../../components/results/ResultsPager';
|
||||||
import ResultsExport from '../../components/results/ResultsExport';
|
import ResultsExport from '../../components/results/ResultsExport';
|
||||||
import ListItems from '../../components/list/ListItems';
|
import ListItems from '../../components/list/ListItems';
|
||||||
|
import ListHelp from '../../components/list/ListHelp';
|
||||||
import Spinner from '../../components/shared/Spinner';
|
import Spinner from '../../components/shared/Spinner';
|
||||||
|
|
||||||
const ListResults = () => {
|
const ListResults = () => {
|
||||||
@@ -48,7 +49,7 @@ const ListResults = () => {
|
|||||||
|
|
||||||
if (!isLoading && isSuccess && data.items.length > 0) {
|
if (!isLoading && isSuccess && data.items.length > 0) {
|
||||||
return (
|
return (
|
||||||
<ResultsLayout source='list'>
|
<ResultsLayout source='list' help={<ListHelp />}>
|
||||||
<div className='row'>
|
<div className='row'>
|
||||||
<div className='col'>
|
<div className='col'>
|
||||||
<ResultsHeader query={body.query} onExport={() => setIsVisible(prevIsVisible => !prevIsVisible)} />
|
<ResultsHeader query={body.query} onExport={() => setIsVisible(prevIsVisible => !prevIsVisible)} />
|
||||||
@@ -69,7 +70,7 @@ const ListResults = () => {
|
|||||||
content = <p>{t('shared.noResults')}</p>
|
content = <p>{t('shared.noResults')}</p>
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<ResultsLayout source='list'>
|
<ResultsLayout source='list' help={<ListHelp />}>
|
||||||
<div className='row'>
|
<div className='row'>
|
||||||
<div className='col-lg-10 offset-lg-2'>
|
<div className='col-lg-10 offset-lg-2'>
|
||||||
{content}
|
{content}
|
||||||
|
|||||||
@@ -1,14 +1,11 @@
|
|||||||
FROM mcr.microsoft.com/dotnet/sdk:6.0 AS base
|
FROM mcr.microsoft.com/dotnet/sdk:10.0 AS base
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build
|
FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build
|
||||||
|
|
||||||
# COPY LOCAL NUGET PACKAGES
|
# COPY SHARED MSBUILD CONFIGURATION
|
||||||
WORKDIR /nuget
|
COPY src/Directory.Build.props /src/Directory.Build.props
|
||||||
COPY local-packages/. .
|
COPY src/Directory.Packages.props /src/Directory.Packages.props
|
||||||
|
|
||||||
# ADD LOCAL NUGET SOURCE
|
|
||||||
RUN dotnet nuget add source /nuget
|
|
||||||
|
|
||||||
# RESTORE PACKAGES (with project files only)
|
# RESTORE PACKAGES (with project files only)
|
||||||
WORKDIR /src/apps
|
WORKDIR /src/apps
|
||||||
@@ -44,4 +41,4 @@ RUN dotnet publish "Rsdo.Concordancer.SystemManager.csproj" -c Release -o /app/p
|
|||||||
FROM base AS final
|
FROM base AS final
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
COPY --from=publish /app/publish .
|
COPY --from=publish /app/publish .
|
||||||
CMD tail -f /dev/null
|
CMD tail -f /dev/null
|
||||||
|
|||||||
@@ -2,16 +2,11 @@
|
|||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<TargetFramework>net6.0</TargetFramework>
|
|
||||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
|
||||||
<EnableNETAnalyzers>false</EnableNETAnalyzers>
|
|
||||||
<Version>1.0.1</Version>
|
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Autofac" Version="6.4.0" />
|
<PackageReference Include="Autofac" />
|
||||||
<PackageReference Include="CommandLineParser" Version="2.9.1" />
|
<PackageReference Include="CommandLineParser" />
|
||||||
<PackageReference Include="Rsdo.StyleCop" Version="1.0.0" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
namespace Rsdo.Concordancer.Core.Extensions;
|
||||||
|
|
||||||
|
public static class StringExtensions
|
||||||
|
{
|
||||||
|
public static bool IsWildcardSearch(this string value)
|
||||||
|
{
|
||||||
|
return !string.IsNullOrEmpty(value) && (value.Contains('*') || value.Contains('?'));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,16 +1,5 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
|
||||||
<TargetFramework>net6.0</TargetFramework>
|
|
||||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
|
||||||
<EnableNETAnalyzers>false</EnableNETAnalyzers>
|
|
||||||
<Version>1.0.1</Version>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<PackageReference Include="Rsdo.StyleCop" Version="1.0.0" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\Rsdo.Concordancer.ServiceModel\Rsdo.Concordancer.ServiceModel.csproj" />
|
<ProjectReference Include="..\Rsdo.Concordancer.ServiceModel\Rsdo.Concordancer.ServiceModel.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|||||||
@@ -14,6 +14,8 @@ public class VersionInfoTableMetadata : IVersionTableMetaData
|
|||||||
|
|
||||||
public string UniqueIndexName => "uc_version";
|
public string UniqueIndexName => "uc_version";
|
||||||
|
|
||||||
|
public bool CreateWithPrimaryKey => false;
|
||||||
|
|
||||||
public object ApplicationContext { get; set; }
|
public object ApplicationContext { get; set; }
|
||||||
|
|
||||||
public bool OwnsSchema => true;
|
public bool OwnsSchema => true;
|
||||||
|
|||||||
+22
@@ -0,0 +1,22 @@
|
|||||||
|
using System;
|
||||||
|
using FluentMigrator;
|
||||||
|
using Rsdo.Concordancer.Core.Entities;
|
||||||
|
using Rsdo.Concordancer.Data.Framework;
|
||||||
|
|
||||||
|
namespace Rsdo.Concordancer.Data.Migrations.v1_0.Corpus;
|
||||||
|
|
||||||
|
[CorpusDb]
|
||||||
|
[Migration(20230413111500)]
|
||||||
|
public class Mig20230413111500_ChangeFormToText : ForwardOnlyMigration
|
||||||
|
{
|
||||||
|
public override void Up()
|
||||||
|
{
|
||||||
|
// Token
|
||||||
|
Alter.Column(nameof(Token.Form)).OnTable(nameof(Token)).AsString(int.MaxValue).Nullable();
|
||||||
|
Alter.Column(nameof(Token.Lemma)).OnTable(nameof(Token)).AsString(int.MaxValue).Nullable();
|
||||||
|
|
||||||
|
// Term
|
||||||
|
Alter.Column(nameof(Term.Form)).OnTable(nameof(Term)).AsString(int.MaxValue).NotNullable();
|
||||||
|
Alter.Column(nameof(Term.Lemma)).OnTable(nameof(Term)).AsString(int.MaxValue).NotNullable();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,19 +1,11 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
|
||||||
<TargetFramework>net6.0</TargetFramework>
|
|
||||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
|
||||||
<EnableNETAnalyzers>false</EnableNETAnalyzers>
|
|
||||||
<Version>1.0.1</Version>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Autofac" Version="6.4.0" />
|
<PackageReference Include="Autofac" />
|
||||||
<PackageReference Include="FluentMigrator" Version="3.3.2" />
|
<PackageReference Include="FluentMigrator" />
|
||||||
<PackageReference Include="FluentMigrator.Runner" Version="3.3.2" />
|
<PackageReference Include="FluentMigrator.Runner" />
|
||||||
<PackageReference Include="FluentMigrator.Runner.Postgres" Version="3.3.2" />
|
<PackageReference Include="FluentMigrator.Runner.Postgres" />
|
||||||
<PackageReference Include="Npgsql" Version="6.0.7" />
|
<PackageReference Include="Npgsql" />
|
||||||
<PackageReference Include="Rsdo.StyleCop" Version="1.0.0" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using OpenSearch.Client;
|
using OpenSearch.Client;
|
||||||
|
using Rsdo.Concordancer.Core.Extensions;
|
||||||
|
|
||||||
namespace Rsdo.Concordancer.Infrastructure.Extensions;
|
namespace Rsdo.Concordancer.Infrastructure.Extensions;
|
||||||
|
|
||||||
@@ -30,4 +32,36 @@ public static class ElasticQueryExtensions
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static QueryContainer ToQuery(this string value, string field)
|
||||||
|
{
|
||||||
|
if (value.IsWildcardSearch())
|
||||||
|
{
|
||||||
|
return new WildcardQuery()
|
||||||
|
{
|
||||||
|
Field = field,
|
||||||
|
Value = value,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return new TermQuery()
|
||||||
|
{
|
||||||
|
Field = field,
|
||||||
|
Value = value,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public static QueryContainer ToQuery(this List<string> values, string field)
|
||||||
|
{
|
||||||
|
if (values.Any(v => v.IsWildcardSearch()))
|
||||||
|
{
|
||||||
|
return values.Select(value => value.ToQuery(field)).ToList().ToBooleanOrQuery();
|
||||||
|
}
|
||||||
|
|
||||||
|
return new TermsQuery()
|
||||||
|
{
|
||||||
|
Field = field,
|
||||||
|
Terms = values,
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,18 +1,10 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
|
||||||
<TargetFramework>net6.0</TargetFramework>
|
|
||||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
|
||||||
<EnableNETAnalyzers>false</EnableNETAnalyzers>
|
|
||||||
<Version>1.0.1</Version>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Autofac" Version="6.4.0" />
|
<PackageReference Include="Autofac" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Configuration" Version="6.0.1" />
|
<PackageReference Include="Microsoft.Extensions.Configuration" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="6.0.1" />
|
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" />
|
||||||
<PackageReference Include="OpenSearch.Client" Version="1.1.0" />
|
<PackageReference Include="OpenSearch.Client" />
|
||||||
<PackageReference Include="Rsdo.StyleCop" Version="1.0.0" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
+19
-14
@@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using OpenSearch.Client;
|
using OpenSearch.Client;
|
||||||
using Rsdo.Concordancer.Infrastructure.Search.Extensions;
|
using Rsdo.Concordancer.Infrastructure.Search.Extensions;
|
||||||
@@ -27,23 +28,27 @@ public abstract class BaseAddRecordsHandler<TEntity, TElasticEntity> : IAddRecor
|
|||||||
// Get index name
|
// Get index name
|
||||||
var indexName = indexProvider.IndexName;
|
var indexName = indexProvider.IndexName;
|
||||||
|
|
||||||
// Create request
|
// Batch entities by 1000
|
||||||
var request = new BulkRequest(indexName)
|
foreach (var batch in entities.Chunk(1000))
|
||||||
{
|
{
|
||||||
Operations = new List<IBulkOperation>(),
|
// Create request
|
||||||
Timeout = TimeSpan.FromMinutes(5),
|
var request = new BulkRequest(indexName)
|
||||||
};
|
{
|
||||||
|
Operations = new List<IBulkOperation>(),
|
||||||
|
Timeout = TimeSpan.FromMinutes(5),
|
||||||
|
};
|
||||||
|
|
||||||
// Convert entities to elastic entities
|
// Convert entities to elastic entities
|
||||||
foreach (var entity in entities)
|
foreach (var entity in batch)
|
||||||
{
|
{
|
||||||
var elasticEntity = ConvertEntity(entity);
|
var elasticEntity = ConvertEntity(entity);
|
||||||
request.Operations.Add(new BulkIndexOperation<TElasticEntity>(elasticEntity));
|
request.Operations.Add(new BulkIndexOperation<TElasticEntity>(elasticEntity));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get response
|
||||||
|
var response = await client.BulkAsync(request);
|
||||||
|
response.ThrowIfInvalid();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get response
|
|
||||||
var response = await client.BulkAsync(request);
|
|
||||||
response.ThrowIfInvalid();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract TElasticEntity ConvertEntity(TEntity entity);
|
protected abstract TElasticEntity ConvertEntity(TEntity entity);
|
||||||
|
|||||||
+2
-12
@@ -35,22 +35,12 @@ public class TermListQueryBuilder : IQueryBuilder<TermListQuery>
|
|||||||
|
|
||||||
if (!string.IsNullOrEmpty(wordQuery.Form))
|
if (!string.IsNullOrEmpty(wordQuery.Form))
|
||||||
{
|
{
|
||||||
queries.Add(
|
queries.Add(wordQuery.Form.ToLower().ToQuery($"{tokenField}.formLower"));
|
||||||
new TermQuery()
|
|
||||||
{
|
|
||||||
Field = $"{tokenField}.formLower",
|
|
||||||
Value = wordQuery.Form.ToLower(),
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!wordQuery.Lemmas.IsNullOrEmpty())
|
if (!wordQuery.Lemmas.IsNullOrEmpty())
|
||||||
{
|
{
|
||||||
queries.Add(
|
queries.Add(wordQuery.Lemmas.ToQuery($"{tokenField}.lemma"));
|
||||||
new TermsQuery()
|
|
||||||
{
|
|
||||||
Field = $"{tokenField}.lemma",
|
|
||||||
Terms = wordQuery.Lemmas,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return queries.Count == 0 ? new MatchNoneQuery() : queries.ToBooleanAndQuery();
|
return queries.Count == 0 ? new MatchNoneQuery() : queries.ToBooleanAndQuery();
|
||||||
|
|||||||
@@ -1,15 +1,7 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
|
||||||
<TargetFramework>net6.0</TargetFramework>
|
|
||||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
|
||||||
<EnableNETAnalyzers>false</EnableNETAnalyzers>
|
|
||||||
<Version>1.0.1</Version>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Rsdo.StyleCop" Version="1.0.0" />
|
<PackageReference Include="Swashbuckle.AspNetCore.Annotations" />
|
||||||
<PackageReference Include="Swashbuckle.AspNetCore.Annotations" Version="6.4.0" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -1,10 +1,14 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using Autofac;
|
using Autofac;
|
||||||
|
using Autofac.Core;
|
||||||
using FluentValidation;
|
using FluentValidation;
|
||||||
using Microsoft.Extensions.Caching.Memory;
|
using Microsoft.Extensions.Caching.Memory;
|
||||||
using Rsdo.Concordancer.Core.Interfaces;
|
using Rsdo.Concordancer.Core.Interfaces;
|
||||||
|
using Rsdo.Concordancer.Core.Search.Queries.Concordances;
|
||||||
|
using Rsdo.Concordancer.Core.Search.Queries.TermLists;
|
||||||
using Rsdo.Concordancer.ServiceModel.Requests.Concordances;
|
using Rsdo.Concordancer.ServiceModel.Requests.Concordances;
|
||||||
|
using Rsdo.Concordancer.ServiceModel.Requests.TermLists;
|
||||||
using Rsdo.Concordancer.ServiceModel.Types;
|
using Rsdo.Concordancer.ServiceModel.Types;
|
||||||
using Rsdo.Concordancer.Services.Framework;
|
using Rsdo.Concordancer.Services.Framework;
|
||||||
using Rsdo.Concordancer.Services.Framework.BulkLoaders;
|
using Rsdo.Concordancer.Services.Framework.BulkLoaders;
|
||||||
@@ -15,6 +19,8 @@ using Rsdo.Concordancer.Services.Framework.Decorators;
|
|||||||
using Rsdo.Concordancer.Services.Search.Aggregations;
|
using Rsdo.Concordancer.Services.Search.Aggregations;
|
||||||
using Rsdo.Concordancer.Services.Search.AlternateSearches;
|
using Rsdo.Concordancer.Services.Search.AlternateSearches;
|
||||||
using Rsdo.Concordancer.Services.Search.QueryFactories;
|
using Rsdo.Concordancer.Services.Search.QueryFactories;
|
||||||
|
using Rsdo.Concordancer.Services.Search.QueryFactories.Concordances;
|
||||||
|
using Rsdo.Concordancer.Services.Search.QueryFactories.TermLists;
|
||||||
using Rsdo.Concordancer.Services.Services.InputQueryParser;
|
using Rsdo.Concordancer.Services.Services.InputQueryParser;
|
||||||
using Rsdo.Concordancer.Services.Services.LemmatizationService;
|
using Rsdo.Concordancer.Services.Services.LemmatizationService;
|
||||||
using Rsdo.Concordancer.Services.Services.ParagraphService;
|
using Rsdo.Concordancer.Services.Services.ParagraphService;
|
||||||
@@ -83,7 +89,8 @@ public class ServicesModule : Module
|
|||||||
builder.RegisterType<DefaultTokenizerService>().Keyed<ITokenizerService>(TokenizerType.Default).SingleInstance();
|
builder.RegisterType<DefaultTokenizerService>().Keyed<ITokenizerService>(TokenizerType.Default).SingleInstance();
|
||||||
builder.RegisterType<InputQueryParser>().As<IInputQueryParser>().SingleInstance();
|
builder.RegisterType<InputQueryParser>().As<IInputQueryParser>().SingleInstance();
|
||||||
builder.RegisterType<ParagraphService>().As<IParagraphService>().InstancePerLifetimeScope();
|
builder.RegisterType<ParagraphService>().As<IParagraphService>().InstancePerLifetimeScope();
|
||||||
builder.RegisterType<LemmatizationService>().As<ILemmatizationService>().InstancePerLifetimeScope();
|
builder.RegisterType<SimpleLemmatizationService>().Keyed<ILemmatizationService>(LemmatizationType.Simple).InstancePerLifetimeScope();
|
||||||
|
builder.RegisterType<WildcardLemmatizationService>().Keyed<ILemmatizationService>(LemmatizationType.Wildcard).InstancePerLifetimeScope();
|
||||||
builder.RegisterType<PartOfSpeechService>().As<IPartOfSpeechService>().InstancePerLifetimeScope();
|
builder.RegisterType<PartOfSpeechService>().As<IPartOfSpeechService>().InstancePerLifetimeScope();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -103,7 +110,33 @@ public class ServicesModule : Module
|
|||||||
private void RegisterSearch(ContainerBuilder builder)
|
private void RegisterSearch(ContainerBuilder builder)
|
||||||
{
|
{
|
||||||
// Query factories
|
// Query factories
|
||||||
builder.RegisterAssemblyTypes(ServicesAssembly).AsClosedTypesOf(typeof(IQueryFactory<,>)).AsImplementedInterfaces().InstancePerLifetimeScope();
|
var wildcardLemmatizationServiceParameter = new ResolvedParameter(
|
||||||
|
(p, ctx) => p.ParameterType == typeof(ILemmatizationService),
|
||||||
|
(p, ctx) => ctx.ResolveKeyed<ILemmatizationService>(LemmatizationType.Wildcard));
|
||||||
|
var simpleLemmatizationServiceParameter = new ResolvedParameter(
|
||||||
|
(p, ctx) => p.ParameterType == typeof(ILemmatizationService),
|
||||||
|
(p, ctx) => ctx.ResolveKeyed<ILemmatizationService>(LemmatizationType.Simple));
|
||||||
|
|
||||||
|
builder.RegisterType<ExportConcordancesQueryFactory>()
|
||||||
|
.As<IQueryFactory<ExportConcordances, ConcordancesQuery>>()
|
||||||
|
.WithParameter(simpleLemmatizationServiceParameter)
|
||||||
|
.InstancePerLifetimeScope();
|
||||||
|
builder.RegisterType<SearchConcordancesQueryFactory>()
|
||||||
|
.As<IQueryFactory<SearchConcordances, ConcordancesQuery>>()
|
||||||
|
.WithParameter(simpleLemmatizationServiceParameter)
|
||||||
|
.InstancePerLifetimeScope();
|
||||||
|
builder.RegisterType<ConcordanceDetailsQueryFactory>()
|
||||||
|
.As<IQueryFactory<ConcordanceDetails, ConcordancesQuery>>()
|
||||||
|
.WithParameter(simpleLemmatizationServiceParameter)
|
||||||
|
.InstancePerLifetimeScope();
|
||||||
|
builder.RegisterType<ExportTermListQueryFactory>()
|
||||||
|
.As<IQueryFactory<ExportTermList, TermListQuery>>()
|
||||||
|
.WithParameter(wildcardLemmatizationServiceParameter)
|
||||||
|
.InstancePerLifetimeScope();
|
||||||
|
builder.RegisterType<SearchTermListQueryFactory>()
|
||||||
|
.As<IQueryFactory<SearchTermList, TermListQuery>>()
|
||||||
|
.WithParameter(wildcardLemmatizationServiceParameter)
|
||||||
|
.InstancePerLifetimeScope();
|
||||||
|
|
||||||
// Aggregations
|
// Aggregations
|
||||||
builder.RegisterType<AggregationProviderFactory>().As<IAggregationProviderFactory>().InstancePerLifetimeScope();
|
builder.RegisterType<AggregationProviderFactory>().As<IAggregationProviderFactory>().InstancePerLifetimeScope();
|
||||||
@@ -112,6 +145,7 @@ public class ServicesModule : Module
|
|||||||
// Alternate searches
|
// Alternate searches
|
||||||
builder.RegisterType<LemmasAlternateSearchProvider>()
|
builder.RegisterType<LemmasAlternateSearchProvider>()
|
||||||
.As<IAlternateSearchProvider<SearchConcordances, SearchConcordancesResponse>>()
|
.As<IAlternateSearchProvider<SearchConcordances, SearchConcordancesResponse>>()
|
||||||
|
.WithParameter(simpleLemmatizationServiceParameter)
|
||||||
.InstancePerLifetimeScope();
|
.InstancePerLifetimeScope();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+2
-1
@@ -4,6 +4,7 @@ using System.Threading.Tasks;
|
|||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Npgsql;
|
using Npgsql;
|
||||||
using Rsdo.Concordancer.Core.Interfaces;
|
using Rsdo.Concordancer.Core.Interfaces;
|
||||||
|
using Rsdo.Concordancer.ServiceModel.Types;
|
||||||
using Rsdo.Concordancer.Services.Framework.DbContext;
|
using Rsdo.Concordancer.Services.Framework.DbContext;
|
||||||
|
|
||||||
namespace Rsdo.Concordancer.Services.Framework.DatabaseManager;
|
namespace Rsdo.Concordancer.Services.Framework.DatabaseManager;
|
||||||
@@ -57,7 +58,7 @@ public class PostgreSqlDatabaseManager : IDatabaseManager
|
|||||||
public async Task UpdateCorpusDatabases()
|
public async Task UpdateCorpusDatabases()
|
||||||
{
|
{
|
||||||
// Update all corpus databases
|
// Update all corpus databases
|
||||||
var corpusIds = await dbContext.Corpus.Select(c => c.Id).ToListAsync();
|
var corpusIds = await dbContext.Corpus.Where(s => s.Status == CorpusStatus.Active).Select(c => c.Id).ToListAsync();
|
||||||
foreach (var corpusId in corpusIds)
|
foreach (var corpusId in corpusIds)
|
||||||
{
|
{
|
||||||
var connectionString = connectionStringProvider.GetCorpusConnectionString(corpusId);
|
var connectionString = connectionStringProvider.GetCorpusConnectionString(corpusId);
|
||||||
|
|||||||
+32
-3
@@ -1,8 +1,11 @@
|
|||||||
using System.Collections.Generic;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Rsdo.Concordancer.Core.Constants;
|
using Rsdo.Concordancer.Core.Constants;
|
||||||
using Rsdo.Concordancer.Core.Interfaces;
|
using Rsdo.Concordancer.Core.Interfaces;
|
||||||
using Rsdo.Concordancer.Core.Model;
|
using Rsdo.Concordancer.Core.Model;
|
||||||
@@ -11,6 +14,7 @@ using Rsdo.Concordancer.Core.Search.Queries.Concordances;
|
|||||||
using Rsdo.Concordancer.ServiceModel.Requests.Concordances;
|
using Rsdo.Concordancer.ServiceModel.Requests.Concordances;
|
||||||
using Rsdo.Concordancer.ServiceModel.Shared;
|
using Rsdo.Concordancer.ServiceModel.Shared;
|
||||||
using Rsdo.Concordancer.ServiceModel.Types;
|
using Rsdo.Concordancer.ServiceModel.Types;
|
||||||
|
using Rsdo.Concordancer.Services.Framework.DbContext;
|
||||||
using Rsdo.Concordancer.Services.Search.QueryFactories;
|
using Rsdo.Concordancer.Services.Search.QueryFactories;
|
||||||
using Rsdo.Concordancer.Services.Services.ParagraphService;
|
using Rsdo.Concordancer.Services.Services.ParagraphService;
|
||||||
|
|
||||||
@@ -18,15 +22,18 @@ namespace Rsdo.Concordancer.Services.RequestHandlers.Concordances;
|
|||||||
|
|
||||||
public class ExportConcordancesHandler : BaseSearchConcordancesHandler, IRequestHandler<ExportConcordances, ExportConcordancesResponse>
|
public class ExportConcordancesHandler : BaseSearchConcordancesHandler, IRequestHandler<ExportConcordances, ExportConcordancesResponse>
|
||||||
{
|
{
|
||||||
|
private readonly CorpusDbContext dbContext;
|
||||||
private readonly IQueryFactory<ExportConcordances, ConcordancesQuery> queryFactory;
|
private readonly IQueryFactory<ExportConcordances, ConcordancesQuery> queryFactory;
|
||||||
private readonly ISearchEngine searchEngine;
|
private readonly ISearchEngine searchEngine;
|
||||||
|
|
||||||
public ExportConcordancesHandler(
|
public ExportConcordancesHandler(
|
||||||
|
CorpusDbContext dbContext,
|
||||||
IParagraphService paragraphService,
|
IParagraphService paragraphService,
|
||||||
IQueryFactory<ExportConcordances, ConcordancesQuery> queryFactory,
|
IQueryFactory<ExportConcordances, ConcordancesQuery> queryFactory,
|
||||||
ISearchEngine searchEngine)
|
ISearchEngine searchEngine)
|
||||||
: base(paragraphService)
|
: base(paragraphService)
|
||||||
{
|
{
|
||||||
|
this.dbContext = dbContext;
|
||||||
this.queryFactory = queryFactory;
|
this.queryFactory = queryFactory;
|
||||||
this.searchEngine = searchEngine;
|
this.searchEngine = searchEngine;
|
||||||
}
|
}
|
||||||
@@ -42,6 +49,9 @@ public class ExportConcordancesHandler : BaseSearchConcordancesHandler, IRequest
|
|||||||
// Get search items
|
// Get search items
|
||||||
var items = await GetItems(query, result.EntityIds);
|
var items = await GetItems(query, result.EntityIds);
|
||||||
|
|
||||||
|
// Get sources
|
||||||
|
var sources = await GetSources(items);
|
||||||
|
|
||||||
// Export
|
// Export
|
||||||
var stream = new MemoryStream();
|
var stream = new MemoryStream();
|
||||||
await using (var writer = new StreamWriter(stream, Encoding.UTF8, 1024, true))
|
await using (var writer = new StreamWriter(stream, Encoding.UTF8, 1024, true))
|
||||||
@@ -52,7 +62,7 @@ public class ExportConcordancesHandler : BaseSearchConcordancesHandler, IRequest
|
|||||||
// Write items
|
// Write items
|
||||||
foreach (var item in items)
|
foreach (var item in items)
|
||||||
{
|
{
|
||||||
await WriteItem(writer, item);
|
await WriteItem(writer, item, sources[item.ParagraphId]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -91,16 +101,35 @@ public class ExportConcordancesHandler : BaseSearchConcordancesHandler, IRequest
|
|||||||
await writer.WriteAsync("Iskani niz");
|
await writer.WriteAsync("Iskani niz");
|
||||||
await writer.WriteAsync("\t");
|
await writer.WriteAsync("\t");
|
||||||
await writer.WriteAsync("Desno besedilo");
|
await writer.WriteAsync("Desno besedilo");
|
||||||
|
await writer.WriteAsync("\t");
|
||||||
|
await writer.WriteAsync("Vir");
|
||||||
await writer.WriteLineAsync();
|
await writer.WriteLineAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static async Task WriteItem(StreamWriter writer, SearchConcordancesResponseItem item)
|
private static async Task WriteItem(StreamWriter writer, SearchConcordancesResponseItem item, string source)
|
||||||
{
|
{
|
||||||
await WriteContext(writer, item.LeftContext);
|
await WriteContext(writer, item.LeftContext);
|
||||||
await writer.WriteAsync("\t");
|
await writer.WriteAsync("\t");
|
||||||
await writer.WriteAsync(item.CenterContext.Form);
|
await writer.WriteAsync(item.CenterContext.Form);
|
||||||
await writer.WriteAsync("\t");
|
await writer.WriteAsync("\t");
|
||||||
await WriteContext(writer, item.RightContext);
|
await WriteContext(writer, item.RightContext);
|
||||||
|
await writer.WriteAsync("\t");
|
||||||
|
await writer.WriteAsync(source);
|
||||||
await writer.WriteLineAsync();
|
await writer.WriteLineAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task<Dictionary<Guid, string>> GetSources(List<SearchConcordancesResponseItem> items)
|
||||||
|
{
|
||||||
|
var paragraphIds = items.Select(i => i.ParagraphId).ToList();
|
||||||
|
var sources = await dbContext.Paragraph.Include(p => p.Text)
|
||||||
|
.Where(p => paragraphIds.Contains(p.Id))
|
||||||
|
.Select(
|
||||||
|
p => new
|
||||||
|
{
|
||||||
|
p.Id,
|
||||||
|
p.Text.SourceFile,
|
||||||
|
})
|
||||||
|
.ToListAsync();
|
||||||
|
return sources.ToDictionary(x => x.Id, x => Path.GetFileNameWithoutExtension(x.SourceFile));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+1
-1
@@ -109,7 +109,7 @@ public class ImportTermListHandler : IRequestHandler<ImportTermList, ExecutionRe
|
|||||||
Lemma = termObj["kandidat"].Value<string>(),
|
Lemma = termObj["kandidat"].Value<string>(),
|
||||||
Msd = termObj["POSoznake"].Value<string>(),
|
Msd = termObj["POSoznake"].Value<string>(),
|
||||||
Weight = termObj["ranking"].Value<decimal>(),
|
Weight = termObj["ranking"].Value<decimal>(),
|
||||||
Frequency = termObj["pogostostpojavljanja"].Value<int>(),
|
Frequency = termObj["pogostostpojavljanja"].Values<int>().First(),
|
||||||
TermListAutoId = termList.AutoId,
|
TermListAutoId = termList.AutoId,
|
||||||
}.ApplyCreateValues();
|
}.ApplyCreateValues();
|
||||||
|
|
||||||
|
|||||||
@@ -90,39 +90,35 @@ public class IndexTextHandler : IRequestHandler<IndexText, ExecutionResult>
|
|||||||
|
|
||||||
private static List<Concordance> GetConcordances(Text text, Paragraph paragraph, List<Token> tokens)
|
private static List<Concordance> GetConcordances(Text text, Paragraph paragraph, List<Token> tokens)
|
||||||
{
|
{
|
||||||
// Get window size (max 10)
|
|
||||||
var windowSize = Math.Min(tokens.Count - 1, 10);
|
|
||||||
|
|
||||||
// Create list of tokens with positions
|
|
||||||
var tokensIdx = tokens.Select((t, i) => new KeyValuePair<int, Token>(i, t)).ToList();
|
|
||||||
|
|
||||||
// Get tokens which will appear in current concordance
|
|
||||||
List<KeyValuePair<int, Token>> concordanceTokens;
|
|
||||||
|
|
||||||
var concordances = new List<Concordance>();
|
var concordances = new List<Concordance>();
|
||||||
while ((concordanceTokens = tokensIdx.Where(x => x.Key >= -windowSize && x.Key <= windowSize).ToList().OrderBy(x => x.Key).ToList()).Any())
|
for (var i = 0; i < tokens.Count; i++)
|
||||||
{
|
{
|
||||||
if (concordanceTokens.Last().Key < 0)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
var concordance = new Concordance()
|
var concordance = new Concordance()
|
||||||
{
|
{
|
||||||
ParagraphId = paragraph.Id,
|
ParagraphId = paragraph.Id,
|
||||||
TextId = text.Id,
|
TextId = text.Id,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Loop through tokens and set it in the position
|
// set center token
|
||||||
foreach (var concordanceToken in concordanceTokens)
|
concordance.SetToken(tokens[i], 0);
|
||||||
|
|
||||||
|
// set left and right context tokens
|
||||||
|
for (var c = 1; c <= 10; c++)
|
||||||
{
|
{
|
||||||
concordance.SetToken(concordanceToken.Value, concordanceToken.Key);
|
// left context
|
||||||
|
if (i - c >= 0)
|
||||||
|
{
|
||||||
|
concordance.SetToken(tokens[i - c], -c);
|
||||||
|
}
|
||||||
|
|
||||||
|
// right context
|
||||||
|
if (i + c < tokens.Count)
|
||||||
|
{
|
||||||
|
concordance.SetToken(tokens[i + c], c);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
concordances.Add(concordance);
|
concordances.Add(concordance);
|
||||||
|
|
||||||
// Decrease indexes of tokens (shift tokens to left, relative to window size)
|
|
||||||
tokensIdx = tokensIdx.Select(x => new KeyValuePair<int, Token>(x.Key - 1, x.Value)).ToList();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return concordances;
|
return concordances;
|
||||||
|
|||||||
@@ -1,25 +1,17 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
|
||||||
<TargetFramework>net6.0</TargetFramework>
|
|
||||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
|
||||||
<EnableNETAnalyzers>false</EnableNETAnalyzers>
|
|
||||||
<Version>1.0.1</Version>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Autofac" Version="6.4.0" />
|
<PackageReference Include="Autofac" />
|
||||||
<PackageReference Include="EFCore.NamingConventions" Version="6.0.0" />
|
<PackageReference Include="EFCore.NamingConventions" />
|
||||||
<PackageReference Include="FluentValidation" Version="11.2.2" />
|
<PackageReference Include="FluentValidation" />
|
||||||
<PackageReference Include="Hangfire.Core" Version="1.7.31" />
|
<PackageReference Include="Hangfire.Core" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="6.0.9" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="6.0.1" />
|
<PackageReference Include="Microsoft.Extensions.Caching.Memory" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="6.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Http" Version="6.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Http" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
<PackageReference Include="Newtonsoft.Json" />
|
||||||
<PackageReference Include="Npgsql" Version="6.0.7" />
|
<PackageReference Include="Npgsql" />
|
||||||
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="6.0.7" />
|
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" />
|
||||||
<PackageReference Include="Rsdo.StyleCop" Version="1.0.0" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ using System.Linq;
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Autofac.Features.Indexed;
|
using Autofac.Features.Indexed;
|
||||||
|
using Rsdo.Concordancer.Core.Extensions;
|
||||||
using Rsdo.Concordancer.ServiceModel.Requests.Concordances;
|
using Rsdo.Concordancer.ServiceModel.Requests.Concordances;
|
||||||
using Rsdo.Concordancer.ServiceModel.Types;
|
using Rsdo.Concordancer.ServiceModel.Types;
|
||||||
using Rsdo.Concordancer.Services.Services.TokenizerService;
|
using Rsdo.Concordancer.Services.Services.TokenizerService;
|
||||||
@@ -21,6 +22,12 @@ public class InputQueryParser : IInputQueryParser
|
|||||||
|
|
||||||
public async Task<IEnumerable<(TokenType type, string form)>> Tokenize(string query)
|
public async Task<IEnumerable<(TokenType type, string form)>> Tokenize(string query)
|
||||||
{
|
{
|
||||||
|
if (query.IsWildcardSearch())
|
||||||
|
{
|
||||||
|
// Classla tokenizer doesn't support wildcards, so use default tokenizer
|
||||||
|
return await tokenizers[TokenizerType.Default].Tokenize(query);
|
||||||
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
return await tokenizers[TokenizerType.Classla].Tokenize(query);
|
return await tokenizers[TokenizerType.Classla].Tokenize(query);
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
namespace Rsdo.Concordancer.Services.Services.LemmatizationService;
|
||||||
|
|
||||||
|
public enum LemmatizationType
|
||||||
|
{
|
||||||
|
Simple,
|
||||||
|
Wildcard,
|
||||||
|
}
|
||||||
+4
-3
@@ -7,17 +7,18 @@ using Rsdo.Concordancer.Services.Framework.DbContext;
|
|||||||
|
|
||||||
namespace Rsdo.Concordancer.Services.Services.LemmatizationService;
|
namespace Rsdo.Concordancer.Services.Services.LemmatizationService;
|
||||||
|
|
||||||
public class LemmatizationService : ILemmatizationService
|
public class SimpleLemmatizationService : ILemmatizationService
|
||||||
{
|
{
|
||||||
private readonly MasterDbContext dbContext;
|
private readonly MasterDbContext dbContext;
|
||||||
|
|
||||||
public LemmatizationService(MasterDbContext dbContext)
|
public SimpleLemmatizationService(MasterDbContext dbContext)
|
||||||
{
|
{
|
||||||
this.dbContext = dbContext;
|
this.dbContext = dbContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<List<string>> GetLemmas(string form)
|
public virtual async Task<List<string>> GetLemmas(string form)
|
||||||
{
|
{
|
||||||
|
// Retrieving lemmas without support for wildcard search
|
||||||
var lemmas = await dbContext.LemmaFormPair.Where(f => f.Form.ToLower() == form.ToLower()).Select(f => f.Lemma).Distinct().ToListAsync();
|
var lemmas = await dbContext.LemmaFormPair.Where(f => f.Form.ToLower() == form.ToLower()).Select(f => f.Lemma).Distinct().ToListAsync();
|
||||||
if (lemmas.IsNullOrEmpty())
|
if (lemmas.IsNullOrEmpty())
|
||||||
{
|
{
|
||||||
+38
@@ -0,0 +1,38 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Rsdo.Concordancer.Core.Extensions;
|
||||||
|
using Rsdo.Concordancer.Services.Framework.DbContext;
|
||||||
|
|
||||||
|
namespace Rsdo.Concordancer.Services.Services.LemmatizationService;
|
||||||
|
|
||||||
|
public class WildcardLemmatizationService : SimpleLemmatizationService
|
||||||
|
{
|
||||||
|
private readonly MasterDbContext dbContext;
|
||||||
|
|
||||||
|
public WildcardLemmatizationService(MasterDbContext dbContext)
|
||||||
|
: base(dbContext)
|
||||||
|
{
|
||||||
|
this.dbContext = dbContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task<List<string>> GetLemmas(string form)
|
||||||
|
{
|
||||||
|
if (!form.IsWildcardSearch())
|
||||||
|
{
|
||||||
|
return await base.GetLemmas(form);
|
||||||
|
}
|
||||||
|
|
||||||
|
var lemmas = await dbContext.LemmaFormPair.Where(f => EF.Functions.Like(f.Form.ToLower(), form.Replace("*", "%").Replace("?", "_").ToLower()))
|
||||||
|
.Select(f => f.Lemma)
|
||||||
|
.Distinct()
|
||||||
|
.ToListAsync();
|
||||||
|
if (lemmas.IsNullOrEmpty())
|
||||||
|
{
|
||||||
|
lemmas.Add(form);
|
||||||
|
}
|
||||||
|
|
||||||
|
return lemmas;
|
||||||
|
}
|
||||||
|
}
|
||||||
+4
-8
@@ -1,21 +1,17 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net6.0</TargetFramework>
|
|
||||||
<IsPackable>false</IsPackable>
|
<IsPackable>false</IsPackable>
|
||||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
|
||||||
<EnableNETAnalyzers>false</EnableNETAnalyzers>
|
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.2" />
|
<PackageReference Include="Microsoft.NET.Test.Sdk" />
|
||||||
<PackageReference Include="Rsdo.StyleCop" Version="1.0.0" />
|
<PackageReference Include="xunit" />
|
||||||
<PackageReference Include="xunit" Version="2.4.2" />
|
<PackageReference Include="xunit.runner.visualstudio">
|
||||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
|
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="coverlet.collector" Version="3.1.2">
|
<PackageReference Include="coverlet.collector">
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
|
|||||||
@@ -1,21 +1,17 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net6.0</TargetFramework>
|
|
||||||
<IsPackable>false</IsPackable>
|
<IsPackable>false</IsPackable>
|
||||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
|
||||||
<EnableNETAnalyzers>false</EnableNETAnalyzers>
|
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.2" />
|
<PackageReference Include="Microsoft.NET.Test.Sdk" />
|
||||||
<PackageReference Include="Rsdo.StyleCop" Version="1.0.0" />
|
<PackageReference Include="xunit" />
|
||||||
<PackageReference Include="xunit" Version="2.4.2" />
|
<PackageReference Include="xunit.runner.visualstudio">
|
||||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
|
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="coverlet.collector" Version="3.1.2">
|
<PackageReference Include="coverlet.collector">
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
|
|||||||
Reference in New Issue
Block a user