diff --git a/.azuredevops/pipelines/publish-job.yml b/.azuredevops/pipelines/publish-job.yml new file mode 100644 index 000000000..24c24d385 --- /dev/null +++ b/.azuredevops/pipelines/publish-job.yml @@ -0,0 +1,93 @@ + +variables: + - template: templates/variables.yml + +stages: +- stage: build + jobs: + - job: Build + pool: + vmImage: ${{ variables.vmImage }} + steps: + - template: templates/build-steps.yml + +- stage: publish + jobs: + - job: + strategy: + matrix: + win10-x64: + runtime: win10-x64 + format: zip + compression: zip + win10-x86: + runtime: win10-x86 + format: zip + compression: zip + osx-x64: + runtime: osx-x64 + format: tar.gz + compression: tar + linux-x64: + runtime: linux-x64 + format: tar.gz + compression: tar + linux-arm: + runtime: linux-arm + format: tar.gz + compression: tar + linux-arm64: + runtime: linux-arm64 + format: tar.gz + compression: tar + pool: + vmImage: ${{ variables.vmImage }} + steps: + - template: templates/publish-os-steps.yml + +- stage: deploy + jobs: + - job: + condition: and(succeeded(), eq(variables.isMain, true)) + steps: + - task: DownloadPipelineArtifact@2 + inputs: + buildType: 'current' + targetPath: '$(System.ArtifactsDirectory)' + + - task: PowerShell@2 + displayName: 'Get Release Notes' + inputs: + targetType: 'inline' + script: | + $response = Invoke-WebRequest -Uri "https://ombireleasenote.azurewebsites.net/api/ReleaseNotesFunction?buildId=$(Build.BuildId)" + Write-Host "##vso[task.setvariable variable=ReleaseNotes;]$response" + + # - task: GitHubRelease@1 + # inputs: + # gitHubConnection: 'github.com_tidusjar' + # repositoryName: 'tidusjar/Ombi' + # action: 'create' + # target: '$(Build.SourceVersion)' + # tagSource: 'userSpecifiedTag' + # tag: '$(gitTag)' + # isDraft: true + # changeLogCompareToRelease: 'lastNonDraftRelease' + # changeLogType: 'commitBased' + + - task: GitHubRelease@1 + inputs: + gitHubConnection: 'github.com_tidusjar' + repositoryName: 'tidusjar/Ombi.Releases' + action: 'create' + target: 'c7fcbb77b58aef1076d635a9ef99e4374abc8672' + tagSource: 'userSpecifiedTag' + tag: '$(gitTag)' + releaseNotesSource: 'inline' + releaseNotesInline: '$(ReleaseNotes)' + assets: | + $(System.ArtifactsDirectory)/**/*.zip + $(System.ArtifactsDirectory)/**/*.tar.gz + isPreRelease: true + changeLogCompareToRelease: 'lastNonDraftRelease' + changeLogType: 'commitBased' diff --git a/.azuredevops/pipelines/templates/build-steps.yml b/.azuredevops/pipelines/templates/build-steps.yml new file mode 100644 index 000000000..111424222 --- /dev/null +++ b/.azuredevops/pipelines/templates/build-steps.yml @@ -0,0 +1,34 @@ +steps: +## This is needed due to https://github.com/microsoft/azure-pipelines-tasks/issues/8429 +## For the set version tool... +- task: DotNetCoreInstaller@1 + displayName: 'Use .NET Core sdk ' + inputs: + packageType: 'sdk' + version: '5.x' + +- task: Yarn@3 + displayName: 'Install UI Dependancies' + inputs: + projectDirectory: '$(UiLocation)' + arguments: 'install' + +- task: Yarn@3 + displayName: 'Build and Publish Angular App' + inputs: + projectDirectory: '$(UiLocation)' + arguments: 'run build' + +- task: PublishPipelineArtifact@1 + inputs: + targetPath: '$(UiLocation)dist' + artifact: 'angular_dist' + publishLocation: 'pipeline' + +- task: DotNetCoreCLI@2 + displayName: Run Unit Tests + inputs: + command: 'custom' + projects: '$(TestProject)' + custom: 'test' + continueOnError: false diff --git a/.azuredevops/pipelines/templates/publish-os-steps.yml b/.azuredevops/pipelines/templates/publish-os-steps.yml new file mode 100644 index 000000000..2f63fa4a4 --- /dev/null +++ b/.azuredevops/pipelines/templates/publish-os-steps.yml @@ -0,0 +1,57 @@ +steps: +- task: DotNetCoreInstaller@1 + displayName: 'Use .NET Core sdk ' + inputs: + packageType: 'sdk' + version: '5.x' + +- task: DotNetCoreInstaller@1 + displayName: 'Use .NET Core sdk for versioning' + inputs: + packageType: 'sdk' + version: '3.1.x' + +- task: PowerShell@2 + displayName: 'Set Version' + inputs: + targetType: 'inline' + script: | + dotnet tool install -g dotnet-setversion + setversion -r $(BuildVersion) + +- task: DotNetCoreCLI@2 + displayName: 'publish $(runtime)' + inputs: + command: 'publish' + publishWebProjects: true + arguments: '-c $(BuildConfiguration) -r "$(runtime)" -o $(Build.ArtifactStagingDirectory)/$(runtime) --self-contained true -p:PublishSingleFile=true' + zipAfterPublish: false + modifyOutputPath: false + +- task: DownloadPipelineArtifact@2 + inputs: + buildType: 'current' + artifactName: 'angular_dist' + targetPath: '$(Build.ArtifactStagingDirectory)/angular_dist' + +- task: CopyFiles@2 + displayName: 'Copy Angular App $(runtime)' + inputs: + SourceFolder: '$(Build.ArtifactStagingDirectory)/angular_dist' + Contents: '**' + TargetFolder: '$(Build.ArtifactStagingDirectory)/$(runtime)/ClientApp/dist' + +- task: ArchiveFiles@2 + displayName: 'Zip $(runtime)' + inputs: + rootFolderOrFile: '$(Build.ArtifactStagingDirectory)/$(runtime)' + includeRootFolder: false + archiveType: $(compression) + archiveFile: '$(Build.ArtifactStagingDirectory)/$(runtime).$(format)' + replaceExistingArchive: true + +- task: PublishPipelineArtifact@1 + inputs: + targetPath: '$(Build.ArtifactStagingDirectory)/$(runtime).$(format)' + artifact: '$(runtime)' + publishLocation: 'pipeline' diff --git a/.azuredevops/pipelines/templates/variables.yml b/.azuredevops/pipelines/templates/variables.yml new file mode 100644 index 000000000..c33cd7999 --- /dev/null +++ b/.azuredevops/pipelines/templates/variables.yml @@ -0,0 +1,30 @@ +variables: + - name: "BuildConfiguration" + value: "Release" + + - name: "vmImage" + value: "ubuntu-latest" + + - name: "Solution" + value: "**/*.sln" + + - name: "TestProject" + value: "**/*.Tests.csproj" + + - name: "NetCoreVersion" + value: "5.0" + + - name: "PublishLocation" + value: "$(Build.SourcesDirectory)/src/Ombi/bin/Release/netcoreapp$(NetCoreVersion)" + + - name: "GitTag" + value: "v$(buildVersion)" + + - name: "UiLocation" + value: "$(Build.SourcesDirectory)/src/Ombi/ClientApp/" + + - name: "BuildVersion" + value: "4.0.$(Build.BuildId)" + + - name: isMain + value: $[eq(variables['Build.SourceBranch'], 'refs/heads/feature/v4')] \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 2236cc395..8f206e648 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -1,9 +1,6 @@ --- -name: Bug report +name: "\U0001F41B Bug report" about: Create a report to help us improve -title: '' -labels: '' -assignees: '' --- @@ -32,6 +29,7 @@ If applicable, a snippet of the logs that seems relevant to the bug if present. **Ombi Version (please complete the following information):** - Version [e.g. 3.0.1158] - Media Server [e.g. Plex] +- Database Type: SQLite (Please change if using MySQL) **Additional context** Add any other context about the problem here. diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 000000000..82f01f053 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,11 @@ +blank_issues_enabled: false +contact_links: + - name: Wiki + url: https://github.com/tidusjar/Ombi/wiki + about: The Ombi wiki should help guide you through installation and setup as well as help resolve common problems and answer frequently asked questions + - name: Reddit support + url: https://www.reddit.com/r/Ombi + about: Ask questions about Ombi + - name: Feature suggestions + url: https://ombifeatures.featureupvote.com + about: Share your suggestions or ideas to make Ombi better! diff --git a/.github/workflows/aspnetcore.yml b/.github/workflows/aspnetcore.yml deleted file mode 100644 index e562216cc..000000000 --- a/.github/workflows/aspnetcore.yml +++ /dev/null @@ -1,18 +0,0 @@ -name: ASP.NET Core CI - -on: [push, pull_request] - -jobs: - build: - - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v1 - - name: Setup .NET Core - uses: actions/setup-dotnet@v1 - with: - dotnet-version: 2.2.108 - - - name: Build Backend - run: ./build.sh --settings_skipverification=true diff --git a/.github/workflows/test.workflow b/.github/workflows/test.workflow deleted file mode 100644 index 7c88813d1..000000000 --- a/.github/workflows/test.workflow +++ /dev/null @@ -1,9 +0,0 @@ -workflow "New workflow" { - on = "push" - resolves = [".NET Core CLI"] -} - -action ".NET Core CLI" { - uses = "baruchiro/github-actions@0.0.1" - args = "build src/Ombi.sln" -} diff --git a/.gitignore b/.gitignore index dbf0d54e0..1a1a229b8 100644 --- a/.gitignore +++ b/.gitignore @@ -247,3 +247,5 @@ _Pvt_Extensions # Ignore local vscode config *.vscode /src/Ombi/database.json +/src/Ombi/healthchecksdb +/src/Ombi/ClientApp/package-lock.json diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 29b920feb..000000000 --- a/.travis.yml +++ /dev/null @@ -1,7 +0,0 @@ -language: csharp -solution: src/Ombi.sln -install: - - mono Tools/nuget.exe restore Ombi.sln - - nuget install NUnit.Runners -OutputDirectory testrunner -script: - - xbuild /p:Configuration=Release Ombi.sln /p:TargetFrameworkVersion="v4.5" diff --git a/BuildTask.ps1 b/BuildTask.ps1 deleted file mode 100644 index 9ed055206..000000000 --- a/BuildTask.ps1 +++ /dev/null @@ -1,12 +0,0 @@ - -param([String]$env='local') - -"Environment: " + $env | Write-Output; -"Build Version: " + $env:APPVEYOR_BUILD_VERSION | Write-Output; -"Base Path: " + $env:APPVEYOR_BUILD_FOLDER | Write-Output; - -$appSettingsPath = $env:APPVEYOR_BUILD_FOLDER + '\src\Ombi\appsettings.json' -$appSettings = Get-Content $appSettingsPath -raw -$appSettings = $appSettings.Replace("{{VERSIONNUMBER}}",$env:APPVEYOR_BUILD_VERSION); -$appSettings = $appSettings.Replace("{{BRANCH}}",$env:APPVEYOR_REPO_BRANCH); -Set-Content -Path $appSettingsPath -Value $appSettings diff --git a/CHANGELOG.md b/CHANGELOG.md index a611b5b99..6febb6683 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,77 @@ # Changelog -## v3.0.4817 (2019-10-15) +## (unreleased) + +### **New Features** + +- Update login.component.ts. [Jamie] + +- Update CHANGELOG.md. [Jamie] + +- Updated SlackNotification.cs. [Tim] + +### **Fixes** + +- Fixed the issue where we couldn't always pick up stuff on the sync. [tidusjar] + +- Removed hangfire completly from Ombi. [tidusjar] + +- Fixed the notifications issue. [tidusjar] + +- Fixed the issues where the DB was being disposed too early. [tidusjar] + +- Fixed an error with the newsletter with the new db structure. [tidusjar] + +- Output some useful stuff to the about window regarding the databases. [tidusjar] + +- Fixed the migration for combined databases. [tidusjar] + +- Fixed the issue where exisitng databases would now fail due to the DB structure changes. [tidusjar] + +- Finished it! [tidusjar] + +- Got MySql working. [tidusjar] + +- Got the new DB structure in place. [tidusjar] + +- Fix for #3219. [tidusjar] + +- Fixed the error in the newsletter. [tidusjar] + +- Fixed #3208. [tidusjar] + +- Use tags and autocomplete for excluded keywords. [Taylor Buchanan] + +- Add comments to clarify filter decisions. [Taylor Buchanan] + +- Fix TS import order. [Taylor Buchanan] + +- Add adult movie filtering. [Taylor Buchanan] + +- Fix search bar overlap on mobile. [Taylor Buchanan] + +- New translations en.json (Slovak) [Jamie] + +- New translations en.json (Slovak) [Jamie] + +- New translations en.json (Slovak) [Jamie] + +- New translations en.json (Slovak) [Jamie] + +- New translations en.json (Slovak) [Jamie] + +- New translations en.json (Slovak) [Jamie] + +- New translations en.json (Slovak) [Jamie] + +- Add SK lang. [Jamie Rees] + +- Add the migration to the correct database... #3214. [tidusjar] + +- Hopefully provide a fix now for #2998 Theory is that the refresh metadata was using stale data and then overriding the availbility that just happened on that media item. [tidusjar] + + +## v3.0.4817 (2019-10-12) ### **New Features** @@ -34,6 +105,8 @@ ### **Fixes** +- Gitchangelog. [tidusjar] + - Fixed #3078. [tidusjar] - Fixes issue #3195 The new string extension method ToHttpsUrl ensures that URLs starting with "https" are no longer turned into "httpss" The commit also replaces all occurances of the error prone .Replace("http", "https") in the whole solution. [msdeibel] diff --git a/README.md b/README.md index e8e269e7f..fdb90a5fc 100644 --- a/README.md +++ b/README.md @@ -9,8 +9,16 @@ ____ [![Patreon](https://img.shields.io/badge/patreon-donate-yellow.svg)](https://patreon.com/tidusjar/Ombi) [![Paypal](https://img.shields.io/badge/paypal-donate-yellow.svg)](https://paypal.me/PlexRequestsNet) +# Feature Requests +Feature requests are handled on Feature Upvote. + +Search the existing requests to see if your suggestion has already been submitted. +(If a similar request exists, please vote, or add additional comments to the request) + +#### [![Feature Requests](https://cloud.githubusercontent.com/assets/390379/10127973/045b3a96-6560-11e5-9b20-31a2032956b2.png)](https://features.ombi.io) ___ + [![Twitter](https://img.shields.io/twitter/follow/tidusjar.svg?style=social)](https://twitter.com/intent/follow?screen_name=tidusjar) Follow me developing Ombi! @@ -33,10 +41,10 @@ We also now have merch up on Teespring! ___ -| Service | Stable | Develop | -|----------|:---------------------------:|:----------------------------:| -| AppVeyor | [![Build status](https://ci.appveyor.com/api/projects/status/hgj8j6lcea7j0yhn/branch/master?svg=true)](https://ci.appveyor.com/project/tidusjar/requestplex/branch/master) | [![Build status](https://ci.appveyor.com/api/projects/status/hgj8j6lcea7j0yhn/branch/develop?svg=true)](https://ci.appveyor.com/project/tidusjar/requestplex/branch/develop) | -| Download |[![Download](http://i.imgur.com/odToka3.png)](https://github.com/tidusjar/Ombi/releases) | [![Download](http://i.imgur.com/odToka3.png)](https://ci.appveyor.com/project/tidusjar/requestplex/branch/develop/artifacts) | +| Service | Stable | Develop | V4 | +|----------|:---------------------------:|:----------------------------:|:----------------------------:| +| Build Status | [![Build status](https://ci.appveyor.com/api/projects/status/hgj8j6lcea7j0yhn/branch/master?svg=true)](https://ci.appveyor.com/project/tidusjar/requestplex/branch/master) | [![Build status](https://ci.appveyor.com/api/projects/status/hgj8j6lcea7j0yhn/branch/develop?svg=true)](https://ci.appveyor.com/project/tidusjar/requestplex/branch/develop) | [![Build Status](https://dev.azure.com/tidusjar/Ombi/_apis/build/status/Ombi%20CI?branchName=feature%2Fv4)](https://dev.azure.com/tidusjar/Ombi/_build/latest?definitionId=18&branchName=feature%2Fv4) +| Download |[![Download](http://i.imgur.com/odToka3.png)](https://github.com/tidusjar/Ombi/releases) | [![Download](http://i.imgur.com/odToka3.png)](https://ci.appveyor.com/project/tidusjar/requestplex/branch/develop/artifacts) | [![Download](http://i.imgur.com/odToka3.png)](https://github.com/tidusjar/ombi.releases/releases) | # Features Here are some of the features Ombi V3 has: * Now working without crashes on Linux. @@ -57,8 +65,9 @@ Here are some of the features Ombi V3 has: We integrate with the following applications: * Plex Media Server * Emby -* Sonarr -* Radarr +* Jellyfin +* Sonarr V2 and V3 +* Radarr V2 * Lidarr * DogNzb * Couch Potato @@ -66,47 +75,45 @@ We integrate with the following applications: ### Notifications Supported notifications: +* Mobile * SMTP Notifications (Email) * Discord -* Gotify * Slack * Pushbullet * Pushover * Mattermost * Telegram +* Gotify +* Twilio +* Webhook -### The difference between Version 3 and 2 +### The difference between Version 4 and 3 Over the last year, we focused on the main functions on Ombi, a complete rewrite while making it better, faster and more stable. We have already done most of the work, but some features are still be missing in this first version. -We are planning to bring back these features in V3 but for now you can find a list below with a quick comparison of features between v2 and v3. +We are planning to bring back these features in V3 but for now you can find a list below with a quick comparison of features between v4 and v3. -| Service | Version 3 | Version 2 | +| Service | Version 4 (Beta) | Version 3 (Stable)| |----------|:----------:|:----------:| -| Multiple Plex/Emby Servers| Yes | No | -| Emby & Plex support | Yes | Yes | -| Mono dependency | No | Yes | -| Notifications support | Yes| Yes | -| Landing page | Yes (brand new) | Yes | +| Multiple Plex/Emby/Jellyfin Servers | Yes | Yes | +| Emby/Jellyfin & Plex support | Yes | Yes | +| Mono dependency | No | No | +| Plex OAuth support | Yes | Yes | | Login page | Yes (brand new) | Yes | -| Custom Notification Messages | Yes | No | +| Discovery page | Yes (brand new) | No | +| Request a movie collection | Yes (brand new) | No | +| Auto Delete Available Requests | Yes (brand new) | No | +| Report issues | Yes | Yes | +| Notifications support | Yes | Yes | +| Custom Notification Messages | Yes | Yes | | Sending newsletters | Yes | Yes | | Send a Mass Email | Yes | Yes | | SickRage | Yes | Yes | | CouchPotato | Yes | Yes | -| DogNzb | Yes | No | -| Issues | Yes | Yes | +| DogNzb | Yes | Yes | | Headphones | No | Yes | -| Lidarr | Yes | No | - -# Feature Requests -Feature requests are handled on FeatHub. - -Search the existing requests to see if your suggestion has already been submitted. -(If a similar request exists, give it a thumbs up (+1), or add additional comments to the request) - -#### [![Feature Requests](https://cloud.githubusercontent.com/assets/390379/10127973/045b3a96-6560-11e5-9b20-31a2032956b2.png)](http://feathub.com/tidusjar/Ombi) +| Lidarr | Yes | Yes | # Preview diff --git a/appveyor.yml b/appveyor.yml deleted file mode 100644 index c2415ad23..000000000 --- a/appveyor.yml +++ /dev/null @@ -1,72 +0,0 @@ -version: 4.0.{build} -configuration: Release -os: Visual Studio 2019 - -environment: - nodejs_version: "11.5.0" - typescript_version: "3.0.1" - github_auth_token: - secure: H/7uCrjmWHGJxgN3l9fbhhdVjvvWI8VVF4ZzQqeXuJwAf+PgSNBdxv4SS+rMQ+RH - - - -# Do not build on tags (GitHub and BitBucket) -skip_tags: true - -install: - # Get the latest stable version of Node.js or io.js - - ps: Install-Product node $env:nodejs_version - - - cmd: set path=%programfiles(x86)%\\Microsoft SDKs\TypeScript\3.6;%path% - - cmd: tsc -v -build_script: - - ps: | - $deployBranches = - "feature/v4", - "develop", - "master"; - - If(($env:APPVEYOR_REPO_BRANCH -in $deployBranches -Or $env:APPVEYOR_REPO_COMMIT_MESSAGE -Match '!deploy') -And $env:APPVEYOR_REPO_COMMIT_MESSAGE -NotMatch '!build') { - Write-Output "This is a deployment build" - $env:Deploy = 'true' - ./build.ps1 - } - Else - { - $env:Deploy = 'false' - Write-Output "This is a not a deployment build" - ./build.ps1 --target=build - } - -skip_commits: - files: - - '**/*.md' - -after_build: -- ps: | - $deployBranches = - "feature/v4", - "develop", - "master"; - - If(($env:APPVEYOR_REPO_BRANCH -in $deployBranches -Or $env:APPVEYOR_REPO_COMMIT_MESSAGE -Match '!deploy') -And $env:APPVEYOR_REPO_COMMIT_MESSAGE -NotMatch '!build') - { - Write-Output "Deploying!" - Get-ChildItem -Recurse .\*.zip | % { Push-AppveyorArtifact $_.FullName -FileName $_.Name } - Get-ChildItem -Recurse .\*.gz | % { Push-AppveyorArtifact $_.FullName -FileName $_.Name } - } - Else - { - Write-Output "No Deployment" - } - -#cache: -#- '%USERPROFILE%\.nuget\packages' -deploy: -- provider: GitHub - release: Ombi v$(appveyor_build_version) - auth_token: - secure: jDpp1/WUQl3uN41fNI3VeZoRZbDiDfs3GPQ1v+C5ZNE3cWdnUvuJfCCfUbYUV1Rp - draft: true - on: - branch: master diff --git a/azure-pipelines.yml b/azure-pipelines.yml deleted file mode 100644 index f2352a798..000000000 --- a/azure-pipelines.yml +++ /dev/null @@ -1,83 +0,0 @@ -# ASP.NET Core -# Build and test ASP.NET Core projects targeting .NET Core. -# Add steps that run tests, create a NuGet package, deploy, and more: -# https://docs.microsoft.com/azure/devops/pipelines/languages/dotnet-core - -trigger: -- master -- feature/v4 -- develop - -variables: - solution: '**/*.sln' - testProj: '**/*.Tests.csproj' - csProj: '**/*.csproj' - buildConfiguration: 'Release' - publishLocation: '$(Build.SourcesDirectory)/src/Ombi/bin/Release/netcoreapp2.2' - -pool: - vmImage: 'ubuntu-latest' - - -steps: -- task: CmdLine@2 - displayName: Run Build Script - inputs: - script: './build.sh' -- task: CmdLine@2 - inputs: - script: | - cd src/Ombi/bin/Release/netcoreapp2.2 - - ls - workingDirectory: '$(Build.SourcesDirectory)' -- task: CopyFiles@2 - displayName: Upload Windows Build - inputs: - SourceFolder: '$(publishLocation)/windows.zip' - TargetFolder: '$(Build.ArtifactStagingDirectory)' - OverWrite: true - -- task: CopyFiles@2 - displayName: Upload OSX Build - inputs: - SourceFolder: '**/osx.tar.gz' - TargetFolder: '$(Build.ArtifactStagingDirectory)' - OverWrite: true - -- task: CopyFiles@2 - displayName: Upload Linux Build - inputs: - SourceFolder: '$(publishLocation)/linux.tar.gz' - TargetFolder: '$(Build.ArtifactStagingDirectory)' - OverWrite: true - -- task: CopyFiles@2 - displayName: Upload Linux-ARM Build - inputs: - SourceFolder: '$(publishLocation)/linux-arm.tar.gz' - TargetFolder: '$(Build.ArtifactStagingDirectory)' - OverWrite: true - -- task: CopyFiles@2 - displayName: Upload Windows 32Bit Build - inputs: - SourceFolder: '$(publishLocation)/windows-32bit.zip' - TargetFolder: '$(Build.ArtifactStagingDirectory)' - OverWrite: true - -- task: CopyFiles@2 - displayName: Upload Linux-ARM64 Build - inputs: - SourceFolder: '$(publishLocation)/linux-arm64.tar.gz' - TargetFolder: '$(Build.ArtifactStagingDirectory)' - OverWrite: true - -- task: PublishTestResults@2 - displayName: Upload Test Results - inputs: - testResultsFormat: 'VSTest' - testResultsFiles: '**/Test.trx' - mergeTestResults: true - failTaskOnFailedTests: true - testRunTitle: 'Unit Tests' \ No newline at end of file diff --git a/build.cake b/build.cake deleted file mode 100644 index 49d446de1..000000000 --- a/build.cake +++ /dev/null @@ -1,306 +0,0 @@ - -#tool "nuget:?package=GitVersion.CommandLine&version=5.0.1" -#addin nuget:?package=SharpZipLib&version=1.2.0 -#addin nuget:?package=Cake.Compression&version=0.2.3 -#addin "Cake.Incubator&version=5.1.0" -#addin nuget:?package=Cake.Yarn&version=0.4.6 - -////////////////////////////////////////////////////////////////////// -// ARGUMENTS -////////////////////////////////////////////////////////////////////// - -var target = Argument("target", "Default"); -var configuration = Argument("configuration", "Release"); - -////////////////////////////////////////////////////////////////////// -// PREPARATION -////////////////////////////////////////////////////////////////////// - -var buildDir = "./src/Ombi/bin/" + configuration; -var nodeModulesDir ="./src/Ombi/ClientApp/node_modules/"; -var wwwRootDistDir = "./src/Ombi/wwwroot/dist/"; -var projDir = "./src/"; // Project Directory -var webProjDir = "./src/Ombi"; -var uiProjectDir = "./src/Ombi/ClientApp"; -var csProj = "./src/Ombi/Ombi.csproj"; // Path to the project.csproj -var solutionFile = "Ombi.sln"; // Solution file if needed -GitVersion versionInfo = null; - -var frameworkVer = "netcoreapp3.0"; - -var buildSettings = new DotNetCoreBuildSettings -{ - Framework = frameworkVer, - Configuration = "Release", - OutputDirectory = Directory(buildDir), -}; - -var publishSettings = new DotNetCorePublishSettings -{ - Framework = frameworkVer, - Configuration = "Release", - OutputDirectory = Directory(buildDir), -}; - -var artifactsFolder = buildDir + "/"+frameworkVer+"/"; -var windowsArtifactsFolder = artifactsFolder + "win10-x64/published"; -var windows32BitArtifactsFolder = artifactsFolder + "win10-x86/published"; -var osxArtifactsFolder = artifactsFolder + "osx-x64/published"; -var linuxArtifactsFolder = artifactsFolder + "linux-x64/published"; -var linuxArmArtifactsFolder = artifactsFolder + "linux-arm/published"; -var linuxArm64BitArtifactsFolder = artifactsFolder + "linux-arm64/published"; - - - - -////////////////////////////////////////////////////////////////////// -// TASKS -////////////////////////////////////////////////////////////////////// - -Task("Clean") - .Does(() => -{ - CleanDirectory(buildDir); - //CleanDirectory(nodeModulesDir); - CleanDirectory(wwwRootDistDir); -}); - -Task("SetVersionInfo") - .IsDependentOn("Clean") - .Does(() => -{ - var settings = new GitVersionSettings { - RepositoryPath = ".", - }; - - if (AppVeyor.IsRunningOnAppVeyor) { - settings.Branch = AppVeyor.Environment.Repository.Branch; - } else { - settings.Branch = "master"; - } - - versionInfo = GitVersion(settings); - -// Information("GitResults -> {0}", versionInfo.Dump()); - -//Information(@"Build:{0}",AppVeyor.Environment.Build.Dump()); - - var buildVersion = string.Empty; - if(string.IsNullOrEmpty(AppVeyor.Environment.Build.Version)) - { - buildVersion = "3.0.000"; - } else{ - buildVersion = AppVeyor.Environment.Build.Version; - } - - if(versionInfo.BranchName.Contains("_")) - { - versionInfo.BranchName = versionInfo.BranchName.Replace("_","-"); - } - var fullVer = buildVersion + "-" + versionInfo.BranchName; - - if(versionInfo.PreReleaseTag.Contains("PullRequest")) - { - fullVer = buildVersion + "-PR"; - } - if(fullVer.Contains("_")) - { - fullVer = fullVer.Replace("_",""); - } - if(fullVer.Contains("/")) - { - fullVer = fullVer.Replace("/",""); - } - - buildSettings.ArgumentCustomization = args => args.Append("/p:SemVer=" + versionInfo.AssemblySemVer); - buildSettings.ArgumentCustomization = args => args.Append("/p:FullVer=" + fullVer); - publishSettings.ArgumentCustomization = args => args.Append("/p:SemVer=" + versionInfo.AssemblySemVer); - publishSettings.ArgumentCustomization = args => args.Append("/p:FullVer=" + fullVer); - //buildSettings.VersionSuffix = versionInfo.BranchName; - //publishSettings.VersionSuffix = versionInfo.BranchName; -}); - -Task("NPM") - .Does(() => { - Yarn.FromPath(uiProjectDir).Install(); -}); - -Task("Gulp Publish") - .IsDependentOn("NPM") - .Does(() => { - Yarn.FromPath(uiProjectDir).RunScript("build"); - }); - -Task("TSLint") - .Does(() => -{ - //Yarn.FromPath(uiProjectDir).RunScript("lint"); -}); - -Task("PrePublish") - .IsDependentOn("SetVersionInfo"); - //.IsDependentOn("Gulp Publish") // these are done in the main csproj - //.IsDependentOn("TSLint"); - - -Task("Package") - .Does(() => -{ - Zip(windowsArtifactsFolder +"/",artifactsFolder + "windows.zip"); - Zip(windows32BitArtifactsFolder +"/",artifactsFolder + "windows-32bit.zip"); - GZipCompress(osxArtifactsFolder, artifactsFolder + "osx.tar.gz"); - GZipCompress(linuxArtifactsFolder, artifactsFolder + "linux.tar.gz"); - GZipCompress(linuxArmArtifactsFolder, artifactsFolder + "linux-arm.tar.gz"); - GZipCompress(linuxArm64BitArtifactsFolder, artifactsFolder + "linux-arm64.tar.gz"); -}); - -Task("Publish") - .IsDependentOn("Upload-Test-Results") - .IsDependentOn("PrePublish") - .IsDependentOn("Publish-Windows") - .IsDependentOn("Publish-Windows-32bit") - .IsDependentOn("Publish-OSX") - .IsDependentOn("Publish-Linux") - .IsDependentOn("Publish-Linux-ARM") - .IsDependentOn("Publish-Linux-ARM-64Bit") - .IsDependentOn("Package"); - -Task("Publish-Windows") - .Does(() => -{ - publishSettings.Runtime = "win10-x64"; - publishSettings.OutputDirectory = Directory(buildDir) + Directory(frameworkVer +"/win10-x64/published"); - - DotNetCorePublish("./src/Ombi/Ombi.csproj", publishSettings); - CopyFile(buildDir + "/"+frameworkVer+"/win10-x64/Swagger.xml", buildDir + "/"+frameworkVer+"/win10-x64/published/Swagger.xml"); - - publishSettings.OutputDirectory = Directory(buildDir) + Directory(frameworkVer +"/win10-x64/published/updater"); - DotNetCorePublish("./src/Ombi.Updater/Ombi.Updater.csproj", publishSettings); -}); - -Task("Publish-Windows-32bit") - .Does(() => -{ - publishSettings.Runtime = "win10-x86"; - publishSettings.OutputDirectory = Directory(buildDir) + Directory(frameworkVer+"/win10-x86/published"); - - DotNetCorePublish("./src/Ombi/Ombi.csproj", publishSettings); - CopyFile(buildDir + "/"+frameworkVer+"/win10-x86/Swagger.xml", buildDir + "/"+frameworkVer+"/win10-x86/published/Swagger.xml"); - - - publishSettings.OutputDirectory = Directory(buildDir) + Directory(frameworkVer +"/win10-x86/published/updater"); - DotNetCorePublish("./src/Ombi.Updater/Ombi.Updater.csproj", publishSettings); -}); - -Task("Publish-OSX") - .Does(() => -{ - publishSettings.Runtime = "osx-x64"; - publishSettings.OutputDirectory = Directory(buildDir) + Directory(frameworkVer+"/osx-x64/published"); - - DotNetCorePublish("./src/Ombi/Ombi.csproj", publishSettings); - CopyFile(buildDir + "/"+frameworkVer+"/osx-x64/Swagger.xml", buildDir + "/"+frameworkVer+"/osx-x64/published/Swagger.xml"); - - publishSettings.OutputDirectory = Directory(buildDir) + Directory(frameworkVer +"/osx-x64/published/updater"); - DotNetCorePublish("./src/Ombi.Updater/Ombi.Updater.csproj", publishSettings); -}); - -Task("Publish-Linux") - .Does(() => -{ - publishSettings.Runtime = "linux-x64"; - publishSettings.OutputDirectory = Directory(buildDir) + Directory(frameworkVer+"/linux-x64/published"); - - DotNetCorePublish("./src/Ombi/Ombi.csproj", publishSettings); - CopyFile(buildDir + "/"+frameworkVer+"/linux-x64/Swagger.xml", buildDir + "/"+frameworkVer+"/linux-x64/published/Swagger.xml"); - - publishSettings.OutputDirectory = Directory(buildDir) + Directory(frameworkVer +"/linux-x64/published/updater"); - DotNetCorePublish("./src/Ombi.Updater/Ombi.Updater.csproj", publishSettings); -}); - -Task("Publish-Linux-ARM") - .Does(() => -{ - publishSettings.Runtime = "linux-arm"; - publishSettings.OutputDirectory = Directory(buildDir) + Directory(frameworkVer+"/linux-arm/published"); - - DotNetCorePublish("./src/Ombi/Ombi.csproj", publishSettings); - CopyFile( - buildDir + "/"+frameworkVer+"/linux-arm/Swagger.xml", - buildDir + "/"+frameworkVer+"/linux-arm/published/Swagger.xml"); - - publishSettings.OutputDirectory = Directory(buildDir) + Directory(frameworkVer +"/linux-arm/published/updater"); - DotNetCorePublish("./src/Ombi.Updater/Ombi.Updater.csproj", publishSettings); -}); - -Task("Publish-Linux-ARM-64Bit") - .Does(() => -{ - publishSettings.Runtime = "linux-arm64"; - publishSettings.OutputDirectory = Directory(buildDir) + Directory(frameworkVer+"/linux-arm64/published"); - - DotNetCorePublish("./src/Ombi/Ombi.csproj", publishSettings); - CopyFile( - buildDir + "/"+frameworkVer+"/linux-arm64/Swagger.xml", - buildDir + "/"+frameworkVer+"/linux-arm64/published/Swagger.xml"); - - publishSettings.OutputDirectory = Directory(buildDir) + Directory(frameworkVer +"/linux-arm64/published/updater"); - DotNetCorePublish("./src/Ombi.Updater/Ombi.Updater.csproj", publishSettings); -}); - -Task("Run-Unit-Tests") - .Does(() => -{ - var settings = new DotNetCoreTestSettings - { - ArgumentCustomization = args => args.Append("--logger \"trx;LogFileName=Test.trx\""), - Configuration = "Release" - }; - var projectFiles = GetFiles("./**/*Tests.csproj"); - foreach(var file in projectFiles) - { - DotNetCoreTest(file.FullPath, settings); - } - - -}); - -Task("Upload-Test-Results") - .IsDependentOn("Run-Unit-Tests") - .ContinueOnError() - .Does(() => { - - }); - -Task("Run-Server-Build") - .Does(() => - { - var settings = new DotNetCoreBuildSettings - { - Framework = frameworkVer, - Configuration = "Release", - OutputDirectory = Directory(buildDir) - }; - DotNetCoreBuild(csProj, settings); - }); - -Task("Run-UI-Build") - .IsDependentOn("PrePublish"); -////////////////////////////////////////////////////////////////////// -// TASK TARGETS -////////////////////////////////////////////////////////////////////// - -Task("Default") - .IsDependentOn("Publish"); - -Task("Build") - .IsDependentOn("SetVersionInfo") - .IsDependentOn("Upload-Test-Results") - .IsDependentOn("Run-Server-Build"); - // .IsDependentOn("Run-UI-Build"); - -////////////////////////////////////////////////////////////////////// -// EXECUTION -////////////////////////////////////////////////////////////////////// - -RunTarget(target); diff --git a/build.ps1 b/build.ps1 deleted file mode 100644 index e61281292..000000000 --- a/build.ps1 +++ /dev/null @@ -1,242 +0,0 @@ -########################################################################## -# This is the Cake bootstrapper script for PowerShell. -# This file was downloaded from https://github.com/cake-build/resources -# Feel free to change this file to fit your needs. -########################################################################## - -<# - -.SYNOPSIS -This is a Powershell script to bootstrap a Cake build. - -.DESCRIPTION -This Powershell script will download NuGet if missing, restore NuGet tools (including Cake) -and execute your Cake build script with the parameters you provide. - -.PARAMETER Script -The build script to execute. -.PARAMETER Target -The build script target to run. -.PARAMETER Configuration -The build configuration to use. -.PARAMETER Verbosity -Specifies the amount of information to be displayed. -.PARAMETER ShowDescription -Shows description about tasks. -.PARAMETER DryRun -Performs a dry run. -.PARAMETER SkipToolPackageRestore -Skips restoring of packages. -.PARAMETER ScriptArgs -Remaining arguments are added here. - -.LINK -https://cakebuild.net - -#> - -[CmdletBinding()] -Param( - [string]$Script = "build.cake", - [string]$Target, - [string]$Configuration, - [ValidateSet("Quiet", "Minimal", "Normal", "Verbose", "Diagnostic")] - [string]$Verbosity, - [switch]$ShowDescription, - [Alias("WhatIf", "Noop")] - [switch]$DryRun, - [switch]$SkipToolPackageRestore, - [Parameter(Position=0,Mandatory=$false,ValueFromRemainingArguments=$true)] - [string[]]$ScriptArgs -) - -# Attempt to set highest encryption available for SecurityProtocol. -# PowerShell will not set this by default (until maybe .NET 4.6.x). This -# will typically produce a message for PowerShell v2 (just an info -# message though) -try { - # Set TLS 1.2 (3072), then TLS 1.1 (768), then TLS 1.0 (192), finally SSL 3.0 (48) - # Use integers because the enumeration values for TLS 1.2 and TLS 1.1 won't - # exist in .NET 4.0, even though they are addressable if .NET 4.5+ is - # installed (.NET 4.5 is an in-place upgrade). - [System.Net.ServicePointManager]::SecurityProtocol = 3072 -bor 768 -bor 192 -bor 48 - } catch { - Write-Output 'Unable to set PowerShell to use TLS 1.2 and TLS 1.1 due to old .NET Framework installed. If you see underlying connection closed or trust errors, you may need to upgrade to .NET Framework 4.5+ and PowerShell v3' - } - -[Reflection.Assembly]::LoadWithPartialName("System.Security") | Out-Null -function MD5HashFile([string] $filePath) -{ - if ([string]::IsNullOrEmpty($filePath) -or !(Test-Path $filePath -PathType Leaf)) - { - return $null - } - - [System.IO.Stream] $file = $null; - [System.Security.Cryptography.MD5] $md5 = $null; - try - { - $md5 = [System.Security.Cryptography.MD5]::Create() - $file = [System.IO.File]::OpenRead($filePath) - return [System.BitConverter]::ToString($md5.ComputeHash($file)) - } - finally - { - if ($file -ne $null) - { - $file.Dispose() - } - } -} - -function GetProxyEnabledWebClient -{ - $wc = New-Object System.Net.WebClient - $proxy = [System.Net.WebRequest]::GetSystemWebProxy() - $proxy.Credentials = [System.Net.CredentialCache]::DefaultCredentials - $wc.Proxy = $proxy - return $wc -} - -Write-Host "Preparing to run build script..." - -if(!$PSScriptRoot){ - $PSScriptRoot = Split-Path $MyInvocation.MyCommand.Path -Parent -} - -$TOOLS_DIR = Join-Path $PSScriptRoot "tools" -$ADDINS_DIR = Join-Path $TOOLS_DIR "Addins" -$MODULES_DIR = Join-Path $TOOLS_DIR "Modules" -$NUGET_EXE = Join-Path $TOOLS_DIR "nuget.exe" -$CAKE_EXE = Join-Path $TOOLS_DIR "Cake/Cake.exe" -$NUGET_URL = "https://dist.nuget.org/win-x86-commandline/latest/nuget.exe" -$PACKAGES_CONFIG = Join-Path $TOOLS_DIR "packages.config" -$PACKAGES_CONFIG_MD5 = Join-Path $TOOLS_DIR "packages.config.md5sum" -$ADDINS_PACKAGES_CONFIG = Join-Path $ADDINS_DIR "packages.config" -$MODULES_PACKAGES_CONFIG = Join-Path $MODULES_DIR "packages.config" - -# Make sure tools folder exists -if ((Test-Path $PSScriptRoot) -and !(Test-Path $TOOLS_DIR)) { - Write-Verbose -Message "Creating tools directory..." - New-Item -Path $TOOLS_DIR -Type directory | out-null -} - -# Make sure that packages.config exist. -if (!(Test-Path $PACKAGES_CONFIG)) { - Write-Verbose -Message "Downloading packages.config..." - try { - $wc = GetProxyEnabledWebClient - $wc.DownloadFile("https://cakebuild.net/download/bootstrapper/packages", $PACKAGES_CONFIG) - } catch { - Throw "Could not download packages.config." - } -} - -# Try find NuGet.exe in path if not exists -if (!(Test-Path $NUGET_EXE)) { - Write-Verbose -Message "Trying to find nuget.exe in PATH..." - $existingPaths = $Env:Path -Split ';' | Where-Object { (![string]::IsNullOrEmpty($_)) -and (Test-Path $_ -PathType Container) } - $NUGET_EXE_IN_PATH = Get-ChildItem -Path $existingPaths -Filter "nuget.exe" | Select -First 1 - if ($NUGET_EXE_IN_PATH -ne $null -and (Test-Path $NUGET_EXE_IN_PATH.FullName)) { - Write-Verbose -Message "Found in PATH at $($NUGET_EXE_IN_PATH.FullName)." - $NUGET_EXE = $NUGET_EXE_IN_PATH.FullName - } -} - -# Try download NuGet.exe if not exists -if (!(Test-Path $NUGET_EXE)) { - Write-Verbose -Message "Downloading NuGet.exe..." - try { - $wc = GetProxyEnabledWebClient - $wc.DownloadFile($NUGET_URL, $NUGET_EXE) - } catch { - Throw "Could not download NuGet.exe." - } -} - -# Save nuget.exe path to environment to be available to child processed -$ENV:NUGET_EXE = $NUGET_EXE - -# Restore tools from NuGet? -if(-Not $SkipToolPackageRestore.IsPresent) { - Push-Location - Set-Location $TOOLS_DIR - - # Check for changes in packages.config and remove installed tools if true. - [string] $md5Hash = MD5HashFile($PACKAGES_CONFIG) - if((!(Test-Path $PACKAGES_CONFIG_MD5)) -Or - ($md5Hash -ne (Get-Content $PACKAGES_CONFIG_MD5 ))) { - Write-Verbose -Message "Missing or changed package.config hash..." - Get-ChildItem -Exclude packages.config,nuget.exe,Cake.Bakery | - Remove-Item -Recurse - } - - Write-Verbose -Message "Restoring tools from NuGet..." - $NuGetOutput = Invoke-Expression "&`"$NUGET_EXE`" install -ExcludeVersion -OutputDirectory `"$TOOLS_DIR`"" - - if ($LASTEXITCODE -ne 0) { - Throw "An error occurred while restoring NuGet tools." - } - else - { - $md5Hash | Out-File $PACKAGES_CONFIG_MD5 -Encoding "ASCII" - } - Write-Verbose -Message ($NuGetOutput | out-string) - - Pop-Location -} - -# Restore addins from NuGet -if (Test-Path $ADDINS_PACKAGES_CONFIG) { - Push-Location - Set-Location $ADDINS_DIR - - Write-Verbose -Message "Restoring addins from NuGet..." - $NuGetOutput = Invoke-Expression "&`"$NUGET_EXE`" install -ExcludeVersion -OutputDirectory `"$ADDINS_DIR`"" - - if ($LASTEXITCODE -ne 0) { - Throw "An error occurred while restoring NuGet addins." - } - - Write-Verbose -Message ($NuGetOutput | out-string) - - Pop-Location -} - -# Restore modules from NuGet -if (Test-Path $MODULES_PACKAGES_CONFIG) { - Push-Location - Set-Location $MODULES_DIR - - Write-Verbose -Message "Restoring modules from NuGet..." - $NuGetOutput = Invoke-Expression "&`"$NUGET_EXE`" install -ExcludeVersion -OutputDirectory `"$MODULES_DIR`"" - - if ($LASTEXITCODE -ne 0) { - Throw "An error occurred while restoring NuGet modules." - } - - Write-Verbose -Message ($NuGetOutput | out-string) - - Pop-Location -} - -# Make sure that Cake has been installed. -if (!(Test-Path $CAKE_EXE)) { - Throw "Could not find Cake.exe at $CAKE_EXE" -} - - - -# Build Cake arguments -$cakeArguments = @("$Script"); -if ($Target) { $cakeArguments += "-target=$Target" } -if ($Configuration) { $cakeArguments += "-configuration=$Configuration" } -if ($Verbosity) { $cakeArguments += "-verbosity=$Verbosity" } -if ($ShowDescription) { $cakeArguments += "-showdescription" } -if ($DryRun) { $cakeArguments += "-dryrun" } -$cakeArguments += $ScriptArgs - -# Start Cake -Write-Host "Running build script..." -&$CAKE_EXE $cakeArguments -exit $LASTEXITCODE \ No newline at end of file diff --git a/build.sh b/build.sh deleted file mode 100755 index 6e14489c8..000000000 --- a/build.sh +++ /dev/null @@ -1,101 +0,0 @@ -#!/usr/bin/env bash - -########################################################################## -# This is the Cake bootstrapper script for Linux and OS X. -# This file was downloaded from https://github.com/cake-build/resources -# Feel free to change this file to fit your needs. -########################################################################## - -# Define directories. -SCRIPT_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) -TOOLS_DIR=$SCRIPT_DIR/tools -NUGET_EXE=$TOOLS_DIR/nuget.exe -CAKE_EXE=$TOOLS_DIR/Cake/Cake.exe -PACKAGES_CONFIG=$TOOLS_DIR/packages.config -PACKAGES_CONFIG_MD5=$TOOLS_DIR/packages.config.md5sum - -# Define md5sum or md5 depending on Linux/OSX -MD5_EXE= -if [[ "$(uname -s)" == "Darwin" ]]; then - MD5_EXE="md5 -r" -else - MD5_EXE="md5sum" -fi - -# Define default arguments. -SCRIPT="build.cake" -TARGET="Default" -CONFIGURATION="Release" -VERBOSITY="verbose" -DRYRUN= -SHOW_VERSION=false -SCRIPT_ARGUMENTS=() - -# Parse arguments. -for i in "$@"; do - case $1 in - -s|--script) SCRIPT="$2"; shift ;; - -t|--target) TARGET="$2"; shift ;; - -c|--configuration) CONFIGURATION="$2"; shift ;; - -v|--verbosity) VERBOSITY="$2"; shift ;; - -d|--dryrun) DRYRUN="-dryrun" ;; - --version) SHOW_VERSION=true ;; - --) shift; SCRIPT_ARGUMENTS+=("$@"); break ;; - *) SCRIPT_ARGUMENTS+=("$1") ;; - esac - shift -done - -# Make sure the tools folder exist. -if [ ! -d "$TOOLS_DIR" ]; then - mkdir "$TOOLS_DIR" -fi - -# Make sure that packages.config exist. -if [ ! -f "$TOOLS_DIR/packages.config" ]; then - echo "Downloading packages.config..." - curl -Lsfo "$TOOLS_DIR/packages.config" https://cakebuild.net/download/bootstrapper/packages - if [ $? -ne 0 ]; then - echo "An error occurred while downloading packages.config." - exit 1 - fi -fi - -# Download NuGet if it does not exist. -if [ ! -f "$NUGET_EXE" ]; then - echo "Downloading NuGet..." - curl -Lsfo "$NUGET_EXE" https://dist.nuget.org/win-x86-commandline/latest/nuget.exe - if [ $? -ne 0 ]; then - echo "An error occurred while downloading nuget.exe." - exit 1 - fi -fi - -# Restore tools from NuGet. -pushd "$TOOLS_DIR" >/dev/null -if [ ! -f $PACKAGES_CONFIG_MD5 ] || [ "$( cat $PACKAGES_CONFIG_MD5 | sed 's/\r$//' )" != "$( $MD5_EXE $PACKAGES_CONFIG | awk '{ print $1 }' )" ]; then - find . -type d ! -name . | xargs rm -rf -fi - -mono "$NUGET_EXE" install -ExcludeVersion -if [ $? -ne 0 ]; then - echo "Could not restore NuGet packages." - exit 1 -fi - -$MD5_EXE $PACKAGES_CONFIG | awk '{ print $1 }' >| $PACKAGES_CONFIG_MD5 - -popd >/dev/null - -# Make sure that Cake has been installed. -if [ ! -f "$CAKE_EXE" ]; then - echo "Could not find Cake.exe at '$CAKE_EXE'." - exit 1 -fi - -# Start Cake -if $SHOW_VERSION; then - exec mono "$CAKE_EXE" -version -else - exec mono "$CAKE_EXE" $SCRIPT -verbosity=$VERBOSITY -configuration=$CONFIGURATION -target=$TARGET $DRYRUN "${SCRIPT_ARGUMENTS[@]}" -fi diff --git a/ci-build.yaml b/ci-build.yaml deleted file mode 100644 index 7aba1cafb..000000000 --- a/ci-build.yaml +++ /dev/null @@ -1,38 +0,0 @@ -# ASP.NET Core -# Build and test ASP.NET Core projects targeting .NET Core. -# Add steps that run tests, create a NuGet package, deploy, and more: -# https://docs.microsoft.com/azure/devops/pipelines/languages/dotnet-core - - -trigger: - branches: - include: - - feature/* - exclude: - - feature/v4 - -variables: - solution: '**/*.sln' - testProj: '**/*.Tests.csproj' - csProj: '**/*.csproj' - buildConfiguration: 'Release' - -pool: - vmImage: 'ubuntu-latest' - -steps: -- task: UseDotNet@2 - displayName: Use dotnet sdk - inputs: - packageType: 'sdk' - version: '2.2.401' -- task: DotNetCoreCLI@2 - displayName: Run Unit Tests - inputs: - command: 'test' - projects: '$(testProj)' -- task: Yarn@3 - displayName: Build UI - inputs: - projectDirectory: '$(Build.SourcesDirectory)/src/Ombi/ClientApp/' - arguments: 'run build' diff --git a/src/Ombi.Api.CloudService/CloudMobileNotification.cs b/src/Ombi.Api.CloudService/CloudMobileNotification.cs new file mode 100644 index 000000000..aba2d90d3 --- /dev/null +++ b/src/Ombi.Api.CloudService/CloudMobileNotification.cs @@ -0,0 +1,51 @@ +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; +using Ombi.Helpers; +using System; +using System.Collections.Generic; +using System.Net.Http; +using System.Threading.Tasks; + +namespace Ombi.Api.CloudService +{ + public interface ICloudMobileNotification + { + Task SendMessage(MobileNotificationRequest notification); + } + public class CloudMobileNotification : ICloudMobileNotification + { + private readonly IApi _api; + private readonly ILogger _logger; + private readonly string _baseUrl; + + public CloudMobileNotification(IApi api, ILogger logger, IOptions settings) + { + _api = api; + _baseUrl = settings.Value.NotificationService; + _logger = logger; + } + + public async Task SendMessage(MobileNotificationRequest notification) + { + var request = new Request("MobileNotification", _baseUrl, HttpMethod.Post); + request.AddJsonBody(notification); + var response = await _api.Request(request); + + if (!response.IsSuccessStatusCode) + { + _logger.LogError($"Error when sending mobile notification message, status code: {response.StatusCode}. Please raise an issue on Github, might be a problem with" + + $" the notification service!"); + return false; + } + return true; + } + } + + public class MobileNotificationRequest + { + public string Title { get; set; } + public string Body { get; set; } + public string To { get; set; } + public Dictionary Data { get; set; } + } +} diff --git a/src/Ombi.Api.CloudService/Ombi.Api.CloudService.csproj b/src/Ombi.Api.CloudService/Ombi.Api.CloudService.csproj new file mode 100644 index 000000000..d92fd7c6d --- /dev/null +++ b/src/Ombi.Api.CloudService/Ombi.Api.CloudService.csproj @@ -0,0 +1,11 @@ + + + + net5.0 + + + + + + + diff --git a/src/Ombi.Api.CouchPotato/Ombi.Api.CouchPotato.csproj b/src/Ombi.Api.CouchPotato/Ombi.Api.CouchPotato.csproj index 3c31ecb84..bdd16edf8 100644 --- a/src/Ombi.Api.CouchPotato/Ombi.Api.CouchPotato.csproj +++ b/src/Ombi.Api.CouchPotato/Ombi.Api.CouchPotato.csproj @@ -1,7 +1,8 @@ - + - netstandard2.1 + net5.0 + 8.0 diff --git a/src/Ombi.Api.Discord/DiscordApi.cs b/src/Ombi.Api.Discord/DiscordApi.cs index 11cdc267e..34342e559 100644 --- a/src/Ombi.Api.Discord/DiscordApi.cs +++ b/src/Ombi.Api.Discord/DiscordApi.cs @@ -1,5 +1,6 @@ using System.Net.Http; using System.Threading.Tasks; +using Newtonsoft.Json; using Ombi.Api.Discord.Models; namespace Ombi.Api.Discord @@ -17,7 +18,7 @@ namespace Ombi.Api.Discord public async Task SendMessage(DiscordWebhookBody body, string webhookId, string webhookToken) { var request = new Request($"webhooks/{webhookId}/{webhookToken}", BaseUrl, HttpMethod.Post); - + request.AddJsonBody(body); request.ApplicationJsonContentType(); diff --git a/src/Ombi.Api.Discord/Models/DiscordWebhookBody.cs b/src/Ombi.Api.Discord/Models/DiscordWebhookBody.cs index 2d74087fb..7700005c8 100644 --- a/src/Ombi.Api.Discord/Models/DiscordWebhookBody.cs +++ b/src/Ombi.Api.Discord/Models/DiscordWebhookBody.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; namespace Ombi.Api.Discord.Models { @@ -13,8 +14,32 @@ namespace Ombi.Api.Discord.Models { public string title { get; set; } public string type => "rich"; // Always rich or embedded content - public string description { get; set; } // Don't really need to set this - public DiscordImage image { get; set; } + public string description { get; set; } + public DateTime timestamp => DateTime.Now; + public string color { get; set; } + public DiscordFooter footer { get; set; } + public DiscordImage thumbnail { get; set; } + public DiscordAuthor author { get; set; } + public List fields { get; set; } + } + + public class DiscordFooter + { + public string text { get; set; } + } + + public class DiscordAuthor + { + public string name { get; set; } + public string url { get; set; } + public string iconurl { get; set; } + } + + public class DiscordField + { + public string name { get; set; } + public string value { get; set; } + public bool inline { get; set; } } public class DiscordImage diff --git a/src/Ombi.Api.Discord/Ombi.Api.Discord.csproj b/src/Ombi.Api.Discord/Ombi.Api.Discord.csproj index 84f215437..f76114f83 100644 --- a/src/Ombi.Api.Discord/Ombi.Api.Discord.csproj +++ b/src/Ombi.Api.Discord/Ombi.Api.Discord.csproj @@ -1,11 +1,12 @@  - netstandard2.1 + net5.0 3.0.0.0 3.0.0.0 + 8.0 diff --git a/src/Ombi.Api.DogNzb/Ombi.Api.DogNzb.csproj b/src/Ombi.Api.DogNzb/Ombi.Api.DogNzb.csproj index 3c31ecb84..bdd16edf8 100644 --- a/src/Ombi.Api.DogNzb/Ombi.Api.DogNzb.csproj +++ b/src/Ombi.Api.DogNzb/Ombi.Api.DogNzb.csproj @@ -1,7 +1,8 @@ - + - netstandard2.1 + net5.0 + 8.0 diff --git a/src/Ombi.Api.Emby/EmbyApiFactory.cs b/src/Ombi.Api.Emby/EmbyApiFactory.cs new file mode 100644 index 000000000..c5c6e1c02 --- /dev/null +++ b/src/Ombi.Api.Emby/EmbyApiFactory.cs @@ -0,0 +1,41 @@ +using Ombi.Api; +using Ombi.Core.Settings; +using Ombi.Core.Settings.Models.External; +using System.Threading.Tasks; + +namespace Ombi.Api.Emby +{ + public class EmbyApiFactory : IEmbyApiFactory + { + private readonly ISettingsService _embySettings; + private readonly IApi _api; + + // TODO, if we need to derive futher, need to rework + public EmbyApiFactory(ISettingsService embySettings, IApi api) + { + _embySettings = embySettings; + _api = api; + } + + public async Task CreateClient() + { + var settings = await _embySettings.GetSettingsAsync(); + return CreateClient(settings); + } + + public IEmbyApi CreateClient(EmbySettings settings) + { + if (settings.IsJellyfin) + { + return new JellyfinApi(_api); + } + return new EmbyApi(_api); + } + } + + public interface IEmbyApiFactory + { + Task CreateClient(); + IEmbyApi CreateClient(EmbySettings settings); + } +} diff --git a/src/Ombi.Api.Emby/IBaseEmbyApi.cs b/src/Ombi.Api.Emby/IBaseEmbyApi.cs new file mode 100644 index 000000000..6f9a6bc7f --- /dev/null +++ b/src/Ombi.Api.Emby/IBaseEmbyApi.cs @@ -0,0 +1,33 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Ombi.Api.Emby.Models; +using Ombi.Api.Emby.Models.Media.Tv; +using Ombi.Api.Emby.Models.Movie; + +namespace Ombi.Api.Emby +{ + public interface IBaseEmbyApi + { + Task GetSystemInformation(string apiKey, string baseUrl); + Task> GetUsers(string baseUri, string apiKey); + Task LogIn(string username, string password, string apiKey, string baseUri); + + Task> GetAllMovies(string apiKey, int startIndex, int count, string userId, + string baseUri); + + Task> GetAllEpisodes(string apiKey, int startIndex, int count, string userId, + string baseUri); + + Task> GetAllShows(string apiKey, int startIndex, int count, string userId, + string baseUri); + + Task> GetCollection(string mediaId, + string apiKey, string userId, string baseUrl); + + Task GetSeriesInformation(string mediaId, string apiKey, string userId, string baseUrl); + Task GetMovieInformation(string mediaId, string apiKey, string userId, string baseUrl); + Task GetEpisodeInformation(string mediaId, string apiKey, string userId, string baseUrl); + Task GetPublicInformation(string baseUrl); + } +} \ No newline at end of file diff --git a/src/Ombi.Api.Emby/IEmbyApi.cs b/src/Ombi.Api.Emby/IEmbyApi.cs index 3c29878b7..e7803116d 100644 --- a/src/Ombi.Api.Emby/IEmbyApi.cs +++ b/src/Ombi.Api.Emby/IEmbyApi.cs @@ -1,34 +1,10 @@ -using System; -using System.Collections.Generic; -using System.Threading.Tasks; +using System.Threading.Tasks; using Ombi.Api.Emby.Models; -using Ombi.Api.Emby.Models.Media.Tv; -using Ombi.Api.Emby.Models.Movie; namespace Ombi.Api.Emby { - public interface IEmbyApi - { - Task GetSystemInformation(string apiKey, string baseUrl); - Task> GetUsers(string baseUri, string apiKey); - Task LogIn(string username, string password, string apiKey, string baseUri); + public interface IEmbyApi : IBaseEmbyApi + { Task LoginConnectUser(string username, string password); - - Task> GetAllMovies(string apiKey, int startIndex, int count, string userId, - string baseUri); - - Task> GetAllEpisodes(string apiKey, int startIndex, int count, string userId, - string baseUri); - - Task> GetAllShows(string apiKey, int startIndex, int count, string userId, - string baseUri); - - Task> GetCollection(string mediaId, - string apiKey, string userId, string baseUrl); - - Task GetSeriesInformation(string mediaId, string apiKey, string userId, string baseUrl); - Task GetMovieInformation(string mediaId, string apiKey, string userId, string baseUrl); - Task GetEpisodeInformation(string mediaId, string apiKey, string userId, string baseUrl); - Task GetPublicInformation(string baseUrl); } } \ No newline at end of file diff --git a/src/Ombi.Api.Emby/JellyfinApi.cs b/src/Ombi.Api.Emby/JellyfinApi.cs new file mode 100644 index 000000000..197fba684 --- /dev/null +++ b/src/Ombi.Api.Emby/JellyfinApi.cs @@ -0,0 +1,180 @@ +using System.Collections.Generic; +using System.Net.Http; +using System.Threading.Tasks; +using Microsoft.EntityFrameworkCore.Internal; +using Newtonsoft.Json; +using Ombi.Api.Emby.Models; +using Ombi.Api.Emby.Models.Media.Tv; +using Ombi.Api.Emby.Models.Movie; +using Ombi.Helpers; + +namespace Ombi.Api.Emby +{ + public class JellyfinApi : IEmbyApi + { + public JellyfinApi(IApi api) + { + Api = api; + } + + private IApi Api { get; } + + /// + /// Returns all users from the Emby Instance + /// + /// + /// + public async Task> GetUsers(string baseUri, string apiKey) + { + var request = new Request("users", baseUri, HttpMethod.Get); + + AddHeaders(request, apiKey); + var obj = await Api.Request>(request); + + return obj; + } + + public async Task GetSystemInformation(string apiKey, string baseUrl) + { + var request = new Request("System/Info", baseUrl, HttpMethod.Get); + + AddHeaders(request, apiKey); + + var obj = await Api.Request(request); + + return obj; + } + + public async Task GetPublicInformation(string baseUrl) + { + var request = new Request("System/Info/public", baseUrl, HttpMethod.Get); + + AddHeaders(request, string.Empty); + + var obj = await Api.Request(request); + + return obj; + } + + public async Task LogIn(string username, string password, string apiKey, string baseUri) + { + var request = new Request("users/authenticatebyname", baseUri, HttpMethod.Post); + var body = new + { + username, + pw = password, + }; + + request.AddJsonBody(body); + + request.AddHeader("X-Emby-Authorization", + $"MediaBrowser Client=\"Ombi\", Device=\"Ombi\", DeviceId=\"v3\", Version=\"v3\""); + AddHeaders(request, apiKey); + + var obj = await Api.Request(request); + return obj; + } + + public async Task> GetCollection(string mediaId, string apiKey, string userId, string baseUrl) + { + var request = new Request($"users/{userId}/items?parentId={mediaId}", baseUrl, HttpMethod.Get); + AddHeaders(request, apiKey); + + request.AddQueryString("Fields", "ProviderIds,Overview"); + + request.AddQueryString("IsVirtualItem", "False"); + + return await Api.Request>(request); + } + + public async Task> GetAllMovies(string apiKey, int startIndex, int count, string userId, string baseUri) + { + return await GetAll("Movie", apiKey, userId, baseUri, true, startIndex, count); + } + + public async Task> GetAllEpisodes(string apiKey, int startIndex, int count, string userId, string baseUri) + { + return await GetAll("Episode", apiKey, userId, baseUri, false, startIndex, count); + } + + public async Task> GetAllShows(string apiKey, int startIndex, int count, string userId, string baseUri) + { + return await GetAll("Series", apiKey, userId, baseUri, false, startIndex, count); + } + + public async Task GetSeriesInformation(string mediaId, string apiKey, string userId, string baseUrl) + { + return await GetInformation(mediaId, apiKey, userId, baseUrl); + } + public async Task GetMovieInformation(string mediaId, string apiKey, string userId, string baseUrl) + { + return await GetInformation(mediaId, apiKey, userId, baseUrl); + } + + public async Task GetEpisodeInformation(string mediaId, string apiKey, string userId, string baseUrl) + { + return await GetInformation(mediaId, apiKey, userId, baseUrl); + } + + private async Task GetInformation(string mediaId, string apiKey, string userId, string baseUrl) + { + var request = new Request($"users/{userId}/items/{mediaId}", baseUrl, HttpMethod.Get); + + AddHeaders(request, apiKey); + var response = await Api.RequestContent(request); + + return JsonConvert.DeserializeObject(response); + } + + private async Task> GetAll(string type, string apiKey, string userId, string baseUri, bool includeOverview = false) + { + var request = new Request($"users/{userId}/items", baseUri, HttpMethod.Get); + + request.AddQueryString("Recursive", true.ToString()); + request.AddQueryString("IncludeItemTypes", type); + request.AddQueryString("Fields", includeOverview ? "ProviderIds,Overview" : "ProviderIds"); + + request.AddQueryString("IsVirtualItem", "False"); + + AddHeaders(request, apiKey); + + + var obj = await Api.Request>(request); + return obj; + } + private async Task> GetAll(string type, string apiKey, string userId, string baseUri, bool includeOverview, int startIndex, int count) + { + var request = new Request($"users/{userId}/items", baseUri, HttpMethod.Get); + + request.AddQueryString("Recursive", true.ToString()); + request.AddQueryString("IncludeItemTypes", type); + request.AddQueryString("Fields", includeOverview ? "ProviderIds,Overview" : "ProviderIds"); + request.AddQueryString("startIndex", startIndex.ToString()); + request.AddQueryString("limit", count.ToString()); + + request.AddQueryString("IsVirtualItem", "False"); + + AddHeaders(request, apiKey); + + + var obj = await Api.Request>(request); + return obj; + } + + private static void AddHeaders(Request req, string apiKey) + { + if (!string.IsNullOrEmpty(apiKey)) + { + req.AddHeader("X-MediaBrowser-Token", apiKey); + } + req.AddHeader("Accept", "application/json"); + req.AddContentHeader("Content-Type", "application/json"); + req.AddHeader("Device", "Ombi"); + } + + public Task LoginConnectUser(string username, string password) + { + throw new System.NotImplementedException(); + } + } +} diff --git a/src/Ombi.Api.Emby/Models/EmbyUser.cs b/src/Ombi.Api.Emby/Models/EmbyUser.cs index 80ce1332b..c128f3893 100644 --- a/src/Ombi.Api.Emby/Models/EmbyUser.cs +++ b/src/Ombi.Api.Emby/Models/EmbyUser.cs @@ -34,7 +34,6 @@ namespace Ombi.Api.Emby.Models public string Name { get; set; } public string ServerId { get; set; } public string ConnectUserName { get; set; } - public string ConnectUserId { get; set; } public string ConnectLinkType { get; set; } public string Id { get; set; } public bool HasPassword { get; set; } diff --git a/src/Ombi.Api.Emby/Ombi.Api.Emby.csproj b/src/Ombi.Api.Emby/Ombi.Api.Emby.csproj index 24c86a86f..5457b0290 100644 --- a/src/Ombi.Api.Emby/Ombi.Api.Emby.csproj +++ b/src/Ombi.Api.Emby/Ombi.Api.Emby.csproj @@ -1,11 +1,12 @@  - netstandard2.1 + net5.0 3.0.0.0 3.0.0.0 + 8.0 diff --git a/src/Ombi.Api.FanartTv/Ombi.Api.FanartTv.csproj b/src/Ombi.Api.FanartTv/Ombi.Api.FanartTv.csproj index 84f215437..f76114f83 100644 --- a/src/Ombi.Api.FanartTv/Ombi.Api.FanartTv.csproj +++ b/src/Ombi.Api.FanartTv/Ombi.Api.FanartTv.csproj @@ -1,11 +1,12 @@  - netstandard2.1 + net5.0 3.0.0.0 3.0.0.0 + 8.0 diff --git a/src/Ombi.Api.Github/Ombi.Api.Github.csproj b/src/Ombi.Api.Github/Ombi.Api.Github.csproj index 3c31ecb84..bdd16edf8 100644 --- a/src/Ombi.Api.Github/Ombi.Api.Github.csproj +++ b/src/Ombi.Api.Github/Ombi.Api.Github.csproj @@ -1,7 +1,8 @@ - + - netstandard2.1 + net5.0 + 8.0 diff --git a/src/Ombi.Api.Gotify/Ombi.Api.Gotify.csproj b/src/Ombi.Api.Gotify/Ombi.Api.Gotify.csproj index 7c02a2978..5f1d62c66 100644 --- a/src/Ombi.Api.Gotify/Ombi.Api.Gotify.csproj +++ b/src/Ombi.Api.Gotify/Ombi.Api.Gotify.csproj @@ -1,11 +1,12 @@ - + - netstandard2.1 + net5.0 3.0.0.0 3.0.0.0 + 8.0 diff --git a/src/Ombi.Api.GroupMe/Ombi.Api.GroupMe.csproj b/src/Ombi.Api.GroupMe/Ombi.Api.GroupMe.csproj index 3c31ecb84..bdd16edf8 100644 --- a/src/Ombi.Api.GroupMe/Ombi.Api.GroupMe.csproj +++ b/src/Ombi.Api.GroupMe/Ombi.Api.GroupMe.csproj @@ -1,7 +1,8 @@ - + - netstandard2.1 + net5.0 + 8.0 diff --git a/src/Ombi.Api.Lidarr/ILidarrApi.cs b/src/Ombi.Api.Lidarr/ILidarrApi.cs index b542ff0a0..9e5e3b57e 100644 --- a/src/Ombi.Api.Lidarr/ILidarrApi.cs +++ b/src/Ombi.Api.Lidarr/ILidarrApi.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using System.Threading; using System.Threading.Tasks; using Ombi.Api.Lidarr.Models; @@ -11,7 +12,7 @@ namespace Ombi.Api.Lidarr Task> GetProfiles(string apiKey, string baseUrl); Task> GetRootFolders(string apiKey, string baseUrl); Task GetArtist(int artistId, string apiKey, string baseUrl); - Task GetArtistByForeignId(string foreignArtistId, string apiKey, string baseUrl); + Task GetArtistByForeignId(string foreignArtistId, string apiKey, string baseUrl, CancellationToken token = default); Task GetAlbumsByArtist(string foreignArtistId); Task GetAlbumByForeignId(string foreignArtistId, string apiKey, string baseUrl); Task> GetArtists(string apiKey, string baseUrl); diff --git a/src/Ombi.Api.Lidarr/LidarrApi.cs b/src/Ombi.Api.Lidarr/LidarrApi.cs index dd589c64d..5e8a81676 100644 --- a/src/Ombi.Api.Lidarr/LidarrApi.cs +++ b/src/Ombi.Api.Lidarr/LidarrApi.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using System.Net.Http; +using System.Threading; using System.Threading.Tasks; using Microsoft.Extensions.Logging; using Ombi.Api.Lidarr.Models; @@ -10,14 +11,12 @@ namespace Ombi.Api.Lidarr { public class LidarrApi : ILidarrApi { - public LidarrApi(ILogger logger, IApi api) + public LidarrApi(IApi api) { - Api = api; - Logger = logger; + _api = api; } - private IApi Api { get; } - private ILogger Logger { get; } + private IApi _api { get; } private const string ApiVersion = "/api/v1"; @@ -26,7 +25,7 @@ namespace Ombi.Api.Lidarr var request = new Request($"{ApiVersion}/qualityprofile", baseUrl, HttpMethod.Get); AddHeaders(request, apiKey); - return Api.Request>(request); + return _api.Request>(request); } public Task> GetRootFolders(string apiKey, string baseUrl) @@ -34,7 +33,7 @@ namespace Ombi.Api.Lidarr var request = new Request($"{ApiVersion}/rootfolder", baseUrl, HttpMethod.Get); AddHeaders(request, apiKey); - return Api.Request>(request); + return _api.Request>(request); } public async Task> ArtistLookup(string searchTerm, string apiKey, string baseUrl) @@ -43,7 +42,7 @@ namespace Ombi.Api.Lidarr request.AddQueryString("term", searchTerm); AddHeaders(request, apiKey); - return await Api.Request>(request); + return await _api.Request>(request); } public Task> AlbumLookup(string searchTerm, string apiKey, string baseUrl) @@ -52,7 +51,7 @@ namespace Ombi.Api.Lidarr request.AddQueryString("term", searchTerm); AddHeaders(request, apiKey); - return Api.Request>(request); + return _api.Request>(request); } public Task GetArtist(int artistId, string apiKey, string baseUrl) @@ -60,16 +59,16 @@ namespace Ombi.Api.Lidarr var request = new Request($"{ApiVersion}/artist/{artistId}", baseUrl, HttpMethod.Get); AddHeaders(request, apiKey); - return Api.Request(request); + return _api.Request(request); } - public async Task GetArtistByForeignId(string foreignArtistId, string apiKey, string baseUrl) + public async Task GetArtistByForeignId(string foreignArtistId, string apiKey, string baseUrl, CancellationToken token = default) { var request = new Request($"{ApiVersion}/artist/lookup", baseUrl, HttpMethod.Get); request.AddQueryString("term", $"lidarr:{foreignArtistId}"); AddHeaders(request, apiKey); - return (await Api.Request>(request)).FirstOrDefault(); + return (await _api.Request>(request, token)).FirstOrDefault(); } public async Task GetAlbumByForeignId(string foreignArtistId, string apiKey, string baseUrl) @@ -78,7 +77,7 @@ namespace Ombi.Api.Lidarr request.AddQueryString("term", $"lidarr:{foreignArtistId}"); AddHeaders(request, apiKey); - var albums = await Api.Request>(request); + var albums = await _api.Request>(request); return albums.FirstOrDefault(); } @@ -86,7 +85,7 @@ namespace Ombi.Api.Lidarr { var request = new Request(string.Empty, $"https://api.lidarr.audio/api/v0.4/artist/{foreignArtistId}", HttpMethod.Get) {IgnoreBaseUrlAppend = true}; - return Api.Request(request); + return _api.Request(request); } public Task> GetArtists(string apiKey, string baseUrl) @@ -94,7 +93,7 @@ namespace Ombi.Api.Lidarr var request = new Request($"{ApiVersion}/artist", baseUrl, HttpMethod.Get); AddHeaders(request, apiKey); - return Api.Request>(request); + return _api.Request>(request); } public Task> GetAllAlbums(string apiKey, string baseUrl) @@ -102,7 +101,7 @@ namespace Ombi.Api.Lidarr var request = new Request($"{ApiVersion}/album", baseUrl, HttpMethod.Get); AddHeaders(request, apiKey); - return Api.Request>(request); + return _api.Request>(request); } public async Task AlbumInformation(string albumId, string apiKey, string baseUrl) @@ -110,7 +109,7 @@ namespace Ombi.Api.Lidarr var request = new Request($"{ApiVersion}/album", baseUrl, HttpMethod.Get); request.AddQueryString("foreignAlbumId", albumId); AddHeaders(request, apiKey); - var albums = await Api.Request>(request); + var albums = await _api.Request>(request); return albums.FirstOrDefault(); } @@ -127,7 +126,7 @@ namespace Ombi.Api.Lidarr var request = new Request($"{ApiVersion}/album", baseUrl, HttpMethod.Get); request.AddQueryString("albumId", albumId.ToString()); AddHeaders(request, apiKey); - return Api.Request>(request); + return _api.Request>(request); } public Task AddArtist(ArtistAdd artist, string apiKey, string baseUrl) @@ -135,7 +134,7 @@ namespace Ombi.Api.Lidarr var request = new Request($"{ApiVersion}/artist", baseUrl, HttpMethod.Post); request.AddJsonBody(artist); AddHeaders(request, apiKey); - return Api.Request(request); + return _api.Request(request); } public async Task MontiorAlbum(int albumId, string apiKey, string baseUrl) @@ -147,7 +146,7 @@ namespace Ombi.Api.Lidarr monitored = true }); AddHeaders(request, apiKey); - return (await Api.Request>(request)).FirstOrDefault(); + return (await _api.Request>(request)).FirstOrDefault(); } public Task> GetAllAlbumsByArtistId(int artistId, string apiKey, string baseUrl) @@ -155,21 +154,21 @@ namespace Ombi.Api.Lidarr var request = new Request($"{ApiVersion}/album", baseUrl, HttpMethod.Get); request.AddQueryString("artistId", artistId.ToString()); AddHeaders(request, apiKey); - return Api.Request>(request); + return _api.Request>(request); } public Task> GetMetadataProfile(string apiKey, string baseUrl) { var request = new Request($"{ApiVersion}/metadataprofile", baseUrl, HttpMethod.Get); AddHeaders(request, apiKey); - return Api.Request>(request); + return _api.Request>(request); } public Task Status(string apiKey, string baseUrl) { var request = new Request($"{ApiVersion}/system/status", baseUrl, HttpMethod.Get); AddHeaders(request, apiKey); - return Api.Request(request); + return _api.Request(request); } public Task AlbumSearch(int[] albumIds, string apiKey, string baseUrl) @@ -177,7 +176,7 @@ namespace Ombi.Api.Lidarr var request = new Request($"{ApiVersion}/command/", baseUrl, HttpMethod.Post); request.AddJsonBody(new { name = "AlbumSearch", albumIds }); AddHeaders(request, apiKey); - return Api.Request(request); + return _api.Request(request); } private void AddHeaders(Request request, string key) diff --git a/src/Ombi.Api.Lidarr/Models/ArtistAdd.cs b/src/Ombi.Api.Lidarr/Models/ArtistAdd.cs index e292e8905..27ff3f733 100644 --- a/src/Ombi.Api.Lidarr/Models/ArtistAdd.cs +++ b/src/Ombi.Api.Lidarr/Models/ArtistAdd.cs @@ -32,17 +32,21 @@ namespace Ombi.Api.Lidarr.Models public class Addoptions { - /// - /// Future = 1 - /// Missing = 2 - /// Existing = 3 - /// First = 5 - /// Latest = 4 - /// None = 6 - /// - public int selectedOption { get; set; } + public MonitorTypes monitor { get; set; } public bool monitored { get; set; } - public bool searchForMissingAlbums { get; set; } + public bool searchForMissingAlbums { get; set; } // Only for Artists add public string[] AlbumsToMonitor { get; set; } // Uses the MusicBrainzAlbumId! } + + public enum MonitorTypes + { + All, + Future, + Missing, + Existing, + Latest, + First, + None, + Unknown + } } \ No newline at end of file diff --git a/src/Ombi.Api.Lidarr/Ombi.Api.Lidarr.csproj b/src/Ombi.Api.Lidarr/Ombi.Api.Lidarr.csproj index 3c31ecb84..bdd16edf8 100644 --- a/src/Ombi.Api.Lidarr/Ombi.Api.Lidarr.csproj +++ b/src/Ombi.Api.Lidarr/Ombi.Api.Lidarr.csproj @@ -1,7 +1,8 @@ - + - netstandard2.1 + net5.0 + 8.0 diff --git a/src/Ombi.Api.Mattermost/Ombi.Api.Mattermost.csproj b/src/Ombi.Api.Mattermost/Ombi.Api.Mattermost.csproj index 1b93a9b39..344b2e504 100644 --- a/src/Ombi.Api.Mattermost/Ombi.Api.Mattermost.csproj +++ b/src/Ombi.Api.Mattermost/Ombi.Api.Mattermost.csproj @@ -1,15 +1,16 @@ - + - netstandard2.1 + net5.0 3.0.0.0 3.0.0.0 + 8.0 - + diff --git a/src/Ombi.Api.MusicBrainz/Ombi.Api.MusicBrainz.csproj b/src/Ombi.Api.MusicBrainz/Ombi.Api.MusicBrainz.csproj index e5ffec654..c703166d5 100644 --- a/src/Ombi.Api.MusicBrainz/Ombi.Api.MusicBrainz.csproj +++ b/src/Ombi.Api.MusicBrainz/Ombi.Api.MusicBrainz.csproj @@ -1,7 +1,8 @@  - netstandard2.1 + net5.0 + 8.0 diff --git a/src/Ombi.Api.Notifications/Ombi.Api.Notifications.csproj b/src/Ombi.Api.Notifications/Ombi.Api.Notifications.csproj index 07a764ec0..349da09d9 100644 --- a/src/Ombi.Api.Notifications/Ombi.Api.Notifications.csproj +++ b/src/Ombi.Api.Notifications/Ombi.Api.Notifications.csproj @@ -1,7 +1,8 @@ - + - netstandard2.1 + net5.0 + 8.0 diff --git a/src/Ombi.Api.Plex/Models/Metadata.cs b/src/Ombi.Api.Plex/Models/Metadata.cs index cda6ce68b..92e66b35c 100644 --- a/src/Ombi.Api.Plex/Models/Metadata.cs +++ b/src/Ombi.Api.Plex/Models/Metadata.cs @@ -44,7 +44,13 @@ namespace Ombi.Api.Plex.Models public string grandparentTheme { get; set; } public string chapterSource { get; set; } public Medium[] Media { get; set; } + public PlexGuids[] Guid { get; set; } // public Director[] Director { get; set; } // public Writer[] Writer { get; set; } } + + public class PlexGuids + { + public string Id { get; set; } + } } \ No newline at end of file diff --git a/src/Ombi.Api.Plex/Ombi.Api.Plex.csproj b/src/Ombi.Api.Plex/Ombi.Api.Plex.csproj index d1a2a1c65..f76114f83 100644 --- a/src/Ombi.Api.Plex/Ombi.Api.Plex.csproj +++ b/src/Ombi.Api.Plex/Ombi.Api.Plex.csproj @@ -1,17 +1,14 @@  - netstandard2.1 + net5.0 3.0.0.0 3.0.0.0 + 8.0 - - - - diff --git a/src/Ombi.Api.Plex/PlexApi.cs b/src/Ombi.Api.Plex/PlexApi.cs index eaafcd75f..0d6356457 100644 --- a/src/Ombi.Api.Plex/PlexApi.cs +++ b/src/Ombi.Api.Plex/PlexApi.cs @@ -135,16 +135,15 @@ namespace Ombi.Api.Plex } /// - // 192.168.1.69:32400/library/metadata/3662/allLeaves - // The metadata ratingkey should be in the Cache - // Search for it and then call the above with the Directory.RatingKey - // THEN! We need the episode metadata using result.Vide.Key ("/library/metadata/3664") - // We then have the GUID which contains the TVDB ID plus the season and episode number: guid="com.plexapp.agents.thetvdb://269586/2/8?lang=en" + /// 192.168.1.69:32400/library/metadata/3662/allLeaves + /// The metadata ratingkey should be in the Cache + /// Search for it and then call the above with the Directory.RatingKey + /// THEN! We need the episode metadata using result.Vide.Key ("/library/metadata/3664") + /// We then have the GUID which contains the TVDB ID plus the season and episode number: guid="com.plexapp.agents.thetvdb://269586/2/8?lang=en" /// /// /// /// - /// public async Task GetEpisodeMetaData(string authToken, string plexFullHost, int ratingKey) { var request = new Request($"/library/metadata/{ratingKey}", plexFullHost, HttpMethod.Get); @@ -308,7 +307,7 @@ namespace Ombi.Api.Plex } private async Task CheckInstallId(PlexSettings s) { - if (s.InstallId == null || s.InstallId == Guid.Empty) + if (s?.InstallId == Guid.Empty || s.InstallId == Guid.Empty) { s.InstallId = Guid.NewGuid(); await _plexSettings.SaveSettingsAsync(s); diff --git a/src/Ombi.Api.Pushbullet/Ombi.Api.Pushbullet.csproj b/src/Ombi.Api.Pushbullet/Ombi.Api.Pushbullet.csproj index 84f215437..f76114f83 100644 --- a/src/Ombi.Api.Pushbullet/Ombi.Api.Pushbullet.csproj +++ b/src/Ombi.Api.Pushbullet/Ombi.Api.Pushbullet.csproj @@ -1,11 +1,12 @@  - netstandard2.1 + net5.0 3.0.0.0 3.0.0.0 + 8.0 diff --git a/src/Ombi.Api.Pushover/Ombi.Api.Pushover.csproj b/src/Ombi.Api.Pushover/Ombi.Api.Pushover.csproj index 7c02a2978..5f1d62c66 100644 --- a/src/Ombi.Api.Pushover/Ombi.Api.Pushover.csproj +++ b/src/Ombi.Api.Pushover/Ombi.Api.Pushover.csproj @@ -1,11 +1,12 @@ - + - netstandard2.1 + net5.0 3.0.0.0 3.0.0.0 + 8.0 diff --git a/src/Ombi.Api.Radarr/IRadarrApi.cs b/src/Ombi.Api.Radarr/IRadarrApi.cs index b675dba96..55e91f710 100644 --- a/src/Ombi.Api.Radarr/IRadarrApi.cs +++ b/src/Ombi.Api.Radarr/IRadarrApi.cs @@ -13,7 +13,7 @@ namespace Ombi.Api.Radarr Task GetMovie(int id, string apiKey, string baseUrl); Task UpdateMovie(MovieResponse movie, string apiKey, string baseUrl); Task MovieSearch(int[] movieIds, string apiKey, string baseUrl); - Task AddMovie(int tmdbId, string title, int year, int qualityId, string rootPath,string apiKey, string baseUrl, bool searchNow, string minimumAvailability); + Task AddMovie(int tmdbId, string title, int year, int qualityId, string rootPath,string apiKey, string baseUrl, bool searchNow, string minimumAvailability); Task> GetTags(string apiKey, string baseUrl); } } \ No newline at end of file diff --git a/src/Ombi.Api.Radarr/IRadarrV3Api.cs b/src/Ombi.Api.Radarr/IRadarrV3Api.cs new file mode 100644 index 000000000..072e8ef51 --- /dev/null +++ b/src/Ombi.Api.Radarr/IRadarrV3Api.cs @@ -0,0 +1,20 @@ +using System.Collections.Generic; +using System.Threading.Tasks; +using Ombi.Api.Radarr.Models; +using Ombi.Api.Radarr.Models.V3; + +namespace Ombi.Api.Radarr +{ + public interface IRadarrV3Api + { + Task> GetMovies(string apiKey, string baseUrl); + Task> GetProfiles(string apiKey, string baseUrl); + Task> GetRootFolders(string apiKey, string baseUrl); + Task SystemStatus(string apiKey, string baseUrl); + Task GetMovie(int id, string apiKey, string baseUrl); + Task UpdateMovie(MovieResponse movie, string apiKey, string baseUrl); + Task MovieSearch(int[] movieIds, string apiKey, string baseUrl); + Task AddMovie(int tmdbId, string title, int year, int qualityId, string rootPath,string apiKey, string baseUrl, bool searchNow, string minimumAvailability); + Task> GetTags(string apiKey, string baseUrl); + } +} \ No newline at end of file diff --git a/src/Ombi.Api.Radarr/Models/SystemStatus.cs b/src/Ombi.Api.Radarr/Models/SystemStatus.cs deleted file mode 100644 index 0232dba24..000000000 --- a/src/Ombi.Api.Radarr/Models/SystemStatus.cs +++ /dev/null @@ -1,25 +0,0 @@ -namespace Ombi.Api.Radarr.Models -{ - public class SystemStatus - { - public string version { get; set; } - public string buildTime { get; set; } - public bool isDebug { get; set; } - public bool isProduction { get; set; } - public bool isAdmin { get; set; } - public bool isUserInteractive { get; set; } - public string startupPath { get; set; } - public string appData { get; set; } - public string osVersion { get; set; } - public bool isMonoRuntime { get; set; } - public bool isMono { get; set; } - public bool isLinux { get; set; } - public bool isOsx { get; set; } - public bool isWindows { get; set; } - public string branch { get; set; } - public string authentication { get; set; } - public string sqliteVersion { get; set; } - public string urlBase { get; set; } - public string runtimeVersion { get; set; } - } -} \ No newline at end of file diff --git a/src/Ombi.Api.Radarr/Models/Cutoff.cs b/src/Ombi.Api.Radarr/Models/V2/Cutoff.cs similarity index 100% rename from src/Ombi.Api.Radarr/Models/Cutoff.cs rename to src/Ombi.Api.Radarr/Models/V2/Cutoff.cs diff --git a/src/Ombi.Api.Radarr/Models/Image.cs b/src/Ombi.Api.Radarr/Models/V2/Image.cs similarity index 100% rename from src/Ombi.Api.Radarr/Models/Image.cs rename to src/Ombi.Api.Radarr/Models/V2/Image.cs diff --git a/src/Ombi.Api.Radarr/Models/Item.cs b/src/Ombi.Api.Radarr/Models/V2/Item.cs similarity index 100% rename from src/Ombi.Api.Radarr/Models/Item.cs rename to src/Ombi.Api.Radarr/Models/V2/Item.cs diff --git a/src/Ombi.Api.Radarr/Models/MovieResponse.cs b/src/Ombi.Api.Radarr/Models/V2/MovieResponse.cs similarity index 100% rename from src/Ombi.Api.Radarr/Models/MovieResponse.cs rename to src/Ombi.Api.Radarr/Models/V2/MovieResponse.cs diff --git a/src/Ombi.Api.Radarr/Models/Quality.cs b/src/Ombi.Api.Radarr/Models/V2/Quality.cs similarity index 100% rename from src/Ombi.Api.Radarr/Models/Quality.cs rename to src/Ombi.Api.Radarr/Models/V2/Quality.cs diff --git a/src/Ombi.Api.Radarr/Models/RadarrAddMovie.cs b/src/Ombi.Api.Radarr/Models/V2/RadarrAddMovie.cs similarity index 81% rename from src/Ombi.Api.Radarr/Models/RadarrAddMovie.cs rename to src/Ombi.Api.Radarr/Models/V2/RadarrAddMovie.cs index 9288058f9..b56049c9a 100644 --- a/src/Ombi.Api.Radarr/Models/RadarrAddMovie.cs +++ b/src/Ombi.Api.Radarr/Models/V2/RadarrAddMovie.cs @@ -2,13 +2,22 @@ namespace Ombi.Api.Radarr.Models { - public class RadarrAddMovieResponse + public class RadarrAddMovieResponse : RadarrAddMovie { - public RadarrAddMovieResponse() { images = new List(); } + public List images { get; set; } + } + + + public class RadarrAddMovie + { + + public RadarrAddMovie() + { + } public RadarrError Error { get; set; } public RadarrAddOptions addOptions { get; set; } public string title { get; set; } @@ -16,7 +25,6 @@ namespace Ombi.Api.Radarr.Models public int qualityProfileId { get; set; } public bool monitored { get; set; } public int tmdbId { get; set; } - public List images { get; set; } public string titleSlug { get; set; } public int year { get; set; } public string minimumAvailability { get; set; } diff --git a/src/Ombi.Api.Radarr/Models/RadarrAddOptions.cs b/src/Ombi.Api.Radarr/Models/V2/RadarrAddOptions.cs similarity index 100% rename from src/Ombi.Api.Radarr/Models/RadarrAddOptions.cs rename to src/Ombi.Api.Radarr/Models/V2/RadarrAddOptions.cs diff --git a/src/Ombi.Api.Radarr/Models/RadarrError.cs b/src/Ombi.Api.Radarr/Models/V2/RadarrError.cs similarity index 100% rename from src/Ombi.Api.Radarr/Models/RadarrError.cs rename to src/Ombi.Api.Radarr/Models/V2/RadarrError.cs diff --git a/src/Ombi.Api.Radarr/Models/RadarrProfile.cs b/src/Ombi.Api.Radarr/Models/V2/RadarrProfile.cs similarity index 100% rename from src/Ombi.Api.Radarr/Models/RadarrProfile.cs rename to src/Ombi.Api.Radarr/Models/V2/RadarrProfile.cs diff --git a/src/Ombi.Api.Radarr/Models/RadarrRootFolder.cs b/src/Ombi.Api.Radarr/Models/V2/RadarrRootFolder.cs similarity index 100% rename from src/Ombi.Api.Radarr/Models/RadarrRootFolder.cs rename to src/Ombi.Api.Radarr/Models/V2/RadarrRootFolder.cs diff --git a/src/Ombi.Api.Radarr/Models/Ratings.cs b/src/Ombi.Api.Radarr/Models/V2/Ratings.cs similarity index 100% rename from src/Ombi.Api.Radarr/Models/Ratings.cs rename to src/Ombi.Api.Radarr/Models/V2/Ratings.cs diff --git a/src/Ombi.Api.Radarr/Models/V2/SystemStatus.cs b/src/Ombi.Api.Radarr/Models/V2/SystemStatus.cs new file mode 100644 index 000000000..6877708c5 --- /dev/null +++ b/src/Ombi.Api.Radarr/Models/V2/SystemStatus.cs @@ -0,0 +1,7 @@ +namespace Ombi.Api.Radarr.Models +{ + public class SystemStatus + { + public string version { get; set; } + } +} \ No newline at end of file diff --git a/src/Ombi.Api.Radarr/Models/Tag.cs b/src/Ombi.Api.Radarr/Models/V2/Tag.cs similarity index 100% rename from src/Ombi.Api.Radarr/Models/Tag.cs rename to src/Ombi.Api.Radarr/Models/V2/Tag.cs diff --git a/src/Ombi.Api.Radarr/Models/V3/RadarrV3QualityProfile.cs b/src/Ombi.Api.Radarr/Models/V3/RadarrV3QualityProfile.cs new file mode 100644 index 000000000..d985da358 --- /dev/null +++ b/src/Ombi.Api.Radarr/Models/V3/RadarrV3QualityProfile.cs @@ -0,0 +1,29 @@ +namespace Ombi.Api.Radarr.Models.V3 +{ + public class RadarrV3QualityProfile + { + public string name { get; set; } + public bool upgradeAllowed { get; set; } + public int cutoff { get; set; } + public string preferredTags { get; set; } + public Item[] items { get; set; } + public int id { get; set; } + } + + public class Item + { + public Quality quality { get; set; } + public object[] items { get; set; } + public bool allowed { get; set; } + } + + public class Quality + { + public int id { get; set; } + public string name { get; set; } + public string source { get; set; } + public int resolution { get; set; } + public string modifier { get; set; } + } + +} diff --git a/src/Ombi.Api.Radarr/Ombi.Api.Radarr.csproj b/src/Ombi.Api.Radarr/Ombi.Api.Radarr.csproj index 2efedfad6..23cb45a6e 100644 --- a/src/Ombi.Api.Radarr/Ombi.Api.Radarr.csproj +++ b/src/Ombi.Api.Radarr/Ombi.Api.Radarr.csproj @@ -1,15 +1,16 @@  - netstandard2.1 + net5.0 3.0.0.0 3.0.0.0 + 8.0 - + diff --git a/src/Ombi.Api.Radarr/RadarrApi.cs b/src/Ombi.Api.Radarr/RadarrApi.cs index 28c838a80..b461ccda8 100644 --- a/src/Ombi.Api.Radarr/RadarrApi.cs +++ b/src/Ombi.Api.Radarr/RadarrApi.cs @@ -69,7 +69,7 @@ namespace Ombi.Api.Radarr return await Api.Request(request); } - public async Task AddMovie(int tmdbId, string title, int year, int qualityId, string rootPath, string apiKey, string baseUrl, bool searchNow, string minimumAvailability) + public async Task AddMovie(int tmdbId, string title, int year, int qualityId, string rootPath, string apiKey, string baseUrl, bool searchNow, string minimumAvailability) { var request = new Request("/api/movie", baseUrl, HttpMethod.Post); @@ -110,7 +110,7 @@ namespace Ombi.Api.Radarr var error = JsonConvert.DeserializeObject>(response).FirstOrDefault(); return new RadarrAddMovieResponse { Error = new RadarrError { message = error?.errorMessage } }; } - return JsonConvert.DeserializeObject(response); + return JsonConvert.DeserializeObject(response); } catch (JsonSerializationException jse) { diff --git a/src/Ombi.Api.Radarr/RadarrV3Api.cs b/src/Ombi.Api.Radarr/RadarrV3Api.cs new file mode 100644 index 000000000..dd1d0b279 --- /dev/null +++ b/src/Ombi.Api.Radarr/RadarrV3Api.cs @@ -0,0 +1,159 @@ +using System.Collections.Generic; +using System.Linq; +using System.Net.Http; +using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using Newtonsoft.Json; +using Ombi.Api.Radarr.Models; +using Ombi.Api.Radarr.Models.V3; +using Ombi.Helpers; + +namespace Ombi.Api.Radarr +{ + //https://radarr.video/docs/api/ + public class RadarrV3Api : IRadarrV3Api + { + public RadarrV3Api(ILogger logger, IApi api) + { + Api = api; + Logger = logger; + } + + private IApi Api { get; } + private ILogger Logger { get; } + + public async Task> GetProfiles(string apiKey, string baseUrl) + { + var request = new Request("/api/v3/qualityProfile", baseUrl, HttpMethod.Get); + + AddHeaders(request, apiKey); + return await Api.Request>(request); + } + + // TODO + public async Task> GetRootFolders(string apiKey, string baseUrl) + { + var request = new Request("/api/v3/rootfolder", baseUrl, HttpMethod.Get); + + AddHeaders(request, apiKey); + return await Api.Request>(request); + } + + public async Task SystemStatus(string apiKey, string baseUrl) + { + var request = new Request("/api/v3/status", baseUrl, HttpMethod.Get); + AddHeaders(request, apiKey); + + return await Api.Request(request); + } + + public async Task> GetMovies(string apiKey, string baseUrl) + { + var request = new Request("/api/v3/movie", baseUrl, HttpMethod.Get); + AddHeaders(request, apiKey); + + return await Api.Request>(request); + } + + public async Task GetMovie(int id, string apiKey, string baseUrl) + { + var request = new Request($"/api/v3/movie/{id}", baseUrl, HttpMethod.Get); + AddHeaders(request, apiKey); + + return await Api.Request(request); + } + + public async Task UpdateMovie(MovieResponse movie, string apiKey, string baseUrl) + { + var request = new Request($"/api/v3/movie/", baseUrl, HttpMethod.Put); + AddHeaders(request, apiKey); + request.AddJsonBody(movie); + + return await Api.Request(request); + } + + public async Task AddMovie(int tmdbId, string title, int year, int qualityId, string rootPath, string apiKey, string baseUrl, bool searchNow, string minimumAvailability) + { + var request = new Request("/api/v3/movie", baseUrl, HttpMethod.Post); + + var options = new RadarrAddMovieResponse + { + title = title, + tmdbId = tmdbId, + qualityProfileId = qualityId, + rootFolderPath = rootPath, + titleSlug = title + year, + monitored = true, + year = year, + minimumAvailability = minimumAvailability + }; + + if (searchNow) + { + options.addOptions = new RadarrAddOptions + { + searchForMovie = true + }; + } + + + request.AddHeader("X-Api-Key", apiKey); + request.AddJsonBody(options); + + var response = await Api.RequestContent(request); + + // TODO check if this is still correct, new API docs show validation as a 405 now + try + { + if (response.Contains("\"message\":")) + { + var error = JsonConvert.DeserializeObject(response); + return new RadarrAddMovieResponse { Error = error }; + } + if (response.Contains("\"errorMessage\":")) + { + var error = JsonConvert.DeserializeObject>(response).FirstOrDefault(); + return new RadarrAddMovieResponse { Error = new RadarrError { message = error?.errorMessage } }; + } + return JsonConvert.DeserializeObject(response); + } + catch (JsonSerializationException jse) + { + Logger.LogError(LoggingEvents.RadarrApi, jse, "Error When adding movie to Radarr, Reponse: {0}", response); + } + return null; + } + + public async Task MovieSearch(int[] movieIds, string apiKey, string baseUrl) + { + var result = await Command(apiKey, baseUrl, new { name = "MoviesSearch", movieIds }); + return result != null; + } + + public async Task> GetTags(string apiKey, string baseUrl) + { + var request = new Request("/api/v3/tag", baseUrl, HttpMethod.Get); + AddHeaders(request, apiKey); + + return await Api.Request>(request); + } + + private async Task Command(string apiKey, string baseUrl, object body) + { + var request = new Request($"/api/v3/Command/", baseUrl, HttpMethod.Post); + request.AddHeader("X-Api-Key", apiKey); + request.AddJsonBody(body); + return await Api.Request(request); + } + + /// + /// Adds the required headers and also the authorization header + /// + /// + /// + private void AddHeaders(Request request, string key) + { + request.AddHeader("X-Api-Key", key); + } + } +} diff --git a/src/Ombi.Api.Service/Ombi.Api.Service.csproj b/src/Ombi.Api.Service/Ombi.Api.Service.csproj index 1e466b24d..11769e131 100644 --- a/src/Ombi.Api.Service/Ombi.Api.Service.csproj +++ b/src/Ombi.Api.Service/Ombi.Api.Service.csproj @@ -1,17 +1,18 @@  - netstandard2.1 + net5.0 3.0.0.0 3.0.0.0 Ombi.Api.Service Ombi.Api.Service + 8.0 - + diff --git a/src/Ombi.Api.SickRage/Ombi.Api.SickRage.csproj b/src/Ombi.Api.SickRage/Ombi.Api.SickRage.csproj index 3c31ecb84..bdd16edf8 100644 --- a/src/Ombi.Api.SickRage/Ombi.Api.SickRage.csproj +++ b/src/Ombi.Api.SickRage/Ombi.Api.SickRage.csproj @@ -1,7 +1,8 @@ - + - netstandard2.1 + net5.0 + 8.0 diff --git a/src/Ombi.Api.Slack/Ombi.Api.Slack.csproj b/src/Ombi.Api.Slack/Ombi.Api.Slack.csproj index 84f215437..f76114f83 100644 --- a/src/Ombi.Api.Slack/Ombi.Api.Slack.csproj +++ b/src/Ombi.Api.Slack/Ombi.Api.Slack.csproj @@ -1,11 +1,12 @@  - netstandard2.1 + net5.0 3.0.0.0 3.0.0.0 + 8.0 diff --git a/src/Ombi.Api.Sonarr/Ombi.Api.Sonarr.csproj b/src/Ombi.Api.Sonarr/Ombi.Api.Sonarr.csproj index 84f215437..f76114f83 100644 --- a/src/Ombi.Api.Sonarr/Ombi.Api.Sonarr.csproj +++ b/src/Ombi.Api.Sonarr/Ombi.Api.Sonarr.csproj @@ -1,11 +1,12 @@  - netstandard2.1 + net5.0 3.0.0.0 3.0.0.0 + 8.0 diff --git a/src/Ombi.Api.Telegram/Ombi.Api.Telegram.csproj b/src/Ombi.Api.Telegram/Ombi.Api.Telegram.csproj index 3c31ecb84..bdd16edf8 100644 --- a/src/Ombi.Api.Telegram/Ombi.Api.Telegram.csproj +++ b/src/Ombi.Api.Telegram/Ombi.Api.Telegram.csproj @@ -1,7 +1,8 @@ - + - netstandard2.1 + net5.0 + 8.0 diff --git a/src/Ombi.Api.Trakt/Ombi.Api.Trakt.csproj b/src/Ombi.Api.Trakt/Ombi.Api.Trakt.csproj index 99ed0f20e..5cd35f0ac 100644 --- a/src/Ombi.Api.Trakt/Ombi.Api.Trakt.csproj +++ b/src/Ombi.Api.Trakt/Ombi.Api.Trakt.csproj @@ -1,11 +1,12 @@  - netstandard2.1 + net5.0 3.0.0.0 3.0.0.0 + 8.0 diff --git a/src/Ombi.Api.Trakt/TraktApi.cs b/src/Ombi.Api.Trakt/TraktApi.cs index c3faa5115..8bdabebe5 100644 --- a/src/Ombi.Api.Trakt/TraktApi.cs +++ b/src/Ombi.Api.Trakt/TraktApi.cs @@ -1,4 +1,5 @@  +using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; @@ -48,7 +49,18 @@ namespace Ombi.Api.Trakt public async Task GetTvExtendedInfo(string imdbId) { - return await Client.Shows.GetShowAsync(imdbId, TraktExtendedOption.Full); + try + { + return await Client.Shows.GetShowAsync(imdbId, TraktExtendedOption.Full); + } + catch (Exception e) + { + // Ignore the exception since the information returned from this API is optional. + Console.WriteLine($"Failed to retrieve extended tv information from Trakt. IMDbId: '{imdbId}'."); + Console.WriteLine(e); + } + + return null; } } } diff --git a/src/Ombi.Api.TvMaze/Ombi.Api.TvMaze.csproj b/src/Ombi.Api.TvMaze/Ombi.Api.TvMaze.csproj index 24c86a86f..5457b0290 100644 --- a/src/Ombi.Api.TvMaze/Ombi.Api.TvMaze.csproj +++ b/src/Ombi.Api.TvMaze/Ombi.Api.TvMaze.csproj @@ -1,11 +1,12 @@  - netstandard2.1 + net5.0 3.0.0.0 3.0.0.0 + 8.0 diff --git a/src/Ombi.Api.Twilio/IWhatsAppApi.cs b/src/Ombi.Api.Twilio/IWhatsAppApi.cs new file mode 100644 index 000000000..490aaa8fc --- /dev/null +++ b/src/Ombi.Api.Twilio/IWhatsAppApi.cs @@ -0,0 +1,9 @@ +using System.Threading.Tasks; + +namespace Ombi.Api.Twilio +{ + public interface IWhatsAppApi + { + Task SendMessage(WhatsAppModel message, string accountSid, string authToken); + } +} \ No newline at end of file diff --git a/src/Ombi.Api.Twilio/Ombi.Api.Twilio.csproj b/src/Ombi.Api.Twilio/Ombi.Api.Twilio.csproj new file mode 100644 index 000000000..7a6146493 --- /dev/null +++ b/src/Ombi.Api.Twilio/Ombi.Api.Twilio.csproj @@ -0,0 +1,11 @@ + + + + net5.0 + + + + + + + diff --git a/src/Ombi.Api.Twilio/WhatsAppApi.cs b/src/Ombi.Api.Twilio/WhatsAppApi.cs new file mode 100644 index 000000000..439a49c6d --- /dev/null +++ b/src/Ombi.Api.Twilio/WhatsAppApi.cs @@ -0,0 +1,28 @@ +using System; +using System.Threading.Tasks; +using Twilio; +using Twilio.Rest.Api.V2010.Account; +using Twilio.Types; + +namespace Ombi.Api.Twilio +{ + public class WhatsAppApi : IWhatsAppApi + { + public async Task SendMessage(WhatsAppModel message, string accountSid, string authToken) + { + TwilioClient.Init(accountSid, authToken); + + if(string.IsNullOrEmpty(message.To)) + { + return string.Empty; + } + var response =await MessageResource.CreateAsync( + body: message.Message, + from: new PhoneNumber($"whatsapp:{message.From}"), + to: new PhoneNumber($"whatsapp:{message.To}") + ); + + return response.Sid; + } + } +} diff --git a/src/Ombi.Api.Twilio/WhatsAppModel.cs b/src/Ombi.Api.Twilio/WhatsAppModel.cs new file mode 100644 index 000000000..e7f4e5c21 --- /dev/null +++ b/src/Ombi.Api.Twilio/WhatsAppModel.cs @@ -0,0 +1,9 @@ +namespace Ombi.Api.Twilio +{ + public class WhatsAppModel + { + public string Message { get; set; } + public string To { get; set; } + public string From { get; set; } + } +} \ No newline at end of file diff --git a/src/Ombi.Api.Webhook/IWebhookApi.cs b/src/Ombi.Api.Webhook/IWebhookApi.cs new file mode 100644 index 000000000..6a22a8b02 --- /dev/null +++ b/src/Ombi.Api.Webhook/IWebhookApi.cs @@ -0,0 +1,10 @@ +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace Ombi.Api.Webhook +{ + public interface IWebhookApi + { + Task PushAsync(string endpoint, string accessToken, IDictionary parameters); + } +} \ No newline at end of file diff --git a/src/Ombi.Api.Webhook/Ombi.Api.Webhook.csproj b/src/Ombi.Api.Webhook/Ombi.Api.Webhook.csproj new file mode 100644 index 000000000..d258a95b2 --- /dev/null +++ b/src/Ombi.Api.Webhook/Ombi.Api.Webhook.csproj @@ -0,0 +1,15 @@ + + + + net5.0 + 3.0.0.0 + 3.0.0.0 + + + + + + + + + \ No newline at end of file diff --git a/src/Ombi.Api.Webhook/WebhookApi.cs b/src/Ombi.Api.Webhook/WebhookApi.cs new file mode 100644 index 000000000..8b6b35ca0 --- /dev/null +++ b/src/Ombi.Api.Webhook/WebhookApi.cs @@ -0,0 +1,40 @@ +using Newtonsoft.Json.Serialization; +using System.Collections.Generic; +using System.Linq; +using System.Net.Http; +using System.Threading.Tasks; + +namespace Ombi.Api.Webhook +{ + public class WebhookApi : IWebhookApi + { + private static readonly CamelCasePropertyNamesContractResolver _nameResolver = new CamelCasePropertyNamesContractResolver(); + + public WebhookApi(IApi api) + { + _api = api; + } + + private readonly IApi _api; + + public async Task PushAsync(string baseUrl, string accessToken, IDictionary parameters) + { + var request = new Request("/", baseUrl, HttpMethod.Post); + + if (!string.IsNullOrWhiteSpace(accessToken)) + { + request.AddHeader("Access-Token", accessToken); + } + + var body = parameters.ToDictionary( + x => _nameResolver.GetResolvedPropertyName(x.Key), + x => x.Value + ); + + request.ApplicationJsonContentType(); + request.AddJsonBody(body); + + await _api.Request(request); + } + } +} diff --git a/src/Ombi.Api/HttpRequestExtensions.cs b/src/Ombi.Api/HttpRequestExtensions.cs index fa2ded97d..a08180362 100644 --- a/src/Ombi.Api/HttpRequestExtensions.cs +++ b/src/Ombi.Api/HttpRequestExtensions.cs @@ -5,7 +5,7 @@ using System.Threading.Tasks; namespace Ombi.Api { - public static class HttpRequestExtnesions + public static class HttpRequestExtensions { public static async Task Clone(this HttpRequestMessage request) { @@ -14,9 +14,9 @@ namespace Ombi.Api Content = await request.Content.Clone(), Version = request.Version }; - foreach (KeyValuePair prop in request.Properties) + foreach (KeyValuePair prop in request.Options) { - clone.Properties.Add(prop); + clone.Options.TryAdd(prop.Key, prop.Value); } foreach (KeyValuePair> header in request.Headers) { diff --git a/src/Ombi.Api/Ombi.Api.csproj b/src/Ombi.Api/Ombi.Api.csproj index 4e9843866..98da29c2a 100644 --- a/src/Ombi.Api/Ombi.Api.csproj +++ b/src/Ombi.Api/Ombi.Api.csproj @@ -1,18 +1,18 @@  - netstandard2.1 + net5.0 3.0.0.0 3.0.0.0 + 8.0 - - + + - diff --git a/src/Ombi.Core.Tests/Engine/V2/MusicSearchEngineV2Tests.cs b/src/Ombi.Core.Tests/Engine/V2/MusicSearchEngineV2Tests.cs index 1871141a2..50ab63346 100644 --- a/src/Ombi.Core.Tests/Engine/V2/MusicSearchEngineV2Tests.cs +++ b/src/Ombi.Core.Tests/Engine/V2/MusicSearchEngineV2Tests.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Security.Principal; using System.Threading.Tasks; using System.Linq; +using System.Threading; using AutoFixture; using Hqub.MusicBrainz.API.Entities; using Moq; @@ -172,7 +173,7 @@ namespace Ombi.Core.Tests.Engine.V2 ApiKey = "dasdsa", Ip = "192.168.1.7" }); - _lidarrApi.Setup(x => x.GetArtistByForeignId(It.IsAny(), It.IsAny(), It.IsAny())) + _lidarrApi.Setup(x => x.GetArtistByForeignId(It.IsAny(), It.IsAny(), It.IsAny(), CancellationToken.None)) .ReturnsAsync(new ArtistResult { images = new Image[] diff --git a/src/Ombi.Core.Tests/Engine/VoteEngineTests.cs b/src/Ombi.Core.Tests/Engine/VoteEngineTests.cs index 41c645815..be874669c 100644 --- a/src/Ombi.Core.Tests/Engine/VoteEngineTests.cs +++ b/src/Ombi.Core.Tests/Engine/VoteEngineTests.cs @@ -34,7 +34,7 @@ namespace Ombi.Core.Tests.Engine MovieRequestEngine = new Mock(); User = new Mock(); User.Setup(x => x.Identity.Name).Returns("abc"); - UserManager = MockHelper.MockUserManager(new List { new OmbiUser { Id = "abc", UserName = "abc" } }); + UserManager = MockHelper.MockUserManager(new List { new OmbiUser { Id = "abc", UserName = "abc", NormalizedUserName = "ABC" } }); Rule = new Mock(); Engine = new VoteEngine(VoteRepository.Object, User.Object, UserManager.Object, Rule.Object, VoteSettings.Object, MusicRequestEngine.Object, TvRequestEngine.Object, MovieRequestEngine.Object); diff --git a/src/Ombi.Core.Tests/Ombi.Core.Tests.csproj b/src/Ombi.Core.Tests/Ombi.Core.Tests.csproj index 89ff21a7c..c86ed0c94 100644 --- a/src/Ombi.Core.Tests/Ombi.Core.Tests.csproj +++ b/src/Ombi.Core.Tests/Ombi.Core.Tests.csproj @@ -1,17 +1,23 @@  - netcoreapp3.0 + net5.0 + true + true - - - - - + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + - + diff --git a/src/Ombi.Core.Tests/Rule/Request/AutoApproveRuleTests.cs b/src/Ombi.Core.Tests/Rule/Request/AutoApproveRuleTests.cs index cae45aaf9..595ba39e0 100644 --- a/src/Ombi.Core.Tests/Rule/Request/AutoApproveRuleTests.cs +++ b/src/Ombi.Core.Tests/Rule/Request/AutoApproveRuleTests.cs @@ -18,7 +18,8 @@ namespace Ombi.Core.Tests.Rule.Request { private List _users = new List { - new OmbiUser { Id = Guid.NewGuid().ToString("N"), UserName="abc",UserType = UserType.LocalUser} + new OmbiUser { Id = Guid.NewGuid().ToString("N"), UserName="abc", NormalizedUserName = "ABC", UserType = UserType.LocalUser}, + new OmbiUser { Id = Guid.NewGuid().ToString("N"), UserName="Sys", NormalizedUserName = "SYS", UserType = UserType.SystemUser} }; [SetUp] @@ -92,6 +93,18 @@ namespace Ombi.Core.Tests.Rule.Request Assert.True(request.Approved); } + [Test] + public async Task Should_ReturnSuccess_WhenSystemUserAndRequestTV() + { + PrincipalMock.Setup(x => x.Identity.Name).Returns("sys"); + UserManager.Setup(x => x.IsInRoleAsync(It.IsAny(), OmbiRoles.AutoApproveTv)).ReturnsAsync(false); + var request = new BaseRequest() { RequestType = Store.Entities.RequestType.TvShow }; + var result = await Rule.Execute(request); + + Assert.True(result.Success); + Assert.True(request.Approved); + } + [Test] public async Task Should_ReturnFail_WhenAutoApproveTV_And_RequestMovie() { diff --git a/src/Ombi.Core.Tests/Rule/Request/CanRequestRuleTests.cs b/src/Ombi.Core.Tests/Rule/Request/CanRequestRuleTests.cs index 90703b6a0..03dc6f68c 100644 --- a/src/Ombi.Core.Tests/Rule/Request/CanRequestRuleTests.cs +++ b/src/Ombi.Core.Tests/Rule/Request/CanRequestRuleTests.cs @@ -18,7 +18,8 @@ namespace Ombi.Core.Tests.Rule.Request { private List _users = new List { - new OmbiUser { Id = Guid.NewGuid().ToString("N"), UserName="abc", UserType = UserType.LocalUser} + new OmbiUser { Id = Guid.NewGuid().ToString("N"), UserName="abc", NormalizedUserName = "ABC", UserType = UserType.LocalUser}, + new OmbiUser { Id = Guid.NewGuid().ToString("N"), UserName="sys", NormalizedUserName = "SYS", UserType = UserType.SystemUser} }; [SetUp] @@ -68,6 +69,17 @@ namespace Ombi.Core.Tests.Rule.Request Assert.True(result.Success); } + [Test] + public async Task Should_ReturnSuccess_WhenRequestingMovieWithSystemRole() + { + PrincipalMock.Setup(x => x.Identity.Name).Returns("sys"); + UserManager.Setup(x => x.IsInRoleAsync(It.IsAny(), OmbiRoles.Admin)).ReturnsAsync(false); + var request = new BaseRequest() { RequestType = Store.Entities.RequestType.Movie }; + var result = await Rule.Execute(request); + + Assert.True(result.Success); + } + [Test] public async Task Should_ReturnSuccess_WhenRequestingTVWithAdminRole() { diff --git a/src/Ombi.Core.Tests/Rule/Search/EmbyAvailabilityRuleTests.cs b/src/Ombi.Core.Tests/Rule/Search/EmbyAvailabilityRuleTests.cs index 5cac19383..8e5c57d67 100644 --- a/src/Ombi.Core.Tests/Rule/Search/EmbyAvailabilityRuleTests.cs +++ b/src/Ombi.Core.Tests/Rule/Search/EmbyAvailabilityRuleTests.cs @@ -54,14 +54,15 @@ namespace Ombi.Core.Tests.Rule.Search { new EmbyServers { - ServerHostname = "http://test.com/" + ServerHostname = "http://test.com/", + ServerId = "8" } } }); ContextMock.Setup(x => x.GetByTheMovieDbId(It.IsAny())).ReturnsAsync(new EmbyContent { ProviderId = "123", - EmbyId = 1.ToString() + EmbyId = 1.ToString(), }); var search = new SearchMovieViewModel() { @@ -70,7 +71,7 @@ namespace Ombi.Core.Tests.Rule.Search var result = await Rule.Execute(search); Assert.True(result.Success); - Assert.That(search.EmbyUrl, Is.EqualTo("http://test.com/#!/item/item.html?id=1")); + Assert.That(search.EmbyUrl, Is.EqualTo("http://test.com/web/index.html#!/item?id=1&serverId=8")); } [Test] @@ -83,7 +84,8 @@ namespace Ombi.Core.Tests.Rule.Search { new EmbyServers { - ServerHostname = string.Empty + ServerHostname = string.Empty, + ServerId = "8" } } }); @@ -99,7 +101,7 @@ namespace Ombi.Core.Tests.Rule.Search var result = await Rule.Execute(search); Assert.True(result.Success); - Assert.That(search.EmbyUrl, Is.EqualTo("https://app.emby.media/#!/item/item.html?id=1")); + Assert.That(search.EmbyUrl, Is.EqualTo("https://app.emby.media/web/index.html#!/item?id=1&serverId=8")); } [Test] diff --git a/src/Ombi.Core.Tests/Rule/Search/LidarrAlbumCacheRuleTests.cs b/src/Ombi.Core.Tests/Rule/Search/LidarrAlbumCacheRuleTests.cs index 6b04a57b7..27dbee614 100644 --- a/src/Ombi.Core.Tests/Rule/Search/LidarrAlbumCacheRuleTests.cs +++ b/src/Ombi.Core.Tests/Rule/Search/LidarrAlbumCacheRuleTests.cs @@ -113,7 +113,7 @@ namespace Ombi.Core.Tests.Rule.Search PercentOfTracks = 100 } }.AsQueryable()); - var request = new SearchAlbumViewModel { ForeignAlbumId = "ABC" }; + var request = new SearchAlbumViewModel { ForeignAlbumId = "abc" }; var result = await Rule.Execute(request); Assert.True(result.Success); diff --git a/src/Ombi.Core.Tests/Rule/Search/LidarrArtistCacheRuleTests.cs b/src/Ombi.Core.Tests/Rule/Search/LidarrArtistCacheRuleTests.cs index 7a2da1e25..c17400acb 100644 --- a/src/Ombi.Core.Tests/Rule/Search/LidarrArtistCacheRuleTests.cs +++ b/src/Ombi.Core.Tests/Rule/Search/LidarrArtistCacheRuleTests.cs @@ -63,7 +63,7 @@ namespace Ombi.Core.Tests.Rule.Search ForeignArtistId = "abc", } }.AsQueryable()); - var request = new SearchArtistViewModel { ForignArtistId = "ABC" }; + var request = new SearchArtistViewModel { ForignArtistId = "abc" }; var result = await Rule.Execute(request); Assert.True(result.Success); diff --git a/src/Ombi.Core/Authentication/OmbiUserManager.cs b/src/Ombi.Core/Authentication/OmbiUserManager.cs index 2c78f39bf..8313f359b 100644 --- a/src/Ombi.Core/Authentication/OmbiUserManager.cs +++ b/src/Ombi.Core/Authentication/OmbiUserManager.cs @@ -49,7 +49,7 @@ namespace Ombi.Core.Authentication IPasswordHasher passwordHasher, IEnumerable> userValidators, IEnumerable> passwordValidators, ILookupNormalizer keyNormalizer, IdentityErrorDescriber errors, IServiceProvider services, ILogger> logger, IPlexApi plexApi, - IEmbyApi embyApi, ISettingsService embySettings, ISettingsService auth) + IEmbyApiFactory embyApi, ISettingsService embySettings, ISettingsService auth) : base(store, optionsAccessor, passwordHasher, userValidators, passwordValidators, keyNormalizer, errors, services, logger) { _plexApi = plexApi; @@ -59,7 +59,7 @@ namespace Ombi.Core.Authentication } private readonly IPlexApi _plexApi; - private readonly IEmbyApi _embyApi; + private readonly IEmbyApiFactory _embyApi; private readonly ISettingsService _embySettings; private readonly ISettingsService _authSettings; @@ -79,7 +79,7 @@ namespace Ombi.Core.Authentication { return await CheckPlexPasswordAsync(user, password); } - if (user.UserType == UserType.EmbyUser) + if (user.UserType == UserType.EmbyUser || user.UserType == UserType.EmbyConnectUser) { return await CheckEmbyPasswordAsync(user, password); } @@ -146,9 +146,12 @@ namespace Ombi.Core.Authentication /// private async Task CheckEmbyPasswordAsync(OmbiUser user, string password) { + var embySettings = await _embySettings.GetSettingsAsync(); + var client = _embyApi.CreateClient(embySettings); + if (user.IsEmbyConnect) { - var result = await _embyApi.LoginConnectUser(user.UserName, password); + var result = await client.LoginConnectUser(user.UserName, password); if (result.AccessToken.HasValue()) { // We cannot update the email address in the user importer due to there is no way @@ -165,12 +168,11 @@ namespace Ombi.Core.Authentication } } - var embySettings = await _embySettings.GetSettingsAsync(); foreach (var server in embySettings.Servers) { try { - var result = await _embyApi.LogIn(user.UserName, password, server.ApiKey, server.FullUri); + var result = await client.LogIn(user.UserName, password, server.ApiKey, server.FullUri); if (result != null) { return true; diff --git a/src/Ombi.Core/Engine/BaseMediaEngine.cs b/src/Ombi.Core/Engine/BaseMediaEngine.cs index fde13a798..fc9847c7d 100644 --- a/src/Ombi.Core/Engine/BaseMediaEngine.cs +++ b/src/Ombi.Core/Engine/BaseMediaEngine.cs @@ -136,7 +136,7 @@ namespace Ombi.Core.Engine { var user = await GetUser(); var existingSub = await _subscriptionRepository.GetAll().FirstOrDefaultAsync(x => - x.UserId.Equals(user.Id) && x.RequestId == requestId && x.RequestType == type); + x.UserId == user.Id && x.RequestId == requestId && x.RequestType == type); if (existingSub != null) { return; @@ -155,23 +155,28 @@ namespace Ombi.Core.Engine { var user = await GetUser(); var existingSub = await _subscriptionRepository.GetAll().FirstOrDefaultAsync(x => - x.UserId.Equals(user.Id) && x.RequestId == requestId && x.RequestType == type); + x.UserId == user.Id && x.RequestId == requestId && x.RequestType == type); if (existingSub != null) { await _subscriptionRepository.Delete(existingSub); } } - private string defaultLangCode; protected async Task DefaultLanguageCode(string currentCode) { if (currentCode.HasValue()) { return currentCode; } + var user = await GetUser(); + + if (string.IsNullOrEmpty(user.Language)) + { + var s = await GetOmbiSettings(); + return s.DefaultLanguageCode; + } - var s = await GetOmbiSettings(); - return s.DefaultLanguageCode; + return user.Language; } private OmbiSettings ombiSettings; diff --git a/src/Ombi.Core/Engine/Demo/DemoMovieSearchEngine.cs b/src/Ombi.Core/Engine/Demo/DemoMovieSearchEngine.cs index 86582fb4d..f392bf7ad 100644 --- a/src/Ombi.Core/Engine/Demo/DemoMovieSearchEngine.cs +++ b/src/Ombi.Core/Engine/Demo/DemoMovieSearchEngine.cs @@ -50,7 +50,7 @@ namespace Ombi.Core.Engine.Demo return null; } - public async Task> NowPlayingMovies() + new public async Task> NowPlayingMovies() { var rand = new Random(); var responses = new List(); @@ -72,18 +72,18 @@ namespace Ombi.Core.Engine.Demo return responses; } - public async Task> PopularMovies() + new public async Task> PopularMovies() { return await NowPlayingMovies(); } - public async Task> TopRatedMovies() + new public async Task> TopRatedMovies() { return await NowPlayingMovies(); } - public async Task> UpcomingMovies() + new public async Task> UpcomingMovies() { return await NowPlayingMovies(); diff --git a/src/Ombi.Core/Engine/Demo/DemoTvSearchEngine.cs b/src/Ombi.Core/Engine/Demo/DemoTvSearchEngine.cs index 54dacda6b..343fb400a 100644 --- a/src/Ombi.Core/Engine/Demo/DemoTvSearchEngine.cs +++ b/src/Ombi.Core/Engine/Demo/DemoTvSearchEngine.cs @@ -26,15 +26,16 @@ namespace Ombi.Core.Engine.Demo public DemoTvSearchEngine(IPrincipal identity, IRequestServiceMain service, ITvMazeApi tvMaze, IMapper mapper, ITraktApi trakt, IRuleEvaluator r, OmbiUserManager um, ICacheService memCache, - ISettingsService s, IRepository sub, IOptions lists) - : base(identity, service, tvMaze, mapper, trakt, r, um, memCache, s, sub) + ISettingsService s, IRepository sub, IOptions lists, IImageService imageService, + ISettingsService custom) + : base(identity, service, tvMaze, mapper, trakt, r, um, custom, memCache, s, sub, imageService) { _demoLists = lists.Value; } private readonly DemoLists _demoLists; - public async Task> Search(string search) + new public async Task> Search(string search) { var searchResult = await TvMazeApi.Search(search); @@ -55,7 +56,7 @@ namespace Ombi.Core.Engine.Demo { continue; } - retVal.Add(await ProcessResult(tvMazeSearch)); + retVal.Add(await ProcessResult(tvMazeSearch, false)); } return retVal; } @@ -77,7 +78,7 @@ namespace Ombi.Core.Engine.Demo } var movieResult = await TvMazeApi.ShowLookup(tv); - responses.Add(await ProcessResult(movieResult)); + responses.Add(await ProcessResult(movieResult, false)); } return responses; diff --git a/src/Ombi.Core/Engine/IMusicRequestEngine.cs b/src/Ombi.Core/Engine/IMusicRequestEngine.cs index 02a051343..306d5c477 100644 --- a/src/Ombi.Core/Engine/IMusicRequestEngine.cs +++ b/src/Ombi.Core/Engine/IMusicRequestEngine.cs @@ -23,5 +23,7 @@ namespace Ombi.Core.Engine Task> SearchAlbumRequest(string search); Task UserHasRequest(string userId); Task GetRemainingRequests(OmbiUser user = null); + Task> GetRequestsByStatus(int count, int position, string sort, string sortOrder, RequestStatus available); + Task> GetRequests(int count, int position, string sort, string sortOrder); } } \ No newline at end of file diff --git a/src/Ombi.Core/Engine/IUserDeletionEngine.cs b/src/Ombi.Core/Engine/IUserDeletionEngine.cs new file mode 100644 index 000000000..99719ae33 --- /dev/null +++ b/src/Ombi.Core/Engine/IUserDeletionEngine.cs @@ -0,0 +1,11 @@ +using Microsoft.AspNetCore.Identity; +using Ombi.Store.Entities; +using System.Threading.Tasks; + +namespace Ombi.Core.Engine +{ + public interface IUserDeletionEngine + { + Task DeleteUser(OmbiUser userToDelete); + } +} diff --git a/src/Ombi.Core/Engine/Interfaces/BaseEngine.cs b/src/Ombi.Core/Engine/Interfaces/BaseEngine.cs index c5cb8c45a..8ddf27656 100644 --- a/src/Ombi.Core/Engine/Interfaces/BaseEngine.cs +++ b/src/Ombi.Core/Engine/Interfaces/BaseEngine.cs @@ -29,7 +29,8 @@ namespace Ombi.Core.Engine.Interfaces private OmbiUser _user; protected async Task GetUser() { - return _user ?? (_user = await UserManager.Users.FirstOrDefaultAsync(x => x.UserName.Equals(Username, StringComparison.CurrentCultureIgnoreCase))); + var username = Username.ToUpper(); + return _user ?? (_user = await UserManager.Users.FirstOrDefaultAsync(x => x.NormalizedUserName == username)); } protected async Task UserAlias() diff --git a/src/Ombi.Core/Engine/Interfaces/IMovieEngineV2.cs b/src/Ombi.Core/Engine/Interfaces/IMovieEngineV2.cs index c1ad70613..3b8d97dc0 100644 --- a/src/Ombi.Core/Engine/Interfaces/IMovieEngineV2.cs +++ b/src/Ombi.Core/Engine/Interfaces/IMovieEngineV2.cs @@ -9,6 +9,7 @@ namespace Ombi.Core.Engine.Interfaces { public interface IMovieEngineV2 { + Task GetMovieInfoByRequestId(int requestId, CancellationToken cancellationToken, string langCode = null); Task GetFullMovieInformation(int theMovieDbId, CancellationToken cancellationToken, string langCode = null); Task> SimilarMovies(int theMovieDbId, string langCode); Task> PopularMovies(); @@ -23,5 +24,7 @@ namespace Ombi.Core.Engine.Interfaces Task> UpcomingMovies(int currentlyLoaded, int toLoad); Task GetMoviesByActor(int actorId, string langCode); int ResultLimit { get; set; } + + Task GetMovieInfoByImdbId(string imdbId, CancellationToken requestAborted); } } \ No newline at end of file diff --git a/src/Ombi.Core/Engine/Interfaces/IMovieRequestEngine.cs b/src/Ombi.Core/Engine/Interfaces/IMovieRequestEngine.cs index 056632efc..64c76b18f 100644 --- a/src/Ombi.Core/Engine/Interfaces/IMovieRequestEngine.cs +++ b/src/Ombi.Core/Engine/Interfaces/IMovieRequestEngine.cs @@ -23,6 +23,7 @@ namespace Ombi.Core.Engine.Interfaces Task> GetUnavailableRequests(int count, int position, string sortProperty, string sortOrder); - Task UpdateAdvancedOptions(MovieAdvancedOptions options); + Task> GetRequestsByStatus(int count, int position, string sortProperty, string sortOrder, RequestStatus status); + Task UpdateAdvancedOptions(MediaAdvancedOptions options); } } \ No newline at end of file diff --git a/src/Ombi.Core/Engine/Interfaces/IMusicSearchEngineV2.cs b/src/Ombi.Core/Engine/Interfaces/IMusicSearchEngineV2.cs index f318290d8..f9889ec9c 100644 --- a/src/Ombi.Core/Engine/Interfaces/IMusicSearchEngineV2.cs +++ b/src/Ombi.Core/Engine/Interfaces/IMusicSearchEngineV2.cs @@ -7,6 +7,7 @@ namespace Ombi.Core.Engine.Interfaces public interface IMusicSearchEngineV2 { Task GetArtistInformation(string artistId); + Task GetArtistInformationByRequestId(int requestId); Task GetReleaseGroupArt(string musicBrainzId, CancellationToken token); } } \ No newline at end of file diff --git a/src/Ombi.Core/Engine/Interfaces/ITvRequestEngine.cs b/src/Ombi.Core/Engine/Interfaces/ITvRequestEngine.cs index 1747351f4..3a4207d9b 100644 --- a/src/Ombi.Core/Engine/Interfaces/ITvRequestEngine.cs +++ b/src/Ombi.Core/Engine/Interfaces/ITvRequestEngine.cs @@ -25,5 +25,7 @@ namespace Ombi.Core.Engine.Interfaces Task UpdateQualityProfile(int requestId, int profileId); Task UpdateRootPath(int requestId, int rootPath); Task> GetRequests(int count, int position, string sortProperty, string sortOrder); + Task> GetRequests(int count, int position, string sortProperty, string sortOrder, RequestStatus status); + Task UpdateAdvancedOptions(MediaAdvancedOptions options); } } \ No newline at end of file diff --git a/src/Ombi.Core/Engine/Interfaces/ITvSearchEngine.cs b/src/Ombi.Core/Engine/Interfaces/ITvSearchEngine.cs index 7ee6c4cf1..b2afb4c6f 100644 --- a/src/Ombi.Core/Engine/Interfaces/ITvSearchEngine.cs +++ b/src/Ombi.Core/Engine/Interfaces/ITvSearchEngine.cs @@ -9,7 +9,7 @@ namespace Ombi.Core.Engine.Interfaces Task> Search(string searchTerm); Task GetShowInformation(int tvdbid); Task> Popular(); - Task> Popular(int currentlyLoaded, int amountToLoad); + Task> Popular(int currentlyLoaded, int amountToLoad, bool includeImages = false); Task> Anticipated(); Task> Anticipated(int currentlyLoaded, int amountToLoad); Task> Trending(); diff --git a/src/Ombi.Core/Engine/Interfaces/ITvSearchEngineV2.cs b/src/Ombi.Core/Engine/Interfaces/ITvSearchEngineV2.cs index 0a18a32bf..a8a27aa19 100644 --- a/src/Ombi.Core/Engine/Interfaces/ITvSearchEngineV2.cs +++ b/src/Ombi.Core/Engine/Interfaces/ITvSearchEngineV2.cs @@ -6,5 +6,6 @@ namespace Ombi.Core public interface ITVSearchEngineV2 { Task GetShowInformation(int tvdbid); + Task GetShowByRequest(int requestId); } } \ No newline at end of file diff --git a/src/Ombi.Core/Engine/MovieRequestEngine.cs b/src/Ombi.Core/Engine/MovieRequestEngine.cs index 48fc9282d..741503795 100644 --- a/src/Ombi.Core/Engine/MovieRequestEngine.cs +++ b/src/Ombi.Core/Engine/MovieRequestEngine.cs @@ -189,11 +189,7 @@ namespace Ombi.Core.Engine var requests = await (OrderMovies(allRequests, orderFilter.OrderType)).Skip(position).Take(count) .ToListAsync(); - requests.ForEach(async x => - { - x.PosterPath = PosterPathHelper.FixPosterPath(x.PosterPath); - await CheckForSubscription(shouldHide, x); - }); + await CheckForSubscription(shouldHide, requests); return new RequestsViewModel { Collection = requests, @@ -230,23 +226,83 @@ namespace Ombi.Core.Engine //var secondProp = TypeDescriptor.GetProperties(propType).Find(properties[1], true); } - allRequests = sortOrder.Equals("asc", StringComparison.InvariantCultureIgnoreCase) - ? allRequests.OrderBy(x => prop.GetValue(x)) - : allRequests.OrderByDescending(x => prop.GetValue(x)); - var total = await allRequests.CountAsync(); - var requests = await allRequests.Skip(position).Take(count) - .ToListAsync(); - requests.ForEach(async x => + // TODO fix this so we execute this on the server + var requests = sortOrder.Equals("asc", StringComparison.InvariantCultureIgnoreCase) + ? allRequests.ToList().OrderBy(x => prop.GetValue(x)).ToList() + : allRequests.ToList().OrderByDescending(x => prop.GetValue(x)).ToList(); + var total = requests.Count(); + requests = requests.Skip(position).Take(count).ToList(); + + await CheckForSubscription(shouldHide, requests); + return new RequestsViewModel { - x.PosterPath = PosterPathHelper.FixPosterPath(x.PosterPath); - await CheckForSubscription(shouldHide, x); - }); + Collection = requests, + Total = total + }; + } + + public async Task> GetRequestsByStatus(int count, int position, string sortProperty, string sortOrder, RequestStatus status) + { + var shouldHide = await HideFromOtherUsers(); + IQueryable allRequests; + if (shouldHide.Hide) + { + allRequests = + MovieRepository.GetWithUser(shouldHide + .UserId); + } + else + { + allRequests = + MovieRepository + .GetWithUser(); + } + + switch (status) + { + case RequestStatus.PendingApproval: + allRequests = allRequests.Where(x => !x.Approved && !x.Available && (!x.Denied.HasValue || !x.Denied.Value)); + break; + case RequestStatus.ProcessingRequest: + allRequests = allRequests.Where(x => x.Approved && !x.Available && (!x.Denied.HasValue || !x.Denied.Value)); + break; + case RequestStatus.Available: + allRequests = allRequests.Where(x => x.Available); + break; + case RequestStatus.Denied: + allRequests = allRequests.Where(x => x.Denied.HasValue && x.Denied.Value && !x.Available); + break; + default: + break; + } + + var prop = TypeDescriptor.GetProperties(typeof(MovieRequests)).Find(sortProperty, true); + + if (sortProperty.Contains('.')) + { + // This is a navigation property currently not supported + prop = TypeDescriptor.GetProperties(typeof(MovieRequests)).Find("RequestedDate", true); + //var properties = sortProperty.Split(new []{'.'}, StringSplitOptions.RemoveEmptyEntries); + //var firstProp = TypeDescriptor.GetProperties(typeof(MovieRequests)).Find(properties[0], true); + //var propType = firstProp.PropertyType; + //var secondProp = TypeDescriptor.GetProperties(propType).Find(properties[1], true); + } + + // TODO fix this so we execute this on the server + var requests = sortOrder.Equals("asc", StringComparison.InvariantCultureIgnoreCase) + ? allRequests.ToList().OrderBy(x => x.RequestedDate).ToList() + : allRequests.ToList().OrderByDescending(x => prop.GetValue(x)).ToList(); + var total = requests.Count(); + requests = requests.Skip(position).Take(count).ToList(); + + await CheckForSubscription(shouldHide, requests); return new RequestsViewModel { Collection = requests, Total = total }; } + public async Task> GetUnavailableRequests(int count, int position, string sortProperty, string sortOrder) { var shouldHide = await HideFromOtherUsers(); @@ -276,17 +332,13 @@ namespace Ombi.Core.Engine //var secondProp = TypeDescriptor.GetProperties(propType).Find(properties[1], true); } - allRequests = sortOrder.Equals("asc", StringComparison.InvariantCultureIgnoreCase) - ? allRequests.OrderBy(x => prop.GetValue(x)) - : allRequests.OrderByDescending(x => prop.GetValue(x)); - var total = await allRequests.CountAsync(); - var requests = await allRequests.Skip(position).Take(count) - .ToListAsync(); - requests.ForEach(async x => - { - x.PosterPath = PosterPathHelper.FixPosterPath(x.PosterPath); - await CheckForSubscription(shouldHide, x); - }); + var requests = (sortOrder.Equals("asc", StringComparison.InvariantCultureIgnoreCase) + ? allRequests.ToList().OrderBy(x => prop.GetValue(x)) + : allRequests.ToList().OrderByDescending(x => prop.GetValue(x))).ToList(); + var total = requests.Count(); + requests = requests.Skip(position).Take(count).ToList(); + + await CheckForSubscription(shouldHide, requests); return new RequestsViewModel { Collection = requests, @@ -295,7 +347,7 @@ namespace Ombi.Core.Engine } - public async Task UpdateAdvancedOptions(MovieAdvancedOptions options) + public async Task UpdateAdvancedOptions(MediaAdvancedOptions options) { var request = await MovieRepository.Find(options.RequestId); if (request == null) @@ -369,35 +421,38 @@ namespace Ombi.Core.Engine allRequests = await MovieRepository.GetWithUser().ToListAsync(); } - allRequests.ForEach(async x => - { - x.PosterPath = PosterPathHelper.FixPosterPath(x.PosterPath); - await CheckForSubscription(shouldHide, x); - }); + await CheckForSubscription(shouldHide, allRequests); + return allRequests; } public async Task GetRequest(int requestId) { var request = await MovieRepository.GetWithUser().Where(x => x.Id == requestId).FirstOrDefaultAsync(); - request.PosterPath = PosterPathHelper.FixPosterPath(request.PosterPath); - await CheckForSubscription(new HideResult(), request); + await CheckForSubscription(new HideResult(), new List{request }); return request; } - private async Task CheckForSubscription(HideResult shouldHide, MovieRequests x) + private async Task CheckForSubscription(HideResult shouldHide, List movieRequests) { - if (shouldHide.UserId == x.RequestedUserId) - { - x.ShowSubscribe = false; - } - else + var requestIds = movieRequests.Select(x => x.Id); + var sub = await _subscriptionRepository.GetAll().Where(s => + s.UserId == shouldHide.UserId && requestIds.Contains(s.RequestId) && s.RequestType == RequestType.Movie) + .ToListAsync(); + foreach (var x in movieRequests) { - x.ShowSubscribe = true; - var sub = await _subscriptionRepository.GetAll().FirstOrDefaultAsync(s => - s.UserId == shouldHide.UserId && s.RequestId == x.Id && s.RequestType == RequestType.Movie); - x.Subscribed = sub != null; + x.PosterPath = PosterPathHelper.FixPosterPath(x.PosterPath); + if (shouldHide.UserId == x.RequestedUserId) + { + x.ShowSubscribe = false; + } + else + { + x.ShowSubscribe = true; + var hasSub = sub.FirstOrDefault(r => r.RequestId == x.Id); + x.Subscribed = hasSub != null; + } } } @@ -420,11 +475,8 @@ namespace Ombi.Core.Engine } var results = allRequests.Where(x => x.Title.Contains(search, CompareOptions.IgnoreCase)).ToList(); - results.ForEach(async x => - { - x.PosterPath = PosterPathHelper.FixPosterPath(x.PosterPath); - await CheckForSubscription(shouldHide, x); - }); + await CheckForSubscription(shouldHide, results); + return results; } @@ -448,7 +500,7 @@ namespace Ombi.Core.Engine request.Denied = true; request.DeniedReason = denyReason; // We are denying a request - NotificationHelper.Notify(request, NotificationType.RequestDeclined); + await NotificationHelper.Notify(request, NotificationType.RequestDeclined); await MovieRepository.Update(request); return new RequestEngineResult @@ -476,7 +528,7 @@ namespace Ombi.Core.Engine var canNotify = await RunSpecificRule(request, SpecificRules.CanSendNotification); if (canNotify.Success) { - NotificationHelper.Notify(request, NotificationType.RequestApproved); + await NotificationHelper.Notify(request, NotificationType.RequestApproved); } if (request.Approved) @@ -592,7 +644,7 @@ namespace Ombi.Core.Engine request.Available = true; request.MarkedAsAvailable = DateTime.Now; - NotificationHelper.Notify(request, NotificationType.RequestAvailable); + await NotificationHelper.Notify(request, NotificationType.RequestAvailable); await MovieRepository.Update(request); return new RequestEngineResult @@ -608,8 +660,8 @@ namespace Ombi.Core.Engine var result = await RunSpecificRule(model, SpecificRules.CanSendNotification); if (result.Success) - { - NotificationHelper.NewRequest(model); + { + await NotificationHelper.NewRequest(model); } await _requestLog.Add(new RequestLog diff --git a/src/Ombi.Core/Engine/MusicRequestEngine.cs b/src/Ombi.Core/Engine/MusicRequestEngine.cs index 8094e79c4..e473c1fb1 100644 --- a/src/Ombi.Core/Engine/MusicRequestEngine.cs +++ b/src/Ombi.Core/Engine/MusicRequestEngine.cs @@ -7,6 +7,7 @@ using System.Collections.Generic; using System.Globalization; using System.Linq; using System.Security.Principal; +using System.Threading; using System.Threading.Tasks; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; @@ -22,6 +23,7 @@ using Ombi.Settings.Settings.Models; using Ombi.Settings.Settings.Models.External; using Ombi.Store.Entities.Requests; using Ombi.Store.Repository; +using System.ComponentModel; namespace Ombi.Core.Engine { @@ -69,12 +71,6 @@ namespace Ombi.Core.Engine }; } - if(album?.artist == null) - { - // Lookup the artist - //album.artist = await _lidarrApi.ArtistLookup(album.artist, s.ApiKey, s.FullUri); - } - var userDetails = await GetUser(); var requestModel = new AlbumRequest @@ -132,7 +128,6 @@ namespace Ombi.Core.Engine return await AddAlbumRequest(requestModel); } - /// /// Gets the requests. /// @@ -259,6 +254,28 @@ namespace Ombi.Core.Engine return allRequests; } + + private async Task CheckForSubscription(HideResult shouldHide, List albumRequests) + { + var requestIds = albumRequests.Select(x => x.Id); + var sub = await _subscriptionRepository.GetAll().Where(s => + s.UserId == shouldHide.UserId && requestIds.Contains(s.RequestId) && s.RequestType == RequestType.Movie) + .ToListAsync(); + foreach (var x in albumRequests) + { + if (shouldHide.UserId == x.RequestedUserId) + { + x.ShowSubscribe = false; + } + else + { + x.ShowSubscribe = true; + var hasSub = sub.FirstOrDefault(r => r.RequestId == x.Id); + x.Subscribed = hasSub != null; + } + } + } + private async Task CheckForSubscription(HideResult shouldHide, AlbumRequest x) { if (shouldHide.UserId == x.RequestedUserId) @@ -320,7 +337,7 @@ namespace Ombi.Core.Engine request.Denied = true; request.DeniedReason = reason; // We are denying a request - NotificationHelper.Notify(request, NotificationType.RequestDeclined); + await NotificationHelper.Notify(request, NotificationType.RequestDeclined); await MusicRepository.Update(request); return new RequestEngineResult @@ -348,7 +365,7 @@ namespace Ombi.Core.Engine var canNotify = await RunSpecificRule(request, SpecificRules.CanSendNotification); if (canNotify.Success) { - NotificationHelper.Notify(request, NotificationType.RequestApproved); + await NotificationHelper.Notify(request, NotificationType.RequestApproved); } if (request.Approved) @@ -475,7 +492,7 @@ namespace Ombi.Core.Engine request.Available = true; request.MarkedAsAvailable = DateTime.Now; - NotificationHelper.Notify(request, NotificationType.RequestAvailable); + await NotificationHelper.Notify(request, NotificationType.RequestAvailable); await MusicRepository.Update(request); return new RequestEngineResult @@ -492,7 +509,7 @@ namespace Ombi.Core.Engine var result = await RunSpecificRule(model, SpecificRules.CanSendNotification); if (result.Success) { - NotificationHelper.NewRequest(model); + await NotificationHelper.NewRequest(model); } await _requestLog.Add(new RequestLog @@ -506,6 +523,110 @@ namespace Ombi.Core.Engine return new RequestEngineResult { Result = true, Message = $"{model.Title} has been successfully added!", RequestId = model.Id }; } - + public async Task> GetRequestsByStatus(int count, int position, string sortProperty, string sortOrder, RequestStatus status) + { + var shouldHide = await HideFromOtherUsers(); + IQueryable allRequests; + if (shouldHide.Hide) + { + allRequests = + MusicRepository.GetWithUser(shouldHide + .UserId); + } + else + { + allRequests = + MusicRepository + .GetWithUser(); + } + + switch (status) + { + case RequestStatus.PendingApproval: + allRequests = allRequests.Where(x => !x.Approved && !x.Available && (!x.Denied.HasValue || !x.Denied.Value)); + break; + case RequestStatus.ProcessingRequest: + allRequests = allRequests.Where(x => x.Approved && !x.Available && (!x.Denied.HasValue || !x.Denied.Value)); + break; + case RequestStatus.Available: + allRequests = allRequests.Where(x => x.Available); + break; + case RequestStatus.Denied: + allRequests = allRequests.Where(x => x.Denied.HasValue && x.Denied.Value && !x.Available); + break; + default: + break; + } + + var prop = TypeDescriptor.GetProperties(typeof(AlbumRequest)).Find(sortProperty, true); + + if (sortProperty.Contains('.')) + { + // This is a navigation property currently not supported + prop = TypeDescriptor.GetProperties(typeof(AlbumRequest)).Find("RequestedDate", true); + //var properties = sortProperty.Split(new []{'.'}, StringSplitOptions.RemoveEmptyEntries); + //var firstProp = TypeDescriptor.GetProperties(typeof(MovieRequests)).Find(properties[0], true); + //var propType = firstProp.PropertyType; + //var secondProp = TypeDescriptor.GetProperties(propType).Find(properties[1], true); + } + + // TODO fix this so we execute this on the server + var requests = sortOrder.Equals("asc", StringComparison.InvariantCultureIgnoreCase) + ? allRequests.ToList().OrderBy(x => x.RequestedDate).ToList() + : allRequests.ToList().OrderByDescending(x => prop.GetValue(x)).ToList(); + var total = requests.Count(); + requests = requests.Skip(position).Take(count).ToList(); + + await CheckForSubscription(shouldHide, requests); + return new RequestsViewModel + { + Collection = requests, + Total = total + }; + } + + public async Task> GetRequests(int count, int position, string sortProperty, string sortOrder) + { + var shouldHide = await HideFromOtherUsers(); + IQueryable allRequests; + if (shouldHide.Hide) + { + allRequests = + MusicRepository.GetWithUser(shouldHide + .UserId); + } + else + { + allRequests = + MusicRepository + .GetWithUser(); + } + + var prop = TypeDescriptor.GetProperties(typeof(MovieRequests)).Find(sortProperty, true); + + if (sortProperty.Contains('.')) + { + // This is a navigation property currently not supported + prop = TypeDescriptor.GetProperties(typeof(MovieRequests)).Find("RequestedDate", true); + //var properties = sortProperty.Split(new []{'.'}, StringSplitOptions.RemoveEmptyEntries); + //var firstProp = TypeDescriptor.GetProperties(typeof(MovieRequests)).Find(properties[0], true); + //var propType = firstProp.PropertyType; + //var secondProp = TypeDescriptor.GetProperties(propType).Find(properties[1], true); + } + + // TODO fix this so we execute this on the server + var requests = sortOrder.Equals("asc", StringComparison.InvariantCultureIgnoreCase) + ? allRequests.ToList().OrderBy(x => x.RequestedDate).ToList() + : allRequests.ToList().OrderByDescending(x => prop.GetValue(x)).ToList(); + var total = requests.Count(); + requests = requests.Skip(position).Take(count).ToList(); + + await CheckForSubscription(shouldHide, requests); + return new RequestsViewModel + { + Collection = requests, + Total = total + }; + } } } \ No newline at end of file diff --git a/src/Ombi.Core/Engine/TvRequestEngine.cs b/src/Ombi.Core/Engine/TvRequestEngine.cs index 189e98c3c..e066261f4 100644 --- a/src/Ombi.Core/Engine/TvRequestEngine.cs +++ b/src/Ombi.Core/Engine/TvRequestEngine.cs @@ -159,8 +159,7 @@ namespace Ombi.Core.Engine .Skip(position).Take(count).ToListAsync(); } - - allRequests.ForEach(async r => { await CheckForSubscription(shouldHide, r); }); + await CheckForSubscription(shouldHide, allRequests); return new RequestsViewModel { @@ -195,7 +194,8 @@ namespace Ombi.Core.Engine { return new RequestsViewModel(); } - allRequests.ForEach(async r => { await CheckForSubscription(shouldHide, r); }); + + await CheckForSubscription(shouldHide, allRequests); return new RequestsViewModel { @@ -217,7 +217,7 @@ namespace Ombi.Core.Engine allRequests = await TvRepository.Get().ToListAsync(); } - allRequests.ForEach(async r => { await CheckForSubscription(shouldHide, r); }); + await CheckForSubscription(shouldHide, allRequests); return allRequests; } @@ -262,7 +262,81 @@ namespace Ombi.Core.Engine allRequests = sortOrder.Equals("asc", StringComparison.InvariantCultureIgnoreCase) ? allRequests.OrderBy(x => prop.GetValue(x)).ToList() : allRequests.OrderByDescending(x => prop.GetValue(x)).ToList(); - allRequests.ForEach(async r => { await CheckForSubscription(shouldHide, r); }); + + await CheckForSubscription(shouldHide, allRequests); + + // Make sure we do not show duplicate child requests + allRequests = allRequests.DistinctBy(x => x.ParentRequest.Title).ToList(); + + allRequests = allRequests.Skip(position).Take(count).ToList(); + + return new RequestsViewModel + { + Collection = allRequests, + Total = total, + }; + } + + public async Task> GetRequests(int count, int position, string sortProperty, string sortOrder, RequestStatus status) + { + var shouldHide = await HideFromOtherUsers(); + List allRequests; + if (shouldHide.Hide) + { + allRequests = await TvRepository.GetChild(shouldHide.UserId).ToListAsync(); + + // Filter out children + + FilterChildren(allRequests, shouldHide); + } + else + { + allRequests = await TvRepository.GetChild().ToListAsync(); + + } + + switch (status) + { + case RequestStatus.PendingApproval: + allRequests = allRequests.Where(x => !x.Approved && !x.Available && (!x.Denied.HasValue || !x.Denied.Value)).ToList(); + break; + case RequestStatus.ProcessingRequest: + allRequests = allRequests.Where(x => x.Approved && !x.Available && (!x.Denied.HasValue || !x.Denied.Value)).ToList(); + break; + case RequestStatus.Available: + allRequests = allRequests.Where(x => x.Available && (!x.Denied.HasValue || !x.Denied.Value)).ToList(); + break; + case RequestStatus.Denied: + allRequests = allRequests.Where(x => x.Denied.HasValue && x.Denied.Value).ToList(); + break; + default: + break; + } + + if (allRequests == null) + { + return new RequestsViewModel(); + } + + var total = allRequests.Count; + + + var prop = TypeDescriptor.GetProperties(typeof(ChildRequests)).Find(sortProperty, true); + + if (sortProperty.Contains('.')) + { + // This is a navigation property currently not supported + prop = TypeDescriptor.GetProperties(typeof(ChildRequests)).Find("Title", true); + //var properties = sortProperty.Split(new []{'.'}, StringSplitOptions.RemoveEmptyEntries); + //var firstProp = TypeDescriptor.GetProperties(typeof(MovieRequests)).Find(properties[0], true); + //var propType = firstProp.PropertyType; + //var secondProp = TypeDescriptor.GetProperties(propType).Find(properties[1], true); + } + allRequests = sortOrder.Equals("asc", StringComparison.InvariantCultureIgnoreCase) + ? allRequests.OrderBy(x => prop.GetValue(x)).ToList() + : allRequests.OrderByDescending(x => prop.GetValue(x)).ToList(); + + await CheckForSubscription(shouldHide, allRequests); // Make sure we do not show duplicate child requests allRequests = allRequests.DistinctBy(x => x.ParentRequest.Title).ToList(); @@ -315,7 +389,7 @@ namespace Ombi.Core.Engine allRequests = sortOrder.Equals("asc", StringComparison.InvariantCultureIgnoreCase) ? allRequests.OrderBy(x => prop.GetValue(x)).ToList() : allRequests.OrderByDescending(x => prop.GetValue(x)).ToList(); - allRequests.ForEach(async r => { await CheckForSubscription(shouldHide, r); }); + await CheckForSubscription(shouldHide, allRequests); // Make sure we do not show duplicate child requests allRequests = allRequests.DistinctBy(x => x.ParentRequest.Title).ToList(); @@ -344,7 +418,7 @@ namespace Ombi.Core.Engine allRequests = await TvRepository.GetLite().ToListAsync(); } - allRequests.ForEach(async r => { await CheckForSubscription(shouldHide, r); }); + await CheckForSubscription(shouldHide, allRequests); return allRequests; } @@ -363,7 +437,7 @@ namespace Ombi.Core.Engine request = await TvRepository.Get().Where(x => x.Id == requestId).FirstOrDefaultAsync(); } - await CheckForSubscription(shouldHide, request); + await CheckForSubscription(shouldHide, new List{request}); return request; } @@ -417,7 +491,7 @@ namespace Ombi.Core.Engine allRequests = await TvRepository.GetChild().Include(x => x.SeasonRequests).Where(x => x.ParentRequestId == tvId).ToListAsync(); } - allRequests.ForEach(async r => { await CheckForSubscription(shouldHide, r); }); + await CheckForSubscription(shouldHide, allRequests); return allRequests; } @@ -436,7 +510,7 @@ namespace Ombi.Core.Engine } var results = await allRequests.Where(x => x.Title.Contains(search, CompareOptions.IgnoreCase)).ToListAsync(); - results.ForEach(async r => { await CheckForSubscription(shouldHide, r); }); + await CheckForSubscription(shouldHide, results); return results; } @@ -501,7 +575,7 @@ namespace Ombi.Core.Engine if (request.Approved) { - NotificationHelper.Notify(request, NotificationType.RequestApproved); + await NotificationHelper.Notify(request, NotificationType.RequestApproved); // Autosend await TvSender.Send(request); } @@ -524,7 +598,7 @@ namespace Ombi.Core.Engine request.Denied = true; request.DeniedReason = reason; await TvRepository.UpdateChild(request); - NotificationHelper.Notify(request, NotificationType.RequestDeclined); + await NotificationHelper.Notify(request, NotificationType.RequestDeclined); return new RequestEngineResult { Result = true @@ -533,7 +607,7 @@ namespace Ombi.Core.Engine public async Task UpdateChildRequest(ChildRequests request) { - await TvRepository.UpdateChild(request); + await TvRepository.UpdateChild(request); return request; } @@ -551,14 +625,14 @@ namespace Ombi.Core.Engine // Delete the parent TvRepository.Db.TvRequests.Remove(parent); } - + await TvRepository.Db.SaveChangesAsync(); } public async Task RemoveTvRequest(int requestId) { var request = await TvRepository.Get().FirstOrDefaultAsync(x => x.Id == requestId); - await TvRepository.Delete(request); + await TvRepository.Delete(request); } public async Task UserHasRequest(string userId) @@ -612,7 +686,7 @@ namespace Ombi.Core.Engine } } await TvRepository.UpdateChild(request); - NotificationHelper.Notify(request, NotificationType.RequestAvailable); + await NotificationHelper.Notify(request, NotificationType.RequestAvailable); return new RequestEngineResult { Result = true, @@ -633,26 +707,32 @@ namespace Ombi.Core.Engine } } - private async Task CheckForSubscription(HideResult shouldHide, TvRequests x) + private async Task CheckForSubscription(HideResult shouldHide, List x) { - foreach (var tv in x.ChildRequests) + foreach (var tvRequest in x) { - await CheckForSubscription(shouldHide, tv); + await CheckForSubscription(shouldHide, tvRequest.ChildRequests); } } - private async Task CheckForSubscription(HideResult shouldHide, ChildRequests x) + private async Task CheckForSubscription(HideResult shouldHide, List childRequests) { - if (shouldHide.UserId == x.RequestedUserId) - { - x.ShowSubscribe = false; - } - else + var sub = _subscriptionRepository.GetAll(); + var childIds = childRequests.Select(x => x.Id); + var relevantSubs = await sub.Where(s => + s.UserId == shouldHide.UserId && childIds.Contains(s.Id) && s.RequestType == RequestType.TvShow).ToListAsync(); + foreach (var x in childRequests) { - x.ShowSubscribe = true; - var sub = await _subscriptionRepository.GetAll().FirstOrDefaultAsync(s => - s.UserId == shouldHide.UserId && s.RequestId == x.Id && s.RequestType == RequestType.TvShow); - x.Subscribed = sub != null; + if (shouldHide.UserId == x.RequestedUserId) + { + x.ShowSubscribe = false; + } + else + { + x.ShowSubscribe = true; + var result = relevantSubs.FirstOrDefault(s => s.RequestId == x.Id); + x.Subscribed = result != null; + } } } @@ -691,7 +771,7 @@ namespace Ombi.Core.Engine var sendRuleResult = await RunSpecificRule(model, SpecificRules.CanSendNotification); if (sendRuleResult.Success) { - NotificationHelper.NewRequest(model); + await NotificationHelper.NewRequest(model); } await _requestLog.Add(new RequestLog @@ -706,7 +786,7 @@ namespace Ombi.Core.Engine if (model.Approved) { // Autosend - NotificationHelper.Notify(model, NotificationType.RequestApproved); + await NotificationHelper.Notify(model, NotificationType.RequestApproved); var result = await TvSender.Send(model); if (result.Success) { @@ -772,5 +852,28 @@ namespace Ombi.Core.Engine NextRequest = DateTime.SpecifyKind(oldestRequestedAt.AddDays(7), DateTimeKind.Utc), }; } + + public async Task UpdateAdvancedOptions(MediaAdvancedOptions options) + { + var request = await TvRepository.Find(options.RequestId); + if (request == null) + { + return new RequestEngineResult + { + Result = false, + ErrorMessage = "Request does not exist" + }; + } + + request.QualityOverride = options.QualityOverride; + request.RootFolder = options.RootPathOverride; + + await TvRepository.Update(request); + + return new RequestEngineResult + { + Result = true + }; + } } } \ No newline at end of file diff --git a/src/Ombi.Core/Engine/TvSearchEngine.cs b/src/Ombi.Core/Engine/TvSearchEngine.cs index f854a5eee..38ba8be1a 100644 --- a/src/Ombi.Core/Engine/TvSearchEngine.cs +++ b/src/Ombi.Core/Engine/TvSearchEngine.cs @@ -27,14 +27,19 @@ namespace Ombi.Core.Engine { public class TvSearchEngine : BaseMediaEngine, ITvSearchEngine { + private readonly ISettingsService _customizationSettings; + private readonly IImageService _imageService; + public TvSearchEngine(IPrincipal identity, IRequestServiceMain service, ITvMazeApi tvMaze, IMapper mapper, - ITraktApi trakt, IRuleEvaluator r, OmbiUserManager um, - ICacheService memCache, ISettingsService s, IRepository sub) + ITraktApi trakt, IRuleEvaluator r, OmbiUserManager um, ISettingsService customizationSettings, + ICacheService memCache, ISettingsService s, IRepository sub, IImageService imageService) : base(identity, service, r, um, memCache, s, sub) { + _imageService = imageService; TvMazeApi = tvMaze; Mapper = mapper; TraktApi = trakt; + _customizationSettings = customizationSettings; } protected ITvMazeApi TvMazeApi { get; } @@ -54,7 +59,7 @@ namespace Ombi.Core.Engine { continue; } - retVal.Add(await ProcessResult(tvMazeSearch)); + retVal.Add(await ProcessResult(tvMazeSearch, false)); } return retVal; } @@ -66,7 +71,7 @@ namespace Ombi.Core.Engine var show = await Cache.GetOrAdd(nameof(GetShowInformation) + tvdbid, async () => await TvMazeApi.ShowLookupByTheTvDbId(tvdbid), DateTime.Now.AddHours(12)); if (show == null) - { + { // We don't have enough information return null; } @@ -93,7 +98,7 @@ namespace Ombi.Core.Engine }; newSeason.Episodes.Add(new EpisodeRequests { - Url = e.url, + Url = e.url.ToHttpsUrl(), Title = e.name, AirDate = e.airstamp.HasValue() ? DateTime.Parse(e.airstamp) : DateTime.MinValue, EpisodeNumber = e.number, @@ -106,14 +111,14 @@ namespace Ombi.Core.Engine // We already have the season, so just add the episode season.Episodes.Add(new EpisodeRequests { - Url = e.url, + Url = e.url.ToHttpsUrl(), Title = e.name, AirDate = e.airstamp.HasValue() ? DateTime.Parse(e.airstamp) : DateTime.MinValue, EpisodeNumber = e.number, }); } } - return await ProcessResult(mapped); + return await ProcessResult(mapped, false); } public async Task> Popular() @@ -123,7 +128,7 @@ namespace Ombi.Core.Engine return await processed; } - public async Task> Popular(int currentlyLoaded, int amountToLoad) + public async Task> Popular(int currentlyLoaded, int amountToLoad, bool includeImages = false) { var pages = PaginationHelper.GetNextPages(currentlyLoaded, amountToLoad, ResultLimit); var results = new List(); @@ -133,7 +138,8 @@ namespace Ombi.Core.Engine async () => await TraktApi.GetPopularShows(pagesToLoad.Page, ResultLimit), DateTime.Now.AddHours(12)); results.AddRange(apiResult.Skip(pagesToLoad.Skip).Take(pagesToLoad.Take)); } - var processed = ProcessResults(results); + + var processed = ProcessResults(results, includeImages); return await processed; } @@ -150,7 +156,7 @@ namespace Ombi.Core.Engine var pages = PaginationHelper.GetNextPages(currentlyLoaded, amountToLoad, ResultLimit); var results = new List(); foreach (var pagesToLoad in pages) - { + { var apiResult = await Cache.GetOrAdd(nameof(Anticipated) + pagesToLoad.Page, async () => await TraktApi.GetAnticipatedShows(pagesToLoad.Page, ResultLimit), DateTime.Now.AddHours(12)); results.AddRange(apiResult.Skip(pagesToLoad.Skip).Take(pagesToLoad.Take)); @@ -181,26 +187,41 @@ namespace Ombi.Core.Engine return await processed; } - protected async Task> ProcessResults(IEnumerable items) + protected async Task> ProcessResults(IEnumerable items, bool includeImages = false) { var retVal = new List(); + var settings = await _customizationSettings.GetSettingsAsync(); foreach (var tvMazeSearch in items) { - retVal.Add(await ProcessResult(tvMazeSearch)); + var result = await ProcessResult(tvMazeSearch, includeImages); + if(settings.HideAvailableFromDiscover && result.Available) + { + continue; + } + retVal.Add(result); } return retVal; } - protected async Task ProcessResult(T tvMazeSearch) + protected async Task ProcessResult(T tvMazeSearch, bool includeImages) { var mapped = Mapper.Map(tvMazeSearch); - return await ProcessResult(mapped); + return await ProcessResult(mapped, includeImages); } - private async Task ProcessResult(SearchTvShowViewModel item) + private async Task ProcessResult(SearchTvShowViewModel item, bool includeImages) { item.TheTvDbId = item.Id.ToString(); - + if (includeImages) + { + + if (item.TheTvDbId.HasValue()) + { + item.BackdropPath = await _imageService.GetTvBackground(item.TheTvDbId); + } + + } + await RunSearchRules(item); return item; diff --git a/src/Ombi.Core/Engine/UserDeletionEngine.cs b/src/Ombi.Core/Engine/UserDeletionEngine.cs new file mode 100644 index 000000000..6ea1e794d --- /dev/null +++ b/src/Ombi.Core/Engine/UserDeletionEngine.cs @@ -0,0 +1,135 @@ +using Microsoft.AspNetCore.Identity; +using Microsoft.EntityFrameworkCore; +using Ombi.Core.Authentication; +using Ombi.Store.Entities; +using Ombi.Store.Entities.Requests; +using Ombi.Store.Repository; +using Ombi.Store.Repository.Requests; +using System.Linq; +using System.Threading.Tasks; + +namespace Ombi.Core.Engine +{ + public class UserDeletionEngine : IUserDeletionEngine + { + private readonly IMovieRequestRepository _movieRepository; + private readonly OmbiUserManager _userManager; + private readonly IRepository _issuesRepository; + private readonly IRepository _issueCommentsRepository; + private readonly IRepository _requestLogRepository; + private readonly IRepository _notificationRepository; + private readonly IRepository _requestSubscriptionRepository; + private readonly IRepository _userNotificationPreferences; + private readonly IRepository _userQualityProfiles; + private readonly ITvRequestRepository _tvRepository; + private readonly IMusicRequestRepository _musicRepository; + private readonly IRepository _voteRepository; + private readonly IRepository _mobileDevicesRepository; + + public UserDeletionEngine(IMovieRequestRepository movieRepository, + OmbiUserManager userManager, + ITvRequestRepository tvRepository, + IMusicRequestRepository musicRepository, + IRepository issueRepo, + IRepository issueCommentsRepo, + IRepository requestLogRepo, + IRepository notificationidsRepo, + IRepository requestSubRepository, + IRepository notificationPreferencesRepo, + IRepository qualityProfilesRepo, + IRepository voteRepository, + IRepository mobileDevicesRepository + ) + { + _movieRepository = movieRepository; + _userManager = userManager; + _tvRepository = tvRepository; + _musicRepository = musicRepository; + _issuesRepository = issueRepo; + _issueCommentsRepository = issueCommentsRepo; + _notificationRepository = notificationidsRepo; + _requestLogRepository = requestLogRepo; + _requestSubscriptionRepository = requestSubRepository; + _notificationRepository = notificationidsRepo; + _userNotificationPreferences = notificationPreferencesRepo; + _userQualityProfiles = qualityProfilesRepo; + _voteRepository = voteRepository; + _mobileDevicesRepository = mobileDevicesRepository; + } + + + public async Task DeleteUser(OmbiUser userToDelete) + { + var userId = userToDelete.Id; + // We need to delete all the requests first + var moviesUserRequested = _movieRepository.GetAll().Where(x => x.RequestedUserId == userId); + var tvUserRequested = _tvRepository.GetChild().Where(x => x.RequestedUserId == userId); + var musicRequested = _musicRepository.GetAll().Where(x => x.RequestedUserId == userId); + var notificationPreferences = _userNotificationPreferences.GetAll().Where(x => x.UserId == userId); + var userQuality = await _userQualityProfiles.GetAll().FirstOrDefaultAsync(x => x.UserId == userId); + + if (moviesUserRequested.Any()) + { + await _movieRepository.DeleteRange(moviesUserRequested); + } + if (tvUserRequested.Any()) + { + await _tvRepository.DeleteChildRange(tvUserRequested); + } + if (musicRequested.Any()) + { + await _musicRepository.DeleteRange(musicRequested); + } + if (notificationPreferences.Any()) + { + await _userNotificationPreferences.DeleteRange(notificationPreferences); + } + if (userQuality != null) + { + await _userQualityProfiles.Delete(userQuality); + } + + // Delete any issues and request logs + var issues = _issuesRepository.GetAll().Where(x => x.UserReportedId == userId); + var issueComments = _issueCommentsRepository.GetAll().Where(x => x.UserId == userId); + var requestLog = _requestLogRepository.GetAll().Where(x => x.UserId == userId); + if (issues.Any()) + { + await _issuesRepository.DeleteRange(issues); + } + if (requestLog.Any()) + { + await _requestLogRepository.DeleteRange(requestLog); + } + if (issueComments.Any()) + { + await _issueCommentsRepository.DeleteRange(issueComments); + } + + // Delete the Subscriptions and mobile notification ids + var subs = _requestSubscriptionRepository.GetAll().Where(x => x.UserId == userId); + var mobileIds = _notificationRepository.GetAll().Where(x => x.UserId == userId); + var votes = _voteRepository.GetAll().Where(x => x.UserId == userId); + var newMobiles = _mobileDevicesRepository.GetAll().Where(x => x.UserId == userId); + if (subs.Any()) + { + await _requestSubscriptionRepository.DeleteRange(subs); + } + if (mobileIds.Any()) + { + await _notificationRepository.DeleteRange(mobileIds); + } + if (votes.Any()) + { + await _voteRepository.DeleteRange(votes); + } + if (newMobiles.Any()) + { + await _mobileDevicesRepository.DeleteRange(newMobiles); + } + + var result = await _userManager.DeleteAsync(userToDelete); + return result; + } + } +} diff --git a/src/Ombi.Core/Engine/V2/CalendarEngine.cs b/src/Ombi.Core/Engine/V2/CalendarEngine.cs index 4b3618780..4a5814e1a 100644 --- a/src/Ombi.Core/Engine/V2/CalendarEngine.cs +++ b/src/Ombi.Core/Engine/V2/CalendarEngine.cs @@ -27,7 +27,7 @@ namespace Ombi.Core.Engine.V2 private readonly IMovieRequestRepository _movieRepo; private readonly ITvRequestRepository _tvRepo; - public async Task> GetCalendarData() + public Task> GetCalendarData() { var viewModel = new List(); var movies = _movieRepo.GetAll().Where(x => @@ -78,7 +78,7 @@ namespace Ombi.Core.Engine.V2 }); } - return viewModel; + return Task.FromResult(viewModel); } private string GetBackgroundColor(BaseRequest req) diff --git a/src/Ombi.Core/Engine/V2/IMultiSearchEngine.cs b/src/Ombi.Core/Engine/V2/IMultiSearchEngine.cs index fdfcb06e6..1b78eaea5 100644 --- a/src/Ombi.Core/Engine/V2/IMultiSearchEngine.cs +++ b/src/Ombi.Core/Engine/V2/IMultiSearchEngine.cs @@ -8,6 +8,6 @@ namespace Ombi.Core.Engine.V2 { public interface IMultiSearchEngine { - Task> MultiSearch(string searchTerm, CancellationToken cancellationToken, string lang = "en"); + Task> MultiSearch(string searchTerm, MultiSearchFilter filter, CancellationToken cancellationToken); } } \ No newline at end of file diff --git a/src/Ombi.Core/Engine/V2/MovieSearchEngineV2.cs b/src/Ombi.Core/Engine/V2/MovieSearchEngineV2.cs index f33a7f3a6..b0a78fbb3 100644 --- a/src/Ombi.Core/Engine/V2/MovieSearchEngineV2.cs +++ b/src/Ombi.Core/Engine/V2/MovieSearchEngineV2.cs @@ -26,17 +26,20 @@ namespace Ombi.Core.Engine.V2 public class MovieSearchEngineV2 : BaseMediaEngine, IMovieEngineV2 { public MovieSearchEngineV2(IPrincipal identity, IRequestServiceMain service, IMovieDbApi movApi, IMapper mapper, - ILogger logger, IRuleEvaluator r, OmbiUserManager um, ICacheService mem, ISettingsService s, IRepository sub) + ILogger logger, IRuleEvaluator r, OmbiUserManager um, ICacheService mem, ISettingsService s, IRepository sub, + ISettingsService customizationSettings) : base(identity, service, r, um, mem, s, sub) { MovieApi = movApi; Mapper = mapper; Logger = logger; + _customizationSettings = customizationSettings; } private IMovieDbApi MovieApi { get; } private IMapper Mapper { get; } private ILogger Logger { get; } + private readonly ISettingsService _customizationSettings; public async Task GetFullMovieInformation(int theMovieDbId, CancellationToken cancellationToken, string langCode = null) @@ -48,6 +51,16 @@ namespace Ombi.Core.Engine.V2 return await ProcessSingleMovie(movieInfo); } + public async Task GetMovieInfoByRequestId(int requestId, CancellationToken cancellationToken, string langCode = null) + { + langCode = await DefaultLanguageCode(langCode); + var request = await RequestService.MovieRequestService.Find(requestId); + var movieInfo = await Cache.GetOrAdd(nameof(GetFullMovieInformation) + request.TheMovieDbId + langCode, + async () => await MovieApi.GetFullMovieInfo(request.TheMovieDbId, cancellationToken, langCode), DateTime.Now.AddHours(12), cancellationToken); + + return await ProcessSingleMovie(movieInfo); + } + public async Task GetCollection(int collectionId, CancellationToken cancellationToken, string langCode = null) { langCode = await DefaultLanguageCode(langCode); @@ -111,7 +124,7 @@ namespace Ombi.Core.Engine.V2 public async Task> PopularMovies(int currentlyLoaded, int toLoad, CancellationToken cancellationToken) { var langCode = await DefaultLanguageCode(null); - + var pages = PaginationHelper.GetNextPages(currentlyLoaded, toLoad, _theMovieDbMaxPageItems); var results = new List(); @@ -239,10 +252,16 @@ namespace Ombi.Core.Engine.V2 protected async Task> TransformMovieResultsToResponse( IEnumerable movies) { + var settings = await _customizationSettings.GetSettingsAsync(); var viewMovies = new List(); foreach (var movie in movies) { - viewMovies.Add(await ProcessSingleMovie(movie)); + var result = await ProcessSingleMovie(movie); + if (settings.HideAvailableFromDiscover && result.Available) + { + continue; + } + viewMovies.Add(result); } return viewMovies; } @@ -342,5 +361,18 @@ namespace Ombi.Core.Engine.V2 viewModel.Subscribed = sub != null; } } + + public async Task GetMovieInfoByImdbId(string imdbId, CancellationToken cancellationToken) + { + var langCode = await DefaultLanguageCode(null); + var findResult = await Cache.GetOrAdd(nameof(GetMovieInfoByImdbId) + imdbId + langCode, + async () => await MovieApi.Find(imdbId, ExternalSource.imdb_id), DateTime.Now.AddHours(12), cancellationToken); + + var movie = findResult.movie_results.FirstOrDefault(); + var movieInfo = await Cache.GetOrAdd(nameof(GetMovieInfoByImdbId) + movie.id + langCode, + async () => await MovieApi.GetFullMovieInfo(movie.id, cancellationToken, langCode), DateTime.Now.AddHours(12), cancellationToken); + + return await ProcessSingleMovie(movieInfo); + } } } \ No newline at end of file diff --git a/src/Ombi.Core/Engine/V2/MultiSearchEngine.cs b/src/Ombi.Core/Engine/V2/MultiSearchEngine.cs index d99d33a76..60cd6377d 100644 --- a/src/Ombi.Core/Engine/V2/MultiSearchEngine.cs +++ b/src/Ombi.Core/Engine/V2/MultiSearchEngine.cs @@ -36,14 +36,15 @@ namespace Ombi.Core.Engine.V2 private readonly IMusicBrainzApi _musicApi; - public async Task> MultiSearch(string searchTerm, CancellationToken cancellationToken, string lang = "en") + public async Task> MultiSearch(string searchTerm, MultiSearchFilter filter, CancellationToken cancellationToken) { + var lang = await DefaultLanguageCode(null); var model = new List(); var movieDbData = (await _movieDbApi.MultiSearch(searchTerm, lang, cancellationToken)).results; var lidarrSettings = await _lidarrSettings.GetSettingsAsync(); - if (lidarrSettings.Enabled) + if (lidarrSettings.Enabled && filter.Music) { var artistResult = await _musicApi.SearchArtist(searchTerm); foreach (var artist in artistResult) @@ -62,9 +63,10 @@ namespace Ombi.Core.Engine.V2 var result = new MultiSearchResult { MediaType = multiSearch.media_type, + Poster = multiSearch.poster_path }; - if (multiSearch.media_type.Equals("movie", StringComparison.InvariantCultureIgnoreCase)) + if (multiSearch.media_type.Equals("movie", StringComparison.InvariantCultureIgnoreCase) && filter.Movies) { if (multiSearch.release_date.HasValue() && DateTime.TryParse(multiSearch.release_date, out var releaseDate)) { @@ -76,7 +78,7 @@ namespace Ombi.Core.Engine.V2 } } - if (multiSearch.media_type.Equals("tv", StringComparison.InvariantCultureIgnoreCase)) + else if (multiSearch.media_type.Equals("tv", StringComparison.InvariantCultureIgnoreCase) && filter.TvShows) { if (multiSearch.release_date.HasValue() && DateTime.TryParse(multiSearch.release_date, out var releaseDate)) { @@ -87,11 +89,14 @@ namespace Ombi.Core.Engine.V2 result.Title = multiSearch.name; } } - - if (multiSearch.media_type.Equals("person", StringComparison.InvariantCultureIgnoreCase)) + else if (multiSearch.media_type.Equals("person", StringComparison.InvariantCultureIgnoreCase) && filter.People) { result.Title = multiSearch.name; } + else + { + continue; + } result.Id = multiSearch.id.ToString(); model.Add(result); diff --git a/src/Ombi.Core/Engine/V2/MusicSearchEngineV2.cs b/src/Ombi.Core/Engine/V2/MusicSearchEngineV2.cs index dd132a460..13256be0a 100644 --- a/src/Ombi.Core/Engine/V2/MusicSearchEngineV2.cs +++ b/src/Ombi.Core/Engine/V2/MusicSearchEngineV2.cs @@ -85,10 +85,10 @@ namespace Ombi.Core.Engine.V2 if (lidarrArtistTask != null) { var artistResult = await lidarrArtistTask; - info.Banner = artistResult.images?.FirstOrDefault(x => x.coverType.Equals("banner", StringComparison.InvariantCultureIgnoreCase))?.url.Replace("http", "https"); - info.Logo = artistResult.images?.FirstOrDefault(x => x.coverType.Equals("logo", StringComparison.InvariantCultureIgnoreCase))?.url.Replace("http", "https"); - info.Poster = artistResult.images?.FirstOrDefault(x => x.coverType.Equals("poster", StringComparison.InvariantCultureIgnoreCase))?.url.Replace("http", "https"); - info.FanArt = artistResult.images?.FirstOrDefault(x => x.coverType.Equals("fanart", StringComparison.InvariantCultureIgnoreCase))?.url.Replace("http", "https"); + info.Banner = artistResult.images?.FirstOrDefault(x => x.coverType.Equals("banner", StringComparison.InvariantCultureIgnoreCase))?.url.ToHttpsUrl(); + info.Logo = artistResult.images?.FirstOrDefault(x => x.coverType.Equals("logo", StringComparison.InvariantCultureIgnoreCase))?.url.ToHttpsUrl(); + info.Poster = artistResult.images?.FirstOrDefault(x => x.coverType.Equals("poster", StringComparison.InvariantCultureIgnoreCase))?.url.ToHttpsUrl(); + info.FanArt = artistResult.images?.FirstOrDefault(x => x.coverType.Equals("fanart", StringComparison.InvariantCultureIgnoreCase))?.url.ToHttpsUrl(); info.Overview = artistResult.overview; } @@ -108,16 +108,22 @@ namespace Ombi.Core.Engine.V2 { if ((cover.thumbnails?.small ?? string.Empty).HasValue()) { - return new AlbumArt(cover.thumbnails.small); + return new AlbumArt(cover.thumbnails.small.ToHttpsUrl()); } if ((cover.thumbnails?.large ?? string.Empty).HasValue()) { - return new AlbumArt(cover.thumbnails.large); + return new AlbumArt(cover.thumbnails.large.ToHttpsUrl()); } } return new AlbumArt(); } + + public async Task GetArtistInformationByRequestId(int requestId) + { + var request = await RequestService.MusicRequestRepository.Find(requestId); + return await GetArtistInformation(request.ForeignArtistId); + } private List GetBandMembers(Artist artist) { @@ -146,69 +152,69 @@ namespace Ombi.Core.Engine.V2 switch (relation.TypeId) { case RelationLinks.AllMusic: - links.AllMusic = relation.Url?.Resource; + links.AllMusic = relation.Url?.Resource.ToHttpsUrl(); break; case RelationLinks.BbcMusic: - links.BbcMusic = relation.Url?.Resource; + links.BbcMusic = relation.Url?.Resource.ToHttpsUrl(); break; case RelationLinks.Discogs: - links.Discogs = relation.Url?.Resource; + links.Discogs = relation.Url?.Resource.ToHttpsUrl(); break; case RelationLinks.Homepage: - links.HomePage = relation.Url?.Resource; + links.HomePage = relation.Url?.Resource.ToHttpsUrl(); break; case RelationLinks.Imdb: - links.Imdb = relation.Url?.Resource; + links.Imdb = relation.Url?.Resource.ToHttpsUrl(); break; case RelationLinks.LastFm: - links.LastFm = relation.Url?.Resource; + links.LastFm = relation.Url?.Resource.ToHttpsUrl(); break; case RelationLinks.MySpace: - links.MySpace = relation.Url?.Resource; + links.MySpace = relation.Url?.Resource.ToHttpsUrl(); break; case RelationLinks.OnlineCommunity: - links.OnlineCommunity = relation.Url?.Resource; + links.OnlineCommunity = relation.Url?.Resource.ToHttpsUrl(); break; case RelationLinks.SocialNetwork: if ((relation.Url?.Resource ?? string.Empty).Contains("twitter", CompareOptions.IgnoreCase)) { - links.Twitter = relation.Url?.Resource; + links.Twitter = relation.Url?.Resource.ToHttpsUrl(); } if ((relation.Url?.Resource ?? string.Empty).Contains("facebook", CompareOptions.IgnoreCase)) { - links.Facebook = relation.Url?.Resource; + links.Facebook = relation.Url?.Resource.ToHttpsUrl(); } if ((relation.Url?.Resource ?? string.Empty).Contains("instagram", CompareOptions.IgnoreCase)) { - links.Instagram = relation.Url?.Resource; + links.Instagram = relation.Url?.Resource.ToHttpsUrl(); } if ((relation.Url?.Resource ?? string.Empty).Contains("vk", CompareOptions.IgnoreCase)) { - links.Vk = relation.Url?.Resource; + links.Vk = relation.Url?.Resource.ToHttpsUrl(); } break; case RelationLinks.Streams: if ((relation.Url?.Resource ?? string.Empty).Contains("spotify", CompareOptions.IgnoreCase)) { - links.Spotify = relation.Url?.Resource; + links.Spotify = relation.Url?.Resource.ToHttpsUrl(); } if ((relation.Url?.Resource ?? string.Empty).Contains("deezer", CompareOptions.IgnoreCase)) { - links.Deezer = relation.Url?.Resource; + links.Deezer = relation.Url?.Resource.ToHttpsUrl(); } break; case RelationLinks.YouTube: - links.YouTube = relation.Url?.Resource; + links.YouTube = relation.Url?.Resource.ToHttpsUrl(); break; case RelationLinks.Download: if ((relation.Url?.Resource ?? string.Empty).Contains("google", CompareOptions.IgnoreCase)) { - links.Google = relation.Url?.Resource; + links.Google = relation.Url?.Resource.ToHttpsUrl(); } if ((relation.Url?.Resource ?? string.Empty).Contains("apple", CompareOptions.IgnoreCase)) { - links.Apple = relation.Url?.Resource; + links.Apple = relation.Url?.Resource.ToHttpsUrl(); } break; diff --git a/src/Ombi.Core/Engine/V2/TvSearchEngineV2.cs b/src/Ombi.Core/Engine/V2/TvSearchEngineV2.cs index aa8bcc9b3..dd2ce22aa 100644 --- a/src/Ombi.Core/Engine/V2/TvSearchEngineV2.cs +++ b/src/Ombi.Core/Engine/V2/TvSearchEngineV2.cs @@ -1,11 +1,9 @@ using System; using AutoMapper; - using System.Collections.Generic; using System.Linq; using System.Security.Principal; using System.Threading.Tasks; - using Ombi.Core.Rule.Interfaces; using Ombi.Store.Repository.Requests; using Ombi.Core.Authentication; @@ -18,64 +16,62 @@ using Ombi.Core.Models.Requests; using Ombi.Core.Models.Search; using Ombi.Core.Models.Search.V2; using Ombi.Core.Settings; -using Ombi.Core.Settings.Models.External; using Ombi.Store.Repository; using TraktSharp.Entities; +using Microsoft.EntityFrameworkCore; namespace Ombi.Core.Engine.V2 { public class TvSearchEngineV2 : BaseMediaEngine, ITVSearchEngineV2 { - public TvSearchEngineV2(IPrincipal identity, IRequestServiceMain service, ITvMazeApi tvMaze, IMapper mapper, ISettingsService plexSettings, - ISettingsService embySettings, IPlexContentRepository repo, IEmbyContentRepository embyRepo, ITraktApi trakt, IRuleEvaluator r, OmbiUserManager um, - ICacheService memCache, ISettingsService s, IRepository sub) + private readonly ITvMazeApi _tvMaze; + private readonly IMapper _mapper; + private readonly ITraktApi _traktApi; + + public TvSearchEngineV2(IPrincipal identity, IRequestServiceMain service, ITvMazeApi tvMaze, IMapper mapper, + ITraktApi trakt, IRuleEvaluator r, OmbiUserManager um, ICacheService memCache, ISettingsService s, + IRepository sub) : base(identity, service, r, um, memCache, s, sub) { - TvMazeApi = tvMaze; - Mapper = mapper; - PlexSettings = plexSettings; - EmbySettings = embySettings; - PlexContentRepo = repo; - TraktApi = trakt; - EmbyContentRepo = embyRepo; + _tvMaze = tvMaze; + _mapper = mapper; + _traktApi = trakt; } - private ITvMazeApi TvMazeApi { get; } - private IMapper Mapper { get; } - private ISettingsService PlexSettings { get; } - private ISettingsService EmbySettings { get; } - private IPlexContentRepository PlexContentRepo { get; } - private IEmbyContentRepository EmbyContentRepo { get; } - private ITraktApi TraktApi { get; } - + public async Task GetShowByRequest(int requestId) + { + var request = await RequestService.TvRequestService.Get().FirstOrDefaultAsync(x => x.Id == requestId); + return await GetShowInformation(request.TvDbId); + } + public async Task GetShowInformation(int tvdbid) { var tvdbshow = await Cache.GetOrAdd(nameof(GetShowInformation) + tvdbid, - async () => await TvMazeApi.ShowLookupByTheTvDbId(tvdbid), DateTime.Now.AddHours(12)); + async () => await _tvMaze.ShowLookupByTheTvDbId(tvdbid), DateTime.Now.AddHours(12)); if (tvdbshow == null) { return null; } var show = await Cache.GetOrAdd("GetTvFullInformation" + tvdbshow.id, - async () => await TvMazeApi.GetTvFullInformation(tvdbshow.id), DateTime.Now.AddHours(12)); + async () => await _tvMaze.GetTvFullInformation(tvdbshow.id), DateTime.Now.AddHours(12)); if (show == null) - { + { // We don't have enough information return null; } - + // Setup the task so we can get the data later on if we have a IMDBID - Task traktInfoTask = new Task(() => null); + Task traktInfoTask = null; if (show.externals?.imdb.HasValue() ?? false) { traktInfoTask = Cache.GetOrAdd("GetExtendedTvInfoTrakt" + show.externals?.imdb, - () => TraktApi.GetTvExtendedInfo(show.externals?.imdb), DateTime.Now.AddHours(12)); + () => _traktApi.GetTvExtendedInfo(show.externals?.imdb), DateTime.Now.AddHours(12)); } - var mapped = Mapper.Map(show); + var mapped = _mapper.Map(show); - foreach (var e in show._embedded.episodes) + foreach (var e in show._embedded?.episodes ?? new Api.TvMaze.Models.V2.Episode[0]) { var season = mapped.SeasonRequests.FirstOrDefault(x => x.SeasonNumber == e.season); if (season == null) @@ -87,7 +83,7 @@ namespace Ombi.Core.Engine.V2 }; newSeason.Episodes.Add(new EpisodeRequests { - Url = e.url, + Url = e.url.ToHttpsUrl(), Title = e.name, AirDate = e.airstamp, EpisodeNumber = e.number, @@ -100,7 +96,7 @@ namespace Ombi.Core.Engine.V2 // We already have the season, so just add the episode season.Episodes.Add(new EpisodeRequests { - Url = e.url, + Url = e.url.ToHttpsUrl(), Title = e.name, AirDate = e.airstamp, EpisodeNumber = e.number, @@ -122,14 +118,14 @@ namespace Ombi.Core.Engine.V2 private SearchTvShowViewModel ProcessResult(T tvMazeSearch) { - return Mapper.Map(tvMazeSearch); + return _mapper.Map(tvMazeSearch); } private async Task ProcessResult(SearchFullInfoTvShowViewModel item, Task showInfoTask) { item.TheTvDbId = item.Id.ToString(); - var oldModel = Mapper.Map(item); + var oldModel = _mapper.Map(item); await RunSearchRules(oldModel); item.Available = oldModel.Available; @@ -141,21 +137,39 @@ namespace Ombi.Core.Engine.V2 item.SeasonRequests = oldModel.SeasonRequests; item.RequestId = oldModel.RequestId; + if (!string.IsNullOrEmpty(item.Images?.Medium)) + { + item.Images.Medium = item.Images.Medium.ToHttpsUrl(); + } + + if (item.Cast?.Any() ?? false) + { + foreach (var cast in item.Cast) + { + if (!string.IsNullOrEmpty(cast.Character?.Image?.Medium)) + { + cast.Character.Image.Medium = cast.Character?.Image?.Medium.ToHttpsUrl(); + } + } + } + return await GetExtraInfo(showInfoTask, item); } private async Task GetExtraInfo(Task showInfoTask, SearchFullInfoTvShowViewModel model) { - var result = await showInfoTask; - if(result == null) + if (showInfoTask != null) { - return model; - } - - model.Trailer = result.Trailer?.AbsoluteUri ?? string.Empty; - model.Certification = result.Certification; - model.Homepage = result.Homepage?.AbsoluteUri ?? string.Empty; + var result = await showInfoTask; + if (result == null) + { + return model; + } + model.Trailer = result.Trailer?.AbsoluteUri.ToHttpsUrl() ?? string.Empty; + model.Certification = result.Certification; + model.Homepage = result.Homepage?.AbsoluteUri.ToHttpsUrl() ?? string.Empty; + } return model; } } diff --git a/src/Ombi.Core/Helpers/NotificationHelper.cs b/src/Ombi.Core/Helpers/NotificationHelper.cs index 1615b24f7..f94e8f0db 100644 --- a/src/Ombi.Core/Helpers/NotificationHelper.cs +++ b/src/Ombi.Core/Helpers/NotificationHelper.cs @@ -1,5 +1,6 @@ using System; -using Hangfire; +using System.Collections.Generic; +using System.Threading.Tasks; using Ombi.Core.Notifications; using Ombi.Helpers; using Ombi.Notifications.Models; @@ -9,13 +10,7 @@ namespace Ombi.Core { public class NotificationHelper : INotificationHelper { - public NotificationHelper(INotificationService service) - { - NotificationService = service; - } - private INotificationService NotificationService { get; } - - public void NewRequest(FullBaseRequest model) + public async Task NewRequest(FullBaseRequest model) { var notificationModel = new NotificationOptions { @@ -24,11 +19,13 @@ namespace Ombi.Core NotificationType = NotificationType.NewRequest, RequestType = model.RequestType }; - BackgroundJob.Enqueue(() => NotificationService.Publish(notificationModel)); - + await OmbiQuartz.TriggerJob(nameof(INotificationService), "Notifications", new Dictionary + { + {JobDataKeys.NotificationOptions, notificationModel} + }); } - public void NewRequest(ChildRequests model) + public async Task NewRequest(ChildRequests model) { var notificationModel = new NotificationOptions { @@ -36,11 +33,14 @@ namespace Ombi.Core DateTime = DateTime.Now, NotificationType = NotificationType.NewRequest, RequestType = model.RequestType - }; - BackgroundJob.Enqueue(() => NotificationService.Publish(notificationModel)); + }; + await OmbiQuartz.TriggerJob(nameof(INotificationService), "Notifications", new Dictionary + { + {JobDataKeys.NotificationOptions, notificationModel} + }); } - public void NewRequest(AlbumRequest model) + public async Task NewRequest(AlbumRequest model) { var notificationModel = new NotificationOptions { @@ -48,12 +48,15 @@ namespace Ombi.Core DateTime = DateTime.Now, NotificationType = NotificationType.NewRequest, RequestType = model.RequestType - }; - BackgroundJob.Enqueue(() => NotificationService.Publish(notificationModel)); + }; + await OmbiQuartz.TriggerJob(nameof(INotificationService), "Notifications", new Dictionary + { + {JobDataKeys.NotificationOptions, notificationModel} + }); } - public void Notify(MovieRequests model, NotificationType type) + public async Task Notify(MovieRequests model, NotificationType type) { var notificationModel = new NotificationOptions { @@ -63,10 +66,13 @@ namespace Ombi.Core RequestType = model.RequestType, Recipient = model.RequestedUser?.Email ?? string.Empty }; - - BackgroundJob.Enqueue(() => NotificationService.Publish(notificationModel)); + + await OmbiQuartz.TriggerJob(nameof(INotificationService), "Notifications", new Dictionary + { + {JobDataKeys.NotificationOptions, notificationModel} + }); } - public void Notify(ChildRequests model, NotificationType type) + public async Task Notify(ChildRequests model, NotificationType type) { var notificationModel = new NotificationOptions { @@ -76,10 +82,13 @@ namespace Ombi.Core RequestType = model.RequestType, Recipient = model.RequestedUser?.Email ?? string.Empty }; - BackgroundJob.Enqueue(() => NotificationService.Publish(notificationModel)); + await OmbiQuartz.TriggerJob(nameof(INotificationService), "Notifications", new Dictionary + { + {JobDataKeys.NotificationOptions, notificationModel} + }); } - public void Notify(AlbumRequest model, NotificationType type) + public async Task Notify(AlbumRequest model, NotificationType type) { var notificationModel = new NotificationOptions { @@ -90,7 +99,18 @@ namespace Ombi.Core Recipient = model.RequestedUser?.Email ?? string.Empty }; - BackgroundJob.Enqueue(() => NotificationService.Publish(notificationModel)); + await OmbiQuartz.TriggerJob(nameof(INotificationService), "Notifications", new Dictionary + { + {JobDataKeys.NotificationOptions, notificationModel} + }); + } + + public async Task Notify(NotificationOptions model) + { + await OmbiQuartz.TriggerJob(nameof(INotificationService), "Notifications", new Dictionary + { + {JobDataKeys.NotificationOptions, model} + }); } } } \ No newline at end of file diff --git a/src/Ombi.Core/Helpers/TvShowRequestBuilder.cs b/src/Ombi.Core/Helpers/TvShowRequestBuilder.cs index 56d227ad0..8ccbed8fb 100644 --- a/src/Ombi.Core/Helpers/TvShowRequestBuilder.cs +++ b/src/Ombi.Core/Helpers/TvShowRequestBuilder.cs @@ -55,7 +55,7 @@ namespace Ombi.Core.Helpers FirstAir = dt; // For some reason the poster path is always http - PosterPath = ShowInfo.image?.medium.Replace("http:", "https:"); + PosterPath = ShowInfo.image?.medium.ToHttpsUrl(); return this; } @@ -113,7 +113,7 @@ namespace Ombi.Core.Helpers EpisodeNumber = ep.number, AirDate = FormatDate(ep.airdate), Title = ep.name, - Url = ep.url + Url = ep.url.ToHttpsUrl() } }, SeasonNumber = ep.season, @@ -126,7 +126,7 @@ namespace Ombi.Core.Helpers EpisodeNumber = ep.number, AirDate = FormatDate(ep.airdate), Title = ep.name, - Url = ep.url + Url = ep.url.ToHttpsUrl() }); } } @@ -146,7 +146,7 @@ namespace Ombi.Core.Helpers EpisodeNumber = ep.number, AirDate = FormatDate(ep.airdate), Title = ep.name, - Url = ep.url + Url = ep.url.ToHttpsUrl() }); } } @@ -170,7 +170,7 @@ namespace Ombi.Core.Helpers EpisodeNumber = ep.number, AirDate = FormatDate(ep.airdate), Title = ep.name, - Url = ep.url + Url = ep.url.ToHttpsUrl() }); } } @@ -200,7 +200,7 @@ namespace Ombi.Core.Helpers EpisodeNumber = ep.number, AirDate = FormatDate(ep.airdate), Title = ep.name, - Url = ep.url, + Url = ep.url.ToHttpsUrl() }); } } @@ -216,7 +216,7 @@ namespace Ombi.Core.Helpers EpisodeNumber = ep.number, AirDate = FormatDate(ep.airdate), Title = ep.name, - Url = ep.url, + Url = ep.url.ToHttpsUrl() }); seasonRequests.Add(newRequest); } diff --git a/src/Ombi.Core/IImageService.cs b/src/Ombi.Core/IImageService.cs new file mode 100644 index 000000000..1493133e6 --- /dev/null +++ b/src/Ombi.Core/IImageService.cs @@ -0,0 +1,9 @@ +using System.Threading.Tasks; + +namespace Ombi.Core +{ + public interface IImageService + { + Task GetTvBackground(string tvdbId); + } +} \ No newline at end of file diff --git a/src/Ombi.Core/ImageService.cs b/src/Ombi.Core/ImageService.cs new file mode 100644 index 000000000..e22605441 --- /dev/null +++ b/src/Ombi.Core/ImageService.cs @@ -0,0 +1,47 @@ +using System; +using System.Linq; +using System.Threading.Tasks; +using Ombi.Api.FanartTv; +using Ombi.Helpers; +using Ombi.Store.Repository; + +namespace Ombi.Core +{ + public class ImageService : IImageService + { + private readonly IApplicationConfigRepository _configRepository; + private readonly IFanartTvApi _fanartTvApi; + private readonly ICacheService _cache; + + public ImageService(IApplicationConfigRepository configRepository, IFanartTvApi fanartTvApi, + ICacheService cache) + { + _configRepository = configRepository; + _fanartTvApi = fanartTvApi; + _cache = cache; + } + + public async Task GetTvBackground(string tvdbId) + { + var key = await _cache.GetOrAdd(CacheKeys.FanartTv, async () => await _configRepository.GetAsync(Store.Entities.ConfigurationTypes.FanartTv), DateTime.Now.AddDays(1)); + var images = await _cache.GetOrAdd($"{CacheKeys.FanartTv}tv{tvdbId}", async () => await _fanartTvApi.GetTvImages(int.Parse(tvdbId), key.Value), DateTime.Now.AddDays(1)); + + if (images == null) + { + return string.Empty; + } + + if (images.showbackground?.Any() ?? false) + { + var enImage = images.showbackground.Where(x => x.lang == "en").OrderByDescending(x => x.likes).Select(x => x.url).FirstOrDefault(); + if (enImage == null) + { + return images.showbackground.OrderByDescending(x => x.likes).Select(x => x.url).FirstOrDefault(); + } + return enImage; + } + + return string.Empty; + } + } +} \ No newline at end of file diff --git a/src/Ombi/Models/Identity/IdentityResult.cs b/src/Ombi.Core/Models/IdentityResult.cs similarity index 100% rename from src/Ombi/Models/Identity/IdentityResult.cs rename to src/Ombi.Core/Models/IdentityResult.cs diff --git a/src/Ombi.Core/Models/Requests/MovieAdvancedOptions.cs b/src/Ombi.Core/Models/Requests/MovieAdvancedOptions.cs index 7ac2f2bd6..02ce0a6bd 100644 --- a/src/Ombi.Core/Models/Requests/MovieAdvancedOptions.cs +++ b/src/Ombi.Core/Models/Requests/MovieAdvancedOptions.cs @@ -1,6 +1,6 @@ namespace Ombi.Core.Models.Requests { - public class MovieAdvancedOptions + public class MediaAdvancedOptions { public int RequestId { get; set; } public int RootPathOverride { get; set; } diff --git a/src/Ombi.Core/Models/Requests/RequestStatus.cs b/src/Ombi.Core/Models/Requests/RequestStatus.cs new file mode 100644 index 000000000..6810b139d --- /dev/null +++ b/src/Ombi.Core/Models/Requests/RequestStatus.cs @@ -0,0 +1,10 @@ +namespace Ombi.Core.Models.Requests +{ + public enum RequestStatus + { + PendingApproval, + ProcessingRequest, + Available, + Denied + } +} diff --git a/src/Ombi.Core/Models/Search/SearchTvShowViewModel.cs b/src/Ombi.Core/Models/Search/SearchTvShowViewModel.cs index c421af45f..dfd038a91 100644 --- a/src/Ombi.Core/Models/Search/SearchTvShowViewModel.cs +++ b/src/Ombi.Core/Models/Search/SearchTvShowViewModel.cs @@ -57,5 +57,10 @@ namespace Ombi.Core.Models.Search // We only have some episodes public bool PartlyAvailable { get; set; } public override RequestType Type => RequestType.TvShow; + + /// + /// Only set on the images call + /// + public string BackdropPath { get; set; } } } \ No newline at end of file diff --git a/src/Ombi.Core/Models/Search/SearchViewModel.cs b/src/Ombi.Core/Models/Search/SearchViewModel.cs index c59b5284d..2f951c97e 100644 --- a/src/Ombi.Core/Models/Search/SearchViewModel.cs +++ b/src/Ombi.Core/Models/Search/SearchViewModel.cs @@ -7,6 +7,8 @@ namespace Ombi.Core.Models.Search { public int Id { get; set; } public bool Approved { get; set; } + public bool? Denied { get; set; } + public string DeniedReason { get; set; } public bool Requested { get; set; } public int RequestId { get; set; } public bool Available { get; set; } diff --git a/src/Ombi.Core/Models/Search/V2/MovieCollectionsViewModel.cs b/src/Ombi.Core/Models/Search/V2/MovieCollectionsViewModel.cs index ace5ce76c..47870c18b 100644 --- a/src/Ombi.Core/Models/Search/V2/MovieCollectionsViewModel.cs +++ b/src/Ombi.Core/Models/Search/V2/MovieCollectionsViewModel.cs @@ -13,7 +13,6 @@ namespace Ombi.Core.Models.Search.V2 public class MovieCollection : SearchViewModel { - public int Id { get; set; } public string Overview { get; set; } public string PosterPath { get; set; } public string Title { get; set; } diff --git a/src/Ombi.Core/Models/Search/V2/MultiSearchFilter.cs b/src/Ombi.Core/Models/Search/V2/MultiSearchFilter.cs new file mode 100644 index 000000000..8e12f1d24 --- /dev/null +++ b/src/Ombi.Core/Models/Search/V2/MultiSearchFilter.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Ombi.Core.Models.Search.V2 +{ + public class MultiSearchFilter + { + public bool Movies { get; set; } + public bool TvShows { get; set; } + public bool Music { get; set; } + public bool People { get; set; } + } +} diff --git a/src/Ombi.Core/Models/Search/V2/MultiSearchResult.cs b/src/Ombi.Core/Models/Search/V2/MultiSearchResult.cs index e514095c9..8346608b5 100644 --- a/src/Ombi.Core/Models/Search/V2/MultiSearchResult.cs +++ b/src/Ombi.Core/Models/Search/V2/MultiSearchResult.cs @@ -5,5 +5,6 @@ public string Id { get; set; } public string MediaType { get; set; } public string Title { get; set; } + public string Poster { get; set; } } } \ No newline at end of file diff --git a/src/Ombi.Core/Models/UI/TwilioSettingsViewModel.cs b/src/Ombi.Core/Models/UI/TwilioSettingsViewModel.cs new file mode 100644 index 000000000..5e19535ad --- /dev/null +++ b/src/Ombi.Core/Models/UI/TwilioSettingsViewModel.cs @@ -0,0 +1,27 @@ +using System.Collections.Generic; +using Ombi.Settings.Settings.Models.Notifications; +using Ombi.Store.Entities; + +namespace Ombi.Core.Models.UI +{ + /// + /// The view model for the notification settings page + /// + /// + public class TwilioSettingsViewModel + { + public int Id { get; set; } + public WhatsAppSettingsViewModel WhatsAppSettings { get; set; } = new WhatsAppSettingsViewModel(); + } + + public class WhatsAppSettingsViewModel : WhatsAppSettings + { + /// + /// Gets or sets the notification templates. + /// + /// + /// The notification templates. + /// + public List NotificationTemplates { get; set; } + } +} diff --git a/src/Ombi.Core/Models/UI/UserViewModel.cs b/src/Ombi.Core/Models/UI/UserViewModel.cs index ca40c2ec5..e74e5037d 100644 --- a/src/Ombi.Core/Models/UI/UserViewModel.cs +++ b/src/Ombi.Core/Models/UI/UserViewModel.cs @@ -13,6 +13,7 @@ namespace Ombi.Core.Models.UI public string EmailAddress { get; set; } public string Password { get; set; } public DateTime? LastLoggedIn { get; set; } + public string Language { get; set; } public bool HasLoggedIn { get; set; } public UserType UserType { get; set; } public int MovieRequestLimit { get; set; } diff --git a/src/Ombi.Core/Models/UI/WebhookNotificationViewModel.cs b/src/Ombi.Core/Models/UI/WebhookNotificationViewModel.cs new file mode 100644 index 000000000..533de1d6b --- /dev/null +++ b/src/Ombi.Core/Models/UI/WebhookNotificationViewModel.cs @@ -0,0 +1,15 @@ + +using System.Collections.Generic; +using Ombi.Settings.Settings.Models.Notifications; +using Ombi.Store.Entities; + +namespace Ombi.Core.Models.UI +{ + /// + /// The view model for the notification settings page + /// + /// + public class WebhookNotificationViewModel : WebhookSettings + { + } +} diff --git a/src/Ombi.Core/Ombi.Core.csproj b/src/Ombi.Core/Ombi.Core.csproj index b944cdd73..8acbaceb0 100644 --- a/src/Ombi.Core/Ombi.Core.csproj +++ b/src/Ombi.Core/Ombi.Core.csproj @@ -1,28 +1,30 @@  - netstandard2.1 + net5.0 3.0.0.0 3.0.0.0 + 8.0 - - - - - + + + + - + + + @@ -38,10 +40,4 @@ - - - ..\..\..\..\Program Files\dotnet\sdk\NuGetFallbackFolder\microsoft.aspnetcore.signalr.core\1.1.0\lib\netstandard2.0\Microsoft.AspNetCore.SignalR.Core.dll - - - \ No newline at end of file diff --git a/src/Ombi.Core/Rule/Rules/Request/AutoApproveRule.cs b/src/Ombi.Core/Rule/Rules/Request/AutoApproveRule.cs index 6b528e806..f427434f0 100644 --- a/src/Ombi.Core/Rule/Rules/Request/AutoApproveRule.cs +++ b/src/Ombi.Core/Rule/Rules/Request/AutoApproveRule.cs @@ -24,7 +24,8 @@ namespace Ombi.Core.Rule.Rules.Request public async Task Execute(BaseRequest obj) { - var user = await _manager.Users.FirstOrDefaultAsync(x => x.UserName.Equals(User.Identity.Name, StringComparison.InvariantCultureIgnoreCase)); + var username = User.Identity.Name.ToUpper(); + var user = await _manager.Users.FirstOrDefaultAsync(x => x.NormalizedUserName == username); if (await _manager.IsInRoleAsync(user, OmbiRoles.Admin) || user.IsSystemUser) { obj.Approved = true; diff --git a/src/Ombi.Core/Rule/Rules/Request/CanRequestRule.cs b/src/Ombi.Core/Rule/Rules/Request/CanRequestRule.cs index 213aa94c8..23ad86dc0 100644 --- a/src/Ombi.Core/Rule/Rules/Request/CanRequestRule.cs +++ b/src/Ombi.Core/Rule/Rules/Request/CanRequestRule.cs @@ -25,7 +25,8 @@ namespace Ombi.Core.Rule.Rules.Request public async Task Execute(BaseRequest obj) { - var user = await _manager.Users.FirstOrDefaultAsync(x => x.UserName.Equals(User.Identity.Name, StringComparison.InvariantCultureIgnoreCase)); + var username = User.Identity.Name.ToUpper(); + var user = await _manager.Users.FirstOrDefaultAsync(x => x.NormalizedUserName == username); if (await _manager.IsInRoleAsync(user, OmbiRoles.Admin) || user.IsSystemUser) return Success(); diff --git a/src/Ombi.Core/Rule/Rules/Request/ExistingMovieRequestRule.cs b/src/Ombi.Core/Rule/Rules/Request/ExistingMovieRequestRule.cs index bc580e9ea..15861ca27 100644 --- a/src/Ombi.Core/Rule/Rules/Request/ExistingMovieRequestRule.cs +++ b/src/Ombi.Core/Rule/Rules/Request/ExistingMovieRequestRule.cs @@ -41,7 +41,7 @@ namespace Ombi.Core.Rule.Rules.Request { // Let's check imdbid existing = await movieRequests.FirstOrDefaultAsync(x => - x.ImdbId.Equals(movie.ImdbId, StringComparison.CurrentCultureIgnoreCase)); + x.ImdbId == movie.ImdbId); if (existing != null) { found = true; diff --git a/src/Ombi.Core/Rule/Rules/Request/ExistingPlexRequestRule.cs b/src/Ombi.Core/Rule/Rules/Request/ExistingPlexRequestRule.cs index 0d887063e..9d4ab30ef 100644 --- a/src/Ombi.Core/Rule/Rules/Request/ExistingPlexRequestRule.cs +++ b/src/Ombi.Core/Rule/Rules/Request/ExistingPlexRequestRule.cs @@ -29,16 +29,16 @@ namespace Ombi.Core.Rule.Rules.Request if (obj.RequestType == RequestType.TvShow) { var tvRequest = (ChildRequests) obj; - - var tvContent = _plexContent.GetAll().Where(x => x.Type == PlexMediaTypeEntity.Show); + + var tvContent = _plexContent.GetAll().Include(x => x.Episodes).Where(x => x.Type == PlexMediaTypeEntity.Show); // We need to do a check on the TVDBId - var anyTvDbMatches = await tvContent.Include(x => x.Episodes).FirstOrDefaultAsync(x => x.HasTvDb && x.TvDbId.Equals(tvRequest.Id.ToString(), StringComparison.InvariantCultureIgnoreCase)); // the Id on the child is the tvdbid at this point + var anyTvDbMatches = await tvContent.FirstOrDefaultAsync(x => x.TvDbId.Length > 0 && x.TvDbId == tvRequest.Id.ToString()); // the Id on the child is the tvdbid at this point if (anyTvDbMatches == null) { // So we do not have a TVDB Id, that really sucks. // Let's try and match on the title and year of the show - var titleAndYearMatch = await tvContent.Include(x=> x.Episodes).FirstOrDefaultAsync(x => - x.Title.Equals(tvRequest.Title, StringComparison.InvariantCultureIgnoreCase) + var titleAndYearMatch = await tvContent.FirstOrDefaultAsync(x => + x.Title == tvRequest.Title && x.ReleaseYear == tvRequest.ReleaseYear.Year.ToString()); if (titleAndYearMatch != null) { diff --git a/src/Ombi.Core/Rule/Rules/Search/EmbyAvailabilityRule.cs b/src/Ombi.Core/Rule/Rules/Search/EmbyAvailabilityRule.cs index 343681e29..75b6633bb 100644 --- a/src/Ombi.Core/Rule/Rules/Search/EmbyAvailabilityRule.cs +++ b/src/Ombi.Core/Rule/Rules/Search/EmbyAvailabilityRule.cs @@ -70,11 +70,11 @@ namespace Ombi.Core.Rule.Rules.Search var server = s.Servers.FirstOrDefault(x => x.ServerHostname != null); if ((server?.ServerHostname ?? string.Empty).HasValue()) { - obj.EmbyUrl = EmbyHelper.GetEmbyMediaUrl(item.EmbyId, server?.ServerHostname, s.IsJellyfin); + obj.EmbyUrl = EmbyHelper.GetEmbyMediaUrl(item.EmbyId, server?.ServerId, server?.ServerHostname, s.IsJellyfin); } else { - obj.EmbyUrl = EmbyHelper.GetEmbyMediaUrl(item.EmbyId, null, s.IsJellyfin); + obj.EmbyUrl = EmbyHelper.GetEmbyMediaUrl(item.EmbyId, server?.ServerId, null, s.IsJellyfin); } } diff --git a/src/Ombi.Core/Rule/Rules/Search/ExistingRule.cs b/src/Ombi.Core/Rule/Rules/Search/ExistingRule.cs index 853ad399c..45e74c3af 100644 --- a/src/Ombi.Core/Rule/Rules/Search/ExistingRule.cs +++ b/src/Ombi.Core/Rule/Rules/Search/ExistingRule.cs @@ -34,6 +34,8 @@ namespace Ombi.Core.Rule.Rules.Search obj.Requested = true; obj.RequestId = movieRequests.Id; obj.Approved = movieRequests.Approved; + obj.Denied = movieRequests.Denied ?? false; + obj.DeniedReason = movieRequests.DeniedReason; obj.Available = movieRequests.Available; return Success(); @@ -49,6 +51,7 @@ namespace Ombi.Core.Rule.Rules.Search request.RequestId = tvRequests.Id; request.Requested = true; request.Approved = tvRequests.ChildRequests.Any(x => x.Approved); + request.Denied = tvRequests.ChildRequests.Any(x => x.Denied ?? false); // Let's modify the seasonsrequested to reflect what we have requested... foreach (var season in request.SeasonRequests) @@ -96,7 +99,9 @@ namespace Ombi.Core.Rule.Rules.Search if (albumRequest != null) // Do we already have a request for this? { obj.Requested = true; - obj.RequestId = albumRequest.Id; + obj.RequestId = albumRequest.Id; + obj.Denied = albumRequest.Denied; + obj.DeniedReason = albumRequest.DeniedReason; obj.Approved = albumRequest.Approved; obj.Available = albumRequest.Available; diff --git a/src/Ombi.Core/Rule/Rules/Search/LidarrAlbumCacheRule.cs b/src/Ombi.Core/Rule/Rules/Search/LidarrAlbumCacheRule.cs index ac01a2dfa..3ca57d635 100644 --- a/src/Ombi.Core/Rule/Rules/Search/LidarrAlbumCacheRule.cs +++ b/src/Ombi.Core/Rule/Rules/Search/LidarrAlbumCacheRule.cs @@ -24,7 +24,7 @@ namespace Ombi.Core.Rule.Rules.Search { // Check if it's in Lidarr var result = _db.GetAll().FirstOrDefault(x => - x.ForeignAlbumId.Equals(obj.ForeignAlbumId, StringComparison.InvariantCultureIgnoreCase)); + x.ForeignAlbumId == obj.ForeignAlbumId); if (result != null) { obj.PercentOfTracks = result.PercentOfTracks; @@ -36,7 +36,7 @@ namespace Ombi.Core.Rule.Rules.Search { // Check if it's in Lidarr var result = _db.GetAll().FirstOrDefault(x => - x.ForeignAlbumId.Equals(release.Id, StringComparison.InvariantCultureIgnoreCase)); + x.ForeignAlbumId == release.Id); if (result != null) { release.PercentOfTracks = result.PercentOfTracks; diff --git a/src/Ombi.Core/Rule/Rules/Search/LidarrArtistCacheRule.cs b/src/Ombi.Core/Rule/Rules/Search/LidarrArtistCacheRule.cs index d9667d66b..a254ea2d3 100644 --- a/src/Ombi.Core/Rule/Rules/Search/LidarrArtistCacheRule.cs +++ b/src/Ombi.Core/Rule/Rules/Search/LidarrArtistCacheRule.cs @@ -21,7 +21,7 @@ namespace Ombi.Core.Rule.Rules.Search { var obj = (SearchArtistViewModel) objec; // Check if it's in Lidarr - var result = _db.GetAll().FirstOrDefault(x => x.ForeignArtistId.Equals(obj.ForignArtistId, StringComparison.InvariantCultureIgnoreCase)); + var result = _db.GetAll().FirstOrDefault(x => x.ForeignArtistId == obj.ForignArtistId); if (result != null) { obj.Monitored = true; // It's in Lidarr so it's monitored diff --git a/src/Ombi.Core/Senders/INotificationHelper.cs b/src/Ombi.Core/Senders/INotificationHelper.cs index 4ba47d761..70947a57e 100644 --- a/src/Ombi.Core/Senders/INotificationHelper.cs +++ b/src/Ombi.Core/Senders/INotificationHelper.cs @@ -1,16 +1,19 @@ -using Ombi.Core.Models.Requests; +using System.Threading.Tasks; +using Ombi.Core.Models.Requests; using Ombi.Helpers; +using Ombi.Notifications.Models; using Ombi.Store.Entities.Requests; namespace Ombi.Core { public interface INotificationHelper { - void NewRequest(FullBaseRequest model); - void NewRequest(ChildRequests model); - void NewRequest(AlbumRequest model); - void Notify(MovieRequests model, NotificationType type); - void Notify(ChildRequests model, NotificationType type); - void Notify(AlbumRequest model, NotificationType type); + Task NewRequest(FullBaseRequest model); + Task NewRequest(ChildRequests model); + Task NewRequest(AlbumRequest model); + Task Notify(MovieRequests model, NotificationType type); + Task Notify(ChildRequests model, NotificationType type); + Task Notify(AlbumRequest model, NotificationType type); + Task Notify(NotificationOptions model); } } \ No newline at end of file diff --git a/src/Ombi.Core/Senders/MovieSender.cs b/src/Ombi.Core/Senders/MovieSender.cs index 567df43b5..33d6afd25 100644 --- a/src/Ombi.Core/Senders/MovieSender.cs +++ b/src/Ombi.Core/Senders/MovieSender.cs @@ -13,6 +13,8 @@ using Ombi.Store.Entities.Requests; using Ombi.Api.DogNzb; using Ombi.Store.Entities; using Ombi.Store.Repository; +using System.Collections.Generic; +using Ombi.Api.Radarr.Models; namespace Ombi.Core.Senders { @@ -20,44 +22,47 @@ namespace Ombi.Core.Senders { public MovieSender(ISettingsService radarrSettings, IRadarrApi api, ILogger log, ISettingsService dogSettings, IDogNzbApi dogApi, ISettingsService cpSettings, - ICouchPotatoApi cpApi, IRepository userProfiles, IRepository requestQueue, INotificationHelper notify) + ICouchPotatoApi cpApi, IRepository userProfiles, IRepository requestQueue, INotificationHelper notify, + IRadarrV3Api radarrV3Api) { - RadarrSettings = radarrSettings; - RadarrApi = api; - Log = log; - DogNzbSettings = dogSettings; - DogNzbApi = dogApi; - CouchPotatoSettings = cpSettings; - CouchPotatoApi = cpApi; + _radarrSettings = radarrSettings; + _radarrV2Api = api; + _log = log; + _dogNzbSettings = dogSettings; + _dogNzbApi = dogApi; + _couchPotatoSettings = cpSettings; + _couchPotatoApi = cpApi; _userProfiles = userProfiles; _requestQueuRepository = requestQueue; _notificationHelper = notify; + _radarrV3Api = radarrV3Api; } - private ISettingsService RadarrSettings { get; } - private IRadarrApi RadarrApi { get; } - private ILogger Log { get; } - private IDogNzbApi DogNzbApi { get; } - private ISettingsService DogNzbSettings { get; } - private ISettingsService CouchPotatoSettings { get; } - private ICouchPotatoApi CouchPotatoApi { get; } + private readonly ISettingsService _radarrSettings; + private readonly IRadarrApi _radarrV2Api; + private readonly ILogger _log; + private readonly IDogNzbApi _dogNzbApi; + private readonly ISettingsService _dogNzbSettings; + private readonly ISettingsService _couchPotatoSettings; + private readonly ICouchPotatoApi _couchPotatoApi; private readonly IRepository _userProfiles; private readonly IRepository _requestQueuRepository; private readonly INotificationHelper _notificationHelper; + private readonly IRadarrV3Api _radarrV3Api; public async Task Send(MovieRequests model) { try { - var cpSettings = await CouchPotatoSettings.GetSettingsAsync(); + var cpSettings = await _couchPotatoSettings.GetSettingsAsync(); //var watcherSettings = await WatcherSettings.GetSettingsAsync(); - var radarrSettings = await RadarrSettings.GetSettingsAsync(); + var radarrSettings = await _radarrSettings.GetSettingsAsync(); if (radarrSettings.Enabled) { return await SendToRadarr(model, radarrSettings); } - var dogSettings = await DogNzbSettings.GetSettingsAsync(); + var dogSettings = await _dogNzbSettings.GetSettingsAsync(); if (dogSettings.Enabled) { await SendToDogNzb(model, dogSettings); @@ -75,7 +80,7 @@ namespace Ombi.Core.Senders } catch (Exception e) { - Log.LogError(e, "Error when sending movie to DVR app, added to the request queue"); + _log.LogError(e, "Error when sending movie to DVR app, added to the request queue"); // Check if already in request quee var existingQueue = await _requestQueuRepository.FirstOrDefaultAsync(x => x.RequestId == model.Id); @@ -95,7 +100,7 @@ namespace Ombi.Core.Senders Type = RequestType.Movie, RetryCount = 0 }); - _notificationHelper.Notify(model, NotificationType.ItemAddedToFaultQueue); + await _notificationHelper.Notify(model, NotificationType.ItemAddedToFaultQueue); } } @@ -108,19 +113,19 @@ namespace Ombi.Core.Senders private async Task SendToCp(FullBaseRequest model, CouchPotatoSettings cpSettings, string cpSettingsDefaultProfileId) { - var result = await CouchPotatoApi.AddMovie(model.ImdbId, cpSettings.ApiKey, model.Title, cpSettings.FullUri, cpSettingsDefaultProfileId); + var result = await _couchPotatoApi.AddMovie(model.ImdbId, cpSettings.ApiKey, model.Title, cpSettings.FullUri, cpSettingsDefaultProfileId); return new SenderResult { Success = result, Sent = true }; } private async Task SendToDogNzb(FullBaseRequest model, DogNzbSettings settings) { var id = model.ImdbId; - return await DogNzbApi.AddMovie(settings.ApiKey, id); + return await _dogNzbApi.AddMovie(settings.ApiKey, id); } private async Task SendToRadarr(MovieRequests model, RadarrSettings settings) { - + var v3 = settings.V3; var qualityToUse = int.Parse(settings.DefaultQualityProfile); var rootFolderPath = settings.DefaultRootPath; @@ -129,7 +134,7 @@ namespace Ombi.Core.Senders if (profiles != null) { if (profiles.RadarrRootPath > 0) - { + { var tempPath = await RadarrRootPath(profiles.RadarrRootPath, settings); if (tempPath.HasValue()) { @@ -152,18 +157,35 @@ namespace Ombi.Core.Senders rootFolderPath = await RadarrRootPath(model.RootPathOverride, settings); } + List movies; // Check if the movie already exists? Since it could be unmonitored - var movies = await RadarrApi.GetMovies(settings.ApiKey, settings.FullUri); + if (settings.V3) + { + movies = await _radarrV3Api.GetMovies(settings.ApiKey, settings.FullUri); + } + else + { + movies = await _radarrV2Api.GetMovies(settings.ApiKey, settings.FullUri); + } var existingMovie = movies.FirstOrDefault(x => x.tmdbId == model.TheMovieDbId); if (existingMovie == null) { - var result = await RadarrApi.AddMovie(model.TheMovieDbId, model.Title, model.ReleaseDate.Year, - qualityToUse, rootFolderPath, settings.ApiKey, settings.FullUri, !settings.AddOnly, - settings.MinimumAvailability); - + RadarrAddMovie result; + if (v3) + { + result = await _radarrV3Api.AddMovie(model.TheMovieDbId, model.Title, model.ReleaseDate.Year, + qualityToUse, rootFolderPath, settings.ApiKey, settings.FullUri, !settings.AddOnly, + settings.MinimumAvailability); + } + else + { + result = await _radarrV2Api.AddMovie(model.TheMovieDbId, model.Title, model.ReleaseDate.Year, + qualityToUse, rootFolderPath, settings.ApiKey, settings.FullUri, !settings.AddOnly, + settings.MinimumAvailability); + } if (!string.IsNullOrEmpty(result.Error?.message)) { - Log.LogError(LoggingEvents.RadarrCacher, result.Error.message); + _log.LogError(LoggingEvents.RadarrCacher, result.Error.message); return new SenderResult { Success = false, Message = result.Error.message, Sent = false }; } if (!string.IsNullOrEmpty(result.title)) @@ -177,11 +199,23 @@ namespace Ombi.Core.Senders { // let's set it to monitored and search for it existingMovie.monitored = true; - await RadarrApi.UpdateMovie(existingMovie, settings.ApiKey, settings.FullUri); - // Search for it - if (!settings.AddOnly) + if (v3) { - await RadarrApi.MovieSearch(new[] { existingMovie.id }, settings.ApiKey, settings.FullUri); + await _radarrV3Api.UpdateMovie(existingMovie, settings.ApiKey, settings.FullUri); + // Search for it + if (!settings.AddOnly) + { + await _radarrV3Api.MovieSearch(new[] { existingMovie.id }, settings.ApiKey, settings.FullUri); + } + } + else + { + await _radarrV2Api.UpdateMovie(existingMovie, settings.ApiKey, settings.FullUri); + // Search for it + if (!settings.AddOnly) + { + await _radarrV2Api.MovieSearch(new[] { existingMovie.id }, settings.ApiKey, settings.FullUri); + } } return new SenderResult { Success = true, Sent = true }; @@ -192,9 +226,18 @@ namespace Ombi.Core.Senders private async Task RadarrRootPath(int overrideId, RadarrSettings settings) { - var paths = await RadarrApi.GetRootFolders(settings.ApiKey, settings.FullUri); - var selectedPath = paths.FirstOrDefault(x => x.id == overrideId); - return selectedPath?.path ?? String.Empty; + if (settings.V3) + { + var paths = await _radarrV3Api.GetRootFolders(settings.ApiKey, settings.FullUri); + var selectedPath = paths.FirstOrDefault(x => x.id == overrideId); + return selectedPath?.path ?? string.Empty; + } + else + { + var paths = await _radarrV2Api.GetRootFolders(settings.ApiKey, settings.FullUri); + var selectedPath = paths.FirstOrDefault(x => x.id == overrideId); + return selectedPath?.path ?? string.Empty; + } } } } \ No newline at end of file diff --git a/src/Ombi.Core/Senders/MusicSender.cs b/src/Ombi.Core/Senders/MusicSender.cs index 04544c6be..6390578dd 100644 --- a/src/Ombi.Core/Senders/MusicSender.cs +++ b/src/Ombi.Core/Senders/MusicSender.cs @@ -65,7 +65,7 @@ namespace Ombi.Core.Senders Type = RequestType.Album, RetryCount = 0 }); - _notificationHelper.Notify(model, NotificationType.ItemAddedToFaultQueue); + await _notificationHelper.Notify(model, NotificationType.ItemAddedToFaultQueue); } } @@ -100,8 +100,8 @@ namespace Ombi.Core.Senders addOptions = new Addoptions { monitored = true, + monitor = MonitorTypes.None, searchForMissingAlbums = false, - selectedOption = 6, // None AlbumsToMonitor = new[] {model.ForeignAlbumId} }, added = DateTime.Now, @@ -126,7 +126,7 @@ namespace Ombi.Core.Senders var album = await _lidarrApi.GetAllAlbumsByArtistId(result.id, settings.ApiKey, settings.FullUri); var albumToSearch = album.FirstOrDefault(x => - x.foreignAlbumId.Equals(model.ForeignAlbumId, StringComparison.InvariantCultureIgnoreCase)); + x.foreignAlbumId == model.ForeignAlbumId); var maxRetryCount = 10; // 5 seconds var currentRetry = 0; while (albumToSearch != null) @@ -139,7 +139,7 @@ namespace Ombi.Core.Senders await Task.Delay(500); album = await _lidarrApi.GetAllAlbumsByArtistId(result.id, settings.ApiKey, settings.FullUri); albumToSearch = album.FirstOrDefault(x => - x.foreignAlbumId.Equals(model.ForeignAlbumId, StringComparison.InvariantCultureIgnoreCase)); + x.foreignAlbumId == model.ForeignAlbumId); } @@ -165,7 +165,7 @@ namespace Ombi.Core.Senders // Get the album id var albums = await _lidarrApi.GetAllAlbumsByArtistId(artist.id, settings.ApiKey, settings.FullUri); var album = albums.FirstOrDefault(x => - x.foreignAlbumId.Equals(model.ForeignAlbumId, StringComparison.InvariantCultureIgnoreCase)); + x.foreignAlbumId == model.ForeignAlbumId); var maxRetryCount = 10; // 5 seconds var currentRetry = 0; while (!albums.Any() || album == null) @@ -178,7 +178,7 @@ namespace Ombi.Core.Senders await Task.Delay(500); albums = await _lidarrApi.GetAllAlbumsByArtistId(artist.id, settings.ApiKey, settings.FullUri); album = albums.FirstOrDefault(x => - x.foreignAlbumId.Equals(model.ForeignAlbumId, StringComparison.InvariantCultureIgnoreCase)); + x.foreignAlbumId == model.ForeignAlbumId); } // Get the album we want. diff --git a/src/Ombi.Core/Senders/TvSender.cs b/src/Ombi.Core/Senders/TvSender.cs index 3a3e34745..91c38428a 100644 --- a/src/Ombi.Core/Senders/TvSender.cs +++ b/src/Ombi.Core/Senders/TvSender.cs @@ -16,7 +16,6 @@ using Ombi.Settings.Settings.Models.External; using Ombi.Store.Entities; using Ombi.Store.Entities.Requests; using Ombi.Store.Repository; -using Remotion.Linq.Parsing.Structure.IntermediateModel; namespace Ombi.Core.Senders { @@ -128,7 +127,7 @@ namespace Ombi.Core.Senders Type = RequestType.TvShow, RetryCount = 0 }); - _notificationHelper.Notify(model, NotificationType.ItemAddedToFaultQueue); + await _notificationHelper.Notify(model, NotificationType.ItemAddedToFaultQueue); } } diff --git a/src/Ombi.DependencyInjection/IocExtensions.cs b/src/Ombi.DependencyInjection/IocExtensions.cs index 4620f404f..76f4879ce 100644 --- a/src/Ombi.DependencyInjection/IocExtensions.cs +++ b/src/Ombi.DependencyInjection/IocExtensions.cs @@ -1,8 +1,6 @@ using System.Diagnostics.CodeAnalysis; using System.Security.Principal; -using Hangfire; using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.SignalR; using Microsoft.Extensions.DependencyInjection; using Ombi.Api.Discord; @@ -35,6 +33,7 @@ using Ombi.Api.FanartTv; using Ombi.Api.Github; using Ombi.Api.Gotify; using Ombi.Api.GroupMe; +using Ombi.Api.Webhook; using Ombi.Api.Lidarr; using Ombi.Api.Mattermost; using Ombi.Api.Notifications; @@ -62,9 +61,10 @@ using Ombi.Schedule.Jobs.Lidarr; using Ombi.Schedule.Jobs.Plex.Interfaces; using Ombi.Schedule.Jobs.SickRage; using Ombi.Schedule.Processor; -using Ombi.Store.Entities; using Quartz.Spi; using Ombi.Api.MusicBrainz; +using Ombi.Api.Twilio; +using Ombi.Api.CloudService; namespace Ombi.DependencyInjection { @@ -101,6 +101,7 @@ namespace Ombi.DependencyInjection services.AddTransient(); services.AddTransient(); services.AddTransient(); + services.AddTransient(); } public static void RegisterEnginesV2(this IServiceCollection services) @@ -131,12 +132,14 @@ namespace Ombi.DependencyInjection services.AddTransient(); services.AddTransient(); services.AddTransient(); + services.AddTransient(); services.AddTransient(); services.AddTransient(); services.AddTransient(); services.AddTransient(); services.AddTransient(); services.AddTransient(); + services.AddTransient(); services.AddTransient(); services.AddTransient(); services.AddTransient(); @@ -148,6 +151,10 @@ namespace Ombi.DependencyInjection services.AddTransient(); services.AddTransient(); services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); } public static void RegisterStore(this IServiceCollection services) { @@ -181,6 +188,7 @@ namespace Ombi.DependencyInjection services.AddTransient(); services.AddTransient(); services.AddSingleton(); + services.AddScoped(); services.AddTransient(); services.AddTransient(); @@ -190,15 +198,16 @@ namespace Ombi.DependencyInjection services.AddTransient(); services.AddTransient(); services.AddTransient(); + services.AddTransient(); services.AddTransient(); - services.AddTransient(); + services.AddTransient(); services.AddTransient(); } public static void RegisterJobs(this IServiceCollection services) { - services.AddSingleton(provider => new IoCJobFactory(provider)); - services.AddTransient(); + services.AddSingleton(); + services.AddSingleton(); services.AddTransient(); services.AddTransient(); @@ -223,6 +232,8 @@ namespace Ombi.DependencyInjection services.AddTransient(); services.AddTransient(); services.AddTransient(); + services.AddTransient(); + services.AddTransient(); } } } diff --git a/src/Ombi.DependencyInjection/Ombi.DependencyInjection.csproj b/src/Ombi.DependencyInjection/Ombi.DependencyInjection.csproj index 59a37d6aa..bbfe532eb 100644 --- a/src/Ombi.DependencyInjection/Ombi.DependencyInjection.csproj +++ b/src/Ombi.DependencyInjection/Ombi.DependencyInjection.csproj @@ -1,20 +1,22 @@  - netstandard2.1 + net5.0 3.0.0.0 3.0.0.0 + 8.0 - - - + + + + @@ -37,6 +39,8 @@ + + diff --git a/src/Ombi.HealthChecks/Checks/BaseHealthCheck.cs b/src/Ombi.HealthChecks/Checks/BaseHealthCheck.cs new file mode 100644 index 000000000..d0c14196c --- /dev/null +++ b/src/Ombi.HealthChecks/Checks/BaseHealthCheck.cs @@ -0,0 +1,26 @@ +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Diagnostics.HealthChecks; +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace Ombi.HealthChecks.Checks +{ + public abstract class BaseHealthCheck : IHealthCheck + { + private readonly IServiceScopeFactory _serviceScopeFactory; + public BaseHealthCheck(IServiceScopeFactory serviceScopeFactory) + { + _serviceScopeFactory = serviceScopeFactory; + } + + public abstract Task CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default); + + protected IServiceScope CreateScope() + { + return _serviceScopeFactory.CreateScope(); + } + } +} diff --git a/src/Ombi.HealthChecks/Checks/CouchPotatoHealthCheck.cs b/src/Ombi.HealthChecks/Checks/CouchPotatoHealthCheck.cs new file mode 100644 index 000000000..a68ce327b --- /dev/null +++ b/src/Ombi.HealthChecks/Checks/CouchPotatoHealthCheck.cs @@ -0,0 +1,53 @@ +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Diagnostics.HealthChecks; +using Ombi.Api.CouchPotato; +using Ombi.Api.Emby; +using Ombi.Api.Emby.Models; +using Ombi.Api.Plex; +using Ombi.Api.Plex.Models.Status; +using Ombi.Core.Settings; +using Ombi.Core.Settings.Models.External; +using Ombi.Settings.Settings.Models.External; +using System; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; + +namespace Ombi.HealthChecks.Checks +{ + public class CouchPotatoHealthCheck : BaseHealthCheck + { + public CouchPotatoHealthCheck(IServiceScopeFactory serviceScopeFactory) : base(serviceScopeFactory) + { + } + public override async Task CheckHealthAsync( + HealthCheckContext context, + CancellationToken cancellationToken = default) + { + using (var scope = CreateScope()) + { + var settingsProvider = scope.ServiceProvider.GetRequiredService>(); + var api = scope.ServiceProvider.GetRequiredService(); + var settings = await settingsProvider.GetSettingsAsync(); + if (!settings.Enabled) + { + return HealthCheckResult.Healthy("CouchPotato is not configured."); + } + + try + { + var result = await api.Status(settings.ApiKey, settings.FullUri); + if (result != null) + { + return HealthCheckResult.Healthy(); + } + return HealthCheckResult.Degraded("Couldn't get the status from CouchPotato"); + } + catch (Exception e) + { + return HealthCheckResult.Unhealthy("Could not communicate with CouchPotato", e); + } + } + } + } +} diff --git a/src/Ombi.HealthChecks/Checks/EmbyHealthCheck.cs b/src/Ombi.HealthChecks/Checks/EmbyHealthCheck.cs new file mode 100644 index 000000000..45c227033 --- /dev/null +++ b/src/Ombi.HealthChecks/Checks/EmbyHealthCheck.cs @@ -0,0 +1,54 @@ +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Diagnostics.HealthChecks; +using Ombi.Api.Emby; +using Ombi.Api.Emby.Models; +using Ombi.Api.Plex; +using Ombi.Api.Plex.Models.Status; +using Ombi.Core.Settings; +using Ombi.Core.Settings.Models.External; +using System; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; + +namespace Ombi.HealthChecks.Checks +{ + public class EmbyHealthCheck : BaseHealthCheck + { + public EmbyHealthCheck(IServiceScopeFactory serviceScopeFactory) : base(serviceScopeFactory) + { + } + public override async Task CheckHealthAsync( + HealthCheckContext context, + CancellationToken cancellationToken = default) + { + using (var scope = CreateScope()) + { + var settingsProvider = scope.ServiceProvider.GetRequiredService>(); + var api = scope.ServiceProvider.GetRequiredService(); + var settings = await settingsProvider.GetSettingsAsync(); + if (settings == null) + { + return HealthCheckResult.Healthy("Emby is not configured."); + } + + var client = api.CreateClient(settings); + var taskResult = new List>(); + foreach (var server in settings.Servers) + { + taskResult.Add(client.GetSystemInformation(server.ApiKey, server.FullUri)); + } + + try + { + var result = await Task.WhenAll(taskResult.ToArray()); + return HealthCheckResult.Healthy(); + } + catch (Exception e) + { + return HealthCheckResult.Unhealthy("Could not communicate with Emby", e); + } + } + } + } +} diff --git a/src/Ombi.HealthChecks/Checks/LidarrHealthCheck.cs b/src/Ombi.HealthChecks/Checks/LidarrHealthCheck.cs new file mode 100644 index 000000000..4efc0a904 --- /dev/null +++ b/src/Ombi.HealthChecks/Checks/LidarrHealthCheck.cs @@ -0,0 +1,48 @@ +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Diagnostics.HealthChecks; +using Ombi.Api.Lidarr; +using Ombi.Core.Settings; +using Ombi.Settings.Settings.Models.External; +using System; +using System.Threading; +using System.Threading.Tasks; + +namespace Ombi.HealthChecks.Checks +{ + public class LidarrHealthCheck : BaseHealthCheck + { + public LidarrHealthCheck(IServiceScopeFactory serviceScopeFactory) : base(serviceScopeFactory) + { + } + + public override async Task CheckHealthAsync( + HealthCheckContext context, + CancellationToken cancellationToken = default) + { + using (var scope = CreateScope()) + { + var settingsProvider = scope.ServiceProvider.GetRequiredService>(); + var api = scope.ServiceProvider.GetRequiredService(); + var settings = await settingsProvider.GetSettingsAsync(); + if (!settings.Enabled) + { + return HealthCheckResult.Healthy("Lidarr is not configured."); + } + + try + { + var result = await api.Status(settings.ApiKey, settings.FullUri); + if (result != null) + { + return HealthCheckResult.Healthy(); + } + return HealthCheckResult.Degraded("Couldn't get the status from Lidarr"); + } + catch (Exception e) + { + return HealthCheckResult.Unhealthy("Could not communicate with Lidarr", e); + } + } + } + } +} diff --git a/src/Ombi.HealthChecks/Checks/OmbiPingHealthCheck.cs b/src/Ombi.HealthChecks/Checks/OmbiPingHealthCheck.cs new file mode 100644 index 000000000..726d02078 --- /dev/null +++ b/src/Ombi.HealthChecks/Checks/OmbiPingHealthCheck.cs @@ -0,0 +1,47 @@ +using HealthChecks.Network; +using Microsoft.Extensions.Diagnostics.HealthChecks; +using System; +using System.Collections.Generic; +using System.Net.NetworkInformation; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace Ombi.HealthChecks.Checks +{ + public class OmbiPingHealthCheck + : IHealthCheck + { + private readonly OmbiPingHealthCheckOptions _options; + public OmbiPingHealthCheck(OmbiPingHealthCheckOptions options) + { + _options = options ?? throw new ArgumentNullException(nameof(options)); + } + public async Task CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default) + { + var configuredHosts = _options.ConfiguredHosts.Values; + + try + { + foreach (var (host, timeout, status) in configuredHosts) + { + using (var ping = new Ping()) + { + var pingReply = await ping.SendPingAsync(host, timeout); + + if (pingReply.Status != IPStatus.Success) + { + return new HealthCheckResult(status, description: $"Ping check for host {host} is failed with status reply:{pingReply.Status}"); + } + } + } + + return HealthCheckResult.Healthy(); + } + catch (Exception ex) + { + return new HealthCheckResult(context.Registration.FailureStatus, exception: ex); + } + } + } +} diff --git a/src/Ombi.HealthChecks/Checks/OmbiPingHealthCheckOptions.cs b/src/Ombi.HealthChecks/Checks/OmbiPingHealthCheckOptions.cs new file mode 100644 index 000000000..f89c71a52 --- /dev/null +++ b/src/Ombi.HealthChecks/Checks/OmbiPingHealthCheckOptions.cs @@ -0,0 +1,16 @@ +using Microsoft.Extensions.Diagnostics.HealthChecks; +using System.Collections.Generic; + +namespace Ombi.HealthChecks.Checks +{ + public class OmbiPingHealthCheckOptions + { + internal Dictionary ConfiguredHosts { get; } = new Dictionary(); + + public OmbiPingHealthCheckOptions AddHost(string host, int timeout, HealthStatus status) + { + ConfiguredHosts.Add(host, (host, timeout, status)); + return this; + } + } +} diff --git a/src/Ombi.HealthChecks/Checks/PlexHealthCheck.cs b/src/Ombi.HealthChecks/Checks/PlexHealthCheck.cs new file mode 100644 index 000000000..182c1b2f8 --- /dev/null +++ b/src/Ombi.HealthChecks/Checks/PlexHealthCheck.cs @@ -0,0 +1,51 @@ +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Diagnostics.HealthChecks; +using Ombi.Api.Plex; +using Ombi.Api.Plex.Models.Status; +using Ombi.Core.Settings; +using Ombi.Core.Settings.Models.External; +using System; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; + +namespace Ombi.HealthChecks.Checks +{ + public class PlexHealthCheck : BaseHealthCheck + { + public PlexHealthCheck(IServiceScopeFactory serviceScopeFactory) : base(serviceScopeFactory) + { + } + public override async Task CheckHealthAsync( + HealthCheckContext context, + CancellationToken cancellationToken = default) + { + using (var scope = CreateScope()) + { + var settingsProvider = scope.ServiceProvider.GetRequiredService>(); + var api = scope.ServiceProvider.GetRequiredService(); + var settings = await settingsProvider.GetSettingsAsync(); + if (settings == null) + { + return HealthCheckResult.Healthy("Plex is not confiured."); + } + + var taskResult = new List>(); + foreach (var server in settings.Servers) + { + taskResult.Add(api.GetStatus(server.PlexAuthToken, server.FullUri)); + } + + try + { + var result = await Task.WhenAll(taskResult.ToArray()); + return HealthCheckResult.Healthy(); + } + catch (Exception e) + { + return HealthCheckResult.Unhealthy("Could not communicate with Plex", e); + } + } + } + } +} diff --git a/src/Ombi.HealthChecks/Checks/RadarrHealthCheck.cs b/src/Ombi.HealthChecks/Checks/RadarrHealthCheck.cs new file mode 100644 index 000000000..e365c73bb --- /dev/null +++ b/src/Ombi.HealthChecks/Checks/RadarrHealthCheck.cs @@ -0,0 +1,47 @@ +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Diagnostics.HealthChecks; +using Ombi.Api.Radarr; +using Ombi.Core.Settings; +using Ombi.Settings.Settings.Models.External; +using System; +using System.Threading; +using System.Threading.Tasks; + +namespace Ombi.HealthChecks.Checks +{ + public class RadarrHealthCheck : BaseHealthCheck, IHealthCheck + { + public RadarrHealthCheck(IServiceScopeFactory serviceScopeFactory) : base(serviceScopeFactory) + { + } + public override async Task CheckHealthAsync( + HealthCheckContext context, + CancellationToken cancellationToken = default) + { + using (var scope = CreateScope()) + { + var settingsProvider = scope.ServiceProvider.GetRequiredService>(); + var api = scope.ServiceProvider.GetRequiredService(); + var settings = await settingsProvider.GetSettingsAsync(); + if (!settings.Enabled) + { + return HealthCheckResult.Healthy("Radarr is not configured."); + } + + try + { + var result = await api.SystemStatus(settings.ApiKey, settings.FullUri); + if (result != null) + { + return HealthCheckResult.Healthy(); + } + return HealthCheckResult.Degraded("Couldn't get the status from Radarr"); + } + catch (Exception e) + { + return HealthCheckResult.Unhealthy("Could not communicate with Radarr", e); + } + } + } + } +} diff --git a/src/Ombi.HealthChecks/Checks/SickrageHealthCheck.cs b/src/Ombi.HealthChecks/Checks/SickrageHealthCheck.cs new file mode 100644 index 000000000..c348e8edf --- /dev/null +++ b/src/Ombi.HealthChecks/Checks/SickrageHealthCheck.cs @@ -0,0 +1,54 @@ +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Diagnostics.HealthChecks; +using Ombi.Api.CouchPotato; +using Ombi.Api.Emby; +using Ombi.Api.Emby.Models; +using Ombi.Api.Plex; +using Ombi.Api.Plex.Models.Status; +using Ombi.Api.SickRage; +using Ombi.Core.Settings; +using Ombi.Core.Settings.Models.External; +using Ombi.Settings.Settings.Models.External; +using System; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; + +namespace Ombi.HealthChecks.Checks +{ + public class SickrageHealthCheck : BaseHealthCheck + { + public SickrageHealthCheck(IServiceScopeFactory serviceScopeFactory) : base(serviceScopeFactory) + { + } + public override async Task CheckHealthAsync( + HealthCheckContext context, + CancellationToken cancellationToken = default) + { + using (var scope = CreateScope()) + { + var settingsProvider = scope.ServiceProvider.GetRequiredService>(); + var api = scope.ServiceProvider.GetRequiredService(); + var settings = await settingsProvider.GetSettingsAsync(); + if (!settings.Enabled) + { + return HealthCheckResult.Healthy("SickRage is not configured."); + } + + try + { + var result = await api.Ping(settings.ApiKey, settings.FullUri); + if (result != null) + { + return HealthCheckResult.Healthy(); + } + return HealthCheckResult.Degraded("Couldn't get the status from SickRage"); + } + catch (Exception e) + { + return HealthCheckResult.Unhealthy("Could not communicate with SickRage", e); + } + } + } + } +} diff --git a/src/Ombi.HealthChecks/Checks/SonarrHealthCheck.cs b/src/Ombi.HealthChecks/Checks/SonarrHealthCheck.cs new file mode 100644 index 000000000..35f2bb46a --- /dev/null +++ b/src/Ombi.HealthChecks/Checks/SonarrHealthCheck.cs @@ -0,0 +1,48 @@ +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Diagnostics.HealthChecks; +using Ombi.Api.Sonarr; +using Ombi.Core.Settings; +using Ombi.Settings.Settings.Models.External; +using System; +using System.Threading; +using System.Threading.Tasks; + +namespace Ombi.HealthChecks.Checks +{ + public class SonarrHealthCheck : BaseHealthCheck + { + public SonarrHealthCheck(IServiceScopeFactory serviceScopeFactory) : base(serviceScopeFactory) + { + } + + public override async Task CheckHealthAsync( + HealthCheckContext context, + CancellationToken cancellationToken = default) + { + using (var scope = CreateScope()) + { + var settingsProvider = scope.ServiceProvider.GetRequiredService>(); + var api = scope.ServiceProvider.GetRequiredService(); + var settings = await settingsProvider.GetSettingsAsync(); + if (!settings.Enabled) + { + return HealthCheckResult.Healthy("Sonarr is not configured."); + } + + try + { + var result = await api.SystemStatus(settings.ApiKey, settings.FullUri); + if (result != null) + { + return HealthCheckResult.Healthy(); + } + return HealthCheckResult.Degraded("Couldn't get the status from Sonarr"); + } + catch (Exception e) + { + return HealthCheckResult.Unhealthy("Could not communicate with Sonarr", e); + } + } + } + } +} diff --git a/src/Ombi.HealthChecks/HealthCheckExtensions.cs b/src/Ombi.HealthChecks/HealthCheckExtensions.cs new file mode 100644 index 000000000..e608d5ec0 --- /dev/null +++ b/src/Ombi.HealthChecks/HealthCheckExtensions.cs @@ -0,0 +1,55 @@ +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Diagnostics.HealthChecks; +using Ombi.HealthChecks.Checks; +using System; +using System.Collections.Generic; + +namespace Ombi.HealthChecks +{ + public static class HealthCheckExtensions + { + public static IHealthChecksBuilder AddOmbiHealthChecks(this IHealthChecksBuilder builder) + { + builder.AddCheck("Plex", tags: new string[] { "MediaServer" }); + builder.AddCheck("Emby", tags: new string[] { "MediaServer" }); + builder.AddCheck("Lidarr", tags: new string[] { "DVR" }); + builder.AddCheck("Sonarr", tags: new string[] { "DVR" }); + builder.AddCheck("Radarr", tags: new string[] { "DVR" }); + builder.AddCheck("CouchPotato", tags: new string[] { "DVR" }); + builder.AddCheck("SickRage", tags: new string[] { "DVR" }); + builder.AddOmbiPingHealthCheck(options => + { + options.AddHost("www.google.co.uk", 5000, HealthStatus.Unhealthy); + options.AddHost("www.google.com", 3000, HealthStatus.Degraded); + }, "External Ping", tags: new string[] { "System" }); + + return builder; + } + + /// + /// Add a health check for network ping. + /// + /// The . + /// The action to configure the ping parameters. + /// The health check name. Optional. If null the type name 'ping' will be used for the name. + /// + /// The that should be reported when the health check fails. Optional. If null then + /// the default status of will be reported. + /// + /// A list of tags that can be used to filter sets of health checks. Optional. + /// An optional System.TimeSpan representing the timeout of the check. + /// The . + public static IHealthChecksBuilder AddOmbiPingHealthCheck(this IHealthChecksBuilder builder, Action setup, string name = default, HealthStatus? failureStatus = default, IEnumerable tags = default, TimeSpan? timeout = default) + { + var options = new OmbiPingHealthCheckOptions(); + setup?.Invoke(options); + + return builder.Add(new HealthCheckRegistration( + name, + sp => new OmbiPingHealthCheck(options), + failureStatus, + tags, + timeout)); + } + } +} diff --git a/src/Ombi.HealthChecks/Ombi.HealthChecks.csproj b/src/Ombi.HealthChecks/Ombi.HealthChecks.csproj new file mode 100644 index 000000000..5171c9c36 --- /dev/null +++ b/src/Ombi.HealthChecks/Ombi.HealthChecks.csproj @@ -0,0 +1,23 @@ + + + + net5.0 + + + + + + + + + + + + + + + + + + + diff --git a/src/Ombi.Helpers.Tests/EmbyHelperTests.cs b/src/Ombi.Helpers.Tests/EmbyHelperTests.cs index 585e324f5..261ba87cc 100644 --- a/src/Ombi.Helpers.Tests/EmbyHelperTests.cs +++ b/src/Ombi.Helpers.Tests/EmbyHelperTests.cs @@ -9,15 +9,17 @@ namespace Ombi.Helpers.Tests public class EmbyHelperTests { [TestCaseSource(nameof(UrlData))] - public string TestUrl(string mediaId, string url) + public string TestUrl(string mediaId, string url, string serverId) { - return EmbyHelper.GetEmbyMediaUrl(mediaId, url); + // http://192.168.68.X:8096/web/index.html#!/item?id=17980&serverId=4e7a85e6ed0b49b9a6d6d15e739a566b + return EmbyHelper.GetEmbyMediaUrl(mediaId, serverId, url); } [TestCaseSource(nameof(JellyfinUrlData))] - public string TestJellyfinUrl(string mediaId, string url) + public string TestJellyfinUrl(string mediaId, string url, string serverId) { - return EmbyHelper.GetEmbyMediaUrl(mediaId, url, true); + // http://192.168.68.X:8097/web/index.html#!/details?id=7ffe222498445d5ebfddb31bc4fa9a6d&serverId=50cce67f0baa425093d189b3017331fb + return EmbyHelper.GetEmbyMediaUrl(mediaId, serverId, url, true); } public static IEnumerable UrlData @@ -25,9 +27,10 @@ namespace Ombi.Helpers.Tests get { var mediaId = 1; - yield return new TestCaseData(mediaId.ToString(), "http://google.com").Returns($"http://google.com/#!/item/item.html?id={mediaId}").SetName("EmbyHelper_GetMediaUrl_WithCustomDomain_WithoutTrailingSlash"); - yield return new TestCaseData(mediaId.ToString(), "http://google.com/").Returns($"http://google.com/#!/item/item.html?id={mediaId}").SetName("EmbyHelper_GetMediaUrl_WithCustomDomain"); - yield return new TestCaseData(mediaId.ToString(), "https://google.com/").Returns($"https://google.com/#!/item/item.html?id={mediaId}").SetName("EmbyHelper_GetMediaUrl_WithCustomDomain_Https"); + yield return new TestCaseData(mediaId.ToString(), "http://google.com", "1").Returns($"http://google.com/web/index.html#!/item?id={mediaId}&serverId=1").SetName("EmbyHelper_GetMediaUrl_WithCustomDomain_WithoutTrailingSlash"); + yield return new TestCaseData(mediaId.ToString(), "http://google.com/", "1").Returns($"http://google.com/web/index.html#!/item?id={mediaId}&serverId=1").SetName("EmbyHelper_GetMediaUrl_WithCustomDomain"); + yield return new TestCaseData(mediaId.ToString(), "https://google.com/", "1").Returns($"https://google.com/web/index.html#!/item?id={mediaId}&serverId=1").SetName("EmbyHelper_GetMediaUrl_WithCustomDomain_Https"); + yield return new TestCaseData(mediaId.ToString(), string.Empty, "1").Returns($"https://app.emby.media/web/index.html#!/item?id={mediaId}&serverId=1").SetName("EmbyHelper_GetMediaUrl_WithOutCustomDomain"); } } @@ -36,9 +39,9 @@ namespace Ombi.Helpers.Tests get { var mediaId = 1; - yield return new TestCaseData(mediaId.ToString(), "http://google.com").Returns($"http://google.com/#!/itemdetails.html?id={mediaId}").SetName("EmbyHelperJellyfin_GetMediaUrl_WithCustomDomain_WithoutTrailingSlash"); - yield return new TestCaseData(mediaId.ToString(), "http://google.com/").Returns($"http://google.com/#!/itemdetails.html?id={mediaId}").SetName("EmbyHelperJellyfin_GetMediaUrl_WithCustomDomain"); - yield return new TestCaseData(mediaId.ToString(), "https://google.com/").Returns($"https://google.com/#!/itemdetails.html?id={mediaId}").SetName("EmbyHelperJellyfin_GetMediaUrl_WithCustomDomain_Https"); + yield return new TestCaseData(mediaId.ToString(), "http://google.com", "1").Returns($"http://google.com/web/index.html#!/details?id={mediaId}&serverId=1").SetName("EmbyHelperJellyfin_GetMediaUrl_WithCustomDomain_WithoutTrailingSlash"); + yield return new TestCaseData(mediaId.ToString(), "http://google.com/", "1").Returns($"http://google.com/web/index.html#!/details?id={mediaId}&serverId=1").SetName("EmbyHelperJellyfin_GetMediaUrl_WithCustomDomain"); + yield return new TestCaseData(mediaId.ToString(), "https://google.com/", "1").Returns($"https://google.com/web/index.html#!/details?id={mediaId}&serverId=1").SetName("EmbyHelperJellyfin_GetMediaUrl_WithCustomDomain_Https"); } } } diff --git a/src/Ombi.Helpers.Tests/Ombi.Helpers.Tests.csproj b/src/Ombi.Helpers.Tests/Ombi.Helpers.Tests.csproj index 45f2f537e..1989f69d8 100644 --- a/src/Ombi.Helpers.Tests/Ombi.Helpers.Tests.csproj +++ b/src/Ombi.Helpers.Tests/Ombi.Helpers.Tests.csproj @@ -1,15 +1,16 @@ - + - netcoreapp3.0 + net5.0 false + - + diff --git a/src/Ombi.Helpers.Tests/PlexHelperTests.cs b/src/Ombi.Helpers.Tests/PlexHelperTests.cs index 8ecb3fa0a..82b59fdf7 100644 --- a/src/Ombi.Helpers.Tests/PlexHelperTests.cs +++ b/src/Ombi.Helpers.Tests/PlexHelperTests.cs @@ -39,6 +39,39 @@ namespace Ombi.Helpers.Tests yield return new TestCaseData("com.plexapp.agents.agent47://tt2543456?lang=en", ProviderIdType.Imdb).Returns("tt2543456").SetName("Unknown IMDB agent"); yield return new TestCaseData("com.plexapp.agents.agent47://456822/1/1?lang=en", ProviderIdType.TvDb).Returns("456822").SetName("Unknown TvDb agent"); yield return new TestCaseData("com.plexapp.agents.agent47://456822/999/999?lang=en", ProviderIdType.TvDb).Returns("456822").SetName("Unknown TvDb agent, large episode and season"); + yield return new TestCaseData("com.plexapp.agents.xbmcnfotv://153021/2/1?lang=xn", ProviderIdType.TvDb).Returns("153021").SetName("xmbc agent, tv episode"); + yield return new TestCaseData("com.plexapp.agents.xbmcnfotv://153021?lang=xn", ProviderIdType.TvDb).Returns("153021").SetName("xmbc agent, tv show"); + yield return new TestCaseData("tmdb://610201", ProviderIdType.MovieDb).Returns("610201").SetName("Themoviedb new plex format"); + } + } + + [TestCaseSource(nameof(ProviderIdGuidDataV2))] + public void GetProviderIdsFromMetadataTests(string guidInput, ProviderId expected) + { + var param = guidInput.Split('|', StringSplitOptions.RemoveEmptyEntries); + var result = PlexHelper.GetProviderIdsFromMetadata(param); + + Assert.AreEqual(expected.ImdbId, result.ImdbId); + Assert.AreEqual(expected.TheMovieDb, result.TheMovieDb); + Assert.AreEqual(expected.TheTvDb, result.TheTvDb); + } + + public static IEnumerable ProviderIdGuidDataV2 + { + get + { + yield return new TestCaseData("plex://movie/5e1632df2d4d84003e48e54e|imdb://tt9178402|tmdb://610201", new ProviderId { ImdbId = "tt9178402", TheMovieDb = "610201" }).SetName("V2 Regular Plex Id"); + yield return new TestCaseData("plex://movie/5d7768253c3c2a001fbcab72|imdb://tt0119567|tmdb://330", new ProviderId { ImdbId = "tt0119567", TheMovieDb = "330" }).SetName("V2 Regular Plex Id Another"); + yield return new TestCaseData("plex://movie/5d7768253c3c2a001fbcab72|imdb://tt0119567", new ProviderId { ImdbId = "tt0119567" }).SetName("V2 Regular Plex Id Single Imdb"); + yield return new TestCaseData("plex://movie/5d7768253c3c2a001fbcab72|tmdb://330", new ProviderId { TheMovieDb = "330" }).SetName("V2 Regular Plex Id Single Tmdb"); + yield return new TestCaseData("com.plexapp.agents.thetvdb://269586/2/8?lang=en", new ProviderId { TheTvDb = "269586" }).SetName("V2 Regular TvDb Id"); + yield return new TestCaseData("com.plexapp.agents.themoviedb://390043?lang=en", new ProviderId { TheMovieDb = "390043" }).SetName("V2 Regular MovieDb Id"); + yield return new TestCaseData("com.plexapp.agents.imdb://tt2543164?lang=en", new ProviderId { ImdbId = "tt2543164" }).SetName("V2 Regular Imdb Id"); + yield return new TestCaseData("com.plexapp.agents.agent47://tt2543456?lang=en", new ProviderId { ImdbId = "tt2543456" }).SetName("V2 Unknown IMDB agent"); + yield return new TestCaseData("com.plexapp.agents.agent47://456822/1/1?lang=en", new ProviderId { TheTvDb = "456822" }).SetName("V2 Unknown TvDb agent"); + yield return new TestCaseData("com.plexapp.agents.agent47://456822/999/999?lang=en", new ProviderId { TheTvDb = "456822" }).SetName("V2 Unknown TvDb agent, large episode and season"); + yield return new TestCaseData("com.plexapp.agents.xbmcnfotv://153021/2/1?lang=xn", new ProviderId { TheTvDb = "153021" }).SetName("V2 xmbc agent, tv episode"); + yield return new TestCaseData("com.plexapp.agents.xbmcnfotv://153021?lang=xn", new ProviderId { TheTvDb = "153021" }).SetName("V2 xmbc agent, tv show"); } } diff --git a/src/Ombi.Helpers.Tests/StringHelperTests.cs b/src/Ombi.Helpers.Tests/StringHelperTests.cs index d03f926ff..80ca32c64 100644 --- a/src/Ombi.Helpers.Tests/StringHelperTests.cs +++ b/src/Ombi.Helpers.Tests/StringHelperTests.cs @@ -40,5 +40,14 @@ namespace Ombi.Helpers.Tests Assert.AreEqual(expectedUrl, sourceUrl.ToHttpsUrl(), "Should return the unchanged invalid URL"); } + + [Test] + public void ToHttpsUrl_ShouldReturnNull_NullUrl() + { + const string sourceUrl = null; + const string expectedUrl = null; + + Assert.AreEqual(expectedUrl, sourceUrl.ToHttpsUrl(), "Should return null for null URL"); + } } } \ No newline at end of file diff --git a/src/Ombi.Helpers.Tests/UriHelperTests.cs b/src/Ombi.Helpers.Tests/UriHelperTests.cs index fd21e66f4..3e1b4aec2 100644 --- a/src/Ombi.Helpers.Tests/UriHelperTests.cs +++ b/src/Ombi.Helpers.Tests/UriHelperTests.cs @@ -62,7 +62,7 @@ namespace Ombi.Helpers.Tests var expected = (string)d.ExpectedResult; var args = d.Arguments.ToList(); args.Add(true); - var newExpected = expected.Replace("http://", "https://"); + var newExpected = expected.ToHttpsUrl(); if (args.Contains(80)) { newExpected = expected; @@ -99,7 +99,7 @@ namespace Ombi.Helpers.Tests } } args.Add(true); - var newExpected = expected.Replace("http://", "https://"); + var newExpected = expected.ToHttpsUrl(); if (args.Contains(80)) { newExpected = expected; diff --git a/src/Ombi.Helpers/ApplicationSettings.cs b/src/Ombi.Helpers/ApplicationSettings.cs index 12be2087c..753b5a4d4 100644 --- a/src/Ombi.Helpers/ApplicationSettings.cs +++ b/src/Ombi.Helpers/ApplicationSettings.cs @@ -3,5 +3,6 @@ public class ApplicationSettings { public string OmbiService { get; set; } + public string NotificationService { get; set; } } } \ No newline at end of file diff --git a/src/Ombi.Helpers/AssemblyHelper.cs b/src/Ombi.Helpers/AssemblyHelper.cs index 055d19dc1..eb4dc55fd 100644 --- a/src/Ombi.Helpers/AssemblyHelper.cs +++ b/src/Ombi.Helpers/AssemblyHelper.cs @@ -1,4 +1,5 @@ -using System.Reflection; +using Microsoft.Extensions.PlatformAbstractions; +using System.Reflection; namespace Ombi.Helpers { @@ -6,10 +7,8 @@ namespace Ombi.Helpers { public static string GetRuntimeVersion() { - var version = Assembly.GetEntryAssembly() - .GetCustomAttribute() - .InformationalVersion; - return version.Equals("1.0.0") ? "4.0.0-develop" : version; + ApplicationEnvironment app = PlatformServices.Default.Application; + return app.ApplicationVersion; } } } \ No newline at end of file diff --git a/src/Ombi.Helpers/EmbyHelper.cs b/src/Ombi.Helpers/EmbyHelper.cs index 1d6004d00..785ca47d4 100644 --- a/src/Ombi.Helpers/EmbyHelper.cs +++ b/src/Ombi.Helpers/EmbyHelper.cs @@ -1,25 +1,26 @@ namespace Ombi.Helpers { - public class EmbyHelper + public static class EmbyHelper { - public static string GetEmbyMediaUrl(string mediaId, string customerServerUrl = null, bool isJellyfin = false) + public static string GetEmbyMediaUrl(string mediaId, string serverId, string customerServerUrl = null, bool isJellyfin = false) { - string path = "item/item"; + //web/index.html#!/details|item + string path = "item"; if (isJellyfin) { - path = "itemdetails"; + path = "details"; } if (customerServerUrl.HasValue()) { if (!customerServerUrl.EndsWith("/")) { - return $"{customerServerUrl}/#!/{path}.html?id={mediaId}"; + return $"{customerServerUrl}/web/index.html#!/{path}?id={mediaId}&serverId={serverId}"; } - return $"{customerServerUrl}#!/{path}.html?id={mediaId}"; + return $"{customerServerUrl}web/index.html#!/{path}?id={mediaId}&serverId={serverId}"; } else { - return $"https://app.emby.media/#!/{path}.html?id={mediaId}"; + return $"https://app.emby.media/web/index.html#!/{path}?id={mediaId}&serverId={serverId}"; } } } diff --git a/src/Ombi.Schedule/JobDataKeys.cs b/src/Ombi.Helpers/JobDataKeys.cs similarity index 52% rename from src/Ombi.Schedule/JobDataKeys.cs rename to src/Ombi.Helpers/JobDataKeys.cs index 46d2dee2a..e0e2f7451 100644 --- a/src/Ombi.Schedule/JobDataKeys.cs +++ b/src/Ombi.Helpers/JobDataKeys.cs @@ -1,7 +1,8 @@ -namespace Ombi.Schedule +namespace Ombi.Helpers { public class JobDataKeys { public const string RecentlyAddedSearch = "recentlyAddedSearch"; + public const string NotificationOptions = nameof(NotificationOptions); } } \ No newline at end of file diff --git a/src/Ombi.Helpers/LoggingEvents.cs b/src/Ombi.Helpers/LoggingEvents.cs index 0723800ab..a7c61d9d2 100644 --- a/src/Ombi.Helpers/LoggingEvents.cs +++ b/src/Ombi.Helpers/LoggingEvents.cs @@ -33,6 +33,8 @@ namespace Ombi.Helpers public static EventId PushoverNotification => new EventId(4005); public static EventId TelegramNotifcation => new EventId(4006); public static EventId GotifyNotification => new EventId(4007); + public static EventId WhatsApp => new EventId(4008); + public static EventId WebhookNotification => new EventId(4009); public static EventId TvSender => new EventId(5000); public static EventId SonarrSender => new EventId(5001); diff --git a/src/Ombi.Helpers/NotificationAgent.cs b/src/Ombi.Helpers/NotificationAgent.cs index 18f28105a..9b5cc93fc 100644 --- a/src/Ombi.Helpers/NotificationAgent.cs +++ b/src/Ombi.Helpers/NotificationAgent.cs @@ -11,5 +11,7 @@ Mattermost = 6, Mobile = 7, Gotify = 8, + Webhook = 9, + WhatsApp = 10 } } \ No newline at end of file diff --git a/src/Ombi.Helpers/Ombi.Helpers.csproj b/src/Ombi.Helpers/Ombi.Helpers.csproj index 36539f4ef..48969ac1a 100644 --- a/src/Ombi.Helpers/Ombi.Helpers.csproj +++ b/src/Ombi.Helpers/Ombi.Helpers.csproj @@ -1,20 +1,23 @@  - netstandard2.1 + net5.0 3.0.0.0 3.0.0.0 + 8.0 - - - - + + + + + + \ No newline at end of file diff --git a/src/Ombi.Schedule/OmbiQuartz.cs b/src/Ombi.Helpers/OmbiQuartz.cs similarity index 66% rename from src/Ombi.Schedule/OmbiQuartz.cs rename to src/Ombi.Helpers/OmbiQuartz.cs index 715bb187b..573bd6262 100644 --- a/src/Ombi.Schedule/OmbiQuartz.cs +++ b/src/Ombi.Helpers/OmbiQuartz.cs @@ -1,18 +1,23 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; using System.Threading.Tasks; -using Ombi.Helpers; using Quartz; using Quartz.Impl; +using Quartz.Impl.Matchers; using Quartz.Spi; -namespace Ombi.Schedule +namespace Ombi.Helpers { public class OmbiQuartz { protected IScheduler _scheduler { get; set; } - + public static IScheduler Scheduler => Instance._scheduler; + private static SemaphoreSlim _semaphore = new SemaphoreSlim(1, 1); + // Singleton protected static OmbiQuartz _instance; @@ -30,13 +35,19 @@ namespace Ombi.Schedule { _scheduler = await new StdSchedulerFactory().GetScheduler(); } - + public IScheduler UseJobFactory(IJobFactory jobFactory) { Scheduler.JobFactory = jobFactory; return Scheduler; } + public static async Task IsJobRunning(string jobName) + { + var running = await Scheduler.GetCurrentlyExecutingJobs(); + return running.Any(x => x.JobDetail.Key.Name.Equals(jobName, StringComparison.InvariantCultureIgnoreCase)); + } + public async Task AddJob(string name, string group, string cronExpression, Dictionary jobData = null) where T : IJob { @@ -50,7 +61,7 @@ namespace Ombi.Schedule } } - if(!cronExpression.HasValue()) + if (!cronExpression.HasValue()) { jobBuilder.StoreDurably(true); } @@ -60,25 +71,44 @@ namespace Ombi.Schedule { ITrigger jobTrigger = TriggerBuilder.Create() .WithIdentity(name + "Trigger", group) - .WithCronSchedule(cronExpression, + .WithCronSchedule(cronExpression, x => x.WithMisfireHandlingInstructionFireAndProceed()) .ForJob(name, group) .StartNow() .Build(); await Scheduler.ScheduleJob(job, jobTrigger); - } + } else { await Scheduler.AddJob(job, true); } - + } public static async Task TriggerJob(string jobName, string group) { - await Scheduler.TriggerJob(new JobKey(jobName, group)); + await _semaphore.WaitAsync(); + + try + { + if (!(await IsJobRunning(jobName))) + { + await Scheduler.TriggerJob(new JobKey(jobName, group)); + } + } + finally + { + _semaphore.Release(); + } + } - + + + public static async Task TriggerJob(string jobName, string group, IDictionary data) + { + await Scheduler.TriggerJob(new JobKey(jobName, group), new JobDataMap(data)); + } + public static async Task Start() { await Scheduler.Start(); diff --git a/src/Ombi.Helpers/PlexHelper.cs b/src/Ombi.Helpers/PlexHelper.cs index de61b8740..4dbde0c92 100644 --- a/src/Ombi.Helpers/PlexHelper.cs +++ b/src/Ombi.Helpers/PlexHelper.cs @@ -33,14 +33,16 @@ namespace Ombi.Helpers { public class PlexHelper { - private const string ImdbMatchExpression = "tt([0-9]{1,10})"; - private const string TvDbIdMatchExpression = "//[0-9]+/([0-9]{1,3})/([0-9]{1,3})"; + private const string ImdbMatchExpression = "tt([0-9]{1,10})"; + private const string TvDbIdMatchExpression = "//[0-9]+/?([0-9]{1,3})/?([0-9]{1,3})"; public static ProviderId GetProviderIdFromPlexGuid(string guid) { //com.plexapp.agents.thetvdb://269586/2/8?lang=en //com.plexapp.agents.themoviedb://390043?lang=en //com.plexapp.agents.imdb://tt2543164?lang=en + //plex://movie/5e1632df2d4d84003e48e54e + // https://github.com/tidusjar/Ombi/issues/3277 if (string.IsNullOrEmpty(guid)) { return new ProviderId(); @@ -55,15 +57,14 @@ namespace Ombi.Helpers { TheTvDb = guidSplit[1] }; - } else - if (guid.Contains("themoviedb", CompareOptions.IgnoreCase)) + } + if (guid.Contains("themoviedb", CompareOptions.IgnoreCase) || guid.Contains("tmdb", CompareOptions.IgnoreCase)) { return new ProviderId { TheMovieDb = guidSplit[1] }; } - else if (guid.Contains("imdb", CompareOptions.IgnoreCase)) { return new ProviderId @@ -71,72 +72,36 @@ namespace Ombi.Helpers ImdbId = guidSplit[1] }; } - else + if (guid.Contains("plex://", CompareOptions.IgnoreCase)) { - var imdbRegex = new Regex(ImdbMatchExpression, RegexOptions.Compiled); - var tvdbRegex = new Regex(TvDbIdMatchExpression, RegexOptions.Compiled); - var imdbMatch = imdbRegex.IsMatch(guid); - if (imdbMatch) - { - return new ProviderId - { - ImdbId = guidSplit[1] - }; - } - else + return new ProviderId { - // Check if it matches the TvDb pattern - var tvdbMatch = tvdbRegex.IsMatch(guid); - if (tvdbMatch) - { - return new ProviderId - { - TheTvDb = guidSplit[1] - }; - } - } + Plex = true + }; } - } - return new ProviderId(); - } - public static EpisodeModelHelper GetSeasonsAndEpisodesFromPlexGuid(string guid) - { - var ep = new EpisodeModelHelper(); - //com.plexapp.agents.thetvdb://269586/2/8?lang=en - //com.plexapp.agents.themoviedb://390043?lang=en - //com.plexapp.agents.imdb://tt2543164?lang=en - if (string.IsNullOrEmpty(guid)) - return null; - try - { - var guidSplit = guid.Split(new[] { '/', '?' }, StringSplitOptions.RemoveEmptyEntries); - if (guidSplit.Length > 2) + var imdbRegex = new Regex(ImdbMatchExpression, RegexOptions.Compiled); + var tvdbRegex = new Regex(TvDbIdMatchExpression, RegexOptions.Compiled); + var imdbMatch = imdbRegex.IsMatch(guid); + if (imdbMatch) { - if (guid.Contains("thetvdb", CompareOptions.IgnoreCase)) - { - ep.ProviderId = new ProviderId {TheTvDb = guidSplit[1]}; - } - if (guid.Contains("themoviedb", CompareOptions.IgnoreCase)) + return new ProviderId { - ep.ProviderId = new ProviderId { TheMovieDb = guidSplit[1] }; + ImdbId = guidSplit[1] + }; + } - } - if (guid.Contains("imdb", CompareOptions.IgnoreCase)) + // Check if it matches the TvDb pattern + var tvdbMatch = tvdbRegex.IsMatch(guid); + if (tvdbMatch) + { + return new ProviderId { - ep.ProviderId = new ProviderId { ImdbId = guidSplit[1] }; - - } - ep.SeasonNumber = int.Parse(guidSplit[2]); - ep.EpisodeNumber = int.Parse(guidSplit[3]); + TheTvDb = guidSplit[1] + }; } - return ep; - - } - catch (Exception) - { - return ep; } + return new ProviderId(); } public static string GetPlexMediaUrl(string machineId, int mediaId) @@ -145,13 +110,37 @@ namespace Ombi.Helpers $"https://app.plex.tv/web/app#!/server/{machineId}/details?key=library%2Fmetadata%2F{mediaId}"; return url; } - } - public class EpisodeModelHelper - { - public ProviderId ProviderId { get; set; } - public int SeasonNumber { get; set; } - public int EpisodeNumber { get; set; } + public static ProviderId GetProviderIdsFromMetadata(params string[] guids) + { + var providerIds = new ProviderId(); + foreach (var guid in guids) + { + var provider = GetProviderIdFromPlexGuid(guid); + if (provider.Type == ProviderType.Plex) + { + // There are more guids! + continue; + } + + switch (provider.Type) + { + case ProviderType.ImdbId: + providerIds.ImdbId = provider.ImdbId; + break; + case ProviderType.TheMovieDbId: + providerIds.TheMovieDb = provider.TheMovieDb; + break; + case ProviderType.TvDbId: + providerIds.TheTvDb = provider.TheTvDb; + break; + default: + throw new ArgumentOutOfRangeException(nameof(provider.Type)); + } + } + + return providerIds; + } } public class ProviderId @@ -159,6 +148,7 @@ namespace Ombi.Helpers public string TheTvDb { get; set; } public string TheMovieDb { get; set; } public string ImdbId { get; set; } + public bool Plex { get; set; } public ProviderType Type { @@ -176,6 +166,10 @@ namespace Ombi.Helpers { return ProviderType.TvDbId; } + if (Plex) + { + return ProviderType.Plex; + } return ProviderType.ImdbId; } } @@ -185,6 +179,7 @@ namespace Ombi.Helpers { ImdbId, TheMovieDbId, - TvDbId + TvDbId, + Plex } } \ No newline at end of file diff --git a/src/Ombi.Helpers/StartupSingleton.cs b/src/Ombi.Helpers/StartupSingleton.cs new file mode 100644 index 000000000..41fd1a9ab --- /dev/null +++ b/src/Ombi.Helpers/StartupSingleton.cs @@ -0,0 +1,15 @@ +namespace Ombi.Helpers +{ + public class StartupSingleton + { + private static StartupSingleton instance; + + private StartupSingleton() { } + + public static StartupSingleton Instance => instance ?? (instance = new StartupSingleton()); + + public string StoragePath { get; set; } + + public string SecurityKey { get; set; } + } +} \ No newline at end of file diff --git a/src/Ombi.Helpers/StoragePathSingleton.cs b/src/Ombi.Helpers/StoragePathSingleton.cs deleted file mode 100644 index c502c4a54..000000000 --- a/src/Ombi.Helpers/StoragePathSingleton.cs +++ /dev/null @@ -1,13 +0,0 @@ -namespace Ombi.Helpers -{ - public class StoragePathSingleton - { - private static StoragePathSingleton instance; - - private StoragePathSingleton() { } - - public static StoragePathSingleton Instance => instance ?? (instance = new StoragePathSingleton()); - - public string StoragePath { get; set; } - } -} \ No newline at end of file diff --git a/src/Ombi.Helpers/StringHelper.cs b/src/Ombi.Helpers/StringHelper.cs index bd9ecb5bb..e918fd35a 100644 --- a/src/Ombi.Helpers/StringHelper.cs +++ b/src/Ombi.Helpers/StringHelper.cs @@ -131,7 +131,7 @@ namespace Ombi.Helpers public static string ToHttpsUrl(this string currentUrl) { - return currentUrl.Replace("http://", "https://"); + return currentUrl?.Replace("http://", "https://"); } } } \ No newline at end of file diff --git a/src/Ombi.Hubs/NotificationHub.cs b/src/Ombi.Hubs/NotificationHub.cs index da6dee830..54d13884a 100644 --- a/src/Ombi.Hubs/NotificationHub.cs +++ b/src/Ombi.Hubs/NotificationHub.cs @@ -43,7 +43,7 @@ namespace Ombi.Hubs } var user = await _userManager.Users. - FirstOrDefaultAsync(x => x.Id.Equals(userIdClaim.Value, StringComparison.InvariantCultureIgnoreCase)); + FirstOrDefaultAsync(x => x.Id == userIdClaim.Value); var claims = await _userManager.GetRolesAsync(user); UsersOnline.TryAdd(Context.ConnectionId, new HubUsers { diff --git a/src/Ombi.Hubs/Ombi.Hubs.csproj b/src/Ombi.Hubs/Ombi.Hubs.csproj index 69a439574..1f994b552 100644 --- a/src/Ombi.Hubs/Ombi.Hubs.csproj +++ b/src/Ombi.Hubs/Ombi.Hubs.csproj @@ -1,7 +1,8 @@  - netstandard2.1 + net5.0 + 8.0 diff --git a/src/Ombi.Mapping/AutoMapperProfile.cs b/src/Ombi.Mapping/AutoMapperProfile.cs index a39bc8e71..1625d7000 100644 --- a/src/Ombi.Mapping/AutoMapperProfile.cs +++ b/src/Ombi.Mapping/AutoMapperProfile.cs @@ -2,8 +2,10 @@ using System.Collections.Generic; using System.Linq; using System.Reflection; +using AutoMapper; using AutoMapper.Configuration; using Microsoft.Extensions.DependencyInjection; +using Ombi.Mapping.Profiles; namespace Ombi.Mapping { @@ -11,18 +13,17 @@ namespace Ombi.Mapping { public static IServiceCollection AddOmbiMappingProfile(this IServiceCollection services) { - Assembly ass = typeof(AutoMapperProfile).GetTypeInfo().Assembly; - var assemblies = new List(); - foreach (TypeInfo ti in ass.DefinedTypes) + var profiles = new List { - if (ti.ImplementedInterfaces.Contains(typeof(IProfileConfiguration))) - { - assemblies.Add(ti.AsType()); - } - } + new MovieProfile(), + new OmbiProfile(), + new SettingsProfile(), + new TvProfile(), + new TvProfileV2() + }; var config = new AutoMapper.MapperConfiguration(cfg => { - cfg.AddProfiles(assemblies); + cfg.AddProfiles(profiles); }); var mapper = config.CreateMapper(); diff --git a/src/Ombi.Mapping/Ombi.Mapping.csproj b/src/Ombi.Mapping/Ombi.Mapping.csproj index 94c8c42d7..cd0ee4724 100644 --- a/src/Ombi.Mapping/Ombi.Mapping.csproj +++ b/src/Ombi.Mapping/Ombi.Mapping.csproj @@ -1,17 +1,18 @@  - netstandard2.1 + net5.0 3.0.0.0 3.0.0.0 + 8.0 - - - + + + diff --git a/src/Ombi.Mapping/Profiles/SettingsProfile.cs b/src/Ombi.Mapping/Profiles/SettingsProfile.cs index f460ce78b..3c27fff7e 100644 --- a/src/Ombi.Mapping/Profiles/SettingsProfile.cs +++ b/src/Ombi.Mapping/Profiles/SettingsProfile.cs @@ -20,6 +20,9 @@ namespace Ombi.Mapping.Profiles CreateMap().ReverseMap(); CreateMap().ReverseMap(); CreateMap().ReverseMap(); + CreateMap().ReverseMap(); + CreateMap().ReverseMap(); + CreateMap().ReverseMap(); } } } \ No newline at end of file diff --git a/src/Ombi.Mapping/Profiles/TvProfile.cs b/src/Ombi.Mapping/Profiles/TvProfile.cs index 0e8264a71..8cb4e38b6 100644 --- a/src/Ombi.Mapping/Profiles/TvProfile.cs +++ b/src/Ombi.Mapping/Profiles/TvProfile.cs @@ -56,8 +56,10 @@ namespace Ombi.Mapping.Profiles .ForMember(dest => dest.Runtime, opts => opts.MapFrom(src => src.Runtime.ToString())) .ForMember(dest => dest.Title, opts => opts.MapFrom(src => src.Title)) .ForMember(dest => dest.Status, opts => opts.MapFrom(src => TraktEnumHelper.GetDescription(src.Status))) - .ForMember(dest => dest.Trailer, opts => opts.MapFrom(src => src.Trailer)) - .ForMember(dest => dest.Homepage, opts => opts.MapFrom(src => src.Homepage)); + .ForMember(dest => dest.Trailer, + opts => opts.MapFrom(src => src.Trailer.ToString().ToHttpsUrl())) + .ForMember(dest => dest.Homepage, + opts => opts.MapFrom(src => src.Homepage.ToString().ToHttpsUrl())); } } } \ No newline at end of file diff --git a/src/Ombi.Mapping/Profiles/TvProfileV2.cs b/src/Ombi.Mapping/Profiles/TvProfileV2.cs index 3a8aeeb62..5ee0645fd 100644 --- a/src/Ombi.Mapping/Profiles/TvProfileV2.cs +++ b/src/Ombi.Mapping/Profiles/TvProfileV2.cs @@ -30,7 +30,7 @@ namespace Ombi.Mapping.Profiles .ForMember(dest => dest.Banner, opts => opts.MapFrom(src => !string.IsNullOrEmpty(src.image.medium) - ? src.image.medium.Replace("http", "https") + ? src.image.medium.ToHttpsUrl() : string.Empty)) .ForMember(dest => dest.Status, opts => opts.MapFrom(src => src.status)); @@ -45,8 +45,8 @@ namespace Ombi.Mapping.Profiles .ForMember(dest => dest.Timezone, opts => opts.MapFrom(src => src.timezone)); CreateMap() - .ForMember(dest => dest.Medium, opts => opts.MapFrom(src => src.medium)) - .ForMember(dest => dest.Original, opts => opts.MapFrom(src => src.original)); + .ForMember(dest => dest.Medium, opts => opts.MapFrom(src => src.medium.ToHttpsUrl())) + .ForMember(dest => dest.Original, opts => opts.MapFrom(src => src.original.ToHttpsUrl())); CreateMap() .ForMember(dest => dest.Character, opts => opts.MapFrom(src => src.character)) @@ -58,7 +58,7 @@ namespace Ombi.Mapping.Profiles .ForMember(dest => dest.Id, opts => opts.MapFrom(src => src.id)) .ForMember(dest => dest.Name, opts => opts.MapFrom(src => src.name)) .ForMember(dest => dest.Image, opts => opts.MapFrom(src => src.image)) - .ForMember(dest => dest.Url, opts => opts.MapFrom(src => src.url)); + .ForMember(dest => dest.Url, opts => opts.MapFrom(src => src.url.ToHttpsUrl())); CreateMap() .ForMember(dest => dest.Person, opts => opts.MapFrom(src => src.person)) @@ -73,7 +73,7 @@ namespace Ombi.Mapping.Profiles CreateMap() .ForMember(dest => dest.Name, opts => opts.MapFrom(src => src.name)) .ForMember(dest => dest.Id, opts => opts.MapFrom(src => src.id)) - .ForMember(dest => dest.Url, opts => opts.MapFrom(src => src.url)) + .ForMember(dest => dest.Url, opts => opts.MapFrom(src => src.url.ToHttpsUrl())) .ForMember(dest => dest.Image, opts => opts.MapFrom(src => src.image)); CreateMap().ReverseMap(); diff --git a/src/Ombi.Notifications.Templates/EmailBasicTemplate.cs b/src/Ombi.Notifications.Templates/EmailBasicTemplate.cs index fc80de193..b8d76e10d 100644 --- a/src/Ombi.Notifications.Templates/EmailBasicTemplate.cs +++ b/src/Ombi.Notifications.Templates/EmailBasicTemplate.cs @@ -13,7 +13,7 @@ namespace Ombi.Notifications.Templates if (string.IsNullOrEmpty(_templateLocation)) { #if DEBUG - _templateLocation = Path.Combine(Directory.GetCurrentDirectory(), "bin", "Debug", "netcoreapp2.2", "Templates", + _templateLocation = Path.Combine(Directory.GetCurrentDirectory(), "bin", "Debug", "netcoreapp3.1", "Templates", "BasicTemplate.html"); #else _templateLocation = Path.Combine(Directory.GetCurrentDirectory(), "Templates","BasicTemplate.html"); diff --git a/src/Ombi.Notifications.Templates/NewsletterTemplate.cs b/src/Ombi.Notifications.Templates/NewsletterTemplate.cs index 389ff5cd6..84d92c21c 100644 --- a/src/Ombi.Notifications.Templates/NewsletterTemplate.cs +++ b/src/Ombi.Notifications.Templates/NewsletterTemplate.cs @@ -13,7 +13,7 @@ namespace Ombi.Notifications.Templates if (string.IsNullOrEmpty(_templateLocation)) { #if DEBUG - _templateLocation = Path.Combine(Directory.GetCurrentDirectory(), "bin", "Debug", "netcoreapp2.0", "Templates", "NewsletterTemplate.html"); + _templateLocation = Path.Combine(Directory.GetCurrentDirectory(), "bin", "Debug", "netcoreapp3.0", "Templates", "NewsletterTemplate.html"); #else _templateLocation = Path.Combine(Directory.GetCurrentDirectory(), "Templates", "NewsletterTemplate.html"); #endif diff --git a/src/Ombi.Notifications.Templates/Ombi.Notifications.Templates.csproj b/src/Ombi.Notifications.Templates/Ombi.Notifications.Templates.csproj index a02def1dc..35adcf7af 100644 --- a/src/Ombi.Notifications.Templates/Ombi.Notifications.Templates.csproj +++ b/src/Ombi.Notifications.Templates/Ombi.Notifications.Templates.csproj @@ -1,11 +1,12 @@  - netstandard2.1 + net5.0 3.0.0.0 3.0.0.0 + 8.0 diff --git a/src/Ombi.Notifications.Tests/Ombi.Notifications.Tests.csproj b/src/Ombi.Notifications.Tests/Ombi.Notifications.Tests.csproj index 8ce8ab43b..469611ac8 100644 --- a/src/Ombi.Notifications.Tests/Ombi.Notifications.Tests.csproj +++ b/src/Ombi.Notifications.Tests/Ombi.Notifications.Tests.csproj @@ -1,14 +1,15 @@  - netcoreapp3.0 + net5.0 - + + diff --git a/src/Ombi.Notifications/Agents/DiscordNotification.cs b/src/Ombi.Notifications/Agents/DiscordNotification.cs index 77580e5e4..dda10f210 100644 --- a/src/Ombi.Notifications/Agents/DiscordNotification.cs +++ b/src/Ombi.Notifications/Agents/DiscordNotification.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Threading.Tasks; using Microsoft.Extensions.Logging; using Ombi.Api.Discord; @@ -104,21 +105,92 @@ namespace Ombi.Notifications.Agents username = settings.Username, }; - string image; - if (model.Other.TryGetValue("image", out image)) + var fields = new List(); + + if (model.Data.TryGetValue("Alias", out var alias)) + { + if (alias.HasValue()) + { + fields.Add(new DiscordField { name = "Requested By", value = alias, inline = true }); + } + } + else { - discordBody.embeds = new List + if (model.Data.TryGetValue("RequestedUser", out var requestedUser)) { - new DiscordEmbeds + if (requestedUser.HasValue()) { - image = new DiscordImage - { - url = image - } + fields.Add(new DiscordField { name = "Requested By", value = requestedUser, inline = true }); } - }; + } + } + if (model.Data.TryGetValue("DenyReason", out var denyReason)) + { + if (denyReason.HasValue()) + { + fields.Add(new DiscordField { name = "Denied Reason", value = denyReason, inline = true }); + } + } + + string color = null; + if (model.Data.TryGetValue("RequestStatus", out var status)) + { + if (status.HasValue()) + { + fields.Add(new DiscordField { name = "Status", value = status, inline = true }); + + color = status switch + { + "Available" => "51283", + "Denied" => "13959168", + "Processing Request" => "37354", + "Pending Approval" => "16754470", + _ => throw new ArgumentOutOfRangeException(nameof(color)) + }; + } + } + + var author = new DiscordAuthor + { + iconurl = settings.Icon.HasValue() ? settings.Icon : string.Empty + }; + + if (model.Data.TryGetValue("ApplicationUrl", out var appUrl)) + { + author.url = appUrl; } + if (model.Data.TryGetValue("ApplicationName", out var appName)) + { + author.name = appName; + } + + + var embed = new DiscordEmbeds + { + fields = fields, + author = author, + color = color + }; + + if (model.Data.TryGetValue("Title", out var title)) + { + embed.title = title; + } + if (model.Data.TryGetValue("Overview", out var overview)) + { + embed.description = overview; + } + string image; + if (model.Other.TryGetValue("image", out image)) + { + embed.thumbnail = new DiscordImage { url = image }; + } + + if (model.Data.Any()) + { + discordBody.embeds = new List { embed }; + } await Api.SendMessage(discordBody, settings.WebHookId, settings.Token); } catch (Exception e) @@ -148,6 +220,7 @@ namespace Ombi.Notifications.Agents var notification = new NotificationMessage { Message = parsed.Message, + Data = parsed.Data.ToDictionary(x => x.Key, x => x.Value) }; notification.Other.Add("image", parsed.Image); await Send(notification, settings); diff --git a/src/Ombi.Notifications/Agents/Interfaces/ILegacyMobileNotification.cs b/src/Ombi.Notifications/Agents/Interfaces/ILegacyMobileNotification.cs new file mode 100644 index 000000000..d0d6db725 --- /dev/null +++ b/src/Ombi.Notifications/Agents/Interfaces/ILegacyMobileNotification.cs @@ -0,0 +1,6 @@ +namespace Ombi.Notifications.Agents +{ + public interface ILegacyMobileNotification : INotification + { + } +} \ No newline at end of file diff --git a/src/Ombi.Notifications/Agents/Interfaces/IMobileNotification.cs b/src/Ombi.Notifications/Agents/Interfaces/IMobileNotification.cs index 1daf7e46a..d4d085dd6 100644 --- a/src/Ombi.Notifications/Agents/Interfaces/IMobileNotification.cs +++ b/src/Ombi.Notifications/Agents/Interfaces/IMobileNotification.cs @@ -1,6 +1,8 @@ -namespace Ombi.Notifications.Agents + +namespace Ombi.Notifications.Agents { public interface IMobileNotification : INotification { + } } \ No newline at end of file diff --git a/src/Ombi.Notifications/Agents/Interfaces/IWebhookNotification.cs b/src/Ombi.Notifications/Agents/Interfaces/IWebhookNotification.cs new file mode 100644 index 000000000..303229878 --- /dev/null +++ b/src/Ombi.Notifications/Agents/Interfaces/IWebhookNotification.cs @@ -0,0 +1,6 @@ +namespace Ombi.Notifications.Agents +{ + public interface IWebhookNotification : INotification + { + } +} \ No newline at end of file diff --git a/src/Ombi.Notifications/Agents/LegacyMobileNotification.cs b/src/Ombi.Notifications/Agents/LegacyMobileNotification.cs new file mode 100644 index 000000000..5ac92d5bf --- /dev/null +++ b/src/Ombi.Notifications/Agents/LegacyMobileNotification.cs @@ -0,0 +1,320 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Identity; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Logging; +using Ombi.Api.Notifications; +using Ombi.Core.Settings; +using Ombi.Helpers; +using Ombi.Notifications.Models; +using Ombi.Settings.Settings.Models; +using Ombi.Settings.Settings.Models.Notifications; +using Ombi.Store.Entities; +using Ombi.Store.Entities.Requests; +using Ombi.Store.Repository; +using Ombi.Store.Repository.Requests; + +namespace Ombi.Notifications.Agents +{ + public class LegacyMobileNotification : BaseNotification, ILegacyMobileNotification + { + public LegacyMobileNotification(IOneSignalApi api, ISettingsService sn, ILogger log, INotificationTemplatesRepository r, + IMovieRequestRepository m, ITvRequestRepository t, ISettingsService s, IRepository notification, + UserManager um, IRepository sub, IMusicRequestRepository music, IRepository issueRepository, + IRepository userPref) : base(sn, r, m, t, s, log, sub, music, userPref) + { + _api = api; + _logger = log; + _notifications = notification; + _userManager = um; + _issueRepository = issueRepository; + } + + public override string NotificationName => "LegacyMobileNotification"; + + private readonly IOneSignalApi _api; + private readonly ILogger _logger; + private readonly IRepository _notifications; + private readonly UserManager _userManager; + private readonly IRepository _issueRepository; + + protected override bool ValidateConfiguration(MobileNotificationSettings settings) + { + return true; + } + + protected override async Task NewRequest(NotificationOptions model, MobileNotificationSettings settings) + { + var parsed = await LoadTemplate(NotificationAgent.Mobile, NotificationType.NewRequest, model); + if (parsed.Disabled) + { + _logger.LogInformation($"Template {NotificationType.NewRequest} is disabled for {NotificationAgent.Mobile}"); + return; + } + var notification = new NotificationMessage + { + Message = parsed.Message, + }; + + // Get admin devices + var playerIds = await GetAdmins(NotificationType.NewRequest); + await Send(playerIds, notification, settings, model, true); + } + + protected override async Task NewIssue(NotificationOptions model, MobileNotificationSettings settings) + { + var parsed = await LoadTemplate(NotificationAgent.Mobile, NotificationType.Issue, model); + if (parsed.Disabled) + { + _logger.LogInformation($"Template {NotificationType.Issue} is disabled for {NotificationAgent.Mobile}"); + return; + } + var notification = new NotificationMessage + { + Message = parsed.Message, + }; + + // Get admin devices + var playerIds = await GetAdmins(NotificationType.Issue); + await Send(playerIds, notification, settings, model); + } + + protected override async Task IssueComment(NotificationOptions model, MobileNotificationSettings settings) + { + var parsed = await LoadTemplate(NotificationAgent.Mobile, NotificationType.IssueComment, model); + if (parsed.Disabled) + { + _logger.LogInformation($"Template {NotificationType.IssueComment} is disabled for {NotificationAgent.Mobile}"); + return; + } + var notification = new NotificationMessage + { + Message = parsed.Message, + }; + if (model.Substitutes.TryGetValue("AdminComment", out var isAdminString)) + { + var isAdmin = bool.Parse(isAdminString); + if (isAdmin) + { + model.Substitutes.TryGetValue("IssueId", out var issueId); + // Send to user + var playerIds = await GetUsersForIssue(model, int.Parse(issueId), NotificationType.IssueComment); + await Send(playerIds, notification, settings, model); + } + else + { + // Send to admin + var playerIds = await GetAdmins(NotificationType.IssueComment); + await Send(playerIds, notification, settings, model); + } + } + } + + protected override async Task IssueResolved(NotificationOptions model, MobileNotificationSettings settings) + { + var parsed = await LoadTemplate(NotificationAgent.Mobile, NotificationType.IssueResolved, model); + if (parsed.Disabled) + { + _logger.LogInformation($"Template {NotificationType.IssueResolved} is disabled for {NotificationAgent.Mobile}"); + return; + } + var notification = new NotificationMessage + { + Message = parsed.Message, + }; + + // Send to user + var playerIds = GetUsers(model, NotificationType.IssueResolved); + + await Send(playerIds, notification, settings, model); + } + + + protected override async Task AddedToRequestQueue(NotificationOptions model, MobileNotificationSettings settings) + { + + var parsed = await LoadTemplate(NotificationAgent.Mobile, NotificationType.ItemAddedToFaultQueue, model); + if (parsed.Disabled) + { + _logger.LogInformation($"Template {NotificationType.ItemAddedToFaultQueue} is disabled for {NotificationAgent.Mobile}"); + return; + } + var notification = new NotificationMessage + { + Message = parsed.Message, + }; + + // Get admin devices + var playerIds = await GetAdmins(NotificationType.Test); + await Send(playerIds, notification, settings, model); + } + + protected override async Task RequestDeclined(NotificationOptions model, MobileNotificationSettings settings) + { + var parsed = await LoadTemplate(NotificationAgent.Mobile, NotificationType.RequestDeclined, model); + if (parsed.Disabled) + { + _logger.LogInformation($"Template {NotificationType.RequestDeclined} is disabled for {NotificationAgent.Mobile}"); + return; + } + var notification = new NotificationMessage + { + Message = parsed.Message, + }; + + // Send to user + var playerIds = GetUsers(model, NotificationType.RequestDeclined); + await AddSubscribedUsers(playerIds); + await Send(playerIds, notification, settings, model); + } + + protected override async Task RequestApproved(NotificationOptions model, MobileNotificationSettings settings) + { + var parsed = await LoadTemplate(NotificationAgent.Mobile, NotificationType.RequestApproved, model); + if (parsed.Disabled) + { + _logger.LogInformation($"Template {NotificationType.RequestApproved} is disabled for {NotificationAgent.Mobile}"); + return; + } + var notification = new NotificationMessage + { + Message = parsed.Message, + }; + + // Send to user + var playerIds = GetUsers(model, NotificationType.RequestApproved); + + await AddSubscribedUsers(playerIds); + await Send(playerIds, notification, settings, model); + } + + protected override async Task AvailableRequest(NotificationOptions model, MobileNotificationSettings settings) + { + var parsed = await LoadTemplate(NotificationAgent.Mobile, NotificationType.RequestAvailable, model); + if (parsed.Disabled) + { + _logger.LogInformation($"Template {NotificationType.RequestAvailable} is disabled for {NotificationAgent.Mobile}"); + return; + } + var notification = new NotificationMessage + { + Message = parsed.Message, + }; + // Send to user + var playerIds = GetUsers(model, NotificationType.RequestAvailable); + + await AddSubscribedUsers(playerIds); + await Send(playerIds, notification, settings, model); + } + protected override Task Send(NotificationMessage model, MobileNotificationSettings settings) + { + throw new NotImplementedException(); + } + + protected async Task Send(List playerIds, NotificationMessage model, MobileNotificationSettings settings, NotificationOptions requestModel, bool isAdminNotification = false) + { + if (playerIds == null || !playerIds.Any()) + { + return; + } + var response = await _api.PushNotification(playerIds, model.Message, isAdminNotification, requestModel.RequestId, (int)requestModel.RequestType); + _logger.LogDebug("Sent message to {0} recipients with message id {1}", response.recipients, response.id); + } + + protected override async Task Test(NotificationOptions model, MobileNotificationSettings settings) + { + var message = $"This is a test from Ombi, if you can see this then we have successfully pushed a notification!"; + var notification = new NotificationMessage + { + Message = message, + }; + // Send to user + var user = await _userManager.Users.Include(x => x.NotificationUserIds).FirstOrDefaultAsync(x => x.Id.Equals(model.UserId)); + if (user == null) + { + return; + } + + var playerIds = user.NotificationUserIds.Select(x => x.PlayerId).ToList(); + await Send(playerIds, notification, settings, model); + } + + private async Task> GetAdmins(NotificationType type) + { + var adminUsers = (await _userManager.GetUsersInRoleAsync(OmbiRoles.Admin)).Select(x => x.Id).ToList(); + var notificationUsers = _notifications.GetAll().Include(x => x.User).Where(x => adminUsers.Contains(x.UserId)); + var playerIds = await notificationUsers.Select(x => x.PlayerId).ToListAsync(); + if (!playerIds.Any()) + { + _logger.LogInformation( + $"there are no admins to send a notification for {type}, for agent {NotificationAgent.Mobile}"); + return null; + } + return playerIds; + } + + private List GetUsers(NotificationOptions model, NotificationType type) + { + var notificationIds = new List(); + if (MovieRequest != null || TvRequest != null) + { + notificationIds = model.RequestType == RequestType.Movie + ? MovieRequest?.RequestedUser?.NotificationUserIds + : TvRequest?.RequestedUser?.NotificationUserIds; + } + if (model.UserId.HasValue() && (!notificationIds?.Any() ?? true)) + { + var user = _userManager.Users.Include(x => x.NotificationUserIds).FirstOrDefault(x => x.Id == model.UserId); + notificationIds = user.NotificationUserIds; + } + + if (!notificationIds?.Any() ?? true) + { + _logger.LogInformation( + $"there are no users to send a notification for {type}, for agent {NotificationAgent.Mobile}"); + return null; + } + var playerIds = notificationIds.Select(x => x.PlayerId).ToList(); + return playerIds; + } + + private async Task> GetUsersForIssue(NotificationOptions model, int issueId, NotificationType type) + { + var notificationIds = new List(); + + var issue = await _issueRepository.GetAll() + .FirstOrDefaultAsync(x => x.Id == issueId); + + // Get the user that raised the issue to send the notification to + var userRaised = await _userManager.Users.Include(x => x.NotificationUserIds).FirstOrDefaultAsync(x => x.Id == issue.UserReportedId); + + notificationIds = userRaised.NotificationUserIds; + + if (!notificationIds?.Any() ?? true) + { + _logger.LogInformation( + $"there are no users to send a notification for {type}, for agent {NotificationAgent.Mobile}"); + return null; + } + var playerIds = notificationIds.Select(x => x.PlayerId).ToList(); + return playerIds; + } + + private async Task AddSubscribedUsers(List playerIds) + { + if (await SubsribedUsers.AnyAsync()) + { + foreach (var user in SubsribedUsers) + { + var notificationId = user.NotificationUserIds; + if (notificationId.Any()) + { + playerIds.AddRange(notificationId.Select(x => x.PlayerId)); + } + } + } + } + } +} \ No newline at end of file diff --git a/src/Ombi.Notifications/Agents/MobileNotification.cs b/src/Ombi.Notifications/Agents/MobileNotification.cs index 363029190..61526802c 100644 --- a/src/Ombi.Notifications/Agents/MobileNotification.cs +++ b/src/Ombi.Notifications/Agents/MobileNotification.cs @@ -5,7 +5,7 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Identity; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; -using Ombi.Api.Notifications; +using Ombi.Api.CloudService; using Ombi.Core.Settings; using Ombi.Helpers; using Ombi.Notifications.Models; @@ -20,8 +20,8 @@ namespace Ombi.Notifications.Agents { public class MobileNotification : BaseNotification, IMobileNotification { - public MobileNotification(IOneSignalApi api, ISettingsService sn, ILogger log, INotificationTemplatesRepository r, - IMovieRequestRepository m, ITvRequestRepository t, ISettingsService s, IRepository notification, + public MobileNotification(ICloudMobileNotification api, ISettingsService sn, ILogger log, INotificationTemplatesRepository r, + IMovieRequestRepository m, ITvRequestRepository t, ISettingsService s, IRepository notification, UserManager um, IRepository sub, IMusicRequestRepository music, IRepository issueRepository, IRepository userPref) : base(sn, r, m, t, s, log, sub, music, userPref) { @@ -34,9 +34,9 @@ namespace Ombi.Notifications.Agents public override string NotificationName => "MobileNotification"; - private readonly IOneSignalApi _api; - private readonly ILogger _logger; - private readonly IRepository _notifications; + private readonly ICloudMobileNotification _api; + private readonly ILogger _logger; + private readonly IRepository _notifications; private readonly UserManager _userManager; private readonly IRepository _issueRepository; @@ -53,9 +53,11 @@ namespace Ombi.Notifications.Agents _logger.LogInformation($"Template {NotificationType.NewRequest} is disabled for {NotificationAgent.Mobile}"); return; } + var notification = new NotificationMessage { Message = parsed.Message, + Data = GetNotificationData(parsed, NotificationType.NewRequest) }; // Get admin devices @@ -74,6 +76,7 @@ namespace Ombi.Notifications.Agents var notification = new NotificationMessage { Message = parsed.Message, + Data = GetNotificationData(parsed, NotificationType.Issue) }; // Get admin devices @@ -92,6 +95,7 @@ namespace Ombi.Notifications.Agents var notification = new NotificationMessage { Message = parsed.Message, + Data = GetNotificationData(parsed, NotificationType.IssueComment) }; if (model.Substitutes.TryGetValue("AdminComment", out var isAdminString)) { @@ -123,6 +127,7 @@ namespace Ombi.Notifications.Agents var notification = new NotificationMessage { Message = parsed.Message, + Data = GetNotificationData(parsed, NotificationType.IssueResolved) }; // Send to user @@ -144,6 +149,7 @@ namespace Ombi.Notifications.Agents var notification = new NotificationMessage { Message = parsed.Message, + Data = GetNotificationData(parsed, NotificationType.ItemAddedToFaultQueue) }; // Get admin devices @@ -162,6 +168,7 @@ namespace Ombi.Notifications.Agents var notification = new NotificationMessage { Message = parsed.Message, + Data = GetNotificationData(parsed, NotificationType.RequestDeclined) }; // Send to user @@ -181,6 +188,7 @@ namespace Ombi.Notifications.Agents var notification = new NotificationMessage { Message = parsed.Message, + Data = GetNotificationData(parsed, NotificationType.RequestApproved) }; // Send to user @@ -198,9 +206,13 @@ namespace Ombi.Notifications.Agents _logger.LogInformation($"Template {NotificationType.RequestAvailable} is disabled for {NotificationAgent.Mobile}"); return; } + + var data = GetNotificationData(parsed, NotificationType.RequestAvailable); + var notification = new NotificationMessage { Message = parsed.Message, + Data = data }; // Send to user var playerIds = GetUsers(model, NotificationType.RequestAvailable); @@ -208,6 +220,14 @@ namespace Ombi.Notifications.Agents await AddSubscribedUsers(playerIds); await Send(playerIds, notification, settings, model); } + + private static Dictionary GetNotificationData(NotificationMessageContent parsed, NotificationType type) + { + var notificationData = parsed.Data.ToDictionary(x => x.Key, x => x.Value); + notificationData[nameof(NotificationType)] = type.ToString(); + return notificationData; + } + protected override Task Send(NotificationMessage model, MobileNotificationSettings settings) { throw new NotImplementedException(); @@ -219,8 +239,18 @@ namespace Ombi.Notifications.Agents { return; } - var response = await _api.PushNotification(playerIds, model.Message, isAdminNotification, requestModel.RequestId, (int)requestModel.RequestType); - _logger.LogDebug("Sent message to {0} recipients with message id {1}", response.recipients, response.id); + foreach (var token in playerIds) + { + await _api.SendMessage(new MobileNotificationRequest() + { + Body = model.Message, + Title = model.Subject, + To = token, + Data = new Dictionary(model.Data) + }); + } + + _logger.LogDebug("Sent message to {0} recipients", playerIds.Count); } protected override async Task Test(NotificationOptions model, MobileNotificationSettings settings) @@ -245,7 +275,7 @@ namespace Ombi.Notifications.Agents { var adminUsers = (await _userManager.GetUsersInRoleAsync(OmbiRoles.Admin)).Select(x => x.Id).ToList(); var notificationUsers = _notifications.GetAll().Include(x => x.User).Where(x => adminUsers.Contains(x.UserId)); - var playerIds = await notificationUsers.Select(x => x.PlayerId).ToListAsync(); + var playerIds = await notificationUsers.Select(x => x.Token).ToListAsync(); if (!playerIds.Any()) { _logger.LogInformation( @@ -306,7 +336,7 @@ namespace Ombi.Notifications.Agents { if (await SubsribedUsers.AnyAsync()) { - foreach (var user in SubsribedUsers.Include(x => x.NotificationUserIds)) + foreach (var user in SubsribedUsers) { var notificationId = user.NotificationUserIds; if (notificationId.Any()) diff --git a/src/Ombi.Notifications/Agents/WebhookNotification.cs b/src/Ombi.Notifications/Agents/WebhookNotification.cs new file mode 100644 index 000000000..2339b6abf --- /dev/null +++ b/src/Ombi.Notifications/Agents/WebhookNotification.cs @@ -0,0 +1,123 @@ +using System; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using Ombi.Api.Webhook; +using Ombi.Core.Settings; +using Ombi.Helpers; +using Ombi.Notifications.Models; +using Ombi.Settings.Settings.Models; +using Ombi.Settings.Settings.Models.Notifications; +using Ombi.Store.Entities; +using Ombi.Store.Repository; +using Ombi.Store.Repository.Requests; + +namespace Ombi.Notifications.Agents +{ + public class WebhookNotification : BaseNotification, IWebhookNotification + { + public WebhookNotification(IWebhookApi api, ISettingsService sn, ILogger log, INotificationTemplatesRepository r, IMovieRequestRepository m, ITvRequestRepository t, + ISettingsService s, IRepository sub, IMusicRequestRepository music, + IRepository userPref) : base(sn, r, m, t, s, log, sub, music, userPref) + { + Api = api; + Logger = log; + } + + public override string NotificationName => "WebhookNotification"; + + private IWebhookApi Api { get; } + private ILogger Logger { get; } + + protected override bool ValidateConfiguration(WebhookSettings settings) + { + return settings.Enabled && !string.IsNullOrEmpty(settings.WebhookUrl); + } + + protected override async Task NewRequest(NotificationOptions model, WebhookSettings settings) + { + await Run(model, settings, NotificationType.NewRequest); + } + + + protected override async Task NewIssue(NotificationOptions model, WebhookSettings settings) + { + await Run(model, settings, NotificationType.Issue); + } + + protected override async Task IssueComment(NotificationOptions model, WebhookSettings settings) + { + await Run(model, settings, NotificationType.IssueComment); + } + + protected override async Task IssueResolved(NotificationOptions model, WebhookSettings settings) + { + await Run(model, settings, NotificationType.IssueResolved); + } + + protected override async Task AddedToRequestQueue(NotificationOptions model, WebhookSettings settings) + { + await Run(model, settings, NotificationType.ItemAddedToFaultQueue); + } + + protected override async Task RequestDeclined(NotificationOptions model, WebhookSettings settings) + { + await Run(model, settings, NotificationType.RequestDeclined); + } + + protected override async Task RequestApproved(NotificationOptions model, WebhookSettings settings) + { + await Run(model, settings, NotificationType.RequestApproved); + } + + protected override async Task AvailableRequest(NotificationOptions model, WebhookSettings settings) + { + await Run(model, settings, NotificationType.RequestAvailable); + } + + protected override async Task Send(NotificationMessage model, WebhookSettings settings) + { + try + { + await Api.PushAsync(settings.WebhookUrl, settings.ApplicationToken, model.Data); + } + catch (Exception e) + { + Logger.LogError(LoggingEvents.WebhookNotification, e, "Failed to send webhook notification"); + } + } + + protected override async Task Test(NotificationOptions model, WebhookSettings settings) + { + var c = new NotificationMessageCurlys(); + + var testData = c.Curlys.ToDictionary(x => x.Key, x => x.Value); + testData[nameof(NotificationType)] = NotificationType.Test.ToString(); + var notification = new NotificationMessage + { + Data = testData, + }; + + await Send(notification, settings); + } + + private async Task Run(NotificationOptions model, WebhookSettings settings, NotificationType type) + { + var parsed = await LoadTemplate(NotificationAgent.Webhook, type, model); + if (parsed.Disabled) + { + Logger.LogInformation($"Template {type} is disabled for {NotificationAgent.Webhook}"); + return; + } + + var notificationData = parsed.Data.ToDictionary(x => x.Key, x => x.Value); + notificationData[nameof(NotificationType)] = type.ToString(); + var notification = new NotificationMessage + { + Data = notificationData, + }; + + await Send(notification, settings); + } + } +} diff --git a/src/Ombi.Notifications/Agents/WhatsAppNotification.cs b/src/Ombi.Notifications/Agents/WhatsAppNotification.cs new file mode 100644 index 000000000..0f0cd5d09 --- /dev/null +++ b/src/Ombi.Notifications/Agents/WhatsAppNotification.cs @@ -0,0 +1,127 @@ +using System; +using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using Ombi.Core.Settings; +using Ombi.Helpers; +using Ombi.Notifications.Models; +using Ombi.Settings.Settings.Models; +using Ombi.Settings.Settings.Models.Notifications; +using Ombi.Store.Entities; +using Ombi.Store.Repository; +using Ombi.Store.Repository.Requests; +using Ombi.Api.Twilio; + +namespace Ombi.Notifications.Agents +{ + public class WhatsAppNotification : BaseNotification + { + public WhatsAppNotification(IWhatsAppApi api, ISettingsService sn, ILogger log, + INotificationTemplatesRepository r, IMovieRequestRepository m, + ITvRequestRepository t, ISettingsService s + , IRepository sub, IMusicRequestRepository music, + IRepository userPref) : base(sn, r, m, t,s,log, sub, music, userPref) + { + Api = api; + Logger = log; + } + + public override string NotificationName => "WhatsAppNotification"; + + private IWhatsAppApi Api { get; } + private ILogger Logger { get; } + + protected override bool ValidateConfiguration(TwilioSettings settings) + { + if (!settings?.WhatsAppSettings?.Enabled ?? false) + { + return false; + } + return (!settings.WhatsAppSettings?.AccountSid?.IsNullOrEmpty() ?? false) + && (!settings.WhatsAppSettings?.AuthToken?.IsNullOrEmpty() ?? false) + && (!settings.WhatsAppSettings?.From?.IsNullOrEmpty() ?? false); + } + + protected override async Task NewRequest(NotificationOptions model, TwilioSettings settings) + { + await Run(model, settings, NotificationType.NewRequest); + } + + protected override async Task NewIssue(NotificationOptions model, TwilioSettings settings) + { + await Run(model, settings, NotificationType.Issue); + } + + protected override async Task IssueComment(NotificationOptions model, TwilioSettings settings) + { + await Run(model, settings, NotificationType.IssueComment); + } + + protected override async Task IssueResolved(NotificationOptions model, TwilioSettings settings) + { + await Run(model, settings, NotificationType.IssueResolved); + } + + protected override async Task AddedToRequestQueue(NotificationOptions model, TwilioSettings settings) + { + await Run(model, settings, NotificationType.ItemAddedToFaultQueue); + } + + protected override async Task RequestDeclined(NotificationOptions model, TwilioSettings settings) + { + await Run(model, settings, NotificationType.RequestDeclined); + } + + protected override async Task RequestApproved(NotificationOptions model, TwilioSettings settings) + { + await Run(model, settings, NotificationType.RequestApproved); + } + + protected override async Task AvailableRequest(NotificationOptions model, TwilioSettings settings) + { + await Run(model, settings, NotificationType.RequestAvailable); + } + + protected override async Task Send(NotificationMessage model, TwilioSettings settings) + { + try + { + var whatsApp = new WhatsAppModel + { + Message = model.Message, + From = settings.WhatsAppSettings.From, + To = ""// TODO + }; + await Api.SendMessage(whatsApp, settings.WhatsAppSettings.AccountSid, settings.WhatsAppSettings.AuthToken); + } + catch (Exception e) + { + Logger.LogError(LoggingEvents.WhatsApp, e, "Failed to send WhatsApp Notification"); + } + } + + protected override async Task Test(NotificationOptions model, TwilioSettings settings) + { + var message = $"This is a test from Ombi, if you can see this then we have successfully pushed a notification!"; + var notification = new NotificationMessage + { + Message = message, + }; + await Send(notification, settings); + } + + private async Task Run(NotificationOptions model, TwilioSettings settings, NotificationType type) + { + var parsed = await LoadTemplate(NotificationAgent.WhatsApp, type, model); + if (parsed.Disabled) + { + Logger.LogInformation($"Template {type} is disabled for {NotificationAgent.WhatsApp}"); + return; + } + var notification = new NotificationMessage + { + Message = parsed.Message, + }; + await Send(notification, settings); + } + } +} diff --git a/src/Ombi.Notifications/BaseNotification.cs b/src/Ombi.Notifications/BaseNotification.cs index c9404eb2c..465ccd22c 100644 --- a/src/Ombi.Notifications/BaseNotification.cs +++ b/src/Ombi.Notifications/BaseNotification.cs @@ -191,7 +191,7 @@ namespace Ombi.Notifications protected IQueryable GetSubscriptions(int requestId, RequestType type) { - var subs = RequestSubscription.GetAll().Include(x => x.User).Where(x => x.RequestId == requestId && type == x.RequestType); + var subs = RequestSubscription.GetAll().Include(x => x.User).ThenInclude(x => x.NotificationUserIds).Where(x => x.RequestId == requestId && type == x.RequestType); return subs.Select(x => x.User); } diff --git a/src/Ombi.Notifications/Interfaces/INotificationService.cs b/src/Ombi.Notifications/Interfaces/INotificationService.cs index f8731b4af..f6a3761c3 100644 --- a/src/Ombi.Notifications/Interfaces/INotificationService.cs +++ b/src/Ombi.Notifications/Interfaces/INotificationService.cs @@ -1,13 +1,12 @@ using System.Threading.Tasks; using Ombi.Notifications; using Ombi.Notifications.Models; +using Quartz; namespace Ombi.Core.Notifications { - public interface INotificationService + public interface INotificationService : IJob { - Task Publish(NotificationOptions model); - Task Publish(NotificationOptions model, Ombi.Settings.Settings.Models.Settings settings); - Task PublishTest(NotificationOptions model, Ombi.Settings.Settings.Models.Settings settings, INotification type); + } } \ No newline at end of file diff --git a/src/Ombi.Notifications/Models/NotificationMessage.cs b/src/Ombi.Notifications/Models/NotificationMessage.cs index f14604d3f..1e0fbf2d6 100644 --- a/src/Ombi.Notifications/Models/NotificationMessage.cs +++ b/src/Ombi.Notifications/Models/NotificationMessage.cs @@ -9,5 +9,6 @@ namespace Ombi.Notifications.Models public string To { get; set; } public Dictionary Other { get; set; } = new Dictionary(); + public IDictionary Data { get; set; } = new Dictionary(); } } \ No newline at end of file diff --git a/src/Ombi.Notifications/NotificationMessageContent.cs b/src/Ombi.Notifications/NotificationMessageContent.cs index 37f7504e9..901b3bcb2 100644 --- a/src/Ombi.Notifications/NotificationMessageContent.cs +++ b/src/Ombi.Notifications/NotificationMessageContent.cs @@ -1,4 +1,6 @@ -namespace Ombi.Notifications +using System.Collections.Generic; + +namespace Ombi.Notifications { public class NotificationMessageContent { @@ -6,5 +8,6 @@ public string Subject { get; set; } public string Message { get; set; } public string Image { get; set; } + public IReadOnlyDictionary Data { get; set; } } } \ No newline at end of file diff --git a/src/Ombi.Notifications/NotificationMessageCurlys.cs b/src/Ombi.Notifications/NotificationMessageCurlys.cs index bfa8213bc..0aea728a4 100644 --- a/src/Ombi.Notifications/NotificationMessageCurlys.cs +++ b/src/Ombi.Notifications/NotificationMessageCurlys.cs @@ -14,10 +14,12 @@ namespace Ombi.Notifications { public class NotificationMessageCurlys { - public void Setup(NotificationOptions opts, FullBaseRequest req, CustomizationSettings s, UserNotificationPreferences pref) + public void Setup(NotificationOptions opts, MovieRequests req, CustomizationSettings s, UserNotificationPreferences pref) { LoadIssues(opts); - RequestId = req.Id.ToString(); + + RequestId = req?.Id.ToString(); + ProviderId = req?.TheMovieDbId.ToString() ?? string.Empty; string title; if (req == null) { @@ -62,13 +64,17 @@ namespace Ombi.Notifications } AdditionalInformation = opts?.AdditionalInformation ?? string.Empty; + + CalculateRequestStatus(req); } public void Setup(NotificationOptions opts, AlbumRequest req, CustomizationSettings s, UserNotificationPreferences pref) { LoadIssues(opts); - RequestId = req.Id.ToString(); + RequestId = req?.Id.ToString(); + ProviderId = req?.ForeignArtistId ?? string.Empty; + string title; if (req == null) { @@ -104,6 +110,7 @@ namespace Ombi.Notifications PosterImage = (req?.Cover.HasValue() ?? false) ? req.Cover : req?.Disk ?? string.Empty; AdditionalInformation = opts?.AdditionalInformation ?? string.Empty; + CalculateRequestStatus(req); } public void SetupNewsletter(CustomizationSettings s) @@ -115,7 +122,8 @@ namespace Ombi.Notifications public void Setup(NotificationOptions opts, ChildRequests req, CustomizationSettings s, UserNotificationPreferences pref) { LoadIssues(opts); - RequestId = req.Id.ToString(); + RequestId = req?.Id.ToString(); + ProviderId = req?.ParentRequest?.TvDbId.ToString() ?? string.Empty; string title; if (req == null) { @@ -194,6 +202,7 @@ namespace Ombi.Notifications EpisodesList = epSb.ToString(); SeasonsList = seasonSb.ToString(); + CalculateRequestStatus(req); } public void Setup(OmbiUser user, CustomizationSettings s) @@ -217,7 +226,32 @@ namespace Ombi.Notifications Type = opts.Substitutes.TryGetValue("RequestType", out val) ? val.Humanize() : string.Empty; } + private void CalculateRequestStatus(BaseRequest req) + { + RequestStatus = string.Empty; + if (req != null) + { + if (req.Available) + { + RequestStatus = "Available"; + return; + } + if (req.Denied ?? false) + { + RequestStatus = "Denied"; + return; + } + if (!req.Available && req.Approved) + { + RequestStatus = "Processing Request"; + return; + } + RequestStatus = "Pending Approval"; + } + } + // User Defined + public string RequestId { get; set; } public string RequestedUser { get; set; } public string UserName { get; set; } public string IssueUser => UserName; @@ -241,7 +275,8 @@ namespace Ombi.Notifications public string UserPreference { get; set; } public string DenyReason { get; set; } public string AvailableDate { get; set; } - public string RequestId { get; set; } + public string RequestStatus { get; set; } + public string ProviderId { get; set; } // System Defined private string LongDate => DateTime.Now.ToString("D"); @@ -251,6 +286,7 @@ namespace Ombi.Notifications public Dictionary Curlys => new Dictionary { + {nameof(RequestId), RequestId }, {nameof(RequestedUser), RequestedUser }, {nameof(Title), Title }, {nameof(RequestedDate), RequestedDate }, @@ -278,7 +314,8 @@ namespace Ombi.Notifications {nameof(UserPreference),UserPreference}, {nameof(DenyReason),DenyReason}, {nameof(AvailableDate),AvailableDate}, - {nameof(RequestId),RequestId}, + {nameof(RequestStatus),RequestStatus}, + {nameof(ProviderId),ProviderId}, }; } } \ No newline at end of file diff --git a/src/Ombi.Notifications/NotificationMessageResolver.cs b/src/Ombi.Notifications/NotificationMessageResolver.cs index 451ef1b55..fe6102eda 100644 --- a/src/Ombi.Notifications/NotificationMessageResolver.cs +++ b/src/Ombi.Notifications/NotificationMessageResolver.cs @@ -47,7 +47,7 @@ namespace Ombi.Notifications body = ReplaceFields(bodyFields, parameters, body); subject = ReplaceFields(subjectFields, parameters, subject); - return new NotificationMessageContent { Message = body ?? string.Empty, Subject = subject ?? string.Empty}; + return new NotificationMessageContent { Message = body ?? string.Empty, Subject = subject ?? string.Empty, Data = parameters }; } public IEnumerable ProcessConditions(IEnumerable conditionalFields, IReadOnlyDictionary parameters) diff --git a/src/Ombi.Notifications/NotificationService.cs b/src/Ombi.Notifications/NotificationService.cs index c2985a21b..8a24382aa 100644 --- a/src/Ombi.Notifications/NotificationService.cs +++ b/src/Ombi.Notifications/NotificationService.cs @@ -7,78 +7,46 @@ using Microsoft.Extensions.Logging; using Ombi.Core.Notifications; using Ombi.Helpers; using Ombi.Notifications.Models; +using Quartz; namespace Ombi.Notifications { public class NotificationService : INotificationService { + private readonly IServiceProvider _provider; + public NotificationService(IServiceProvider provider, ILogger log) { + _provider = provider; Log = log; NotificationAgents = new List(); - - var baseSearchType = typeof(BaseNotification<>).Name; - - var ass = typeof(NotificationService).GetTypeInfo().Assembly; - - foreach (var ti in ass.DefinedTypes) - { - if (ti?.BaseType?.Name == baseSearchType) - { - var type = ti?.AsType(); - var ctors = type.GetConstructors(); - var ctor = ctors.FirstOrDefault(); - - var services = new List(); - foreach (var param in ctor.GetParameters()) - { - services.Add(provider.GetService(param.ParameterType)); - } - - var item = Activator.CreateInstance(type, services.ToArray()); - NotificationAgents.Add((INotification)item); - } - } + PopulateAgents(); } - + private List NotificationAgents { get; } private ILogger Log { get; } - /// ^ + /// /// Sends a notification to the user. This one is used in normal notification scenarios /// - /// The model. + /// The model. /// - public async Task Publish(NotificationOptions model) + public async Task Execute(IJobExecutionContext context) { - var notificationTasks = new List(); - + JobDataMap dataMap = context.MergedJobDataMap; + var model = (NotificationOptions)dataMap.Get(JobDataKeys.NotificationOptions); + foreach (var agent in NotificationAgents) { - notificationTasks.Add(NotifyAsync(agent,model)); + await NotifyAsync(agent, model); } - await Task.WhenAll(notificationTasks).ConfigureAwait(false); } - /// - /// Sends a notification to the user, this is usually for testing the settings. - /// - /// The model. - /// The settings. - /// - public async Task Publish(NotificationOptions model, Settings.Settings.Models.Settings settings) - { - var notificationTasks = NotificationAgents.Select(notification => NotifyAsync(notification, model, settings)); - - await Task.WhenAll(notificationTasks).ConfigureAwait(false); - } - - private async Task NotifyAsync(INotification notification, NotificationOptions model) { try { - await notification.NotifyAsync(model).ConfigureAwait(false); + await notification.NotifyAsync(model); } catch (Exception ex) { @@ -86,26 +54,31 @@ namespace Ombi.Notifications } } - - private async Task NotifyAsync(INotification notification, NotificationOptions model, Ombi.Settings.Settings.Models.Settings settings) + + private void PopulateAgents() { - if (model.RequestId == 0) - { - throw new ArgumentException("RequestId is not set"); - } - try - { - await notification.NotifyAsync(model, settings).ConfigureAwait(false); - } - catch (Exception ex) + var baseSearchType = typeof(BaseNotification<>).Name; + + var ass = typeof(NotificationService).GetTypeInfo().Assembly; + + foreach (var ti in ass.DefinedTypes) { - throw new InvalidOperationException(ex.Message); - } - } + if (ti?.BaseType?.Name == baseSearchType) + { + var type = ti?.AsType(); + var ctors = type.GetConstructors(); + var ctor = ctors.FirstOrDefault(); - public async Task PublishTest(NotificationOptions model, Ombi.Settings.Settings.Models.Settings settings, INotification type) - { - await type.NotifyAsync(model, settings); + var services = new List(); + foreach (var param in ctor.GetParameters()) + { + services.Add(_provider.GetService(param.ParameterType)); + } + + var item = Activator.CreateInstance(type, services.ToArray()); + NotificationAgents.Add((INotification)item); + } + } } } } \ No newline at end of file diff --git a/src/Ombi.Notifications/Ombi.Notifications.csproj b/src/Ombi.Notifications/Ombi.Notifications.csproj index 3015c150d..798026b47 100644 --- a/src/Ombi.Notifications/Ombi.Notifications.csproj +++ b/src/Ombi.Notifications/Ombi.Notifications.csproj @@ -1,27 +1,31 @@  - netstandard2.1 + net5.0 3.0.0.0 3.0.0.0 + 8.0 - + + + + diff --git a/src/Ombi.Schedule.Tests/IssuesPurgeTests.cs b/src/Ombi.Schedule.Tests/IssuesPurgeTests.cs index 068b00b13..712fdabee 100644 --- a/src/Ombi.Schedule.Tests/IssuesPurgeTests.cs +++ b/src/Ombi.Schedule.Tests/IssuesPurgeTests.cs @@ -9,6 +9,8 @@ using Ombi.Settings.Settings.Models; using Ombi.Store.Entities.Requests; using Ombi.Store.Repository; using System.Threading.Tasks; +using MockQueryable; +using MockQueryable.Moq; namespace Ombi.Schedule.Tests { @@ -49,7 +51,7 @@ namespace Ombi.Schedule.Tests }; Settings.Setup(x => x.GetSettingsAsync()).ReturnsAsync(new IssueSettings { DeleteIssues = true, DaysAfterResolvedToDelete = 5 }); - Repo.Setup(x => x.GetAll()).Returns(new EnumerableQuery(issues)); + Repo.Setup(x => x.GetAll()).Returns(new List(issues).AsQueryable().BuildMock().Object); await Job.Execute(null); Assert.That(issues.First().Status, Is.EqualTo(IssueStatus.Deleted)); @@ -74,7 +76,7 @@ namespace Ombi.Schedule.Tests }; Settings.Setup(x => x.GetSettingsAsync()).ReturnsAsync(new IssueSettings { DeleteIssues = true, DaysAfterResolvedToDelete = 5 }); - Repo.Setup(x => x.GetAll()).Returns(new EnumerableQuery(issues)); + Repo.Setup(x => x.GetAll()).Returns(new EnumerableQuery(issues).AsQueryable().BuildMock().Object); await Job.Execute(null); Assert.That(issues[0].Status, Is.Not.EqualTo(IssueStatus.Deleted)); @@ -100,7 +102,7 @@ namespace Ombi.Schedule.Tests }; Settings.Setup(x => x.GetSettingsAsync()).ReturnsAsync(new IssueSettings { DeleteIssues = true, DaysAfterResolvedToDelete = 5 }); - Repo.Setup(x => x.GetAll()).Returns(new EnumerableQuery(issues)); + Repo.Setup(x => x.GetAll()).Returns(new EnumerableQuery(issues).AsQueryable().BuildMock().Object); await Job.Execute(null); Assert.That(issues[0].Status, Is.Not.EqualTo(IssueStatus.Deleted)); diff --git a/src/Ombi.Schedule.Tests/Ombi.Schedule.Tests.csproj b/src/Ombi.Schedule.Tests/Ombi.Schedule.Tests.csproj index 70a456b6a..003c240f1 100644 --- a/src/Ombi.Schedule.Tests/Ombi.Schedule.Tests.csproj +++ b/src/Ombi.Schedule.Tests/Ombi.Schedule.Tests.csproj @@ -1,27 +1,22 @@  - netcoreapp3.0 + net5.0 - + + - + - - - ..\..\..\..\Program Files\dotnet\sdk\NuGetFallbackFolder\microsoft.aspnetcore.signalr.core\1.1.0\lib\netstandard2.0\Microsoft.AspNetCore.SignalR.Core.dll - - - diff --git a/src/Ombi.Schedule.Tests/OmbiQuartzTests.cs b/src/Ombi.Schedule.Tests/OmbiQuartzTests.cs index fe6a1cb94..70d57e8e7 100644 --- a/src/Ombi.Schedule.Tests/OmbiQuartzTests.cs +++ b/src/Ombi.Schedule.Tests/OmbiQuartzTests.cs @@ -3,6 +3,7 @@ using NUnit.Framework; using Quartz; using System.Threading; using System.Threading.Tasks; +using Ombi.Helpers; namespace Ombi.Schedule.Tests { diff --git a/src/Ombi.Schedule.Tests/PlexAvailabilityCheckerTests.cs b/src/Ombi.Schedule.Tests/PlexAvailabilityCheckerTests.cs index dc5cc06e5..7704b78ac 100644 --- a/src/Ombi.Schedule.Tests/PlexAvailabilityCheckerTests.cs +++ b/src/Ombi.Schedule.Tests/PlexAvailabilityCheckerTests.cs @@ -5,11 +5,11 @@ using System.Linq.Expressions; using System.Threading; using System.Threading.Tasks; using Castle.Components.DictionaryAdapter; -using Hangfire; using Microsoft.AspNetCore.SignalR; using Moq; using MockQueryable.Moq; using NUnit.Framework; +using Ombi.Core; using Ombi.Core.Notifications; using Ombi.Hubs; using Ombi.Schedule.Jobs.Plex; @@ -30,19 +30,19 @@ namespace Ombi.Schedule.Tests _repo = new Mock(); _tv = new Mock(); _movie = new Mock(); - _notify = new Mock(); + _notify = new Mock(); var hub = new Mock>(); hub.Setup(x => x.Clients.Clients(It.IsAny>()).SendCoreAsync(It.IsAny(), It.IsAny(), It.IsAny())); NotificationHub.UsersOnline.TryAdd("A", new HubUsers()); - Checker = new PlexAvailabilityChecker(_repo.Object, _tv.Object, _movie.Object, _notify.Object, new Mock().Object, null, hub.Object); + Checker = new PlexAvailabilityChecker(_repo.Object, _tv.Object, _movie.Object, _notify.Object, null, hub.Object); } private Mock _repo; private Mock _tv; private Mock _movie; - private Mock _notify; + private Mock _notify; private PlexAvailabilityChecker Checker; [Test] diff --git a/src/Ombi.Schedule/IoCJobActivator.cs b/src/Ombi.Schedule/IoCJobActivator.cs deleted file mode 100644 index 787ef8b6d..000000000 --- a/src/Ombi.Schedule/IoCJobActivator.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System; -using System.Linq; -using System.Reflection; -using Hangfire; -using Microsoft.Extensions.DependencyInjection; - -namespace Ombi.Schedule -{ - public class IoCJobActivator : JobActivator - { - private readonly IServiceProvider _container; - public IoCJobActivator(IServiceProvider container) - { - _container = container; - } - - public override object ActivateJob(Type type) - { - var scopeFactory = _container.GetService(); - var scope = scopeFactory.CreateScope(); - var scopedContainer = scope.ServiceProvider; - - var interfaceType = type.GetTypeInfo().ImplementedInterfaces.FirstOrDefault(); - var implementation = scopedContainer.GetRequiredService(interfaceType); - return implementation; - } - } -} \ No newline at end of file diff --git a/src/Ombi.Schedule/IocJobFactory.cs b/src/Ombi.Schedule/IocJobFactory.cs index 795c1fec5..abb458e39 100644 --- a/src/Ombi.Schedule/IocJobFactory.cs +++ b/src/Ombi.Schedule/IocJobFactory.cs @@ -7,26 +7,18 @@ namespace Ombi.Schedule { public class IoCJobFactory : IJobFactory { - private readonly IServiceProvider _factory; - - public IoCJobFactory(IServiceProvider factory) + private readonly IServiceProvider _serviceProvider; + public IoCJobFactory(IServiceProvider serviceProvider) { - _factory = factory; + _serviceProvider = serviceProvider; } public IJob NewJob(TriggerFiredBundle bundle, IScheduler scheduler) { - var scopeFactory = _factory.GetService(); - var scope = scopeFactory.CreateScope(); - var scopedContainer = scope.ServiceProvider; - - var implementation = scopedContainer.GetRequiredService(bundle.JobDetail.JobType) as IJob; - return implementation; + return _serviceProvider.GetRequiredService(); } public void ReturnJob(IJob job) { - var disposable = job as IDisposable; - disposable?.Dispose(); } } } \ No newline at end of file diff --git a/src/Ombi.Schedule/Jobs/ArrAvailabilityChecker.cs b/src/Ombi.Schedule/Jobs/ArrAvailabilityChecker.cs new file mode 100644 index 000000000..d8676ab86 --- /dev/null +++ b/src/Ombi.Schedule/Jobs/ArrAvailabilityChecker.cs @@ -0,0 +1,218 @@ +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.SignalR; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Logging; +using Ombi.Core; +using Ombi.Core.Settings; +using Ombi.Helpers; +using Ombi.Hubs; +using Ombi.Notifications.Models; +using Ombi.Schedule.Jobs.Plex.Models; +using Ombi.Settings.Settings.Models.External; +using Ombi.Store.Entities; +using Ombi.Store.Repository; +using Ombi.Store.Repository.Requests; +using Quartz; + +namespace Ombi.Schedule.Jobs.Radarr +{ + public class ArrAvailabilityChecker : IArrAvailabilityChecker + { + private readonly IExternalRepository _radarrRepo; + private readonly IExternalRepository _sonarrRepo; + private readonly ILogger _logger; + private readonly ISettingsService _radarrSettings; + private readonly ISettingsService _sonarrSettings; + private readonly IExternalRepository _sonarrEpisodeRepo; + private readonly INotificationHelper _notification; + private readonly IHubContext _hub; + private readonly ITvRequestRepository _tvRequest; + private readonly IMovieRequestRepository _movies; + + public ArrAvailabilityChecker( + IExternalRepository radarrRepo, + IExternalRepository sonarrRepo, + IExternalRepository sonarrEpisodeRepo, + INotificationHelper notification, IHubContext hub, + ITvRequestRepository tvRequest, IMovieRequestRepository movies, + ILogger log, + ISettingsService radarrSettings, + ISettingsService sonarrSettings) + { + _radarrRepo = radarrRepo; + _sonarrRepo = sonarrRepo; + _sonarrEpisodeRepo = sonarrEpisodeRepo; + _notification = notification; + _hub = hub; + _tvRequest = tvRequest; + _movies = movies; + _logger = log; + _radarrSettings = radarrSettings; + _sonarrSettings = sonarrSettings; + } + public async Task Execute(IJobExecutionContext job) + { + var radarrSettings = await _radarrSettings.GetSettingsAsync(); + var sonarrSettings = await _sonarrSettings.GetSettingsAsync(); + + if (radarrSettings.ScanForAvailability) + { + await ProcessMovies(); + } + + if (sonarrSettings.ScanForAvailability) + { + await ProcessTvShows(); + } + } + + private async Task ProcessMovies() + { + var availableRadarrMovies = _radarrRepo.GetAll().Where(x => x.HasFile).ToImmutableHashSet(); + var unavailableMovieRequests = _movies.GetAll().Where(x => !x.Available).ToImmutableHashSet(); + + var itemsForAvailability = new List(); + foreach (var movieRequest in unavailableMovieRequests) + { + // Do we have an item in the radarr list + var available = availableRadarrMovies.Any(x => x.TheMovieDbId == movieRequest.TheMovieDbId); + if (available) + { + _logger.LogInformation($"Found move '{movieRequest.Title}' available in Radarr"); + movieRequest.Available = true; + movieRequest.MarkedAsAvailable = DateTime.UtcNow; + itemsForAvailability.Add(new AvailabilityModel + { + Id = movieRequest.Id, + RequestedUser = movieRequest.RequestedUser != null ? movieRequest.RequestedUser.Email : string.Empty + }); + } + } + + if (itemsForAvailability.Any()) + { + await _hub.Clients.Clients(NotificationHub.AdminConnectionIds) + .SendAsync(NotificationHub.NotificationEvent, "Radarr Availability Checker found some new available movies!"); + await _movies.SaveChangesAsync(); + } + foreach (var item in itemsForAvailability) + { + await _notification.Notify(new NotificationOptions + { + DateTime = DateTime.Now, + NotificationType = NotificationType.RequestAvailable, + RequestId = item.Id, + RequestType = RequestType.Movie, + Recipient = item.RequestedUser + }); + } + + } + + public async Task ProcessTvShows() + { + var tv = await _tvRequest.GetChild().Where(x => !x.Available).ToListAsync(); + var sonarrEpisodes = _sonarrEpisodeRepo.GetAll().Where(x => x.HasFile); + + foreach (var child in tv) + { + var tvDbId = child.ParentRequest.TvDbId; + IQueryable seriesEpisodes = sonarrEpisodes.Where(x => x.TvDbId == tvDbId); + + if (seriesEpisodes == null || !seriesEpisodes.Any()) + { + continue; + } + + //if (!seriesEpisodes.Any()) + //{ + // // Let's try and match the series by name + // seriesEpisodes = sonarrEpisodes.Where(x => + // x.EpisodeNumber == child.Title && + // x.Series.ReleaseYear == child.ParentRequest.ReleaseDate.Year.ToString()); + + //} + + var availableEpisode = new List(); + foreach (var season in child.SeasonRequests) + { + foreach (var episode in season.Episodes) + { + if (episode.Available) + { + continue; + } + var foundEp = await seriesEpisodes.AnyAsync( + x => x.EpisodeNumber == episode.EpisodeNumber && + x.SeasonNumber == episode.Season.SeasonNumber); + + if (foundEp) + { + availableEpisode.Add(new AvailabilityModel + { + Id = episode.Id + }); + episode.Available = true; + } + } + } + + //TODO Partial avilability notifications here + if (availableEpisode.Any()) + { + //await _hub.Clients.Clients(NotificationHub.AdminConnectionIds) + // .SendAsync(NotificationHub.NotificationEvent, "Sonarr Availability Checker found some new available episodes!"); + await _tvRequest.Save(); + } + //foreach(var c in availableEpisode) + //{ + // await _tvRepo.MarkEpisodeAsAvailable(c.Id); + //} + + // Check to see if all of the episodes in all seasons are available for this request + var allAvailable = child.SeasonRequests.All(x => x.Episodes.All(c => c.Available)); + if (allAvailable) + { + await _hub.Clients.Clients(NotificationHub.AdminConnectionIds) + .SendAsync(NotificationHub.NotificationEvent, "Sonarr Availability Checker found some new available Shows!"); + child.Available = true; + child.MarkedAsAvailable = DateTime.UtcNow; + _logger.LogInformation("[ARR_AC] - Child request {0} is now available, sending notification", $"{child.Title} - {child.Id}"); + // We have ful-fulled this request! + await _tvRequest.Save(); + await _notification.Notify(new NotificationOptions + { + DateTime = DateTime.Now, + NotificationType = NotificationType.RequestAvailable, + RequestId = child.Id, + RequestType = RequestType.TvShow, + Recipient = child.RequestedUser.Email + }); + } + } + + await _tvRequest.Save(); + } + + private bool _disposed; + protected virtual void Dispose(bool disposing) + { + if (_disposed) + return; + + if (disposing) + { + } + _disposed = true; + } + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + } +} diff --git a/src/Ombi.Schedule/Jobs/Couchpotato/CouchPotatoSync.cs b/src/Ombi.Schedule/Jobs/Couchpotato/CouchPotatoSync.cs index 8ac9e33e0..98a0c0910 100644 --- a/src/Ombi.Schedule/Jobs/Couchpotato/CouchPotatoSync.cs +++ b/src/Ombi.Schedule/Jobs/Couchpotato/CouchPotatoSync.cs @@ -80,7 +80,7 @@ namespace Ombi.Schedule.Jobs.Couchpotato // Let's remove the old cached data using (var tran = await _ctx.Database.BeginTransactionAsync()) { - await _ctx.Database.ExecuteSqlCommandAsync("DELETE FROM CouchPotatoCache"); + await _ctx.Database.ExecuteSqlRawAsync("DELETE FROM CouchPotatoCache"); tran.Commit(); } @@ -132,7 +132,7 @@ namespace Ombi.Schedule.Jobs.Couchpotato if (disposing) { - _settings?.Dispose(); + //_settings?.Dispose(); _ctx?.Dispose(); } _disposed = true; diff --git a/src/Ombi.Schedule/Jobs/Emby/EmbyAvaliabilityChecker.cs b/src/Ombi.Schedule/Jobs/Emby/EmbyAvaliabilityChecker.cs index 18c4c28a7..48537ef65 100644 --- a/src/Ombi.Schedule/Jobs/Emby/EmbyAvaliabilityChecker.cs +++ b/src/Ombi.Schedule/Jobs/Emby/EmbyAvaliabilityChecker.cs @@ -28,10 +28,10 @@ using System; using System.Linq; using System.Threading.Tasks; -using Hangfire; using Microsoft.AspNetCore.SignalR; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; +using Ombi.Core; using Ombi.Core.Notifications; using Ombi.Helpers; using Ombi.Hubs; @@ -47,7 +47,7 @@ namespace Ombi.Schedule.Jobs.Emby public class EmbyAvaliabilityChecker : IEmbyAvaliabilityChecker { public EmbyAvaliabilityChecker(IEmbyContentRepository repo, ITvRequestRepository t, IMovieRequestRepository m, - INotificationService n, ILogger log, IHubContext notification) + INotificationHelper n, ILogger log, IHubContext notification) { _repo = repo; _tvRepo = t; @@ -60,19 +60,19 @@ namespace Ombi.Schedule.Jobs.Emby private readonly ITvRequestRepository _tvRepo; private readonly IMovieRequestRepository _movieRepo; private readonly IEmbyContentRepository _repo; - private readonly INotificationService _notificationService; + private readonly INotificationHelper _notificationService; private readonly ILogger _log; private readonly IHubContext _notification; public async Task Execute(IJobExecutionContext job) { + _log.LogInformation("Starting Emby Availability Check"); await _notification.Clients.Clients(NotificationHub.AdminConnectionIds) .SendAsync(NotificationHub.NotificationEvent, "Emby Availability Checker Started"); await ProcessMovies(); await ProcessTv(); - await OmbiQuartz.TriggerJob(nameof(IRefreshMetadata), "System"); - + _log.LogInformation("Finished Emby Availability Check"); await _notification.Clients.Clients(NotificationHub.AdminConnectionIds) .SendAsync(NotificationHub.NotificationEvent, "Emby Availability Checker Finished"); } @@ -109,14 +109,14 @@ namespace Ombi.Schedule.Jobs.Emby _log.LogDebug("MovieId: {0}, RequestUser: {1}", movie.Id, recipient); - BackgroundJob.Enqueue(() => _notificationService.Publish(new NotificationOptions + await _notificationService.Notify(new NotificationOptions { DateTime = DateTime.Now, NotificationType = NotificationType.RequestAvailable, RequestId = movie.Id, RequestType = RequestType.Movie, Recipient = recipient, - })); + }); } } await _movieRepo.Save(); @@ -170,7 +170,7 @@ namespace Ombi.Schedule.Jobs.Emby { // Let's try and match the series by name seriesEpisodes = embyEpisodes.Where(x => - x.Series.Title.Equals(child.Title, StringComparison.CurrentCultureIgnoreCase)); + x.Series.Title == child.Title); } foreach (var season in child.SeasonRequests) @@ -200,14 +200,14 @@ namespace Ombi.Schedule.Jobs.Emby // We have fulfulled this request! child.Available = true; child.MarkedAsAvailable = DateTime.Now; - BackgroundJob.Enqueue(() => _notificationService.Publish(new NotificationOptions + await _notificationService.Notify(new NotificationOptions { DateTime = DateTime.Now, NotificationType = NotificationType.RequestAvailable, RequestId = child.Id, RequestType = RequestType.TvShow, Recipient = child.RequestedUser.Email - })); + }); } } @@ -222,7 +222,6 @@ namespace Ombi.Schedule.Jobs.Emby if (disposing) { - _movieRepo?.Dispose(); } _disposed = true; } diff --git a/src/Ombi.Schedule/Jobs/Emby/EmbyContentSync.cs b/src/Ombi.Schedule/Jobs/Emby/EmbyContentSync.cs index 6a58af097..f8bde2755 100644 --- a/src/Ombi.Schedule/Jobs/Emby/EmbyContentSync.cs +++ b/src/Ombi.Schedule/Jobs/Emby/EmbyContentSync.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -using Hangfire; using Microsoft.AspNetCore.SignalR; using Microsoft.Extensions.Logging; using Ombi.Api.Emby; @@ -15,35 +14,36 @@ using Ombi.Schedule.Jobs.Ombi; using Ombi.Store.Entities; using Ombi.Store.Repository; using Quartz; -using Serilog; using EmbyMediaType = Ombi.Store.Entities.EmbyMediaType; namespace Ombi.Schedule.Jobs.Emby { public class EmbyContentSync : IEmbyContentSync { - public EmbyContentSync(ISettingsService settings, IEmbyApi api, ILogger logger, + public EmbyContentSync(ISettingsService settings, IEmbyApiFactory api, ILogger logger, IEmbyContentRepository repo, IHubContext notification) { _logger = logger; _settings = settings; - _api = api; + _apiFactory = api; _repo = repo; _notification = notification; } private readonly ILogger _logger; private readonly ISettingsService _settings; - private readonly IEmbyApi _api; + private readonly IEmbyApiFactory _apiFactory; private readonly IEmbyContentRepository _repo; private readonly IHubContext _notification; + private IEmbyApi Api { get; set; } public async Task Execute(IJobExecutionContext job) { var embySettings = await _settings.GetSettingsAsync(); if (!embySettings.Enable) return; - + + Api = _apiFactory.CreateClient(embySettings); await _notification.Clients.Clients(NotificationHub.AdminConnectionIds) .SendAsync(NotificationHub.NotificationEvent, "Emby Content Sync Started"); @@ -78,7 +78,7 @@ namespace Ombi.Schedule.Jobs.Emby //await _repo.ExecuteSql("DELETE FROM EmbyEpisode"); //await _repo.ExecuteSql("DELETE FROM EmbyContent"); - var movies = await _api.GetAllMovies(server.ApiKey, 0, 200, server.AdministratorId, server.FullUri); + var movies = await Api.GetAllMovies(server.ApiKey, 0, 200, server.AdministratorId, server.FullUri); var totalCount = movies.TotalRecordCount; var processed = 1; @@ -91,7 +91,7 @@ namespace Ombi.Schedule.Jobs.Emby if (movie.Type.Equals("boxset", StringComparison.InvariantCultureIgnoreCase)) { var movieInfo = - await _api.GetCollection(movie.Id, server.ApiKey, server.AdministratorId, server.FullUri); + await Api.GetCollection(movie.Id, server.ApiKey, server.AdministratorId, server.FullUri); foreach (var item in movieInfo.Items) { await ProcessMovies(item, mediaToAdd, server); @@ -108,7 +108,7 @@ namespace Ombi.Schedule.Jobs.Emby } // Get the next batch - movies = await _api.GetAllMovies(server.ApiKey, processed, 200, server.AdministratorId, server.FullUri); + movies = await Api.GetAllMovies(server.ApiKey, processed, 200, server.AdministratorId, server.FullUri); await _repo.AddRange(mediaToAdd); mediaToAdd.Clear(); @@ -116,7 +116,7 @@ namespace Ombi.Schedule.Jobs.Emby // TV Time - var tv = await _api.GetAllShows(server.ApiKey, 0, 200, server.AdministratorId, server.FullUri); + var tv = await Api.GetAllShows(server.ApiKey, 0, 200, server.AdministratorId, server.FullUri); var totalTv = tv.TotalRecordCount; processed = 1; while (processed < totalTv) @@ -145,7 +145,7 @@ namespace Ombi.Schedule.Jobs.Emby Title = tvShow.Name, Type = EmbyMediaType.Series, EmbyId = tvShow.Id, - Url = EmbyHelper.GetEmbyMediaUrl(tvShow.Id, server.ServerHostname, settings.IsJellyfin), + Url = EmbyHelper.GetEmbyMediaUrl(tvShow.Id, server?.ServerId, server.ServerHostname, settings.IsJellyfin), AddedAt = DateTime.UtcNow }); } @@ -162,7 +162,7 @@ namespace Ombi.Schedule.Jobs.Emby } } // Get the next batch - tv = await _api.GetAllShows(server.ApiKey, processed, 200, server.AdministratorId, server.FullUri); + tv = await Api.GetAllShows(server.ApiKey, processed, 200, server.AdministratorId, server.FullUri); await _repo.AddRange(mediaToAdd); mediaToAdd.Clear(); } @@ -186,7 +186,7 @@ namespace Ombi.Schedule.Jobs.Emby Title = movieInfo.Name, Type = EmbyMediaType.Movie, EmbyId = movieInfo.Id, - Url = EmbyHelper.GetEmbyMediaUrl(movieInfo.Id, server.ServerHostname), + Url = EmbyHelper.GetEmbyMediaUrl(movieInfo.Id, server?.ServerId, server.ServerHostname), AddedAt = DateTime.UtcNow, }); } @@ -216,8 +216,7 @@ namespace Ombi.Schedule.Jobs.Emby if (disposing) { - _settings?.Dispose(); - _repo?.Dispose(); + //_settings?.Dispose(); } _disposed = true; } diff --git a/src/Ombi.Schedule/Jobs/Emby/EmbyEpisodeSync.cs b/src/Ombi.Schedule/Jobs/Emby/EmbyEpisodeSync.cs index a10e3046c..2cc03a16c 100644 --- a/src/Ombi.Schedule/Jobs/Emby/EmbyEpisodeSync.cs +++ b/src/Ombi.Schedule/Jobs/Emby/EmbyEpisodeSync.cs @@ -29,25 +29,26 @@ using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -using Hangfire; using Microsoft.AspNetCore.SignalR; using Microsoft.Extensions.Logging; using Ombi.Api.Emby; using Ombi.Core.Settings; using Ombi.Core.Settings.Models.External; using Ombi.Hubs; +using Ombi.Helpers; using Ombi.Store.Entities; using Ombi.Store.Repository; using Quartz; +using Ombi.Schedule.Jobs.Ombi; namespace Ombi.Schedule.Jobs.Emby { public class EmbyEpisodeSync : IEmbyEpisodeSync { - public EmbyEpisodeSync(ISettingsService s, IEmbyApi api, ILogger l, IEmbyContentRepository repo + public EmbyEpisodeSync(ISettingsService s, IEmbyApiFactory api, ILogger l, IEmbyContentRepository repo , IHubContext notification) { - _api = api; + _apiFactory = api; _logger = l; _settings = s; _repo = repo; @@ -55,16 +56,18 @@ namespace Ombi.Schedule.Jobs.Emby } private readonly ISettingsService _settings; - private readonly IEmbyApi _api; + private readonly IEmbyApiFactory _apiFactory; private readonly ILogger _logger; private readonly IEmbyContentRepository _repo; private readonly IHubContext _notification; + private IEmbyApi Api { get; set; } public async Task Execute(IJobExecutionContext job) { var settings = await _settings.GetSettingsAsync(); - + + Api = _apiFactory.CreateClient(settings); await _notification.Clients.Clients(NotificationHub.AdminConnectionIds) .SendAsync(NotificationHub.NotificationEvent, "Emby Episode Sync Started"); foreach (var server in settings.Servers) @@ -72,15 +75,15 @@ namespace Ombi.Schedule.Jobs.Emby await CacheEpisodes(server); } - await _notification.Clients.Clients(NotificationHub.AdminConnectionIds) .SendAsync(NotificationHub.NotificationEvent, "Emby Episode Sync Finished"); - await OmbiQuartz.TriggerJob(nameof(IEmbyAvaliabilityChecker), "Emby"); + _logger.LogInformation("Emby Episode Sync Finished - Triggering Metadata refresh"); + await OmbiQuartz.TriggerJob(nameof(IRefreshMetadata), "System"); } private async Task CacheEpisodes(EmbyServers server) { - var allEpisodes = await _api.GetAllEpisodes(server.ApiKey, 0, 200, server.AdministratorId, server.FullUri); + var allEpisodes = await Api.GetAllEpisodes(server.ApiKey, 0, 200, server.AdministratorId, server.FullUri); var total = allEpisodes.TotalRecordCount; var processed = 1; var epToAdd = new HashSet(); @@ -147,7 +150,7 @@ namespace Ombi.Schedule.Jobs.Emby await _repo.AddRange(epToAdd); epToAdd.Clear(); - allEpisodes = await _api.GetAllEpisodes(server.ApiKey, processed, 200, server.AdministratorId, server.FullUri); + allEpisodes = await Api.GetAllEpisodes(server.ApiKey, processed, 200, server.AdministratorId, server.FullUri); } if (epToAdd.Any()) @@ -164,8 +167,7 @@ namespace Ombi.Schedule.Jobs.Emby if (disposing) { - _settings?.Dispose(); - _repo?.Dispose(); + //_settings?.Dispose(); } _disposed = true; } diff --git a/src/Ombi.Schedule/Jobs/Emby/EmbyUserImporter.cs b/src/Ombi.Schedule/Jobs/Emby/EmbyUserImporter.cs index cd0bd0b8e..1207e1f42 100644 --- a/src/Ombi.Schedule/Jobs/Emby/EmbyUserImporter.cs +++ b/src/Ombi.Schedule/Jobs/Emby/EmbyUserImporter.cs @@ -45,10 +45,10 @@ namespace Ombi.Schedule.Jobs.Emby { public class EmbyUserImporter : IEmbyUserImporter { - public EmbyUserImporter(IEmbyApi api, UserManager um, ILogger log, + public EmbyUserImporter(IEmbyApiFactory api, UserManager um, ILogger log, ISettingsService embySettings, ISettingsService ums, IHubContext notification) { - _api = api; + _apiFactory = api; _userManager = um; _log = log; _embySettings = embySettings; @@ -56,12 +56,13 @@ namespace Ombi.Schedule.Jobs.Emby _notification = notification; } - private readonly IEmbyApi _api; + private readonly IEmbyApiFactory _apiFactory; private readonly UserManager _userManager; private readonly ILogger _log; private readonly ISettingsService _embySettings; private readonly ISettingsService _userManagementSettings; private readonly IHubContext _notification; + private IEmbyApi Api { get; set; } public async Task Execute(IJobExecutionContext job) { @@ -76,9 +77,11 @@ namespace Ombi.Schedule.Jobs.Emby return; } + Api = _apiFactory.CreateClient(settings); + await _notification.Clients.Clients(NotificationHub.AdminConnectionIds) - .SendAsync(NotificationHub.NotificationEvent, "Emby User Importer Started"); - var allUsers = await _userManager.Users.Where(x => x.UserType == UserType.EmbyUser).ToListAsync(); + .SendAsync(NotificationHub.NotificationEvent, $"{(settings.IsJellyfin ? "Jellyfin" : "Emby")} User Importer Started"); + var allUsers = await _userManager.Users.Where(x => x.UserType == UserType.EmbyUser || x.UserType == UserType.EmbyConnectUser).ToListAsync(); foreach (var server in settings.Servers) { if (string.IsNullOrEmpty(server.ApiKey)) @@ -86,7 +89,7 @@ namespace Ombi.Schedule.Jobs.Emby continue; } - var embyUsers = await _api.GetUsers(server.FullUri, server.ApiKey); + var embyUsers = await Api.GetUsers(server.FullUri, server.ApiKey); foreach (var embyUser in embyUsers) { // Check if we should import this user @@ -95,8 +98,7 @@ namespace Ombi.Schedule.Jobs.Emby // Do not import these, they are not allowed into the country. continue; } - // Check if this Plex User already exists - // We are using the Plex USERNAME and Not the TITLE, the Title is for HOME USERS + // Check if this Emby User already exists var existingEmbyUser = allUsers.FirstOrDefault(x => x.ProviderUserId == embyUser.Id); if (existingEmbyUser == null) { @@ -106,16 +108,14 @@ namespace Ombi.Schedule.Jobs.Emby _log.LogInformation("Could not create Emby user since the have no username, PlexUserId: {0}", embyUser.Id); continue; } - + var isConnectUser = embyUser.ConnectUserName.HasValue(); // Create this users - // We do not store a password against the user since they will authenticate via Plex var newUser = new OmbiUser { - UserType = UserType.EmbyUser, - UserName = embyUser.ConnectUserName.HasValue() ? embyUser.ConnectUserName : embyUser.Name, + UserType = isConnectUser ? UserType.EmbyConnectUser : UserType.EmbyUser, + UserName = isConnectUser ? embyUser.ConnectUserName : embyUser.Name, ProviderUserId = embyUser.Id, - Alias = string.Empty, - EmbyConnectUserId = embyUser.ConnectUserId.HasValue() ? embyUser.ConnectUserId : string.Empty, + Alias = isConnectUser ? embyUser.Name : string.Empty, MovieRequestLimit = userManagementSettings.MovieRequestLimit, EpisodeRequestLimit = userManagementSettings.EpisodeRequestLimit }; @@ -140,8 +140,6 @@ namespace Ombi.Schedule.Jobs.Emby { // Do we need to update this user? existingEmbyUser.UserName = embyUser.Name; - existingEmbyUser.EmbyConnectUserId = - embyUser.ConnectUserId.HasValue() ? embyUser.ConnectUserId : string.Empty; if (existingEmbyUser.IsEmbyConnect) { @@ -149,6 +147,7 @@ namespace Ombi.Schedule.Jobs.Emby // Since we need the username and password to connect to emby connect, // We update the email address in the OmbiUserManager when the emby connect user logs in existingEmbyUser.UserName = embyUser.ConnectUserName; + existingEmbyUser.Alias = embyUser.Name; } await _userManager.UpdateAsync(existingEmbyUser); @@ -169,8 +168,8 @@ namespace Ombi.Schedule.Jobs.Emby if (disposing) { _userManager?.Dispose(); - _embySettings?.Dispose(); - _userManagementSettings?.Dispose(); + //_embySettings?.Dispose(); + //_userManagementSettings?.Dispose(); } _disposed = true; } diff --git a/src/Ombi.Schedule/Jobs/IArrAvailabilityChecker.cs b/src/Ombi.Schedule/Jobs/IArrAvailabilityChecker.cs new file mode 100644 index 000000000..f2a2df601 --- /dev/null +++ b/src/Ombi.Schedule/Jobs/IArrAvailabilityChecker.cs @@ -0,0 +1,6 @@ +namespace Ombi.Schedule.Jobs.Radarr +{ + public interface IArrAvailabilityChecker : IBaseJob + { + } +} diff --git a/src/Ombi.Schedule/Jobs/Lidarr/LidarrAlbumSync.cs b/src/Ombi.Schedule/Jobs/Lidarr/LidarrAlbumSync.cs index a2cecfb18..9530cf5a1 100644 --- a/src/Ombi.Schedule/Jobs/Lidarr/LidarrAlbumSync.cs +++ b/src/Ombi.Schedule/Jobs/Lidarr/LidarrAlbumSync.cs @@ -1,7 +1,7 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Threading.Tasks; -using Hangfire; using Microsoft.AspNetCore.SignalR; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Internal; @@ -21,14 +21,12 @@ namespace Ombi.Schedule.Jobs.Lidarr public class LidarrAlbumSync : ILidarrAlbumSync { public LidarrAlbumSync(ISettingsService lidarr, ILidarrApi lidarrApi, ILogger log, ExternalContext ctx, - IBackgroundJobClient job, ILidarrAvailabilityChecker availability, IHubContext notification) + IHubContext notification) { _lidarrSettings = lidarr; _lidarrApi = lidarrApi; _logger = log; _ctx = ctx; - _job = job; - _availability = availability; _notification = notification; } @@ -36,8 +34,6 @@ namespace Ombi.Schedule.Jobs.Lidarr private readonly ILidarrApi _lidarrApi; private readonly ILogger _logger; private readonly ExternalContext _ctx; - private readonly IBackgroundJobClient _job; - private readonly ILidarrAvailabilityChecker _availability; private readonly IHubContext _notification; public async Task Execute(IJobExecutionContext ctx) @@ -58,7 +54,7 @@ namespace Ombi.Schedule.Jobs.Lidarr // Let's remove the old cached data using (var tran = await _ctx.Database.BeginTransactionAsync()) { - await _ctx.Database.ExecuteSqlCommandAsync("DELETE FROM LidarrAlbumCache"); + await _ctx.Database.ExecuteSqlRawAsync("DELETE FROM LidarrAlbumCache"); tran.Commit(); } @@ -123,7 +119,7 @@ namespace Ombi.Schedule.Jobs.Lidarr if (disposing) { _ctx?.Dispose(); - _lidarrSettings?.Dispose(); + //_lidarrSettings?.Dispose(); } _disposed = true; } diff --git a/src/Ombi.Schedule/Jobs/Lidarr/LidarrArtistSync.cs b/src/Ombi.Schedule/Jobs/Lidarr/LidarrArtistSync.cs index 9c2493dea..edcd6cbe6 100644 --- a/src/Ombi.Schedule/Jobs/Lidarr/LidarrArtistSync.cs +++ b/src/Ombi.Schedule/Jobs/Lidarr/LidarrArtistSync.cs @@ -1,10 +1,9 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Threading.Tasks; -using Hangfire; using Microsoft.AspNetCore.SignalR; using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Internal; using Microsoft.Extensions.Logging; using Ombi.Api.Lidarr; using Ombi.Core.Settings; @@ -54,7 +53,7 @@ namespace Ombi.Schedule.Jobs.Lidarr // Let's remove the old cached data using (var tran = await _ctx.Database.BeginTransactionAsync()) { - await _ctx.Database.ExecuteSqlCommandAsync("DELETE FROM LidarrArtistCache"); + await _ctx.Database.ExecuteSqlRawAsync("DELETE FROM LidarrArtistCache"); tran.Commit(); } @@ -115,7 +114,7 @@ namespace Ombi.Schedule.Jobs.Lidarr if (disposing) { _ctx?.Dispose(); - _lidarrSettings?.Dispose(); + //_lidarrSettings?.Dispose(); } _disposed = true; } diff --git a/src/Ombi.Schedule/Jobs/Lidarr/LidarrAvailabilityChecker.cs b/src/Ombi.Schedule/Jobs/Lidarr/LidarrAvailabilityChecker.cs index a7706a433..99b27fec7 100644 --- a/src/Ombi.Schedule/Jobs/Lidarr/LidarrAvailabilityChecker.cs +++ b/src/Ombi.Schedule/Jobs/Lidarr/LidarrAvailabilityChecker.cs @@ -2,11 +2,10 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -using Hangfire; using Microsoft.AspNetCore.SignalR; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; -using Ombi.Core.Notifications; +using Ombi.Core; using Ombi.Helpers; using Ombi.Hubs; using Ombi.Notifications.Models; @@ -20,22 +19,20 @@ namespace Ombi.Schedule.Jobs.Lidarr { public class LidarrAvailabilityChecker : ILidarrAvailabilityChecker { - public LidarrAvailabilityChecker(IMusicRequestRepository requests, IRepository albums, ILogger log, - IBackgroundJobClient job, INotificationService notification, IHubContext notificationHub) + public LidarrAvailabilityChecker(IMusicRequestRepository requests, IExternalRepository albums, ILogger log, + INotificationHelper notification, IHubContext notificationHub) { _cachedAlbums = albums; _requestRepository = requests; _logger = log; - _job = job; _notificationService = notification; _notification = notificationHub; } private readonly IMusicRequestRepository _requestRepository; - private readonly IRepository _cachedAlbums; + private readonly IExternalRepository _cachedAlbums; private readonly ILogger _logger; - private readonly IBackgroundJobClient _job; - private readonly INotificationService _notificationService; + private readonly INotificationHelper _notificationService; private readonly IHubContext _notification; public async Task Execute(IJobExecutionContext ctx) @@ -67,14 +64,15 @@ namespace Ombi.Schedule.Jobs.Lidarr _logger.LogDebug("AlbumId: {0}, RequestUser: {1}", albumRequest.Id, recipient); - _job.Enqueue(() => _notificationService.Publish(new NotificationOptions + + await _notificationService.Notify(new NotificationOptions { DateTime = DateTime.Now, NotificationType = NotificationType.RequestAvailable, RequestId = albumRequest.Id, RequestType = RequestType.Album, Recipient = recipient, - })); + }); } await _notification.Clients.Clients(NotificationHub.AdminConnectionIds) diff --git a/src/Ombi.Schedule/Jobs/Ombi/AutoDeleteRequests.cs b/src/Ombi.Schedule/Jobs/Ombi/AutoDeleteRequests.cs new file mode 100644 index 000000000..6625a3bbb --- /dev/null +++ b/src/Ombi.Schedule/Jobs/Ombi/AutoDeleteRequests.cs @@ -0,0 +1,88 @@ +using System; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Logging; +using Ombi.Core.Settings; +using Ombi.Settings.Settings.Models; +using Ombi.Store.Repository.Requests; +using Quartz; + +namespace Ombi.Schedule.Jobs.Ombi +{ + public class AutoDeleteRequests : IAutoDeleteRequests + { + + private readonly ISettingsService _ombiSettings; + private readonly IMovieRequestRepository _movieRequests; + private readonly ITvRequestRepository _tvRequestRepository; + private readonly ILogger _logger; + + public AutoDeleteRequests(ISettingsService ombiSettings, IMovieRequestRepository movieRequest, + ILogger logger, ITvRequestRepository tvRequestRepository) + { + _ombiSettings = ombiSettings; + _movieRequests = movieRequest; + _tvRequestRepository = tvRequestRepository; + _logger = logger; + } + + public async Task Execute(IJobExecutionContext job) + { + var settings = await _ombiSettings.GetSettingsAsync(); + if (!settings.AutoDeleteAvailableRequests) + { + return; + } + var date = DateTime.UtcNow.AddDays(-settings.AutoDeleteAfterDays).Date; + await ProcessMovieRequests(date); + await ProcessTvRequests(date); + } + + private async Task ProcessMovieRequests(DateTime date) + { + var requestsToDelete = await _movieRequests.GetAll().Where(x => x.Available && x.MarkedAsAvailable.HasValue && x.MarkedAsAvailable.Value < date).ToListAsync(); + + _logger.LogInformation($"Deleting {requestsToDelete.Count} movie requests that have now been scheduled for deletion, All available requests before {date::MM/dd/yyyy} will be deleted"); + foreach (var r in requestsToDelete) + { + _logger.LogInformation($"Deleting movie title {r.Title} as it was approved on {r.MarkedAsApproved:MM/dd/yyyy hh:mm tt}"); + } + + await _movieRequests.DeleteRange(requestsToDelete); + } + + private async Task ProcessTvRequests(DateTime date) + { + var requestsToDelete = await _tvRequestRepository.GetChild().Where(x => x.Available && x.MarkedAsAvailable.HasValue && x.MarkedAsAvailable.Value < date).ToListAsync(); + + _logger.LogInformation($"Deleting {requestsToDelete.Count} episode requests that have now been scheduled for deletion, All available requests before {date::MM/dd/yyyy} will be deleted"); + + await _tvRequestRepository.DeleteChildRange(requestsToDelete); + + // Check if we have parent requests without any child requests now + var parentRequests = await _tvRequestRepository.Get().Where(x => !x.ChildRequests.Any()).ToListAsync(); + + await _tvRequestRepository.DeleteRange(parentRequests); + } + + private bool _disposed; + + protected virtual void Dispose(bool disposing) + { + if (_disposed) + return; + + if (disposing) + { + } + _disposed = true; + } + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + } +} \ No newline at end of file diff --git a/src/Ombi.Schedule/Jobs/Ombi/IAutoDeleteRequests.cs b/src/Ombi.Schedule/Jobs/Ombi/IAutoDeleteRequests.cs new file mode 100644 index 000000000..9c23e2c8b --- /dev/null +++ b/src/Ombi.Schedule/Jobs/Ombi/IAutoDeleteRequests.cs @@ -0,0 +1,4 @@ +namespace Ombi.Schedule.Jobs.Ombi +{ + public interface IAutoDeleteRequests : IBaseJob { } +} \ No newline at end of file diff --git a/src/Ombi.Schedule/Jobs/Ombi/Interfaces/IOmbiAutomaticUpdater.cs b/src/Ombi.Schedule/Jobs/Ombi/Interfaces/IOmbiAutomaticUpdater.cs index 484700c85..85765b6c6 100644 --- a/src/Ombi.Schedule/Jobs/Ombi/Interfaces/IOmbiAutomaticUpdater.cs +++ b/src/Ombi.Schedule/Jobs/Ombi/Interfaces/IOmbiAutomaticUpdater.cs @@ -1,5 +1,4 @@ using System.Threading.Tasks; -using Hangfire.Server; namespace Ombi.Schedule.Jobs.Ombi { diff --git a/src/Ombi.Schedule/Jobs/Ombi/Interfaces/IRefreshMetadata.cs b/src/Ombi.Schedule/Jobs/Ombi/Interfaces/IRefreshMetadata.cs index c29a80994..70b2e5a43 100644 --- a/src/Ombi.Schedule/Jobs/Ombi/Interfaces/IRefreshMetadata.cs +++ b/src/Ombi.Schedule/Jobs/Ombi/Interfaces/IRefreshMetadata.cs @@ -1,9 +1,11 @@ -using System.Collections.Generic; +using Ombi.Store.Entities; +using System.Collections.Generic; using System.Threading.Tasks; namespace Ombi.Schedule.Jobs.Ombi { public interface IRefreshMetadata : IBaseJob { + Task GetTheMovieDbId(bool hasTvDbId, bool hasImdb, string tvdbID, string imdbId, string title, bool movie); } } \ No newline at end of file diff --git a/src/Ombi.Schedule/Jobs/Ombi/Interfaces/IssuesPurge.cs b/src/Ombi.Schedule/Jobs/Ombi/Interfaces/IssuesPurge.cs index f82ba71cd..da14135d9 100644 --- a/src/Ombi.Schedule/Jobs/Ombi/Interfaces/IssuesPurge.cs +++ b/src/Ombi.Schedule/Jobs/Ombi/Interfaces/IssuesPurge.cs @@ -1,6 +1,7 @@ using System; using System.Linq; using System.Threading.Tasks; +using Microsoft.EntityFrameworkCore; using Ombi.Core.Settings; using Ombi.Settings.Settings.Models; using Ombi.Store.Entities.Requests; @@ -31,7 +32,7 @@ namespace Ombi.Schedule.Jobs.Ombi var today = DateTime.UtcNow.Date; - var resolved = _issuesRepository.GetAll().Where(x => x.Status == IssueStatus.Resolved); + var resolved = await _issuesRepository.GetAll().Where(x => x.Status == IssueStatus.Resolved).ToListAsync(); var toDelete = resolved.Where(x => x.ResovledDate.HasValue && (today - x.ResovledDate.Value.Date).TotalDays >= settings.DaysAfterResolvedToDelete); foreach (var d in toDelete) @@ -50,8 +51,7 @@ namespace Ombi.Schedule.Jobs.Ombi if (disposing) { - _issuesRepository?.Dispose(); - _settings?.Dispose(); + //_settings?.Dispose(); } _disposed = true; } diff --git a/src/Ombi.Schedule/Jobs/Ombi/MediaDatabaseRefresh.cs b/src/Ombi.Schedule/Jobs/Ombi/MediaDatabaseRefresh.cs index cf8cbd831..66ce28487 100644 --- a/src/Ombi.Schedule/Jobs/Ombi/MediaDatabaseRefresh.cs +++ b/src/Ombi.Schedule/Jobs/Ombi/MediaDatabaseRefresh.cs @@ -1,8 +1,6 @@ using System; using System.Threading.Tasks; -using Hangfire; using Microsoft.Extensions.Logging; -using Ombi.Api.Plex; using Ombi.Core.Settings; using Ombi.Core.Settings.Models.External; using Ombi.Helpers; @@ -99,8 +97,7 @@ namespace Ombi.Schedule.Jobs.Ombi if (disposing) { - _plexRepo?.Dispose(); - _settings?.Dispose(); + //_settings?.Dispose(); } _disposed = true; } diff --git a/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs b/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs index 59f24b379..e9ad9333c 100644 --- a/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs +++ b/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs @@ -1,4 +1,5 @@ using System; +using System.Collections; using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; @@ -11,6 +12,7 @@ using Microsoft.AspNetCore.SignalR; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; using MimeKit; +using Ombi.Api.CouchPotato.Models; using Ombi.Api.Lidarr; using Ombi.Api.Lidarr.Models; using Ombi.Api.TheMovieDb; @@ -28,6 +30,7 @@ using Ombi.Settings.Settings.Models.External; using Ombi.Settings.Settings.Models.Notifications; using Ombi.Store.Entities; using Ombi.Store.Repository; +using Org.BouncyCastle.Utilities.Collections; using Quartz; using ContentType = Ombi.Store.Entities.ContentType; @@ -39,9 +42,9 @@ namespace Ombi.Schedule.Jobs.Ombi IMovieDbApi movieApi, ITvMazeApi tvApi, IEmailProvider email, ISettingsService custom, ISettingsService emailSettings, INotificationTemplatesRepository templateRepo, UserManager um, ISettingsService newsletter, ILogger log, - ILidarrApi lidarrApi, IRepository albumCache, ISettingsService lidarrSettings, + ILidarrApi lidarrApi, IExternalRepository albumCache, ISettingsService lidarrSettings, ISettingsService ombiSettings, ISettingsService plexSettings, ISettingsService embySettings - , IHubContext notification) + , IHubContext notification, IRefreshMetadata refreshMetadata) { _plex = plex; _emby = emby; @@ -66,6 +69,7 @@ namespace Ombi.Schedule.Jobs.Ombi _plexSettings.ClearCache(); _emailSettings.ClearCache(); _customizationSettings.ClearCache(); + _refreshMetadata = refreshMetadata; } private readonly IPlexContentRepository _plex; @@ -82,11 +86,12 @@ namespace Ombi.Schedule.Jobs.Ombi private readonly UserManager _userManager; private readonly ILogger _log; private readonly ILidarrApi _lidarrApi; - private readonly IRepository _lidarrAlbumRepository; + private readonly IExternalRepository _lidarrAlbumRepository; private readonly ISettingsService _lidarrSettings; private readonly ISettingsService _plexSettings; private readonly ISettingsService _embySettings; private readonly IHubContext _notification; + private readonly IRefreshMetadata _refreshMetadata; public async Task Start(NewsletterSettings settings, bool test) { @@ -118,7 +123,7 @@ namespace Ombi.Schedule.Jobs.Ombi // Get the Content var plexContent = _plex.GetAll().Include(x => x.Episodes).AsNoTracking(); var embyContent = _emby.GetAll().Include(x => x.Episodes).AsNoTracking(); - var lidarrContent = _lidarrAlbumRepository.GetAll().Where(x => x.FullyAvailable).AsNoTracking(); + var lidarrContent = _lidarrAlbumRepository.GetAll().AsNoTracking().ToList().Where(x => x.FullyAvailable); var addedLog = _recentlyAddedLog.GetAll(); var addedPlexMovieLogIds = addedLog.Where(x => x.Type == RecentlyAddedType.Plex && x.ContentType == ContentType.Parent).Select(x => x.ContentId).ToHashSet(); @@ -132,16 +137,29 @@ namespace Ombi.Schedule.Jobs.Ombi // Filter out the ones that we haven't sent yet - var plexContentMoviesToSend = plexContent.Where(x => x.Type == PlexMediaTypeEntity.Movie && x.HasTheMovieDb && !addedPlexMovieLogIds.Contains(StringHelper.IntParseLinq(x.TheMovieDbId))); - var embyContentMoviesToSend = embyContent.Where(x => x.Type == EmbyMediaType.Movie && x.HasTheMovieDb && !addedEmbyMoviesLogIds.Contains(StringHelper.IntParseLinq(x.TheMovieDbId))); + var plexContentLocalDataset = plexContent.Where(x => x.Type == PlexMediaTypeEntity.Movie && !string.IsNullOrEmpty(x.TheMovieDbId)).ToHashSet(); + var embyContentLocalDataset = embyContent.Where(x => x.Type == EmbyMediaType.Movie && !string.IsNullOrEmpty(x.TheMovieDbId)).ToHashSet(); + var plexContentMoviesToSend = plexContentLocalDataset.Where(x => !addedPlexMovieLogIds.Contains(StringHelper.IntParseLinq(x.TheMovieDbId))).ToHashSet(); + var embyContentMoviesToSend = embyContentLocalDataset.Where(x => !addedEmbyMoviesLogIds.Contains(StringHelper.IntParseLinq(x.TheMovieDbId))).ToHashSet(); var lidarrContentAlbumsToSend = lidarrContent.Where(x => !addedAlbumLogIds.Contains(x.ForeignAlbumId)).ToHashSet(); _log.LogInformation("Plex Movies to send: {0}", plexContentMoviesToSend.Count()); _log.LogInformation("Emby Movies to send: {0}", embyContentMoviesToSend.Count()); _log.LogInformation("Albums to send: {0}", lidarrContentAlbumsToSend.Count()); + // Find the movies that do not yet have MovieDbIds + var needsMovieDbPlex = plexContent.Where(x => x.Type == PlexMediaTypeEntity.Movie && !string.IsNullOrEmpty(x.TheMovieDbId)).ToHashSet(); + var needsMovieDbEmby = embyContent.Where(x => x.Type == EmbyMediaType.Movie && !string.IsNullOrEmpty(x.TheMovieDbId)).ToHashSet(); + var newPlexMovies = await GetMoviesWithoutId(addedPlexMovieLogIds, needsMovieDbPlex); + var newEmbyMovies = await GetMoviesWithoutId(addedEmbyMoviesLogIds, needsMovieDbEmby); + plexContentMoviesToSend = plexContentMoviesToSend.Union(newPlexMovies).ToHashSet(); + embyContentMoviesToSend = embyContentMoviesToSend.Union(newEmbyMovies).ToHashSet(); + + plexContentMoviesToSend = plexContentMoviesToSend.DistinctBy(x => x.Id).ToHashSet(); + embyContentMoviesToSend = embyContentMoviesToSend.DistinctBy(x => x.Id).ToHashSet(); + var plexEpisodesToSend = - FilterPlexEpisodes(_plex.GetAllEpisodes().Include(x => x.Series).Where(x => x.Series.HasTvDb).AsNoTracking(), addedPlexEpisodesLogIds); - var embyEpisodesToSend = FilterEmbyEpisodes(_emby.GetAllEpisodes().Include(x => x.Series).Where(x => x.Series.HasTvDb).AsNoTracking(), + FilterPlexEpisodes(_plex.GetAllEpisodes().Include(x => x.Series).AsNoTracking(), addedPlexEpisodesLogIds); + var embyEpisodesToSend = FilterEmbyEpisodes(_emby.GetAllEpisodes().Include(x => x.Series).AsNoTracking(), addedEmbyEpisodesLogIds); _log.LogInformation("Plex Episodes to send: {0}", plexEpisodesToSend.Count()); @@ -152,7 +170,7 @@ namespace Ombi.Schedule.Jobs.Ombi if (test) { var plexm = plexContent.Where(x => x.Type == PlexMediaTypeEntity.Movie).OrderByDescending(x => x.AddedAt).Take(10); - var embym = embyContent.Where(x => x.Type == EmbyMediaType.Movie ).OrderByDescending(x => x.AddedAt).Take(10); + var embym = embyContent.Where(x => x.Type == EmbyMediaType.Movie).OrderByDescending(x => x.AddedAt).Take(10); var plext = _plex.GetAllEpisodes().Include(x => x.Series).OrderByDescending(x => x.Series.AddedAt).Take(10).ToHashSet(); var embyt = _emby.GetAllEpisodes().Include(x => x.Series).OrderByDescending(x => x.AddedAt).Take(10).ToHashSet(); var lidarr = lidarrContent.OrderByDescending(x => x.AddedAt).Take(10).ToHashSet(); @@ -160,7 +178,7 @@ namespace Ombi.Schedule.Jobs.Ombi } else { - body = await BuildHtml(plexContentMoviesToSend, embyContentMoviesToSend, plexEpisodesToSend, embyEpisodesToSend, lidarrContentAlbumsToSend, settings, embySettings, plexSettings); + body = await BuildHtml(plexContentMoviesToSend.AsQueryable(), embyContentMoviesToSend.AsQueryable(), plexEpisodesToSend, embyEpisodesToSend, lidarrContentAlbumsToSend, settings, embySettings, plexSettings); if (body.IsNullOrEmpty()) { return; @@ -200,7 +218,7 @@ namespace Ombi.Schedule.Jobs.Ombi Body = bodyBuilder.ToMessageBody(), Subject = messageContent.Subject }; - + foreach (var user in users) { // Get the users to send it to @@ -303,6 +321,64 @@ namespace Ombi.Schedule.Jobs.Ombi .SendAsync(NotificationHub.NotificationEvent, "Newsletter Finished"); } + private async Task> GetMoviesWithoutId(HashSet addedMovieLogIds, HashSet needsMovieDbPlex) + { + foreach (var movie in needsMovieDbPlex) + { + var id = await _refreshMetadata.GetTheMovieDbId(false, true, null, movie.ImdbId, movie.Title, true); + movie.TheMovieDbId = id.ToString(); + } + + var result = needsMovieDbPlex.Where(x => x.HasTheMovieDb && !addedMovieLogIds.Contains(StringHelper.IntParseLinq(x.TheMovieDbId))); + await UpdateTheMovieDbId(result); + // Filter them out now + return result.ToHashSet(); + } + + private async Task> GetMoviesWithoutId(HashSet addedMovieLogIds, HashSet needsMovieDbPlex) + { + foreach (var movie in needsMovieDbPlex) + { + var id = await _refreshMetadata.GetTheMovieDbId(false, true, null, movie.ImdbId, movie.Title, true); + movie.TheMovieDbId = id.ToString(); + } + + var result = needsMovieDbPlex.Where(x => x.HasTheMovieDb && !addedMovieLogIds.Contains(StringHelper.IntParseLinq(x.TheMovieDbId))); + await UpdateTheMovieDbId(result); + // Filter them out now + return result.ToHashSet(); + } + + private async Task UpdateTheMovieDbId(IEnumerable content) + { + foreach (var movie in content) + { + if (!movie.HasTheMovieDb) + { + continue; + } + var entity = await _plex.Find(movie.Id); + entity.TheMovieDbId = movie.TheMovieDbId; + _plex.UpdateWithoutSave(entity); + } + await _plex.SaveChangesAsync(); + } + + private async Task UpdateTheMovieDbId(IEnumerable content) + { + foreach (var movie in content) + { + if (!movie.HasTheMovieDb) + { + continue; + } + var entity = await _emby.Find(movie.Id); + entity.TheMovieDbId = movie.TheMovieDbId; + _emby.UpdateWithoutSave(entity); + } + await _plex.SaveChangesAsync(); + } + public async Task Execute(IJobExecutionContext job) { var newsletterSettings = await _newsletterSettings.GetSettingsAsync(); @@ -312,7 +388,7 @@ namespace Ombi.Schedule.Jobs.Ombi private HashSet FilterPlexEpisodes(IEnumerable source, IQueryable recentlyAdded) { var itemsToReturn = new HashSet(); - foreach (var ep in source) + foreach (var ep in source.Where(x => x.Series.HasTvDb)) { var tvDbId = StringHelper.IntParseLinq(ep.Series.TvDbId); if (recentlyAdded.Any(x => x.ContentId == tvDbId && x.EpisodeNumber == ep.EpisodeNumber && x.SeasonNumber == ep.SeasonNumber)) @@ -329,7 +405,7 @@ namespace Ombi.Schedule.Jobs.Ombi private HashSet FilterEmbyEpisodes(IEnumerable source, IQueryable recentlyAdded) { var itemsToReturn = new HashSet(); - foreach (var ep in source) + foreach (var ep in source.Where(x => x.Series.HasTvDb)) { var tvDbId = StringHelper.IntParseLinq(ep.Series.TvDbId); if (recentlyAdded.Any(x => x.ContentId == tvDbId && x.EpisodeNumber == ep.EpisodeNumber && x.SeasonNumber == ep.SeasonNumber)) @@ -353,7 +429,7 @@ namespace Ombi.Schedule.Jobs.Ombi return resolver.ParseMessage(template, curlys); } - private async Task BuildHtml(IQueryable plexContentToSend, IQueryable embyContentToSend, + private async Task BuildHtml(IQueryable plexContentToSend, IQueryable embyContentToSend, HashSet plexEpisodes, HashSet embyEp, HashSet albums, NewsletterSettings settings, EmbySettings embySettings, PlexSettings plexSettings) { @@ -575,7 +651,9 @@ namespace Ombi.Schedule.Jobs.Ombi { releaseDate = $"({DateTime.Parse(info.ReleaseDate).Year})"; } +#pragma warning disable RCS1075 // Avoid empty catch clause that catches System.Exception. catch (Exception) +#pragma warning restore RCS1075 // Avoid empty catch clause that catches System.Exception. { // Swallow, couldn't parse the date } @@ -698,12 +776,12 @@ namespace Ombi.Schedule.Jobs.Ombi { banner = banner.ToHttpsUrl(); // Always use the Https banners } - + var tvInfo = await _movieApi.GetTVInfo(t.TheMovieDbId); if (tvInfo != null && tvInfo.backdrop_path.HasValue()) { - AddBackgroundInsideTable(sb, $"https://image.tmdb.org/t/p/w500{tvInfo.backdrop_path}"); + AddBackgroundInsideTable(sb, $"https://image.tmdb.org/t/p/w500{tvInfo.backdrop_path}"); } else { @@ -717,7 +795,8 @@ namespace Ombi.Schedule.Jobs.Ombi if (!string.IsNullOrEmpty(info.premiered) && info.premiered.Length > 4) { title = $"{t.Title} ({info.premiered.Remove(4)})"; - } else + } + else { title = $"{t.Title}"; } @@ -756,7 +835,7 @@ namespace Ombi.Schedule.Jobs.Ombi { AddGenres(sb, $"Genres: {string.Join(", ", info.genres.Select(x => x.ToString()).ToArray())}"); } - + } catch (Exception e) { @@ -777,7 +856,7 @@ namespace Ombi.Schedule.Jobs.Ombi } } - + private async Task ProcessEmbyTv(HashSet embyContent, StringBuilder sb, string serverUrl) { @@ -881,7 +960,7 @@ namespace Ombi.Schedule.Jobs.Ombi { AddGenres(sb, $"Genres: {string.Join(", ", info.genres.Select(x => x.ToString()).ToArray())}"); } - + } catch (Exception e) { @@ -938,6 +1017,7 @@ namespace Ombi.Schedule.Jobs.Ombi } private bool _disposed; + protected virtual void Dispose(bool disposing) { if (_disposed) @@ -945,12 +1025,9 @@ namespace Ombi.Schedule.Jobs.Ombi if (disposing) { - _plex?.Dispose(); - _emby?.Dispose(); - _newsletterSettings?.Dispose(); - _customizationSettings?.Dispose(); - _emailSettings.Dispose(); - _recentlyAddedLog.Dispose(); + //_newsletterSettings?.Dispose(); + //_customizationSettings?.Dispose(); + //_emailSettings.Dispose(); _templateRepo?.Dispose(); _userManager?.Dispose(); } diff --git a/src/Ombi.Schedule/Jobs/Ombi/OmbiAutomaticUpdater.cs b/src/Ombi.Schedule/Jobs/Ombi/OmbiAutomaticUpdater.cs index 82187ed50..e44728698 100644 --- a/src/Ombi.Schedule/Jobs/Ombi/OmbiAutomaticUpdater.cs +++ b/src/Ombi.Schedule/Jobs/Ombi/OmbiAutomaticUpdater.cs @@ -9,8 +9,6 @@ using System.Reflection; using System.Runtime.InteropServices; using System.Text; using System.Threading.Tasks; -using Hangfire; -using Hangfire.Server; using Microsoft.Extensions.Logging; using Ombi.Core.Processor; using Ombi.Core.Settings; @@ -337,7 +335,7 @@ namespace Ombi.Schedule.Jobs.Ombi if (disposing) { - Settings?.Dispose(); + //Settings?.Dispose(); } _disposed = true; } diff --git a/src/Ombi.Schedule/Jobs/Ombi/RefreshMetadata.cs b/src/Ombi.Schedule/Jobs/Ombi/RefreshMetadata.cs index dd48e442d..30878adaf 100644 --- a/src/Ombi.Schedule/Jobs/Ombi/RefreshMetadata.cs +++ b/src/Ombi.Schedule/Jobs/Ombi/RefreshMetadata.cs @@ -2,8 +2,8 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -using Hangfire; using Microsoft.AspNetCore.SignalR; +using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; using Ombi.Api.Emby; using Ombi.Api.TheMovieDb; @@ -25,7 +25,7 @@ namespace Ombi.Schedule.Jobs.Ombi { public RefreshMetadata(IPlexContentRepository plexRepo, IEmbyContentRepository embyRepo, ILogger log, ITvMazeApi tvApi, ISettingsService plexSettings, - IMovieDbApi movieApi, ISettingsService embySettings, IEmbyApi embyApi, IHubContext notification) + IMovieDbApi movieApi, ISettingsService embySettings, IEmbyApiFactory embyApi, IHubContext notification) { _plexRepo = plexRepo; _embyRepo = embyRepo; @@ -34,7 +34,7 @@ namespace Ombi.Schedule.Jobs.Ombi _tvApi = tvApi; _plexSettings = plexSettings; _embySettings = embySettings; - _embyApi = embyApi; + _embyApiFactory = embyApi; _notification = notification; } @@ -45,8 +45,9 @@ namespace Ombi.Schedule.Jobs.Ombi private readonly ITvMazeApi _tvApi; private readonly ISettingsService _plexSettings; private readonly ISettingsService _embySettings; - private readonly IEmbyApi _embyApi; + private readonly IEmbyApiFactory _embyApiFactory; private readonly IHubContext _notification; + private IEmbyApi EmbyApi { get; set; } public async Task Execute(IJobExecutionContext job) { @@ -60,23 +61,28 @@ namespace Ombi.Schedule.Jobs.Ombi if (settings.Enable) { await StartPlex(); + + await OmbiQuartz.TriggerJob(nameof(IPlexAvailabilityChecker), "Plex"); } var embySettings = await _embySettings.GetSettingsAsync(); if (embySettings.Enable) { await StartEmby(embySettings); + + await OmbiQuartz.TriggerJob(nameof(IEmbyAvaliabilityChecker), "Emby"); } } catch (Exception e) { - _log.LogError(e, "Exception when refreshing the Plex Metadata"); + _log.LogError(e, $"Exception when refreshing the Metadata Refresh"); await _notification.Clients.Clients(NotificationHub.AdminConnectionIds) .SendAsync(NotificationHub.NotificationEvent, "Metadata Refresh Failed"); - throw; + return; } + _log.LogInformation("Metadata refresh finished"); await _notification.Clients.Clients(NotificationHub.AdminConnectionIds) .SendAsync(NotificationHub.NotificationEvent, "Metadata Refresh Finished"); } @@ -84,26 +90,27 @@ namespace Ombi.Schedule.Jobs.Ombi private async Task StartPlex() { // Ensure we check that we have not linked this item to a request - var allMovies = _plexRepo.GetAll().Where(x => - x.Type == PlexMediaTypeEntity.Movie && !x.RequestId.HasValue && (!x.TheMovieDbId.HasValue() || !x.ImdbId.HasValue())); + var allMovies = await _plexRepo.GetAll().Where(x => + x.Type == PlexMediaTypeEntity.Movie && x.RequestId == null && (x.TheMovieDbId == null || x.ImdbId == null)).ToListAsync(); await StartPlexMovies(allMovies); // Now Tv - var allTv = _plexRepo.GetAll().Where(x => - x.Type == PlexMediaTypeEntity.Show && !x.RequestId.HasValue && (!x.TheMovieDbId.HasValue() || !x.ImdbId.HasValue() || !x.TvDbId.HasValue())); + var allTv = await _plexRepo.GetAll().Where(x => + x.Type == PlexMediaTypeEntity.Show && x.RequestId == null && (x.TheMovieDbId == null || x.ImdbId == null || x.TvDbId == null)).ToListAsync(); await StartPlexTv(allTv); } private async Task StartEmby(EmbySettings s) { + EmbyApi = _embyApiFactory.CreateClient(s); await StartEmbyMovies(s); await StartEmbyTv(); } - private async Task StartPlexTv(IQueryable allTv) + private async Task StartPlexTv(List allTv) { foreach (var show in allTv) - { + { // Just double check there is no associated request id if (show.RequestId.HasValue) { @@ -138,8 +145,8 @@ namespace Ombi.Schedule.Jobs.Ombi private async Task StartEmbyTv() { - var allTv = _embyRepo.GetAll().Where(x => - x.Type == EmbyMediaType.Series && (!x.TheMovieDbId.HasValue() || !x.ImdbId.HasValue() || !x.TvDbId.HasValue())); + var allTv = await _embyRepo.GetAll().Where(x => + x.Type == EmbyMediaType.Series && (x.TheMovieDbId == null || x.ImdbId == null || x.TvDbId == null)).ToListAsync(); foreach (var show in allTv) { @@ -171,7 +178,7 @@ namespace Ombi.Schedule.Jobs.Ombi } } - private async Task StartPlexMovies(IQueryable allMovies) + private async Task StartPlexMovies(List allMovies) { foreach (var movie in allMovies) { @@ -203,8 +210,8 @@ namespace Ombi.Schedule.Jobs.Ombi private async Task StartEmbyMovies(EmbySettings settings) { - var allMovies = _embyRepo.GetAll().Where(x => - x.Type == EmbyMediaType.Movie && (!x.TheMovieDbId.HasValue() || !x.ImdbId.HasValue())); + var allMovies = await _embyRepo.GetAll().Where(x => + x.Type == EmbyMediaType.Movie && (x.TheMovieDbId == null || x.ImdbId == null)).ToListAsync(); foreach (var movie in allMovies) { movie.ImdbId.HasValue(); @@ -223,7 +230,7 @@ namespace Ombi.Schedule.Jobs.Ombi foreach (var server in settings.Servers) { _log.LogInformation($"Checking server {server.Name} for upto date metadata"); - var movieInfo = await _embyApi.GetMovieInformation(movie.EmbyId, server.ApiKey, server.AdministratorId, + var movieInfo = await EmbyApi.GetMovieInformation(movie.EmbyId, server.ApiKey, server.AdministratorId, server.FullUri); if (movieInfo.ProviderIds?.Imdb.HasValue() ?? false) @@ -256,7 +263,7 @@ namespace Ombi.Schedule.Jobs.Ombi } } - private async Task GetTheMovieDbId(bool hasTvDbId, bool hasImdb, string tvdbID, string imdbId, string title, bool movie) + public async Task GetTheMovieDbId(bool hasTvDbId, bool hasImdb, string tvdbID, string imdbId, string title, bool movie) { _log.LogInformation("The Media item {0} does not have a TheMovieDbId, searching for TheMovieDbId", title); FindResult result = null; @@ -365,9 +372,7 @@ namespace Ombi.Schedule.Jobs.Ombi if (disposing) { - _plexRepo?.Dispose(); - _embyRepo?.Dispose(); - _plexSettings?.Dispose(); + //_plexSettings?.Dispose(); } _disposed = true; } diff --git a/src/Ombi.Schedule/Jobs/Ombi/ResendFailedRequests.cs b/src/Ombi.Schedule/Jobs/Ombi/ResendFailedRequests.cs index 344e3a874..0072ec010 100644 --- a/src/Ombi.Schedule/Jobs/Ombi/ResendFailedRequests.cs +++ b/src/Ombi.Schedule/Jobs/Ombi/ResendFailedRequests.cs @@ -36,7 +36,7 @@ namespace Ombi.Schedule.Jobs.Ombi public async Task Execute(IJobExecutionContext job) { // Get all the failed ones! - var failedRequests = _requestQueue.GetAll().Where(x => !x.Completed.HasValue); + var failedRequests = _requestQueue.GetAll().Where(x => x.Completed == null); foreach (var request in failedRequests) { diff --git a/src/Ombi.Schedule/Jobs/Ombi/WelcomeEmail.cs b/src/Ombi.Schedule/Jobs/Ombi/WelcomeEmail.cs index f98072e9e..03733e52f 100644 --- a/src/Ombi.Schedule/Jobs/Ombi/WelcomeEmail.cs +++ b/src/Ombi.Schedule/Jobs/Ombi/WelcomeEmail.cs @@ -70,8 +70,8 @@ namespace Ombi.Schedule.Jobs.Ombi if (disposing) { - _emailSettings?.Dispose(); - _customizationSettings?.Dispose(); + //_emailSettings?.Dispose(); + //_customizationSettings?.Dispose(); } _disposed = true; } diff --git a/src/Ombi.Schedule/Jobs/Plex/Models/AvailabilityModel.cs b/src/Ombi.Schedule/Jobs/Plex/Models/AvailabilityModel.cs new file mode 100644 index 000000000..44d018404 --- /dev/null +++ b/src/Ombi.Schedule/Jobs/Plex/Models/AvailabilityModel.cs @@ -0,0 +1,10 @@ +using Ombi.Store.Entities; + +namespace Ombi.Schedule.Jobs.Plex.Models +{ + public class AvailabilityModel + { + public int Id { get; set; } + public string RequestedUser { get; set; } + } +} diff --git a/src/Ombi.Schedule/Jobs/Plex/PlexAvailabilityChecker.cs b/src/Ombi.Schedule/Jobs/Plex/PlexAvailabilityChecker.cs index e7ad5d86c..d1d26d6e1 100644 --- a/src/Ombi.Schedule/Jobs/Plex/PlexAvailabilityChecker.cs +++ b/src/Ombi.Schedule/Jobs/Plex/PlexAvailabilityChecker.cs @@ -2,14 +2,14 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -using Hangfire; using Microsoft.AspNetCore.SignalR; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; -using Ombi.Core.Notifications; +using Ombi.Core; using Ombi.Helpers; using Ombi.Hubs; using Ombi.Notifications.Models; +using Ombi.Schedule.Jobs.Plex.Models; using Ombi.Store.Entities; using Ombi.Store.Entities.Requests; using Ombi.Store.Repository; @@ -21,13 +21,12 @@ namespace Ombi.Schedule.Jobs.Plex public class PlexAvailabilityChecker : IPlexAvailabilityChecker { public PlexAvailabilityChecker(IPlexContentRepository repo, ITvRequestRepository tvRequest, IMovieRequestRepository movies, - INotificationService notification, IBackgroundJobClient background, ILogger log, IHubContext hub) + INotificationHelper notification, ILogger log, IHubContext hub) { _tvRepo = tvRequest; _repo = repo; _movieRepo = movies; _notificationService = notification; - _backgroundJobClient = background; _log = log; _notification = hub; } @@ -35,8 +34,7 @@ namespace Ombi.Schedule.Jobs.Plex private readonly ITvRequestRepository _tvRepo; private readonly IMovieRequestRepository _movieRepo; private readonly IPlexContentRepository _repo; - private readonly INotificationService _notificationService; - private readonly IBackgroundJobClient _backgroundJobClient; + private readonly INotificationHelper _notificationService; private readonly ILogger _log; private readonly IHubContext _notification; @@ -62,13 +60,13 @@ namespace Ombi.Schedule.Jobs.Plex .SendAsync(NotificationHub.NotificationEvent, "Plex Availability Check Finished"); } - private Task ProcessTv() + private async Task ProcessTv() { - var tv = _tvRepo.GetChild().Where(x => !x.Available); - return ProcessTv(tv); + var tv = await _tvRepo.GetChild().Where(x => !x.Available).ToListAsync(); + await ProcessTv(tv); } - private async Task ProcessTv(IQueryable tv) + private async Task ProcessTv(List tv) { var plexEpisodes = _repo.GetAllEpisodes().Include(x => x.Series); @@ -107,11 +105,12 @@ namespace Ombi.Schedule.Jobs.Plex { // Let's try and match the series by name seriesEpisodes = plexEpisodes.Where(x => - x.Series.Title.Equals(child.Title, StringComparison.InvariantCultureIgnoreCase) && - x.Series.ReleaseYear.Equals(child.ParentRequest.ReleaseDate.Year.ToString(), StringComparison.InvariantCultureIgnoreCase)); + x.Series.Title == child.Title && + x.Series.ReleaseYear == child.ParentRequest.ReleaseDate.Year.ToString()); } + var availableEpisode = new List(); foreach (var season in child.SeasonRequests) { foreach (var episode in season.Episodes) @@ -120,26 +119,41 @@ namespace Ombi.Schedule.Jobs.Plex { continue; } - var foundEp = await seriesEpisodes.FirstOrDefaultAsync( + var foundEp = await seriesEpisodes.AnyAsync( x => x.EpisodeNumber == episode.EpisodeNumber && x.SeasonNumber == episode.Season.SeasonNumber); - if (foundEp != null) + if (foundEp) { + availableEpisode.Add(new AvailabilityModel + { + Id = episode.Id + }); episode.Available = true; } } } + //TODO Partial avilability notifications here + if (availableEpisode.Any()) + { + await _tvRepo.Save(); + } + //foreach(var c in availableEpisode) + //{ + // await _tvRepo.MarkEpisodeAsAvailable(c.Id); + //} + // Check to see if all of the episodes in all seasons are available for this request var allAvailable = child.SeasonRequests.All(x => x.Episodes.All(c => c.Available)); if (allAvailable) { + child.Available = true; + child.MarkedAsAvailable = DateTime.UtcNow; _log.LogInformation("[PAC] - Child request {0} is now available, sending notification", $"{child.Title} - {child.Id}"); // We have ful-fulled this request! - child.Available = true; - child.MarkedAsAvailable = DateTime.Now; - await _notificationService.Publish(new NotificationOptions + await _tvRepo.Save(); + await _notificationService.Notify(new NotificationOptions { DateTime = DateTime.Now, NotificationType = NotificationType.RequestAvailable, @@ -157,9 +171,15 @@ namespace Ombi.Schedule.Jobs.Plex { // Get all non available var movies = _movieRepo.GetAll().Include(x => x.RequestedUser).Where(x => !x.Available); + var itemsForAvailbility = new List(); foreach (var movie in movies) { + if (movie.Available) + { + return; + } + PlexServerContent item = null; if (movie.ImdbId.HasValue()) { @@ -178,24 +198,34 @@ namespace Ombi.Schedule.Jobs.Plex continue; } + _log.LogInformation("[PAC] - Movie request {0} is now available, sending notification", $"{movie.Title} - {movie.Id}"); movie.Available = true; - movie.MarkedAsAvailable = DateTime.Now; - item.RequestId = movie.Id; + movie.MarkedAsAvailable = DateTime.UtcNow; + itemsForAvailbility.Add(new AvailabilityModel + { + Id = movie.Id, + RequestedUser = movie.RequestedUser != null ? movie.RequestedUser.Email : string.Empty + }); + } - _log.LogInformation("[PAC] - Movie request {0} is now available, sending notification", $"{movie.Title} - {movie.Id}"); - await _notificationService.Publish(new NotificationOptions + if (itemsForAvailbility.Any()) + { + await _movieRepo.SaveChangesAsync(); + } + foreach (var i in itemsForAvailbility) + { + + await _notificationService.Notify(new NotificationOptions { DateTime = DateTime.Now, NotificationType = NotificationType.RequestAvailable, - RequestId = movie.Id, + RequestId = i.Id, RequestType = RequestType.Movie, - Recipient = movie.RequestedUser != null ? movie.RequestedUser.Email : string.Empty + Recipient = i.RequestedUser }); - } - await _movieRepo.Save(); - await _repo.SaveChangesAsync(); + //await _repo.SaveChangesAsync(); } private bool _disposed; @@ -206,8 +236,6 @@ namespace Ombi.Schedule.Jobs.Plex if (disposing) { - _movieRepo?.Dispose(); - _repo?.Dispose(); } _disposed = true; } diff --git a/src/Ombi.Schedule/Jobs/Plex/PlexContentSync.cs b/src/Ombi.Schedule/Jobs/Plex/PlexContentSync.cs index f698a2dc3..f554e428d 100644 --- a/src/Ombi.Schedule/Jobs/Plex/PlexContentSync.cs +++ b/src/Ombi.Schedule/Jobs/Plex/PlexContentSync.cs @@ -29,7 +29,6 @@ using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -using Hangfire; using Microsoft.AspNetCore.SignalR; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; @@ -79,13 +78,11 @@ namespace Ombi.Schedule.Jobs.Plex { return; } - await Notification.Clients.Clients(NotificationHub.AdminConnectionIds) - .SendAsync(NotificationHub.NotificationEvent, recentlyAddedSearch ? "Plex Recently Added Sync Started" : "Plex Content Sync Started"); + await NotifyClient(recentlyAddedSearch ? "Plex Recently Added Sync Started" : "Plex Content Sync Started"); if (!ValidateSettings(plexSettings)) { Logger.LogError("Plex Settings are not valid"); - await Notification.Clients.Clients(NotificationHub.AdminConnectionIds) - .SendAsync(NotificationHub.NotificationEvent, recentlyAddedSearch ? "Plex Recently Added Sync, Settings Not Valid" : "Plex Content, Settings Not Valid"); + await NotifyClient(recentlyAddedSearch ? "Plex Recently Added Sync, Settings Not Valid" : "Plex Content, Settings Not Valid"); return; } var processedContent = new ProcessedContent(); @@ -105,35 +102,28 @@ namespace Ombi.Schedule.Jobs.Plex } catch (Exception e) { - await Notification.Clients.Clients(NotificationHub.AdminConnectionIds) - .SendAsync(NotificationHub.NotificationEvent, recentlyAddedSearch ? "Plex Recently Added Sync Errored" : "Plex Content Sync Errored"); + await NotifyClient(recentlyAddedSearch ? "Plex Recently Added Sync Errored" : "Plex Content Sync Errored"); Logger.LogWarning(LoggingEvents.PlexContentCacher, e, "Exception thrown when attempting to cache the Plex Content"); } if (!recentlyAddedSearch) { + await NotifyClient("Plex Sync - Starting Episode Sync"); Logger.LogInformation("Starting EP Cacher"); await OmbiQuartz.TriggerJob(nameof(IPlexEpisodeSync), "Plex"); } if ((processedContent?.HasProcessedContent ?? false) && recentlyAddedSearch) { + await NotifyClient("Plex Sync - Checking if any requests are now available"); Logger.LogInformation("Kicking off Plex Availability Checker"); await OmbiQuartz.TriggerJob(nameof(IPlexAvailabilityChecker), "Plex"); - Logger.LogInformation("Starting Metadata refresh"); - // Just check what we send it - await OmbiQuartz.TriggerJob(nameof(IRefreshMetadata), "System"); - } - - if ((processedContent?.HasProcessedContent ?? false) && recentlyAddedSearch) - { - - await OmbiQuartz.TriggerJob(nameof(IPlexAvailabilityChecker), "Plex"); } - Logger.LogInformation("Finished Plex Content Cacher, with processed content: {0}, episodes: {1}. Recently Added Scan: {2}", processedContent?.Content?.Count() ?? 0, processedContent?.Episodes?.Count() ?? 0, recentlyAddedSearch); + var processedCont = processedContent?.Content?.Count() ?? 0; + var processedEp = processedContent?.Episodes?.Count() ?? 0; + Logger.LogInformation("Finished Plex Content Cacher, with processed content: {0}, episodes: {1}. Recently Added Scan: {2}", processedCont, processedEp, recentlyAddedSearch); - await Notification.Clients.Clients(NotificationHub.AdminConnectionIds) - .SendAsync(NotificationHub.NotificationEvent, recentlyAddedSearch ? "Plex Recently Added Sync Finished" : "Plex Content Sync Finished"); + await NotifyClient(recentlyAddedSearch ? $"Plex Recently Added Sync Finished, We processed {processedCont}, and {processedEp} Episodes" : "Plex Content Sync Finished"); } @@ -175,6 +165,7 @@ namespace Ombi.Schedule.Jobs.Plex var allContent = await GetAllContent(servers, recentlyAddedSearch); Logger.LogDebug("We found {0} items", allContent.Count); + // Let's now process this. var contentToAdd = new HashSet(); @@ -187,7 +178,7 @@ namespace Ombi.Schedule.Jobs.Plex { Logger.LogDebug("Found some episodes, this must be a recently added sync"); var count = 0; - foreach (var epInfo in content.Metadata ?? new Metadata[]{}) + foreach (var epInfo in content.Metadata ?? new Metadata[] { }) { count++; var grandParentKey = epInfo.grandparentRatingKey; @@ -202,11 +193,15 @@ namespace Ombi.Schedule.Jobs.Plex await ProcessTvShow(servers, show, contentToAdd, contentProcessed); if (contentToAdd.Any()) { - await Repo.AddRange(contentToAdd, false); + await Repo.AddRange(contentToAdd, recentlyAddedSearch ? true : false); if (recentlyAddedSearch) { foreach (var plexServerContent in contentToAdd) { + if (plexServerContent.Id <= 0) + { + Logger.LogInformation($"Item '{plexServerContent.Title}' has an Plex ID of {plexServerContent.Id} and a Plex Key of {plexServerContent.Key}"); + } contentProcessed.Add(plexServerContent.Id, plexServerContent.Key); } } @@ -286,9 +281,21 @@ namespace Ombi.Schedule.Jobs.Plex Logger.LogDebug("Adding movie {0}", movie.title); var metaData = await PlexApi.GetMetadata(servers.PlexAuthToken, servers.FullUri, movie.ratingKey); - var providerIds = PlexHelper.GetProviderIdFromPlexGuid(metaData.MediaContainer.Metadata - .FirstOrDefault() - .guid); + + var meta = metaData.MediaContainer.Metadata.FirstOrDefault(); + var guids = new List + { + meta.guid + }; + if (meta.Guid != null) + { + foreach (var g in meta.Guid) + { + guids.Add(g.Id); + } + } + + var providerIds = PlexHelper.GetProviderIdsFromMetadata(guids.ToArray()); var item = new PlexServerContent { @@ -301,15 +308,15 @@ namespace Ombi.Schedule.Jobs.Plex Seasons = new List(), Quality = movie.Media?.FirstOrDefault()?.videoResolution ?? string.Empty }; - if (providerIds.Type == ProviderType.ImdbId) + if (providerIds.ImdbId.HasValue()) { item.ImdbId = providerIds.ImdbId; } - if (providerIds.Type == ProviderType.TheMovieDbId) + if (providerIds.TheMovieDb.HasValue()) { item.TheMovieDbId = providerIds.TheMovieDb; } - if (providerIds.Type == ProviderType.TvDbId) + if (providerIds.TheTvDb.HasValue()) { item.TvDbId = providerIds.TheTvDb; } @@ -395,7 +402,7 @@ namespace Ombi.Schedule.Jobs.Plex await Repo.Delete(existingKey); existingKey = null; } - else if(existingContent == null) + else if (existingContent == null) { existingContent = await Repo.GetFirstContentByCustom(x => x.Key == show.ratingKey); } @@ -513,7 +520,7 @@ namespace Ombi.Schedule.Jobs.Plex // But it does not contain the `guid` property that we need to pull out thetvdb id... var showMetadata = await PlexApi.GetMetadata(servers.PlexAuthToken, servers.FullUri, show.ratingKey); - + var item = new PlexServerContent { AddedAt = DateTime.Now, @@ -568,20 +575,31 @@ namespace Ombi.Schedule.Jobs.Plex private static void GetProviderIds(PlexMetadata showMetadata, PlexServerContent existingContent) { + var metadata = showMetadata.MediaContainer.Metadata.FirstOrDefault(); + var guids = new List + { + metadata.guid + }; + if (metadata.Guid != null) + { + foreach (var g in metadata.Guid) + { + guids.Add(g.Id); + } + } var providerIds = - PlexHelper.GetProviderIdFromPlexGuid(showMetadata.MediaContainer.Metadata.FirstOrDefault() - .guid); - if (providerIds.Type == ProviderType.ImdbId) + PlexHelper.GetProviderIdsFromMetadata(guids.ToArray()); + if (providerIds.ImdbId.HasValue()) { existingContent.ImdbId = providerIds.ImdbId; } - if (providerIds.Type == ProviderType.TheMovieDbId) + if (providerIds.TheMovieDb.HasValue()) { existingContent.TheMovieDbId = providerIds.TheMovieDb; } - if (providerIds.Type == ProviderType.TvDbId) + if (providerIds.TheTvDb.HasValue()) { existingContent.TvDbId = providerIds.TheTvDb; } @@ -643,7 +661,11 @@ namespace Ombi.Schedule.Jobs.Plex return libs; } - + private async Task NotifyClient(string message) + { + await Notification.Clients.Clients(NotificationHub.AdminConnectionIds) + .SendAsync(NotificationHub.NotificationEvent, $"Plex Sync - {message}"); + } private static bool ValidateSettings(PlexSettings plex) { @@ -668,8 +690,7 @@ namespace Ombi.Schedule.Jobs.Plex if (disposing) { - Plex?.Dispose(); - Repo?.Dispose(); + //Plex?.Dispose(); EpisodeSync?.Dispose(); } _disposed = true; diff --git a/src/Ombi.Schedule/Jobs/Plex/PlexEpisodeSync.cs b/src/Ombi.Schedule/Jobs/Plex/PlexEpisodeSync.cs index b6e54849b..50c5d1f39 100644 --- a/src/Ombi.Schedule/Jobs/Plex/PlexEpisodeSync.cs +++ b/src/Ombi.Schedule/Jobs/Plex/PlexEpisodeSync.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -using Hangfire; using Microsoft.AspNetCore.SignalR; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; @@ -12,6 +11,7 @@ using Ombi.Core.Settings; using Ombi.Core.Settings.Models.External; using Ombi.Helpers; using Ombi.Hubs; +using Ombi.Schedule.Jobs.Ombi; using Ombi.Schedule.Jobs.Plex.Interfaces; using Ombi.Store.Entities; using Ombi.Store.Repository; @@ -64,7 +64,9 @@ namespace Ombi.Schedule.Jobs.Plex } - await OmbiQuartz.TriggerJob(nameof(IPlexAvailabilityChecker), "Plex"); + _log.LogInformation("Plex Episode Sync Finished - Triggering Metadata refresh"); + await OmbiQuartz.TriggerJob(nameof(IRefreshMetadata), "System"); + await _notification.Clients.Clients(NotificationHub.AdminConnectionIds) .SendAsync(NotificationHub.NotificationEvent, "Plex Episode Sync Finished"); } @@ -164,7 +166,7 @@ namespace Ombi.Schedule.Jobs.Plex { // Ok let's try and match it to a title. TODO (This is experimental) seriesExists = await _repo.GetAll().FirstOrDefaultAsync(x => - x.Title.Equals(episode.grandparentTitle, StringComparison.CurrentCultureIgnoreCase)); + x.Title == episode.grandparentTitle); if (seriesExists == null) { _log.LogWarning( @@ -216,8 +218,7 @@ namespace Ombi.Schedule.Jobs.Plex if (disposing) { - _repo?.Dispose(); - _settings?.Dispose(); + //_settings?.Dispose(); } _disposed = true; } @@ -228,4 +229,4 @@ namespace Ombi.Schedule.Jobs.Plex GC.SuppressFinalize(this); } } -} \ No newline at end of file +} diff --git a/src/Ombi.Schedule/Jobs/Plex/PlexUserImporter.cs b/src/Ombi.Schedule/Jobs/Plex/PlexUserImporter.cs index 5451e80a8..c80703f81 100644 --- a/src/Ombi.Schedule/Jobs/Plex/PlexUserImporter.cs +++ b/src/Ombi.Schedule/Jobs/Plex/PlexUserImporter.cs @@ -195,8 +195,8 @@ namespace Ombi.Schedule.Jobs.Plex if (disposing) { _userManager?.Dispose(); - _plexSettings?.Dispose(); - _userManagementSettings?.Dispose(); + //_plexSettings?.Dispose(); + //_userManagementSettings?.Dispose(); } _disposed = true; } diff --git a/src/Ombi.Schedule/Jobs/Radarr/RadarrSync.cs b/src/Ombi.Schedule/Jobs/Radarr/RadarrSync.cs index 56a97b0ab..3657fba61 100644 --- a/src/Ombi.Schedule/Jobs/Radarr/RadarrSync.cs +++ b/src/Ombi.Schedule/Jobs/Radarr/RadarrSync.cs @@ -49,29 +49,29 @@ namespace Ombi.Schedule.Jobs.Radarr // Let's remove the old cached data using (var tran = await _ctx.Database.BeginTransactionAsync()) { - await _ctx.Database.ExecuteSqlCommandAsync("DELETE FROM RadarrCache"); + await _ctx.Database.ExecuteSqlRawAsync("DELETE FROM RadarrCache"); tran.Commit(); } var movieIds = new List(); foreach (var m in movies) { - if(m.monitored) - { - if (m.tmdbId > 0) + if (m.monitored || m.hasFile) { - movieIds.Add(new RadarrCache + if (m.tmdbId > 0) { - TheMovieDbId = m.tmdbId, - HasFile = m.hasFile - }); - } - else - { - Logger.LogError("TMDBId is not > 0 for movie {0}", m.title); + movieIds.Add(new RadarrCache + { + TheMovieDbId = m.tmdbId, + HasFile = m.hasFile + }); + } + else + { + Logger.LogError("TMDBId is not > 0 for movie {0}", m.title); + } } } - } using (var tran = await _ctx.Database.BeginTransactionAsync()) { @@ -81,6 +81,8 @@ namespace Ombi.Schedule.Jobs.Radarr tran.Commit(); } } + + await OmbiQuartz.TriggerJob(nameof(IArrAvailabilityChecker), "DVR"); } catch (System.Exception ex) { @@ -112,7 +114,7 @@ namespace Ombi.Schedule.Jobs.Radarr if (disposing) { _ctx?.Dispose(); - RadarrSettings?.Dispose(); + //RadarrSettings?.Dispose(); } _disposed = true; } diff --git a/src/Ombi.Schedule/Jobs/SickRage/SickRageSync.cs b/src/Ombi.Schedule/Jobs/SickRage/SickRageSync.cs index fbf594281..a223a0cfa 100644 --- a/src/Ombi.Schedule/Jobs/SickRage/SickRageSync.cs +++ b/src/Ombi.Schedule/Jobs/SickRage/SickRageSync.cs @@ -48,7 +48,7 @@ namespace Ombi.Schedule.Jobs.SickRage var ids = srShows.Select(x => x.tvdbid); using (var tran = await _ctx.Database.BeginTransactionAsync()) { - await _ctx.Database.ExecuteSqlCommandAsync("DELETE FROM SickRageCache"); + await _ctx.Database.ExecuteSqlRawAsync("DELETE FROM SickRageCache"); tran.Commit(); } @@ -57,7 +57,7 @@ namespace Ombi.Schedule.Jobs.SickRage await _ctx.SickRageCache.AddRangeAsync(entites); var episodesToAdd = new List(); - await _ctx.Database.ExecuteSqlCommandAsync("DELETE FROM SickRageEpisodeCache"); + await _ctx.Database.ExecuteSqlRawAsync("DELETE FROM SickRageEpisodeCache"); foreach (var s in srShows) { var seasons = await _api.GetSeasonList(s.tvdbid, settings.ApiKey, settings.FullUri); @@ -100,7 +100,7 @@ namespace Ombi.Schedule.Jobs.SickRage if (disposing) { - _settings?.Dispose(); + //_settings?.Dispose(); _ctx?.Dispose(); } _disposed = true; diff --git a/src/Ombi.Schedule/Jobs/Sonarr/SonarrSync.cs b/src/Ombi.Schedule/Jobs/Sonarr/SonarrSync.cs index e8707cc3a..bf3ee8406 100644 --- a/src/Ombi.Schedule/Jobs/Sonarr/SonarrSync.cs +++ b/src/Ombi.Schedule/Jobs/Sonarr/SonarrSync.cs @@ -11,6 +11,7 @@ using Ombi.Api.Sonarr; using Ombi.Api.Sonarr.Models; using Ombi.Core.Settings; using Ombi.Helpers; +using Ombi.Schedule.Jobs.Radarr; using Ombi.Settings.Settings.Models.External; using Ombi.Store.Context; using Ombi.Store.Entities; @@ -33,7 +34,7 @@ namespace Ombi.Schedule.Jobs.Sonarr private readonly ISonarrApi _api; private readonly ILogger _log; private readonly ExternalContext _ctx; - + public async Task Execute(IJobExecutionContext job) { try @@ -50,49 +51,84 @@ namespace Ombi.Schedule.Jobs.Sonarr var ids = sonarrSeries.Select(x => x.tvdbId); using (var tran = await _ctx.Database.BeginTransactionAsync()) { - await _ctx.Database.ExecuteSqlCommandAsync("DELETE FROM SonarrCache"); + await _ctx.Database.ExecuteSqlRawAsync("DELETE FROM SonarrCache"); tran.Commit(); } + var existingSeries = await _ctx.SonarrCache.Select(x => x.TvDbId).ToListAsync(); + + //var entites = ids.Except(existingSeries).Select(id => new SonarrCache { TvDbId = id }).ToImmutableHashSet(); var entites = ids.Select(id => new SonarrCache { TvDbId = id }).ToImmutableHashSet(); await _ctx.SonarrCache.AddRangeAsync(entites); entites.Clear(); using (var tran = await _ctx.Database.BeginTransactionAsync()) { - await _ctx.Database.ExecuteSqlCommandAsync("DELETE FROM SonarrEpisodeCache"); + await _ctx.Database.ExecuteSqlRawAsync("DELETE FROM SonarrEpisodeCache"); tran.Commit(); } foreach (var s in sonarrSeries) { - if (!s.monitored) + if (!s.monitored || s.episodeFileCount == 0) // We have files { continue; } + _log.LogDebug("Syncing series: {0}", s.title); var episodes = await _api.GetEpisodes(s.id, settings.ApiKey, settings.FullUri); var monitoredEpisodes = episodes.Where(x => x.monitored || x.hasFile); - + + //var allExistingEpisodes = await _ctx.SonarrEpisodeCache.Where(x => x.TvDbId == s.tvdbId).ToListAsync(); // Add to DB _log.LogDebug("We have the episodes, adding to db transaction"); - using (var tran = await _ctx.Database.BeginTransactionAsync()) - { - await _ctx.SonarrEpisodeCache.AddRangeAsync(monitoredEpisodes.Select(episode => + var episodesToAdd = monitoredEpisodes.Select(episode => new SonarrEpisodeCache { EpisodeNumber = episode.episodeNumber, SeasonNumber = episode.seasonNumber, TvDbId = s.tvdbId, HasFile = episode.hasFile - })); + }); + //var episodesToAdd = new List(); + + //foreach (var monitored in monitoredEpisodes) + //{ + // var existing = allExistingEpisodes.FirstOrDefault(x => x.SeasonNumber == monitored.seasonNumber && x.EpisodeNumber == monitored.episodeNumber); + // if (existing == null) + // { + // // Just add a new one + // episodesToAdd.Add(new SonarrEpisodeCache + // { + // EpisodeNumber = monitored.episodeNumber, + // SeasonNumber = monitored.seasonNumber, + // TvDbId = s.tvdbId, + // HasFile = monitored.hasFile + // }); + // } + // else + // { + // // Do we need to update the availability? + // if (monitored.hasFile != existing.HasFile) + // { + // existing.HasFile = monitored.hasFile; + // } + // } + + //} + + using (var tran = await _ctx.Database.BeginTransactionAsync()) + { + await _ctx.SonarrEpisodeCache.AddRangeAsync(episodesToAdd); _log.LogDebug("Commiting the transaction"); await _ctx.SaveChangesAsync(); tran.Commit(); } } - + } + + await OmbiQuartz.TriggerJob(nameof(IArrAvailabilityChecker), "DVR"); } catch (Exception e) { @@ -108,7 +144,7 @@ namespace Ombi.Schedule.Jobs.Sonarr if (disposing) { - _settings?.Dispose(); + //_settings?.Dispose(); _ctx?.Dispose(); } _disposed = true; diff --git a/src/Ombi.Schedule/Ombi.Schedule.csproj b/src/Ombi.Schedule/Ombi.Schedule.csproj index 4145c081e..ac63d5b2f 100644 --- a/src/Ombi.Schedule/Ombi.Schedule.csproj +++ b/src/Ombi.Schedule/Ombi.Schedule.csproj @@ -1,23 +1,17 @@  - netstandard2.1 + net5.0 3.0.0.0 3.0.0.0 + 8.0 - - - - - - - - + diff --git a/src/Ombi.Schedule/OmbiScheduler.cs b/src/Ombi.Schedule/OmbiScheduler.cs index 75305b84f..4a91052c7 100644 --- a/src/Ombi.Schedule/OmbiScheduler.cs +++ b/src/Ombi.Schedule/OmbiScheduler.cs @@ -1,8 +1,9 @@ using System; using System.Collections.Generic; using System.Threading.Tasks; -using Microsoft.AspNetCore.Builder; +using Ombi.Core.Notifications; using Ombi.Core.Settings; +using Ombi.Helpers; using Ombi.Schedule.Jobs; using Ombi.Schedule.Jobs.Couchpotato; using Ombi.Schedule.Jobs.Emby; @@ -14,7 +15,6 @@ using Ombi.Schedule.Jobs.Radarr; using Ombi.Schedule.Jobs.SickRage; using Ombi.Schedule.Jobs.Sonarr; using Ombi.Settings.Settings.Models; -using Quartz; using Quartz.Spi; namespace Ombi.Schedule @@ -53,6 +53,7 @@ namespace Ombi.Schedule await AddEmby(s); await AddDvrApps(s); await AddSystem(s); + await AddNotifications(s); // Run Quartz await OmbiQuartz.Start(); @@ -66,12 +67,14 @@ namespace Ombi.Schedule await OmbiQuartz.Instance.AddJob(nameof(INewsletterJob), "System", JobSettingsHelper.Newsletter(s)); await OmbiQuartz.Instance.AddJob(nameof(IResendFailedRequests), "System", JobSettingsHelper.ResendFailedRequests(s)); await OmbiQuartz.Instance.AddJob(nameof(IMediaDatabaseRefresh), "System", JobSettingsHelper.MediaDatabaseRefresh(s)); + await OmbiQuartz.Instance.AddJob(nameof(IAutoDeleteRequests), "System", JobSettingsHelper.AutoDeleteRequests(s)); } private static async Task AddDvrApps(JobSettings s) { await OmbiQuartz.Instance.AddJob(nameof(ISonarrSync), "DVR", JobSettingsHelper.Sonarr(s)); await OmbiQuartz.Instance.AddJob(nameof(IRadarrSync), "DVR", JobSettingsHelper.Radarr(s)); + await OmbiQuartz.Instance.AddJob(nameof(IArrAvailabilityChecker), "DVR", null); await OmbiQuartz.Instance.AddJob(nameof(ICouchPotatoSync), "DVR", JobSettingsHelper.CouchPotato(s)); await OmbiQuartz.Instance.AddJob(nameof(ISickRageSync), "DVR", JobSettingsHelper.SickRageSync(s)); await OmbiQuartz.Instance.AddJob(nameof(ILidarrArtistSync), "DVR", JobSettingsHelper.LidarrArtistSync(s)); @@ -95,5 +98,9 @@ namespace Ombi.Schedule await OmbiQuartz.Instance.AddJob(nameof(IEmbyAvaliabilityChecker), "Emby", null); await OmbiQuartz.Instance.AddJob(nameof(IEmbyUserImporter), "Emby", JobSettingsHelper.UserImporter(s)); } + private static async Task AddNotifications(JobSettings s) + { + await OmbiQuartz.Instance.AddJob(nameof(INotificationService), "Notifications", null); + } } } \ No newline at end of file diff --git a/src/Ombi.Schedule/QuartzJobRunner.cs b/src/Ombi.Schedule/QuartzJobRunner.cs new file mode 100644 index 000000000..2a8a39db0 --- /dev/null +++ b/src/Ombi.Schedule/QuartzJobRunner.cs @@ -0,0 +1,27 @@ +using System; +using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection; +using Quartz; + +namespace Ombi.Schedule +{ + public class QuartzJobRunner : IJob + { + private readonly IServiceProvider _serviceProvider; + public QuartzJobRunner(IServiceProvider serviceProvider) + { + _serviceProvider = serviceProvider; + } + + public async Task Execute(IJobExecutionContext context) + { + using (var scope = _serviceProvider.CreateScope()) + { + var jobType = context.JobDetail.JobType; + var job = scope.ServiceProvider.GetRequiredService(jobType) as IJob; + + await job.Execute(context); + } + } + } +} \ No newline at end of file diff --git a/src/Ombi.Settings.Tests/CustomizationSettingsTests.cs b/src/Ombi.Settings.Tests/CustomizationSettingsTests.cs index 6d83b99d9..ad0516305 100644 --- a/src/Ombi.Settings.Tests/CustomizationSettingsTests.cs +++ b/src/Ombi.Settings.Tests/CustomizationSettingsTests.cs @@ -15,9 +15,9 @@ namespace Tests { ApplicationUrl = applicationUrl }; - c.AddToUrl(append); + var result = c.AddToUrl(append); - return c.ApplicationUrl; + return result; } public static IEnumerable TestData @@ -25,6 +25,8 @@ namespace Tests get { yield return new TestCaseData("https://google.com/", "token?").Returns("https://google.com/token?").SetName("ForwardSlash_On_AppUrl_NotOn_Append"); + yield return new TestCaseData("https://google.com", "token?").Returns("https://google.com/token?").SetName("NoForwardSlash_On_AppUrl_NotOn_Append"); + yield return new TestCaseData(null, "token?").Returns(null).SetName("NullValue"); } } } diff --git a/src/Ombi.Settings.Tests/Ombi.Settings.Tests.csproj b/src/Ombi.Settings.Tests/Ombi.Settings.Tests.csproj index ad99af008..4e86eb9fe 100644 --- a/src/Ombi.Settings.Tests/Ombi.Settings.Tests.csproj +++ b/src/Ombi.Settings.Tests/Ombi.Settings.Tests.csproj @@ -1,6 +1,6 @@  - netcoreapp3.0 + net5.0 false @@ -8,7 +8,8 @@ - + + diff --git a/src/Ombi.Settings/Ombi.Settings.csproj b/src/Ombi.Settings/Ombi.Settings.csproj index 96f01a823..dc015ef9f 100644 --- a/src/Ombi.Settings/Ombi.Settings.csproj +++ b/src/Ombi.Settings/Ombi.Settings.csproj @@ -1,17 +1,18 @@  - netstandard2.1 + net5.0 3.0.0.0 3.0.0.0 + 8.0 - - - + + + diff --git a/src/Ombi.Settings/Settings/ISettingsService.cs b/src/Ombi.Settings/Settings/ISettingsService.cs index 70c5ebeb8..80c8a338f 100644 --- a/src/Ombi.Settings/Settings/ISettingsService.cs +++ b/src/Ombi.Settings/Settings/ISettingsService.cs @@ -3,7 +3,7 @@ using System.Threading.Tasks; namespace Ombi.Core.Settings { - public interface ISettingsService : IDisposable + public interface ISettingsService { T GetSettings(); Task GetSettingsAsync(); diff --git a/src/Ombi.Settings/Settings/Models/CustomizationSettings.cs b/src/Ombi.Settings/Settings/Models/CustomizationSettings.cs index a9fcf8f83..1f2155331 100644 --- a/src/Ombi.Settings/Settings/Models/CustomizationSettings.cs +++ b/src/Ombi.Settings/Settings/Models/CustomizationSettings.cs @@ -11,23 +11,26 @@ public string Logo { get; set; } public bool RecentlyAddedPage { get; set; } public bool UseCustomPage { get; set; } + public bool HideAvailableFromDiscover { get; set; } - public void AddToUrl(string part) + public string AddToUrl(string part) { - if (string.IsNullOrEmpty(ApplicationUrl)) + var appUrl = ApplicationUrl; + if (string.IsNullOrEmpty(appUrl)) { - ApplicationUrl = part; + return null; } - if (ApplicationUrl.EndsWith("/")) + if (appUrl.EndsWith("/")) { - ApplicationUrl = ApplicationUrl.Remove(ApplicationUrl.Length - 1); + appUrl = appUrl.Remove(ApplicationUrl.Length - 1); } if (!part.StartsWith("/")) { part = "/" + part; } - ApplicationUrl = ApplicationUrl + part; + appUrl = appUrl + part; + return appUrl; } } } \ No newline at end of file diff --git a/src/Ombi.Settings/Settings/Models/External/EmbySettings.cs b/src/Ombi.Settings/Settings/Models/External/EmbySettings.cs index 3ade5746b..b3ffce0e1 100644 --- a/src/Ombi.Settings/Settings/Models/External/EmbySettings.cs +++ b/src/Ombi.Settings/Settings/Models/External/EmbySettings.cs @@ -12,6 +12,7 @@ namespace Ombi.Core.Settings.Models.External public class EmbyServers : ExternalSettings { + public string ServerId { get; set; } public string Name { get; set; } public string ApiKey { get; set; } public string AdministratorId { get; set; } diff --git a/src/Ombi.Settings/Settings/Models/External/RadarrSettings.cs b/src/Ombi.Settings/Settings/Models/External/RadarrSettings.cs index bfed9708c..ca9bd266f 100644 --- a/src/Ombi.Settings/Settings/Models/External/RadarrSettings.cs +++ b/src/Ombi.Settings/Settings/Models/External/RadarrSettings.cs @@ -1,14 +1,14 @@ -using Ombi.Core.Settings.Models.External; - -namespace Ombi.Settings.Settings.Models.External +namespace Ombi.Settings.Settings.Models.External { public class RadarrSettings : ExternalSettings { public bool Enabled { get; set; } + public bool V3 { get; set; } public string ApiKey { get; set; } public string DefaultQualityProfile { get; set; } public string DefaultRootPath { get; set; } public bool AddOnly { get; set; } public string MinimumAvailability { get; set; } + public bool ScanForAvailability { get; set; } } } \ No newline at end of file diff --git a/src/Ombi.Settings/Settings/Models/External/SonarrSettings.cs b/src/Ombi.Settings/Settings/Models/External/SonarrSettings.cs index bbbe58fd3..44c910519 100644 --- a/src/Ombi.Settings/Settings/Models/External/SonarrSettings.cs +++ b/src/Ombi.Settings/Settings/Models/External/SonarrSettings.cs @@ -20,5 +20,6 @@ public bool AddOnly { get; set; } public bool V3 { get; set; } public int LanguageProfile { get; set; } + public bool ScanForAvailability { get; set; } } } \ No newline at end of file diff --git a/src/Ombi.Settings/Settings/Models/JobSettings.cs b/src/Ombi.Settings/Settings/Models/JobSettings.cs index 4376088a3..9bdad5e2b 100644 --- a/src/Ombi.Settings/Settings/Models/JobSettings.cs +++ b/src/Ombi.Settings/Settings/Models/JobSettings.cs @@ -11,11 +11,11 @@ public string AutomaticUpdater { get; set; } public string UserImporter { get; set; } public string SickRageSync { get; set; } - public string RefreshMetadata { get; set; } public string Newsletter { get; set; } public string LidarrArtistSync { get; set; } public string IssuesPurge { get; set; } public string RetryRequests { get; set; } public string MediaDatabaseRefresh { get; set; } + public string AutoDeleteRequests { get; set; } } } \ No newline at end of file diff --git a/src/Ombi.Settings/Settings/Models/JobSettingsHelper.cs b/src/Ombi.Settings/Settings/Models/JobSettingsHelper.cs index 272ad3444..2778ba478 100644 --- a/src/Ombi.Settings/Settings/Models/JobSettingsHelper.cs +++ b/src/Ombi.Settings/Settings/Models/JobSettingsHelper.cs @@ -56,11 +56,6 @@ namespace Ombi.Settings.Settings.Models return ValidateCron(Get(s.SickRageSync, Cron.Hourly(35))); } - public static string RefreshMetadata(JobSettings s) - { - return ValidateCron(Get(s.RefreshMetadata, Cron.DayInterval(3))); - } - public static string LidarrArtistSync(JobSettings s) { return ValidateCron(Get(s.LidarrArtistSync, Cron.Hourly(40))); @@ -81,6 +76,11 @@ namespace Ombi.Settings.Settings.Models return ValidateCron(Get(s.MediaDatabaseRefresh, Cron.DayInterval(5))); } + public static string AutoDeleteRequests(JobSettings s) + { + return ValidateCron(Get(s.AutoDeleteRequests, Cron.Daily())); + } + private static string Get(string settings, string defaultCron) { return settings.HasValue() ? settings : defaultCron; diff --git a/src/Ombi.Settings/Settings/Models/Notifications/DiscordNotificationSettings.cs b/src/Ombi.Settings/Settings/Models/Notifications/DiscordNotificationSettings.cs index 2616fa4c3..45dc17ee1 100644 --- a/src/Ombi.Settings/Settings/Models/Notifications/DiscordNotificationSettings.cs +++ b/src/Ombi.Settings/Settings/Models/Notifications/DiscordNotificationSettings.cs @@ -8,6 +8,7 @@ namespace Ombi.Settings.Settings.Models.Notifications public bool Enabled { get; set; } public string WebhookUrl { get; set; } public string Username { get; set; } + public string Icon { get; set; } [JsonIgnore] public string WebHookId => SplitWebUrl(4); diff --git a/src/Ombi.Settings/Settings/Models/Notifications/TwilioSettings.cs b/src/Ombi.Settings/Settings/Models/Notifications/TwilioSettings.cs new file mode 100644 index 000000000..d4b0d69ba --- /dev/null +++ b/src/Ombi.Settings/Settings/Models/Notifications/TwilioSettings.cs @@ -0,0 +1,15 @@ +namespace Ombi.Settings.Settings.Models.Notifications +{ + public class TwilioSettings : Settings + { + public WhatsAppSettings WhatsAppSettings { get; set; } + } + + public class WhatsAppSettings + { + public bool Enabled { get; set; } + public string From { get; set; } + public string AccountSid { get; set; } + public string AuthToken { get; set; } + } +} \ No newline at end of file diff --git a/src/Ombi.Settings/Settings/Models/Notifications/WebhookSettings.cs b/src/Ombi.Settings/Settings/Models/Notifications/WebhookSettings.cs new file mode 100644 index 000000000..1c304e84c --- /dev/null +++ b/src/Ombi.Settings/Settings/Models/Notifications/WebhookSettings.cs @@ -0,0 +1,9 @@ +namespace Ombi.Settings.Settings.Models.Notifications +{ + public class WebhookSettings : Settings + { + public bool Enabled { get; set; } + public string WebhookUrl { get; set; } + public string ApplicationToken { get; set; } + } +} \ No newline at end of file diff --git a/src/Ombi.Settings/Settings/Models/OmbiSettings.cs b/src/Ombi.Settings/Settings/Models/OmbiSettings.cs index e0787326e..11812e439 100644 --- a/src/Ombi.Settings/Settings/Models/OmbiSettings.cs +++ b/src/Ombi.Settings/Settings/Models/OmbiSettings.cs @@ -10,6 +10,9 @@ public bool IgnoreCertificateErrors { get; set; } public bool DoNotSendNotificationsForAutoApprove { get; set; } public bool HideRequestsUsers { get; set; } + public bool DisableHealthChecks { get; set; } public string DefaultLanguageCode { get; set; } = "en"; + public bool AutoDeleteAvailableRequests { get; set; } + public int AutoDeleteAfterDays { get; set; } } } \ No newline at end of file diff --git a/src/Ombi.Settings/Settings/SettingsService.cs b/src/Ombi.Settings/Settings/SettingsService.cs index 57ae482a2..d2f2fdef6 100644 --- a/src/Ombi.Settings/Settings/SettingsService.cs +++ b/src/Ombi.Settings/Settings/SettingsService.cs @@ -155,24 +155,5 @@ namespace Ombi.Settings.Settings return settings.Content; //return _protector.Unprotect(settings.Content); } - - private bool _disposed; - protected virtual void Dispose(bool disposing) - { - if (_disposed) - return; - - if (disposing) - { - Repo?.Dispose(); - } - _disposed = true; - } - - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } } } \ No newline at end of file diff --git a/src/Ombi.Store/Context/MySql/OmbiMySqlContext.cs b/src/Ombi.Store/Context/MySql/OmbiMySqlContext.cs index a0d11f76a..c0b46d7c0 100644 --- a/src/Ombi.Store/Context/MySql/OmbiMySqlContext.cs +++ b/src/Ombi.Store/Context/MySql/OmbiMySqlContext.cs @@ -5,6 +5,7 @@ namespace Ombi.Store.Context.MySql public sealed class OmbiMySqlContext : OmbiContext { private static bool _created; + public OmbiMySqlContext(DbContextOptions options) : base(options) { if (_created) return; @@ -12,5 +13,10 @@ namespace Ombi.Store.Context.MySql Database.Migrate(); } + + public override void Dispose() + { + base.Dispose(); + } } } \ No newline at end of file diff --git a/src/Ombi.Store/Context/OmbiContext.cs b/src/Ombi.Store/Context/OmbiContext.cs index 4694f1151..90e559875 100644 --- a/src/Ombi.Store/Context/OmbiContext.cs +++ b/src/Ombi.Store/Context/OmbiContext.cs @@ -7,6 +7,7 @@ using Microsoft.EntityFrameworkCore; using Ombi.Helpers; using Ombi.Store.Entities; using Ombi.Store.Entities.Requests; +using Ombi.Store.Repository.Requests; namespace Ombi.Store.Context { @@ -17,6 +18,7 @@ namespace Ombi.Store.Context } + /// /// This allows a sub class to call the base class 'DbContext' non typed constructor /// This is need because instances of the subclasses will use a specific typed DbContextOptions @@ -35,6 +37,7 @@ namespace Ombi.Store.Context public DbSet AlbumRequests { get; set; } public DbSet TvRequests { get; set; } public DbSet ChildRequests { get; set; } + public DbSet EpisodeRequests { get; set; } public DbSet Issues { get; set; } public DbSet IssueCategories { get; set; } @@ -48,6 +51,7 @@ namespace Ombi.Store.Context public DbSet Tokens { get; set; } public DbSet RequestSubscription { get; set; } public DbSet UserNotificationPreferences { get; set; } + public DbSet MobileDevices { get; set; } public DbSet UserQualityProfileses { get; set; } public DbSet RequestQueue { get; set; } @@ -57,7 +61,7 @@ namespace Ombi.Store.Context using (var tran = Database.BeginTransaction()) { // Make sure we have the API User - var apiUserExists = Users.Any(x => x.UserName.Equals("Api", StringComparison.CurrentCultureIgnoreCase)); + var apiUserExists = Users.ToList().Any(x => x.NormalizedUserName == "API"); if (!apiUserExists) { Users.Add(new OmbiUser @@ -89,7 +93,7 @@ namespace Ombi.Store.Context } needToSave = true; - NotificationTemplates notificationToAdd; + NotificationTemplates notificationToAdd = null; switch (notificationType) { case NotificationType.NewRequest: @@ -116,7 +120,7 @@ namespace Ombi.Store.Context notificationToAdd = new NotificationTemplates { NotificationType = notificationType, - Message = "Hello! Your request for {Title} on {ApplicationName}! This is now available! :)", + Message = "Hello! Your request for {Title} on {ApplicationName} is now available! :)", Subject = "{ApplicationName}: {Title} is now available!", Agent = agent, Enabled = true, @@ -155,14 +159,17 @@ namespace Ombi.Store.Context }; break; case NotificationType.WelcomeEmail: - notificationToAdd = new NotificationTemplates + if (agent == NotificationAgent.Email) { - NotificationType = notificationType, - Message = "Hello! You have been invited to use {ApplicationName}! You can login here: {ApplicationUrl}", - Subject = "Invite to {ApplicationName}", - Agent = agent, - Enabled = true, - }; + notificationToAdd = new NotificationTemplates + { + NotificationType = notificationType, + Message = "Hello! You have been invited to use {ApplicationName}! You can login here: {ApplicationUrl}", + Subject = "Invite to {ApplicationName}", + Agent = agent, + Enabled = true, + }; + } break; case NotificationType.IssueResolved: notificationToAdd = new NotificationTemplates @@ -200,7 +207,10 @@ namespace Ombi.Store.Context default: throw new ArgumentOutOfRangeException(); } - NotificationTemplates.Add(notificationToAdd); + if (notificationToAdd != null) + { + NotificationTemplates.Add(notificationToAdd); + } } } @@ -215,4 +225,4 @@ namespace Ombi.Store.Context } } } -} \ No newline at end of file +} diff --git a/src/Ombi.Store/Context/Sqlite/ExternalSqliteContext.cs b/src/Ombi.Store/Context/Sqlite/ExternalSqliteContext.cs index af30920aa..f442531bc 100644 --- a/src/Ombi.Store/Context/Sqlite/ExternalSqliteContext.cs +++ b/src/Ombi.Store/Context/Sqlite/ExternalSqliteContext.cs @@ -1,4 +1,5 @@ using System; +using Microsoft.Data.Sqlite; using Microsoft.EntityFrameworkCore; namespace Ombi.Store.Context.Sqlite @@ -13,7 +14,9 @@ namespace Ombi.Store.Context.Sqlite _created = true; Upgrade(); Database.SetCommandTimeout(60); + Database.Migrate(); + } @@ -21,10 +24,12 @@ namespace Ombi.Store.Context.Sqlite { try { - Database.ExecuteSqlCommand(@"INSERT INTO __EFMigrationsHistory (MigrationId,ProductVersion) + Database.ExecuteSqlRaw(@"INSERT OR IGNORE INTO __EFMigrationsHistory (MigrationId,ProductVersion) VALUES('20191103205133_Inital', '2.2.6-servicing-10079'); "); } +#pragma warning disable RCS1075 // Avoid empty catch clause that catches System.Exception. catch (Exception) +#pragma warning restore RCS1075 // Avoid empty catch clause that catches System.Exception. { // ignored } diff --git a/src/Ombi.Store/Context/Sqlite/OmbiSqliteContext.cs b/src/Ombi.Store/Context/Sqlite/OmbiSqliteContext.cs index 5d6e29e31..c47694587 100644 --- a/src/Ombi.Store/Context/Sqlite/OmbiSqliteContext.cs +++ b/src/Ombi.Store/Context/Sqlite/OmbiSqliteContext.cs @@ -22,7 +22,7 @@ namespace Ombi.Store.Context.Sqlite { try { - Database.ExecuteSqlCommand(@"INSERT INTO __EFMigrationsHistory (MigrationId,ProductVersion) + Database.ExecuteSqlRaw(@"INSERT OR IGNORE INTO __EFMigrationsHistory (MigrationId,ProductVersion) VALUES('20191102235658_Inital', '2.2.6-servicing-10079'); "); } catch (Exception) diff --git a/src/Ombi.Store/Context/Sqlite/SettingsSqliteContext.cs b/src/Ombi.Store/Context/Sqlite/SettingsSqliteContext.cs index 19e155a71..9be3d84fb 100644 --- a/src/Ombi.Store/Context/Sqlite/SettingsSqliteContext.cs +++ b/src/Ombi.Store/Context/Sqlite/SettingsSqliteContext.cs @@ -20,10 +20,12 @@ namespace Ombi.Store.Context.Sqlite { try { - Database.ExecuteSqlCommand(@"INSERT INTO __EFMigrationsHistory (MigrationId,ProductVersion) + Database.ExecuteSqlRaw(@"INSERT OR IGNORE INTO __EFMigrationsHistory (MigrationId,ProductVersion) VALUES('20191103205204_Inital', '2.2.6-servicing-10079'); "); } - catch (Exception) +#pragma warning disable RCS1075 // Avoid empty catch clause that catches System.Exception. + catch (Exception) +#pragma warning restore RCS1075 // Avoid empty catch clause that catches System.Exception. { // ignored } diff --git a/src/Ombi.Store/Entities/ApplicationConfiguration.cs b/src/Ombi.Store/Entities/ApplicationConfiguration.cs index 809264312..012a80345 100644 --- a/src/Ombi.Store/Entities/ApplicationConfiguration.cs +++ b/src/Ombi.Store/Entities/ApplicationConfiguration.cs @@ -17,6 +17,7 @@ namespace Ombi.Store.Entities TheMovieDb = 4, StoragePath = 5, Notification = 6, - BaseUrl=7, + BaseUrl = 7, + SecurityToken = 8 } } \ No newline at end of file diff --git a/src/Ombi.Store/Entities/MobileDevices.cs b/src/Ombi.Store/Entities/MobileDevices.cs new file mode 100644 index 000000000..674cb8df9 --- /dev/null +++ b/src/Ombi.Store/Entities/MobileDevices.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations.Schema; + +namespace Ombi.Store.Entities +{ + public class MobileDevices : Entity + { + public string Token { get; set; } + public string UserId { get; set; } + public DateTime AddedAt { get; set; } + [ForeignKey(nameof(UserId))] + public OmbiUser User { get; set; } + } +} \ No newline at end of file diff --git a/src/Ombi.Store/Entities/OmbiUser.cs b/src/Ombi.Store/Entities/OmbiUser.cs index edb9708a9..919d9a22c 100644 --- a/src/Ombi.Store/Entities/OmbiUser.cs +++ b/src/Ombi.Store/Entities/OmbiUser.cs @@ -19,7 +19,7 @@ namespace Ombi.Store.Entities public DateTime? LastLoggedIn { get; set; } - public string EmbyConnectUserId { get; set; } + public string Language { get; set; } public int? MovieRequestLimit { get; set; } public int? EpisodeRequestLimit { get; set; } @@ -31,7 +31,7 @@ namespace Ombi.Store.Entities public List UserNotificationPreferences { get; set; } [NotMapped] - public bool IsEmbyConnect => UserType == UserType.EmbyUser && EmbyConnectUserId.HasValue(); + public bool IsEmbyConnect => UserType == UserType.EmbyConnectUser; [NotMapped] public virtual string UserAlias => string.IsNullOrEmpty(Alias) ? UserName : Alias; diff --git a/src/Ombi.Store/Entities/Requests/AlbumRequest.cs b/src/Ombi.Store/Entities/Requests/AlbumRequest.cs index 2735603c6..eecf05e6e 100644 --- a/src/Ombi.Store/Entities/Requests/AlbumRequest.cs +++ b/src/Ombi.Store/Entities/Requests/AlbumRequest.cs @@ -17,5 +17,34 @@ namespace Ombi.Store.Entities.Requests public bool Subscribed { get; set; } [NotMapped] public bool ShowSubscribe { get; set; } + + + [NotMapped] + public string RequestStatus { + get + { + if (Available) + { + return "Common.Available"; + } + + if (Denied ?? false) + { + return "Common.Denied"; + } + + if (Approved & !Available) + { + return "Common.ProcessingRequest"; + } + + if (!Approved && !Available) + { + return "Common.PendingApproval"; + } + + return string.Empty; + } + } } } \ No newline at end of file diff --git a/src/Ombi.Store/Entities/Requests/Issues.cs b/src/Ombi.Store/Entities/Requests/Issues.cs index d31ce7015..082261a15 100644 --- a/src/Ombi.Store/Entities/Requests/Issues.cs +++ b/src/Ombi.Store/Entities/Requests/Issues.cs @@ -13,13 +13,14 @@ namespace Ombi.Store.Entities.Requests public int? RequestId { get; set; } public string Subject { get; set; } public string Description { get; set; } - public int SeasonNumber { get; set; } - public int EpisodeNumber { get; set; } + //public int SeasonNumber { get; set; } + //public int EpisodeNumber { get; set; } public int IssueCategoryId { get; set; } [ForeignKey(nameof(IssueCategoryId))] public IssueCategory IssueCategory { get; set; } public IssueStatus Status { get; set; } public DateTime? ResovledDate { get; set; } + public DateTime CreatedDate { get; set; } [ForeignKey(nameof(UserReported))] public string UserReportedId { get; set; } public OmbiUser UserReported { get; set; } diff --git a/src/Ombi.Store/Entities/Requests/MovieRequests.cs b/src/Ombi.Store/Entities/Requests/MovieRequests.cs index 93853fbfd..42b17be73 100644 --- a/src/Ombi.Store/Entities/Requests/MovieRequests.cs +++ b/src/Ombi.Store/Entities/Requests/MovieRequests.cs @@ -43,6 +43,11 @@ namespace Ombi.Store.Entities.Requests return "Common.Available"; } + if (Denied ?? false) + { + return "Common.Denied"; + } + if (Approved & !Available) { return "Common.ProcessingRequest"; diff --git a/src/Ombi.Store/Entities/User.cs b/src/Ombi.Store/Entities/User.cs index 68d1dbe00..b53af5a33 100644 --- a/src/Ombi.Store/Entities/User.cs +++ b/src/Ombi.Store/Entities/User.cs @@ -33,5 +33,6 @@ namespace Ombi.Store.Entities LocalUser = 1, PlexUser = 2, EmbyUser = 3, + EmbyConnectUser = 4, } } \ No newline at end of file diff --git a/src/Ombi.Store/Migration.txt b/src/Ombi.Store/Migration.txt index 5d1131a75..331299143 100644 --- a/src/Ombi.Store/Migration.txt +++ b/src/Ombi.Store/Migration.txt @@ -1,3 +1,3 @@ -dotnet ef migrations add Inital --context OmbiContext --startup-project ../Ombi/Ombi.csproj +dotnet ef migrations add Inital --context OmbiSqliteContext --startup-project ../Ombi/Ombi.csproj If running migrations for any db provider other than Sqlite, then ensure the database.json is pointing at the correct DB type \ No newline at end of file diff --git a/src/Ombi.Store/Migrations/ExternalMySql/ExternalMySqlContextModelSnapshot.cs b/src/Ombi.Store/Migrations/ExternalMySql/ExternalMySqlContextModelSnapshot.cs index c9ca6fc74..890e24b76 100644 --- a/src/Ombi.Store/Migrations/ExternalMySql/ExternalMySqlContextModelSnapshot.cs +++ b/src/Ombi.Store/Migrations/ExternalMySql/ExternalMySqlContextModelSnapshot.cs @@ -14,15 +14,17 @@ namespace Ombi.Store.Migrations.ExternalMySql { #pragma warning disable 612, 618 modelBuilder - .HasAnnotation("ProductVersion", "2.2.6-servicing-10079") + .HasAnnotation("ProductVersion", "3.1.1") .HasAnnotation("Relational:MaxIdentifierLength", 64); modelBuilder.Entity("Ombi.Store.Entities.CouchPotatoCache", b => { b.Property("Id") - .ValueGeneratedOnAdd(); + .ValueGeneratedOnAdd() + .HasColumnType("int"); - b.Property("TheMovieDbId"); + b.Property("TheMovieDbId") + .HasColumnType("int"); b.HasKey("Id"); @@ -32,26 +34,36 @@ namespace Ombi.Store.Migrations.ExternalMySql modelBuilder.Entity("Ombi.Store.Entities.EmbyContent", b => { b.Property("Id") - .ValueGeneratedOnAdd(); + .ValueGeneratedOnAdd() + .HasColumnType("int"); - b.Property("AddedAt"); + b.Property("AddedAt") + .HasColumnType("datetime(6)"); b.Property("EmbyId") - .IsRequired(); + .IsRequired() + .HasColumnType("varchar(255) CHARACTER SET utf8mb4"); - b.Property("ImdbId"); + b.Property("ImdbId") + .HasColumnType("longtext CHARACTER SET utf8mb4"); - b.Property("ProviderId"); + b.Property("ProviderId") + .HasColumnType("longtext CHARACTER SET utf8mb4"); - b.Property("TheMovieDbId"); + b.Property("TheMovieDbId") + .HasColumnType("longtext CHARACTER SET utf8mb4"); - b.Property("Title"); + b.Property("Title") + .HasColumnType("longtext CHARACTER SET utf8mb4"); - b.Property("TvDbId"); + b.Property("TvDbId") + .HasColumnType("longtext CHARACTER SET utf8mb4"); - b.Property("Type"); + b.Property("Type") + .HasColumnType("int"); - b.Property("Url"); + b.Property("Url") + .HasColumnType("longtext CHARACTER SET utf8mb4"); b.HasKey("Id"); @@ -61,27 +73,38 @@ namespace Ombi.Store.Migrations.ExternalMySql modelBuilder.Entity("Ombi.Store.Entities.EmbyEpisode", b => { b.Property("Id") - .ValueGeneratedOnAdd(); + .ValueGeneratedOnAdd() + .HasColumnType("int"); - b.Property("AddedAt"); + b.Property("AddedAt") + .HasColumnType("datetime(6)"); - b.Property("EmbyId"); + b.Property("EmbyId") + .HasColumnType("longtext CHARACTER SET utf8mb4"); - b.Property("EpisodeNumber"); + b.Property("EpisodeNumber") + .HasColumnType("int"); - b.Property("ImdbId"); + b.Property("ImdbId") + .HasColumnType("longtext CHARACTER SET utf8mb4"); - b.Property("ParentId"); + b.Property("ParentId") + .HasColumnType("varchar(255) CHARACTER SET utf8mb4"); - b.Property("ProviderId"); + b.Property("ProviderId") + .HasColumnType("longtext CHARACTER SET utf8mb4"); - b.Property("SeasonNumber"); + b.Property("SeasonNumber") + .HasColumnType("int"); - b.Property("TheMovieDbId"); + b.Property("TheMovieDbId") + .HasColumnType("longtext CHARACTER SET utf8mb4"); - b.Property("Title"); + b.Property("Title") + .HasColumnType("longtext CHARACTER SET utf8mb4"); - b.Property("TvDbId"); + b.Property("TvDbId") + .HasColumnType("longtext CHARACTER SET utf8mb4"); b.HasKey("Id"); @@ -93,23 +116,32 @@ namespace Ombi.Store.Migrations.ExternalMySql modelBuilder.Entity("Ombi.Store.Entities.LidarrAlbumCache", b => { b.Property("Id") - .ValueGeneratedOnAdd(); + .ValueGeneratedOnAdd() + .HasColumnType("int"); - b.Property("AddedAt"); + b.Property("AddedAt") + .HasColumnType("datetime(6)"); - b.Property("ArtistId"); + b.Property("ArtistId") + .HasColumnType("int"); - b.Property("ForeignAlbumId"); + b.Property("ForeignAlbumId") + .HasColumnType("longtext CHARACTER SET utf8mb4"); - b.Property("Monitored"); + b.Property("Monitored") + .HasColumnType("tinyint(1)"); - b.Property("PercentOfTracks"); + b.Property("PercentOfTracks") + .HasColumnType("decimal(65,30)"); - b.Property("ReleaseDate"); + b.Property("ReleaseDate") + .HasColumnType("datetime(6)"); - b.Property("Title"); + b.Property("Title") + .HasColumnType("longtext CHARACTER SET utf8mb4"); - b.Property("TrackCount"); + b.Property("TrackCount") + .HasColumnType("int"); b.HasKey("Id"); @@ -119,15 +151,20 @@ namespace Ombi.Store.Migrations.ExternalMySql modelBuilder.Entity("Ombi.Store.Entities.LidarrArtistCache", b => { b.Property("Id") - .ValueGeneratedOnAdd(); + .ValueGeneratedOnAdd() + .HasColumnType("int"); - b.Property("ArtistId"); + b.Property("ArtistId") + .HasColumnType("int"); - b.Property("ArtistName"); + b.Property("ArtistName") + .HasColumnType("longtext CHARACTER SET utf8mb4"); - b.Property("ForeignArtistId"); + b.Property("ForeignArtistId") + .HasColumnType("longtext CHARACTER SET utf8mb4"); - b.Property("Monitored"); + b.Property("Monitored") + .HasColumnType("tinyint(1)"); b.HasKey("Id"); @@ -137,19 +174,26 @@ namespace Ombi.Store.Migrations.ExternalMySql modelBuilder.Entity("Ombi.Store.Entities.PlexEpisode", b => { b.Property("Id") - .ValueGeneratedOnAdd(); + .ValueGeneratedOnAdd() + .HasColumnType("int"); - b.Property("EpisodeNumber"); + b.Property("EpisodeNumber") + .HasColumnType("int"); - b.Property("GrandparentKey"); + b.Property("GrandparentKey") + .HasColumnType("int"); - b.Property("Key"); + b.Property("Key") + .HasColumnType("int"); - b.Property("ParentKey"); + b.Property("ParentKey") + .HasColumnType("int"); - b.Property("SeasonNumber"); + b.Property("SeasonNumber") + .HasColumnType("int"); - b.Property("Title"); + b.Property("Title") + .HasColumnType("longtext CHARACTER SET utf8mb4"); b.HasKey("Id"); @@ -161,17 +205,23 @@ namespace Ombi.Store.Migrations.ExternalMySql modelBuilder.Entity("Ombi.Store.Entities.PlexSeasonsContent", b => { b.Property("Id") - .ValueGeneratedOnAdd(); + .ValueGeneratedOnAdd() + .HasColumnType("int"); - b.Property("ParentKey"); + b.Property("ParentKey") + .HasColumnType("int"); - b.Property("PlexContentId"); + b.Property("PlexContentId") + .HasColumnType("int"); - b.Property("PlexServerContentId"); + b.Property("PlexServerContentId") + .HasColumnType("int"); - b.Property("SeasonKey"); + b.Property("SeasonKey") + .HasColumnType("int"); - b.Property("SeasonNumber"); + b.Property("SeasonNumber") + .HasColumnType("int"); b.HasKey("Id"); @@ -183,29 +233,41 @@ namespace Ombi.Store.Migrations.ExternalMySql modelBuilder.Entity("Ombi.Store.Entities.PlexServerContent", b => { b.Property("Id") - .ValueGeneratedOnAdd(); + .ValueGeneratedOnAdd() + .HasColumnType("int"); - b.Property("AddedAt"); + b.Property("AddedAt") + .HasColumnType("datetime(6)"); - b.Property("ImdbId"); + b.Property("ImdbId") + .HasColumnType("longtext CHARACTER SET utf8mb4"); - b.Property("Key"); + b.Property("Key") + .HasColumnType("int"); - b.Property("Quality"); + b.Property("Quality") + .HasColumnType("longtext CHARACTER SET utf8mb4"); - b.Property("ReleaseYear"); + b.Property("ReleaseYear") + .HasColumnType("longtext CHARACTER SET utf8mb4"); - b.Property("RequestId"); + b.Property("RequestId") + .HasColumnType("int"); - b.Property("TheMovieDbId"); + b.Property("TheMovieDbId") + .HasColumnType("longtext CHARACTER SET utf8mb4"); - b.Property("Title"); + b.Property("Title") + .HasColumnType("longtext CHARACTER SET utf8mb4"); - b.Property("TvDbId"); + b.Property("TvDbId") + .HasColumnType("longtext CHARACTER SET utf8mb4"); - b.Property("Type"); + b.Property("Type") + .HasColumnType("int"); - b.Property("Url"); + b.Property("Url") + .HasColumnType("longtext CHARACTER SET utf8mb4"); b.HasKey("Id"); @@ -215,11 +277,14 @@ namespace Ombi.Store.Migrations.ExternalMySql modelBuilder.Entity("Ombi.Store.Entities.RadarrCache", b => { b.Property("Id") - .ValueGeneratedOnAdd(); + .ValueGeneratedOnAdd() + .HasColumnType("int"); - b.Property("HasFile"); + b.Property("HasFile") + .HasColumnType("tinyint(1)"); - b.Property("TheMovieDbId"); + b.Property("TheMovieDbId") + .HasColumnType("int"); b.HasKey("Id"); @@ -229,9 +294,11 @@ namespace Ombi.Store.Migrations.ExternalMySql modelBuilder.Entity("Ombi.Store.Entities.SickRageCache", b => { b.Property("Id") - .ValueGeneratedOnAdd(); + .ValueGeneratedOnAdd() + .HasColumnType("int"); - b.Property("TvDbId"); + b.Property("TvDbId") + .HasColumnType("int"); b.HasKey("Id"); @@ -241,13 +308,17 @@ namespace Ombi.Store.Migrations.ExternalMySql modelBuilder.Entity("Ombi.Store.Entities.SickRageEpisodeCache", b => { b.Property("Id") - .ValueGeneratedOnAdd(); + .ValueGeneratedOnAdd() + .HasColumnType("int"); - b.Property("EpisodeNumber"); + b.Property("EpisodeNumber") + .HasColumnType("int"); - b.Property("SeasonNumber"); + b.Property("SeasonNumber") + .HasColumnType("int"); - b.Property("TvDbId"); + b.Property("TvDbId") + .HasColumnType("int"); b.HasKey("Id"); @@ -257,9 +328,11 @@ namespace Ombi.Store.Migrations.ExternalMySql modelBuilder.Entity("Ombi.Store.Entities.SonarrCache", b => { b.Property("Id") - .ValueGeneratedOnAdd(); + .ValueGeneratedOnAdd() + .HasColumnType("int"); - b.Property("TvDbId"); + b.Property("TvDbId") + .HasColumnType("int"); b.HasKey("Id"); @@ -269,15 +342,20 @@ namespace Ombi.Store.Migrations.ExternalMySql modelBuilder.Entity("Ombi.Store.Entities.SonarrEpisodeCache", b => { b.Property("Id") - .ValueGeneratedOnAdd(); + .ValueGeneratedOnAdd() + .HasColumnType("int"); - b.Property("EpisodeNumber"); + b.Property("EpisodeNumber") + .HasColumnType("int"); - b.Property("HasFile"); + b.Property("HasFile") + .HasColumnType("tinyint(1)"); - b.Property("SeasonNumber"); + b.Property("SeasonNumber") + .HasColumnType("int"); - b.Property("TvDbId"); + b.Property("TvDbId") + .HasColumnType("int"); b.HasKey("Id"); @@ -298,12 +376,13 @@ namespace Ombi.Store.Migrations.ExternalMySql .WithMany("Episodes") .HasForeignKey("GrandparentKey") .HasPrincipalKey("Key") - .OnDelete(DeleteBehavior.Cascade); + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); }); modelBuilder.Entity("Ombi.Store.Entities.PlexSeasonsContent", b => { - b.HasOne("Ombi.Store.Entities.PlexServerContent") + b.HasOne("Ombi.Store.Entities.PlexServerContent", null) .WithMany("Seasons") .HasForeignKey("PlexServerContentId"); }); diff --git a/src/Ombi.Store/Migrations/ExternalSqlite/20191113213617_RequestIdPatch.Designer.cs b/src/Ombi.Store/Migrations/ExternalSqlite/20191113213617_RequestIdPatch.Designer.cs new file mode 100644 index 000000000..0183e897c --- /dev/null +++ b/src/Ombi.Store/Migrations/ExternalSqlite/20191113213617_RequestIdPatch.Designer.cs @@ -0,0 +1,314 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Ombi.Store.Context.Sqlite; + +namespace Ombi.Store.Migrations.ExternalSqlite +{ + [DbContext(typeof(ExternalSqliteContext))] + [Migration("20191113213617_RequestIdPatch")] + partial class RequestIdPatch + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.2.6-servicing-10079"); + + modelBuilder.Entity("Ombi.Store.Entities.CouchPotatoCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("TheMovieDbId"); + + b.HasKey("Id"); + + b.ToTable("CouchPotatoCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("EmbyId") + .IsRequired(); + + b.Property("ImdbId"); + + b.Property("ProviderId"); + + b.Property("TheMovieDbId"); + + b.Property("Title"); + + b.Property("TvDbId"); + + b.Property("Type"); + + b.Property("Url"); + + b.HasKey("Id"); + + b.ToTable("EmbyContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyEpisode", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("EmbyId"); + + b.Property("EpisodeNumber"); + + b.Property("ImdbId"); + + b.Property("ParentId"); + + b.Property("ProviderId"); + + b.Property("SeasonNumber"); + + b.Property("TheMovieDbId"); + + b.Property("Title"); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.HasIndex("ParentId"); + + b.ToTable("EmbyEpisode"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.LidarrAlbumCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("ArtistId"); + + b.Property("ForeignAlbumId"); + + b.Property("Monitored"); + + b.Property("PercentOfTracks"); + + b.Property("ReleaseDate"); + + b.Property("Title"); + + b.Property("TrackCount"); + + b.HasKey("Id"); + + b.ToTable("LidarrAlbumCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.LidarrArtistCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ArtistId"); + + b.Property("ArtistName"); + + b.Property("ForeignArtistId"); + + b.Property("Monitored"); + + b.HasKey("Id"); + + b.ToTable("LidarrArtistCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexEpisode", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("EpisodeNumber"); + + b.Property("GrandparentKey"); + + b.Property("Key"); + + b.Property("ParentKey"); + + b.Property("SeasonNumber"); + + b.Property("Title"); + + b.HasKey("Id"); + + b.HasIndex("GrandparentKey"); + + b.ToTable("PlexEpisode"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexSeasonsContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ParentKey"); + + b.Property("PlexContentId"); + + b.Property("PlexServerContentId"); + + b.Property("SeasonKey"); + + b.Property("SeasonNumber"); + + b.HasKey("Id"); + + b.HasIndex("PlexServerContentId"); + + b.ToTable("PlexSeasonsContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexServerContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("ImdbId"); + + b.Property("Key"); + + b.Property("Quality"); + + b.Property("ReleaseYear"); + + b.Property("RequestId"); + + b.Property("TheMovieDbId"); + + b.Property("Title"); + + b.Property("TvDbId"); + + b.Property("Type"); + + b.Property("Url"); + + b.HasKey("Id"); + + b.ToTable("PlexServerContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RadarrCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("HasFile"); + + b.Property("TheMovieDbId"); + + b.HasKey("Id"); + + b.ToTable("RadarrCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SickRageCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.ToTable("SickRageCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SickRageEpisodeCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("EpisodeNumber"); + + b.Property("SeasonNumber"); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.ToTable("SickRageEpisodeCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SonarrCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.ToTable("SonarrCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SonarrEpisodeCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("EpisodeNumber"); + + b.Property("HasFile"); + + b.Property("SeasonNumber"); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.ToTable("SonarrEpisodeCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyEpisode", b => + { + b.HasOne("Ombi.Store.Entities.EmbyContent", "Series") + .WithMany("Episodes") + .HasForeignKey("ParentId") + .HasPrincipalKey("EmbyId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexEpisode", b => + { + b.HasOne("Ombi.Store.Entities.PlexServerContent", "Series") + .WithMany("Episodes") + .HasForeignKey("GrandparentKey") + .HasPrincipalKey("Key") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexSeasonsContent", b => + { + b.HasOne("Ombi.Store.Entities.PlexServerContent") + .WithMany("Seasons") + .HasForeignKey("PlexServerContentId"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Ombi.Store/Migrations/ExternalSqlite/20191113213617_RequestIdPatch.cs b/src/Ombi.Store/Migrations/ExternalSqlite/20191113213617_RequestIdPatch.cs new file mode 100644 index 000000000..29c1a4033 --- /dev/null +++ b/src/Ombi.Store/Migrations/ExternalSqlite/20191113213617_RequestIdPatch.cs @@ -0,0 +1,22 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +namespace Ombi.Store.Migrations.ExternalSqlite +{ + public partial class RequestIdPatch : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + + //migrationBuilder.AddColumn( + // name: "RequestId", + // table: "PlexServerContent", + // nullable: true); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + + } + } +} diff --git a/src/Ombi.Store/Migrations/OmbiMySql/20200218230644_MobileDevices.Designer.cs b/src/Ombi.Store/Migrations/OmbiMySql/20200218230644_MobileDevices.Designer.cs new file mode 100644 index 000000000..b92f5ca05 --- /dev/null +++ b/src/Ombi.Store/Migrations/OmbiMySql/20200218230644_MobileDevices.Designer.cs @@ -0,0 +1,1155 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Ombi.Store.Context.MySql; + +namespace Ombi.Store.Migrations.OmbiMySql +{ + [DbContext(typeof(OmbiMySqlContext))] + [Migration("20200218230644_MobileDevices")] + partial class MobileDevices + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "3.1.1") + .HasAnnotation("Relational:MaxIdentifierLength", 64); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .HasColumnType("varchar(255) CHARACTER SET utf8mb4"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("Name") + .HasColumnType("varchar(256) CHARACTER SET utf8mb4") + .HasMaxLength(256); + + b.Property("NormalizedName") + .HasColumnType("varchar(256) CHARACTER SET utf8mb4") + .HasMaxLength(256); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasName("RoleNameIndex"); + + b.ToTable("AspNetRoles"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("ClaimType") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("ClaimValue") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("varchar(255) CHARACTER SET utf8mb4"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("ClaimType") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("ClaimValue") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("varchar(255) CHARACTER SET utf8mb4"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("varchar(255) CHARACTER SET utf8mb4"); + + b.Property("ProviderKey") + .HasColumnType("varchar(255) CHARACTER SET utf8mb4"); + + b.Property("ProviderDisplayName") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("varchar(255) CHARACTER SET utf8mb4"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("varchar(255) CHARACTER SET utf8mb4"); + + b.Property("RoleId") + .HasColumnType("varchar(255) CHARACTER SET utf8mb4"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("varchar(255) CHARACTER SET utf8mb4"); + + b.Property("LoginProvider") + .HasColumnType("varchar(255) CHARACTER SET utf8mb4"); + + b.Property("Name") + .HasColumnType("varchar(255) CHARACTER SET utf8mb4"); + + b.Property("Value") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Audit", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AuditArea") + .HasColumnType("int"); + + b.Property("AuditType") + .HasColumnType("int"); + + b.Property("DateTime") + .HasColumnType("datetime(6)"); + + b.Property("Description") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("User") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.HasKey("Id"); + + b.ToTable("Audit"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.MobileDevices", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AddedAt") + .HasColumnType("datetime(6)"); + + b.Property("Token") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("UserId") + .HasColumnType("varchar(255) CHARACTER SET utf8mb4"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("MobileDevices"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationTemplates", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Agent") + .HasColumnType("int"); + + b.Property("Enabled") + .HasColumnType("tinyint(1)"); + + b.Property("Message") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("NotificationType") + .HasColumnType("int"); + + b.Property("Subject") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.HasKey("Id"); + + b.ToTable("NotificationTemplates"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationUserId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AddedAt") + .HasColumnType("datetime(6)"); + + b.Property("PlayerId") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("UserId") + .HasColumnType("varchar(255) CHARACTER SET utf8mb4"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("NotificationUserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.OmbiUser", b => + { + b.Property("Id") + .HasColumnType("varchar(255) CHARACTER SET utf8mb4"); + + b.Property("AccessFailedCount") + .HasColumnType("int"); + + b.Property("Alias") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("Email") + .HasColumnType("varchar(256) CHARACTER SET utf8mb4") + .HasMaxLength(256); + + b.Property("EmailConfirmed") + .HasColumnType("tinyint(1)"); + + b.Property("EmbyConnectUserId") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("EpisodeRequestLimit") + .HasColumnType("int"); + + b.Property("LastLoggedIn") + .HasColumnType("datetime(6)"); + + b.Property("LockoutEnabled") + .HasColumnType("tinyint(1)"); + + b.Property("LockoutEnd") + .HasColumnType("datetime(6)"); + + b.Property("MovieRequestLimit") + .HasColumnType("int"); + + b.Property("MusicRequestLimit") + .HasColumnType("int"); + + b.Property("NormalizedEmail") + .HasColumnType("varchar(256) CHARACTER SET utf8mb4") + .HasMaxLength(256); + + b.Property("NormalizedUserName") + .HasColumnType("varchar(256) CHARACTER SET utf8mb4") + .HasMaxLength(256); + + b.Property("PasswordHash") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("PhoneNumber") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("tinyint(1)"); + + b.Property("ProviderUserId") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("SecurityStamp") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("TwoFactorEnabled") + .HasColumnType("tinyint(1)"); + + b.Property("UserAccessToken") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("UserName") + .HasColumnType("varchar(256) CHARACTER SET utf8mb4") + .HasMaxLength(256); + + b.Property("UserType") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasName("UserNameIndex"); + + b.ToTable("AspNetUsers"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RecentlyAddedLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AddedAt") + .HasColumnType("datetime(6)"); + + b.Property("AlbumId") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("ContentId") + .HasColumnType("int"); + + b.Property("ContentType") + .HasColumnType("int"); + + b.Property("EpisodeNumber") + .HasColumnType("int"); + + b.Property("SeasonNumber") + .HasColumnType("int"); + + b.Property("Type") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("RecentlyAddedLog"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestQueue", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Completed") + .HasColumnType("datetime(6)"); + + b.Property("Dts") + .HasColumnType("datetime(6)"); + + b.Property("Error") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("RequestId") + .HasColumnType("int"); + + b.Property("RetryCount") + .HasColumnType("int"); + + b.Property("Type") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("RequestQueue"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestSubscription", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("RequestId") + .HasColumnType("int"); + + b.Property("RequestType") + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("varchar(255) CHARACTER SET utf8mb4"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("RequestSubscription"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.AlbumRequest", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Approved") + .HasColumnType("tinyint(1)"); + + b.Property("ArtistName") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("Available") + .HasColumnType("tinyint(1)"); + + b.Property("Cover") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("Denied") + .HasColumnType("tinyint(1)"); + + b.Property("DeniedReason") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("Disk") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("ForeignAlbumId") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("ForeignArtistId") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("MarkedAsApproved") + .HasColumnType("datetime(6)"); + + b.Property("MarkedAsAvailable") + .HasColumnType("datetime(6)"); + + b.Property("MarkedAsDenied") + .HasColumnType("datetime(6)"); + + b.Property("Rating") + .HasColumnType("decimal(65,30)"); + + b.Property("ReleaseDate") + .HasColumnType("datetime(6)"); + + b.Property("RequestType") + .HasColumnType("int"); + + b.Property("RequestedByAlias") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("RequestedDate") + .HasColumnType("datetime(6)"); + + b.Property("RequestedUserId") + .HasColumnType("varchar(255) CHARACTER SET utf8mb4"); + + b.Property("Title") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.HasKey("Id"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("AlbumRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.ChildRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Approved") + .HasColumnType("tinyint(1)"); + + b.Property("Available") + .HasColumnType("tinyint(1)"); + + b.Property("Denied") + .HasColumnType("tinyint(1)"); + + b.Property("DeniedReason") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("IssueId") + .HasColumnType("int"); + + b.Property("MarkedAsApproved") + .HasColumnType("datetime(6)"); + + b.Property("MarkedAsAvailable") + .HasColumnType("datetime(6)"); + + b.Property("MarkedAsDenied") + .HasColumnType("datetime(6)"); + + b.Property("ParentRequestId") + .HasColumnType("int"); + + b.Property("RequestType") + .HasColumnType("int"); + + b.Property("RequestedByAlias") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("RequestedDate") + .HasColumnType("datetime(6)"); + + b.Property("RequestedUserId") + .HasColumnType("varchar(255) CHARACTER SET utf8mb4"); + + b.Property("SeriesType") + .HasColumnType("int"); + + b.Property("Title") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.HasKey("Id"); + + b.HasIndex("ParentRequestId"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("ChildRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueCategory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Value") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.HasKey("Id"); + + b.ToTable("IssueCategory"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueComments", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Comment") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("Date") + .HasColumnType("datetime(6)"); + + b.Property("IssuesId") + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("varchar(255) CHARACTER SET utf8mb4"); + + b.HasKey("Id"); + + b.HasIndex("IssuesId"); + + b.HasIndex("UserId"); + + b.ToTable("IssueComments"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Description") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("EpisodeNumber") + .HasColumnType("int"); + + b.Property("IssueCategoryId") + .HasColumnType("int"); + + b.Property("IssueId") + .HasColumnType("int"); + + b.Property("ProviderId") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("RequestId") + .HasColumnType("int"); + + b.Property("RequestType") + .HasColumnType("int"); + + b.Property("ResovledDate") + .HasColumnType("datetime(6)"); + + b.Property("SeasonNumber") + .HasColumnType("int"); + + b.Property("Status") + .HasColumnType("int"); + + b.Property("Subject") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("Title") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("UserReportedId") + .HasColumnType("varchar(255) CHARACTER SET utf8mb4"); + + b.HasKey("Id"); + + b.HasIndex("IssueCategoryId"); + + b.HasIndex("IssueId"); + + b.HasIndex("UserReportedId"); + + b.ToTable("Issues"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.MovieRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Approved") + .HasColumnType("tinyint(1)"); + + b.Property("Available") + .HasColumnType("tinyint(1)"); + + b.Property("Background") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("Denied") + .HasColumnType("tinyint(1)"); + + b.Property("DeniedReason") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("DigitalReleaseDate") + .HasColumnType("datetime(6)"); + + b.Property("ImdbId") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("IssueId") + .HasColumnType("int"); + + b.Property("LangCode") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("MarkedAsApproved") + .HasColumnType("datetime(6)"); + + b.Property("MarkedAsAvailable") + .HasColumnType("datetime(6)"); + + b.Property("MarkedAsDenied") + .HasColumnType("datetime(6)"); + + b.Property("Overview") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("PosterPath") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("QualityOverride") + .HasColumnType("int"); + + b.Property("ReleaseDate") + .HasColumnType("datetime(6)"); + + b.Property("RequestType") + .HasColumnType("int"); + + b.Property("RequestedByAlias") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("RequestedDate") + .HasColumnType("datetime(6)"); + + b.Property("RequestedUserId") + .HasColumnType("varchar(255) CHARACTER SET utf8mb4"); + + b.Property("RootPathOverride") + .HasColumnType("int"); + + b.Property("Status") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("TheMovieDbId") + .HasColumnType("int"); + + b.Property("Title") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.HasKey("Id"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("MovieRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.RequestLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("EpisodeCount") + .HasColumnType("int"); + + b.Property("RequestDate") + .HasColumnType("datetime(6)"); + + b.Property("RequestId") + .HasColumnType("int"); + + b.Property("RequestType") + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("varchar(255) CHARACTER SET utf8mb4"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("RequestLog"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.TvRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Background") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("ImdbId") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("Overview") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("PosterPath") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("QualityOverride") + .HasColumnType("int"); + + b.Property("ReleaseDate") + .HasColumnType("datetime(6)"); + + b.Property("RootFolder") + .HasColumnType("int"); + + b.Property("Status") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("Title") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("TotalSeasons") + .HasColumnType("int"); + + b.Property("TvDbId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("TvRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Tokens", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Token") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("UserId") + .HasColumnType("varchar(255) CHARACTER SET utf8mb4"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Tokens"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserNotificationPreferences", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Agent") + .HasColumnType("int"); + + b.Property("Enabled") + .HasColumnType("tinyint(1)"); + + b.Property("UserId") + .HasColumnType("varchar(255) CHARACTER SET utf8mb4"); + + b.Property("Value") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserNotificationPreferences"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserQualityProfiles", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("RadarrQualityProfile") + .HasColumnType("int"); + + b.Property("RadarrRootPath") + .HasColumnType("int"); + + b.Property("SonarrQualityProfile") + .HasColumnType("int"); + + b.Property("SonarrQualityProfileAnime") + .HasColumnType("int"); + + b.Property("SonarrRootPath") + .HasColumnType("int"); + + b.Property("SonarrRootPathAnime") + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("varchar(255) CHARACTER SET utf8mb4"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserQualityProfiles"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Votes", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Date") + .HasColumnType("datetime(6)"); + + b.Property("Deleted") + .HasColumnType("tinyint(1)"); + + b.Property("RequestId") + .HasColumnType("int"); + + b.Property("RequestType") + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("varchar(255) CHARACTER SET utf8mb4"); + + b.Property("VoteType") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Votes"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.EpisodeRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AirDate") + .HasColumnType("datetime(6)"); + + b.Property("Approved") + .HasColumnType("tinyint(1)"); + + b.Property("Available") + .HasColumnType("tinyint(1)"); + + b.Property("EpisodeNumber") + .HasColumnType("int"); + + b.Property("Requested") + .HasColumnType("tinyint(1)"); + + b.Property("SeasonId") + .HasColumnType("int"); + + b.Property("Title") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("Url") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.HasKey("Id"); + + b.HasIndex("SeasonId"); + + b.ToTable("EpisodeRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.SeasonRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("ChildRequestId") + .HasColumnType("int"); + + b.Property("SeasonNumber") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("ChildRequestId"); + + b.ToTable("SeasonRequests"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Ombi.Store.Entities.OmbiUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Ombi.Store.Entities.MobileDevices", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationUserId", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany("NotificationUserIds") + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestSubscription", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.AlbumRequest", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.ChildRequests", b => + { + b.HasOne("Ombi.Store.Entities.Requests.TvRequests", "ParentRequest") + .WithMany("ChildRequests") + .HasForeignKey("ParentRequestId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueComments", b => + { + b.HasOne("Ombi.Store.Entities.Requests.Issues", "Issues") + .WithMany("Comments") + .HasForeignKey("IssuesId"); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b => + { + b.HasOne("Ombi.Store.Entities.Requests.IssueCategory", "IssueCategory") + .WithMany() + .HasForeignKey("IssueCategoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Ombi.Store.Entities.Requests.ChildRequests", null) + .WithMany("Issues") + .HasForeignKey("IssueId"); + + b.HasOne("Ombi.Store.Entities.Requests.MovieRequests", null) + .WithMany("Issues") + .HasForeignKey("IssueId"); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "UserReported") + .WithMany() + .HasForeignKey("UserReportedId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.MovieRequests", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.RequestLog", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Tokens", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserNotificationPreferences", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany("UserNotificationPreferences") + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserQualityProfiles", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Votes", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.EpisodeRequests", b => + { + b.HasOne("Ombi.Store.Repository.Requests.SeasonRequests", "Season") + .WithMany("Episodes") + .HasForeignKey("SeasonId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.SeasonRequests", b => + { + b.HasOne("Ombi.Store.Entities.Requests.ChildRequests", "ChildRequest") + .WithMany("SeasonRequests") + .HasForeignKey("ChildRequestId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Ombi.Store/Migrations/OmbiMySql/20200218230644_MobileDevices.cs b/src/Ombi.Store/Migrations/OmbiMySql/20200218230644_MobileDevices.cs new file mode 100644 index 000000000..7dc1afb66 --- /dev/null +++ b/src/Ombi.Store/Migrations/OmbiMySql/20200218230644_MobileDevices.cs @@ -0,0 +1,55 @@ +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using System; + +namespace Ombi.Store.Migrations.OmbiMySql +{ + public partial class MobileDevices : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { +// migrationBuilder.Sql(@"CREATE TABLE `MobileDevices` ( +// `Id` int NOT NULL AUTO_INCREMENT, +// `Token` longtext CHARACTER SET utf8mb4 NULL, +// `UserId` varchar(255) CHARACTER SET utf8mb4 NOT NULL, +// `AddedAt` datetime(6) NOT NULL, +// CONSTRAINT `PK_MobileDevices` PRIMARY KEY (`Id`), +// CONSTRAINT `FK_MobileDevices_AspNetUsers_UserId` FOREIGN KEY (`UserId`) REFERENCES `AspNetUsers` (`Id`) ON DELETE RESTRICT +//);"); + + migrationBuilder.CreateTable( + name: "MobileDevices", + columns: table => new + { + Id = table.Column(nullable: false).Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + Token = table.Column(maxLength: 256, nullable: true), + UserId = table.Column(maxLength: 255, nullable: false), + AddedAt = table.Column(maxLength: 256, nullable: false), + }, + constraints: table => + { + table.PrimaryKey("PK_MobileDevices", x => x.Id); + table.ForeignKey( + name: "FK_MobileDevices_AspNetUsers_UserId", + column: x => x.UserId, + principalTable: "AspNetUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + }); + + + migrationBuilder.CreateIndex( + name: "IX_MobileDevices_UserId", + table: "MobileDevices", + column: "UserId"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "MobileDevices"); + + + } + } +} diff --git a/src/Ombi.Store/Migrations/OmbiMySql/20200516194814_IssueCreatedDate.Designer.cs b/src/Ombi.Store/Migrations/OmbiMySql/20200516194814_IssueCreatedDate.Designer.cs new file mode 100644 index 000000000..b8203bb65 --- /dev/null +++ b/src/Ombi.Store/Migrations/OmbiMySql/20200516194814_IssueCreatedDate.Designer.cs @@ -0,0 +1,1152 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Ombi.Store.Context.MySql; + +namespace Ombi.Store.Migrations.OmbiMySql +{ + [DbContext(typeof(OmbiMySqlContext))] + [Migration("20200516194814_IssueCreatedDate")] + partial class IssueCreatedDate + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "3.1.1") + .HasAnnotation("Relational:MaxIdentifierLength", 64); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .HasColumnType("varchar(255) CHARACTER SET utf8mb4"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("Name") + .HasColumnType("varchar(256) CHARACTER SET utf8mb4") + .HasMaxLength(256); + + b.Property("NormalizedName") + .HasColumnType("varchar(256) CHARACTER SET utf8mb4") + .HasMaxLength(256); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasName("RoleNameIndex"); + + b.ToTable("AspNetRoles"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("ClaimType") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("ClaimValue") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("varchar(255) CHARACTER SET utf8mb4"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("ClaimType") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("ClaimValue") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("varchar(255) CHARACTER SET utf8mb4"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("varchar(255) CHARACTER SET utf8mb4"); + + b.Property("ProviderKey") + .HasColumnType("varchar(255) CHARACTER SET utf8mb4"); + + b.Property("ProviderDisplayName") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("varchar(255) CHARACTER SET utf8mb4"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("varchar(255) CHARACTER SET utf8mb4"); + + b.Property("RoleId") + .HasColumnType("varchar(255) CHARACTER SET utf8mb4"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("varchar(255) CHARACTER SET utf8mb4"); + + b.Property("LoginProvider") + .HasColumnType("varchar(255) CHARACTER SET utf8mb4"); + + b.Property("Name") + .HasColumnType("varchar(255) CHARACTER SET utf8mb4"); + + b.Property("Value") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Audit", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AuditArea") + .HasColumnType("int"); + + b.Property("AuditType") + .HasColumnType("int"); + + b.Property("DateTime") + .HasColumnType("datetime(6)"); + + b.Property("Description") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("User") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.HasKey("Id"); + + b.ToTable("Audit"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.MobileDevices", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AddedAt") + .HasColumnType("datetime(6)"); + + b.Property("Token") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("UserId") + .HasColumnType("varchar(255) CHARACTER SET utf8mb4"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("MobileDevices"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationTemplates", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Agent") + .HasColumnType("int"); + + b.Property("Enabled") + .HasColumnType("tinyint(1)"); + + b.Property("Message") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("NotificationType") + .HasColumnType("int"); + + b.Property("Subject") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.HasKey("Id"); + + b.ToTable("NotificationTemplates"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationUserId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AddedAt") + .HasColumnType("datetime(6)"); + + b.Property("PlayerId") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("UserId") + .HasColumnType("varchar(255) CHARACTER SET utf8mb4"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("NotificationUserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.OmbiUser", b => + { + b.Property("Id") + .HasColumnType("varchar(255) CHARACTER SET utf8mb4"); + + b.Property("AccessFailedCount") + .HasColumnType("int"); + + b.Property("Alias") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("Email") + .HasColumnType("varchar(256) CHARACTER SET utf8mb4") + .HasMaxLength(256); + + b.Property("EmailConfirmed") + .HasColumnType("tinyint(1)"); + + b.Property("EmbyConnectUserId") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("EpisodeRequestLimit") + .HasColumnType("int"); + + b.Property("LastLoggedIn") + .HasColumnType("datetime(6)"); + + b.Property("LockoutEnabled") + .HasColumnType("tinyint(1)"); + + b.Property("LockoutEnd") + .HasColumnType("datetime(6)"); + + b.Property("MovieRequestLimit") + .HasColumnType("int"); + + b.Property("MusicRequestLimit") + .HasColumnType("int"); + + b.Property("NormalizedEmail") + .HasColumnType("varchar(256) CHARACTER SET utf8mb4") + .HasMaxLength(256); + + b.Property("NormalizedUserName") + .HasColumnType("varchar(256) CHARACTER SET utf8mb4") + .HasMaxLength(256); + + b.Property("PasswordHash") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("PhoneNumber") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("tinyint(1)"); + + b.Property("ProviderUserId") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("SecurityStamp") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("TwoFactorEnabled") + .HasColumnType("tinyint(1)"); + + b.Property("UserAccessToken") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("UserName") + .HasColumnType("varchar(256) CHARACTER SET utf8mb4") + .HasMaxLength(256); + + b.Property("UserType") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasName("UserNameIndex"); + + b.ToTable("AspNetUsers"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RecentlyAddedLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AddedAt") + .HasColumnType("datetime(6)"); + + b.Property("AlbumId") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("ContentId") + .HasColumnType("int"); + + b.Property("ContentType") + .HasColumnType("int"); + + b.Property("EpisodeNumber") + .HasColumnType("int"); + + b.Property("SeasonNumber") + .HasColumnType("int"); + + b.Property("Type") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("RecentlyAddedLog"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestQueue", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Completed") + .HasColumnType("datetime(6)"); + + b.Property("Dts") + .HasColumnType("datetime(6)"); + + b.Property("Error") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("RequestId") + .HasColumnType("int"); + + b.Property("RetryCount") + .HasColumnType("int"); + + b.Property("Type") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("RequestQueue"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestSubscription", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("RequestId") + .HasColumnType("int"); + + b.Property("RequestType") + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("varchar(255) CHARACTER SET utf8mb4"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("RequestSubscription"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.AlbumRequest", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Approved") + .HasColumnType("tinyint(1)"); + + b.Property("ArtistName") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("Available") + .HasColumnType("tinyint(1)"); + + b.Property("Cover") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("Denied") + .HasColumnType("tinyint(1)"); + + b.Property("DeniedReason") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("Disk") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("ForeignAlbumId") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("ForeignArtistId") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("MarkedAsApproved") + .HasColumnType("datetime(6)"); + + b.Property("MarkedAsAvailable") + .HasColumnType("datetime(6)"); + + b.Property("MarkedAsDenied") + .HasColumnType("datetime(6)"); + + b.Property("Rating") + .HasColumnType("decimal(65,30)"); + + b.Property("ReleaseDate") + .HasColumnType("datetime(6)"); + + b.Property("RequestType") + .HasColumnType("int"); + + b.Property("RequestedByAlias") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("RequestedDate") + .HasColumnType("datetime(6)"); + + b.Property("RequestedUserId") + .HasColumnType("varchar(255) CHARACTER SET utf8mb4"); + + b.Property("Title") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.HasKey("Id"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("AlbumRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.ChildRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Approved") + .HasColumnType("tinyint(1)"); + + b.Property("Available") + .HasColumnType("tinyint(1)"); + + b.Property("Denied") + .HasColumnType("tinyint(1)"); + + b.Property("DeniedReason") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("IssueId") + .HasColumnType("int"); + + b.Property("MarkedAsApproved") + .HasColumnType("datetime(6)"); + + b.Property("MarkedAsAvailable") + .HasColumnType("datetime(6)"); + + b.Property("MarkedAsDenied") + .HasColumnType("datetime(6)"); + + b.Property("ParentRequestId") + .HasColumnType("int"); + + b.Property("RequestType") + .HasColumnType("int"); + + b.Property("RequestedByAlias") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("RequestedDate") + .HasColumnType("datetime(6)"); + + b.Property("RequestedUserId") + .HasColumnType("varchar(255) CHARACTER SET utf8mb4"); + + b.Property("SeriesType") + .HasColumnType("int"); + + b.Property("Title") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.HasKey("Id"); + + b.HasIndex("ParentRequestId"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("ChildRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueCategory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Value") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.HasKey("Id"); + + b.ToTable("IssueCategory"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueComments", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Comment") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("Date") + .HasColumnType("datetime(6)"); + + b.Property("IssuesId") + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("varchar(255) CHARACTER SET utf8mb4"); + + b.HasKey("Id"); + + b.HasIndex("IssuesId"); + + b.HasIndex("UserId"); + + b.ToTable("IssueComments"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("CreatedDate") + .HasColumnType("datetime(6)"); + + b.Property("Description") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("IssueCategoryId") + .HasColumnType("int"); + + b.Property("IssueId") + .HasColumnType("int"); + + b.Property("ProviderId") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("RequestId") + .HasColumnType("int"); + + b.Property("RequestType") + .HasColumnType("int"); + + b.Property("ResovledDate") + .HasColumnType("datetime(6)"); + + b.Property("Status") + .HasColumnType("int"); + + b.Property("Subject") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("Title") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("UserReportedId") + .HasColumnType("varchar(255) CHARACTER SET utf8mb4"); + + b.HasKey("Id"); + + b.HasIndex("IssueCategoryId"); + + b.HasIndex("IssueId"); + + b.HasIndex("UserReportedId"); + + b.ToTable("Issues"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.MovieRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Approved") + .HasColumnType("tinyint(1)"); + + b.Property("Available") + .HasColumnType("tinyint(1)"); + + b.Property("Background") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("Denied") + .HasColumnType("tinyint(1)"); + + b.Property("DeniedReason") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("DigitalReleaseDate") + .HasColumnType("datetime(6)"); + + b.Property("ImdbId") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("IssueId") + .HasColumnType("int"); + + b.Property("LangCode") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("MarkedAsApproved") + .HasColumnType("datetime(6)"); + + b.Property("MarkedAsAvailable") + .HasColumnType("datetime(6)"); + + b.Property("MarkedAsDenied") + .HasColumnType("datetime(6)"); + + b.Property("Overview") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("PosterPath") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("QualityOverride") + .HasColumnType("int"); + + b.Property("ReleaseDate") + .HasColumnType("datetime(6)"); + + b.Property("RequestType") + .HasColumnType("int"); + + b.Property("RequestedByAlias") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("RequestedDate") + .HasColumnType("datetime(6)"); + + b.Property("RequestedUserId") + .HasColumnType("varchar(255) CHARACTER SET utf8mb4"); + + b.Property("RootPathOverride") + .HasColumnType("int"); + + b.Property("Status") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("TheMovieDbId") + .HasColumnType("int"); + + b.Property("Title") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.HasKey("Id"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("MovieRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.RequestLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("EpisodeCount") + .HasColumnType("int"); + + b.Property("RequestDate") + .HasColumnType("datetime(6)"); + + b.Property("RequestId") + .HasColumnType("int"); + + b.Property("RequestType") + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("varchar(255) CHARACTER SET utf8mb4"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("RequestLog"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.TvRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Background") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("ImdbId") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("Overview") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("PosterPath") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("QualityOverride") + .HasColumnType("int"); + + b.Property("ReleaseDate") + .HasColumnType("datetime(6)"); + + b.Property("RootFolder") + .HasColumnType("int"); + + b.Property("Status") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("Title") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("TotalSeasons") + .HasColumnType("int"); + + b.Property("TvDbId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("TvRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Tokens", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Token") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("UserId") + .HasColumnType("varchar(255) CHARACTER SET utf8mb4"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Tokens"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserNotificationPreferences", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Agent") + .HasColumnType("int"); + + b.Property("Enabled") + .HasColumnType("tinyint(1)"); + + b.Property("UserId") + .HasColumnType("varchar(255) CHARACTER SET utf8mb4"); + + b.Property("Value") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserNotificationPreferences"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserQualityProfiles", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("RadarrQualityProfile") + .HasColumnType("int"); + + b.Property("RadarrRootPath") + .HasColumnType("int"); + + b.Property("SonarrQualityProfile") + .HasColumnType("int"); + + b.Property("SonarrQualityProfileAnime") + .HasColumnType("int"); + + b.Property("SonarrRootPath") + .HasColumnType("int"); + + b.Property("SonarrRootPathAnime") + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("varchar(255) CHARACTER SET utf8mb4"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserQualityProfiles"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Votes", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Date") + .HasColumnType("datetime(6)"); + + b.Property("Deleted") + .HasColumnType("tinyint(1)"); + + b.Property("RequestId") + .HasColumnType("int"); + + b.Property("RequestType") + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("varchar(255) CHARACTER SET utf8mb4"); + + b.Property("VoteType") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Votes"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.EpisodeRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AirDate") + .HasColumnType("datetime(6)"); + + b.Property("Approved") + .HasColumnType("tinyint(1)"); + + b.Property("Available") + .HasColumnType("tinyint(1)"); + + b.Property("EpisodeNumber") + .HasColumnType("int"); + + b.Property("Requested") + .HasColumnType("tinyint(1)"); + + b.Property("SeasonId") + .HasColumnType("int"); + + b.Property("Title") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("Url") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.HasKey("Id"); + + b.HasIndex("SeasonId"); + + b.ToTable("EpisodeRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.SeasonRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("ChildRequestId") + .HasColumnType("int"); + + b.Property("SeasonNumber") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("ChildRequestId"); + + b.ToTable("SeasonRequests"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Ombi.Store.Entities.OmbiUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Ombi.Store.Entities.MobileDevices", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationUserId", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany("NotificationUserIds") + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestSubscription", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.AlbumRequest", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.ChildRequests", b => + { + b.HasOne("Ombi.Store.Entities.Requests.TvRequests", "ParentRequest") + .WithMany("ChildRequests") + .HasForeignKey("ParentRequestId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueComments", b => + { + b.HasOne("Ombi.Store.Entities.Requests.Issues", "Issues") + .WithMany("Comments") + .HasForeignKey("IssuesId"); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b => + { + b.HasOne("Ombi.Store.Entities.Requests.IssueCategory", "IssueCategory") + .WithMany() + .HasForeignKey("IssueCategoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Ombi.Store.Entities.Requests.ChildRequests", null) + .WithMany("Issues") + .HasForeignKey("IssueId"); + + b.HasOne("Ombi.Store.Entities.Requests.MovieRequests", null) + .WithMany("Issues") + .HasForeignKey("IssueId"); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "UserReported") + .WithMany() + .HasForeignKey("UserReportedId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.MovieRequests", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.RequestLog", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Tokens", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserNotificationPreferences", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany("UserNotificationPreferences") + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserQualityProfiles", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Votes", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.EpisodeRequests", b => + { + b.HasOne("Ombi.Store.Repository.Requests.SeasonRequests", "Season") + .WithMany("Episodes") + .HasForeignKey("SeasonId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.SeasonRequests", b => + { + b.HasOne("Ombi.Store.Entities.Requests.ChildRequests", "ChildRequest") + .WithMany("SeasonRequests") + .HasForeignKey("ChildRequestId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Ombi.Store/Migrations/OmbiMySql/20200516194814_IssueCreatedDate.cs b/src/Ombi.Store/Migrations/OmbiMySql/20200516194814_IssueCreatedDate.cs new file mode 100644 index 000000000..6ee4f13eb --- /dev/null +++ b/src/Ombi.Store/Migrations/OmbiMySql/20200516194814_IssueCreatedDate.cs @@ -0,0 +1,24 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +namespace Ombi.Store.Migrations.OmbiMySql +{ + public partial class IssueCreatedDate : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "CreatedDate", + table: "Issues", + nullable: false, + defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified)); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "CreatedDate", + table: "Issues"); + } + } +} diff --git a/src/Ombi.Store/Migrations/OmbiMySql/20200610223540_UserProfile.Designer.cs b/src/Ombi.Store/Migrations/OmbiMySql/20200610223540_UserProfile.Designer.cs new file mode 100644 index 000000000..822053e8a --- /dev/null +++ b/src/Ombi.Store/Migrations/OmbiMySql/20200610223540_UserProfile.Designer.cs @@ -0,0 +1,1155 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Ombi.Store.Context.MySql; + +namespace Ombi.Store.Migrations.OmbiMySql +{ + [DbContext(typeof(OmbiMySqlContext))] + [Migration("20200610223540_UserProfile")] + partial class UserProfile + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "3.1.1") + .HasAnnotation("Relational:MaxIdentifierLength", 64); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .HasColumnType("varchar(255) CHARACTER SET utf8mb4"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("Name") + .HasColumnType("varchar(256) CHARACTER SET utf8mb4") + .HasMaxLength(256); + + b.Property("NormalizedName") + .HasColumnType("varchar(256) CHARACTER SET utf8mb4") + .HasMaxLength(256); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasName("RoleNameIndex"); + + b.ToTable("AspNetRoles"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("ClaimType") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("ClaimValue") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("varchar(255) CHARACTER SET utf8mb4"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("ClaimType") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("ClaimValue") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("varchar(255) CHARACTER SET utf8mb4"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("varchar(255) CHARACTER SET utf8mb4"); + + b.Property("ProviderKey") + .HasColumnType("varchar(255) CHARACTER SET utf8mb4"); + + b.Property("ProviderDisplayName") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("varchar(255) CHARACTER SET utf8mb4"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("varchar(255) CHARACTER SET utf8mb4"); + + b.Property("RoleId") + .HasColumnType("varchar(255) CHARACTER SET utf8mb4"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("varchar(255) CHARACTER SET utf8mb4"); + + b.Property("LoginProvider") + .HasColumnType("varchar(255) CHARACTER SET utf8mb4"); + + b.Property("Name") + .HasColumnType("varchar(255) CHARACTER SET utf8mb4"); + + b.Property("Value") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Audit", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AuditArea") + .HasColumnType("int"); + + b.Property("AuditType") + .HasColumnType("int"); + + b.Property("DateTime") + .HasColumnType("datetime(6)"); + + b.Property("Description") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("User") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.HasKey("Id"); + + b.ToTable("Audit"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.MobileDevices", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AddedAt") + .HasColumnType("datetime(6)"); + + b.Property("Token") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("UserId") + .HasColumnType("varchar(255) CHARACTER SET utf8mb4"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("MobileDevices"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationTemplates", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Agent") + .HasColumnType("int"); + + b.Property("Enabled") + .HasColumnType("tinyint(1)"); + + b.Property("Message") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("NotificationType") + .HasColumnType("int"); + + b.Property("Subject") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.HasKey("Id"); + + b.ToTable("NotificationTemplates"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationUserId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AddedAt") + .HasColumnType("datetime(6)"); + + b.Property("PlayerId") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("UserId") + .HasColumnType("varchar(255) CHARACTER SET utf8mb4"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("NotificationUserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.OmbiUser", b => + { + b.Property("Id") + .HasColumnType("varchar(255) CHARACTER SET utf8mb4"); + + b.Property("AccessFailedCount") + .HasColumnType("int"); + + b.Property("Alias") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("Email") + .HasColumnType("varchar(256) CHARACTER SET utf8mb4") + .HasMaxLength(256); + + b.Property("EmailConfirmed") + .HasColumnType("tinyint(1)"); + + b.Property("EmbyConnectUserId") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("EpisodeRequestLimit") + .HasColumnType("int"); + + b.Property("Language") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("LastLoggedIn") + .HasColumnType("datetime(6)"); + + b.Property("LockoutEnabled") + .HasColumnType("tinyint(1)"); + + b.Property("LockoutEnd") + .HasColumnType("datetime(6)"); + + b.Property("MovieRequestLimit") + .HasColumnType("int"); + + b.Property("MusicRequestLimit") + .HasColumnType("int"); + + b.Property("NormalizedEmail") + .HasColumnType("varchar(256) CHARACTER SET utf8mb4") + .HasMaxLength(256); + + b.Property("NormalizedUserName") + .HasColumnType("varchar(256) CHARACTER SET utf8mb4") + .HasMaxLength(256); + + b.Property("PasswordHash") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("PhoneNumber") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("tinyint(1)"); + + b.Property("ProviderUserId") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("SecurityStamp") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("TwoFactorEnabled") + .HasColumnType("tinyint(1)"); + + b.Property("UserAccessToken") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("UserName") + .HasColumnType("varchar(256) CHARACTER SET utf8mb4") + .HasMaxLength(256); + + b.Property("UserType") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasName("UserNameIndex"); + + b.ToTable("AspNetUsers"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RecentlyAddedLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AddedAt") + .HasColumnType("datetime(6)"); + + b.Property("AlbumId") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("ContentId") + .HasColumnType("int"); + + b.Property("ContentType") + .HasColumnType("int"); + + b.Property("EpisodeNumber") + .HasColumnType("int"); + + b.Property("SeasonNumber") + .HasColumnType("int"); + + b.Property("Type") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("RecentlyAddedLog"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestQueue", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Completed") + .HasColumnType("datetime(6)"); + + b.Property("Dts") + .HasColumnType("datetime(6)"); + + b.Property("Error") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("RequestId") + .HasColumnType("int"); + + b.Property("RetryCount") + .HasColumnType("int"); + + b.Property("Type") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("RequestQueue"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestSubscription", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("RequestId") + .HasColumnType("int"); + + b.Property("RequestType") + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("varchar(255) CHARACTER SET utf8mb4"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("RequestSubscription"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.AlbumRequest", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Approved") + .HasColumnType("tinyint(1)"); + + b.Property("ArtistName") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("Available") + .HasColumnType("tinyint(1)"); + + b.Property("Cover") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("Denied") + .HasColumnType("tinyint(1)"); + + b.Property("DeniedReason") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("Disk") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("ForeignAlbumId") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("ForeignArtistId") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("MarkedAsApproved") + .HasColumnType("datetime(6)"); + + b.Property("MarkedAsAvailable") + .HasColumnType("datetime(6)"); + + b.Property("MarkedAsDenied") + .HasColumnType("datetime(6)"); + + b.Property("Rating") + .HasColumnType("decimal(65,30)"); + + b.Property("ReleaseDate") + .HasColumnType("datetime(6)"); + + b.Property("RequestType") + .HasColumnType("int"); + + b.Property("RequestedByAlias") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("RequestedDate") + .HasColumnType("datetime(6)"); + + b.Property("RequestedUserId") + .HasColumnType("varchar(255) CHARACTER SET utf8mb4"); + + b.Property("Title") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.HasKey("Id"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("AlbumRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.ChildRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Approved") + .HasColumnType("tinyint(1)"); + + b.Property("Available") + .HasColumnType("tinyint(1)"); + + b.Property("Denied") + .HasColumnType("tinyint(1)"); + + b.Property("DeniedReason") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("IssueId") + .HasColumnType("int"); + + b.Property("MarkedAsApproved") + .HasColumnType("datetime(6)"); + + b.Property("MarkedAsAvailable") + .HasColumnType("datetime(6)"); + + b.Property("MarkedAsDenied") + .HasColumnType("datetime(6)"); + + b.Property("ParentRequestId") + .HasColumnType("int"); + + b.Property("RequestType") + .HasColumnType("int"); + + b.Property("RequestedByAlias") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("RequestedDate") + .HasColumnType("datetime(6)"); + + b.Property("RequestedUserId") + .HasColumnType("varchar(255) CHARACTER SET utf8mb4"); + + b.Property("SeriesType") + .HasColumnType("int"); + + b.Property("Title") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.HasKey("Id"); + + b.HasIndex("ParentRequestId"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("ChildRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueCategory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Value") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.HasKey("Id"); + + b.ToTable("IssueCategory"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueComments", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Comment") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("Date") + .HasColumnType("datetime(6)"); + + b.Property("IssuesId") + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("varchar(255) CHARACTER SET utf8mb4"); + + b.HasKey("Id"); + + b.HasIndex("IssuesId"); + + b.HasIndex("UserId"); + + b.ToTable("IssueComments"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("CreatedDate") + .HasColumnType("datetime(6)"); + + b.Property("Description") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("IssueCategoryId") + .HasColumnType("int"); + + b.Property("IssueId") + .HasColumnType("int"); + + b.Property("ProviderId") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("RequestId") + .HasColumnType("int"); + + b.Property("RequestType") + .HasColumnType("int"); + + b.Property("ResovledDate") + .HasColumnType("datetime(6)"); + + b.Property("Status") + .HasColumnType("int"); + + b.Property("Subject") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("Title") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("UserReportedId") + .HasColumnType("varchar(255) CHARACTER SET utf8mb4"); + + b.HasKey("Id"); + + b.HasIndex("IssueCategoryId"); + + b.HasIndex("IssueId"); + + b.HasIndex("UserReportedId"); + + b.ToTable("Issues"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.MovieRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Approved") + .HasColumnType("tinyint(1)"); + + b.Property("Available") + .HasColumnType("tinyint(1)"); + + b.Property("Background") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("Denied") + .HasColumnType("tinyint(1)"); + + b.Property("DeniedReason") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("DigitalReleaseDate") + .HasColumnType("datetime(6)"); + + b.Property("ImdbId") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("IssueId") + .HasColumnType("int"); + + b.Property("LangCode") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("MarkedAsApproved") + .HasColumnType("datetime(6)"); + + b.Property("MarkedAsAvailable") + .HasColumnType("datetime(6)"); + + b.Property("MarkedAsDenied") + .HasColumnType("datetime(6)"); + + b.Property("Overview") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("PosterPath") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("QualityOverride") + .HasColumnType("int"); + + b.Property("ReleaseDate") + .HasColumnType("datetime(6)"); + + b.Property("RequestType") + .HasColumnType("int"); + + b.Property("RequestedByAlias") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("RequestedDate") + .HasColumnType("datetime(6)"); + + b.Property("RequestedUserId") + .HasColumnType("varchar(255) CHARACTER SET utf8mb4"); + + b.Property("RootPathOverride") + .HasColumnType("int"); + + b.Property("Status") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("TheMovieDbId") + .HasColumnType("int"); + + b.Property("Title") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.HasKey("Id"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("MovieRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.RequestLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("EpisodeCount") + .HasColumnType("int"); + + b.Property("RequestDate") + .HasColumnType("datetime(6)"); + + b.Property("RequestId") + .HasColumnType("int"); + + b.Property("RequestType") + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("varchar(255) CHARACTER SET utf8mb4"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("RequestLog"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.TvRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Background") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("ImdbId") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("Overview") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("PosterPath") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("QualityOverride") + .HasColumnType("int"); + + b.Property("ReleaseDate") + .HasColumnType("datetime(6)"); + + b.Property("RootFolder") + .HasColumnType("int"); + + b.Property("Status") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("Title") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("TotalSeasons") + .HasColumnType("int"); + + b.Property("TvDbId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("TvRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Tokens", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Token") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("UserId") + .HasColumnType("varchar(255) CHARACTER SET utf8mb4"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Tokens"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserNotificationPreferences", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Agent") + .HasColumnType("int"); + + b.Property("Enabled") + .HasColumnType("tinyint(1)"); + + b.Property("UserId") + .HasColumnType("varchar(255) CHARACTER SET utf8mb4"); + + b.Property("Value") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserNotificationPreferences"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserQualityProfiles", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("RadarrQualityProfile") + .HasColumnType("int"); + + b.Property("RadarrRootPath") + .HasColumnType("int"); + + b.Property("SonarrQualityProfile") + .HasColumnType("int"); + + b.Property("SonarrQualityProfileAnime") + .HasColumnType("int"); + + b.Property("SonarrRootPath") + .HasColumnType("int"); + + b.Property("SonarrRootPathAnime") + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("varchar(255) CHARACTER SET utf8mb4"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserQualityProfiles"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Votes", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Date") + .HasColumnType("datetime(6)"); + + b.Property("Deleted") + .HasColumnType("tinyint(1)"); + + b.Property("RequestId") + .HasColumnType("int"); + + b.Property("RequestType") + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("varchar(255) CHARACTER SET utf8mb4"); + + b.Property("VoteType") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Votes"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.EpisodeRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AirDate") + .HasColumnType("datetime(6)"); + + b.Property("Approved") + .HasColumnType("tinyint(1)"); + + b.Property("Available") + .HasColumnType("tinyint(1)"); + + b.Property("EpisodeNumber") + .HasColumnType("int"); + + b.Property("Requested") + .HasColumnType("tinyint(1)"); + + b.Property("SeasonId") + .HasColumnType("int"); + + b.Property("Title") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("Url") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.HasKey("Id"); + + b.HasIndex("SeasonId"); + + b.ToTable("EpisodeRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.SeasonRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("ChildRequestId") + .HasColumnType("int"); + + b.Property("SeasonNumber") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("ChildRequestId"); + + b.ToTable("SeasonRequests"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Ombi.Store.Entities.OmbiUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Ombi.Store.Entities.MobileDevices", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationUserId", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany("NotificationUserIds") + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestSubscription", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.AlbumRequest", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.ChildRequests", b => + { + b.HasOne("Ombi.Store.Entities.Requests.TvRequests", "ParentRequest") + .WithMany("ChildRequests") + .HasForeignKey("ParentRequestId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueComments", b => + { + b.HasOne("Ombi.Store.Entities.Requests.Issues", "Issues") + .WithMany("Comments") + .HasForeignKey("IssuesId"); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b => + { + b.HasOne("Ombi.Store.Entities.Requests.IssueCategory", "IssueCategory") + .WithMany() + .HasForeignKey("IssueCategoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Ombi.Store.Entities.Requests.ChildRequests", null) + .WithMany("Issues") + .HasForeignKey("IssueId"); + + b.HasOne("Ombi.Store.Entities.Requests.MovieRequests", null) + .WithMany("Issues") + .HasForeignKey("IssueId"); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "UserReported") + .WithMany() + .HasForeignKey("UserReportedId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.MovieRequests", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.RequestLog", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Tokens", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserNotificationPreferences", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany("UserNotificationPreferences") + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserQualityProfiles", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Votes", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.EpisodeRequests", b => + { + b.HasOne("Ombi.Store.Repository.Requests.SeasonRequests", "Season") + .WithMany("Episodes") + .HasForeignKey("SeasonId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.SeasonRequests", b => + { + b.HasOne("Ombi.Store.Entities.Requests.ChildRequests", "ChildRequest") + .WithMany("SeasonRequests") + .HasForeignKey("ChildRequestId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Ombi.Store/Migrations/OmbiMySql/20200610223540_UserProfile.cs b/src/Ombi.Store/Migrations/OmbiMySql/20200610223540_UserProfile.cs new file mode 100644 index 000000000..be3238859 --- /dev/null +++ b/src/Ombi.Store/Migrations/OmbiMySql/20200610223540_UserProfile.cs @@ -0,0 +1,23 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +namespace Ombi.Store.Migrations.OmbiMySql +{ + public partial class UserProfile : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "Language", + table: "AspNetUsers", + nullable: true); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "Language", + table: "AspNetUsers"); + } + } +} diff --git a/src/Ombi.Store/Migrations/OmbiMySql/20200731151314_RemoveEmbyConnectionid.Designer.cs b/src/Ombi.Store/Migrations/OmbiMySql/20200731151314_RemoveEmbyConnectionid.Designer.cs new file mode 100644 index 000000000..370495409 --- /dev/null +++ b/src/Ombi.Store/Migrations/OmbiMySql/20200731151314_RemoveEmbyConnectionid.Designer.cs @@ -0,0 +1,1152 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Ombi.Store.Context.MySql; + +namespace Ombi.Store.Migrations.OmbiMySql +{ + [DbContext(typeof(OmbiMySqlContext))] + [Migration("20200731151314_RemoveEmbyConnectionid")] + partial class RemoveEmbyConnectionid + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "3.1.1") + .HasAnnotation("Relational:MaxIdentifierLength", 64); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .HasColumnType("varchar(255) CHARACTER SET utf8mb4"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("Name") + .HasColumnType("varchar(256) CHARACTER SET utf8mb4") + .HasMaxLength(256); + + b.Property("NormalizedName") + .HasColumnType("varchar(256) CHARACTER SET utf8mb4") + .HasMaxLength(256); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasName("RoleNameIndex"); + + b.ToTable("AspNetRoles"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("ClaimType") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("ClaimValue") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("varchar(255) CHARACTER SET utf8mb4"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("ClaimType") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("ClaimValue") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("varchar(255) CHARACTER SET utf8mb4"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("varchar(255) CHARACTER SET utf8mb4"); + + b.Property("ProviderKey") + .HasColumnType("varchar(255) CHARACTER SET utf8mb4"); + + b.Property("ProviderDisplayName") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("varchar(255) CHARACTER SET utf8mb4"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("varchar(255) CHARACTER SET utf8mb4"); + + b.Property("RoleId") + .HasColumnType("varchar(255) CHARACTER SET utf8mb4"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("varchar(255) CHARACTER SET utf8mb4"); + + b.Property("LoginProvider") + .HasColumnType("varchar(255) CHARACTER SET utf8mb4"); + + b.Property("Name") + .HasColumnType("varchar(255) CHARACTER SET utf8mb4"); + + b.Property("Value") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Audit", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AuditArea") + .HasColumnType("int"); + + b.Property("AuditType") + .HasColumnType("int"); + + b.Property("DateTime") + .HasColumnType("datetime(6)"); + + b.Property("Description") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("User") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.HasKey("Id"); + + b.ToTable("Audit"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.MobileDevices", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AddedAt") + .HasColumnType("datetime(6)"); + + b.Property("Token") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("UserId") + .HasColumnType("varchar(255) CHARACTER SET utf8mb4"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("MobileDevices"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationTemplates", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Agent") + .HasColumnType("int"); + + b.Property("Enabled") + .HasColumnType("tinyint(1)"); + + b.Property("Message") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("NotificationType") + .HasColumnType("int"); + + b.Property("Subject") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.HasKey("Id"); + + b.ToTable("NotificationTemplates"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationUserId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AddedAt") + .HasColumnType("datetime(6)"); + + b.Property("PlayerId") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("UserId") + .HasColumnType("varchar(255) CHARACTER SET utf8mb4"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("NotificationUserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.OmbiUser", b => + { + b.Property("Id") + .HasColumnType("varchar(255) CHARACTER SET utf8mb4"); + + b.Property("AccessFailedCount") + .HasColumnType("int"); + + b.Property("Alias") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("Email") + .HasColumnType("varchar(256) CHARACTER SET utf8mb4") + .HasMaxLength(256); + + b.Property("EmailConfirmed") + .HasColumnType("tinyint(1)"); + + b.Property("EpisodeRequestLimit") + .HasColumnType("int"); + + b.Property("Language") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("LastLoggedIn") + .HasColumnType("datetime(6)"); + + b.Property("LockoutEnabled") + .HasColumnType("tinyint(1)"); + + b.Property("LockoutEnd") + .HasColumnType("datetime(6)"); + + b.Property("MovieRequestLimit") + .HasColumnType("int"); + + b.Property("MusicRequestLimit") + .HasColumnType("int"); + + b.Property("NormalizedEmail") + .HasColumnType("varchar(256) CHARACTER SET utf8mb4") + .HasMaxLength(256); + + b.Property("NormalizedUserName") + .HasColumnType("varchar(256) CHARACTER SET utf8mb4") + .HasMaxLength(256); + + b.Property("PasswordHash") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("PhoneNumber") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("tinyint(1)"); + + b.Property("ProviderUserId") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("SecurityStamp") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("TwoFactorEnabled") + .HasColumnType("tinyint(1)"); + + b.Property("UserAccessToken") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("UserName") + .HasColumnType("varchar(256) CHARACTER SET utf8mb4") + .HasMaxLength(256); + + b.Property("UserType") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasName("UserNameIndex"); + + b.ToTable("AspNetUsers"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RecentlyAddedLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AddedAt") + .HasColumnType("datetime(6)"); + + b.Property("AlbumId") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("ContentId") + .HasColumnType("int"); + + b.Property("ContentType") + .HasColumnType("int"); + + b.Property("EpisodeNumber") + .HasColumnType("int"); + + b.Property("SeasonNumber") + .HasColumnType("int"); + + b.Property("Type") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("RecentlyAddedLog"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestQueue", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Completed") + .HasColumnType("datetime(6)"); + + b.Property("Dts") + .HasColumnType("datetime(6)"); + + b.Property("Error") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("RequestId") + .HasColumnType("int"); + + b.Property("RetryCount") + .HasColumnType("int"); + + b.Property("Type") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("RequestQueue"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestSubscription", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("RequestId") + .HasColumnType("int"); + + b.Property("RequestType") + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("varchar(255) CHARACTER SET utf8mb4"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("RequestSubscription"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.AlbumRequest", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Approved") + .HasColumnType("tinyint(1)"); + + b.Property("ArtistName") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("Available") + .HasColumnType("tinyint(1)"); + + b.Property("Cover") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("Denied") + .HasColumnType("tinyint(1)"); + + b.Property("DeniedReason") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("Disk") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("ForeignAlbumId") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("ForeignArtistId") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("MarkedAsApproved") + .HasColumnType("datetime(6)"); + + b.Property("MarkedAsAvailable") + .HasColumnType("datetime(6)"); + + b.Property("MarkedAsDenied") + .HasColumnType("datetime(6)"); + + b.Property("Rating") + .HasColumnType("decimal(65,30)"); + + b.Property("ReleaseDate") + .HasColumnType("datetime(6)"); + + b.Property("RequestType") + .HasColumnType("int"); + + b.Property("RequestedByAlias") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("RequestedDate") + .HasColumnType("datetime(6)"); + + b.Property("RequestedUserId") + .HasColumnType("varchar(255) CHARACTER SET utf8mb4"); + + b.Property("Title") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.HasKey("Id"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("AlbumRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.ChildRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Approved") + .HasColumnType("tinyint(1)"); + + b.Property("Available") + .HasColumnType("tinyint(1)"); + + b.Property("Denied") + .HasColumnType("tinyint(1)"); + + b.Property("DeniedReason") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("IssueId") + .HasColumnType("int"); + + b.Property("MarkedAsApproved") + .HasColumnType("datetime(6)"); + + b.Property("MarkedAsAvailable") + .HasColumnType("datetime(6)"); + + b.Property("MarkedAsDenied") + .HasColumnType("datetime(6)"); + + b.Property("ParentRequestId") + .HasColumnType("int"); + + b.Property("RequestType") + .HasColumnType("int"); + + b.Property("RequestedByAlias") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("RequestedDate") + .HasColumnType("datetime(6)"); + + b.Property("RequestedUserId") + .HasColumnType("varchar(255) CHARACTER SET utf8mb4"); + + b.Property("SeriesType") + .HasColumnType("int"); + + b.Property("Title") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.HasKey("Id"); + + b.HasIndex("ParentRequestId"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("ChildRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueCategory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Value") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.HasKey("Id"); + + b.ToTable("IssueCategory"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueComments", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Comment") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("Date") + .HasColumnType("datetime(6)"); + + b.Property("IssuesId") + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("varchar(255) CHARACTER SET utf8mb4"); + + b.HasKey("Id"); + + b.HasIndex("IssuesId"); + + b.HasIndex("UserId"); + + b.ToTable("IssueComments"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("CreatedDate") + .HasColumnType("datetime(6)"); + + b.Property("Description") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("IssueCategoryId") + .HasColumnType("int"); + + b.Property("IssueId") + .HasColumnType("int"); + + b.Property("ProviderId") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("RequestId") + .HasColumnType("int"); + + b.Property("RequestType") + .HasColumnType("int"); + + b.Property("ResovledDate") + .HasColumnType("datetime(6)"); + + b.Property("Status") + .HasColumnType("int"); + + b.Property("Subject") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("Title") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("UserReportedId") + .HasColumnType("varchar(255) CHARACTER SET utf8mb4"); + + b.HasKey("Id"); + + b.HasIndex("IssueCategoryId"); + + b.HasIndex("IssueId"); + + b.HasIndex("UserReportedId"); + + b.ToTable("Issues"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.MovieRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Approved") + .HasColumnType("tinyint(1)"); + + b.Property("Available") + .HasColumnType("tinyint(1)"); + + b.Property("Background") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("Denied") + .HasColumnType("tinyint(1)"); + + b.Property("DeniedReason") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("DigitalReleaseDate") + .HasColumnType("datetime(6)"); + + b.Property("ImdbId") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("IssueId") + .HasColumnType("int"); + + b.Property("LangCode") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("MarkedAsApproved") + .HasColumnType("datetime(6)"); + + b.Property("MarkedAsAvailable") + .HasColumnType("datetime(6)"); + + b.Property("MarkedAsDenied") + .HasColumnType("datetime(6)"); + + b.Property("Overview") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("PosterPath") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("QualityOverride") + .HasColumnType("int"); + + b.Property("ReleaseDate") + .HasColumnType("datetime(6)"); + + b.Property("RequestType") + .HasColumnType("int"); + + b.Property("RequestedByAlias") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("RequestedDate") + .HasColumnType("datetime(6)"); + + b.Property("RequestedUserId") + .HasColumnType("varchar(255) CHARACTER SET utf8mb4"); + + b.Property("RootPathOverride") + .HasColumnType("int"); + + b.Property("Status") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("TheMovieDbId") + .HasColumnType("int"); + + b.Property("Title") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.HasKey("Id"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("MovieRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.RequestLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("EpisodeCount") + .HasColumnType("int"); + + b.Property("RequestDate") + .HasColumnType("datetime(6)"); + + b.Property("RequestId") + .HasColumnType("int"); + + b.Property("RequestType") + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("varchar(255) CHARACTER SET utf8mb4"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("RequestLog"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.TvRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Background") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("ImdbId") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("Overview") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("PosterPath") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("QualityOverride") + .HasColumnType("int"); + + b.Property("ReleaseDate") + .HasColumnType("datetime(6)"); + + b.Property("RootFolder") + .HasColumnType("int"); + + b.Property("Status") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("Title") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("TotalSeasons") + .HasColumnType("int"); + + b.Property("TvDbId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("TvRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Tokens", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Token") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("UserId") + .HasColumnType("varchar(255) CHARACTER SET utf8mb4"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Tokens"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserNotificationPreferences", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Agent") + .HasColumnType("int"); + + b.Property("Enabled") + .HasColumnType("tinyint(1)"); + + b.Property("UserId") + .HasColumnType("varchar(255) CHARACTER SET utf8mb4"); + + b.Property("Value") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserNotificationPreferences"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserQualityProfiles", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("RadarrQualityProfile") + .HasColumnType("int"); + + b.Property("RadarrRootPath") + .HasColumnType("int"); + + b.Property("SonarrQualityProfile") + .HasColumnType("int"); + + b.Property("SonarrQualityProfileAnime") + .HasColumnType("int"); + + b.Property("SonarrRootPath") + .HasColumnType("int"); + + b.Property("SonarrRootPathAnime") + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("varchar(255) CHARACTER SET utf8mb4"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserQualityProfiles"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Votes", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Date") + .HasColumnType("datetime(6)"); + + b.Property("Deleted") + .HasColumnType("tinyint(1)"); + + b.Property("RequestId") + .HasColumnType("int"); + + b.Property("RequestType") + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("varchar(255) CHARACTER SET utf8mb4"); + + b.Property("VoteType") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Votes"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.EpisodeRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AirDate") + .HasColumnType("datetime(6)"); + + b.Property("Approved") + .HasColumnType("tinyint(1)"); + + b.Property("Available") + .HasColumnType("tinyint(1)"); + + b.Property("EpisodeNumber") + .HasColumnType("int"); + + b.Property("Requested") + .HasColumnType("tinyint(1)"); + + b.Property("SeasonId") + .HasColumnType("int"); + + b.Property("Title") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("Url") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.HasKey("Id"); + + b.HasIndex("SeasonId"); + + b.ToTable("EpisodeRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.SeasonRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("ChildRequestId") + .HasColumnType("int"); + + b.Property("SeasonNumber") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("ChildRequestId"); + + b.ToTable("SeasonRequests"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Ombi.Store.Entities.OmbiUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Ombi.Store.Entities.MobileDevices", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationUserId", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany("NotificationUserIds") + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestSubscription", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.AlbumRequest", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.ChildRequests", b => + { + b.HasOne("Ombi.Store.Entities.Requests.TvRequests", "ParentRequest") + .WithMany("ChildRequests") + .HasForeignKey("ParentRequestId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueComments", b => + { + b.HasOne("Ombi.Store.Entities.Requests.Issues", "Issues") + .WithMany("Comments") + .HasForeignKey("IssuesId"); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b => + { + b.HasOne("Ombi.Store.Entities.Requests.IssueCategory", "IssueCategory") + .WithMany() + .HasForeignKey("IssueCategoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Ombi.Store.Entities.Requests.ChildRequests", null) + .WithMany("Issues") + .HasForeignKey("IssueId"); + + b.HasOne("Ombi.Store.Entities.Requests.MovieRequests", null) + .WithMany("Issues") + .HasForeignKey("IssueId"); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "UserReported") + .WithMany() + .HasForeignKey("UserReportedId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.MovieRequests", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.RequestLog", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Tokens", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserNotificationPreferences", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany("UserNotificationPreferences") + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserQualityProfiles", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Votes", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.EpisodeRequests", b => + { + b.HasOne("Ombi.Store.Repository.Requests.SeasonRequests", "Season") + .WithMany("Episodes") + .HasForeignKey("SeasonId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.SeasonRequests", b => + { + b.HasOne("Ombi.Store.Entities.Requests.ChildRequests", "ChildRequest") + .WithMany("SeasonRequests") + .HasForeignKey("ChildRequestId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Ombi.Store/Migrations/OmbiMySql/20200731151314_RemoveEmbyConnectionid.cs b/src/Ombi.Store/Migrations/OmbiMySql/20200731151314_RemoveEmbyConnectionid.cs new file mode 100644 index 000000000..c216b5eae --- /dev/null +++ b/src/Ombi.Store/Migrations/OmbiMySql/20200731151314_RemoveEmbyConnectionid.cs @@ -0,0 +1,24 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace Ombi.Store.Migrations.OmbiMySql +{ + public partial class RemoveEmbyConnectionid : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.Sql("UPDATE AspNetUsers SET UserType = 4 WHERE EmbyConnectUserId IS NOT NULL"); + migrationBuilder.DropColumn( + name: "EmbyConnectUserId", + table: "AspNetUsers"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "EmbyConnectUserId", + table: "AspNetUsers", + type: "longtext CHARACTER SET utf8mb4", + nullable: true); + } + } +} diff --git a/src/Ombi.Store/Migrations/OmbiMySql/20200829205234_Charset.Designer.cs b/src/Ombi.Store/Migrations/OmbiMySql/20200829205234_Charset.Designer.cs new file mode 100644 index 000000000..c6251941f --- /dev/null +++ b/src/Ombi.Store/Migrations/OmbiMySql/20200829205234_Charset.Designer.cs @@ -0,0 +1,1152 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Ombi.Store.Context.MySql; + +namespace Ombi.Store.Migrations.OmbiMySql +{ + [DbContext(typeof(OmbiMySqlContext))] + [Migration("20200829205234_Charset")] + partial class Charset + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "3.1.1") + .HasAnnotation("Relational:MaxIdentifierLength", 64); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .HasColumnType("varchar(255)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("longtext"); + + b.Property("Name") + .HasColumnType("varchar(256)") + .HasMaxLength(256); + + b.Property("NormalizedName") + .HasColumnType("varchar(256)") + .HasMaxLength(256); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasName("RoleNameIndex"); + + b.ToTable("AspNetRoles"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("ClaimType") + .HasColumnType("longtext"); + + b.Property("ClaimValue") + .HasColumnType("longtext"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("ClaimType") + .HasColumnType("longtext"); + + b.Property("ClaimValue") + .HasColumnType("longtext"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("varchar(255)"); + + b.Property("ProviderKey") + .HasColumnType("varchar(255)"); + + b.Property("ProviderDisplayName") + .HasColumnType("longtext"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.Property("RoleId") + .HasColumnType("varchar(255)"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.Property("LoginProvider") + .HasColumnType("varchar(255)"); + + b.Property("Name") + .HasColumnType("varchar(255)"); + + b.Property("Value") + .HasColumnType("longtext"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Audit", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AuditArea") + .HasColumnType("int"); + + b.Property("AuditType") + .HasColumnType("int"); + + b.Property("DateTime") + .HasColumnType("datetime(6)"); + + b.Property("Description") + .HasColumnType("longtext"); + + b.Property("User") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("Audit"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.MobileDevices", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AddedAt") + .HasColumnType("datetime(6)"); + + b.Property("Token") + .HasColumnType("longtext"); + + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("MobileDevices"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationTemplates", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Agent") + .HasColumnType("int"); + + b.Property("Enabled") + .HasColumnType("tinyint(1)"); + + b.Property("Message") + .HasColumnType("longtext"); + + b.Property("NotificationType") + .HasColumnType("int"); + + b.Property("Subject") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("NotificationTemplates"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationUserId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AddedAt") + .HasColumnType("datetime(6)"); + + b.Property("PlayerId") + .HasColumnType("longtext"); + + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("NotificationUserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.OmbiUser", b => + { + b.Property("Id") + .HasColumnType("varchar(255)"); + + b.Property("AccessFailedCount") + .HasColumnType("int"); + + b.Property("Alias") + .HasColumnType("longtext"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("longtext"); + + b.Property("Email") + .HasColumnType("varchar(256)") + .HasMaxLength(256); + + b.Property("EmailConfirmed") + .HasColumnType("tinyint(1)"); + + b.Property("EpisodeRequestLimit") + .HasColumnType("int"); + + b.Property("Language") + .HasColumnType("longtext"); + + b.Property("LastLoggedIn") + .HasColumnType("datetime(6)"); + + b.Property("LockoutEnabled") + .HasColumnType("tinyint(1)"); + + b.Property("LockoutEnd") + .HasColumnType("datetime(6)"); + + b.Property("MovieRequestLimit") + .HasColumnType("int"); + + b.Property("MusicRequestLimit") + .HasColumnType("int"); + + b.Property("NormalizedEmail") + .HasColumnType("varchar(256)") + .HasMaxLength(256); + + b.Property("NormalizedUserName") + .HasColumnType("varchar(256)") + .HasMaxLength(256); + + b.Property("PasswordHash") + .HasColumnType("longtext"); + + b.Property("PhoneNumber") + .HasColumnType("longtext"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("tinyint(1)"); + + b.Property("ProviderUserId") + .HasColumnType("longtext"); + + b.Property("SecurityStamp") + .HasColumnType("longtext"); + + b.Property("TwoFactorEnabled") + .HasColumnType("tinyint(1)"); + + b.Property("UserAccessToken") + .HasColumnType("longtext"); + + b.Property("UserName") + .HasColumnType("varchar(256)") + .HasMaxLength(256); + + b.Property("UserType") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasName("UserNameIndex"); + + b.ToTable("AspNetUsers"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RecentlyAddedLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AddedAt") + .HasColumnType("datetime(6)"); + + b.Property("AlbumId") + .HasColumnType("longtext"); + + b.Property("ContentId") + .HasColumnType("int"); + + b.Property("ContentType") + .HasColumnType("int"); + + b.Property("EpisodeNumber") + .HasColumnType("int"); + + b.Property("SeasonNumber") + .HasColumnType("int"); + + b.Property("Type") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("RecentlyAddedLog"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestQueue", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Completed") + .HasColumnType("datetime(6)"); + + b.Property("Dts") + .HasColumnType("datetime(6)"); + + b.Property("Error") + .HasColumnType("longtext"); + + b.Property("RequestId") + .HasColumnType("int"); + + b.Property("RetryCount") + .HasColumnType("int"); + + b.Property("Type") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("RequestQueue"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestSubscription", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("RequestId") + .HasColumnType("int"); + + b.Property("RequestType") + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("RequestSubscription"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.AlbumRequest", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Approved") + .HasColumnType("tinyint(1)"); + + b.Property("ArtistName") + .HasColumnType("longtext"); + + b.Property("Available") + .HasColumnType("tinyint(1)"); + + b.Property("Cover") + .HasColumnType("longtext"); + + b.Property("Denied") + .HasColumnType("tinyint(1)"); + + b.Property("DeniedReason") + .HasColumnType("longtext"); + + b.Property("Disk") + .HasColumnType("longtext"); + + b.Property("ForeignAlbumId") + .HasColumnType("longtext"); + + b.Property("ForeignArtistId") + .HasColumnType("longtext"); + + b.Property("MarkedAsApproved") + .HasColumnType("datetime(6)"); + + b.Property("MarkedAsAvailable") + .HasColumnType("datetime(6)"); + + b.Property("MarkedAsDenied") + .HasColumnType("datetime(6)"); + + b.Property("Rating") + .HasColumnType("decimal(65,30)"); + + b.Property("ReleaseDate") + .HasColumnType("datetime(6)"); + + b.Property("RequestType") + .HasColumnType("int"); + + b.Property("RequestedByAlias") + .HasColumnType("longtext"); + + b.Property("RequestedDate") + .HasColumnType("datetime(6)"); + + b.Property("RequestedUserId") + .HasColumnType("varchar(255)"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("AlbumRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.ChildRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Approved") + .HasColumnType("tinyint(1)"); + + b.Property("Available") + .HasColumnType("tinyint(1)"); + + b.Property("Denied") + .HasColumnType("tinyint(1)"); + + b.Property("DeniedReason") + .HasColumnType("longtext"); + + b.Property("IssueId") + .HasColumnType("int"); + + b.Property("MarkedAsApproved") + .HasColumnType("datetime(6)"); + + b.Property("MarkedAsAvailable") + .HasColumnType("datetime(6)"); + + b.Property("MarkedAsDenied") + .HasColumnType("datetime(6)"); + + b.Property("ParentRequestId") + .HasColumnType("int"); + + b.Property("RequestType") + .HasColumnType("int"); + + b.Property("RequestedByAlias") + .HasColumnType("longtext"); + + b.Property("RequestedDate") + .HasColumnType("datetime(6)"); + + b.Property("RequestedUserId") + .HasColumnType("varchar(255)"); + + b.Property("SeriesType") + .HasColumnType("int"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("ParentRequestId"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("ChildRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueCategory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Value") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("IssueCategory"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueComments", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Comment") + .HasColumnType("longtext"); + + b.Property("Date") + .HasColumnType("datetime(6)"); + + b.Property("IssuesId") + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("IssuesId"); + + b.HasIndex("UserId"); + + b.ToTable("IssueComments"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("CreatedDate") + .HasColumnType("datetime(6)"); + + b.Property("Description") + .HasColumnType("longtext"); + + b.Property("IssueCategoryId") + .HasColumnType("int"); + + b.Property("IssueId") + .HasColumnType("int"); + + b.Property("ProviderId") + .HasColumnType("longtext"); + + b.Property("RequestId") + .HasColumnType("int"); + + b.Property("RequestType") + .HasColumnType("int"); + + b.Property("ResovledDate") + .HasColumnType("datetime(6)"); + + b.Property("Status") + .HasColumnType("int"); + + b.Property("Subject") + .HasColumnType("longtext"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.Property("UserReportedId") + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("IssueCategoryId"); + + b.HasIndex("IssueId"); + + b.HasIndex("UserReportedId"); + + b.ToTable("Issues"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.MovieRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Approved") + .HasColumnType("tinyint(1)"); + + b.Property("Available") + .HasColumnType("tinyint(1)"); + + b.Property("Background") + .HasColumnType("longtext"); + + b.Property("Denied") + .HasColumnType("tinyint(1)"); + + b.Property("DeniedReason") + .HasColumnType("longtext"); + + b.Property("DigitalReleaseDate") + .HasColumnType("datetime(6)"); + + b.Property("ImdbId") + .HasColumnType("longtext"); + + b.Property("IssueId") + .HasColumnType("int"); + + b.Property("LangCode") + .HasColumnType("longtext"); + + b.Property("MarkedAsApproved") + .HasColumnType("datetime(6)"); + + b.Property("MarkedAsAvailable") + .HasColumnType("datetime(6)"); + + b.Property("MarkedAsDenied") + .HasColumnType("datetime(6)"); + + b.Property("Overview") + .HasColumnType("longtext"); + + b.Property("PosterPath") + .HasColumnType("longtext"); + + b.Property("QualityOverride") + .HasColumnType("int"); + + b.Property("ReleaseDate") + .HasColumnType("datetime(6)"); + + b.Property("RequestType") + .HasColumnType("int"); + + b.Property("RequestedByAlias") + .HasColumnType("longtext"); + + b.Property("RequestedDate") + .HasColumnType("datetime(6)"); + + b.Property("RequestedUserId") + .HasColumnType("varchar(255)"); + + b.Property("RootPathOverride") + .HasColumnType("int"); + + b.Property("Status") + .HasColumnType("longtext"); + + b.Property("TheMovieDbId") + .HasColumnType("int"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("MovieRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.RequestLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("EpisodeCount") + .HasColumnType("int"); + + b.Property("RequestDate") + .HasColumnType("datetime(6)"); + + b.Property("RequestId") + .HasColumnType("int"); + + b.Property("RequestType") + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("RequestLog"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.TvRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Background") + .HasColumnType("longtext"); + + b.Property("ImdbId") + .HasColumnType("longtext"); + + b.Property("Overview") + .HasColumnType("longtext"); + + b.Property("PosterPath") + .HasColumnType("longtext"); + + b.Property("QualityOverride") + .HasColumnType("int"); + + b.Property("ReleaseDate") + .HasColumnType("datetime(6)"); + + b.Property("RootFolder") + .HasColumnType("int"); + + b.Property("Status") + .HasColumnType("longtext"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.Property("TotalSeasons") + .HasColumnType("int"); + + b.Property("TvDbId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("TvRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Tokens", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Token") + .HasColumnType("longtext"); + + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Tokens"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserNotificationPreferences", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Agent") + .HasColumnType("int"); + + b.Property("Enabled") + .HasColumnType("tinyint(1)"); + + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.Property("Value") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserNotificationPreferences"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserQualityProfiles", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("RadarrQualityProfile") + .HasColumnType("int"); + + b.Property("RadarrRootPath") + .HasColumnType("int"); + + b.Property("SonarrQualityProfile") + .HasColumnType("int"); + + b.Property("SonarrQualityProfileAnime") + .HasColumnType("int"); + + b.Property("SonarrRootPath") + .HasColumnType("int"); + + b.Property("SonarrRootPathAnime") + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserQualityProfiles"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Votes", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Date") + .HasColumnType("datetime(6)"); + + b.Property("Deleted") + .HasColumnType("tinyint(1)"); + + b.Property("RequestId") + .HasColumnType("int"); + + b.Property("RequestType") + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.Property("VoteType") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Votes"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.EpisodeRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AirDate") + .HasColumnType("datetime(6)"); + + b.Property("Approved") + .HasColumnType("tinyint(1)"); + + b.Property("Available") + .HasColumnType("tinyint(1)"); + + b.Property("EpisodeNumber") + .HasColumnType("int"); + + b.Property("Requested") + .HasColumnType("tinyint(1)"); + + b.Property("SeasonId") + .HasColumnType("int"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.Property("Url") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("SeasonId"); + + b.ToTable("EpisodeRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.SeasonRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("ChildRequestId") + .HasColumnType("int"); + + b.Property("SeasonNumber") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("ChildRequestId"); + + b.ToTable("SeasonRequests"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Ombi.Store.Entities.OmbiUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Ombi.Store.Entities.MobileDevices", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationUserId", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany("NotificationUserIds") + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestSubscription", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.AlbumRequest", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.ChildRequests", b => + { + b.HasOne("Ombi.Store.Entities.Requests.TvRequests", "ParentRequest") + .WithMany("ChildRequests") + .HasForeignKey("ParentRequestId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueComments", b => + { + b.HasOne("Ombi.Store.Entities.Requests.Issues", "Issues") + .WithMany("Comments") + .HasForeignKey("IssuesId"); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b => + { + b.HasOne("Ombi.Store.Entities.Requests.IssueCategory", "IssueCategory") + .WithMany() + .HasForeignKey("IssueCategoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Ombi.Store.Entities.Requests.ChildRequests", null) + .WithMany("Issues") + .HasForeignKey("IssueId"); + + b.HasOne("Ombi.Store.Entities.Requests.MovieRequests", null) + .WithMany("Issues") + .HasForeignKey("IssueId"); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "UserReported") + .WithMany() + .HasForeignKey("UserReportedId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.MovieRequests", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.RequestLog", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Tokens", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserNotificationPreferences", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany("UserNotificationPreferences") + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserQualityProfiles", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Votes", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.EpisodeRequests", b => + { + b.HasOne("Ombi.Store.Repository.Requests.SeasonRequests", "Season") + .WithMany("Episodes") + .HasForeignKey("SeasonId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.SeasonRequests", b => + { + b.HasOne("Ombi.Store.Entities.Requests.ChildRequests", "ChildRequest") + .WithMany("SeasonRequests") + .HasForeignKey("ChildRequestId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Ombi.Store/Migrations/OmbiMySql/20200829205234_Charset.cs b/src/Ombi.Store/Migrations/OmbiMySql/20200829205234_Charset.cs new file mode 100644 index 000000000..d907bc0e1 --- /dev/null +++ b/src/Ombi.Store/Migrations/OmbiMySql/20200829205234_Charset.cs @@ -0,0 +1,1457 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace Ombi.Store.Migrations.OmbiMySql +{ + public partial class Charset : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.Sql("SET FOREIGN_KEY_CHECKS=0;"); + migrationBuilder.AlterColumn( + name: "UserId", + table: "Votes", + nullable: true, + oldClrType: typeof(string), + oldType: "varchar(255) CHARACTER SET utf8mb4", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "UserId", + table: "UserQualityProfiles", + nullable: true, + oldClrType: typeof(string), + oldType: "varchar(255) CHARACTER SET utf8mb4", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Value", + table: "UserNotificationPreferences", + nullable: true, + oldClrType: typeof(string), + oldType: "longtext CHARACTER SET utf8mb4", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "UserId", + table: "UserNotificationPreferences", + nullable: true, + oldClrType: typeof(string), + oldType: "varchar(255) CHARACTER SET utf8mb4", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Title", + table: "TvRequests", + nullable: true, + oldClrType: typeof(string), + oldType: "longtext CHARACTER SET utf8mb4", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Status", + table: "TvRequests", + nullable: true, + oldClrType: typeof(string), + oldType: "longtext CHARACTER SET utf8mb4", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "PosterPath", + table: "TvRequests", + nullable: true, + oldClrType: typeof(string), + oldType: "longtext CHARACTER SET utf8mb4", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Overview", + table: "TvRequests", + nullable: true, + oldClrType: typeof(string), + oldType: "longtext CHARACTER SET utf8mb4", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "ImdbId", + table: "TvRequests", + nullable: true, + oldClrType: typeof(string), + oldType: "longtext CHARACTER SET utf8mb4", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Background", + table: "TvRequests", + nullable: true, + oldClrType: typeof(string), + oldType: "longtext CHARACTER SET utf8mb4", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "UserId", + table: "Tokens", + nullable: true, + oldClrType: typeof(string), + oldType: "varchar(255) CHARACTER SET utf8mb4", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Token", + table: "Tokens", + nullable: true, + oldClrType: typeof(string), + oldType: "longtext CHARACTER SET utf8mb4", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "UserId", + table: "RequestSubscription", + nullable: true, + oldClrType: typeof(string), + oldType: "varchar(255) CHARACTER SET utf8mb4", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Error", + table: "RequestQueue", + nullable: true, + oldClrType: typeof(string), + oldType: "longtext CHARACTER SET utf8mb4", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "UserId", + table: "RequestLog", + nullable: true, + oldClrType: typeof(string), + oldType: "varchar(255) CHARACTER SET utf8mb4", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "AlbumId", + table: "RecentlyAddedLog", + nullable: true, + oldClrType: typeof(string), + oldType: "longtext CHARACTER SET utf8mb4", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "UserId", + table: "NotificationUserId", + nullable: true, + oldClrType: typeof(string), + oldType: "varchar(255) CHARACTER SET utf8mb4", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "PlayerId", + table: "NotificationUserId", + nullable: true, + oldClrType: typeof(string), + oldType: "longtext CHARACTER SET utf8mb4", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Subject", + table: "NotificationTemplates", + nullable: true, + oldClrType: typeof(string), + oldType: "longtext CHARACTER SET utf8mb4", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Message", + table: "NotificationTemplates", + nullable: true, + oldClrType: typeof(string), + oldType: "longtext CHARACTER SET utf8mb4", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Title", + table: "MovieRequests", + nullable: true, + oldClrType: typeof(string), + oldType: "longtext CHARACTER SET utf8mb4", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Status", + table: "MovieRequests", + nullable: true, + oldClrType: typeof(string), + oldType: "longtext CHARACTER SET utf8mb4", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "RequestedUserId", + table: "MovieRequests", + nullable: true, + oldClrType: typeof(string), + oldType: "varchar(255) CHARACTER SET utf8mb4", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "RequestedByAlias", + table: "MovieRequests", + nullable: true, + oldClrType: typeof(string), + oldType: "longtext CHARACTER SET utf8mb4", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "PosterPath", + table: "MovieRequests", + nullable: true, + oldClrType: typeof(string), + oldType: "longtext CHARACTER SET utf8mb4", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Overview", + table: "MovieRequests", + nullable: true, + oldClrType: typeof(string), + oldType: "longtext CHARACTER SET utf8mb4", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "LangCode", + table: "MovieRequests", + nullable: true, + oldClrType: typeof(string), + oldType: "longtext CHARACTER SET utf8mb4", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "ImdbId", + table: "MovieRequests", + nullable: true, + oldClrType: typeof(string), + oldType: "longtext CHARACTER SET utf8mb4", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "DeniedReason", + table: "MovieRequests", + nullable: true, + oldClrType: typeof(string), + oldType: "longtext CHARACTER SET utf8mb4", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Background", + table: "MovieRequests", + nullable: true, + oldClrType: typeof(string), + oldType: "longtext CHARACTER SET utf8mb4", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "UserId", + table: "MobileDevices", + nullable: true, + oldClrType: typeof(string), + oldType: "varchar(255) CHARACTER SET utf8mb4", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Token", + table: "MobileDevices", + nullable: true, + oldClrType: typeof(string), + oldType: "longtext CHARACTER SET utf8mb4", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "UserReportedId", + table: "Issues", + nullable: true, + oldClrType: typeof(string), + oldType: "varchar(255) CHARACTER SET utf8mb4", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Title", + table: "Issues", + nullable: true, + oldClrType: typeof(string), + oldType: "longtext CHARACTER SET utf8mb4", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Subject", + table: "Issues", + nullable: true, + oldClrType: typeof(string), + oldType: "longtext CHARACTER SET utf8mb4", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "ProviderId", + table: "Issues", + nullable: true, + oldClrType: typeof(string), + oldType: "longtext CHARACTER SET utf8mb4", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Description", + table: "Issues", + nullable: true, + oldClrType: typeof(string), + oldType: "longtext CHARACTER SET utf8mb4", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "UserId", + table: "IssueComments", + nullable: true, + oldClrType: typeof(string), + oldType: "varchar(255) CHARACTER SET utf8mb4", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Comment", + table: "IssueComments", + nullable: true, + oldClrType: typeof(string), + oldType: "longtext CHARACTER SET utf8mb4", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Value", + table: "IssueCategory", + nullable: true, + oldClrType: typeof(string), + oldType: "longtext CHARACTER SET utf8mb4", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Url", + table: "EpisodeRequests", + nullable: true, + oldClrType: typeof(string), + oldType: "longtext CHARACTER SET utf8mb4", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Title", + table: "EpisodeRequests", + nullable: true, + oldClrType: typeof(string), + oldType: "longtext CHARACTER SET utf8mb4", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Title", + table: "ChildRequests", + nullable: true, + oldClrType: typeof(string), + oldType: "longtext CHARACTER SET utf8mb4", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "RequestedUserId", + table: "ChildRequests", + nullable: true, + oldClrType: typeof(string), + oldType: "varchar(255) CHARACTER SET utf8mb4", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "RequestedByAlias", + table: "ChildRequests", + nullable: true, + oldClrType: typeof(string), + oldType: "longtext CHARACTER SET utf8mb4", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "DeniedReason", + table: "ChildRequests", + nullable: true, + oldClrType: typeof(string), + oldType: "longtext CHARACTER SET utf8mb4", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "User", + table: "Audit", + nullable: true, + oldClrType: typeof(string), + oldType: "longtext CHARACTER SET utf8mb4", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Description", + table: "Audit", + nullable: true, + oldClrType: typeof(string), + oldType: "longtext CHARACTER SET utf8mb4", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Value", + table: "AspNetUserTokens", + nullable: true, + oldClrType: typeof(string), + oldType: "longtext CHARACTER SET utf8mb4", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Name", + table: "AspNetUserTokens", + nullable: false, + oldClrType: typeof(string), + oldType: "varchar(255) CHARACTER SET utf8mb4"); + + migrationBuilder.AlterColumn( + name: "LoginProvider", + table: "AspNetUserTokens", + nullable: false, + oldClrType: typeof(string), + oldType: "varchar(255) CHARACTER SET utf8mb4"); + + migrationBuilder.AlterColumn( + name: "UserId", + table: "AspNetUserTokens", + nullable: false, + oldClrType: typeof(string), + oldType: "varchar(255) CHARACTER SET utf8mb4"); + + migrationBuilder.AlterColumn( + name: "UserName", + table: "AspNetUsers", + maxLength: 256, + nullable: true, + oldClrType: typeof(string), + oldType: "varchar(256) CHARACTER SET utf8mb4", + oldMaxLength: 256, + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "UserAccessToken", + table: "AspNetUsers", + nullable: true, + oldClrType: typeof(string), + oldType: "longtext CHARACTER SET utf8mb4", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "SecurityStamp", + table: "AspNetUsers", + nullable: true, + oldClrType: typeof(string), + oldType: "longtext CHARACTER SET utf8mb4", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "ProviderUserId", + table: "AspNetUsers", + nullable: true, + oldClrType: typeof(string), + oldType: "longtext CHARACTER SET utf8mb4", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "PhoneNumber", + table: "AspNetUsers", + nullable: true, + oldClrType: typeof(string), + oldType: "longtext CHARACTER SET utf8mb4", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "PasswordHash", + table: "AspNetUsers", + nullable: true, + oldClrType: typeof(string), + oldType: "longtext CHARACTER SET utf8mb4", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "NormalizedUserName", + table: "AspNetUsers", + maxLength: 256, + nullable: true, + oldClrType: typeof(string), + oldType: "varchar(256) CHARACTER SET utf8mb4", + oldMaxLength: 256, + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "NormalizedEmail", + table: "AspNetUsers", + maxLength: 256, + nullable: true, + oldClrType: typeof(string), + oldType: "varchar(256) CHARACTER SET utf8mb4", + oldMaxLength: 256, + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Language", + table: "AspNetUsers", + nullable: true, + oldClrType: typeof(string), + oldType: "longtext CHARACTER SET utf8mb4", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Email", + table: "AspNetUsers", + maxLength: 256, + nullable: true, + oldClrType: typeof(string), + oldType: "varchar(256) CHARACTER SET utf8mb4", + oldMaxLength: 256, + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "ConcurrencyStamp", + table: "AspNetUsers", + nullable: true, + oldClrType: typeof(string), + oldType: "longtext CHARACTER SET utf8mb4", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Alias", + table: "AspNetUsers", + nullable: true, + oldClrType: typeof(string), + oldType: "longtext CHARACTER SET utf8mb4", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Id", + table: "AspNetUsers", + nullable: false, + oldClrType: typeof(string), + oldType: "varchar(255) CHARACTER SET utf8mb4"); + + migrationBuilder.AlterColumn( + name: "RoleId", + table: "AspNetUserRoles", + nullable: false, + oldClrType: typeof(string), + oldType: "varchar(255) CHARACTER SET utf8mb4"); + + migrationBuilder.AlterColumn( + name: "UserId", + table: "AspNetUserRoles", + nullable: false, + oldClrType: typeof(string), + oldType: "varchar(255) CHARACTER SET utf8mb4"); + + migrationBuilder.AlterColumn( + name: "UserId", + table: "AspNetUserLogins", + nullable: false, + oldClrType: typeof(string), + oldType: "varchar(255) CHARACTER SET utf8mb4"); + + migrationBuilder.AlterColumn( + name: "ProviderDisplayName", + table: "AspNetUserLogins", + nullable: true, + oldClrType: typeof(string), + oldType: "longtext CHARACTER SET utf8mb4", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "ProviderKey", + table: "AspNetUserLogins", + nullable: false, + oldClrType: typeof(string), + oldType: "varchar(255) CHARACTER SET utf8mb4"); + + migrationBuilder.AlterColumn( + name: "LoginProvider", + table: "AspNetUserLogins", + nullable: false, + oldClrType: typeof(string), + oldType: "varchar(255) CHARACTER SET utf8mb4"); + + migrationBuilder.AlterColumn( + name: "UserId", + table: "AspNetUserClaims", + nullable: false, + oldClrType: typeof(string), + oldType: "varchar(255) CHARACTER SET utf8mb4"); + + migrationBuilder.AlterColumn( + name: "ClaimValue", + table: "AspNetUserClaims", + nullable: true, + oldClrType: typeof(string), + oldType: "longtext CHARACTER SET utf8mb4", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "ClaimType", + table: "AspNetUserClaims", + nullable: true, + oldClrType: typeof(string), + oldType: "longtext CHARACTER SET utf8mb4", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "NormalizedName", + table: "AspNetRoles", + maxLength: 256, + nullable: true, + oldClrType: typeof(string), + oldType: "varchar(256) CHARACTER SET utf8mb4", + oldMaxLength: 256, + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Name", + table: "AspNetRoles", + maxLength: 256, + nullable: true, + oldClrType: typeof(string), + oldType: "varchar(256) CHARACTER SET utf8mb4", + oldMaxLength: 256, + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "ConcurrencyStamp", + table: "AspNetRoles", + nullable: true, + oldClrType: typeof(string), + oldType: "longtext CHARACTER SET utf8mb4", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Id", + table: "AspNetRoles", + nullable: false, + oldClrType: typeof(string), + oldType: "varchar(255) CHARACTER SET utf8mb4"); + + migrationBuilder.AlterColumn( + name: "RoleId", + table: "AspNetRoleClaims", + nullable: false, + oldClrType: typeof(string), + oldType: "varchar(255) CHARACTER SET utf8mb4"); + + migrationBuilder.AlterColumn( + name: "ClaimValue", + table: "AspNetRoleClaims", + nullable: true, + oldClrType: typeof(string), + oldType: "longtext CHARACTER SET utf8mb4", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "ClaimType", + table: "AspNetRoleClaims", + nullable: true, + oldClrType: typeof(string), + oldType: "longtext CHARACTER SET utf8mb4", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Title", + table: "AlbumRequests", + nullable: true, + oldClrType: typeof(string), + oldType: "longtext CHARACTER SET utf8mb4", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "RequestedUserId", + table: "AlbumRequests", + nullable: true, + oldClrType: typeof(string), + oldType: "varchar(255) CHARACTER SET utf8mb4", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "RequestedByAlias", + table: "AlbumRequests", + nullable: true, + oldClrType: typeof(string), + oldType: "longtext CHARACTER SET utf8mb4", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "ForeignArtistId", + table: "AlbumRequests", + nullable: true, + oldClrType: typeof(string), + oldType: "longtext CHARACTER SET utf8mb4", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "ForeignAlbumId", + table: "AlbumRequests", + nullable: true, + oldClrType: typeof(string), + oldType: "longtext CHARACTER SET utf8mb4", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Disk", + table: "AlbumRequests", + nullable: true, + oldClrType: typeof(string), + oldType: "longtext CHARACTER SET utf8mb4", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "DeniedReason", + table: "AlbumRequests", + nullable: true, + oldClrType: typeof(string), + oldType: "longtext CHARACTER SET utf8mb4", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Cover", + table: "AlbumRequests", + nullable: true, + oldClrType: typeof(string), + oldType: "longtext CHARACTER SET utf8mb4", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "ArtistName", + table: "AlbumRequests", + nullable: true, + oldClrType: typeof(string), + oldType: "longtext CHARACTER SET utf8mb4", + oldNullable: true); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.AlterColumn( + name: "UserId", + table: "Votes", + type: "varchar(255) CHARACTER SET utf8mb4", + nullable: true, + oldClrType: typeof(string), + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "UserId", + table: "UserQualityProfiles", + type: "varchar(255) CHARACTER SET utf8mb4", + nullable: true, + oldClrType: typeof(string), + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Value", + table: "UserNotificationPreferences", + type: "longtext CHARACTER SET utf8mb4", + nullable: true, + oldClrType: typeof(string), + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "UserId", + table: "UserNotificationPreferences", + type: "varchar(255) CHARACTER SET utf8mb4", + nullable: true, + oldClrType: typeof(string), + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Title", + table: "TvRequests", + type: "longtext CHARACTER SET utf8mb4", + nullable: true, + oldClrType: typeof(string), + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Status", + table: "TvRequests", + type: "longtext CHARACTER SET utf8mb4", + nullable: true, + oldClrType: typeof(string), + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "PosterPath", + table: "TvRequests", + type: "longtext CHARACTER SET utf8mb4", + nullable: true, + oldClrType: typeof(string), + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Overview", + table: "TvRequests", + type: "longtext CHARACTER SET utf8mb4", + nullable: true, + oldClrType: typeof(string), + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "ImdbId", + table: "TvRequests", + type: "longtext CHARACTER SET utf8mb4", + nullable: true, + oldClrType: typeof(string), + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Background", + table: "TvRequests", + type: "longtext CHARACTER SET utf8mb4", + nullable: true, + oldClrType: typeof(string), + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "UserId", + table: "Tokens", + type: "varchar(255) CHARACTER SET utf8mb4", + nullable: true, + oldClrType: typeof(string), + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Token", + table: "Tokens", + type: "longtext CHARACTER SET utf8mb4", + nullable: true, + oldClrType: typeof(string), + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "UserId", + table: "RequestSubscription", + type: "varchar(255) CHARACTER SET utf8mb4", + nullable: true, + oldClrType: typeof(string), + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Error", + table: "RequestQueue", + type: "longtext CHARACTER SET utf8mb4", + nullable: true, + oldClrType: typeof(string), + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "UserId", + table: "RequestLog", + type: "varchar(255) CHARACTER SET utf8mb4", + nullable: true, + oldClrType: typeof(string), + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "AlbumId", + table: "RecentlyAddedLog", + type: "longtext CHARACTER SET utf8mb4", + nullable: true, + oldClrType: typeof(string), + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "UserId", + table: "NotificationUserId", + type: "varchar(255) CHARACTER SET utf8mb4", + nullable: true, + oldClrType: typeof(string), + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "PlayerId", + table: "NotificationUserId", + type: "longtext CHARACTER SET utf8mb4", + nullable: true, + oldClrType: typeof(string), + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Subject", + table: "NotificationTemplates", + type: "longtext CHARACTER SET utf8mb4", + nullable: true, + oldClrType: typeof(string), + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Message", + table: "NotificationTemplates", + type: "longtext CHARACTER SET utf8mb4", + nullable: true, + oldClrType: typeof(string), + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Title", + table: "MovieRequests", + type: "longtext CHARACTER SET utf8mb4", + nullable: true, + oldClrType: typeof(string), + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Status", + table: "MovieRequests", + type: "longtext CHARACTER SET utf8mb4", + nullable: true, + oldClrType: typeof(string), + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "RequestedUserId", + table: "MovieRequests", + type: "varchar(255) CHARACTER SET utf8mb4", + nullable: true, + oldClrType: typeof(string), + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "RequestedByAlias", + table: "MovieRequests", + type: "longtext CHARACTER SET utf8mb4", + nullable: true, + oldClrType: typeof(string), + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "PosterPath", + table: "MovieRequests", + type: "longtext CHARACTER SET utf8mb4", + nullable: true, + oldClrType: typeof(string), + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Overview", + table: "MovieRequests", + type: "longtext CHARACTER SET utf8mb4", + nullable: true, + oldClrType: typeof(string), + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "LangCode", + table: "MovieRequests", + type: "longtext CHARACTER SET utf8mb4", + nullable: true, + oldClrType: typeof(string), + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "ImdbId", + table: "MovieRequests", + type: "longtext CHARACTER SET utf8mb4", + nullable: true, + oldClrType: typeof(string), + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "DeniedReason", + table: "MovieRequests", + type: "longtext CHARACTER SET utf8mb4", + nullable: true, + oldClrType: typeof(string), + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Background", + table: "MovieRequests", + type: "longtext CHARACTER SET utf8mb4", + nullable: true, + oldClrType: typeof(string), + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "UserId", + table: "MobileDevices", + type: "varchar(255) CHARACTER SET utf8mb4", + nullable: true, + oldClrType: typeof(string), + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Token", + table: "MobileDevices", + type: "longtext CHARACTER SET utf8mb4", + nullable: true, + oldClrType: typeof(string), + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "UserReportedId", + table: "Issues", + type: "varchar(255) CHARACTER SET utf8mb4", + nullable: true, + oldClrType: typeof(string), + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Title", + table: "Issues", + type: "longtext CHARACTER SET utf8mb4", + nullable: true, + oldClrType: typeof(string), + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Subject", + table: "Issues", + type: "longtext CHARACTER SET utf8mb4", + nullable: true, + oldClrType: typeof(string), + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "ProviderId", + table: "Issues", + type: "longtext CHARACTER SET utf8mb4", + nullable: true, + oldClrType: typeof(string), + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Description", + table: "Issues", + type: "longtext CHARACTER SET utf8mb4", + nullable: true, + oldClrType: typeof(string), + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "UserId", + table: "IssueComments", + type: "varchar(255) CHARACTER SET utf8mb4", + nullable: true, + oldClrType: typeof(string), + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Comment", + table: "IssueComments", + type: "longtext CHARACTER SET utf8mb4", + nullable: true, + oldClrType: typeof(string), + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Value", + table: "IssueCategory", + type: "longtext CHARACTER SET utf8mb4", + nullable: true, + oldClrType: typeof(string), + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Url", + table: "EpisodeRequests", + type: "longtext CHARACTER SET utf8mb4", + nullable: true, + oldClrType: typeof(string), + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Title", + table: "EpisodeRequests", + type: "longtext CHARACTER SET utf8mb4", + nullable: true, + oldClrType: typeof(string), + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Title", + table: "ChildRequests", + type: "longtext CHARACTER SET utf8mb4", + nullable: true, + oldClrType: typeof(string), + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "RequestedUserId", + table: "ChildRequests", + type: "varchar(255) CHARACTER SET utf8mb4", + nullable: true, + oldClrType: typeof(string), + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "RequestedByAlias", + table: "ChildRequests", + type: "longtext CHARACTER SET utf8mb4", + nullable: true, + oldClrType: typeof(string), + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "DeniedReason", + table: "ChildRequests", + type: "longtext CHARACTER SET utf8mb4", + nullable: true, + oldClrType: typeof(string), + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "User", + table: "Audit", + type: "longtext CHARACTER SET utf8mb4", + nullable: true, + oldClrType: typeof(string), + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Description", + table: "Audit", + type: "longtext CHARACTER SET utf8mb4", + nullable: true, + oldClrType: typeof(string), + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Value", + table: "AspNetUserTokens", + type: "longtext CHARACTER SET utf8mb4", + nullable: true, + oldClrType: typeof(string), + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Name", + table: "AspNetUserTokens", + type: "varchar(255) CHARACTER SET utf8mb4", + nullable: false, + oldClrType: typeof(string)); + + migrationBuilder.AlterColumn( + name: "LoginProvider", + table: "AspNetUserTokens", + type: "varchar(255) CHARACTER SET utf8mb4", + nullable: false, + oldClrType: typeof(string)); + + migrationBuilder.AlterColumn( + name: "UserId", + table: "AspNetUserTokens", + type: "varchar(255) CHARACTER SET utf8mb4", + nullable: false, + oldClrType: typeof(string)); + + migrationBuilder.AlterColumn( + name: "UserName", + table: "AspNetUsers", + type: "varchar(256) CHARACTER SET utf8mb4", + maxLength: 256, + nullable: true, + oldClrType: typeof(string), + oldMaxLength: 256, + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "UserAccessToken", + table: "AspNetUsers", + type: "longtext CHARACTER SET utf8mb4", + nullable: true, + oldClrType: typeof(string), + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "SecurityStamp", + table: "AspNetUsers", + type: "longtext CHARACTER SET utf8mb4", + nullable: true, + oldClrType: typeof(string), + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "ProviderUserId", + table: "AspNetUsers", + type: "longtext CHARACTER SET utf8mb4", + nullable: true, + oldClrType: typeof(string), + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "PhoneNumber", + table: "AspNetUsers", + type: "longtext CHARACTER SET utf8mb4", + nullable: true, + oldClrType: typeof(string), + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "PasswordHash", + table: "AspNetUsers", + type: "longtext CHARACTER SET utf8mb4", + nullable: true, + oldClrType: typeof(string), + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "NormalizedUserName", + table: "AspNetUsers", + type: "varchar(256) CHARACTER SET utf8mb4", + maxLength: 256, + nullable: true, + oldClrType: typeof(string), + oldMaxLength: 256, + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "NormalizedEmail", + table: "AspNetUsers", + type: "varchar(256) CHARACTER SET utf8mb4", + maxLength: 256, + nullable: true, + oldClrType: typeof(string), + oldMaxLength: 256, + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Language", + table: "AspNetUsers", + type: "longtext CHARACTER SET utf8mb4", + nullable: true, + oldClrType: typeof(string), + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Email", + table: "AspNetUsers", + type: "varchar(256) CHARACTER SET utf8mb4", + maxLength: 256, + nullable: true, + oldClrType: typeof(string), + oldMaxLength: 256, + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "ConcurrencyStamp", + table: "AspNetUsers", + type: "longtext CHARACTER SET utf8mb4", + nullable: true, + oldClrType: typeof(string), + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Alias", + table: "AspNetUsers", + type: "longtext CHARACTER SET utf8mb4", + nullable: true, + oldClrType: typeof(string), + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Id", + table: "AspNetUsers", + type: "varchar(255) CHARACTER SET utf8mb4", + nullable: false, + oldClrType: typeof(string)); + + migrationBuilder.AlterColumn( + name: "RoleId", + table: "AspNetUserRoles", + type: "varchar(255) CHARACTER SET utf8mb4", + nullable: false, + oldClrType: typeof(string)); + + migrationBuilder.AlterColumn( + name: "UserId", + table: "AspNetUserRoles", + type: "varchar(255) CHARACTER SET utf8mb4", + nullable: false, + oldClrType: typeof(string)); + + migrationBuilder.AlterColumn( + name: "UserId", + table: "AspNetUserLogins", + type: "varchar(255) CHARACTER SET utf8mb4", + nullable: false, + oldClrType: typeof(string)); + + migrationBuilder.AlterColumn( + name: "ProviderDisplayName", + table: "AspNetUserLogins", + type: "longtext CHARACTER SET utf8mb4", + nullable: true, + oldClrType: typeof(string), + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "ProviderKey", + table: "AspNetUserLogins", + type: "varchar(255) CHARACTER SET utf8mb4", + nullable: false, + oldClrType: typeof(string)); + + migrationBuilder.AlterColumn( + name: "LoginProvider", + table: "AspNetUserLogins", + type: "varchar(255) CHARACTER SET utf8mb4", + nullable: false, + oldClrType: typeof(string)); + + migrationBuilder.AlterColumn( + name: "UserId", + table: "AspNetUserClaims", + type: "varchar(255) CHARACTER SET utf8mb4", + nullable: false, + oldClrType: typeof(string)); + + migrationBuilder.AlterColumn( + name: "ClaimValue", + table: "AspNetUserClaims", + type: "longtext CHARACTER SET utf8mb4", + nullable: true, + oldClrType: typeof(string), + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "ClaimType", + table: "AspNetUserClaims", + type: "longtext CHARACTER SET utf8mb4", + nullable: true, + oldClrType: typeof(string), + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "NormalizedName", + table: "AspNetRoles", + type: "varchar(256) CHARACTER SET utf8mb4", + maxLength: 256, + nullable: true, + oldClrType: typeof(string), + oldMaxLength: 256, + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Name", + table: "AspNetRoles", + type: "varchar(256) CHARACTER SET utf8mb4", + maxLength: 256, + nullable: true, + oldClrType: typeof(string), + oldMaxLength: 256, + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "ConcurrencyStamp", + table: "AspNetRoles", + type: "longtext CHARACTER SET utf8mb4", + nullable: true, + oldClrType: typeof(string), + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Id", + table: "AspNetRoles", + type: "varchar(255) CHARACTER SET utf8mb4", + nullable: false, + oldClrType: typeof(string)); + + migrationBuilder.AlterColumn( + name: "RoleId", + table: "AspNetRoleClaims", + type: "varchar(255) CHARACTER SET utf8mb4", + nullable: false, + oldClrType: typeof(string)); + + migrationBuilder.AlterColumn( + name: "ClaimValue", + table: "AspNetRoleClaims", + type: "longtext CHARACTER SET utf8mb4", + nullable: true, + oldClrType: typeof(string), + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "ClaimType", + table: "AspNetRoleClaims", + type: "longtext CHARACTER SET utf8mb4", + nullable: true, + oldClrType: typeof(string), + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Title", + table: "AlbumRequests", + type: "longtext CHARACTER SET utf8mb4", + nullable: true, + oldClrType: typeof(string), + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "RequestedUserId", + table: "AlbumRequests", + type: "varchar(255) CHARACTER SET utf8mb4", + nullable: true, + oldClrType: typeof(string), + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "RequestedByAlias", + table: "AlbumRequests", + type: "longtext CHARACTER SET utf8mb4", + nullable: true, + oldClrType: typeof(string), + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "ForeignArtistId", + table: "AlbumRequests", + type: "longtext CHARACTER SET utf8mb4", + nullable: true, + oldClrType: typeof(string), + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "ForeignAlbumId", + table: "AlbumRequests", + type: "longtext CHARACTER SET utf8mb4", + nullable: true, + oldClrType: typeof(string), + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Disk", + table: "AlbumRequests", + type: "longtext CHARACTER SET utf8mb4", + nullable: true, + oldClrType: typeof(string), + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "DeniedReason", + table: "AlbumRequests", + type: "longtext CHARACTER SET utf8mb4", + nullable: true, + oldClrType: typeof(string), + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Cover", + table: "AlbumRequests", + type: "longtext CHARACTER SET utf8mb4", + nullable: true, + oldClrType: typeof(string), + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "ArtistName", + table: "AlbumRequests", + type: "longtext CHARACTER SET utf8mb4", + nullable: true, + oldClrType: typeof(string), + oldNullable: true); + + + migrationBuilder.Sql("SET FOREIGN_KEY_CHECKS=1;"); + } + } +} diff --git a/src/Ombi.Store/Migrations/OmbiMySql/OmbiMySqlContextModelSnapshot.cs b/src/Ombi.Store/Migrations/OmbiMySql/OmbiMySqlContextModelSnapshot.cs index 7952ce974..1678a77c1 100644 --- a/src/Ombi.Store/Migrations/OmbiMySql/OmbiMySqlContextModelSnapshot.cs +++ b/src/Ombi.Store/Migrations/OmbiMySql/OmbiMySqlContextModelSnapshot.cs @@ -3,7 +3,6 @@ using System; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using Ombi.Store.Context; using Ombi.Store.Context.MySql; namespace Ombi.Store.Migrations.OmbiMySql @@ -15,21 +14,24 @@ namespace Ombi.Store.Migrations.OmbiMySql { #pragma warning disable 612, 618 modelBuilder - .HasAnnotation("ProductVersion", "2.2.6-servicing-10079") + .HasAnnotation("ProductVersion", "3.1.1") .HasAnnotation("Relational:MaxIdentifierLength", 64); modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => { b.Property("Id") - .ValueGeneratedOnAdd(); + .HasColumnType("varchar(255)"); b.Property("ConcurrencyStamp") - .IsConcurrencyToken(); + .IsConcurrencyToken() + .HasColumnType("longtext"); b.Property("Name") + .HasColumnType("varchar(256)") .HasMaxLength(256); b.Property("NormalizedName") + .HasColumnType("varchar(256)") .HasMaxLength(256); b.HasKey("Id"); @@ -44,14 +46,18 @@ namespace Ombi.Store.Migrations.OmbiMySql modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => { b.Property("Id") - .ValueGeneratedOnAdd(); + .ValueGeneratedOnAdd() + .HasColumnType("int"); - b.Property("ClaimType"); + b.Property("ClaimType") + .HasColumnType("longtext"); - b.Property("ClaimValue"); + b.Property("ClaimValue") + .HasColumnType("longtext"); b.Property("RoleId") - .IsRequired(); + .IsRequired() + .HasColumnType("varchar(255)"); b.HasKey("Id"); @@ -63,14 +69,18 @@ namespace Ombi.Store.Migrations.OmbiMySql modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => { b.Property("Id") - .ValueGeneratedOnAdd(); + .ValueGeneratedOnAdd() + .HasColumnType("int"); - b.Property("ClaimType"); + b.Property("ClaimType") + .HasColumnType("longtext"); - b.Property("ClaimValue"); + b.Property("ClaimValue") + .HasColumnType("longtext"); b.Property("UserId") - .IsRequired(); + .IsRequired() + .HasColumnType("varchar(255)"); b.HasKey("Id"); @@ -81,14 +91,18 @@ namespace Ombi.Store.Migrations.OmbiMySql modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => { - b.Property("LoginProvider"); + b.Property("LoginProvider") + .HasColumnType("varchar(255)"); - b.Property("ProviderKey"); + b.Property("ProviderKey") + .HasColumnType("varchar(255)"); - b.Property("ProviderDisplayName"); + b.Property("ProviderDisplayName") + .HasColumnType("longtext"); b.Property("UserId") - .IsRequired(); + .IsRequired() + .HasColumnType("varchar(255)"); b.HasKey("LoginProvider", "ProviderKey"); @@ -99,9 +113,11 @@ namespace Ombi.Store.Migrations.OmbiMySql modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => { - b.Property("UserId"); + b.Property("UserId") + .HasColumnType("varchar(255)"); - b.Property("RoleId"); + b.Property("RoleId") + .HasColumnType("varchar(255)"); b.HasKey("UserId", "RoleId"); @@ -112,13 +128,17 @@ namespace Ombi.Store.Migrations.OmbiMySql modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => { - b.Property("UserId"); + b.Property("UserId") + .HasColumnType("varchar(255)"); - b.Property("LoginProvider"); + b.Property("LoginProvider") + .HasColumnType("varchar(255)"); - b.Property("Name"); + b.Property("Name") + .HasColumnType("varchar(255)"); - b.Property("Value"); + b.Property("Value") + .HasColumnType("longtext"); b.HasKey("UserId", "LoginProvider", "Name"); @@ -128,37 +148,71 @@ namespace Ombi.Store.Migrations.OmbiMySql modelBuilder.Entity("Ombi.Store.Entities.Audit", b => { b.Property("Id") - .ValueGeneratedOnAdd(); + .ValueGeneratedOnAdd() + .HasColumnType("int"); - b.Property("AuditArea"); + b.Property("AuditArea") + .HasColumnType("int"); - b.Property("AuditType"); + b.Property("AuditType") + .HasColumnType("int"); - b.Property("DateTime"); + b.Property("DateTime") + .HasColumnType("datetime(6)"); - b.Property("Description"); + b.Property("Description") + .HasColumnType("longtext"); - b.Property("User"); + b.Property("User") + .HasColumnType("longtext"); b.HasKey("Id"); b.ToTable("Audit"); }); + modelBuilder.Entity("Ombi.Store.Entities.MobileDevices", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AddedAt") + .HasColumnType("datetime(6)"); + + b.Property("Token") + .HasColumnType("longtext"); + + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("MobileDevices"); + }); + modelBuilder.Entity("Ombi.Store.Entities.NotificationTemplates", b => { b.Property("Id") - .ValueGeneratedOnAdd(); + .ValueGeneratedOnAdd() + .HasColumnType("int"); - b.Property("Agent"); + b.Property("Agent") + .HasColumnType("int"); - b.Property("Enabled"); + b.Property("Enabled") + .HasColumnType("tinyint(1)"); - b.Property("Message"); + b.Property("Message") + .HasColumnType("longtext"); - b.Property("NotificationType"); + b.Property("NotificationType") + .HasColumnType("int"); - b.Property("Subject"); + b.Property("Subject") + .HasColumnType("longtext"); b.HasKey("Id"); @@ -168,13 +222,17 @@ namespace Ombi.Store.Migrations.OmbiMySql modelBuilder.Entity("Ombi.Store.Entities.NotificationUserId", b => { b.Property("Id") - .ValueGeneratedOnAdd(); + .ValueGeneratedOnAdd() + .HasColumnType("int"); - b.Property("AddedAt"); + b.Property("AddedAt") + .HasColumnType("datetime(6)"); - b.Property("PlayerId"); + b.Property("PlayerId") + .HasColumnType("longtext"); - b.Property("UserId"); + b.Property("UserId") + .HasColumnType("varchar(255)"); b.HasKey("Id"); @@ -186,58 +244,81 @@ namespace Ombi.Store.Migrations.OmbiMySql modelBuilder.Entity("Ombi.Store.Entities.OmbiUser", b => { b.Property("Id") - .ValueGeneratedOnAdd(); + .HasColumnType("varchar(255)"); - b.Property("AccessFailedCount"); + b.Property("AccessFailedCount") + .HasColumnType("int"); - b.Property("Alias"); + b.Property("Alias") + .HasColumnType("longtext"); b.Property("ConcurrencyStamp") - .IsConcurrencyToken(); + .IsConcurrencyToken() + .HasColumnType("longtext"); b.Property("Email") + .HasColumnType("varchar(256)") .HasMaxLength(256); - b.Property("EmailConfirmed"); + b.Property("EmailConfirmed") + .HasColumnType("tinyint(1)"); - b.Property("EmbyConnectUserId"); + b.Property("EpisodeRequestLimit") + .HasColumnType("int"); - b.Property("EpisodeRequestLimit"); + b.Property("Language") + .HasColumnType("longtext"); - b.Property("LastLoggedIn"); + b.Property("LastLoggedIn") + .HasColumnType("datetime(6)"); - b.Property("LockoutEnabled"); + b.Property("LockoutEnabled") + .HasColumnType("tinyint(1)"); - b.Property("LockoutEnd"); + b.Property("LockoutEnd") + .HasColumnType("datetime(6)"); - b.Property("MovieRequestLimit"); + b.Property("MovieRequestLimit") + .HasColumnType("int"); - b.Property("MusicRequestLimit"); + b.Property("MusicRequestLimit") + .HasColumnType("int"); b.Property("NormalizedEmail") + .HasColumnType("varchar(256)") .HasMaxLength(256); b.Property("NormalizedUserName") + .HasColumnType("varchar(256)") .HasMaxLength(256); - b.Property("PasswordHash"); + b.Property("PasswordHash") + .HasColumnType("longtext"); - b.Property("PhoneNumber"); + b.Property("PhoneNumber") + .HasColumnType("longtext"); - b.Property("PhoneNumberConfirmed"); + b.Property("PhoneNumberConfirmed") + .HasColumnType("tinyint(1)"); - b.Property("ProviderUserId"); + b.Property("ProviderUserId") + .HasColumnType("longtext"); - b.Property("SecurityStamp"); + b.Property("SecurityStamp") + .HasColumnType("longtext"); - b.Property("TwoFactorEnabled"); + b.Property("TwoFactorEnabled") + .HasColumnType("tinyint(1)"); - b.Property("UserAccessToken"); + b.Property("UserAccessToken") + .HasColumnType("longtext"); b.Property("UserName") + .HasColumnType("varchar(256)") .HasMaxLength(256); - b.Property("UserType"); + b.Property("UserType") + .HasColumnType("int"); b.HasKey("Id"); @@ -254,21 +335,29 @@ namespace Ombi.Store.Migrations.OmbiMySql modelBuilder.Entity("Ombi.Store.Entities.RecentlyAddedLog", b => { b.Property("Id") - .ValueGeneratedOnAdd(); + .ValueGeneratedOnAdd() + .HasColumnType("int"); - b.Property("AddedAt"); + b.Property("AddedAt") + .HasColumnType("datetime(6)"); - b.Property("AlbumId"); + b.Property("AlbumId") + .HasColumnType("longtext"); - b.Property("ContentId"); + b.Property("ContentId") + .HasColumnType("int"); - b.Property("ContentType"); + b.Property("ContentType") + .HasColumnType("int"); - b.Property("EpisodeNumber"); + b.Property("EpisodeNumber") + .HasColumnType("int"); - b.Property("SeasonNumber"); + b.Property("SeasonNumber") + .HasColumnType("int"); - b.Property("Type"); + b.Property("Type") + .HasColumnType("int"); b.HasKey("Id"); @@ -278,19 +367,26 @@ namespace Ombi.Store.Migrations.OmbiMySql modelBuilder.Entity("Ombi.Store.Entities.RequestQueue", b => { b.Property("Id") - .ValueGeneratedOnAdd(); + .ValueGeneratedOnAdd() + .HasColumnType("int"); - b.Property("Completed"); + b.Property("Completed") + .HasColumnType("datetime(6)"); - b.Property("Dts"); + b.Property("Dts") + .HasColumnType("datetime(6)"); - b.Property("Error"); + b.Property("Error") + .HasColumnType("longtext"); - b.Property("RequestId"); + b.Property("RequestId") + .HasColumnType("int"); - b.Property("RetryCount"); + b.Property("RetryCount") + .HasColumnType("int"); - b.Property("Type"); + b.Property("Type") + .HasColumnType("int"); b.HasKey("Id"); @@ -300,13 +396,17 @@ namespace Ombi.Store.Migrations.OmbiMySql modelBuilder.Entity("Ombi.Store.Entities.RequestSubscription", b => { b.Property("Id") - .ValueGeneratedOnAdd(); + .ValueGeneratedOnAdd() + .HasColumnType("int"); - b.Property("RequestId"); + b.Property("RequestId") + .HasColumnType("int"); - b.Property("RequestType"); + b.Property("RequestType") + .HasColumnType("int"); - b.Property("UserId"); + b.Property("UserId") + .HasColumnType("varchar(255)"); b.HasKey("Id"); @@ -318,45 +418,65 @@ namespace Ombi.Store.Migrations.OmbiMySql modelBuilder.Entity("Ombi.Store.Entities.Requests.AlbumRequest", b => { b.Property("Id") - .ValueGeneratedOnAdd(); + .ValueGeneratedOnAdd() + .HasColumnType("int"); - b.Property("Approved"); + b.Property("Approved") + .HasColumnType("tinyint(1)"); - b.Property("ArtistName"); + b.Property("ArtistName") + .HasColumnType("longtext"); - b.Property("Available"); + b.Property("Available") + .HasColumnType("tinyint(1)"); - b.Property("Cover"); + b.Property("Cover") + .HasColumnType("longtext"); - b.Property("Denied"); + b.Property("Denied") + .HasColumnType("tinyint(1)"); - b.Property("DeniedReason"); + b.Property("DeniedReason") + .HasColumnType("longtext"); - b.Property("Disk"); + b.Property("Disk") + .HasColumnType("longtext"); - b.Property("ForeignAlbumId"); + b.Property("ForeignAlbumId") + .HasColumnType("longtext"); - b.Property("ForeignArtistId"); + b.Property("ForeignArtistId") + .HasColumnType("longtext"); - b.Property("MarkedAsApproved"); + b.Property("MarkedAsApproved") + .HasColumnType("datetime(6)"); - b.Property("MarkedAsAvailable"); + b.Property("MarkedAsAvailable") + .HasColumnType("datetime(6)"); - b.Property("MarkedAsDenied"); + b.Property("MarkedAsDenied") + .HasColumnType("datetime(6)"); - b.Property("Rating"); + b.Property("Rating") + .HasColumnType("decimal(65,30)"); - b.Property("ReleaseDate"); + b.Property("ReleaseDate") + .HasColumnType("datetime(6)"); - b.Property("RequestType"); + b.Property("RequestType") + .HasColumnType("int"); - b.Property("RequestedByAlias"); + b.Property("RequestedByAlias") + .HasColumnType("longtext"); - b.Property("RequestedDate"); + b.Property("RequestedDate") + .HasColumnType("datetime(6)"); - b.Property("RequestedUserId"); + b.Property("RequestedUserId") + .HasColumnType("varchar(255)"); - b.Property("Title"); + b.Property("Title") + .HasColumnType("longtext"); b.HasKey("Id"); @@ -368,37 +488,53 @@ namespace Ombi.Store.Migrations.OmbiMySql modelBuilder.Entity("Ombi.Store.Entities.Requests.ChildRequests", b => { b.Property("Id") - .ValueGeneratedOnAdd(); + .ValueGeneratedOnAdd() + .HasColumnType("int"); - b.Property("Approved"); + b.Property("Approved") + .HasColumnType("tinyint(1)"); - b.Property("Available"); + b.Property("Available") + .HasColumnType("tinyint(1)"); - b.Property("Denied"); + b.Property("Denied") + .HasColumnType("tinyint(1)"); - b.Property("DeniedReason"); + b.Property("DeniedReason") + .HasColumnType("longtext"); - b.Property("IssueId"); + b.Property("IssueId") + .HasColumnType("int"); - b.Property("MarkedAsApproved"); + b.Property("MarkedAsApproved") + .HasColumnType("datetime(6)"); - b.Property("MarkedAsAvailable"); + b.Property("MarkedAsAvailable") + .HasColumnType("datetime(6)"); - b.Property("MarkedAsDenied"); + b.Property("MarkedAsDenied") + .HasColumnType("datetime(6)"); - b.Property("ParentRequestId"); + b.Property("ParentRequestId") + .HasColumnType("int"); - b.Property("RequestType"); + b.Property("RequestType") + .HasColumnType("int"); - b.Property("RequestedByAlias"); + b.Property("RequestedByAlias") + .HasColumnType("longtext"); - b.Property("RequestedDate"); + b.Property("RequestedDate") + .HasColumnType("datetime(6)"); - b.Property("RequestedUserId"); + b.Property("RequestedUserId") + .HasColumnType("varchar(255)"); - b.Property("SeriesType"); + b.Property("SeriesType") + .HasColumnType("int"); - b.Property("Title"); + b.Property("Title") + .HasColumnType("longtext"); b.HasKey("Id"); @@ -412,9 +548,11 @@ namespace Ombi.Store.Migrations.OmbiMySql modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueCategory", b => { b.Property("Id") - .ValueGeneratedOnAdd(); + .ValueGeneratedOnAdd() + .HasColumnType("int"); - b.Property("Value"); + b.Property("Value") + .HasColumnType("longtext"); b.HasKey("Id"); @@ -424,15 +562,20 @@ namespace Ombi.Store.Migrations.OmbiMySql modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueComments", b => { b.Property("Id") - .ValueGeneratedOnAdd(); + .ValueGeneratedOnAdd() + .HasColumnType("int"); - b.Property("Comment"); + b.Property("Comment") + .HasColumnType("longtext"); - b.Property("Date"); + b.Property("Date") + .HasColumnType("datetime(6)"); - b.Property("IssuesId"); + b.Property("IssuesId") + .HasColumnType("int"); - b.Property("UserId"); + b.Property("UserId") + .HasColumnType("varchar(255)"); b.HasKey("Id"); @@ -446,29 +589,44 @@ namespace Ombi.Store.Migrations.OmbiMySql modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b => { b.Property("Id") - .ValueGeneratedOnAdd(); + .ValueGeneratedOnAdd() + .HasColumnType("int"); - b.Property("Description"); + b.Property("CreatedDate") + .HasColumnType("datetime(6)"); - b.Property("IssueCategoryId"); + b.Property("Description") + .HasColumnType("longtext"); - b.Property("IssueId"); + b.Property("IssueCategoryId") + .HasColumnType("int"); - b.Property("ProviderId"); + b.Property("IssueId") + .HasColumnType("int"); - b.Property("RequestId"); + b.Property("ProviderId") + .HasColumnType("longtext"); - b.Property("RequestType"); + b.Property("RequestId") + .HasColumnType("int"); - b.Property("ResovledDate"); + b.Property("RequestType") + .HasColumnType("int"); - b.Property("Status"); + b.Property("ResovledDate") + .HasColumnType("datetime(6)"); - b.Property("Subject"); + b.Property("Status") + .HasColumnType("int"); - b.Property("Title"); + b.Property("Subject") + .HasColumnType("longtext"); - b.Property("UserReportedId"); + b.Property("Title") + .HasColumnType("longtext"); + + b.Property("UserReportedId") + .HasColumnType("varchar(255)"); b.HasKey("Id"); @@ -484,55 +642,80 @@ namespace Ombi.Store.Migrations.OmbiMySql modelBuilder.Entity("Ombi.Store.Entities.Requests.MovieRequests", b => { b.Property("Id") - .ValueGeneratedOnAdd(); + .ValueGeneratedOnAdd() + .HasColumnType("int"); - b.Property("Approved"); + b.Property("Approved") + .HasColumnType("tinyint(1)"); - b.Property("Available"); + b.Property("Available") + .HasColumnType("tinyint(1)"); - b.Property("Background"); + b.Property("Background") + .HasColumnType("longtext"); - b.Property("Denied"); + b.Property("Denied") + .HasColumnType("tinyint(1)"); - b.Property("DeniedReason"); + b.Property("DeniedReason") + .HasColumnType("longtext"); - b.Property("DigitalReleaseDate"); + b.Property("DigitalReleaseDate") + .HasColumnType("datetime(6)"); - b.Property("ImdbId"); + b.Property("ImdbId") + .HasColumnType("longtext"); - b.Property("IssueId"); + b.Property("IssueId") + .HasColumnType("int"); - b.Property("LangCode"); + b.Property("LangCode") + .HasColumnType("longtext"); - b.Property("MarkedAsApproved"); + b.Property("MarkedAsApproved") + .HasColumnType("datetime(6)"); - b.Property("MarkedAsAvailable"); + b.Property("MarkedAsAvailable") + .HasColumnType("datetime(6)"); - b.Property("MarkedAsDenied"); + b.Property("MarkedAsDenied") + .HasColumnType("datetime(6)"); - b.Property("Overview"); + b.Property("Overview") + .HasColumnType("longtext"); - b.Property("PosterPath"); + b.Property("PosterPath") + .HasColumnType("longtext"); - b.Property("QualityOverride"); + b.Property("QualityOverride") + .HasColumnType("int"); - b.Property("ReleaseDate"); + b.Property("ReleaseDate") + .HasColumnType("datetime(6)"); - b.Property("RequestType"); + b.Property("RequestType") + .HasColumnType("int"); - b.Property("RequestedByAlias"); + b.Property("RequestedByAlias") + .HasColumnType("longtext"); - b.Property("RequestedDate"); + b.Property("RequestedDate") + .HasColumnType("datetime(6)"); - b.Property("RequestedUserId"); + b.Property("RequestedUserId") + .HasColumnType("varchar(255)"); - b.Property("RootPathOverride"); + b.Property("RootPathOverride") + .HasColumnType("int"); - b.Property("Status"); + b.Property("Status") + .HasColumnType("longtext"); - b.Property("TheMovieDbId"); + b.Property("TheMovieDbId") + .HasColumnType("int"); - b.Property("Title"); + b.Property("Title") + .HasColumnType("longtext"); b.HasKey("Id"); @@ -544,17 +727,23 @@ namespace Ombi.Store.Migrations.OmbiMySql modelBuilder.Entity("Ombi.Store.Entities.Requests.RequestLog", b => { b.Property("Id") - .ValueGeneratedOnAdd(); + .ValueGeneratedOnAdd() + .HasColumnType("int"); - b.Property("EpisodeCount"); + b.Property("EpisodeCount") + .HasColumnType("int"); - b.Property("RequestDate"); + b.Property("RequestDate") + .HasColumnType("datetime(6)"); - b.Property("RequestId"); + b.Property("RequestId") + .HasColumnType("int"); - b.Property("RequestType"); + b.Property("RequestType") + .HasColumnType("int"); - b.Property("UserId"); + b.Property("UserId") + .HasColumnType("varchar(255)"); b.HasKey("Id"); @@ -566,29 +755,41 @@ namespace Ombi.Store.Migrations.OmbiMySql modelBuilder.Entity("Ombi.Store.Entities.Requests.TvRequests", b => { b.Property("Id") - .ValueGeneratedOnAdd(); + .ValueGeneratedOnAdd() + .HasColumnType("int"); - b.Property("Background"); + b.Property("Background") + .HasColumnType("longtext"); - b.Property("ImdbId"); + b.Property("ImdbId") + .HasColumnType("longtext"); - b.Property("Overview"); + b.Property("Overview") + .HasColumnType("longtext"); - b.Property("PosterPath"); + b.Property("PosterPath") + .HasColumnType("longtext"); - b.Property("QualityOverride"); + b.Property("QualityOverride") + .HasColumnType("int"); - b.Property("ReleaseDate"); + b.Property("ReleaseDate") + .HasColumnType("datetime(6)"); - b.Property("RootFolder"); + b.Property("RootFolder") + .HasColumnType("int"); - b.Property("Status"); + b.Property("Status") + .HasColumnType("longtext"); - b.Property("Title"); + b.Property("Title") + .HasColumnType("longtext"); - b.Property("TotalSeasons"); + b.Property("TotalSeasons") + .HasColumnType("int"); - b.Property("TvDbId"); + b.Property("TvDbId") + .HasColumnType("int"); b.HasKey("Id"); @@ -598,11 +799,14 @@ namespace Ombi.Store.Migrations.OmbiMySql modelBuilder.Entity("Ombi.Store.Entities.Tokens", b => { b.Property("Id") - .ValueGeneratedOnAdd(); + .ValueGeneratedOnAdd() + .HasColumnType("int"); - b.Property("Token"); + b.Property("Token") + .HasColumnType("longtext"); - b.Property("UserId"); + b.Property("UserId") + .HasColumnType("varchar(255)"); b.HasKey("Id"); @@ -614,15 +818,20 @@ namespace Ombi.Store.Migrations.OmbiMySql modelBuilder.Entity("Ombi.Store.Entities.UserNotificationPreferences", b => { b.Property("Id") - .ValueGeneratedOnAdd(); + .ValueGeneratedOnAdd() + .HasColumnType("int"); - b.Property("Agent"); + b.Property("Agent") + .HasColumnType("int"); - b.Property("Enabled"); + b.Property("Enabled") + .HasColumnType("tinyint(1)"); - b.Property("UserId"); + b.Property("UserId") + .HasColumnType("varchar(255)"); - b.Property("Value"); + b.Property("Value") + .HasColumnType("longtext"); b.HasKey("Id"); @@ -634,21 +843,29 @@ namespace Ombi.Store.Migrations.OmbiMySql modelBuilder.Entity("Ombi.Store.Entities.UserQualityProfiles", b => { b.Property("Id") - .ValueGeneratedOnAdd(); + .ValueGeneratedOnAdd() + .HasColumnType("int"); - b.Property("RadarrQualityProfile"); + b.Property("RadarrQualityProfile") + .HasColumnType("int"); - b.Property("RadarrRootPath"); + b.Property("RadarrRootPath") + .HasColumnType("int"); - b.Property("SonarrQualityProfile"); + b.Property("SonarrQualityProfile") + .HasColumnType("int"); - b.Property("SonarrQualityProfileAnime"); + b.Property("SonarrQualityProfileAnime") + .HasColumnType("int"); - b.Property("SonarrRootPath"); + b.Property("SonarrRootPath") + .HasColumnType("int"); - b.Property("SonarrRootPathAnime"); + b.Property("SonarrRootPathAnime") + .HasColumnType("int"); - b.Property("UserId"); + b.Property("UserId") + .HasColumnType("varchar(255)"); b.HasKey("Id"); @@ -660,19 +877,26 @@ namespace Ombi.Store.Migrations.OmbiMySql modelBuilder.Entity("Ombi.Store.Entities.Votes", b => { b.Property("Id") - .ValueGeneratedOnAdd(); + .ValueGeneratedOnAdd() + .HasColumnType("int"); - b.Property("Date"); + b.Property("Date") + .HasColumnType("datetime(6)"); - b.Property("Deleted"); + b.Property("Deleted") + .HasColumnType("tinyint(1)"); - b.Property("RequestId"); + b.Property("RequestId") + .HasColumnType("int"); - b.Property("RequestType"); + b.Property("RequestType") + .HasColumnType("int"); - b.Property("UserId"); + b.Property("UserId") + .HasColumnType("varchar(255)"); - b.Property("VoteType"); + b.Property("VoteType") + .HasColumnType("int"); b.HasKey("Id"); @@ -684,23 +908,32 @@ namespace Ombi.Store.Migrations.OmbiMySql modelBuilder.Entity("Ombi.Store.Repository.Requests.EpisodeRequests", b => { b.Property("Id") - .ValueGeneratedOnAdd(); + .ValueGeneratedOnAdd() + .HasColumnType("int"); - b.Property("AirDate"); + b.Property("AirDate") + .HasColumnType("datetime(6)"); - b.Property("Approved"); + b.Property("Approved") + .HasColumnType("tinyint(1)"); - b.Property("Available"); + b.Property("Available") + .HasColumnType("tinyint(1)"); - b.Property("EpisodeNumber"); + b.Property("EpisodeNumber") + .HasColumnType("int"); - b.Property("Requested"); + b.Property("Requested") + .HasColumnType("tinyint(1)"); - b.Property("SeasonId"); + b.Property("SeasonId") + .HasColumnType("int"); - b.Property("Title"); + b.Property("Title") + .HasColumnType("longtext"); - b.Property("Url"); + b.Property("Url") + .HasColumnType("longtext"); b.HasKey("Id"); @@ -712,11 +945,14 @@ namespace Ombi.Store.Migrations.OmbiMySql modelBuilder.Entity("Ombi.Store.Repository.Requests.SeasonRequests", b => { b.Property("Id") - .ValueGeneratedOnAdd(); + .ValueGeneratedOnAdd() + .HasColumnType("int"); - b.Property("ChildRequestId"); + b.Property("ChildRequestId") + .HasColumnType("int"); - b.Property("SeasonNumber"); + b.Property("SeasonNumber") + .HasColumnType("int"); b.HasKey("Id"); @@ -727,47 +963,60 @@ namespace Ombi.Store.Migrations.OmbiMySql modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole") + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) .WithMany() .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade); + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); }); modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => { - b.HasOne("Ombi.Store.Entities.OmbiUser") + b.HasOne("Ombi.Store.Entities.OmbiUser", null) .WithMany() .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade); + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); }); modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => { - b.HasOne("Ombi.Store.Entities.OmbiUser") + b.HasOne("Ombi.Store.Entities.OmbiUser", null) .WithMany() .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade); + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); }); modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole") + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) .WithMany() .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade); + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); - b.HasOne("Ombi.Store.Entities.OmbiUser") + b.HasOne("Ombi.Store.Entities.OmbiUser", null) .WithMany() .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade); + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); }); modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => { - b.HasOne("Ombi.Store.Entities.OmbiUser") + b.HasOne("Ombi.Store.Entities.OmbiUser", null) .WithMany() .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade); + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Ombi.Store.Entities.MobileDevices", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); }); modelBuilder.Entity("Ombi.Store.Entities.NotificationUserId", b => @@ -796,7 +1045,8 @@ namespace Ombi.Store.Migrations.OmbiMySql b.HasOne("Ombi.Store.Entities.Requests.TvRequests", "ParentRequest") .WithMany("ChildRequests") .HasForeignKey("ParentRequestId") - .OnDelete(DeleteBehavior.Cascade); + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") .WithMany() @@ -819,13 +1069,14 @@ namespace Ombi.Store.Migrations.OmbiMySql b.HasOne("Ombi.Store.Entities.Requests.IssueCategory", "IssueCategory") .WithMany() .HasForeignKey("IssueCategoryId") - .OnDelete(DeleteBehavior.Cascade); + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); - b.HasOne("Ombi.Store.Entities.Requests.ChildRequests") + b.HasOne("Ombi.Store.Entities.Requests.ChildRequests", null) .WithMany("Issues") .HasForeignKey("IssueId"); - b.HasOne("Ombi.Store.Entities.Requests.MovieRequests") + b.HasOne("Ombi.Store.Entities.Requests.MovieRequests", null) .WithMany("Issues") .HasForeignKey("IssueId"); @@ -881,7 +1132,8 @@ namespace Ombi.Store.Migrations.OmbiMySql b.HasOne("Ombi.Store.Repository.Requests.SeasonRequests", "Season") .WithMany("Episodes") .HasForeignKey("SeasonId") - .OnDelete(DeleteBehavior.Cascade); + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); }); modelBuilder.Entity("Ombi.Store.Repository.Requests.SeasonRequests", b => @@ -889,7 +1141,8 @@ namespace Ombi.Store.Migrations.OmbiMySql b.HasOne("Ombi.Store.Entities.Requests.ChildRequests", "ChildRequest") .WithMany("SeasonRequests") .HasForeignKey("ChildRequestId") - .OnDelete(DeleteBehavior.Cascade); + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); }); #pragma warning restore 612, 618 } diff --git a/src/Ombi.Store/Migrations/OmbiSqlite/20200218231003_MobileDevices.Designer.cs b/src/Ombi.Store/Migrations/OmbiSqlite/20200218231003_MobileDevices.Designer.cs new file mode 100644 index 000000000..08d05fe78 --- /dev/null +++ b/src/Ombi.Store/Migrations/OmbiSqlite/20200218231003_MobileDevices.Designer.cs @@ -0,0 +1,1154 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Ombi.Store.Context.Sqlite; + +namespace Ombi.Store.Migrations.OmbiSqlite +{ + [DbContext(typeof(OmbiSqliteContext))] + [Migration("20200218231003_MobileDevices")] + partial class MobileDevices + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "3.1.1"); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("TEXT"); + + b.Property("Name") + .HasColumnType("TEXT") + .HasMaxLength(256); + + b.Property("NormalizedName") + .HasColumnType("TEXT") + .HasMaxLength(256); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasName("RoleNameIndex"); + + b.ToTable("AspNetRoles"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ClaimType") + .HasColumnType("TEXT"); + + b.Property("ClaimValue") + .HasColumnType("TEXT"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ClaimType") + .HasColumnType("TEXT"); + + b.Property("ClaimValue") + .HasColumnType("TEXT"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("TEXT"); + + b.Property("ProviderKey") + .HasColumnType("TEXT"); + + b.Property("ProviderDisplayName") + .HasColumnType("TEXT"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("TEXT"); + + b.Property("RoleId") + .HasColumnType("TEXT"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("TEXT"); + + b.Property("LoginProvider") + .HasColumnType("TEXT"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("Value") + .HasColumnType("TEXT"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Audit", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AuditArea") + .HasColumnType("INTEGER"); + + b.Property("AuditType") + .HasColumnType("INTEGER"); + + b.Property("DateTime") + .HasColumnType("TEXT"); + + b.Property("Description") + .HasColumnType("TEXT"); + + b.Property("User") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("Audit"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.MobileDevices", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AddedAt") + .HasColumnType("TEXT"); + + b.Property("Token") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("MobileDevices"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationTemplates", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Agent") + .HasColumnType("INTEGER"); + + b.Property("Enabled") + .HasColumnType("INTEGER"); + + b.Property("Message") + .HasColumnType("TEXT"); + + b.Property("NotificationType") + .HasColumnType("INTEGER"); + + b.Property("Subject") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("NotificationTemplates"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationUserId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AddedAt") + .HasColumnType("TEXT"); + + b.Property("PlayerId") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("NotificationUserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.OmbiUser", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("AccessFailedCount") + .HasColumnType("INTEGER"); + + b.Property("Alias") + .HasColumnType("TEXT"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("TEXT"); + + b.Property("Email") + .HasColumnType("TEXT") + .HasMaxLength(256); + + b.Property("EmailConfirmed") + .HasColumnType("INTEGER"); + + b.Property("EmbyConnectUserId") + .HasColumnType("TEXT"); + + b.Property("EpisodeRequestLimit") + .HasColumnType("INTEGER"); + + b.Property("LastLoggedIn") + .HasColumnType("TEXT"); + + b.Property("LockoutEnabled") + .HasColumnType("INTEGER"); + + b.Property("LockoutEnd") + .HasColumnType("TEXT"); + + b.Property("MovieRequestLimit") + .HasColumnType("INTEGER"); + + b.Property("MusicRequestLimit") + .HasColumnType("INTEGER"); + + b.Property("NormalizedEmail") + .HasColumnType("TEXT") + .HasMaxLength(256); + + b.Property("NormalizedUserName") + .HasColumnType("TEXT") + .HasMaxLength(256); + + b.Property("PasswordHash") + .HasColumnType("TEXT"); + + b.Property("PhoneNumber") + .HasColumnType("TEXT"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("INTEGER"); + + b.Property("ProviderUserId") + .HasColumnType("TEXT"); + + b.Property("SecurityStamp") + .HasColumnType("TEXT"); + + b.Property("TwoFactorEnabled") + .HasColumnType("INTEGER"); + + b.Property("UserAccessToken") + .HasColumnType("TEXT"); + + b.Property("UserName") + .HasColumnType("TEXT") + .HasMaxLength(256); + + b.Property("UserType") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasName("UserNameIndex"); + + b.ToTable("AspNetUsers"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RecentlyAddedLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AddedAt") + .HasColumnType("TEXT"); + + b.Property("AlbumId") + .HasColumnType("TEXT"); + + b.Property("ContentId") + .HasColumnType("INTEGER"); + + b.Property("ContentType") + .HasColumnType("INTEGER"); + + b.Property("EpisodeNumber") + .HasColumnType("INTEGER"); + + b.Property("SeasonNumber") + .HasColumnType("INTEGER"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("RecentlyAddedLog"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestQueue", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Completed") + .HasColumnType("TEXT"); + + b.Property("Dts") + .HasColumnType("TEXT"); + + b.Property("Error") + .HasColumnType("TEXT"); + + b.Property("RequestId") + .HasColumnType("INTEGER"); + + b.Property("RetryCount") + .HasColumnType("INTEGER"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("RequestQueue"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestSubscription", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("RequestId") + .HasColumnType("INTEGER"); + + b.Property("RequestType") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("RequestSubscription"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.AlbumRequest", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Approved") + .HasColumnType("INTEGER"); + + b.Property("ArtistName") + .HasColumnType("TEXT"); + + b.Property("Available") + .HasColumnType("INTEGER"); + + b.Property("Cover") + .HasColumnType("TEXT"); + + b.Property("Denied") + .HasColumnType("INTEGER"); + + b.Property("DeniedReason") + .HasColumnType("TEXT"); + + b.Property("Disk") + .HasColumnType("TEXT"); + + b.Property("ForeignAlbumId") + .HasColumnType("TEXT"); + + b.Property("ForeignArtistId") + .HasColumnType("TEXT"); + + b.Property("MarkedAsApproved") + .HasColumnType("TEXT"); + + b.Property("MarkedAsAvailable") + .HasColumnType("TEXT"); + + b.Property("MarkedAsDenied") + .HasColumnType("TEXT"); + + b.Property("Rating") + .HasColumnType("TEXT"); + + b.Property("ReleaseDate") + .HasColumnType("TEXT"); + + b.Property("RequestType") + .HasColumnType("INTEGER"); + + b.Property("RequestedByAlias") + .HasColumnType("TEXT"); + + b.Property("RequestedDate") + .HasColumnType("TEXT"); + + b.Property("RequestedUserId") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("AlbumRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.ChildRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Approved") + .HasColumnType("INTEGER"); + + b.Property("Available") + .HasColumnType("INTEGER"); + + b.Property("Denied") + .HasColumnType("INTEGER"); + + b.Property("DeniedReason") + .HasColumnType("TEXT"); + + b.Property("IssueId") + .HasColumnType("INTEGER"); + + b.Property("MarkedAsApproved") + .HasColumnType("TEXT"); + + b.Property("MarkedAsAvailable") + .HasColumnType("TEXT"); + + b.Property("MarkedAsDenied") + .HasColumnType("TEXT"); + + b.Property("ParentRequestId") + .HasColumnType("INTEGER"); + + b.Property("RequestType") + .HasColumnType("INTEGER"); + + b.Property("RequestedByAlias") + .HasColumnType("TEXT"); + + b.Property("RequestedDate") + .HasColumnType("TEXT"); + + b.Property("RequestedUserId") + .HasColumnType("TEXT"); + + b.Property("SeriesType") + .HasColumnType("INTEGER"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("ParentRequestId"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("ChildRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueCategory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Value") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("IssueCategory"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueComments", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Comment") + .HasColumnType("TEXT"); + + b.Property("Date") + .HasColumnType("TEXT"); + + b.Property("IssuesId") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("IssuesId"); + + b.HasIndex("UserId"); + + b.ToTable("IssueComments"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Description") + .HasColumnType("TEXT"); + + b.Property("EpisodeNumber") + .HasColumnType("INTEGER"); + + b.Property("IssueCategoryId") + .HasColumnType("INTEGER"); + + b.Property("IssueId") + .HasColumnType("INTEGER"); + + b.Property("ProviderId") + .HasColumnType("TEXT"); + + b.Property("RequestId") + .HasColumnType("INTEGER"); + + b.Property("RequestType") + .HasColumnType("INTEGER"); + + b.Property("ResovledDate") + .HasColumnType("TEXT"); + + b.Property("SeasonNumber") + .HasColumnType("INTEGER"); + + b.Property("Status") + .HasColumnType("INTEGER"); + + b.Property("Subject") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.Property("UserReportedId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("IssueCategoryId"); + + b.HasIndex("IssueId"); + + b.HasIndex("UserReportedId"); + + b.ToTable("Issues"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.MovieRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Approved") + .HasColumnType("INTEGER"); + + b.Property("Available") + .HasColumnType("INTEGER"); + + b.Property("Background") + .HasColumnType("TEXT"); + + b.Property("Denied") + .HasColumnType("INTEGER"); + + b.Property("DeniedReason") + .HasColumnType("TEXT"); + + b.Property("DigitalReleaseDate") + .HasColumnType("TEXT"); + + b.Property("ImdbId") + .HasColumnType("TEXT"); + + b.Property("IssueId") + .HasColumnType("INTEGER"); + + b.Property("LangCode") + .HasColumnType("TEXT"); + + b.Property("MarkedAsApproved") + .HasColumnType("TEXT"); + + b.Property("MarkedAsAvailable") + .HasColumnType("TEXT"); + + b.Property("MarkedAsDenied") + .HasColumnType("TEXT"); + + b.Property("Overview") + .HasColumnType("TEXT"); + + b.Property("PosterPath") + .HasColumnType("TEXT"); + + b.Property("QualityOverride") + .HasColumnType("INTEGER"); + + b.Property("ReleaseDate") + .HasColumnType("TEXT"); + + b.Property("RequestType") + .HasColumnType("INTEGER"); + + b.Property("RequestedByAlias") + .HasColumnType("TEXT"); + + b.Property("RequestedDate") + .HasColumnType("TEXT"); + + b.Property("RequestedUserId") + .HasColumnType("TEXT"); + + b.Property("RootPathOverride") + .HasColumnType("INTEGER"); + + b.Property("Status") + .HasColumnType("TEXT"); + + b.Property("TheMovieDbId") + .HasColumnType("INTEGER"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("MovieRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.RequestLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("EpisodeCount") + .HasColumnType("INTEGER"); + + b.Property("RequestDate") + .HasColumnType("TEXT"); + + b.Property("RequestId") + .HasColumnType("INTEGER"); + + b.Property("RequestType") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("RequestLog"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.TvRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Background") + .HasColumnType("TEXT"); + + b.Property("ImdbId") + .HasColumnType("TEXT"); + + b.Property("Overview") + .HasColumnType("TEXT"); + + b.Property("PosterPath") + .HasColumnType("TEXT"); + + b.Property("QualityOverride") + .HasColumnType("INTEGER"); + + b.Property("ReleaseDate") + .HasColumnType("TEXT"); + + b.Property("RootFolder") + .HasColumnType("INTEGER"); + + b.Property("Status") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.Property("TotalSeasons") + .HasColumnType("INTEGER"); + + b.Property("TvDbId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("TvRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Tokens", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Token") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Tokens"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserNotificationPreferences", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Agent") + .HasColumnType("INTEGER"); + + b.Property("Enabled") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.Property("Value") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserNotificationPreferences"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserQualityProfiles", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("RadarrQualityProfile") + .HasColumnType("INTEGER"); + + b.Property("RadarrRootPath") + .HasColumnType("INTEGER"); + + b.Property("SonarrQualityProfile") + .HasColumnType("INTEGER"); + + b.Property("SonarrQualityProfileAnime") + .HasColumnType("INTEGER"); + + b.Property("SonarrRootPath") + .HasColumnType("INTEGER"); + + b.Property("SonarrRootPathAnime") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserQualityProfiles"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Votes", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Date") + .HasColumnType("TEXT"); + + b.Property("Deleted") + .HasColumnType("INTEGER"); + + b.Property("RequestId") + .HasColumnType("INTEGER"); + + b.Property("RequestType") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.Property("VoteType") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Votes"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.EpisodeRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AirDate") + .HasColumnType("TEXT"); + + b.Property("Approved") + .HasColumnType("INTEGER"); + + b.Property("Available") + .HasColumnType("INTEGER"); + + b.Property("EpisodeNumber") + .HasColumnType("INTEGER"); + + b.Property("Requested") + .HasColumnType("INTEGER"); + + b.Property("SeasonId") + .HasColumnType("INTEGER"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.Property("Url") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("SeasonId"); + + b.ToTable("EpisodeRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.SeasonRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChildRequestId") + .HasColumnType("INTEGER"); + + b.Property("SeasonNumber") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("ChildRequestId"); + + b.ToTable("SeasonRequests"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Ombi.Store.Entities.OmbiUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Ombi.Store.Entities.MobileDevices", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationUserId", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany("NotificationUserIds") + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestSubscription", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.AlbumRequest", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.ChildRequests", b => + { + b.HasOne("Ombi.Store.Entities.Requests.TvRequests", "ParentRequest") + .WithMany("ChildRequests") + .HasForeignKey("ParentRequestId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueComments", b => + { + b.HasOne("Ombi.Store.Entities.Requests.Issues", "Issues") + .WithMany("Comments") + .HasForeignKey("IssuesId"); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b => + { + b.HasOne("Ombi.Store.Entities.Requests.IssueCategory", "IssueCategory") + .WithMany() + .HasForeignKey("IssueCategoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Ombi.Store.Entities.Requests.ChildRequests", null) + .WithMany("Issues") + .HasForeignKey("IssueId"); + + b.HasOne("Ombi.Store.Entities.Requests.MovieRequests", null) + .WithMany("Issues") + .HasForeignKey("IssueId"); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "UserReported") + .WithMany() + .HasForeignKey("UserReportedId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.MovieRequests", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.RequestLog", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Tokens", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserNotificationPreferences", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany("UserNotificationPreferences") + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserQualityProfiles", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Votes", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.EpisodeRequests", b => + { + b.HasOne("Ombi.Store.Repository.Requests.SeasonRequests", "Season") + .WithMany("Episodes") + .HasForeignKey("SeasonId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.SeasonRequests", b => + { + b.HasOne("Ombi.Store.Entities.Requests.ChildRequests", "ChildRequest") + .WithMany("SeasonRequests") + .HasForeignKey("ChildRequestId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Ombi.Store/Migrations/OmbiSqlite/20200218231003_MobileDevices.cs b/src/Ombi.Store/Migrations/OmbiSqlite/20200218231003_MobileDevices.cs new file mode 100644 index 000000000..fe52c67ac --- /dev/null +++ b/src/Ombi.Store/Migrations/OmbiSqlite/20200218231003_MobileDevices.cs @@ -0,0 +1,198 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +namespace Ombi.Store.Migrations.OmbiSqlite +{ + public partial class MobileDevices : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "EmbyEpisode"); + + migrationBuilder.DropTable( + name: "PlexEpisode"); + + migrationBuilder.DropTable( + name: "PlexSeasonsContent"); + + migrationBuilder.DropTable( + name: "EmbyContent"); + + migrationBuilder.DropTable( + name: "PlexServerContent"); + + + + migrationBuilder.CreateTable( + name: "MobileDevices", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true), + Token = table.Column(nullable: true), + UserId = table.Column(nullable: true), + AddedAt = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_MobileDevices", x => x.Id); + table.ForeignKey( + name: "FK_MobileDevices_AspNetUsers_UserId", + column: x => x.UserId, + principalTable: "AspNetUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + }); + + migrationBuilder.CreateIndex( + name: "IX_MobileDevices_UserId", + table: "MobileDevices", + column: "UserId"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "MobileDevices"); + + + + migrationBuilder.CreateTable( + name: "EmbyContent", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true), + AddedAt = table.Column(nullable: false), + EmbyId = table.Column(nullable: false), + ImdbId = table.Column(nullable: true), + ProviderId = table.Column(nullable: true), + TheMovieDbId = table.Column(nullable: true), + Title = table.Column(nullable: true), + TvDbId = table.Column(nullable: true), + Type = table.Column(nullable: false), + Url = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_EmbyContent", x => x.Id); + table.UniqueConstraint("AK_EmbyContent_EmbyId", x => x.EmbyId); + }); + + migrationBuilder.CreateTable( + name: "PlexServerContent", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true), + AddedAt = table.Column(nullable: false), + ImdbId = table.Column(nullable: true), + Key = table.Column(nullable: false), + Quality = table.Column(nullable: true), + ReleaseYear = table.Column(nullable: true), + RequestId = table.Column(nullable: true), + TheMovieDbId = table.Column(nullable: true), + Title = table.Column(nullable: true), + TvDbId = table.Column(nullable: true), + Type = table.Column(nullable: false), + Url = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_PlexServerContent", x => x.Id); + table.UniqueConstraint("AK_PlexServerContent_Key", x => x.Key); + }); + + migrationBuilder.CreateTable( + name: "EmbyEpisode", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true), + AddedAt = table.Column(nullable: false), + EmbyId = table.Column(nullable: true), + EpisodeNumber = table.Column(nullable: false), + ImdbId = table.Column(nullable: true), + ParentId = table.Column(nullable: true), + ProviderId = table.Column(nullable: true), + SeasonNumber = table.Column(nullable: false), + TheMovieDbId = table.Column(nullable: true), + Title = table.Column(nullable: true), + TvDbId = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_EmbyEpisode", x => x.Id); + table.ForeignKey( + name: "FK_EmbyEpisode_EmbyContent_ParentId", + column: x => x.ParentId, + principalTable: "EmbyContent", + principalColumn: "EmbyId", + onDelete: ReferentialAction.Restrict); + }); + + migrationBuilder.CreateTable( + name: "PlexEpisode", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true), + EpisodeNumber = table.Column(nullable: false), + GrandparentKey = table.Column(nullable: false), + Key = table.Column(nullable: false), + ParentKey = table.Column(nullable: false), + SeasonNumber = table.Column(nullable: false), + Title = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_PlexEpisode", x => x.Id); + table.ForeignKey( + name: "FK_PlexEpisode_PlexServerContent_GrandparentKey", + column: x => x.GrandparentKey, + principalTable: "PlexServerContent", + principalColumn: "Key", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "PlexSeasonsContent", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true), + ParentKey = table.Column(nullable: false), + PlexContentId = table.Column(nullable: false), + PlexServerContentId = table.Column(nullable: true), + SeasonKey = table.Column(nullable: false), + SeasonNumber = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_PlexSeasonsContent", x => x.Id); + table.ForeignKey( + name: "FK_PlexSeasonsContent_PlexServerContent_PlexServerContentId", + column: x => x.PlexServerContentId, + principalTable: "PlexServerContent", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + }); + + migrationBuilder.CreateIndex( + name: "IX_EmbyEpisode_ParentId", + table: "EmbyEpisode", + column: "ParentId"); + + migrationBuilder.CreateIndex( + name: "IX_PlexEpisode_GrandparentKey", + table: "PlexEpisode", + column: "GrandparentKey"); + + migrationBuilder.CreateIndex( + name: "IX_PlexSeasonsContent_PlexServerContentId", + table: "PlexSeasonsContent", + column: "PlexServerContentId"); + } + } +} diff --git a/src/Ombi.Store/Migrations/OmbiSqlite/20200516200222_IssueCreatedDate.Designer.cs b/src/Ombi.Store/Migrations/OmbiSqlite/20200516200222_IssueCreatedDate.Designer.cs new file mode 100644 index 000000000..9da348540 --- /dev/null +++ b/src/Ombi.Store/Migrations/OmbiSqlite/20200516200222_IssueCreatedDate.Designer.cs @@ -0,0 +1,1151 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Ombi.Store.Context.Sqlite; + +namespace Ombi.Store.Migrations.OmbiSqlite +{ + [DbContext(typeof(OmbiSqliteContext))] + [Migration("20200516200222_IssueCreatedDate")] + partial class IssueCreatedDate + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "3.1.1"); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("TEXT"); + + b.Property("Name") + .HasColumnType("TEXT") + .HasMaxLength(256); + + b.Property("NormalizedName") + .HasColumnType("TEXT") + .HasMaxLength(256); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasName("RoleNameIndex"); + + b.ToTable("AspNetRoles"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ClaimType") + .HasColumnType("TEXT"); + + b.Property("ClaimValue") + .HasColumnType("TEXT"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ClaimType") + .HasColumnType("TEXT"); + + b.Property("ClaimValue") + .HasColumnType("TEXT"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("TEXT"); + + b.Property("ProviderKey") + .HasColumnType("TEXT"); + + b.Property("ProviderDisplayName") + .HasColumnType("TEXT"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("TEXT"); + + b.Property("RoleId") + .HasColumnType("TEXT"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("TEXT"); + + b.Property("LoginProvider") + .HasColumnType("TEXT"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("Value") + .HasColumnType("TEXT"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Audit", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AuditArea") + .HasColumnType("INTEGER"); + + b.Property("AuditType") + .HasColumnType("INTEGER"); + + b.Property("DateTime") + .HasColumnType("TEXT"); + + b.Property("Description") + .HasColumnType("TEXT"); + + b.Property("User") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("Audit"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.MobileDevices", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AddedAt") + .HasColumnType("TEXT"); + + b.Property("Token") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("MobileDevices"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationTemplates", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Agent") + .HasColumnType("INTEGER"); + + b.Property("Enabled") + .HasColumnType("INTEGER"); + + b.Property("Message") + .HasColumnType("TEXT"); + + b.Property("NotificationType") + .HasColumnType("INTEGER"); + + b.Property("Subject") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("NotificationTemplates"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationUserId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AddedAt") + .HasColumnType("TEXT"); + + b.Property("PlayerId") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("NotificationUserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.OmbiUser", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("AccessFailedCount") + .HasColumnType("INTEGER"); + + b.Property("Alias") + .HasColumnType("TEXT"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("TEXT"); + + b.Property("Email") + .HasColumnType("TEXT") + .HasMaxLength(256); + + b.Property("EmailConfirmed") + .HasColumnType("INTEGER"); + + b.Property("EmbyConnectUserId") + .HasColumnType("TEXT"); + + b.Property("EpisodeRequestLimit") + .HasColumnType("INTEGER"); + + b.Property("LastLoggedIn") + .HasColumnType("TEXT"); + + b.Property("LockoutEnabled") + .HasColumnType("INTEGER"); + + b.Property("LockoutEnd") + .HasColumnType("TEXT"); + + b.Property("MovieRequestLimit") + .HasColumnType("INTEGER"); + + b.Property("MusicRequestLimit") + .HasColumnType("INTEGER"); + + b.Property("NormalizedEmail") + .HasColumnType("TEXT") + .HasMaxLength(256); + + b.Property("NormalizedUserName") + .HasColumnType("TEXT") + .HasMaxLength(256); + + b.Property("PasswordHash") + .HasColumnType("TEXT"); + + b.Property("PhoneNumber") + .HasColumnType("TEXT"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("INTEGER"); + + b.Property("ProviderUserId") + .HasColumnType("TEXT"); + + b.Property("SecurityStamp") + .HasColumnType("TEXT"); + + b.Property("TwoFactorEnabled") + .HasColumnType("INTEGER"); + + b.Property("UserAccessToken") + .HasColumnType("TEXT"); + + b.Property("UserName") + .HasColumnType("TEXT") + .HasMaxLength(256); + + b.Property("UserType") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasName("UserNameIndex"); + + b.ToTable("AspNetUsers"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RecentlyAddedLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AddedAt") + .HasColumnType("TEXT"); + + b.Property("AlbumId") + .HasColumnType("TEXT"); + + b.Property("ContentId") + .HasColumnType("INTEGER"); + + b.Property("ContentType") + .HasColumnType("INTEGER"); + + b.Property("EpisodeNumber") + .HasColumnType("INTEGER"); + + b.Property("SeasonNumber") + .HasColumnType("INTEGER"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("RecentlyAddedLog"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestQueue", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Completed") + .HasColumnType("TEXT"); + + b.Property("Dts") + .HasColumnType("TEXT"); + + b.Property("Error") + .HasColumnType("TEXT"); + + b.Property("RequestId") + .HasColumnType("INTEGER"); + + b.Property("RetryCount") + .HasColumnType("INTEGER"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("RequestQueue"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestSubscription", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("RequestId") + .HasColumnType("INTEGER"); + + b.Property("RequestType") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("RequestSubscription"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.AlbumRequest", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Approved") + .HasColumnType("INTEGER"); + + b.Property("ArtistName") + .HasColumnType("TEXT"); + + b.Property("Available") + .HasColumnType("INTEGER"); + + b.Property("Cover") + .HasColumnType("TEXT"); + + b.Property("Denied") + .HasColumnType("INTEGER"); + + b.Property("DeniedReason") + .HasColumnType("TEXT"); + + b.Property("Disk") + .HasColumnType("TEXT"); + + b.Property("ForeignAlbumId") + .HasColumnType("TEXT"); + + b.Property("ForeignArtistId") + .HasColumnType("TEXT"); + + b.Property("MarkedAsApproved") + .HasColumnType("TEXT"); + + b.Property("MarkedAsAvailable") + .HasColumnType("TEXT"); + + b.Property("MarkedAsDenied") + .HasColumnType("TEXT"); + + b.Property("Rating") + .HasColumnType("TEXT"); + + b.Property("ReleaseDate") + .HasColumnType("TEXT"); + + b.Property("RequestType") + .HasColumnType("INTEGER"); + + b.Property("RequestedByAlias") + .HasColumnType("TEXT"); + + b.Property("RequestedDate") + .HasColumnType("TEXT"); + + b.Property("RequestedUserId") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("AlbumRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.ChildRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Approved") + .HasColumnType("INTEGER"); + + b.Property("Available") + .HasColumnType("INTEGER"); + + b.Property("Denied") + .HasColumnType("INTEGER"); + + b.Property("DeniedReason") + .HasColumnType("TEXT"); + + b.Property("IssueId") + .HasColumnType("INTEGER"); + + b.Property("MarkedAsApproved") + .HasColumnType("TEXT"); + + b.Property("MarkedAsAvailable") + .HasColumnType("TEXT"); + + b.Property("MarkedAsDenied") + .HasColumnType("TEXT"); + + b.Property("ParentRequestId") + .HasColumnType("INTEGER"); + + b.Property("RequestType") + .HasColumnType("INTEGER"); + + b.Property("RequestedByAlias") + .HasColumnType("TEXT"); + + b.Property("RequestedDate") + .HasColumnType("TEXT"); + + b.Property("RequestedUserId") + .HasColumnType("TEXT"); + + b.Property("SeriesType") + .HasColumnType("INTEGER"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("ParentRequestId"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("ChildRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueCategory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Value") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("IssueCategory"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueComments", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Comment") + .HasColumnType("TEXT"); + + b.Property("Date") + .HasColumnType("TEXT"); + + b.Property("IssuesId") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("IssuesId"); + + b.HasIndex("UserId"); + + b.ToTable("IssueComments"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("CreatedDate") + .HasColumnType("TEXT"); + + b.Property("Description") + .HasColumnType("TEXT"); + + b.Property("IssueCategoryId") + .HasColumnType("INTEGER"); + + b.Property("IssueId") + .HasColumnType("INTEGER"); + + b.Property("ProviderId") + .HasColumnType("TEXT"); + + b.Property("RequestId") + .HasColumnType("INTEGER"); + + b.Property("RequestType") + .HasColumnType("INTEGER"); + + b.Property("ResovledDate") + .HasColumnType("TEXT"); + + b.Property("Status") + .HasColumnType("INTEGER"); + + b.Property("Subject") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.Property("UserReportedId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("IssueCategoryId"); + + b.HasIndex("IssueId"); + + b.HasIndex("UserReportedId"); + + b.ToTable("Issues"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.MovieRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Approved") + .HasColumnType("INTEGER"); + + b.Property("Available") + .HasColumnType("INTEGER"); + + b.Property("Background") + .HasColumnType("TEXT"); + + b.Property("Denied") + .HasColumnType("INTEGER"); + + b.Property("DeniedReason") + .HasColumnType("TEXT"); + + b.Property("DigitalReleaseDate") + .HasColumnType("TEXT"); + + b.Property("ImdbId") + .HasColumnType("TEXT"); + + b.Property("IssueId") + .HasColumnType("INTEGER"); + + b.Property("LangCode") + .HasColumnType("TEXT"); + + b.Property("MarkedAsApproved") + .HasColumnType("TEXT"); + + b.Property("MarkedAsAvailable") + .HasColumnType("TEXT"); + + b.Property("MarkedAsDenied") + .HasColumnType("TEXT"); + + b.Property("Overview") + .HasColumnType("TEXT"); + + b.Property("PosterPath") + .HasColumnType("TEXT"); + + b.Property("QualityOverride") + .HasColumnType("INTEGER"); + + b.Property("ReleaseDate") + .HasColumnType("TEXT"); + + b.Property("RequestType") + .HasColumnType("INTEGER"); + + b.Property("RequestedByAlias") + .HasColumnType("TEXT"); + + b.Property("RequestedDate") + .HasColumnType("TEXT"); + + b.Property("RequestedUserId") + .HasColumnType("TEXT"); + + b.Property("RootPathOverride") + .HasColumnType("INTEGER"); + + b.Property("Status") + .HasColumnType("TEXT"); + + b.Property("TheMovieDbId") + .HasColumnType("INTEGER"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("MovieRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.RequestLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("EpisodeCount") + .HasColumnType("INTEGER"); + + b.Property("RequestDate") + .HasColumnType("TEXT"); + + b.Property("RequestId") + .HasColumnType("INTEGER"); + + b.Property("RequestType") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("RequestLog"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.TvRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Background") + .HasColumnType("TEXT"); + + b.Property("ImdbId") + .HasColumnType("TEXT"); + + b.Property("Overview") + .HasColumnType("TEXT"); + + b.Property("PosterPath") + .HasColumnType("TEXT"); + + b.Property("QualityOverride") + .HasColumnType("INTEGER"); + + b.Property("ReleaseDate") + .HasColumnType("TEXT"); + + b.Property("RootFolder") + .HasColumnType("INTEGER"); + + b.Property("Status") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.Property("TotalSeasons") + .HasColumnType("INTEGER"); + + b.Property("TvDbId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("TvRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Tokens", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Token") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Tokens"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserNotificationPreferences", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Agent") + .HasColumnType("INTEGER"); + + b.Property("Enabled") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.Property("Value") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserNotificationPreferences"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserQualityProfiles", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("RadarrQualityProfile") + .HasColumnType("INTEGER"); + + b.Property("RadarrRootPath") + .HasColumnType("INTEGER"); + + b.Property("SonarrQualityProfile") + .HasColumnType("INTEGER"); + + b.Property("SonarrQualityProfileAnime") + .HasColumnType("INTEGER"); + + b.Property("SonarrRootPath") + .HasColumnType("INTEGER"); + + b.Property("SonarrRootPathAnime") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserQualityProfiles"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Votes", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Date") + .HasColumnType("TEXT"); + + b.Property("Deleted") + .HasColumnType("INTEGER"); + + b.Property("RequestId") + .HasColumnType("INTEGER"); + + b.Property("RequestType") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.Property("VoteType") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Votes"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.EpisodeRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AirDate") + .HasColumnType("TEXT"); + + b.Property("Approved") + .HasColumnType("INTEGER"); + + b.Property("Available") + .HasColumnType("INTEGER"); + + b.Property("EpisodeNumber") + .HasColumnType("INTEGER"); + + b.Property("Requested") + .HasColumnType("INTEGER"); + + b.Property("SeasonId") + .HasColumnType("INTEGER"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.Property("Url") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("SeasonId"); + + b.ToTable("EpisodeRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.SeasonRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChildRequestId") + .HasColumnType("INTEGER"); + + b.Property("SeasonNumber") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("ChildRequestId"); + + b.ToTable("SeasonRequests"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Ombi.Store.Entities.OmbiUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Ombi.Store.Entities.MobileDevices", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationUserId", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany("NotificationUserIds") + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestSubscription", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.AlbumRequest", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.ChildRequests", b => + { + b.HasOne("Ombi.Store.Entities.Requests.TvRequests", "ParentRequest") + .WithMany("ChildRequests") + .HasForeignKey("ParentRequestId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueComments", b => + { + b.HasOne("Ombi.Store.Entities.Requests.Issues", "Issues") + .WithMany("Comments") + .HasForeignKey("IssuesId"); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b => + { + b.HasOne("Ombi.Store.Entities.Requests.IssueCategory", "IssueCategory") + .WithMany() + .HasForeignKey("IssueCategoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Ombi.Store.Entities.Requests.ChildRequests", null) + .WithMany("Issues") + .HasForeignKey("IssueId"); + + b.HasOne("Ombi.Store.Entities.Requests.MovieRequests", null) + .WithMany("Issues") + .HasForeignKey("IssueId"); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "UserReported") + .WithMany() + .HasForeignKey("UserReportedId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.MovieRequests", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.RequestLog", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Tokens", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserNotificationPreferences", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany("UserNotificationPreferences") + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserQualityProfiles", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Votes", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.EpisodeRequests", b => + { + b.HasOne("Ombi.Store.Repository.Requests.SeasonRequests", "Season") + .WithMany("Episodes") + .HasForeignKey("SeasonId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.SeasonRequests", b => + { + b.HasOne("Ombi.Store.Entities.Requests.ChildRequests", "ChildRequest") + .WithMany("SeasonRequests") + .HasForeignKey("ChildRequestId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Ombi.Store/Migrations/OmbiSqlite/20200516200222_IssueCreatedDate.cs b/src/Ombi.Store/Migrations/OmbiSqlite/20200516200222_IssueCreatedDate.cs new file mode 100644 index 000000000..bced7846a --- /dev/null +++ b/src/Ombi.Store/Migrations/OmbiSqlite/20200516200222_IssueCreatedDate.cs @@ -0,0 +1,24 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +namespace Ombi.Store.Migrations.OmbiSqlite +{ + public partial class IssueCreatedDate : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "CreatedDate", + table: "Issues", + nullable: false, + defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified)); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "CreatedDate", + table: "Issues"); + } + } +} diff --git a/src/Ombi.Store/Migrations/OmbiSqlite/20200610223651_UserProfile.Designer.cs b/src/Ombi.Store/Migrations/OmbiSqlite/20200610223651_UserProfile.Designer.cs new file mode 100644 index 000000000..5dc05600d --- /dev/null +++ b/src/Ombi.Store/Migrations/OmbiSqlite/20200610223651_UserProfile.Designer.cs @@ -0,0 +1,1154 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Ombi.Store.Context.Sqlite; + +namespace Ombi.Store.Migrations.OmbiSqlite +{ + [DbContext(typeof(OmbiSqliteContext))] + [Migration("20200610223651_UserProfile")] + partial class UserProfile + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "3.1.1"); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("TEXT"); + + b.Property("Name") + .HasColumnType("TEXT") + .HasMaxLength(256); + + b.Property("NormalizedName") + .HasColumnType("TEXT") + .HasMaxLength(256); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasName("RoleNameIndex"); + + b.ToTable("AspNetRoles"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ClaimType") + .HasColumnType("TEXT"); + + b.Property("ClaimValue") + .HasColumnType("TEXT"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ClaimType") + .HasColumnType("TEXT"); + + b.Property("ClaimValue") + .HasColumnType("TEXT"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("TEXT"); + + b.Property("ProviderKey") + .HasColumnType("TEXT"); + + b.Property("ProviderDisplayName") + .HasColumnType("TEXT"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("TEXT"); + + b.Property("RoleId") + .HasColumnType("TEXT"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("TEXT"); + + b.Property("LoginProvider") + .HasColumnType("TEXT"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("Value") + .HasColumnType("TEXT"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Audit", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AuditArea") + .HasColumnType("INTEGER"); + + b.Property("AuditType") + .HasColumnType("INTEGER"); + + b.Property("DateTime") + .HasColumnType("TEXT"); + + b.Property("Description") + .HasColumnType("TEXT"); + + b.Property("User") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("Audit"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.MobileDevices", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AddedAt") + .HasColumnType("TEXT"); + + b.Property("Token") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("MobileDevices"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationTemplates", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Agent") + .HasColumnType("INTEGER"); + + b.Property("Enabled") + .HasColumnType("INTEGER"); + + b.Property("Message") + .HasColumnType("TEXT"); + + b.Property("NotificationType") + .HasColumnType("INTEGER"); + + b.Property("Subject") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("NotificationTemplates"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationUserId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AddedAt") + .HasColumnType("TEXT"); + + b.Property("PlayerId") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("NotificationUserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.OmbiUser", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("AccessFailedCount") + .HasColumnType("INTEGER"); + + b.Property("Alias") + .HasColumnType("TEXT"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("TEXT"); + + b.Property("Email") + .HasColumnType("TEXT") + .HasMaxLength(256); + + b.Property("EmailConfirmed") + .HasColumnType("INTEGER"); + + b.Property("EmbyConnectUserId") + .HasColumnType("TEXT"); + + b.Property("EpisodeRequestLimit") + .HasColumnType("INTEGER"); + + b.Property("Language") + .HasColumnType("TEXT"); + + b.Property("LastLoggedIn") + .HasColumnType("TEXT"); + + b.Property("LockoutEnabled") + .HasColumnType("INTEGER"); + + b.Property("LockoutEnd") + .HasColumnType("TEXT"); + + b.Property("MovieRequestLimit") + .HasColumnType("INTEGER"); + + b.Property("MusicRequestLimit") + .HasColumnType("INTEGER"); + + b.Property("NormalizedEmail") + .HasColumnType("TEXT") + .HasMaxLength(256); + + b.Property("NormalizedUserName") + .HasColumnType("TEXT") + .HasMaxLength(256); + + b.Property("PasswordHash") + .HasColumnType("TEXT"); + + b.Property("PhoneNumber") + .HasColumnType("TEXT"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("INTEGER"); + + b.Property("ProviderUserId") + .HasColumnType("TEXT"); + + b.Property("SecurityStamp") + .HasColumnType("TEXT"); + + b.Property("TwoFactorEnabled") + .HasColumnType("INTEGER"); + + b.Property("UserAccessToken") + .HasColumnType("TEXT"); + + b.Property("UserName") + .HasColumnType("TEXT") + .HasMaxLength(256); + + b.Property("UserType") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasName("UserNameIndex"); + + b.ToTable("AspNetUsers"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RecentlyAddedLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AddedAt") + .HasColumnType("TEXT"); + + b.Property("AlbumId") + .HasColumnType("TEXT"); + + b.Property("ContentId") + .HasColumnType("INTEGER"); + + b.Property("ContentType") + .HasColumnType("INTEGER"); + + b.Property("EpisodeNumber") + .HasColumnType("INTEGER"); + + b.Property("SeasonNumber") + .HasColumnType("INTEGER"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("RecentlyAddedLog"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestQueue", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Completed") + .HasColumnType("TEXT"); + + b.Property("Dts") + .HasColumnType("TEXT"); + + b.Property("Error") + .HasColumnType("TEXT"); + + b.Property("RequestId") + .HasColumnType("INTEGER"); + + b.Property("RetryCount") + .HasColumnType("INTEGER"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("RequestQueue"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestSubscription", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("RequestId") + .HasColumnType("INTEGER"); + + b.Property("RequestType") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("RequestSubscription"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.AlbumRequest", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Approved") + .HasColumnType("INTEGER"); + + b.Property("ArtistName") + .HasColumnType("TEXT"); + + b.Property("Available") + .HasColumnType("INTEGER"); + + b.Property("Cover") + .HasColumnType("TEXT"); + + b.Property("Denied") + .HasColumnType("INTEGER"); + + b.Property("DeniedReason") + .HasColumnType("TEXT"); + + b.Property("Disk") + .HasColumnType("TEXT"); + + b.Property("ForeignAlbumId") + .HasColumnType("TEXT"); + + b.Property("ForeignArtistId") + .HasColumnType("TEXT"); + + b.Property("MarkedAsApproved") + .HasColumnType("TEXT"); + + b.Property("MarkedAsAvailable") + .HasColumnType("TEXT"); + + b.Property("MarkedAsDenied") + .HasColumnType("TEXT"); + + b.Property("Rating") + .HasColumnType("TEXT"); + + b.Property("ReleaseDate") + .HasColumnType("TEXT"); + + b.Property("RequestType") + .HasColumnType("INTEGER"); + + b.Property("RequestedByAlias") + .HasColumnType("TEXT"); + + b.Property("RequestedDate") + .HasColumnType("TEXT"); + + b.Property("RequestedUserId") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("AlbumRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.ChildRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Approved") + .HasColumnType("INTEGER"); + + b.Property("Available") + .HasColumnType("INTEGER"); + + b.Property("Denied") + .HasColumnType("INTEGER"); + + b.Property("DeniedReason") + .HasColumnType("TEXT"); + + b.Property("IssueId") + .HasColumnType("INTEGER"); + + b.Property("MarkedAsApproved") + .HasColumnType("TEXT"); + + b.Property("MarkedAsAvailable") + .HasColumnType("TEXT"); + + b.Property("MarkedAsDenied") + .HasColumnType("TEXT"); + + b.Property("ParentRequestId") + .HasColumnType("INTEGER"); + + b.Property("RequestType") + .HasColumnType("INTEGER"); + + b.Property("RequestedByAlias") + .HasColumnType("TEXT"); + + b.Property("RequestedDate") + .HasColumnType("TEXT"); + + b.Property("RequestedUserId") + .HasColumnType("TEXT"); + + b.Property("SeriesType") + .HasColumnType("INTEGER"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("ParentRequestId"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("ChildRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueCategory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Value") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("IssueCategory"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueComments", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Comment") + .HasColumnType("TEXT"); + + b.Property("Date") + .HasColumnType("TEXT"); + + b.Property("IssuesId") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("IssuesId"); + + b.HasIndex("UserId"); + + b.ToTable("IssueComments"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("CreatedDate") + .HasColumnType("TEXT"); + + b.Property("Description") + .HasColumnType("TEXT"); + + b.Property("IssueCategoryId") + .HasColumnType("INTEGER"); + + b.Property("IssueId") + .HasColumnType("INTEGER"); + + b.Property("ProviderId") + .HasColumnType("TEXT"); + + b.Property("RequestId") + .HasColumnType("INTEGER"); + + b.Property("RequestType") + .HasColumnType("INTEGER"); + + b.Property("ResovledDate") + .HasColumnType("TEXT"); + + b.Property("Status") + .HasColumnType("INTEGER"); + + b.Property("Subject") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.Property("UserReportedId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("IssueCategoryId"); + + b.HasIndex("IssueId"); + + b.HasIndex("UserReportedId"); + + b.ToTable("Issues"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.MovieRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Approved") + .HasColumnType("INTEGER"); + + b.Property("Available") + .HasColumnType("INTEGER"); + + b.Property("Background") + .HasColumnType("TEXT"); + + b.Property("Denied") + .HasColumnType("INTEGER"); + + b.Property("DeniedReason") + .HasColumnType("TEXT"); + + b.Property("DigitalReleaseDate") + .HasColumnType("TEXT"); + + b.Property("ImdbId") + .HasColumnType("TEXT"); + + b.Property("IssueId") + .HasColumnType("INTEGER"); + + b.Property("LangCode") + .HasColumnType("TEXT"); + + b.Property("MarkedAsApproved") + .HasColumnType("TEXT"); + + b.Property("MarkedAsAvailable") + .HasColumnType("TEXT"); + + b.Property("MarkedAsDenied") + .HasColumnType("TEXT"); + + b.Property("Overview") + .HasColumnType("TEXT"); + + b.Property("PosterPath") + .HasColumnType("TEXT"); + + b.Property("QualityOverride") + .HasColumnType("INTEGER"); + + b.Property("ReleaseDate") + .HasColumnType("TEXT"); + + b.Property("RequestType") + .HasColumnType("INTEGER"); + + b.Property("RequestedByAlias") + .HasColumnType("TEXT"); + + b.Property("RequestedDate") + .HasColumnType("TEXT"); + + b.Property("RequestedUserId") + .HasColumnType("TEXT"); + + b.Property("RootPathOverride") + .HasColumnType("INTEGER"); + + b.Property("Status") + .HasColumnType("TEXT"); + + b.Property("TheMovieDbId") + .HasColumnType("INTEGER"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("MovieRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.RequestLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("EpisodeCount") + .HasColumnType("INTEGER"); + + b.Property("RequestDate") + .HasColumnType("TEXT"); + + b.Property("RequestId") + .HasColumnType("INTEGER"); + + b.Property("RequestType") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("RequestLog"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.TvRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Background") + .HasColumnType("TEXT"); + + b.Property("ImdbId") + .HasColumnType("TEXT"); + + b.Property("Overview") + .HasColumnType("TEXT"); + + b.Property("PosterPath") + .HasColumnType("TEXT"); + + b.Property("QualityOverride") + .HasColumnType("INTEGER"); + + b.Property("ReleaseDate") + .HasColumnType("TEXT"); + + b.Property("RootFolder") + .HasColumnType("INTEGER"); + + b.Property("Status") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.Property("TotalSeasons") + .HasColumnType("INTEGER"); + + b.Property("TvDbId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("TvRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Tokens", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Token") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Tokens"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserNotificationPreferences", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Agent") + .HasColumnType("INTEGER"); + + b.Property("Enabled") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.Property("Value") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserNotificationPreferences"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserQualityProfiles", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("RadarrQualityProfile") + .HasColumnType("INTEGER"); + + b.Property("RadarrRootPath") + .HasColumnType("INTEGER"); + + b.Property("SonarrQualityProfile") + .HasColumnType("INTEGER"); + + b.Property("SonarrQualityProfileAnime") + .HasColumnType("INTEGER"); + + b.Property("SonarrRootPath") + .HasColumnType("INTEGER"); + + b.Property("SonarrRootPathAnime") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserQualityProfiles"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Votes", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Date") + .HasColumnType("TEXT"); + + b.Property("Deleted") + .HasColumnType("INTEGER"); + + b.Property("RequestId") + .HasColumnType("INTEGER"); + + b.Property("RequestType") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.Property("VoteType") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Votes"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.EpisodeRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AirDate") + .HasColumnType("TEXT"); + + b.Property("Approved") + .HasColumnType("INTEGER"); + + b.Property("Available") + .HasColumnType("INTEGER"); + + b.Property("EpisodeNumber") + .HasColumnType("INTEGER"); + + b.Property("Requested") + .HasColumnType("INTEGER"); + + b.Property("SeasonId") + .HasColumnType("INTEGER"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.Property("Url") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("SeasonId"); + + b.ToTable("EpisodeRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.SeasonRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChildRequestId") + .HasColumnType("INTEGER"); + + b.Property("SeasonNumber") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("ChildRequestId"); + + b.ToTable("SeasonRequests"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Ombi.Store.Entities.OmbiUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Ombi.Store.Entities.MobileDevices", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationUserId", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany("NotificationUserIds") + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestSubscription", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.AlbumRequest", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.ChildRequests", b => + { + b.HasOne("Ombi.Store.Entities.Requests.TvRequests", "ParentRequest") + .WithMany("ChildRequests") + .HasForeignKey("ParentRequestId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueComments", b => + { + b.HasOne("Ombi.Store.Entities.Requests.Issues", "Issues") + .WithMany("Comments") + .HasForeignKey("IssuesId"); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b => + { + b.HasOne("Ombi.Store.Entities.Requests.IssueCategory", "IssueCategory") + .WithMany() + .HasForeignKey("IssueCategoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Ombi.Store.Entities.Requests.ChildRequests", null) + .WithMany("Issues") + .HasForeignKey("IssueId"); + + b.HasOne("Ombi.Store.Entities.Requests.MovieRequests", null) + .WithMany("Issues") + .HasForeignKey("IssueId"); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "UserReported") + .WithMany() + .HasForeignKey("UserReportedId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.MovieRequests", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.RequestLog", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Tokens", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserNotificationPreferences", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany("UserNotificationPreferences") + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserQualityProfiles", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Votes", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.EpisodeRequests", b => + { + b.HasOne("Ombi.Store.Repository.Requests.SeasonRequests", "Season") + .WithMany("Episodes") + .HasForeignKey("SeasonId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.SeasonRequests", b => + { + b.HasOne("Ombi.Store.Entities.Requests.ChildRequests", "ChildRequest") + .WithMany("SeasonRequests") + .HasForeignKey("ChildRequestId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Ombi.Store/Migrations/OmbiSqlite/20200610223651_UserProfile.cs b/src/Ombi.Store/Migrations/OmbiSqlite/20200610223651_UserProfile.cs new file mode 100644 index 000000000..3579d21b6 --- /dev/null +++ b/src/Ombi.Store/Migrations/OmbiSqlite/20200610223651_UserProfile.cs @@ -0,0 +1,22 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace Ombi.Store.Migrations.OmbiSqlite +{ + public partial class UserProfile : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "Language", + table: "AspNetUsers", + nullable: true); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "Language", + table: "AspNetUsers"); + } + } +} diff --git a/src/Ombi.Store/Migrations/OmbiSqlite/20200731151356_RemoveEmbyConnectionid.Designer.cs b/src/Ombi.Store/Migrations/OmbiSqlite/20200731151356_RemoveEmbyConnectionid.Designer.cs new file mode 100644 index 000000000..1cedabfe7 --- /dev/null +++ b/src/Ombi.Store/Migrations/OmbiSqlite/20200731151356_RemoveEmbyConnectionid.Designer.cs @@ -0,0 +1,1151 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Ombi.Store.Context.Sqlite; + +namespace Ombi.Store.Migrations.OmbiSqlite +{ + [DbContext(typeof(OmbiSqliteContext))] + [Migration("20200731151356_RemoveEmbyConnectionid")] + partial class RemoveEmbyConnectionid + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "3.1.1"); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("TEXT"); + + b.Property("Name") + .HasColumnType("TEXT") + .HasMaxLength(256); + + b.Property("NormalizedName") + .HasColumnType("TEXT") + .HasMaxLength(256); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasName("RoleNameIndex"); + + b.ToTable("AspNetRoles"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ClaimType") + .HasColumnType("TEXT"); + + b.Property("ClaimValue") + .HasColumnType("TEXT"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ClaimType") + .HasColumnType("TEXT"); + + b.Property("ClaimValue") + .HasColumnType("TEXT"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("TEXT"); + + b.Property("ProviderKey") + .HasColumnType("TEXT"); + + b.Property("ProviderDisplayName") + .HasColumnType("TEXT"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("TEXT"); + + b.Property("RoleId") + .HasColumnType("TEXT"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("TEXT"); + + b.Property("LoginProvider") + .HasColumnType("TEXT"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("Value") + .HasColumnType("TEXT"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Audit", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AuditArea") + .HasColumnType("INTEGER"); + + b.Property("AuditType") + .HasColumnType("INTEGER"); + + b.Property("DateTime") + .HasColumnType("TEXT"); + + b.Property("Description") + .HasColumnType("TEXT"); + + b.Property("User") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("Audit"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.MobileDevices", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AddedAt") + .HasColumnType("TEXT"); + + b.Property("Token") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("MobileDevices"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationTemplates", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Agent") + .HasColumnType("INTEGER"); + + b.Property("Enabled") + .HasColumnType("INTEGER"); + + b.Property("Message") + .HasColumnType("TEXT"); + + b.Property("NotificationType") + .HasColumnType("INTEGER"); + + b.Property("Subject") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("NotificationTemplates"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationUserId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AddedAt") + .HasColumnType("TEXT"); + + b.Property("PlayerId") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("NotificationUserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.OmbiUser", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("AccessFailedCount") + .HasColumnType("INTEGER"); + + b.Property("Alias") + .HasColumnType("TEXT"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("TEXT"); + + b.Property("Email") + .HasColumnType("TEXT") + .HasMaxLength(256); + + b.Property("EmailConfirmed") + .HasColumnType("INTEGER"); + + b.Property("EpisodeRequestLimit") + .HasColumnType("INTEGER"); + + b.Property("Language") + .HasColumnType("TEXT"); + + b.Property("LastLoggedIn") + .HasColumnType("TEXT"); + + b.Property("LockoutEnabled") + .HasColumnType("INTEGER"); + + b.Property("LockoutEnd") + .HasColumnType("TEXT"); + + b.Property("MovieRequestLimit") + .HasColumnType("INTEGER"); + + b.Property("MusicRequestLimit") + .HasColumnType("INTEGER"); + + b.Property("NormalizedEmail") + .HasColumnType("TEXT") + .HasMaxLength(256); + + b.Property("NormalizedUserName") + .HasColumnType("TEXT") + .HasMaxLength(256); + + b.Property("PasswordHash") + .HasColumnType("TEXT"); + + b.Property("PhoneNumber") + .HasColumnType("TEXT"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("INTEGER"); + + b.Property("ProviderUserId") + .HasColumnType("TEXT"); + + b.Property("SecurityStamp") + .HasColumnType("TEXT"); + + b.Property("TwoFactorEnabled") + .HasColumnType("INTEGER"); + + b.Property("UserAccessToken") + .HasColumnType("TEXT"); + + b.Property("UserName") + .HasColumnType("TEXT") + .HasMaxLength(256); + + b.Property("UserType") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasName("UserNameIndex"); + + b.ToTable("AspNetUsers"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RecentlyAddedLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AddedAt") + .HasColumnType("TEXT"); + + b.Property("AlbumId") + .HasColumnType("TEXT"); + + b.Property("ContentId") + .HasColumnType("INTEGER"); + + b.Property("ContentType") + .HasColumnType("INTEGER"); + + b.Property("EpisodeNumber") + .HasColumnType("INTEGER"); + + b.Property("SeasonNumber") + .HasColumnType("INTEGER"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("RecentlyAddedLog"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestQueue", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Completed") + .HasColumnType("TEXT"); + + b.Property("Dts") + .HasColumnType("TEXT"); + + b.Property("Error") + .HasColumnType("TEXT"); + + b.Property("RequestId") + .HasColumnType("INTEGER"); + + b.Property("RetryCount") + .HasColumnType("INTEGER"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("RequestQueue"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestSubscription", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("RequestId") + .HasColumnType("INTEGER"); + + b.Property("RequestType") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("RequestSubscription"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.AlbumRequest", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Approved") + .HasColumnType("INTEGER"); + + b.Property("ArtistName") + .HasColumnType("TEXT"); + + b.Property("Available") + .HasColumnType("INTEGER"); + + b.Property("Cover") + .HasColumnType("TEXT"); + + b.Property("Denied") + .HasColumnType("INTEGER"); + + b.Property("DeniedReason") + .HasColumnType("TEXT"); + + b.Property("Disk") + .HasColumnType("TEXT"); + + b.Property("ForeignAlbumId") + .HasColumnType("TEXT"); + + b.Property("ForeignArtistId") + .HasColumnType("TEXT"); + + b.Property("MarkedAsApproved") + .HasColumnType("TEXT"); + + b.Property("MarkedAsAvailable") + .HasColumnType("TEXT"); + + b.Property("MarkedAsDenied") + .HasColumnType("TEXT"); + + b.Property("Rating") + .HasColumnType("TEXT"); + + b.Property("ReleaseDate") + .HasColumnType("TEXT"); + + b.Property("RequestType") + .HasColumnType("INTEGER"); + + b.Property("RequestedByAlias") + .HasColumnType("TEXT"); + + b.Property("RequestedDate") + .HasColumnType("TEXT"); + + b.Property("RequestedUserId") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("AlbumRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.ChildRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Approved") + .HasColumnType("INTEGER"); + + b.Property("Available") + .HasColumnType("INTEGER"); + + b.Property("Denied") + .HasColumnType("INTEGER"); + + b.Property("DeniedReason") + .HasColumnType("TEXT"); + + b.Property("IssueId") + .HasColumnType("INTEGER"); + + b.Property("MarkedAsApproved") + .HasColumnType("TEXT"); + + b.Property("MarkedAsAvailable") + .HasColumnType("TEXT"); + + b.Property("MarkedAsDenied") + .HasColumnType("TEXT"); + + b.Property("ParentRequestId") + .HasColumnType("INTEGER"); + + b.Property("RequestType") + .HasColumnType("INTEGER"); + + b.Property("RequestedByAlias") + .HasColumnType("TEXT"); + + b.Property("RequestedDate") + .HasColumnType("TEXT"); + + b.Property("RequestedUserId") + .HasColumnType("TEXT"); + + b.Property("SeriesType") + .HasColumnType("INTEGER"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("ParentRequestId"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("ChildRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueCategory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Value") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("IssueCategory"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueComments", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Comment") + .HasColumnType("TEXT"); + + b.Property("Date") + .HasColumnType("TEXT"); + + b.Property("IssuesId") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("IssuesId"); + + b.HasIndex("UserId"); + + b.ToTable("IssueComments"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("CreatedDate") + .HasColumnType("TEXT"); + + b.Property("Description") + .HasColumnType("TEXT"); + + b.Property("IssueCategoryId") + .HasColumnType("INTEGER"); + + b.Property("IssueId") + .HasColumnType("INTEGER"); + + b.Property("ProviderId") + .HasColumnType("TEXT"); + + b.Property("RequestId") + .HasColumnType("INTEGER"); + + b.Property("RequestType") + .HasColumnType("INTEGER"); + + b.Property("ResovledDate") + .HasColumnType("TEXT"); + + b.Property("Status") + .HasColumnType("INTEGER"); + + b.Property("Subject") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.Property("UserReportedId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("IssueCategoryId"); + + b.HasIndex("IssueId"); + + b.HasIndex("UserReportedId"); + + b.ToTable("Issues"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.MovieRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Approved") + .HasColumnType("INTEGER"); + + b.Property("Available") + .HasColumnType("INTEGER"); + + b.Property("Background") + .HasColumnType("TEXT"); + + b.Property("Denied") + .HasColumnType("INTEGER"); + + b.Property("DeniedReason") + .HasColumnType("TEXT"); + + b.Property("DigitalReleaseDate") + .HasColumnType("TEXT"); + + b.Property("ImdbId") + .HasColumnType("TEXT"); + + b.Property("IssueId") + .HasColumnType("INTEGER"); + + b.Property("LangCode") + .HasColumnType("TEXT"); + + b.Property("MarkedAsApproved") + .HasColumnType("TEXT"); + + b.Property("MarkedAsAvailable") + .HasColumnType("TEXT"); + + b.Property("MarkedAsDenied") + .HasColumnType("TEXT"); + + b.Property("Overview") + .HasColumnType("TEXT"); + + b.Property("PosterPath") + .HasColumnType("TEXT"); + + b.Property("QualityOverride") + .HasColumnType("INTEGER"); + + b.Property("ReleaseDate") + .HasColumnType("TEXT"); + + b.Property("RequestType") + .HasColumnType("INTEGER"); + + b.Property("RequestedByAlias") + .HasColumnType("TEXT"); + + b.Property("RequestedDate") + .HasColumnType("TEXT"); + + b.Property("RequestedUserId") + .HasColumnType("TEXT"); + + b.Property("RootPathOverride") + .HasColumnType("INTEGER"); + + b.Property("Status") + .HasColumnType("TEXT"); + + b.Property("TheMovieDbId") + .HasColumnType("INTEGER"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("MovieRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.RequestLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("EpisodeCount") + .HasColumnType("INTEGER"); + + b.Property("RequestDate") + .HasColumnType("TEXT"); + + b.Property("RequestId") + .HasColumnType("INTEGER"); + + b.Property("RequestType") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("RequestLog"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.TvRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Background") + .HasColumnType("TEXT"); + + b.Property("ImdbId") + .HasColumnType("TEXT"); + + b.Property("Overview") + .HasColumnType("TEXT"); + + b.Property("PosterPath") + .HasColumnType("TEXT"); + + b.Property("QualityOverride") + .HasColumnType("INTEGER"); + + b.Property("ReleaseDate") + .HasColumnType("TEXT"); + + b.Property("RootFolder") + .HasColumnType("INTEGER"); + + b.Property("Status") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.Property("TotalSeasons") + .HasColumnType("INTEGER"); + + b.Property("TvDbId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("TvRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Tokens", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Token") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Tokens"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserNotificationPreferences", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Agent") + .HasColumnType("INTEGER"); + + b.Property("Enabled") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.Property("Value") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserNotificationPreferences"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserQualityProfiles", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("RadarrQualityProfile") + .HasColumnType("INTEGER"); + + b.Property("RadarrRootPath") + .HasColumnType("INTEGER"); + + b.Property("SonarrQualityProfile") + .HasColumnType("INTEGER"); + + b.Property("SonarrQualityProfileAnime") + .HasColumnType("INTEGER"); + + b.Property("SonarrRootPath") + .HasColumnType("INTEGER"); + + b.Property("SonarrRootPathAnime") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserQualityProfiles"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Votes", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Date") + .HasColumnType("TEXT"); + + b.Property("Deleted") + .HasColumnType("INTEGER"); + + b.Property("RequestId") + .HasColumnType("INTEGER"); + + b.Property("RequestType") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.Property("VoteType") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Votes"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.EpisodeRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AirDate") + .HasColumnType("TEXT"); + + b.Property("Approved") + .HasColumnType("INTEGER"); + + b.Property("Available") + .HasColumnType("INTEGER"); + + b.Property("EpisodeNumber") + .HasColumnType("INTEGER"); + + b.Property("Requested") + .HasColumnType("INTEGER"); + + b.Property("SeasonId") + .HasColumnType("INTEGER"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.Property("Url") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("SeasonId"); + + b.ToTable("EpisodeRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.SeasonRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChildRequestId") + .HasColumnType("INTEGER"); + + b.Property("SeasonNumber") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("ChildRequestId"); + + b.ToTable("SeasonRequests"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Ombi.Store.Entities.OmbiUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Ombi.Store.Entities.MobileDevices", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationUserId", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany("NotificationUserIds") + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestSubscription", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.AlbumRequest", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.ChildRequests", b => + { + b.HasOne("Ombi.Store.Entities.Requests.TvRequests", "ParentRequest") + .WithMany("ChildRequests") + .HasForeignKey("ParentRequestId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueComments", b => + { + b.HasOne("Ombi.Store.Entities.Requests.Issues", "Issues") + .WithMany("Comments") + .HasForeignKey("IssuesId"); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b => + { + b.HasOne("Ombi.Store.Entities.Requests.IssueCategory", "IssueCategory") + .WithMany() + .HasForeignKey("IssueCategoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Ombi.Store.Entities.Requests.ChildRequests", null) + .WithMany("Issues") + .HasForeignKey("IssueId"); + + b.HasOne("Ombi.Store.Entities.Requests.MovieRequests", null) + .WithMany("Issues") + .HasForeignKey("IssueId"); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "UserReported") + .WithMany() + .HasForeignKey("UserReportedId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.MovieRequests", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.RequestLog", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Tokens", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserNotificationPreferences", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany("UserNotificationPreferences") + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserQualityProfiles", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Votes", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.EpisodeRequests", b => + { + b.HasOne("Ombi.Store.Repository.Requests.SeasonRequests", "Season") + .WithMany("Episodes") + .HasForeignKey("SeasonId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.SeasonRequests", b => + { + b.HasOne("Ombi.Store.Entities.Requests.ChildRequests", "ChildRequest") + .WithMany("SeasonRequests") + .HasForeignKey("ChildRequestId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Ombi.Store/Migrations/OmbiSqlite/20200731151356_RemoveEmbyConnectionid.cs b/src/Ombi.Store/Migrations/OmbiSqlite/20200731151356_RemoveEmbyConnectionid.cs new file mode 100644 index 000000000..0549a9f25 --- /dev/null +++ b/src/Ombi.Store/Migrations/OmbiSqlite/20200731151356_RemoveEmbyConnectionid.cs @@ -0,0 +1,67 @@ +using Microsoft.EntityFrameworkCore.Migrations; +using System; + +namespace Ombi.Store.Migrations.OmbiSqlite +{ + public partial class RemoveEmbyConnectionid : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + //migrationBuilder.DropColumn( + // name: "EmbyConnectUserId", + // table: "AspNetUsers"); + + migrationBuilder.CreateTable( + name: "AspNetUsers_New", + columns: table => new + { + Id = table.Column(nullable: false), + UserName = table.Column(maxLength: 256, nullable: true), + NormalizedUserName = table.Column(maxLength: 256, nullable: true), + Email = table.Column(maxLength: 256, nullable: true), + NormalizedEmail = table.Column(maxLength: 256, nullable: true), + EmailConfirmed = table.Column(nullable: false), + PhoneNumber = table.Column(nullable: true), + PhoneNumberConfirmed = table.Column(nullable: false), + TwoFactorEnabled = table.Column(nullable: false), + LockoutEnd = table.Column(nullable: true), + LockoutEnabled = table.Column(nullable: false), + AccessFailedCount = table.Column(nullable: false), + Alias = table.Column(nullable: true), + UserType = table.Column(nullable: false), + ProviderUserId = table.Column(nullable: true), + LastLoggedIn = table.Column(nullable: true), + MovieRequestLimit = table.Column(nullable: true), + EpisodeRequestLimit = table.Column(nullable: true), + MusicRequestLimit = table.Column(nullable: true), + UserAccessToken = table.Column(nullable: true), + PasswordHash = table.Column(nullable: true), + SecurityStamp = table.Column(nullable: true), + ConcurrencyStamp = table.Column(nullable: true), + Language = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AspNetUsers", x => x.Id); + }); + + migrationBuilder.Sql("UPDATE AspNetUsers SET UserType = 4 WHERE EmbyConnectUserId IS NOT NULL"); + migrationBuilder.Sql(@"INSERT INTO AspNetUsers_New SELECT `Id`,`UserName`,`NormalizedUserName`,`Email`,`NormalizedEmail`,`EmailConfirmed`,`PhoneNumber`, + `PhoneNumberConfirmed`,`TwoFactorEnabled`,`LockoutEnd`,`LockoutEnabled`,`AccessFailedCount`,`Alias`,`UserType`,`ProviderUserId`,`LastLoggedIn`,`MovieRequestLimit`, + `EpisodeRequestLimit`,`MusicRequestLimit`,`UserAccessToken`,`PasswordHash`,`SecurityStamp`,`ConcurrencyStamp`,`Language` FROM AspNetUsers;"); + migrationBuilder.Sql("PRAGMA foreign_keys=\"0\"", true); + migrationBuilder.Sql("DROP TABLE AspNetUsers", true); + migrationBuilder.Sql("ALTER TABLE AspNetUsers_New RENAME TO AspNetUsers", true); + migrationBuilder.Sql("PRAGMA foreign_keys=\"1\"", true); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "EmbyConnectUserId", + table: "AspNetUsers", + type: "TEXT", + nullable: true); + } + } +} diff --git a/src/Ombi.Store/Migrations/OmbiSqlite/OmbiSqliteContextModelSnapshot.cs b/src/Ombi.Store/Migrations/OmbiSqlite/OmbiSqliteContextModelSnapshot.cs index 271c38300..7e9457be4 100644 --- a/src/Ombi.Store/Migrations/OmbiSqlite/OmbiSqliteContextModelSnapshot.cs +++ b/src/Ombi.Store/Migrations/OmbiSqlite/OmbiSqliteContextModelSnapshot.cs @@ -3,7 +3,6 @@ using System; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using Ombi.Store.Context; using Ombi.Store.Context.Sqlite; namespace Ombi.Store.Migrations.OmbiSqlite @@ -15,20 +14,23 @@ namespace Ombi.Store.Migrations.OmbiSqlite { #pragma warning disable 612, 618 modelBuilder - .HasAnnotation("ProductVersion", "2.2.6-servicing-10079"); + .HasAnnotation("ProductVersion", "3.1.1"); modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => { b.Property("Id") - .ValueGeneratedOnAdd(); + .HasColumnType("TEXT"); b.Property("ConcurrencyStamp") - .IsConcurrencyToken(); + .IsConcurrencyToken() + .HasColumnType("TEXT"); b.Property("Name") + .HasColumnType("TEXT") .HasMaxLength(256); b.Property("NormalizedName") + .HasColumnType("TEXT") .HasMaxLength(256); b.HasKey("Id"); @@ -43,14 +45,18 @@ namespace Ombi.Store.Migrations.OmbiSqlite modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => { b.Property("Id") - .ValueGeneratedOnAdd(); + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); - b.Property("ClaimType"); + b.Property("ClaimType") + .HasColumnType("TEXT"); - b.Property("ClaimValue"); + b.Property("ClaimValue") + .HasColumnType("TEXT"); b.Property("RoleId") - .IsRequired(); + .IsRequired() + .HasColumnType("TEXT"); b.HasKey("Id"); @@ -62,14 +68,18 @@ namespace Ombi.Store.Migrations.OmbiSqlite modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => { b.Property("Id") - .ValueGeneratedOnAdd(); + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); - b.Property("ClaimType"); + b.Property("ClaimType") + .HasColumnType("TEXT"); - b.Property("ClaimValue"); + b.Property("ClaimValue") + .HasColumnType("TEXT"); b.Property("UserId") - .IsRequired(); + .IsRequired() + .HasColumnType("TEXT"); b.HasKey("Id"); @@ -80,14 +90,18 @@ namespace Ombi.Store.Migrations.OmbiSqlite modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => { - b.Property("LoginProvider"); + b.Property("LoginProvider") + .HasColumnType("TEXT"); - b.Property("ProviderKey"); + b.Property("ProviderKey") + .HasColumnType("TEXT"); - b.Property("ProviderDisplayName"); + b.Property("ProviderDisplayName") + .HasColumnType("TEXT"); b.Property("UserId") - .IsRequired(); + .IsRequired() + .HasColumnType("TEXT"); b.HasKey("LoginProvider", "ProviderKey"); @@ -98,9 +112,11 @@ namespace Ombi.Store.Migrations.OmbiSqlite modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => { - b.Property("UserId"); + b.Property("UserId") + .HasColumnType("TEXT"); - b.Property("RoleId"); + b.Property("RoleId") + .HasColumnType("TEXT"); b.HasKey("UserId", "RoleId"); @@ -111,13 +127,17 @@ namespace Ombi.Store.Migrations.OmbiSqlite modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => { - b.Property("UserId"); + b.Property("UserId") + .HasColumnType("TEXT"); - b.Property("LoginProvider"); + b.Property("LoginProvider") + .HasColumnType("TEXT"); - b.Property("Name"); + b.Property("Name") + .HasColumnType("TEXT"); - b.Property("Value"); + b.Property("Value") + .HasColumnType("TEXT"); b.HasKey("UserId", "LoginProvider", "Name"); @@ -127,98 +147,71 @@ namespace Ombi.Store.Migrations.OmbiSqlite modelBuilder.Entity("Ombi.Store.Entities.Audit", b => { b.Property("Id") - .ValueGeneratedOnAdd(); + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); - b.Property("AuditArea"); + b.Property("AuditArea") + .HasColumnType("INTEGER"); - b.Property("AuditType"); + b.Property("AuditType") + .HasColumnType("INTEGER"); - b.Property("DateTime"); + b.Property("DateTime") + .HasColumnType("TEXT"); - b.Property("Description"); + b.Property("Description") + .HasColumnType("TEXT"); - b.Property("User"); + b.Property("User") + .HasColumnType("TEXT"); b.HasKey("Id"); b.ToTable("Audit"); }); - modelBuilder.Entity("Ombi.Store.Entities.EmbyContent", b => + modelBuilder.Entity("Ombi.Store.Entities.MobileDevices", b => { b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("AddedAt"); - - b.Property("EmbyId") - .IsRequired(); - - b.Property("ImdbId"); - - b.Property("ProviderId"); - - b.Property("TheMovieDbId"); - - b.Property("Title"); - - b.Property("TvDbId"); - - b.Property("Type"); - - b.Property("Url"); - - b.HasKey("Id"); - - b.ToTable("EmbyContent"); - }); - - modelBuilder.Entity("Ombi.Store.Entities.EmbyEpisode", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("AddedAt"); - - b.Property("EmbyId"); - - b.Property("EpisodeNumber"); + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); - b.Property("ImdbId"); + b.Property("AddedAt") + .HasColumnType("TEXT"); - b.Property("ParentId"); + b.Property("Token") + .HasColumnType("TEXT"); - b.Property("ProviderId"); - - b.Property("SeasonNumber"); - - b.Property("TheMovieDbId"); - - b.Property("Title"); - - b.Property("TvDbId"); + b.Property("UserId") + .HasColumnType("TEXT"); b.HasKey("Id"); - b.HasIndex("ParentId"); + b.HasIndex("UserId"); - b.ToTable("EmbyEpisode"); + b.ToTable("MobileDevices"); }); modelBuilder.Entity("Ombi.Store.Entities.NotificationTemplates", b => { b.Property("Id") - .ValueGeneratedOnAdd(); + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); - b.Property("Agent"); + b.Property("Agent") + .HasColumnType("INTEGER"); - b.Property("Enabled"); + b.Property("Enabled") + .HasColumnType("INTEGER"); - b.Property("Message"); + b.Property("Message") + .HasColumnType("TEXT"); - b.Property("NotificationType"); + b.Property("NotificationType") + .HasColumnType("INTEGER"); - b.Property("Subject"); + b.Property("Subject") + .HasColumnType("TEXT"); b.HasKey("Id"); @@ -228,13 +221,17 @@ namespace Ombi.Store.Migrations.OmbiSqlite modelBuilder.Entity("Ombi.Store.Entities.NotificationUserId", b => { b.Property("Id") - .ValueGeneratedOnAdd(); + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); - b.Property("AddedAt"); + b.Property("AddedAt") + .HasColumnType("TEXT"); - b.Property("PlayerId"); + b.Property("PlayerId") + .HasColumnType("TEXT"); - b.Property("UserId"); + b.Property("UserId") + .HasColumnType("TEXT"); b.HasKey("Id"); @@ -246,58 +243,81 @@ namespace Ombi.Store.Migrations.OmbiSqlite modelBuilder.Entity("Ombi.Store.Entities.OmbiUser", b => { b.Property("Id") - .ValueGeneratedOnAdd(); + .HasColumnType("TEXT"); - b.Property("AccessFailedCount"); + b.Property("AccessFailedCount") + .HasColumnType("INTEGER"); - b.Property("Alias"); + b.Property("Alias") + .HasColumnType("TEXT"); b.Property("ConcurrencyStamp") - .IsConcurrencyToken(); + .IsConcurrencyToken() + .HasColumnType("TEXT"); b.Property("Email") + .HasColumnType("TEXT") .HasMaxLength(256); - b.Property("EmailConfirmed"); + b.Property("EmailConfirmed") + .HasColumnType("INTEGER"); - b.Property("EmbyConnectUserId"); + b.Property("EpisodeRequestLimit") + .HasColumnType("INTEGER"); - b.Property("EpisodeRequestLimit"); + b.Property("Language") + .HasColumnType("TEXT"); - b.Property("LastLoggedIn"); + b.Property("LastLoggedIn") + .HasColumnType("TEXT"); - b.Property("LockoutEnabled"); + b.Property("LockoutEnabled") + .HasColumnType("INTEGER"); - b.Property("LockoutEnd"); + b.Property("LockoutEnd") + .HasColumnType("TEXT"); - b.Property("MovieRequestLimit"); + b.Property("MovieRequestLimit") + .HasColumnType("INTEGER"); - b.Property("MusicRequestLimit"); + b.Property("MusicRequestLimit") + .HasColumnType("INTEGER"); b.Property("NormalizedEmail") + .HasColumnType("TEXT") .HasMaxLength(256); b.Property("NormalizedUserName") + .HasColumnType("TEXT") .HasMaxLength(256); - b.Property("PasswordHash"); + b.Property("PasswordHash") + .HasColumnType("TEXT"); - b.Property("PhoneNumber"); + b.Property("PhoneNumber") + .HasColumnType("TEXT"); - b.Property("PhoneNumberConfirmed"); + b.Property("PhoneNumberConfirmed") + .HasColumnType("INTEGER"); - b.Property("ProviderUserId"); + b.Property("ProviderUserId") + .HasColumnType("TEXT"); - b.Property("SecurityStamp"); + b.Property("SecurityStamp") + .HasColumnType("TEXT"); - b.Property("TwoFactorEnabled"); + b.Property("TwoFactorEnabled") + .HasColumnType("INTEGER"); - b.Property("UserAccessToken"); + b.Property("UserAccessToken") + .HasColumnType("TEXT"); b.Property("UserName") + .HasColumnType("TEXT") .HasMaxLength(256); - b.Property("UserType"); + b.Property("UserType") + .HasColumnType("INTEGER"); b.HasKey("Id"); @@ -311,102 +331,32 @@ namespace Ombi.Store.Migrations.OmbiSqlite b.ToTable("AspNetUsers"); }); - modelBuilder.Entity("Ombi.Store.Entities.PlexEpisode", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("EpisodeNumber"); - - b.Property("GrandparentKey"); - - b.Property("Key"); - - b.Property("ParentKey"); - - b.Property("SeasonNumber"); - - b.Property("Title"); - - b.HasKey("Id"); - - b.HasIndex("GrandparentKey"); - - b.ToTable("PlexEpisode"); - }); - - modelBuilder.Entity("Ombi.Store.Entities.PlexSeasonsContent", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("ParentKey"); - - b.Property("PlexContentId"); - - b.Property("PlexServerContentId"); - - b.Property("SeasonKey"); - - b.Property("SeasonNumber"); - - b.HasKey("Id"); - - b.HasIndex("PlexServerContentId"); - - b.ToTable("PlexSeasonsContent"); - }); - - modelBuilder.Entity("Ombi.Store.Entities.PlexServerContent", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("AddedAt"); - - b.Property("ImdbId"); - - b.Property("Key"); - - b.Property("Quality"); - - b.Property("ReleaseYear"); - - b.Property("RequestId"); - - b.Property("TheMovieDbId"); - - b.Property("Title"); - - b.Property("TvDbId"); - - b.Property("Type"); - - b.Property("Url"); - - b.HasKey("Id"); - - b.ToTable("PlexServerContent"); - }); - modelBuilder.Entity("Ombi.Store.Entities.RecentlyAddedLog", b => { b.Property("Id") - .ValueGeneratedOnAdd(); + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); - b.Property("AddedAt"); + b.Property("AddedAt") + .HasColumnType("TEXT"); - b.Property("AlbumId"); + b.Property("AlbumId") + .HasColumnType("TEXT"); - b.Property("ContentId"); + b.Property("ContentId") + .HasColumnType("INTEGER"); - b.Property("ContentType"); + b.Property("ContentType") + .HasColumnType("INTEGER"); - b.Property("EpisodeNumber"); + b.Property("EpisodeNumber") + .HasColumnType("INTEGER"); - b.Property("SeasonNumber"); + b.Property("SeasonNumber") + .HasColumnType("INTEGER"); - b.Property("Type"); + b.Property("Type") + .HasColumnType("INTEGER"); b.HasKey("Id"); @@ -416,19 +366,26 @@ namespace Ombi.Store.Migrations.OmbiSqlite modelBuilder.Entity("Ombi.Store.Entities.RequestQueue", b => { b.Property("Id") - .ValueGeneratedOnAdd(); + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); - b.Property("Completed"); + b.Property("Completed") + .HasColumnType("TEXT"); - b.Property("Dts"); + b.Property("Dts") + .HasColumnType("TEXT"); - b.Property("Error"); + b.Property("Error") + .HasColumnType("TEXT"); - b.Property("RequestId"); + b.Property("RequestId") + .HasColumnType("INTEGER"); - b.Property("RetryCount"); + b.Property("RetryCount") + .HasColumnType("INTEGER"); - b.Property("Type"); + b.Property("Type") + .HasColumnType("INTEGER"); b.HasKey("Id"); @@ -438,13 +395,17 @@ namespace Ombi.Store.Migrations.OmbiSqlite modelBuilder.Entity("Ombi.Store.Entities.RequestSubscription", b => { b.Property("Id") - .ValueGeneratedOnAdd(); + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); - b.Property("RequestId"); + b.Property("RequestId") + .HasColumnType("INTEGER"); - b.Property("RequestType"); + b.Property("RequestType") + .HasColumnType("INTEGER"); - b.Property("UserId"); + b.Property("UserId") + .HasColumnType("TEXT"); b.HasKey("Id"); @@ -456,45 +417,65 @@ namespace Ombi.Store.Migrations.OmbiSqlite modelBuilder.Entity("Ombi.Store.Entities.Requests.AlbumRequest", b => { b.Property("Id") - .ValueGeneratedOnAdd(); + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); - b.Property("Approved"); + b.Property("Approved") + .HasColumnType("INTEGER"); - b.Property("ArtistName"); + b.Property("ArtistName") + .HasColumnType("TEXT"); - b.Property("Available"); + b.Property("Available") + .HasColumnType("INTEGER"); - b.Property("Cover"); + b.Property("Cover") + .HasColumnType("TEXT"); - b.Property("Denied"); + b.Property("Denied") + .HasColumnType("INTEGER"); - b.Property("DeniedReason"); + b.Property("DeniedReason") + .HasColumnType("TEXT"); - b.Property("Disk"); + b.Property("Disk") + .HasColumnType("TEXT"); - b.Property("ForeignAlbumId"); + b.Property("ForeignAlbumId") + .HasColumnType("TEXT"); - b.Property("ForeignArtistId"); + b.Property("ForeignArtistId") + .HasColumnType("TEXT"); - b.Property("MarkedAsApproved"); + b.Property("MarkedAsApproved") + .HasColumnType("TEXT"); - b.Property("MarkedAsAvailable"); + b.Property("MarkedAsAvailable") + .HasColumnType("TEXT"); - b.Property("MarkedAsDenied"); + b.Property("MarkedAsDenied") + .HasColumnType("TEXT"); - b.Property("Rating"); + b.Property("Rating") + .HasColumnType("TEXT"); - b.Property("ReleaseDate"); + b.Property("ReleaseDate") + .HasColumnType("TEXT"); - b.Property("RequestType"); + b.Property("RequestType") + .HasColumnType("INTEGER"); - b.Property("RequestedByAlias"); + b.Property("RequestedByAlias") + .HasColumnType("TEXT"); - b.Property("RequestedDate"); + b.Property("RequestedDate") + .HasColumnType("TEXT"); - b.Property("RequestedUserId"); + b.Property("RequestedUserId") + .HasColumnType("TEXT"); - b.Property("Title"); + b.Property("Title") + .HasColumnType("TEXT"); b.HasKey("Id"); @@ -506,37 +487,53 @@ namespace Ombi.Store.Migrations.OmbiSqlite modelBuilder.Entity("Ombi.Store.Entities.Requests.ChildRequests", b => { b.Property("Id") - .ValueGeneratedOnAdd(); + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); - b.Property("Approved"); + b.Property("Approved") + .HasColumnType("INTEGER"); - b.Property("Available"); + b.Property("Available") + .HasColumnType("INTEGER"); - b.Property("Denied"); + b.Property("Denied") + .HasColumnType("INTEGER"); - b.Property("DeniedReason"); + b.Property("DeniedReason") + .HasColumnType("TEXT"); - b.Property("IssueId"); + b.Property("IssueId") + .HasColumnType("INTEGER"); - b.Property("MarkedAsApproved"); + b.Property("MarkedAsApproved") + .HasColumnType("TEXT"); - b.Property("MarkedAsAvailable"); + b.Property("MarkedAsAvailable") + .HasColumnType("TEXT"); - b.Property("MarkedAsDenied"); + b.Property("MarkedAsDenied") + .HasColumnType("TEXT"); - b.Property("ParentRequestId"); + b.Property("ParentRequestId") + .HasColumnType("INTEGER"); - b.Property("RequestType"); + b.Property("RequestType") + .HasColumnType("INTEGER"); - b.Property("RequestedByAlias"); + b.Property("RequestedByAlias") + .HasColumnType("TEXT"); - b.Property("RequestedDate"); + b.Property("RequestedDate") + .HasColumnType("TEXT"); - b.Property("RequestedUserId"); + b.Property("RequestedUserId") + .HasColumnType("TEXT"); - b.Property("SeriesType"); + b.Property("SeriesType") + .HasColumnType("INTEGER"); - b.Property("Title"); + b.Property("Title") + .HasColumnType("TEXT"); b.HasKey("Id"); @@ -550,9 +547,11 @@ namespace Ombi.Store.Migrations.OmbiSqlite modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueCategory", b => { b.Property("Id") - .ValueGeneratedOnAdd(); + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); - b.Property("Value"); + b.Property("Value") + .HasColumnType("TEXT"); b.HasKey("Id"); @@ -562,15 +561,20 @@ namespace Ombi.Store.Migrations.OmbiSqlite modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueComments", b => { b.Property("Id") - .ValueGeneratedOnAdd(); + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); - b.Property("Comment"); + b.Property("Comment") + .HasColumnType("TEXT"); - b.Property("Date"); + b.Property("Date") + .HasColumnType("TEXT"); - b.Property("IssuesId"); + b.Property("IssuesId") + .HasColumnType("INTEGER"); - b.Property("UserId"); + b.Property("UserId") + .HasColumnType("TEXT"); b.HasKey("Id"); @@ -584,29 +588,44 @@ namespace Ombi.Store.Migrations.OmbiSqlite modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b => { b.Property("Id") - .ValueGeneratedOnAdd(); + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); - b.Property("Description"); + b.Property("CreatedDate") + .HasColumnType("TEXT"); - b.Property("IssueCategoryId"); + b.Property("Description") + .HasColumnType("TEXT"); - b.Property("IssueId"); + b.Property("IssueCategoryId") + .HasColumnType("INTEGER"); - b.Property("ProviderId"); + b.Property("IssueId") + .HasColumnType("INTEGER"); - b.Property("RequestId"); + b.Property("ProviderId") + .HasColumnType("TEXT"); - b.Property("RequestType"); + b.Property("RequestId") + .HasColumnType("INTEGER"); - b.Property("ResovledDate"); + b.Property("RequestType") + .HasColumnType("INTEGER"); - b.Property("Status"); + b.Property("ResovledDate") + .HasColumnType("TEXT"); - b.Property("Subject"); + b.Property("Status") + .HasColumnType("INTEGER"); - b.Property("Title"); + b.Property("Subject") + .HasColumnType("TEXT"); - b.Property("UserReportedId"); + b.Property("Title") + .HasColumnType("TEXT"); + + b.Property("UserReportedId") + .HasColumnType("TEXT"); b.HasKey("Id"); @@ -622,55 +641,80 @@ namespace Ombi.Store.Migrations.OmbiSqlite modelBuilder.Entity("Ombi.Store.Entities.Requests.MovieRequests", b => { b.Property("Id") - .ValueGeneratedOnAdd(); + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); - b.Property("Approved"); + b.Property("Approved") + .HasColumnType("INTEGER"); - b.Property("Available"); + b.Property("Available") + .HasColumnType("INTEGER"); - b.Property("Background"); + b.Property("Background") + .HasColumnType("TEXT"); - b.Property("Denied"); + b.Property("Denied") + .HasColumnType("INTEGER"); - b.Property("DeniedReason"); + b.Property("DeniedReason") + .HasColumnType("TEXT"); - b.Property("DigitalReleaseDate"); + b.Property("DigitalReleaseDate") + .HasColumnType("TEXT"); - b.Property("ImdbId"); + b.Property("ImdbId") + .HasColumnType("TEXT"); - b.Property("IssueId"); + b.Property("IssueId") + .HasColumnType("INTEGER"); - b.Property("LangCode"); + b.Property("LangCode") + .HasColumnType("TEXT"); - b.Property("MarkedAsApproved"); + b.Property("MarkedAsApproved") + .HasColumnType("TEXT"); - b.Property("MarkedAsAvailable"); + b.Property("MarkedAsAvailable") + .HasColumnType("TEXT"); - b.Property("MarkedAsDenied"); + b.Property("MarkedAsDenied") + .HasColumnType("TEXT"); - b.Property("Overview"); + b.Property("Overview") + .HasColumnType("TEXT"); - b.Property("PosterPath"); + b.Property("PosterPath") + .HasColumnType("TEXT"); - b.Property("QualityOverride"); + b.Property("QualityOverride") + .HasColumnType("INTEGER"); - b.Property("ReleaseDate"); + b.Property("ReleaseDate") + .HasColumnType("TEXT"); - b.Property("RequestType"); + b.Property("RequestType") + .HasColumnType("INTEGER"); - b.Property("RequestedByAlias"); + b.Property("RequestedByAlias") + .HasColumnType("TEXT"); - b.Property("RequestedDate"); + b.Property("RequestedDate") + .HasColumnType("TEXT"); - b.Property("RequestedUserId"); + b.Property("RequestedUserId") + .HasColumnType("TEXT"); - b.Property("RootPathOverride"); + b.Property("RootPathOverride") + .HasColumnType("INTEGER"); - b.Property("Status"); + b.Property("Status") + .HasColumnType("TEXT"); - b.Property("TheMovieDbId"); + b.Property("TheMovieDbId") + .HasColumnType("INTEGER"); - b.Property("Title"); + b.Property("Title") + .HasColumnType("TEXT"); b.HasKey("Id"); @@ -682,17 +726,23 @@ namespace Ombi.Store.Migrations.OmbiSqlite modelBuilder.Entity("Ombi.Store.Entities.Requests.RequestLog", b => { b.Property("Id") - .ValueGeneratedOnAdd(); + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); - b.Property("EpisodeCount"); + b.Property("EpisodeCount") + .HasColumnType("INTEGER"); - b.Property("RequestDate"); + b.Property("RequestDate") + .HasColumnType("TEXT"); - b.Property("RequestId"); + b.Property("RequestId") + .HasColumnType("INTEGER"); - b.Property("RequestType"); + b.Property("RequestType") + .HasColumnType("INTEGER"); - b.Property("UserId"); + b.Property("UserId") + .HasColumnType("TEXT"); b.HasKey("Id"); @@ -704,29 +754,41 @@ namespace Ombi.Store.Migrations.OmbiSqlite modelBuilder.Entity("Ombi.Store.Entities.Requests.TvRequests", b => { b.Property("Id") - .ValueGeneratedOnAdd(); + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); - b.Property("Background"); + b.Property("Background") + .HasColumnType("TEXT"); - b.Property("ImdbId"); + b.Property("ImdbId") + .HasColumnType("TEXT"); - b.Property("Overview"); + b.Property("Overview") + .HasColumnType("TEXT"); - b.Property("PosterPath"); + b.Property("PosterPath") + .HasColumnType("TEXT"); - b.Property("QualityOverride"); + b.Property("QualityOverride") + .HasColumnType("INTEGER"); - b.Property("ReleaseDate"); + b.Property("ReleaseDate") + .HasColumnType("TEXT"); - b.Property("RootFolder"); + b.Property("RootFolder") + .HasColumnType("INTEGER"); - b.Property("Status"); + b.Property("Status") + .HasColumnType("TEXT"); - b.Property("Title"); + b.Property("Title") + .HasColumnType("TEXT"); - b.Property("TotalSeasons"); + b.Property("TotalSeasons") + .HasColumnType("INTEGER"); - b.Property("TvDbId"); + b.Property("TvDbId") + .HasColumnType("INTEGER"); b.HasKey("Id"); @@ -736,11 +798,14 @@ namespace Ombi.Store.Migrations.OmbiSqlite modelBuilder.Entity("Ombi.Store.Entities.Tokens", b => { b.Property("Id") - .ValueGeneratedOnAdd(); + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); - b.Property("Token"); + b.Property("Token") + .HasColumnType("TEXT"); - b.Property("UserId"); + b.Property("UserId") + .HasColumnType("TEXT"); b.HasKey("Id"); @@ -752,15 +817,20 @@ namespace Ombi.Store.Migrations.OmbiSqlite modelBuilder.Entity("Ombi.Store.Entities.UserNotificationPreferences", b => { b.Property("Id") - .ValueGeneratedOnAdd(); + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); - b.Property("Agent"); + b.Property("Agent") + .HasColumnType("INTEGER"); - b.Property("Enabled"); + b.Property("Enabled") + .HasColumnType("INTEGER"); - b.Property("UserId"); + b.Property("UserId") + .HasColumnType("TEXT"); - b.Property("Value"); + b.Property("Value") + .HasColumnType("TEXT"); b.HasKey("Id"); @@ -772,21 +842,29 @@ namespace Ombi.Store.Migrations.OmbiSqlite modelBuilder.Entity("Ombi.Store.Entities.UserQualityProfiles", b => { b.Property("Id") - .ValueGeneratedOnAdd(); + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); - b.Property("RadarrQualityProfile"); + b.Property("RadarrQualityProfile") + .HasColumnType("INTEGER"); - b.Property("RadarrRootPath"); + b.Property("RadarrRootPath") + .HasColumnType("INTEGER"); - b.Property("SonarrQualityProfile"); + b.Property("SonarrQualityProfile") + .HasColumnType("INTEGER"); - b.Property("SonarrQualityProfileAnime"); + b.Property("SonarrQualityProfileAnime") + .HasColumnType("INTEGER"); - b.Property("SonarrRootPath"); + b.Property("SonarrRootPath") + .HasColumnType("INTEGER"); - b.Property("SonarrRootPathAnime"); + b.Property("SonarrRootPathAnime") + .HasColumnType("INTEGER"); - b.Property("UserId"); + b.Property("UserId") + .HasColumnType("TEXT"); b.HasKey("Id"); @@ -798,19 +876,26 @@ namespace Ombi.Store.Migrations.OmbiSqlite modelBuilder.Entity("Ombi.Store.Entities.Votes", b => { b.Property("Id") - .ValueGeneratedOnAdd(); + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); - b.Property("Date"); + b.Property("Date") + .HasColumnType("TEXT"); - b.Property("Deleted"); + b.Property("Deleted") + .HasColumnType("INTEGER"); - b.Property("RequestId"); + b.Property("RequestId") + .HasColumnType("INTEGER"); - b.Property("RequestType"); + b.Property("RequestType") + .HasColumnType("INTEGER"); - b.Property("UserId"); + b.Property("UserId") + .HasColumnType("TEXT"); - b.Property("VoteType"); + b.Property("VoteType") + .HasColumnType("INTEGER"); b.HasKey("Id"); @@ -822,23 +907,32 @@ namespace Ombi.Store.Migrations.OmbiSqlite modelBuilder.Entity("Ombi.Store.Repository.Requests.EpisodeRequests", b => { b.Property("Id") - .ValueGeneratedOnAdd(); + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); - b.Property("AirDate"); + b.Property("AirDate") + .HasColumnType("TEXT"); - b.Property("Approved"); + b.Property("Approved") + .HasColumnType("INTEGER"); - b.Property("Available"); + b.Property("Available") + .HasColumnType("INTEGER"); - b.Property("EpisodeNumber"); + b.Property("EpisodeNumber") + .HasColumnType("INTEGER"); - b.Property("Requested"); + b.Property("Requested") + .HasColumnType("INTEGER"); - b.Property("SeasonId"); + b.Property("SeasonId") + .HasColumnType("INTEGER"); - b.Property("Title"); + b.Property("Title") + .HasColumnType("TEXT"); - b.Property("Url"); + b.Property("Url") + .HasColumnType("TEXT"); b.HasKey("Id"); @@ -850,11 +944,14 @@ namespace Ombi.Store.Migrations.OmbiSqlite modelBuilder.Entity("Ombi.Store.Repository.Requests.SeasonRequests", b => { b.Property("Id") - .ValueGeneratedOnAdd(); + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); - b.Property("ChildRequestId"); + b.Property("ChildRequestId") + .HasColumnType("INTEGER"); - b.Property("SeasonNumber"); + b.Property("SeasonNumber") + .HasColumnType("INTEGER"); b.HasKey("Id"); @@ -865,55 +962,60 @@ namespace Ombi.Store.Migrations.OmbiSqlite modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole") + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) .WithMany() .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade); + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); }); modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => { - b.HasOne("Ombi.Store.Entities.OmbiUser") + b.HasOne("Ombi.Store.Entities.OmbiUser", null) .WithMany() .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade); + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); }); modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => { - b.HasOne("Ombi.Store.Entities.OmbiUser") + b.HasOne("Ombi.Store.Entities.OmbiUser", null) .WithMany() .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade); + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); }); modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole") + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) .WithMany() .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade); + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); - b.HasOne("Ombi.Store.Entities.OmbiUser") + b.HasOne("Ombi.Store.Entities.OmbiUser", null) .WithMany() .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade); + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); }); modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => { - b.HasOne("Ombi.Store.Entities.OmbiUser") + b.HasOne("Ombi.Store.Entities.OmbiUser", null) .WithMany() .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade); + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); }); - modelBuilder.Entity("Ombi.Store.Entities.EmbyEpisode", b => + modelBuilder.Entity("Ombi.Store.Entities.MobileDevices", b => { - b.HasOne("Ombi.Store.Entities.EmbyContent", "Series") - .WithMany("Episodes") - .HasForeignKey("ParentId") - .HasPrincipalKey("EmbyId"); + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); }); modelBuilder.Entity("Ombi.Store.Entities.NotificationUserId", b => @@ -923,22 +1025,6 @@ namespace Ombi.Store.Migrations.OmbiSqlite .HasForeignKey("UserId"); }); - modelBuilder.Entity("Ombi.Store.Entities.PlexEpisode", b => - { - b.HasOne("Ombi.Store.Entities.PlexServerContent", "Series") - .WithMany("Episodes") - .HasForeignKey("GrandparentKey") - .HasPrincipalKey("Key") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Ombi.Store.Entities.PlexSeasonsContent", b => - { - b.HasOne("Ombi.Store.Entities.PlexServerContent") - .WithMany("Seasons") - .HasForeignKey("PlexServerContentId"); - }); - modelBuilder.Entity("Ombi.Store.Entities.RequestSubscription", b => { b.HasOne("Ombi.Store.Entities.OmbiUser", "User") @@ -958,7 +1044,8 @@ namespace Ombi.Store.Migrations.OmbiSqlite b.HasOne("Ombi.Store.Entities.Requests.TvRequests", "ParentRequest") .WithMany("ChildRequests") .HasForeignKey("ParentRequestId") - .OnDelete(DeleteBehavior.Cascade); + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") .WithMany() @@ -981,13 +1068,14 @@ namespace Ombi.Store.Migrations.OmbiSqlite b.HasOne("Ombi.Store.Entities.Requests.IssueCategory", "IssueCategory") .WithMany() .HasForeignKey("IssueCategoryId") - .OnDelete(DeleteBehavior.Cascade); + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); - b.HasOne("Ombi.Store.Entities.Requests.ChildRequests") + b.HasOne("Ombi.Store.Entities.Requests.ChildRequests", null) .WithMany("Issues") .HasForeignKey("IssueId"); - b.HasOne("Ombi.Store.Entities.Requests.MovieRequests") + b.HasOne("Ombi.Store.Entities.Requests.MovieRequests", null) .WithMany("Issues") .HasForeignKey("IssueId"); @@ -1043,7 +1131,8 @@ namespace Ombi.Store.Migrations.OmbiSqlite b.HasOne("Ombi.Store.Repository.Requests.SeasonRequests", "Season") .WithMany("Episodes") .HasForeignKey("SeasonId") - .OnDelete(DeleteBehavior.Cascade); + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); }); modelBuilder.Entity("Ombi.Store.Repository.Requests.SeasonRequests", b => @@ -1051,7 +1140,8 @@ namespace Ombi.Store.Migrations.OmbiSqlite b.HasOne("Ombi.Store.Entities.Requests.ChildRequests", "ChildRequest") .WithMany("SeasonRequests") .HasForeignKey("ChildRequestId") - .OnDelete(DeleteBehavior.Cascade); + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); }); #pragma warning restore 612, 618 } diff --git a/src/Ombi.Store/Ombi.Store.csproj b/src/Ombi.Store/Ombi.Store.csproj index b33052157..78fa5b8c6 100644 --- a/src/Ombi.Store/Ombi.Store.csproj +++ b/src/Ombi.Store/Ombi.Store.csproj @@ -1,22 +1,25 @@  - netstandard2.1 + net5.0 3.0.0.0 3.0.0.0 true + 8.0 - - - - - - - + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + diff --git a/src/Ombi.Store/Repository/BaseRepository.cs b/src/Ombi.Store/Repository/BaseRepository.cs index 41a7eeb31..2908309ce 100644 --- a/src/Ombi.Store/Repository/BaseRepository.cs +++ b/src/Ombi.Store/Repository/BaseRepository.cs @@ -80,52 +80,35 @@ namespace Ombi.Store.Repository public async Task ExecuteSql(string sql) { - await _ctx.Database.ExecuteSqlCommandAsync(sql); + await _ctx.Database.ExecuteSqlRawAsync(sql); } protected async Task InternalSaveChanges() { - var policy = Policy - .Handle() - .WaitAndRetryAsync(new[] - { - TimeSpan.FromSeconds(1), - TimeSpan.FromSeconds(5), - TimeSpan.FromSeconds(10) - }); - - var result = await policy.ExecuteAndCaptureAsync(async () => - { - using (var tran = await _ctx.Database.BeginTransactionAsync()) - { - var r = await _ctx.SaveChangesAsync(); - tran.Commit(); - return r; - } - }); - return result.Result; + var r = await _ctx.SaveChangesAsync(); + return r; } - private bool _disposed; - // Protected implementation of Dispose pattern. - protected virtual void Dispose(bool disposing) - { - if (_disposed) - return; + //private bool _disposed; + //// Protected implementation of Dispose pattern. + //protected virtual void Dispose(bool disposing) + //{ + // if (_disposed) + // return; - if (disposing) - { - _ctx?.Dispose(); - } + // if (disposing) + // { + // _ctx?.Dispose(); + // } - _disposed = true; - } + // _disposed = true; + //} - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } + //public void Dispose() + //{ + // Dispose(true); + // GC.SuppressFinalize(this); + //} } } \ No newline at end of file diff --git a/src/Ombi.Store/Repository/IExternalRepository.cs b/src/Ombi.Store/Repository/IExternalRepository.cs index de8b6db67..b22cb5ea8 100644 --- a/src/Ombi.Store/Repository/IExternalRepository.cs +++ b/src/Ombi.Store/Repository/IExternalRepository.cs @@ -9,7 +9,7 @@ using Ombi.Store.Entities; namespace Ombi.Store.Repository { - public interface IExternalRepository : IDisposable where T : Entity + public interface IExternalRepository where T : Entity { Task Find(object key); IQueryable GetAll(); diff --git a/src/Ombi.Store/Repository/IRepository.cs b/src/Ombi.Store/Repository/IRepository.cs index 810b586a3..fd7dcc86d 100644 --- a/src/Ombi.Store/Repository/IRepository.cs +++ b/src/Ombi.Store/Repository/IRepository.cs @@ -9,7 +9,7 @@ using Ombi.Store.Entities; namespace Ombi.Store.Repository { - public interface IRepository : IDisposable where T : Entity + public interface IRepository where T : Entity { Task Find(object key); IQueryable GetAll(); diff --git a/src/Ombi.Store/Repository/ISettingsRepository.cs b/src/Ombi.Store/Repository/ISettingsRepository.cs index 1c2729245..c600765f3 100644 --- a/src/Ombi.Store/Repository/ISettingsRepository.cs +++ b/src/Ombi.Store/Repository/ISettingsRepository.cs @@ -5,7 +5,7 @@ using Ombi.Store.Entities; namespace Ombi.Store.Repository { - public interface ISettingsRepository : IDisposable + public interface ISettingsRepository { /// /// Inserts the specified entity. diff --git a/src/Ombi.Store/Repository/Requests/IMovieRequestRepository.cs b/src/Ombi.Store/Repository/Requests/IMovieRequestRepository.cs index 275937360..5c44b2d6c 100644 --- a/src/Ombi.Store/Repository/Requests/IMovieRequestRepository.cs +++ b/src/Ombi.Store/Repository/Requests/IMovieRequestRepository.cs @@ -10,6 +10,7 @@ namespace Ombi.Store.Repository.Requests MovieRequests GetRequest(int theMovieDbId); Task Update(MovieRequests request); Task Save(); + Task MarkAsAvailable(int id); IQueryable GetWithUser(); IQueryable GetWithUser(string userId); IQueryable GetAll(string userId); diff --git a/src/Ombi.Store/Repository/Requests/ITvRequestRepository.cs b/src/Ombi.Store/Repository/Requests/ITvRequestRepository.cs index 1c6e4d302..396ec9dfb 100644 --- a/src/Ombi.Store/Repository/Requests/ITvRequestRepository.cs +++ b/src/Ombi.Store/Repository/Requests/ITvRequestRepository.cs @@ -6,12 +6,10 @@ using Ombi.Store.Entities.Requests; namespace Ombi.Store.Repository.Requests { - public interface ITvRequestRepository + public interface ITvRequestRepository : IRepository { OmbiContext Db { get; } - Task Add(TvRequests request); Task AddChild(ChildRequests request); - Task Delete(TvRequests request); Task DeleteChild(ChildRequests request); IQueryable Get(); IQueryable GetLite(); @@ -23,6 +21,8 @@ namespace Ombi.Store.Repository.Requests Task UpdateChild(ChildRequests request); IQueryable GetChild(); IQueryable GetChild(string userId); + Task MarkEpisodeAsAvailable(int id); + Task MarkChildAsAvailable(int id); Task Save(); Task DeleteChildRange(IEnumerable request); } diff --git a/src/Ombi.Store/Repository/Requests/MovieRequestRepository.cs b/src/Ombi.Store/Repository/Requests/MovieRequestRepository.cs index 2df4cac0f..bbf52c7f0 100644 --- a/src/Ombi.Store/Repository/Requests/MovieRequestRepository.cs +++ b/src/Ombi.Store/Repository/Requests/MovieRequestRepository.cs @@ -54,6 +54,14 @@ namespace Ombi.Store.Repository.Requests .AsQueryable(); } + public async Task MarkAsAvailable(int id) + { + var movieRequest = new MovieRequests{ Id = id, Available = true, MarkedAsAvailable = DateTime.UtcNow}; + var attached = Db.MovieRequests.Attach(movieRequest); + attached.Property(x => x.Available).IsModified = true; + attached.Property(x => x.MarkedAsAvailable).IsModified = true; + await Db.SaveChangesAsync(); + } public IQueryable GetWithUser(string userId) { diff --git a/src/Ombi.Store/Repository/Requests/TvRequestRepository.cs b/src/Ombi.Store/Repository/Requests/TvRequestRepository.cs index 8c6fc2461..985f464fd 100644 --- a/src/Ombi.Store/Repository/Requests/TvRequestRepository.cs +++ b/src/Ombi.Store/Repository/Requests/TvRequestRepository.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Microsoft.EntityFrameworkCore; @@ -100,6 +101,23 @@ namespace Ombi.Store.Repository.Requests .AsQueryable(); } + public async Task MarkChildAsAvailable(int id) + { + var request = new ChildRequests { Id = id, Available = true, MarkedAsAvailable = DateTime.UtcNow }; + var attached = Db.ChildRequests.Attach(request); + attached.Property(x => x.Available).IsModified = true; + attached.Property(x => x.MarkedAsAvailable).IsModified = true; + await Db.SaveChangesAsync(); + } + + public async Task MarkEpisodeAsAvailable(int id) + { + var request = new EpisodeRequests { Id = id, Available = true }; + var attached = Db.EpisodeRequests.Attach(request); + attached.Property(x => x.Available).IsModified = true; + await Db.SaveChangesAsync(); + } + public async Task Save() { await InternalSaveChanges(); @@ -128,10 +146,10 @@ namespace Ombi.Store.Repository.Requests public async Task Update(TvRequests request) { Db.Update(request); - + await InternalSaveChanges(); } - + public async Task UpdateChild(ChildRequests request) { Db.Update(request); diff --git a/src/Ombi.Store/Repository/SettingsJsonRepository.cs b/src/Ombi.Store/Repository/SettingsJsonRepository.cs index cceb8cdec..8fd3d46da 100644 --- a/src/Ombi.Store/Repository/SettingsJsonRepository.cs +++ b/src/Ombi.Store/Repository/SettingsJsonRepository.cs @@ -121,24 +121,5 @@ namespace Ombi.Store.Repository return r; } } - - private bool _disposed; - protected virtual void Dispose(bool disposing) - { - if (_disposed) - return; - - if (disposing) - { - Db?.Dispose(); - } - _disposed = true; - } - - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } } } \ No newline at end of file diff --git a/src/Ombi.Test.Common/MockHelper.cs b/src/Ombi.Test.Common/MockHelper.cs index 3e871c48f..00e327abc 100644 --- a/src/Ombi.Test.Common/MockHelper.cs +++ b/src/Ombi.Test.Common/MockHelper.cs @@ -3,7 +3,6 @@ using MockQueryable.Moq; using Moq; using Ombi.Core.Authentication; using Ombi.Store.Entities; -using System; using System.Collections.Generic; using System.Linq; diff --git a/src/Ombi.Test.Common/Ombi.Test.Common.csproj b/src/Ombi.Test.Common/Ombi.Test.Common.csproj index d43dad1b2..ecc1edfd4 100644 --- a/src/Ombi.Test.Common/Ombi.Test.Common.csproj +++ b/src/Ombi.Test.Common/Ombi.Test.Common.csproj @@ -1,13 +1,14 @@  - netstandard2.1 + net5.0 + 8.0 - + diff --git a/src/Ombi.Tests/Ombi.Tests.csproj b/src/Ombi.Tests/Ombi.Tests.csproj index a2ac1aac6..97970530e 100644 --- a/src/Ombi.Tests/Ombi.Tests.csproj +++ b/src/Ombi.Tests/Ombi.Tests.csproj @@ -1,19 +1,20 @@  - netcoreapp3.0 + net5.0 false - + + - + diff --git a/src/Ombi.TheMovieDbApi/Models/FullMovieInfo.cs b/src/Ombi.TheMovieDbApi/Models/FullMovieInfo.cs index 0e352580f..3149ed5a1 100644 --- a/src/Ombi.TheMovieDbApi/Models/FullMovieInfo.cs +++ b/src/Ombi.TheMovieDbApi/Models/FullMovieInfo.cs @@ -70,6 +70,23 @@ namespace Ombi.Api.TheMovieDb.Models public ExternalIds ExternalIds { get; set; } [JsonProperty("keywords")] public Keywords Keywords { get; set; } + + //[JsonProperty("images")] + //public List Images { get; set; } // add images to append_to_response + } + + public class Images + { + [JsonProperty("backdrops")] + public List Backdrops { get; set; } + [JsonProperty("posters")] + public List Posters { get; set; } + } + + public class ImageContent + { + [JsonProperty("file_path")] + public string FilePath { get; set; } } public class Keywords diff --git a/src/Ombi.TheMovieDbApi/Ombi.Api.TheMovieDb.csproj b/src/Ombi.TheMovieDbApi/Ombi.Api.TheMovieDb.csproj index 8ed3686b7..d0611a8a9 100644 --- a/src/Ombi.TheMovieDbApi/Ombi.Api.TheMovieDb.csproj +++ b/src/Ombi.TheMovieDbApi/Ombi.Api.TheMovieDb.csproj @@ -1,17 +1,18 @@  - netstandard2.1 + net5.0 Ombi.Api.TheMovieDb 3.0.0.0 3.0.0.0 + 8.0 - + diff --git a/src/Ombi.Updater/Ombi.Updater.csproj b/src/Ombi.Updater/Ombi.Updater.csproj index 68adbb762..7e959f6ec 100644 --- a/src/Ombi.Updater/Ombi.Updater.csproj +++ b/src/Ombi.Updater/Ombi.Updater.csproj @@ -3,7 +3,7 @@ Exe win10-x64;win10-x86;osx-x64;ubuntu-x64;debian.8-x64;centos.7-x64;linux-x64;linux-arm;linux-arm64; - netcoreapp3.0 + net5.0 3.0.0.0 3.0.0.0 @@ -12,14 +12,14 @@ - - - - - - - - + + + + + + + + diff --git a/src/Ombi.sln b/src/Ombi.sln index d557516c9..7a32a4bf9 100644 --- a/src/Ombi.sln +++ b/src/Ombi.sln @@ -7,9 +7,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ombi", "Ombi\Ombi.csproj", EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{9D30CCF8-A115-4EB7-A34D-07780D752789}" ProjectSection(SolutionItems) = preProject - ..\appveyor.yml = ..\appveyor.yml + ..\.azuredevops\pipelines\templates\build-steps.yml = ..\.azuredevops\pipelines\templates\build-steps.yml ..\build.cake = ..\build.cake ..\CHANGELOG.md = ..\CHANGELOG.md + ..\.azuredevops\pipelines\publish-job.yml = ..\.azuredevops\pipelines\publish-job.yml EndProjectSection EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ombi.Core", "Ombi.Core\Ombi.Core.csproj", "{F56E79C7-791D-4668-A0EC-29E3BBC8D24B}" @@ -108,7 +109,15 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ombi.Hubs", "Ombi.Hubs\Ombi EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ombi.Api.GroupMe", "Ombi.Api.GroupMe\Ombi.Api.GroupMe.csproj", "{9266403C-B04D-4C0F-AC39-82F12C781949}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ombi.Api.MusicBrainz", "Ombi.Api.MusicBrainz\Ombi.Api.MusicBrainz.csproj", "{C5C1769B-4197-4410-A160-0EEF39EDDC98}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ombi.Api.MusicBrainz", "Ombi.Api.MusicBrainz\Ombi.Api.MusicBrainz.csproj", "{C5C1769B-4197-4410-A160-0EEF39EDDC98}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ombi.Api.Twilio", "Ombi.Api.Twilio\Ombi.Api.Twilio.csproj", "{34E5DD1A-6A90-448B-9E71-64D1ACD6C1A3}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ombi.HealthChecks", "Ombi.HealthChecks\Ombi.HealthChecks.csproj", "{59D19538-0496-44EE-936E-EBBC22CF7B27}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ombi.Api.Webhook", "Ombi.Api.Webhook\Ombi.Api.Webhook.csproj", "{E2186FDA-D827-4781-8663-130AC382F12C}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ombi.Api.CloudService", "Ombi.Api.CloudService\Ombi.Api.CloudService.csproj", "{5DE40A66-B369-469E-8626-ECE23D9D8034}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -292,6 +301,22 @@ Global {C5C1769B-4197-4410-A160-0EEF39EDDC98}.Debug|Any CPU.Build.0 = Debug|Any CPU {C5C1769B-4197-4410-A160-0EEF39EDDC98}.Release|Any CPU.ActiveCfg = Release|Any CPU {C5C1769B-4197-4410-A160-0EEF39EDDC98}.Release|Any CPU.Build.0 = Release|Any CPU + {34E5DD1A-6A90-448B-9E71-64D1ACD6C1A3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {34E5DD1A-6A90-448B-9E71-64D1ACD6C1A3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {34E5DD1A-6A90-448B-9E71-64D1ACD6C1A3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {34E5DD1A-6A90-448B-9E71-64D1ACD6C1A3}.Release|Any CPU.Build.0 = Release|Any CPU + {59D19538-0496-44EE-936E-EBBC22CF7B27}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {59D19538-0496-44EE-936E-EBBC22CF7B27}.Debug|Any CPU.Build.0 = Debug|Any CPU + {59D19538-0496-44EE-936E-EBBC22CF7B27}.Release|Any CPU.ActiveCfg = Release|Any CPU + {59D19538-0496-44EE-936E-EBBC22CF7B27}.Release|Any CPU.Build.0 = Release|Any CPU + {E2186FDA-D827-4781-8663-130AC382F12C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E2186FDA-D827-4781-8663-130AC382F12C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E2186FDA-D827-4781-8663-130AC382F12C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E2186FDA-D827-4781-8663-130AC382F12C}.Release|Any CPU.Build.0 = Release|Any CPU + {5DE40A66-B369-469E-8626-ECE23D9D8034}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5DE40A66-B369-469E-8626-ECE23D9D8034}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5DE40A66-B369-469E-8626-ECE23D9D8034}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5DE40A66-B369-469E-8626-ECE23D9D8034}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -334,6 +359,10 @@ Global {27111E7C-748E-4996-BD71-2117027C6460} = {6F42AB98-9196-44C4-B888-D5E409F415A1} {9266403C-B04D-4C0F-AC39-82F12C781949} = {9293CA11-360A-4C20-A674-B9E794431BF5} {C5C1769B-4197-4410-A160-0EEF39EDDC98} = {9293CA11-360A-4C20-A674-B9E794431BF5} + {34E5DD1A-6A90-448B-9E71-64D1ACD6C1A3} = {9293CA11-360A-4C20-A674-B9E794431BF5} + {59D19538-0496-44EE-936E-EBBC22CF7B27} = {410F36CF-9C60-428A-B191-6FD90610991A} + {E2186FDA-D827-4781-8663-130AC382F12C} = {9293CA11-360A-4C20-A674-B9E794431BF5} + {5DE40A66-B369-469E-8626-ECE23D9D8034} = {9293CA11-360A-4C20-A674-B9E794431BF5} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {192E9BF8-00B4-45E4-BCCC-4C215725C869} diff --git a/src/Ombi/.gitignore b/src/Ombi/.gitignore index 49c402ee8..d28f49b37 100644 --- a/src/Ombi/.gitignore +++ b/src/Ombi/.gitignore @@ -7,4 +7,4 @@ wwwroot/dist /connect.lock /coverage/* /Logs/** -**.db +**.db \ No newline at end of file diff --git a/src/Ombi/ClientApp/angular.json b/src/Ombi/ClientApp/angular.json index d7801204f..4038c9a56 100644 --- a/src/Ombi/ClientApp/angular.json +++ b/src/Ombi/ClientApp/angular.json @@ -13,6 +13,7 @@ "build": { "builder": "@angular-devkit/build-angular:browser", "options": { + "aot": true, "progress": true, "extractCss": true, "outputPath": "dist", @@ -24,29 +25,34 @@ "src/assets" ], "styles": [ + "./node_modules/@angular/material/prebuilt-themes/deeppurple-amber.css", "src/styles/_imports.scss", "node_modules/bootstrap/scss/bootstrap.scss", - "node_modules/angular-bootstrap-md/scss/mdb-free.scss", - "node_modules/pace/themes/orange/pace-theme-flat-top.css", + "node_modules/primeng/resources/themes/md-dark-deeppurple/theme.css", "node_modules/font-awesome/scss/font-awesome.scss", "node_modules/primeng/resources/primeng.min.css", - "node_modules/primeng/resources/themes/nova-light/theme.css", "node_modules/primeicons/primeicons.css", "node_modules/please-wait/src/please-wait.scss", "node_modules/@fullcalendar/core/main.min.css", + "node_modules/@fullcalendar/daygrid/main.min.css", "node_modules/spinkit/scss/spinners/11-folding-cube.scss", "node_modules/spinkit/scss/spinkit.scss" ], "scripts": [ "node_modules/jquery/dist/jquery.min.js", "node_modules/chart.js/dist/Chart.js", - "node_modules/hammerjs/hammer.min.js", "./node_modules/@fullcalendar/core/main.js", "./node_modules/@fullcalendar/interaction/main.js" ] }, "configurations": { "production": { + "budgets": [ + { + "type": "anyComponentStyle", + "maximumWarning": "6kb" + } + ], "fileReplacements": [ { "replace": "src/environments/environment.ts", @@ -64,6 +70,12 @@ "buildOptimizer": true }, "hmr": { + "budgets": [ + { + "type": "anyComponentStyle", + "maximumWarning": "6kb" + } + ], "fileReplacements": [ { "replace": "src/environments/environment.ts", diff --git a/src/Ombi/ClientApp/package-lock.json b/src/Ombi/ClientApp/package-lock.json deleted file mode 100644 index 58b19bfaa..000000000 --- a/src/Ombi/ClientApp/package-lock.json +++ /dev/null @@ -1,9865 +0,0 @@ -{ - "name": "ombi", - "version": "3.0.0", - "lockfileVersion": 1, - "requires": true, - "dependencies": { - "@angular-devkit/architect": { - "version": "0.800.6", - "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.800.6.tgz", - "integrity": "sha512-946ceRci/1yx09g8iRvULLoVihcB2RW9nhpCCMum4L9wheip8t4FWso3pd3JtPQGJV9dmsnwPzR9s12bncmj3g==", - "dev": true, - "requires": { - "@angular-devkit/core": "8.0.6", - "rxjs": "6.4.0" - }, - "dependencies": { - "rxjs": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.4.0.tgz", - "integrity": "sha512-Z9Yfa11F6B9Sg/BK9MnqnQ+aQYicPLtilXBp2yUtDt2JRCE0h26d33EnfO3ZxoNxG0T92OUucP3Ct7cpfkdFfw==", - "dev": true, - "requires": { - "tslib": "^1.9.0" - } - } - } - }, - "@angular-devkit/build-angular": { - "version": "0.800.6", - "resolved": "https://registry.npmjs.org/@angular-devkit/build-angular/-/build-angular-0.800.6.tgz", - "integrity": "sha512-b6WPGN8PReRizeTe5sR3XS2sqTqfCeFIDXI4sPy3T3XdmO1dB/UP8trsHXifuNTNSVIID4X0hDwXuz36Lk+4Jw==", - "dev": true, - "requires": { - "@angular-devkit/architect": "0.800.6", - "@angular-devkit/build-optimizer": "0.800.6", - "@angular-devkit/build-webpack": "0.800.6", - "@angular-devkit/core": "8.0.6", - "@ngtools/webpack": "8.0.6", - "ajv": "6.10.0", - "autoprefixer": "9.5.1", - "browserslist": "4.5.5", - "caniuse-lite": "1.0.30000974", - "circular-dependency-plugin": "5.0.2", - "clean-css": "4.2.1", - "copy-webpack-plugin": "5.0.2", - "core-js": "3.0.1", - "file-loader": "3.0.1", - "glob": "7.1.3", - "istanbul-instrumenter-loader": "3.0.1", - "karma-source-map-support": "1.4.0", - "less": "3.9.0", - "less-loader": "4.1.0", - "license-webpack-plugin": "2.1.1", - "loader-utils": "1.2.3", - "mini-css-extract-plugin": "0.6.0", - "minimatch": "3.0.4", - "open": "6.2.0", - "parse5": "4.0.0", - "postcss": "7.0.14", - "postcss-import": "12.0.1", - "postcss-loader": "3.0.0", - "raw-loader": "1.0.0", - "rxjs": "6.4.0", - "sass": "1.19.0", - "sass-loader": "7.1.0", - "semver": "6.0.0", - "source-map-loader": "0.2.4", - "source-map-support": "0.5.12", - "speed-measure-webpack-plugin": "1.3.1", - "stats-webpack-plugin": "0.7.0", - "style-loader": "0.23.1", - "stylus": "0.54.5", - "stylus-loader": "3.0.2", - "terser-webpack-plugin": "1.2.3", - "tree-kill": "1.2.1", - "webpack": "4.30.0", - "webpack-dev-middleware": "3.6.2", - "webpack-dev-server": "3.3.1", - "webpack-merge": "4.2.1", - "webpack-sources": "1.3.0", - "webpack-subresource-integrity": "1.1.0-rc.6", - "worker-plugin": "3.1.0" - }, - "dependencies": { - "ajv": { - "version": "6.10.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.0.tgz", - "integrity": "sha512-nffhOpkymDECQyR0mnsUtoCE8RlX38G0rYP+wgLWFyZuUyuuojSSvi/+euOiQBIn63whYwYVIIH1TvE3tu4OEg==", - "dev": true, - "requires": { - "fast-deep-equal": "^2.0.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "core-js": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.0.1.tgz", - "integrity": "sha512-sco40rF+2KlE0ROMvydjkrVMMG1vYilP2ALoRXcYR4obqbYIuV3Bg+51GEDW+HF8n7NRA+iaA4qD0nD9lo9mew==", - "dev": true - }, - "glob": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", - "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "parse5": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-4.0.0.tgz", - "integrity": "sha512-VrZ7eOd3T1Fk4XWNXMgiGBK/z0MG48BWG2uQNU4I72fkQuKUTZpl+u9k+CxEG0twMVzSmXEEz12z5Fnw1jIQFA==", - "dev": true - }, - "rxjs": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.4.0.tgz", - "integrity": "sha512-Z9Yfa11F6B9Sg/BK9MnqnQ+aQYicPLtilXBp2yUtDt2JRCE0h26d33EnfO3ZxoNxG0T92OUucP3Ct7cpfkdFfw==", - "dev": true, - "requires": { - "tslib": "^1.9.0" - } - }, - "semver": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.0.0.tgz", - "integrity": "sha512-0UewU+9rFapKFnlbirLi3byoOuhrSsli/z/ihNnvM24vgF+8sNBiI1LZPBSH9wJKUwaUbw+s3hToDLCXkrghrQ==", - "dev": true - } - } - }, - "@angular-devkit/build-optimizer": { - "version": "0.800.6", - "resolved": "https://registry.npmjs.org/@angular-devkit/build-optimizer/-/build-optimizer-0.800.6.tgz", - "integrity": "sha512-f8u9c5VA+bxbYREKX6EY8QsbIT8ziDRHlhJ1n6H2nUTaQi+THtbPfrDsf3S3aVACfkkY+LEGGl135XEPr5PoxA==", - "dev": true, - "requires": { - "loader-utils": "1.2.3", - "source-map": "0.5.6", - "typescript": "3.4.4", - "webpack-sources": "1.3.0" - }, - "dependencies": { - "source-map": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz", - "integrity": "sha1-dc449SvwczxafwwRjYEzSiu19BI=", - "dev": true - }, - "typescript": { - "version": "3.4.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.4.4.tgz", - "integrity": "sha512-xt5RsIRCEaf6+j9AyOBgvVuAec0i92rgCaS3S+UVf5Z/vF2Hvtsw08wtUTJqp4djwznoAgjSxeCcU4r+CcDBJA==", - "dev": true - } - } - }, - "@angular-devkit/build-webpack": { - "version": "0.800.6", - "resolved": "https://registry.npmjs.org/@angular-devkit/build-webpack/-/build-webpack-0.800.6.tgz", - "integrity": "sha512-FwNGa99dxL9dACv/eLTP6u50tlPLG01yqp/JFAgxS0OmDkEMjSBLNgS8b8qhTo8XMhMsMWzb8yIUwV1PcSj6qg==", - "dev": true, - "requires": { - "@angular-devkit/architect": "0.800.6", - "@angular-devkit/core": "8.0.6", - "rxjs": "6.4.0", - "webpack-merge": "4.2.1" - }, - "dependencies": { - "rxjs": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.4.0.tgz", - "integrity": "sha512-Z9Yfa11F6B9Sg/BK9MnqnQ+aQYicPLtilXBp2yUtDt2JRCE0h26d33EnfO3ZxoNxG0T92OUucP3Ct7cpfkdFfw==", - "dev": true, - "requires": { - "tslib": "^1.9.0" - } - } - } - }, - "@angular-devkit/core": { - "version": "8.0.6", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-8.0.6.tgz", - "integrity": "sha512-gbKEVsQuYqBJPzgaxEitvs0aN9NwmUHhTkum28mRyPbS3witay/q8+3ls48M2W+98Da/PQbfndxFY4OCa+qHEA==", - "dev": true, - "requires": { - "ajv": "6.10.0", - "fast-json-stable-stringify": "2.0.0", - "magic-string": "0.25.2", - "rxjs": "6.4.0", - "source-map": "0.7.3" - }, - "dependencies": { - "ajv": { - "version": "6.10.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.0.tgz", - "integrity": "sha512-nffhOpkymDECQyR0mnsUtoCE8RlX38G0rYP+wgLWFyZuUyuuojSSvi/+euOiQBIn63whYwYVIIH1TvE3tu4OEg==", - "dev": true, - "requires": { - "fast-deep-equal": "^2.0.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "rxjs": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.4.0.tgz", - "integrity": "sha512-Z9Yfa11F6B9Sg/BK9MnqnQ+aQYicPLtilXBp2yUtDt2JRCE0h26d33EnfO3ZxoNxG0T92OUucP3Ct7cpfkdFfw==", - "dev": true, - "requires": { - "tslib": "^1.9.0" - } - }, - "source-map": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", - "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", - "dev": true - } - } - }, - "@angular-devkit/schematics": { - "version": "8.0.6", - "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-8.0.6.tgz", - "integrity": "sha512-FGPcVKxNvtdFB0A6oHyxtWeugL83nW+kPATlAimgh1hu7TCP94dDpflCV9o/lgZlH817xTYXrhToXJaMZSnDPw==", - "dev": true, - "requires": { - "@angular-devkit/core": "8.0.6", - "rxjs": "6.4.0" - }, - "dependencies": { - "rxjs": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.4.0.tgz", - "integrity": "sha512-Z9Yfa11F6B9Sg/BK9MnqnQ+aQYicPLtilXBp2yUtDt2JRCE0h26d33EnfO3ZxoNxG0T92OUucP3Ct7cpfkdFfw==", - "dev": true, - "requires": { - "tslib": "^1.9.0" - } - } - } - }, - "@angular/animations": { - "version": "8.1.2", - "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-8.1.2.tgz", - "integrity": "sha512-szR5qzRe6vS1qrPhV2p5fMp5vQxT2SaljXGs3Xgt2Tl23om0XVNcqK0I8NNuK/ehuJ5LXQ1fJHniGcmN2aUw0g==", - "requires": { - "tslib": "^1.9.0" - } - }, - "@angular/cdk": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/@angular/cdk/-/cdk-8.1.1.tgz", - "integrity": "sha512-5hBmhrHf9+WjGVIT8gbhT0Nh37BAjgI2TGRkt1o4qX8cG+1B6gU2MxM+CDJ7PhxSJi9lW93lq2AMuWwnRSllyg==", - "requires": { - "parse5": "^5.0.0", - "tslib": "^1.7.1" - } - }, - "@angular/cli": { - "version": "8.0.6", - "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-8.0.6.tgz", - "integrity": "sha512-COBpeoXyLt8FiOhsmoEnDfQcm0aTdUSUHsH3zNkVTcyxpRzZVspTDGzxhK0UsCpddXS/MMjJiXph6SJ1el3qaQ==", - "dev": true, - "requires": { - "@angular-devkit/architect": "0.800.6", - "@angular-devkit/core": "8.0.6", - "@angular-devkit/schematics": "8.0.6", - "@schematics/angular": "8.0.6", - "@schematics/update": "0.800.6", - "@yarnpkg/lockfile": "1.1.0", - "debug": "^4.1.1", - "ini": "1.3.5", - "inquirer": "6.3.1", - "npm-package-arg": "6.1.0", - "open": "6.2.0", - "pacote": "9.5.0", - "read-package-tree": "5.2.2", - "semver": "6.0.0", - "symbol-observable": "1.2.0", - "universal-analytics": "^0.4.20", - "uuid": "^3.3.2" - }, - "dependencies": { - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "semver": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.0.0.tgz", - "integrity": "sha512-0UewU+9rFapKFnlbirLi3byoOuhrSsli/z/ihNnvM24vgF+8sNBiI1LZPBSH9wJKUwaUbw+s3hToDLCXkrghrQ==", - "dev": true - } - } - }, - "@angular/common": { - "version": "8.1.2", - "resolved": "https://registry.npmjs.org/@angular/common/-/common-8.1.2.tgz", - "integrity": "sha512-bywFofN5RjcvygYEC/3eo+bfUnYBmARA6DPau8fm6D2ZGpXrWXJ3Thd99ZesuuffvpniaIHlAjbHGI83XSnixQ==", - "requires": { - "tslib": "^1.9.0" - } - }, - "@angular/compiler": { - "version": "8.1.2", - "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-8.1.2.tgz", - "integrity": "sha512-oRkHrstOV6imbb4mGf6q20d4N4iYfBbI6WfxtPL4dz08GipGg4Zvekn4e3R01vzhFBxssGcgmeEtFQJh/UzI8g==", - "requires": { - "tslib": "^1.9.0" - } - }, - "@angular/compiler-cli": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-8.0.0.tgz", - "integrity": "sha512-Z0U0Ih8A7V3J1gq7AXnXbrGAD2ERmz7JbREJJRHDWiUNxIqGQiV3Odo1V8FL5n/cKvLwSYM2Ubvk10gb0+3njA==", - "dev": true, - "requires": { - "canonical-path": "1.0.0", - "chokidar": "^2.1.1", - "convert-source-map": "^1.5.1", - "dependency-graph": "^0.7.2", - "magic-string": "^0.25.0", - "minimist": "^1.2.0", - "reflect-metadata": "^0.1.2", - "shelljs": "^0.8.1", - "source-map": "^0.6.1", - "tslib": "^1.9.0", - "yargs": "13.1.0" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - }, - "camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true - }, - "cliui": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz", - "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", - "dev": true, - "requires": { - "string-width": "^2.1.1", - "strip-ansi": "^4.0.0", - "wrap-ansi": "^2.0.0" - }, - "dependencies": { - "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true, - "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - } - } - } - }, - "find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "requires": { - "locate-path": "^3.0.0" - } - }, - "get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true - }, - "invert-kv": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz", - "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true - }, - "lcid": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz", - "integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==", - "dev": true, - "requires": { - "invert-kv": "^2.0.0" - } - }, - "os-locale": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz", - "integrity": "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==", - "dev": true, - "requires": { - "execa": "^1.0.0", - "lcid": "^2.0.0", - "mem": "^4.0.0" - } - }, - "require-main-filename": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", - "dev": true - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, - "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - }, - "dependencies": { - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true - }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "requires": { - "ansi-regex": "^4.1.0" - } - } - } - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "^3.0.0" - } - }, - "which-module": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", - "dev": true - }, - "y18n": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", - "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", - "dev": true - }, - "yargs": { - "version": "13.1.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.1.0.tgz", - "integrity": "sha512-1UhJbXfzHiPqkfXNHYhiz79qM/kZqjTE8yGlEjZa85Q+3+OwcV6NRkV7XOV1W2Eom2bzILeUn55pQYffjVOLAg==", - "dev": true, - "requires": { - "cliui": "^4.0.0", - "find-up": "^3.0.0", - "get-caller-file": "^2.0.1", - "os-locale": "^3.1.0", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^3.0.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^13.0.0" - } - }, - "yargs-parser": { - "version": "13.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.1.tgz", - "integrity": "sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ==", - "dev": true, - "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } - } - } - }, - "@angular/core": { - "version": "8.1.2", - "resolved": "https://registry.npmjs.org/@angular/core/-/core-8.1.2.tgz", - "integrity": "sha512-Gm/UIUnIkeah39vxi4enVH/CUcPZOgGDyw4RNagw4pH8dTP8V0RUz8uteOr3DS+Eh49BcHkrT2oU5MBZSZ3lvw==", - "requires": { - "tslib": "^1.9.0" - } - }, - "@angular/forms": { - "version": "8.1.2", - "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-8.1.2.tgz", - "integrity": "sha512-DHqbWt6AGnLkNajLZUAH4yQrxZdgUkjzEW6oxwvS2PxmLIrppz4TYWizfAVQndZ1Ddl7Eo1zRoRzqqHT90XyGA==", - "requires": { - "tslib": "^1.9.0" - } - }, - "@angular/http": { - "version": "7.2.15", - "resolved": "https://registry.npmjs.org/@angular/http/-/http-7.2.15.tgz", - "integrity": "sha512-TR7PEdmLWNIre3Zn8lvyb4lSrvPUJhKLystLnp4hBMcWsJqq5iK8S3bnlR4viZ9HMlf7bW7+Hm4SI6aB3tdUtw==", - "requires": { - "tslib": "^1.9.0" - } - }, - "@angular/language-service": { - "version": "8.1.2", - "resolved": "https://registry.npmjs.org/@angular/language-service/-/language-service-8.1.2.tgz", - "integrity": "sha512-9DR5TclsEpMIzCmagLHKYDTAqcZUkZKPjkngqIAUJg5R4IUjsuYn8NZX+agoOrS4ky6Dy9FXGYUC+QB0iEiycg==", - "dev": true - }, - "@angular/material": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/@angular/material/-/material-8.1.1.tgz", - "integrity": "sha512-45aaxKuLTrthzhAhG2+OY86wafuRBteZcRjDG7rKZ3Cc3KteUp5QwAi+QbhHzs4O3WXLWTAmuLYJelRqRqqw7g==", - "requires": { - "tslib": "^1.7.1" - } - }, - "@angular/platform-browser": { - "version": "8.1.2", - "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-8.1.2.tgz", - "integrity": "sha512-n61OtH3B0e+LTHCfHPjB7hiuo0ZxKxZvNWigczGyLZf2abga5jac2bNrdZnU8zXC44AUfasUD2qDS2IPIhNbqA==", - "requires": { - "tslib": "^1.9.0" - } - }, - "@angular/platform-browser-dynamic": { - "version": "8.1.2", - "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-8.1.2.tgz", - "integrity": "sha512-NmbGMwKPbYq3ZFt6nOqRslJsQNRS2E94cjkSLseEb5wauUmdUBX9stoHu8BOhvd+EIEcYhD7uxPB+L/qPsH46g==", - "requires": { - "tslib": "^1.9.0" - } - }, - "@angular/platform-server": { - "version": "8.1.2", - "resolved": "https://registry.npmjs.org/@angular/platform-server/-/platform-server-8.1.2.tgz", - "integrity": "sha512-wZdKqormXipsm1Qd4K6CT3pyA38jE1F7xK+1+VVoLYCQuSGMermZ2SE+M7DpxK8ZpT53r5HfwJZCt5xrEKvyoQ==", - "requires": { - "domino": "^2.1.2", - "tslib": "^1.9.0", - "xhr2": "^0.1.4" - } - }, - "@angular/router": { - "version": "8.1.2", - "resolved": "https://registry.npmjs.org/@angular/router/-/router-8.1.2.tgz", - "integrity": "sha512-+SWoYZHyDBBUydDTbIu+hyoGzWtSA4VUsriUPWEOCplzQiabFhWxVvcT00mO0cim4XfupL1tmiPjE66sivLYBw==", - "requires": { - "tslib": "^1.9.0" - } - }, - "@angularclass/hmr": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@angularclass/hmr/-/hmr-2.1.3.tgz", - "integrity": "sha1-NOZY7T2jfyOwogDi2lqJvpK7IJ8=" - }, - "@aspnet/signalr": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/@aspnet/signalr/-/signalr-1.1.4.tgz", - "integrity": "sha512-Jp9nPc8hmmhbG9OKiHe2fOKskBHfg+3Y9foSKHxjgGtyI743hXjGFv3uFlUg503K9f8Ilu63gQt3fDkLICBRyg==", - "requires": { - "eventsource": "^1.0.7", - "request": "^2.88.0", - "ws": "^6.0.0" - } - }, - "@auth0/angular-jwt": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@auth0/angular-jwt/-/angular-jwt-2.1.2.tgz", - "integrity": "sha512-/ldNAqTmaX07PiabFZ7RZNT4Qdpt44/PxY9yoAcvmbGHhETpuKkBvcN11EC+4fKkO+J+KtTSxMGkcSIq0Wv5Ag==", - "requires": { - "url": "^0.11.0" - } - }, - "@babel/code-frame": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.5.5.tgz", - "integrity": "sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw==", - "requires": { - "@babel/highlight": "^7.0.0" - } - }, - "@babel/highlight": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.5.0.tgz", - "integrity": "sha512-7dV4eu9gBxoM0dAnj/BCFDW9LFU0zvTrkq0ugM7pnHEgguOEeOz1so2ZghEdzviYzQEED0r4EAgpsBChKy1TRQ==", - "requires": { - "chalk": "^2.0.0", - "esutils": "^2.0.2", - "js-tokens": "^4.0.0" - } - }, - "@fullcalendar/core": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@fullcalendar/core/-/core-4.2.0.tgz", - "integrity": "sha512-4kd5OGHxjMtwI0gUHKwAYzmR0Z79Qf8y0ARx2Ruh20JdVy3Tznn6oKwdpkUbaXWrLXNDoXYRkBiFCIgC27VNCw==" - }, - "@fullcalendar/interaction": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@fullcalendar/interaction/-/interaction-4.2.0.tgz", - "integrity": "sha512-wwAyocUp1HEY7c7xCymR9EGdh7AWZrwNiBQlIpP3ne0eJT0U4ZjlnoOoels3VPsTJ9a6pdO1/XoGjEvL1T5y4g==" - }, - "@ng-bootstrap/ng-bootstrap": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/@ng-bootstrap/ng-bootstrap/-/ng-bootstrap-4.2.1.tgz", - "integrity": "sha512-7etP9X9jKIkbuDzU3ngI2jQhHQDZxIu0ErvlkHb7u7YH9akIOLVkXvz2mTMvcFABWZhze64UjFuEgR46b6WGSw==", - "requires": { - "tslib": "^1.9.0" - } - }, - "@ngtools/webpack": { - "version": "8.0.6", - "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-8.0.6.tgz", - "integrity": "sha512-ulu+5lLt4RjmcCXbmaGCjqjuOWt18DVek/Sq4HFE9E7zP+n7HercsU6h+9PrtaZThj9NB0B7A+afRB5aAQN/bQ==", - "dev": true, - "requires": { - "@angular-devkit/core": "8.0.6", - "enhanced-resolve": "4.1.0", - "rxjs": "6.4.0", - "tree-kill": "1.2.1", - "webpack-sources": "1.3.0" - }, - "dependencies": { - "rxjs": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.4.0.tgz", - "integrity": "sha512-Z9Yfa11F6B9Sg/BK9MnqnQ+aQYicPLtilXBp2yUtDt2JRCE0h26d33EnfO3ZxoNxG0T92OUucP3Ct7cpfkdFfw==", - "dev": true, - "requires": { - "tslib": "^1.9.0" - } - } - } - }, - "@ngu/carousel": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/@ngu/carousel/-/carousel-1.5.5.tgz", - "integrity": "sha512-tPDThxM325ss4fBzUtu7OExuC0aR8QIZIHJwYHpfF955TR9Zs0argokopS8DX9mCTM3tYL+Qgy1ui0KjCJzHBg==", - "requires": { - "tslib": "^1.9.0" - } - }, - "@ngx-translate/core": { - "version": "11.0.1", - "resolved": "https://registry.npmjs.org/@ngx-translate/core/-/core-11.0.1.tgz", - "integrity": "sha512-nBCa1ZD9fAUY/3eskP3Lql2fNg8OMrYIej1/5GRsfcutx9tG/5fZLCv9m6UCw1aS+u4uK/vXjv1ctG/FdMvaWg==", - "requires": { - "tslib": "^1.9.0" - } - }, - "@ngx-translate/http-loader": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@ngx-translate/http-loader/-/http-loader-4.0.0.tgz", - "integrity": "sha512-x8LumqydWD7eX9yQTAVeoCM9gFUIGVTUjZqbxdAUavAA3qVnk9wCQux7iHLPXpydl8vyQmLoPQR+fFU+DUDOMA==", - "requires": { - "tslib": "^1.9.0" - } - }, - "@schematics/angular": { - "version": "8.0.6", - "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-8.0.6.tgz", - "integrity": "sha512-F0/MrbvrJQJIjt0GwEkmf9PZUX0xQlCjlDcH6U7yBni0/+R5Gd5g3G0f12fsSa2iAwpwrLkKpiQluj29eFituQ==", - "dev": true, - "requires": { - "@angular-devkit/core": "8.0.6", - "@angular-devkit/schematics": "8.0.6" - } - }, - "@schematics/update": { - "version": "0.800.6", - "resolved": "https://registry.npmjs.org/@schematics/update/-/update-0.800.6.tgz", - "integrity": "sha512-vrzGIJtMiwLWl96+aJXMYrPgPtktLRpY8ZiNnlLm3pMDmeg08uButRh/pQGt02HuO/apTNJ5g0bmG8K5wS4I5A==", - "dev": true, - "requires": { - "@angular-devkit/core": "8.0.6", - "@angular-devkit/schematics": "8.0.6", - "@yarnpkg/lockfile": "1.1.0", - "ini": "1.3.5", - "pacote": "9.5.0", - "rxjs": "6.4.0", - "semver": "6.0.0", - "semver-intersect": "1.4.0" - }, - "dependencies": { - "rxjs": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.4.0.tgz", - "integrity": "sha512-Z9Yfa11F6B9Sg/BK9MnqnQ+aQYicPLtilXBp2yUtDt2JRCE0h26d33EnfO3ZxoNxG0T92OUucP3Ct7cpfkdFfw==", - "dev": true, - "requires": { - "tslib": "^1.9.0" - } - }, - "semver": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.0.0.tgz", - "integrity": "sha512-0UewU+9rFapKFnlbirLi3byoOuhrSsli/z/ihNnvM24vgF+8sNBiI1LZPBSH9wJKUwaUbw+s3hToDLCXkrghrQ==", - "dev": true - } - } - }, - "@types/events": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/events/-/events-3.0.0.tgz", - "integrity": "sha512-EaObqwIvayI5a8dCzhFrjKzVwKLxjoG9T6Ppd5CEo07LRKfQ8Yokw54r5+Wq7FaBQ+yXRvQAYPrHwya1/UFt9g==", - "dev": true - }, - "@types/glob": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.1.tgz", - "integrity": "sha512-1Bh06cbWJUHMC97acuD6UMG29nMt0Aqz1vF3guLfG+kHHJhy3AyohZFFxYk2f7Q1SQIrNwvncxAE0N/9s70F2w==", - "dev": true, - "requires": { - "@types/events": "*", - "@types/minimatch": "*", - "@types/node": "*" - } - }, - "@types/jasmine": { - "version": "2.8.16", - "resolved": "https://registry.npmjs.org/@types/jasmine/-/jasmine-2.8.16.tgz", - "integrity": "sha512-056oRlBBp7MDzr+HoU5su099s/s7wjZ3KcHxLfv+Byqb9MwdLUvsfLgw1VS97hsh3ddxSPyQu+olHMnoVTUY6g==", - "dev": true - }, - "@types/jasminewd2": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/@types/jasminewd2/-/jasminewd2-2.0.6.tgz", - "integrity": "sha512-2ZOKrxb8bKRmP/po5ObYnRDgFE4i+lQiEB27bAMmtMWLgJSqlIDqlLx6S0IRorpOmOPRQ6O80NujTmQAtBkeNw==", - "dev": true, - "requires": { - "@types/jasmine": "*" - } - }, - "@types/jquery": { - "version": "3.3.30", - "resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-3.3.30.tgz", - "integrity": "sha512-chB+QbLulamShZAFcTJtl8opZwHFBpDOP6nRLrPGkhC6N1aKWrDXg2Nc71tEg6ny6E8SQpRwbWSi9GdstH5VJA==", - "requires": { - "@types/sizzle": "*" - } - }, - "@types/minimatch": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", - "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==", - "dev": true - }, - "@types/node": { - "version": "8.9.5", - "resolved": "https://registry.npmjs.org/@types/node/-/node-8.9.5.tgz", - "integrity": "sha512-jRHfWsvyMtXdbhnz5CVHxaBgnV6duZnPlQuRSo/dm/GnmikNcmZhxIES4E9OZjUmQ8C+HCl4KJux+cXN/ErGDQ==", - "dev": true - }, - "@types/q": { - "version": "0.0.32", - "resolved": "https://registry.npmjs.org/@types/q/-/q-0.0.32.tgz", - "integrity": "sha1-vShOV8hPEyXacCur/IKlMoGQwMU=", - "optional": true - }, - "@types/selenium-webdriver": { - "version": "3.0.16", - "resolved": "https://registry.npmjs.org/@types/selenium-webdriver/-/selenium-webdriver-3.0.16.tgz", - "integrity": "sha512-lMC2G0ItF2xv4UCiwbJGbnJlIuUixHrioOhNGHSCsYCJ8l4t9hMCUimCytvFv7qy6AfSzRxhRHoGa+UqaqwyeA==" - }, - "@types/sizzle": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.2.tgz", - "integrity": "sha512-7EJYyKTL7tFR8+gDbB6Wwz/arpGa0Mywk1TJbNzKzHtzbwVmY4HR9WqS5VV7dsBUKQmPNr192jHr/VpBluj/hg==" - }, - "@types/source-list-map": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/@types/source-list-map/-/source-list-map-0.1.2.tgz", - "integrity": "sha512-K5K+yml8LTo9bWJI/rECfIPrGgxdpeNbj+d53lwN4QjW1MCwlkhUms+gtdzigTeUyBr09+u8BwOIY3MXvHdcsA==", - "dev": true - }, - "@types/webpack-sources": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/@types/webpack-sources/-/webpack-sources-0.1.5.tgz", - "integrity": "sha512-zfvjpp7jiafSmrzJ2/i3LqOyTYTuJ7u1KOXlKgDlvsj9Rr0x7ZiYu5lZbXwobL7lmsRNtPXlBfmaUD8eU2Hu8w==", - "dev": true, - "requires": { - "@types/node": "*", - "@types/source-list-map": "*", - "source-map": "^0.6.1" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } - } - }, - "@webassemblyjs/ast": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.8.5.tgz", - "integrity": "sha512-aJMfngIZ65+t71C3y2nBBg5FFG0Okt9m0XEgWZ7Ywgn1oMAT8cNwx00Uv1cQyHtidq0Xn94R4TAywO+LCQ+ZAQ==", - "dev": true, - "requires": { - "@webassemblyjs/helper-module-context": "1.8.5", - "@webassemblyjs/helper-wasm-bytecode": "1.8.5", - "@webassemblyjs/wast-parser": "1.8.5" - } - }, - "@webassemblyjs/floating-point-hex-parser": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.8.5.tgz", - "integrity": "sha512-9p+79WHru1oqBh9ewP9zW95E3XAo+90oth7S5Re3eQnECGq59ly1Ri5tsIipKGpiStHsUYmY3zMLqtk3gTcOtQ==", - "dev": true - }, - "@webassemblyjs/helper-api-error": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.8.5.tgz", - "integrity": "sha512-Za/tnzsvnqdaSPOUXHyKJ2XI7PDX64kWtURyGiJJZKVEdFOsdKUCPTNEVFZq3zJ2R0G5wc2PZ5gvdTRFgm81zA==", - "dev": true - }, - "@webassemblyjs/helper-buffer": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.8.5.tgz", - "integrity": "sha512-Ri2R8nOS0U6G49Q86goFIPNgjyl6+oE1abW1pS84BuhP1Qcr5JqMwRFT3Ah3ADDDYGEgGs1iyb1DGX+kAi/c/Q==", - "dev": true - }, - "@webassemblyjs/helper-code-frame": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.8.5.tgz", - "integrity": "sha512-VQAadSubZIhNpH46IR3yWO4kZZjMxN1opDrzePLdVKAZ+DFjkGD/rf4v1jap744uPVU6yjL/smZbRIIJTOUnKQ==", - "dev": true, - "requires": { - "@webassemblyjs/wast-printer": "1.8.5" - } - }, - "@webassemblyjs/helper-fsm": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-fsm/-/helper-fsm-1.8.5.tgz", - "integrity": "sha512-kRuX/saORcg8se/ft6Q2UbRpZwP4y7YrWsLXPbbmtepKr22i8Z4O3V5QE9DbZK908dh5Xya4Un57SDIKwB9eow==", - "dev": true - }, - "@webassemblyjs/helper-module-context": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-module-context/-/helper-module-context-1.8.5.tgz", - "integrity": "sha512-/O1B236mN7UNEU4t9X7Pj38i4VoU8CcMHyy3l2cV/kIF4U5KoHXDVqcDuOs1ltkac90IM4vZdHc52t1x8Yfs3g==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.8.5", - "mamacro": "^0.0.3" - } - }, - "@webassemblyjs/helper-wasm-bytecode": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.8.5.tgz", - "integrity": "sha512-Cu4YMYG3Ddl72CbmpjU/wbP6SACcOPVbHN1dI4VJNJVgFwaKf1ppeFJrwydOG3NDHxVGuCfPlLZNyEdIYlQ6QQ==", - "dev": true - }, - "@webassemblyjs/helper-wasm-section": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.8.5.tgz", - "integrity": "sha512-VV083zwR+VTrIWWtgIUpqfvVdK4ff38loRmrdDBgBT8ADXYsEZ5mPQ4Nde90N3UYatHdYoDIFb7oHzMncI02tA==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.8.5", - "@webassemblyjs/helper-buffer": "1.8.5", - "@webassemblyjs/helper-wasm-bytecode": "1.8.5", - "@webassemblyjs/wasm-gen": "1.8.5" - } - }, - "@webassemblyjs/ieee754": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.8.5.tgz", - "integrity": "sha512-aaCvQYrvKbY/n6wKHb/ylAJr27GglahUO89CcGXMItrOBqRarUMxWLJgxm9PJNuKULwN5n1csT9bYoMeZOGF3g==", - "dev": true, - "requires": { - "@xtuc/ieee754": "^1.2.0" - } - }, - "@webassemblyjs/leb128": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.8.5.tgz", - "integrity": "sha512-plYUuUwleLIziknvlP8VpTgO4kqNaH57Y3JnNa6DLpu/sGcP6hbVdfdX5aHAV716pQBKrfuU26BJK29qY37J7A==", - "dev": true, - "requires": { - "@xtuc/long": "4.2.2" - } - }, - "@webassemblyjs/utf8": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.8.5.tgz", - "integrity": "sha512-U7zgftmQriw37tfD934UNInokz6yTmn29inT2cAetAsaU9YeVCveWEwhKL1Mg4yS7q//NGdzy79nlXh3bT8Kjw==", - "dev": true - }, - "@webassemblyjs/wasm-edit": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.8.5.tgz", - "integrity": "sha512-A41EMy8MWw5yvqj7MQzkDjU29K7UJq1VrX2vWLzfpRHt3ISftOXqrtojn7nlPsZ9Ijhp5NwuODuycSvfAO/26Q==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.8.5", - "@webassemblyjs/helper-buffer": "1.8.5", - "@webassemblyjs/helper-wasm-bytecode": "1.8.5", - "@webassemblyjs/helper-wasm-section": "1.8.5", - "@webassemblyjs/wasm-gen": "1.8.5", - "@webassemblyjs/wasm-opt": "1.8.5", - "@webassemblyjs/wasm-parser": "1.8.5", - "@webassemblyjs/wast-printer": "1.8.5" - } - }, - "@webassemblyjs/wasm-gen": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.8.5.tgz", - "integrity": "sha512-BCZBT0LURC0CXDzj5FXSc2FPTsxwp3nWcqXQdOZE4U7h7i8FqtFK5Egia6f9raQLpEKT1VL7zr4r3+QX6zArWg==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.8.5", - "@webassemblyjs/helper-wasm-bytecode": "1.8.5", - "@webassemblyjs/ieee754": "1.8.5", - "@webassemblyjs/leb128": "1.8.5", - "@webassemblyjs/utf8": "1.8.5" - } - }, - "@webassemblyjs/wasm-opt": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.8.5.tgz", - "integrity": "sha512-HKo2mO/Uh9A6ojzu7cjslGaHaUU14LdLbGEKqTR7PBKwT6LdPtLLh9fPY33rmr5wcOMrsWDbbdCHq4hQUdd37Q==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.8.5", - "@webassemblyjs/helper-buffer": "1.8.5", - "@webassemblyjs/wasm-gen": "1.8.5", - "@webassemblyjs/wasm-parser": "1.8.5" - } - }, - "@webassemblyjs/wasm-parser": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.8.5.tgz", - "integrity": "sha512-pi0SYE9T6tfcMkthwcgCpL0cM9nRYr6/6fjgDtL6q/ZqKHdMWvxitRi5JcZ7RI4SNJJYnYNaWy5UUrHQy998lw==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.8.5", - "@webassemblyjs/helper-api-error": "1.8.5", - "@webassemblyjs/helper-wasm-bytecode": "1.8.5", - "@webassemblyjs/ieee754": "1.8.5", - "@webassemblyjs/leb128": "1.8.5", - "@webassemblyjs/utf8": "1.8.5" - } - }, - "@webassemblyjs/wast-parser": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-parser/-/wast-parser-1.8.5.tgz", - "integrity": "sha512-daXC1FyKWHF1i11obK086QRlsMsY4+tIOKgBqI1lxAnkp9xe9YMcgOxm9kLe+ttjs5aWV2KKE1TWJCN57/Btsg==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.8.5", - "@webassemblyjs/floating-point-hex-parser": "1.8.5", - "@webassemblyjs/helper-api-error": "1.8.5", - "@webassemblyjs/helper-code-frame": "1.8.5", - "@webassemblyjs/helper-fsm": "1.8.5", - "@xtuc/long": "4.2.2" - } - }, - "@webassemblyjs/wast-printer": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.8.5.tgz", - "integrity": "sha512-w0U0pD4EhlnvRyeJzBqaVSJAo9w/ce7/WPogeXLzGkO6hzhr4GnQIZ4W4uUt5b9ooAaXPtnXlj0gzsXEOUNYMg==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.8.5", - "@webassemblyjs/wast-parser": "1.8.5", - "@xtuc/long": "4.2.2" - } - }, - "@xtuc/ieee754": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", - "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", - "dev": true - }, - "@xtuc/long": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", - "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", - "dev": true - }, - "@yarnpkg/lockfile": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz", - "integrity": "sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==", - "dev": true - }, - "@yellowspot/ng-truncate": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@yellowspot/ng-truncate/-/ng-truncate-1.5.0.tgz", - "integrity": "sha512-HzBImGAacDbPtV5Dony3eoyeF2zdDmXRjNL7sJa2IaV12ROQ8OxE1e/l8rLMJ23Nd1uzres4P0WmEc6iibfYaw==", - "requires": { - "tslib": "^1.9.0" - } - }, - "JSONStream": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", - "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", - "dev": true, - "requires": { - "jsonparse": "^1.2.0", - "through": ">=2.2.7 <3" - } - }, - "abbrev": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", - "optional": true - }, - "accepts": { - "version": "1.3.7", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", - "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", - "dev": true, - "requires": { - "mime-types": "~2.1.24", - "negotiator": "0.6.2" - } - }, - "acorn": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.2.1.tgz", - "integrity": "sha512-JD0xT5FCRDNyjDda3Lrg/IxFscp9q4tiYtxE1/nOzlKCk7hIRuYjhq1kCNkbPjMRMZuFq20HNQn1I9k8Oj0E+Q==", - "dev": true - }, - "acorn-dynamic-import": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/acorn-dynamic-import/-/acorn-dynamic-import-4.0.0.tgz", - "integrity": "sha512-d3OEjQV4ROpoflsnUA8HozoIR504TFxNivYEUi6uwz0IYhBkTDXGuWlNdMtybRt3nqVx/L6XqMt0FxkXuWKZhw==", - "dev": true - }, - "adm-zip": { - "version": "0.4.13", - "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.13.tgz", - "integrity": "sha512-fERNJX8sOXfel6qCBCMPvZLzENBEhZTzKqg6vrOW5pvoEaQuJhRU4ndTAh6lHOxn1I6jnz2NHra56ZODM751uw==", - "optional": true - }, - "after": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/after/-/after-0.8.2.tgz", - "integrity": "sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8=" - }, - "agent-base": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.3.0.tgz", - "integrity": "sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==", - "requires": { - "es6-promisify": "^5.0.0" - } - }, - "agentkeepalive": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-3.5.2.tgz", - "integrity": "sha512-e0L/HNe6qkQ7H19kTlRRqUibEAwDK5AFk6y3PtMsuut2VAH6+Q4xZml1tNDJD7kSAyqmbG/K08K5WEJYtUrSlQ==", - "dev": true, - "requires": { - "humanize-ms": "^1.2.1" - } - }, - "ajv": { - "version": "6.10.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz", - "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==", - "requires": { - "fast-deep-equal": "^2.0.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "ajv-errors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-1.0.1.tgz", - "integrity": "sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ==", - "dev": true - }, - "ajv-keywords": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.4.1.tgz", - "integrity": "sha512-RO1ibKvd27e6FEShVFfPALuHI3WjSVNeK5FIsmme/LYRNxjKuNj+Dt7bucLa6NdSv3JcVTyMlm9kGR84z1XpaQ==", - "dev": true - }, - "amdefine": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", - "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=" - }, - "angular-bootstrap-md": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/angular-bootstrap-md/-/angular-bootstrap-md-7.5.4.tgz", - "integrity": "sha512-LBVqSswd49hJ3YNTkXzwM0Cn1+9SQ2kVYQxX36ZjxaKNeDQKaUk3V2Rb/y8krhDJrPJh37pDzRmlCDObg37EIA==", - "requires": { - "tslib": "^1.9.0" - } - }, - "angular-router-loader": { - "version": "0.8.5", - "resolved": "https://registry.npmjs.org/angular-router-loader/-/angular-router-loader-0.8.5.tgz", - "integrity": "sha512-8wggCTKGgzB1o8co3Wvj+p9pKN7T7q3C477lEz3NLjvPVzUti8rv9i45Di+4aO/k+HvzGh3s8QdNlXU2Bl4avQ==", - "requires": { - "loader-utils": "^1.0.2" - } - }, - "angular2-template-loader": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/angular2-template-loader/-/angular2-template-loader-0.6.2.tgz", - "integrity": "sha1-wNROkP/w+sleiyPwQ6zaf9HFHXw=", - "requires": { - "loader-utils": "^0.2.15" - }, - "dependencies": { - "big.js": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/big.js/-/big.js-3.2.0.tgz", - "integrity": "sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q==" - }, - "json5": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", - "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=" - }, - "loader-utils": { - "version": "0.2.17", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-0.2.17.tgz", - "integrity": "sha1-+G5jdNQyBabmxg6RlvF8Apm/s0g=", - "requires": { - "big.js": "^3.1.3", - "emojis-list": "^2.0.0", - "json5": "^0.5.0", - "object-assign": "^4.0.1" - } - } - } - }, - "ansi-colors": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.4.tgz", - "integrity": "sha512-hHUXGagefjN2iRrID63xckIvotOXOojhQKWIPUZ4mNUZ9nLZW+7FMNoE1lOkEhNWYsx/7ysGIuJYCiMAA9FnrA==", - "dev": true - }, - "ansi-escapes": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", - "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==", - "dev": true - }, - "ansi-html": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/ansi-html/-/ansi-html-0.0.7.tgz", - "integrity": "sha1-gTWEAhliqenm/QOflA0S9WynhZ4=", - "dev": true - }, - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "requires": { - "color-convert": "^1.9.0" - } - }, - "anymatch": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", - "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", - "dev": true, - "requires": { - "micromatch": "^3.1.4", - "normalize-path": "^2.1.1" - }, - "dependencies": { - "normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "dev": true, - "requires": { - "remove-trailing-separator": "^1.0.1" - } - } - } - }, - "app-root-path": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/app-root-path/-/app-root-path-2.2.1.tgz", - "integrity": "sha512-91IFKeKk7FjfmezPKkwtaRvSpnUc4gDwPAjA1YZ9Gn0q0PPeW+vbeUsZuyDwjI7+QTHhcLen2v25fi/AmhvbJA==" - }, - "aproba": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", - "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" - }, - "are-we-there-yet": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz", - "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", - "requires": { - "delegates": "^1.0.0", - "readable-stream": "^2.0.6" - } - }, - "argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "requires": { - "sprintf-js": "~1.0.2" - } - }, - "arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=" - }, - "arr-flatten": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", - "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==" - }, - "arr-union": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", - "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=" - }, - "array-find-index": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", - "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=", - "optional": true - }, - "array-flatten": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz", - "integrity": "sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==", - "dev": true - }, - "array-union": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", - "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", - "requires": { - "array-uniq": "^1.0.1" - } - }, - "array-uniq": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", - "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=" - }, - "array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=" - }, - "arraybuffer.slice": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz", - "integrity": "sha512-wGUIVQXuehL5TCqQun8OW81jGzAWycqzFF8lFp+GOM5BXLYj3bKNsYC4daB7n6XjCqxQA/qgTJ+8ANR3acjrog==" - }, - "arrify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", - "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", - "optional": true - }, - "asap": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", - "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=", - "dev": true - }, - "asn1": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", - "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", - "requires": { - "safer-buffer": "~2.1.0" - } - }, - "asn1.js": { - "version": "4.10.1", - "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz", - "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==", - "dev": true, - "requires": { - "bn.js": "^4.0.0", - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0" - } - }, - "aspnet-prerendering": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/aspnet-prerendering/-/aspnet-prerendering-3.0.1.tgz", - "integrity": "sha1-C252e0nkJeHT1ZYR+sgMnG9bAQA=", - "requires": { - "domain-task": "^3.0.0" - } - }, - "assert": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/assert/-/assert-1.5.0.tgz", - "integrity": "sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA==", - "dev": true, - "requires": { - "object-assign": "^4.1.1", - "util": "0.10.3" - }, - "dependencies": { - "inherits": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", - "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=", - "dev": true - }, - "util": { - "version": "0.10.3", - "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", - "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", - "dev": true, - "requires": { - "inherits": "2.0.1" - } - } - } - }, - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" - }, - "assign-symbols": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", - "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=" - }, - "async": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", - "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", - "dev": true, - "requires": { - "lodash": "^4.17.14" - } - }, - "async-each": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz", - "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==", - "dev": true - }, - "async-foreach": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/async-foreach/-/async-foreach-0.1.3.tgz", - "integrity": "sha1-NhIfhFwFeBct5Bmpfb6x0W7DRUI=", - "optional": true - }, - "async-limiter": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz", - "integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg==" - }, - "asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" - }, - "atob": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", - "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==" - }, - "autoprefixer": { - "version": "9.5.1", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-9.5.1.tgz", - "integrity": "sha512-KJSzkStUl3wP0D5sdMlP82Q52JLy5+atf2MHAre48+ckWkXgixmfHyWmA77wFDy6jTHU6mIgXv6hAQ2mf1PjJQ==", - "dev": true, - "requires": { - "browserslist": "^4.5.4", - "caniuse-lite": "^1.0.30000957", - "normalize-range": "^0.1.2", - "num2fraction": "^1.2.2", - "postcss": "^7.0.14", - "postcss-value-parser": "^3.3.1" - } - }, - "awesome-typescript-loader": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/awesome-typescript-loader/-/awesome-typescript-loader-5.2.1.tgz", - "integrity": "sha512-slv66OAJB8orL+UUaTI3pKlLorwIvS4ARZzYR9iJJyGsEgOqueMfOMdKySWzZ73vIkEe3fcwFgsKMg4d8zyb1g==", - "requires": { - "chalk": "^2.4.1", - "enhanced-resolve": "^4.0.0", - "loader-utils": "^1.1.0", - "lodash": "^4.17.5", - "micromatch": "^3.1.9", - "mkdirp": "^0.5.1", - "source-map-support": "^0.5.3", - "webpack-log": "^1.2.0" - } - }, - "aws-sign2": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" - }, - "aws4": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", - "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==" - }, - "babel-code-frame": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", - "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "esutils": "^2.0.2", - "js-tokens": "^3.0.2" - }, - "dependencies": { - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - } - }, - "js-tokens": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", - "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", - "dev": true - }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - } - } - }, - "babel-generator": { - "version": "6.26.1", - "resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.1.tgz", - "integrity": "sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA==", - "dev": true, - "requires": { - "babel-messages": "^6.23.0", - "babel-runtime": "^6.26.0", - "babel-types": "^6.26.0", - "detect-indent": "^4.0.0", - "jsesc": "^1.3.0", - "lodash": "^4.17.4", - "source-map": "^0.5.7", - "trim-right": "^1.0.1" - }, - "dependencies": { - "jsesc": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz", - "integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=", - "dev": true - } - } - }, - "babel-messages": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", - "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } - }, - "babel-runtime": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", - "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", - "dev": true, - "requires": { - "core-js": "^2.4.0", - "regenerator-runtime": "^0.11.0" - } - }, - "babel-template": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz", - "integrity": "sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI=", - "dev": true, - "requires": { - "babel-runtime": "^6.26.0", - "babel-traverse": "^6.26.0", - "babel-types": "^6.26.0", - "babylon": "^6.18.0", - "lodash": "^4.17.4" - } - }, - "babel-traverse": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz", - "integrity": "sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4=", - "dev": true, - "requires": { - "babel-code-frame": "^6.26.0", - "babel-messages": "^6.23.0", - "babel-runtime": "^6.26.0", - "babel-types": "^6.26.0", - "babylon": "^6.18.0", - "debug": "^2.6.8", - "globals": "^9.18.0", - "invariant": "^2.2.2", - "lodash": "^4.17.4" - } - }, - "babel-types": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", - "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=", - "dev": true, - "requires": { - "babel-runtime": "^6.26.0", - "esutils": "^2.0.2", - "lodash": "^4.17.4", - "to-fast-properties": "^1.0.3" - } - }, - "babylon": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", - "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==", - "dev": true - }, - "backo2": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz", - "integrity": "sha1-MasayLEpNjRj41s+u2n038+6eUc=" - }, - "balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" - }, - "base": { - "version": "0.11.2", - "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", - "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", - "requires": { - "cache-base": "^1.0.1", - "class-utils": "^0.3.5", - "component-emitter": "^1.2.1", - "define-property": "^1.0.0", - "isobject": "^3.0.1", - "mixin-deep": "^1.2.0", - "pascalcase": "^0.1.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } - } - }, - "base64-arraybuffer": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz", - "integrity": "sha1-c5JncZI7Whl0etZmqlzUv5xunOg=" - }, - "base64-js": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.0.tgz", - "integrity": "sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw==", - "dev": true - }, - "batch": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", - "integrity": "sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY=", - "dev": true - }, - "bcrypt-pbkdf": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", - "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", - "requires": { - "tweetnacl": "^0.14.3" - } - }, - "better-assert": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/better-assert/-/better-assert-1.0.2.tgz", - "integrity": "sha1-QIZrnhueC1W0gYlDEeaPr/rrxSI=", - "requires": { - "callsite": "1.0.0" - } - }, - "big.js": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", - "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==" - }, - "binary-extensions": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", - "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", - "dev": true - }, - "blob": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/blob/-/blob-0.0.5.tgz", - "integrity": "sha512-gaqbzQPqOoamawKg0LGVd7SzLgXS+JH61oWprSLH+P+abTczqJbhTR8CmJ2u9/bUYNmHTGJx/UEmn6doAvvuig==" - }, - "block-stream": { - "version": "0.0.9", - "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz", - "integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=", - "optional": true, - "requires": { - "inherits": "~2.0.0" - } - }, - "blocking-proxy": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/blocking-proxy/-/blocking-proxy-1.0.1.tgz", - "integrity": "sha512-KE8NFMZr3mN2E0HcvCgRtX7DjhiIQrwle+nSVJVC/yqFb9+xznHl2ZcoBp2L9qzkI4t4cBFJ1efXF8Dwi132RA==", - "optional": true, - "requires": { - "minimist": "^1.2.0" - } - }, - "bluebird": { - "version": "3.5.5", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.5.tgz", - "integrity": "sha512-5am6HnnfN+urzt4yfg7IgTbotDjIT/u8AJpEt0sIU9FtXfVeezXAPKswrG+xKUCOYAINpSdgZVDU6QFh+cuH3w==", - "dev": true - }, - "bn.js": { - "version": "4.11.8", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", - "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", - "dev": true - }, - "body-parser": { - "version": "1.19.0", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", - "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", - "dev": true, - "requires": { - "bytes": "3.1.0", - "content-type": "~1.0.4", - "debug": "2.6.9", - "depd": "~1.1.2", - "http-errors": "1.7.2", - "iconv-lite": "0.4.24", - "on-finished": "~2.3.0", - "qs": "6.7.0", - "raw-body": "2.4.0", - "type-is": "~1.6.17" - }, - "dependencies": { - "bytes": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", - "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", - "dev": true - }, - "qs": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", - "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==", - "dev": true - } - } - }, - "bonjour": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/bonjour/-/bonjour-3.5.0.tgz", - "integrity": "sha1-jokKGD2O6aI5OzhExpGkK897yfU=", - "dev": true, - "requires": { - "array-flatten": "^2.1.0", - "deep-equal": "^1.0.1", - "dns-equal": "^1.0.0", - "dns-txt": "^2.0.2", - "multicast-dns": "^6.0.1", - "multicast-dns-service-types": "^1.1.0" - } - }, - "bootstrap": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-4.3.1.tgz", - "integrity": "sha512-rXqOmH1VilAt2DyPzluTi2blhk17bO7ef+zLLPlWvG494pDxcM234pJ8wTc/6R40UWizAIIMgxjvxZg5kmsbag==" - }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "requires": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "brorand": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", - "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=", - "dev": true - }, - "browserify-aes": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", - "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", - "dev": true, - "requires": { - "buffer-xor": "^1.0.3", - "cipher-base": "^1.0.0", - "create-hash": "^1.1.0", - "evp_bytestokey": "^1.0.3", - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } - }, - "browserify-cipher": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", - "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", - "dev": true, - "requires": { - "browserify-aes": "^1.0.4", - "browserify-des": "^1.0.0", - "evp_bytestokey": "^1.0.0" - } - }, - "browserify-des": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", - "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", - "dev": true, - "requires": { - "cipher-base": "^1.0.1", - "des.js": "^1.0.0", - "inherits": "^2.0.1", - "safe-buffer": "^5.1.2" - } - }, - "browserify-rsa": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", - "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", - "dev": true, - "requires": { - "bn.js": "^4.1.0", - "randombytes": "^2.0.1" - } - }, - "browserify-sign": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.0.4.tgz", - "integrity": "sha1-qk62jl17ZYuqa/alfmMMvXqT0pg=", - "dev": true, - "requires": { - "bn.js": "^4.1.1", - "browserify-rsa": "^4.0.0", - "create-hash": "^1.1.0", - "create-hmac": "^1.1.2", - "elliptic": "^6.0.0", - "inherits": "^2.0.1", - "parse-asn1": "^5.0.0" - } - }, - "browserify-zlib": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", - "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", - "dev": true, - "requires": { - "pako": "~1.0.5" - } - }, - "browserslist": { - "version": "4.5.5", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.5.5.tgz", - "integrity": "sha512-0QFO1r/2c792Ohkit5XI8Cm8pDtZxgNl2H6HU4mHrpYz7314pEYcsAVVatM0l/YmxPnEzh9VygXouj4gkFUTKA==", - "dev": true, - "requires": { - "caniuse-lite": "^1.0.30000960", - "electron-to-chromium": "^1.3.124", - "node-releases": "^1.1.14" - } - }, - "browserstack": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/browserstack/-/browserstack-1.5.2.tgz", - "integrity": "sha512-+6AFt9HzhKykcPF79W6yjEUJcdvZOV0lIXdkORXMJftGrDl0OKWqRF4GHqpDNkxiceDT/uB7Fb/aDwktvXX7dg==", - "optional": true, - "requires": { - "https-proxy-agent": "^2.2.1" - } - }, - "buffer": { - "version": "4.9.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", - "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", - "dev": true, - "requires": { - "base64-js": "^1.0.2", - "ieee754": "^1.1.4", - "isarray": "^1.0.0" - } - }, - "buffer-from": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", - "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" - }, - "buffer-indexof": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/buffer-indexof/-/buffer-indexof-1.1.1.tgz", - "integrity": "sha512-4/rOEg86jivtPTeOUUT61jJO1Ya1TrR/OkqCSZDyq84WJh3LuuiphBYJN+fm5xufIk4XAFcEwte/8WzC8If/1g==", - "dev": true - }, - "buffer-xor": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", - "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=", - "dev": true - }, - "builtin-modules": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", - "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=" - }, - "builtin-status-codes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", - "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=", - "dev": true - }, - "builtins": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/builtins/-/builtins-1.0.3.tgz", - "integrity": "sha1-y5T662HIaWRR2zZTThQi+U8K7og=", - "dev": true - }, - "bytes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", - "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=", - "dev": true - }, - "cacache": { - "version": "11.3.3", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-11.3.3.tgz", - "integrity": "sha512-p8WcneCytvzPxhDvYp31PD039vi77I12W+/KfR9S8AZbaiARFBCpsPJS+9uhWfeBfeAtW7o/4vt3MUqLkbY6nA==", - "dev": true, - "requires": { - "bluebird": "^3.5.5", - "chownr": "^1.1.1", - "figgy-pudding": "^3.5.1", - "glob": "^7.1.4", - "graceful-fs": "^4.1.15", - "lru-cache": "^5.1.1", - "mississippi": "^3.0.0", - "mkdirp": "^0.5.1", - "move-concurrently": "^1.0.1", - "promise-inflight": "^1.0.1", - "rimraf": "^2.6.3", - "ssri": "^6.0.1", - "unique-filename": "^1.1.1", - "y18n": "^4.0.0" - }, - "dependencies": { - "lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "dev": true, - "requires": { - "yallist": "^3.0.2" - } - }, - "y18n": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", - "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", - "dev": true - }, - "yallist": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.3.tgz", - "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==", - "dev": true - } - } - }, - "cache-base": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", - "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", - "requires": { - "collection-visit": "^1.0.0", - "component-emitter": "^1.2.1", - "get-value": "^2.0.6", - "has-value": "^1.0.0", - "isobject": "^3.0.1", - "set-value": "^2.0.0", - "to-object-path": "^0.3.0", - "union-value": "^1.0.0", - "unset-value": "^1.0.0" - } - }, - "caller-callsite": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/caller-callsite/-/caller-callsite-2.0.0.tgz", - "integrity": "sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ=", - "dev": true, - "requires": { - "callsites": "^2.0.0" - } - }, - "caller-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-2.0.0.tgz", - "integrity": "sha1-Ro+DBE42mrIBD6xfBs7uFbsssfQ=", - "dev": true, - "requires": { - "caller-callsite": "^2.0.0" - } - }, - "callsite": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz", - "integrity": "sha1-KAOY5dZkvXQDi28JBRU+borxvCA=" - }, - "callsites": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz", - "integrity": "sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA=", - "dev": true - }, - "camelcase": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", - "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=", - "optional": true - }, - "camelcase-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", - "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", - "optional": true, - "requires": { - "camelcase": "^2.0.0", - "map-obj": "^1.0.0" - } - }, - "caniuse-lite": { - "version": "1.0.30000974", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000974.tgz", - "integrity": "sha512-xc3rkNS/Zc3CmpMKuczWEdY2sZgx09BkAxfvkxlAEBTqcMHeL8QnPqhKse+5sRTi3nrw2pJwToD2WvKn1Uhvww==", - "dev": true - }, - "canonical-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/canonical-path/-/canonical-path-1.0.0.tgz", - "integrity": "sha512-feylzsbDxi1gPZ1IjystzIQZagYYLvfKrSuygUCgf7z6x790VEzze5QEkdSV1U58RA7Hi0+v6fv4K54atOzATg==", - "dev": true - }, - "caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "chardet": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", - "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", - "dev": true - }, - "chart.js": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-2.5.0.tgz", - "integrity": "sha1-/m51Gok3afVucr7lrZEgfhxZKVc=", - "requires": { - "chartjs-color": "^2.0.0", - "moment": "^2.10.6" - } - }, - "chartjs-color": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/chartjs-color/-/chartjs-color-2.3.0.tgz", - "integrity": "sha512-hEvVheqczsoHD+fZ+tfPUE+1+RbV6b+eksp2LwAhwRTVXEjCSEavvk+Hg3H6SZfGlPh/UfmWKGIvZbtobOEm3g==", - "requires": { - "chartjs-color-string": "^0.6.0", - "color-convert": "^0.5.3" - }, - "dependencies": { - "color-convert": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-0.5.3.tgz", - "integrity": "sha1-vbbGnOZg+t/+CwAHzER+G59ygr0=" - } - } - }, - "chartjs-color-string": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/chartjs-color-string/-/chartjs-color-string-0.6.0.tgz", - "integrity": "sha512-TIB5OKn1hPJvO7JcteW4WY/63v6KwEdt6udfnDE9iCAZgy+V4SrbSxoIbTw/xkUIapjEI4ExGtD0+6D3KyFd7A==", - "requires": { - "color-name": "^1.0.0" - } - }, - "chokidar": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.6.tgz", - "integrity": "sha512-V2jUo67OKkc6ySiRpJrjlpJKl9kDuG+Xb8VgsGzb+aEouhgS1D0weyPU4lEzdAcsCAvrih2J2BqyXqHWvVLw5g==", - "dev": true, - "requires": { - "anymatch": "^2.0.0", - "async-each": "^1.0.1", - "braces": "^2.3.2", - "fsevents": "^1.2.7", - "glob-parent": "^3.1.0", - "inherits": "^2.0.3", - "is-binary-path": "^1.0.0", - "is-glob": "^4.0.0", - "normalize-path": "^3.0.0", - "path-is-absolute": "^1.0.0", - "readdirp": "^2.2.1", - "upath": "^1.1.1" - } - }, - "chownr": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.2.tgz", - "integrity": "sha512-GkfeAQh+QNy3wquu9oIZr6SS5x7wGdSgNQvD10X3r+AZr1Oys22HW8kAmDMvNg2+Dm0TeGaEuO8gFwdBXxwO8A==", - "dev": true - }, - "chrome-trace-event": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.2.tgz", - "integrity": "sha512-9e/zx1jw7B4CO+c/RXoCsfg/x1AfUBioy4owYH0bJprEYAx5hRFLRhWBqHAG57D0ZM4H7vxbP7bPe0VwhQRYDQ==", - "dev": true, - "requires": { - "tslib": "^1.9.0" - } - }, - "cipher-base": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", - "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", - "dev": true, - "requires": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } - }, - "circular-dependency-plugin": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/circular-dependency-plugin/-/circular-dependency-plugin-5.0.2.tgz", - "integrity": "sha512-oC7/DVAyfcY3UWKm0sN/oVoDedQDQiw/vIiAnuTWTpE5s0zWf7l3WY417Xw/Fbi/QbAjctAkxgMiS9P0s3zkmA==", - "dev": true - }, - "class-utils": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", - "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", - "requires": { - "arr-union": "^3.1.0", - "define-property": "^0.2.5", - "isobject": "^3.0.0", - "static-extend": "^0.1.1" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "requires": { - "is-descriptor": "^0.1.0" - } - } - } - }, - "clean-css": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.1.tgz", - "integrity": "sha512-4ZxI6dy4lrY6FHzfiy1aEOXgu4LIsW2MhwG0VBKdcoGoH/XLFgaHSdLTGr4O8Be6A8r3MOphEiI8Gc1n0ecf3g==", - "dev": true, - "requires": { - "source-map": "~0.6.0" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } - } - }, - "cli-cursor": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", - "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", - "dev": true, - "requires": { - "restore-cursor": "^2.0.0" - } - }, - "cli-width": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", - "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=", - "dev": true - }, - "cliui": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", - "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", - "optional": true, - "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wrap-ansi": "^2.0.0" - } - }, - "clone": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", - "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=", - "dev": true - }, - "clone-deep": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-2.0.2.tgz", - "integrity": "sha512-SZegPTKjCgpQH63E+eN6mVEEPdQBOUzjyJm5Pora4lrwWRFS8I0QAxV/KD6vV/i0WuijHZWQC1fMsPEdxfdVCQ==", - "dev": true, - "requires": { - "for-own": "^1.0.0", - "is-plain-object": "^2.0.4", - "kind-of": "^6.0.0", - "shallow-clone": "^1.0.0" - } - }, - "co": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", - "dev": true - }, - "code-point-at": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" - }, - "codelyzer": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/codelyzer/-/codelyzer-4.5.0.tgz", - "integrity": "sha512-oO6vCkjqsVrEsmh58oNlnJkRXuA30hF8cdNAQV9DytEalDwyOFRvHMnlKFzmOStNerOmPGZU9GAHnBo4tGvtiQ==", - "requires": { - "app-root-path": "^2.1.0", - "css-selector-tokenizer": "^0.7.0", - "cssauron": "^1.4.0", - "semver-dsl": "^1.0.1", - "source-map": "^0.5.7", - "sprintf-js": "^1.1.1" - }, - "dependencies": { - "sprintf-js": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.2.tgz", - "integrity": "sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==" - } - } - }, - "collection-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", - "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", - "requires": { - "map-visit": "^1.0.0", - "object-visit": "^1.0.0" - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" - }, - "combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "requires": { - "delayed-stream": "~1.0.0" - } - }, - "commander": { - "version": "2.20.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.0.tgz", - "integrity": "sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==" - }, - "commondir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", - "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", - "dev": true - }, - "component-bind": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/component-bind/-/component-bind-1.0.0.tgz", - "integrity": "sha1-AMYIq33Nk4l8AAllGx06jh5zu9E=" - }, - "component-emitter": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", - "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==" - }, - "component-inherit": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/component-inherit/-/component-inherit-0.0.3.tgz", - "integrity": "sha1-ZF/ErfWLcrZJ1crmUTVhnbJv8UM=" - }, - "compressible": { - "version": "2.0.17", - "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.17.tgz", - "integrity": "sha512-BGHeLCK1GV7j1bSmQQAi26X+GgWcTjLr/0tzSvMCl3LH1w1IJ4PFSPoV5316b30cneTziC+B1a+3OjoSUcQYmw==", - "dev": true, - "requires": { - "mime-db": ">= 1.40.0 < 2" - } - }, - "compression": { - "version": "1.7.4", - "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", - "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", - "dev": true, - "requires": { - "accepts": "~1.3.5", - "bytes": "3.0.0", - "compressible": "~2.0.16", - "debug": "2.6.9", - "on-headers": "~1.0.2", - "safe-buffer": "5.1.2", - "vary": "~1.1.2" - }, - "dependencies": { - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - } - } - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" - }, - "concat-stream": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", - "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", - "dev": true, - "requires": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^2.2.2", - "typedarray": "^0.0.6" - } - }, - "connect-history-api-fallback": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz", - "integrity": "sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg==", - "dev": true - }, - "console-browserify": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", - "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=", - "dev": true, - "requires": { - "date-now": "^0.1.4" - } - }, - "console-control-strings": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" - }, - "constants-browserify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", - "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=", - "dev": true - }, - "content-disposition": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", - "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", - "dev": true, - "requires": { - "safe-buffer": "5.1.2" - }, - "dependencies": { - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - } - } - }, - "content-type": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", - "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", - "dev": true - }, - "convert-source-map": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.6.0.tgz", - "integrity": "sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.1" - }, - "dependencies": { - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - } - } - }, - "cookie": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", - "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==", - "dev": true - }, - "cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=", - "dev": true - }, - "copy-concurrently": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/copy-concurrently/-/copy-concurrently-1.0.5.tgz", - "integrity": "sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A==", - "dev": true, - "requires": { - "aproba": "^1.1.1", - "fs-write-stream-atomic": "^1.0.8", - "iferr": "^0.1.5", - "mkdirp": "^0.5.1", - "rimraf": "^2.5.4", - "run-queue": "^1.0.0" - } - }, - "copy-descriptor": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", - "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=" - }, - "copy-webpack-plugin": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-5.0.2.tgz", - "integrity": "sha512-7nC7EynPrnBTtBwwbG1aTqrfNS1aTb9eEjSmQDqFtKAsJrR3uDb+pCDIFT2LzhW+SgGJxQcYzThrmXzzZ720uw==", - "dev": true, - "requires": { - "cacache": "^11.3.1", - "find-cache-dir": "^2.0.0", - "glob-parent": "^3.1.0", - "globby": "^7.1.1", - "is-glob": "^4.0.0", - "loader-utils": "^1.1.0", - "minimatch": "^3.0.4", - "normalize-path": "^3.0.0", - "p-limit": "^2.1.0", - "serialize-javascript": "^1.4.0", - "webpack-log": "^2.0.0" - }, - "dependencies": { - "globby": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/globby/-/globby-7.1.1.tgz", - "integrity": "sha1-+yzP+UAfhgCUXfral0QMypcrhoA=", - "dev": true, - "requires": { - "array-union": "^1.0.1", - "dir-glob": "^2.0.0", - "glob": "^7.1.2", - "ignore": "^3.3.5", - "pify": "^3.0.0", - "slash": "^1.0.0" - } - }, - "pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", - "dev": true - }, - "webpack-log": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/webpack-log/-/webpack-log-2.0.0.tgz", - "integrity": "sha512-cX8G2vR/85UYG59FgkoMamwHUIkSSlV3bBMRsbxVXVUk2j6NleCKjQ/WE9eYg9WY4w25O9w8wKP4rzNZFmUcUg==", - "dev": true, - "requires": { - "ansi-colors": "^3.0.0", - "uuid": "^3.3.2" - } - } - } - }, - "core-js": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.9.tgz", - "integrity": "sha512-HOpZf6eXmnl7la+cUdMnLvUxKNqLUzJvgIziQ0DiF3JwSImNphIqdGqzj6hIKyX04MmV0poclQ7+wjWvxQyR2A==" - }, - "core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" - }, - "cosmiconfig": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.2.1.tgz", - "integrity": "sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA==", - "dev": true, - "requires": { - "import-fresh": "^2.0.0", - "is-directory": "^0.3.1", - "js-yaml": "^3.13.1", - "parse-json": "^4.0.0" - }, - "dependencies": { - "parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", - "dev": true, - "requires": { - "error-ex": "^1.3.1", - "json-parse-better-errors": "^1.0.1" - } - } - } - }, - "create-ecdh": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.3.tgz", - "integrity": "sha512-GbEHQPMOswGpKXM9kCWVrremUcBmjteUaQ01T9rkKCPDXfUHX0IoP9LpHYo2NPFampa4e+/pFDc3jQdxrxQLaw==", - "dev": true, - "requires": { - "bn.js": "^4.1.0", - "elliptic": "^6.0.0" - } - }, - "create-hash": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", - "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", - "dev": true, - "requires": { - "cipher-base": "^1.0.1", - "inherits": "^2.0.1", - "md5.js": "^1.3.4", - "ripemd160": "^2.0.1", - "sha.js": "^2.4.0" - } - }, - "create-hmac": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", - "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", - "dev": true, - "requires": { - "cipher-base": "^1.0.3", - "create-hash": "^1.1.0", - "inherits": "^2.0.1", - "ripemd160": "^2.0.0", - "safe-buffer": "^5.0.1", - "sha.js": "^2.4.8" - } - }, - "cross-spawn": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-3.0.1.tgz", - "integrity": "sha1-ElYDfsufDF9549bvE14wdwGEuYI=", - "optional": true, - "requires": { - "lru-cache": "^4.0.1", - "which": "^1.2.9" - } - }, - "crypto-browserify": { - "version": "3.12.0", - "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", - "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", - "dev": true, - "requires": { - "browserify-cipher": "^1.0.0", - "browserify-sign": "^4.0.0", - "create-ecdh": "^4.0.0", - "create-hash": "^1.1.0", - "create-hmac": "^1.1.0", - "diffie-hellman": "^5.0.0", - "inherits": "^2.0.1", - "pbkdf2": "^3.0.3", - "public-encrypt": "^4.0.0", - "randombytes": "^2.0.0", - "randomfill": "^1.0.3" - } - }, - "css-parse": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/css-parse/-/css-parse-1.7.0.tgz", - "integrity": "sha1-Mh9s9zeCpv91ERE5D8BeLGV9jJs=", - "dev": true - }, - "css-selector-tokenizer": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/css-selector-tokenizer/-/css-selector-tokenizer-0.7.1.tgz", - "integrity": "sha512-xYL0AMZJ4gFzJQsHUKa5jiWWi2vH77WVNg7JYRyewwj6oPh4yb/y6Y9ZCw9dsj/9UauMhtuxR+ogQd//EdEVNA==", - "requires": { - "cssesc": "^0.1.0", - "fastparse": "^1.1.1", - "regexpu-core": "^1.0.0" - } - }, - "cssauron": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/cssauron/-/cssauron-1.4.0.tgz", - "integrity": "sha1-pmAt/34EqDBtwNuaVR6S6LVmKtg=", - "requires": { - "through": "X.X.X" - } - }, - "cssesc": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-0.1.0.tgz", - "integrity": "sha1-yBSQPkViM3GgR3tAEJqq++6t27Q=" - }, - "currently-unhandled": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", - "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=", - "optional": true, - "requires": { - "array-find-index": "^1.0.1" - } - }, - "cyclist": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-0.2.2.tgz", - "integrity": "sha1-GzN5LhHpFKL9bW7WRHRkRE5fpkA=", - "dev": true - }, - "d": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", - "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", - "requires": { - "es5-ext": "^0.10.50", - "type": "^1.0.1" - } - }, - "dashdash": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", - "requires": { - "assert-plus": "^1.0.0" - } - }, - "date-now": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", - "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=", - "dev": true - }, - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - }, - "debuglog": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/debuglog/-/debuglog-1.0.1.tgz", - "integrity": "sha1-qiT/uaw9+aI1GDfPstJ5NgzXhJI=", - "dev": true - }, - "decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" - }, - "decode-uri-component": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", - "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=" - }, - "deep-equal": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz", - "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=", - "dev": true - }, - "default-gateway": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-4.2.0.tgz", - "integrity": "sha512-h6sMrVB1VMWVrW13mSc6ia/DwYYw5MN6+exNu1OaJeFac5aSAvwM7lZ0NVfTABuSkQelr4h5oebg3KB1XPdjgA==", - "dev": true, - "requires": { - "execa": "^1.0.0", - "ip-regex": "^2.1.0" - } - }, - "define-properties": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", - "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", - "requires": { - "object-keys": "^1.0.12" - } - }, - "define-property": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", - "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", - "requires": { - "is-descriptor": "^1.0.2", - "isobject": "^3.0.1" - }, - "dependencies": { - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } - } - }, - "del": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz", - "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=", - "optional": true, - "requires": { - "globby": "^5.0.0", - "is-path-cwd": "^1.0.0", - "is-path-in-cwd": "^1.0.0", - "object-assign": "^4.0.1", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0", - "rimraf": "^2.2.8" - } - }, - "delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" - }, - "delegates": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=" - }, - "depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", - "dev": true - }, - "dependency-graph": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/dependency-graph/-/dependency-graph-0.7.2.tgz", - "integrity": "sha512-KqtH4/EZdtdfWX0p6MGP9jljvxSY6msy/pRUD4jgNwVpv3v1QmNLlsB3LDSSUg79BRVSn7jI1QPRtArGABovAQ==", - "dev": true - }, - "des.js": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz", - "integrity": "sha1-wHTS4qpqipoH29YfmhXCzYPsjsw=", - "dev": true, - "requires": { - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0" - } - }, - "destroy": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", - "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=", - "dev": true - }, - "detect-indent": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz", - "integrity": "sha1-920GQ1LN9Docts5hnE7jqUdd4gg=", - "dev": true, - "requires": { - "repeating": "^2.0.0" - } - }, - "detect-node": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.0.4.tgz", - "integrity": "sha512-ZIzRpLJrOj7jjP2miAtgqIfmzbxa4ZOr5jJc601zklsfEx9oTzmmj2nVpIPRpNlRTIh8lc1kyViIY7BWSGNmKw==", - "dev": true - }, - "dezalgo": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.3.tgz", - "integrity": "sha1-f3Qt4Gb8dIvI24IFad3c5Jvw1FY=", - "dev": true, - "requires": { - "asap": "^2.0.0", - "wrappy": "1" - } - }, - "diff": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", - "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==" - }, - "diffie-hellman": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", - "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", - "dev": true, - "requires": { - "bn.js": "^4.1.0", - "miller-rabin": "^4.0.0", - "randombytes": "^2.0.0" - } - }, - "dir-glob": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-2.2.2.tgz", - "integrity": "sha512-f9LBi5QWzIW3I6e//uxZoLBlUt9kcp66qo0sSCxL6YZKc75R1c4MFCoe/LaZiBGmgujvQdxc5Bn3QhfyvK5Hsw==", - "dev": true, - "requires": { - "path-type": "^3.0.0" - }, - "dependencies": { - "path-type": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", - "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", - "dev": true, - "requires": { - "pify": "^3.0.0" - } - }, - "pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", - "dev": true - } - } - }, - "dns-equal": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz", - "integrity": "sha1-s55/HabrCnW6nBcySzR1PEfgZU0=", - "dev": true - }, - "dns-packet": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-1.3.1.tgz", - "integrity": "sha512-0UxfQkMhYAUaZI+xrNZOz/as5KgDU0M/fQ9b6SpkyLbk3GEswDi6PADJVaYJradtRVsRIlF1zLyOodbcTCDzUg==", - "dev": true, - "requires": { - "ip": "^1.1.0", - "safe-buffer": "^5.0.1" - } - }, - "dns-txt": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/dns-txt/-/dns-txt-2.0.2.tgz", - "integrity": "sha1-uR2Ab10nGI5Ks+fRB9iBocxGQrY=", - "dev": true, - "requires": { - "buffer-indexof": "^1.0.0" - } - }, - "domain-browser": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz", - "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==", - "dev": true - }, - "domain-context": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/domain-context/-/domain-context-0.5.1.tgz", - "integrity": "sha1-MhxmpBBVmHUHsjlqzF8E5T+5l8Q=" - }, - "domain-task": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/domain-task/-/domain-task-3.0.3.tgz", - "integrity": "sha1-T+fXQ5rP55LWm/jmv6ax41aGLUU=", - "requires": { - "domain-context": "^0.5.1", - "is-absolute-url": "^2.1.0", - "isomorphic-fetch": "^2.2.1" - } - }, - "domino": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/domino/-/domino-2.1.3.tgz", - "integrity": "sha512-EwjTbUv1Q/RLQOdn9k7ClHutrQcWGsfXaRQNOnM/KgK4xDBoLFEcIRFuBSxAx13Vfa63X029gXYrNFrSy+DOSg==" - }, - "duplexify": { - "version": "3.7.1", - "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", - "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", - "dev": true, - "requires": { - "end-of-stream": "^1.0.0", - "inherits": "^2.0.1", - "readable-stream": "^2.0.0", - "stream-shift": "^1.0.0" - } - }, - "ecc-jsbn": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", - "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", - "requires": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" - } - }, - "ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", - "dev": true - }, - "electron-to-chromium": { - "version": "1.3.199", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.199.tgz", - "integrity": "sha512-gachlDdHSK47s0N2e58GH9HMC6Z4ip0SfmYUa5iEbE50AKaOUXysaJnXMfKj0xB245jWbYcyFSH+th3rqsF8hA==", - "dev": true - }, - "elliptic": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.0.tgz", - "integrity": "sha512-eFOJTMyCYb7xtE/caJ6JJu+bhi67WCYNbkGSknu20pmM8Ke/bqOfdnZWxyoGN26JgfxTbXrsCkEw4KheCT/KGg==", - "dev": true, - "requires": { - "bn.js": "^4.4.0", - "brorand": "^1.0.1", - "hash.js": "^1.0.0", - "hmac-drbg": "^1.0.0", - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0", - "minimalistic-crypto-utils": "^1.0.0" - } - }, - "emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", - "dev": true - }, - "emojis-list": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz", - "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k=" - }, - "encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", - "dev": true - }, - "encoding": { - "version": "0.1.12", - "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.12.tgz", - "integrity": "sha1-U4tm8+5izRq1HsMjgp0flIDHS+s=", - "requires": { - "iconv-lite": "~0.4.13" - } - }, - "end-of-stream": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", - "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", - "dev": true, - "requires": { - "once": "^1.4.0" - } - }, - "engine.io-client": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.3.2.tgz", - "integrity": "sha512-y0CPINnhMvPuwtqXfsGuWE8BB66+B6wTtCofQDRecMQPYX3MYUZXFNKDhdrSe3EVjgOu4V3rxdeqN/Tr91IgbQ==", - "requires": { - "component-emitter": "1.2.1", - "component-inherit": "0.0.3", - "debug": "~3.1.0", - "engine.io-parser": "~2.1.1", - "has-cors": "1.1.0", - "indexof": "0.0.1", - "parseqs": "0.0.5", - "parseuri": "0.0.5", - "ws": "~6.1.0", - "xmlhttprequest-ssl": "~1.5.4", - "yeast": "0.1.2" - }, - "dependencies": { - "component-emitter": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", - "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=" - }, - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "requires": { - "ms": "2.0.0" - } - }, - "ws": { - "version": "6.1.4", - "resolved": "https://registry.npmjs.org/ws/-/ws-6.1.4.tgz", - "integrity": "sha512-eqZfL+NE/YQc1/ZynhojeV8q+H050oR8AZ2uIev7RU10svA9ZnJUddHcOUZTJLinZ9yEfdA2kSATS2qZK5fhJA==", - "requires": { - "async-limiter": "~1.0.0" - } - } - } - }, - "engine.io-parser": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.1.3.tgz", - "integrity": "sha512-6HXPre2O4Houl7c4g7Ic/XzPnHBvaEmN90vtRO9uLmwtRqQmTOw0QMevL1TOfL2Cpu1VzsaTmMotQgMdkzGkVA==", - "requires": { - "after": "0.8.2", - "arraybuffer.slice": "~0.0.7", - "base64-arraybuffer": "0.1.5", - "blob": "0.0.5", - "has-binary2": "~1.0.2" - } - }, - "enhanced-resolve": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.1.0.tgz", - "integrity": "sha512-F/7vkyTtyc/llOIn8oWclcB25KdRaiPBpZYDgJHgh/UHtpgT2p2eldQgtQnLtUvfMKPKxbRaQM/hHkvLHt1Vng==", - "requires": { - "graceful-fs": "^4.1.2", - "memory-fs": "^0.4.0", - "tapable": "^1.0.0" - } - }, - "err-code": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/err-code/-/err-code-1.1.2.tgz", - "integrity": "sha1-BuARbTAo9q70gGhJ6w6mp0iuaWA=", - "dev": true - }, - "errno": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", - "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==", - "requires": { - "prr": "~1.0.1" - } - }, - "error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "requires": { - "is-arrayish": "^0.2.1" - } - }, - "es5-ext": { - "version": "0.10.50", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.50.tgz", - "integrity": "sha512-KMzZTPBkeQV/JcSQhI5/z6d9VWJ3EnQ194USTUwIYZ2ZbpN8+SGXQKt1h68EX44+qt+Fzr8DO17vnxrw7c3agw==", - "requires": { - "es6-iterator": "~2.0.3", - "es6-symbol": "~3.1.1", - "next-tick": "^1.0.0" - } - }, - "es6-iterator": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", - "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", - "requires": { - "d": "1", - "es5-ext": "^0.10.35", - "es6-symbol": "^3.1.1" - } - }, - "es6-promise": { - "version": "4.2.8", - "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz", - "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==" - }, - "es6-promisify": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", - "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=", - "requires": { - "es6-promise": "^4.0.3" - } - }, - "es6-symbol": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz", - "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=", - "requires": { - "d": "1", - "es5-ext": "~0.10.14" - } - }, - "escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=", - "dev": true - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" - }, - "eslint-scope": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", - "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==", - "dev": true, - "requires": { - "esrecurse": "^4.1.0", - "estraverse": "^4.1.1" - } - }, - "esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" - }, - "esrecurse": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", - "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", - "dev": true, - "requires": { - "estraverse": "^4.1.0" - } - }, - "estraverse": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", - "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", - "dev": true - }, - "esutils": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", - "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=" - }, - "etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", - "dev": true - }, - "eventemitter2": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-5.0.1.tgz", - "integrity": "sha1-YZegldX7a1folC9v1+qtY6CclFI=" - }, - "eventemitter3": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.1.2.tgz", - "integrity": "sha512-tvtQIeLVHjDkJYnzf2dgVMxfuSGJeM/7UCG17TT4EumTfNtF+0nebF/4zWOIkCreAbtNqhGEboB6BWrwqNaw4Q==", - "dev": true - }, - "events": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.0.0.tgz", - "integrity": "sha512-Dc381HFWJzEOhQ+d8pkNon++bk9h6cdAoAj4iE6Q4y6xgTzySWXlKn05/TVNpjnfRqi/X0EpJEJohPjNI3zpVA==", - "dev": true - }, - "eventsource": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-1.0.7.tgz", - "integrity": "sha512-4Ln17+vVT0k8aWq+t/bF5arcS3EpT9gYtW66EPacdj/mAFevznsnyoHLPy2BA8gbIQeIHoPsvwmfBftfcG//BQ==", - "requires": { - "original": "^1.0.0" - } - }, - "evp_bytestokey": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", - "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", - "dev": true, - "requires": { - "md5.js": "^1.3.4", - "safe-buffer": "^5.1.1" - } - }, - "execa": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", - "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", - "dev": true, - "requires": { - "cross-spawn": "^6.0.0", - "get-stream": "^4.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" - }, - "dependencies": { - "cross-spawn": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", - "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", - "dev": true, - "requires": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - } - } - } - }, - "exit": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", - "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=", - "optional": true - }, - "expand-brackets": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", - "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", - "requires": { - "debug": "^2.3.3", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "posix-character-classes": "^0.1.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "express": { - "version": "4.17.1", - "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", - "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", - "dev": true, - "requires": { - "accepts": "~1.3.7", - "array-flatten": "1.1.1", - "body-parser": "1.19.0", - "content-disposition": "0.5.3", - "content-type": "~1.0.4", - "cookie": "0.4.0", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "~1.1.2", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "~1.1.2", - "fresh": "0.5.2", - "merge-descriptors": "1.0.1", - "methods": "~1.1.2", - "on-finished": "~2.3.0", - "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", - "proxy-addr": "~2.0.5", - "qs": "6.7.0", - "range-parser": "~1.2.1", - "safe-buffer": "5.1.2", - "send": "0.17.1", - "serve-static": "1.14.1", - "setprototypeof": "1.1.1", - "statuses": "~1.5.0", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" - }, - "dependencies": { - "array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=", - "dev": true - }, - "qs": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", - "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==", - "dev": true - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - } - } - }, - "extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" - }, - "extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "requires": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - }, - "dependencies": { - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "requires": { - "is-plain-object": "^2.0.4" - } - } - } - }, - "external-editor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", - "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", - "dev": true, - "requires": { - "chardet": "^0.7.0", - "iconv-lite": "^0.4.24", - "tmp": "^0.0.33" - }, - "dependencies": { - "tmp": { - "version": "0.0.33", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", - "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", - "dev": true, - "requires": { - "os-tmpdir": "~1.0.2" - } - } - } - }, - "extglob": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", - "requires": { - "array-unique": "^0.3.2", - "define-property": "^1.0.0", - "expand-brackets": "^2.1.4", - "extend-shallow": "^2.0.1", - "fragment-cache": "^0.2.1", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "requires": { - "is-extendable": "^0.1.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } - } - }, - "extsprintf": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" - }, - "fast-deep-equal": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", - "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=" - }, - "fast-json-stable-stringify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", - "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" - }, - "fastparse": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/fastparse/-/fastparse-1.1.2.tgz", - "integrity": "sha512-483XLLxTVIwWK3QTrMGRqUfUpoOs/0hbQrl2oz4J0pAcm3A3bu84wxTFqGqkJzewCLdME38xJLJAxBABfQT8sQ==" - }, - "faye-websocket": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.10.0.tgz", - "integrity": "sha1-TkkvjQTftviQA1B/btvy1QHnxvQ=", - "dev": true, - "requires": { - "websocket-driver": ">=0.5.1" - } - }, - "figgy-pudding": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.1.tgz", - "integrity": "sha512-vNKxJHTEKNThjfrdJwHc7brvM6eVevuO5nTj6ez8ZQ1qbXTvGthucRF7S4vf2cr71QVnT70V34v0S1DyQsti0w==", - "dev": true - }, - "figures": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", - "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", - "dev": true, - "requires": { - "escape-string-regexp": "^1.0.5" - } - }, - "file-loader": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-3.0.1.tgz", - "integrity": "sha512-4sNIOXgtH/9WZq4NvlfU3Opn5ynUsqBwSLyM+I7UOwdGigTBYfVVQEwe/msZNX/j4pCJTIM14Fsw66Svo1oVrw==", - "dev": true, - "requires": { - "loader-utils": "^1.0.2", - "schema-utils": "^1.0.0" - } - }, - "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "finalhandler": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", - "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", - "dev": true, - "requires": { - "debug": "2.6.9", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "on-finished": "~2.3.0", - "parseurl": "~1.3.3", - "statuses": "~1.5.0", - "unpipe": "~1.0.0" - } - }, - "find-cache-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", - "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", - "dev": true, - "requires": { - "commondir": "^1.0.1", - "make-dir": "^2.0.0", - "pkg-dir": "^3.0.0" - } - }, - "find-up": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", - "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", - "requires": { - "path-exists": "^2.0.0", - "pinkie-promise": "^2.0.0" - } - }, - "flush-write-stream": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz", - "integrity": "sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "readable-stream": "^2.3.6" - } - }, - "follow-redirects": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.7.0.tgz", - "integrity": "sha512-m/pZQy4Gj287eNy94nivy5wchN3Kp+Q5WgUPNy5lJSZ3sgkVKSYV/ZChMAQVIgx1SqfZ2zBZtPA2YlXIWxxJOQ==", - "dev": true, - "requires": { - "debug": "^3.2.6" - }, - "dependencies": { - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - } - } - }, - "font-awesome": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/font-awesome/-/font-awesome-4.7.0.tgz", - "integrity": "sha1-j6jPBBGhoxr9B7BtKQK7n8gVoTM=" - }, - "for-in": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", - "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=" - }, - "for-own": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", - "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", - "dev": true, - "requires": { - "for-in": "^1.0.1" - } - }, - "forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" - }, - "form-data": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", - "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - } - }, - "forwarded": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", - "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=", - "dev": true - }, - "fragment-cache": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", - "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", - "requires": { - "map-cache": "^0.2.2" - } - }, - "fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", - "dev": true - }, - "from2": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", - "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=", - "dev": true, - "requires": { - "inherits": "^2.0.1", - "readable-stream": "^2.0.0" - } - }, - "fs-minipass": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.6.tgz", - "integrity": "sha512-crhvyXcMejjv3Z5d2Fa9sf5xLYVCF5O1c71QxbVnbLsmYMBEvDAftewesN/HhY03YRoA7zOMxjNGrF5svGaaeQ==", - "dev": true, - "requires": { - "minipass": "^2.2.1" - } - }, - "fs-write-stream-atomic": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz", - "integrity": "sha1-tH31NJPvkR33VzHnCp3tAYnbQMk=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "iferr": "^0.1.5", - "imurmurhash": "^0.1.4", - "readable-stream": "1 || 2" - } - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" - }, - "fsevents": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.9.tgz", - "integrity": "sha512-oeyj2H3EjjonWcFjD5NvZNE9Rqe4UW+nQBU2HNeKw0koVLEFIhtyETyAakeAM3de7Z/SW5kcA+fZUait9EApnw==", - "dev": true, - "optional": true, - "requires": { - "nan": "^2.12.1", - "node-pre-gyp": "^0.12.0" - }, - "dependencies": { - "abbrev": { - "version": "1.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "ansi-regex": { - "version": "2.1.1", - "bundled": true, - "dev": true - }, - "aproba": { - "version": "1.2.0", - "bundled": true, - "dev": true, - "optional": true - }, - "are-we-there-yet": { - "version": "1.1.5", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "delegates": "^1.0.0", - "readable-stream": "^2.0.6" - } - }, - "balanced-match": { - "version": "1.0.0", - "bundled": true, - "dev": true - }, - "brace-expansion": { - "version": "1.1.11", - "bundled": true, - "dev": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "chownr": { - "version": "1.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "code-point-at": { - "version": "1.1.0", - "bundled": true, - "dev": true - }, - "concat-map": { - "version": "0.0.1", - "bundled": true, - "dev": true - }, - "console-control-strings": { - "version": "1.1.0", - "bundled": true, - "dev": true - }, - "core-util-is": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "debug": { - "version": "4.1.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "ms": "^2.1.1" - } - }, - "deep-extend": { - "version": "0.6.0", - "bundled": true, - "dev": true, - "optional": true - }, - "delegates": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "detect-libc": { - "version": "1.0.3", - "bundled": true, - "dev": true, - "optional": true - }, - "fs-minipass": { - "version": "1.2.5", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minipass": "^2.2.1" - } - }, - "fs.realpath": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "gauge": { - "version": "2.7.4", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "aproba": "^1.0.3", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.0", - "object-assign": "^4.1.0", - "signal-exit": "^3.0.0", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wide-align": "^1.1.0" - } - }, - "glob": { - "version": "7.1.3", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "has-unicode": { - "version": "2.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "iconv-lite": { - "version": "0.4.24", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, - "ignore-walk": { - "version": "3.0.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minimatch": "^3.0.4" - } - }, - "inflight": { - "version": "1.0.6", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.3", - "bundled": true, - "dev": true - }, - "ini": { - "version": "1.3.5", - "bundled": true, - "dev": true, - "optional": true - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "isarray": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "minimatch": { - "version": "3.0.4", - "bundled": true, - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "0.0.8", - "bundled": true, - "dev": true - }, - "minipass": { - "version": "2.3.5", - "bundled": true, - "dev": true, - "requires": { - "safe-buffer": "^5.1.2", - "yallist": "^3.0.0" - } - }, - "minizlib": { - "version": "1.2.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minipass": "^2.2.1" - } - }, - "mkdirp": { - "version": "0.5.1", - "bundled": true, - "dev": true, - "requires": { - "minimist": "0.0.8" - } - }, - "ms": { - "version": "2.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "needle": { - "version": "2.3.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "debug": "^4.1.0", - "iconv-lite": "^0.4.4", - "sax": "^1.2.4" - } - }, - "node-pre-gyp": { - "version": "0.12.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "detect-libc": "^1.0.2", - "mkdirp": "^0.5.1", - "needle": "^2.2.1", - "nopt": "^4.0.1", - "npm-packlist": "^1.1.6", - "npmlog": "^4.0.2", - "rc": "^1.2.7", - "rimraf": "^2.6.1", - "semver": "^5.3.0", - "tar": "^4" - } - }, - "nopt": { - "version": "4.0.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "abbrev": "1", - "osenv": "^0.1.4" - } - }, - "npm-bundled": { - "version": "1.0.6", - "bundled": true, - "dev": true, - "optional": true - }, - "npm-packlist": { - "version": "1.4.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "ignore-walk": "^3.0.1", - "npm-bundled": "^1.0.1" - } - }, - "npmlog": { - "version": "4.1.2", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "are-we-there-yet": "~1.1.2", - "console-control-strings": "~1.1.0", - "gauge": "~2.7.3", - "set-blocking": "~2.0.0" - } - }, - "number-is-nan": { - "version": "1.0.1", - "bundled": true, - "dev": true - }, - "object-assign": { - "version": "4.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "once": { - "version": "1.4.0", - "bundled": true, - "dev": true, - "requires": { - "wrappy": "1" - } - }, - "os-homedir": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "os-tmpdir": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "osenv": { - "version": "0.1.5", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.0" - } - }, - "path-is-absolute": { - "version": "1.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "process-nextick-args": { - "version": "2.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "rc": { - "version": "1.2.8", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "bundled": true, - "dev": true, - "optional": true - } - } - }, - "readable-stream": { - "version": "2.3.6", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "rimraf": { - "version": "2.6.3", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "glob": "^7.1.3" - } - }, - "safe-buffer": { - "version": "5.1.2", - "bundled": true, - "dev": true - }, - "safer-buffer": { - "version": "2.1.2", - "bundled": true, - "dev": true, - "optional": true - }, - "sax": { - "version": "1.2.4", - "bundled": true, - "dev": true, - "optional": true - }, - "semver": { - "version": "5.7.0", - "bundled": true, - "dev": true, - "optional": true - }, - "set-blocking": { - "version": "2.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "signal-exit": { - "version": "3.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "string-width": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, - "string_decoder": { - "version": "1.1.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "safe-buffer": "~5.1.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "bundled": true, - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "strip-json-comments": { - "version": "2.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "tar": { - "version": "4.4.8", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "chownr": "^1.1.1", - "fs-minipass": "^1.2.5", - "minipass": "^2.3.4", - "minizlib": "^1.1.1", - "mkdirp": "^0.5.0", - "safe-buffer": "^5.1.2", - "yallist": "^3.0.2" - } - }, - "util-deprecate": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "wide-align": { - "version": "1.1.3", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "string-width": "^1.0.2 || 2" - } - }, - "wrappy": { - "version": "1.0.2", - "bundled": true, - "dev": true - }, - "yallist": { - "version": "3.0.3", - "bundled": true, - "dev": true - } - } - }, - "fstream": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz", - "integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==", - "requires": { - "graceful-fs": "^4.1.2", - "inherits": "~2.0.0", - "mkdirp": ">=0.5 0", - "rimraf": "2" - } - }, - "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" - }, - "gauge": { - "version": "2.7.4", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", - "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", - "requires": { - "aproba": "^1.0.3", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.0", - "object-assign": "^4.1.0", - "signal-exit": "^3.0.0", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wide-align": "^1.1.0" - } - }, - "gaze": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/gaze/-/gaze-1.1.3.tgz", - "integrity": "sha512-BRdNm8hbWzFzWHERTrejLqwHDfS4GibPoq5wjTPIoJHoBtKGPg3xAFfxmM+9ztbXelxcf2hwQcaz1PtmFeue8g==", - "optional": true, - "requires": { - "globule": "^1.0.0" - } - }, - "genfun": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/genfun/-/genfun-5.0.0.tgz", - "integrity": "sha512-KGDOARWVga7+rnB3z9Sd2Letx515owfk0hSxHGuqjANb1M+x2bGZGqHLiozPsYMdM2OubeMni/Hpwmjq6qIUhA==", - "dev": true - }, - "get-caller-file": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", - "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==" - }, - "get-stdin": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", - "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=" - }, - "get-stream": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", - "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", - "dev": true, - "requires": { - "pump": "^3.0.0" - } - }, - "get-value": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", - "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=" - }, - "getpass": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", - "requires": { - "assert-plus": "^1.0.0" - } - }, - "glob": { - "version": "7.1.4", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", - "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "glob-parent": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", - "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", - "dev": true, - "requires": { - "is-glob": "^3.1.0", - "path-dirname": "^1.0.0" - }, - "dependencies": { - "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true, - "requires": { - "is-extglob": "^2.1.0" - } - } - } - }, - "globals": { - "version": "9.18.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", - "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==", - "dev": true - }, - "globby": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz", - "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=", - "optional": true, - "requires": { - "array-union": "^1.0.1", - "arrify": "^1.0.0", - "glob": "^7.0.3", - "object-assign": "^4.0.1", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" - } - }, - "globule": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/globule/-/globule-1.2.1.tgz", - "integrity": "sha512-g7QtgWF4uYSL5/dn71WxubOrS7JVGCnFPEnoeChJmBnyR9Mw8nGoEwOgJL/RC2Te0WhbsEUCejfH8SZNJ+adYQ==", - "optional": true, - "requires": { - "glob": "~7.1.1", - "lodash": "~4.17.10", - "minimatch": "~3.0.2" - } - }, - "graceful-fs": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.0.tgz", - "integrity": "sha512-jpSvDPV4Cq/bgtpndIWbI5hmYxhQGHPC4d4cqBPb4DLniCfhJokdXhwhaDuLBGLQdvvRum/UiX6ECVIPvDXqdg==" - }, - "hammerjs": { - "version": "2.0.8", - "resolved": "https://registry.npmjs.org/hammerjs/-/hammerjs-2.0.8.tgz", - "integrity": "sha1-BO93hiz/K7edMPdpIJWTAiK/YPE=" - }, - "handle-thing": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.0.tgz", - "integrity": "sha512-d4sze1JNC454Wdo2fkuyzCr6aHcbL6PGGuFAz0Li/NcOm1tCHGnWDRmJP85dh9IhQErTc2svWFEX5xHIOo//kQ==", - "dev": true - }, - "har-schema": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", - "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" - }, - "har-validator": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", - "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", - "requires": { - "ajv": "^6.5.5", - "har-schema": "^2.0.0" - } - }, - "has-ansi": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", - "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "has-binary2": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-binary2/-/has-binary2-1.0.3.tgz", - "integrity": "sha512-G1LWKhDSvhGeAQ8mPVQlqNcOB2sJdwATtZKl2pDKKHfpf/rYj24lkinxf69blJbnsvtqqNU+L3SL50vzZhXOnw==", - "requires": { - "isarray": "2.0.1" - }, - "dependencies": { - "isarray": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", - "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=" - } - } - }, - "has-cors": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/has-cors/-/has-cors-1.1.0.tgz", - "integrity": "sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk=" - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" - }, - "has-symbols": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz", - "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=" - }, - "has-unicode": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=" - }, - "has-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", - "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", - "requires": { - "get-value": "^2.0.6", - "has-values": "^1.0.0", - "isobject": "^3.0.0" - } - }, - "has-values": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", - "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", - "requires": { - "is-number": "^3.0.0", - "kind-of": "^4.0.0" - }, - "dependencies": { - "kind-of": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", - "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "hash-base": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz", - "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=", - "dev": true, - "requires": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } - }, - "hash.js": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", - "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "minimalistic-assert": "^1.0.1" - } - }, - "hmac-drbg": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", - "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", - "dev": true, - "requires": { - "hash.js": "^1.0.3", - "minimalistic-assert": "^1.0.0", - "minimalistic-crypto-utils": "^1.0.1" - } - }, - "hosted-git-info": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.7.1.tgz", - "integrity": "sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w==" - }, - "hpack.js": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", - "integrity": "sha1-h3dMCUnlE/QuhFdbPEVoH63ioLI=", - "dev": true, - "requires": { - "inherits": "^2.0.1", - "obuf": "^1.0.0", - "readable-stream": "^2.0.1", - "wbuf": "^1.1.0" - } - }, - "html-entities": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-1.2.1.tgz", - "integrity": "sha1-DfKTUfByEWNRXfueVUPl9u7VFi8=", - "dev": true - }, - "http-cache-semantics": { - "version": "3.8.1", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-3.8.1.tgz", - "integrity": "sha512-5ai2iksyV8ZXmnZhHH4rWPoxxistEexSi5936zIQ1bnNTW5VnA85B6P/VpXiRM017IgRvb2kKo1a//y+0wSp3w==", - "dev": true - }, - "http-deceiver": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", - "integrity": "sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc=", - "dev": true - }, - "http-errors": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", - "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", - "dev": true, - "requires": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.1", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.0" - }, - "dependencies": { - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", - "dev": true - } - } - }, - "http-parser-js": { - "version": "0.4.10", - "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.4.10.tgz", - "integrity": "sha1-ksnBN0w1CF912zWexWzCV8u5P6Q=", - "dev": true - }, - "http-proxy": { - "version": "1.17.0", - "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.17.0.tgz", - "integrity": "sha512-Taqn+3nNvYRfJ3bGvKfBSRwy1v6eePlm3oc/aWVxZp57DQr5Eq3xhKJi7Z4hZpS8PC3H4qI+Yly5EmFacGuA/g==", - "dev": true, - "requires": { - "eventemitter3": "^3.0.0", - "follow-redirects": "^1.0.0", - "requires-port": "^1.0.0" - } - }, - "http-proxy-agent": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz", - "integrity": "sha512-qwHbBLV7WviBl0rQsOzH6o5lwyOIvwp/BdFnvVxXORldu5TmjFfjzBcWUWS5kWAZhmv+JtiDhSuQCp4sBfbIgg==", - "dev": true, - "requires": { - "agent-base": "4", - "debug": "3.1.0" - }, - "dependencies": { - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - } - } - }, - "http-proxy-middleware": { - "version": "0.19.1", - "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-0.19.1.tgz", - "integrity": "sha512-yHYTgWMQO8VvwNS22eLLloAkvungsKdKTLO8AJlftYIKNfJr3GK3zK0ZCfzDDGUBttdGc8xFy1mCitvNKQtC3Q==", - "dev": true, - "requires": { - "http-proxy": "^1.17.0", - "is-glob": "^4.0.0", - "lodash": "^4.17.11", - "micromatch": "^3.1.10" - } - }, - "http-signature": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", - "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", - "requires": { - "assert-plus": "^1.0.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" - } - }, - "https-browserify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", - "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=", - "dev": true - }, - "https-proxy-agent": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.2.tgz", - "integrity": "sha512-c8Ndjc9Bkpfx/vCJueCPy0jlP4ccCCSNDp8xwCZzPjKJUm+B+u9WX2x98Qx4n1PiMNTWo3D7KK5ifNV/yJyRzg==", - "requires": { - "agent-base": "^4.3.0", - "debug": "^3.1.0" - }, - "dependencies": { - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "requires": { - "ms": "^2.1.1" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - } - } - }, - "humanize-ms": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", - "integrity": "sha1-xG4xWaKT9riW2ikxbYtv6Lt5u+0=", - "dev": true, - "requires": { - "ms": "^2.0.0" - } - }, - "iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, - "ieee754": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", - "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==", - "dev": true - }, - "iferr": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/iferr/-/iferr-0.1.5.tgz", - "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE=", - "dev": true - }, - "ignore": { - "version": "3.3.10", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz", - "integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==", - "dev": true - }, - "ignore-walk": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.1.tgz", - "integrity": "sha512-DTVlMx3IYPe0/JJcYP7Gxg7ttZZu3IInhuEhbchuqneY9wWe5Ojy2mXLBaQFUQmo0AW2r3qG7m1mg86js+gnlQ==", - "dev": true, - "requires": { - "minimatch": "^3.0.4" - } - }, - "image-size": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/image-size/-/image-size-0.5.5.tgz", - "integrity": "sha1-Cd/Uq50g4p6xw+gLiZA3jfnjy5w=", - "dev": true, - "optional": true - }, - "immediate": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", - "integrity": "sha1-nbHb0Pr43m++D13V5Wu2BigN5ps=" - }, - "import-cwd": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/import-cwd/-/import-cwd-2.1.0.tgz", - "integrity": "sha1-qmzzbnInYShcs3HsZRn1PiQ1sKk=", - "dev": true, - "requires": { - "import-from": "^2.1.0" - } - }, - "import-fresh": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz", - "integrity": "sha1-2BNVwVYS04bGH53dOSLUMEgipUY=", - "dev": true, - "requires": { - "caller-path": "^2.0.0", - "resolve-from": "^3.0.0" - } - }, - "import-from": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/import-from/-/import-from-2.1.0.tgz", - "integrity": "sha1-M1238qev/VOqpHHUuAId7ja387E=", - "dev": true, - "requires": { - "resolve-from": "^3.0.0" - } - }, - "import-local": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-2.0.0.tgz", - "integrity": "sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ==", - "dev": true, - "requires": { - "pkg-dir": "^3.0.0", - "resolve-cwd": "^2.0.0" - } - }, - "imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", - "dev": true - }, - "in-publish": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/in-publish/-/in-publish-2.0.0.tgz", - "integrity": "sha1-4g/146KvwmkDILbcVSaCqcf631E=", - "optional": true - }, - "indent-string": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", - "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", - "optional": true, - "requires": { - "repeating": "^2.0.0" - } - }, - "indexof": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", - "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=" - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "ini": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", - "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==" - }, - "inquirer": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.3.1.tgz", - "integrity": "sha512-MmL624rfkFt4TG9y/Jvmt8vdmOo836U7Y0Hxr2aFk3RelZEGX4Igk0KabWrcaaZaTv9uzglOqWh1Vly+FAWAXA==", - "dev": true, - "requires": { - "ansi-escapes": "^3.2.0", - "chalk": "^2.4.2", - "cli-cursor": "^2.1.0", - "cli-width": "^2.0.0", - "external-editor": "^3.0.3", - "figures": "^2.0.0", - "lodash": "^4.17.11", - "mute-stream": "0.0.7", - "run-async": "^2.2.0", - "rxjs": "^6.4.0", - "string-width": "^2.1.0", - "strip-ansi": "^5.1.0", - "through": "^2.3.6" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true - }, - "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true, - "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - }, - "dependencies": { - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "^3.0.0" - } - } - } - }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "requires": { - "ansi-regex": "^4.1.0" - }, - "dependencies": { - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true - } - } - } - } - }, - "internal-ip": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/internal-ip/-/internal-ip-4.3.0.tgz", - "integrity": "sha512-S1zBo1D6zcsyuC6PMmY5+55YMILQ9av8lotMx447Bq6SAgo/sDK6y6uUKmuYhW7eacnIhFfsPmCNYdDzsnnDCg==", - "dev": true, - "requires": { - "default-gateway": "^4.2.0", - "ipaddr.js": "^1.9.0" - } - }, - "interpret": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.2.0.tgz", - "integrity": "sha512-mT34yGKMNceBQUoVn7iCDKDntA7SC6gycMAWzGx1z/CMCTV7b2AAtXlo3nRyHZ1FelRkQbQjprHSYGwzLtkVbw==", - "dev": true - }, - "invariant": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", - "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", - "dev": true, - "requires": { - "loose-envify": "^1.0.0" - } - }, - "invert-kv": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", - "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", - "optional": true - }, - "ip": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", - "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=", - "dev": true - }, - "ip-regex": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-2.1.0.tgz", - "integrity": "sha1-+ni/XS5pE8kRzp+BnuUUa7bYROk=", - "dev": true - }, - "ipaddr.js": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.0.tgz", - "integrity": "sha512-M4Sjn6N/+O6/IXSJseKqHoFc+5FdGJ22sXqnjTpdZweHK64MzEPAyQZyEU3R/KRv2GLoa7nNtg/C2Ev6m7z+eA==", - "dev": true - }, - "is-absolute-url": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-2.1.0.tgz", - "integrity": "sha1-UFMN+4T8yap9vnhS6Do3uTufKqY=" - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=" - }, - "is-binary-path": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", - "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", - "dev": true, - "requires": { - "binary-extensions": "^1.0.0" - } - }, - "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - }, - "dependencies": { - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" - } - } - }, - "is-directory": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz", - "integrity": "sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE=", - "dev": true - }, - "is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=" - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true - }, - "is-finite": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz", - "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "is-glob": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", - "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", - "dev": true, - "requires": { - "is-extglob": "^2.1.1" - } - }, - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-path-cwd": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", - "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=", - "optional": true - }, - "is-path-in-cwd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz", - "integrity": "sha512-FjV1RTW48E7CWM7eE/J2NJvAEEVektecDBVBE5Hh3nM1Jd0kvhHtX68Pr3xsDf857xt3Y4AkwVULK1Vku62aaQ==", - "optional": true, - "requires": { - "is-path-inside": "^1.0.0" - } - }, - "is-path-inside": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", - "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", - "optional": true, - "requires": { - "path-is-inside": "^1.0.1" - } - }, - "is-plain-obj": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", - "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=", - "dev": true - }, - "is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "requires": { - "isobject": "^3.0.1" - } - }, - "is-promise": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", - "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=", - "dev": true - }, - "is-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" - }, - "is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" - }, - "is-utf8": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", - "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=" - }, - "is-windows": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", - "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==" - }, - "is-wsl": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", - "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=", - "dev": true - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - }, - "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" - }, - "isomorphic-fetch": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz", - "integrity": "sha1-YRrhrPFPXoH3KVB0coGf6XM1WKk=", - "requires": { - "node-fetch": "^1.0.1", - "whatwg-fetch": ">=0.10.0" - } - }, - "isstream": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" - }, - "istanbul-instrumenter-loader": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/istanbul-instrumenter-loader/-/istanbul-instrumenter-loader-3.0.1.tgz", - "integrity": "sha512-a5SPObZgS0jB/ixaKSMdn6n/gXSrK2S6q/UfRJBT3e6gQmVjwZROTODQsYW5ZNwOu78hG62Y3fWlebaVOL0C+w==", - "dev": true, - "requires": { - "convert-source-map": "^1.5.0", - "istanbul-lib-instrument": "^1.7.3", - "loader-utils": "^1.1.0", - "schema-utils": "^0.3.0" - }, - "dependencies": { - "ajv": { - "version": "5.5.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", - "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", - "dev": true, - "requires": { - "co": "^4.6.0", - "fast-deep-equal": "^1.0.0", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.3.0" - } - }, - "fast-deep-equal": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", - "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=", - "dev": true - }, - "json-schema-traverse": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", - "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=", - "dev": true - }, - "schema-utils": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.3.0.tgz", - "integrity": "sha1-9YdyIs4+kx7a4DnxfrNxbnE3+M8=", - "dev": true, - "requires": { - "ajv": "^5.0.0" - } - } - } - }, - "istanbul-lib-coverage": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-1.2.1.tgz", - "integrity": "sha512-PzITeunAgyGbtY1ibVIUiV679EFChHjoMNRibEIobvmrCRaIgwLxNucOSimtNWUhEib/oO7QY2imD75JVgCJWQ==", - "dev": true - }, - "istanbul-lib-instrument": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-1.10.2.tgz", - "integrity": "sha512-aWHxfxDqvh/ZlxR8BBaEPVSWDPUkGD63VjGQn3jcw8jCp7sHEMKcrj4xfJn/ABzdMEHiQNyvDQhqm5o8+SQg7A==", - "dev": true, - "requires": { - "babel-generator": "^6.18.0", - "babel-template": "^6.16.0", - "babel-traverse": "^6.18.0", - "babel-types": "^6.18.0", - "babylon": "^6.18.0", - "istanbul-lib-coverage": "^1.2.1", - "semver": "^5.3.0" - } - }, - "jasmine": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/jasmine/-/jasmine-2.8.0.tgz", - "integrity": "sha1-awicChFXax8W3xG4AUbZHU6Lij4=", - "optional": true, - "requires": { - "exit": "^0.1.2", - "glob": "^7.0.6", - "jasmine-core": "~2.8.0" - } - }, - "jasmine-core": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-2.8.0.tgz", - "integrity": "sha1-vMl5rh+f0FcB5F5S5l06XWPxok4=", - "optional": true - }, - "jasminewd2": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/jasminewd2/-/jasminewd2-2.2.0.tgz", - "integrity": "sha1-43zwsX8ZnM4jvqcbIDk5Uka07E4=", - "optional": true - }, - "jquery": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.3.1.tgz", - "integrity": "sha512-Ubldcmxp5np52/ENotGxlLe6aGMvmF4R8S6tZjsP6Knsaxd/xp3Zrh50cG93lR6nPXyUFwzN3ZSOQI0wRJNdGg==" - }, - "js-base64": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.5.1.tgz", - "integrity": "sha512-M7kLczedRMYX4L8Mdh4MzyAMM9O5osx+4FcOQuTvr3A9F2D9S5JXheN0ewNbrvK2UatkTRhL5ejGmGSjNMiZuw==", - "optional": true - }, - "js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" - }, - "js-yaml": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", - "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", - "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - } - }, - "jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" - }, - "jsesc": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", - "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=" - }, - "json-parse-better-errors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", - "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", - "dev": true - }, - "json-schema": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", - "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" - }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" - }, - "json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" - }, - "json3": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/json3/-/json3-3.3.3.tgz", - "integrity": "sha512-c7/8mbUsKigAbLkD5B010BK4D9LZm7A1pNItkEwiUZRpIN66exu/e7YQWysGun+TRKaJp8MhemM+VkfWv42aCA==", - "dev": true - }, - "json5": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", - "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", - "requires": { - "minimist": "^1.2.0" - } - }, - "jsonparse": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", - "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=", - "dev": true - }, - "jsprim": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", - "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", - "requires": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.2.3", - "verror": "1.10.0" - } - }, - "jszip": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.2.2.tgz", - "integrity": "sha512-NmKajvAFQpbg3taXQXr/ccS2wcucR1AZ+NtyWp2Nq7HHVsXhcJFR8p0Baf32C2yVvBylFWVeKf+WI2AnvlPhpA==", - "requires": { - "lie": "~3.3.0", - "pako": "~1.0.2", - "readable-stream": "~2.3.6", - "set-immediate-shim": "~1.0.1" - } - }, - "karma-source-map-support": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/karma-source-map-support/-/karma-source-map-support-1.4.0.tgz", - "integrity": "sha512-RsBECncGO17KAoJCYXjv+ckIz+Ii9NCi+9enk+rq6XC81ezYkb4/RHE6CTXdA7IOJqoF3wcaLfVG0CPmE5ca6A==", - "dev": true, - "requires": { - "source-map-support": "^0.5.5" - } - }, - "killable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/killable/-/killable-1.0.1.tgz", - "integrity": "sha512-LzqtLKlUwirEUyl/nicirVmNiPvYs7l5n8wOPP7fyJVpUPkvCnW/vuiXGpylGUlnPDnB7311rARzAt3Mhswpjg==", - "dev": true - }, - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" - }, - "lcid": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", - "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", - "optional": true, - "requires": { - "invert-kv": "^1.0.0" - } - }, - "less": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/less/-/less-3.9.0.tgz", - "integrity": "sha512-31CmtPEZraNUtuUREYjSqRkeETFdyEHSEPAGq4erDlUXtda7pzNmctdljdIagSb589d/qXGWiiP31R5JVf+v0w==", - "dev": true, - "requires": { - "clone": "^2.1.2", - "errno": "^0.1.1", - "graceful-fs": "^4.1.2", - "image-size": "~0.5.0", - "mime": "^1.4.1", - "mkdirp": "^0.5.0", - "promise": "^7.1.1", - "request": "^2.83.0", - "source-map": "~0.6.0" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "optional": true - } - } - }, - "less-loader": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/less-loader/-/less-loader-4.1.0.tgz", - "integrity": "sha512-KNTsgCE9tMOM70+ddxp9yyt9iHqgmSs0yTZc5XH5Wo+g80RWRIYNqE58QJKm/yMud5wZEvz50ugRDuzVIkyahg==", - "dev": true, - "requires": { - "clone": "^2.1.1", - "loader-utils": "^1.1.0", - "pify": "^3.0.0" - }, - "dependencies": { - "pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", - "dev": true - } - } - }, - "license-webpack-plugin": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/license-webpack-plugin/-/license-webpack-plugin-2.1.1.tgz", - "integrity": "sha512-TiarZIg5vkQ2rGdYJn2+5YxO/zqlqjpK5IVglr7OfmrN1sBCakS+PQrsP2uC5gtve1ZDb9WMSUMlmHDQ0FoW4w==", - "dev": true, - "requires": { - "@types/webpack-sources": "^0.1.5", - "webpack-sources": "^1.2.0" - } - }, - "lie": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz", - "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==", - "requires": { - "immediate": "~3.0.5" - } - }, - "load-json-file": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", - "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", - "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0", - "strip-bom": "^2.0.0" - } - }, - "loader-runner": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.4.0.tgz", - "integrity": "sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw==", - "dev": true - }, - "loader-utils": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.2.3.tgz", - "integrity": "sha512-fkpz8ejdnEMG3s37wGL07iSBDg99O9D5yflE9RGNH3hRdx9SOwYfnGYdZOUIZitN8E+E2vkq3MUMYMvPYl5ZZA==", - "requires": { - "big.js": "^5.2.2", - "emojis-list": "^2.0.0", - "json5": "^1.0.1" - } - }, - "locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, - "requires": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - }, - "dependencies": { - "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", - "dev": true - } - } - }, - "lodash": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==" - }, - "lodash.clonedeep": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", - "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=", - "dev": true - }, - "lodash.tail": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lodash.tail/-/lodash.tail-4.1.1.tgz", - "integrity": "sha1-0jM6NtnncXyK0vfKyv7HwytERmQ=", - "dev": true - }, - "log-symbols": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", - "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", - "requires": { - "chalk": "^2.0.1" - } - }, - "loglevel": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.6.3.tgz", - "integrity": "sha512-LoEDv5pgpvWgPF4kNYuIp0qqSJVWak/dML0RY74xlzMZiT9w77teNAwKYKWBTYjlokMirg+o3jBwp+vlLrcfAA==", - "dev": true - }, - "loglevelnext": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/loglevelnext/-/loglevelnext-1.0.5.tgz", - "integrity": "sha512-V/73qkPuJmx4BcBF19xPBr+0ZRVBhc4POxvZTZdMeXpJ4NItXSJ/MSwuFT0kQJlCbXvdlZoQQ/418bS1y9Jh6A==", - "requires": { - "es6-symbol": "^3.1.1", - "object.assign": "^4.1.0" - } - }, - "loose-envify": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", - "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", - "dev": true, - "requires": { - "js-tokens": "^3.0.0 || ^4.0.0" - } - }, - "loud-rejection": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", - "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=", - "optional": true, - "requires": { - "currently-unhandled": "^0.4.1", - "signal-exit": "^3.0.0" - } - }, - "lru-cache": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", - "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", - "optional": true, - "requires": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" - } - }, - "magic-string": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.2.tgz", - "integrity": "sha512-iLs9mPjh9IuTtRsqqhNGYcZXGei0Nh/A4xirrsqW7c+QhKVFL2vm7U09ru6cHRD22azaP/wMDgI+HCqbETMTtg==", - "dev": true, - "requires": { - "sourcemap-codec": "^1.4.4" - } - }, - "make-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", - "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", - "dev": true, - "requires": { - "pify": "^4.0.1", - "semver": "^5.6.0" - }, - "dependencies": { - "pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", - "dev": true - } - } - }, - "make-error": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.5.tgz", - "integrity": "sha512-c3sIjNUow0+8swNwVpqoH4YCShKNFkMaw6oH1mNS2haDZQqkeZFlHS3dhoeEbKKmJB4vXpJucU6oH75aDYeE9g==", - "optional": true - }, - "make-fetch-happen": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-4.0.2.tgz", - "integrity": "sha512-YMJrAjHSb/BordlsDEcVcPyTbiJKkzqMf48N8dAJZT9Zjctrkb6Yg4TY9Sq2AwSIQJFn5qBBKVTYt3vP5FMIHA==", - "dev": true, - "requires": { - "agentkeepalive": "^3.4.1", - "cacache": "^11.3.3", - "http-cache-semantics": "^3.8.1", - "http-proxy-agent": "^2.1.0", - "https-proxy-agent": "^2.2.1", - "lru-cache": "^5.1.1", - "mississippi": "^3.0.0", - "node-fetch-npm": "^2.0.2", - "promise-retry": "^1.1.1", - "socks-proxy-agent": "^4.0.0", - "ssri": "^6.0.0" - }, - "dependencies": { - "lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "dev": true, - "requires": { - "yallist": "^3.0.2" - } - }, - "yallist": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.3.tgz", - "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==", - "dev": true - } - } - }, - "mamacro": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/mamacro/-/mamacro-0.0.3.tgz", - "integrity": "sha512-qMEwh+UujcQ+kbz3T6V+wAmO2U8veoq2w+3wY8MquqwVA3jChfwY+Tk52GZKDfACEPjuZ7r2oJLejwpt8jtwTA==", - "dev": true - }, - "map-age-cleaner": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz", - "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==", - "dev": true, - "requires": { - "p-defer": "^1.0.0" - } - }, - "map-cache": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", - "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=" - }, - "map-obj": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", - "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=" - }, - "map-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", - "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", - "requires": { - "object-visit": "^1.0.0" - } - }, - "md5.js": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", - "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", - "dev": true, - "requires": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1", - "safe-buffer": "^5.1.2" - } - }, - "media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", - "dev": true - }, - "mem": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/mem/-/mem-4.3.0.tgz", - "integrity": "sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w==", - "dev": true, - "requires": { - "map-age-cleaner": "^0.1.1", - "mimic-fn": "^2.0.0", - "p-is-promise": "^2.0.0" - } - }, - "memory-fs": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", - "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=", - "requires": { - "errno": "^0.1.3", - "readable-stream": "^2.0.1" - } - }, - "meow": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", - "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", - "optional": true, - "requires": { - "camelcase-keys": "^2.0.0", - "decamelize": "^1.1.2", - "loud-rejection": "^1.0.0", - "map-obj": "^1.0.1", - "minimist": "^1.1.3", - "normalize-package-data": "^2.3.4", - "object-assign": "^4.0.1", - "read-pkg-up": "^1.0.1", - "redent": "^1.0.0", - "trim-newlines": "^1.0.0" - } - }, - "merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=", - "dev": true - }, - "methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", - "dev": true - }, - "micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - } - }, - "miller-rabin": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", - "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", - "dev": true, - "requires": { - "bn.js": "^4.0.0", - "brorand": "^1.0.1" - } - }, - "mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "dev": true - }, - "mime-db": { - "version": "1.40.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.40.0.tgz", - "integrity": "sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA==" - }, - "mime-types": { - "version": "2.1.24", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.24.tgz", - "integrity": "sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==", - "requires": { - "mime-db": "1.40.0" - } - }, - "mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true - }, - "mini-css-extract-plugin": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-0.6.0.tgz", - "integrity": "sha512-79q5P7YGI6rdnVyIAV4NXpBQJFWdkzJxCim3Kog4078fM0piAaFlwocqbejdWtLW1cEzCexPrh6EdyFsPgVdAw==", - "dev": true, - "requires": { - "loader-utils": "^1.1.0", - "normalize-url": "^2.0.1", - "schema-utils": "^1.0.0", - "webpack-sources": "^1.1.0" - } - }, - "minimalistic-assert": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", - "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", - "dev": true - }, - "minimalistic-crypto-utils": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", - "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=", - "dev": true - }, - "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" - }, - "minipass": { - "version": "2.3.5", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.3.5.tgz", - "integrity": "sha512-Gi1W4k059gyRbyVUZQ4mEqLm0YIUiGYfvxhF6SIlk3ui1WVxMTGfGdQ2SInh3PDrRTVvPKgULkpJtT4RH10+VA==", - "dev": true, - "requires": { - "safe-buffer": "^5.1.2", - "yallist": "^3.0.0" - }, - "dependencies": { - "yallist": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.3.tgz", - "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==", - "dev": true - } - } - }, - "minizlib": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.2.1.tgz", - "integrity": "sha512-7+4oTUOWKg7AuL3vloEWekXY2/D20cevzsrNT2kGWm+39J9hGTCBv8VI5Pm5lXZ/o3/mdR4f8rflAPhnQb8mPA==", - "dev": true, - "requires": { - "minipass": "^2.2.1" - } - }, - "mississippi": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-3.0.0.tgz", - "integrity": "sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA==", - "dev": true, - "requires": { - "concat-stream": "^1.5.0", - "duplexify": "^3.4.2", - "end-of-stream": "^1.1.0", - "flush-write-stream": "^1.0.0", - "from2": "^2.1.0", - "parallel-transform": "^1.1.0", - "pump": "^3.0.0", - "pumpify": "^1.3.3", - "stream-each": "^1.1.0", - "through2": "^2.0.0" - } - }, - "mixin-deep": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", - "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", - "requires": { - "for-in": "^1.0.2", - "is-extendable": "^1.0.1" - }, - "dependencies": { - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "requires": { - "is-plain-object": "^2.0.4" - } - } - } - }, - "mixin-object": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/mixin-object/-/mixin-object-2.0.1.tgz", - "integrity": "sha1-T7lJRB2rGCVA8f4DW6YOGUel5X4=", - "dev": true, - "requires": { - "for-in": "^0.1.3", - "is-extendable": "^0.1.1" - }, - "dependencies": { - "for-in": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/for-in/-/for-in-0.1.8.tgz", - "integrity": "sha1-2Hc5COMSVhCZUrH9ubP6hn0ndeE=", - "dev": true - } - } - }, - "mkdirp": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", - "requires": { - "minimist": "0.0.8" - }, - "dependencies": { - "minimist": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" - } - } - }, - "moment": { - "version": "2.24.0", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.24.0.tgz", - "integrity": "sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg==" - }, - "move-concurrently": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", - "integrity": "sha1-viwAX9oy4LKa8fBdfEszIUxwH5I=", - "dev": true, - "requires": { - "aproba": "^1.1.1", - "copy-concurrently": "^1.0.0", - "fs-write-stream-atomic": "^1.0.8", - "mkdirp": "^0.5.1", - "rimraf": "^2.5.4", - "run-queue": "^1.0.3" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - }, - "multicast-dns": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-6.2.3.tgz", - "integrity": "sha512-ji6J5enbMyGRHIAkAOu3WdV8nggqviKCEKtXcOqfphZZtQrmHKycfynJ2V7eVPUA4NhJ6V7Wf4TmGbTwKE9B6g==", - "dev": true, - "requires": { - "dns-packet": "^1.3.1", - "thunky": "^1.0.2" - } - }, - "multicast-dns-service-types": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz", - "integrity": "sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE=", - "dev": true - }, - "mute-stream": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", - "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", - "dev": true - }, - "nan": { - "version": "2.14.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz", - "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==", - "optional": true - }, - "nanomatch": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", - "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "fragment-cache": "^0.2.1", - "is-windows": "^1.0.2", - "kind-of": "^6.0.2", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - } - }, - "negotiator": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", - "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==", - "dev": true - }, - "neo-async": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.1.tgz", - "integrity": "sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw==", - "dev": true - }, - "next-tick": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", - "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=" - }, - "ng2-cookies": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/ng2-cookies/-/ng2-cookies-1.0.12.tgz", - "integrity": "sha1-Pz5hPgE3sGSbcFxngHS0vQgUnMw=" - }, - "ngx-bootstrap": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/ngx-bootstrap/-/ngx-bootstrap-3.3.0.tgz", - "integrity": "sha512-eGKjMPM4XhYVCr/NdGnQ3SCOSUGMe00lytOmuDAgHf2JwMGfMD3EE7hX9KAONfNbUEuHzRfsjDAuQhWbCvZ8xg==" - }, - "ngx-clipboard": { - "version": "12.2.0", - "resolved": "https://registry.npmjs.org/ngx-clipboard/-/ngx-clipboard-12.2.0.tgz", - "integrity": "sha512-1moe/2dIUUSGVgTTeItOY8fcULPl47ilSSF2+88Adf91PYMPmilZv7jljlQaLADck5sDDsvYlTTZZTgDqjRHgA==", - "requires": { - "ngx-window-token": "^2.0.0", - "tslib": "^1.9.0" - } - }, - "ngx-infinite-scroll": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/ngx-infinite-scroll/-/ngx-infinite-scroll-7.2.0.tgz", - "integrity": "sha512-EcqjKpU1ukRV3YXOW8cTVtbzPpa9UPaRtYBCg0ZQH3ceCDm+xzLbd4pXy6oKAIN4zN1r/pyGuf5XOJkA8vr6yg==", - "requires": { - "opencollective-postinstall": "^2.0.2" - } - }, - "ngx-moment": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/ngx-moment/-/ngx-moment-3.4.0.tgz", - "integrity": "sha512-GEqzSsu12VsXXP35aerlQpuZ1ienEYQZxHmp+RH7EuJD7hWamKgLOpmbiDI9Ij3KLW/UApvonYzZvyRSv3ea/w==", - "requires": { - "tslib": "^1.9.0" - } - }, - "ngx-order-pipe": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/ngx-order-pipe/-/ngx-order-pipe-2.0.3.tgz", - "integrity": "sha512-AOZMSk8BukW56J3NSklNZzZGO4Q4bQwMFy0ClDfrf2AcOso8rJApHV4VXqCQJpwn+7EJh3D8uQFLG/9JC7xoqw==", - "requires": { - "tslib": "^1.9.0" - } - }, - "ngx-page-scroll": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ngx-page-scroll/-/ngx-page-scroll-5.0.1.tgz", - "integrity": "sha512-bn8qzjijAQqXKzwiUHn7ommLDKplR7KNEJdhqpFZK9jczf/n5SVkWMzbhE9nPg7JjWzvgoBSzx3/IVnWaOKVIg==" - }, - "ngx-window-token": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/ngx-window-token/-/ngx-window-token-2.0.1.tgz", - "integrity": "sha512-rvqdqJEfnWXQFU5fyfYt06E10tR/UtFOYdF3QebfcOh5VIJhnTKiprX8e4B9OrX7WEVFm9BT8uV72xXcEgsaKA==", - "requires": { - "tslib": "^1.9.0" - } - }, - "nice-try": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", - "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", - "dev": true - }, - "node-fetch": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz", - "integrity": "sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==", - "requires": { - "encoding": "^0.1.11", - "is-stream": "^1.0.1" - } - }, - "node-fetch-npm": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/node-fetch-npm/-/node-fetch-npm-2.0.2.tgz", - "integrity": "sha512-nJIxm1QmAj4v3nfCvEeCrYSoVwXyxLnaPBK5W1W5DGEJwjlKuC2VEUycGw5oxk+4zZahRrB84PUJJgEmhFTDFw==", - "dev": true, - "requires": { - "encoding": "^0.1.11", - "json-parse-better-errors": "^1.0.0", - "safe-buffer": "^5.1.1" - } - }, - "node-forge": { - "version": "0.7.5", - "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.7.5.tgz", - "integrity": "sha512-MmbQJ2MTESTjt3Gi/3yG1wGpIMhUfcIypUCGtTizFR9IiccFwxSpfp0vtIZlkFclEqERemxfnSdZEMR9VqqEFQ==", - "dev": true - }, - "node-gyp": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-3.8.0.tgz", - "integrity": "sha512-3g8lYefrRRzvGeSowdJKAKyks8oUpLEd/DyPV4eMhVlhJ0aNaZqIrNUIPuEWWTAoPqyFkfGrM67MC69baqn6vA==", - "optional": true, - "requires": { - "fstream": "^1.0.0", - "glob": "^7.0.3", - "graceful-fs": "^4.1.2", - "mkdirp": "^0.5.0", - "nopt": "2 || 3", - "npmlog": "0 || 1 || 2 || 3 || 4", - "osenv": "0", - "request": "^2.87.0", - "rimraf": "2", - "semver": "~5.3.0", - "tar": "^2.0.0", - "which": "1" - }, - "dependencies": { - "semver": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", - "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=", - "optional": true - } - } - }, - "node-libs-browser": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.2.1.tgz", - "integrity": "sha512-h/zcD8H9kaDZ9ALUWwlBUDo6TKF8a7qBSCSEGfjTVIYeqsioSKaAX+BN7NgiMGp6iSIXZ3PxgCu8KS3b71YK5Q==", - "dev": true, - "requires": { - "assert": "^1.1.1", - "browserify-zlib": "^0.2.0", - "buffer": "^4.3.0", - "console-browserify": "^1.1.0", - "constants-browserify": "^1.0.0", - "crypto-browserify": "^3.11.0", - "domain-browser": "^1.1.1", - "events": "^3.0.0", - "https-browserify": "^1.0.0", - "os-browserify": "^0.3.0", - "path-browserify": "0.0.1", - "process": "^0.11.10", - "punycode": "^1.2.4", - "querystring-es3": "^0.2.0", - "readable-stream": "^2.3.3", - "stream-browserify": "^2.0.1", - "stream-http": "^2.7.2", - "string_decoder": "^1.0.0", - "timers-browserify": "^2.0.4", - "tty-browserify": "0.0.0", - "url": "^0.11.0", - "util": "^0.11.0", - "vm-browserify": "^1.0.1" - }, - "dependencies": { - "punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", - "dev": true - } - } - }, - "node-releases": { - "version": "1.1.25", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.25.tgz", - "integrity": "sha512-fI5BXuk83lKEoZDdH3gRhtsNgh05/wZacuXkgbiYkceE7+QIMXOg98n9ZV7mz27B+kFHnqHcUpscZZlGRSmTpQ==", - "dev": true, - "requires": { - "semver": "^5.3.0" - } - }, - "node-sass": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/node-sass/-/node-sass-4.12.0.tgz", - "integrity": "sha512-A1Iv4oN+Iel6EPv77/HddXErL2a+gZ4uBeZUy+a8O35CFYTXhgA8MgLCWBtwpGZdCvTvQ9d+bQxX/QC36GDPpQ==", - "optional": true, - "requires": { - "async-foreach": "^0.1.3", - "chalk": "^1.1.1", - "cross-spawn": "^3.0.0", - "gaze": "^1.0.0", - "get-stdin": "^4.0.1", - "glob": "^7.0.3", - "in-publish": "^2.0.0", - "lodash": "^4.17.11", - "meow": "^3.7.0", - "mkdirp": "^0.5.1", - "nan": "^2.13.2", - "node-gyp": "^3.8.0", - "npmlog": "^4.0.0", - "request": "^2.88.0", - "sass-graph": "^2.2.4", - "stdout-stream": "^1.4.0", - "true-case-path": "^1.0.2" - }, - "dependencies": { - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "optional": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "optional": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - } - }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "optional": true - } - } - }, - "nopt": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", - "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", - "optional": true, - "requires": { - "abbrev": "1" - } - }, - "normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "requires": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - } - }, - "normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true - }, - "normalize-range": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", - "integrity": "sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=", - "dev": true - }, - "normalize-url": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-2.0.1.tgz", - "integrity": "sha512-D6MUW4K/VzoJ4rJ01JFKxDrtY1v9wrgzCX5f2qj/lzH1m/lW6MhUZFKerVsnyjOhOsYzI9Kqqak+10l4LvLpMw==", - "dev": true, - "requires": { - "prepend-http": "^2.0.0", - "query-string": "^5.0.1", - "sort-keys": "^2.0.0" - } - }, - "npm-bundled": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.0.6.tgz", - "integrity": "sha512-8/JCaftHwbd//k6y2rEWp6k1wxVfpFzB6t1p825+cUb7Ym2XQfhwIC5KwhrvzZRJu+LtDE585zVaS32+CGtf0g==", - "dev": true - }, - "npm-package-arg": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-6.1.0.tgz", - "integrity": "sha512-zYbhP2k9DbJhA0Z3HKUePUgdB1x7MfIfKssC+WLPFMKTBZKpZh5m13PgexJjCq6KW7j17r0jHWcCpxEqnnncSA==", - "dev": true, - "requires": { - "hosted-git-info": "^2.6.0", - "osenv": "^0.1.5", - "semver": "^5.5.0", - "validate-npm-package-name": "^3.0.0" - } - }, - "npm-packlist": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.4.4.tgz", - "integrity": "sha512-zTLo8UcVYtDU3gdeaFu2Xu0n0EvelfHDGuqtNIn5RO7yQj4H1TqNdBc/yZjxnWA0PVB8D3Woyp0i5B43JwQ6Vw==", - "dev": true, - "requires": { - "ignore-walk": "^3.0.1", - "npm-bundled": "^1.0.1" - } - }, - "npm-pick-manifest": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/npm-pick-manifest/-/npm-pick-manifest-2.2.3.tgz", - "integrity": "sha512-+IluBC5K201+gRU85vFlUwX3PFShZAbAgDNp2ewJdWMVSppdo/Zih0ul2Ecky/X7b51J7LrrUAP+XOmOCvYZqA==", - "dev": true, - "requires": { - "figgy-pudding": "^3.5.1", - "npm-package-arg": "^6.0.0", - "semver": "^5.4.1" - } - }, - "npm-registry-fetch": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/npm-registry-fetch/-/npm-registry-fetch-3.9.1.tgz", - "integrity": "sha512-VQCEZlydXw4AwLROAXWUR7QDfe2Y8Id/vpAgp6TI1/H78a4SiQ1kQrKZALm5/zxM5n4HIi+aYb+idUAV/RuY0Q==", - "dev": true, - "requires": { - "JSONStream": "^1.3.4", - "bluebird": "^3.5.1", - "figgy-pudding": "^3.4.1", - "lru-cache": "^5.1.1", - "make-fetch-happen": "^4.0.2", - "npm-package-arg": "^6.1.0" - }, - "dependencies": { - "lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "dev": true, - "requires": { - "yallist": "^3.0.2" - } - }, - "yallist": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.3.tgz", - "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==", - "dev": true - } - } - }, - "npm-run-path": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", - "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", - "dev": true, - "requires": { - "path-key": "^2.0.0" - } - }, - "npmlog": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", - "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", - "requires": { - "are-we-there-yet": "~1.1.2", - "console-control-strings": "~1.1.0", - "gauge": "~2.7.3", - "set-blocking": "~2.0.0" - } - }, - "num2fraction": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/num2fraction/-/num2fraction-1.2.2.tgz", - "integrity": "sha1-b2gragJ6Tp3fpFZM0lidHU5mnt4=", - "dev": true - }, - "number-is-nan": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" - }, - "oauth-sign": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", - "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==" - }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" - }, - "object-component": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/object-component/-/object-component-0.0.3.tgz", - "integrity": "sha1-8MaapQ78lbhmwYb0AKM3acsvEpE=" - }, - "object-copy": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", - "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", - "requires": { - "copy-descriptor": "^0.1.0", - "define-property": "^0.2.5", - "kind-of": "^3.0.3" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==" - }, - "object-visit": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", - "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", - "requires": { - "isobject": "^3.0.0" - } - }, - "object.assign": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", - "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", - "requires": { - "define-properties": "^1.1.2", - "function-bind": "^1.1.1", - "has-symbols": "^1.0.0", - "object-keys": "^1.0.11" - } - }, - "object.pick": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", - "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", - "requires": { - "isobject": "^3.0.1" - } - }, - "obuf": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", - "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", - "dev": true - }, - "on-finished": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", - "dev": true, - "requires": { - "ee-first": "1.1.1" - } - }, - "on-headers": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", - "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", - "dev": true - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "requires": { - "wrappy": "1" - } - }, - "onetime": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", - "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", - "dev": true, - "requires": { - "mimic-fn": "^1.0.0" - }, - "dependencies": { - "mimic-fn": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", - "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", - "dev": true - } - } - }, - "open": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/open/-/open-6.2.0.tgz", - "integrity": "sha512-Vxf6HJkwrqmvh9UAID3MnMYXntbTxKLOSfOnO7LJdzPf3NE3KQYFNV0/Lcz2VAndbRFil58XVCyh8tiX11fiYw==", - "dev": true, - "requires": { - "is-wsl": "^1.1.0" - } - }, - "opencollective-postinstall": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/opencollective-postinstall/-/opencollective-postinstall-2.0.2.tgz", - "integrity": "sha512-pVOEP16TrAO2/fjej1IdOyupJY8KDUM1CvsaScRbw6oddvpQoOfGk4ywha0HKKVAD6RkW4x6Q+tNBwhf3Bgpuw==" - }, - "opn": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/opn/-/opn-5.5.0.tgz", - "integrity": "sha512-PqHpggC9bLV0VeWcdKhkpxY+3JTzetLSqTCWL/z/tFIbI6G8JCjondXklT1JinczLz2Xib62sSp0T/gKT4KksA==", - "dev": true, - "requires": { - "is-wsl": "^1.1.0" - } - }, - "optimist": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", - "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", - "optional": true, - "requires": { - "minimist": "~0.0.1", - "wordwrap": "~0.0.2" - }, - "dependencies": { - "minimist": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", - "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=", - "optional": true - } - } - }, - "original": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/original/-/original-1.0.2.tgz", - "integrity": "sha512-hyBVl6iqqUOJ8FqRe+l/gS8H+kKYjrEndd5Pm1MfBtsEKA038HkkdbAl/72EAXGyonD/PFsvmVG+EvcIpliMBg==", - "requires": { - "url-parse": "^1.4.3" - } - }, - "os-browserify": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", - "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=", - "dev": true - }, - "os-homedir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=" - }, - "os-locale": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", - "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", - "optional": true, - "requires": { - "lcid": "^1.0.0" - } - }, - "os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" - }, - "osenv": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", - "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", - "requires": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.0" - } - }, - "p-defer": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz", - "integrity": "sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=", - "dev": true - }, - "p-finally": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", - "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", - "dev": true - }, - "p-is-promise": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-2.1.0.tgz", - "integrity": "sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg==", - "dev": true - }, - "p-limit": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.0.tgz", - "integrity": "sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ==", - "dev": true, - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dev": true, - "requires": { - "p-limit": "^2.0.0" - } - }, - "p-map": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", - "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==", - "dev": true - }, - "p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true - }, - "pace": { - "version": "github:HubSpot/pace#c6846cbf6b928e9903b569269fa9fbf32f2554f4", - "from": "github:HubSpot/pace#v1.0.2" - }, - "pacote": { - "version": "9.5.0", - "resolved": "https://registry.npmjs.org/pacote/-/pacote-9.5.0.tgz", - "integrity": "sha512-aUplXozRbzhaJO48FaaeClmN+2Mwt741MC6M3bevIGZwdCaP7frXzbUOfOWa91FPHoLITzG0hYaKY363lxO3bg==", - "dev": true, - "requires": { - "bluebird": "^3.5.3", - "cacache": "^11.3.2", - "figgy-pudding": "^3.5.1", - "get-stream": "^4.1.0", - "glob": "^7.1.3", - "lru-cache": "^5.1.1", - "make-fetch-happen": "^4.0.1", - "minimatch": "^3.0.4", - "minipass": "^2.3.5", - "mississippi": "^3.0.0", - "mkdirp": "^0.5.1", - "normalize-package-data": "^2.4.0", - "npm-package-arg": "^6.1.0", - "npm-packlist": "^1.1.12", - "npm-pick-manifest": "^2.2.3", - "npm-registry-fetch": "^3.8.0", - "osenv": "^0.1.5", - "promise-inflight": "^1.0.1", - "promise-retry": "^1.1.1", - "protoduck": "^5.0.1", - "rimraf": "^2.6.2", - "safe-buffer": "^5.1.2", - "semver": "^5.6.0", - "ssri": "^6.0.1", - "tar": "^4.4.8", - "unique-filename": "^1.1.1", - "which": "^1.3.1" - }, - "dependencies": { - "lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "dev": true, - "requires": { - "yallist": "^3.0.2" - } - }, - "tar": { - "version": "4.4.10", - "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.10.tgz", - "integrity": "sha512-g2SVs5QIxvo6OLp0GudTqEf05maawKUxXru104iaayWA09551tFCTI8f1Asb4lPfkBr91k07iL4c11XO3/b0tA==", - "dev": true, - "requires": { - "chownr": "^1.1.1", - "fs-minipass": "^1.2.5", - "minipass": "^2.3.5", - "minizlib": "^1.2.1", - "mkdirp": "^0.5.0", - "safe-buffer": "^5.1.2", - "yallist": "^3.0.3" - } - }, - "yallist": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.3.tgz", - "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==", - "dev": true - } - } - }, - "pako": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.10.tgz", - "integrity": "sha512-0DTvPVU3ed8+HNXOu5Bs+o//Mbdj9VNQMUOe9oKCwh8l0GNwpTDMKCWbRjgtD291AWnkAgkqA/LOnQS8AmS1tw==" - }, - "parallel-transform": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/parallel-transform/-/parallel-transform-1.1.0.tgz", - "integrity": "sha1-1BDwZbBdojCB/NEPKIVMKb2jOwY=", - "dev": true, - "requires": { - "cyclist": "~0.2.2", - "inherits": "^2.0.3", - "readable-stream": "^2.1.5" - } - }, - "parse-asn1": { - "version": "5.1.4", - "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.4.tgz", - "integrity": "sha512-Qs5duJcuvNExRfFZ99HDD3z4mAi3r9Wl/FOjEOijlxwCZs7E7mW2vjTpgQ4J8LpTF8x5v+1Vn5UQFejmWT11aw==", - "dev": true, - "requires": { - "asn1.js": "^4.0.0", - "browserify-aes": "^1.0.0", - "create-hash": "^1.1.0", - "evp_bytestokey": "^1.0.0", - "pbkdf2": "^3.0.3", - "safe-buffer": "^5.1.1" - } - }, - "parse-json": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", - "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "requires": { - "error-ex": "^1.2.0" - } - }, - "parse5": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.0.tgz", - "integrity": "sha512-fxNG2sQjHvlVAYmzBZS9YlDp6PTSSDwa98vkD4QgVDDCAo84z5X1t5XyJQ62ImdLXx5NdIIfihey6xpum9/gRQ==", - "optional": true - }, - "parseqs": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.5.tgz", - "integrity": "sha1-1SCKNzjkZ2bikbouoXNoSSGouJ0=", - "requires": { - "better-assert": "~1.0.0" - } - }, - "parseuri": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.5.tgz", - "integrity": "sha1-gCBKUNTbt3m/3G6+J3jZDkvOMgo=", - "requires": { - "better-assert": "~1.0.0" - } - }, - "parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", - "dev": true - }, - "pascalcase": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", - "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=" - }, - "path-browserify": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.1.tgz", - "integrity": "sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ==", - "dev": true - }, - "path-dirname": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", - "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", - "dev": true - }, - "path-exists": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", - "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", - "requires": { - "pinkie-promise": "^2.0.0" - } - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" - }, - "path-is-inside": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", - "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=" - }, - "path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", - "dev": true - }, - "path-parse": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", - "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==" - }, - "path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=", - "dev": true - }, - "path-type": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", - "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", - "requires": { - "graceful-fs": "^4.1.2", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" - } - }, - "pbkdf2": { - "version": "3.0.17", - "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.17.tgz", - "integrity": "sha512-U/il5MsrZp7mGg3mSQfn742na2T+1/vHDCG5/iTI3X9MKUuYUZVLQhyRsg06mCgDBTd57TxzgZt7P+fYfjRLtA==", - "dev": true, - "requires": { - "create-hash": "^1.1.2", - "create-hmac": "^1.1.4", - "ripemd160": "^2.0.1", - "safe-buffer": "^5.0.1", - "sha.js": "^2.4.8" - } - }, - "performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" - }, - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" - }, - "pinkie": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", - "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=" - }, - "pinkie-promise": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", - "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", - "requires": { - "pinkie": "^2.0.0" - } - }, - "pkg-dir": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", - "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", - "dev": true, - "requires": { - "find-up": "^3.0.0" - }, - "dependencies": { - "find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "requires": { - "locate-path": "^3.0.0" - } - } - } - }, - "please-wait": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/please-wait/-/please-wait-0.0.5.tgz", - "integrity": "sha1-ZwmM5iYOkuCAni07fCPx0Wfa2WA=" - }, - "popper.js": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.15.0.tgz", - "integrity": "sha512-w010cY1oCUmI+9KwwlWki+r5jxKfTFDVoadl7MSrIujHU5MJ5OR6HTDj6Xo8aoR/QsA56x8jKjA59qGH4ELtrA==" - }, - "portfinder": { - "version": "1.0.21", - "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.21.tgz", - "integrity": "sha512-ESabpDCzmBS3ekHbmpAIiESq3udRsCBGiBZLsC+HgBKv2ezb0R4oG+7RnYEVZ/ZCfhel5Tx3UzdNWA0Lox2QCA==", - "dev": true, - "requires": { - "async": "^1.5.2", - "debug": "^2.2.0", - "mkdirp": "0.5.x" - }, - "dependencies": { - "async": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", - "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", - "dev": true - } - } - }, - "posix-character-classes": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", - "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=" - }, - "postcss": { - "version": "7.0.14", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.14.tgz", - "integrity": "sha512-NsbD6XUUMZvBxtQAJuWDJeeC4QFsmWsfozWxCJPWf3M55K9iu2iMDaKqyoOdTJ1R4usBXuxlVFAIo8rZPQD4Bg==", - "dev": true, - "requires": { - "chalk": "^2.4.2", - "source-map": "^0.6.1", - "supports-color": "^6.1.0" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "supports-color": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", - "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "postcss-import": { - "version": "12.0.1", - "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-12.0.1.tgz", - "integrity": "sha512-3Gti33dmCjyKBgimqGxL3vcV8w9+bsHwO5UrBawp796+jdardbcFl4RP5w/76BwNL7aGzpKstIfF9I+kdE8pTw==", - "dev": true, - "requires": { - "postcss": "^7.0.1", - "postcss-value-parser": "^3.2.3", - "read-cache": "^1.0.0", - "resolve": "^1.1.7" - } - }, - "postcss-load-config": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-2.1.0.tgz", - "integrity": "sha512-4pV3JJVPLd5+RueiVVB+gFOAa7GWc25XQcMp86Zexzke69mKf6Nx9LRcQywdz7yZI9n1udOxmLuAwTBypypF8Q==", - "dev": true, - "requires": { - "cosmiconfig": "^5.0.0", - "import-cwd": "^2.0.0" - } - }, - "postcss-loader": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-3.0.0.tgz", - "integrity": "sha512-cLWoDEY5OwHcAjDnkyRQzAXfs2jrKjXpO/HQFcc5b5u/r7aa471wdmChmwfnv7x2u840iat/wi0lQ5nbRgSkUA==", - "dev": true, - "requires": { - "loader-utils": "^1.1.0", - "postcss": "^7.0.0", - "postcss-load-config": "^2.0.0", - "schema-utils": "^1.0.0" - } - }, - "postcss-value-parser": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", - "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", - "dev": true - }, - "prepend-http": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", - "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=", - "dev": true - }, - "primeicons": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/primeicons/-/primeicons-1.0.0.tgz", - "integrity": "sha512-p/hzIjUVccW4eJPhuORHI3AUkDpqfvCQVrjxbFEejnTEdWY4C8fomVfjiaA9jCu83fSQnBHuRIGB96iAR8R6uA==" - }, - "primeng": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/primeng/-/primeng-7.1.3.tgz", - "integrity": "sha512-t+DC5VtTJBCz4fPa3wMspByhtdQYgyLEIMWok2kH1J/a/2bTXSYM31ueHKjgV8XuUaeDwMzARLTQv+V9HczIEQ==" - }, - "process": { - "version": "0.11.10", - "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", - "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=", - "dev": true - }, - "process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" - }, - "promise": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", - "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==", - "dev": true, - "optional": true, - "requires": { - "asap": "~2.0.3" - } - }, - "promise-inflight": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", - "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=", - "dev": true - }, - "promise-retry": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-1.1.1.tgz", - "integrity": "sha1-ZznpaOMFHaIM5kl/srUPaRHfPW0=", - "dev": true, - "requires": { - "err-code": "^1.0.0", - "retry": "^0.10.0" - } - }, - "protoduck": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/protoduck/-/protoduck-5.0.1.tgz", - "integrity": "sha512-WxoCeDCoCBY55BMvj4cAEjdVUFGRWed9ZxPlqTKYyw1nDDTQ4pqmnIMAGfJlg7Dx35uB/M+PHJPTmGOvaCaPTg==", - "dev": true, - "requires": { - "genfun": "^5.0.0" - } - }, - "protractor": { - "version": "5.4.2", - "resolved": "https://registry.npmjs.org/protractor/-/protractor-5.4.2.tgz", - "integrity": "sha512-zlIj64Cr6IOWP7RwxVeD8O4UskLYPoyIcg0HboWJL9T79F1F0VWtKkGTr/9GN6BKL+/Q/GmM7C9kFVCfDbP5sA==", - "optional": true, - "requires": { - "@types/q": "^0.0.32", - "@types/selenium-webdriver": "^3.0.0", - "blocking-proxy": "^1.0.0", - "browserstack": "^1.5.1", - "chalk": "^1.1.3", - "glob": "^7.0.3", - "jasmine": "2.8.0", - "jasminewd2": "^2.1.0", - "optimist": "~0.6.0", - "q": "1.4.1", - "saucelabs": "^1.5.0", - "selenium-webdriver": "3.6.0", - "source-map-support": "~0.4.0", - "webdriver-js-extender": "2.1.0", - "webdriver-manager": "^12.0.6" - }, - "dependencies": { - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" - }, - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - } - }, - "source-map-support": { - "version": "0.4.18", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz", - "integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==", - "optional": true, - "requires": { - "source-map": "^0.5.6" - } - }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" - }, - "webdriver-manager": { - "version": "12.1.5", - "resolved": "https://registry.npmjs.org/webdriver-manager/-/webdriver-manager-12.1.5.tgz", - "integrity": "sha512-f1apDjMpZ8SHlXtXGzqBxOjV+WQcDRz5PN7pWScgjXS7vhUIFcM3V89Shetf4A04n8DDR2MxiVQq6JproFcRZw==", - "optional": true, - "requires": { - "adm-zip": "^0.4.9", - "chalk": "^1.1.1", - "del": "^2.2.0", - "glob": "^7.0.3", - "ini": "^1.3.4", - "minimist": "^1.2.0", - "q": "^1.4.1", - "request": "^2.87.0", - "rimraf": "^2.5.2", - "semver": "^5.3.0", - "xml2js": "^0.4.17" - } - } - } - }, - "proxy-addr": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.5.tgz", - "integrity": "sha512-t/7RxHXPH6cJtP0pRG6smSr9QJidhB+3kXu0KgXnbGYMgzEnUxRQ4/LDdfOwZEMyIh3/xHb8PX3t+lfL9z+YVQ==", - "dev": true, - "requires": { - "forwarded": "~0.1.2", - "ipaddr.js": "1.9.0" - } - }, - "prr": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", - "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=" - }, - "pseudomap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", - "optional": true - }, - "psl": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.2.0.tgz", - "integrity": "sha512-GEn74ZffufCmkDDLNcl3uuyF/aSD6exEyh1v/ZSdAomB82t6G9hzJVRx0jBmLDW+VfZqks3aScmMw9DszwUalA==" - }, - "public-encrypt": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", - "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", - "dev": true, - "requires": { - "bn.js": "^4.1.0", - "browserify-rsa": "^4.0.0", - "create-hash": "^1.1.0", - "parse-asn1": "^5.0.0", - "randombytes": "^2.0.1", - "safe-buffer": "^5.1.2" - } - }, - "pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "pumpify": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", - "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", - "dev": true, - "requires": { - "duplexify": "^3.6.0", - "inherits": "^2.0.3", - "pump": "^2.0.0" - }, - "dependencies": { - "pump": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", - "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", - "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - } - } - }, - "punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" - }, - "q": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/q/-/q-1.4.1.tgz", - "integrity": "sha1-VXBbzZPF82c1MMLCy8DCs63cKG4=" - }, - "qs": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", - "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" - }, - "query-string": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/query-string/-/query-string-5.1.1.tgz", - "integrity": "sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw==", - "dev": true, - "requires": { - "decode-uri-component": "^0.2.0", - "object-assign": "^4.1.0", - "strict-uri-encode": "^1.0.0" - } - }, - "querystring": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", - "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=" - }, - "querystring-es3": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", - "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=", - "dev": true - }, - "querystringify": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.1.1.tgz", - "integrity": "sha512-w7fLxIRCRT7U8Qu53jQnJyPkYZIaR4n5151KMfcJlO/A9397Wxb1amJvROTK6TOnp7PfoAmg/qXiNHI+08jRfA==" - }, - "randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, - "requires": { - "safe-buffer": "^5.1.0" - } - }, - "randomfill": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", - "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", - "dev": true, - "requires": { - "randombytes": "^2.0.5", - "safe-buffer": "^5.1.0" - } - }, - "range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", - "dev": true - }, - "raw-body": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", - "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", - "dev": true, - "requires": { - "bytes": "3.1.0", - "http-errors": "1.7.2", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - }, - "dependencies": { - "bytes": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", - "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", - "dev": true - } - } - }, - "raw-loader": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/raw-loader/-/raw-loader-1.0.0.tgz", - "integrity": "sha512-Uqy5AqELpytJTRxYT4fhltcKPj0TyaEpzJDcGz7DFJi+pQOOi3GjR/DOdxTkTsF+NzhnldIoG6TORaBlInUuqA==", - "dev": true, - "requires": { - "loader-utils": "^1.1.0", - "schema-utils": "^1.0.0" - } - }, - "read-cache": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", - "integrity": "sha1-5mTvMRYRZsl1HNvo28+GtftY93Q=", - "dev": true, - "requires": { - "pify": "^2.3.0" - } - }, - "read-package-json": { - "version": "2.0.13", - "resolved": "https://registry.npmjs.org/read-package-json/-/read-package-json-2.0.13.tgz", - "integrity": "sha512-/1dZ7TRZvGrYqE0UAfN6qQb5GYBsNcqS1C0tNK601CFOJmtHI7NIGXwetEPU/OtoFHZL3hDxm4rolFFVE9Bnmg==", - "dev": true, - "requires": { - "glob": "^7.1.1", - "graceful-fs": "^4.1.2", - "json-parse-better-errors": "^1.0.1", - "normalize-package-data": "^2.0.0", - "slash": "^1.0.0" - } - }, - "read-package-tree": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/read-package-tree/-/read-package-tree-5.2.2.tgz", - "integrity": "sha512-rW3XWUUkhdKmN2JKB4FL563YAgtINifso5KShykufR03nJ5loGFlkUMe1g/yxmqX073SoYYTsgXu7XdDinKZuA==", - "dev": true, - "requires": { - "debuglog": "^1.0.1", - "dezalgo": "^1.0.0", - "once": "^1.3.0", - "read-package-json": "^2.0.0", - "readdir-scoped-modules": "^1.0.0" - } - }, - "read-pkg": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", - "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", - "requires": { - "load-json-file": "^1.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^1.0.0" - } - }, - "read-pkg-up": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", - "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", - "requires": { - "find-up": "^1.0.0", - "read-pkg": "^1.0.0" - } - }, - "readable-stream": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - }, - "dependencies": { - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - } - } - }, - "readdir-scoped-modules": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/readdir-scoped-modules/-/readdir-scoped-modules-1.1.0.tgz", - "integrity": "sha512-asaikDeqAQg7JifRsZn1NJZXo9E+VwlyCfbkZhwyISinqk5zNS6266HS5kah6P0SaQKGF6SkNnZVHUzHFYxYDw==", - "dev": true, - "requires": { - "debuglog": "^1.0.1", - "dezalgo": "^1.0.0", - "graceful-fs": "^4.1.2", - "once": "^1.3.0" - } - }, - "readdirp": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", - "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.11", - "micromatch": "^3.1.10", - "readable-stream": "^2.0.2" - } - }, - "rechoir": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", - "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", - "dev": true, - "requires": { - "resolve": "^1.1.6" - } - }, - "redent": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", - "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=", - "optional": true, - "requires": { - "indent-string": "^2.1.0", - "strip-indent": "^1.0.1" - } - }, - "reflect-metadata": { - "version": "0.1.13", - "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz", - "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==", - "dev": true - }, - "regenerate": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.0.tgz", - "integrity": "sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg==" - }, - "regenerator-runtime": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", - "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==", - "dev": true - }, - "regex-not": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", - "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", - "requires": { - "extend-shallow": "^3.0.2", - "safe-regex": "^1.1.0" - } - }, - "regexpu-core": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-1.0.0.tgz", - "integrity": "sha1-hqdj9Y7k18L2sQLkdkBQ3n7ZDGs=", - "requires": { - "regenerate": "^1.2.1", - "regjsgen": "^0.2.0", - "regjsparser": "^0.1.4" - } - }, - "regjsgen": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz", - "integrity": "sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc=" - }, - "regjsparser": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz", - "integrity": "sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=", - "requires": { - "jsesc": "~0.5.0" - } - }, - "remove-trailing-separator": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", - "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", - "dev": true - }, - "repeat-element": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", - "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==" - }, - "repeat-string": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=" - }, - "repeating": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", - "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", - "requires": { - "is-finite": "^1.0.0" - } - }, - "request": { - "version": "2.88.0", - "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", - "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", - "requires": { - "aws-sign2": "~0.7.0", - "aws4": "^1.8.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.6", - "extend": "~3.0.2", - "forever-agent": "~0.6.1", - "form-data": "~2.3.2", - "har-validator": "~5.1.0", - "http-signature": "~1.2.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "oauth-sign": "~0.9.0", - "performance-now": "^2.1.0", - "qs": "~6.5.2", - "safe-buffer": "^5.1.2", - "tough-cookie": "~2.4.3", - "tunnel-agent": "^0.6.0", - "uuid": "^3.3.2" - } - }, - "require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=" - }, - "require-main-filename": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", - "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=" - }, - "requires-port": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=" - }, - "resolve": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.11.1.tgz", - "integrity": "sha512-vIpgF6wfuJOZI7KKKSP+HmiKggadPQAdsp5HiC1mvqnfp0gF1vdwgBWZIdrVft9pgqoMFQN+R7BSWZiBxx+BBw==", - "requires": { - "path-parse": "^1.0.6" - } - }, - "resolve-cwd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-2.0.0.tgz", - "integrity": "sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=", - "dev": true, - "requires": { - "resolve-from": "^3.0.0" - } - }, - "resolve-from": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", - "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", - "dev": true - }, - "resolve-url": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", - "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=" - }, - "restore-cursor": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", - "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", - "dev": true, - "requires": { - "onetime": "^2.0.0", - "signal-exit": "^3.0.2" - } - }, - "ret": { - "version": "0.1.15", - "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", - "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==" - }, - "retry": { - "version": "0.10.1", - "resolved": "https://registry.npmjs.org/retry/-/retry-0.10.1.tgz", - "integrity": "sha1-52OI0heZLCUnUCQdPTlW/tmNj/Q=", - "dev": true - }, - "rimraf": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", - "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", - "requires": { - "glob": "^7.1.3" - } - }, - "ripemd160": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", - "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", - "dev": true, - "requires": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1" - } - }, - "run-async": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", - "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", - "dev": true, - "requires": { - "is-promise": "^2.1.0" - } - }, - "run-queue": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/run-queue/-/run-queue-1.0.3.tgz", - "integrity": "sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec=", - "dev": true, - "requires": { - "aproba": "^1.1.1" - } - }, - "rxjs": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.2.tgz", - "integrity": "sha512-HUb7j3kvb7p7eCUHE3FqjoDsC1xfZQ4AHFWfTKSpZ+sAhhz5X1WX0ZuUqWbzB2QhSLp3DoLUG+hMdEDKqWo2Zg==", - "requires": { - "tslib": "^1.9.0" - } - }, - "safe-buffer": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz", - "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==" - }, - "safe-regex": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", - "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", - "requires": { - "ret": "~0.1.10" - } - }, - "safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" - }, - "sass": { - "version": "1.19.0", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.19.0.tgz", - "integrity": "sha512-8kzKCgxCzh8/zEn3AuRwzLWVSSFj8omkiGwqdJdeOufjM+I88dXxu9LYJ/Gw4rRTHXesN0r1AixBuqM6yLQUJw==", - "dev": true, - "requires": { - "chokidar": "^2.0.0" - } - }, - "sass-graph": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/sass-graph/-/sass-graph-2.2.4.tgz", - "integrity": "sha1-E/vWPNHK8JCLn9k0dq1DpR0eC0k=", - "optional": true, - "requires": { - "glob": "^7.0.0", - "lodash": "^4.0.0", - "scss-tokenizer": "^0.2.3", - "yargs": "^7.0.0" - } - }, - "sass-loader": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-7.1.0.tgz", - "integrity": "sha512-+G+BKGglmZM2GUSfT9TLuEp6tzehHPjAMoRRItOojWIqIGPloVCMhNIQuG639eJ+y033PaGTSjLaTHts8Kw79w==", - "dev": true, - "requires": { - "clone-deep": "^2.0.1", - "loader-utils": "^1.0.1", - "lodash.tail": "^4.1.1", - "neo-async": "^2.5.0", - "pify": "^3.0.0", - "semver": "^5.5.0" - }, - "dependencies": { - "pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", - "dev": true - } - } - }, - "saucelabs": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/saucelabs/-/saucelabs-1.5.0.tgz", - "integrity": "sha512-jlX3FGdWvYf4Q3LFfFWS1QvPg3IGCGWxIc8QBFdPTbpTJnt/v17FHXYVAn7C8sHf1yUXo2c7yIM0isDryfYtHQ==", - "optional": true, - "requires": { - "https-proxy-agent": "^2.2.1" - } - }, - "sax": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", - "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" - }, - "schema-utils": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", - "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", - "dev": true, - "requires": { - "ajv": "^6.1.0", - "ajv-errors": "^1.0.0", - "ajv-keywords": "^3.1.0" - } - }, - "scss-tokenizer": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/scss-tokenizer/-/scss-tokenizer-0.2.3.tgz", - "integrity": "sha1-jrBtualyMzOCTT9VMGQRSYR85dE=", - "optional": true, - "requires": { - "js-base64": "^2.1.8", - "source-map": "^0.4.2" - }, - "dependencies": { - "source-map": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", - "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", - "optional": true, - "requires": { - "amdefine": ">=0.0.4" - } - } - } - }, - "select-hose": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", - "integrity": "sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo=", - "dev": true - }, - "selenium-webdriver": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/selenium-webdriver/-/selenium-webdriver-3.6.0.tgz", - "integrity": "sha512-WH7Aldse+2P5bbFBO4Gle/nuQOdVwpHMTL6raL3uuBj/vPG07k6uzt3aiahu352ONBr5xXh0hDlM3LhtXPOC4Q==", - "requires": { - "jszip": "^3.1.3", - "rimraf": "^2.5.4", - "tmp": "0.0.30", - "xml2js": "^0.4.17" - } - }, - "selfsigned": { - "version": "1.10.4", - "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-1.10.4.tgz", - "integrity": "sha512-9AukTiDmHXGXWtWjembZ5NDmVvP2695EtpgbCsxCa68w3c88B+alqbmZ4O3hZ4VWGXeGWzEVdvqgAJD8DQPCDw==", - "dev": true, - "requires": { - "node-forge": "0.7.5" - } - }, - "semver": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz", - "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==" - }, - "semver-dsl": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/semver-dsl/-/semver-dsl-1.0.1.tgz", - "integrity": "sha1-02eN5VVeimH2Ke7QJTZq5fJzQKA=", - "requires": { - "semver": "^5.3.0" - } - }, - "semver-intersect": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/semver-intersect/-/semver-intersect-1.4.0.tgz", - "integrity": "sha512-d8fvGg5ycKAq0+I6nfWeCx6ffaWJCsBYU0H2Rq56+/zFePYfT8mXkB3tWBSjR5BerkHNZ5eTPIk1/LBYas35xQ==", - "dev": true, - "requires": { - "semver": "^5.0.0" - } - }, - "send": { - "version": "0.17.1", - "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", - "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", - "dev": true, - "requires": { - "debug": "2.6.9", - "depd": "~1.1.2", - "destroy": "~1.0.4", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "~1.7.2", - "mime": "1.6.0", - "ms": "2.1.1", - "on-finished": "~2.3.0", - "range-parser": "~1.2.1", - "statuses": "~1.5.0" - }, - "dependencies": { - "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", - "dev": true - } - } - }, - "serialize-javascript": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-1.7.0.tgz", - "integrity": "sha512-ke8UG8ulpFOxO8f8gRYabHQe/ZntKlcig2Mp+8+URDP1D8vJZ0KUt7LYo07q25Z/+JVSgpr/cui9PIp5H6/+nA==", - "dev": true - }, - "serve-index": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", - "integrity": "sha1-03aNabHn2C5c4FD/9bRTvqEqkjk=", - "dev": true, - "requires": { - "accepts": "~1.3.4", - "batch": "0.6.1", - "debug": "2.6.9", - "escape-html": "~1.0.3", - "http-errors": "~1.6.2", - "mime-types": "~2.1.17", - "parseurl": "~1.3.2" - }, - "dependencies": { - "http-errors": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", - "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", - "dev": true, - "requires": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.0", - "statuses": ">= 1.4.0 < 2" - } - }, - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", - "dev": true - }, - "setprototypeof": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", - "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", - "dev": true - } - } - }, - "serve-static": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", - "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", - "dev": true, - "requires": { - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.17.1" - } - }, - "set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" - }, - "set-immediate-shim": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz", - "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=" - }, - "set-value": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", - "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", - "requires": { - "extend-shallow": "^2.0.1", - "is-extendable": "^0.1.1", - "is-plain-object": "^2.0.3", - "split-string": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "setimmediate": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", - "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=", - "dev": true - }, - "setprototypeof": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", - "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==", - "dev": true - }, - "sha.js": { - "version": "2.4.11", - "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", - "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", - "dev": true, - "requires": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } - }, - "shallow-clone": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-1.0.0.tgz", - "integrity": "sha512-oeXreoKR/SyNJtRJMAKPDSvd28OqEwG4eR/xc856cRGBII7gX9lvAqDxusPm0846z/w/hWYjI1NpKwJ00NHzRA==", - "dev": true, - "requires": { - "is-extendable": "^0.1.1", - "kind-of": "^5.0.0", - "mixin-object": "^2.0.1" - }, - "dependencies": { - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true - } - } - }, - "shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", - "dev": true, - "requires": { - "shebang-regex": "^1.0.0" - } - }, - "shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", - "dev": true - }, - "shelljs": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.3.tgz", - "integrity": "sha512-fc0BKlAWiLpwZljmOvAOTE/gXawtCoNrP5oaY7KIaQbbyHeQVg01pSEuEGvGh3HEdBU4baCD7wQBwADmM/7f7A==", - "dev": true, - "requires": { - "glob": "^7.0.0", - "interpret": "^1.0.0", - "rechoir": "^0.6.2" - } - }, - "signal-exit": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", - "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" - }, - "slash": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", - "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=", - "dev": true - }, - "smart-buffer": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.0.2.tgz", - "integrity": "sha512-JDhEpTKzXusOqXZ0BUIdH+CjFdO/CR3tLlf5CN34IypI+xMmXW1uB16OOY8z3cICbJlDAVJzNbwBhNO0wt9OAw==", - "dev": true - }, - "snapdragon": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", - "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", - "requires": { - "base": "^0.11.1", - "debug": "^2.2.0", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "map-cache": "^0.2.2", - "source-map": "^0.5.6", - "source-map-resolve": "^0.5.0", - "use": "^3.1.0" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "snapdragon-node": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", - "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", - "requires": { - "define-property": "^1.0.0", - "isobject": "^3.0.0", - "snapdragon-util": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } - } - }, - "snapdragon-util": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", - "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", - "requires": { - "kind-of": "^3.2.0" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "socket.io-client": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.2.0.tgz", - "integrity": "sha512-56ZrkTDbdTLmBIyfFYesgOxsjcLnwAKoN4CiPyTVkMQj3zTUh0QAx3GbvIvLpFEOvQWu92yyWICxB0u7wkVbYA==", - "requires": { - "backo2": "1.0.2", - "base64-arraybuffer": "0.1.5", - "component-bind": "1.0.0", - "component-emitter": "1.2.1", - "debug": "~3.1.0", - "engine.io-client": "~3.3.1", - "has-binary2": "~1.0.2", - "has-cors": "1.1.0", - "indexof": "0.0.1", - "object-component": "0.0.3", - "parseqs": "0.0.5", - "parseuri": "0.0.5", - "socket.io-parser": "~3.3.0", - "to-array": "0.1.4" - }, - "dependencies": { - "component-emitter": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", - "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=" - }, - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "requires": { - "ms": "2.0.0" - } - } - } - }, - "socket.io-parser": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.3.0.tgz", - "integrity": "sha512-hczmV6bDgdaEbVqhAeVMM/jfUfzuEZHsQg6eOmLgJht6G3mPKMxYm75w2+qhAQZ+4X+1+ATZ+QFKeOZD5riHng==", - "requires": { - "component-emitter": "1.2.1", - "debug": "~3.1.0", - "isarray": "2.0.1" - }, - "dependencies": { - "component-emitter": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", - "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=" - }, - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "requires": { - "ms": "2.0.0" - } - }, - "isarray": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", - "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=" - } - } - }, - "sockjs": { - "version": "0.3.19", - "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.19.tgz", - "integrity": "sha512-V48klKZl8T6MzatbLlzzRNhMepEys9Y4oGFpypBFFn1gLI/QQ9HtLLyWJNbPlwGLelOVOEijUbTTJeLLI59jLw==", - "dev": true, - "requires": { - "faye-websocket": "^0.10.0", - "uuid": "^3.0.1" - } - }, - "sockjs-client": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/sockjs-client/-/sockjs-client-1.3.0.tgz", - "integrity": "sha512-R9jxEzhnnrdxLCNln0xg5uGHqMnkhPSTzUZH2eXcR03S/On9Yvoq2wyUZILRUhZCNVu2PmwWVoyuiPz8th8zbg==", - "dev": true, - "requires": { - "debug": "^3.2.5", - "eventsource": "^1.0.7", - "faye-websocket": "~0.11.1", - "inherits": "^2.0.3", - "json3": "^3.3.2", - "url-parse": "^1.4.3" - }, - "dependencies": { - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "faye-websocket": { - "version": "0.11.3", - "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.3.tgz", - "integrity": "sha512-D2y4bovYpzziGgbHYtGCMjlJM36vAl/y+xUyn1C+FVx8szd1E+86KwVw6XvYSzOP8iMpm1X0I4xJD+QtUb36OA==", - "dev": true, - "requires": { - "websocket-driver": ">=0.5.1" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - } - } - }, - "socks": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.3.2.tgz", - "integrity": "sha512-pCpjxQgOByDHLlNqlnh/mNSAxIUkyBBuwwhTcV+enZGbDaClPvHdvm6uvOwZfFJkam7cGhBNbb4JxiP8UZkRvQ==", - "dev": true, - "requires": { - "ip": "^1.1.5", - "smart-buffer": "4.0.2" - } - }, - "socks-proxy-agent": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-4.0.2.tgz", - "integrity": "sha512-NT6syHhI9LmuEMSK6Kd2V7gNv5KFZoLE7V5udWmn0de+3Mkj3UMA/AJPLyeNUVmElCurSHtUdM3ETpR3z770Wg==", - "dev": true, - "requires": { - "agent-base": "~4.2.1", - "socks": "~2.3.2" - }, - "dependencies": { - "agent-base": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.2.1.tgz", - "integrity": "sha512-JVwXMr9nHYTUXsBFKUqhJwvlcYU/blreOEUkhNR2eXZIvwd+c+o5V4MgDPKWnMS/56awN3TRzIP+KoPn+roQtg==", - "dev": true, - "requires": { - "es6-promisify": "^5.0.0" - } - } - } - }, - "sort-keys": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-2.0.0.tgz", - "integrity": "sha1-ZYU1WEhh7JfXMNbPQYIuH1ZoQSg=", - "dev": true, - "requires": { - "is-plain-obj": "^1.0.0" - } - }, - "source-list-map": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz", - "integrity": "sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==", - "dev": true - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" - }, - "source-map-loader": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/source-map-loader/-/source-map-loader-0.2.4.tgz", - "integrity": "sha512-OU6UJUty+i2JDpTItnizPrlpOIBLmQbWMuBg9q5bVtnHACqw1tn9nNwqJLbv0/00JjnJb/Ee5g5WS5vrRv7zIQ==", - "dev": true, - "requires": { - "async": "^2.5.0", - "loader-utils": "^1.1.0" - } - }, - "source-map-resolve": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz", - "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==", - "requires": { - "atob": "^2.1.1", - "decode-uri-component": "^0.2.0", - "resolve-url": "^0.2.1", - "source-map-url": "^0.4.0", - "urix": "^0.1.0" - } - }, - "source-map-support": { - "version": "0.5.12", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.12.tgz", - "integrity": "sha512-4h2Pbvyy15EE02G+JOZpUCmqWJuqrs+sEkzewTm++BPi7Hvn/HwcqLAcNxYAyI0x13CpPPn+kMjl+hplXMHITQ==", - "requires": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" - } - } - }, - "source-map-url": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", - "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=" - }, - "sourcemap-codec": { - "version": "1.4.6", - "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.6.tgz", - "integrity": "sha512-1ZooVLYFxC448piVLBbtOxFcXwnymH9oUF8nRd3CuYDVvkRBxRl6pB4Mtas5a4drtL+E8LDgFkQNcgIw6tc8Hg==", - "dev": true - }, - "spdx-correct": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz", - "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==", - "requires": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-exceptions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz", - "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==" - }, - "spdx-expression-parse": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", - "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", - "requires": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-license-ids": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz", - "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==" - }, - "spdy": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.0.tgz", - "integrity": "sha512-ot0oEGT/PGUpzf/6uk4AWLqkq+irlqHXkrdbk51oWONh3bxQmBuljxPNl66zlRRcIJStWq0QkLUCPOPjgjvU0Q==", - "dev": true, - "requires": { - "debug": "^4.1.0", - "handle-thing": "^2.0.0", - "http-deceiver": "^1.2.7", - "select-hose": "^2.0.0", - "spdy-transport": "^3.0.0" - }, - "dependencies": { - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - } - } - }, - "spdy-transport": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz", - "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==", - "dev": true, - "requires": { - "debug": "^4.1.0", - "detect-node": "^2.0.4", - "hpack.js": "^2.1.6", - "obuf": "^1.1.2", - "readable-stream": "^3.0.6", - "wbuf": "^1.7.3" - }, - "dependencies": { - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "readable-stream": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.4.0.tgz", - "integrity": "sha512-jItXPLmrSR8jmTRmRWJXCnGJsfy85mB3Wd/uINMXA65yrnFo0cPClFIUWzo2najVNSl+mx7/4W8ttlLWJe99pQ==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - } - } - }, - "speed-measure-webpack-plugin": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/speed-measure-webpack-plugin/-/speed-measure-webpack-plugin-1.3.1.tgz", - "integrity": "sha512-qVIkJvbtS9j/UeZumbdfz0vg+QfG/zxonAjzefZrqzkr7xOncLVXkeGbTpzd1gjCBM4PmVNkWlkeTVhgskAGSQ==", - "dev": true, - "requires": { - "chalk": "^2.0.1" - } - }, - "spinkit": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/spinkit/-/spinkit-1.2.5.tgz", - "integrity": "sha1-kPn0ZqIOjjnvJNqVnB5hHCow3VQ=" - }, - "split-string": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", - "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", - "requires": { - "extend-shallow": "^3.0.0" - } - }, - "sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" - }, - "sshpk": { - "version": "1.16.1", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", - "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", - "requires": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "bcrypt-pbkdf": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jsbn": "~0.1.0", - "safer-buffer": "^2.0.2", - "tweetnacl": "~0.14.0" - } - }, - "ssri": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.1.tgz", - "integrity": "sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA==", - "dev": true, - "requires": { - "figgy-pudding": "^3.5.1" - } - }, - "static-extend": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", - "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", - "requires": { - "define-property": "^0.2.5", - "object-copy": "^0.1.0" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "requires": { - "is-descriptor": "^0.1.0" - } - } - } - }, - "stats-webpack-plugin": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/stats-webpack-plugin/-/stats-webpack-plugin-0.7.0.tgz", - "integrity": "sha512-NT0YGhwuQ0EOX+uPhhUcI6/+1Sq/pMzNuSCBVT4GbFl/ac6I/JZefBcjlECNfAb1t3GOx5dEj1Z7x0cAxeeVLQ==", - "dev": true, - "requires": { - "lodash": "^4.17.4" - } - }, - "statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", - "dev": true - }, - "stdout-stream": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/stdout-stream/-/stdout-stream-1.4.1.tgz", - "integrity": "sha512-j4emi03KXqJWcIeF8eIXkjMFN1Cmb8gUlDYGeBALLPo5qdyTfA9bOtl8m33lRoC+vFMkP3gl0WsDr6+gzxbbTA==", - "optional": true, - "requires": { - "readable-stream": "^2.0.1" - } - }, - "store": { - "version": "2.0.12", - "resolved": "https://registry.npmjs.org/store/-/store-2.0.12.tgz", - "integrity": "sha1-jFNOKguDH3K3X8XxEZhXxE711ZM=" - }, - "stream-browserify": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.2.tgz", - "integrity": "sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg==", - "dev": true, - "requires": { - "inherits": "~2.0.1", - "readable-stream": "^2.0.2" - } - }, - "stream-each": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/stream-each/-/stream-each-1.2.3.tgz", - "integrity": "sha512-vlMC2f8I2u/bZGqkdfLQW/13Zihpej/7PmSiMQsbYddxuTsJp8vRe2x2FvVExZg7FaOds43ROAuFJwPR4MTZLw==", - "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "stream-shift": "^1.0.0" - } - }, - "stream-http": { - "version": "2.8.3", - "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.3.tgz", - "integrity": "sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw==", - "dev": true, - "requires": { - "builtin-status-codes": "^3.0.0", - "inherits": "^2.0.1", - "readable-stream": "^2.3.6", - "to-arraybuffer": "^1.0.0", - "xtend": "^4.0.0" - } - }, - "stream-shift": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.0.tgz", - "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=", - "dev": true - }, - "strict-uri-encode": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz", - "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=", - "dev": true - }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - }, - "dependencies": { - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - } - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", - "requires": { - "is-utf8": "^0.2.0" - } - }, - "strip-eof": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", - "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", - "dev": true - }, - "strip-indent": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", - "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", - "optional": true, - "requires": { - "get-stdin": "^4.0.1" - } - }, - "style-loader": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-0.23.1.tgz", - "integrity": "sha512-XK+uv9kWwhZMZ1y7mysB+zoihsEj4wneFWAS5qoiLwzW0WzSqMrrsIy+a3zkQJq0ipFtBpX5W3MqyRIBF/WFGg==", - "dev": true, - "requires": { - "loader-utils": "^1.1.0", - "schema-utils": "^1.0.0" - } - }, - "stylus": { - "version": "0.54.5", - "resolved": "https://registry.npmjs.org/stylus/-/stylus-0.54.5.tgz", - "integrity": "sha1-QrlWCTHKcJDOhRWnmLqeaqPW3Hk=", - "dev": true, - "requires": { - "css-parse": "1.7.x", - "debug": "*", - "glob": "7.0.x", - "mkdirp": "0.5.x", - "sax": "0.5.x", - "source-map": "0.1.x" - }, - "dependencies": { - "glob": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.0.6.tgz", - "integrity": "sha1-IRuvr0nlJbjNkyYNFKsTYVKz9Xo=", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.2", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "sax": { - "version": "0.5.8", - "resolved": "https://registry.npmjs.org/sax/-/sax-0.5.8.tgz", - "integrity": "sha1-1HLbIo6zMcJQaw6MFVJK25OdEsE=", - "dev": true - }, - "source-map": { - "version": "0.1.43", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", - "integrity": "sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y=", - "dev": true, - "requires": { - "amdefine": ">=0.0.4" - } - } - } - }, - "stylus-loader": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/stylus-loader/-/stylus-loader-3.0.2.tgz", - "integrity": "sha512-+VomPdZ6a0razP+zinir61yZgpw2NfljeSsdUF5kJuEzlo3khXhY19Fn6l8QQz1GRJGtMCo8nG5C04ePyV7SUA==", - "dev": true, - "requires": { - "loader-utils": "^1.0.2", - "lodash.clonedeep": "^4.5.0", - "when": "~3.6.x" - } - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "requires": { - "has-flag": "^3.0.0" - } - }, - "sweetalert2": { - "version": "7.33.1", - "resolved": "https://registry.npmjs.org/sweetalert2/-/sweetalert2-7.33.1.tgz", - "integrity": "sha512-69KYtyhtxejFG0HDb8aVhAwbpAWPSTZwaL5vxDHgojErD2KeFxTmRgmkbiLtMC8UdTFXRmvTPtZTF4459MUb7w==" - }, - "symbol-observable": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz", - "integrity": "sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==", - "dev": true - }, - "tapable": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", - "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==" - }, - "tar": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.2.tgz", - "integrity": "sha512-FCEhQ/4rE1zYv9rYXJw/msRqsnmlje5jHP6huWeBZ704jUTy02c5AZyWujpMR1ax6mVw9NyJMfuK2CMDWVIfgA==", - "optional": true, - "requires": { - "block-stream": "*", - "fstream": "^1.0.12", - "inherits": "2" - } - }, - "terser": { - "version": "3.17.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-3.17.0.tgz", - "integrity": "sha512-/FQzzPJmCpjAH9Xvk2paiWrFq+5M6aVOf+2KRbwhByISDX/EujxsK+BAvrhb6H+2rtrLCHK9N01wO014vrIwVQ==", - "dev": true, - "requires": { - "commander": "^2.19.0", - "source-map": "~0.6.1", - "source-map-support": "~0.5.10" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } - } - }, - "terser-webpack-plugin": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.2.3.tgz", - "integrity": "sha512-GOK7q85oAb/5kE12fMuLdn2btOS9OBZn4VsecpHDywoUC/jLhSAKOiYo0ezx7ss2EXPMzyEWFoE0s1WLE+4+oA==", - "dev": true, - "requires": { - "cacache": "^11.0.2", - "find-cache-dir": "^2.0.0", - "schema-utils": "^1.0.0", - "serialize-javascript": "^1.4.0", - "source-map": "^0.6.1", - "terser": "^3.16.1", - "webpack-sources": "^1.1.0", - "worker-farm": "^1.5.2" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } - } - }, - "through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" - }, - "through2": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", - "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", - "dev": true, - "requires": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" - } - }, - "thunky": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.0.3.tgz", - "integrity": "sha512-YwT8pjmNcAXBZqrubu22P4FYsh2D4dxRmnWBOL8Jk8bUcRUtc5326kx32tuTmFDAZtLOGEVNl8POAR8j896Iow==", - "dev": true - }, - "timers-browserify": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.10.tgz", - "integrity": "sha512-YvC1SV1XdOUaL6gx5CoGroT3Gu49pK9+TZ38ErPldOWW4j49GI1HKs9DV+KGq/w6y+LZ72W1c8cKz2vzY+qpzg==", - "dev": true, - "requires": { - "setimmediate": "^1.0.4" - } - }, - "tmp": { - "version": "0.0.30", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.30.tgz", - "integrity": "sha1-ckGdSovn1s51FI/YsyTlk6cRwu0=", - "requires": { - "os-tmpdir": "~1.0.1" - } - }, - "to-array": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/to-array/-/to-array-0.1.4.tgz", - "integrity": "sha1-F+bBH3PdTz10zaek/zI46a2b+JA=" - }, - "to-arraybuffer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", - "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=", - "dev": true - }, - "to-fast-properties": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", - "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=", - "dev": true - }, - "to-object-path": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", - "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "to-regex": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", - "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", - "requires": { - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "regex-not": "^1.0.2", - "safe-regex": "^1.1.0" - } - }, - "to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", - "requires": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" - } - }, - "toidentifier": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", - "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", - "dev": true - }, - "tough-cookie": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", - "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", - "requires": { - "psl": "^1.1.24", - "punycode": "^1.4.1" - }, - "dependencies": { - "punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" - } - } - }, - "tree-kill": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.1.tgz", - "integrity": "sha512-4hjqbObwlh2dLyW4tcz0Ymw0ggoaVDMveUB9w8kFSQScdRLo0gxO9J7WFcUBo+W3C1TLdFIEwNOWebgZZ0RH9Q==", - "dev": true - }, - "trim-newlines": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", - "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=", - "optional": true - }, - "trim-right": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", - "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=", - "dev": true - }, - "true-case-path": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/true-case-path/-/true-case-path-1.0.3.tgz", - "integrity": "sha512-m6s2OdQe5wgpFMC+pAJ+q9djG82O2jcHPOI6RNg1yy9rCYR+WD6Nbpl32fDpfC56nirdRy+opFa/Vk7HYhqaew==", - "optional": true, - "requires": { - "glob": "^7.1.2" - } - }, - "ts-node": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-5.0.1.tgz", - "integrity": "sha512-XK7QmDcNHVmZkVtkiwNDWiERRHPyU8nBqZB1+iv2UhOG0q3RQ9HsZ2CMqISlFbxjrYFGfG2mX7bW4dAyxBVzUw==", - "optional": true, - "requires": { - "arrify": "^1.0.0", - "chalk": "^2.3.0", - "diff": "^3.1.0", - "make-error": "^1.1.1", - "minimist": "^1.2.0", - "mkdirp": "^0.5.1", - "source-map-support": "^0.5.3", - "yn": "^2.0.0" - } - }, - "tslib": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", - "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==" - }, - "tslint": { - "version": "5.18.0", - "resolved": "https://registry.npmjs.org/tslint/-/tslint-5.18.0.tgz", - "integrity": "sha512-Q3kXkuDEijQ37nXZZLKErssQVnwCV/+23gFEMROi8IlbaBG6tXqLPQJ5Wjcyt/yHPKBC+hD5SzuGaMora+ZS6w==", - "requires": { - "@babel/code-frame": "^7.0.0", - "builtin-modules": "^1.1.1", - "chalk": "^2.3.0", - "commander": "^2.12.1", - "diff": "^3.2.0", - "glob": "^7.1.1", - "js-yaml": "^3.13.1", - "minimatch": "^3.0.4", - "mkdirp": "^0.5.1", - "resolve": "^1.3.2", - "semver": "^5.3.0", - "tslib": "^1.8.0", - "tsutils": "^2.29.0" - } - }, - "tslint-angular": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/tslint-angular/-/tslint-angular-1.1.2.tgz", - "integrity": "sha512-YDLdgQXBSFcVdDZH3mThx21fKzRctIgmCWpuwmppFLc7QHV3tdWDaFnD5lwUmgvLH8W0o+KsXhSzZ2uIsFJ+YA==", - "requires": { - "codelyzer": "^4.0.2", - "tslint": "^5.8.0" - } - }, - "tsutils": { - "version": "2.29.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz", - "integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==", - "requires": { - "tslib": "^1.8.1" - } - }, - "tty-browserify": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", - "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=", - "dev": true - }, - "tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", - "requires": { - "safe-buffer": "^5.0.1" - } - }, - "tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" - }, - "type": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/type/-/type-1.0.1.tgz", - "integrity": "sha512-MAM5dBMJCJNKs9E7JXo4CXRAansRfG0nlJxW7Wf6GZzSOvH31zClSaHdIMWLehe/EGMBkqeC55rrkaOr5Oo7Nw==" - }, - "type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", - "dev": true, - "requires": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" - } - }, - "typedarray": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", - "dev": true - }, - "typescript": { - "version": "3.4.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.4.5.tgz", - "integrity": "sha512-YycBxUb49UUhdNMU5aJ7z5Ej2XGmaIBL0x34vZ82fn3hGvD+bgrMrVDpatgz2f7YxUMJxMkbWxJZeAvDxVe7Vw==", - "dev": true - }, - "union-value": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", - "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", - "requires": { - "arr-union": "^3.1.0", - "get-value": "^2.0.6", - "is-extendable": "^0.1.1", - "set-value": "^2.0.1" - } - }, - "unique-filename": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", - "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", - "dev": true, - "requires": { - "unique-slug": "^2.0.0" - } - }, - "unique-slug": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", - "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", - "dev": true, - "requires": { - "imurmurhash": "^0.1.4" - } - }, - "universal-analytics": { - "version": "0.4.20", - "resolved": "https://registry.npmjs.org/universal-analytics/-/universal-analytics-0.4.20.tgz", - "integrity": "sha512-gE91dtMvNkjO+kWsPstHRtSwHXz0l2axqptGYp5ceg4MsuurloM0PU3pdOfpb5zBXUvyjT4PwhWK2m39uczZuw==", - "dev": true, - "requires": { - "debug": "^3.0.0", - "request": "^2.88.0", - "uuid": "^3.0.0" - }, - "dependencies": { - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - } - } - }, - "unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", - "dev": true - }, - "unset-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", - "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", - "requires": { - "has-value": "^0.3.1", - "isobject": "^3.0.0" - }, - "dependencies": { - "has-value": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", - "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", - "requires": { - "get-value": "^2.0.3", - "has-values": "^0.1.4", - "isobject": "^2.0.0" - }, - "dependencies": { - "isobject": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", - "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", - "requires": { - "isarray": "1.0.0" - } - } - } - }, - "has-values": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", - "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=" - } - } - }, - "upath": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/upath/-/upath-1.1.2.tgz", - "integrity": "sha512-kXpym8nmDmlCBr7nKdIx8P2jNBa+pBpIUFRnKJ4dr8htyYGJFokkr2ZvERRtUN+9SY+JqXouNgUPtv6JQva/2Q==", - "dev": true - }, - "uri-js": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", - "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", - "requires": { - "punycode": "^2.1.0" - } - }, - "urix": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", - "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=" - }, - "url": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", - "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", - "requires": { - "punycode": "1.3.2", - "querystring": "0.2.0" - }, - "dependencies": { - "punycode": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", - "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=" - } - } - }, - "url-parse": { - "version": "1.4.7", - "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.4.7.tgz", - "integrity": "sha512-d3uaVyzDB9tQoSXFvuSUNFibTd9zxd2bkVrDRvF5TmvWWQwqE4lgYJ5m+x1DbecWkw+LK4RNl2CU1hHuOKPVlg==", - "requires": { - "querystringify": "^2.1.1", - "requires-port": "^1.0.0" - } - }, - "use": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", - "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==" - }, - "util": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/util/-/util-0.11.1.tgz", - "integrity": "sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ==", - "dev": true, - "requires": { - "inherits": "2.0.3" - }, - "dependencies": { - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", - "dev": true - } - } - }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" - }, - "utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", - "dev": true - }, - "uuid": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", - "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==" - }, - "validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "requires": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, - "validate-npm-package-name": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-3.0.0.tgz", - "integrity": "sha1-X6kS2B630MdK/BQN5zF/DKffQ34=", - "dev": true, - "requires": { - "builtins": "^1.0.3" - } - }, - "vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", - "dev": true - }, - "verror": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", - "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", - "requires": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" - } - }, - "vm-browserify": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.0.tgz", - "integrity": "sha512-iq+S7vZJE60yejDYM0ek6zg308+UZsdtPExWP9VZoCFCz1zkJoXFnAX7aZfd/ZwrkidzdUZL0C/ryW+JwAiIGw==", - "dev": true - }, - "watchpack": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.6.0.tgz", - "integrity": "sha512-i6dHe3EyLjMmDlU1/bGQpEw25XSjkJULPuAVKCbNRefQVq48yXKUpwg538F7AZTf9kyr57zj++pQFltUa5H7yA==", - "dev": true, - "requires": { - "chokidar": "^2.0.2", - "graceful-fs": "^4.1.2", - "neo-async": "^2.5.0" - } - }, - "wbuf": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz", - "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==", - "dev": true, - "requires": { - "minimalistic-assert": "^1.0.0" - } - }, - "webdriver-js-extender": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/webdriver-js-extender/-/webdriver-js-extender-2.1.0.tgz", - "integrity": "sha512-lcUKrjbBfCK6MNsh7xaY2UAUmZwe+/ib03AjVOpFobX4O7+83BUveSrLfU0Qsyb1DaKJdQRbuU+kM9aZ6QUhiQ==", - "optional": true, - "requires": { - "@types/selenium-webdriver": "^3.0.0", - "selenium-webdriver": "^3.0.1" - } - }, - "webpack": { - "version": "4.30.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.30.0.tgz", - "integrity": "sha512-4hgvO2YbAFUhyTdlR4FNyt2+YaYBYHavyzjCMbZzgglo02rlKi/pcsEzwCuCpsn1ryzIl1cq/u8ArIKu8JBYMg==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.8.5", - "@webassemblyjs/helper-module-context": "1.8.5", - "@webassemblyjs/wasm-edit": "1.8.5", - "@webassemblyjs/wasm-parser": "1.8.5", - "acorn": "^6.0.5", - "acorn-dynamic-import": "^4.0.0", - "ajv": "^6.1.0", - "ajv-keywords": "^3.1.0", - "chrome-trace-event": "^1.0.0", - "enhanced-resolve": "^4.1.0", - "eslint-scope": "^4.0.0", - "json-parse-better-errors": "^1.0.2", - "loader-runner": "^2.3.0", - "loader-utils": "^1.1.0", - "memory-fs": "~0.4.1", - "micromatch": "^3.1.8", - "mkdirp": "~0.5.0", - "neo-async": "^2.5.0", - "node-libs-browser": "^2.0.0", - "schema-utils": "^1.0.0", - "tapable": "^1.1.0", - "terser-webpack-plugin": "^1.1.0", - "watchpack": "^1.5.0", - "webpack-sources": "^1.3.0" - } - }, - "webpack-core": { - "version": "0.6.9", - "resolved": "https://registry.npmjs.org/webpack-core/-/webpack-core-0.6.9.tgz", - "integrity": "sha1-/FcViMhVjad76e+23r3Fo7FyvcI=", - "dev": true, - "requires": { - "source-list-map": "~0.1.7", - "source-map": "~0.4.1" - }, - "dependencies": { - "source-list-map": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-0.1.8.tgz", - "integrity": "sha1-xVCyq1Qn9rPyH1r+rYjE9Vh7IQY=", - "dev": true - }, - "source-map": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", - "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", - "dev": true, - "requires": { - "amdefine": ">=0.0.4" - } - } - } - }, - "webpack-dev-middleware": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-3.6.2.tgz", - "integrity": "sha512-A47I5SX60IkHrMmZUlB0ZKSWi29TZTcPz7cha1Z75yYOsgWh/1AcPmQEbC8ZIbU3A1ytSv1PMU0PyPz2Lmz2jg==", - "dev": true, - "requires": { - "memory-fs": "^0.4.1", - "mime": "^2.3.1", - "range-parser": "^1.0.3", - "webpack-log": "^2.0.0" - }, - "dependencies": { - "mime": { - "version": "2.4.4", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.4.tgz", - "integrity": "sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA==", - "dev": true - }, - "webpack-log": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/webpack-log/-/webpack-log-2.0.0.tgz", - "integrity": "sha512-cX8G2vR/85UYG59FgkoMamwHUIkSSlV3bBMRsbxVXVUk2j6NleCKjQ/WE9eYg9WY4w25O9w8wKP4rzNZFmUcUg==", - "dev": true, - "requires": { - "ansi-colors": "^3.0.0", - "uuid": "^3.3.2" - } - } - } - }, - "webpack-dev-server": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-3.3.1.tgz", - "integrity": "sha512-jY09LikOyGZrxVTXK0mgIq9y2IhCoJ05848dKZqX1gAGLU1YDqgpOT71+W53JH/wI4v6ky4hm+KvSyW14JEs5A==", - "dev": true, - "requires": { - "ansi-html": "0.0.7", - "bonjour": "^3.5.0", - "chokidar": "^2.1.5", - "compression": "^1.7.4", - "connect-history-api-fallback": "^1.6.0", - "debug": "^4.1.1", - "del": "^4.1.0", - "express": "^4.16.4", - "html-entities": "^1.2.1", - "http-proxy-middleware": "^0.19.1", - "import-local": "^2.0.0", - "internal-ip": "^4.2.0", - "ip": "^1.1.5", - "killable": "^1.0.1", - "loglevel": "^1.6.1", - "opn": "^5.5.0", - "portfinder": "^1.0.20", - "schema-utils": "^1.0.0", - "selfsigned": "^1.10.4", - "semver": "^6.0.0", - "serve-index": "^1.9.1", - "sockjs": "0.3.19", - "sockjs-client": "1.3.0", - "spdy": "^4.0.0", - "strip-ansi": "^3.0.1", - "supports-color": "^6.1.0", - "url": "^0.11.0", - "webpack-dev-middleware": "^3.6.2", - "webpack-log": "^2.0.0", - "yargs": "12.0.5" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - }, - "camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true - }, - "cliui": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz", - "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", - "dev": true, - "requires": { - "string-width": "^2.1.1", - "strip-ansi": "^4.0.0", - "wrap-ansi": "^2.0.0" - }, - "dependencies": { - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "^3.0.0" - } - } - } - }, - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "del": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/del/-/del-4.1.1.tgz", - "integrity": "sha512-QwGuEUouP2kVwQenAsOof5Fv8K9t3D8Ca8NxcXKrIpEHjTXK5J2nXLdP+ALI1cgv8wj7KuwBhTwBkOZSJKM5XQ==", - "dev": true, - "requires": { - "@types/glob": "^7.1.1", - "globby": "^6.1.0", - "is-path-cwd": "^2.0.0", - "is-path-in-cwd": "^2.0.0", - "p-map": "^2.0.0", - "pify": "^4.0.1", - "rimraf": "^2.6.3" - } - }, - "find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "requires": { - "locate-path": "^3.0.0" - } - }, - "globby": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", - "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=", - "dev": true, - "requires": { - "array-union": "^1.0.1", - "glob": "^7.0.3", - "object-assign": "^4.0.1", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" - }, - "dependencies": { - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true - } - } - }, - "invert-kv": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz", - "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true - }, - "is-path-cwd": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz", - "integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==", - "dev": true - }, - "is-path-in-cwd": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-2.1.0.tgz", - "integrity": "sha512-rNocXHgipO+rvnP6dk3zI20RpOtrAM/kzbB258Uw5BWr3TpXi861yzjo16Dn4hUox07iw5AyeMLHWsujkjzvRQ==", - "dev": true, - "requires": { - "is-path-inside": "^2.1.0" - } - }, - "is-path-inside": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-2.1.0.tgz", - "integrity": "sha512-wiyhTzfDWsvwAW53OBWF5zuvaOGlZ6PwYxAbPVDhpm+gM09xKQGjBq/8uYN12aDvMxnAnq3dxTyoSoRNmg5YFg==", - "dev": true, - "requires": { - "path-is-inside": "^1.0.2" - } - }, - "lcid": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz", - "integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==", - "dev": true, - "requires": { - "invert-kv": "^2.0.0" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "os-locale": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz", - "integrity": "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==", - "dev": true, - "requires": { - "execa": "^1.0.0", - "lcid": "^2.0.0", - "mem": "^4.0.0" - } - }, - "pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", - "dev": true - }, - "semver": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.2.0.tgz", - "integrity": "sha512-jdFC1VdUGT/2Scgbimf7FSx9iJLXoqfglSF+gJeuNWVpiE37OIbc1jywR/GJyFdz3mnkz2/id0L0J/cr0izR5A==", - "dev": true - }, - "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true, - "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - }, - "dependencies": { - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "^3.0.0" - } - } - } - }, - "supports-color": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", - "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - }, - "webpack-log": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/webpack-log/-/webpack-log-2.0.0.tgz", - "integrity": "sha512-cX8G2vR/85UYG59FgkoMamwHUIkSSlV3bBMRsbxVXVUk2j6NleCKjQ/WE9eYg9WY4w25O9w8wKP4rzNZFmUcUg==", - "dev": true, - "requires": { - "ansi-colors": "^3.0.0", - "uuid": "^3.3.2" - } - }, - "which-module": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", - "dev": true - }, - "yargs": { - "version": "12.0.5", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.5.tgz", - "integrity": "sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw==", - "dev": true, - "requires": { - "cliui": "^4.0.0", - "decamelize": "^1.2.0", - "find-up": "^3.0.0", - "get-caller-file": "^1.0.1", - "os-locale": "^3.0.0", - "require-directory": "^2.1.1", - "require-main-filename": "^1.0.1", - "set-blocking": "^2.0.0", - "string-width": "^2.0.0", - "which-module": "^2.0.0", - "y18n": "^3.2.1 || ^4.0.0", - "yargs-parser": "^11.1.1" - } - }, - "yargs-parser": { - "version": "11.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-11.1.1.tgz", - "integrity": "sha512-C6kB/WJDiaxONLJQnF8ccx9SEeoTTLek8RVbaOIsrAUS8VrBEXfmeSnCZxygc+XC2sNMBIwOOnfcxiynjHsVSQ==", - "dev": true, - "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } - } - } - }, - "webpack-log": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/webpack-log/-/webpack-log-1.2.0.tgz", - "integrity": "sha512-U9AnICnu50HXtiqiDxuli5gLB5PGBo7VvcHx36jRZHwK4vzOYLbImqT4lwWwoMHdQWwEKw736fCHEekokTEKHA==", - "requires": { - "chalk": "^2.1.0", - "log-symbols": "^2.1.0", - "loglevelnext": "^1.0.1", - "uuid": "^3.1.0" - } - }, - "webpack-merge": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-4.2.1.tgz", - "integrity": "sha512-4p8WQyS98bUJcCvFMbdGZyZmsKuWjWVnVHnAS3FFg0HDaRVrPbkivx2RYCre8UiemD67RsiFFLfn4JhLAin8Vw==", - "dev": true, - "requires": { - "lodash": "^4.17.5" - } - }, - "webpack-sources": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.3.0.tgz", - "integrity": "sha512-OiVgSrbGu7NEnEvQJJgdSFPl2qWKkWq5lHMhgiToIiN9w34EBnjYzSYs+VbL5KoYiLNtFFa7BZIKxRED3I32pA==", - "dev": true, - "requires": { - "source-list-map": "^2.0.0", - "source-map": "~0.6.1" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } - } - }, - "webpack-subresource-integrity": { - "version": "1.1.0-rc.6", - "resolved": "https://registry.npmjs.org/webpack-subresource-integrity/-/webpack-subresource-integrity-1.1.0-rc.6.tgz", - "integrity": "sha512-Az7y8xTniNhaA0620AV1KPwWOqawurVVDzQSpPAeR5RwNbL91GoBSJAAo9cfd+GiFHwsS5bbHepBw1e6Hzxy4w==", - "dev": true, - "requires": { - "webpack-core": "^0.6.8" - } - }, - "websocket-driver": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.3.tgz", - "integrity": "sha512-bpxWlvbbB459Mlipc5GBzzZwhoZgGEZLuqPaR0INBGnPAY1vdBX6hPnoFXiw+3yWxDuHyQjO2oXTMyS8A5haFg==", - "dev": true, - "requires": { - "http-parser-js": ">=0.4.0 <0.4.11", - "safe-buffer": ">=5.1.0", - "websocket-extensions": ">=0.1.1" - } - }, - "websocket-extensions": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.3.tgz", - "integrity": "sha512-nqHUnMXmBzT0w570r2JpJxfiSD1IzoI+HGVdd3aZ0yNi3ngvQ4jv1dtHt5VGxfI2yj5yqImPhOK4vmIh2xMbGg==", - "dev": true - }, - "whatwg-fetch": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.0.0.tgz", - "integrity": "sha512-9GSJUgz1D4MfyKU7KRqwOjXCXTqWdFNvEr7eUBYchQiVc744mqK/MzXPNR2WsPkmkOa4ywfg8C2n8h+13Bey1Q==" - }, - "when": { - "version": "3.6.4", - "resolved": "https://registry.npmjs.org/when/-/when-3.6.4.tgz", - "integrity": "sha1-RztRfsFZ4rhQBUl6E5g/CVQS404=", - "dev": true - }, - "which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "requires": { - "isexe": "^2.0.0" - } - }, - "which-module": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", - "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=", - "optional": true - }, - "wide-align": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", - "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", - "requires": { - "string-width": "^1.0.2 || 2" - } - }, - "wordwrap": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", - "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", - "optional": true - }, - "worker-farm": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.7.0.tgz", - "integrity": "sha512-rvw3QTZc8lAxyVrqcSGVm5yP/IJ2UcB3U0graE3LCFoZ0Yn2x4EoVSqJKdB/T5M+FLcRPjz4TDacRf3OCfNUzw==", - "dev": true, - "requires": { - "errno": "~0.1.7" - } - }, - "worker-plugin": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/worker-plugin/-/worker-plugin-3.1.0.tgz", - "integrity": "sha512-iQ9KTTmmN5fhfc2KMR7CcDblvcrg1QQ4pXymqZ3cRZF8L0890YLBcEqlIsGPdxoFwghyN8RA1pCEhCKuTF4Lkw==", - "dev": true, - "requires": { - "loader-utils": "^1.1.0" - } - }, - "wrap-ansi": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", - "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", - "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1" - } - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" - }, - "ws": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.1.tgz", - "integrity": "sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA==", - "requires": { - "async-limiter": "~1.0.0" - } - }, - "xhr2": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/xhr2/-/xhr2-0.1.4.tgz", - "integrity": "sha1-f4dliEdxbbUCYyOBL4GMras4el8=" - }, - "xml2js": { - "version": "0.4.19", - "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz", - "integrity": "sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q==", - "requires": { - "sax": ">=0.6.0", - "xmlbuilder": "~9.0.1" - } - }, - "xmlbuilder": { - "version": "9.0.7", - "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz", - "integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0=" - }, - "xmlhttprequest-ssl": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz", - "integrity": "sha1-wodrBhaKrcQOV9l+gRkayPQ5iz4=" - }, - "xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "dev": true - }, - "y18n": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", - "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=" - }, - "yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", - "optional": true - }, - "yargs": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-7.1.0.tgz", - "integrity": "sha1-a6MY6xaWFyf10oT46gA+jWFU0Mg=", - "optional": true, - "requires": { - "camelcase": "^3.0.0", - "cliui": "^3.2.0", - "decamelize": "^1.1.1", - "get-caller-file": "^1.0.1", - "os-locale": "^1.4.0", - "read-pkg-up": "^1.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^1.0.1", - "set-blocking": "^2.0.0", - "string-width": "^1.0.2", - "which-module": "^1.0.0", - "y18n": "^3.2.1", - "yargs-parser": "^5.0.0" - }, - "dependencies": { - "camelcase": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", - "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", - "optional": true - } - } - }, - "yargs-parser": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-5.0.0.tgz", - "integrity": "sha1-J17PDX/+Bcd+ZOfIbkzZS/DhIoo=", - "optional": true, - "requires": { - "camelcase": "^3.0.0" - }, - "dependencies": { - "camelcase": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", - "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", - "optional": true - } - } - }, - "yeast": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz", - "integrity": "sha1-AI4G2AlDIMNy28L47XagymyKxBk=" - }, - "yn": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/yn/-/yn-2.0.0.tgz", - "integrity": "sha1-5a2ryKz0CPY4X8dklWhMiOavaJo=", - "optional": true - }, - "zone.js": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/zone.js/-/zone.js-0.9.1.tgz", - "integrity": "sha512-GkPiJL8jifSrKReKaTZ5jkhrMEgXbXYC+IPo1iquBjayRa0q86w3Dipjn8b415jpitMExe9lV8iTsv8tk3DGag==" - } - } -} diff --git a/src/Ombi/ClientApp/package.json b/src/Ombi/ClientApp/package.json index a9358e516..988d20daf 100644 --- a/src/Ombi/ClientApp/package.json +++ b/src/Ombi/ClientApp/package.json @@ -4,29 +4,29 @@ "scripts": { "ng": "ng", "start": "ng serve --port 3578 --configuration hmr", - "build": "node --max_old_space_size=2048 node_modules/@angular/cli/bin/ng build --prod", + "build": "node --max_old_space_size=6144 node_modules/@angular/cli/bin/ng build --prod", "lint": "ng lint" }, "private": true, "dependencies": { - "@angular/animations": "^8.0.0", - "@angular/cdk": "^8.0.0", - "@angular/common": "^8.0.0", - "@angular/compiler": "^8.0.0", - "@angular/core": "^8.0.0", - "@angular/forms": "^8.0.0", - "@angular/http": "^7.2.15", - "@angular/material": "^8.0.0", - "@angular/platform-browser": "^8.0.0", - "@angular/platform-browser-dynamic": "^8.0.0", - "@angular/platform-server": "^8.0.0", - "@angular/router": "^8.0.0", + "@angular/animations": "^9.1.7", + "@angular/cdk": "^9.2.3", + "@angular/common": "^9.1.7", + "@angular/compiler": "^9.1.7", + "@angular/core": "^9.1.7", + "@angular/forms": "^9.1.7", + "@angular/localize": "^11.0.2", + "@angular/material": "^9.2.3", + "@angular/platform-browser": "^9.1.7", + "@angular/platform-browser-dynamic": "^9.1.7", + "@angular/platform-server": "^9.1.7", + "@angular/router": "^9.1.7", "@angularclass/hmr": "^2.1.3", "@aspnet/signalr": "^1.1.0", "@auth0/angular-jwt": "^2.1.0", "@fullcalendar/core": "^4.2.0", + "@fullcalendar/daygrid": "^4.4.0", "@fullcalendar/interaction": "^4.2.0", - "@ng-bootstrap/ng-bootstrap": "^4.0.1", "@ngu/carousel": "^1.4.9-beta-2", "@ngx-translate/core": "^11.0.1", "@ngx-translate/http-loader": "^4.0.0", @@ -34,51 +34,45 @@ "@yellowspot/ng-truncate": "^1.4.0", "angular-bootstrap-md": "^7.5.4", "angular-router-loader": "^0.8.5", - "angular2-template-loader": "^0.6.2", - "aspnet-prerendering": "^3.0.1", - "awesome-typescript-loader": "^5.2.0", + "angularx-qrcode": "^2.1.0", "bootstrap": "^4.2.1", - "chart.js": "2.5.0", + "chart.js": "2.9.4", "core-js": "^2.5.4", "eventemitter2": "^5.0.1", "font-awesome": "^4.7.0", - "fullcalendar":"^4.0.0-alpha.4", - "hammerjs": "^2.0.8", + "fullcalendar": "^4.0.0-alpha.4", "jquery": "3.3.1", "moment": "^2.23.0", "ng2-cookies": "^1.0.12", - "ngx-bootstrap": "^3.1.4", "ngx-clipboard": "^12.1.0", - "ngx-infinite-scroll": "^7.1.0", + "ngx-infinite-scroll": "^9.0.0", "ngx-moment": "^3.0.1", "ngx-order-pipe": "^2.0.1", - "ngx-page-scroll": "^5.0.1", - "pace": "github:HubSpot/pace#v1.0.2", "please-wait": "^0.0.5", "popper.js": "^1.14.3", - "primeicons": "^1.0.0", - "primeng": "^7.0.3", + "primeicons": "^4.0.0", + "primeng": "^10.0.3", "rxjs": "^6.5.2", - "socket.io-client": "^2.2.0", "spinkit": "^1.2.5", "store": "^2.0.12", - "sweetalert2": "^7.33.1", + "ts-md5": "^1.2.7", + "tslib": "^1.10.0", "tslint-angular": "^1.1.2", - "zone.js": "^0.9.1" + "zone.js": "~0.10.2" }, "devDependencies": { - "@angular-devkit/build-angular": "^0.800.2", - "@angular/cli": "~8.0.2", - "@angular/compiler-cli": "8.0.0", - "@angular/language-service": "^8.0.0", + "@angular-devkit/build-angular": "~0.901.6", + "@angular/cli": "~9.1.6", + "@angular/compiler-cli": "^9.1.7", + "@angular/language-service": "^9.1.7", "@types/jasmine": "~2.8.6", "@types/jasminewd2": "~2.0.3", - "@types/node": "~8.9.4", - "codelyzer": "^4.5.0", - "typescript": "~3.4.5" + "@types/node": "^12.11.1", + "codelyzer": "^5.1.2", + "typescript": "~3.8.3" }, "optionalDependencies": { - "node-sass": "^4.11.0", + "node-sass": "^4.12.0", "protractor": "~5.4.0", "ts-node": "~5.0.1", "tslint": "^5.12.0" diff --git a/src/Ombi/ClientApp/src/app/app.component.html b/src/Ombi/ClientApp/src/app/app.component.html index e356c06d2..d4297aeb4 100644 --- a/src/Ombi/ClientApp/src/app/app.component.html +++ b/src/Ombi/ClientApp/src/app/app.component.html @@ -1,5 +1,4 @@ - - + + +
+ +
+
+ {{result.title}} +
+
+
+

{{result.title}}

+
+
+ + + {{'Common.Available' | translate}} + + + + {{'Common.ProcessingRequest' | translate}} + + + + {{'Common.RequestDenied' | translate}} + + + + {{'Common.PendingApproval' | translate}} + + + + play_circle_outline + + + + play_circle_outline + + + + + play_circle_outline + + + + play_circle_outline + + +
+
+ + + + {{'Discovery.CardDetails.Studio' | translate}}: {{movie.productionCompanies[0].name}} + + + {{'Discovery.CardDetails.Network' | translate}}: + {{tv.network.name}} + + + {{'Discovery.CardDetails.Director' | translate}}: {{movie.credits.crew[0].name}} + + Director: {{tvCreator}} + + {{'Discovery.CardDetails.InCinemas' | translate}}: + {{movie.releaseDate | amLocal | amDateFormat: 'LL'}} + + {{'Discovery.CardDetails.FirstAired' | translate}}: + {{tv.firstAired | amLocal | amDateFormat: 'LL'}} + + + {{'Discovery.CardDetails.Writer' | translate}}: {{movie.credits.crew[1].name}} + + {{'Discovery.CardDetails.ExecProducer' | translate}}: {{tvProducer}} + + + + + + +
+
+

{{result.overview}}

+
+
+ +
+
+ +
+ + + + + + + + + + +
+ +
+ + + + + + + + {{'Search.ViewOnPlex' | + translate}} + {{'Search.ViewOnEmby' | + translate}} + +
+
+
+
+
+
\ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/discover/components/grid/discover-grid.component.scss b/src/Ombi/ClientApp/src/app/discover/components/grid/discover-grid.component.scss new file mode 100644 index 000000000..caecaddb0 --- /dev/null +++ b/src/Ombi/ClientApp/src/app/discover/components/grid/discover-grid.component.scss @@ -0,0 +1,137 @@ +$ombi-primary:#3f3f3f; +$card-background: #2b2b2b; + +$blue: #1976D2; +$pink: #C2185B; +$green:#1DE9B6; +$orange:#F57C00; + +.btn-blue { + background-color: $blue; +} + +.btn-pink { + background-color: $pink; +} + +.btn-green { + background-color: $green; +} + +.btn-orange { + background-color: $orange; +} + +.btn-spacing { + margin-top:10%; +} + +#cardImage { + border-radius: 5px 5px 0px 0px; + height: 75%; +} + +.dark-card { + border-radius: 8px; +} + +// Changed height to 100% to make all cards the same height +.top-spacing { + margin-top: 1%; +} + +.card-poster { + width: 100%; + border-radius: 8px 0px 0px 8px; + margin-top: -6.5%; + margin-bottom: -6.6%; +} + +.main-container { + margin-left: -2%; +} + + +.rating { + position: absolute; + font-weight: bold; +} + +$border-width: 3px; + +.available { + background-color: #1DE9B6 !important; + color: black !important; +} + +.approved { + background-color: #ff5722 !important; +} + +.requested { + background-color: #ffd740 !important; + color: black !important; +} + +.denied { + background-color: #C2185B !important; +} + +.notrequested { + background-color: #303030 !important; +} + +.expand { + text-align: center; +} + +@media (min-width: 1025px) { + + // Changed height to 100% to make all cards the same height + .grow { + transition: all .2s ease-in-out; + height: 100%; + } + + .grow:hover { + transform: scale(1.1); + } +} + +::ng-deep mat-dialog-container.mat-dialog-container { + // background-color: $ombi-primary; + // color: white; + border-radius: 2% +} + + +/* Title adjust for the Discover page */ +.mat-card-content h6 { + overflow: hidden; + white-space: nowrap; + font-weight: 400; + font-size: 1.1rem; +} + +/* Summary adjust for Discover page */ +.small, +small { + font-size: 0.8rem; +} + +@media (min-width: 2000px) { + #cardImage { + height: 80%; + object-fit: cover; + display: block; + } +} + +.overview { + font-size: 1.2em; +} + +.backdrop { + background-position: 50% 33%; + background-size: cover; +} \ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/discover/components/grid/discover-grid.component.ts b/src/Ombi/ClientApp/src/app/discover/components/grid/discover-grid.component.ts new file mode 100644 index 000000000..4c28c1174 --- /dev/null +++ b/src/Ombi/ClientApp/src/app/discover/components/grid/discover-grid.component.ts @@ -0,0 +1,156 @@ +import { Component, OnInit, Input } from "@angular/core"; +import { IDiscoverCardResult } from "../../interfaces"; +import { RequestType, ISearchTvResult, ISearchMovieResult, ISearchMovieResultContainer } from "../../../interfaces"; +import { ImageService, RequestService, SearchV2Service } from "../../../services"; +import { MatDialog } from "@angular/material/dialog"; +import { ISearchTvResultV2 } from "../../../interfaces/ISearchTvResultV2"; +import { ISearchMovieResultV2 } from "../../../interfaces/ISearchMovieResultV2"; +import { EpisodeRequestComponent } from "../../../shared/episode-request/episode-request.component"; +import { MatSnackBar } from "@angular/material/snack-bar"; +import { Router } from "@angular/router"; +import { DomSanitizer } from "@angular/platform-browser"; + +@Component({ + selector: "discover-grid", + templateUrl: "./discover-grid.component.html", + styleUrls: ["./discover-grid.component.scss"], +}) +export class DiscoverGridComponent implements OnInit { + + @Input() public result: IDiscoverCardResult; + public RequestType = RequestType; + public requesting: boolean; + + public tv: ISearchTvResultV2; + public tvCreator: string; + public tvProducer: string; + public movie: ISearchMovieResultV2; + + constructor(private searchService: SearchV2Service, private dialog: MatDialog, + private requestService: RequestService, private notification: MatSnackBar, + private router: Router, private sanitizer: DomSanitizer, private imageService: ImageService) { } + + public ngOnInit() { + if (this.result.type == RequestType.tvShow) { + this.getExtraTvInfo(); + } + if (this.result.type == RequestType.movie) { + this.getExtraMovieInfo(); + } + } + + public async getExtraTvInfo() { + this.tv = await this.searchService.getTvInfo(this.result.id); + this.setTvDefaults(this.tv); + this.updateTvItem(this.tv); + const creator = this.tv.crew.filter(tv => { + return tv.type === "Creator"; + })[0]; + if (creator && creator.person) { + this.tvCreator = creator.person.name; + } + const crewResult = this.tv.crew.filter(tv => { + return tv.type === "Executive Producer"; + })[0] + if (crewResult && crewResult.person) { + this.tvProducer = crewResult.person.name; + } + this.setTvBackground(); + } + + public openDetails() { + if (this.result.type === RequestType.movie) { + this.router.navigate(['/details/movie/', this.result.id]); + } else if (this.result.type === RequestType.tvShow) { + this.router.navigate(['/details/tv/', this.result.id]); + } + } + + public getStatusClass(): string { + if (this.result.available) { + return "available"; + } + if (this.result.approved) { + return "approved"; + } + if (this.result.requested) { + return "requested"; + } + return "notrequested"; + } + + private getExtraMovieInfo() { + // if (!this.result.imdbid) { + this.searchService.getFullMovieDetails(this.result.id) + .subscribe(m => { + this.movie = m; + this.updateMovieItem(m); + }); + + this.setMovieBackground() + // } + } + + private setMovieBackground(): void { + this.result.background = this.sanitizer.bypassSecurityTrustStyle + ("linear-gradient( rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0.5) ), url(" + "https://image.tmdb.org/t/p/original" + this.result.background + ")"); + } + + private setTvBackground(): void { + if (this.result.background != null) { + this.result.background = this.sanitizer.bypassSecurityTrustStyle + ("linear-gradient( rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0.5) ), url(https://image.tmdb.org/t/p/original" + this.result.background + ")"); + } else { + this.imageService.getTvBanner(this.result.id).subscribe(x => { + if (x) { + this.result.background = this.sanitizer.bypassSecurityTrustStyle + ("linear-gradient( rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0.5) ), url(" + x + ")"); + } + }); + } + } + + private updateMovieItem(updated: ISearchMovieResultV2) { + this.result.url = "http://www.imdb.com/title/" + updated.imdbId + "/"; + this.result.available = updated.available; + this.result.requested = updated.requested; + this.result.requested = updated.requestProcessing; + this.result.rating = updated.voteAverage; + } + + + private setTvDefaults(x: ISearchTvResultV2) { + if (!x.imdbId) { + x.imdbId = "https://www.tvmaze.com/shows/" + x.seriesId; + } else { + x.imdbId = "http://www.imdb.com/title/" + x.imdbId + "/"; + } + } + + private updateTvItem(updated: ISearchTvResultV2) { + this.result.title = updated.title; + this.result.id = updated.id; + this.result.available = updated.fullyAvailable; + this.result.posterPath = updated.banner; + this.result.requested = updated.requested; + this.result.url = updated.imdbId; + } + + public async request() { + this.requesting = true; + if (this.result.type === RequestType.movie) { + const result = await this.requestService.requestMovie({ theMovieDbId: this.result.id, languageCode: "" }).toPromise(); + + if (result.result) { + this.result.requested = true; + this.notification.open(result.message, "Ok"); + } else { + this.notification.open(result.errorMessage, "Ok"); + } + } else if (this.result.type === RequestType.tvShow) { + this.dialog.open(EpisodeRequestComponent, { width: "700px", data: this.tv, panelClass: 'modal-panel' }) + } + this.requesting = false; + } + +} diff --git a/src/Ombi/ClientApp/src/app/discover/components/index.ts b/src/Ombi/ClientApp/src/app/discover/components/index.ts index 428e894e1..e65e48bd3 100644 --- a/src/Ombi/ClientApp/src/app/discover/components/index.ts +++ b/src/Ombi/ClientApp/src/app/discover/components/index.ts @@ -6,7 +6,8 @@ import { DiscoverCardComponent } from "./card/discover-card.component"; import { Routes } from "@angular/router"; import { AuthGuard } from "../../auth/auth.guard"; import { SearchService, RequestService } from "../../services"; -import { MatDialog } from "@angular/material"; +import { MatDialog } from "@angular/material/dialog"; +import { DiscoverGridComponent } from "./grid/discover-grid.component"; export const components: any[] = [ @@ -15,6 +16,7 @@ export const components: any[] = [ DiscoverCardDetailsComponent, DiscoverCollectionsComponent, DiscoverActorComponent, + DiscoverGridComponent, ]; diff --git a/src/Ombi/ClientApp/src/app/discover/discover.module.ts b/src/Ombi/ClientApp/src/app/discover/discover.module.ts index 31e51fe24..e40cf102a 100644 --- a/src/Ombi/ClientApp/src/app/discover/discover.module.ts +++ b/src/Ombi/ClientApp/src/app/discover/discover.module.ts @@ -1,6 +1,7 @@ import { NgModule } from "@angular/core"; import { RouterModule } from "@angular/router"; import { InfiniteScrollModule } from 'ngx-infinite-scroll'; +import {MatButtonToggleModule} from '@angular/material/button-toggle'; import { SharedModule } from "../shared/shared.module"; import { PipeModule } from "../pipes/pipe.module"; @@ -13,6 +14,7 @@ import * as fromComponents from './components'; RouterModule.forChild(fromComponents.routes), SharedModule, PipeModule, + MatButtonToggleModule, InfiniteScrollModule, ], declarations: [ diff --git a/src/Ombi/ClientApp/src/app/discover/interfaces.ts b/src/Ombi/ClientApp/src/app/discover/interfaces.ts index 786c57320..8a3276a2d 100644 --- a/src/Ombi/ClientApp/src/app/discover/interfaces.ts +++ b/src/Ombi/ClientApp/src/app/discover/interfaces.ts @@ -8,8 +8,21 @@ export interface IDiscoverCardResult { type: RequestType; available: boolean; approved: boolean; + denied: boolean; requested: boolean; rating: number; overview: string; imdbid: string; -} \ No newline at end of file + background: string|any; +} + +export enum DiscoverOption { + Combined = 1, + Movie = 2, + Tv = 3 +} + +export enum DisplayOption { + Card = 1, + List = 2 +} diff --git a/src/Ombi/ClientApp/src/app/interfaces/ICommon.ts b/src/Ombi/ClientApp/src/app/interfaces/ICommon.ts index 06f33eb69..13a91af6c 100644 --- a/src/Ombi/ClientApp/src/app/interfaces/ICommon.ts +++ b/src/Ombi/ClientApp/src/app/interfaces/ICommon.ts @@ -29,7 +29,13 @@ export interface IUsersModel { export interface INavBar { icon: string; + faIcon: string; name: string; link: string; requiresAdmin: boolean; + enabled: boolean; + toolTip?: boolean; + toolTipMessage?: string; + style?: string; + externalLink?: boolean; } \ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/interfaces/IMusicSearchResultV2.ts b/src/Ombi/ClientApp/src/app/interfaces/IMusicSearchResultV2.ts index 1f66ac8ba..ca8f62c1e 100644 --- a/src/Ombi/ClientApp/src/app/interfaces/IMusicSearchResultV2.ts +++ b/src/Ombi/ClientApp/src/app/interfaces/IMusicSearchResultV2.ts @@ -35,6 +35,8 @@ export interface IReleaseGroups { fullyAvailable: boolean; image: string; // Set by another api call + + selected: boolean; // Set via UI } export interface IArtistLinks { diff --git a/src/Ombi/ClientApp/src/app/interfaces/INotificationSettings.ts b/src/Ombi/ClientApp/src/app/interfaces/INotificationSettings.ts index 5472a6c7c..d08778e2a 100644 --- a/src/Ombi/ClientApp/src/app/interfaces/INotificationSettings.ts +++ b/src/Ombi/ClientApp/src/app/interfaces/INotificationSettings.ts @@ -27,11 +27,16 @@ export interface INotificationTemplates { } export enum NotificationAgent { - Email, - Discord, - Pushbullet, - Pushover, - Telegram, + Email = 0, + Discord = 1, + Pushbullet = 2, + Pushover = 3, + Telegram = 4, + Slack = 5, + Mattermost = 6, + Mobile = 7, + Gotify = 8, + WhatsApp = 9 } export enum NotificationType { @@ -47,11 +52,13 @@ export enum NotificationType { IssueResolved = 9, IssueComment = 10, Newsletter = 11, + WhatsApp = 12, } export interface IDiscordNotifcationSettings extends INotificationSettings { webhookUrl: string; username: string; + icon: string; notificationTemplates: INotificationTemplates[]; } @@ -85,6 +92,18 @@ export interface IPushbulletNotificationSettings extends INotificationSettings { channelTag: string; } +export interface ITwilioSettings extends ISettings { + whatsAppSettings: IWhatsAppSettings; +} + +export interface IWhatsAppSettings { + enabled: number; + from: string; + accountSid: string; + authToken: string; + notificationTemplates: INotificationTemplates[]; +} + export interface IPushoverNotificationSettings extends INotificationSettings { accessToken: string; notificationTemplates: INotificationTemplates[]; @@ -101,6 +120,11 @@ export interface IGotifyNotificationSettings extends INotificationSettings { priority: number; } +export interface IWebhookNotificationSettings extends INotificationSettings { + webhookUrl: string; + applicationToken: string; +} + export interface IMattermostNotifcationSettings extends INotificationSettings { webhookUrl: string; username: string; diff --git a/src/Ombi/ClientApp/src/app/interfaces/ISearchMovieResult.ts b/src/Ombi/ClientApp/src/app/interfaces/ISearchMovieResult.ts index e52bdd8dc..f2460714f 100644 --- a/src/Ombi/ClientApp/src/app/interfaces/ISearchMovieResult.ts +++ b/src/Ombi/ClientApp/src/app/interfaces/ISearchMovieResult.ts @@ -38,6 +38,7 @@ export interface IMultiSearchResult { id: string; mediaType: string; title: string; + poster: string; } export interface ILanguageRefine { diff --git a/src/Ombi/ClientApp/src/app/interfaces/ISettings.ts b/src/Ombi/ClientApp/src/app/interfaces/ISettings.ts index e56c517ca..0656bb1db 100644 --- a/src/Ombi/ClientApp/src/app/interfaces/ISettings.ts +++ b/src/Ombi/ClientApp/src/app/interfaces/ISettings.ts @@ -16,6 +16,9 @@ export interface IOmbiSettings extends ISettings { doNotSendNotificationsForAutoApprove: boolean; hideRequestsUsers: boolean; defaultLanguageCode: string; + disableHealthChecks: boolean; + autoDeleteAvailableRequests: boolean; + autoDeleteAfterDays: number; } export interface IUpdateSettings extends ISettings { @@ -38,6 +41,7 @@ export interface IEmbySettings extends ISettings { } export interface IEmbyServer extends IExternalSettings { + serverId: string; name: string; apiKey: string; administratorId: string; @@ -46,6 +50,7 @@ export interface IEmbyServer extends IExternalSettings { } export interface IPublicInfo { + id: string; serverName: string; isJellyfin: boolean; } @@ -82,16 +87,19 @@ export interface ISonarrSettings extends IExternalSettings { addOnly: boolean; v3: boolean; languageProfile: number; + scanForAvailability: boolean; } export interface IRadarrSettings extends IExternalSettings { enabled: boolean; apiKey: string; - defaultQualityProfile: string; + defaultQualityProfile: number; defaultRootPath: string; fullRootPath: string; addOnly: boolean; minimumAvailability: string; + scanForAvailability: boolean; + v3: boolean; } export interface ILidarrSettings extends IExternalSettings { @@ -128,6 +136,7 @@ export interface ICustomizationSettings extends ISettings { customDonationMessage: string; recentlyAddedPage: boolean; useCustomPage: boolean; + hideAvailableFromDiscover: boolean; } export interface IJobSettings { @@ -139,13 +148,13 @@ export interface IJobSettings { automaticUpdater: string; userImporter: string; sickRageSync: string; - refreshMetadata: string; newsletter: string; plexRecentlyAddedSync: string; lidarrArtistSync: string; issuesPurge: string; retryRequests: string; mediaDatabaseRefresh: string; + autoDeleteRequests: string; } export interface IIssueSettings extends ISettings { @@ -195,9 +204,6 @@ export interface IAbout { ombiDatabaseType: string; externalDatabaseType: string; settingsDatabaseType: string; - ombiConnectionString: string; - externalConnectionString: string; - settingsConnectionString: string; storagePath: string; notSupported: boolean; } diff --git a/src/Ombi/ClientApp/src/app/interfaces/IUser.ts b/src/Ombi/ClientApp/src/app/interfaces/IUser.ts index 0816ad42e..4235d55cf 100644 --- a/src/Ombi/ClientApp/src/app/interfaces/IUser.ts +++ b/src/Ombi/ClientApp/src/app/interfaces/IUser.ts @@ -15,6 +15,7 @@ export interface IUser { episodeRequestLimit: number; musicRequestLimit: number; userAccessToken: string; + language: string; userQualityProfiles: IUserQualityProfiles; // FOR UI @@ -71,6 +72,18 @@ export interface IMobileUsersViewModel { devices: number; } +export interface ICloudMobileModel { + userId: string; + username: string; + devices: ICloudMobileDevices[]; +} +export interface ICloudMobileDevices { + token: string; + userId: string; + addedAt: Date; + user: IUser; +} + export interface IMassEmailUserModel { user: IUser; selected: boolean; @@ -91,6 +104,7 @@ export interface INotificationPreferences { } export enum INotificationAgent { + Email = 0, Discord = 1, Pushbullet = 2, @@ -99,4 +113,7 @@ export enum INotificationAgent { Slack = 5, Mattermost = 6, Mobile = 7, + Gotify = 8, + Webhook = 9, + WhatsApp = 10 } diff --git a/src/Ombi/ClientApp/src/app/issues/components/issues-list/issues-list.component.html b/src/Ombi/ClientApp/src/app/issues/components/issues-list/issues-list.component.html index bcae7e76c..61f154193 100644 --- a/src/Ombi/ClientApp/src/app/issues/components/issues-list/issues-list.component.html +++ b/src/Ombi/ClientApp/src/app/issues/components/issues-list/issues-list.component.html @@ -1,28 +1,21 @@ - - - - - + - - - + + + - - - - -
{{column}} {{element[column]}} -
-
-
{{element.requestId}}
-
-
-
+
+
+
{{element.requestId}}
+
+
+
\ No newline at end of file + + + + + --> \ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/issues/components/issues-list/issues-list.component.ts b/src/Ombi/ClientApp/src/app/issues/components/issues-list/issues-list.component.ts index 5528401ff..82883a4f2 100644 --- a/src/Ombi/ClientApp/src/app/issues/components/issues-list/issues-list.component.ts +++ b/src/Ombi/ClientApp/src/app/issues/components/issues-list/issues-list.component.ts @@ -6,6 +6,7 @@ import { IIssueCount, IIssues, IPagenator, IssueStatus } from "../../../interfac import { COLUMNS } from "./issues-list.constants"; @Component({ + selector: "issues-list", templateUrl: "issues-list.component.html", }) export class IssuesListComponent implements OnInit { diff --git a/src/Ombi/ClientApp/src/app/issues/issues.component.html b/src/Ombi/ClientApp/src/app/issues/issues.component.html index 242427b8b..ff8440569 100644 --- a/src/Ombi/ClientApp/src/app/issues/issues.component.html +++ b/src/Ombi/ClientApp/src/app/issues/issues.component.html @@ -1,28 +1,25 @@ -

- - - - {{'Issues.PendingTitle' | translate}} {{count.pending}} - -
- -
-
-
- - {{'Issues.InProgressTitle' | translate}} {{count.inProgress}} - -
- -
-
-
- - {{'Issues.ResolvedTitle' | translate}} {{count.resolved}} - -
- -
-
-
-
\ No newline at end of file +
+ + + +
+ +
+
+
+ + +
+ +
+
+
+ + +
+ +
+
+
+
+
\ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/issues/issues.component.scss b/src/Ombi/ClientApp/src/app/issues/issues.component.scss new file mode 100644 index 000000000..0de21e45d --- /dev/null +++ b/src/Ombi/ClientApp/src/app/issues/issues.component.scss @@ -0,0 +1,4 @@ +.small-middle-container { + margin: auto; + width: 95%; +} \ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/issues/issues.component.ts b/src/Ombi/ClientApp/src/app/issues/issues.component.ts index 55e4fe9be..c97eb4eff 100644 --- a/src/Ombi/ClientApp/src/app/issues/issues.component.ts +++ b/src/Ombi/ClientApp/src/app/issues/issues.component.ts @@ -6,6 +6,7 @@ import { IIssueCount, IIssues, IPagenator, IssueStatus } from "../interfaces"; @Component({ templateUrl: "issues.component.html", + styleUrls: ['issues.component.scss'] }) export class IssuesComponent implements OnInit { diff --git a/src/Ombi/ClientApp/src/app/issues/issues.module.ts b/src/Ombi/ClientApp/src/app/issues/issues.module.ts index cc7240553..2607d336a 100644 --- a/src/Ombi/ClientApp/src/app/issues/issues.module.ts +++ b/src/Ombi/ClientApp/src/app/issues/issues.module.ts @@ -1,9 +1,7 @@ import { NgModule } from "@angular/core"; import { RouterModule, Routes } from "@angular/router"; -import { NgbModule } from "@ng-bootstrap/ng-bootstrap"; import { OrderModule } from "ngx-order-pipe"; -import { PaginatorModule, SharedModule, TabViewModule } from "primeng/primeng"; import { IdentityService, SearchService } from "../services"; @@ -16,25 +14,20 @@ import { IssuesComponent } from "./issues.component"; import { IssuesTableComponent } from "./issuestable.component"; import { PipeModule } from "../pipes/pipe.module"; -import { IssuesListComponent } from "./components/issues-list/issues-list.component"; import * as fromComponents from "./components"; const routes: Routes = [ - { path: "", component: IssuesListComponent, canActivate: [AuthGuard] }, + { path: "", component: IssuesComponent, canActivate: [AuthGuard] }, { path: ":id", component: IssueDetailsComponent, canActivate: [AuthGuard] }, ]; @NgModule({ imports: [ RouterModule.forChild(routes), - NgbModule.forRoot(), - SharedModule, OrderModule, PipeModule, OmbiShared, - PaginatorModule, - TabViewModule, ], declarations: [ IssuesComponent, diff --git a/src/Ombi/ClientApp/src/app/issues/issuestable.component.html b/src/Ombi/ClientApp/src/app/issues/issuestable.component.html index 83dc8a1db..8713d09b2 100644 --- a/src/Ombi/ClientApp/src/app/issues/issuestable.component.html +++ b/src/Ombi/ClientApp/src/app/issues/issuestable.component.html @@ -1,4 +1,68 @@ - +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
{{ 'Issues.ColumnTitle' | translate}} {{element.title}} {{ 'Issues.Category' | translate}} {{element.issueCategory.value}} {{ 'Issues.Subject' | translate}} {{element.subject}} {{ 'Issues.Status' | translate}} {{IssueStatus[element.status] | humanize}} {{ 'Issues.ReportedBy' | translate}} {{element.userReported.userAlias}} + + + + +
+ + \ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/issues/issuestable.component.ts b/src/Ombi/ClientApp/src/app/issues/issuestable.component.ts index aadfd546a..d1c656662 100644 --- a/src/Ombi/ClientApp/src/app/issues/issuestable.component.ts +++ b/src/Ombi/ClientApp/src/app/issues/issuestable.component.ts @@ -13,6 +13,7 @@ export class IssuesTableComponent { @Output() public changePage = new EventEmitter(); + public displayedColumns = ["title", "category", "subject", "status", "reportedBy", "actions"] public IssueStatus = IssueStatus; public order: string = "id"; diff --git a/src/Ombi/ClientApp/src/app/landingpage/landingpage.component.html b/src/Ombi/ClientApp/src/app/landingpage/landingpage.component.html index 03878033f..298ce4c11 100644 --- a/src/Ombi/ClientApp/src/app/landingpage/landingpage.component.html +++ b/src/Ombi/ClientApp/src/app/landingpage/landingpage.component.html @@ -1,7 +1,7 @@ 
-
+
@@ -11,20 +11,21 @@
-
-
-

Notice

+

 Notice

+
+
+ +

{{ 'LandingPage.OnlineHeading' | translate }}

-

{{ 'LandingPage.PartiallyOnlineHeading' | translate }}

@@ -40,8 +41,8 @@
-
- +
+
diff --git a/src/Ombi/ClientApp/src/app/landingpage/landingpage.component.scss b/src/Ombi/ClientApp/src/app/landingpage/landingpage.component.scss index 8cb255d73..e05400aff 100644 --- a/src/Ombi/ClientApp/src/app/landingpage/landingpage.component.scss +++ b/src/Ombi/ClientApp/src/app/landingpage/landingpage.component.scss @@ -1,4 +1,12 @@ -@media only screen and (max-width: 992px) { + + .small-middle-container{ + margin: auto; + width: 75%; + padding-top: 15%; + } + + +@media only screen and (max-width: 992px) { div.centered { max-height: 100%; overflow-y: auto; @@ -45,4 +53,12 @@ div.bg { p { font-size: 14px !important; +} + +span, b, i, p { + color:white !important; +} + +::ng-deep body { + background-color:#303030 !important; } \ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/landingpage/landingpage.component.ts b/src/Ombi/ClientApp/src/app/landingpage/landingpage.component.ts index 5ccd0011a..80bba97b2 100644 --- a/src/Ombi/ClientApp/src/app/landingpage/landingpage.component.ts +++ b/src/Ombi/ClientApp/src/app/landingpage/landingpage.component.ts @@ -39,7 +39,7 @@ export class LandingPageComponent implements OnDestroy, OnInit { }); this.timer = setInterval(() => { this.cycleBackground(); - }, 15000); + }, 30000); const base = this.href; if (base.length > 1) { diff --git a/src/Ombi/ClientApp/src/app/login/login.component.html b/src/Ombi/ClientApp/src/app/login/login.component.html index 3817b78e3..9fcc4c1ee 100644 --- a/src/Ombi/ClientApp/src/app/login/login.component.html +++ b/src/Ombi/ClientApp/src/app/login/login.component.html @@ -1,43 +1,49 @@ - -
+
+
-
+
- - - - - - + -
+
\ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/login/login.component.ts b/src/Ombi/ClientApp/src/app/login/login.component.ts index 91d3acf5f..bdb57d403 100644 --- a/src/Ombi/ClientApp/src/app/login/login.component.ts +++ b/src/Ombi/ClientApp/src/app/login/login.component.ts @@ -15,7 +15,7 @@ import { ImageService } from "../services"; import { fadeInOutAnimation } from "../animations/fadeinout"; import { StorageService } from "../shared/storage/storage-service"; -import { MatSnackBar } from "@angular/material"; +import { MatSnackBar } from "@angular/material/snack-bar"; @Component({ templateUrl: "./login.component.html", @@ -33,6 +33,7 @@ export class LoginComponent implements OnDestroy, OnInit { public baseUrl: string; public loginWithOmbi: boolean; public pinTimer: any; + public oauthLoading: boolean; public get appName(): string { if (this.customizationSettings.applicationName) { @@ -97,7 +98,7 @@ export class LoginComponent implements OnDestroy, OnInit { }); this.timer = setInterval(() => { this.cycleBackground(); - }, 15000); + }, 30000); const base = this.href; if (base.length > 1) { @@ -159,12 +160,10 @@ export class LoginComponent implements OnDestroy, OnInit { this.oAuthWindow!.location.replace(x.url); this.pinTimer = setInterval(() => { - - this.notify.open("Authenticating. Loading... Please Wait", "OK", { - duration: 3000 - }); + + this.oauthLoading = true; this.getPinResult(x.pinId); - }, 10000); + }, 4000); }); }); } @@ -173,24 +172,25 @@ export class LoginComponent implements OnDestroy, OnInit { this.authService.oAuth(pinId).subscribe(x => { if(x.access_token) { this.store.save("id_token", x.access_token); - + if (this.authService.loggedIn()) { this.ngOnDestroy(); if(this.oAuthWindow) { this.oAuthWindow.close(); } + this.oauthLoading = false; this.router.navigate(["search"]); return; - } + } } - + }, err => { console.log(err); this.notify.open(err.body, "OK", { duration: 3000 }); - + this.router.navigate(["login"]); }); } diff --git a/src/Ombi/ClientApp/src/app/media-details/components/artist/artist-details.component.html b/src/Ombi/ClientApp/src/app/media-details/components/artist/artist-details.component.html index d24ce157d..46c5b97c9 100644 --- a/src/Ombi/ClientApp/src/app/media-details/components/artist/artist-details.component.html +++ b/src/Ombi/ClientApp/src/app/media-details/components/artist/artist-details.component.html @@ -1,41 +1,40 @@
- +
- + -
-
+
+
-
+
- + - -
+ +
- + -
+
+ +
+ + + + + -
- - - - - - @@ -78,40 +77,50 @@ -
-
+
+
-
+
-
- - - - - - +
+ + + + + -
-
-
-
- - - {{artist.overview}} - - -
-
+
-
-
- -
-
+
+
+
+ + + {{artist.overview}} + + +
+
+ +
+
+ +
+
- -
+ +
- + -
+
-
+
- - + - - + + + - - - - - - - - @@ -63,143 +60,136 @@ {{ 'MediaDetails.Denied' | translate }} - - -
-
- -
- -
- - - - - - - - - - - - - - - - -
- -
-
-
- - - {{movie.overview}} - - +
-
-
-
- -
-
- -
-
- - - - - {{'MediaDetails.RecommendationsTitle' | translate}} - - - -
- -
- +
+
-
+
-
-
-
+
+
+
diff --git a/src/Ombi/ClientApp/src/app/media-details/components/movie/movie-details.component.ts b/src/Ombi/ClientApp/src/app/media-details/components/movie/movie-details.component.ts index ae649fc3d..55a69fe15 100644 --- a/src/Ombi/ClientApp/src/app/media-details/components/movie/movie-details.component.ts +++ b/src/Ombi/ClientApp/src/app/media-details/components/movie/movie-details.component.ts @@ -3,12 +3,13 @@ import { ImageService, SearchV2Service, RequestService, MessageService } from ". import { ActivatedRoute } from "@angular/router"; import { DomSanitizer } from "@angular/platform-browser"; import { ISearchMovieResultV2 } from "../../../interfaces/ISearchMovieResultV2"; -import { MatDialog } from "@angular/material"; +import { MatDialog } from "@angular/material/dialog"; import { YoutubeTrailerComponent } from "../shared/youtube-trailer.component"; import { AuthService } from "../../../auth/auth.service"; import { IMovieRequests, RequestType, IAdvancedData } from "../../../interfaces"; import { DenyDialogComponent } from "../shared/deny-dialog/deny-dialog.component"; import { NewIssueComponent } from "../shared/new-issue/new-issue.component"; +import { StorageService } from "../../../shared/storage/storage-service"; @Component({ templateUrl: "./movie-details.component.html", @@ -21,35 +22,58 @@ export class MovieDetailsComponent { public movieRequest: IMovieRequests; public isAdmin: boolean; public advancedOptions: IAdvancedData; + public showAdvanced: boolean; // Set on the UI private theMovidDbId: number; + private imdbId: string; constructor(private searchService: SearchV2Service, private route: ActivatedRoute, private sanitizer: DomSanitizer, private imageService: ImageService, public dialog: MatDialog, private requestService: RequestService, - public messageService: MessageService, private auth: AuthService) { + public messageService: MessageService, private auth: AuthService, + private storage: StorageService) { this.route.params.subscribe((params: any) => { + if (typeof params.movieDbId === 'string' || params.movieDbId instanceof String) { + if (params.movieDbId.startsWith("tt")) { + this.imdbId = params.movieDbId; + } + } this.theMovidDbId = params.movieDbId; this.load(); }); } - public load() { + public async load() { this.isAdmin = this.auth.hasRole("admin") || this.auth.hasRole("poweruser"); - this.searchService.getFullMovieDetails(this.theMovidDbId).subscribe(async x => { - this.movie = x; - if (this.movie.requestId > 0) { - // Load up this request - this.hasRequest = true; - this.movieRequest = await this.requestService.getMovieRequest(this.movie.requestId); - } - this.imageService.getMovieBanner(this.theMovidDbId.toString()).subscribe(x => { - this.movie.background = this.sanitizer.bypassSecurityTrustStyle - ("url(" + x + ")"); - }); - }); + if (this.imdbId) { + this.searchService.getMovieByImdbId(this.imdbId).subscribe(async x => { + this.movie = x; + if (this.movie.requestId > 0) { + // Load up this request + this.hasRequest = true; + this.movieRequest = await this.requestService.getMovieRequest(this.movie.requestId); + } + this.imageService.getMovieBanner(this.theMovidDbId.toString()).subscribe(x => { + this.movie.background = this.sanitizer.bypassSecurityTrustStyle + ("url(" + x + ")"); + }); + }); + } else { + this.searchService.getFullMovieDetails(this.theMovidDbId).subscribe(async x => { + this.movie = x; + if (this.movie.requestId > 0) { + // Load up this request + this.hasRequest = true; + this.movieRequest = await this.requestService.getMovieRequest(this.movie.requestId); + } + this.imageService.getMovieBanner(this.theMovidDbId.toString()).subscribe(x => { + this.movie.background = this.sanitizer.bypassSecurityTrustStyle + ("url(" + x + ")"); + }); + }); + } } public async request() { @@ -72,36 +96,37 @@ export class MovieDetailsComponent { public async deny() { const dialogRef = this.dialog.open(DenyDialogComponent, { width: '250px', - data: {requestId: this.movieRequest.id, requestType: RequestType.movie} - }); - - dialogRef.afterClosed().subscribe(result => { + data: { requestId: this.movieRequest.id, requestType: RequestType.movie } + }); + + dialogRef.afterClosed().subscribe(result => { this.movieRequest.denied = result; - if(this.movieRequest.denied) { + if (this.movieRequest.denied) { this.movie.approved = false; } - }); + }); } public async issue() { const dialogRef = this.dialog.open(NewIssueComponent, { width: '500px', - data: {requestId: this.movieRequest ? this.movieRequest.id : null, requestType: RequestType.movie, imdbid: this.movie.imdbId} - }); + data: { requestId: this.movieRequest ? this.movieRequest.id : null, requestType: RequestType.movie, providerId: this.movie.imdbId ? this.movie.imdbId : this.movie.id, title: this.movie.title } + }); } public async approve() { + this.movie.approved = true; const result = await this.requestService.approveMovie({ id: this.movieRequest.id }).toPromise(); if (result.result) { - this.movie.approved = false; this.messageService.send("Successfully Approved", "Ok"); } else { + this.movie.approved = false; this.messageService.send(result.errorMessage, "Ok"); } } public async markAvailable() { - const result = await this.requestService.markMovieAvailable({id: this.movieRequest.id}).toPromise(); + const result = await this.requestService.markMovieAvailable({ id: this.movieRequest.id }).toPromise(); if (result.result) { this.movie.available = true; this.messageService.send(result.message, "Ok"); @@ -110,7 +135,13 @@ export class MovieDetailsComponent { } } - public setAdvancedOptions(data: any) { + public setAdvancedOptions(data: IAdvancedData) { this.advancedOptions = data; + if (data.rootFolderId) { + this.movieRequest.qualityOverrideTitle = data.rootFolders.filter(x => x.id == data.rootFolderId)[0].path; + } + if (data.profileId) { + this.movieRequest.rootPathOverrideTitle = data.profiles.filter(x => x.id == data.profileId)[0].name; + } } } diff --git a/src/Ombi/ClientApp/src/app/media-details/components/movie/panels/movie-admin-panel/movie-admin-panel.component.html b/src/Ombi/ClientApp/src/app/media-details/components/movie/panels/movie-admin-panel/movie-admin-panel.component.html index 13fc86050..94bb66a12 100644 --- a/src/Ombi/ClientApp/src/app/media-details/components/movie/panels/movie-admin-panel/movie-admin-panel.component.html +++ b/src/Ombi/ClientApp/src/app/media-details/components/movie/panels/movie-admin-panel/movie-admin-panel.component.html @@ -1,3 +1,3 @@ -
- +
+
\ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/media-details/components/movie/panels/movie-admin-panel/movie-admin-panel.component.ts b/src/Ombi/ClientApp/src/app/media-details/components/movie/panels/movie-admin-panel/movie-admin-panel.component.ts index 8c3f378a7..e19840a6d 100644 --- a/src/Ombi/ClientApp/src/app/media-details/components/movie/panels/movie-admin-panel/movie-admin-panel.component.ts +++ b/src/Ombi/ClientApp/src/app/media-details/components/movie/panels/movie-admin-panel/movie-admin-panel.component.ts @@ -1,7 +1,7 @@ import { Component, Input, OnInit, EventEmitter, Output } from "@angular/core"; import { RadarrService } from "../../../../../services"; import { IRadarrProfile, IRadarrRootFolder, IMovieRequests, IAdvancedData } from "../../../../../interfaces"; -import { MatDialog } from "@angular/material"; +import { MatDialog } from "@angular/material/dialog"; import { MovieAdvancedOptionsComponent } from "../movie-advanced-options/movie-advanced-options.component"; import { RequestServiceV2 } from "../../../../../services/requestV2.service"; @@ -13,6 +13,7 @@ export class MovieAdminPanelComponent implements OnInit { @Input() public movie: IMovieRequests; @Output() public advancedOptionsChanged = new EventEmitter(); + @Output() public radarrEnabledChange = new EventEmitter(); public radarrEnabled: boolean; public radarrProfiles: IRadarrProfile[]; @@ -34,6 +35,8 @@ export class MovieAdminPanelComponent implements OnInit { this.setRootFolderOverrides(); }); } + + this.radarrEnabledChange.emit(this.radarrEnabled); } public async openAdvancedOptions() { diff --git a/src/Ombi/ClientApp/src/app/media-details/components/movie/panels/movie-advanced-options/movie-advanced-options.component.html b/src/Ombi/ClientApp/src/app/media-details/components/movie/panels/movie-advanced-options/movie-advanced-options.component.html index ad98fb432..8caecdfdf 100644 --- a/src/Ombi/ClientApp/src/app/media-details/components/movie/panels/movie-advanced-options/movie-advanced-options.component.html +++ b/src/Ombi/ClientApp/src/app/media-details/components/movie/panels/movie-advanced-options/movie-advanced-options.component.html @@ -1,22 +1,23 @@ +

- -

Advanced Options

-
+ Advanced Options +
- Radarr Quality Profile - - {{profile.name}} - + {{'MediaDetails.QualityProfilesSelect' | translate }} + + {{profile.name}} + - +
+
- Radarr Root Folders + {{'MediaDetails.RootFolderSelect' | translate }} - {{profile.path}} + {{profile.path}} - -
-
+ +
+
-
+
\ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/media-details/components/movie/panels/movie-advanced-options/movie-advanced-options.component.ts b/src/Ombi/ClientApp/src/app/media-details/components/movie/panels/movie-advanced-options/movie-advanced-options.component.ts index 4e237890d..d5c3310fb 100644 --- a/src/Ombi/ClientApp/src/app/media-details/components/movie/panels/movie-advanced-options/movie-advanced-options.component.ts +++ b/src/Ombi/ClientApp/src/app/media-details/components/movie/panels/movie-advanced-options/movie-advanced-options.component.ts @@ -1,5 +1,5 @@ import { Component, Inject } from "@angular/core"; -import { MatDialogRef, MAT_DIALOG_DATA } from "@angular/material"; +import { MatDialogRef, MAT_DIALOG_DATA } from "@angular/material/dialog"; import { IAdvancedData } from "../../../../../interfaces"; @Component({ diff --git a/src/Ombi/ClientApp/src/app/media-details/components/movie/panels/movie-information-panel.component.html b/src/Ombi/ClientApp/src/app/media-details/components/movie/panels/movie-information-panel.component.html index 304d35be5..449dd09c4 100644 --- a/src/Ombi/ClientApp/src/app/media-details/components/movie/panels/movie-information-panel.component.html +++ b/src/Ombi/ClientApp/src/app/media-details/components/movie/panels/movie-information-panel.component.html @@ -1,35 +1,39 @@
- Status: + {{'MediaDetails.Status' | translate }}:
{{movie.status}}
- Availability + {{'MediaDetails.Availability' | translate }}
{{'Common.Available' | translate}}
{{'Common.NotAvailable' | translate}}
- Request Status + {{'MediaDetails.RequestStatus' | translate }}
{{'Common.ProcessingRequest' | translate}}
{{'Common.PendingApproval' | translate}}
{{'Common.NotRequested' | translate}}
+
+ {{'MediaDetails.Quality' | translate }}: +
{{movie.quality | quality}}
+
- Root Folder Override -
{{advancedOptions.rootFolder.path}}
+ {{'MediaDetails.RootFolderOverride' | translate }} +
{{request.rootPathOverrideTitle}}
- Quality Override -
{{advancedOptions.profile.name}}
+ {{'MediaDetails.QualityOverride' | translate }} +
{{request.qualityOverrideTitle}}

- Genres: + {{'MediaDetails.Genres' | translate }}:
@@ -40,45 +44,45 @@

- Theatrical Release: + {{'MediaDetails.TheatricalRelease' | translate }}:
{{movie.releaseDate | date: 'mediumDate'}}
- Digital Release: + {{'MediaDetails.DigitalRelease' | translate }}:
{{movie.digitalReleaseDate | date: 'mediumDate'}}
- User Score: + {{'MediaDetails.UserScore' | translate }}:
{{movie.voteAverage | number:'1.0-1'}} / 10
- Votes: + {{'MediaDetails.Votes' | translate }}:
{{movie.voteCount | thousandShort: 1}}
- Runtime: -
{{movie.runtime}} Minutes
+ {{'MediaDetails.Runtime' | translate }}: +
{{'MediaDetails.Minutes' | translate:{runtime: movie.runtime} }}
- Revenue: + {{'MediaDetails.Revenue' | translate }}:
{{movie.revenue | currency: 'USD'}}
- Budget: + {{'MediaDetails.Budget' | translate }}:
{{movie.budget | currency: 'USD'}}

- Keywords/Tags: + {{'MediaDetails.Keywords' | translate }}: {{keyword.name}} diff --git a/src/Ombi/ClientApp/src/app/media-details/components/movie/panels/movie-information-panel.component.ts b/src/Ombi/ClientApp/src/app/media-details/components/movie/panels/movie-information-panel.component.ts index 64b458de4..3bfb68f56 100644 --- a/src/Ombi/ClientApp/src/app/media-details/components/movie/panels/movie-information-panel.component.ts +++ b/src/Ombi/ClientApp/src/app/media-details/components/movie/panels/movie-information-panel.component.ts @@ -1,6 +1,6 @@ import { Component, ViewEncapsulation, Input } from "@angular/core"; import { ISearchMovieResultV2 } from "../../../../interfaces/ISearchMovieResultV2"; -import { IAdvancedData } from "../../../../interfaces"; +import { IAdvancedData, IMovieRequests } from "../../../../interfaces"; @Component({ templateUrl: "./movie-information-panel.component.html", @@ -10,5 +10,6 @@ import { IAdvancedData } from "../../../../interfaces"; }) export class MovieInformationPanelComponent { @Input() public movie: ISearchMovieResultV2; - @Input() public advancedOptions: IAdvancedData; + @Input() public request: IMovieRequests; + @Input() public advancedOptions: boolean; } diff --git a/src/Ombi/ClientApp/src/app/media-details/components/shared/cast-carousel/cast-carousel.component.html b/src/Ombi/ClientApp/src/app/media-details/components/shared/cast-carousel/cast-carousel.component.html index 1e0cbea7e..4a986a684 100644 --- a/src/Ombi/ClientApp/src/app/media-details/components/shared/cast-carousel/cast-carousel.component.html +++ b/src/Ombi/ClientApp/src/app/media-details/components/shared/cast-carousel/cast-carousel.component.html @@ -1,29 +1,30 @@ {{'MediaDetails.Casts.CastTitle' | translate}} - - -
-
- - - - - - - - -
-
- {{'MediaDetails.Casts.Character' | translate}}: {{item.character}} - {{'MediaDetails.Casts.Character' | translate}}: {{item.character.name}} -
-
- {{'MediaDetails.Casts.Actor' | translate}}: {{item.name}} - {{'MediaDetails.Casts.Actor' | translate}}: {{item.person.name}} -
-
-
-
+ + + + +
-
\ No newline at end of file + \ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/media-details/components/shared/cast-carousel/cast-carousel.component.scss b/src/Ombi/ClientApp/src/app/media-details/components/shared/cast-carousel/cast-carousel.component.scss index d9db92e00..b73d71007 100644 --- a/src/Ombi/ClientApp/src/app/media-details/components/shared/cast-carousel/cast-carousel.component.scss +++ b/src/Ombi/ClientApp/src/app/media-details/components/shared/cast-carousel/cast-carousel.component.scss @@ -1,7 +1,83 @@ @import "~@angular/material/theming"; @import "~styles/variables.scss"; -.actor-background { - .dark & { - background: $backgroundTint-dark; - } -} + ::ng-deep body .ui-carousel .ui-carousel-content .ui-carousel-prev, +body .ui-carousel .ui-carousel-content .ui-carousel-next { + background-color: #ffffff; + border: solid 1px rgba(178, 193, 205, 0.64); + -moz-border-radius: 50%; + -webkit-border-radius: 50%; + border-radius: 50%; + margin: 0.2em; + color: #333333; + -moz-transition: color 0.2s; + -o-transition: color 0.2s; + -webkit-transition: color 0.2s; + transition: color 0.2s; +} + +::ng-deep body .ui-carousel .ui-carousel-content .ui-carousel-prev:not(.ui-state-disabled):hover, +body .ui-carousel .ui-carousel-content .ui-carousel-next:not(.ui-state-disabled):hover { + background-color: #ffffff; + color: #000; + border-color: solid 1px rgba(178, 193, 205, 0.64); +} + +::ng-deep body .ui-carousel .ui-carousel-dots-container .ui-carousel-dot-item>.ui-button { + border-color: transparent; + background-color: transparent; +} + +::ng-deep body .ui-carousel .ui-carousel-dots-container .ui-carousel-dot-item .ui-carousel-dot-icon { + width: 20px; + height: 6px; + background-color: rgba(255, 255, 255, 0.44); + margin: 0 0.2em; +} + +::ng-deep body .ui-carousel .ui-carousel-dots-container .ui-carousel-dot-item .ui-carousel-dot-icon::before { + content: " "; +} + +::ng-deep body .ui-carousel .ui-carousel-dots-container .ui-carousel-dot-item.ui-state-highlight .ui-carousel-dot-icon { + background-color: #FFF; +} + +.carousel-item { + text-align: center; +} + +::ng-deep .ui-carousel-next { + background-color: #ffffff; + border: solid 1px rgba(178, 193, 205, 0.64); + border-radius: 50%; + margin: 0.2em; + color: #333333; + transition: color 0.2s; +} + +::ng-deep .ui-carousel-content button:focus { + outline: none; +} + +.bottom-space { + padding-bottom: 10px; +} + +@media (min-width: 979px) { + + .cast-profile-img { + border-radius: 100%; + width: 200px; + max-height: 200px; + object-fit: cover; + } +} +@media (max-width: 978px) { + + .cast-profile-img { + border-radius: 100%; + width: 100px; + max-height: 100px; + object-fit: cover; + } +} \ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/media-details/components/shared/cast-carousel/cast-carousel.component.ts b/src/Ombi/ClientApp/src/app/media-details/components/shared/cast-carousel/cast-carousel.component.ts index d7baa81f0..6924bac6c 100644 --- a/src/Ombi/ClientApp/src/app/media-details/components/shared/cast-carousel/cast-carousel.component.ts +++ b/src/Ombi/ClientApp/src/app/media-details/components/shared/cast-carousel/cast-carousel.component.ts @@ -6,6 +6,27 @@ import { Component, Input } from "@angular/core"; styleUrls: ["./cast-carousel.component.scss"] }) export class CastCarouselComponent { - + + constructor() { + this.responsiveOptions = [ + { + breakpoint: '1024px', + numVisible: 5, + numScroll: 5 + }, + { + breakpoint: '768px', + numVisible: 3, + numScroll: 3 + }, + { + breakpoint: '560px', + numVisible: 1, + numScroll: 1 + } + ]; + } + @Input() cast: any[]; + public responsiveOptions: any[]; } diff --git a/src/Ombi/ClientApp/src/app/media-details/components/shared/deny-dialog/deny-dialog.component.html b/src/Ombi/ClientApp/src/app/media-details/components/shared/deny-dialog/deny-dialog.component.html index 5863b76eb..6235d5fe6 100644 --- a/src/Ombi/ClientApp/src/app/media-details/components/shared/deny-dialog/deny-dialog.component.html +++ b/src/Ombi/ClientApp/src/app/media-details/components/shared/deny-dialog/deny-dialog.component.html @@ -5,6 +5,6 @@
- - + +
\ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/media-details/components/shared/deny-dialog/deny-dialog.component.ts b/src/Ombi/ClientApp/src/app/media-details/components/shared/deny-dialog/deny-dialog.component.ts index 8d6e92e64..8ead47144 100644 --- a/src/Ombi/ClientApp/src/app/media-details/components/shared/deny-dialog/deny-dialog.component.ts +++ b/src/Ombi/ClientApp/src/app/media-details/components/shared/deny-dialog/deny-dialog.component.ts @@ -1,6 +1,6 @@ import { Component, Inject, Output, EventEmitter } from "@angular/core"; import { IDenyDialogData } from "../interfaces/interfaces"; -import { MatDialogRef, MAT_DIALOG_DATA } from "@angular/material"; +import { MatDialogRef, MAT_DIALOG_DATA } from "@angular/material/dialog"; import { RequestService, MessageService } from "../../../../services"; import { RequestType, IRequestEngineResult } from "../../../../interfaces"; diff --git a/src/Ombi/ClientApp/src/app/media-details/components/shared/interfaces/interfaces.ts b/src/Ombi/ClientApp/src/app/media-details/components/shared/interfaces/interfaces.ts index 2f2b54cbc..a2a0b6154 100644 --- a/src/Ombi/ClientApp/src/app/media-details/components/shared/interfaces/interfaces.ts +++ b/src/Ombi/ClientApp/src/app/media-details/components/shared/interfaces/interfaces.ts @@ -9,5 +9,6 @@ export interface IDenyDialogData { export interface IIssueDialogData { requestType: RequestType; requestId: number; - imdbId: string; + providerId: string; + title: string; } \ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/media-details/components/shared/issues-panel/issues-panel.component.html b/src/Ombi/ClientApp/src/app/media-details/components/shared/issues-panel/issues-panel.component.html new file mode 100644 index 000000000..c4c05dff9 --- /dev/null +++ b/src/Ombi/ClientApp/src/app/media-details/components/shared/issues-panel/issues-panel.component.html @@ -0,0 +1,63 @@ + + + + + {{'Issues.Title' | translate}} + + + {{issuesCount}} error_outline + {{issuesCount}} + + + + + + + + + + {{ 'Issues.Subject' | translate}}: {{issue.subject}} + + + {{ 'Issues.ReportedBy' | translate}}: {{issue.userReported.userAlias}} + + + {{'Issues.Category' | translate}}: {{issue.issueCategory.value}} + + + +
+ +
+ {{'Issues.Description' | translate}}: {{issue.description}} +
+
+ {{'Issues.Status' | translate}}: {{IssueStatus[issue.status] | humanize}} +
+
+ {{'Issues.ResolvedDate' | translate}}: {{issue.resolvedDate}} +
+
+ {{'Issues.CreatedDate' | translate}}: {{issue.createdDate | date}} +
+ + +
+
+
+ +
+
+ +
+
+ +
+
+
+
+ + +
+ +
\ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/media-details/components/shared/issues-panel/issues-panel.component.scss b/src/Ombi/ClientApp/src/app/media-details/components/shared/issues-panel/issues-panel.component.scss new file mode 100644 index 000000000..4bcaff470 --- /dev/null +++ b/src/Ombi/ClientApp/src/app/media-details/components/shared/issues-panel/issues-panel.component.scss @@ -0,0 +1,7 @@ +.action-buttons { + padding-top: 1%; +} + +.button-padding { + padding: 1%; +} \ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/media-details/components/shared/issues-panel/issues-panel.component.ts b/src/Ombi/ClientApp/src/app/media-details/components/shared/issues-panel/issues-panel.component.ts new file mode 100644 index 000000000..dda7bcb89 --- /dev/null +++ b/src/Ombi/ClientApp/src/app/media-details/components/shared/issues-panel/issues-panel.component.ts @@ -0,0 +1,63 @@ +import { Component, Input, OnInit } from "@angular/core"; +import { IssuesService, NotificationService, SettingsService } from "../../../../services"; +import { RequestType, IIssues, IssueStatus, IIssueSettings } from "../../../../interfaces"; +import { TranslateService } from "@ngx-translate/core"; + +@Component({ + selector: "issues-panel", + templateUrl: "./issues-panel.component.html", + styleUrls: ["./issues-panel.component.scss"] +}) +export class IssuesPanelComponent implements OnInit { + + @Input() public providerId: string; + @Input() public isAdmin: boolean; + + public issuesCount: number; + public issues: IIssues[]; + public IssueStatus = IssueStatus; + public isOutstanding: boolean; + public loadingFlag: boolean; + public settings: IIssueSettings; + + constructor(private issuesService: IssuesService, private notificationService: NotificationService, + private translateService: TranslateService, private settingsService: SettingsService) { + + } + + public async ngOnInit() { + this.issues = await this.issuesService.getIssuesByProviderId(this.providerId); + this.issuesCount = this.issues.length; + this.calculateOutstanding(); + this.settings = await this.settingsService.getIssueSettings().toPromise(); + } + + public resolve(issue: IIssues) { + this.issuesService.updateStatus({issueId: issue.id, status: IssueStatus.Resolved}).subscribe(x => { + this.notificationService.success(this.translateService.instant("Issues.MarkedAsResolved")); + issue.status = IssueStatus.Resolved; + this.calculateOutstanding(); + }); + } + + public inProgress(issue: IIssues) { + this.issuesService.updateStatus({issueId: issue.id, status: IssueStatus.InProgress}).subscribe(x => { + this.notificationService.success(this.translateService.instant("Issues.MarkedAsInProgress")); + issue.status = IssueStatus.InProgress; + }); + } + + public async delete(issue: IIssues) { + await this.issuesService.deleteIssue(issue.id); + this.notificationService.success(this.translateService.instant("Issues.DeletedIssue")); + this.issues = this.issues.filter((el) => { return el.id !== issue.id; }); + this.issuesCount = this.issues.length; + this.calculateOutstanding(); + } + + private calculateOutstanding() { + this.isOutstanding = this.issues.some((i) => { + return i.status !== IssueStatus.Resolved; + }); + } +} diff --git a/src/Ombi/ClientApp/src/app/media-details/components/shared/new-issue/new-issue.component.html b/src/Ombi/ClientApp/src/app/media-details/components/shared/new-issue/new-issue.component.html index 0bbcbe8c0..e3f8220d6 100644 --- a/src/Ombi/ClientApp/src/app/media-details/components/shared/new-issue/new-issue.component.html +++ b/src/Ombi/ClientApp/src/app/media-details/components/shared/new-issue/new-issue.component.html @@ -1,29 +1,27 @@

{{ 'Issues.IssueDialog.Title' | translate}}

-
- - {{'Issues.IssueDialog.SelectCategory' | translate}} - - - {{cat.value}} - - - +
+ + {{'Issues.IssueDialog.SelectCategory' | translate}} + + + {{cat.value}} + + + - - - + + + - - - -
+ + + +
- - + +
\ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/media-details/components/shared/new-issue/new-issue.component.ts b/src/Ombi/ClientApp/src/app/media-details/components/shared/new-issue/new-issue.component.ts index 636a4a1cf..c42c14fe2 100644 --- a/src/Ombi/ClientApp/src/app/media-details/components/shared/new-issue/new-issue.component.ts +++ b/src/Ombi/ClientApp/src/app/media-details/components/shared/new-issue/new-issue.component.ts @@ -1,6 +1,6 @@ import { Component, Inject, OnInit } from "@angular/core"; import { IDenyDialogData, IIssueDialogData } from "../interfaces/interfaces"; -import { MatDialogRef, MAT_DIALOG_DATA } from "@angular/material"; +import { MatDialogRef, MAT_DIALOG_DATA } from "@angular/material/dialog"; import { MessageService, IssuesService } from "../../../../services"; import { IIssues, IIssueCategory, IssueStatus, RequestType } from "../../../../interfaces"; import { TranslateService } from "@ngx-translate/core"; @@ -20,6 +20,7 @@ export class NewIssueComponent implements OnInit { private issueService: IssuesService, public messageService: MessageService, private translate: TranslateService) { + debugger; this.issue = { subject: "", description: "", @@ -31,8 +32,8 @@ export class NewIssueComponent implements OnInit { comments: [], requestId: data.requestId, requestType: data.requestType, - title: "", - providerId: data.imdbId, + title: data.title, + providerId: data.providerId, userReported: undefined, }; } @@ -41,7 +42,6 @@ export class NewIssueComponent implements OnInit { this.issueCategories = await this.issueService.getCategories().toPromise(); } - public async createIssue() { const result = await this.issueService.createIssue(this.issue).toPromise(); if(result) { diff --git a/src/Ombi/ClientApp/src/app/media-details/components/shared/social-icons/social-icons.component.html b/src/Ombi/ClientApp/src/app/media-details/components/shared/social-icons/social-icons.component.html index c9eaba371..f5772842b 100644 --- a/src/Ombi/ClientApp/src/app/media-details/components/shared/social-icons/social-icons.component.html +++ b/src/Ombi/ClientApp/src/app/media-details/components/shared/social-icons/social-icons.component.html @@ -6,7 +6,7 @@ target="_blank"> - + diff --git a/src/Ombi/ClientApp/src/app/media-details/components/shared/social-icons/social-icons.component.scss b/src/Ombi/ClientApp/src/app/media-details/components/shared/social-icons/social-icons.component.scss index 57c6d10ed..866723b93 100644 --- a/src/Ombi/ClientApp/src/app/media-details/components/shared/social-icons/social-icons.component.scss +++ b/src/Ombi/ClientApp/src/app/media-details/components/shared/social-icons/social-icons.component.scss @@ -1,11 +1,4 @@ -.grow-social { - transition: all .2s ease-in-out; -} -.grow-social:hover { - transform: scale(1.1); - color: black; -} .media-icons.plex { color: #feb801 !important; diff --git a/src/Ombi/ClientApp/src/app/media-details/components/shared/youtube-trailer.component.ts b/src/Ombi/ClientApp/src/app/media-details/components/shared/youtube-trailer.component.ts index 3456759cf..c0812071d 100644 --- a/src/Ombi/ClientApp/src/app/media-details/components/shared/youtube-trailer.component.ts +++ b/src/Ombi/ClientApp/src/app/media-details/components/shared/youtube-trailer.component.ts @@ -1,5 +1,5 @@ import { Component, Inject } from "@angular/core"; -import { MatDialogRef, MAT_DIALOG_DATA } from "@angular/material"; +import { MatDialogRef, MAT_DIALOG_DATA } from "@angular/material/dialog"; @Component({ selector: "youtube-trailer", diff --git a/src/Ombi/ClientApp/src/app/media-details/components/tv/panels/tv-admin-panel/tv-admin-panel.component.html b/src/Ombi/ClientApp/src/app/media-details/components/tv/panels/tv-admin-panel/tv-admin-panel.component.html new file mode 100644 index 000000000..473f0e97b --- /dev/null +++ b/src/Ombi/ClientApp/src/app/media-details/components/tv/panels/tv-admin-panel/tv-admin-panel.component.html @@ -0,0 +1,3 @@ +
+ +
\ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/media-details/components/tv/panels/tv-admin-panel/tv-admin-panel.component.ts b/src/Ombi/ClientApp/src/app/media-details/components/tv/panels/tv-admin-panel/tv-admin-panel.component.ts new file mode 100644 index 000000000..40ca64e1c --- /dev/null +++ b/src/Ombi/ClientApp/src/app/media-details/components/tv/panels/tv-admin-panel/tv-admin-panel.component.ts @@ -0,0 +1,83 @@ +import { Component, Input, OnInit, EventEmitter, Output } from "@angular/core"; +import { RadarrService, SonarrService } from "../../../../../services"; +import { IRadarrProfile, IRadarrRootFolder, IAdvancedData, ITvRequests, ISonarrProfile, ISonarrRootFolder } from "../../../../../interfaces"; +import { MatDialog } from "@angular/material/dialog"; + +import { RequestServiceV2 } from "../../../../../services/requestV2.service"; +import { MovieAdvancedOptionsComponent } from "../../../movie/panels/movie-advanced-options/movie-advanced-options.component"; + +@Component({ + templateUrl: "./tv-admin-panel.component.html", + selector: "tv-admin-panel", +}) +export class TvAdminPanelComponent implements OnInit { + + @Input() public tv: ITvRequests; + @Output() public advancedOptionsChanged = new EventEmitter(); + @Output() public sonarrEnabledChange = new EventEmitter(); + + public sonarrEnabled: boolean; + public radarrProfiles: IRadarrProfile[]; + public selectedRadarrProfile: IRadarrProfile; + public radarrRootFolders: IRadarrRootFolder[]; + public selectRadarrRootFolders: IRadarrRootFolder; + + + public sonarrProfiles: ISonarrProfile[]; + public sonarrRootFolders: ISonarrRootFolder[]; + + constructor(private sonarrService: SonarrService, private requestService: RequestServiceV2, private dialog: MatDialog) { } + + public async ngOnInit() { + this.sonarrEnabled = await this.sonarrService.isEnabled(); + if (this.sonarrEnabled) { + this.sonarrService.getQualityProfilesWithoutSettings() + .subscribe(x => { + this.sonarrProfiles = x; + this.setQualityOverrides(); + }); + this.sonarrService.getRootFoldersWithoutSettings() + .subscribe(x => { + this.sonarrRootFolders = x; + this.setRootFolderOverrides(); + }); + } + + this.sonarrEnabledChange.emit(this.sonarrEnabled); + } + + public async openAdvancedOptions() { + const dialog = this.dialog.open(MovieAdvancedOptionsComponent, { width: "700px", data: { profiles: this.sonarrProfiles, rootFolders: this.sonarrRootFolders }, panelClass: 'modal-panel' }) + await dialog.afterClosed().subscribe(async result => { + if (result) { + // get the name and ids + result.rootFolder = result.rootFolders.filter(f => f.id === +result.rootFolderId)[0]; + result.profile = result.profiles.filter(f => f.id === +result.profileId)[0]; + await this.requestService.updateTvAdvancedOptions({ qualityOverride: result.profileId, rootPathOverride: result.rootFolderId, requestId: this.tv.id }).toPromise(); + this.advancedOptionsChanged.emit(result); + } + }); + } + + private setQualityOverrides(): void { + if (this.sonarrProfiles) { + const profile = this.sonarrProfiles.filter((p) => { + return p.id === this.tv.qualityOverride; + }); + if (profile.length > 0) { + this.tv.qualityOverrideTitle = profile[0].name; + } + } + } + + private setRootFolderOverrides(): void { + if (this.sonarrRootFolders) { + const path = this.sonarrRootFolders.filter((folder) => { + return folder.id === this.tv.rootFolder; + }); + if (path.length > 0) { + this.tv.rootPathOverrideTitle = path[0].path; + } + } + } +} diff --git a/src/Ombi/ClientApp/src/app/media-details/components/tv/panels/tv-information-panel/tv-information-panel.component.html b/src/Ombi/ClientApp/src/app/media-details/components/tv/panels/tv-information-panel/tv-information-panel.component.html index 5c5844817..fb3c1c65e 100644 --- a/src/Ombi/ClientApp/src/app/media-details/components/tv/panels/tv-information-panel/tv-information-panel.component.html +++ b/src/Ombi/ClientApp/src/app/media-details/components/tv/panels/tv-information-panel/tv-information-panel.component.html @@ -1,6 +1,6 @@
- Status: + {{'MediaDetails.Status' | translate }}:
{{tv.status}}
@@ -11,17 +11,19 @@
- -
- Status: -
- {{tv.status}} -
+
+ {{'MediaDetails.RootFolderOverride' | translate }} +
{{request.rootPathOverrideTitle}}
+
+
+ {{'MediaDetails.QualityOverride' | translate }} +
{{request.qualityOverrideTitle}}
+
- Runtime: + {{'MediaDetails.Runtime' | translate }}:
- {{tv.runtime}} Minutes + {{'MediaDetails.Minutes' | translate:{ runtime: tv.runtime} }}
@@ -38,7 +40,7 @@
- Genres: + {{'MediaDetails.Genres' | translate }}:
{{genre}} | diff --git a/src/Ombi/ClientApp/src/app/media-details/components/tv/panels/tv-information-panel/tv-information-panel.component.ts b/src/Ombi/ClientApp/src/app/media-details/components/tv/panels/tv-information-panel/tv-information-panel.component.ts index 0e64c566a..3d3f77e75 100644 --- a/src/Ombi/ClientApp/src/app/media-details/components/tv/panels/tv-information-panel/tv-information-panel.component.ts +++ b/src/Ombi/ClientApp/src/app/media-details/components/tv/panels/tv-information-panel/tv-information-panel.component.ts @@ -1,4 +1,5 @@ import { Component, ViewEncapsulation, Input, OnInit } from "@angular/core"; +import { ITvRequests } from "../../../../../interfaces"; import { ISearchTvResultV2 } from "../../../../../interfaces/ISearchTvResultV2"; @Component({ @@ -9,6 +10,8 @@ import { ISearchTvResultV2 } from "../../../../../interfaces/ISearchTvResultV2"; }) export class TvInformationPanelComponent implements OnInit { @Input() public tv: ISearchTvResultV2; + @Input() public request: ITvRequests; + @Input() public advancedOptions: boolean; public seasonCount: number; public totalEpisodes: number = 0; diff --git a/src/Ombi/ClientApp/src/app/media-details/components/tv/panels/tv-requests/tv-requests-panel.component.ts b/src/Ombi/ClientApp/src/app/media-details/components/tv/panels/tv-requests/tv-requests-panel.component.ts index fe32ae988..201d4c274 100644 --- a/src/Ombi/ClientApp/src/app/media-details/components/tv/panels/tv-requests/tv-requests-panel.component.ts +++ b/src/Ombi/ClientApp/src/app/media-details/components/tv/panels/tv-requests/tv-requests-panel.component.ts @@ -2,7 +2,7 @@ import { Component, Input } from "@angular/core"; import { IChildRequests, RequestType } from "../../../../../interfaces"; import { RequestService } from "../../../../../services/request.service"; import { MessageService } from "../../../../../services"; -import { MatDialog } from "@angular/material"; +import { MatDialog } from "@angular/material/dialog"; import { DenyDialogComponent } from "../../../shared/deny-dialog/deny-dialog.component"; @Component({ diff --git a/src/Ombi/ClientApp/src/app/media-details/components/tv/tv-details.component.html b/src/Ombi/ClientApp/src/app/media-details/components/tv/tv-details.component.html index eb37fa3d5..0df2ba1fb 100644 --- a/src/Ombi/ClientApp/src/app/media-details/components/tv/tv-details.component.html +++ b/src/Ombi/ClientApp/src/app/media-details/components/tv/tv-details.component.html @@ -1,105 +1,128 @@
- +
+
+
+

{{ 'MediaDetails.NotEnoughInfo' | translate }}

+
+
- -
-
-
+ - +
- -
+ - - +
+
+
-
+ -
+ +
- + + - - -
-
+
-
-
+
- - - - - + -
+ + + -
-
-
- - - {{tv.overview}} - - +
-
- + +
+
+ + + + + + + + + + + + + +
+ + +
+
+
+ + + {{tv.overview}} + + +
+
+ +
+ +
+
-
-
-
+
+
-
-
+ - -
+
-
- - - - - Requests - - - - +
+
+ +
+ + + + + Requests + + + + - + -
+
-
+
-
+
-
-
-
+
+
+ +
+
\ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/media-details/components/tv/tv-details.component.ts b/src/Ombi/ClientApp/src/app/media-details/components/tv/tv-details.component.ts index 438df619f..ef86fbdce 100644 --- a/src/Ombi/ClientApp/src/app/media-details/components/tv/tv-details.component.ts +++ b/src/Ombi/ClientApp/src/app/media-details/components/tv/tv-details.component.ts @@ -1,13 +1,14 @@ import { Component, ViewEncapsulation, OnInit } from "@angular/core"; -import { ImageService, SearchV2Service, MessageService, RequestService } from "../../../services"; +import { ImageService, SearchV2Service, MessageService, RequestService, SonarrService } from "../../../services"; import { ActivatedRoute } from "@angular/router"; import { DomSanitizer } from "@angular/platform-browser"; import { ISearchTvResultV2 } from "../../../interfaces/ISearchTvResultV2"; -import { MatDialog } from "@angular/material"; +import { MatDialog } from "@angular/material/dialog"; import { YoutubeTrailerComponent } from "../shared/youtube-trailer.component"; import { EpisodeRequestComponent } from "../../../shared/episode-request/episode-request.component"; -import { IChildRequests } from "../../../interfaces"; +import { IAdvancedData, IChildRequests, ISonarrProfile, ISonarrRootFolder, ITvRequests, RequestType } from "../../../interfaces"; import { AuthService } from "../../../auth/auth.service"; +import { NewIssueComponent } from "../shared/new-issue/new-issue.component"; @Component({ templateUrl: "./tv-details.component.html", @@ -18,15 +19,18 @@ export class TvDetailsComponent implements OnInit { public tv: ISearchTvResultV2; public tvRequest: IChildRequests[]; + public showRequest: ITvRequests; public fromSearch: boolean; public isAdmin: boolean; + public advancedOptions: IAdvancedData; + public showAdvanced: boolean; // Set on the UI private tvdbId: number; constructor(private searchService: SearchV2Service, private route: ActivatedRoute, private sanitizer: DomSanitizer, private imageService: ImageService, public dialog: MatDialog, public messageService: MessageService, private requestService: RequestService, - private auth: AuthService) { + private auth: AuthService, private sonarrService: SonarrService) { this.route.params.subscribe((params: any) => { this.tvdbId = params.tvdbId; this.fromSearch = params.search; @@ -49,6 +53,7 @@ export class TvDetailsComponent implements OnInit { if (this.tv.requestId) { this.tvRequest = await this.requestService.getChildRequests(this.tv.requestId).toPromise(); + this.showRequest = this.tvRequest.length > 0 ? this.tvRequest[0].parentRequest : undefined; } const tvBanner = await this.imageService.getTvBanner(this.tvdbId).toPromise(); @@ -59,8 +64,14 @@ export class TvDetailsComponent implements OnInit { this.dialog.open(EpisodeRequestComponent, { width: "800px", data: this.tv, panelClass: 'modal-panel' }) } + public async issue() { + const dialogRef = this.dialog.open(NewIssueComponent, { + width: '500px', + data: { requestId: this.tvRequest ? this.tv.requestId : null, requestType: RequestType.tvShow, providerId: this.tv.theTvDbId, title: this.tv.title } + }); + } + public openDialog() { - debugger; let trailerLink = this.tv.trailer; trailerLink = trailerLink.split('?v=')[1]; @@ -69,4 +80,15 @@ export class TvDetailsComponent implements OnInit { data: trailerLink }); } + + public setAdvancedOptions(data: IAdvancedData) { + this.advancedOptions = data; + console.log(this.advancedOptions); + if (data.rootFolderId) { + this.showRequest.qualityOverrideTitle = data.rootFolders.filter(x => x.id == data.rootFolderId)[0].path; + } + if (data.profileId) { + this.showRequest.rootPathOverrideTitle = data.profiles.filter(x => x.id == data.profileId)[0].name; + } + } } diff --git a/src/Ombi/ClientApp/src/app/media-details/media-details.component.scss b/src/Ombi/ClientApp/src/app/media-details/media-details.component.scss index 0fa9f9351..f3c655c6f 100644 --- a/src/Ombi/ClientApp/src/app/media-details/media-details.component.scss +++ b/src/Ombi/ClientApp/src/app/media-details/media-details.component.scss @@ -1,30 +1,26 @@ @import "~@angular/material/theming"; @import "~styles/variables.scss"; - //MINE @media (max-width: 570px) { - h1 { - font-size: 1.5rem; - } - - .mobile-poster { - display: block; - position: absolute; - width: 70px; - left: 12px; - bottom: 2px; - } - - - #info-wrapper .sidebar-poster { - margin-top: -126px !important; - } + h1 { + font-size: 1.5rem; + } + .mobile-poster { + display: block; + position: absolute; + width: 70px; + left: 12px; + bottom: 2px; + } + #info-wrapper .sidebar-poster { + margin-top: -126px !important; + } } @media (max-width: 767px) { - #summary-wrapper { - height: 350px !important; - } + #summary-wrapper { + height: 350px !important; + } } #summary-wrapper .full-screenshot, @@ -32,190 +28,198 @@ #watching-wrapper .full-screenshot, .hero-wrapper .full-screenshot, #statics-top-wrapper .full-screenshot { - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; - background-size: cover; - background-position: center; - background-position: 50% 10%; - opacity: 0; - transition: all 1s; + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + background-size: cover; + background-position: center; + background-position: 50% 10%; + opacity: 0; + transition: all 1s; } #summary-wrapper, .summary-wrapper { - background-color: #000; - background-size: cover; - background-position: 50% 10%; - transition: all .5s; - height: 450px; - color: #fff; - position: relative; + background-color: #000; + background-size: cover; + background-position: 50% 10%; + transition: all .5s; + height: 450px; + color: #fff; + position: relative; } - #summary-wrapper .full-screenshot.enabled, .summary-wrapper .full-screenshot.enabled, #watching-wrapper .full-screenshot.enabled, .hero-wrapper .full-screenshot.enabled, #statics-top-wrapper .full-screenshot.enabled { - opacity: 1; + opacity: 1; } #summary-wrapper .shadow-base, .summary-wrapper .shadow-base { - bottom: 0; - background-image: -webkit-linear-gradient(top, transparent 0%, rgba(0, 0, 0, 0.5) 100%); - background-image: -o-linear-gradient(top, transparent 0%, rgba(0, 0, 0, 0.5) 100%); - background-image: linear-gradient(to bottom, transparent 0%, rgba(0, 0, 0, 0.5) 100%); - background-repeat: repeat-x; + bottom: 0; + background-image: -webkit-linear-gradient(top, transparent 0%, rgba(0, 0, 0, 0.5) 100%); + background-image: -o-linear-gradient(top, transparent 0%, rgba(0, 0, 0, 0.5) 100%); + background-image: linear-gradient(to bottom, transparent 0%, rgba(0, 0, 0, 0.5) 100%); + background-repeat: repeat-x; } .shadow-base { - height: 75px; - width: 100%; - position: absolute; - bottom: 0; - left: 0; - background-image: -webkit-linear-gradient(top, transparent 0%, rgba(0, 0, 0, 0.3) 100%); - background-image: -o-linear-gradient(top, transparent 0%, rgba(0, 0, 0, 0.3) 100%); - background-image: linear-gradient(to bottom, transparent 0%, rgba(0, 0, 0, 0.3) 100%); - background-repeat: repeat-x; - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#4D000000', GradientType=0); + height: 75px; + width: 100%; + position: absolute; + bottom: 0; + left: 0; + background-image: -webkit-linear-gradient(top, transparent 0%, rgba(0, 0, 0, 0.3) 100%); + background-image: -o-linear-gradient(top, transparent 0%, rgba(0, 0, 0, 0.3) 100%); + background-image: linear-gradient(to bottom, transparent 0%, rgba(0, 0, 0, 0.3) 100%); + background-repeat: repeat-x; + // filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#4D000000', GradientType=0); } .available-bottom-border { - border-bottom: solid 8px #1DE9B6; + border-bottom: solid 8px #1DE9B6; } #summary-wrapper .summary .container, .summary-wrapper .summary .container { - position: absolute; - bottom: 0; - left: 0; - right: 0; + position: absolute; + bottom: 0; + left: 0; + right: 0; } #summary-wrapper, .summary-wrapper { - background-color: #000; - background-size: cover; - background-position: 50% 10%; - transition: all .5s; - height: 550px; - color: #fff; - position: relative; + background-color: #000; + background-size: cover; + background-position: 50% 10%; + transition: all .5s; + height: 550px; + color: #fff; + position: relative; } - .grey-text { - color: #999; + color: #999; } - - #summary-wrapper .summary .container h1, .summary-wrapper .summary .container h1 { - margin: 0; - text-shadow: 1px 1px 5px #000; - line-height: 1.2; + margin: 0; + text-shadow: 1px 1px 5px #000; + line-height: 1.2; } #info-wrapper { - min-height: 600px; + min-height: 600px; } - #info-wrapper .sidebar.affixable.affix-top { - position: relative !important; + position: relative !important; } #info-wrapper .sidebar-poster { - margin-top: -280px; - width: 250px; + margin-top: -280px; + width: 250px; } #info-wrapper .sidebar .poster { - border: solid 3px #fff; - position: relative; - -webkit-box-shadow: 0 0 20px 0 #666; - box-shadow: 0 0 20px 0 #666; + border: solid 3px #fff; + position: relative; + -webkit-box-shadow: 0 0 20px 0 #666; + box-shadow: 0 0 20px 0 #666; } #info-wrapper .sidebar .poster img { - width: 100%; + width: 100%; } .full-width { - width: 100%; + width: 100%; } #info-wrapper .sidebar .poster .real { - height: 100%; - top: 0; - left: 0; + height: 100%; + top: 0; + left: 0; } .card-spacer { - padding-top: 1%; + padding-top: 1%; } .card-full { - height: 100%; + height: 100%; } .imdb-color { - color: black; - background-color: #f5de50; + color: black; + background-color: #f5de50; } .btn-spacing { - margin-right: 10px !important; + margin-right: 10px !important; } .spacing-below { - margin-bottom: 15px !important; + margin-bottom: 15px !important; } .left-seperator { - margin-left: 40px; + margin-left: 40px; } .tagline { - margin-top: 10px; - margin-left: 10px; - text-shadow: 1px 1px 5px #000; + margin-top: 10px; + margin-left: 10px; + text-shadow: 1px 1px 5px #000; } .preview-poster { - width: 173px; + width: 173px; } .media-icons { - color: mat-color($ombi-app-primary) !important; - padding: 1%; + color: mat-color($ombi-app-primary) !important; + padding: 1%; } .media-row { - padding-top: 2%; + padding-top: 2%; } .cast-profile-img { - border-radius: 10%; - width: 170px; + border-radius: 100%; + width: 170px; } + + + .small-middle-container { - margin: auto; - width: 95%; + margin: auto; + width: 95%; } .keywords-panel { - margin-top: 8%; + margin-top: 8%; } .medium-font { - font-size: 16px; + font-size: 16px; +} + +.issuesPanel { + padding-top: 1%; + padding-bottom: 1%; } + +.no-info { + text-align: center; + padding-top: 15%; +} \ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/media-details/media-details.module.ts b/src/Ombi/ClientApp/src/app/media-details/media-details.module.ts index 3a1f6e466..2544a4935 100644 --- a/src/Ombi/ClientApp/src/app/media-details/media-details.module.ts +++ b/src/Ombi/ClientApp/src/app/media-details/media-details.module.ts @@ -12,7 +12,6 @@ import { PipeModule } from "../pipes/pipe.module"; import * as fromComponents from './components'; import { AuthGuard } from "../auth/auth.guard"; -import { RequestServiceV2 } from "../services/requestV2.service"; import { ArtistDetailsComponent } from "./components/artist/artist-details.component"; diff --git a/src/Ombi/ClientApp/src/app/my-nav/SearchFilter.ts b/src/Ombi/ClientApp/src/app/my-nav/SearchFilter.ts new file mode 100644 index 000000000..40af3af79 --- /dev/null +++ b/src/Ombi/ClientApp/src/app/my-nav/SearchFilter.ts @@ -0,0 +1,7 @@ + +export class SearchFilter { + movies: boolean; + tvShows: boolean; + music: boolean; + people: boolean; +} diff --git a/src/Ombi/ClientApp/src/app/my-nav/my-nav.component.html b/src/Ombi/ClientApp/src/app/my-nav/my-nav.component.html index 52eb57759..849fc9f21 100644 --- a/src/Ombi/ClientApp/src/app/my-nav/my-nav.component.html +++ b/src/Ombi/ClientApp/src/app/my-nav/my-nav.component.html @@ -1,54 +1,120 @@ - - {{applicationName}} - - - - {{nav.icon}} -  {{nav.name | translate}} - - - - exit_to_app - {{ 'NavigationBar.Logout' | translate }} - - - - - {{ 'NavigationBar.ChangeTheme' | translate }} - - - - - - - - - - -
- - - - + + + {{applicationName}} + +
+
+
+ +
+
+

{{username}}

+

{{welcomeText | translate}}

+
+
- + + - - + + + + + wb_incandescent + brightness_4 +  {{ 'NavigationBar.ChangeTheme' | translate }} + + + exit_to_app +  {{ 'NavigationBar.Logout' | translate }} + + + + +
+
+ + + +
+
+
+ + + + + +
+ + +
+ +
+
+
+
+ + + + {{ 'NavigationBar.Filter.Movies' | translate}} + + {{ 'NavigationBar.Filter.TvShows' | translate}} + + {{ 'NavigationBar.Filter.Music' | translate}} + + {{ 'NavigationBar.Filter.People' | translate}} + +
+ +
-
+ + + + + + +
- +
- + \ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/my-nav/my-nav.component.scss b/src/Ombi/ClientApp/src/app/my-nav/my-nav.component.scss index af226e40a..b8abd28dc 100644 --- a/src/Ombi/ClientApp/src/app/my-nav/my-nav.component.scss +++ b/src/Ombi/ClientApp/src/app/my-nav/my-nav.component.scss @@ -1,10 +1,12 @@ @import "~styles/variables.scss"; .sidenav-container { min-height: 100vh; + -webkit-overflow-scrolling:touch; + overflow:auto; } .sidenav { - width: 200px; + width: 220px; } .sidenav .mat-toolbar { @@ -47,12 +49,74 @@ color:white; } -.active-list-item-dark { +::ng-deep .dark .active-list-item { background: $accent-dark !important; - color:black; + color:black !important; + font-weight:500; } -.bottom-nav-link { - bottom: 0; +.slide-menu { + width: 100%; +} + +::ng-deep .smaller-panel { + max-width: 170px !important; +} + +.mat-drawer-content { + position: relative; + overflow: hidden; + z-index: 1; + display: block; + height: 100%; + /* overflow: auto; */ +} + +.profile-img-container { + margin: 20px auto 10px; + overflow: hidden; + text-align: center; + width: 80%; +} +.profile-img { + float: left; + height: 40px; + margin-right: 15px; +} +.profile-info { + overflow: hidden; + text-align: left; +} +.profile-info > h3 { + font-size: 15px; + text-transform: capitalize; + // color: #333; + margin-bottom: 2px; +} +.profile-info > p { + // color: #333; + font-size: 11px; + margin-top: 5px; +} + +.profile-img img { + border-radius: 6px; + box-shadow: 4px 3px 6px 0 rgba(0,0,0,.2); + width: 45px; +} + +.outer-profile { + background-color: #303030; + box-shadow: inset 0 0 3px #000000; + padding: 1px; +} + +.full { + width: 100%; +} +.bottom-nav { position: absolute; + bottom: 0; + left: 0; + text-align: center; } \ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/my-nav/my-nav.component.ts b/src/Ombi/ClientApp/src/app/my-nav/my-nav.component.ts index a3825d4e8..553dcbf2c 100644 --- a/src/Ombi/ClientApp/src/app/my-nav/my-nav.component.ts +++ b/src/Ombi/ClientApp/src/app/my-nav/my-nav.component.ts @@ -4,6 +4,18 @@ import { Observable } from 'rxjs'; import { map } from 'rxjs/operators'; import { INavBar } from '../interfaces/ICommon'; import { StorageService } from '../shared/storage/storage-service'; +import { SettingsService } from '../services'; +import { MatSlideToggleChange } from '@angular/material/slide-toggle'; +import { SearchFilter } from './SearchFilter'; +import { Md5 } from 'ts-md5/dist/md5'; +import { RequestType } from '../interfaces'; + +export enum SearchFilterType { + Movie = 1, + TvShow = 2, + Music = 3, + People = 4 +} @Component({ selector: 'app-my-nav', @@ -19,32 +31,66 @@ export class MyNavComponent implements OnInit { @Input() public showNav: boolean; @Input() public applicationName: string; + @Input() public applicationLogo: string; @Input() public username: string; @Input() public isAdmin: string; + @Input() public email: string; @Output() public logoutClick = new EventEmitter(); @Output() public themeChange = new EventEmitter(); public theme: string; + public issuesEnabled: boolean = false; + public navItems: INavBar[]; + public searchFilter: SearchFilter; + public SearchFilterType = SearchFilterType; + public emailHash: string | Int32Array; + public welcomeText: string; + public RequestType = RequestType; constructor(private breakpointObserver: BreakpointObserver, - private store: StorageService) { + private settingsService: SettingsService, + private store: StorageService) { } - public ngOnInit(): void { + public async ngOnInit() { + + this.searchFilter = { + movies: true, + music: false, + people: false, + tvShows: true + } + + this.setWelcomeText(); + if (this.email) { + const md5 = new Md5(); + this.emailHash = md5.appendStr(this.email).end(); + } + + this.issuesEnabled = await this.settingsService.issueEnabled().toPromise(); + const customizationSettings = await this.settingsService.getCustomization().toPromise(); + console.log("issues enabled: " + this.issuesEnabled); this.theme = this.store.get("theme"); - if(!this.theme) { - this.store.save("theme","light"); + if (!this.theme) { + this.store.save("theme", "dark"); + } + var filter = this.store.get("searchFilter"); + if (filter) { + this.searchFilter = Object.assign(new SearchFilter(), JSON.parse(filter)); } + this.navItems = [ + { name: "NavigationBar.Discover", icon: "find_replace", link: "/discover", requiresAdmin: false, enabled: true, faIcon: null }, + { name: "NavigationBar.Requests", icon: "list", link: "/requests-list", requiresAdmin: false, enabled: true, faIcon: null }, + { name: "NavigationBar.Issues", icon: "notification_important", link: "/issues", requiresAdmin: false, enabled: this.issuesEnabled, faIcon: null }, + { name: "NavigationBar.UserManagement", icon: "account_circle", link: "/usermanagement", requiresAdmin: true, enabled: true, faIcon: null }, + // { name: "NavigationBar.Calendar", icon: "calendar_today", link: "/calendar", requiresAdmin: false, enabled: true }, + { name: "NavigationBar.Donate", icon: "attach_money", link: "https://www.paypal.me/PlexRequestsNet", externalLink: true, requiresAdmin: true, enabled: true, toolTip: true, style: "color:red;", toolTipMessage: 'NavigationBar.DonateTooltip', faIcon: null }, + { name: "NavigationBar.Donate", icon: "attach_money", link: customizationSettings.customDonationUrl, externalLink: true, requiresAdmin: false, enabled: customizationSettings.enableCustomDonations, toolTip: true, toolTipMessage: customizationSettings.customDonationMessage, faIcon: null }, + { name: "NavigationBar.FeatureSuggestion", icon: null, link: "https://features.ombi.io/", externalLink: true, requiresAdmin: true, enabled: true, toolTip: true, toolTipMessage: 'NavigationBar.FeatureSuggestionTooltip', faIcon: "fa-lightbulb-o" }, + { name: "NavigationBar.Settings", icon: "settings", link: "/Settings/About", requiresAdmin: true, enabled: true, faIcon: null }, + { name: "NavigationBar.UserPreferences", icon: "person", link: "/user-preferences", requiresAdmin: false, enabled: true, faIcon: null }, + ]; } - public navItems: INavBar[] = [ - { name: "NavigationBar.Discover", icon: "find_replace", link: "/discover", requiresAdmin: false }, - { name: "NavigationBar.Requests", icon: "list", link: "/requests-list", requiresAdmin: false }, - { name: "NavigationBar.UserManagement", icon: "account_circle", link: "/usermanagement", requiresAdmin: true }, - { name: "NavigationBar.Calendar", icon: "calendar_today", link: "/calendar", requiresAdmin: false }, - { name: "NavigationBar.Settings", icon: "settings", link: "/Settings/About", requiresAdmin: true }, - { name: "NavigationBar.UserPreferences", icon: "person", link: "/user-preferences", requiresAdmin: false }, - ] - public logOut() { this.logoutClick.emit(); } @@ -63,8 +109,36 @@ export class MyNavComponent implements OnInit { } } - public getTheme(){ - return this.theme === 'dark' ? 'active-list-item-dark' : 'active-list-item'; + public changeFilter(event: MatSlideToggleChange, searchFilterType: SearchFilterType) { + switch (searchFilterType) { + case SearchFilterType.Movie: + this.searchFilter.movies = event.checked; + break; + case SearchFilterType.TvShow: + this.searchFilter.tvShows = event.checked; + break; + case SearchFilterType.Music: + this.searchFilter.music = event.checked; + break; + case SearchFilterType.People: + this.searchFilter.people = event.checked; + break; + } + this.store.save("searchFilter", JSON.stringify(this.searchFilter)); } + private setWelcomeText() { + var d = new Date(); + var hour = d.getHours(); + + if (hour >= 0 && hour < 12) { + this.welcomeText = 'NavigationBar.MorningWelcome'; + } + if (hour >= 12 && hour < 18) { + this.welcomeText = 'NavigationBar.AfternoonWelcome'; + } + if (hour >= 18 && hour < 24) { + this.welcomeText = 'NavigationBar.EveningWelcome'; + } + } } diff --git a/src/Ombi/ClientApp/src/app/my-nav/nav-search.component.html b/src/Ombi/ClientApp/src/app/my-nav/nav-search.component.html index a28deb192..ccf574725 100644 --- a/src/Ombi/ClientApp/src/app/my-nav/nav-search.component.html +++ b/src/Ombi/ClientApp/src/app/my-nav/nav-search.component.html @@ -1,31 +1,42 @@ - + -
-   - {{result.title}} -
-
-   - - {{result.title}} -
+
+ + + -
-   - - {{result.title}} -
+ + + + + + + + +   + {{result.title}} + + +   -
-   - {{result.title}} -
- - + {{result.title}} +
+ +   - \ No newline at end of file + {{result.title}} + + + +   + {{result.title}} + +
+
+
+
\ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/my-nav/nav-search.component.scss b/src/Ombi/ClientApp/src/app/my-nav/nav-search.component.scss index 31d3114d6..31245eb0e 100644 --- a/src/Ombi/ClientApp/src/app/my-nav/nav-search.component.scss +++ b/src/Ombi/ClientApp/src/app/my-nav/nav-search.component.scss @@ -1,49 +1,47 @@ $ombi-primary:#3f3f3f; $ombi-primary-darker:#2b2b2b; $ombi-accent: #258a6d; - @media (max-width: 767px) { - .quater-width { - width: 15em !important; - } + .quater-width { + width: 15em !important; + } } .quater-width { - width: 25em; + width: 25em; } .autocomplete-img { - vertical-align: middle; - height: 63px; + vertical-align: middle; + height: 63px; } .mat-option { - height: 50px; - line-height: 50px; - padding: 0px 5px; + height: 75px; + line-height: 50px; + padding: 0px 0px; } -::ng-deep ngb-typeahead-window.dropdown-menu { - background-color: $ombi-primary; - overflow: auto; - height: 33em; +.search-bar { + background-color: $ombi-primary-darker; + border: solid 1px $ombi-primary-darker; } -::ng-deep ngb-typeahead-window button.dropdown-item { - color: white; +.search-bar:focus { + background-color: white; } -::ng-deep ngb-typeahead-window .dropdown-item.active, -.dropdown-item:active { - text-decoration: none; - background-color: $ombi-accent; +::ng-deep .mat-form-field-underline{ + bottom:0.5em; } -.search-bar { - background-color: $ombi-primary-darker; - border: solid 1px $ombi-primary-darker; -} -.search-bar:focus { - background-color: white; -} +.option-img { + vertical-align: middle; + margin-right: 8px; + } + + .options { + margin-bottom: 5px; + } + diff --git a/src/Ombi/ClientApp/src/app/my-nav/nav-search.component.ts b/src/Ombi/ClientApp/src/app/my-nav/nav-search.component.ts index ed90f8dd1..9467f9544 100644 --- a/src/Ombi/ClientApp/src/app/my-nav/nav-search.component.ts +++ b/src/Ombi/ClientApp/src/app/my-nav/nav-search.component.ts @@ -1,56 +1,78 @@ -import { Component } from '@angular/core'; -import { Observable } from 'rxjs'; -import { debounceTime, distinctUntilChanged, switchMap } from 'rxjs/operators'; +import { Component, Input, OnInit } from "@angular/core"; +import { + debounceTime, + switchMap, + tap, + finalize, +} from "rxjs/operators"; -import { SearchV2Service } from '../services/searchV2.service'; -import { IMultiSearchResult } from '../interfaces'; -import { Router } from '@angular/router'; -import { NgbTypeaheadSelectItemEvent } from '@ng-bootstrap/ng-bootstrap'; +import { empty} from "rxjs"; +import { SearchV2Service } from "../services/searchV2.service"; +import { IMultiSearchResult } from "../interfaces"; +import { Router } from "@angular/router"; +import { FormGroup, FormBuilder } from "@angular/forms"; +import { MatAutocompleteSelectedEvent } from "@angular/material/autocomplete"; +import { SearchFilter } from "./SearchFilter"; @Component({ - selector: 'app-nav-search', - templateUrl: './nav-search.component.html', - styleUrls: ['./nav-search.component.scss'] + selector: "app-nav-search", + templateUrl: "./nav-search.component.html", + styleUrls: ["./nav-search.component.scss"], }) -export class NavSearchComponent { +export class NavSearchComponent implements OnInit { + @Input() public filter: SearchFilter; + public selectedItem: string; + public results: IMultiSearchResult[]; + public searching = false; - public selectedItem: string; - - public searching = false; - public searchFailed = false; - - public formatter = (result: IMultiSearchResult) => { - return result.title; - } - - public searchModel = (text$: Observable) => - text$.pipe( - debounceTime(600), - distinctUntilChanged(), - switchMap(term => term.length < 2 ? [] - : this.searchService.multiSearch(term) - ) - ) + public searchForm: FormGroup; - constructor(private searchService: SearchV2Service, private router: Router) { + constructor( + private searchService: SearchV2Service, + private router: Router, + private fb: FormBuilder + ) {} - } + public async ngOnInit() { + this.searchForm = this.fb.group({ + input: null, + }); - + this.searchForm + .get("input") + .valueChanges.pipe( + debounceTime(600), + tap(() => (this.searching = true)), + switchMap((value: string) => { + if (value) { + return this.searchService + .multiSearch(value, this.filter) + .pipe(finalize(() => (this.searching = false))); + } + return empty().pipe(finalize(() => (this.searching = false))); + }) + ) + .subscribe((r) => (this.results = r)); + } - public selected(event: NgbTypeaheadSelectItemEvent) { - if (event.item.mediaType == "movie") { - this.router.navigate([`details/movie/${event.item.id}`]); - return; - } else if (event.item.mediaType == "tv") { - this.router.navigate([`details/tv/${event.item.id}/true`]); - return; - } else if (event.item.mediaType == "person") { - this.router.navigate([`discover/actor/${event.item.id}`]); - return; - } else if (event.item.mediaType == "Artist") { - this.router.navigate([`details/artist/${event.item.id}`]); - return; - } + public selected(event: MatAutocompleteSelectedEvent) { + this.searchForm.controls.input.setValue(null); + const val = event.option.value as IMultiSearchResult; + if (val.mediaType == "movie") { + this.router.navigate([`details/movie/${val.id}`]); + return; + } else if (val.mediaType == "tv") { + this.router.navigate([`details/tv/${val.id}/true`]); + return; + } else if (val.mediaType == "person") { + this.router.navigate([`discover/actor/${val.id}`]); + return; + } else if (val.mediaType == "Artist") { + this.router.navigate([`details/artist/${val.id}`]); + return; } + } + displayFn(result: IMultiSearchResult) { + if (result) { return result.title; } + } } diff --git a/src/Ombi/ClientApp/src/app/pipes/QualityPipe.ts b/src/Ombi/ClientApp/src/app/pipes/QualityPipe.ts new file mode 100644 index 000000000..393e08640 --- /dev/null +++ b/src/Ombi/ClientApp/src/app/pipes/QualityPipe.ts @@ -0,0 +1,11 @@ +import { Pipe, PipeTransform } from '@angular/core'; + +@Pipe({ name: 'quality' }) +export class QualityPipe implements PipeTransform { + transform(value: string): string { + if (value.toUpperCase() === "4K" || value.toUpperCase() === "8K") { + return value; + } + return value + "p"; + } +} \ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/pipes/pipe.module.ts b/src/Ombi/ClientApp/src/app/pipes/pipe.module.ts index 6a0af4a45..a947851b3 100644 --- a/src/Ombi/ClientApp/src/app/pipes/pipe.module.ts +++ b/src/Ombi/ClientApp/src/app/pipes/pipe.module.ts @@ -2,15 +2,16 @@ import { HumanizePipe } from "./HumanizePipe"; import { ThousandShortPipe } from "./ThousandShortPipe"; import { SafePipe } from "./SafePipe"; +import { QualityPipe } from "./QualityPipe"; @NgModule({ imports: [], - declarations: [HumanizePipe, ThousandShortPipe, SafePipe], - exports: [HumanizePipe, ThousandShortPipe, SafePipe], + declarations: [HumanizePipe, ThousandShortPipe, SafePipe, QualityPipe], + exports: [HumanizePipe, ThousandShortPipe, SafePipe, QualityPipe], }) export class PipeModule { - public static forRoot(): ModuleWithProviders { + public static forRoot(): ModuleWithProviders { return { ngModule: PipeModule, providers: [], diff --git a/src/Ombi/ClientApp/src/app/recentlyAdded/recentlyAdded.component.html b/src/Ombi/ClientApp/src/app/recentlyAdded/recentlyAdded.component.html deleted file mode 100644 index ee60b7c87..000000000 --- a/src/Ombi/ClientApp/src/app/recentlyAdded/recentlyAdded.component.html +++ /dev/null @@ -1,51 +0,0 @@ -

Recently Added

- -
- -
- - - -
- poster -
{{movie.title}}
-
- - -
- - - -
- - - -
- - - - poster - {{t.title}} -
- Season: {{t.seasonNumber}} -
- Episode: {{t.episodeNumber}} -
- - - -
diff --git a/src/Ombi/ClientApp/src/app/recentlyAdded/recentlyAdded.component.ts b/src/Ombi/ClientApp/src/app/recentlyAdded/recentlyAdded.component.ts deleted file mode 100644 index f426a39d1..000000000 --- a/src/Ombi/ClientApp/src/app/recentlyAdded/recentlyAdded.component.ts +++ /dev/null @@ -1,131 +0,0 @@ -import { Component, OnInit } from "@angular/core"; -import { NguCarouselConfig } from "@ngu/carousel"; - -import { IRecentlyAddedMovies, IRecentlyAddedTvShows } from "../interfaces"; -import { ImageService, RecentlyAddedService } from "../services"; - -@Component({ - templateUrl: "recentlyAdded.component.html", - styles: [` - .leftRs { - position: absolute; - margin: auto; - top: 0; - bottom: 0; - width: 50px; - height: 50px; - box-shadow: 1px 2px 10px -1px rgba(0, 0, 0, .3); - border-radius: 100%; - left: 0; - background: #df691a; - } - - .rightRs { - position: absolute; - margin: auto; - top: 0; - bottom: 0; - width: 50px; - height: 50px; - box-shadow: 1px 2px 10px -1px rgba(0, 0, 0, .3); - border-radius: 100%; - right: 0; - background: #df691a; - } - `], -}) - -export class RecentlyAddedComponent implements OnInit { - public movies: IRecentlyAddedMovies[]; - public tv: IRecentlyAddedTvShows[]; - public range: Date[]; - - public groupTv: boolean = false; - - // https://github.com/sheikalthaf/ngu-carousel - public carouselTile: NguCarouselConfig; - - constructor(private recentlyAddedService: RecentlyAddedService, - private imageService: ImageService) {} - - public ngOnInit() { - this.getMovies(); - this.getShows(); - - this.carouselTile = { - grid: {xs: 2, sm: 3, md: 3, lg: 5, all: 0}, - slide: 2, - speed: 400, - animation: "lazy", - point: { - visible: true, - }, - load: 2, - touch: true, - easing: "ease", - }; - } - - public close() { - if (this.range.length < 2) { - return; - } - if (!this.range[1]) { - // If we do not have a second date then just set it to now - this.range[1] = new Date(); - } - this.getMovies(); - } - - public change() { - this.getShows(); - } - - private getShows() { - if (this.groupTv) { - this.recentlyAddedService.getRecentlyAddedTvGrouped().subscribe(x => { - this.tv = x; - - this.tv.forEach((t) => { - this.imageService.getTvPoster(t.tvDbId).subscribe(p => { - if (p) { - t.posterPath = p; - } - }); - }); - }); - } else { - this.recentlyAddedService.getRecentlyAddedTv().subscribe(x => { - this.tv = x; - - this.tv.forEach((t) => { - this.imageService.getTvPoster(t.tvDbId).subscribe(p => { - if (p) { - t.posterPath = p; - } - }); - }); - }); - } - } - - private getMovies() { - this.recentlyAddedService.getRecentlyAddedMovies().subscribe(x => { - this.movies = x; - - this.movies.forEach((movie) => { - if (movie.theMovieDbId) { - this.imageService.getMoviePoster(movie.theMovieDbId).subscribe(p => { - movie.posterPath = p; - }); - } else if (movie.imdbId) { - this.imageService.getMoviePoster(movie.imdbId).subscribe(p => { - movie.posterPath = p; - }); - } else { - movie.posterPath = ""; - } - }); - }); - } -} diff --git a/src/Ombi/ClientApp/src/app/recentlyAdded/recentlyAdded.module.ts b/src/Ombi/ClientApp/src/app/recentlyAdded/recentlyAdded.module.ts deleted file mode 100644 index cf0b423a3..000000000 --- a/src/Ombi/ClientApp/src/app/recentlyAdded/recentlyAdded.module.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { NgModule } from "@angular/core"; -import { RouterModule, Routes } from "@angular/router"; - -import { NgbModule } from "@ng-bootstrap/ng-bootstrap"; -import { OrderModule } from "ngx-order-pipe"; -import { CalendarModule, PaginatorModule, SharedModule, TabViewModule } from "primeng/primeng"; - -import { IdentityService, ImageService, RecentlyAddedService } from "../services"; - -import { AuthGuard } from "../auth/auth.guard"; - -import { SharedModule as OmbiShared } from "../shared/shared.module"; - -import { RecentlyAddedComponent } from "./recentlyAdded.component"; - -import { NguCarouselModule } from "@ngu/carousel"; - -const routes: Routes = [ - { path: "", component: RecentlyAddedComponent, canActivate: [AuthGuard] }, -]; - -@NgModule({ - imports: [ - RouterModule.forChild(routes), - NgbModule.forRoot(), - SharedModule, - OrderModule, - OmbiShared, - PaginatorModule, - TabViewModule, - CalendarModule, - NguCarouselModule, - ], - declarations: [ - RecentlyAddedComponent, - ], - exports: [ - RouterModule, - ], - providers: [ - IdentityService, - RecentlyAddedService, - ImageService, - ], - -}) -export class RecentlyAddedModule { } diff --git a/src/Ombi/ClientApp/src/app/requests-list/components/albums-grid/albums-grid.component.html b/src/Ombi/ClientApp/src/app/requests-list/components/albums-grid/albums-grid.component.html new file mode 100644 index 000000000..63e771e89 --- /dev/null +++ b/src/Ombi/ClientApp/src/app/requests-list/components/albums-grid/albums-grid.component.html @@ -0,0 +1,72 @@ +
+ + + + +
+
+ + + + + +
+
+ +
+
+ + + 10 + 15 + 30 + 100 + + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
{{ 'Requests.ArtistName' | translate}} {{element.artistName}} {{ 'Requests.AlbumName' | translate}} {{element.title}} ({{element.releaseDate | amLocal | amDateFormat: 'YYYY'}}) {{'Requests.RequestedBy' | translate}} {{element.requestedUser?.userAlias}} {{ 'Requests.RequestDate' | translate}} {{element.requestedDate | amLocal | amDateFormat: 'LL'}} {{ 'Requests.RequestStatus' | translate}} {{element.requestStatus | translate}} + + +
+ + +
\ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/requests-list/components/albums-grid/albums-grid.component.scss b/src/Ombi/ClientApp/src/app/requests-list/components/albums-grid/albums-grid.component.scss new file mode 100644 index 000000000..fd5a5e47c --- /dev/null +++ b/src/Ombi/ClientApp/src/app/requests-list/components/albums-grid/albums-grid.component.scss @@ -0,0 +1,49 @@ +@import "~styles/variables.scss"; + +.dark .mat-header-cell { + background: $accent-dark !important; + font-size: 1em; + font-weight: bold; + color: #303030; +} + +.mat-form-field { + float:right; + margin-right:20px; +} + +/*::ng-deep .dark .mat-form-field-label{ + font-size: 1.2em; +}*/ + +::ng-deep .mat-form-field-infix { + width: 8em; + margin-top:1em; +} + +::ng-deep .dark .mat-tab-label-active{ + background: $accent-dark !important; + color: #303030 !important; + font-weight:bold; +} + +::ng-deep .mat-tab-label{ + opacity: 1; +} + +::ng-deep .row { + margin-right:0; + margin-left:0; +} + +@media (min-width: 500px) { + .justify-content-md-center { + justify-content: normal !important; + } +} + +@media (min-width: 1170px){ + .justify-content-md-center { + justify-content: center !important; + } +} \ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/requests-list/components/albums-grid/albums-grid.component.ts b/src/Ombi/ClientApp/src/app/requests-list/components/albums-grid/albums-grid.component.ts new file mode 100644 index 000000000..633ddf1c2 --- /dev/null +++ b/src/Ombi/ClientApp/src/app/requests-list/components/albums-grid/albums-grid.component.ts @@ -0,0 +1,136 @@ +import { Component, AfterViewInit, ViewChild, EventEmitter, Output, ChangeDetectorRef, OnInit } from "@angular/core"; +import { IRequestsViewModel, IAlbumRequest } from "../../../interfaces"; +import { MatPaginator } from "@angular/material/paginator"; +import { MatSort } from "@angular/material/sort"; +import { merge, Observable, of as observableOf } from 'rxjs'; +import { catchError, map, startWith, switchMap } from 'rxjs/operators'; + +import { RequestServiceV2 } from "../../../services/requestV2.service"; +import { AuthService } from "../../../auth/auth.service"; +import { StorageService } from "../../../shared/storage/storage-service"; +import { RequestFilterType } from "../../models/RequestFilterType"; + +@Component({ + templateUrl: "./albums-grid.component.html", + selector: "albums-grid", + styleUrls: ["./albums-grid.component.scss"] +}) +export class AlbumsGridComponent implements OnInit, AfterViewInit { + public dataSource: IAlbumRequest[] = []; + public resultsLength: number; + public isLoadingResults = true; + public displayedColumns: string[] = ['artistName', 'title', 'requestedUser.requestedBy', 'requestStatus','requestedDate', 'actions']; + public gridCount: string = "15"; + public isAdmin: boolean; + public defaultSort: string = "requestedDate"; + public defaultOrder: string = "desc"; + public currentFilter: RequestFilterType = RequestFilterType.All; + + public RequestFilter = RequestFilterType; + + + private storageKey = "Albums_DefaultRequestListSort"; + private storageKeyOrder = "Albums_DefaultRequestListSortOrder"; + private storageKeyGridCount = "Albums_DefaultGridCount"; + private storageKeyCurrentFilter = "Albums_DefaultFilter"; + + @Output() public onOpenOptions = new EventEmitter<{ request: any, filter: any, onChange: any }>(); + + @ViewChild(MatPaginator) paginator: MatPaginator; + @ViewChild(MatSort) sort: MatSort; + + constructor(private requestService: RequestServiceV2, private ref: ChangeDetectorRef, + private auth: AuthService, private storageService: StorageService) { + + } + + public ngOnInit() { + this.isAdmin = this.auth.hasRole("admin") || this.auth.hasRole("poweruser"); + + const defaultCount = this.storageService.get(this.storageKeyGridCount); + const defaultSort = this.storageService.get(this.storageKey); + const defaultOrder = this.storageService.get(this.storageKeyOrder); + const defaultFilter = +this.storageService.get(this.storageKeyCurrentFilter); + if (defaultSort) { + this.defaultSort = defaultSort; + } + if (defaultOrder) { + this.defaultOrder = defaultOrder; + } + if (defaultCount) { + this.gridCount = defaultCount; + } + if (defaultFilter) { + this.currentFilter = defaultFilter; + } + } + + public async ngAfterViewInit() { + + this.storageService.save(this.storageKeyGridCount, this.gridCount); + this.storageService.save(this.storageKeyCurrentFilter, (+this.currentFilter).toString()); + + // If the user changes the sort order, reset back to the first page. + this.sort.sortChange.subscribe(() => this.paginator.pageIndex = 0); + this.paginator.showFirstLastButtons = true; + + merge(this.sort.sortChange, this.paginator.page) + .pipe( + startWith({}), + switchMap((value: any) => { + this.isLoadingResults = true; + if (value.active || value.direction) { + this.storageService.save(this.storageKey, value.active); + this.storageService.save(this.storageKeyOrder, value.direction); + } + return this.loadData(); + }), + map((data: IRequestsViewModel) => { + // Flip flag to show that loading has finished. + this.isLoadingResults = false; + this.resultsLength = data.total; + + return data.collection; + }), + catchError((err) => { + this.isLoadingResults = false; + return observableOf([]); + }) + ).subscribe(data => this.dataSource = data); + } + + public loadData(): Observable> { + switch(RequestFilterType[RequestFilterType[this.currentFilter]]) { + case RequestFilterType.All: + return this.requestService.getAlbumRequests(+this.gridCount, this.paginator.pageIndex * +this.gridCount, this.sort.active, this.sort.direction); + case RequestFilterType.Pending: + return this.requestService.getAlbumPendingRequests(+this.gridCount, this.paginator.pageIndex * +this.gridCount, this.sort.active, this.sort.direction); + case RequestFilterType.Available: + return this.requestService.getAlbumAvailableRequests(+this.gridCount, this.paginator.pageIndex * +this.gridCount, this.sort.active, this.sort.direction); + case RequestFilterType.Processing: + return this.requestService.getAlbumProcessingRequests(+this.gridCount, this.paginator.pageIndex * +this.gridCount, this.sort.active, this.sort.direction); + case RequestFilterType.Denied: + return this.requestService.getAlbumDeniedRequests(+this.gridCount, this.paginator.pageIndex * +this.gridCount, this.sort.active, this.sort.direction); + } + + } + + public openOptions(request: IAlbumRequest) { + const filter = () => { + this.dataSource = this.dataSource.filter((req) => { + return req.id !== request.id; + }) + }; + + const onChange = () => { + this.ref.detectChanges(); + }; + + this.onOpenOptions.emit({ request: request, filter: filter, onChange: onChange }); + } + + public switchFilter(type: RequestFilterType) { + this.currentFilter = type; + this.ngAfterViewInit(); + } +} diff --git a/src/Ombi/ClientApp/src/app/requests-list/components/index.ts b/src/Ombi/ClientApp/src/app/requests-list/components/index.ts index 7f226fea5..eac024141 100644 --- a/src/Ombi/ClientApp/src/app/requests-list/components/index.ts +++ b/src/Ombi/ClientApp/src/app/requests-list/components/index.ts @@ -5,14 +5,21 @@ import { RequestServiceV2 } from "../../services/requestV2.service"; import { RequestService } from "../../services"; import { TvGridComponent } from "./tv-grid/tv-grid.component"; import { GridSpinnerComponent } from "./grid-spinner/grid-spinner.component"; +import { RequestOptionsComponent } from "./options/request-options.component"; +import { AlbumsGridComponent } from "./albums-grid/albums-grid.component"; export const components: any[] = [ RequestsListComponent, MoviesGridComponent, TvGridComponent, GridSpinnerComponent, + RequestOptionsComponent, + AlbumsGridComponent ]; +export const entryComponents: any[] = [ + RequestOptionsComponent +]; export const providers: any[] = [ RequestService, diff --git a/src/Ombi/ClientApp/src/app/requests-list/components/movies-grid/movies-grid.component.html b/src/Ombi/ClientApp/src/app/requests-list/components/movies-grid/movies-grid.component.html index e4a670b9c..c32ceea1b 100644 --- a/src/Ombi/ClientApp/src/app/requests-list/components/movies-grid/movies-grid.component.html +++ b/src/Ombi/ClientApp/src/app/requests-list/components/movies-grid/movies-grid.component.html @@ -1,56 +1,74 @@
- - - 10 - 15 - 30 - 100 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Requested By {{element.requestedUser?.userAlias}} Title {{element.title}} ({{element.releaseDate | amLocal | amDateFormat: - 'YYYY'}}) Request Date {{element.requestedDate | amLocal | amDateFormat: 'LL'}} Status {{element.status}} Request Status {{element.requestStatus | translate}} - -
- - -
+ + +
+
+ + + + + +
+
+ +
+
+ + + 10 + 15 + 30 + 100 + + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
{{ 'Requests.RequestsTitle' | translate}} {{element.title}} ({{element.releaseDate | amLocal | amDateFormat: 'YYYY'}}) {{'Requests.RequestedBy' | translate}} {{element.requestedUser?.userAlias}} {{ 'Requests.RequestDate' | translate}} {{element.requestedDate | amLocal | amDateFormat: 'LL'}} {{ 'Requests.Status' | translate}} {{element.status}} {{ 'Requests.RequestStatus' | translate}} {{element.requestStatus | translate}} + + +
+ + +
\ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/requests-list/components/movies-grid/movies-grid.component.scss b/src/Ombi/ClientApp/src/app/requests-list/components/movies-grid/movies-grid.component.scss new file mode 100644 index 000000000..fd5a5e47c --- /dev/null +++ b/src/Ombi/ClientApp/src/app/requests-list/components/movies-grid/movies-grid.component.scss @@ -0,0 +1,49 @@ +@import "~styles/variables.scss"; + +.dark .mat-header-cell { + background: $accent-dark !important; + font-size: 1em; + font-weight: bold; + color: #303030; +} + +.mat-form-field { + float:right; + margin-right:20px; +} + +/*::ng-deep .dark .mat-form-field-label{ + font-size: 1.2em; +}*/ + +::ng-deep .mat-form-field-infix { + width: 8em; + margin-top:1em; +} + +::ng-deep .dark .mat-tab-label-active{ + background: $accent-dark !important; + color: #303030 !important; + font-weight:bold; +} + +::ng-deep .mat-tab-label{ + opacity: 1; +} + +::ng-deep .row { + margin-right:0; + margin-left:0; +} + +@media (min-width: 500px) { + .justify-content-md-center { + justify-content: normal !important; + } +} + +@media (min-width: 1170px){ + .justify-content-md-center { + justify-content: center !important; + } +} \ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/requests-list/components/movies-grid/movies-grid.component.ts b/src/Ombi/ClientApp/src/app/requests-list/components/movies-grid/movies-grid.component.ts index f892f74c6..93cf37a64 100644 --- a/src/Ombi/ClientApp/src/app/requests-list/components/movies-grid/movies-grid.component.ts +++ b/src/Ombi/ClientApp/src/app/requests-list/components/movies-grid/movies-grid.component.ts @@ -1,47 +1,88 @@ -import { Component, AfterViewInit, ViewChild } from "@angular/core"; +import { Component, AfterViewInit, ViewChild, EventEmitter, Output, ChangeDetectorRef, OnInit } from "@angular/core"; import { IMovieRequests, IRequestsViewModel } from "../../../interfaces"; -import { MatPaginator, MatSort } from "@angular/material"; +import { MatPaginator } from "@angular/material/paginator"; +import { MatSort } from "@angular/material/sort"; import { merge, Observable, of as observableOf } from 'rxjs'; import { catchError, map, startWith, switchMap } from 'rxjs/operators'; import { RequestServiceV2 } from "../../../services/requestV2.service"; +import { AuthService } from "../../../auth/auth.service"; +import { StorageService } from "../../../shared/storage/storage-service"; +import { RequestFilterType } from "../../models/RequestFilterType"; @Component({ templateUrl: "./movies-grid.component.html", selector: "movies-grid", - styleUrls: ["../requests-list.component.scss"] + styleUrls: ["./movies-grid.component.scss"] }) -export class MoviesGridComponent implements AfterViewInit { +export class MoviesGridComponent implements OnInit, AfterViewInit { public dataSource: IMovieRequests[] = []; public resultsLength: number; public isLoadingResults = true; - public displayedColumns: string[] = ['requestedUser.requestedBy', 'title', 'requestedDate', 'status', 'requestStatus', 'actions']; + public displayedColumns: string[] = ['title', 'requestedUser.requestedBy', 'status', 'requestStatus','requestedDate', 'actions']; public gridCount: string = "15"; - public showUnavailableRequests: boolean; + public isAdmin: boolean; + public defaultSort: string = "requestedDate"; + public defaultOrder: string = "desc"; + public currentFilter: RequestFilterType = RequestFilterType.All; - @ViewChild(MatPaginator, {static: false}) paginator: MatPaginator; - @ViewChild(MatSort, {static: false}) sort: MatSort; + public RequestFilter = RequestFilterType; - constructor(private requestService: RequestServiceV2) { + private storageKey = "Movie_DefaultRequestListSort"; + private storageKeyOrder = "Movie_DefaultRequestListSortOrder"; + private storageKeyGridCount = "Movie_DefaultGridCount"; + private storageKeyCurrentFilter = "Movie_DefaultFilter"; + + @Output() public onOpenOptions = new EventEmitter<{ request: any, filter: any, onChange: any }>(); + + @ViewChild(MatPaginator) paginator: MatPaginator; + @ViewChild(MatSort) sort: MatSort; + + constructor(private requestService: RequestServiceV2, private ref: ChangeDetectorRef, + private auth: AuthService, private storageService: StorageService) { + + } + + public ngOnInit() { + this.isAdmin = this.auth.hasRole("admin") || this.auth.hasRole("poweruser"); + + const defaultCount = this.storageService.get(this.storageKeyGridCount); + const defaultSort = this.storageService.get(this.storageKey); + const defaultOrder = this.storageService.get(this.storageKeyOrder); + const defaultFilter = +this.storageService.get(this.storageKeyCurrentFilter); + if (defaultSort) { + this.defaultSort = defaultSort; + } + if (defaultOrder) { + this.defaultOrder = defaultOrder; + } + if (defaultCount) { + this.gridCount = defaultCount; + } + if (defaultFilter) { + this.currentFilter = defaultFilter; + } } public async ngAfterViewInit() { - // const results = await this.requestService.getMovieRequests(this.gridCount, 0, OrderType.RequestedDateDesc, - // { availabilityFilter: FilterType.None, statusFilter: FilterType.None }).toPromise(); - // this.dataSource = results.collection; - // this.resultsLength = results.total; + + this.storageService.save(this.storageKeyGridCount, this.gridCount); + this.storageService.save(this.storageKeyCurrentFilter, (+this.currentFilter).toString()); // If the user changes the sort order, reset back to the first page. this.sort.sortChange.subscribe(() => this.paginator.pageIndex = 0); + this.paginator.showFirstLastButtons = true; merge(this.sort.sortChange, this.paginator.page) .pipe( startWith({}), - switchMap(() => { + switchMap((value: any) => { this.isLoadingResults = true; - // eturn this.exampleDatabase!.getRepoIssues( - // this.sort.active, this.sort.direction, this.paginator.pageIndex); + if (value.active || value.direction) { + this.storageService.save(this.storageKey, value.active); + this.storageService.save(this.storageKeyOrder, value.direction); + } return this.loadData(); }), map((data: IRequestsViewModel) => { @@ -59,10 +100,37 @@ export class MoviesGridComponent implements AfterViewInit { } public loadData(): Observable> { - if (this.showUnavailableRequests) { - return this.requestService.getMovieUnavailableRequests(+this.gridCount, this.paginator.pageIndex * +this.gridCount, this.sort.active, this.sort.direction); - } else { - return this.requestService.getMovieRequests(+this.gridCount, this.paginator.pageIndex * +this.gridCount, this.sort.active, this.sort.direction); + switch(RequestFilterType[RequestFilterType[this.currentFilter]]) { + case RequestFilterType.All: + return this.requestService.getMovieRequests(+this.gridCount, this.paginator.pageIndex * +this.gridCount, this.sort.active, this.sort.direction); + case RequestFilterType.Pending: + return this.requestService.getMoviePendingRequests(+this.gridCount, this.paginator.pageIndex * +this.gridCount, this.sort.active, this.sort.direction); + case RequestFilterType.Available: + return this.requestService.getMovieAvailableRequests(+this.gridCount, this.paginator.pageIndex * +this.gridCount, this.sort.active, this.sort.direction); + case RequestFilterType.Processing: + return this.requestService.getMovieProcessingRequests(+this.gridCount, this.paginator.pageIndex * +this.gridCount, this.sort.active, this.sort.direction); + case RequestFilterType.Denied: + return this.requestService.getMovieDeniedRequests(+this.gridCount, this.paginator.pageIndex * +this.gridCount, this.sort.active, this.sort.direction); } + + } + + public openOptions(request: IMovieRequests) { + const filter = () => { + this.dataSource = this.dataSource.filter((req) => { + return req.id !== request.id; + }) + }; + + const onChange = () => { + this.ref.detectChanges(); + }; + + this.onOpenOptions.emit({ request: request, filter: filter, onChange: onChange }); + } + + public switchFilter(type: RequestFilterType) { + this.currentFilter = type; + this.ngAfterViewInit(); } } diff --git a/src/Ombi/ClientApp/src/app/requests-list/components/options/request-options.component.html b/src/Ombi/ClientApp/src/app/requests-list/components/options/request-options.component.html new file mode 100644 index 000000000..be749cc28 --- /dev/null +++ b/src/Ombi/ClientApp/src/app/requests-list/components/options/request-options.component.html @@ -0,0 +1,11 @@ + + + {{'Requests.RequestPanel.Delete' | translate}} + + + {{'Requests.RequestPanel.Approve' | translate}} + + + {{'Requests.RequestPanel.ChangeAvailability' | translate}} + + \ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/requests-list/components/options/request-options.component.ts b/src/Ombi/ClientApp/src/app/requests-list/components/options/request-options.component.ts new file mode 100644 index 000000000..625efe31c --- /dev/null +++ b/src/Ombi/ClientApp/src/app/requests-list/components/options/request-options.component.ts @@ -0,0 +1,59 @@ +import { Component, Inject } from '@angular/core'; +import { MAT_BOTTOM_SHEET_DATA, MatBottomSheetRef } from '@angular/material/bottom-sheet'; +import { RequestService } from '../../../services'; +import { RequestType } from '../../../interfaces'; +import { UpdateType } from '../../models/UpdateType'; + +@Component({ + selector: 'request-options', + templateUrl: './request-options.component.html', +}) +export class RequestOptionsComponent { + + public RequestType = RequestType; + + constructor(@Inject(MAT_BOTTOM_SHEET_DATA) public data: any, + private requestService: RequestService, private bottomSheetRef: MatBottomSheetRef) { } + + public async delete() { + if (this.data.type === RequestType.movie) { + await this.requestService.removeMovieRequestAsync(this.data.id); + } + if (this.data.type === RequestType.tvShow) { + await this.requestService.deleteChild(this.data.id).toPromise(); + } + if (this.data.type === RequestType.album) { + await this.requestService.removeAlbumRequest(this.data.id).toPromise(); + } + + this.bottomSheetRef.dismiss({type: UpdateType.Delete}); + return; + } + + public async approve() { + if (this.data.type === RequestType.movie) { + await this.requestService.approveMovie({id: this.data.id}).toPromise(); + } + if (this.data.type === RequestType.tvShow) { + await this.requestService.approveChild({id: this.data.id}).toPromise(); + } + if (this.data.type === RequestType.album) { + await this.requestService.approveAlbum({id: this.data.id}).toPromise(); + } + + this.bottomSheetRef.dismiss({type: UpdateType.Approve}); + return; + } + + public async changeAvailability() { + if (this.data.type === RequestType.movie) { + await this.requestService.markMovieAvailable({id: this.data.id}).toPromise(); + } + if (this.data.type === RequestType.album) { + await this.requestService.markAlbumAvailable({id: this.data.id}).toPromise(); + } + + this.bottomSheetRef.dismiss({type: UpdateType.Availability}); + return; + } +} \ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/requests-list/components/requests-list.component.html b/src/Ombi/ClientApp/src/app/requests-list/components/requests-list.component.html index 4c0111d06..9a58c9d1d 100644 --- a/src/Ombi/ClientApp/src/app/requests-list/components/requests-list.component.html +++ b/src/Ombi/ClientApp/src/app/requests-list/components/requests-list.component.html @@ -1,19 +1,22 @@
+
- + - + -

Some more tab content

-

...

+ + +
+
diff --git a/src/Ombi/ClientApp/src/app/requests-list/components/requests-list.component.scss b/src/Ombi/ClientApp/src/app/requests-list/components/requests-list.component.scss index c875fa54c..f8a34118d 100644 --- a/src/Ombi/ClientApp/src/app/requests-list/components/requests-list.component.scss +++ b/src/Ombi/ClientApp/src/app/requests-list/components/requests-list.component.scss @@ -1,4 +1,65 @@ +@import "~styles/variables.scss"; + .small-middle-container{ margin: auto; - width: 95%; + width: 85%; + margin-top:10px; } + +::ng-deep .dark .mat-header-cell { + background: rgba(0, 0, 0, 0.381)!important; + font-size: 1em; + font-weight: 500; + color: rgba(255, 255, 255, 0.842) !important; +} + +::ng-deep .dark .mat-header-cell .mat-checkbox-frame { + border-color: #FFF; +} + +.mat-form-field { + float:right; +} + +::ng-deep .mat-form-field-label{ + font-size: 1.2em; +} + +::ng-deep .mat-form-field-infix { + width: 10em; + margin-top:1em; +} + +::ng-deep .dark .mat-tab-label-active{ + background: $accent-dark !important; + color: #303030 !important; + font-weight:bold; +} + +::ng-deep .mat-tab-label{ + opacity: 1; +} + +::ng-deep .mat-tab-header { + margin-top: 2em; +} + +::ng-deep .dark .mat-sort-header-arrow{ + color:#c6c6c6; +} + +::ng-deep .mat-column-actions{ + text-align:end; +} + +@media (min-width: 500px) { + .justify-content-md-center { + justify-content: normal !important; + } +} + +@media (min-width: 1170px){ + .justify-content-md-center { + justify-content: center !important; + } +} \ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/requests-list/components/requests-list.component.ts b/src/Ombi/ClientApp/src/app/requests-list/components/requests-list.component.ts index 6489b6208..6cdd84af3 100644 --- a/src/Ombi/ClientApp/src/app/requests-list/components/requests-list.component.ts +++ b/src/Ombi/ClientApp/src/app/requests-list/components/requests-list.component.ts @@ -1,8 +1,40 @@ -import { Component } from "@angular/core"; +import { Component, ViewChild } from "@angular/core"; +import { MatBottomSheet } from "@angular/material/bottom-sheet"; +import { RequestOptionsComponent } from "./options/request-options.component"; +import { UpdateType } from "../models/UpdateType"; +import { MoviesGridComponent } from "./movies-grid/movies-grid.component"; @Component({ templateUrl: "./requests-list.component.html", styleUrls: ["./requests-list.component.scss"] }) export class RequestsListComponent { + + constructor(private bottomSheet: MatBottomSheet) { } + + public onOpenOptions(event: { request: any, filter: any, onChange: any }) { + const ref = this.bottomSheet.open(RequestOptionsComponent, { data: { id: event.request.id, type: event.request.requestType, canApprove: event.request.canApprove } }); + + ref.afterDismissed().subscribe((result) => { + if(!result) { + return; + } + if (result.type == UpdateType.Delete) { + event.filter(); + return; + } + if (result.type == UpdateType.Approve) { + // Need to do this here, as the status is calculated on the server + event.request.requestStatus = 'Common.ProcessingRequest'; + event.onChange(); + return; + } + if (result.type == UpdateType.Availability) { + // Need to do this here, as the status is calculated on the server + event.request.requestStatus = 'Common.Available'; + event.onChange(); + return; + } + }); + } } diff --git a/src/Ombi/ClientApp/src/app/requests-list/components/tv-grid/tv-grid.component.html b/src/Ombi/ClientApp/src/app/requests-list/components/tv-grid/tv-grid.component.html index f13a0feba..a612d5180 100644 --- a/src/Ombi/ClientApp/src/app/requests-list/components/tv-grid/tv-grid.component.html +++ b/src/Ombi/ClientApp/src/app/requests-list/components/tv-grid/tv-grid.component.html @@ -2,68 +2,80 @@ - - - 10 - 15 - 30 - 100 - - - +
+
+ + + + + +
+
+
+
+ + + 10 + 15 + 30 + 100 + + +
+
- - - - +
Series {{element.parentRequest.title}}
- - - - + + + + - - - - + + + - - + - + - - - + - +
{{'Common.PendingApproval' |translate}}
+
{{'Common.Available' | translate}}
+ + + - - - - + + + + + + + + + - - -
Requested By {{element.requestedUser.userAlias}} {{'Requests.RequestsTitle' | translate}} {{element.parentRequest.title}} Status - {{element.parentRequest.status}} - {{'Requests.RequestedBy' | translate}} {{element.requestedUser.userAlias}} Requested Date - {{element.requestedDate | amLocal | amDateFormat: 'LL'}} + {{'Requests.RequestDate' | translate}} + {{element.requestedDate | amLocal | amDateFormat: 'LL'}} Request Status + + {{'Requests.RequestStatus' | translate}}
{{'Common.ProcessingRequest' | translate}}
-
{{'Common.PendingApproval' | - translate}} -
-
{{'Common.NotRequested' | - translate}} -
-
- - {{'Requests.Status' | translate}} + {{element.parentRequest.status}} + + + +
+ + + - -
+ +
\ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/requests-list/components/tv-grid/tv-grid.component.ts b/src/Ombi/ClientApp/src/app/requests-list/components/tv-grid/tv-grid.component.ts index bf1e8069d..7617808a2 100644 --- a/src/Ombi/ClientApp/src/app/requests-list/components/tv-grid/tv-grid.component.ts +++ b/src/Ombi/ClientApp/src/app/requests-list/components/tv-grid/tv-grid.component.ts @@ -1,41 +1,87 @@ -import { Component, AfterViewInit, ViewChild } from "@angular/core"; +import { Component, AfterViewInit, ViewChild, Output, EventEmitter, ChangeDetectorRef, OnInit } from "@angular/core"; import { IRequestsViewModel, IChildRequests } from "../../../interfaces"; -import { MatPaginator, MatSort } from "@angular/material"; +import { MatPaginator } from "@angular/material/paginator"; +import { MatSort } from "@angular/material/sort"; import { merge, of as observableOf, Observable } from 'rxjs'; import { catchError, map, startWith, switchMap } from 'rxjs/operators'; import { RequestServiceV2 } from "../../../services/requestV2.service"; +import { AuthService } from "../../../auth/auth.service"; +import { StorageService } from "../../../shared/storage/storage-service"; +import { RequestFilterType } from "../../models/RequestFilterType"; @Component({ templateUrl: "./tv-grid.component.html", selector: "tv-grid", styleUrls: ["../requests-list.component.scss"] }) -export class TvGridComponent implements AfterViewInit { +export class TvGridComponent implements OnInit, AfterViewInit { public dataSource: IChildRequests[] = []; public resultsLength: number; public isLoadingResults = true; public displayedColumns: string[] = ['series', 'requestedBy', 'status', 'requestStatus', 'requestedDate','actions']; public gridCount: string = "15"; - public showUnavailableRequests: boolean; + public isAdmin: boolean; + public defaultSort: string = "requestedDate"; + public defaultOrder: string = "desc"; + public currentFilter: RequestFilterType = RequestFilterType.All; - @ViewChild(MatPaginator, {static: false}) paginator: MatPaginator; - @ViewChild(MatSort, {static: false}) sort: MatSort; + public RequestFilter = RequestFilterType; - constructor(private requestService: RequestServiceV2) { + private storageKey = "Tv_DefaultRequestListSort"; + private storageKeyOrder = "Tv_DefaultRequestListSortOrder"; + private storageKeyGridCount = "Tv_DefaultGridCount"; + private storageKeyCurrentFilter = "Tv_DefaultFilter"; + + @Output() public onOpenOptions = new EventEmitter<{request: any, filter: any, onChange: any}>(); + + @ViewChild(MatPaginator) paginator: MatPaginator; + @ViewChild(MatSort) sort: MatSort; + + constructor(private requestService: RequestServiceV2, private auth: AuthService, + private ref: ChangeDetectorRef, private storageService: StorageService) { } + public ngOnInit() { + this.isAdmin = this.auth.hasRole("admin") || this.auth.hasRole("poweruser"); + const defaultCount = this.storageService.get(this.storageKeyGridCount); + const defaultSort = this.storageService.get(this.storageKey); + const defaultOrder = this.storageService.get(this.storageKeyOrder); + const defaultFilter = +this.storageService.get(this.storageKeyCurrentFilter); + if (defaultSort) { + this.defaultSort = defaultSort; + } + if (defaultOrder) { + this.defaultOrder = defaultOrder; + } + if (defaultCount) { + this.gridCount = defaultCount; + } + if (defaultFilter) { + this.currentFilter = defaultFilter; + } + } + public async ngAfterViewInit() { + this.storageService.save(this.storageKeyGridCount, this.gridCount); + this.storageService.save(this.storageKeyCurrentFilter, (+this.currentFilter).toString()); + this.paginator.showFirstLastButtons = true; + // If the user changes the sort order, reset back to the first page. this.sort.sortChange.subscribe(() => this.paginator.pageIndex = 0); merge(this.sort.sortChange, this.paginator.page) .pipe( startWith({}), - switchMap(() => { + switchMap((value: any) => { this.isLoadingResults = true; + + if (value.active || value.direction) { + this.storageService.save(this.storageKey, value.active); + this.storageService.save(this.storageKeyOrder, value.direction); + } return this.loadData(); }), map((data: IRequestsViewModel) => { @@ -52,11 +98,35 @@ export class TvGridComponent implements AfterViewInit { ).subscribe(data => this.dataSource = data); } + public openOptions(request: IChildRequests) { + const filter = () => { this.dataSource = this.dataSource.filter((req) => { + return req.id !== request.id; + })}; + + const onChange = () => { + this.ref.detectChanges(); + }; + + this.onOpenOptions.emit({request: request, filter: filter, onChange}); + } + private loadData(): Observable> { - if(this.showUnavailableRequests) { - return this.requestService.getTvUnavailableRequests(+this.gridCount, this.paginator.pageIndex * +this.gridCount, this.sort.active, this.sort.direction); - } else { - return this.requestService.getTvRequests(+this.gridCount, this.paginator.pageIndex * +this.gridCount, this.sort.active, this.sort.direction); + switch(RequestFilterType[RequestFilterType[this.currentFilter]]) { + case RequestFilterType.All: + return this.requestService.getTvRequests(+this.gridCount, this.paginator.pageIndex * +this.gridCount, this.sort.active, this.sort.direction); + case RequestFilterType.Pending: + return this.requestService.getPendingTvRequests(+this.gridCount, this.paginator.pageIndex * +this.gridCount, this.sort.active, this.sort.direction); + case RequestFilterType.Available: + return this.requestService.getAvailableTvRequests(+this.gridCount, this.paginator.pageIndex * +this.gridCount, this.sort.active, this.sort.direction); + case RequestFilterType.Processing: + return this.requestService.getProcessingTvRequests(+this.gridCount, this.paginator.pageIndex * +this.gridCount, this.sort.active, this.sort.direction); + case RequestFilterType.Denied: + return this.requestService.getDeniedTvRequests(+this.gridCount, this.paginator.pageIndex * +this.gridCount, this.sort.active, this.sort.direction); } } + + public switchFilter(type: RequestFilterType) { + this.currentFilter = type; + this.ngAfterViewInit(); + } } diff --git a/src/Ombi/ClientApp/src/app/requests-list/models/RequestFilterType.ts b/src/Ombi/ClientApp/src/app/requests-list/models/RequestFilterType.ts new file mode 100644 index 000000000..6c39b07af --- /dev/null +++ b/src/Ombi/ClientApp/src/app/requests-list/models/RequestFilterType.ts @@ -0,0 +1,7 @@ +export enum RequestFilterType { + All, + Pending, + Processing, + Available, + Denied +} diff --git a/src/Ombi/ClientApp/src/app/requests-list/models/UpdateType.ts b/src/Ombi/ClientApp/src/app/requests-list/models/UpdateType.ts new file mode 100644 index 000000000..3a0f690db --- /dev/null +++ b/src/Ombi/ClientApp/src/app/requests-list/models/UpdateType.ts @@ -0,0 +1,5 @@ +export enum UpdateType { + Delete, + Approve, + Availability +} \ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/requests-list/requests-list.module.ts b/src/Ombi/ClientApp/src/app/requests-list/requests-list.module.ts index c6d7157c8..205cc2046 100644 --- a/src/Ombi/ClientApp/src/app/requests-list/requests-list.module.ts +++ b/src/Ombi/ClientApp/src/app/requests-list/requests-list.module.ts @@ -9,6 +9,7 @@ import { AuthGuard } from "../auth/auth.guard"; import * as fromComponents from './components'; import { RequestsListComponent } from "./components/requests-list.component"; +import { MatBottomSheetModule } from "@angular/material/bottom-sheet"; const routes: Routes = [ { path: "", component: RequestsListComponent, canActivate: [AuthGuard] }, @@ -18,6 +19,7 @@ const routes: Routes = [ RouterModule.forChild(routes), SharedModule, PipeModule, + MatBottomSheetModule ], declarations: [ ...fromComponents.components @@ -26,6 +28,7 @@ const routes: Routes = [ RouterModule, ], entryComponents: [ + ...fromComponents.entryComponents ], providers: [ ...fromComponents.providers diff --git a/src/Ombi/ClientApp/src/app/requests/movierequests.component.ts b/src/Ombi/ClientApp/src/app/requests/movierequests.component.ts index 69a2359cf..798600447 100644 --- a/src/Ombi/ClientApp/src/app/requests/movierequests.component.ts +++ b/src/Ombi/ClientApp/src/app/requests/movierequests.component.ts @@ -1,386 +1,386 @@ -import { PlatformLocation, APP_BASE_HREF } from "@angular/common"; -import { Component, Input, OnInit, Inject } from "@angular/core"; -import { DomSanitizer } from "@angular/platform-browser"; -import { Subject } from "rxjs"; -import { debounceTime, distinctUntilChanged } from "rxjs/operators"; - -import { AuthService } from "../auth/auth.service"; -import { FilterType, IFilter, IIssueCategory, IMovieRequests, IPagenator, IRadarrProfile, IRadarrRootFolder, OrderType } from "../interfaces"; -import { NotificationService, RadarrService, RequestService } from "../services"; - -@Component({ - selector: "movie-requests", - templateUrl: "./movierequests.component.html", -}) -export class MovieRequestsComponent implements OnInit { - public movieRequests: IMovieRequests[]; - public defaultPoster: string; - - public searchChanged: Subject = new Subject(); - public searchText: string; - - public isAdmin: boolean; // Also PowerUser - - public radarrProfiles: IRadarrProfile[]; - public radarrRootFolders: IRadarrRootFolder[]; - - @Input() public issueCategories: IIssueCategory[]; - @Input() public issuesEnabled: boolean; - public issuesBarVisible = false; - public issueRequest: IMovieRequests; - public issueProviderId: string; - public issueCategorySelected: IIssueCategory; - - public filterDisplay: boolean; - public filter: IFilter; - public filterType = FilterType; - - public orderType: OrderType = OrderType.RequestedDateDesc; - public OrderType = OrderType; - public denyDisplay: boolean; - public requestToDeny: IMovieRequests; - public rejectionReason: string; - - public totalMovies: number = 100; - public currentlyLoaded: number; - private amountToLoad: number; - private href: string; - - constructor( - private requestService: RequestService, - private auth: AuthService, - private notificationService: NotificationService, - private radarrService: RadarrService, - private sanitizer: DomSanitizer, - @Inject(APP_BASE_HREF) href:string) { - this.href = href; - this.searchChanged.pipe( - debounceTime(600), // Wait Xms after the last event before emitting last event - distinctUntilChanged(), // only emit if value is different from previous value - ).subscribe(x => { - this.searchText = x as string; - if (this.searchText === "") { - this.resetSearch(); - return; - } - this.requestService.searchMovieRequests(this.searchText) - .subscribe(m => { - this.setOverrides(m); - this.movieRequests = m; - }); - }); - this.defaultPoster = "../../../images/default_movie_poster.png"; - const base = this.href; - if (base) { - this.defaultPoster = "../../.." + base + "/images/default_movie_poster.png"; - } - } - - public ngOnInit() { - this.amountToLoad = 10; - this.currentlyLoaded = 10; - this.filter = { - availabilityFilter: FilterType.None, - statusFilter: FilterType.None, - }; - this.loadInit(); - this.isAdmin = this.auth.hasRole("admin") || this.auth.hasRole("poweruser"); - - } - - public paginate(event: IPagenator) { - const skipAmount = event.first; - this.loadRequests(this.amountToLoad, skipAmount); - } - - public search(text: any) { - this.searchChanged.next(text.target.value); - } - - public removeRequest(request: IMovieRequests) { - this.requestService.removeMovieRequest(request); - this.removeRequestFromUi(request); - this.loadRequests(this.amountToLoad, this.currentlyLoaded = 0); - } - - public changeAvailability(request: IMovieRequests, available: boolean) { - request.available = available; - - if (available) { - this.requestService.markMovieAvailable({ id: request.id }).subscribe(x => { - if (x.result) { - this.notificationService.success( - `${request.title} Is now available`); - } else { - this.notificationService.warning("Request Available", x.message ? x.message : x.errorMessage); - request.approved = false; - } - }); - } else { - this.requestService.markMovieUnavailable({ id: request.id }).subscribe(x => { - if (x.result) { - this.notificationService.success( - `${request.title} Is now unavailable`); - } else { - this.notificationService.warning("Request Available", x.message ? x.message : x.errorMessage); - request.approved = false; - } - }); - } - } - - public approve(request: IMovieRequests) { - request.approved = true; - this.approveRequest(request); - } - - public deny(request: IMovieRequests) { - this.requestToDeny = request; - this.denyDisplay = true; - } - - public denyRequest() { - this.requestService.denyMovie({ id: this.requestToDeny.id, reason: this.rejectionReason }) - .subscribe(x => { - this.denyDisplay = false; - if (x.result) { - this.notificationService.success( - `Request for ${this.requestToDeny.title} has been denied successfully`); - const index = this.movieRequests.indexOf(this.requestToDeny, 0); - if (index > -1) { - this.movieRequests[index].denied = true; - } - } else { - this.notificationService.warning("Request Denied", x.message ? x.message : x.errorMessage); - this.requestToDeny.denied = false; - } - }); - } - - public selectRootFolder(searchResult: IMovieRequests, rootFolderSelected: IRadarrRootFolder, event: any) { - event.preventDefault(); - searchResult.rootPathOverride = rootFolderSelected.id; - this.setOverride(searchResult); - this.updateRequest(searchResult); - } - - public selectQualityProfile(searchResult: IMovieRequests, profileSelected: IRadarrProfile, event: any) { - event.preventDefault(); - searchResult.qualityOverride = profileSelected.id; - this.setOverride(searchResult); - this.updateRequest(searchResult); - } - - public reportIssue(catId: IIssueCategory, req: IMovieRequests) { - this.issueRequest = req; - this.issueCategorySelected = catId; - this.issuesBarVisible = true; - this.issueProviderId = req.theMovieDbId.toString(); - } - - public ignore(event: any): void { - event.preventDefault(); - } - - public clearFilter(el: any) { - el = el.toElement || el.relatedTarget || el.target || el.srcElement; - - el = el.parentElement; - el = el.querySelectorAll("INPUT"); - for (el of el) { - el.checked = false; - el.parentElement.classList.remove("active"); - } - - this.filterDisplay = false; - this.filter.availabilityFilter = FilterType.None; - this.filter.statusFilter = FilterType.None; - - this.resetSearch(); - } - - public filterAvailability(filter: FilterType, el: any) { - this.filterActiveStyle(el); - this.filter.availabilityFilter = filter; - this.loadInit(); - } - - public filterStatus(filter: FilterType, el: any) { - this.filterActiveStyle(el); - this.filter.statusFilter = filter; - this.loadInit(); - } - - public setOrder(value: OrderType, el: any) { - el = el.toElement || el.relatedTarget || el.target || el.srcElement; - - const parent = el.parentElement; - const previousFilter = parent.querySelector(".active"); - - previousFilter.className = ""; - el.className = "active"; - - this.orderType = value; - - this.loadInit(); - } - - public subscribe(request: IMovieRequests) { - request.subscribed = true; - this.requestService.subscribeToMovie(request.id) - .subscribe(x => { - this.notificationService.success("Subscribed To Movie!"); - }); - } - - public unSubscribe(request: IMovieRequests) { - request.subscribed = false; - this.requestService.unSubscribeToMovie(request.id) - .subscribe(x => { - this.notificationService.success("Unsubscribed Movie!"); - }); - } - - public isRequestUser(request: IMovieRequests) { - if (request.requestedUser.userName === this.auth.claims().name) { - return true; - } - return false; - } - - private filterActiveStyle(el: any) { - el = el.toElement || el.relatedTarget || el.target || el.srcElement; - - el = el.parentElement; //gets radio div - el = el.parentElement; //gets form group div - el = el.parentElement; //gets status filter div - el = el.querySelectorAll("INPUT"); - for (el of el) { - if (el.checked) { - if (!el.parentElement.classList.contains("active")) { - el.parentElement.className += " active"; - } - } else { - el.parentElement.classList.remove("active"); - } - } - } - - private loadRequests(amountToLoad: number, currentlyLoaded: number) { - this.requestService.getMovieRequests(amountToLoad, currentlyLoaded, this.orderType, this.filter) - .subscribe(x => { - this.setOverrides(x.collection); - if (!this.movieRequests) { - this.movieRequests = []; - } - this.movieRequests = x.collection; - this.totalMovies = x.total; - this.currentlyLoaded = currentlyLoaded + amountToLoad; - }); - } - - private updateRequest(request: IMovieRequests) { - this.requestService.updateMovieRequest(request) - .subscribe(x => { - this.setOverride(x); - request = x; - }); - } - - private approveRequest(request: IMovieRequests) { - this.requestService.approveMovie({ id: request.id }) - .subscribe(x => { - request.approved = true; - if (x.result) { - this.notificationService.success( - `Request for ${request.title} has been approved successfully`); - } else { - this.notificationService.warning("Request Approved", x.message ? x.message : x.errorMessage); - request.approved = false; - } - }); - } - - private loadInit() { - this.requestService.getMovieRequests(this.amountToLoad, 0, this.orderType, this.filter) - .subscribe(x => { - this.movieRequests = x.collection; - this.totalMovies = x.total; - - this.movieRequests.forEach((req) => { - this.setBackground(req); - this.setPoster(req); - }); - if (this.isAdmin) { - this.radarrService.getQualityProfilesFromSettings().subscribe(c => { - this.radarrProfiles = c; - this.movieRequests.forEach((req) => this.setQualityOverrides(req)); - }); - this.radarrService.getRootFoldersFromSettings().subscribe(c => { - this.radarrRootFolders = c; - this.movieRequests.forEach((req) => this.setRootFolderOverrides(req)); - }); - } - }); - } - - private resetSearch() { - this.currentlyLoaded = 5; - this.loadInit(); - } - - private removeRequestFromUi(key: IMovieRequests) { - const index = this.movieRequests.indexOf(key, 0); - if (index > -1) { - this.movieRequests.splice(index, 1); - } - } - - private setOverrides(requests: IMovieRequests[]): void { - requests.forEach((req) => { - this.setOverride(req); - }); - } - - private setQualityOverrides(req: IMovieRequests): void { - if (this.radarrProfiles) { - const profile = this.radarrProfiles.filter((p) => { - return p.id === req.qualityOverride; - }); - if (profile.length > 0) { - req.qualityOverrideTitle = profile[0].name; - } - } - } - private setRootFolderOverrides(req: IMovieRequests): void { - if (this.radarrRootFolders) { - const path = this.radarrRootFolders.filter((folder) => { - return folder.id === req.rootPathOverride; - }); - if (path.length > 0) { - req.rootPathOverrideTitle = path[0].path; - } - } - } - - private setOverride(req: IMovieRequests): void { - this.setPoster(req); - this.setBackground(req); - this.setQualityOverrides(req); - this.setRootFolderOverrides(req); - } - - private setPoster(req: IMovieRequests): void { - if (req.posterPath === null) { - req.posterPath = this.defaultPoster; - } else { - req.posterPath = "https://image.tmdb.org/t/p/w300/" + req.posterPath; - } - } - - private setBackground(req: IMovieRequests): void { - req.backgroundPath = this.sanitizer.bypassSecurityTrustStyle - ("url(" + "https://image.tmdb.org/t/p/w1280" + req.background + ")"); - } - -} +// import { PlatformLocation, APP_BASE_HREF } from "@angular/common"; +// import { Component, Input, OnInit, Inject } from "@angular/core"; +// import { DomSanitizer } from "@angular/platform-browser"; +// import { Subject } from "rxjs"; +// import { debounceTime, distinctUntilChanged } from "rxjs/operators"; + +// import { AuthService } from "../auth/auth.service"; +// import { FilterType, IFilter, IIssueCategory, IMovieRequests, IPagenator, IRadarrProfile, IRadarrRootFolder, OrderType } from "../interfaces"; +// import { NotificationService, RadarrService, RequestService } from "../services"; + +// @Component({ +// selector: "movie-requests", +// templateUrl: "./movierequests.component.html", +// }) +// export class MovieRequestsComponent implements OnInit { +// public movieRequests: IMovieRequests[]; +// public defaultPoster: string; + +// public searchChanged: Subject = new Subject(); +// public searchText: string; + +// public isAdmin: boolean; // Also PowerUser + +// public radarrProfiles: IRadarrProfile[]; +// public radarrRootFolders: IRadarrRootFolder[]; + +// @Input() public issueCategories: IIssueCategory[]; +// @Input() public issuesEnabled: boolean; +// public issuesBarVisible = false; +// public issueRequest: IMovieRequests; +// public issueProviderId: string; +// public issueCategorySelected: IIssueCategory; + +// public filterDisplay: boolean; +// public filter: IFilter; +// public filterType = FilterType; + +// public orderType: OrderType = OrderType.RequestedDateDesc; +// public OrderType = OrderType; +// public denyDisplay: boolean; +// public requestToDeny: IMovieRequests; +// public rejectionReason: string; + +// public totalMovies: number = 100; +// public currentlyLoaded: number; +// private amountToLoad: number; +// private href: string; + +// constructor( +// private requestService: RequestService, +// private auth: AuthService, +// private notificationService: NotificationService, +// private radarrService: RadarrService, +// private sanitizer: DomSanitizer, +// @Inject(APP_BASE_HREF) href:string) { +// this.href = href; +// this.searchChanged.pipe( +// debounceTime(600), // Wait Xms after the last event before emitting last event +// distinctUntilChanged(), // only emit if value is different from previous value +// ).subscribe(x => { +// this.searchText = x as string; +// if (this.searchText === "") { +// this.resetSearch(); +// return; +// } +// this.requestService.searchMovieRequests(this.searchText) +// .subscribe(m => { +// this.setOverrides(m); +// this.movieRequests = m; +// }); +// }); +// this.defaultPoster = "../../../images/default_movie_poster.png"; +// const base = this.href; +// if (base) { +// this.defaultPoster = "../../.." + base + "/images/default_movie_poster.png"; +// } +// } + +// public ngOnInit() { +// this.amountToLoad = 10; +// this.currentlyLoaded = 10; +// this.filter = { +// availabilityFilter: FilterType.None, +// statusFilter: FilterType.None, +// }; +// this.loadInit(); +// this.isAdmin = this.auth.hasRole("admin") || this.auth.hasRole("poweruser"); + +// } + +// public paginate(event: IPagenator) { +// const skipAmount = event.first; +// this.loadRequests(this.amountToLoad, skipAmount); +// } + +// public search(text: any) { +// this.searchChanged.next(text.target.value); +// } + +// public removeRequest(request: IMovieRequests) { +// this.requestService.removeMovieRequest(request.id); +// this.removeRequestFromUi(request); +// this.loadRequests(this.amountToLoad, this.currentlyLoaded = 0); +// } + +// public changeAvailability(request: IMovieRequests, available: boolean) { +// request.available = available; + +// if (available) { +// this.requestService.markMovieAvailable({ id: request.id }).subscribe(x => { +// if (x.result) { +// this.notificationService.success( +// `${request.title} Is now available`); +// } else { +// this.notificationService.warning("Request Available", x.message ? x.message : x.errorMessage); +// request.approved = false; +// } +// }); +// } else { +// this.requestService.markMovieUnavailable({ id: request.id }).subscribe(x => { +// if (x.result) { +// this.notificationService.success( +// `${request.title} Is now unavailable`); +// } else { +// this.notificationService.warning("Request Available", x.message ? x.message : x.errorMessage); +// request.approved = false; +// } +// }); +// } +// } + +// public approve(request: IMovieRequests) { +// request.approved = true; +// this.approveRequest(request); +// } + +// public deny(request: IMovieRequests) { +// this.requestToDeny = request; +// this.denyDisplay = true; +// } + +// public denyRequest() { +// this.requestService.denyMovie({ id: this.requestToDeny.id, reason: this.rejectionReason }) +// .subscribe(x => { +// this.denyDisplay = false; +// if (x.result) { +// this.notificationService.success( +// `Request for ${this.requestToDeny.title} has been denied successfully`); +// const index = this.movieRequests.indexOf(this.requestToDeny, 0); +// if (index > -1) { +// this.movieRequests[index].denied = true; +// } +// } else { +// this.notificationService.warning("Request Denied", x.message ? x.message : x.errorMessage); +// this.requestToDeny.denied = false; +// } +// }); +// } + +// public selectRootFolder(searchResult: IMovieRequests, rootFolderSelected: IRadarrRootFolder, event: any) { +// event.preventDefault(); +// searchResult.rootPathOverride = rootFolderSelected.id; +// this.setOverride(searchResult); +// this.updateRequest(searchResult); +// } + +// public selectQualityProfile(searchResult: IMovieRequests, profileSelected: IRadarrProfile, event: any) { +// event.preventDefault(); +// searchResult.qualityOverride = profileSelected.id; +// this.setOverride(searchResult); +// this.updateRequest(searchResult); +// } + +// public reportIssue(catId: IIssueCategory, req: IMovieRequests) { +// this.issueRequest = req; +// this.issueCategorySelected = catId; +// this.issuesBarVisible = true; +// this.issueProviderId = req.theMovieDbId.toString(); +// } + +// public ignore(event: any): void { +// event.preventDefault(); +// } + +// public clearFilter(el: any) { +// el = el.toElement || el.relatedTarget || el.target || el.srcElement; + +// el = el.parentElement; +// el = el.querySelectorAll("INPUT"); +// for (el of el) { +// el.checked = false; +// el.parentElement.classList.remove("active"); +// } + +// this.filterDisplay = false; +// this.filter.availabilityFilter = FilterType.None; +// this.filter.statusFilter = FilterType.None; + +// this.resetSearch(); +// } + +// public filterAvailability(filter: FilterType, el: any) { +// this.filterActiveStyle(el); +// this.filter.availabilityFilter = filter; +// this.loadInit(); +// } + +// public filterStatus(filter: FilterType, el: any) { +// this.filterActiveStyle(el); +// this.filter.statusFilter = filter; +// this.loadInit(); +// } + +// public setOrder(value: OrderType, el: any) { +// el = el.toElement || el.relatedTarget || el.target || el.srcElement; + +// const parent = el.parentElement; +// const previousFilter = parent.querySelector(".active"); + +// previousFilter.className = ""; +// el.className = "active"; + +// this.orderType = value; + +// this.loadInit(); +// } + +// public subscribe(request: IMovieRequests) { +// request.subscribed = true; +// this.requestService.subscribeToMovie(request.id) +// .subscribe(x => { +// this.notificationService.success("Subscribed To Movie!"); +// }); +// } + +// public unSubscribe(request: IMovieRequests) { +// request.subscribed = false; +// this.requestService.unSubscribeToMovie(request.id) +// .subscribe(x => { +// this.notificationService.success("Unsubscribed Movie!"); +// }); +// } + +// public isRequestUser(request: IMovieRequests) { +// if (request.requestedUser.userName === this.auth.claims().name) { +// return true; +// } +// return false; +// } + +// private filterActiveStyle(el: any) { +// el = el.toElement || el.relatedTarget || el.target || el.srcElement; + +// el = el.parentElement; //gets radio div +// el = el.parentElement; //gets form group div +// el = el.parentElement; //gets status filter div +// el = el.querySelectorAll("INPUT"); +// for (el of el) { +// if (el.checked) { +// if (!el.parentElement.classList.contains("active")) { +// el.parentElement.className += " active"; +// } +// } else { +// el.parentElement.classList.remove("active"); +// } +// } +// } + +// private loadRequests(amountToLoad: number, currentlyLoaded: number) { +// this.requestService.getMovieRequests(amountToLoad, currentlyLoaded, this.orderType, this.filter) +// .subscribe(x => { +// this.setOverrides(x.collection); +// if (!this.movieRequests) { +// this.movieRequests = []; +// } +// this.movieRequests = x.collection; +// this.totalMovies = x.total; +// this.currentlyLoaded = currentlyLoaded + amountToLoad; +// }); +// } + +// private updateRequest(request: IMovieRequests) { +// this.requestService.updateMovieRequest(request) +// .subscribe(x => { +// this.setOverride(x); +// request = x; +// }); +// } + +// private approveRequest(request: IMovieRequests) { +// this.requestService.approveMovie({ id: request.id }) +// .subscribe(x => { +// request.approved = true; +// if (x.result) { +// this.notificationService.success( +// `Request for ${request.title} has been approved successfully`); +// } else { +// this.notificationService.warning("Request Approved", x.message ? x.message : x.errorMessage); +// request.approved = false; +// } +// }); +// } + +// private loadInit() { +// this.requestService.getMovieRequests(this.amountToLoad, 0, this.orderType, this.filter) +// .subscribe(x => { +// this.movieRequests = x.collection; +// this.totalMovies = x.total; + +// this.movieRequests.forEach((req) => { +// this.setBackground(req); +// this.setPoster(req); +// }); +// if (this.isAdmin) { +// this.radarrService.getQualityProfilesFromSettings().subscribe(c => { +// this.radarrProfiles = c; +// this.movieRequests.forEach((req) => this.setQualityOverrides(req)); +// }); +// this.radarrService.getRootFoldersFromSettings().subscribe(c => { +// this.radarrRootFolders = c; +// this.movieRequests.forEach((req) => this.setRootFolderOverrides(req)); +// }); +// } +// }); +// } + +// private resetSearch() { +// this.currentlyLoaded = 5; +// this.loadInit(); +// } + +// private removeRequestFromUi(key: IMovieRequests) { +// const index = this.movieRequests.indexOf(key, 0); +// if (index > -1) { +// this.movieRequests.splice(index, 1); +// } +// } + +// private setOverrides(requests: IMovieRequests[]): void { +// requests.forEach((req) => { +// this.setOverride(req); +// }); +// } + +// private setQualityOverrides(req: IMovieRequests): void { +// if (this.radarrProfiles) { +// const profile = this.radarrProfiles.filter((p) => { +// return p.id === req.qualityOverride; +// }); +// if (profile.length > 0) { +// req.qualityOverrideTitle = profile[0].name; +// } +// } +// } +// private setRootFolderOverrides(req: IMovieRequests): void { +// if (this.radarrRootFolders) { +// const path = this.radarrRootFolders.filter((folder) => { +// return folder.id === req.rootPathOverride; +// }); +// if (path.length > 0) { +// req.rootPathOverrideTitle = path[0].path; +// } +// } +// } + +// private setOverride(req: IMovieRequests): void { +// this.setPoster(req); +// this.setBackground(req); +// this.setQualityOverrides(req); +// this.setRootFolderOverrides(req); +// } + +// private setPoster(req: IMovieRequests): void { +// if (req.posterPath === null) { +// req.posterPath = this.defaultPoster; +// } else { +// req.posterPath = "https://image.tmdb.org/t/p/w300/" + req.posterPath; +// } +// } + +// private setBackground(req: IMovieRequests): void { +// req.backgroundPath = this.sanitizer.bypassSecurityTrustStyle +// ("url(" + "https://image.tmdb.org/t/p/w1280" + req.background + ")"); +// } + +// } diff --git a/src/Ombi/ClientApp/src/app/requests/music/musicrequests.component.ts b/src/Ombi/ClientApp/src/app/requests/music/musicrequests.component.ts index 54d0ca0c4..ccac00776 100644 --- a/src/Ombi/ClientApp/src/app/requests/music/musicrequests.component.ts +++ b/src/Ombi/ClientApp/src/app/requests/music/musicrequests.component.ts @@ -1,349 +1,349 @@ -import { PlatformLocation, APP_BASE_HREF } from "@angular/common"; -import { Component, Input, OnInit, Inject } from "@angular/core"; -import { DomSanitizer } from "@angular/platform-browser"; -import { Subject } from "rxjs"; -import { debounceTime, distinctUntilChanged } from "rxjs/operators"; - -import { AuthService } from "../../auth/auth.service"; -import { FilterType, IAlbumRequest, IFilter, IIssueCategory, IPagenator, OrderType } from "../../interfaces"; -import { NotificationService, RequestService } from "../../services"; - -@Component({ - selector: "music-requests", - templateUrl: "./musicrequests.component.html", -}) -export class MusicRequestsComponent implements OnInit { - public albumRequests: IAlbumRequest[]; - public defaultPoster: string; - - public searchChanged: Subject = new Subject(); - public searchText: string; - - public isAdmin: boolean; // Also PowerUser - - @Input() public issueCategories: IIssueCategory[]; - @Input() public issuesEnabled: boolean; - public issuesBarVisible = false; - public issueRequest: IAlbumRequest; - public issueProviderId: string; - public issueCategorySelected: IIssueCategory; - - public filterDisplay: boolean; - public filter: IFilter; - public filterType = FilterType; - - public orderType: OrderType = OrderType.RequestedDateDesc; - public OrderType = OrderType; - public denyDisplay: boolean; - public requestToDeny: IAlbumRequest; - public rejectionReason: string; - - public totalAlbums: number = 100; - public currentlyLoaded: number; - private amountToLoad: number; - private href: string; - - constructor( - private requestService: RequestService, - private auth: AuthService, - private notificationService: NotificationService, - private sanitizer: DomSanitizer, - @Inject(APP_BASE_HREF) href:string) { - this.href = href; - this.searchChanged.pipe( - debounceTime(600), // Wait Xms after the last event before emitting last event - distinctUntilChanged(), // only emit if value is different from previous value - ).subscribe(x => { - this.searchText = x as string; - if (this.searchText === "") { - this.resetSearch(); - return; - } - this.requestService.searchAlbumRequests(this.searchText) - .subscribe(m => { - this.setOverrides(m); - this.albumRequests = m; - }); - }); - this.defaultPoster = "../../../images/default-music-placeholder.png"; - const base = this.href; - if (base) { - this.defaultPoster = "../../.." + base + "/images/default-music-placeholder.png"; - } - } - - public ngOnInit() { - this.amountToLoad = 10; - this.currentlyLoaded = 10; - this.filter = { - availabilityFilter: FilterType.None, - statusFilter: FilterType.None, - }; - this.loadInit(); - this.isAdmin = this.auth.hasRole("admin") || this.auth.hasRole("poweruser"); - } - - public paginate(event: IPagenator) { - const skipAmount = event.first; - this.loadRequests(this.amountToLoad, skipAmount); - } - - public search(text: any) { - this.searchChanged.next(text.target.value); - } - - public async removeRequest(request: IAlbumRequest) { - await this.requestService.removeAlbumRequest(request).toPromise(); - this.removeRequestFromUi(request); - this.loadRequests(this.amountToLoad, this.currentlyLoaded = 0); - } - - public changeAvailability(request: IAlbumRequest, available: boolean) { - request.available = available; - - if (available) { - this.requestService.markAlbumAvailable({ id: request.id }).subscribe(x => { - if (x.result) { - this.notificationService.success( - `${request.title} Is now available`); - } else { - this.notificationService.warning("Request Available", x.message ? x.message : x.errorMessage); - request.approved = false; - } - }); - } else { - this.requestService.markAlbumUnavailable({ id: request.id }).subscribe(x => { - if (x.result) { - this.notificationService.success( - `${request.title} Is now unavailable`); - } else { - this.notificationService.warning("Request Available", x.message ? x.message : x.errorMessage); - request.approved = false; - } - }); - } - } - - public approve(request: IAlbumRequest) { - request.approved = true; - this.approveRequest(request); - } - - public deny(request: IAlbumRequest) { - this.requestToDeny = request; - this.denyDisplay = true; - } - - public denyRequest() { - this.requestService.denyAlbum({ id: this.requestToDeny.id, reason: this.rejectionReason }) - .subscribe(x => { - if (x.result) { - this.notificationService.success( - `Request for ${this.requestToDeny.title} has been denied successfully`); - } else { - this.notificationService.warning("Request Denied", x.message ? x.message : x.errorMessage); - this.requestToDeny.denied = false; - } - }); - } - - public reportIssue(catId: IIssueCategory, req: IAlbumRequest) { - this.issueRequest = req; - this.issueCategorySelected = catId; - this.issuesBarVisible = true; - this.issueProviderId = req.foreignAlbumId; - } - - public ignore(event: any): void { - event.preventDefault(); - } - - public clearFilter(el: any) { - el = el.toElement || el.relatedTarget || el.target || el.srcElement; - - el = el.parentElement; - el = el.querySelectorAll("INPUT"); - for (el of el) { - el.checked = false; - el.parentElement.classList.remove("active"); - } - - this.filterDisplay = false; - this.filter.availabilityFilter = FilterType.None; - this.filter.statusFilter = FilterType.None; - - this.resetSearch(); - } - - public filterAvailability(filter: FilterType, el: any) { - this.filterActiveStyle(el); - this.filter.availabilityFilter = filter; - this.loadInit(); - } - - public filterStatus(filter: FilterType, el: any) { - this.filterActiveStyle(el); - this.filter.statusFilter = filter; - this.loadInit(); - } - - public setOrder(value: OrderType, el: any) { - el = el.toElement || el.relatedTarget || el.target || el.srcElement; - - const parent = el.parentElement; - const previousFilter = parent.querySelector(".active"); - - previousFilter.className = ""; - el.className = "active"; - - this.orderType = value; - - this.loadInit(); - } - - public isRequestUser(request: IAlbumRequest) { - if (request.requestedUser.userName === this.auth.claims().name) { - return true; - } - return false; - } - - // public subscribe(request: IAlbumRequest) { - // request.subscribed = true; - // this.requestService.subscribeToMovie(request.id) - // .subscribe(x => { - // this.notificationService.success("Subscribed To Movie!"); - // }); - // } - - // public unSubscribe(request: IMovieRequests) { - // request.subscribed = false; - // this.requestService.unSubscribeToMovie(request.id) - // .subscribe(x => { - // this.notificationService.success("Unsubscribed Movie!"); - // }); - // } - - private filterActiveStyle(el: any) { - el = el.toElement || el.relatedTarget || el.target || el.srcElement; - - el = el.parentElement; //gets radio div - el = el.parentElement; //gets form group div - el = el.parentElement; //gets status filter div - el = el.querySelectorAll("INPUT"); - for (el of el) { - if (el.checked) { - if (!el.parentElement.classList.contains("active")) { - el.parentElement.className += " active"; - } - } else { - el.parentElement.classList.remove("active"); - } - } - } - - private loadRequests(amountToLoad: number, currentlyLoaded: number) { - this.requestService.getAlbumRequests(amountToLoad, currentlyLoaded, this.orderType, this.filter) - .subscribe(x => { - this.setOverrides(x.collection); - if (!this.albumRequests) { - this.albumRequests = []; - } - this.albumRequests = x.collection; - this.totalAlbums = x.total; - this.currentlyLoaded = currentlyLoaded + amountToLoad; - }); - } - - private approveRequest(request: IAlbumRequest) { - this.requestService.approveAlbum({ id: request.id }) - .subscribe(x => { - request.approved = true; - if (x.result) { - this.notificationService.success( - `Request for ${request.title} has been approved successfully`); - } else { - this.notificationService.warning("Request Approved", x.message ? x.message : x.errorMessage); - request.approved = false; - } - }); - } - - private loadInit() { - this.requestService.getAlbumRequests(this.amountToLoad, 0, this.orderType, this.filter) - .subscribe(x => { - this.albumRequests = x.collection; - this.totalAlbums = x.total; - - this.setOverrides(this.albumRequests); - - if (this.isAdmin) { - // this.radarrService.getQualityProfilesFromSettings().subscribe(c => { - // this.radarrProfiles = c; - // this.albumRequests.forEach((req) => this.setQualityOverrides(req)); - // }); - // this.radarrService.getRootFoldersFromSettings().subscribe(c => { - // this.radarrRootFolders = c; - // this.albumRequests.forEach((req) => this.setRootFolderOverrides(req)); - // }); - } - }); - } - - private resetSearch() { - this.currentlyLoaded = 5; - this.loadInit(); - } - - private removeRequestFromUi(key: IAlbumRequest) { - const index = this.albumRequests.indexOf(key, 0); - if (index > -1) { - this.albumRequests.splice(index, 1); - } - } - - private setOverrides(requests: IAlbumRequest[]): void { - requests.forEach((req) => { - this.setOverride(req); - }); - } - - // private setQualityOverrides(req: IMovieRequests): void { - // if (this.radarrProfiles) { - // const profile = this.radarrProfiles.filter((p) => { - // return p.id === req.qualityOverride; - // }); - // if (profile.length > 0) { - // req.qualityOverrideTitle = profile[0].name; - // } - // } - // } - // private setRootFolderOverrides(req: IMovieRequests): void { - // if (this.radarrRootFolders) { - // const path = this.radarrRootFolders.filter((folder) => { - // return folder.id === req.rootPathOverride; - // }); - // if (path.length > 0) { - // req.rootPathOverrideTitle = path[0].path; - // } - // } - // } - - private setOverride(req: IAlbumRequest): void { - this.setAlbumBackground(req); - // this.setQualityOverrides(req); - // this.setRootFolderOverrides(req); - } - private setAlbumBackground(req: IAlbumRequest) { - if (req.disk === null) { - if (req.cover === null) { - req.disk = this.defaultPoster; - } else { - req.disk = req.cover; - } - } - req.background = this.sanitizer.bypassSecurityTrustStyle - ("url(" + req.cover + ")"); - } - -} +// import { PlatformLocation, APP_BASE_HREF } from "@angular/common"; +// import { Component, Input, OnInit, Inject } from "@angular/core"; +// import { DomSanitizer } from "@angular/platform-browser"; +// import { Subject } from "rxjs"; +// import { debounceTime, distinctUntilChanged } from "rxjs/operators"; + +// import { AuthService } from "../../auth/auth.service"; +// import { FilterType, IAlbumRequest, IFilter, IIssueCategory, IPagenator, OrderType } from "../../interfaces"; +// import { NotificationService, RequestService } from "../../services"; + +// @Component({ +// selector: "music-requests", +// templateUrl: "./musicrequests.component.html", +// }) +// export class MusicRequestsComponent implements OnInit { +// public albumRequests: IAlbumRequest[]; +// public defaultPoster: string; + +// public searchChanged: Subject = new Subject(); +// public searchText: string; + +// public isAdmin: boolean; // Also PowerUser + +// @Input() public issueCategories: IIssueCategory[]; +// @Input() public issuesEnabled: boolean; +// public issuesBarVisible = false; +// public issueRequest: IAlbumRequest; +// public issueProviderId: string; +// public issueCategorySelected: IIssueCategory; + +// public filterDisplay: boolean; +// public filter: IFilter; +// public filterType = FilterType; + +// public orderType: OrderType = OrderType.RequestedDateDesc; +// public OrderType = OrderType; +// public denyDisplay: boolean; +// public requestToDeny: IAlbumRequest; +// public rejectionReason: string; + +// public totalAlbums: number = 100; +// public currentlyLoaded: number; +// private amountToLoad: number; +// private href: string; + +// constructor( +// private requestService: RequestService, +// private auth: AuthService, +// private notificationService: NotificationService, +// private sanitizer: DomSanitizer, +// @Inject(APP_BASE_HREF) href:string) { +// this.href = href; +// this.searchChanged.pipe( +// debounceTime(600), // Wait Xms after the last event before emitting last event +// distinctUntilChanged(), // only emit if value is different from previous value +// ).subscribe(x => { +// this.searchText = x as string; +// if (this.searchText === "") { +// this.resetSearch(); +// return; +// } +// this.requestService.searchAlbumRequests(this.searchText) +// .subscribe(m => { +// this.setOverrides(m); +// this.albumRequests = m; +// }); +// }); +// this.defaultPoster = "../../../images/default-music-placeholder.png"; +// const base = this.href; +// if (base) { +// this.defaultPoster = "../../.." + base + "/images/default-music-placeholder.png"; +// } +// } + +// public ngOnInit() { +// this.amountToLoad = 10; +// this.currentlyLoaded = 10; +// this.filter = { +// availabilityFilter: FilterType.None, +// statusFilter: FilterType.None, +// }; +// this.loadInit(); +// this.isAdmin = this.auth.hasRole("admin") || this.auth.hasRole("poweruser"); +// } + +// public paginate(event: IPagenator) { +// const skipAmount = event.first; +// this.loadRequests(this.amountToLoad, skipAmount); +// } + +// public search(text: any) { +// this.searchChanged.next(text.target.value); +// } + +// public async removeRequest(request: IAlbumRequest) { +// await this.requestService.removeAlbumRequest(request).toPromise(); +// this.removeRequestFromUi(request); +// this.loadRequests(this.amountToLoad, this.currentlyLoaded = 0); +// } + +// public changeAvailability(request: IAlbumRequest, available: boolean) { +// request.available = available; + +// if (available) { +// this.requestService.markAlbumAvailable({ id: request.id }).subscribe(x => { +// if (x.result) { +// this.notificationService.success( +// `${request.title} Is now available`); +// } else { +// this.notificationService.warning("Request Available", x.message ? x.message : x.errorMessage); +// request.approved = false; +// } +// }); +// } else { +// this.requestService.markAlbumUnavailable({ id: request.id }).subscribe(x => { +// if (x.result) { +// this.notificationService.success( +// `${request.title} Is now unavailable`); +// } else { +// this.notificationService.warning("Request Available", x.message ? x.message : x.errorMessage); +// request.approved = false; +// } +// }); +// } +// } + +// public approve(request: IAlbumRequest) { +// request.approved = true; +// this.approveRequest(request); +// } + +// public deny(request: IAlbumRequest) { +// this.requestToDeny = request; +// this.denyDisplay = true; +// } + +// public denyRequest() { +// this.requestService.denyAlbum({ id: this.requestToDeny.id, reason: this.rejectionReason }) +// .subscribe(x => { +// if (x.result) { +// this.notificationService.success( +// `Request for ${this.requestToDeny.title} has been denied successfully`); +// } else { +// this.notificationService.warning("Request Denied", x.message ? x.message : x.errorMessage); +// this.requestToDeny.denied = false; +// } +// }); +// } + +// public reportIssue(catId: IIssueCategory, req: IAlbumRequest) { +// this.issueRequest = req; +// this.issueCategorySelected = catId; +// this.issuesBarVisible = true; +// this.issueProviderId = req.foreignAlbumId; +// } + +// public ignore(event: any): void { +// event.preventDefault(); +// } + +// public clearFilter(el: any) { +// el = el.toElement || el.relatedTarget || el.target || el.srcElement; + +// el = el.parentElement; +// el = el.querySelectorAll("INPUT"); +// for (el of el) { +// el.checked = false; +// el.parentElement.classList.remove("active"); +// } + +// this.filterDisplay = false; +// this.filter.availabilityFilter = FilterType.None; +// this.filter.statusFilter = FilterType.None; + +// this.resetSearch(); +// } + +// public filterAvailability(filter: FilterType, el: any) { +// this.filterActiveStyle(el); +// this.filter.availabilityFilter = filter; +// this.loadInit(); +// } + +// public filterStatus(filter: FilterType, el: any) { +// this.filterActiveStyle(el); +// this.filter.statusFilter = filter; +// this.loadInit(); +// } + +// public setOrder(value: OrderType, el: any) { +// el = el.toElement || el.relatedTarget || el.target || el.srcElement; + +// const parent = el.parentElement; +// const previousFilter = parent.querySelector(".active"); + +// previousFilter.className = ""; +// el.className = "active"; + +// this.orderType = value; + +// this.loadInit(); +// } + +// public isRequestUser(request: IAlbumRequest) { +// if (request.requestedUser.userName === this.auth.claims().name) { +// return true; +// } +// return false; +// } + +// // public subscribe(request: IAlbumRequest) { +// // request.subscribed = true; +// // this.requestService.subscribeToMovie(request.id) +// // .subscribe(x => { +// // this.notificationService.success("Subscribed To Movie!"); +// // }); +// // } + +// // public unSubscribe(request: IMovieRequests) { +// // request.subscribed = false; +// // this.requestService.unSubscribeToMovie(request.id) +// // .subscribe(x => { +// // this.notificationService.success("Unsubscribed Movie!"); +// // }); +// // } + +// private filterActiveStyle(el: any) { +// el = el.toElement || el.relatedTarget || el.target || el.srcElement; + +// el = el.parentElement; //gets radio div +// el = el.parentElement; //gets form group div +// el = el.parentElement; //gets status filter div +// el = el.querySelectorAll("INPUT"); +// for (el of el) { +// if (el.checked) { +// if (!el.parentElement.classList.contains("active")) { +// el.parentElement.className += " active"; +// } +// } else { +// el.parentElement.classList.remove("active"); +// } +// } +// } + +// private loadRequests(amountToLoad: number, currentlyLoaded: number) { +// this.requestService.getAlbumRequests(amountToLoad, currentlyLoaded, this.orderType, this.filter) +// .subscribe(x => { +// this.setOverrides(x.collection); +// if (!this.albumRequests) { +// this.albumRequests = []; +// } +// this.albumRequests = x.collection; +// this.totalAlbums = x.total; +// this.currentlyLoaded = currentlyLoaded + amountToLoad; +// }); +// } + +// private approveRequest(request: IAlbumRequest) { +// this.requestService.approveAlbum({ id: request.id }) +// .subscribe(x => { +// request.approved = true; +// if (x.result) { +// this.notificationService.success( +// `Request for ${request.title} has been approved successfully`); +// } else { +// this.notificationService.warning("Request Approved", x.message ? x.message : x.errorMessage); +// request.approved = false; +// } +// }); +// } + +// private loadInit() { +// this.requestService.getAlbumRequests(this.amountToLoad, 0, this.orderType, this.filter) +// .subscribe(x => { +// this.albumRequests = x.collection; +// this.totalAlbums = x.total; + +// this.setOverrides(this.albumRequests); + +// if (this.isAdmin) { +// // this.radarrService.getQualityProfilesFromSettings().subscribe(c => { +// // this.radarrProfiles = c; +// // this.albumRequests.forEach((req) => this.setQualityOverrides(req)); +// // }); +// // this.radarrService.getRootFoldersFromSettings().subscribe(c => { +// // this.radarrRootFolders = c; +// // this.albumRequests.forEach((req) => this.setRootFolderOverrides(req)); +// // }); +// } +// }); +// } + +// private resetSearch() { +// this.currentlyLoaded = 5; +// this.loadInit(); +// } + +// private removeRequestFromUi(key: IAlbumRequest) { +// const index = this.albumRequests.indexOf(key, 0); +// if (index > -1) { +// this.albumRequests.splice(index, 1); +// } +// } + +// private setOverrides(requests: IAlbumRequest[]): void { +// requests.forEach((req) => { +// this.setOverride(req); +// }); +// } + +// // private setQualityOverrides(req: IMovieRequests): void { +// // if (this.radarrProfiles) { +// // const profile = this.radarrProfiles.filter((p) => { +// // return p.id === req.qualityOverride; +// // }); +// // if (profile.length > 0) { +// // req.qualityOverrideTitle = profile[0].name; +// // } +// // } +// // } +// // private setRootFolderOverrides(req: IMovieRequests): void { +// // if (this.radarrRootFolders) { +// // const path = this.radarrRootFolders.filter((folder) => { +// // return folder.id === req.rootPathOverride; +// // }); +// // if (path.length > 0) { +// // req.rootPathOverrideTitle = path[0].path; +// // } +// // } +// // } + +// private setOverride(req: IAlbumRequest): void { +// this.setAlbumBackground(req); +// // this.setQualityOverrides(req); +// // this.setRootFolderOverrides(req); +// } +// private setAlbumBackground(req: IAlbumRequest) { +// if (req.disk === null) { +// if (req.cover === null) { +// req.disk = this.defaultPoster; +// } else { +// req.disk = req.cover; +// } +// } +// req.background = this.sanitizer.bypassSecurityTrustStyle +// ("url(" + req.cover + ")"); +// } + +// } diff --git a/src/Ombi/ClientApp/src/app/requests/remainingrequests.component.ts b/src/Ombi/ClientApp/src/app/requests/remainingrequests.component.ts index b7d23a3df..abdf16c63 100644 --- a/src/Ombi/ClientApp/src/app/requests/remainingrequests.component.ts +++ b/src/Ombi/ClientApp/src/app/requests/remainingrequests.component.ts @@ -1,68 +1,68 @@ -import { IRemainingRequests } from "../interfaces/IRemainingRequests"; -import { RequestService } from "../services"; +// import { IRemainingRequests } from "../interfaces/IRemainingRequests"; +// import { RequestService } from "../services"; -import { Component, Input, OnInit } from "@angular/core"; -import { Observable } from "rxjs"; +// import { Component, Input, OnInit } from "@angular/core"; +// import { Observable } from "rxjs"; -@Component({ - selector: "remaining-requests", - templateUrl: "./remainingrequests.component.html", -}) +// @Component({ +// selector: "remaining-requests", +// templateUrl: "./remainingrequests.component.html", +// }) -export class RemainingRequestsComponent implements OnInit { - public remaining: IRemainingRequests; - @Input() public movie: boolean; - @Input() public tv: boolean; - @Input() public music: boolean; - public daysUntil: number; - public hoursUntil: number; - public minutesUntil: number; - @Input() public quotaRefreshEvents: Observable; +// export class RemainingRequestsComponent implements OnInit { +// public remaining: IRemainingRequests; +// @Input() public movie: boolean; +// @Input() public tv: boolean; +// @Input() public music: boolean; +// public daysUntil: number; +// public hoursUntil: number; +// public minutesUntil: number; +// @Input() public quotaRefreshEvents: Observable; - constructor(private requestService: RequestService) { - } +// constructor(private requestService: RequestService) { +// } - public ngOnInit() { - this.update(); +// public ngOnInit() { +// this.update(); - this.quotaRefreshEvents.subscribe(() => { - this.update(); - }); - } +// this.quotaRefreshEvents.subscribe(() => { +// this.update(); +// }); +// } - public update(): void { - const callback = (remaining => { - this.remaining = remaining; - if(this.remaining) { - this.calculateTime(); - } - }); - if (this.movie) { - this.requestService.getRemainingMovieRequests().subscribe(callback); - } - if(this.tv) { - this.requestService.getRemainingTvRequests().subscribe(callback); - } - if(this.music) { - this.requestService.getRemainingMusicRequests().subscribe(callback); - } - } +// public update(): void { +// const callback = (remaining => { +// this.remaining = remaining; +// if(this.remaining) { +// this.calculateTime(); +// } +// }); +// if (this.movie) { +// this.requestService.getRemainingMovieRequests().subscribe(callback); +// } +// if(this.tv) { +// this.requestService.getRemainingTvRequests().subscribe(callback); +// } +// if(this.music) { +// this.requestService.getRemainingMusicRequests().subscribe(callback); +// } +// } - private calculateTime(): void { - this.daysUntil = Math.ceil(this.daysUntilNextRequest()); - this.hoursUntil = Math.ceil(this.hoursUntilNextRequest()); - this.minutesUntil = Math.ceil(this.minutesUntilNextRequest()); - } +// private calculateTime(): void { +// this.daysUntil = Math.ceil(this.daysUntilNextRequest()); +// this.hoursUntil = Math.ceil(this.hoursUntilNextRequest()); +// this.minutesUntil = Math.ceil(this.minutesUntilNextRequest()); +// } - private daysUntilNextRequest(): number { - return (new Date(this.remaining.nextRequest).getTime() - new Date().getTime()) / 1000 / 60 / 60 / 24; - } +// private daysUntilNextRequest(): number { +// return (new Date(this.remaining.nextRequest).getTime() - new Date().getTime()) / 1000 / 60 / 60 / 24; +// } - private hoursUntilNextRequest(): number { - return (new Date(this.remaining.nextRequest).getTime() - new Date().getTime()) / 1000 / 60 / 60; - } +// private hoursUntilNextRequest(): number { +// return (new Date(this.remaining.nextRequest).getTime() - new Date().getTime()) / 1000 / 60 / 60; +// } - private minutesUntilNextRequest(): number { - return (new Date(this.remaining.nextRequest).getTime() - new Date().getTime()) / 1000 / 60; - } -} +// private minutesUntilNextRequest(): number { +// return (new Date(this.remaining.nextRequest).getTime() - new Date().getTime()) / 1000 / 60; +// } +// } diff --git a/src/Ombi/ClientApp/src/app/requests/remainingrequests.module.ts b/src/Ombi/ClientApp/src/app/requests/remainingrequests.module.ts index 411a94dfd..06a1d79de 100644 --- a/src/Ombi/ClientApp/src/app/requests/remainingrequests.module.ts +++ b/src/Ombi/ClientApp/src/app/requests/remainingrequests.module.ts @@ -2,18 +2,11 @@ import { FormsModule } from "@angular/forms"; import { RouterModule } from "@angular/router"; -import { NgbModule } from "@ng-bootstrap/ng-bootstrap"; - -import { SidebarModule, TooltipModule, TreeTableModule } from "primeng/primeng"; import { RequestService } from "../services"; @NgModule({ imports: [ - FormsModule, - NgbModule.forRoot(), - TreeTableModule, - SidebarModule, - TooltipModule, + FormsModule ], declarations: [ ], diff --git a/src/Ombi/ClientApp/src/app/requests/request.component.ts b/src/Ombi/ClientApp/src/app/requests/request.component.ts index b318d619b..ee92a740e 100644 --- a/src/Ombi/ClientApp/src/app/requests/request.component.ts +++ b/src/Ombi/ClientApp/src/app/requests/request.component.ts @@ -1,48 +1,48 @@  -import { Component, OnInit } from "@angular/core"; - -import { IIssueCategory } from "../interfaces"; -import { IssuesService, SettingsService } from "../services"; - -@Component({ - templateUrl: "./request.component.html", -}) -export class RequestComponent implements OnInit { - - public showMovie = true; - public showTv = false; - public showAlbums = false; - - public issueCategories: IIssueCategory[]; - public issuesEnabled = false; - public musicEnabled: boolean; - - constructor(private issuesService: IssuesService, - private settingsService: SettingsService) { - - } - - public ngOnInit(): void { - this.issuesService.getCategories().subscribe(x => this.issueCategories = x); - this.settingsService.lidarrEnabled().subscribe(x => this.musicEnabled = x); - this.settingsService.getIssueSettings().subscribe(x => this.issuesEnabled = x.enabled); - } - - public selectMovieTab() { - this.showMovie = true; - this.showTv = false; - this.showAlbums = false; - } - - public selectTvTab() { - this.showMovie = false; - this.showTv = true; - this.showAlbums = false; - } - - public selectMusicTab() { - this.showMovie = false; - this.showTv = false; - this.showAlbums = true; - } -} +// import { Component, OnInit } from "@angular/core"; + +// import { IIssueCategory } from "../interfaces"; +// import { IssuesService, SettingsService } from "../services"; + +// @Component({ +// templateUrl: "./request.component.html", +// }) +// export class RequestComponent implements OnInit { + +// public showMovie = true; +// public showTv = false; +// public showAlbums = false; + +// public issueCategories: IIssueCategory[]; +// public issuesEnabled = false; +// public musicEnabled: boolean; + +// constructor(private issuesService: IssuesService, +// private settingsService: SettingsService) { + +// } + +// public ngOnInit(): void { +// this.issuesService.getCategories().subscribe(x => this.issueCategories = x); +// this.settingsService.lidarrEnabled().subscribe(x => this.musicEnabled = x); +// this.settingsService.getIssueSettings().subscribe(x => this.issuesEnabled = x.enabled); +// } + +// public selectMovieTab() { +// this.showMovie = true; +// this.showTv = false; +// this.showAlbums = false; +// } + +// public selectTvTab() { +// this.showMovie = false; +// this.showTv = true; +// this.showAlbums = false; +// } + +// public selectMusicTab() { +// this.showMovie = false; +// this.showTv = false; +// this.showAlbums = true; +// } +// } diff --git a/src/Ombi/ClientApp/src/app/requests/requests.module.ts b/src/Ombi/ClientApp/src/app/requests/requests.module.ts index 63d7117f5..bb491d5ff 100644 --- a/src/Ombi/ClientApp/src/app/requests/requests.module.ts +++ b/src/Ombi/ClientApp/src/app/requests/requests.module.ts @@ -1,60 +1,49 @@ -import { NgModule } from "@angular/core"; -import { RouterModule, Routes } from "@angular/router"; - -import { NgbModule } from "@ng-bootstrap/ng-bootstrap"; -import { OrderModule } from "ngx-order-pipe"; - -import { InfiniteScrollModule } from "ngx-infinite-scroll"; - -import { ButtonModule, DialogModule, PaginatorModule } from "primeng/primeng"; -import { MovieRequestsComponent } from "./movierequests.component"; -import { MusicRequestsComponent } from "./music/musicrequests.component"; -// Request -import { RequestComponent } from "./request.component"; -import { TvRequestChildrenComponent } from "./tvrequest-children.component"; -import { TvRequestsComponent } from "./tvrequests.component"; - -import { SidebarModule, TooltipModule, TreeTableModule } from "primeng/primeng"; - -import { IdentityService, RadarrService, RequestService, SonarrService } from "../services"; - -import { AuthGuard } from "../auth/auth.guard"; - -import { SharedModule } from "../shared/shared.module"; - -const routes: Routes = [ - { path: "", component: RequestComponent, canActivate: [AuthGuard] }, -]; -@NgModule({ - imports: [ - RouterModule.forChild(routes), - NgbModule.forRoot(), - InfiniteScrollModule, - ButtonModule, - DialogModule, - TreeTableModule, - SharedModule, - SidebarModule, - OrderModule, - PaginatorModule, - TooltipModule, - ], - declarations: [ - RequestComponent, - MovieRequestsComponent, - TvRequestsComponent, - TvRequestChildrenComponent, - MusicRequestsComponent, - ], - exports: [ - RouterModule, - ], - providers: [ - IdentityService, - RequestService, - RadarrService, - SonarrService, - ], - -}) -export class RequestsModule { } +// import { NgModule } from "@angular/core"; +// import { RouterModule, Routes } from "@angular/router"; +// import { OrderModule } from "ngx-order-pipe"; + +// import { InfiniteScrollModule } from "ngx-infinite-scroll"; + +// import { MovieRequestsComponent } from "./movierequests.component"; +// import { MusicRequestsComponent } from "./music/musicrequests.component"; +// // Request +// import { RequestComponent } from "./request.component"; +// import { TvRequestChildrenComponent } from "./tvrequest-children.component"; +// import { TvRequestsComponent } from "./tvrequests.component"; + + +// import { IdentityService, RadarrService, RequestService, SonarrService } from "../services"; + +// import { AuthGuard } from "../auth/auth.guard"; + +// import { SharedModule } from "../shared/shared.module"; + +// const routes: Routes = [ +// { path: "", component: RequestComponent, canActivate: [AuthGuard] }, +// ]; +// @NgModule({ +// imports: [ +// RouterModule.forChild(routes), +// InfiniteScrollModule, +// SharedModule, +// OrderModule, +// ], +// declarations: [ +// RequestComponent, +// MovieRequestsComponent, +// TvRequestsComponent, +// TvRequestChildrenComponent, +// MusicRequestsComponent, +// ], +// exports: [ +// RouterModule, +// ], +// providers: [ +// IdentityService, +// RequestService, +// RadarrService, +// SonarrService, +// ], + +// }) +// export class RequestsModule { } diff --git a/src/Ombi/ClientApp/src/app/requests/tvrequest-children.component.ts b/src/Ombi/ClientApp/src/app/requests/tvrequest-children.component.ts index 2c2145fb9..fec1222de 100644 --- a/src/Ombi/ClientApp/src/app/requests/tvrequest-children.component.ts +++ b/src/Ombi/ClientApp/src/app/requests/tvrequest-children.component.ts @@ -1,138 +1,138 @@ -import { Component, EventEmitter, Input, Output } from "@angular/core"; -import { IChildRequests } from "../interfaces"; +// import { Component, EventEmitter, Input, Output } from "@angular/core"; +// import { IChildRequests } from "../interfaces"; -import { NotificationService, RequestService } from "../services"; +// import { NotificationService, RequestService } from "../services"; -@Component({ - selector: "tvrequests-children", - templateUrl: "./tvrequest-children.component.html", -}) -export class TvRequestChildrenComponent { - @Input() public childRequests: IChildRequests[]; - @Input() public isAdmin: boolean; - @Input() public currentUser: string; +// @Component({ +// selector: "tvrequests-children", +// templateUrl: "./tvrequest-children.component.html", +// }) +// export class TvRequestChildrenComponent { +// @Input() public childRequests: IChildRequests[]; +// @Input() public isAdmin: boolean; +// @Input() public currentUser: string; - public denyDisplay: boolean; - public requestToDeny: IChildRequests; - public rejectionReason: string; +// public denyDisplay: boolean; +// public requestToDeny: IChildRequests; +// public rejectionReason: string; - @Output() public requestDeleted = new EventEmitter(); +// @Output() public requestDeleted = new EventEmitter(); - constructor(private requestService: RequestService, - private notificationService: NotificationService) { } +// constructor(private requestService: RequestService, +// private notificationService: NotificationService) { } - public removeRequest(request: IChildRequests) { - this.requestService.deleteChild(request) - .subscribe(x => { - this.removeRequestFromUi(request); - this.requestDeleted.emit(request.id); - }); - } +// public removeRequest(request: IChildRequests) { +// this.requestService.deleteChild(request.id) +// .subscribe(x => { +// this.removeRequestFromUi(request); +// this.requestDeleted.emit(request.id); +// }); +// } - public changeAvailability(request: IChildRequests, available: boolean) { - request.available = available; - request.seasonRequests.forEach((season) => { - season.episodes.forEach((ep) => { - ep.available = available; - }); - }); - if (available) { - this.requestService.markTvAvailable({ id: request.id }).subscribe(x => { - if (x.result) { - this.notificationService.success( - `This request is now available`); - } else { - this.notificationService.warning("Request Available", x.message ? x.message : x.errorMessage); - request.approved = false; - } - }); - } else { - this.requestService.markTvUnavailable({ id: request.id }).subscribe(x => { - if (x.result) { - this.notificationService.success( - `This request is now unavailable`); - } else { - this.notificationService.warning("Request Available", x.message ? x.message : x.errorMessage); - request.approved = false; - } - }); - } - } +// public changeAvailability(request: IChildRequests, available: boolean) { +// request.available = available; +// request.seasonRequests.forEach((season) => { +// season.episodes.forEach((ep) => { +// ep.available = available; +// }); +// }); +// if (available) { +// this.requestService.markTvAvailable({ id: request.id }).subscribe(x => { +// if (x.result) { +// this.notificationService.success( +// `This request is now available`); +// } else { +// this.notificationService.warning("Request Available", x.message ? x.message : x.errorMessage); +// request.approved = false; +// } +// }); +// } else { +// this.requestService.markTvUnavailable({ id: request.id }).subscribe(x => { +// if (x.result) { +// this.notificationService.success( +// `This request is now unavailable`); +// } else { +// this.notificationService.warning("Request Available", x.message ? x.message : x.errorMessage); +// request.approved = false; +// } +// }); +// } +// } - public deny(request: IChildRequests) { - request.denied = true; - this.requestToDeny = request; - this.denyDisplay = true; +// public deny(request: IChildRequests) { +// request.denied = true; +// this.requestToDeny = request; +// this.denyDisplay = true; - request.seasonRequests.forEach((season) => { - season.episodes.forEach((ep) => { - ep.approved = false; - }); - }); - } +// request.seasonRequests.forEach((season) => { +// season.episodes.forEach((ep) => { +// ep.approved = false; +// }); +// }); +// } - public denyRequest() { - this.requestService.denyChild({ id: this.requestToDeny.id, reason: this.rejectionReason }) - .subscribe(x => { - this.denyDisplay = false; - if (x.result) { - this.notificationService.success( - `Request has been denied successfully`); - } else { - this.notificationService.warning("Request Denied", x.message ? x.message : x.errorMessage); - this.requestToDeny.approved = false; - } - }); - } +// public denyRequest() { +// this.requestService.denyChild({ id: this.requestToDeny.id, reason: this.rejectionReason }) +// .subscribe(x => { +// this.denyDisplay = false; +// if (x.result) { +// this.notificationService.success( +// `Request has been denied successfully`); +// } else { +// this.notificationService.warning("Request Denied", x.message ? x.message : x.errorMessage); +// this.requestToDeny.approved = false; +// } +// }); +// } - public approve(request: IChildRequests) { - request.approved = true; - request.denied = false; - request.seasonRequests.forEach((season) => { - season.episodes.forEach((ep) => { - ep.approved = true; - }); - }); - this.requestService.approveChild({ id: request.id }) - .subscribe(x => { - if (x.result) { - this.notificationService.success( - `Request has been approved successfully`); - } else { - this.notificationService.warning("Request Approved", x.message ? x.message : x.errorMessage); - request.approved = false; - } - }); - } +// public approve(request: IChildRequests) { +// request.approved = true; +// request.denied = false; +// request.seasonRequests.forEach((season) => { +// season.episodes.forEach((ep) => { +// ep.approved = true; +// }); +// }); +// this.requestService.approveChild({ id: request.id }) +// .subscribe(x => { +// if (x.result) { +// this.notificationService.success( +// `Request has been approved successfully`); +// } else { +// this.notificationService.warning("Request Approved", x.message ? x.message : x.errorMessage); +// request.approved = false; +// } +// }); +// } - public subscribe(request: IChildRequests) { - request.subscribed = true; - this.requestService.subscribeToTv(request.id) - .subscribe(x => { - this.notificationService.success("Subscribed To TV Show!"); - }); - } +// public subscribe(request: IChildRequests) { +// request.subscribed = true; +// this.requestService.subscribeToTv(request.id) +// .subscribe(x => { +// this.notificationService.success("Subscribed To TV Show!"); +// }); +// } - public unSubscribe(request: IChildRequests) { - request.subscribed = false; - this.requestService.unSubscribeToTv(request.id) - .subscribe(x => { - this.notificationService.success("Unsubscribed TV Show!"); - }); - } +// public unSubscribe(request: IChildRequests) { +// request.subscribed = false; +// this.requestService.unSubscribeToTv(request.id) +// .subscribe(x => { +// this.notificationService.success("Unsubscribed TV Show!"); +// }); +// } - public isRequestUser(request: IChildRequests) { - if (request.requestedUser.userName === this.currentUser) { - return true; - } - return false; - } +// public isRequestUser(request: IChildRequests) { +// if (request.requestedUser.userName === this.currentUser) { +// return true; +// } +// return false; +// } - private removeRequestFromUi(key: IChildRequests) { - const index = this.childRequests.indexOf(key, 0); - if (index > -1) { - this.childRequests.splice(index, 1); - } - } +// private removeRequestFromUi(key: IChildRequests) { +// const index = this.childRequests.indexOf(key, 0); +// if (index > -1) { +// this.childRequests.splice(index, 1); +// } +// } -} +// } diff --git a/src/Ombi/ClientApp/src/app/requests/tvrequests.component.html b/src/Ombi/ClientApp/src/app/requests/tvrequests.component.html index 7c5e13479..889b485d7 100644 --- a/src/Ombi/ClientApp/src/app/requests/tvrequests.component.html +++ b/src/Ombi/ClientApp/src/app/requests/tvrequests.component.html @@ -6,109 +6,107 @@
-
- -
-
-
-
+
+ +
+
+
+
-
+
- poster + poster -
+
-
- -
-
- Status: - {{node.status}} -
+
+ +
+
+ Status: + {{node.status}} +
-
Release Date: {{node.releaseDate | amLocal | amDateFormat: 'LL'}}
-
-
{{ 'Requests.QualityOverride' | translate }} - {{node.qualityOverrideTitle}} -
-
{{ 'Requests.RootFolderOverride' | translate }} - {{node.rootPathOverrideTitle}} -
+
Release Date: {{node.releaseDate | amLocal | amDateFormat: 'LL'}}
+
+
{{ 'Requests.QualityOverride' | translate }} + {{node.qualityOverrideTitle}} +
+
{{ 'Requests.RootFolderOverride' | translate }} + {{node.rootPathOverrideTitle}}
- -
-
-
+
+ + -
- -
- - - -
+ +
- -
- - - -
- +
- + +
- -
- -
- +
+ +
+ +
+

-
+
- \ No newline at end of file + \ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/requests/tvrequests.component.ts b/src/Ombi/ClientApp/src/app/requests/tvrequests.component.ts index 4ecf1e6ac..1386efd1f 100644 --- a/src/Ombi/ClientApp/src/app/requests/tvrequests.component.ts +++ b/src/Ombi/ClientApp/src/app/requests/tvrequests.component.ts @@ -1,226 +1,226 @@ -import { PlatformLocation, APP_BASE_HREF } from "@angular/common"; -import { Component, Input, OnInit, Inject } from "@angular/core"; -import { DomSanitizer } from "@angular/platform-browser"; -import { Subject } from "rxjs"; -import { debounceTime, distinctUntilChanged } from "rxjs/operators"; - -import { AuthService } from "../auth/auth.service"; -import { FilterType, IIssueCategory, IPagenator, IRequestsViewModel, ISonarrProfile, ISonarrRootFolder, ITvRequests, OrderType } from "../interfaces"; -import { NotificationService, RequestService, SonarrService } from "../services"; -import { ImageService } from "../services/image.service"; - -@Component({ - selector: "tv-requests", - templateUrl: "./tvrequests.component.html", - styleUrls: ["./tvrequests.component.scss"], -}) -export class TvRequestsComponent implements OnInit { - - public tvRequests: IRequestsViewModel; - public searchChanged = new Subject(); - public searchText: string; - public isAdmin: boolean; - public currentUser: string; - public showChildDialogue = false; // This is for the child modal popup - public selectedSeason: ITvRequests; - public defaultPoster: string; - - @Input() public issueCategories: IIssueCategory[]; - @Input() public issuesEnabled: boolean; - public issueProviderId: string; - public issuesBarVisible = false; - public issueRequest: ITvRequests; - public issueCategorySelected: IIssueCategory; - - public sonarrProfiles: ISonarrProfile[] = []; - public sonarrRootFolders: ISonarrRootFolder[] = []; - - public totalTv: number = 100; - private currentlyLoaded: number; - private amountToLoad: number; - private href: string; - - constructor( - private requestService: RequestService, - private auth: AuthService, - private sanitizer: DomSanitizer, - private imageService: ImageService, - private sonarrService: SonarrService, - private notificationService: NotificationService, - @Inject(APP_BASE_HREF) href:string) { - this.href= href; - this.isAdmin = this.auth.hasRole("admin") || this.auth.hasRole("poweruser"); - this.currentUser = this.auth.claims().name; - if (this.isAdmin) { - this.sonarrService.getQualityProfilesWithoutSettings() - .subscribe(x => this.sonarrProfiles = x); +// import { PlatformLocation, APP_BASE_HREF } from "@angular/common"; +// import { Component, Input, OnInit, Inject } from "@angular/core"; +// import { DomSanitizer } from "@angular/platform-browser"; +// import { Subject } from "rxjs"; +// import { debounceTime, distinctUntilChanged } from "rxjs/operators"; + +// import { AuthService } from "../auth/auth.service"; +// import { FilterType, IIssueCategory, IPagenator, IRequestsViewModel, ISonarrProfile, ISonarrRootFolder, ITvRequests, OrderType } from "../interfaces"; +// import { NotificationService, RequestService, SonarrService } from "../services"; +// import { ImageService } from "../services/image.service"; + +// @Component({ +// selector: "tv-requests", +// templateUrl: "./tvrequests.component.html", +// styleUrls: ["./tvrequests.component.scss"], +// }) +// export class TvRequestsComponent implements OnInit { + +// public tvRequests: IRequestsViewModel; +// public searchChanged = new Subject(); +// public searchText: string; +// public isAdmin: boolean; +// public currentUser: string; +// public showChildDialogue = false; // This is for the child modal popup +// public selectedSeason: ITvRequests; +// public defaultPoster: string; + +// @Input() public issueCategories: IIssueCategory[]; +// @Input() public issuesEnabled: boolean; +// public issueProviderId: string; +// public issuesBarVisible = false; +// public issueRequest: ITvRequests; +// public issueCategorySelected: IIssueCategory; + +// public sonarrProfiles: ISonarrProfile[] = []; +// public sonarrRootFolders: ISonarrRootFolder[] = []; + +// public totalTv: number = 100; +// private currentlyLoaded: number; +// private amountToLoad: number; +// private href: string; + +// constructor( +// private requestService: RequestService, +// private auth: AuthService, +// private sanitizer: DomSanitizer, +// private imageService: ImageService, +// private sonarrService: SonarrService, +// private notificationService: NotificationService, +// @Inject(APP_BASE_HREF) href:string) { +// this.href= href; +// this.isAdmin = this.auth.hasRole("admin") || this.auth.hasRole("poweruser"); +// this.currentUser = this.auth.claims().name; +// if (this.isAdmin) { +// this.sonarrService.getQualityProfilesWithoutSettings() +// .subscribe(x => this.sonarrProfiles = x); - this.sonarrService.getRootFoldersWithoutSettings() - .subscribe(x => this.sonarrRootFolders = x); - } - } - - public openClosestTab(node: ITvRequests,el: any) { - el.preventDefault(); - node.open = !node.open; - } - - public ngOnInit() { - this.amountToLoad = 10; - this.currentlyLoaded = 10; - this.tvRequests = {collection:[], total:0}; - - this.searchChanged.pipe( - debounceTime(600), // Wait Xms after the last event before emitting last event - distinctUntilChanged(), // only emit if value is different from previous value - ).subscribe(x => { - this.searchText = x as string; - if (this.searchText === "") { - this.resetSearch(); - return; - } - this.requestService.searchTvRequests(this.searchText) - .subscribe(m => { - this.tvRequests.collection = m; - this.tvRequests.collection.forEach((val) => this.loadBackdrop(val)); - this.tvRequests.collection.forEach((val) => this.setOverride(val)); - }); - }); - this.defaultPoster = "../../../images/default_tv_poster.png"; - const base = this.href; - if (base) { - this.defaultPoster = "../../.." + base + "/images/default_tv_poster.png"; - } - - this.loadInit(); - } - - public paginate(event: IPagenator) { - const skipAmount = event.first; - - this.requestService.getTvRequests(this.amountToLoad, skipAmount, OrderType.RequestedDateDesc, FilterType.None, FilterType.None) - .subscribe(x => { - this.tvRequests = x; - this.currentlyLoaded = this.currentlyLoaded + this.amountToLoad; - }); - } - - public search(text: any) { - this.searchChanged.next(text.target.value); - } - - public showChildren(request: ITvRequests) { - this.selectedSeason = request; - this.showChildDialogue = true; - } - - public childRequestDeleted(childId: number): void { - // Refresh the UI, hackly way around reloading the data - this.ngOnInit(); - } - - public selectRootFolder(searchResult: ITvRequests, rootFolderSelected: ISonarrRootFolder, event: any) { - event.preventDefault(); - searchResult.rootFolder = rootFolderSelected.id; - this.setOverride(searchResult); - this.setRootFolder(searchResult); - } - - public selectQualityProfile(searchResult: ITvRequests, profileSelected: ISonarrProfile, event: any) { - event.preventDefault(); - searchResult.qualityOverride = profileSelected.id; - this.setOverride(searchResult); - this.setQualityProfile(searchResult); - } - - public reportIssue(catId: IIssueCategory, req: ITvRequests) { - this.issueRequest = req; - this.issueCategorySelected = catId; - this.issuesBarVisible = true; - this.issueProviderId = req.id.toString(); - } - - private setOverride(req: ITvRequests): void { - this.setQualityOverrides(req); - this.setRootFolderOverrides(req); - } - - private setQualityProfile(req: ITvRequests) { - this.requestService.setQualityProfile(req.id, req.qualityOverride).subscribe(x => { - if(x) { - this.notificationService.success("Quality profile updated"); - } else { - this.notificationService.error("Could not update the quality profile"); - } - }); - } - - private setRootFolder(req: ITvRequests) { - this.requestService.setRootFolder(req.id, req.rootFolder).subscribe(x => { - if(x) { - this.notificationService.success("Quality profile updated"); - } else { - this.notificationService.error("Could not update the quality profile"); - } - }); - } - - private setQualityOverrides(req: ITvRequests): void { - if (this.sonarrProfiles) { - const profile = this.sonarrProfiles.filter((p) => { - return p.id === req.qualityOverride; - }); - if (profile.length > 0) { - req.qualityOverrideTitle = profile[0].name; - } - } - } - private setRootFolderOverrides(req: ITvRequests): void { - if (this.sonarrRootFolders) { - const path = this.sonarrRootFolders.filter((folder) => { - return folder.id === req.rootFolder; - }); - if (path.length > 0) { - req.rootPathOverrideTitle = path[0].path; - } - } - } - - private loadInit() { - this.requestService.getTotalTv().subscribe(x => this.totalTv = x); - this.requestService.getTvRequests(this.amountToLoad, 0, OrderType.RequestedDateDesc, FilterType.None, FilterType.None) - .subscribe(x => { - this.tvRequests = x; - this.tvRequests.collection.forEach((val, index) => { - this.setDefaults(val); - this.loadBackdrop(val); - this.setOverride(val); - }); - }); - } - - private resetSearch() { - this.currentlyLoaded = 5; - this.loadInit(); - } - - private setDefaults(val: ITvRequests) { - if (val.posterPath === null) { - val.posterPath = this.defaultPoster; - } - } - - private loadBackdrop(val: ITvRequests): void { - if (val.background != null) { - val.background = this.sanitizer.bypassSecurityTrustStyle - ("url(https://image.tmdb.org/t/p/w1280" + val.background + ")"); - } else { - this.imageService.getTvBanner(val.tvDbId).subscribe(x => { - if (x) { - val.background = this.sanitizer.bypassSecurityTrustStyle - ("url(" + x + ")"); - } - }); - } - } -} +// this.sonarrService.getRootFoldersWithoutSettings() +// .subscribe(x => this.sonarrRootFolders = x); +// } +// } + +// public openClosestTab(node: ITvRequests,el: any) { +// el.preventDefault(); +// node.open = !node.open; +// } + +// public ngOnInit() { +// this.amountToLoad = 10; +// this.currentlyLoaded = 10; +// this.tvRequests = {collection:[], total:0}; + +// this.searchChanged.pipe( +// debounceTime(600), // Wait Xms after the last event before emitting last event +// distinctUntilChanged(), // only emit if value is different from previous value +// ).subscribe(x => { +// this.searchText = x as string; +// if (this.searchText === "") { +// this.resetSearch(); +// return; +// } +// this.requestService.searchTvRequests(this.searchText) +// .subscribe(m => { +// this.tvRequests.collection = m; +// this.tvRequests.collection.forEach((val) => this.loadBackdrop(val)); +// this.tvRequests.collection.forEach((val) => this.setOverride(val)); +// }); +// }); +// this.defaultPoster = "../../../images/default_tv_poster.png"; +// const base = this.href; +// if (base) { +// this.defaultPoster = "../../.." + base + "/images/default_tv_poster.png"; +// } + +// this.loadInit(); +// } + +// public paginate(event: IPagenator) { +// const skipAmount = event.first; + +// this.requestService.getTvRequests(this.amountToLoad, skipAmount, OrderType.RequestedDateDesc, FilterType.None, FilterType.None) +// .subscribe(x => { +// this.tvRequests = x; +// this.currentlyLoaded = this.currentlyLoaded + this.amountToLoad; +// }); +// } + +// public search(text: any) { +// this.searchChanged.next(text.target.value); +// } + +// public showChildren(request: ITvRequests) { +// this.selectedSeason = request; +// this.showChildDialogue = true; +// } + +// public childRequestDeleted(childId: number): void { +// // Refresh the UI, hackly way around reloading the data +// this.ngOnInit(); +// } + +// public selectRootFolder(searchResult: ITvRequests, rootFolderSelected: ISonarrRootFolder, event: any) { +// event.preventDefault(); +// searchResult.rootFolder = rootFolderSelected.id; +// this.setOverride(searchResult); +// this.setRootFolder(searchResult); +// } + +// public selectQualityProfile(searchResult: ITvRequests, profileSelected: ISonarrProfile, event: any) { +// event.preventDefault(); +// searchResult.qualityOverride = profileSelected.id; +// this.setOverride(searchResult); +// this.setQualityProfile(searchResult); +// } + +// public reportIssue(catId: IIssueCategory, req: ITvRequests) { +// this.issueRequest = req; +// this.issueCategorySelected = catId; +// this.issuesBarVisible = true; +// this.issueProviderId = req.id.toString(); +// } + +// private setOverride(req: ITvRequests): void { +// this.setQualityOverrides(req); +// this.setRootFolderOverrides(req); +// } + +// private setQualityProfile(req: ITvRequests) { +// this.requestService.setQualityProfile(req.id, req.qualityOverride).subscribe(x => { +// if(x) { +// this.notificationService.success("Quality profile updated"); +// } else { +// this.notificationService.error("Could not update the quality profile"); +// } +// }); +// } + +// private setRootFolder(req: ITvRequests) { +// this.requestService.setRootFolder(req.id, req.rootFolder).subscribe(x => { +// if(x) { +// this.notificationService.success("Quality profile updated"); +// } else { +// this.notificationService.error("Could not update the quality profile"); +// } +// }); +// } + +// private setQualityOverrides(req: ITvRequests): void { +// if (this.sonarrProfiles) { +// const profile = this.sonarrProfiles.filter((p) => { +// return p.id === req.qualityOverride; +// }); +// if (profile.length > 0) { +// req.qualityOverrideTitle = profile[0].name; +// } +// } +// } +// private setRootFolderOverrides(req: ITvRequests): void { +// if (this.sonarrRootFolders) { +// const path = this.sonarrRootFolders.filter((folder) => { +// return folder.id === req.rootFolder; +// }); +// if (path.length > 0) { +// req.rootPathOverrideTitle = path[0].path; +// } +// } +// } + +// private loadInit() { +// this.requestService.getTotalTv().subscribe(x => this.totalTv = x); +// this.requestService.getTvRequests(this.amountToLoad, 0, OrderType.RequestedDateDesc, FilterType.None, FilterType.None) +// .subscribe(x => { +// this.tvRequests = x; +// this.tvRequests.collection.forEach((val, index) => { +// this.setDefaults(val); +// this.loadBackdrop(val); +// this.setOverride(val); +// }); +// }); +// } + +// private resetSearch() { +// this.currentlyLoaded = 5; +// this.loadInit(); +// } + +// private setDefaults(val: ITvRequests) { +// if (val.posterPath === null) { +// val.posterPath = this.defaultPoster; +// } +// } + +// private loadBackdrop(val: ITvRequests): void { +// if (val.background != null) { +// val.background = this.sanitizer.bypassSecurityTrustStyle +// ("url(https://image.tmdb.org/t/p/w1280" + val.background + ")"); +// } else { +// this.imageService.getTvBanner(val.tvDbId).subscribe(x => { +// if (x) { +// val.background = this.sanitizer.bypassSecurityTrustStyle +// ("url(" + x + ")"); +// } +// }); +// } +// } +// } diff --git a/src/Ombi/ClientApp/src/app/search/search.module.ts b/src/Ombi/ClientApp/src/app/search/search.module.ts index 6490076af..d0a3f0e78 100644 --- a/src/Ombi/ClientApp/src/app/search/search.module.ts +++ b/src/Ombi/ClientApp/src/app/search/search.module.ts @@ -3,7 +3,6 @@ import { NgModule } from "@angular/core"; import { FormsModule } from "@angular/forms"; import { RouterModule, Routes } from "@angular/router"; -import { NgbModule } from "@ng-bootstrap/ng-bootstrap"; import { MovieSearchComponent } from "./moviesearch.component"; import { MovieSearchGridComponent } from "./moviesearchgrid.component"; @@ -16,8 +15,6 @@ import { TvSearchComponent } from "./tvsearch.component"; import { CardsFreeModule } from "angular-bootstrap-md"; -import { SidebarModule, TooltipModule, TreeTableModule } from "primeng/primeng"; - import { RequestService } from "../services"; import { SearchService } from "../services"; @@ -35,7 +32,6 @@ const routes: Routes = [ CommonModule, FormsModule, RouterModule.forChild(routes), - NgbModule.forRoot(), TreeTableModule, SharedModule, SidebarModule, diff --git a/src/Ombi/ClientApp/src/app/services/applications/sonarr.service.ts b/src/Ombi/ClientApp/src/app/services/applications/sonarr.service.ts index 4745dbebd..67321d899 100644 --- a/src/Ombi/ClientApp/src/app/services/applications/sonarr.service.ts +++ b/src/Ombi/ClientApp/src/app/services/applications/sonarr.service.ts @@ -31,4 +31,8 @@ export class SonarrService extends ServiceHelpers { public getV3LanguageProfiles(settings: ISonarrSettings): Observable { return this.http.post(`${this.url}/v3/languageprofiles/`, JSON.stringify(settings), {headers: this.headers}); } + + public isEnabled(): Promise { + return this.http.get(`${this.url}/enabled/`, { headers: this.headers }).toPromise(); + } } diff --git a/src/Ombi/ClientApp/src/app/services/applications/tester.service.ts b/src/Ombi/ClientApp/src/app/services/applications/tester.service.ts index 1b7c55821..ad663da4f 100644 --- a/src/Ombi/ClientApp/src/app/services/applications/tester.service.ts +++ b/src/Ombi/ClientApp/src/app/services/applications/tester.service.ts @@ -24,6 +24,8 @@ import { ISlackNotificationSettings, ISonarrSettings, ITelegramNotifcationSettings, + IWebhookNotificationSettings, + IWhatsAppSettings, } from "../../interfaces"; @Injectable() @@ -48,10 +50,18 @@ export class TesterService extends ServiceHelpers { return this.http.post(`${this.url}gotify`, JSON.stringify(settings), { headers: this.headers }); } + public webhookTest(settings: IWebhookNotificationSettings): Observable { + return this.http.post(`${this.url}webhook`, JSON.stringify(settings), { headers: this.headers }); + } + public mattermostTest(settings: IMattermostNotifcationSettings): Observable { return this.http.post(`${this.url}mattermost`, JSON.stringify(settings), {headers: this.headers}); } + public whatsAppTest(settings: IWhatsAppSettings): Observable { + return this.http.post(`${this.url}whatsapp`, JSON.stringify(settings), {headers: this.headers}); + } + public slackTest(settings: ISlackNotificationSettings): Observable { return this.http.post(`${this.url}slack`, JSON.stringify(settings), {headers: this.headers}); } diff --git a/src/Ombi/ClientApp/src/app/services/cloudmobile.service.ts b/src/Ombi/ClientApp/src/app/services/cloudmobile.service.ts new file mode 100644 index 000000000..d1675ae75 --- /dev/null +++ b/src/Ombi/ClientApp/src/app/services/cloudmobile.service.ts @@ -0,0 +1,22 @@ +import { APP_BASE_HREF } from "@angular/common"; +import { Injectable, Inject } from "@angular/core"; + +import { HttpClient } from "@angular/common/http"; +import { Observable } from "rxjs"; + +import { ICloudMobileDevices, ICloudMobileModel } from "../interfaces"; +import { ServiceHelpers } from "./service.helpers"; + +@Injectable() +export class CloudMobileService extends ServiceHelpers { + constructor(http: HttpClient, @Inject(APP_BASE_HREF) href:string) { + super(http, "/api/v2/mobile/", href); + } + public getDevices(): Observable { + return this.http.get(`${this.url}users/`, {headers: this.headers}); + } + + public send(userId: string, message: string): Promise { + return this.http.post(`${this.url}send/`, { userId, message }, {headers: this.headers}).toPromise(); + } +} diff --git a/src/Ombi/ClientApp/src/app/services/identity.service.ts b/src/Ombi/ClientApp/src/app/services/identity.service.ts index 37e8afbda..9d2b4f8c6 100644 --- a/src/Ombi/ClientApp/src/app/services/identity.service.ts +++ b/src/Ombi/ClientApp/src/app/services/identity.service.ts @@ -75,7 +75,12 @@ export class IdentityService extends ServiceHelpers { public getNotificationPreferences(): Observable { return this.http.get(`${this.url}notificationpreferences`, {headers: this.headers}); } + public getNotificationPreferencesForUser(userId: string): Observable { return this.http.get(`${this.url}notificationpreferences/${userId}`, {headers: this.headers}); } + + public updateLanguage(lang: string): Observable { + return this.http.post(`${this.url}language`, {lang: lang}, {headers: this.headers}); + } } diff --git a/src/Ombi/ClientApp/src/app/services/issues.service.ts b/src/Ombi/ClientApp/src/app/services/issues.service.ts index 4500fb90c..eff9ef4ce 100644 --- a/src/Ombi/ClientApp/src/app/services/issues.service.ts +++ b/src/Ombi/ClientApp/src/app/services/issues.service.ts @@ -29,6 +29,14 @@ export class IssuesService extends ServiceHelpers { return this.http.get(this.url, {headers: this.headers}); } + public getIssuesByRequestId(requestId: number): Promise { + return this.http.get(`${this.url}request/${requestId}`, {headers: this.headers}).toPromise(); + } + + public getIssuesByProviderId(providerId: string): Promise { + return this.http.get(`${this.url}provider/${providerId}`, {headers: this.headers}).toPromise(); + } + public getIssuesPage(take: number, skip: number, status: IssueStatus): Observable { return this.http.get(`${this.url}${take}/${skip}/${status}`, {headers: this.headers}); } @@ -60,4 +68,8 @@ export class IssuesService extends ServiceHelpers { public deleteComment(id: number): Observable { return this.http.delete(`${this.url}comments/${id}`, { headers: this.headers }); } + + public deleteIssue(id: number): Promise { + return this.http.delete(`${this.url}${id}`, { headers: this.headers }).toPromise(); + } } diff --git a/src/Ombi/ClientApp/src/app/services/job.service.ts b/src/Ombi/ClientApp/src/app/services/job.service.ts index c855b354b..2e991d941 100644 --- a/src/Ombi/ClientApp/src/app/services/job.service.ts +++ b/src/Ombi/ClientApp/src/app/services/job.service.ts @@ -46,4 +46,8 @@ export class JobService extends ServiceHelpers { public runNewsletter(): Observable { return this.http.post(`${this.url}newsletter/`, {headers: this.headers}); } + + public runArrAvailabilityChecker(): Observable { + return this.http.post(`${this.url}arrAvailability/`, {headers: this.headers}); + } } diff --git a/src/Ombi/ClientApp/src/app/services/message.service.ts b/src/Ombi/ClientApp/src/app/services/message.service.ts index 0886e6b78..1c4e6eded 100644 --- a/src/Ombi/ClientApp/src/app/services/message.service.ts +++ b/src/Ombi/ClientApp/src/app/services/message.service.ts @@ -1,5 +1,5 @@ import { Injectable } from "@angular/core"; -import { MatSnackBar, MatSnackBarConfig } from "@angular/material"; +import { MatSnackBar, MatSnackBarConfig } from "@angular/material/snack-bar"; @Injectable() export class MessageService { diff --git a/src/Ombi/ClientApp/src/app/services/notification.service.ts b/src/Ombi/ClientApp/src/app/services/notification.service.ts index 95a0a1f81..df2e6c737 100644 --- a/src/Ombi/ClientApp/src/app/services/notification.service.ts +++ b/src/Ombi/ClientApp/src/app/services/notification.service.ts @@ -1,6 +1,5 @@ import { Injectable } from "@angular/core"; -import { Message } from "primeng/components/common/api"; -import { MatSnackBar, MatSnackBarConfig } from "@angular/material"; +import { MatSnackBar, MatSnackBarConfig } from "@angular/material/snack-bar"; @Injectable() export class NotificationService { @@ -8,13 +7,7 @@ export class NotificationService { private config: MatSnackBarConfig = { duration:3000, - - } - public messages: Message[] = []; - public addMessage(message: Message) { - this.clearMessages(); - this.messages.push(message); - this.messages = JSON.parse(JSON.stringify(this.messages)); // NOTE: THIS IS A HACK AROUND A BUG https://github.com/primefaces/primeng/issues/2943 + } public success(body: string) { @@ -32,8 +25,4 @@ export class NotificationService { public error(body: string) { this.snackbar.open(body, "OK", this.config); } - - public clearMessages() { - this.messages = []; - } } diff --git a/src/Ombi/ClientApp/src/app/services/request.service.ts b/src/Ombi/ClientApp/src/app/services/request.service.ts index 2f5b860ed..c9d37db89 100644 --- a/src/Ombi/ClientApp/src/app/services/request.service.ts +++ b/src/Ombi/ClientApp/src/app/services/request.service.ts @@ -4,7 +4,7 @@ import { Injectable, Inject } from "@angular/core"; import { HttpClient } from "@angular/common/http"; import { Observable } from "rxjs"; -import { TreeNode } from "primeng/primeng"; +import { UITreeNode } from "primeng/tree"; import { FilterType, IAlbumRequest, IAlbumRequestModel, IAlbumUpdateModel, IChildRequests, IDenyAlbumModel, IDenyMovieModel, IFilter, IMovieRequestModel, IMovieRequests, IMovieUpdateModel, IRequestEngineResult, IRequestsViewModel, ITvDenyModel, ITvRequests, ITvUpdateModel, OrderType } from "../interfaces"; import { ITvRequestViewModel } from "../interfaces"; @@ -74,8 +74,12 @@ export class RequestService extends ServiceHelpers { return this.http.get(`${this.url}movie/info/${requestId}`, {headers: this.headers}).toPromise(); } - public removeMovieRequest(request: IMovieRequests) { - this.http.delete(`${this.url}movie/${request.id}`, {headers: this.headers}).subscribe(); + public removeMovieRequest(requestId: number) { + this.http.delete(`${this.url}movie/${requestId}`, {headers: this.headers}).subscribe(); + } + + public removeMovieRequestAsync(requestId: number) { + return this.http.delete(`${this.url}movie/${requestId}`, {headers: this.headers}).toPromise(); } public updateMovieRequest(request: IMovieRequests): Observable { @@ -86,8 +90,8 @@ export class RequestService extends ServiceHelpers { return this.http.get>(`${this.url}tv/${count}/${position}/${order}/${status}/${availability}`, {headers: this.headers}); } - public getTvRequestsTree(count: number, position: number): Observable { - return this.http.get(`${this.url}tv/${count}/${position}/tree`, {headers: this.headers}); + public getTvRequestsTree(count: number, position: number): Observable { + return this.http.get(`${this.url}tv/${count}/${position}/tree`, {headers: this.headers}); } public getChildRequests(requestId: number): Observable { @@ -98,12 +102,12 @@ export class RequestService extends ServiceHelpers { return this.http.get(`${this.url}tv/search/${search}`, {headers: this.headers}); } - public searchTvRequestsTree(search: string): Observable { - return this.http.get(`${this.url}tv/search/${search}/tree`, {headers: this.headers}); + public searchTvRequestsTree(search: string): Observable { + return this.http.get(`${this.url}tv/search/${search}/tree`, {headers: this.headers}); } - public removeTvRequest(request: ITvRequests) { - this.http.delete(`${this.url}tv/${request.id}`, {headers: this.headers}).subscribe(); + public removeTvRequest(requestId: number) { + this.http.delete(`${this.url}tv/${requestId}`, {headers: this.headers}).subscribe(); } public markTvAvailable(movie: ITvUpdateModel): Observable { @@ -129,8 +133,8 @@ export class RequestService extends ServiceHelpers { public approveChild(child: ITvUpdateModel): Observable { return this.http.post(`${this.url}tv/approve`, JSON.stringify(child), {headers: this.headers}); } - public deleteChild(child: IChildRequests): Observable { - return this.http.delete(`${this.url}tv/child/${child.id}`, {headers: this.headers}); + public deleteChild(childId: number): Observable { + return this.http.delete(`${this.url}tv/child/${childId}`, {headers: this.headers}); } public subscribeToMovie(requestId: number): Observable { @@ -185,8 +189,8 @@ export class RequestService extends ServiceHelpers { return this.http.get(`${this.url}music/search/${search}`, {headers: this.headers}); } - public removeAlbumRequest(request: IAlbumRequest): any { - return this.http.delete(`${this.url}music/${request.id}`, {headers: this.headers}); + public removeAlbumRequest(request: number): any { + return this.http.delete(`${this.url}music/${request}`, {headers: this.headers}); } } diff --git a/src/Ombi/ClientApp/src/app/services/requestV2.service.ts b/src/Ombi/ClientApp/src/app/services/requestV2.service.ts index a7dca2a19..6b03e8440 100644 --- a/src/Ombi/ClientApp/src/app/services/requestV2.service.ts +++ b/src/Ombi/ClientApp/src/app/services/requestV2.service.ts @@ -4,7 +4,7 @@ import { Injectable, Inject } from "@angular/core"; import { HttpClient } from "@angular/common/http"; import { Observable } from "rxjs"; import { ServiceHelpers } from "./service.helpers"; -import { IRequestsViewModel, IMovieRequests, IChildRequests, IMovieAdvancedOptions, IRequestEngineResult } from "../interfaces"; +import { IRequestsViewModel, IMovieRequests, IChildRequests, IMovieAdvancedOptions as IMediaAdvancedOptions, IRequestEngineResult, IAlbumRequest } from "../interfaces"; @Injectable() @@ -17,20 +17,75 @@ export class RequestServiceV2 extends ServiceHelpers { return this.http.get>(`${this.url}movie/${count}/${position}/${sortProperty}/${order}`, {headers: this.headers}); } + public getMovieAvailableRequests(count: number, position: number, sortProperty: string , order: string): Observable> { + return this.http.get>(`${this.url}movie/available/${count}/${position}/${sortProperty}/${order}`, {headers: this.headers}); + } + + public getMovieProcessingRequests(count: number, position: number, sortProperty: string , order: string): Observable> { + return this.http.get>(`${this.url}movie/processing/${count}/${position}/${sortProperty}/${order}`, {headers: this.headers}); + } + + public getMoviePendingRequests(count: number, position: number, sortProperty: string , order: string): Observable> { + return this.http.get>(`${this.url}movie/pending/${count}/${position}/${sortProperty}/${order}`, {headers: this.headers}); + } + + public getMovieDeniedRequests(count: number, position: number, sortProperty: string , order: string): Observable> { + return this.http.get>(`${this.url}movie/denied/${count}/${position}/${sortProperty}/${order}`, {headers: this.headers}); + } + public getTvRequests(count: number, position: number, sortProperty: string , order: string): Observable> { return this.http.get>(`${this.url}tv/${count}/${position}/${sortProperty}/${order}`, {headers: this.headers}); - } - - public updateMovieAdvancedOptions(options: IMovieAdvancedOptions): Observable { + } + + public getPendingTvRequests(count: number, position: number, sortProperty: string , order: string): Observable> { + return this.http.get>(`${this.url}tv/pending/${count}/${position}/${sortProperty}/${order}`, {headers: this.headers}); + } + + public getProcessingTvRequests(count: number, position: number, sortProperty: string , order: string): Observable> { + return this.http.get>(`${this.url}tv/processing/${count}/${position}/${sortProperty}/${order}`, {headers: this.headers}); + } + + public getAvailableTvRequests(count: number, position: number, sortProperty: string , order: string): Observable> { + return this.http.get>(`${this.url}tv/available/${count}/${position}/${sortProperty}/${order}`, {headers: this.headers}); + } + + public getDeniedTvRequests(count: number, position: number, sortProperty: string , order: string): Observable> { + return this.http.get>(`${this.url}tv/denied/${count}/${position}/${sortProperty}/${order}`, {headers: this.headers}); + } + + public updateMovieAdvancedOptions(options: IMediaAdvancedOptions): Observable { return this.http.post(`${this.url}movie/advancedoptions`, options, {headers: this.headers}); } - + + public updateTvAdvancedOptions(options: IMediaAdvancedOptions): Observable { + return this.http.post(`${this.url}tv/advancedoptions`, options, {headers: this.headers}); + } + public getMovieUnavailableRequests(count: number, position: number, sortProperty: string , order: string): Observable> { return this.http.get>(`${this.url}movie/unavailable/${count}/${position}/${sortProperty}/${order}`, {headers: this.headers}); } public getTvUnavailableRequests(count: number, position: number, sortProperty: string , order: string): Observable> { return this.http.get>(`${this.url}tv/unavailable/${count}/${position}/${sortProperty}/${order}`, {headers: this.headers}); - } - + } + + public getAlbumRequests(count: number, position: number, sortProperty: string , order: string): Observable> { + return this.http.get>(`${this.url}Album/${count}/${position}/${sortProperty}/${order}`, {headers: this.headers}); + } + + public getAlbumAvailableRequests(count: number, position: number, sortProperty: string , order: string): Observable> { + return this.http.get>(`${this.url}Album/available/${count}/${position}/${sortProperty}/${order}`, {headers: this.headers}); + } + + public getAlbumProcessingRequests(count: number, position: number, sortProperty: string , order: string): Observable> { + return this.http.get>(`${this.url}Album/processing/${count}/${position}/${sortProperty}/${order}`, {headers: this.headers}); + } + + public getAlbumPendingRequests(count: number, position: number, sortProperty: string , order: string): Observable> { + return this.http.get>(`${this.url}Album/pending/${count}/${position}/${sortProperty}/${order}`, {headers: this.headers}); + } + + public getAlbumDeniedRequests(count: number, position: number, sortProperty: string , order: string): Observable> { + return this.http.get>(`${this.url}Album/denied/${count}/${position}/${sortProperty}/${order}`, {headers: this.headers}); + } } diff --git a/src/Ombi/ClientApp/src/app/services/search.service.ts b/src/Ombi/ClientApp/src/app/services/search.service.ts index 3b4da673a..0adfed3ad 100644 --- a/src/Ombi/ClientApp/src/app/services/search.service.ts +++ b/src/Ombi/ClientApp/src/app/services/search.service.ts @@ -4,7 +4,7 @@ import { Injectable, Inject } from "@angular/core"; import { HttpClient } from "@angular/common/http"; import { Observable } from "rxjs"; -import { TreeNode } from "primeng/primeng"; +import { UITreeNode } from "primeng/tree"; import { ISearchMovieResult } from "../interfaces"; import { ISearchTvResult } from "../interfaces"; import { ISearchAlbumResult, ISearchArtistResult } from "../interfaces/ISearchMusicResult"; @@ -58,12 +58,12 @@ export class SearchService extends ServiceHelpers { return this.http.get(`${this.url}/Tv/${searchTerm}`, { headers: this.headers }); } - public searchTvTreeNode(searchTerm: string): Observable { - return this.http.get(`${this.url}/Tv/${searchTerm}/tree`, { headers: this.headers }); + public searchTvTreeNode(searchTerm: string): Observable { + return this.http.get(`${this.url}/Tv/${searchTerm}/tree`, { headers: this.headers }); } - public getShowInformationTreeNode(theTvDbId: number): Observable { - return this.http.get(`${this.url}/Tv/info/${theTvDbId}/Tree`, { headers: this.headers }); + public getShowInformationTreeNode(theTvDbId: number): Observable { + return this.http.get(`${this.url}/Tv/info/${theTvDbId}/Tree`, { headers: this.headers }); } public getShowInformation(theTvDbId: number): Observable { diff --git a/src/Ombi/ClientApp/src/app/services/searchV2.service.ts b/src/Ombi/ClientApp/src/app/services/searchV2.service.ts index 59dd71917..6536e3cf6 100644 --- a/src/Ombi/ClientApp/src/app/services/searchV2.service.ts +++ b/src/Ombi/ClientApp/src/app/services/searchV2.service.ts @@ -10,6 +10,7 @@ import { ServiceHelpers } from "./service.helpers"; import { ISearchMovieResultV2 } from "../interfaces/ISearchMovieResultV2"; import { ISearchTvResultV2, IMovieCollectionsViewModel, IActorCredits } from "../interfaces/ISearchTvResultV2"; import { IArtistSearchResult, IAlbumArt } from "../interfaces/IMusicSearchResultV2"; +import { SearchFilter } from "../my-nav/SearchFilter"; @Injectable() export class SearchV2Service extends ServiceHelpers { @@ -17,16 +18,25 @@ export class SearchV2Service extends ServiceHelpers { super(http, "/api/v2/search", href); } - public multiSearch(searchTerm: string): Observable { - return this.http.get(`${this.url}/multi/${searchTerm}`); + public multiSearch(searchTerm: string, filter: SearchFilter): Observable { + return this.http.post(`${this.url}/multi/${searchTerm}`, filter); } public getFullMovieDetails(theMovieDbId: number): Observable { return this.http.get(`${this.url}/Movie/${theMovieDbId}`); } + + public getMovieByImdbId(imdbId: string): Observable { + return this.http.get(`${this.url}/Movie/imdb/${imdbId}`); + } + + public getFullMovieDetailsByRequestId(requestId: number): Promise { + return this.http.get(`${this.url}/Movie/request/${requestId}`).toPromise(); + } + public getFullMovieDetailsPromise(theMovieDbId: number): Promise { return this.http.get(`${this.url}/Movie/${theMovieDbId}`).toPromise(); } - + public similarMovies(theMovieDbId: number, langCode: string): Observable { return this.http.post(`${this.url}/Movie/similar`, {theMovieDbId, languageCode: langCode}); } @@ -53,11 +63,11 @@ export class SearchV2Service extends ServiceHelpers { public nowPlayingMoviesByPage(currentlyLoaded: number, toLoad: number): Promise { return this.http.get(`${this.url}/Movie/nowplaying/${currentlyLoaded}/${toLoad}`).toPromise(); } - + public topRatedMovies(): Observable { return this.http.get(`${this.url}/Movie/toprated`); } - + public popularTv(): Observable { return this.http.get(`${this.url}/Tv/popular`, { headers: this.headers }); } @@ -75,7 +85,7 @@ export class SearchV2Service extends ServiceHelpers { public anticipatedTvByPage(currentlyLoaded: number, toLoad: number): Promise { return this.http.get(`${this.url}/Tv/anticipated/${currentlyLoaded}/${toLoad}`, { headers: this.headers }).toPromise(); } - + public trendingTv(): Observable { return this.http.get(`${this.url}/Tv/trending`, { headers: this.headers }); } @@ -83,15 +93,19 @@ export class SearchV2Service extends ServiceHelpers { public trendingTvByPage(currentlyLoaded: number, toLoad: number): Promise { return this.http.get(`${this.url}/Tv/trending/${currentlyLoaded}/${toLoad}`, { headers: this.headers }).toPromise(); } - + public getTvInfo(tvdbid: number): Promise { return this.http.get(`${this.url}/Tv/${tvdbid}`, { headers: this.headers }).toPromise(); } - + + public getTvInfoWithRequestId(requestId: number): Promise { + return this.http.get(`${this.url}/Tv/request/${requestId}`, { headers: this.headers }).toPromise(); + } + public getTvInfoWithMovieDbId(theMovieDbId: number): Promise { return this.http.get(`${this.url}/Tv/moviedb/${theMovieDbId}`, { headers: this.headers }).toPromise(); } - + public getMovieCollections(collectionId: number): Promise { return this.http.get(`${this.url}/movie/collection/${collectionId}`, { headers: this.headers }).toPromise(); } diff --git a/src/Ombi/ClientApp/src/app/services/settings.service.ts b/src/Ombi/ClientApp/src/app/services/settings.service.ts index fb50f3e89..2d32bbcba 100644 --- a/src/Ombi/ClientApp/src/app/services/settings.service.ts +++ b/src/Ombi/ClientApp/src/app/services/settings.service.ts @@ -36,6 +36,8 @@ import { IUpdateSettings, IUserManagementSettings, IVoteSettings, + ITwilioSettings, + IWebhookNotificationSettings, } from "../interfaces"; import { ServiceHelpers } from "./service.helpers"; @@ -192,6 +194,14 @@ export class SettingsService extends ServiceHelpers { .post(`${this.url}/notifications/gotify`, JSON.stringify(settings), { headers: this.headers }); } + public getWebhookNotificationSettings(): Observable { + return this.http.get(`${this.url}/notifications/webhook`, { headers: this.headers }); + } + public saveWebhookNotificationSettings(settings: IWebhookNotificationSettings): Observable { + return this.http + .post(`${this.url}/notifications/webhook`, JSON.stringify(settings), { headers: this.headers }); + } + public getSlackNotificationSettings(): Observable { return this.http.get(`${this.url}/notifications/slack`, {headers: this.headers}); } @@ -254,6 +264,15 @@ export class SettingsService extends ServiceHelpers { .post(`${this.url}/notifications/telegram`, JSON.stringify(settings), {headers: this.headers}); } + public getTwilioSettings(): Observable { + return this.http.get(`${this.url}/notifications/twilio`, {headers: this.headers}); + } + + public saveTwilioSettings(settings: ITwilioSettings): Observable { + return this.http + .post(`${this.url}/notifications/twilio`, JSON.stringify(settings), {headers: this.headers}); + } + public getJobSettings(): Observable { return this.http.get(`${this.url}/jobs`, {headers: this.headers}); } diff --git a/src/Ombi/ClientApp/src/app/services/signlarnotification.service.ts b/src/Ombi/ClientApp/src/app/services/signlarnotification.service.ts index ea4c4691c..2597fff54 100644 --- a/src/Ombi/ClientApp/src/app/services/signlarnotification.service.ts +++ b/src/Ombi/ClientApp/src/app/services/signlarnotification.service.ts @@ -3,8 +3,6 @@ import { AuthService } from '../auth/auth.service'; import { HubConnection } from '@aspnet/signalr'; import * as signalR from '@aspnet/signalr'; -import { PlatformLocation } from '@angular/common'; -import { platformBrowser } from '@angular/platform-browser'; @Injectable() export class SignalRNotificationService { @@ -12,18 +10,14 @@ export class SignalRNotificationService { private hubConnection: HubConnection | undefined; public Notification: EventEmitter; - constructor(private authService: AuthService, private platform: PlatformLocation) { + constructor(private authService: AuthService) { this.Notification = new EventEmitter(); } public initialize(): void { this.stopConnection(); - let url = "/hubs/notification"; - const baseUrl = this.platform.getBaseHrefFromDOM(); - if(baseUrl !== null && baseUrl.length > 1) { - url = baseUrl + url; - } + let url = "hubs/notification"; this.hubConnection = new signalR.HubConnectionBuilder().withUrl(url, { accessTokenFactory: () => { return this.authService.getToken(); @@ -35,12 +29,16 @@ export class SignalRNotificationService { this.Notification.emit(data); }); + let retryCount = 0; this.hubConnection.start().then((data: any) => { console.log('Now connected'); }).catch((error: any) => { + retryCount++; console.log('Could not connect ' + error); - setTimeout(() => this.initialize(), 3000); + if (retryCount <= 3) { + setTimeout(() => this.initialize(), 3000); + } }); } diff --git a/src/Ombi/ClientApp/src/app/services/system.service.ts b/src/Ombi/ClientApp/src/app/services/system.service.ts index 20f60c8d8..ef6f947a8 100644 --- a/src/Ombi/ClientApp/src/app/services/system.service.ts +++ b/src/Ombi/ClientApp/src/app/services/system.service.ts @@ -18,4 +18,7 @@ export class SystemService extends ServiceHelpers { public getLog(logName: string): Observable { return this.http.get(`${this.url}logs/${logName}`, {responseType: 'text'}); } + public getNews(): Observable { + return this.http.get(`${this.url}news`, {responseType: 'text'}); + } } diff --git a/src/Ombi/ClientApp/src/app/settings/about/about.component.html b/src/Ombi/ClientApp/src/app/settings/about/about.component.html index b82f3ea4d..a9e1028d1 100644 --- a/src/Ombi/ClientApp/src/app/settings/about/about.component.html +++ b/src/Ombi/ClientApp/src/app/settings/about/about.component.html @@ -1,7 +1,8 @@  -
+
About - +
+
NOT SUPPORTED OS. Please use the docker image available on the Container Station (It's free)
@@ -16,10 +17,10 @@ style="color:#df691a">(New Update Available)
-
+
Github
@@ -77,20 +78,25 @@
Ombi Database
-
{{about.ombiDatabaseType}} - {{about.ombiConnectionString}}
+
{{about.ombiDatabaseType}}
External Database
-
{{about.externalDatabaseType}} - {{about.externalConnectionString}}
+
{{about.externalDatabaseType}}
Settings Database
-
{{about.settingsDatabaseType}} - {{about.settingsConnectionString}}
+
{{about.settingsDatabaseType}}
- +
+
+
+

News

+
+
diff --git a/src/Ombi/ClientApp/src/app/settings/about/about.component.scss b/src/Ombi/ClientApp/src/app/settings/about/about.component.scss index c99e10bc3..daeccd03a 100644 --- a/src/Ombi/ClientApp/src/app/settings/about/about.component.scss +++ b/src/Ombi/ClientApp/src/app/settings/about/about.component.scss @@ -17,4 +17,24 @@ flex: 1; overflow: hidden; word-wrap: break-word; + } + + .small-middle-container{ + margin: auto; + width: 85%; + margin-top:10px; + } + + :host ::ng-deep strong { + color: #fff; + background-color: #007bff; + display: inline-block; + padding: 0.25em 0.4em; + font-size: 75%; + font-weight: 700; + line-height: 1; + text-align: center; + white-space: nowrap; + vertical-align: baseline; + border-radius: 0.25rem; } \ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/settings/about/about.component.ts b/src/Ombi/ClientApp/src/app/settings/about/about.component.ts index a9a761c84..c3fd4b056 100644 --- a/src/Ombi/ClientApp/src/app/settings/about/about.component.ts +++ b/src/Ombi/ClientApp/src/app/settings/about/about.component.ts @@ -1,6 +1,6 @@ import { Component, OnInit } from "@angular/core"; import { IAbout } from "../../interfaces/ISettings"; -import { JobService, SettingsService, HubService } from "../../services"; +import { JobService, SettingsService, HubService, SystemService } from "../../services"; import { IConnectedUser } from "../../interfaces"; @Component({ @@ -12,18 +12,23 @@ export class AboutComponent implements OnInit { public about: IAbout; public newUpdate: boolean; public connectedUsers: IConnectedUser[]; + public newsHtml: string; constructor(private readonly settingsService: SettingsService, - private readonly jobService: JobService, - private readonly hubService: HubService) { } + private readonly jobService: JobService, + private readonly hubService: HubService, + private readonly systemService: SystemService) { } public async ngOnInit() { this.settingsService.about().subscribe(x => this.about = x); - this.jobService.getCachedUpdate().subscribe(x => { - if (x === true) { - this.newUpdate = true; - } - }); + this.newsHtml = await this.systemService.getNews().toPromise(); + + // TODO + // this.jobService.getCachedUpdate().subscribe(x => { + // if (x === true) { + // // this.newUpdate = true; // TODO + // } + // }); this.connectedUsers = await this.hubService.getConnectedUsers(); } diff --git a/src/Ombi/ClientApp/src/app/settings/authentication/authentication.component.html b/src/Ombi/ClientApp/src/app/settings/authentication/authentication.component.html index a270d513c..1d6b6f5d3 100644 --- a/src/Ombi/ClientApp/src/app/settings/authentication/authentication.component.html +++ b/src/Ombi/ClientApp/src/app/settings/authentication/authentication.component.html @@ -1,23 +1,20 @@  - +
Authentication +
- -
-
- - + + Allow users to login without a password
- - + Enable Plex OAuth
@@ -59,9 +56,11 @@
- +
-
-
-
\ No newline at end of file + + +
\ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/settings/authentication/authentication.component.scss b/src/Ombi/ClientApp/src/app/settings/authentication/authentication.component.scss new file mode 100644 index 000000000..2afbcf328 --- /dev/null +++ b/src/Ombi/ClientApp/src/app/settings/authentication/authentication.component.scss @@ -0,0 +1,15 @@ +@import "~styles/variables.scss"; +.small-middle-container { + margin: auto; + width: 95%; + margin-top: 10px; +} + +.control-label { + font-weight: 400; +} + +::ng-deep .dark .btn:hover { + box-shadow: 0 5px 11px 0 rgba(255, 255, 255, 0.18), 0 4px 15px 0 rgba(255, 255, 255, 0.15); + color: inherit; +} \ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/settings/authentication/authentication.component.ts b/src/Ombi/ClientApp/src/app/settings/authentication/authentication.component.ts index 50152409c..6f140f8af 100644 --- a/src/Ombi/ClientApp/src/app/settings/authentication/authentication.component.ts +++ b/src/Ombi/ClientApp/src/app/settings/authentication/authentication.component.ts @@ -6,6 +6,7 @@ import { SettingsService } from "../../services"; @Component({ templateUrl: "./authentication.component.html", + styleUrls: ["./authentication.component.scss"], }) export class AuthenticationComponent implements OnInit { diff --git a/src/Ombi/ClientApp/src/app/settings/couchpotato/couchpotato.component.html b/src/Ombi/ClientApp/src/app/settings/couchpotato/couchpotato.component.html index ae8f7bb6f..3ca5a133e 100644 --- a/src/Ombi/ClientApp/src/app/settings/couchpotato/couchpotato.component.html +++ b/src/Ombi/ClientApp/src/app/settings/couchpotato/couchpotato.component.html @@ -1,100 +1,88 @@  +
CouchPotato Settings -
-
-
-
- - + +
+
+
+ Enable
- - -
- -
- - The IP/Hostname is required +
+
+
+ +
+ + Hostname or IP + + The IP/Hostname is required +
-
- -
- - - - The Port is required -
- - -
- - - - - The API Key is required -
-
-
- - - +
+ + API Key + + The API Key is required +
-
-
- -
- +
+ + Port + + The Port is required + +
+
+ SSL
-
-
-
-
- - -
-
- - -
-
- -
- -
-
- +
+ + Base URL + +
-
- -
- +
+ +
+
+
+ + Quality Profiles + + {{profile.label}} + + A Default Quality Profile is required + +
+
+ +
+
- - - - -
-
- +
+
+
+ +
-
-
-
- +
+
+ +
+
\ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/settings/couchpotato/couchpotato.component.scss b/src/Ombi/ClientApp/src/app/settings/couchpotato/couchpotato.component.scss new file mode 100644 index 000000000..2499a1794 --- /dev/null +++ b/src/Ombi/ClientApp/src/app/settings/couchpotato/couchpotato.component.scss @@ -0,0 +1,6 @@ +@import "~styles/shared.scss"; +.small-middle-container { + margin: auto; + width: 95%; + margin-top: 10px; +} diff --git a/src/Ombi/ClientApp/src/app/settings/couchpotato/couchpotato.component.ts b/src/Ombi/ClientApp/src/app/settings/couchpotato/couchpotato.component.ts index f4b209189..112e66b5c 100644 --- a/src/Ombi/ClientApp/src/app/settings/couchpotato/couchpotato.component.ts +++ b/src/Ombi/ClientApp/src/app/settings/couchpotato/couchpotato.component.ts @@ -7,6 +7,7 @@ import { ICouchPotatoProfiles } from "../../interfaces"; @Component({ templateUrl: "./couchpotato.component.html", + styleUrls: ["./couchpotato.component.scss"] }) export class CouchPotatoComponent implements OnInit { diff --git a/src/Ombi/ClientApp/src/app/settings/customization/customization.component.html b/src/Ombi/ClientApp/src/app/settings/customization/customization.component.html index 1a20ab95c..55f4a1b42 100644 --- a/src/Ombi/ClientApp/src/app/settings/customization/customization.component.html +++ b/src/Ombi/ClientApp/src/app/settings/customization/customization.component.html @@ -1,62 +1,80 @@  - +
-
+
Customization -
- - +
+
+ + Application Name + - - - +
+
+ + Application URL + - - - +
+
+ + Custom Logo + - -
- -
- +
+
+
+ +
+ +
- - - Enable Custom Donation Link - - - - - +
+ + Hide Available Content On The Discover Page + +
+
+ + Enable Custom Donation Link + +
+
+ + Custom Donation URL + - - +
+
+ + Custom Donation Message + - - - +
+
+ Enable Custom Page - - - + +
+
+ + Custom CSS + + +
- +
- - -
- -
\ No newline at end of file + +
+
\ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/settings/customization/customization.component.scss b/src/Ombi/ClientApp/src/app/settings/customization/customization.component.scss new file mode 100644 index 000000000..fae15b828 --- /dev/null +++ b/src/Ombi/ClientApp/src/app/settings/customization/customization.component.scss @@ -0,0 +1,16 @@ +@import "~styles/shared.scss"; +.small-middle-container { + margin: auto; + width: 95%; + margin-top: 10px; +} + +textarea { + min-height: 100px; + height: auto; + max-height: 800px; +} + +.row { + display: block; +} \ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/settings/customization/customization.component.ts b/src/Ombi/ClientApp/src/app/settings/customization/customization.component.ts index 0daf9ffad..4e2b22129 100644 --- a/src/Ombi/ClientApp/src/app/settings/customization/customization.component.ts +++ b/src/Ombi/ClientApp/src/app/settings/customization/customization.component.ts @@ -6,6 +6,7 @@ import { SettingsService } from "../../services"; @Component({ templateUrl: "./customization.component.html", + styleUrls: ["./customization.component.scss"], }) export class CustomizationComponent implements OnInit { diff --git a/src/Ombi/ClientApp/src/app/settings/dognzb/dognzb.component.html b/src/Ombi/ClientApp/src/app/settings/dognzb/dognzb.component.html index 827f1ac2d..6587c07d1 100644 --- a/src/Ombi/ClientApp/src/app/settings/dognzb/dognzb.component.html +++ b/src/Ombi/ClientApp/src/app/settings/dognzb/dognzb.component.html @@ -1,54 +1,47 @@  - +
-
+
DogNzb Settings -
-
-
-
- - -
-
- - - -
- - - - - The API Key is required + +
+
+
+ Enabled +
- - - +
+
+
+
+ + DogNzb API Key + + The API Key is required + +
-
-
- +
+ Movies
-
-
-
-
-
- - +
+ TV Shows
- -
-
- - +
+
+
+
+
+
+ +
-
+
\ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/settings/dognzb/dognzb.component.scss b/src/Ombi/ClientApp/src/app/settings/dognzb/dognzb.component.scss new file mode 100644 index 000000000..aa1beaebc --- /dev/null +++ b/src/Ombi/ClientApp/src/app/settings/dognzb/dognzb.component.scss @@ -0,0 +1,11 @@ +@import "~styles/shared.scss"; +.small-middle-container { + margin: auto; + width: 95%; + margin-top: 10px; +} + +::ng-deep .dark .btn:hover { + box-shadow: 0 5px 11px 0 rgba(255, 255, 255, 0.18), 0 4px 15px 0 rgba(255, 255, 255, 0.15); + color: inherit; +} \ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/settings/dognzb/dognzb.component.ts b/src/Ombi/ClientApp/src/app/settings/dognzb/dognzb.component.ts index aff18f64e..16683a0e3 100644 --- a/src/Ombi/ClientApp/src/app/settings/dognzb/dognzb.component.ts +++ b/src/Ombi/ClientApp/src/app/settings/dognzb/dognzb.component.ts @@ -5,6 +5,7 @@ import { NotificationService, SettingsService } from "../../services"; @Component({ templateUrl: "./dognzb.component.html", + styleUrls: ["./dognzb.component.scss"] }) export class DogNzbComponent implements OnInit { diff --git a/src/Ombi/ClientApp/src/app/settings/emby/emby.component.html b/src/Ombi/ClientApp/src/app/settings/emby/emby.component.html index 18d42bb47..e6d35b1c1 100644 --- a/src/Ombi/ClientApp/src/app/settings/emby/emby.component.html +++ b/src/Ombi/ClientApp/src/app/settings/emby/emby.component.html @@ -1,5 +1,6 @@  +
@@ -7,102 +8,104 @@
-
-
- - +
+
+
+ Enable +
-
- -
- - -
- - -
-
-
- -
-
-
-
-
- -
- -
-
-
- -
- -
+ + +
+ +
+
+
+
+
+ + Server Name + +
-
- -
- -
-
+
+ + Hostname / IP + + -
-
- - +
+ + Server ID + +
-
+ + Port + + -
- -
- -
+ + SSL +
- -
- -
- - Current URL: "{{server.serverHostname}}/#!/{{settings.isJellyfin ? ("itemdetails"): ("item/item")}}.html?id=1" - Current URL: "https://app.emby.media/#!/{{settings.isJellyfin ? ("itemdetails"): ("item/item")}}.html?id=1 -
+
+ + API Key + + +
+
+ + Base URL + + +
+
+ + Externally Facing Hostname + + + + Current URL: "{{server.serverHostname}}/#!/{{settings.isJellyfin ? ("itemdetails"): ("item/item")}}.html?id=1" + Current URL: "https://app.emby.media/#!/{{settings.isJellyfin ? ("itemdetails"): ("item/item")}}.html?id=1 +
+ +
- +
- +
- - -
- -
+ + + + + +
- +
-
+
- +
+
diff --git a/src/Ombi/ClientApp/src/app/settings/emby/emby.component.scss b/src/Ombi/ClientApp/src/app/settings/emby/emby.component.scss new file mode 100644 index 000000000..649201f48 --- /dev/null +++ b/src/Ombi/ClientApp/src/app/settings/emby/emby.component.scss @@ -0,0 +1,41 @@ +@import "~styles/shared.scss"; +.small-middle-container { + margin: auto; + width: 95%; + margin-top: 10px; +} + +.col-md-10 { + display: grid; +} + +.col-md-2 { + display: contents; +} + +.control-label { + font-weight: 400; +} + +.row { + display: block; +} + +.btn-danger-outline { + background-color: #E84C3D; +} + +.btn-success-outline { + background-color: #1b9d1b; +} + +::ng-deep .dark .btn:hover { + box-shadow: 0 5px 11px 0 rgba(255, 255, 255, 0.18), 0 4px 15px 0 rgba(255, 255, 255, 0.15); + color: inherit; +} + +@media (min-width:1440px) { + .col-md-2 { + display: inline-table; + } +} \ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/settings/emby/emby.component.ts b/src/Ombi/ClientApp/src/app/settings/emby/emby.component.ts index bc1d2bbb2..5db2d1120 100644 --- a/src/Ombi/ClientApp/src/app/settings/emby/emby.component.ts +++ b/src/Ombi/ClientApp/src/app/settings/emby/emby.component.ts @@ -2,14 +2,18 @@ import { IEmbyServer, IEmbySettings } from "../../interfaces"; import { EmbyService, JobService, NotificationService, SettingsService, TesterService } from "../../services"; +import { MatTabChangeEvent } from "@angular/material/tabs"; +import {FormControl} from '@angular/forms'; @Component({ templateUrl: "./emby.component.html", + styleUrls: ["./emby.component.scss"] }) export class EmbyComponent implements OnInit { public settings: IEmbySettings; - public hasDiscovered: boolean; + public hasDiscoveredOrDirty: boolean; + selected = new FormControl(0); constructor(private settingsService: SettingsService, private notificationService: NotificationService, @@ -25,24 +29,33 @@ export class EmbyComponent implements OnInit { const result = await this.embyService.getPublicInfo(server).toPromise(); this.settings.isJellyfin = result.isJellyfin; server.name = result.serverName; - this.hasDiscovered = true; + server.serverId = result.id; + this.hasDiscoveredOrDirty = true; } - public addTab() { - if (this.settings.servers == null) { - this.settings.servers = []; + public addTab(event: MatTabChangeEvent) { + const tabName = event.tab.textLabel; + if (tabName == "Add Server"){ + if (this.settings.servers == null) { + this.settings.servers = []; + } + this.settings.servers.push({ + name: "New " + this.settings.servers.length + "*", + id: Math.floor(Math.random() * (99999 - 0 + 1) + 1), + apiKey: "", + administratorId: "", + enableEpisodeSearching: false, + ip: "", + port: 0, + ssl: false, + subDir: "", + } as IEmbyServer); + this.selected.setValue(this.settings.servers.length - 1); } - this.settings.servers.push({ - name: "New*", - id: Math.floor(Math.random() * (99999 - 0 + 1) + 1), - apiKey: "", - administratorId: "", - enableEpisodeSearching: false, - ip: "", - port: 0, - ssl: false, - subDir: "", - } as IEmbyServer); + } + + public toggle() { + this.hasDiscoveredOrDirty = true; } public test(server: IEmbyServer) { @@ -59,6 +72,7 @@ export class EmbyComponent implements OnInit { const index = this.settings.servers.indexOf(server, 0); if (index > -1) { this.settings.servers.splice(index, 1); + this.selected.setValue(this.settings.servers.length - 1); } } diff --git a/src/Ombi/ClientApp/src/app/settings/failedrequests/failedrequest.component.html b/src/Ombi/ClientApp/src/app/settings/failedrequests/failedrequests.component.html similarity index 94% rename from src/Ombi/ClientApp/src/app/settings/failedrequests/failedrequest.component.html rename to src/Ombi/ClientApp/src/app/settings/failedrequests/failedrequests.component.html index 898710199..37434ac04 100644 --- a/src/Ombi/ClientApp/src/app/settings/failedrequests/failedrequest.component.html +++ b/src/Ombi/ClientApp/src/app/settings/failedrequests/failedrequests.component.html @@ -1,7 +1,7 @@  - +
@@ -24,3 +24,4 @@
+
diff --git a/src/Ombi/ClientApp/src/app/settings/failedrequests/failedrequests.component.scss b/src/Ombi/ClientApp/src/app/settings/failedrequests/failedrequests.component.scss new file mode 100644 index 000000000..018bebef8 --- /dev/null +++ b/src/Ombi/ClientApp/src/app/settings/failedrequests/failedrequests.component.scss @@ -0,0 +1,5 @@ +.small-middle-container{ + margin: auto; + width: 85%; + margin-top:10px; +} \ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/settings/failedrequests/failedrequests.component.ts b/src/Ombi/ClientApp/src/app/settings/failedrequests/failedrequests.component.ts index a303ac713..feae7cfaf 100644 --- a/src/Ombi/ClientApp/src/app/settings/failedrequests/failedrequests.component.ts +++ b/src/Ombi/ClientApp/src/app/settings/failedrequests/failedrequests.component.ts @@ -3,7 +3,8 @@ import { IFailedRequestsViewModel, RequestType } from "../../interfaces"; import { RequestRetryService } from "../../services"; @Component({ - templateUrl: "./failedrequest.component.html", + templateUrl: "./failedrequests.component.html", + styleUrls: ["./failedrequests.component.scss"], }) export class FailedRequestsComponent implements OnInit { diff --git a/src/Ombi/ClientApp/src/app/settings/issues/issues.component.html b/src/Ombi/ClientApp/src/app/settings/issues/issues.component.html index fa5988a79..702ca6915 100644 --- a/src/Ombi/ClientApp/src/app/settings/issues/issues.component.html +++ b/src/Ombi/ClientApp/src/app/settings/issues/issues.component.html @@ -1,27 +1,29 @@  +
Issues -
+
+
- - + + Enable
- - + + Enable In Progress State
- - + + Delete issues after they have been resolved
@@ -33,19 +35,16 @@
-
+
- +
-
- - - -
@@ -57,11 +56,12 @@ name="categoryToAdd" value="{{categoryToAdd.value}}">
- +
-
+
+ Categories:
{{cat.value}} @@ -73,4 +73,5 @@
-
\ No newline at end of file + +
\ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/settings/issues/issues.component.scss b/src/Ombi/ClientApp/src/app/settings/issues/issues.component.scss new file mode 100644 index 000000000..ddf1eb4d8 --- /dev/null +++ b/src/Ombi/ClientApp/src/app/settings/issues/issues.component.scss @@ -0,0 +1,50 @@ +@import "~styles/shared.scss"; +.small-middle-container { + margin: auto; + width: 95%; + margin-top: 10px; +} + +.control-label { + font-weight: 400; +} + +.col-md-6 { + display: contents; +} + +.col-md-9 { + display: inline-table; +} + +.col-md-3 { + display: inline-table; +} + +.row { + display: block; +} + +.btn-danger-outline { + background-color: #E84C3D; +} + +.btn-success-outline { + background-color: #1b9d1b; +} + +::ng-deep .dark .categoryResults { + background-color: rgba(0, 0, 0, 0.05); + padding: 1em; +} + +::ng-deep .dark .btn:hover { + box-shadow: 0 5px 11px 0 rgba(255, 255, 255, 0.18), 0 4px 15px 0 rgba(255, 255, 255, 0.15); + color: inherit; +} + +@media (min-width:1440px) { + .col-md-6 { + display: inline-table; + } +} \ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/settings/issues/issues.component.ts b/src/Ombi/ClientApp/src/app/settings/issues/issues.component.ts index cfe0bd65c..cfb6ae94d 100644 --- a/src/Ombi/ClientApp/src/app/settings/issues/issues.component.ts +++ b/src/Ombi/ClientApp/src/app/settings/issues/issues.component.ts @@ -6,6 +6,7 @@ import { IssuesService, NotificationService, SettingsService } from "../../servi @Component({ templateUrl: "./issues.component.html", + styleUrls: ["./issues.component.scss"] }) export class IssuesComponent implements OnInit { diff --git a/src/Ombi/ClientApp/src/app/settings/jobs/jobs.component.html b/src/Ombi/ClientApp/src/app/settings/jobs/jobs.component.html index 314b19146..ec2a42c99 100644 --- a/src/Ombi/ClientApp/src/app/settings/jobs/jobs.component.html +++ b/src/Ombi/ClientApp/src/app/settings/jobs/jobs.component.html @@ -72,27 +72,19 @@
- + The Emby Sync is required
- + The User Importer is required
-
- - - The Refresh Metadata is required - -
- -
@@ -113,6 +105,13 @@ The Media Database Refresh is required
+ +
+ + + Auto Available Request Deletion is required + +
diff --git a/src/Ombi/ClientApp/src/app/settings/jobs/jobs.component.scss b/src/Ombi/ClientApp/src/app/settings/jobs/jobs.component.scss new file mode 100644 index 000000000..018bebef8 --- /dev/null +++ b/src/Ombi/ClientApp/src/app/settings/jobs/jobs.component.scss @@ -0,0 +1,5 @@ +.small-middle-container{ + margin: auto; + width: 85%; + margin-top:10px; +} \ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/settings/jobs/jobs.component.ts b/src/Ombi/ClientApp/src/app/settings/jobs/jobs.component.ts index 1a543f885..914d126d0 100644 --- a/src/Ombi/ClientApp/src/app/settings/jobs/jobs.component.ts +++ b/src/Ombi/ClientApp/src/app/settings/jobs/jobs.component.ts @@ -1,21 +1,23 @@ import { Component, OnInit } from "@angular/core"; import { FormBuilder, FormGroup, Validators } from "@angular/forms"; -import { NotificationService, SettingsService } from "../../services"; +import { NotificationService, SettingsService, JobService } from "../../services"; @Component({ templateUrl: "./jobs.component.html", + styleUrls: ["./jobs.component.scss"] }) export class JobsComponent implements OnInit { public form: FormGroup; - + public profilesRunning: boolean; - + constructor(private readonly settingsService: SettingsService, private readonly fb: FormBuilder, - private readonly notificationService: NotificationService) { } - + private readonly notificationService: NotificationService, + private readonly jobsService: JobService) { } + public ngOnInit() { this.settingsService.getJobSettings().subscribe(x => { this.form = this.fb.group({ @@ -26,28 +28,28 @@ export class JobsComponent implements OnInit { userImporter: [x.userImporter, Validators.required], sonarrSync: [x.sonarrSync, Validators.required], radarrSync: [x.radarrSync, Validators.required], - sickRageSync: [x.sickRageSync, Validators.required], - refreshMetadata: [x.refreshMetadata, Validators.required], + sickRageSync: [x.sickRageSync, Validators.required], newsletter: [x.newsletter, Validators.required], plexRecentlyAddedSync: [x.plexRecentlyAddedSync, Validators.required], lidarrArtistSync: [x.lidarrArtistSync, Validators.required], issuesPurge: [x.issuesPurge, Validators.required], retryRequests: [x.retryRequests, Validators.required], mediaDatabaseRefresh: [x.mediaDatabaseRefresh, Validators.required], - }); + autoDeleteRequests: [x.autoDeleteRequests, Validators.required] + }); }); } public testCron(expression: string) { this.settingsService.testCron({ expression }).subscribe(x => { - if(x.success) { - this.notificationService.success("Cron is Valid"); + if(x.success) { + this.notificationService.success("Cron is Valid"); } else { this.notificationService.error(x.message); } }); } - + public onSubmit(form: FormGroup) { if (form.invalid) { this.notificationService.error("Please check your entered values"); @@ -62,4 +64,8 @@ export class JobsComponent implements OnInit { } }); } + + public runArrAvailabilityChecker() { + this.jobsService.runArrAvailabilityChecker().subscribe(); + } } diff --git a/src/Ombi/ClientApp/src/app/settings/landingpage/landingpage.component.html b/src/Ombi/ClientApp/src/app/settings/landingpage/landingpage.component.html index 26711c6e5..91b923833 100644 --- a/src/Ombi/ClientApp/src/app/settings/landingpage/landingpage.component.html +++ b/src/Ombi/ClientApp/src/app/settings/landingpage/landingpage.component.html @@ -1,59 +1,61 @@ - - - + +
-
-
+
Landing Page Configuration - - +
+
+ Enable - -
-
- - + + + +
+
+ + Notice Message + + +
-
-

Notice Message

-
-
- +

Notice Preview:

+
+
-
-

Notice Preview:

-
-
-
- - + - + -
-
- +
+
+ +
-
+
diff --git a/src/Ombi/ClientApp/src/app/settings/landingpage/landingpage.component.scss b/src/Ombi/ClientApp/src/app/settings/landingpage/landingpage.component.scss new file mode 100644 index 000000000..2b7480f99 --- /dev/null +++ b/src/Ombi/ClientApp/src/app/settings/landingpage/landingpage.component.scss @@ -0,0 +1,30 @@ +@import "~styles/shared.scss"; +.small-middle-container{ + margin: auto; + width: 95%; + margin-top:10px; +} + +@media (min-width: 1200px){ + .container { + max-width: inherit; + } +} + +@media (min-width: 992px){ + .container { + max-width: inherit; + } +} + +@media (min-width: 768px){ + .container { + max-width: inherit; + } +} + +@media (min-width: 576px){ + .container { + max-width: inherit; + } +} \ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/settings/landingpage/landingpage.component.ts b/src/Ombi/ClientApp/src/app/settings/landingpage/landingpage.component.ts index c79c66ff7..616013725 100644 --- a/src/Ombi/ClientApp/src/app/settings/landingpage/landingpage.component.ts +++ b/src/Ombi/ClientApp/src/app/settings/landingpage/landingpage.component.ts @@ -6,6 +6,7 @@ import { SettingsService } from "../../services"; @Component({ templateUrl: "./landingpage.component.html", + styleUrls: ["./landingpage.component.scss"], }) export class LandingPageComponent implements OnInit { diff --git a/src/Ombi/ClientApp/src/app/settings/lidarr/lidarr.component.html b/src/Ombi/ClientApp/src/app/settings/lidarr/lidarr.component.html index 633f8dbbd..850902dd1 100644 --- a/src/Ombi/ClientApp/src/app/settings/lidarr/lidarr.component.html +++ b/src/Ombi/ClientApp/src/app/settings/lidarr/lidarr.component.html @@ -1,119 +1,137 @@  -
-
- Lidarr Settings -
- - Advanced -
-
-
-
-
+
+
+ Lidarr Settings +
+ + +
+
+
Enable
- - -
- - - -
-
- - - -
-
- - - -
- - -
- - Enable SSL - -
- - -
- - - +
+ Advanced
+
-
- -
- - Quality Profiles - - - {{quality.name}} - - - -
-
- -
- - Default Root Folder - - - {{folder.path}} - - - -
-
- -
- - Metadata Profile - - - {{folder.name}} - - - -
-
- - -
- - Album Folder - -
- -
- - Do not search - +
+
+
+ +
+ + Hostname or IP + + + + Port + + + + SSL + +
+
+
+ + API key + + +
+
+ + Base URL + + +
+
+ + +
+
+ +
+
+ + Quality Profiles + + + {{quality.name}} + + + +
- -
-
- +
+
+ +
+ +
+ + + Default Root Folder + + + {{folder.path}} + + +
-
+
+
+
+
+
+ + Metadata Profile + + + {{folder.name}} + + + + + +
+ + Album Folder + +
+
-
-
- +
+ + Do not search +
+
- -
-
-
+
+
+
+
+ +
+
+
+
+ +
+
+
+
+ +
+
\ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/settings/lidarr/lidarr.component.scss b/src/Ombi/ClientApp/src/app/settings/lidarr/lidarr.component.scss new file mode 100644 index 000000000..2898f062e --- /dev/null +++ b/src/Ombi/ClientApp/src/app/settings/lidarr/lidarr.component.scss @@ -0,0 +1,17 @@ +@import "~styles/shared.scss"; +.small-middle-container { + margin: auto; + width: 95%; + margin-top: 10px; +} + +.col-8 { + display: inline-table; +} +.col-md-5 { + display: inline-table; +} + +.row { + display: block; +} \ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/settings/lidarr/lidarr.component.ts b/src/Ombi/ClientApp/src/app/settings/lidarr/lidarr.component.ts index 45efdb792..7ff770c4c 100644 --- a/src/Ombi/ClientApp/src/app/settings/lidarr/lidarr.component.ts +++ b/src/Ombi/ClientApp/src/app/settings/lidarr/lidarr.component.ts @@ -8,6 +8,7 @@ import { SettingsService } from "../../services"; @Component({ templateUrl: "./lidarr.component.html", + styleUrls: ["./lidarr.component.scss"] }) export class LidarrComponent implements OnInit { @@ -34,7 +35,7 @@ export class LidarrComponent implements OnInit { this.form = this.fb.group({ enabled: [x.enabled], apiKey: [x.apiKey, [Validators.required]], - defaultQualityProfile: [x.defaultQualityProfile, [Validators.required]], + defaultQualityProfile: [+x.defaultQualityProfile, [Validators.required]], defaultRootPath: [x.defaultRootPath, [Validators.required]], ssl: [x.ssl], subDir: [x.subDir], @@ -44,6 +45,15 @@ export class LidarrComponent implements OnInit { metadataProfileId: [x.metadataProfileId, [Validators.required]], addOnly: [x.addOnly], }); + + this.qualities = []; + this.qualities.push({ name: "Please Select", id: -1 }); + + this.rootFolders = []; + this.rootFolders.push({ path: "Please Select", id: -1 }); + + this.metadataProfiles = []; + this.metadataProfiles.push({ name: "Please Select", id: -1 }); if (x.defaultQualityProfile) { this.getProfiles(this.form); @@ -55,15 +65,6 @@ export class LidarrComponent implements OnInit { this.getMetadataProfiles(this.form); } }); - - this.qualities = []; - this.qualities.push({ name: "Please Select", id: -1 }); - - this.rootFolders = []; - this.rootFolders.push({ path: "Please Select", id: -1 }); - - this.metadataProfiles = []; - this.metadataProfiles.push({ name: "Please Select", id: -1 }); } public getProfiles(form: FormGroup) { diff --git a/src/Ombi/ClientApp/src/app/settings/logs/logs.component.scss b/src/Ombi/ClientApp/src/app/settings/logs/logs.component.scss index 637848b40..18096ace2 100644 --- a/src/Ombi/ClientApp/src/app/settings/logs/logs.component.scss +++ b/src/Ombi/ClientApp/src/app/settings/logs/logs.component.scss @@ -1,8 +1,13 @@ .small-middle-container{ margin: auto; - width: 80%; + width: 85%; + margin-top:10px; } .code-block { - font-size: 10px; + font-size: 12px; +} + +::ng-deep .dark .code-block { + color:#FFF !important; } \ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/settings/massemail/massemail.component.html b/src/Ombi/ClientApp/src/app/settings/massemail/massemail.component.html index 5c51c68ca..a858b98d8 100644 --- a/src/Ombi/ClientApp/src/app/settings/massemail/massemail.component.html +++ b/src/Ombi/ClientApp/src/app/settings/massemail/massemail.component.html @@ -1,5 +1,5 @@  - +
Mass Email @@ -47,4 +47,5 @@ -
\ No newline at end of file + +
\ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/settings/massemail/massemail.component.scss b/src/Ombi/ClientApp/src/app/settings/massemail/massemail.component.scss new file mode 100644 index 000000000..018bebef8 --- /dev/null +++ b/src/Ombi/ClientApp/src/app/settings/massemail/massemail.component.scss @@ -0,0 +1,5 @@ +.small-middle-container{ + margin: auto; + width: 85%; + margin-top:10px; +} \ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/settings/massemail/massemail.component.ts b/src/Ombi/ClientApp/src/app/settings/massemail/massemail.component.ts index 91693103f..17beb5405 100644 --- a/src/Ombi/ClientApp/src/app/settings/massemail/massemail.component.ts +++ b/src/Ombi/ClientApp/src/app/settings/massemail/massemail.component.ts @@ -5,6 +5,7 @@ import { IdentityService, NotificationMessageService, NotificationService, Setti @Component({ templateUrl: "./massemail.component.html", + styleUrls: ["./massemail.component.scss"] }) export class MassEmailComponent implements OnInit { diff --git a/src/Ombi/ClientApp/src/app/settings/notifications/cloudmobile.component.html b/src/Ombi/ClientApp/src/app/settings/notifications/cloudmobile.component.html new file mode 100644 index 000000000..a569a6ef4 --- /dev/null +++ b/src/Ombi/ClientApp/src/app/settings/notifications/cloudmobile.component.html @@ -0,0 +1,55 @@ + + +
+
+ Mobile Notifications + +
+
+
+ + + + + + + + + + + + + + +
+ + + + + Username {{element.username}}
+ + +
+ + Message + + +
+
+ +
+
+
+ +
+ +
+ +
+
+ +
+
+
+
+
\ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/settings/notifications/cloudmobile.coponent.ts b/src/Ombi/ClientApp/src/app/settings/notifications/cloudmobile.coponent.ts new file mode 100644 index 000000000..e78860e09 --- /dev/null +++ b/src/Ombi/ClientApp/src/app/settings/notifications/cloudmobile.coponent.ts @@ -0,0 +1,82 @@ +import { Component, OnInit } from "@angular/core"; +import { FormBuilder, FormGroup } from "@angular/forms"; + +import { IMobileNotifcationSettings, IMobileUsersViewModel, INotificationTemplates, NotificationType, ICloudMobileDevices, ICloudMobileModel } from "../../interfaces"; +import { TesterService } from "../../services"; +import { NotificationService } from "../../services"; +import { MobileService, SettingsService } from "../../services"; +import { CloudMobileService } from "../../services/cloudmobile.service"; +import { SelectionModel } from "@angular/cdk/collections"; +import { MatTableDataSource } from "@angular/material/table"; + +@Component({ + templateUrl: "./cloudmobile.component.html", +}) +export class CloudMobileComponent implements OnInit { + + public NotificationType = NotificationType; + public templates: INotificationTemplates[]; + public form: FormGroup; + public devices: MatTableDataSource; + public selection = new SelectionModel(true, []); + displayedColumns: string[] = ['select', 'username']; + public message: string; + + constructor(private settingsService: SettingsService, + private notificationService: NotificationService, + private fb: FormBuilder, + private mobileService: CloudMobileService) { } + + public async ngOnInit() { + this.settingsService.getMobileNotificationSettings().subscribe(x => { + this.templates = x.notificationTemplates; + + this.form = this.fb.group({ + }); + }); + + var result = await this.mobileService.getDevices().toPromise(); + if (result.length > 0) { + this.devices = new MatTableDataSource(result); + } + } + + public onSubmit(form: FormGroup) { + if (form.invalid) { + this.notificationService.error("Please check your entered values"); + return; + } + + const settings = form.value; + settings.notificationTemplates = this.templates; + + this.settingsService.saveMobileNotificationSettings(settings).subscribe(x => { + if (x) { + this.notificationService.success("Successfully saved the Mobile settings"); + } else { + this.notificationService.success("There was an error when saving the Mobile settings"); + } + }); + + } + + public async sendMessage(form: FormGroup) { + if (form.invalid) { + this.notificationService.error("Please check your entered values"); + return; + } + if (this.selection.selected.length <= 0) { + this.notificationService.warning("Warning", "Please select a user to send the test notification"); + return; + } + + await this.selection.selected.forEach(async (u) => { + await this.mobileService.send(u.userId, this.message); + + this.notificationService.success( + "Successfully sent a Mobile message"); + + + }); + } +} diff --git a/src/Ombi/ClientApp/src/app/settings/notifications/discord.component.html b/src/Ombi/ClientApp/src/app/settings/notifications/discord.component.html index fd907f1b2..140198c94 100644 --- a/src/Ombi/ClientApp/src/app/settings/notifications/discord.component.html +++ b/src/Ombi/ClientApp/src/app/settings/notifications/discord.component.html @@ -1,56 +1,64 @@ - - -
-
+ +
+
Discord Notifications -
-
- -
-
- - +
+
+ +
+
+
+
+ Enable +
+
+
-
- - -
- - - The Webhook Url is required -
- -
- -
- +
+
+ + Webhook Url + + + + Username + + +
+
+ + Icon + + +
+ +
+
-
+
- +
+
+ +
+
-
-
- +
+
+ +
+
-
- - - -
-
- -
-
- -
+ +
-
- +
+ +
\ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/settings/notifications/discord.component.ts b/src/Ombi/ClientApp/src/app/settings/notifications/discord.component.ts index bbd43e974..73f271894 100644 --- a/src/Ombi/ClientApp/src/app/settings/notifications/discord.component.ts +++ b/src/Ombi/ClientApp/src/app/settings/notifications/discord.component.ts @@ -8,6 +8,7 @@ import { SettingsService } from "../../services"; @Component({ templateUrl: "./discord.component.html", + styleUrls: ["./notificationtemplate.component.scss"] }) export class DiscordComponent implements OnInit { @@ -28,6 +29,7 @@ export class DiscordComponent implements OnInit { enabled: [x.enabled], username: [x.username], webhookUrl: [x.webhookUrl, [Validators.required]], + icon: [x.icon] }); }); diff --git a/src/Ombi/ClientApp/src/app/settings/notifications/emailnotification.component.html b/src/Ombi/ClientApp/src/app/settings/notifications/emailnotification.component.html index d73c76f06..33aa3a06c 100644 --- a/src/Ombi/ClientApp/src/app/settings/notifications/emailnotification.component.html +++ b/src/Ombi/ClientApp/src/app/settings/notifications/emailnotification.component.html @@ -1,105 +1,119 @@ - - -
+ +
Email Notifications -
-
- -
-
- - -
-
- -
-
- -
-
- -
-
- +
+
+ +
+
+
+ Enable +
+
+ Enable SMTP Authentication + +
+
+ Disable TLS/SSL +
+
+ Disable Certificate + Checking +
+
-
-
-
- -
-
-
- - - - The Host is required -
+
+
+ + SMTP Host + + + Host is required + + + + SMTP Port + + + Port is required + + +
+
+ + Email Sender + + + Email Sender Address is required + + + Email Sender Address needs to be a valid email address + + + + Sender Name + + +
-
- -
- - The Port is required -
-
+
+ + Admin Email + + + Admin Email is required + + + Admin Email needs to be a valid email address + + +
-
- -
- - The Email Sender Address is required - The Email Sender Address needs to be a valid email address -
-
- -
-
-
-
-
- -
- - - The Admin Email Address is required - The Admin Email needs to be a valid email address - -
- - -
- - - - The Username is required -
- -
- - - - The Password is required -
+
+ + Username + + + Username is required + + -
-
- - + + Password + + + Password is required + + +
+
+
+
+
+ +
+
+
+
+ +
- -
+ +
-
+
+ +
\ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/settings/notifications/emailnotification.component.ts b/src/Ombi/ClientApp/src/app/settings/notifications/emailnotification.component.ts index f67828afb..f880891a5 100644 --- a/src/Ombi/ClientApp/src/app/settings/notifications/emailnotification.component.ts +++ b/src/Ombi/ClientApp/src/app/settings/notifications/emailnotification.component.ts @@ -9,6 +9,7 @@ import { SettingsService } from "../../services"; @Component({ templateUrl: "./emailnotification.component.html", + styleUrls: ["./notificationtemplate.component.scss"] }) export class EmailNotificationComponent implements OnInit { public NotificationType = NotificationType; diff --git a/src/Ombi/ClientApp/src/app/settings/notifications/gotify.component.html b/src/Ombi/ClientApp/src/app/settings/notifications/gotify.component.html index 9148cb880..0b732fd74 100644 --- a/src/Ombi/ClientApp/src/app/settings/notifications/gotify.component.html +++ b/src/Ombi/ClientApp/src/app/settings/notifications/gotify.component.html @@ -1,6 +1,6 @@  -
+
Gotify Notifications
diff --git a/src/Ombi/ClientApp/src/app/settings/notifications/gotify.component.ts b/src/Ombi/ClientApp/src/app/settings/notifications/gotify.component.ts index f6c08d41b..94345a391 100644 --- a/src/Ombi/ClientApp/src/app/settings/notifications/gotify.component.ts +++ b/src/Ombi/ClientApp/src/app/settings/notifications/gotify.component.ts @@ -8,6 +8,7 @@ import { SettingsService } from "../../services"; @Component({ templateUrl: "./gotify.component.html", + styleUrls: ["./notificationtemplate.component.scss"] }) export class GotifyComponent implements OnInit { public NotificationType = NotificationType; diff --git a/src/Ombi/ClientApp/src/app/settings/notifications/mattermost.component.html b/src/Ombi/ClientApp/src/app/settings/notifications/mattermost.component.html index c1e308315..ea18e07e5 100644 --- a/src/Ombi/ClientApp/src/app/settings/notifications/mattermost.component.html +++ b/src/Ombi/ClientApp/src/app/settings/notifications/mattermost.component.html @@ -1,6 +1,6 @@  -
+
Mattermost Notifications
diff --git a/src/Ombi/ClientApp/src/app/settings/notifications/mattermost.component.ts b/src/Ombi/ClientApp/src/app/settings/notifications/mattermost.component.ts index 65a33a4f3..cb5a85ff1 100644 --- a/src/Ombi/ClientApp/src/app/settings/notifications/mattermost.component.ts +++ b/src/Ombi/ClientApp/src/app/settings/notifications/mattermost.component.ts @@ -8,6 +8,7 @@ import { SettingsService } from "../../services"; @Component({ templateUrl: "./mattermost.component.html", + styleUrls: ["./notificationtemplate.component.scss"] }) export class MattermostComponent implements OnInit { diff --git a/src/Ombi/ClientApp/src/app/settings/notifications/mobile.component.html b/src/Ombi/ClientApp/src/app/settings/notifications/mobile.component.html index 2b7ea9b2c..b01a8b459 100644 --- a/src/Ombi/ClientApp/src/app/settings/notifications/mobile.component.html +++ b/src/Ombi/ClientApp/src/app/settings/notifications/mobile.component.html @@ -1,8 +1,8 @@  -
+
- Mobile Notifications + Legacy Mobile Notifications
@@ -35,7 +35,7 @@
- +
+ Enable
+
- + Disable TV
- + Disable Movies
- + Disable Music
- -
- -
+ + Subject + +
- -
- -
+ + Message + +
- - - + + - - +
@@ -62,15 +65,15 @@

-
- -
- + + Add External Email (For users that are not in Ombi) + +
- +
@@ -80,7 +83,7 @@ {{email}}
- +
diff --git a/src/Ombi/ClientApp/src/app/settings/notifications/newsletter.component.ts b/src/Ombi/ClientApp/src/app/settings/notifications/newsletter.component.ts index eae7176e2..cdefe9682 100644 --- a/src/Ombi/ClientApp/src/app/settings/notifications/newsletter.component.ts +++ b/src/Ombi/ClientApp/src/app/settings/notifications/newsletter.component.ts @@ -6,6 +6,7 @@ import { TesterService } from "../../services/applications/tester.service"; @Component({ templateUrl: "./newsletter.component.html", + styleUrls: ["./notificationtemplate.component.scss"] }) export class NewsletterComponent implements OnInit { diff --git a/src/Ombi/ClientApp/src/app/settings/notifications/notificationtemplate.component.html b/src/Ombi/ClientApp/src/app/settings/notifications/notificationtemplate.component.html index 1fd475a38..02551a345 100644 --- a/src/Ombi/ClientApp/src/app/settings/notifications/notificationtemplate.component.html +++ b/src/Ombi/ClientApp/src/app/settings/notifications/notificationtemplate.component.html @@ -1,36 +1,26 @@ - - + +

+ + + + + {{NotificationType[template.notificationType] | humanize}} + + - - - -
-
- -
-
- -
-
- -
- -
- -
-
+
+ Enable +
-
- -
- -
-
-
-
+ + + -
-
-
+ + + +
+ +
\ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/settings/notifications/notificationtemplate.component.scss b/src/Ombi/ClientApp/src/app/settings/notifications/notificationtemplate.component.scss index fa0219742..33f8a2d6c 100644 --- a/src/Ombi/ClientApp/src/app/settings/notifications/notificationtemplate.component.scss +++ b/src/Ombi/ClientApp/src/app/settings/notifications/notificationtemplate.component.scss @@ -1,4 +1,5 @@ -::ng-deep ngb-accordion > div.card { +@import "~styles/shared.scss"; +::ng-deep ngb-accordion > div.card { color:white; padding-top: 0px; } @@ -6,3 +7,9 @@ ::ng-deep ngb-accordion > div.card > div.card-header { padding:0px; } + +.small-middle-container{ + margin: auto; + width: 95%; + margin-top:10px; +} \ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/settings/notifications/pushbullet.component.html b/src/Ombi/ClientApp/src/app/settings/notifications/pushbullet.component.html index d78096308..3c4db7698 100644 --- a/src/Ombi/ClientApp/src/app/settings/notifications/pushbullet.component.html +++ b/src/Ombi/ClientApp/src/app/settings/notifications/pushbullet.component.html @@ -1,6 +1,6 @@  -
+
Pushbullet Notifications
diff --git a/src/Ombi/ClientApp/src/app/settings/notifications/pushbullet.component.ts b/src/Ombi/ClientApp/src/app/settings/notifications/pushbullet.component.ts index d65a0e3b5..541fc3b52 100644 --- a/src/Ombi/ClientApp/src/app/settings/notifications/pushbullet.component.ts +++ b/src/Ombi/ClientApp/src/app/settings/notifications/pushbullet.component.ts @@ -8,6 +8,7 @@ import { SettingsService } from "../../services"; @Component({ templateUrl: "./pushbullet.component.html", + styleUrls: ["./notificationtemplate.component.scss"] }) export class PushbulletComponent implements OnInit { public NotificationType = NotificationType; diff --git a/src/Ombi/ClientApp/src/app/settings/notifications/pushover.component.html b/src/Ombi/ClientApp/src/app/settings/notifications/pushover.component.html index 499263dec..8ce9b401d 100644 --- a/src/Ombi/ClientApp/src/app/settings/notifications/pushover.component.html +++ b/src/Ombi/ClientApp/src/app/settings/notifications/pushover.component.html @@ -1,6 +1,6 @@  -
+
Pushover Notifications
diff --git a/src/Ombi/ClientApp/src/app/settings/notifications/pushover.component.ts b/src/Ombi/ClientApp/src/app/settings/notifications/pushover.component.ts index 64f339192..825afc8ac 100644 --- a/src/Ombi/ClientApp/src/app/settings/notifications/pushover.component.ts +++ b/src/Ombi/ClientApp/src/app/settings/notifications/pushover.component.ts @@ -8,6 +8,7 @@ import { SettingsService } from "../../services"; @Component({ templateUrl: "./pushover.component.html", + styleUrls: ["./notificationtemplate.component.scss"] }) export class PushoverComponent implements OnInit { public NotificationType = NotificationType; diff --git a/src/Ombi/ClientApp/src/app/settings/notifications/slack.component.html b/src/Ombi/ClientApp/src/app/settings/notifications/slack.component.html index c4e5418df..15ef796fc 100644 --- a/src/Ombi/ClientApp/src/app/settings/notifications/slack.component.html +++ b/src/Ombi/ClientApp/src/app/settings/notifications/slack.component.html @@ -1,6 +1,6 @@  -
+
Slack Notifications
diff --git a/src/Ombi/ClientApp/src/app/settings/notifications/slack.component.ts b/src/Ombi/ClientApp/src/app/settings/notifications/slack.component.ts index 7ea53d0fb..c32d44432 100644 --- a/src/Ombi/ClientApp/src/app/settings/notifications/slack.component.ts +++ b/src/Ombi/ClientApp/src/app/settings/notifications/slack.component.ts @@ -8,6 +8,7 @@ import { SettingsService } from "../../services"; @Component({ templateUrl: "./slack.component.html", + styleUrls: ["./notificationtemplate.component.scss"] }) export class SlackComponent implements OnInit { public NotificationType = NotificationType; diff --git a/src/Ombi/ClientApp/src/app/settings/notifications/telegram.component.html b/src/Ombi/ClientApp/src/app/settings/notifications/telegram.component.html index c456281f8..d89d14483 100644 --- a/src/Ombi/ClientApp/src/app/settings/notifications/telegram.component.html +++ b/src/Ombi/ClientApp/src/app/settings/notifications/telegram.component.html @@ -1,6 +1,6 @@  -
+
Telegram Notifications
diff --git a/src/Ombi/ClientApp/src/app/settings/notifications/telegram.component.ts b/src/Ombi/ClientApp/src/app/settings/notifications/telegram.component.ts index 7d216901b..085a7ee75 100644 --- a/src/Ombi/ClientApp/src/app/settings/notifications/telegram.component.ts +++ b/src/Ombi/ClientApp/src/app/settings/notifications/telegram.component.ts @@ -8,6 +8,7 @@ import { SettingsService } from "../../services"; @Component({ templateUrl: "./telegram.component.html", + styleUrls: ["./notificationtemplate.component.scss"] }) export class TelegramComponent implements OnInit { diff --git a/src/Ombi/ClientApp/src/app/settings/notifications/twilio/twilio.component.html b/src/Ombi/ClientApp/src/app/settings/notifications/twilio/twilio.component.html new file mode 100644 index 000000000..9c9d0ea1e --- /dev/null +++ b/src/Ombi/ClientApp/src/app/settings/notifications/twilio/twilio.component.html @@ -0,0 +1,22 @@ + + +
+
+ Twilio + Below are the supported integrations with Twilio + + + + + + + + +
+
+ +
+
+ +
+
\ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/settings/notifications/twilio/twilio.component.ts b/src/Ombi/ClientApp/src/app/settings/notifications/twilio/twilio.component.ts new file mode 100644 index 000000000..4f2364107 --- /dev/null +++ b/src/Ombi/ClientApp/src/app/settings/notifications/twilio/twilio.component.ts @@ -0,0 +1,55 @@ +import { Component, OnInit } from "@angular/core"; +import { FormBuilder, FormGroup, Validators } from "@angular/forms"; + +import { INotificationTemplates, ITwilioSettings, NotificationType } from "../../../interfaces"; +import { TesterService } from "../../../services"; +import { NotificationService } from "../../../services"; +import { SettingsService } from "../../../services"; + +@Component({ + templateUrl: "./twilio.component.html", +}) +export class TwilioComponent implements OnInit { + public NotificationType = NotificationType; + public templates: INotificationTemplates[]; + public form: FormGroup; + + constructor(private settingsService: SettingsService, + private notificationService: NotificationService, + private fb: FormBuilder, + private testerService: TesterService) { } + + public ngOnInit() { + this.settingsService.getTwilioSettings().subscribe(x => { + this.templates = x.whatsAppSettings.notificationTemplates; + + this.form = this.fb.group({ + whatsAppSettings: this.fb.group({ + enabled: [x.whatsAppSettings.enabled], + accountSid: [x.whatsAppSettings.accountSid], + authToken: [x.whatsAppSettings.authToken], + from: [x.whatsAppSettings.from], + }), + }); + }); + } + + public onSubmit(form: FormGroup) { + if (form.invalid) { + this.notificationService.error("Please check your entered values"); + return; + } + + const settings = form.value; + settings.whatsAppSettings.notificationTemplates = this.templates; + + this.settingsService.saveTwilioSettings(settings).subscribe(x => { + if (x) { + this.notificationService.success("Successfully saved the Twilio settings"); + } else { + this.notificationService.success("There was an error when saving the Twilio settings"); + } + }); + + } +} diff --git a/src/Ombi/ClientApp/src/app/settings/notifications/twilio/whatsapp.component.html b/src/Ombi/ClientApp/src/app/settings/notifications/twilio/whatsapp.component.html new file mode 100644 index 000000000..9ce863df7 --- /dev/null +++ b/src/Ombi/ClientApp/src/app/settings/notifications/twilio/whatsapp.component.html @@ -0,0 +1,37 @@ +
+
+
+
+
+ Enable +
+ +
+ + + +
+
+ + + +
+
+ + + +
+
+
+ +
+
+
+ +
+ +
+ +
+
+
\ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/settings/notifications/twilio/whatsapp.component.ts b/src/Ombi/ClientApp/src/app/settings/notifications/twilio/whatsapp.component.ts new file mode 100644 index 000000000..80222e426 --- /dev/null +++ b/src/Ombi/ClientApp/src/app/settings/notifications/twilio/whatsapp.component.ts @@ -0,0 +1,37 @@ +import { Component, Input } from "@angular/core"; +import { FormGroup } from "@angular/forms"; +import { TesterService, NotificationService } from "../../../services"; +import { INotificationTemplates, NotificationType } from "../../../interfaces"; + + + +@Component({ + templateUrl: "./whatsapp.component.html", + selector: "app-whatsapp" +}) +export class WhatsAppComponent { + + public NotificationType = NotificationType; + @Input() public templates: INotificationTemplates[]; + @Input() public form: FormGroup; + + constructor(private testerService: TesterService, + private notificationService: NotificationService) { } + + + public test(form: FormGroup) { + if (form.invalid) { + this.notificationService.error("Please check your entered values"); + return; + } + + this.testerService.whatsAppTest(form.get("whatsAppSettings").value).subscribe(x => { + if (x) { + this.notificationService.success( "Successfully sent a WhatsApp message, please check the appropriate channel"); + } else { + this.notificationService.error("There was an error when sending the WhatsApp message. Please check your settings"); + } + }); + + } +} diff --git a/src/Ombi/ClientApp/src/app/settings/notifications/webhook.component.html b/src/Ombi/ClientApp/src/app/settings/notifications/webhook.component.html new file mode 100644 index 000000000..1ee583104 --- /dev/null +++ b/src/Ombi/ClientApp/src/app/settings/notifications/webhook.component.html @@ -0,0 +1,49 @@ + + +
+
+ Webhook Notifications +
+
+ +
+
+ + +
+
+ +
+ + + + The Webhook URL is required +
+ +
+ + + + The Application Token is required +
+ +
+
+ +
+
+ +
+
+ +
+
+
+
+
+
\ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/settings/notifications/webhook.component.ts b/src/Ombi/ClientApp/src/app/settings/notifications/webhook.component.ts new file mode 100644 index 000000000..2a7069b4c --- /dev/null +++ b/src/Ombi/ClientApp/src/app/settings/notifications/webhook.component.ts @@ -0,0 +1,65 @@ +import { Component, OnInit } from "@angular/core"; +import { FormBuilder, FormGroup, Validators } from "@angular/forms"; + +import { INotificationTemplates, IWebhookNotificationSettings, NotificationType } from "../../interfaces"; +import { TesterService } from "../../services"; +import { NotificationService } from "../../services"; +import { SettingsService } from "../../services"; + +@Component({ + templateUrl: "./webhook.component.html", + styleUrls: ["./notificationtemplate.component.scss"] +}) +export class WebhookComponent implements OnInit { + public NotificationType = NotificationType; + public templates: INotificationTemplates[]; + public form: FormGroup; + + constructor(private settingsService: SettingsService, + private notificationService: NotificationService, + private fb: FormBuilder, + private testerService: TesterService) { } + + public ngOnInit() { + this.settingsService.getWebhookNotificationSettings().subscribe(x => { + this.form = this.fb.group({ + enabled: [x.enabled], + webhookUrl: [x.webhookUrl, [Validators.required]], + applicationToken: [x.applicationToken], + }); + }); + } + + public onSubmit(form: FormGroup) { + if (form.invalid) { + this.notificationService.error("Please check your entered values"); + return; + } + + const settings = form.value; + + this.settingsService.saveWebhookNotificationSettings(settings).subscribe(x => { + if (x) { + this.notificationService.success("Successfully saved the Webhook settings"); + } else { + this.notificationService.success("There was an error when saving the Webhook settings"); + } + }); + + } + + public test(form: FormGroup) { + if (form.invalid) { + this.notificationService.error("Please check your entered values"); + return; + } + + this.testerService.webhookTest(form.value).subscribe(x => { + if (x) { + this.notificationService.success("Successfully sent a Webhook message"); + } else { + this.notificationService.error("There was an error when sending the Webhook message. Please check your settings"); + } + }); + } +} diff --git a/src/Ombi/ClientApp/src/app/settings/ombi/ombi.component.html b/src/Ombi/ClientApp/src/app/settings/ombi/ombi.component.html index 48a5d8883..63d9ce2a1 100644 --- a/src/Ombi/ClientApp/src/app/settings/ombi/ombi.component.html +++ b/src/Ombi/ClientApp/src/app/settings/ombi/ombi.component.html @@ -1,65 +1,78 @@  - +
-
- Ombi Configuration - -
- -
- - - - - - +
+ Ombi Configuration + +
+
+ + Base URL + + +
+
+ + Api Key + + -
- -
- - -
-
-
- -
-
-
-
-
-
-
- - Do not send Notifications if a User has the Auto Approve permission -
- - Hide requests from other users - -
- - Ignore any certificate errors - -
- - Allow us to collect anonymous analytical data e.g. browser used - -
- - - -- - - {{lang.nativeName}} - - - -
-
-
- + +
+
+ + Do not send Notifications if a User has the Auto Approve permission +
+
+ + Hide requests from other users + +
+
+ + Auto Delete Available Requests + +
+
+ + Delete After Days of Availbility + + +
+
+ + Ignore any certificate errors (Please restart after changing) + +
+
+ + Allow us to collect anonymous analytical data e.g. browser used + +
+ +
+ + + -- + + {{lang.nativeName}} + + + +
+
+
+ +
+
-
-
- +
+
\ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/settings/ombi/ombi.component.scss b/src/Ombi/ClientApp/src/app/settings/ombi/ombi.component.scss new file mode 100644 index 000000000..65e7e6bc9 --- /dev/null +++ b/src/Ombi/ClientApp/src/app/settings/ombi/ombi.component.scss @@ -0,0 +1,27 @@ +@import "~styles/shared.scss"; +.small-middle-container { + margin: auto; + width: 95%; + margin-top: 10px; +} + +textarea { + min-height: 100px; + height: auto; + max-height: 800px; +} + +.row { + display: block; +} + +button, [type="button"]{ + padding: 0; + border: none; + background: transparent; + color: white; +} + +::ng-deep .mat-form-field-suffix .mat-icon{ + font-size:120%; +} \ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/settings/ombi/ombi.component.ts b/src/Ombi/ClientApp/src/app/settings/ombi/ombi.component.ts index 4aec1a57c..d2b7ba942 100644 --- a/src/Ombi/ClientApp/src/app/settings/ombi/ombi.component.ts +++ b/src/Ombi/ClientApp/src/app/settings/ombi/ombi.component.ts @@ -5,10 +5,11 @@ import { ILanguageRefine, IOmbiSettings } from "../../interfaces"; import { NotificationService } from "../../services"; import { SettingsService } from "../../services"; -import * as languageData from "../../../other/iso-lang.json"; +import languageData from "./../../../other/iso-lang.json"; @Component({ templateUrl: "./ombi.component.html", + styleUrls: ["./ombi.component.scss"], }) export class OmbiComponent implements OnInit { @@ -29,9 +30,12 @@ export class OmbiComponent implements OnInit { doNotSendNotificationsForAutoApprove: [x.doNotSendNotificationsForAutoApprove], hideRequestsUsers: [x.hideRequestsUsers], defaultLanguageCode: [x.defaultLanguageCode], + disableHealthChecks: [x.disableHealthChecks], + autoDeleteAvailableRequests: [x.autoDeleteAvailableRequests], + autoDeleteAfterDays: [x.autoDeleteAfterDays] }); }); - this.langauges = languageData; + this.langauges = languageData } public refreshApiKey() { diff --git a/src/Ombi/ClientApp/src/app/settings/plex/plex.component.html b/src/Ombi/ClientApp/src/app/settings/plex/plex.component.html index 6310a9cf1..eb143bccb 100644 --- a/src/Ombi/ClientApp/src/app/settings/plex/plex.component.html +++ b/src/Ombi/ClientApp/src/app/settings/plex/plex.component.html @@ -1,196 +1,188 @@  -
-
- Advanced - -
-
-
-
+
+
Plex Configuration -
+
-
-
- - +
+ Enable +
-
-
- +
+ Advanced +
+
- - - -
- - -
-
-
- +
+ + +
+ +
+
+
+
+ + +
+ + Server Name + +
-
-
-
- -
- -
- -
+
+ + Hostname or IP + + + + + Port + + + + + SSL + +
+
+ + Plex Authorization Token + + + + + Machine Identifier + + +
+
+
+ + Episode Batch Size + +
- -
- -
- +
+
+ +
+
+
+ + Server + + + {{s.name}} + +
- -
- -
- -
+
+ +
+ Note: if nothing is selected, we will monitor all libraries +
+
+
- -
-
- - +
+
+
+
+
+
+ {{lib.title}} +
- - -
- -
- -
+
+
+
+
+ +
+ + Username + +
- -
- -
- -
+
+ + Password + +
- -
-
- -
- -
-
-
- -
+
+
+
+
+
+
-
- -
-
-
-
-
- -
-
-
- - - -
-
+
-
- -
- Note: if nothing is selected, we will monitor all libraries
-
- -
-
-
-
-
-
- - -
-
-
+
- -
- -
- -
-
-
-
- -
+
-
- - - -
- -
-
-
-
-
-
-
-
-
- -
-
-
-
+ + + + + +
- +
+
+ \ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/settings/plex/plex.component.scss b/src/Ombi/ClientApp/src/app/settings/plex/plex.component.scss new file mode 100644 index 000000000..18f044f29 --- /dev/null +++ b/src/Ombi/ClientApp/src/app/settings/plex/plex.component.scss @@ -0,0 +1,17 @@ +@import "~styles/shared.scss"; +.small-middle-container { + margin: auto; + width: 95%; + margin-top: 10px; +} + +.col-8 { + display: inline-table; +} +.col-md-5 { + display: inline-table; +} + +.row { + display: block; +} diff --git a/src/Ombi/ClientApp/src/app/settings/plex/plex.component.ts b/src/Ombi/ClientApp/src/app/settings/plex/plex.component.ts index df09e8167..7509fb45a 100644 --- a/src/Ombi/ClientApp/src/app/settings/plex/plex.component.ts +++ b/src/Ombi/ClientApp/src/app/settings/plex/plex.component.ts @@ -1,12 +1,15 @@ -import { Component, OnDestroy, OnInit } from "@angular/core"; +import { Component, OnDestroy, OnInit, ViewChild } from "@angular/core"; import { Subject } from "rxjs"; import { takeUntil } from "rxjs/operators"; import { IPlexLibrariesSettings, IPlexServer, IPlexServerResponse, IPlexServerViewModel, IPlexSettings } from "../../interfaces"; import { JobService, NotificationService, PlexService, SettingsService, TesterService } from "../../services"; +import { MatTabChangeEvent, MatTabGroup } from "@angular/material/tabs"; +import {FormControl} from '@angular/forms'; @Component({ templateUrl: "./plex.component.html", + styleUrls: ["./plex.component.scss"] }) export class PlexComponent implements OnInit, OnDestroy { public settings: IPlexSettings; @@ -14,6 +17,8 @@ export class PlexComponent implements OnInit, OnDestroy { public username: string; public password: string; public serversButton = false; + selected = new FormControl(0); + @ViewChild("tabGroup", {static: false}) public tagGroup: MatTabGroup; public advanced = false; @@ -67,18 +72,26 @@ export class PlexComponent implements OnInit, OnDestroy { }); } - public addTab() { - if (this.settings.servers == null) { + public addTab(event: MatTabChangeEvent) { + + const tabName = event.tab.textLabel; + if (tabName == "Add Server"){ + + if (this.settings.servers == null) { this.settings.servers = []; - } - this.settings.servers.push( { name: "New*", id: Math.floor(Math.random() * (99999 - 0 + 1) + 1) }); + } + this.settings.servers.push( { name: "New" + this.settings.servers.length + "*", id: Math.floor(Math.random() * (99999 - 0 + 1) + 1) }); + //this.tagGroup.selectedIndex = (0); + this.selected.setValue(this.settings.servers.length - 1); + } } public removeServer(server: IPlexServer) { const index = this.settings.servers.indexOf(server, 0); if (index > -1) { this.settings.servers.splice(index, 1); + this.selected.setValue(this.settings.servers.length - 1); } } diff --git a/src/Ombi/ClientApp/src/app/settings/radarr/radarr.component.html b/src/Ombi/ClientApp/src/app/settings/radarr/radarr.component.html index 08a8035c2..a6016b73f 100644 --- a/src/Ombi/ClientApp/src/app/settings/radarr/radarr.component.html +++ b/src/Ombi/ClientApp/src/app/settings/radarr/radarr.component.html @@ -1,136 +1,111 @@  -
+
Radarr Settings -
- Advanced - -
-
-
-
-
- - +
+ +
+
+
+
+ Enable +
+
+ V3 +
+
+ Scan for Availability +
+
+ + Do not search for Movies + +
+
- - - -
- - - -
- -
- - - -
- - -
- - - -
-
-
- - - +
+
+
+ +
+ + Hostname or IP + + + + Port + + + + SSL +
-
-
- -
- +
+
+ + API key + +
-
-
-
- -
- -
- - +
+ + Base URL + +
- - -
- -
- - - +
+ +
+
+
-
- - +
+ + Quality Profiles + + + {{quality.name}} + + + -
- -
-
-
-
-
-
-
- - -
-
+
+
+ +
+
+ + Default Root Folder + + + {{folder.path}} + + + -
-
- +
+
+ + Default Minimum Availability + + + {{min.name}} + + +
- - -
-
- +
+
+
+
+ +
+
+
diff --git a/src/Ombi/ClientApp/src/app/settings/radarr/radarr.component.scss b/src/Ombi/ClientApp/src/app/settings/radarr/radarr.component.scss new file mode 100644 index 000000000..2898f062e --- /dev/null +++ b/src/Ombi/ClientApp/src/app/settings/radarr/radarr.component.scss @@ -0,0 +1,17 @@ +@import "~styles/shared.scss"; +.small-middle-container { + margin: auto; + width: 95%; + margin-top: 10px; +} + +.col-8 { + display: inline-table; +} +.col-md-5 { + display: inline-table; +} + +.row { + display: block; +} \ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/settings/radarr/radarr.component.ts b/src/Ombi/ClientApp/src/app/settings/radarr/radarr.component.ts index d68396a66..905a72f36 100644 --- a/src/Ombi/ClientApp/src/app/settings/radarr/radarr.component.ts +++ b/src/Ombi/ClientApp/src/app/settings/radarr/radarr.component.ts @@ -10,6 +10,7 @@ import { SettingsService } from "../../services"; @Component({ templateUrl: "./radarr.component.html", + styleUrls: ["./radarr.component.scss"] }) export class RadarrComponent implements OnInit { @@ -18,7 +19,6 @@ export class RadarrComponent implements OnInit { public minimumAvailabilityOptions: IMinimumAvailability[]; public profilesRunning: boolean; public rootFoldersRunning: boolean; - public advanced = false; public form: FormGroup; constructor(private settingsService: SettingsService, @@ -34,7 +34,7 @@ export class RadarrComponent implements OnInit { this.form = this.fb.group({ enabled: [x.enabled], apiKey: [x.apiKey, [Validators.required]], - defaultQualityProfile: [x.defaultQualityProfile, [Validators.required]], + defaultQualityProfile: [+x.defaultQualityProfile, [Validators.required]], defaultRootPath: [x.defaultRootPath, [Validators.required]], ssl: [x.ssl], subDir: [x.subDir], @@ -42,6 +42,8 @@ export class RadarrComponent implements OnInit { port: [x.port, [Validators.required]], addOnly: [x.addOnly], minimumAvailability: [x.minimumAvailability, [Validators.required]], + scanForAvailability: [x.scanForAvailability], + v3: [x.v3] }); if (x.defaultQualityProfile) { diff --git a/src/Ombi/ClientApp/src/app/settings/settings.module.ts b/src/Ombi/ClientApp/src/app/settings/settings.module.ts index e4be0c24e..58ceb9c64 100644 --- a/src/Ombi/ClientApp/src/app/settings/settings.module.ts +++ b/src/Ombi/ClientApp/src/app/settings/settings.module.ts @@ -2,7 +2,6 @@ import { CommonModule } from "@angular/common"; import { NgModule } from "@angular/core"; import { FormsModule, ReactiveFormsModule } from "@angular/forms"; import { RouterModule, Routes } from "@angular/router"; -import { NgbAccordionModule, NgbModule } from "@ng-bootstrap/ng-bootstrap"; // import { TagInputModule } from "ngx-chips"; import { ClipboardModule } from "ngx-clipboard"; @@ -37,6 +36,7 @@ import { PushbulletComponent } from "./notifications/pushbullet.component"; import { PushoverComponent } from "./notifications/pushover.component"; import { SlackComponent } from "./notifications/slack.component"; import { TelegramComponent } from "./notifications/telegram.component"; +import { WebhookComponent } from "./notifications/webhook.component"; import { OmbiComponent } from "./ombi/ombi.component"; import { PlexComponent } from "./plex/plex.component"; import { RadarrComponent } from "./radarr/radarr.component"; @@ -50,11 +50,23 @@ import { WikiComponent } from "./wiki.component"; import { SettingsMenuComponent } from "./settingsmenu.component"; -import { AutoCompleteModule, CalendarModule, DialogModule, InputSwitchModule, InputTextModule, MenuModule, RadioButtonModule, TooltipModule } from "primeng/primeng"; -import { MatMenuModule} from "@angular/material"; +import {AutoCompleteModule } from "primeng/autocomplete"; +import {CalendarModule } from "primeng/calendar"; +import {InputSwitchModule } from "primeng/inputswitch"; +import {InputTextModule } from "primeng/inputtext"; +import {DialogModule } from "primeng/dialog"; +import {MenuModule } from "primeng/menu"; +import {RadioButtonModule } from "primeng/radiobutton"; +import {TooltipModule } from "primeng/tooltip"; + +import { MatMenuModule } from "@angular/material/menu"; import { SharedModule } from "../shared/shared.module"; import { HubService } from "../services/hub.service"; import { LogsComponent } from "./logs/logs.component"; +import { TwilioComponent } from "./notifications/twilio/twilio.component"; +import { WhatsAppComponent } from "./notifications/twilio/whatsapp.component"; +import { CloudMobileComponent } from "./notifications/cloudmobile.coponent"; +import { CloudMobileService } from "../services/cloudmobile.service"; const routes: Routes = [ { path: "Ombi", component: OmbiComponent, canActivate: [AuthGuard] }, @@ -71,7 +83,9 @@ const routes: Routes = [ { path: "Pushover", component: PushoverComponent, canActivate: [AuthGuard] }, { path: "Pushbullet", component: PushbulletComponent, canActivate: [AuthGuard] }, { path: "Gotify", component: GotifyComponent, canActivate: [AuthGuard] }, + { path: "Webhook", component: WebhookComponent, canActivate: [AuthGuard] }, { path: "Mattermost", component: MattermostComponent, canActivate: [AuthGuard] }, + { path: "Twilio", component: TwilioComponent, canActivate: [AuthGuard] }, { path: "UserManagement", component: UserManagementComponent, canActivate: [AuthGuard] }, { path: "Update", component: UpdateComponent, canActivate: [AuthGuard] }, { path: "CouchPotato", component: CouchPotatoComponent, canActivate: [AuthGuard] }, @@ -89,6 +103,7 @@ const routes: Routes = [ { path: "TheMovieDb", component: TheMovieDbComponent, canActivate: [AuthGuard] }, { path: "FailedRequests", component: FailedRequestsComponent, canActivate: [AuthGuard] }, { path: "Logs", component: LogsComponent, canActivate: [AuthGuard] }, + { path: "CloudMobile", component: CloudMobileComponent, canActivate: [AuthGuard] }, ]; @NgModule({ @@ -100,9 +115,7 @@ const routes: Routes = [ MenuModule, InputSwitchModule, InputTextModule, - NgbModule, TooltipModule, - NgbAccordionModule, AutoCompleteModule, CalendarModule, // TagInputModule, @@ -131,6 +144,7 @@ const routes: Routes = [ MattermostComponent, PushbulletComponent, GotifyComponent, + WebhookComponent, UserManagementComponent, UpdateComponent, AboutComponent, @@ -149,6 +163,9 @@ const routes: Routes = [ TheMovieDbComponent, FailedRequestsComponent, LogsComponent, + TwilioComponent, + WhatsAppComponent, + CloudMobileComponent, ], exports: [ RouterModule, @@ -173,6 +190,7 @@ const routes: Routes = [ SystemService, FileDownloadService, TheMovieDbService, + CloudMobileService, ], }) diff --git a/src/Ombi/ClientApp/src/app/settings/settingsmenu.component.html b/src/Ombi/ClientApp/src/app/settings/settingsmenu.component.html index 41a5c5d66..20b843139 100644 --- a/src/Ombi/ClientApp/src/app/settings/settingsmenu.component.html +++ b/src/Ombi/ClientApp/src/app/settings/settingsmenu.component.html @@ -1,63 +1,64 @@ - - + - - - - - - - + + + + + + + + - - + + - - - + + + - - - + + + - + - - - - - - - - - - - + + + + + + + + + + + + + + - - - - - - - -
\ No newline at end of file + + + + + + \ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/settings/sickrage/sickrage.component.html b/src/Ombi/ClientApp/src/app/settings/sickrage/sickrage.component.html index 6307b6332..fb2c6c56a 100644 --- a/src/Ombi/ClientApp/src/app/settings/sickrage/sickrage.component.html +++ b/src/Ombi/ClientApp/src/app/settings/sickrage/sickrage.component.html @@ -1,75 +1,83 @@  -
+
SickRage Settings - - -
-
-
- - + +
+
+
+
+ Enable +
+
+ SSL +
+
+
+
+ +
+ + SickRage Hostname or IP + + The IP/Hostname is required + +
-
- - - - The IP/Hostname is required -
- -
- - - - The Port is required -
- - -
- - - - The API Key is required -
-
-
- - +
+ + Port + + The Port is required + +
+
+ + SickRage API Key + + The API Key is required +
-
-
- -
- + +
+ + SickRage Base URL + +
-
-
-
- -
- +
+
+ +
+
+ + Quality Profiles + + {{quality.display}} + + A Default Quality Profile is required + +
+
- A Default Quality Profile is required - -
-
-
- +
+
+ +
-
-
-
- +
+
+ +
diff --git a/src/Ombi/ClientApp/src/app/settings/sickrage/sickrage.component.scss b/src/Ombi/ClientApp/src/app/settings/sickrage/sickrage.component.scss new file mode 100644 index 000000000..05f28b202 --- /dev/null +++ b/src/Ombi/ClientApp/src/app/settings/sickrage/sickrage.component.scss @@ -0,0 +1,10 @@ +.small-middle-container { + margin: auto; + width: 95%; + margin-top: 10px; +} + +::ng-deep .dark .btn:hover { + box-shadow: 0 5px 11px 0 rgba(255, 255, 255, 0.18), 0 4px 15px 0 rgba(255, 255, 255, 0.15); + color: inherit; +} \ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/settings/sickrage/sickrage.component.ts b/src/Ombi/ClientApp/src/app/settings/sickrage/sickrage.component.ts index 6baf916ca..75e45fe7f 100644 --- a/src/Ombi/ClientApp/src/app/settings/sickrage/sickrage.component.ts +++ b/src/Ombi/ClientApp/src/app/settings/sickrage/sickrage.component.ts @@ -8,6 +8,7 @@ import { SettingsService } from "../../services"; @Component({ templateUrl: "./sickrage.component.html", + styleUrls: ["./sickrage.component.scss"] }) export class SickRageComponent implements OnInit { diff --git a/src/Ombi/ClientApp/src/app/settings/sonarr/sonarr.component.html b/src/Ombi/ClientApp/src/app/settings/sonarr/sonarr.component.html index f016fd56e..2e2e13170 100644 --- a/src/Ombi/ClientApp/src/app/settings/sonarr/sonarr.component.html +++ b/src/Ombi/ClientApp/src/app/settings/sonarr/sonarr.component.html @@ -1,176 +1,176 @@ - -
+ +
Sonarr Settings -
- Advanced - -
- - -
-
-
-
- - +
+ +
+
+
+
+ Enable
-
-
- -
-
-
- - +
+ V3
+
+ Advanced +
+
+ Scan for Availability +
+
- -
- - - -
- -
- - - -
- - -
- - - -
-
-
- - - +
+
+
+ +
+ + Sonarr Hostname or IP + + The IP/Hostname is required + + + Port + + The Port is required + + SSL +
-
-
- -
- +
+ + Sonarr API Key + + The API Key is required + +
+ +
+ + Sonarr Base URL + +
-
-
- -
- +
+ +
- - - +
+ +
+
+
+ + Quality Profiles + + {{quality.name}} + + A Default Quality Profile is required + +
+ +
+
+
+ + Quality Profiles (Anime) + + {{quality.name}} + + A Default Quality Profile is required + +
-
- -
- -
- -
-
+
+
+
+
+
+
+ + Default Root Folders + + {{folder.path}} + + A Default Root Folder is required + +
-
- -
- - -
-
+
+
+
+ + Default Root Folders (Anime) + + {{folder.path}} + + A Default Root Folder (Anime) is required + +
+
-
- -
-
-
- -
- -
- - +
+ +
+
+
+
+
+ + Language Profiles + + {{lang.name}} + + A Language Profile is required + +
+
-
-
-
- - +
+
+ Enable season folders +
+
- -
-
-
- - +
+
+ Do not search +
- -
+
+
- +
-
-
- +
-
-
\ No newline at end of file +
diff --git a/src/Ombi/ClientApp/src/app/settings/sonarr/sonarr.component.scss b/src/Ombi/ClientApp/src/app/settings/sonarr/sonarr.component.scss new file mode 100644 index 000000000..dd9ab640e --- /dev/null +++ b/src/Ombi/ClientApp/src/app/settings/sonarr/sonarr.component.scss @@ -0,0 +1,19 @@ +@import "~styles/shared.scss"; +.small-middle-container { + margin: auto; + width: 95%; + margin-top: 10px; +} + +.col-8 { + display: inline-table; +} +.col-md-5 { + display: inline-table; +} + +::ng-deep .load { + max-width: fit-content; + margin-left: 3em; + padding: 0.5rem 1.14rem; +} diff --git a/src/Ombi/ClientApp/src/app/settings/sonarr/sonarr.component.ts b/src/Ombi/ClientApp/src/app/settings/sonarr/sonarr.component.ts index 11845a06e..157accf02 100644 --- a/src/Ombi/ClientApp/src/app/settings/sonarr/sonarr.component.ts +++ b/src/Ombi/ClientApp/src/app/settings/sonarr/sonarr.component.ts @@ -1,5 +1,5 @@ import { Component, OnInit } from "@angular/core"; -import { FormBuilder, FormGroup, Validators } from "@angular/forms"; +import { FormBuilder, FormControl, FormGroup, Validators } from "@angular/forms"; import { ILanguageProfiles, ISonarrProfile, ISonarrRootFolder } from "../../interfaces"; @@ -11,6 +11,7 @@ import { SettingsService } from "../../services"; @Component({ templateUrl: "./sonarr.component.html", + styleUrls: ["./sonarr.component.scss"] }) export class SonarrComponent implements OnInit { @@ -27,12 +28,32 @@ export class SonarrComponent implements OnInit { public langRunning: boolean; public form: FormGroup; public advanced = false; + formErrors: any; constructor(private settingsService: SettingsService, private sonarrService: SonarrService, private notificationService: NotificationService, private testerService: TesterService, - private fb: FormBuilder) { } + private fb: FormBuilder){} + + onFormValuesChanged() + { + for ( const field in this.formErrors ) + { + if ( !this.formErrors.hasOwnProperty(field) ) + { + continue; + } + // Clear previous errors + this.formErrors[field] = {}; + // Get the control + const control = this.form.get(field); + if ( control && control.dirty && !control.valid && control.value === "Please Select") + { + this.formErrors[field] = control.errors; + } + } + } public ngOnInit() { this.settingsService.getSonarr() @@ -40,8 +61,8 @@ export class SonarrComponent implements OnInit { this.form = this.fb.group({ enabled: [x.enabled], apiKey: [x.apiKey, [Validators.required]], - qualityProfile: [x.qualityProfile, [Validators.required]], - rootPath: [x.rootPath, [Validators.required]], + qualityProfile: [x.qualityProfile, [Validators.required, validateProfile]], + rootPath: [x.rootPath, [Validators.required, validateProfile]], qualityProfileAnime: [x.qualityProfileAnime], rootPathAnime: [x.rootPathAnime], ssl: [x.ssl], @@ -52,6 +73,7 @@ export class SonarrComponent implements OnInit { seasonFolders: [x.seasonFolders], v3: [x.v3], languageProfile: [x.languageProfile], + scanForAvailability: [x.scanForAvailability] }); if (x.qualityProfile) { @@ -66,6 +88,16 @@ export class SonarrComponent implements OnInit { if(x.v3) { this.form.controls.languageProfile.setValidators([Validators.required]); } + + this.formErrors ={ + apiKey: {}, + qualityProfile: {}, + rootPath: {}, + ip: {}, + port: {}, + + }; + this.onFormValuesChanged(); }); this.rootFolders = []; this.qualities = []; @@ -80,9 +112,8 @@ export class SonarrComponent implements OnInit { this.sonarrService.getQualityProfiles(form.value) .subscribe(x => { this.qualities = x; - this.qualities.unshift({ name: "Please Select", id: -1 }); this.qualitiesAnime = x; - + this.qualities.unshift({ name: "Please Select", id: -1 }); this.profilesRunning = false; this.notificationService.success("Successfully retrieved the Quality Profiles"); }); @@ -154,3 +185,10 @@ export class SonarrComponent implements OnInit { }); } } +function validateProfile(qualityProfile): { [key: string]:boolean } | null { + + if (qualityProfile.value !== undefined && (isNaN(qualityProfile.value) || qualityProfile.value == -1)) { + return { 'profileValidation': true }; + } + return null; +} \ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/settings/themoviedb/themoviedb.component.html b/src/Ombi/ClientApp/src/app/settings/themoviedb/themoviedb.component.html index 1b44cc362..57f25a1c4 100644 --- a/src/Ombi/ClientApp/src/app/settings/themoviedb/themoviedb.component.html +++ b/src/Ombi/ClientApp/src/app/settings/themoviedb/themoviedb.component.html @@ -1,50 +1,55 @@  - -
- The Movie Database -
-
-
- - +
+
+ The Movie Database +
+
+
+ + Show Adult Movies +
-
-
- - -
+
+
+ + + + + + {{option.name}} + + + + + + + {{key.name}} + cancel + + + +
+
-
-
- +
+
+ +
+
-
-
\ No newline at end of file +
+
\ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/settings/themoviedb/themoviedb.component.scss b/src/Ombi/ClientApp/src/app/settings/themoviedb/themoviedb.component.scss new file mode 100644 index 000000000..f4210e5a6 --- /dev/null +++ b/src/Ombi/ClientApp/src/app/settings/themoviedb/themoviedb.component.scss @@ -0,0 +1,15 @@ +@import "~styles/shared.scss"; +.small-middle-container { + margin: auto; + width: 95%; + margin-top: 10px; +} + +::ng-deep .dark .btn:hover { + box-shadow: 0 5px 11px 0 rgba(255, 255, 255, 0.18), 0 4px 15px 0 rgba(255, 255, 255, 0.15); + color: inherit; +} + +.example-chip-list { + width: 100%; + } \ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/settings/themoviedb/themoviedb.component.ts b/src/Ombi/ClientApp/src/app/settings/themoviedb/themoviedb.component.ts index 4fc9138a0..228d4fc42 100644 --- a/src/Ombi/ClientApp/src/app/settings/themoviedb/themoviedb.component.ts +++ b/src/Ombi/ClientApp/src/app/settings/themoviedb/themoviedb.component.ts @@ -1,10 +1,13 @@ -import { Component, OnInit } from "@angular/core"; -import { empty, of } from "rxjs"; +import {COMMA, ENTER} from "@angular/cdk/keycodes"; +import { Component, OnInit, ElementRef, ViewChild } from "@angular/core"; +import { MatAutocomplete } from "@angular/material/autocomplete"; -import { ITheMovieDbSettings } from "../../interfaces"; +import { ITheMovieDbSettings, IMovieDbKeyword } from "../../interfaces"; import { NotificationService } from "../../services"; import { SettingsService } from "../../services"; import { TheMovieDbService } from "../../services"; +import { FormBuilder, FormGroup } from "@angular/forms"; +import { debounceTime, switchMap } from "rxjs/operators"; interface IKeywordTag { id: number; @@ -14,17 +17,25 @@ interface IKeywordTag { @Component({ templateUrl: "./themoviedb.component.html", + styleUrls: ["./themoviedb.component.scss"] }) export class TheMovieDbComponent implements OnInit { public settings: ITheMovieDbSettings; public excludedKeywords: IKeywordTag[]; + public tagForm: FormGroup; + public filteredTags: IMovieDbKeyword[]; + @ViewChild('fruitInput') public fruitInput: ElementRef; constructor(private settingsService: SettingsService, private notificationService: NotificationService, - private tmdbService: TheMovieDbService) { } + private tmdbService: TheMovieDbService, + private fb: FormBuilder) { } public ngOnInit() { + this.tagForm = this.fb.group({ + input: null, + }); this.settingsService.getTheMovieDbSettings().subscribe(settings => { this.settings = settings; this.excludedKeywords = settings.excludedKeywordIds @@ -34,29 +45,36 @@ export class TheMovieDbComponent implements OnInit { initial: true, })) : []; + this.excludedKeywords.forEach(key => { + this.tmdbService.getKeyword(key.id).subscribe(keyResult => { + this.excludedKeywords.filter((val, idx) => { + val.name = keyResult.name; + }) + }); + }); }); - } - public autocompleteKeyword = (text: string) => this.tmdbService.getKeywords(text); + this.tagForm + .get("input") + .valueChanges.pipe( + debounceTime(600), + switchMap((value: string) => { + if (value) { + return this.tmdbService.getKeywords(value); + } + }) + ) + .subscribe((r) => (this.filteredTags = r)); - public onAddingKeyword = (tag: string | IKeywordTag) => { - if (typeof tag === "string") { - const id = Number(tag); - return isNaN(id) ? empty() : this.tmdbService.getKeyword(id); - } else { - return of(tag); - } } - public onKeywordSelect = (keyword: IKeywordTag) => { - if (keyword.initial) { - this.tmdbService.getKeyword(keyword.id) - .subscribe(k => { - keyword.name = k.name; - keyword.initial = false; - }); + public remove(tag: IKeywordTag): void { + const index = this.excludedKeywords.indexOf(tag); + + if (index >= 0) { + this.excludedKeywords.splice(index, 1); } - } + } public save() { this.settings.excludedKeywordIds = this.excludedKeywords.map(k => k.id); @@ -68,4 +86,13 @@ export class TheMovieDbComponent implements OnInit { } }); } + + public async optionSelected(item: IMovieDbKeyword) { + + if ((item.name || '').trim()) { + this.excludedKeywords.push({ id: item.id, name: item.name, initial: false }); + } + + this.tagForm.controls.input.setValue(null); + } } diff --git a/src/Ombi/ClientApp/src/app/settings/update/update.component.html b/src/Ombi/ClientApp/src/app/settings/update/update.component.html index e82fcd30d..990015d76 100644 --- a/src/Ombi/ClientApp/src/app/settings/update/update.component.html +++ b/src/Ombi/ClientApp/src/app/settings/update/update.component.html @@ -1,7 +1,7 @@  -
+
Update Settings
diff --git a/src/Ombi/ClientApp/src/app/settings/update/update.component.scss b/src/Ombi/ClientApp/src/app/settings/update/update.component.scss new file mode 100644 index 000000000..60e52d81a --- /dev/null +++ b/src/Ombi/ClientApp/src/app/settings/update/update.component.scss @@ -0,0 +1,5 @@ +.small-middle-container{ + margin: auto; + width: 85%; + margin-top:10px; +} diff --git a/src/Ombi/ClientApp/src/app/settings/update/update.component.ts b/src/Ombi/ClientApp/src/app/settings/update/update.component.ts index df0e8b32e..d4648b35b 100644 --- a/src/Ombi/ClientApp/src/app/settings/update/update.component.ts +++ b/src/Ombi/ClientApp/src/app/settings/update/update.component.ts @@ -6,6 +6,7 @@ import { JobService, SettingsService } from "../../services"; @Component({ templateUrl: "./update.component.html", + styleUrls: ["./update.component.scss"] }) export class UpdateComponent implements OnInit { diff --git a/src/Ombi/ClientApp/src/app/settings/usermanagement/usermanagement.component.html b/src/Ombi/ClientApp/src/app/settings/usermanagement/usermanagement.component.html index 80331272c..870bd45ae 100644 --- a/src/Ombi/ClientApp/src/app/settings/usermanagement/usermanagement.component.html +++ b/src/Ombi/ClientApp/src/app/settings/usermanagement/usermanagement.component.html @@ -1,44 +1,35 @@  - +
User Importer Settings - +
-
- - +
+ + Import Plex Users
-
- - + Import Plex Admin
-
-

Plex Users exclude from Import

+

Plex Users excluded from Import

-
- -
-
- - -
+ Import Emby Users
-

Emby Users exclude from Import

+

Emby Users excluded from Import

@@ -50,9 +41,9 @@
-
- - +
+ + {{c.value | humanize}}
@@ -61,24 +52,26 @@
- +
- +
-
-
- - -
+
-
-
\ No newline at end of file +
+
+
+
+
\ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/settings/usermanagement/usermanagement.component.scss b/src/Ombi/ClientApp/src/app/settings/usermanagement/usermanagement.component.scss new file mode 100644 index 000000000..1766c63b9 --- /dev/null +++ b/src/Ombi/ClientApp/src/app/settings/usermanagement/usermanagement.component.scss @@ -0,0 +1,48 @@ +@import "~styles/shared.scss"; +.small-middle-container { + margin: auto; + width: 95%; + margin-top: 10px; +} + +.col-md-6 { + display: contents; +} + +.col-md-5 { + display: contents; +} + +.control-label { + font-weight: 400; +} + +.form-control { + width: auto; +} + +.row { + display: block; +} + +.btn-danger-outline { + background-color: #E84C3D; +} + +.btn-success-outline { + background-color: #1b9d1b; +} + +::ng-deep .dark .btn:hover { + box-shadow: 0 5px 11px 0 rgba(255, 255, 255, 0.18), 0 4px 15px 0 rgba(255, 255, 255, 0.15); + color: inherit; +} + +@media (min-width:1440px) { + .col-md-6 { + display: inline-table; + } + .col-md-5 { + display: inline-table; + } +} \ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/settings/usermanagement/usermanagement.component.ts b/src/Ombi/ClientApp/src/app/settings/usermanagement/usermanagement.component.ts index 66babd94a..00483e4f2 100644 --- a/src/Ombi/ClientApp/src/app/settings/usermanagement/usermanagement.component.ts +++ b/src/Ombi/ClientApp/src/app/settings/usermanagement/usermanagement.component.ts @@ -6,6 +6,7 @@ import { EmbyService, IdentityService, JobService, NotificationService, PlexServ @Component({ templateUrl: "./usermanagement.component.html", + styleUrls: ["./usermanagement.component.scss"] }) export class UserManagementComponent implements OnInit { diff --git a/src/Ombi/ClientApp/src/app/settings/vote/vote.component.html b/src/Ombi/ClientApp/src/app/settings/vote/vote.component.html index c5877f3d8..a556fa048 100644 --- a/src/Ombi/ClientApp/src/app/settings/vote/vote.component.html +++ b/src/Ombi/ClientApp/src/app/settings/vote/vote.component.html @@ -1,14 +1,14 @@  +
Vote -
-
+ +
- - + Enable
@@ -36,15 +36,13 @@
- +
-
+
- - - - - -
\ No newline at end of file +
+
\ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/settings/vote/vote.component.scss b/src/Ombi/ClientApp/src/app/settings/vote/vote.component.scss new file mode 100644 index 000000000..8644e48e5 --- /dev/null +++ b/src/Ombi/ClientApp/src/app/settings/vote/vote.component.scss @@ -0,0 +1,14 @@ +@import "~styles/shared.scss"; +.small-middle-container { + margin: auto; + width: 95%; + margin-top: 10px; +} + +::ng-deep .dark .btn:hover { + box-shadow: 0 5px 11px 0 rgba(255, 255, 255, 0.18), 0 4px 15px 0 rgba(255, 255, 255, 0.15); + color: inherit; +} +.form-control { + width: auto; +} \ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/settings/vote/vote.component.ts b/src/Ombi/ClientApp/src/app/settings/vote/vote.component.ts index d99239b96..d0804b4b2 100644 --- a/src/Ombi/ClientApp/src/app/settings/vote/vote.component.ts +++ b/src/Ombi/ClientApp/src/app/settings/vote/vote.component.ts @@ -5,6 +5,7 @@ import { NotificationService, SettingsService } from "../../services"; @Component({ templateUrl: "./vote.component.html", + styleUrls: ["vote.component.scss"] }) export class VoteComponent implements OnInit { diff --git a/src/Ombi/ClientApp/src/app/settings/wiki.component.html b/src/Ombi/ClientApp/src/app/settings/wiki.component.html index 9f02b1354..52cedf6ea 100644 --- a/src/Ombi/ClientApp/src/app/settings/wiki.component.html +++ b/src/Ombi/ClientApp/src/app/settings/wiki.component.html @@ -1,5 +1,5 @@ -
-
+
+ -
+
-
- - - +
+
+
+ +
+ + + +
+
+ + + +
+
+ + + +
+
+ + + +
+
+ + + +
- - Choose the Roles -
-
- {{c.value | humanize}} -
-
+
-
-
- {{c.value | humanize}} -
-
-
- - -
- - - Set Request Limits - -
- - - -
-
- - - -
+
+ +
+ + + +
+
+ + + +
+
+ + + +
+ + + Sonarr Quality Profile + + + {{folder.name}} + + + + + + Sonarr Quality Profile (Anime) + + + {{folder.name}} + + + + + + Sonarr Root Folder + + + {{folder.path}} + + + + + + Sonarr Root Folder (Anime) + + + {{folder.path}} + + + + + + Radarr Quality Profiles + + + {{folder.name}} + + + + + + Radarr Root Folder + + + {{folder.path}} + + + +
+ +
+ +
+
+ {{c.value | humanize}} +
+
+ +
+
+ {{c.value | humanize}} +
+
+
+ + +
+ +
- +
+
+
-
- - -
-
- - Notification Preferences -
-
- - - -
-
-
- - -
-
+
- - Quality & Root Path Preferences +
- - Sonarr Quality Profile - - - {{folder.name}} - - - - - - Sonarr Quality Profile (Anime) - - - {{folder.name}} - - - - - - Sonarr Root Folder - - - {{folder.path}} - - - - - - Sonarr Root Folder (Anime) - - - {{folder.path}} - - - +
+ +
+ + + - - Radarr Quality Profiles - - - {{folder.name}} - - - +
- - Radarr Root Folder - - - {{folder.path}} - - - +
+
+ +
+
-
- - -
-
- - Actions - -
- - - -
-
- -
+
\ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/usermanagement/usermanagement-user.component.ts b/src/Ombi/ClientApp/src/app/usermanagement/usermanagement-user.component.ts index d467f02b7..db0403a01 100644 --- a/src/Ombi/ClientApp/src/app/usermanagement/usermanagement-user.component.ts +++ b/src/Ombi/ClientApp/src/app/usermanagement/usermanagement-user.component.ts @@ -1,10 +1,9 @@ -import { Component, OnInit } from "@angular/core"; +import { Location } from "@angular/common"; +import { Component, OnInit } from "@angular/core"; import { ActivatedRoute, Router } from "@angular/router"; import { ICheckbox, INotificationAgent, INotificationPreferences, IRadarrProfile, IRadarrRootFolder, ISonarrProfile, ISonarrRootFolder, IUser, UserType } from "../interfaces"; -import { IdentityService, NotificationService, RadarrService, SonarrService, MessageService } from "../services"; - -import { ConfirmationService } from "primeng/primeng"; +import { IdentityService, RadarrService, SonarrService, MessageService } from "../services"; @Component({ templateUrl: "./usermanagement-user.component.html", @@ -17,7 +16,7 @@ export class UserManagementUserComponent implements OnInit { public availableClaims: ICheckbox[]; public confirmPass: ""; public notificationPreferences: INotificationPreferences[]; - + public sonarrQualities: ISonarrProfile[]; public sonarrRootFolders: ISonarrRootFolder[]; public radarrQualities: IRadarrProfile[]; @@ -30,9 +29,9 @@ export class UserManagementUserComponent implements OnInit { private notificationService: MessageService, private router: Router, private route: ActivatedRoute, - private confirmationService: ConfirmationService, private sonarrService: SonarrService, - private radarrService: RadarrService) { + private radarrService: RadarrService, + private location: Location) { this.route.params.subscribe((params: any) => { if(params.id) { @@ -41,7 +40,7 @@ export class UserManagementUserComponent implements OnInit { this.identityService.getUserById(this.userId).subscribe(x => { this.user = x; }); - } + } }); } @@ -74,6 +73,7 @@ export class UserManagementUserComponent implements OnInit { musicRequestLimit: 0, episodeRequestQuota: null, movieRequestQuota: null, + language: null, userQualityProfiles: { radarrQualityProfile: 0, radarrRootPath: 0, @@ -121,26 +121,16 @@ export class UserManagementUserComponent implements OnInit { public delete() { - this.confirmationService.confirm({ - message: "Are you sure that you want to delete this user? If this user has any requests they will also be deleted.", - header: "Are you sure?", - icon: "fa fa-trash", - accept: () => { - this.identityService.deleteUser(this.user).subscribe(x => { - if (x.successful) { - this.notificationService.send(`The user ${this.user.userName} was deleted`); - this.router.navigate(["usermanagement"]); - } else { - x.errors.forEach((val) => { - this.notificationService.send(val); - }); - } - + this.identityService.deleteUser(this.user).subscribe(x => { + if (x.successful) { + this.notificationService.send(`The user ${this.user.userName} was deleted`); + this.router.navigate(["usermanagement"]); + } else { + x.errors.forEach((val) => { + this.notificationService.send(val); }); - }, - reject: () => { - return; - }, + } + }); } @@ -183,4 +173,8 @@ export class UserManagementUserComponent implements OnInit { }); } + public back() { + this.location.back(); + } + } diff --git a/src/Ombi/ClientApp/src/app/usermanagement/usermanagement.component.html b/src/Ombi/ClientApp/src/app/usermanagement/usermanagement.component.html index d2f4c52aa..4b64e2f45 100644 --- a/src/Ombi/ClientApp/src/app/usermanagement/usermanagement.component.html +++ b/src/Ombi/ClientApp/src/app/usermanagement/usermanagement.component.html @@ -1,12 +1,14 @@ -

User Management

+
+
+ - + - - - + +
+
- - + + + + - - - - + + + + - - - - + + + + - + - + - - - + - - - - + + + + - - - - - - + + + + + + + - - - - - - - - + + + + + + + + - + - - -
@@ -23,128 +25,131 @@ [aria-label]="checkboxLabel(row)"> - + - - Username {{element.userName}} Username {{element.userName}} Alias {{element.alias}} Alias {{element.alias}} Email {{element.emailAddress}} Email {{element.emailAddress}} Requests Remaining
{{'UserManagment.MovieRemaining' | translate: {remaining: u.movieRequestQuota.remaining, total: u.movieRequestLimit} }} -
-
+
+
{{'UserManagment.TvRemaining' | translate: {remaining: u.episodeRequestQuota.remaining, total: u.episodeRequestLimit} }} -
-
+
+
{{'UserManagment.MusicRemaining' | translate: {remaining: u.musicRequestQuota.remaining, total: u.musicRequestLimit} }} -
+
Next Request Due -
+ +
Next Request Due +
{{'UserManagment.MovieDue' | translate: {date: (u.movieRequestQuota.nextRequest | amLocal | amDateFormat: 'l LT')} }} -
-
+
+
{{'UserManagment.TvDue' | translate: {date: (u.episodeRequestQuota.nextRequest | amLocal | amDateFormat: 'l LT')} }} -
-
+
+
{{'UserManagment.MusicDue' | translate: {date: (u.musicRequestQuota.nextRequest | amLocal | amDateFormat: 'l LT')} }} -
-
Last Logged In - + + Last Logged In + {{u.lastLoggedIn | amLocal | amDateFormat: 'l LT'}} - - + + Not logged in yet! - User Type - Local User - Plex User - Emby User User Type + Local User + Plex User + Emby User Roles -
- {{claim.value}} -
-
- - Roles +
+ {{claim.value}} +
+
+ + - +
+ + + - +

Bulk Edit


+
-
- - +
+ + {{c.value | humanize}} +
-
-
-
- -
- -
-
+
-
- -
- -
-
- - + + Movie Request Limit + + + + Episode Request Limit + + + + Music Request Limit + + + + + - +
+
diff --git a/src/Ombi/ClientApp/src/app/usermanagement/usermanagement.component.scss b/src/Ombi/ClientApp/src/app/usermanagement/usermanagement.component.scss new file mode 100644 index 000000000..19dab627d --- /dev/null +++ b/src/Ombi/ClientApp/src/app/usermanagement/usermanagement.component.scss @@ -0,0 +1,88 @@ +@import "~styles/variables.scss"; + +.small-middle-container{ + margin: auto; + width: 85%; + margin-top:10px; +} + +::ng-deep .dark .content .mat-header-cell { + background: rgba(0, 0, 0, 0.381)!important; + font-size: 1em; + font-weight: 500; + color: rgba(255, 255, 255, 0.842) !important; +} + +::ng-deep .dark .mat-header-cell .mat-checkbox-frame { + border-color: #FFF; +} + + +.mat-form-field { + float:right; +} + +::ng-deep .mat-form-field-label{ + font-size: 1.2em; +} + +::ng-deep .mat-form-field-infix { + width: 10em; + margin-top:1em; +} + +::ng-deep .mat-tab-label{ + opacity: 1; +} + +.full { + width: 100%; +} + +.content { + margin-top: 2em; +} + +.buttons { + margin-top: 2em; + transition: 0.5s; + & .mat-raised-button { + background: $accent; + color:#fff; + } + :disabled { + opacity:0.4; + } + ::ng-deep .dark & button { + background: $accent-dark !important; + color: #303030 !important; + } + /* + &:hover{ + box-shadow: 0 1em 1em -0.8em #fff; + transform: translateY(-0.50em); + transition: 0.5s; + background: #fff !important; + } + &:disabled{ + opacity: 0.4; + } + .offset { + box-shadow: + 0.3em 0.3em 0 0 #fff, + inset 0.3em 0.3em 0 0 #fff; + + &:hover, + &:focus { + box-shadow: + 0 0 0 0 #fff, + inset 6em 3.5em 0 0 #fff; + } + } + }*/ +} +/*.dark .buttons button { + background: $accent-dark !important; + color: #303030; +} +*/ \ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/usermanagement/usermanagement.component.ts b/src/Ombi/ClientApp/src/app/usermanagement/usermanagement.component.ts index 07d54f3d1..4071c6b8f 100644 --- a/src/Ombi/ClientApp/src/app/usermanagement/usermanagement.component.ts +++ b/src/Ombi/ClientApp/src/app/usermanagement/usermanagement.component.ts @@ -1,21 +1,23 @@ -import { Component, OnInit, ViewChild } from "@angular/core"; +import { AfterViewInit, Component, OnInit, ViewChild } from "@angular/core"; import { ICheckbox, ICustomizationSettings, IEmailNotificationSettings, IUser } from "../interfaces"; import { IdentityService, NotificationService, SettingsService } from "../services"; -import { MatSort, MatTableDataSource } from "@angular/material"; +import { MatSort } from "@angular/material/sort"; +import { MatTableDataSource } from "@angular/material/table"; import { SelectionModel } from "@angular/cdk/collections"; @Component({ templateUrl: "./usermanagement.component.html", + styleUrls: ["./usermanagement.component.scss"], }) -export class UserManagementComponent implements OnInit { +export class UserManagementComponent implements OnInit, AfterViewInit { public displayedColumns: string[] = ['select', 'username', 'alias', 'email', 'roles', 'remainingRequests', 'nextRequestDue', 'lastLoggedIn', 'userType', 'actions', 'welcome']; public dataSource: MatTableDataSource; public selection = new SelectionModel(true, []); - @ViewChild(MatSort, {static: false}) public sort: MatSort; + @ViewChild(MatSort) public sort: MatSort; public users: IUser[]; public checkAll = false; public emailSettings: IEmailNotificationSettings; @@ -24,6 +26,7 @@ export class UserManagementComponent implements OnInit { public availableClaims: ICheckbox[]; public bulkMovieLimit?: number; public bulkEpisodeLimit?: number; + public bulkMusicLimit?: number; public plexEnabled: boolean; constructor(private identityService: IdentityService, @@ -31,11 +34,11 @@ export class UserManagementComponent implements OnInit { private notificationService: NotificationService, private plexSettings: SettingsService) { } + public async ngOnInit() { this.users = await this.identityService.getUsers().toPromise(); - + this.dataSource = new MatTableDataSource(this.users); - this.dataSource.sort = this.sort; this.plexSettings.getPlex().subscribe(x => this.plexEnabled = x.enable); @@ -44,6 +47,10 @@ export class UserManagementComponent implements OnInit { this.settingsService.getEmailNotificationSettings().subscribe(x => this.emailSettings = x); } + public ngAfterViewInit(): void { + this.dataSource.sort = this.sort; + } + public welcomeEmail(user: IUser) { if (!user.emailAddress) { this.notificationService.error("The user needs an email address."); @@ -78,6 +85,9 @@ export class UserManagementComponent implements OnInit { if (this.bulkMovieLimit) { x.movieRequestLimit = this.bulkMovieLimit; } + if (this.bulkMusicLimit) { + x.musicRequestLimit = this.bulkMusicLimit; + } this.identityService.updateUser(x).subscribe(y => { if (!y.successful) { this.notificationService.error(`Could not update user ${x.userName}. Reason ${y.errors[0]}`); @@ -89,6 +99,7 @@ export class UserManagementComponent implements OnInit { this.showBulkEdit = false; this.bulkMovieLimit = undefined; this.bulkEpisodeLimit = undefined; + this.bulkMusicLimit = undefined; } public isAllSelected() { diff --git a/src/Ombi/ClientApp/src/app/usermanagement/usermanagement.module.ts b/src/Ombi/ClientApp/src/app/usermanagement/usermanagement.module.ts index 166f42673..3ac5aed21 100644 --- a/src/Ombi/ClientApp/src/app/usermanagement/usermanagement.module.ts +++ b/src/Ombi/ClientApp/src/app/usermanagement/usermanagement.module.ts @@ -2,9 +2,11 @@ import { NgModule } from "@angular/core"; import { FormsModule, ReactiveFormsModule } from "@angular/forms"; import { RouterModule, Routes } from "@angular/router"; -import { ConfirmationService, ConfirmDialogModule, MultiSelectModule, SidebarModule, TooltipModule } from "primeng/primeng"; +import { ConfirmDialogModule } from "primeng/confirmdialog"; +import { MultiSelectModule } from "primeng/multiselect"; +import { SidebarModule } from "primeng/sidebar"; +import { TooltipModule } from "primeng/tooltip"; -import { NgbModule } from "@ng-bootstrap/ng-bootstrap"; import { UpdateDetailsComponent } from "./updatedetails.component"; import { UserManagementUserComponent } from "./usermanagement-user.component"; @@ -32,7 +34,6 @@ const routes: Routes = [ FormsModule, ReactiveFormsModule, RouterModule.forChild(routes), - NgbModule.forRoot(), MultiSelectModule, PipeModule, ConfirmDialogModule, @@ -51,7 +52,6 @@ const routes: Routes = [ ], providers: [ IdentityService, - ConfirmationService, PlexService, RadarrService, SonarrService, diff --git a/src/Ombi/ClientApp/src/app/vote/vote.component.ts b/src/Ombi/ClientApp/src/app/vote/vote.component.ts index 44abb8774..989165d4e 100644 --- a/src/Ombi/ClientApp/src/app/vote/vote.component.ts +++ b/src/Ombi/ClientApp/src/app/vote/vote.component.ts @@ -1,6 +1,6 @@ import { Component, OnInit, ViewChild } from "@angular/core"; -import { OverlayPanel } from "primeng/primeng"; +import { OverlayPanel } from "primeng/overlaypanel"; import { NotificationService, VoteService } from "../services"; import { IVoteEngineResult, IVoteViewModel, RequestTypes, VoteType } from "../interfaces"; @@ -18,7 +18,7 @@ export class VoteComponent implements OnInit { public completedVotes: IVoteViewModel[]; public VoteType = VoteType; public panelImage: string; - @ViewChild("op", {static: false}) public overlayPanel: OverlayPanel; + @ViewChild("op") public overlayPanel: OverlayPanel; constructor(private voteService: VoteService, private notificationSerivce: NotificationService) { } diff --git a/src/Ombi/ClientApp/src/app/vote/vote.module.ts b/src/Ombi/ClientApp/src/app/vote/vote.module.ts index ee7532da5..30727b41a 100644 --- a/src/Ombi/ClientApp/src/app/vote/vote.module.ts +++ b/src/Ombi/ClientApp/src/app/vote/vote.module.ts @@ -1,9 +1,9 @@ import { NgModule } from "@angular/core"; import { RouterModule, Routes } from "@angular/router"; -import { NgbModule } from "@ng-bootstrap/ng-bootstrap"; import { OrderModule } from "ngx-order-pipe"; -import { OverlayPanelModule, SharedModule, TabViewModule } from "primeng/primeng"; +import { OverlayPanelModule } from "primeng/overlaypanel"; +import { TabViewModule } from "primeng/tabview"; import { VoteService } from "../services"; @@ -20,8 +20,6 @@ const routes: Routes = [ @NgModule({ imports: [ RouterModule.forChild(routes), - NgbModule.forRoot(), - SharedModule, OrderModule, OmbiShared, TabViewModule, diff --git a/src/Ombi/ClientApp/src/app/wizard/createadmin/createadmin.component.ts b/src/Ombi/ClientApp/src/app/wizard/createadmin/createadmin.component.ts index cabe30426..e691ca627 100644 --- a/src/Ombi/ClientApp/src/app/wizard/createadmin/createadmin.component.ts +++ b/src/Ombi/ClientApp/src/app/wizard/createadmin/createadmin.component.ts @@ -1,31 +1,16 @@ -import { Component, OnInit, Input } from "@angular/core"; -import { Router } from "@angular/router"; - -import { PlatformLocation } from "@angular/common"; -import { IdentityService } from "../../services"; -import { NotificationService } from "../../services"; +import { Component, Input } from "@angular/core"; import { ICreateWizardUser } from "../../interfaces"; @Component({ selector: "wizard-local-admin", templateUrl: "./createadmin.component.html", }) -export class CreateAdminComponent implements OnInit { +export class CreateAdminComponent { @Input() user: ICreateWizardUser; public username: string; - public password: string; - public baseUrl: string; - - - constructor(private location: PlatformLocation) { } - - public ngOnInit(): void { - const base = this.location.getBaseHrefFromDOM(); - if (base.length > 1) { - this.baseUrl = base; - } - } + public password: string; + constructor() { } } diff --git a/src/Ombi/ClientApp/src/app/wizard/emby/emby.component.ts b/src/Ombi/ClientApp/src/app/wizard/emby/emby.component.ts index dc9dfca70..58d5dd3f6 100644 --- a/src/Ombi/ClientApp/src/app/wizard/emby/emby.component.ts +++ b/src/Ombi/ClientApp/src/app/wizard/emby/emby.component.ts @@ -1,10 +1,8 @@ import { Component, OnInit } from "@angular/core"; -import { Router } from "@angular/router"; import { EmbyService } from "../../services"; import { NotificationService } from "../../services"; -import { PlatformLocation } from "@angular/common"; import { IEmbySettings } from "../../interfaces"; @Component({ @@ -14,19 +12,12 @@ import { IEmbySettings } from "../../interfaces"; export class EmbyComponent implements OnInit { public embySettings: IEmbySettings; - public baseUrl: string; constructor(private embyService: EmbyService, - private router: Router, - private notificationService: NotificationService, - private location: PlatformLocation) { + private notificationService: NotificationService) { } public ngOnInit() { - const base = this.location.getBaseHrefFromDOM(); - if (base.length > 1) { - this.baseUrl = base; - } this.embySettings = { servers: [], isJellyfin: false, @@ -44,7 +35,7 @@ export class EmbyComponent implements OnInit { ssl: false, subDir: "", serverHostname: "", - + serverId: undefined }); } diff --git a/src/Ombi/ClientApp/src/app/wizard/plex/plex.component.ts b/src/Ombi/ClientApp/src/app/wizard/plex/plex.component.ts index 1ea7615f3..e469ddc00 100644 --- a/src/Ombi/ClientApp/src/app/wizard/plex/plex.component.ts +++ b/src/Ombi/ClientApp/src/app/wizard/plex/plex.component.ts @@ -1,7 +1,6 @@ import { Component, OnDestroy, OnInit } from "@angular/core"; import { Router } from "@angular/router"; -import { PlatformLocation } from "@angular/common"; import { AuthService } from "../../auth/auth.service"; import { PlexOAuthService, PlexService, PlexTvService, SettingsService } from "../../services"; import { IdentityService, NotificationService } from "../../services"; @@ -15,7 +14,6 @@ export class PlexComponent implements OnInit, OnDestroy { public login: string; public password: string; - public baseUrl: string; public pinTimer: any; private clientId: string; @@ -24,14 +22,10 @@ export class PlexComponent implements OnInit, OnDestroy { private notificationService: NotificationService, private identityService: IdentityService, private plexTv: PlexTvService, private settingsService: SettingsService, - private location: PlatformLocation, private authService: AuthService, + private authService: AuthService, private plexOauth: PlexOAuthService, private store: StorageService) { } public ngOnInit(): void { - const base = this.location.getBaseHrefFromDOM(); - if (base.length > 1) { - this.baseUrl = base; - } this.settingsService.getClientId().subscribe(x => this.clientId = x); } diff --git a/src/Ombi/ClientApp/src/app/wizard/welcome/welcome.component.ts b/src/Ombi/ClientApp/src/app/wizard/welcome/welcome.component.ts index 805264f96..a46b04bd4 100644 --- a/src/Ombi/ClientApp/src/app/wizard/welcome/welcome.component.ts +++ b/src/Ombi/ClientApp/src/app/wizard/welcome/welcome.component.ts @@ -1,5 +1,4 @@ -import { PlatformLocation } from "@angular/common"; -import { Component, OnInit } from "@angular/core"; +import { Component, OnInit } from "@angular/core"; import { Router } from "@angular/router"; import { ICreateWizardUser } from "../../interfaces"; import { IdentityService, NotificationService } from "../../services"; @@ -9,10 +8,9 @@ import { IdentityService, NotificationService } from "../../services"; }) export class WelcomeComponent implements OnInit { - public baseUrl: string; public localUser: ICreateWizardUser; - constructor(private router: Router, private location: PlatformLocation, + constructor(private router: Router, private identityService: IdentityService, private notificationService: NotificationService) { } public ngOnInit(): void { @@ -21,10 +19,6 @@ export class WelcomeComponent implements OnInit { username:"", usePlexAdminAccount:false } - const base = this.location.getBaseHrefFromDOM(); - if (base.length > 1) { - this.baseUrl = base; - } } public createUser() { diff --git a/src/Ombi/ClientApp/src/app/wizard/wizard.module.ts b/src/Ombi/ClientApp/src/app/wizard/wizard.module.ts index 7efdbe504..5438e8e9c 100644 --- a/src/Ombi/ClientApp/src/app/wizard/wizard.module.ts +++ b/src/Ombi/ClientApp/src/app/wizard/wizard.module.ts @@ -3,8 +3,7 @@ import { NgModule } from "@angular/core"; import { FormsModule, ReactiveFormsModule } from "@angular/forms"; import { RouterModule, Routes } from "@angular/router"; -import {ConfirmationService, ConfirmDialogModule } from "primeng/primeng"; -import { MatStepperModule } from "@angular/material"; +import { MatStepperModule } from "@angular/material/stepper"; import { CreateAdminComponent } from "./createadmin/createadmin.component"; import { EmbyComponent } from "./emby/emby.component"; @@ -31,7 +30,6 @@ const routes: Routes = [ CommonModule, FormsModule, ReactiveFormsModule, - ConfirmDialogModule, SharedModule, MatStepperModule, RouterModule.forChild(routes), @@ -50,7 +48,6 @@ const routes: Routes = [ PlexService, IdentityService, EmbyService, - ConfirmationService, PlexOAuthService, ], diff --git a/src/Ombi/ClientApp/src/index.html b/src/Ombi/ClientApp/src/index.html index ffa026566..f7804c77f 100644 --- a/src/Ombi/ClientApp/src/index.html +++ b/src/Ombi/ClientApp/src/index.html @@ -2,39 +2,70 @@ - - - - - - - - - - - Ombi + + + + + + + + + + + + + + + + + + + Ombi + + - + - - - + backgroundColor: bgColor, + loadingHtml: "
" + }); + + diff --git a/src/Ombi/ClientApp/src/main.ts b/src/Ombi/ClientApp/src/main.ts index b88de5819..85668688d 100644 --- a/src/Ombi/ClientApp/src/main.ts +++ b/src/Ombi/ClientApp/src/main.ts @@ -9,8 +9,6 @@ import { environment } from "./environments/environment"; import "./polyfills"; -import "hammerjs"; - import { enableProdMode } from "@angular/core"; import { platformBrowserDynamic } from "@angular/platform-browser-dynamic"; import { AppModule } from "./app/app.module"; diff --git a/src/Ombi/ClientApp/src/polyfills.ts b/src/Ombi/ClientApp/src/polyfills.ts index a12fe103c..886a3ddf4 100644 --- a/src/Ombi/ClientApp/src/polyfills.ts +++ b/src/Ombi/ClientApp/src/polyfills.ts @@ -1,2 +1,6 @@ +/*************************************************************************************************** + * Load `$localize` onto the global scope - used if i18n tags appear in Angular templates. + */ +import '@angular/localize/init'; import "core-js/es7/reflect"; import "zone.js/dist/zone"; diff --git a/src/Ombi/ClientApp/src/styles/_imports.scss b/src/Ombi/ClientApp/src/styles/_imports.scss index 04416038e..8897ace2e 100644 --- a/src/Ombi/ClientApp/src/styles/_imports.scss +++ b/src/Ombi/ClientApp/src/styles/_imports.scss @@ -1,4 +1,4 @@ -@import "./Styles.scss"; -@import "./shared.scss"; +@import "./shared.scss"; @import "./buttons.scss"; -@import "./primeng-overrides.scss" \ No newline at end of file +@import "./primeng-overrides.scss"; +@import "./material-overrides.scss"; \ No newline at end of file diff --git a/src/Ombi/ClientApp/src/styles/buttons.scss b/src/Ombi/ClientApp/src/styles/buttons.scss index 01df07bac..c9b94cabf 100644 --- a/src/Ombi/ClientApp/src/styles/buttons.scss +++ b/src/Ombi/ClientApp/src/styles/buttons.scss @@ -18,4 +18,4 @@ $orange:#F57C00; .btn-orange { background-color: $orange; -} +} \ No newline at end of file diff --git a/src/Ombi/ClientApp/src/styles/material-overrides.scss b/src/Ombi/ClientApp/src/styles/material-overrides.scss new file mode 100644 index 000000000..d97175df7 --- /dev/null +++ b/src/Ombi/ClientApp/src/styles/material-overrides.scss @@ -0,0 +1,15 @@ +.lg-form-field .mat-form-field-infix { + width: 480px; +} + +.md-form-field .mat-form-field-infix { + width: 380px; +} + +td.mat-cell { + padding: 0.75rem !important; +} + +.mat-form-field { + display: block !important; +} \ No newline at end of file diff --git a/src/Ombi/ClientApp/src/styles/shared.scss b/src/Ombi/ClientApp/src/styles/shared.scss index e2c888362..c743d06a9 100644 --- a/src/Ombi/ClientApp/src/styles/shared.scss +++ b/src/Ombi/ClientApp/src/styles/shared.scss @@ -1,24 +1,51 @@ -@media (max-width: 978px) { +@import "~styles/variables.scss"; +/*@media (max-width: 978px) { .top-spacing { - padding-top: 10%; + padding-top: 2%; } - .modal-panel { - max-height: 100vh !important; - max-width: 100vw !important; - height: 100%; + .modal-panel { + max-height: 100vh !important; + max-width: 100vw !important; + height: 100%; } } @media (min-width: 979px) { .top-spacing { - padding-top: 4%; + padding-top: 2%; + } +}*/ + +@media (max-width: 978px) { + .top-space { + padding-top: 2%; + } + + .modal-panel { + max-height: 100vh !important; + max-width: 100vw !important; + height: 100%; } } +@media (min-width: 979px) { + .top-space { + padding-top: 2%; + } +} + + html, body { min-height: 100vh; - overflow: auto; + overflow: initial; + scrollbar-color: #616161 #303030; //firefox + scrollbar-width: thin; //firefox + -webkit-overflow-scrolling: touch; +} + +.custom-background { + background-color: $background-dark !important; } .spinner-container { @@ -30,40 +57,85 @@ body { height: 50px; } + /* Scrollbar */ ::-webkit-scrollbar { width: 7px; - background: rgba(0, 0, 0, 0); + background: #818181; } ::-webkit-scrollbar-track { background: rgba(0, 0, 0, 0); } +// Changed color of the scrollbar ::-webkit-scrollbar-thumb { border-radius: 3px; - background: #41927b; + background: #303030; } .sidenav ::-webkit-scrollbar-track { display: none; } -.grow { - transition: all .2s ease-in-out; -} +@media (min-width: 1025px) { + .grow { + transition: all .2s ease-in-out; + } -.grow:hover { - transform: scale(1.1); - color: black; + .grow:hover { + transform: scale(1.1); + color: black; + } } table { - width: 100%; + width: 100%; } .loading-spinner { display: flex; padding-bottom: 4%; -} \ No newline at end of file +} + +::ng-deep .dark .form-control { + background-color: rgba(0, 0, 0, 0.18); + color: #fff; + border: 1px solid rgba(0, 0, 0, 0.18); +} + +::ng-deep .dark .nav-link.active { + color: #303030; + background-color: $accent-dark; + border-color: rgba(0, 0, 0, 0.18); + font-weight: 400; +} + +::ng-deep .dark .nav-link { + color: #fff; + background-color: rgba(0, 0, 0, 0.18); + border-color: rgba(0, 0, 0, 0.18); +} + +::ng-deep .dark .ui-autocomplete.ui-autocomplete-multiple .ui-autocomplete-multiple-container .ui-autocomplete-input-token input { + color: #fff; +} + +::ng-deep .dark .ui-inputtext { + background-color: rgba(0, 0, 0, 0.18); + color: #fff; + border: 1px solid rgba(0, 0, 0, 0.18); +} + +::ng-deep .mat-toolbar.mat-primary { + margin-bottom: 0.5em; +} + +::ng-deep .dark .mat-form-field.mat-focused .mat-form-field-label { + color: $accent-dark; +} + +::ng-deep .mat-form-field.mat-focused .mat-form-field-label { + color: $accent; +} diff --git a/src/Ombi/ClientApp/src/styles/variables.scss b/src/Ombi/ClientApp/src/styles/variables.scss index 5df0cebe5..2bd0d40e5 100644 --- a/src/Ombi/ClientApp/src/styles/variables.scss +++ b/src/Ombi/ClientApp/src/styles/variables.scss @@ -30,7 +30,7 @@ $warn: mat-color($ombi-app-warn); // DARK -$background-dark: at-color(mat-palette($mat-grey, 800));; +$background-dark: mat-color(mat-palette($mat-grey, 800));; $backgroundTint-dark: mat-color(mat-palette($mat-grey, 900)); $text-dark: white; $panel: mat-color(mat-palette($mat-grey, 800)); diff --git a/src/Ombi/ClientApp/src/tsconfig.app.json b/src/Ombi/ClientApp/src/tsconfig.app.json index 27ef116e0..aef5c882b 100644 --- a/src/Ombi/ClientApp/src/tsconfig.app.json +++ b/src/Ombi/ClientApp/src/tsconfig.app.json @@ -2,14 +2,17 @@ "compileOnSave": false, "compilerOptions": { "baseUrl": "./", + "module": "esnext", "outDir": "./dist/out-tsc", "sourceMap": true, "declaration": false, "moduleResolution": "node", "emitDecoratorMetadata": true, "experimentalDecorators": true, - "target": "es5", + "target": "es2015", + "types": ["node"], "resolveJsonModule":true, + "allowSyntheticDefaultImports":true, "typeRoots": [ "node_modules/@types" ], @@ -18,4 +21,12 @@ "dom" ] } +, + "files": [ + "main.ts", + "polyfills.ts" + ], + "include": [ + "src/**/*.d.ts" + ] } diff --git a/src/Ombi/ClientApp/yarn.lock b/src/Ombi/ClientApp/yarn.lock index c4dc3f0ec..d2dc99e84 100644 --- a/src/Ombi/ClientApp/yarn.lock +++ b/src/Ombi/ClientApp/yarn.lock @@ -2,285 +2,1170 @@ # yarn lockfile v1 -"@angular-devkit/architect@0.800.2": - version "0.800.2" - resolved "https://registry.yarnpkg.com/@angular-devkit/architect/-/architect-0.800.2.tgz#0924864e57d1e56bddeae257c8779a2662c34e69" - integrity sha512-251GOQwI3254AtnGWZoHmjOMFcz7h6M3fPmRHpYuuhRPIwZnQCKaszYI7gaP9zR7uArLUwsuPo+YYz8lb6Giwg== - dependencies: - "@angular-devkit/core" "8.0.2" - rxjs "6.4.0" - -"@angular-devkit/build-angular@^0.800.2": - version "0.800.2" - resolved "https://registry.yarnpkg.com/@angular-devkit/build-angular/-/build-angular-0.800.2.tgz#712f106f50fb8301816e4417493e98e1e12eb296" - integrity sha512-RlYPEp5FVKosgzWhbI7llM3lGIxAYuCwEPloeUL4XaDasNe2zmLNUlYDVTrF7GpZRoAgiIejmT0HvvKfEuZNZQ== - dependencies: - "@angular-devkit/architect" "0.800.2" - "@angular-devkit/build-optimizer" "0.800.2" - "@angular-devkit/build-webpack" "0.800.2" - "@angular-devkit/core" "8.0.2" - "@ngtools/webpack" "8.0.2" - ajv "6.10.0" - autoprefixer "9.5.1" - browserslist "4.5.5" - caniuse-api "3.0.0" - circular-dependency-plugin "5.0.2" - clean-css "4.2.1" - copy-webpack-plugin "5.0.2" - core-js "3.0.1" - file-loader "3.0.1" - glob "7.1.3" - istanbul-instrumenter-loader "3.0.1" +"@angular-devkit/architect@0.901.6": + version "0.901.6" + resolved "https://registry.yarnpkg.com/@angular-devkit/architect/-/architect-0.901.6.tgz#5fb113850b025bdac894d1bb306b4d2ea51f8416" + integrity sha512-0pWzn10gCZxMCrS62NlD38qE2R7l5fPfBuNylntNqvzw9L7iS1ARgqMlAKn8KLaNG6FrXONmgUWHsV987ZICIw== + dependencies: + "@angular-devkit/core" "9.1.6" + rxjs "6.5.4" + +"@angular-devkit/build-angular@~0.901.6": + version "0.901.6" + resolved "https://registry.yarnpkg.com/@angular-devkit/build-angular/-/build-angular-0.901.6.tgz#034f7ba5a5adda715fcbcc35f33ff8a7c62dd4a2" + integrity sha512-jgLFKRWSZIZZVb7fiGC0SHzBFYBkDOLTw/MRta8p81o8WzLe0uxGVP4RlIj6fZxv3Vvb1NZI4HHrgt/jASaj4A== + dependencies: + "@angular-devkit/architect" "0.901.6" + "@angular-devkit/build-optimizer" "0.901.6" + "@angular-devkit/build-webpack" "0.901.6" + "@angular-devkit/core" "9.1.6" + "@babel/core" "7.9.0" + "@babel/generator" "7.9.3" + "@babel/preset-env" "7.9.0" + "@babel/template" "7.8.6" + "@jsdevtools/coverage-istanbul-loader" "3.0.3" + "@ngtools/webpack" "9.1.6" + ajv "6.12.0" + autoprefixer "9.7.4" + babel-loader "8.0.6" + browserslist "^4.9.1" + cacache "15.0.0" + caniuse-lite "^1.0.30001032" + circular-dependency-plugin "5.2.0" + copy-webpack-plugin "5.1.1" + core-js "3.6.4" + css-loader "3.5.1" + cssnano "4.1.10" + file-loader "6.0.0" + find-cache-dir "3.3.1" + glob "7.1.6" + jest-worker "25.1.0" karma-source-map-support "1.4.0" - less "3.9.0" - less-loader "4.1.0" - license-webpack-plugin "2.1.1" - loader-utils "1.2.3" - mini-css-extract-plugin "0.6.0" + less "3.11.1" + less-loader "5.0.0" + license-webpack-plugin "2.1.4" + loader-utils "2.0.0" + mini-css-extract-plugin "0.9.0" minimatch "3.0.4" - open "6.2.0" + open "7.0.3" parse5 "4.0.0" - postcss "7.0.14" + postcss "7.0.27" postcss-import "12.0.1" postcss-loader "3.0.0" - raw-loader "1.0.0" - rxjs "6.4.0" - sass "1.19.0" - sass-loader "7.1.0" - semver "6.0.0" + raw-loader "4.0.0" + regenerator-runtime "0.13.5" + rimraf "3.0.2" + rollup "2.1.0" + rxjs "6.5.4" + sass "1.26.3" + sass-loader "8.0.2" + semver "7.1.3" + source-map "0.7.3" source-map-loader "0.2.4" - source-map-support "0.5.12" speed-measure-webpack-plugin "1.3.1" - stats-webpack-plugin "0.7.0" - style-loader "0.23.1" - stylus "0.54.5" + style-loader "1.1.3" + stylus "0.54.7" stylus-loader "3.0.2" - terser-webpack-plugin "1.2.3" - tree-kill "1.2.1" - webpack "4.30.0" - webpack-dev-middleware "3.6.2" - webpack-dev-server "3.3.1" - webpack-merge "4.2.1" - webpack-sources "1.3.0" - webpack-subresource-integrity "1.1.0-rc.6" - worker-plugin "3.1.0" - -"@angular-devkit/build-optimizer@0.800.2": - version "0.800.2" - resolved "https://registry.yarnpkg.com/@angular-devkit/build-optimizer/-/build-optimizer-0.800.2.tgz#4223b2ac8c2a4c05682d1f3cb0417b4630b4a943" - integrity sha512-A/lX7Fjfeh5PspGURV8fJeOsrIYM/7why7mC6v78zdxaErd4S18wUXJDfndjx3qiKyuq76Uu4cQcS7XfClpb8Q== - dependencies: - loader-utils "1.2.3" - source-map "0.5.6" - typescript "3.4.4" - webpack-sources "1.3.0" - -"@angular-devkit/build-webpack@0.800.2": - version "0.800.2" - resolved "https://registry.yarnpkg.com/@angular-devkit/build-webpack/-/build-webpack-0.800.2.tgz#af90ea503eece948390bce154a53df9d7c566539" - integrity sha512-Bd/sazcriUTFQCGFDyUkjXSmpn8hRLIyLIXBLAn+5coH4Y4xNy8PXt+hnr6ffwu92h/WnyxKIJi44+5aoUBURA== - dependencies: - "@angular-devkit/architect" "0.800.2" - "@angular-devkit/core" "8.0.2" - rxjs "6.4.0" - webpack-merge "4.2.1" - -"@angular-devkit/core@8.0.2": - version "8.0.2" - resolved "https://registry.yarnpkg.com/@angular-devkit/core/-/core-8.0.2.tgz#22b017b38b4d6127ab2e39a27990fd7962d3844a" - integrity sha512-S2OPYe6Qu7qTS8Q2lzf4qNjXdbN/J2YVnd3wGauMI8Tih5tY/NzUW3h5ds09nRcjsdBDuT0qgf3IMlCZWIABvQ== - dependencies: - ajv "6.10.0" - fast-json-stable-stringify "2.0.0" - magic-string "0.25.2" - rxjs "6.4.0" + terser "4.6.10" + terser-webpack-plugin "2.3.5" + tree-kill "1.2.2" + webpack "4.42.0" + webpack-dev-middleware "3.7.2" + webpack-dev-server "3.10.3" + webpack-merge "4.2.2" + webpack-sources "1.4.3" + webpack-subresource-integrity "1.4.0" + worker-plugin "4.0.3" + +"@angular-devkit/build-optimizer@0.901.6": + version "0.901.6" + resolved "https://registry.yarnpkg.com/@angular-devkit/build-optimizer/-/build-optimizer-0.901.6.tgz#2dc85c5ae61113df16566949ae3833283864bb8b" + integrity sha512-M0H9SrOq4QOYqGCIguGQDWizf+XL7whJjBtYHxI7jEjtzar3zkTFgzZ/znv49R56Zch1niH0mBgtDxCFFWqarQ== + dependencies: + loader-utils "2.0.0" + source-map "0.7.3" + tslib "1.11.1" + typescript "3.6.5" + webpack-sources "1.4.3" + +"@angular-devkit/build-webpack@0.901.6": + version "0.901.6" + resolved "https://registry.yarnpkg.com/@angular-devkit/build-webpack/-/build-webpack-0.901.6.tgz#62a0d8cd94c8c61b734b0a6c149c922dd8908c42" + integrity sha512-jEk850AtIFK+xbXXiloVvueXTbJOL1mANR2UBrmWk7V4Bct+gHVerdXjn9vo1Tsd8BgemUYAcqvLldCx9MSDTg== + dependencies: + "@angular-devkit/architect" "0.901.6" + "@angular-devkit/core" "9.1.6" + rxjs "6.5.4" + +"@angular-devkit/core@9.1.6": + version "9.1.6" + resolved "https://registry.yarnpkg.com/@angular-devkit/core/-/core-9.1.6.tgz#d108430a48e58bf1efd1b87aa2edb64e3b9241d1" + integrity sha512-lYXoRtsMsfyIrNAa49Hcx79FPRW6ZrWjK2yJ3avON1Q3WEHYb/DIUP+ItyOQAkNUsCVMyK4wkddsu8PsqEW6tg== + dependencies: + ajv "6.12.0" + fast-json-stable-stringify "2.1.0" + magic-string "0.25.7" + rxjs "6.5.4" source-map "0.7.3" -"@angular-devkit/schematics@8.0.2": - version "8.0.2" - resolved "https://registry.yarnpkg.com/@angular-devkit/schematics/-/schematics-8.0.2.tgz#854a4366c7dc7462bebd10c24e808b5c9f65b6e2" - integrity sha512-v+g0MOPADJJ5QNNmojCyh2sw1GOzadlbHPdTFqZOm77b2Bi79dRm+yuYMuY6a2nUt7DIcioLRcOFwV8UctajRg== +"@angular-devkit/schematics@9.1.6": + version "9.1.6" + resolved "https://registry.yarnpkg.com/@angular-devkit/schematics/-/schematics-9.1.6.tgz#759b01ef6815fd2d7366c3f1907d5878403a816e" + integrity sha512-twS8Sxc6NG4A0n7yITugP0snIMJ2Rm6aOGkckomWjZAP1fPo8pup8EFGc5wUBAtAOM3DJBphEnskpwEWCkBaLg== dependencies: - "@angular-devkit/core" "8.0.2" - rxjs "6.4.0" + "@angular-devkit/core" "9.1.6" + ora "4.0.3" + rxjs "6.5.4" -"@angular/animations@^8.0.0": - version "8.0.0" - resolved "https://registry.yarnpkg.com/@angular/animations/-/animations-8.0.0.tgz#6286094babdb3879f7aefcd73aa31772469e50b4" - integrity sha512-hggSRi83rmocLwzrKZtmFcqPdivKSJqp2yiYaiNmJ2yQWJ1JW/Lurypv9H347RWxmwCCwC2kV8embTGbOXIFDQ== - dependencies: - tslib "^1.9.0" +"@angular/animations@^9.1.7": + version "9.1.8" + resolved "https://registry.yarnpkg.com/@angular/animations/-/animations-9.1.8.tgz#5745f1bf2731d72f7dbbd010d98acf4116225a60" + integrity sha512-YP+cAhweAjloE+gux5nbq4pvAbHqjrjPr3k/PApvp9M0CFZfZWhKEIlDygTU2TX52q0+zDvON7zdBcN6cpGNAA== -"@angular/cdk@^8.0.0": - version "8.0.0" - resolved "https://registry.yarnpkg.com/@angular/cdk/-/cdk-8.0.0.tgz#34ca95e71d71780b29b5ba07318c88c4577bdc25" - integrity sha512-2vsRWEHNARe0iRmqgzvM67gwfRy+aKvdef4Qu9L+ndSsTrrZT3tSgG8SMn1v9SfBHnx5G8mo4d1AMquXG69AuQ== - dependencies: - tslib "^1.7.1" +"@angular/cdk@^9.2.3": + version "9.2.4" + resolved "https://registry.yarnpkg.com/@angular/cdk/-/cdk-9.2.4.tgz#8413958bd275e4c34be3b96f56444671dd30ba93" + integrity sha512-iw2+qHMXHYVC6K/fttHeNHIieSKiTEodVutZoOEcBu9rmRTGbLB26V/CRsfIRmA1RBk+uFYWc6UQZnMC3RdnJQ== optionalDependencies: parse5 "^5.0.0" -"@angular/cli@~8.0.2": - version "8.0.2" - resolved "https://registry.yarnpkg.com/@angular/cli/-/cli-8.0.2.tgz#b64c044342f0af2ed7e78e51c54087693407a47b" - integrity sha512-xXSCwTKonC6nMqKPDlEFhXjKBu85jVB+KYo2tLU+RKtgFeIF/hTaUWQTvWXRwRsQAfBhB1cwe0oijdljOItTgw== - dependencies: - "@angular-devkit/architect" "0.800.2" - "@angular-devkit/core" "8.0.2" - "@angular-devkit/schematics" "8.0.2" - "@schematics/angular" "8.0.2" - "@schematics/update" "0.800.2" +"@angular/cli@~9.1.6": + version "9.1.6" + resolved "https://registry.yarnpkg.com/@angular/cli/-/cli-9.1.6.tgz#9622745d3fdf73b3045048e7df6c44f5aa8e97f5" + integrity sha512-hQnad0LQx0n+FiMRUV2RX9+L0dLsISu7uzimGLjgJVtW6Bc1cVnaTkKhOqHRQG2Q4Iv8adKWf5UL5tMZz/roDA== + dependencies: + "@angular-devkit/architect" "0.901.6" + "@angular-devkit/core" "9.1.6" + "@angular-devkit/schematics" "9.1.6" + "@schematics/angular" "9.1.6" + "@schematics/update" "0.901.6" "@yarnpkg/lockfile" "1.1.0" - debug "^4.1.1" + ansi-colors "4.1.1" + debug "4.1.1" ini "1.3.5" - inquirer "6.3.1" - npm-package-arg "6.1.0" - open "6.2.0" - pacote "9.5.0" - read-package-tree "5.2.2" - semver "6.0.0" + inquirer "7.1.0" + npm-package-arg "8.0.1" + npm-pick-manifest "6.0.0" + open "7.0.3" + pacote "9.5.12" + read-package-tree "5.3.1" + rimraf "3.0.2" + semver "7.1.3" symbol-observable "1.2.0" - universal-analytics "^0.4.20" - uuid "^3.3.2" + universal-analytics "0.4.20" + uuid "7.0.2" -"@angular/common@^8.0.0": - version "8.0.0" - resolved "https://registry.yarnpkg.com/@angular/common/-/common-8.0.0.tgz#700aeda9be8af96692fce0ea6bf6157f7c874c0e" - integrity sha512-iOAJZ0+1zTRHnHE/5G30+4Q66W1pfZkSkxZIXvgijZ+wtuNloYdWNy/IdZ/m7ayBI7A6FsYEhyMUoWz2HVEJNw== - dependencies: - tslib "^1.9.0" +"@angular/common@>= 5.0.0 < 9.1.0": + version "9.0.4" + resolved "https://registry.yarnpkg.com/@angular/common/-/common-9.0.4.tgz#7d168b22c5c43e72112d0a19242eca22b62bb4f3" + integrity sha512-F3qoYrceEdCd5SlgObcbSIIdKfRXgyTBO2gbbArQHFe4GvewkH3isTn5uqAF6sfJlb7rXWZGrD6C3d9brw/fEw== -"@angular/compiler-cli@8.0.0": - version "8.0.0" - resolved "https://registry.yarnpkg.com/@angular/compiler-cli/-/compiler-cli-8.0.0.tgz#b53ebb5accc34a68bf7a63d16130ca7c568f8a51" - integrity sha512-Z0U0Ih8A7V3J1gq7AXnXbrGAD2ERmz7JbREJJRHDWiUNxIqGQiV3Odo1V8FL5n/cKvLwSYM2Ubvk10gb0+3njA== +"@angular/common@^9.1.7": + version "9.1.8" + resolved "https://registry.yarnpkg.com/@angular/common/-/common-9.1.8.tgz#65112901fd5464379f37aab42bf5c14587fbcc12" + integrity sha512-+vyd9iOEIgtd4aUIBJSIQjM4Z3vupeMpyw4tyPdbLLb86PZeRMSPEDyaK6BxGubHiiUmB8nZ39rnqOvc9sWssw== + +"@angular/compiler-cli@^9.1.7": + version "9.1.8" + resolved "https://registry.yarnpkg.com/@angular/compiler-cli/-/compiler-cli-9.1.8.tgz#87aa892107b63cb2355bdcafaf69a6b8cc81919d" + integrity sha512-11LBB3KIMRAglBsrC+B9jItvGFJe8mq4jp8hiXo/q0qfKVRl1TQy4opu1w63vr5mzGp+29Z4e5NOm8iAveU/3A== dependencies: canonical-path "1.0.0" - chokidar "^2.1.1" + chokidar "^3.0.0" convert-source-map "^1.5.1" dependency-graph "^0.7.2" + fs-extra "4.0.2" magic-string "^0.25.0" minimist "^1.2.0" reflect-metadata "^0.1.2" - shelljs "^0.8.1" + semver "^6.3.0" source-map "^0.6.1" - tslib "^1.9.0" - yargs "13.1.0" + sourcemap-codec "^1.4.8" + yargs "15.3.0" + +"@angular/compiler@^9.1.7": + version "9.1.8" + resolved "https://registry.yarnpkg.com/@angular/compiler/-/compiler-9.1.8.tgz#8e5b080e3c46abf20ccee729bcbc66e1a9d3d194" + integrity sha512-pbsiw+GRdSMbS9Oc+um1WBmypgWB6q3pygyyUXF+8pkpex822hODL7mwMAuNNSS1zNnMzd4bJh0uvPElNLpGHA== + +"@angular/core@^9.1.7": + version "9.1.8" + resolved "https://registry.yarnpkg.com/@angular/core/-/core-9.1.8.tgz#dac2bda4e55238691c87a7acc7de1c29dad5cf98" + integrity sha512-B9ul+DG2qWzO3IrKV09ddDFsLbqjU3jagCL9ovyvu9U0fwWmsNilTVmSa9U/rVx+6mbyqUyfeeF2h6WUllEvCw== + +"@angular/forms@^9.1.7": + version "9.1.8" + resolved "https://registry.yarnpkg.com/@angular/forms/-/forms-9.1.8.tgz#cef8ba19b69500a0950c3eaa9029a9483621155c" + integrity sha512-JLlGh8/y7L/6SFHCgfQysqowWetHH9ZfuGK0aN1unNxvDAUvYTUhweLC6n+zkq/iOQ/FAoJDUEVZQhcBS2ROKA== + +"@angular/language-service@^9.1.7": + version "9.1.8" + resolved "https://registry.yarnpkg.com/@angular/language-service/-/language-service-9.1.8.tgz#dcc8d27c355876ba0a6f4ea4375703e45b6d994c" + integrity sha512-+G2uFUNLCUEn4oThPO1reMHW1RzFqqJpvVs2joKnTzpAwOXWcPppj0vvmX/WzbZ7HWouFg8fjNfRn5tBVMgyXg== + +"@angular/localize@^11.0.2": + version "11.0.2" + resolved "https://registry.yarnpkg.com/@angular/localize/-/localize-11.0.2.tgz#de0fce15d31c958478c280b3aecb398841146f9f" + integrity sha512-G7v/WPjno5QgY2XvYqK9pKP5lsaE17rP6/FIYhTFoA2TTSTJQ0mWlIQigcTvr+AT2t4U6nFJeteGuyIIvpMJYg== + dependencies: + "@babel/core" "7.8.3" + glob "7.1.2" + yargs "^16.1.1" + +"@angular/material@^9.2.3": + version "9.2.4" + resolved "https://registry.yarnpkg.com/@angular/material/-/material-9.2.4.tgz#2666ef606fbb88d60f8e2f18c5e4f94a3dd572d8" + integrity sha512-LkoTXE6B0slvMhvfZDdPWaz4yaYLkaAp5VSPunI9pxGsPxzqEV9e210wC1/sjG/76Nk8Ep7/2z9XKac8Q9bMwA== + +"@angular/platform-browser-dynamic@^9.1.7": + version "9.1.8" + resolved "https://registry.yarnpkg.com/@angular/platform-browser-dynamic/-/platform-browser-dynamic-9.1.8.tgz#c603e3c8f06eef07d6659ea3690e3b2e3ecdc6e7" + integrity sha512-6mZ8vc+P1UIANYBWYbT5L0u+vktYvwYWVyISzJyRuIei5ywL/lm0g0YnmhI4a/ZhPHxVriz0/Gu4mgwceqh+6Q== + +"@angular/platform-browser@^9.1.7": + version "9.1.8" + resolved "https://registry.yarnpkg.com/@angular/platform-browser/-/platform-browser-9.1.8.tgz#541b25bd81488a2a4fdf40857c297e7d0eb93aa3" + integrity sha512-nXUhtu3YBkyCj0Uz/hAtZp+TTn9/VYHUrcIiGY7HJpGF0M9huTAu7gqtItQ2Fbtqfi0EPSGt1NqH75W6HvMvAA== + +"@angular/platform-server@^9.1.7": + version "9.1.8" + resolved "https://registry.yarnpkg.com/@angular/platform-server/-/platform-server-9.1.8.tgz#3bc46252dc8f035d37016f2263f620da54999302" + integrity sha512-mpz/E4z4D70HP+6kD45zFF8x+AOJk7r/Ck2j0K/GI84x0uAJFA0u405Q2ljaewxwEDZs0AYh6g/7yhsXgnApJg== + dependencies: + domino "^2.1.2" + xhr2 "^0.2.0" -"@angular/compiler@^8.0.0": - version "8.0.0" - resolved "https://registry.yarnpkg.com/@angular/compiler/-/compiler-8.0.0.tgz#302c987737e1473db3a113ff70fbbb315aa41b58" - integrity sha512-4rKsVFMNykF83tPL1VE1+j9kZ3cWHUsLOAB/VqmF64EcR/GsbjKog2v23rSso5kqUtPiVq/FWGYllW6qMdxtJA== +"@angular/router@^9.1.7": + version "9.1.8" + resolved "https://registry.yarnpkg.com/@angular/router/-/router-9.1.8.tgz#d01026a43f65d4e867a29e381824b70e2fa733d9" + integrity sha512-ZZdJ4y4YiowQRx4/hEiAw+mGulqrNnnhX1Alfwua7k9paqk+BKyUq3ipy48L1sgk0LxwzeAvvfPS7ad/w/WjfQ== + +"@angularclass/hmr@^2.1.3": + version "2.1.3" + resolved "https://registry.yarnpkg.com/@angularclass/hmr/-/hmr-2.1.3.tgz#34e658ed3da37f23b0a200e2da5a89be92bb209f" + +"@aspnet/signalr@^1.1.0": + version "1.1.4" + resolved "https://registry.yarnpkg.com/@aspnet/signalr/-/signalr-1.1.4.tgz#417cf808f4074a8aec45d27f03c4b8df9d96bb0b" + integrity sha512-Jp9nPc8hmmhbG9OKiHe2fOKskBHfg+3Y9foSKHxjgGtyI743hXjGFv3uFlUg503K9f8Ilu63gQt3fDkLICBRyg== dependencies: - tslib "^1.9.0" + eventsource "^1.0.7" + request "^2.88.0" + ws "^6.0.0" -"@angular/core@^8.0.0": - version "8.0.0" - resolved "https://registry.yarnpkg.com/@angular/core/-/core-8.0.0.tgz#bf7a582b818e9181d830219907470e2b865ba32f" - integrity sha512-mrkP1PTzqCmZGLYll+TDyawLXHzi+FcRPqSuRxCmDMthUUE93SLXT2yISDkx9aMPtFKgFr6KfrIkKuCz16BP/g== +"@auth0/angular-jwt@^2.1.0": + version "2.1.0" + resolved "https://registry.yarnpkg.com/@auth0/angular-jwt/-/angular-jwt-2.1.0.tgz#5c90ee7d927e70cefa8db7c89a64eb67c05a912d" dependencies: - tslib "^1.9.0" + url "^0.11.0" -"@angular/forms@^8.0.0": - version "8.0.0" - resolved "https://registry.yarnpkg.com/@angular/forms/-/forms-8.0.0.tgz#6d636c4f83004290e1a5732a05e87148aaf6ed64" - integrity sha512-T6XdG3mALWzvnrN3fA1hAmfwvraiF1SPMWNXgPk2riuMf8CFdoro+tQZ4eo1islHrTTw5QzmqN8JJALfhAG6bg== +"@babel/code-frame@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.8.3.tgz#33e25903d7481181534e12ec0a25f16b6fcf419e" + integrity sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g== dependencies: - tslib "^1.9.0" + "@babel/highlight" "^7.8.3" -"@angular/http@^7.2.15": - version "7.2.15" - resolved "https://registry.yarnpkg.com/@angular/http/-/http-7.2.15.tgz#a32bea9e67e99eef88150085aeebbe7aeecd39eb" - integrity sha512-TR7PEdmLWNIre3Zn8lvyb4lSrvPUJhKLystLnp4hBMcWsJqq5iK8S3bnlR4viZ9HMlf7bW7+Hm4SI6aB3tdUtw== +"@babel/compat-data@^7.9.0", "@babel/compat-data@^7.9.6": + version "7.9.6" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.9.6.tgz#3f604c40e420131affe6f2c8052e9a275ae2049b" + integrity sha512-5QPTrNen2bm7RBc7dsOmcA5hbrS4O2Vhmk5XOL4zWW/zD/hV0iinpefDlkm+tBBy8kDtFaaeEvmAqt+nURAV2g== dependencies: - tslib "^1.9.0" + browserslist "^4.11.1" + invariant "^2.2.4" + semver "^5.5.0" -"@angular/language-service@^8.0.0": - version "8.0.0" - resolved "https://registry.yarnpkg.com/@angular/language-service/-/language-service-8.0.0.tgz#1ee4ce5003897cad53597da28f4c94fe30519bfb" - integrity sha512-vGk14oWroEo6ycO4cooznx57nn2sASmCQ/sdE8UVwySUKl940TsVzijgaGqapTepFof9sMqN77y2G15eRKQeAQ== +"@babel/core@7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.8.3.tgz#30b0ebb4dd1585de6923a0b4d179e0b9f5d82941" + integrity sha512-4XFkf8AwyrEG7Ziu3L2L0Cv+WyY47Tcsp70JFmpftbAA1K7YL/sgE9jh9HyNj08Y/U50ItUchpN0w6HxAoX1rA== + dependencies: + "@babel/code-frame" "^7.8.3" + "@babel/generator" "^7.8.3" + "@babel/helpers" "^7.8.3" + "@babel/parser" "^7.8.3" + "@babel/template" "^7.8.3" + "@babel/traverse" "^7.8.3" + "@babel/types" "^7.8.3" + convert-source-map "^1.7.0" + debug "^4.1.0" + gensync "^1.0.0-beta.1" + json5 "^2.1.0" + lodash "^4.17.13" + resolve "^1.3.2" + semver "^5.4.1" + source-map "^0.5.0" + +"@babel/core@7.9.0": + version "7.9.0" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.9.0.tgz#ac977b538b77e132ff706f3b8a4dbad09c03c56e" + integrity sha512-kWc7L0fw1xwvI0zi8OKVBuxRVefwGOrKSQMvrQ3dW+bIIavBY3/NpXmpjMy7bQnLgwgzWQZ8TlM57YHpHNHz4w== + dependencies: + "@babel/code-frame" "^7.8.3" + "@babel/generator" "^7.9.0" + "@babel/helper-module-transforms" "^7.9.0" + "@babel/helpers" "^7.9.0" + "@babel/parser" "^7.9.0" + "@babel/template" "^7.8.6" + "@babel/traverse" "^7.9.0" + "@babel/types" "^7.9.0" + convert-source-map "^1.7.0" + debug "^4.1.0" + gensync "^1.0.0-beta.1" + json5 "^2.1.2" + lodash "^4.17.13" + resolve "^1.3.2" + semver "^5.4.1" + source-map "^0.5.0" + +"@babel/core@^7.7.5": + version "7.8.6" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.8.6.tgz#27d7df9258a45c2e686b6f18b6c659e563aa4636" + integrity sha512-Sheg7yEJD51YHAvLEV/7Uvw95AeWqYPL3Vk3zGujJKIhJ+8oLw2ALaf3hbucILhKsgSoADOvtKRJuNVdcJkOrg== + dependencies: + "@babel/code-frame" "^7.8.3" + "@babel/generator" "^7.8.6" + "@babel/helpers" "^7.8.4" + "@babel/parser" "^7.8.6" + "@babel/template" "^7.8.6" + "@babel/traverse" "^7.8.6" + "@babel/types" "^7.8.6" + convert-source-map "^1.7.0" + debug "^4.1.0" + gensync "^1.0.0-beta.1" + json5 "^2.1.0" + lodash "^4.17.13" + resolve "^1.3.2" + semver "^5.4.1" + source-map "^0.5.0" + +"@babel/generator@7.9.3": + version "7.9.3" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.9.3.tgz#7c8b2956c6f68b3ab732bd16305916fbba521d94" + integrity sha512-RpxM252EYsz9qLUIq6F7YJyK1sv0wWDBFuztfDGWaQKzHjqDHysxSiRUpA/X9jmfqo+WzkAVKFaUily5h+gDCQ== + dependencies: + "@babel/types" "^7.9.0" + jsesc "^2.5.1" + lodash "^4.17.13" + source-map "^0.5.0" + +"@babel/generator@^7.8.3", "@babel/generator@^7.8.6": + version "7.8.6" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.8.6.tgz#57adf96d370c9a63c241cd719f9111468578537a" + integrity sha512-4bpOR5ZBz+wWcMeVtcf7FbjcFzCp+817z2/gHNncIRcM9MmKzUhtWCYAq27RAfUrAFwb+OCG1s9WEaVxfi6cjg== + dependencies: + "@babel/types" "^7.8.6" + jsesc "^2.5.1" + lodash "^4.17.13" + source-map "^0.5.0" + +"@babel/generator@^7.9.0", "@babel/generator@^7.9.6": + version "7.9.6" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.9.6.tgz#5408c82ac5de98cda0d77d8124e99fa1f2170a43" + integrity sha512-+htwWKJbH2bL72HRluF8zumBxzuX0ZZUFl3JLNyoUjM/Ho8wnVpPXM6aUz8cfKDqQ/h7zHqKt4xzJteUosckqQ== + dependencies: + "@babel/types" "^7.9.6" + jsesc "^2.5.1" + lodash "^4.17.13" + source-map "^0.5.0" + +"@babel/helper-annotate-as-pure@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.8.3.tgz#60bc0bc657f63a0924ff9a4b4a0b24a13cf4deee" + integrity sha512-6o+mJrZBxOoEX77Ezv9zwW7WV8DdluouRKNY/IR5u/YTMuKHgugHOzYWlYvYLpLA9nPsQCAAASpCIbjI9Mv+Uw== + dependencies: + "@babel/types" "^7.8.3" + +"@babel/helper-builder-binary-assignment-operator-visitor@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.8.3.tgz#c84097a427a061ac56a1c30ebf54b7b22d241503" + integrity sha512-5eFOm2SyFPK4Rh3XMMRDjN7lBH0orh3ss0g3rTYZnBQ+r6YPj7lgDyCvPphynHvUrobJmeMignBr6Acw9mAPlw== + dependencies: + "@babel/helper-explode-assignable-expression" "^7.8.3" + "@babel/types" "^7.8.3" + +"@babel/helper-compilation-targets@^7.8.7": + version "7.9.6" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.9.6.tgz#1e05b7ccc9d38d2f8b40b458b380a04dcfadd38a" + integrity sha512-x2Nvu0igO0ejXzx09B/1fGBxY9NXQlBW2kZsSxCJft+KHN8t9XWzIvFxtPHnBOAXpVsdxZKZFbRUC8TsNKajMw== + dependencies: + "@babel/compat-data" "^7.9.6" + browserslist "^4.11.1" + invariant "^2.2.4" + levenary "^1.1.1" + semver "^5.5.0" -"@angular/material@^8.0.0": - version "8.0.0" - resolved "https://registry.yarnpkg.com/@angular/material/-/material-8.0.0.tgz#21dd15c318d1e29eb4d1a2dd888ddb027897eb49" - integrity sha512-c7O7GhZd46xF2WB6T/YPam5lJkTgQLdIS53IqwZIFhL427+SEfPvejVzRnVfZCI3NdrKiWt/5VsvtQZwWzlGvw== +"@babel/helper-create-regexp-features-plugin@^7.8.3": + version "7.8.6" + resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.8.6.tgz#7fa040c97fb8aebe1247a5c645330c32d083066b" + integrity sha512-bPyujWfsHhV/ztUkwGHz/RPV1T1TDEsSZDsN42JPehndA+p1KKTh3npvTadux0ZhCrytx9tvjpWNowKby3tM6A== + dependencies: + "@babel/helper-annotate-as-pure" "^7.8.3" + "@babel/helper-regex" "^7.8.3" + regexpu-core "^4.6.0" + +"@babel/helper-create-regexp-features-plugin@^7.8.8": + version "7.8.8" + resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.8.8.tgz#5d84180b588f560b7864efaeea89243e58312087" + integrity sha512-LYVPdwkrQEiX9+1R29Ld/wTrmQu1SSKYnuOk3g0CkcZMA1p0gsNxJFj/3gBdaJ7Cg0Fnek5z0DsMULePP7Lrqg== dependencies: - tslib "^1.7.1" + "@babel/helper-annotate-as-pure" "^7.8.3" + "@babel/helper-regex" "^7.8.3" + regexpu-core "^4.7.0" -"@angular/platform-browser-dynamic@^8.0.0": - version "8.0.0" - resolved "https://registry.yarnpkg.com/@angular/platform-browser-dynamic/-/platform-browser-dynamic-8.0.0.tgz#c15f394579ff44f3752033de58edc1afa5065d59" - integrity sha512-dx7W7JoSFbsveexjZ/BPlsXbMDLWVLmRCo7IqLvibMrTbdpaaOCNJIXJk1X+f7JJrQ7SwlZaVkoLCMoDWw6fmA== +"@babel/helper-define-map@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-define-map/-/helper-define-map-7.8.3.tgz#a0655cad5451c3760b726eba875f1cd8faa02c15" + integrity sha512-PoeBYtxoZGtct3md6xZOCWPcKuMuk3IHhgxsRRNtnNShebf4C8YonTSblsK4tvDbm+eJAw2HAPOfCr+Q/YRG/g== + dependencies: + "@babel/helper-function-name" "^7.8.3" + "@babel/types" "^7.8.3" + lodash "^4.17.13" + +"@babel/helper-explode-assignable-expression@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.8.3.tgz#a728dc5b4e89e30fc2dfc7d04fa28a930653f982" + integrity sha512-N+8eW86/Kj147bO9G2uclsg5pwfs/fqqY5rwgIL7eTBklgXjcOJ3btzS5iM6AitJcftnY7pm2lGsrJVYLGjzIw== + dependencies: + "@babel/traverse" "^7.8.3" + "@babel/types" "^7.8.3" + +"@babel/helper-function-name@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.8.3.tgz#eeeb665a01b1f11068e9fb86ad56a1cb1a824cca" + integrity sha512-BCxgX1BC2hD/oBlIFUgOCQDOPV8nSINxCwM3o93xP4P9Fq6aV5sgv2cOOITDMtCfQ+3PvHp3l689XZvAM9QyOA== + dependencies: + "@babel/helper-get-function-arity" "^7.8.3" + "@babel/template" "^7.8.3" + "@babel/types" "^7.8.3" + +"@babel/helper-function-name@^7.9.5": + version "7.9.5" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.9.5.tgz#2b53820d35275120e1874a82e5aabe1376920a5c" + integrity sha512-JVcQZeXM59Cd1qanDUxv9fgJpt3NeKUaqBqUEvfmQ+BCOKq2xUgaWZW2hr0dkbyJgezYuplEoh5knmrnS68efw== + dependencies: + "@babel/helper-get-function-arity" "^7.8.3" + "@babel/template" "^7.8.3" + "@babel/types" "^7.9.5" + +"@babel/helper-get-function-arity@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.8.3.tgz#b894b947bd004381ce63ea1db9f08547e920abd5" + integrity sha512-FVDR+Gd9iLjUMY1fzE2SR0IuaJToR4RkCDARVfsBBPSP53GEqSFjD8gNyxg246VUyc/ALRxFaAK8rVG7UT7xRA== + dependencies: + "@babel/types" "^7.8.3" + +"@babel/helper-hoist-variables@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.8.3.tgz#1dbe9b6b55d78c9b4183fc8cdc6e30ceb83b7134" + integrity sha512-ky1JLOjcDUtSc+xkt0xhYff7Z6ILTAHKmZLHPxAhOP0Nd77O+3nCsd6uSVYur6nJnCI029CrNbYlc0LoPfAPQg== + dependencies: + "@babel/types" "^7.8.3" + +"@babel/helper-member-expression-to-functions@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.8.3.tgz#659b710498ea6c1d9907e0c73f206eee7dadc24c" + integrity sha512-fO4Egq88utkQFjbPrSHGmGLFqmrshs11d46WI+WZDESt7Wu7wN2G2Iu+NMMZJFDOVRHAMIkB5SNh30NtwCA7RA== + dependencies: + "@babel/types" "^7.8.3" + +"@babel/helper-module-imports@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.8.3.tgz#7fe39589b39c016331b6b8c3f441e8f0b1419498" + integrity sha512-R0Bx3jippsbAEtzkpZ/6FIiuzOURPcMjHp+Z6xPe6DtApDJx+w7UYyOLanZqO8+wKR9G10s/FmHXvxaMd9s6Kg== + dependencies: + "@babel/types" "^7.8.3" + +"@babel/helper-module-transforms@^7.9.0": + version "7.9.0" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.9.0.tgz#43b34dfe15961918707d247327431388e9fe96e5" + integrity sha512-0FvKyu0gpPfIQ8EkxlrAydOWROdHpBmiCiRwLkUiBGhCUPRRbVD2/tm3sFr/c/GWFrQ/ffutGUAnx7V0FzT2wA== + dependencies: + "@babel/helper-module-imports" "^7.8.3" + "@babel/helper-replace-supers" "^7.8.6" + "@babel/helper-simple-access" "^7.8.3" + "@babel/helper-split-export-declaration" "^7.8.3" + "@babel/template" "^7.8.6" + "@babel/types" "^7.9.0" + lodash "^4.17.13" + +"@babel/helper-optimise-call-expression@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.8.3.tgz#7ed071813d09c75298ef4f208956006b6111ecb9" + integrity sha512-Kag20n86cbO2AvHca6EJsvqAd82gc6VMGule4HwebwMlwkpXuVqrNRj6CkCV2sKxgi9MyAUnZVnZ6lJ1/vKhHQ== + dependencies: + "@babel/types" "^7.8.3" + +"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz#9ea293be19babc0f52ff8ca88b34c3611b208670" + integrity sha512-j+fq49Xds2smCUNYmEHF9kGNkhbet6yVIBp4e6oeQpH1RUs/Ir06xUKzDjDkGcaaokPiTNs2JBWHjaE4csUkZQ== + +"@babel/helper-regex@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-regex/-/helper-regex-7.8.3.tgz#139772607d51b93f23effe72105b319d2a4c6965" + integrity sha512-BWt0QtYv/cg/NecOAZMdcn/waj/5P26DR4mVLXfFtDokSR6fyuG0Pj+e2FqtSME+MqED1khnSMulkmGl8qWiUQ== + dependencies: + lodash "^4.17.13" + +"@babel/helper-remap-async-to-generator@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.8.3.tgz#273c600d8b9bf5006142c1e35887d555c12edd86" + integrity sha512-kgwDmw4fCg7AVgS4DukQR/roGp+jP+XluJE5hsRZwxCYGg+Rv9wSGErDWhlI90FODdYfd4xG4AQRiMDjjN0GzA== + dependencies: + "@babel/helper-annotate-as-pure" "^7.8.3" + "@babel/helper-wrap-function" "^7.8.3" + "@babel/template" "^7.8.3" + "@babel/traverse" "^7.8.3" + "@babel/types" "^7.8.3" + +"@babel/helper-replace-supers@^7.8.3", "@babel/helper-replace-supers@^7.8.6": + version "7.8.6" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.8.6.tgz#5ada744fd5ad73203bf1d67459a27dcba67effc8" + integrity sha512-PeMArdA4Sv/Wf4zXwBKPqVj7n9UF/xg6slNRtZW84FM7JpE1CbG8B612FyM4cxrf4fMAMGO0kR7voy1ForHHFA== + dependencies: + "@babel/helper-member-expression-to-functions" "^7.8.3" + "@babel/helper-optimise-call-expression" "^7.8.3" + "@babel/traverse" "^7.8.6" + "@babel/types" "^7.8.6" + +"@babel/helper-simple-access@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.8.3.tgz#7f8109928b4dab4654076986af575231deb639ae" + integrity sha512-VNGUDjx5cCWg4vvCTR8qQ7YJYZ+HBjxOgXEl7ounz+4Sn7+LMD3CFrCTEU6/qXKbA2nKg21CwhhBzO0RpRbdCw== + dependencies: + "@babel/template" "^7.8.3" + "@babel/types" "^7.8.3" + +"@babel/helper-split-export-declaration@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.8.3.tgz#31a9f30070f91368a7182cf05f831781065fc7a9" + integrity sha512-3x3yOeyBhW851hroze7ElzdkeRXQYQbFIb7gLK1WQYsw2GWDay5gAJNw1sWJ0VFP6z5J1whqeXH/WCdCjZv6dA== + dependencies: + "@babel/types" "^7.8.3" + +"@babel/helper-validator-identifier@^7.9.5": + version "7.9.5" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.9.5.tgz#90977a8e6fbf6b431a7dc31752eee233bf052d80" + integrity sha512-/8arLKUFq882w4tWGj9JYzRpAlZgiWUJ+dtteNTDqrRBz9Iguck9Rn3ykuBDoUwh2TO4tSAJlrxDUOXWklJe4g== + +"@babel/helper-wrap-function@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.8.3.tgz#9dbdb2bb55ef14aaa01fe8c99b629bd5352d8610" + integrity sha512-LACJrbUET9cQDzb6kG7EeD7+7doC3JNvUgTEQOx2qaO1fKlzE/Bf05qs9w1oXQMmXlPO65lC3Tq9S6gZpTErEQ== + dependencies: + "@babel/helper-function-name" "^7.8.3" + "@babel/template" "^7.8.3" + "@babel/traverse" "^7.8.3" + "@babel/types" "^7.8.3" + +"@babel/helpers@^7.8.3", "@babel/helpers@^7.8.4": + version "7.8.4" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.8.4.tgz#754eb3ee727c165e0a240d6c207de7c455f36f73" + integrity sha512-VPbe7wcQ4chu4TDQjimHv/5tj73qz88o12EPkO2ValS2QiQS/1F2SsjyIGNnAD0vF/nZS6Cf9i+vW6HIlnaR8w== + dependencies: + "@babel/template" "^7.8.3" + "@babel/traverse" "^7.8.4" + "@babel/types" "^7.8.3" + +"@babel/helpers@^7.9.0": + version "7.9.6" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.9.6.tgz#092c774743471d0bb6c7de3ad465ab3d3486d580" + integrity sha512-tI4bUbldloLcHWoRUMAj4g1bF313M/o6fBKhIsb3QnGVPwRm9JsNf/gqMkQ7zjqReABiffPV6RWj7hEglID5Iw== + dependencies: + "@babel/template" "^7.8.3" + "@babel/traverse" "^7.9.6" + "@babel/types" "^7.9.6" + +"@babel/highlight@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.8.3.tgz#28f173d04223eaaa59bc1d439a3836e6d1265797" + integrity sha512-PX4y5xQUvy0fnEVHrYOarRPXVWafSjTW9T0Hab8gVIawpl2Sj0ORyrygANq+KjcNlSSTw0YCLSNA8OyZ1I4yEg== + dependencies: + chalk "^2.0.0" + esutils "^2.0.2" + js-tokens "^4.0.0" + +"@babel/parser@^7.8.3", "@babel/parser@^7.8.6": + version "7.8.6" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.8.6.tgz#ba5c9910cddb77685a008e3c587af8d27b67962c" + integrity sha512-trGNYSfwq5s0SgM1BMEB8hX3NDmO7EP2wsDGDexiaKMB92BaRpS+qZfpkMqUBhcsOTBwNy9B/jieo4ad/t/z2g== + +"@babel/parser@^7.9.0", "@babel/parser@^7.9.6": + version "7.9.6" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.9.6.tgz#3b1bbb30dabe600cd72db58720998376ff653bc7" + integrity sha512-AoeIEJn8vt+d/6+PXDRPaksYhnlbMIiejioBZvvMQsOjW/JYK6k/0dKnvvP3EhK5GfMBWDPtrxRtegWdAcdq9Q== + +"@babel/plugin-proposal-async-generator-functions@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.8.3.tgz#bad329c670b382589721b27540c7d288601c6e6f" + integrity sha512-NZ9zLv848JsV3hs8ryEh7Uaz/0KsmPLqv0+PdkDJL1cJy0K4kOCFa8zc1E3mp+RHPQcpdfb/6GovEsW4VDrOMw== dependencies: - tslib "^1.9.0" + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-remap-async-to-generator" "^7.8.3" + "@babel/plugin-syntax-async-generators" "^7.8.0" -"@angular/platform-browser@^8.0.0": - version "8.0.0" - resolved "https://registry.yarnpkg.com/@angular/platform-browser/-/platform-browser-8.0.0.tgz#fc7c55a0483e67e5606e499c129fda60ae8d4363" - integrity sha512-fTD+pTMbq+On9Uv3VXiei2lfuX7GX31dngm/Y4yWTFeW6eXy0+7kkfflzpLOb0hykCZvcXzarqCuEBBYNLrrOg== +"@babel/plugin-proposal-dynamic-import@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.8.3.tgz#38c4fe555744826e97e2ae930b0fb4cc07e66054" + integrity sha512-NyaBbyLFXFLT9FP+zk0kYlUlA8XtCUbehs67F0nnEg7KICgMc2mNkIeu9TYhKzyXMkrapZFwAhXLdnt4IYHy1w== dependencies: - tslib "^1.9.0" + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/plugin-syntax-dynamic-import" "^7.8.0" -"@angular/platform-server@^8.0.0": - version "8.0.0" - resolved "https://registry.yarnpkg.com/@angular/platform-server/-/platform-server-8.0.0.tgz#87e80acba6b09955046dc0a9da7cd6b2e005061a" - integrity sha512-pA6m1okOfyy2qH5A6jUxrhx6z7eAG+ne7IM+j/6JUBDjp4KO9BC84aa/xfpZq5dsskl8E8II9c4hUKocMyeRjA== +"@babel/plugin-proposal-json-strings@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.8.3.tgz#da5216b238a98b58a1e05d6852104b10f9a70d6b" + integrity sha512-KGhQNZ3TVCQG/MjRbAUwuH+14y9q0tpxs1nWWs3pbSleRdDro9SAMMDyye8HhY1gqZ7/NqIc8SKhya0wRDgP1Q== dependencies: - domino "^2.1.2" - tslib "^1.9.0" - xhr2 "^0.1.4" + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/plugin-syntax-json-strings" "^7.8.0" -"@angular/router@^8.0.0": - version "8.0.0" - resolved "https://registry.yarnpkg.com/@angular/router/-/router-8.0.0.tgz#26094fd473e17441b0ae8af4883ec1b4ea3ad569" - integrity sha512-DGUTb8qpndE5m716xh00GxuC8o7qamlqbUruGB+SQD6ynU7s5yLGxtKffxqb1BT63+YewpsVxc2Koruvb1qjDw== +"@babel/plugin-proposal-nullish-coalescing-operator@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.8.3.tgz#e4572253fdeed65cddeecfdab3f928afeb2fd5d2" + integrity sha512-TS9MlfzXpXKt6YYomudb/KU7nQI6/xnapG6in1uZxoxDghuSMZsPb6D2fyUwNYSAp4l1iR7QtFOjkqcRYcUsfw== dependencies: - tslib "^1.9.0" + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.0" -"@angularclass/hmr@^2.1.3": - version "2.1.3" - resolved "https://registry.yarnpkg.com/@angularclass/hmr/-/hmr-2.1.3.tgz#34e658ed3da37f23b0a200e2da5a89be92bb209f" +"@babel/plugin-proposal-numeric-separator@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.8.3.tgz#5d6769409699ec9b3b68684cd8116cedff93bad8" + integrity sha512-jWioO1s6R/R+wEHizfaScNsAx+xKgwTLNXSh7tTC4Usj3ItsPEhYkEpU4h+lpnBwq7NBVOJXfO6cRFYcX69JUQ== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/plugin-syntax-numeric-separator" "^7.8.3" -"@aspnet/signalr@^1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@aspnet/signalr/-/signalr-1.1.0.tgz#616be5d565f78ea6ab3910d8a5fb0690471b35f9" +"@babel/plugin-proposal-object-rest-spread@^7.9.0": + version "7.9.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.9.6.tgz#7a093586fcb18b08266eb1a7177da671ac575b63" + integrity sha512-Ga6/fhGqA9Hj+y6whNpPv8psyaK5xzrQwSPsGPloVkvmH+PqW1ixdnfJ9uIO06OjQNYol3PMnfmJ8vfZtkzF+A== dependencies: - eventsource "^1.0.7" - request "^2.88.0" - ws "^6.0.0" + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/plugin-syntax-object-rest-spread" "^7.8.0" + "@babel/plugin-transform-parameters" "^7.9.5" -"@auth0/angular-jwt@^2.1.0": - version "2.1.0" - resolved "https://registry.yarnpkg.com/@auth0/angular-jwt/-/angular-jwt-2.1.0.tgz#5c90ee7d927e70cefa8db7c89a64eb67c05a912d" +"@babel/plugin-proposal-optional-catch-binding@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.8.3.tgz#9dee96ab1650eed88646ae9734ca167ac4a9c5c9" + integrity sha512-0gkX7J7E+AtAw9fcwlVQj8peP61qhdg/89D5swOkjYbkboA2CVckn3kiyum1DE0wskGb7KJJxBdyEBApDLLVdw== dependencies: - url "^0.11.0" + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/plugin-syntax-optional-catch-binding" "^7.8.0" + +"@babel/plugin-proposal-optional-chaining@^7.9.0": + version "7.9.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.9.0.tgz#31db16b154c39d6b8a645292472b98394c292a58" + integrity sha512-NDn5tu3tcv4W30jNhmc2hyD5c56G6cXx4TesJubhxrJeCvuuMpttxr0OnNCqbZGhFjLrg+NIhxxC+BK5F6yS3w== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/plugin-syntax-optional-chaining" "^7.8.0" + +"@babel/plugin-proposal-unicode-property-regex@^7.4.4": + version "7.8.8" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.8.8.tgz#ee3a95e90cdc04fe8cd92ec3279fa017d68a0d1d" + integrity sha512-EVhjVsMpbhLw9ZfHWSx2iy13Q8Z/eg8e8ccVWt23sWQK5l1UdkoLJPN5w69UA4uITGBnEZD2JOe4QOHycYKv8A== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.8.8" + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-proposal-unicode-property-regex@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.8.3.tgz#b646c3adea5f98800c9ab45105ac34d06cd4a47f" + integrity sha512-1/1/rEZv2XGweRwwSkLpY+s60za9OZ1hJs4YDqFHCw0kYWYwL5IFljVY1MYBL+weT1l9pokDO2uhSTLVxzoHkQ== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.8.3" + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-syntax-async-generators@^7.8.0": + version "7.8.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz#a983fb1aeb2ec3f6ed042a210f640e90e786fe0d" + integrity sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-dynamic-import@^7.8.0": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz#62bf98b2da3cd21d626154fc96ee5b3cb68eacb3" + integrity sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-json-strings@^7.8.0": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz#01ca21b668cd8218c9e640cb6dd88c5412b2c96a" + integrity sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-nullish-coalescing-operator@^7.8.0": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz#167ed70368886081f74b5c36c65a88c03b66d1a9" + integrity sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-numeric-separator@^7.8.0", "@babel/plugin-syntax-numeric-separator@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.8.3.tgz#0e3fb63e09bea1b11e96467271c8308007e7c41f" + integrity sha512-H7dCMAdN83PcCmqmkHB5dtp+Xa9a6LKSvA2hiFBC/5alSHxM5VgWZXFqDi0YFe8XNGT6iCa+z4V4zSt/PdZ7Dw== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-syntax-object-rest-spread@^7.8.0": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz#60e225edcbd98a640332a2e72dd3e66f1af55871" + integrity sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-optional-catch-binding@^7.8.0": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz#6111a265bcfb020eb9efd0fdfd7d26402b9ed6c1" + integrity sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-optional-chaining@^7.8.0": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz#4f69c2ab95167e0180cd5336613f8c5788f7d48a" + integrity sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-top-level-await@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.8.3.tgz#3acdece695e6b13aaf57fc291d1a800950c71391" + integrity sha512-kwj1j9lL/6Wd0hROD3b/OZZ7MSrZLqqn9RAZ5+cYYsflQ9HZBIKCUkr3+uL1MEJ1NePiUbf98jjiMQSv0NMR9g== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-transform-arrow-functions@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.8.3.tgz#82776c2ed0cd9e1a49956daeb896024c9473b8b6" + integrity sha512-0MRF+KC8EqH4dbuITCWwPSzsyO3HIWWlm30v8BbbpOrS1B++isGxPnnuq/IZvOX5J2D/p7DQalQm+/2PnlKGxg== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-transform-async-to-generator@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.8.3.tgz#4308fad0d9409d71eafb9b1a6ee35f9d64b64086" + integrity sha512-imt9tFLD9ogt56Dd5CI/6XgpukMwd/fLGSrix2httihVe7LOGVPhyhMh1BU5kDM7iHD08i8uUtmV2sWaBFlHVQ== + dependencies: + "@babel/helper-module-imports" "^7.8.3" + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-remap-async-to-generator" "^7.8.3" + +"@babel/plugin-transform-block-scoped-functions@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.8.3.tgz#437eec5b799b5852072084b3ae5ef66e8349e8a3" + integrity sha512-vo4F2OewqjbB1+yaJ7k2EJFHlTP3jR634Z9Cj9itpqNjuLXvhlVxgnjsHsdRgASR8xYDrx6onw4vW5H6We0Jmg== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-transform-block-scoping@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.8.3.tgz#97d35dab66857a437c166358b91d09050c868f3a" + integrity sha512-pGnYfm7RNRgYRi7bids5bHluENHqJhrV4bCZRwc5GamaWIIs07N4rZECcmJL6ZClwjDz1GbdMZFtPs27hTB06w== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + lodash "^4.17.13" + +"@babel/plugin-transform-classes@^7.9.0": + version "7.9.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.9.5.tgz#800597ddb8aefc2c293ed27459c1fcc935a26c2c" + integrity sha512-x2kZoIuLC//O5iA7PEvecB105o7TLzZo8ofBVhP79N+DO3jaX+KYfww9TQcfBEZD0nikNyYcGB1IKtRq36rdmg== + dependencies: + "@babel/helper-annotate-as-pure" "^7.8.3" + "@babel/helper-define-map" "^7.8.3" + "@babel/helper-function-name" "^7.9.5" + "@babel/helper-optimise-call-expression" "^7.8.3" + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-replace-supers" "^7.8.6" + "@babel/helper-split-export-declaration" "^7.8.3" + globals "^11.1.0" + +"@babel/plugin-transform-computed-properties@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.8.3.tgz#96d0d28b7f7ce4eb5b120bb2e0e943343c86f81b" + integrity sha512-O5hiIpSyOGdrQZRQ2ccwtTVkgUDBBiCuK//4RJ6UfePllUTCENOzKxfh6ulckXKc0DixTFLCfb2HVkNA7aDpzA== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-transform-destructuring@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.8.3.tgz#20ddfbd9e4676906b1056ee60af88590cc7aaa0b" + integrity sha512-H4X646nCkiEcHZUZaRkhE2XVsoz0J/1x3VVujnn96pSoGCtKPA99ZZA+va+gK+92Zycd6OBKCD8tDb/731bhgQ== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-transform-dotall-regex@^7.4.4", "@babel/plugin-transform-dotall-regex@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.8.3.tgz#c3c6ec5ee6125c6993c5cbca20dc8621a9ea7a6e" + integrity sha512-kLs1j9Nn4MQoBYdRXH6AeaXMbEJFaFu/v1nQkvib6QzTj8MZI5OQzqmD83/2jEM1z0DLilra5aWO5YpyC0ALIw== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.8.3" + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-transform-duplicate-keys@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.8.3.tgz#8d12df309aa537f272899c565ea1768e286e21f1" + integrity sha512-s8dHiBUbcbSgipS4SMFuWGqCvyge5V2ZeAWzR6INTVC3Ltjig/Vw1G2Gztv0vU/hRG9X8IvKvYdoksnUfgXOEQ== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-transform-exponentiation-operator@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.8.3.tgz#581a6d7f56970e06bf51560cd64f5e947b70d7b7" + integrity sha512-zwIpuIymb3ACcInbksHaNcR12S++0MDLKkiqXHl3AzpgdKlFNhog+z/K0+TGW+b0w5pgTq4H6IwV/WhxbGYSjQ== + dependencies: + "@babel/helper-builder-binary-assignment-operator-visitor" "^7.8.3" + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-transform-for-of@^7.9.0": + version "7.9.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.9.0.tgz#0f260e27d3e29cd1bb3128da5e76c761aa6c108e" + integrity sha512-lTAnWOpMwOXpyDx06N+ywmF3jNbafZEqZ96CGYabxHrxNX8l5ny7dt4bK/rGwAh9utyP2b2Hv7PlZh1AAS54FQ== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-transform-function-name@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.8.3.tgz#279373cb27322aaad67c2683e776dfc47196ed8b" + integrity sha512-rO/OnDS78Eifbjn5Py9v8y0aR+aSYhDhqAwVfsTl0ERuMZyr05L1aFSCJnbv2mmsLkit/4ReeQ9N2BgLnOcPCQ== + dependencies: + "@babel/helper-function-name" "^7.8.3" + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-transform-literals@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.8.3.tgz#aef239823d91994ec7b68e55193525d76dbd5dc1" + integrity sha512-3Tqf8JJ/qB7TeldGl+TT55+uQei9JfYaregDcEAyBZ7akutriFrt6C/wLYIer6OYhleVQvH/ntEhjE/xMmy10A== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-transform-member-expression-literals@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.8.3.tgz#963fed4b620ac7cbf6029c755424029fa3a40410" + integrity sha512-3Wk2EXhnw+rP+IDkK6BdtPKsUE5IeZ6QOGrPYvw52NwBStw9V1ZVzxgK6fSKSxqUvH9eQPR3tm3cOq79HlsKYA== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-transform-modules-amd@^7.9.0": + version "7.9.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.9.6.tgz#8539ec42c153d12ea3836e0e3ac30d5aae7b258e" + integrity sha512-zoT0kgC3EixAyIAU+9vfaUVKTv9IxBDSabgHoUCBP6FqEJ+iNiN7ip7NBKcYqbfUDfuC2mFCbM7vbu4qJgOnDw== + dependencies: + "@babel/helper-module-transforms" "^7.9.0" + "@babel/helper-plugin-utils" "^7.8.3" + babel-plugin-dynamic-import-node "^2.3.3" + +"@babel/plugin-transform-modules-commonjs@^7.9.0": + version "7.9.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.9.6.tgz#64b7474a4279ee588cacd1906695ca721687c277" + integrity sha512-7H25fSlLcn+iYimmsNe3uK1at79IE6SKW9q0/QeEHTMC9MdOZ+4bA+T1VFB5fgOqBWoqlifXRzYD0JPdmIrgSQ== + dependencies: + "@babel/helper-module-transforms" "^7.9.0" + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-simple-access" "^7.8.3" + babel-plugin-dynamic-import-node "^2.3.3" + +"@babel/plugin-transform-modules-systemjs@^7.9.0": + version "7.9.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.9.6.tgz#207f1461c78a231d5337a92140e52422510d81a4" + integrity sha512-NW5XQuW3N2tTHim8e1b7qGy7s0kZ2OH3m5octc49K1SdAKGxYxeIx7hiIz05kS1R2R+hOWcsr1eYwcGhrdHsrg== + dependencies: + "@babel/helper-hoist-variables" "^7.8.3" + "@babel/helper-module-transforms" "^7.9.0" + "@babel/helper-plugin-utils" "^7.8.3" + babel-plugin-dynamic-import-node "^2.3.3" + +"@babel/plugin-transform-modules-umd@^7.9.0": + version "7.9.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.9.0.tgz#e909acae276fec280f9b821a5f38e1f08b480697" + integrity sha512-uTWkXkIVtg/JGRSIABdBoMsoIeoHQHPTL0Y2E7xf5Oj7sLqwVsNXOkNk0VJc7vF0IMBsPeikHxFjGe+qmwPtTQ== + dependencies: + "@babel/helper-module-transforms" "^7.9.0" + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-transform-named-capturing-groups-regex@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.8.3.tgz#a2a72bffa202ac0e2d0506afd0939c5ecbc48c6c" + integrity sha512-f+tF/8UVPU86TrCb06JoPWIdDpTNSGGcAtaD9mLP0aYGA0OS0j7j7DHJR0GTFrUZPUU6loZhbsVZgTh0N+Qdnw== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.8.3" + +"@babel/plugin-transform-new-target@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.8.3.tgz#60cc2ae66d85c95ab540eb34babb6434d4c70c43" + integrity sha512-QuSGysibQpyxexRyui2vca+Cmbljo8bcRckgzYV4kRIsHpVeyeC3JDO63pY+xFZ6bWOBn7pfKZTqV4o/ix9sFw== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-transform-object-super@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.8.3.tgz#ebb6a1e7a86ffa96858bd6ac0102d65944261725" + integrity sha512-57FXk+gItG/GejofIyLIgBKTas4+pEU47IXKDBWFTxdPd7F80H8zybyAY7UoblVfBhBGs2EKM+bJUu2+iUYPDQ== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-replace-supers" "^7.8.3" + +"@babel/plugin-transform-parameters@^7.8.7", "@babel/plugin-transform-parameters@^7.9.5": + version "7.9.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.9.5.tgz#173b265746f5e15b2afe527eeda65b73623a0795" + integrity sha512-0+1FhHnMfj6lIIhVvS4KGQJeuhe1GI//h5uptK4PvLt+BGBxsoUJbd3/IW002yk//6sZPlFgsG1hY6OHLcy6kA== + dependencies: + "@babel/helper-get-function-arity" "^7.8.3" + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-transform-property-literals@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.8.3.tgz#33194300d8539c1ed28c62ad5087ba3807b98263" + integrity sha512-uGiiXAZMqEoQhRWMK17VospMZh5sXWg+dlh2soffpkAl96KAm+WZuJfa6lcELotSRmooLqg0MWdH6UUq85nmmg== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-transform-regenerator@^7.8.7": + version "7.8.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.8.7.tgz#5e46a0dca2bee1ad8285eb0527e6abc9c37672f8" + integrity sha512-TIg+gAl4Z0a3WmD3mbYSk+J9ZUH6n/Yc57rtKRnlA/7rcCvpekHXe0CMZHP1gYp7/KLe9GHTuIba0vXmls6drA== + dependencies: + regenerator-transform "^0.14.2" + +"@babel/plugin-transform-reserved-words@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.8.3.tgz#9a0635ac4e665d29b162837dd3cc50745dfdf1f5" + integrity sha512-mwMxcycN3omKFDjDQUl+8zyMsBfjRFr0Zn/64I41pmjv4NJuqcYlEtezwYtw9TFd9WR1vN5kiM+O0gMZzO6L0A== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-transform-shorthand-properties@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.8.3.tgz#28545216e023a832d4d3a1185ed492bcfeac08c8" + integrity sha512-I9DI6Odg0JJwxCHzbzW08ggMdCezoWcuQRz3ptdudgwaHxTjxw5HgdFJmZIkIMlRymL6YiZcped4TTCB0JcC8w== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-transform-spread@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.8.3.tgz#9c8ffe8170fdfb88b114ecb920b82fb6e95fe5e8" + integrity sha512-CkuTU9mbmAoFOI1tklFWYYbzX5qCIZVXPVy0jpXgGwkplCndQAa58s2jr66fTeQnA64bDox0HL4U56CFYoyC7g== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-transform-sticky-regex@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.8.3.tgz#be7a1290f81dae767475452199e1f76d6175b100" + integrity sha512-9Spq0vGCD5Bb4Z/ZXXSK5wbbLFMG085qd2vhL1JYu1WcQ5bXqZBAYRzU1d+p79GcHs2szYv5pVQCX13QgldaWw== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-regex" "^7.8.3" + +"@babel/plugin-transform-template-literals@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.8.3.tgz#7bfa4732b455ea6a43130adc0ba767ec0e402a80" + integrity sha512-820QBtykIQOLFT8NZOcTRJ1UNuztIELe4p9DCgvj4NK+PwluSJ49we7s9FB1HIGNIYT7wFUJ0ar2QpCDj0escQ== + dependencies: + "@babel/helper-annotate-as-pure" "^7.8.3" + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-transform-typeof-symbol@^7.8.4": + version "7.8.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.8.4.tgz#ede4062315ce0aaf8a657a920858f1a2f35fc412" + integrity sha512-2QKyfjGdvuNfHsb7qnBBlKclbD4CfshH2KvDabiijLMGXPHJXGxtDzwIF7bQP+T0ysw8fYTtxPafgfs/c1Lrqg== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-transform-unicode-regex@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.8.3.tgz#0cef36e3ba73e5c57273effb182f46b91a1ecaad" + integrity sha512-+ufgJjYdmWfSQ+6NS9VGUR2ns8cjJjYbrbi11mZBTaWm+Fui/ncTLFF28Ei1okavY+xkojGr1eJxNsWYeA5aZw== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.8.3" + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/preset-env@7.9.0": + version "7.9.0" + resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.9.0.tgz#a5fc42480e950ae8f5d9f8f2bbc03f52722df3a8" + integrity sha512-712DeRXT6dyKAM/FMbQTV/FvRCms2hPCx+3weRjZ8iQVQWZejWWk1wwG6ViWMyqb/ouBbGOl5b6aCk0+j1NmsQ== + dependencies: + "@babel/compat-data" "^7.9.0" + "@babel/helper-compilation-targets" "^7.8.7" + "@babel/helper-module-imports" "^7.8.3" + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/plugin-proposal-async-generator-functions" "^7.8.3" + "@babel/plugin-proposal-dynamic-import" "^7.8.3" + "@babel/plugin-proposal-json-strings" "^7.8.3" + "@babel/plugin-proposal-nullish-coalescing-operator" "^7.8.3" + "@babel/plugin-proposal-numeric-separator" "^7.8.3" + "@babel/plugin-proposal-object-rest-spread" "^7.9.0" + "@babel/plugin-proposal-optional-catch-binding" "^7.8.3" + "@babel/plugin-proposal-optional-chaining" "^7.9.0" + "@babel/plugin-proposal-unicode-property-regex" "^7.8.3" + "@babel/plugin-syntax-async-generators" "^7.8.0" + "@babel/plugin-syntax-dynamic-import" "^7.8.0" + "@babel/plugin-syntax-json-strings" "^7.8.0" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.0" + "@babel/plugin-syntax-numeric-separator" "^7.8.0" + "@babel/plugin-syntax-object-rest-spread" "^7.8.0" + "@babel/plugin-syntax-optional-catch-binding" "^7.8.0" + "@babel/plugin-syntax-optional-chaining" "^7.8.0" + "@babel/plugin-syntax-top-level-await" "^7.8.3" + "@babel/plugin-transform-arrow-functions" "^7.8.3" + "@babel/plugin-transform-async-to-generator" "^7.8.3" + "@babel/plugin-transform-block-scoped-functions" "^7.8.3" + "@babel/plugin-transform-block-scoping" "^7.8.3" + "@babel/plugin-transform-classes" "^7.9.0" + "@babel/plugin-transform-computed-properties" "^7.8.3" + "@babel/plugin-transform-destructuring" "^7.8.3" + "@babel/plugin-transform-dotall-regex" "^7.8.3" + "@babel/plugin-transform-duplicate-keys" "^7.8.3" + "@babel/plugin-transform-exponentiation-operator" "^7.8.3" + "@babel/plugin-transform-for-of" "^7.9.0" + "@babel/plugin-transform-function-name" "^7.8.3" + "@babel/plugin-transform-literals" "^7.8.3" + "@babel/plugin-transform-member-expression-literals" "^7.8.3" + "@babel/plugin-transform-modules-amd" "^7.9.0" + "@babel/plugin-transform-modules-commonjs" "^7.9.0" + "@babel/plugin-transform-modules-systemjs" "^7.9.0" + "@babel/plugin-transform-modules-umd" "^7.9.0" + "@babel/plugin-transform-named-capturing-groups-regex" "^7.8.3" + "@babel/plugin-transform-new-target" "^7.8.3" + "@babel/plugin-transform-object-super" "^7.8.3" + "@babel/plugin-transform-parameters" "^7.8.7" + "@babel/plugin-transform-property-literals" "^7.8.3" + "@babel/plugin-transform-regenerator" "^7.8.7" + "@babel/plugin-transform-reserved-words" "^7.8.3" + "@babel/plugin-transform-shorthand-properties" "^7.8.3" + "@babel/plugin-transform-spread" "^7.8.3" + "@babel/plugin-transform-sticky-regex" "^7.8.3" + "@babel/plugin-transform-template-literals" "^7.8.3" + "@babel/plugin-transform-typeof-symbol" "^7.8.4" + "@babel/plugin-transform-unicode-regex" "^7.8.3" + "@babel/preset-modules" "^0.1.3" + "@babel/types" "^7.9.0" + browserslist "^4.9.1" + core-js-compat "^3.6.2" + invariant "^2.2.2" + levenary "^1.1.1" + semver "^5.5.0" + +"@babel/preset-modules@^0.1.3": + version "0.1.3" + resolved "https://registry.yarnpkg.com/@babel/preset-modules/-/preset-modules-0.1.3.tgz#13242b53b5ef8c883c3cf7dddd55b36ce80fbc72" + integrity sha512-Ra3JXOHBq2xd56xSF7lMKXdjBn3T772Y1Wet3yWnkDly9zHvJki029tAFzvAAK5cf4YV3yoxuP61crYRol6SVg== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/plugin-proposal-unicode-property-regex" "^7.4.4" + "@babel/plugin-transform-dotall-regex" "^7.4.4" + "@babel/types" "^7.4.4" + esutils "^2.0.2" + +"@babel/runtime@^7.8.4": + version "7.9.6" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.9.6.tgz#a9102eb5cadedf3f31d08a9ecf294af7827ea29f" + integrity sha512-64AF1xY3OAkFHqOb9s4jpgk1Mm5vDZ4L3acHvAml+53nO1XbXLuDodsVpO4OIUsmemlUHMxNdYMNJmsvOwLrvQ== + dependencies: + regenerator-runtime "^0.13.4" + +"@babel/template@7.8.6", "@babel/template@^7.8.3", "@babel/template@^7.8.6": + version "7.8.6" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.8.6.tgz#86b22af15f828dfb086474f964dcc3e39c43ce2b" + integrity sha512-zbMsPMy/v0PWFZEhQJ66bqjhH+z0JgMoBWuikXybgG3Gkd/3t5oQ1Rw2WQhnSrsOmsKXnZOx15tkC4qON/+JPg== + dependencies: + "@babel/code-frame" "^7.8.3" + "@babel/parser" "^7.8.6" + "@babel/types" "^7.8.6" + +"@babel/traverse@^7.8.3", "@babel/traverse@^7.8.4", "@babel/traverse@^7.8.6": + version "7.8.6" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.8.6.tgz#acfe0c64e1cd991b3e32eae813a6eb564954b5ff" + integrity sha512-2B8l0db/DPi8iinITKuo7cbPznLCEk0kCxDoB9/N6gGNg/gxOXiR/IcymAFPiBwk5w6TtQ27w4wpElgp9btR9A== + dependencies: + "@babel/code-frame" "^7.8.3" + "@babel/generator" "^7.8.6" + "@babel/helper-function-name" "^7.8.3" + "@babel/helper-split-export-declaration" "^7.8.3" + "@babel/parser" "^7.8.6" + "@babel/types" "^7.8.6" + debug "^4.1.0" + globals "^11.1.0" + lodash "^4.17.13" + +"@babel/traverse@^7.9.0", "@babel/traverse@^7.9.6": + version "7.9.6" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.9.6.tgz#5540d7577697bf619cc57b92aa0f1c231a94f442" + integrity sha512-b3rAHSjbxy6VEAvlxM8OV/0X4XrG72zoxme6q1MOoe2vd0bEc+TwayhuC1+Dfgqh1QEG+pj7atQqvUprHIccsg== + dependencies: + "@babel/code-frame" "^7.8.3" + "@babel/generator" "^7.9.6" + "@babel/helper-function-name" "^7.9.5" + "@babel/helper-split-export-declaration" "^7.8.3" + "@babel/parser" "^7.9.6" + "@babel/types" "^7.9.6" + debug "^4.1.0" + globals "^11.1.0" + lodash "^4.17.13" + +"@babel/types@^7.4.4", "@babel/types@^7.9.0", "@babel/types@^7.9.5", "@babel/types@^7.9.6": + version "7.9.6" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.9.6.tgz#2c5502b427251e9de1bd2dff95add646d95cc9f7" + integrity sha512-qxXzvBO//jO9ZnoasKF1uJzHd2+M6Q2ZPIVfnFps8JJvXy0ZBbwbNOmE6SGIY5XOY6d1Bo5lb9d9RJ8nv3WSeA== + dependencies: + "@babel/helper-validator-identifier" "^7.9.5" + lodash "^4.17.13" + to-fast-properties "^2.0.0" + +"@babel/types@^7.8.3", "@babel/types@^7.8.6": + version "7.8.6" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.8.6.tgz#629ecc33c2557fcde7126e58053127afdb3e6d01" + integrity sha512-wqz7pgWMIrht3gquyEFPVXeXCti72Rm8ep9b5tQKz9Yg9LzJA3HxosF1SB3Kc81KD1A3XBkkVYtJvCKS2Z/QrA== + dependencies: + esutils "^2.0.2" + lodash "^4.17.13" + to-fast-properties "^2.0.0" "@fullcalendar/core@^4.2.0": - version "4.2.0" - resolved "https://registry.yarnpkg.com/@fullcalendar/core/-/core-4.2.0.tgz#16716d6617137e54fceeb03c72f5124c92b86e58" - integrity sha512-4kd5OGHxjMtwI0gUHKwAYzmR0Z79Qf8y0ARx2Ruh20JdVy3Tznn6oKwdpkUbaXWrLXNDoXYRkBiFCIgC27VNCw== + version "4.4.0" + resolved "https://registry.yarnpkg.com/@fullcalendar/core/-/core-4.4.0.tgz#79dbc0cca836ce628a07e739a456da11ff141373" + integrity sha512-PC4mmXHJHAlXmUEmZVnePyA8yYCOBdxBNq8yjJqedEtT1X0x36yTFz/Y0Ux6bniICZDqYtk0xoxe6jaxi++e0g== + +"@fullcalendar/daygrid@^4.4.0": + version "4.4.0" + resolved "https://registry.yarnpkg.com/@fullcalendar/daygrid/-/daygrid-4.4.0.tgz#25fcae7226b62688b4e086a611582e72253b5229" + integrity sha512-pDfvL0XZxKHTZ4VFOmwaYe3LmuABEIZsEopeqQ8y5O6BDen9KCbJqgHeCI8FpASSBd6bNlUx7il7EHdSoHhgIw== "@fullcalendar/interaction@^4.2.0": - version "4.2.0" - resolved "https://registry.yarnpkg.com/@fullcalendar/interaction/-/interaction-4.2.0.tgz#312e83f575aed67c33aec69884664d436aaedef2" - integrity sha512-wwAyocUp1HEY7c7xCymR9EGdh7AWZrwNiBQlIpP3ne0eJT0U4ZjlnoOoels3VPsTJ9a6pdO1/XoGjEvL1T5y4g== + version "4.4.0" + resolved "https://registry.yarnpkg.com/@fullcalendar/interaction/-/interaction-4.4.0.tgz#fc8f8baaf5cb3533d6ce0a684d6f9952a4430685" + integrity sha512-nGu0ZzYYlNpIhqfyv3JupteWKFETs3W1MzbRJcEZkuPncn4BooEi4A2blgHfacHAmmpaNkT84tAmhzi734MFBA== -"@ng-bootstrap/ng-bootstrap@^4.0.1": - version "4.0.1" - resolved "https://registry.yarnpkg.com/@ng-bootstrap/ng-bootstrap/-/ng-bootstrap-4.0.1.tgz#75a6b881b24d869624caa5b5f8a4070650ad5bc4" +"@istanbuljs/schema@^0.1.2": + version "0.1.2" + resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.2.tgz#26520bf09abe4a5644cd5414e37125a8954241dd" + integrity sha512-tsAQNx32a8CoFhjhijUIhI4kccIAgmGhy8LZMZgGfmXcpMbPRUqn5LWmgRttILi6yeGmBJd2xsPkFMs0PzgPCw== + +"@jsdevtools/coverage-istanbul-loader@3.0.3": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@jsdevtools/coverage-istanbul-loader/-/coverage-istanbul-loader-3.0.3.tgz#102e414b02ae2f0b3c7fd45a705601e1fd4867c5" + integrity sha512-TAdNkeGB5Fe4Og+ZkAr1Kvn9by2sfL44IAHFtxlh1BA1XJ5cLpO9iSNki5opWESv3l3vSHsZ9BNKuqFKbEbFaA== dependencies: - tslib "^1.9.0" + convert-source-map "^1.7.0" + istanbul-lib-instrument "^4.0.1" + loader-utils "^1.4.0" + merge-source-map "^1.1.0" + schema-utils "^2.6.4" -"@ngtools/webpack@8.0.2": - version "8.0.2" - resolved "https://registry.yarnpkg.com/@ngtools/webpack/-/webpack-8.0.2.tgz#d60167b514b531ed6ae308b4911739dd102e41c7" - integrity sha512-5P0FHF4p5H/G9xGjOG9meDViXcdW3RPdJa2nX1gGpii3/dhFhmU4pxjKn1Bfs4x+PB9FQQvhSvGIBLNf+B4y5Q== +"@ngtools/webpack@9.1.6": + version "9.1.6" + resolved "https://registry.yarnpkg.com/@ngtools/webpack/-/webpack-9.1.6.tgz#7fa8763d4e128a4e371bafa9328a64cf1de246dd" + integrity sha512-W/9kENoiYARDGXqXSmOekQddUlQUVxfYP7JgQwqdg7JYktIpThicbV/iLBChZwWnmn9mb7MDw1IPeUTkZzrO2Q== dependencies: - "@angular-devkit/core" "8.0.2" - enhanced-resolve "4.1.0" - rxjs "6.4.0" - tree-kill "1.2.1" - webpack-sources "1.3.0" + "@angular-devkit/core" "9.1.6" + enhanced-resolve "4.1.1" + rxjs "6.5.4" + webpack-sources "1.4.3" "@ngu/carousel@^1.4.9-beta-2": version "1.5.5" @@ -300,28 +1185,39 @@ dependencies: tslib "^1.9.0" -"@schematics/angular@8.0.2": - version "8.0.2" - resolved "https://registry.yarnpkg.com/@schematics/angular/-/angular-8.0.2.tgz#80d2a4d55f89b0f843f64d38f588ccca4fdf4de2" - integrity sha512-mN9qsoBVpbY1Q7BP8WaiHsyDv+kl5WrIHw/9OASLrGZcoVY7+oj2CfznVq0XRwvVjDtm6ZFor5ruxLF9dQUOSw== +"@scarf/scarf@0.1.5": + version "0.1.5" + resolved "https://registry.yarnpkg.com/@scarf/scarf/-/scarf-0.1.5.tgz#fc4cc88294eca336eed9a91549180346de5e6946" + integrity sha512-Fx6atDc7JM1r0WkPCDhNetVZNp+DO21q/HGlomAKBG+k8vb1B8fg8Yige4oCf1P9OWTZWm5tM5i3jlXhrSbNOg== + +"@schematics/angular@9.1.6": + version "9.1.6" + resolved "https://registry.yarnpkg.com/@schematics/angular/-/angular-9.1.6.tgz#411b45174b3900dc79d061a86aec8539894dd06b" + integrity sha512-Q9lPTf1/pXBWuFOLzwtrU88Gwkfn9JLiSb45xSQZ771cCD68tZyL4V9fH+u7139y3H3ID2xebMs7WiddAERLyw== dependencies: - "@angular-devkit/core" "8.0.2" - "@angular-devkit/schematics" "8.0.2" + "@angular-devkit/core" "9.1.6" + "@angular-devkit/schematics" "9.1.6" -"@schematics/update@0.800.2": - version "0.800.2" - resolved "https://registry.yarnpkg.com/@schematics/update/-/update-0.800.2.tgz#48d23bf60f2870f0887946165cad42c243c4faac" - integrity sha512-HPjbzr/LfFLdMzi6zMQK8mPyLw+nt+m7OQsdoeOkFgHkHVfHrKQWcOGt4A0D6keDJ6K2g7W5CsqFR6/GMac7Mg== +"@schematics/update@0.901.6": + version "0.901.6" + resolved "https://registry.yarnpkg.com/@schematics/update/-/update-0.901.6.tgz#a6bf0ec294983373ec8e9d675d50e8b44c6a7bc7" + integrity sha512-fKDjD/nGOsrPglOeMVNW+/wa8t73XBrsVneaLg3qmWp6c80JQAxwryE+3MTnBP7apZCLR2YZlKySbY54gLRs6w== dependencies: - "@angular-devkit/core" "8.0.2" - "@angular-devkit/schematics" "8.0.2" + "@angular-devkit/core" "9.1.6" + "@angular-devkit/schematics" "9.1.6" "@yarnpkg/lockfile" "1.1.0" ini "1.3.5" - pacote "9.5.0" - rxjs "6.4.0" - semver "6.0.0" + npm-package-arg "^8.0.0" + pacote "9.5.12" + rxjs "6.5.4" + semver "7.1.3" semver-intersect "1.4.0" +"@types/color-name@^1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@types/color-name/-/color-name-1.1.1.tgz#1c1261bbeaa10a8055bbc5d8ab84b7b2afc846a0" + integrity sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ== + "@types/events@*": version "3.0.0" resolved "https://registry.yarnpkg.com/@types/events/-/events-3.0.0.tgz#2862f3f58a9a7f7c3e78d79f130dd4d71c25c2a7" @@ -366,14 +1262,20 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-12.0.7.tgz#4f2563bad652b2acb1722d7e7aae2b0ff62d192c" integrity sha512-1YKeT4JitGgE4SOzyB9eMwO0nGVNkNEsm9qlIt1Lqm/tG2QEiSMTD4kS3aO6L+w5SClLVxALmIBESK6Mk5wX0A== -"@types/node@~8.9.4": - version "8.9.5" - resolved "https://registry.yarnpkg.com/@types/node/-/node-8.9.5.tgz#162b864bc70be077e6db212b322754917929e976" +"@types/node@^12.11.1": + version "12.12.41" + resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.41.tgz#cf48562b53ab6cf85d28dde95f1d06815af275c8" + integrity sha512-Q+eSkdYQJ2XK1AJnr4Ji8Gvk3sRDybEwfTvtL9CA25FFUSD2EgZQewN6VCyWYZCXg5MWZdwogdTNBhlWRcWS1w== "@types/q@^0.0.32": version "0.0.32" resolved "https://registry.yarnpkg.com/@types/q/-/q-0.0.32.tgz#bd284e57c84f1325da702babfc82a5328190c0c5" +"@types/q@^1.5.1": + version "1.5.4" + resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.4.tgz#15925414e0ad2cd765bfef58842f7e26a7accb24" + integrity sha512-1HcDas8SEj4z1Wc696tH56G8OlRaH/sqZOynNNB+HF0WOeXPaxTtbYzJY2oEfiUxjSKjhCKr+MvR7dCHcEelug== + "@types/selenium-webdriver@^3.0.0": version "3.0.14" resolved "https://registry.yarnpkg.com/@types/selenium-webdriver/-/selenium-webdriver-3.0.14.tgz#0b20a2370e6b1b8322c9c3dfcaa409e6c7c0c0a9" @@ -556,8 +1458,11 @@ resolved "https://registry.yarnpkg.com/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz#e77a97fbd345b76d83245edcd17d393b1b41fb31" "@yellowspot/ng-truncate@^1.4.0": - version "1.4.0" - resolved "https://registry.yarnpkg.com/@yellowspot/ng-truncate/-/ng-truncate-1.4.0.tgz#dcb40f5571ef71a9cf09f6a24e83e1f43b2d2a6c" + version "1.5.1" + resolved "https://registry.yarnpkg.com/@yellowspot/ng-truncate/-/ng-truncate-1.5.1.tgz#fe9cd170517b9cc05fe240b8a4052141c0290f44" + integrity sha512-tAVlVqz1XGAbL3HKg8i/Sy++iilhvoujNkwE34IsVQ+ndiOJEgSmj8OntrsfrkBL2KlOs6L507nUz4MWzh+G0A== + dependencies: + tslib "^1.9.0" JSONStream@^1.3.4: version "1.3.5" @@ -569,6 +1474,7 @@ JSONStream@^1.3.4: abbrev@1: version "1.1.1" resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" + integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== accepts@~1.3.4, accepts@~1.3.5: version "1.3.5" @@ -585,36 +1491,42 @@ accepts@~1.3.7: mime-types "~2.1.24" negotiator "0.6.2" -acorn-dynamic-import@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/acorn-dynamic-import/-/acorn-dynamic-import-4.0.0.tgz#482210140582a36b83c3e342e1cfebcaa9240948" - integrity sha512-d3OEjQV4ROpoflsnUA8HozoIR504TFxNivYEUi6uwz0IYhBkTDXGuWlNdMtybRt3nqVx/L6XqMt0FxkXuWKZhw== - -acorn@^6.0.5: - version "6.1.1" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.1.1.tgz#7d25ae05bb8ad1f9b699108e1094ecd7884adc1f" - integrity sha512-jPTiwtOxaHNaAPg/dmrJ/beuzLRnXtB0kQPQ8JpotKJgTB6rX6c8mlf315941pyjBSaPg8NHXS9fhP4u17DpGA== +acorn@^6.2.1: + version "6.4.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.0.tgz#b659d2ffbafa24baf5db1cdbb2c94a983ecd2784" + integrity sha512-gac8OEcQ2Li1dxIEWGZzsp2BitJxwkwcOm0zHAJLcPJaVvm58FRnk6RkuLRpU1EujipU2ZFODv2P9DLMfnV8mw== adm-zip@^0.4.9: version "0.4.13" resolved "https://registry.yarnpkg.com/adm-zip/-/adm-zip-0.4.13.tgz#597e2f8cc3672151e1307d3e95cddbc75672314a" -after@0.8.2: - version "0.8.2" - resolved "https://registry.yarnpkg.com/after/-/after-0.8.2.tgz#fedb394f9f0e02aa9768e702bda23b505fae7e1f" - agent-base@4, agent-base@^4.1.0, agent-base@~4.2.0: version "4.2.1" resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.2.1.tgz#d89e5999f797875674c07d87f260fc41e83e8ca9" dependencies: es6-promisify "^5.0.0" +agent-base@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.3.0.tgz#8165f01c436009bccad0b1d122f05ed770efc6ee" + integrity sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg== + dependencies: + es6-promisify "^5.0.0" + agentkeepalive@^3.4.1: version "3.5.2" resolved "https://registry.yarnpkg.com/agentkeepalive/-/agentkeepalive-3.5.2.tgz#a113924dd3fa24a0bc3b78108c450c2abee00f67" dependencies: humanize-ms "^1.2.1" +aggregate-error@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.0.1.tgz#db2fe7246e536f40d9b5442a39e117d7dd6a24e0" + integrity sha512-quoaXsZ9/BLNae5yiNoUz+Nhkwz83GhWwtYFglcjEQB2NDHCIpApbqXxIFnm4Pq/Nvhrsq5sYJFyohrrxnTGAA== + dependencies: + clean-stack "^2.0.0" + indent-string "^4.0.0" + ajv-errors@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/ajv-errors/-/ajv-errors-1.0.1.tgz#f35986aceb91afadec4102fbd85014950cefa64d" @@ -623,26 +1535,22 @@ ajv-keywords@^3.1.0: version "3.2.0" resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.2.0.tgz#e86b819c602cf8821ad637413698f1dec021847a" -ajv@6.10.0: - version "6.10.0" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.10.0.tgz#90d0d54439da587cd7e843bfb7045f50bd22bdf1" - integrity sha512-nffhOpkymDECQyR0mnsUtoCE8RlX38G0rYP+wgLWFyZuUyuuojSSvi/+euOiQBIn63whYwYVIIH1TvE3tu4OEg== +ajv-keywords@^3.4.1: + version "3.4.1" + resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.4.1.tgz#ef916e271c64ac12171fd8384eaae6b2345854da" + integrity sha512-RO1ibKvd27e6FEShVFfPALuHI3WjSVNeK5FIsmme/LYRNxjKuNj+Dt7bucLa6NdSv3JcVTyMlm9kGR84z1XpaQ== + +ajv@6.12.0, ajv@^6.10.2, ajv@^6.5.5: + version "6.12.0" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.0.tgz#06d60b96d87b8454a5adaba86e7854da629db4b7" + integrity sha512-D6gFiFA0RRLyUbvijN74DWAjXSFxWKaWP7mldxkVhyhAV3+SWA9HEJPHQ2c9soIeTFJqcSdFDGFgdqs1iUU2Hw== dependencies: - fast-deep-equal "^2.0.1" + fast-deep-equal "^3.1.1" fast-json-stable-stringify "^2.0.0" json-schema-traverse "^0.4.1" uri-js "^4.2.2" -ajv@^5.0.0: - version "5.5.2" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.5.2.tgz#73b5eeca3fab653e3d3f9422b341ad42205dc965" - dependencies: - co "^4.6.0" - fast-deep-equal "^1.0.0" - fast-json-stable-stringify "^2.0.0" - json-schema-traverse "^0.3.0" - -ajv@^6.1.0, ajv@^6.5.5: +ajv@^6.1.0: version "6.7.0" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.7.0.tgz#e3ce7bb372d6577bb1839f1dfdfcbf5ad2948d96" dependencies: @@ -651,9 +1559,25 @@ ajv@^6.1.0, ajv@^6.5.5: json-schema-traverse "^0.4.1" uri-js "^4.2.2" +ajv@^6.12.0: + version "6.12.2" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.2.tgz#c629c5eced17baf314437918d2da88c99d5958cd" + integrity sha512-k+V+hzjm5q/Mr8ef/1Y9goCmlsK4I6Sm74teeyGvFk1XrOsbsKLjEdrvny42CZ+a8sXbk8KWpY/bDwS+FLL2UQ== + dependencies: + fast-deep-equal "^3.1.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + +alphanum-sort@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/alphanum-sort/-/alphanum-sort-1.0.2.tgz#97a1119649b211ad33691d9f9f486a8ec9fbe0a3" + integrity sha1-l6ERlkmyEa0zaR2fn0hqjsn74KM= + amdefine@>=0.0.4: version "1.0.1" resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5" + integrity sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU= angular-bootstrap-md@^7.5.4: version "7.5.4" @@ -668,20 +1592,30 @@ angular-router-loader@^0.8.5: dependencies: loader-utils "^1.0.2" -angular2-template-loader@^0.6.2: - version "0.6.2" - resolved "https://registry.yarnpkg.com/angular2-template-loader/-/angular2-template-loader-0.6.2.tgz#c0d44e90fff0fac95e8b23f043acda7fd1c51d7c" +angularx-qrcode@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/angularx-qrcode/-/angularx-qrcode-2.1.0.tgz#94ba30647f851305c58b6365ec9eb8fb91bb97dc" + integrity sha512-4mtlPJmemQINEz8OH6cYOllLJ77kFamk38G1L8OLF4X/nrxWaFIxMiKcPHf/HVeqATSAPismgqPu9aM5RhF/ig== dependencies: - loader-utils "^0.2.15" + "@angular/common" ">= 5.0.0 < 9.1.0" + qrcode "1.4.2" + tslib "^1.9.0" + +ansi-colors@4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348" + integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA== ansi-colors@^3.0.0: version "3.2.3" resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-3.2.3.tgz#57d35b8686e851e2cc04c403f1c00203976a1813" -ansi-escapes@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.2.0.tgz#8780b98ff9dbf5638152d1f1fe5c1d7b4442976b" - integrity sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ== +ansi-escapes@^4.2.1: + version "4.3.0" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.0.tgz#a4ce2b33d6b214b7950d8595c212f12ac9cc569d" + integrity sha512-EiYhwo0v255HUL6eDyuLrXEkTi7WwVCLAw+SeOQ7M7qdun1z1pum4DEm/nuqIVbPvi9RPPc9k9LbyBv6H0DwVg== + dependencies: + type-fest "^0.8.1" ansi-html@0.0.7: version "0.0.7" @@ -690,26 +1624,42 @@ ansi-html@0.0.7: ansi-regex@^2.0.0: version "2.1.1" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" + integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8= ansi-regex@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" + integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg= ansi-regex@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997" integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg== +ansi-regex@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.0.tgz#388539f55179bf39339c81af30a654d69f87cb75" + integrity sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg== + ansi-styles@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" + integrity sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4= -ansi-styles@^3.2.1: +ansi-styles@^3.2.0, ansi-styles@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" dependencies: color-convert "^1.9.0" +ansi-styles@^4.0.0, ansi-styles@^4.1.0: + version "4.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.2.1.tgz#90ae75c424d008d2624c5bf29ead3177ebfcf359" + integrity sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA== + dependencies: + "@types/color-name" "^1.1.1" + color-convert "^2.0.1" + anymatch@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-2.0.0.tgz#bcb24b4f37934d9aa7ac17b4adaf89e7c76ef2eb" @@ -717,10 +1667,23 @@ anymatch@^2.0.0: micromatch "^3.1.4" normalize-path "^2.1.1" +anymatch@~3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.1.tgz#c55ecf02185e2469259399310c173ce31233b142" + integrity sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg== + dependencies: + normalize-path "^3.0.0" + picomatch "^2.0.4" + app-root-path@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/app-root-path/-/app-root-path-2.1.0.tgz#98bf6599327ecea199309866e8140368fd2e646a" +app-root-path@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/app-root-path/-/app-root-path-2.2.1.tgz#d0df4a682ee408273583d43f6f79e9892624bc9a" + integrity sha512-91IFKeKk7FjfmezPKkwtaRvSpnUc4gDwPAjA1YZ9Gn0q0PPeW+vbeUsZuyDwjI7+QTHhcLen2v25fi/AmhvbJA== + aproba@^1.0.3, aproba@^1.1.1: version "1.2.0" resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" @@ -728,6 +1691,7 @@ aproba@^1.0.3, aproba@^1.1.1: are-we-there-yet@~1.1.2: version "1.1.5" resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz#4b35c2944f062a8bfcda66410760350fe9ddfc21" + integrity sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w== dependencies: delegates "^1.0.0" readable-stream "^2.0.6" @@ -738,6 +1702,14 @@ argparse@^1.0.7: dependencies: sprintf-js "~1.0.2" +aria-query@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-3.0.0.tgz#65b3fcc1ca1155a8c9ae64d6eee297f15d5133cc" + integrity sha1-ZbP8wcoRVajJrmTW7uKX8V1RM8w= + dependencies: + ast-types-flow "0.0.7" + commander "^2.11.0" + arr-diff@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" @@ -753,6 +1725,7 @@ arr-union@^3.1.0: array-find-index@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/array-find-index/-/array-find-index-1.0.2.tgz#df010aa1287e164bbda6f9723b0a96a1ec4187a1" + integrity sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E= array-flatten@1.1.1: version "1.1.1" @@ -776,10 +1749,6 @@ array-unique@^0.3.2: version "0.3.2" resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" -arraybuffer.slice@~0.0.7: - version "0.0.7" - resolved "https://registry.yarnpkg.com/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz#3bbc4275dd584cc1b10809b89d4e8b63a69e7675" - arrify@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" @@ -799,18 +1768,14 @@ asn1.js@^4.0.0: asn1@~0.2.3: version "0.2.4" resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136" + integrity sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg== dependencies: safer-buffer "~2.1.0" -aspnet-prerendering@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/aspnet-prerendering/-/aspnet-prerendering-3.0.1.tgz#0b6e767b49e425e1d3d59611fac80c9c6f5b0100" - dependencies: - domain-task "^3.0.0" - assert-plus@1.0.0, assert-plus@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" + integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU= assert@^1.1.1: version "1.4.1" @@ -822,6 +1787,11 @@ assign-symbols@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" +ast-types-flow@0.0.7: + version "0.0.7" + resolved "https://registry.yarnpkg.com/ast-types-flow/-/ast-types-flow-0.0.7.tgz#f70b735c6bca1a5c9c22d982c3e39e7feba3bdad" + integrity sha1-9wtzXGvKGlycItmCw+Oef+ujva0= + async-each@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.1.tgz#19d386a1d9edc6e7c1c85d388aedbcc56d33602d" @@ -834,14 +1804,12 @@ async-each@^1.0.1: async-foreach@^0.1.3: version "0.1.3" resolved "https://registry.yarnpkg.com/async-foreach/-/async-foreach-0.1.3.tgz#36121f845c0578172de419a97dbeb1d16ec34542" + integrity sha1-NhIfhFwFeBct5Bmpfb6x0W7DRUI= async-limiter@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.0.tgz#78faed8c3d074ab81f22b4e985d79e8738f720f8" - -async@^1.5.2: - version "1.5.2" - resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" + version "1.0.1" + resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.1.tgz#dd379e94f0db8310b08291f9d64c3209766617fd" + integrity sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ== async@^2.5.0: version "2.6.1" @@ -849,48 +1817,53 @@ async@^2.5.0: dependencies: lodash "^4.17.10" +async@^2.6.2: + version "2.6.3" + resolved "https://registry.yarnpkg.com/async/-/async-2.6.3.tgz#d72625e2344a3656e3a3ad4fa749fa83299d82ff" + integrity sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg== + dependencies: + lodash "^4.17.14" + asynckit@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= -atob@^2.1.1: +atob@^2.1.1, atob@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" -autoprefixer@9.5.1: - version "9.5.1" - resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-9.5.1.tgz#243b1267b67e7e947f28919d786b50d3bb0fb357" - integrity sha512-KJSzkStUl3wP0D5sdMlP82Q52JLy5+atf2MHAre48+ckWkXgixmfHyWmA77wFDy6jTHU6mIgXv6hAQ2mf1PjJQ== +autoprefixer@9.7.4: + version "9.7.4" + resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-9.7.4.tgz#f8bf3e06707d047f0641d87aee8cfb174b2a5378" + integrity sha512-g0Ya30YrMBAEZk60lp+qfX5YQllG+S5W3GYCFvyHTvhOki0AEQJLPEcIuGRsqVwLi8FvXPVtwTGhfr38hVpm0g== dependencies: - browserslist "^4.5.4" - caniuse-lite "^1.0.30000957" + browserslist "^4.8.3" + caniuse-lite "^1.0.30001020" + chalk "^2.4.2" normalize-range "^0.1.2" num2fraction "^1.2.2" - postcss "^7.0.14" - postcss-value-parser "^3.3.1" - -awesome-typescript-loader@^5.2.0: - version "5.2.1" - resolved "https://registry.yarnpkg.com/awesome-typescript-loader/-/awesome-typescript-loader-5.2.1.tgz#a41daf7847515f4925cdbaa3075d61f289e913fc" - dependencies: - chalk "^2.4.1" - enhanced-resolve "^4.0.0" - loader-utils "^1.1.0" - lodash "^4.17.5" - micromatch "^3.1.9" - mkdirp "^0.5.1" - source-map-support "^0.5.3" - webpack-log "^1.2.0" + postcss "^7.0.26" + postcss-value-parser "^4.0.2" aws-sign2@~0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" + integrity sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg= aws4@^1.8.0: - version "1.8.0" - resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.8.0.tgz#f0e003d9ca9e7f59c7a508945d7b2ef9a04a542f" + version "1.9.1" + resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.9.1.tgz#7e33d8f7d449b3f673cd72deb9abdc552dbe528e" + integrity sha512-wMHVg2EOHaMRxbzgFJ9gtjOOCrI80OHLG14rxi28XwOW8ux6IiEbRCGGGqCtdAIg4FQCbW20k9RsT4y3gJlFug== + +axobject-query@2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/axobject-query/-/axobject-query-2.0.2.tgz#ea187abe5b9002b377f925d8bf7d1c561adf38f9" + integrity sha512-MCeek8ZH7hKyO1rWUbKNQBbl4l2eY0ntk7OGi+q0RlafrCnfPxC06WZA+uebCfmYp4mNU9jRBP1AhGyf8+W3ww== + dependencies: + ast-types-flow "0.0.7" -babel-code-frame@^6.22.0, babel-code-frame@^6.26.0: +babel-code-frame@^6.22.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b" dependencies: @@ -898,80 +1871,27 @@ babel-code-frame@^6.22.0, babel-code-frame@^6.26.0: esutils "^2.0.2" js-tokens "^3.0.2" -babel-generator@^6.18.0: - version "6.26.1" - resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.26.1.tgz#1844408d3b8f0d35a404ea7ac180f087a601bd90" - dependencies: - babel-messages "^6.23.0" - babel-runtime "^6.26.0" - babel-types "^6.26.0" - detect-indent "^4.0.0" - jsesc "^1.3.0" - lodash "^4.17.4" - source-map "^0.5.7" - trim-right "^1.0.1" - -babel-messages@^6.23.0: - version "6.23.0" - resolved "https://registry.yarnpkg.com/babel-messages/-/babel-messages-6.23.0.tgz#f3cdf4703858035b2a2951c6ec5edf6c62f2630e" - dependencies: - babel-runtime "^6.22.0" - -babel-runtime@^6.22.0, babel-runtime@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe" - dependencies: - core-js "^2.4.0" - regenerator-runtime "^0.11.0" - -babel-template@^6.16.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-template/-/babel-template-6.26.0.tgz#de03e2d16396b069f46dd9fff8521fb1a0e35e02" +babel-loader@8.0.6: + version "8.0.6" + resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-8.0.6.tgz#e33bdb6f362b03f4bb141a0c21ab87c501b70dfb" + integrity sha512-4BmWKtBOBm13uoUwd08UwjZlaw3O9GWf456R9j+5YykFZ6LUIjIKLc0zEZf+hauxPOJs96C8k6FvYD09vWzhYw== dependencies: - babel-runtime "^6.26.0" - babel-traverse "^6.26.0" - babel-types "^6.26.0" - babylon "^6.18.0" - lodash "^4.17.4" - -babel-traverse@^6.18.0, babel-traverse@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.26.0.tgz#46a9cbd7edcc62c8e5c064e2d2d8d0f4035766ee" - dependencies: - babel-code-frame "^6.26.0" - babel-messages "^6.23.0" - babel-runtime "^6.26.0" - babel-types "^6.26.0" - babylon "^6.18.0" - debug "^2.6.8" - globals "^9.18.0" - invariant "^2.2.2" - lodash "^4.17.4" + find-cache-dir "^2.0.0" + loader-utils "^1.0.2" + mkdirp "^0.5.1" + pify "^4.0.1" -babel-types@^6.18.0, babel-types@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.26.0.tgz#a3b073f94ab49eb6fa55cd65227a334380632497" +babel-plugin-dynamic-import-node@^2.3.3: + version "2.3.3" + resolved "https://registry.yarnpkg.com/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz#84fda19c976ec5c6defef57f9427b3def66e17a3" + integrity sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ== dependencies: - babel-runtime "^6.26.0" - esutils "^2.0.2" - lodash "^4.17.4" - to-fast-properties "^1.0.3" - -babylon@^6.18.0: - version "6.18.0" - resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.18.0.tgz#af2f3b88fa6f5c1e4c634d1a0f8eac4f55b395e3" - -backo2@1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/backo2/-/backo2-1.0.2.tgz#31ab1ac8b129363463e35b3ebb69f4dfcfba7947" + object.assign "^4.1.0" balanced-match@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" - -base64-arraybuffer@0.1.5: - version "0.1.5" - resolved "https://registry.yarnpkg.com/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz#73926771923b5a19747ad666aa5cd4bf9c6e9ce8" + integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= base64-js@^1.0.2: version "1.3.0" @@ -996,19 +1916,10 @@ batch@0.6.1: bcrypt-pbkdf@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" + integrity sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4= dependencies: tweetnacl "^0.14.3" -better-assert@~1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/better-assert/-/better-assert-1.0.2.tgz#40866b9e1b9e0b55b481894311e68faffaebc522" - dependencies: - callsite "1.0.0" - -big.js@^3.1.3: - version "3.2.0" - resolved "https://registry.yarnpkg.com/big.js/-/big.js-3.2.0.tgz#a5fc298b81b9e0dca2e458824784b65c52ba588e" - big.js@^5.2.2: version "5.2.2" resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328" @@ -1017,13 +1928,15 @@ binary-extensions@^1.0.0: version "1.12.0" resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.12.0.tgz#c2d780f53d45bba8317a8902d4ceeaf3a6385b14" -blob@0.0.5: - version "0.0.5" - resolved "https://registry.yarnpkg.com/blob/-/blob-0.0.5.tgz#d680eeef25f8cd91ad533f5b01eed48e64caf683" +binary-extensions@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.0.0.tgz#23c0df14f6a88077f5f986c0d167ec03c3d5537c" + integrity sha512-Phlt0plgpIIBOGTT/ehfFnbNlfsDEiqmzE2KRXoX1bLIlir4X/MR+zSyBEkL05ffWgnRSf/DXv+WrUAVr93/ow== block-stream@*: version "0.0.9" resolved "https://registry.yarnpkg.com/block-stream/-/block-stream-0.0.9.tgz#13ebfe778a03205cfe03751481ebb4b3300c126a" + integrity sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo= dependencies: inherits "~2.0.0" @@ -1037,6 +1950,11 @@ bluebird@^3.5.1, bluebird@^3.5.3: version "3.5.3" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.3.tgz#7d01c6f9616c9a51ab0f8c549a79dfe6ec33efa7" +bluebird@^3.5.5: + version "3.7.2" + resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" + integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg== + bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.4.0: version "4.11.8" resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.8.tgz#2cde09eb5ee341f484746bb0309b3253b1b1442f" @@ -1068,6 +1986,11 @@ bonjour@^3.5.0: multicast-dns "^6.0.1" multicast-dns-service-types "^1.1.0" +boolbase@^1.0.0, boolbase@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" + integrity sha1-aN/1++YMUes3cl6p4+0xDcwed24= + bootstrap@^4.2.1: version "4.2.1" resolved "https://registry.yarnpkg.com/bootstrap/-/bootstrap-4.2.1.tgz#8f8bdca024dbf0e8644da32e918c8a03a90a5757" @@ -1075,6 +1998,7 @@ bootstrap@^4.2.1: brace-expansion@^1.1.7: version "1.1.11" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== dependencies: balanced-match "^1.0.0" concat-map "0.0.1" @@ -1094,6 +2018,13 @@ braces@^2.3.0, braces@^2.3.1, braces@^2.3.2: split-string "^3.0.2" to-regex "^3.0.1" +braces@~3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" + integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== + dependencies: + fill-range "^7.0.1" + brorand@^1.0.1: version "1.1.0" resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" @@ -1151,23 +2082,24 @@ browserify-zlib@^0.2.0: dependencies: pako "~1.0.5" -browserslist@4.5.5: - version "4.5.5" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.5.5.tgz#fe1a352330d2490d5735574c149a85bc18ef9b82" - integrity sha512-0QFO1r/2c792Ohkit5XI8Cm8pDtZxgNl2H6HU4mHrpYz7314pEYcsAVVatM0l/YmxPnEzh9VygXouj4gkFUTKA== +browserslist@^4.0.0, browserslist@^4.11.1, browserslist@^4.9.1: + version "4.12.0" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.12.0.tgz#06c6d5715a1ede6c51fc39ff67fd647f740b656d" + integrity sha512-UH2GkcEDSI0k/lRkuDSzFl9ZZ87skSy9w2XAn1MsZnL+4c4rqbBd3e82UWHbYDpztABrPBhZsTEeuxVfHppqDg== dependencies: - caniuse-lite "^1.0.30000960" - electron-to-chromium "^1.3.124" - node-releases "^1.1.14" + caniuse-lite "^1.0.30001043" + electron-to-chromium "^1.3.413" + node-releases "^1.1.53" + pkg-up "^2.0.0" -browserslist@^4.0.0, browserslist@^4.5.4: - version "4.6.2" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.6.2.tgz#574c665950915c2ac73a4594b8537a9eba26203f" - integrity sha512-2neU/V0giQy9h3XMPwLhEY3+Ao0uHSwHvU8Q1Ea6AgLVL1sXbX3dzPrJ8NWe5Hi4PoTkCYXOtVR9rfRLI0J/8Q== +browserslist@^4.8.3: + version "4.9.0" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.9.0.tgz#ff85c390889e0f754d7bd8ad13412575cdcf5dc7" + integrity sha512-seffIXhwgB84+OCeT/aMjpZnsAsYDiMSC+CEs3UkF8iU64BZGYcu+TZYs/IBpo4nRi0vJywUJWYdbTsOhFTweg== dependencies: - caniuse-lite "^1.0.30000974" - electron-to-chromium "^1.3.150" - node-releases "^1.1.23" + caniuse-lite "^1.0.30001030" + electron-to-chromium "^1.3.361" + node-releases "^1.1.50" browserstack@^1.5.1: version "1.5.2" @@ -1216,25 +2148,74 @@ bytes@3.1.0: resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.0.tgz#f6cf7933a360e0588fa9fde85651cdc7f805d1f6" integrity sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg== -cacache@^11.0.1, cacache@^11.0.2, cacache@^11.3.1, cacache@^11.3.2: - version "11.3.2" - resolved "https://registry.yarnpkg.com/cacache/-/cacache-11.3.2.tgz#2d81e308e3d258ca38125b676b98b2ac9ce69bfa" +cacache@15.0.0: + version "15.0.0" + resolved "https://registry.yarnpkg.com/cacache/-/cacache-15.0.0.tgz#133b59edbd2a37ea8ef2d54964c6f247e47e5059" + integrity sha512-L0JpXHhplbJSiDGzyJJnJCTL7er7NzbBgxzVqLswEb4bO91Zbv17OUMuUeu/q0ZwKn3V+1HM4wb9tO4eVE/K8g== dependencies: - bluebird "^3.5.3" + chownr "^1.1.2" + fs-minipass "^2.0.0" + glob "^7.1.4" + infer-owner "^1.0.4" + lru-cache "^5.1.1" + minipass "^3.1.1" + minipass-collect "^1.0.2" + minipass-flush "^1.0.5" + minipass-pipeline "^1.2.2" + mkdirp "^1.0.3" + move-concurrently "^1.0.1" + p-map "^3.0.0" + promise-inflight "^1.0.1" + rimraf "^2.7.1" + ssri "^8.0.0" + tar "^6.0.1" + unique-filename "^1.1.1" + +cacache@^12.0.0, cacache@^12.0.2, cacache@^12.0.3: + version "12.0.3" + resolved "https://registry.yarnpkg.com/cacache/-/cacache-12.0.3.tgz#be99abba4e1bf5df461cd5a2c1071fc432573390" + integrity sha512-kqdmfXEGFepesTuROHMs3MpFLWrPkSSpRqOw80RCflZXy/khxaArvFrQ7uJxSUduzAufc6G0g1VUCOZXxWavPw== + dependencies: + bluebird "^3.5.5" chownr "^1.1.1" figgy-pudding "^3.5.1" - glob "^7.1.3" + glob "^7.1.4" graceful-fs "^4.1.15" + infer-owner "^1.0.3" lru-cache "^5.1.1" mississippi "^3.0.0" mkdirp "^0.5.1" move-concurrently "^1.0.1" promise-inflight "^1.0.1" - rimraf "^2.6.2" + rimraf "^2.6.3" ssri "^6.0.1" unique-filename "^1.1.1" y18n "^4.0.0" +cacache@^13.0.1: + version "13.0.1" + resolved "https://registry.yarnpkg.com/cacache/-/cacache-13.0.1.tgz#a8000c21697089082f85287a1aec6e382024a71c" + integrity sha512-5ZvAxd05HDDU+y9BVvcqYu2LLXmPnQ0hW62h32g4xBTgL/MppR4/04NHfj/ycM2y6lmTnbw6HVi+1eN0Psba6w== + dependencies: + chownr "^1.1.2" + figgy-pudding "^3.5.1" + fs-minipass "^2.0.0" + glob "^7.1.4" + graceful-fs "^4.2.2" + infer-owner "^1.0.4" + lru-cache "^5.1.1" + minipass "^3.0.0" + minipass-collect "^1.0.2" + minipass-flush "^1.0.5" + minipass-pipeline "^1.2.2" + mkdirp "^0.5.1" + move-concurrently "^1.0.1" + p-map "^3.0.0" + promise-inflight "^1.0.1" + rimraf "^2.7.1" + ssri "^7.0.0" + unique-filename "^1.1.1" + cache-base@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2" @@ -1249,13 +2230,29 @@ cache-base@^1.0.1: union-value "^1.0.0" unset-value "^1.0.0" -callsite@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/callsite/-/callsite-1.0.0.tgz#280398e5d664bd74038b6f0905153e6e8af1bc20" +caller-callsite@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/caller-callsite/-/caller-callsite-2.0.0.tgz#847e0fce0a223750a9a027c54b33731ad3154134" + integrity sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ= + dependencies: + callsites "^2.0.0" + +caller-path@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-2.0.0.tgz#468f83044e369ab2010fac5f06ceee15bb2cb1f4" + integrity sha1-Ro+DBE42mrIBD6xfBs7uFbsssfQ= + dependencies: + caller-callsite "^2.0.0" + +callsites@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-2.0.0.tgz#06eb84f00eea413da86affefacbffb36093b3c50" + integrity sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA= camelcase-keys@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-2.1.0.tgz#308beeaffdf28119051efa1d932213c91b8f92e7" + integrity sha1-MIvur/3ygRkFHvodkyITyRuPkuc= dependencies: camelcase "^2.0.0" map-obj "^1.0.0" @@ -1263,17 +2260,19 @@ camelcase-keys@^2.0.0: camelcase@^2.0.0: version "2.1.1" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-2.1.1.tgz#7c1d16d679a1bbe59ca02cacecfb011e201f5a1f" + integrity sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8= camelcase@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-3.0.0.tgz#32fc4b9fcdaf845fcdf7e73bb97cac2261f0ab0a" + integrity sha1-MvxLn82vhF/N9+c7uXysImHwqwo= -camelcase@^5.0.0: +camelcase@^5.0.0, camelcase@^5.3.1: version "5.3.1" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== -caniuse-api@3.0.0: +caniuse-api@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/caniuse-api/-/caniuse-api-3.0.0.tgz#5e4d90e2274961d46291997df599e3ed008ee4c0" integrity sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw== @@ -1283,10 +2282,15 @@ caniuse-api@3.0.0: lodash.memoize "^4.1.2" lodash.uniq "^4.5.0" -caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000957, caniuse-lite@^1.0.30000960, caniuse-lite@^1.0.30000974: - version "1.0.30000974" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000974.tgz#b7afe14ee004e97ce6dc73e3f878290a12928ad8" - integrity sha512-xc3rkNS/Zc3CmpMKuczWEdY2sZgx09BkAxfvkxlAEBTqcMHeL8QnPqhKse+5sRTi3nrw2pJwToD2WvKn1Uhvww== +caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001020, caniuse-lite@^1.0.30001032, caniuse-lite@^1.0.30001043: + version "1.0.30001062" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001062.tgz#d814b648338504b315222ace6f1a533d9a55e390" + integrity sha512-ei9ZqeOnN7edDrb24QfJ0OZicpEbsWxv7WusOiQGz/f2SfvBgHHbOEwBJ8HKGVSyx8Z6ndPjxzR6m0NQq+0bfw== + +caniuse-lite@^1.0.30001030: + version "1.0.30001030" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001030.tgz#78076c4c6d67d3e41d6eb9399853fb27fe6e44ee" + integrity sha512-QGK0W4Ft/Ac+zTjEiRJfwDNATvS3fodDczBXrH42784kcfqcDKpEPfN08N0HQjrAp8He/Jw8QiSS9QRn7XAbUw== canonical-path@1.0.0: version "1.0.0" @@ -1295,6 +2299,7 @@ canonical-path@1.0.0: caseless@~0.12.0: version "0.12.0" resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" + integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= chalk@^1.1.1, chalk@^1.1.3: version "1.1.3" @@ -1306,7 +2311,7 @@ chalk@^1.1.1, chalk@^1.1.3: strip-ansi "^3.0.0" supports-color "^2.0.0" -chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.0, chalk@^2.4.1, chalk@^2.4.2: +chalk@^2.0.0, chalk@^2.0.1, chalk@^2.3.0, chalk@^2.4.1, chalk@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" dependencies: @@ -1314,31 +2319,57 @@ chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.0, chalk@^2.4.1, chalk@^2.4.2: escape-string-regexp "^1.0.5" supports-color "^5.3.0" +chalk@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-3.0.0.tgz#3f73c2bf526591f574cc492c51e2456349f844e4" + integrity sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + chardet@^0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" -chart.js@2.5.0: - version "2.5.0" - resolved "https://registry.yarnpkg.com/chart.js/-/chart.js-2.5.0.tgz#fe6e751a893769f56e72bee5ad91207e1c592957" +chart.js@2.9.4: + version "2.9.4" + resolved "https://registry.yarnpkg.com/chart.js/-/chart.js-2.9.4.tgz#0827f9563faffb2dc5c06562f8eb10337d5b9684" + integrity sha512-B07aAzxcrikjAPyV+01j7BmOpxtQETxTSlQ26BEYJ+3iUkbNKaOJ/nDbT6JjyqYxseM0ON12COHYdU2cTIjC7A== dependencies: - chartjs-color "^2.0.0" - moment "^2.10.6" + chartjs-color "^2.1.0" + moment "^2.10.2" -chartjs-color-string@^0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/chartjs-color-string/-/chartjs-color-string-0.5.0.tgz#8d3752d8581d86687c35bfe2cb80ac5213ceb8c1" +chartjs-color-string@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/chartjs-color-string/-/chartjs-color-string-0.6.0.tgz#1df096621c0e70720a64f4135ea171d051402f71" + integrity sha512-TIB5OKn1hPJvO7JcteW4WY/63v6KwEdt6udfnDE9iCAZgy+V4SrbSxoIbTw/xkUIapjEI4ExGtD0+6D3KyFd7A== dependencies: color-name "^1.0.0" -chartjs-color@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/chartjs-color/-/chartjs-color-2.2.0.tgz#84a2fb755787ed85c39dd6dd8c7b1d88429baeae" +chartjs-color@^2.1.0: + version "2.4.1" + resolved "https://registry.yarnpkg.com/chartjs-color/-/chartjs-color-2.4.1.tgz#6118bba202fe1ea79dd7f7c0f9da93467296c3b0" + integrity sha512-haqOg1+Yebys/Ts/9bLo/BqUcONQOdr/hoEr2LLTRl6C5LXctUdHxsCYfvQVg5JIxITrfCNUDr4ntqmQk9+/0w== dependencies: - chartjs-color-string "^0.5.0" - color-convert "^0.5.3" + chartjs-color-string "^0.6.0" + color-convert "^1.9.3" + +"chokidar@>=2.0.0 <4.0.0": + version "3.3.1" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.3.1.tgz#c84e5b3d18d9a4d77558fef466b1bf16bbeb3450" + integrity sha512-4QYCEWOcK3OJrxwvyyAOxFuhpvOVCYkr33LPfFNBjAD/w3sEzWsp2BUOkI4l9bHvWioAd0rc6NlHUOEaWkTeqg== + dependencies: + anymatch "~3.1.1" + braces "~3.0.2" + glob-parent "~5.1.0" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.3.0" + optionalDependencies: + fsevents "~2.1.2" -chokidar@^2.0.0, chokidar@^2.0.2: +chokidar@^2.0.2: version "2.0.4" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.0.4.tgz#356ff4e2b0e8e43e322d18a372460bbcf3accd26" dependencies: @@ -1357,10 +2388,10 @@ chokidar@^2.0.0, chokidar@^2.0.2: optionalDependencies: fsevents "^1.2.2" -chokidar@^2.1.1, chokidar@^2.1.5: - version "2.1.6" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.1.6.tgz#b6cad653a929e244ce8a834244164d241fa954c5" - integrity sha512-V2jUo67OKkc6ySiRpJrjlpJKl9kDuG+Xb8VgsGzb+aEouhgS1D0weyPU4lEzdAcsCAvrih2J2BqyXqHWvVLw5g== +chokidar@^2.1.8: + version "2.1.8" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.1.8.tgz#804b3a7b6a99358c3c5c61e71d8728f041cff917" + integrity sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg== dependencies: anymatch "^2.0.0" async-each "^1.0.1" @@ -1376,13 +2407,39 @@ chokidar@^2.1.1, chokidar@^2.1.5: optionalDependencies: fsevents "^1.2.7" +chokidar@^3.0.0: + version "3.4.0" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.4.0.tgz#b30611423ce376357c765b9b8f904b9fba3c0be8" + integrity sha512-aXAaho2VJtisB/1fg1+3nlLJqGOuewTzQpd/Tz0yTg2R0e4IGtshYvtjowyEumcBv2z+y4+kc75Mz7j5xJskcQ== + dependencies: + anymatch "~3.1.1" + braces "~3.0.2" + glob-parent "~5.1.0" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.4.0" + optionalDependencies: + fsevents "~2.1.2" + chownr@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.1.tgz#54726b8b8fff4df053c42187e801fb4412df1494" -chrome-trace-event@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.0.tgz#45a91bd2c20c9411f0963b5aaeb9a1b95e09cc48" +chownr@^1.1.2: + version "1.1.4" + resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b" + integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg== + +chownr@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/chownr/-/chownr-2.0.0.tgz#15bfbe53d2eab4cf70f18a8cd68ebe5b3cb1dece" + integrity sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ== + +chrome-trace-event@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.2.tgz#234090ee97c7d4ad1a2c4beae27505deffc608a4" + integrity sha512-9e/zx1jw7B4CO+c/RXoCsfg/x1AfUBioy4owYH0bJprEYAx5hRFLRhWBqHAG57D0ZM4H7vxbP7bPe0VwhQRYDQ== dependencies: tslib "^1.9.0" @@ -1393,9 +2450,10 @@ cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: inherits "^2.0.1" safe-buffer "^5.0.1" -circular-dependency-plugin@5.0.2: - version "5.0.2" - resolved "https://registry.yarnpkg.com/circular-dependency-plugin/-/circular-dependency-plugin-5.0.2.tgz#da168c0b37e7b43563fb9f912c1c007c213389ef" +circular-dependency-plugin@5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/circular-dependency-plugin/-/circular-dependency-plugin-5.2.0.tgz#e09dbc2dd3e2928442403e2d45b41cea06bc0a93" + integrity sha512-7p4Kn/gffhQaavNfyDFg7LS5S/UT1JAjyGd4UqR2+jzoYF02eDkj0Ec3+48TsIa4zghjLY87nQHIh/ecK9qLdw== class-utils@^0.3.5: version "0.3.6" @@ -1406,17 +2464,22 @@ class-utils@^0.3.5: isobject "^3.0.0" static-extend "^0.1.1" -clean-css@4.2.1: - version "4.2.1" - resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-4.2.1.tgz#2d411ef76b8569b6d0c84068dabe85b0aa5e5c17" - dependencies: - source-map "~0.6.0" +clean-stack@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" + integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== -cli-cursor@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5" +cli-cursor@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307" + integrity sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw== dependencies: - restore-cursor "^2.0.0" + restore-cursor "^3.1.0" + +cli-spinners@^2.2.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.3.0.tgz#0632239a4b5aa4c958610142c34bb7a651fc8df5" + integrity sha512-Xs2Hf2nzrvJMFKimOR7YR0QwZ8fc0u98kdtwN1eNAZzNQgH3vK2pXzff6GJtKh7S5hoJ87ECiAiZFS2fb5Ii2w== cli-width@^2.0.0: version "2.2.0" @@ -1425,6 +2488,7 @@ cli-width@^2.0.0: cliui@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/cliui/-/cliui-3.2.0.tgz#120601537a916d29940f934da3b48d585a39213d" + integrity sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0= dependencies: string-width "^1.0.1" strip-ansi "^3.0.1" @@ -1438,28 +2502,66 @@ cliui@^4.0.0: strip-ansi "^4.0.0" wrap-ansi "^2.0.0" -clone-deep@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/clone-deep/-/clone-deep-2.0.2.tgz#00db3a1e173656730d1188c3d6aced6d7ea97713" +cliui@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-5.0.0.tgz#deefcfdb2e800784aa34f46fa08e06851c7bbbc5" + integrity sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA== + dependencies: + string-width "^3.1.0" + strip-ansi "^5.2.0" + wrap-ansi "^5.1.0" + +cliui@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-6.0.0.tgz#511d702c0c4e41ca156d7d0e96021f23e13225b1" + integrity sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.0" + wrap-ansi "^6.2.0" + +cliui@^7.0.2: + version "7.0.4" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" + integrity sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.0" + wrap-ansi "^7.0.0" + +clone-deep@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/clone-deep/-/clone-deep-4.0.1.tgz#c19fd9bdbbf85942b4fd979c84dcf7d5f07c2387" + integrity sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ== dependencies: - for-own "^1.0.0" is-plain-object "^2.0.4" - kind-of "^6.0.0" - shallow-clone "^1.0.0" + kind-of "^6.0.2" + shallow-clone "^3.0.0" + +clone@^1.0.2: + version "1.0.4" + resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e" + integrity sha1-2jCcwmPfFZlMaIypAheco8fNfH4= clone@^2.1.1, clone@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.2.tgz#1b7f4b9f591f1e8f83670401600345a02887435f" -co@^4.6.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" +coa@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/coa/-/coa-2.0.2.tgz#43f6c21151b4ef2bf57187db0d73de229e3e7ec3" + integrity sha512-q5/jG+YQnSy4nRTV4F7lPepBJZ8qBNJJDBuJdoejDyLXgmL7IEo+Le2JDZudFTFt7mrCqIRaSjws4ygRCTCAXA== + dependencies: + "@types/q" "^1.5.1" + chalk "^2.4.1" + q "^1.1.2" code-point-at@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" + integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c= -codelyzer@^4.0.2, codelyzer@^4.5.0: +codelyzer@^4.0.2: version "4.5.0" resolved "https://registry.yarnpkg.com/codelyzer/-/codelyzer-4.5.0.tgz#a65ddeeeca2894653253a89bfa229118ff9f59b1" dependencies: @@ -1470,6 +2572,21 @@ codelyzer@^4.0.2, codelyzer@^4.5.0: source-map "^0.5.7" sprintf-js "^1.1.1" +codelyzer@^5.1.2: + version "5.2.2" + resolved "https://registry.yarnpkg.com/codelyzer/-/codelyzer-5.2.2.tgz#d0530a455784e6bea0b6d7e97166c73c30a5347f" + integrity sha512-jB4FZ1Sx7kZhvZVdf+N2BaKTdrrNZOL0Bj10RRfrhHrb3zEvXjJvvq298JPMJAiyiCS/v4zs1QlGU0ip7xGqeA== + dependencies: + app-root-path "^2.2.1" + aria-query "^3.0.0" + axobject-query "2.0.2" + css-selector-tokenizer "^0.7.1" + cssauron "^1.4.0" + damerau-levenshtein "^1.0.4" + semver-dsl "^1.0.1" + source-map "^0.5.7" + sprintf-js "^1.1.2" + collection-visit@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0" @@ -1477,55 +2594,68 @@ collection-visit@^1.0.0: map-visit "^1.0.0" object-visit "^1.0.0" -color-convert@^0.5.3: - version "0.5.3" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-0.5.3.tgz#bdb6c69ce660fadffe0b0007cc447e1b9f7282bd" - -color-convert@^1.9.0: +color-convert@^1.9.0, color-convert@^1.9.1, color-convert@^1.9.3: version "1.9.3" resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" dependencies: color-name "1.1.3" +color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + dependencies: + color-name "~1.1.4" + color-name@1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" -color-name@^1.0.0: +color-name@^1.0.0, color-name@~1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" + integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + +color-string@^1.5.2: + version "1.5.3" + resolved "https://registry.yarnpkg.com/color-string/-/color-string-1.5.3.tgz#c9bbc5f01b58b5492f3d6857459cb6590ce204cc" + integrity sha512-dC2C5qeWoYkxki5UAXapdjqO672AM4vZuPGRQfO8b5HKuKGBbKWpITyDYN7TOFKvRW7kOgAn3746clDBMDJyQw== + dependencies: + color-name "^1.0.0" + simple-swizzle "^0.2.2" + +color@^3.0.0: + version "3.1.2" + resolved "https://registry.yarnpkg.com/color/-/color-3.1.2.tgz#68148e7f85d41ad7649c5fa8c8106f098d229e10" + integrity sha512-vXTJhHebByxZn3lDvDJYw4lR5+uB3vuoHsuYA5AKuxRVn5wzzIfQKGLBmgdVRHKTJYeK5rvJcHnrd0Li49CFpg== + dependencies: + color-convert "^1.9.1" + color-string "^1.5.2" combined-stream@^1.0.6, combined-stream@~1.0.6: - version "1.0.7" - resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.7.tgz#2d1d24317afb8abe95d6d2c0b07b57813539d828" + version "1.0.8" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" + integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== dependencies: delayed-stream "~1.0.0" +commander@^2.11.0, commander@^2.20.0: + version "2.20.3" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" + integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== + commander@^2.12.1: version "2.19.0" resolved "https://registry.yarnpkg.com/commander/-/commander-2.19.0.tgz#f6198aa84e5b83c46054b94ddedbfed5ee9ff12a" -commander@^2.19.0: - version "2.20.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.0.tgz#d58bb2b5c1ee8f87b0d340027e9e94e222c5a422" - integrity sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ== - commondir@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" -component-bind@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/component-bind/-/component-bind-1.0.0.tgz#00c608ab7dcd93897c0009651b1d3a8e1e73bbd1" - -component-emitter@1.2.1, component-emitter@^1.2.0, component-emitter@^1.2.1: +component-emitter@^1.2.0, component-emitter@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.2.1.tgz#137918d6d78283f7df7a6b7c5a63e140e69425e6" -component-inherit@0.0.3: - version "0.0.3" - resolved "https://registry.yarnpkg.com/component-inherit/-/component-inherit-0.0.3.tgz#645fc4adf58b72b649d5cae65135619db26ff143" - compressible@~2.0.16: version "2.0.17" resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.17.tgz#6e8c108a16ad58384a977f3a482ca20bff2f38c1" @@ -1549,6 +2679,7 @@ compression@^1.7.4: concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= concat-stream@^1.5.0: version "1.6.2" @@ -1573,6 +2704,7 @@ console-browserify@^1.1.0: console-control-strings@^1.0.0, console-control-strings@~1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" + integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4= constants-browserify@^1.0.0: version "1.0.0" @@ -1589,12 +2721,19 @@ content-type@~1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" -convert-source-map@^1.5.0, convert-source-map@^1.5.1: +convert-source-map@^1.5.1: version "1.6.0" resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.6.0.tgz#51b537a8c43e0f04dec1993bffcdd504e758ac20" dependencies: safe-buffer "~5.1.1" +convert-source-map@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.7.0.tgz#17a2cb882d7f77d3490585e2ce6c524424a3a442" + integrity sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA== + dependencies: + safe-buffer "~5.1.1" + cookie-signature@1.0.6: version "1.0.6" resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" @@ -1624,31 +2763,41 @@ copy-descriptor@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" -copy-webpack-plugin@5.0.2: - version "5.0.2" - resolved "https://registry.yarnpkg.com/copy-webpack-plugin/-/copy-webpack-plugin-5.0.2.tgz#56186dfddbf9aa1b29c97fa4c796c1be98870da4" - integrity sha512-7nC7EynPrnBTtBwwbG1aTqrfNS1aTb9eEjSmQDqFtKAsJrR3uDb+pCDIFT2LzhW+SgGJxQcYzThrmXzzZ720uw== +copy-webpack-plugin@5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/copy-webpack-plugin/-/copy-webpack-plugin-5.1.1.tgz#5481a03dea1123d88a988c6ff8b78247214f0b88" + integrity sha512-P15M5ZC8dyCjQHWwd4Ia/dm0SgVvZJMYeykVIVYXbGyqO4dWB5oyPHp9i7wjwo5LhtlhKbiBCdS2NvM07Wlybg== dependencies: - cacache "^11.3.1" - find-cache-dir "^2.0.0" + cacache "^12.0.3" + find-cache-dir "^2.1.0" glob-parent "^3.1.0" globby "^7.1.1" - is-glob "^4.0.0" - loader-utils "^1.1.0" + is-glob "^4.0.1" + loader-utils "^1.2.3" minimatch "^3.0.4" normalize-path "^3.0.0" - p-limit "^2.1.0" - serialize-javascript "^1.4.0" + p-limit "^2.2.1" + schema-utils "^1.0.0" + serialize-javascript "^2.1.2" webpack-log "^2.0.0" -core-js@3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.0.1.tgz#1343182634298f7f38622f95e73f54e48ddf4738" - integrity sha512-sco40rF+2KlE0ROMvydjkrVMMG1vYilP2ALoRXcYR4obqbYIuV3Bg+51GEDW+HF8n7NRA+iaA4qD0nD9lo9mew== +core-js-compat@^3.6.2: + version "3.6.4" + resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.6.4.tgz#938476569ebb6cda80d339bcf199fae4f16fff17" + integrity sha512-zAa3IZPvsJ0slViBQ2z+vgyyTuhd3MFn1rBQjZSKVEgB0UMYhUkCj9jJUVPgGTGqWvsBVmfnruXgTcNyTlEiSA== + dependencies: + browserslist "^4.8.3" + semver "7.0.0" -core-js@^2.4.0, core-js@^2.5.4: - version "2.6.3" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.3.tgz#4b70938bdffdaf64931e66e2db158f0892289c49" +core-js@3.6.4: + version "3.6.4" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.6.4.tgz#440a83536b458114b9cb2ac1580ba377dc470647" + integrity sha512-4paDGScNgZP2IXXilaffL9X7968RuvwlkK3xWtZRVqgd8SYNiVKRJvkFd1aqqEuPfN7E68ZHEp9hDj6lHj4Hyw== + +core-js@^2.5.4: + version "2.6.11" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.11.tgz#38831469f9922bded8ee21c9dc46985e0399308c" + integrity sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg== core-js@~2.3.0: version "2.3.0" @@ -1657,6 +2806,7 @@ core-js@~2.3.0: core-util-is@1.0.2, core-util-is@~1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" + integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= cosmiconfig@^4.0.0: version "4.0.0" @@ -1667,6 +2817,16 @@ cosmiconfig@^4.0.0: parse-json "^4.0.0" require-from-string "^2.0.1" +cosmiconfig@^5.0.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-5.2.1.tgz#040f726809c591e77a17c0a3626ca45b4f168b1a" + integrity sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA== + dependencies: + import-fresh "^2.0.0" + is-directory "^0.3.1" + js-yaml "^3.13.1" + parse-json "^4.0.0" + create-ecdh@^4.0.0: version "4.0.3" resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.3.tgz#c9111b6f33045c4697f144787f9254cdc77c45ff" @@ -1698,6 +2858,7 @@ create-hmac@^1.1.0, create-hmac@^1.1.2, create-hmac@^1.1.4: cross-spawn@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-3.0.1.tgz#1256037ecb9f0c5f79e3d6ef135e30770184b982" + integrity sha1-ElYDfsufDF9549bvE14wdwGEuYI= dependencies: lru-cache "^4.0.1" which "^1.2.9" @@ -1728,9 +2889,59 @@ crypto-browserify@^3.11.0: randombytes "^2.0.0" randomfill "^1.0.3" -css-parse@1.7.x: - version "1.7.0" - resolved "https://registry.yarnpkg.com/css-parse/-/css-parse-1.7.0.tgz#321f6cf73782a6ff751111390fc05e2c657d8c9b" +css-color-names@0.0.4, css-color-names@^0.0.4: + version "0.0.4" + resolved "https://registry.yarnpkg.com/css-color-names/-/css-color-names-0.0.4.tgz#808adc2e79cf84738069b646cb20ec27beb629e0" + integrity sha1-gIrcLnnPhHOAabZGyyDsJ762KeA= + +css-declaration-sorter@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/css-declaration-sorter/-/css-declaration-sorter-4.0.1.tgz#c198940f63a76d7e36c1e71018b001721054cb22" + integrity sha512-BcxQSKTSEEQUftYpBVnsH4SF05NTuBokb19/sBt6asXGKZ/6VP7PLG1CBCkFDYOnhXhPh0jMhO6xZ71oYHXHBA== + dependencies: + postcss "^7.0.1" + timsort "^0.3.0" + +css-loader@3.5.1: + version "3.5.1" + resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-3.5.1.tgz#db2b2336f4169edb68e6a829ad4fd36552647b77" + integrity sha512-0G4CbcZzQ9D1Q6ndOfjFuMDo8uLYMu5vc9Abs5ztyHcKvmil6GJrMiNjzzi3tQvUF+mVRuDg7bE6Oc0Prolgig== + dependencies: + camelcase "^5.3.1" + cssesc "^3.0.0" + icss-utils "^4.1.1" + loader-utils "^1.2.3" + normalize-path "^3.0.0" + postcss "^7.0.27" + postcss-modules-extract-imports "^2.0.0" + postcss-modules-local-by-default "^3.0.2" + postcss-modules-scope "^2.2.0" + postcss-modules-values "^3.0.0" + postcss-value-parser "^4.0.3" + schema-utils "^2.6.5" + semver "^6.3.0" + +css-parse@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/css-parse/-/css-parse-2.0.0.tgz#a468ee667c16d81ccf05c58c38d2a97c780dbfd4" + integrity sha1-pGjuZnwW2BzPBcWMONKpfHgNv9Q= + dependencies: + css "^2.0.0" + +css-select-base-adapter@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/css-select-base-adapter/-/css-select-base-adapter-0.1.1.tgz#3b2ff4972cc362ab88561507a95408a1432135d7" + integrity sha512-jQVeeRG70QI08vSTwf1jHxp74JoZsr2XSgETae8/xC8ovSnL2WF87GTLO86Sbwdt2lK4Umg4HnnwMO4YF3Ce7w== + +css-select@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/css-select/-/css-select-2.1.0.tgz#6a34653356635934a81baca68d0255432105dbef" + integrity sha512-Dqk7LQKpwLoH3VovzZnkzegqNSuAziQyNZUcrdDM401iY+R5NkGBXGmtO05/yaXQziALuPogeG0b7UAgjnTJTQ== + dependencies: + boolbase "^1.0.0" + css-what "^3.2.1" + domutils "^1.7.0" + nth-check "^1.0.2" css-selector-tokenizer@^0.7.0: version "0.7.1" @@ -1740,6 +2951,46 @@ css-selector-tokenizer@^0.7.0: fastparse "^1.1.1" regexpu-core "^1.0.0" +css-selector-tokenizer@^0.7.1: + version "0.7.2" + resolved "https://registry.yarnpkg.com/css-selector-tokenizer/-/css-selector-tokenizer-0.7.2.tgz#11e5e27c9a48d90284f22d45061c303d7a25ad87" + integrity sha512-yj856NGuAymN6r8bn8/Jl46pR+OC3eEvAhfGYDUe7YPtTPAYrSSw4oAniZ9Y8T5B92hjhwTBLUen0/vKPxf6pw== + dependencies: + cssesc "^3.0.0" + fastparse "^1.1.2" + regexpu-core "^4.6.0" + +css-tree@1.0.0-alpha.37: + version "1.0.0-alpha.37" + resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.0.0-alpha.37.tgz#98bebd62c4c1d9f960ec340cf9f7522e30709a22" + integrity sha512-DMxWJg0rnz7UgxKT0Q1HU/L9BeJI0M6ksor0OgqOnF+aRCDWg/N2641HmVyU9KVIu0OVVWOb2IpC9A+BJRnejg== + dependencies: + mdn-data "2.0.4" + source-map "^0.6.1" + +css-tree@1.0.0-alpha.39: + version "1.0.0-alpha.39" + resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.0.0-alpha.39.tgz#2bff3ffe1bb3f776cf7eefd91ee5cba77a149eeb" + integrity sha512-7UvkEYgBAHRG9Nt980lYxjsTrCyHFN53ky3wVsDkiMdVqylqRt+Zc+jm5qw7/qyOvN2dHSYtX0e4MbCCExSvnA== + dependencies: + mdn-data "2.0.6" + source-map "^0.6.1" + +css-what@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/css-what/-/css-what-3.2.1.tgz#f4a8f12421064621b456755e34a03a2c22df5da1" + integrity sha512-WwOrosiQTvyms+Ti5ZC5vGEK0Vod3FTt1ca+payZqvKuGJF+dq7bG63DstxtN0dpm6FxY27a/zS3Wten+gEtGw== + +css@^2.0.0: + version "2.2.4" + resolved "https://registry.yarnpkg.com/css/-/css-2.2.4.tgz#c646755c73971f2bba6a601e2cf2fd71b1298929" + integrity sha512-oUnjmWpy0niI3x/mPL8dVEI1l7MnG3+HHyRPHf+YFSbK+svOhXpmSOcDURUh2aOCgl2grzrOPt1nHLuCVFULLw== + dependencies: + inherits "^2.0.3" + source-map "^0.6.1" + source-map-resolve "^0.5.2" + urix "^0.1.0" + cssauron@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/cssauron/-/cssauron-1.4.0.tgz#a6602dff7e04a8306dc0db9a551e92e8b5662ad8" @@ -1750,9 +3001,90 @@ cssesc@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-0.1.0.tgz#c814903e45623371a0477b40109aaafbeeaddbb4" +cssesc@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee" + integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg== + +cssnano-preset-default@^4.0.7: + version "4.0.7" + resolved "https://registry.yarnpkg.com/cssnano-preset-default/-/cssnano-preset-default-4.0.7.tgz#51ec662ccfca0f88b396dcd9679cdb931be17f76" + integrity sha512-x0YHHx2h6p0fCl1zY9L9roD7rnlltugGu7zXSKQx6k2rYw0Hi3IqxcoAGF7u9Q5w1nt7vK0ulxV8Lo+EvllGsA== + dependencies: + css-declaration-sorter "^4.0.1" + cssnano-util-raw-cache "^4.0.1" + postcss "^7.0.0" + postcss-calc "^7.0.1" + postcss-colormin "^4.0.3" + postcss-convert-values "^4.0.1" + postcss-discard-comments "^4.0.2" + postcss-discard-duplicates "^4.0.2" + postcss-discard-empty "^4.0.1" + postcss-discard-overridden "^4.0.1" + postcss-merge-longhand "^4.0.11" + postcss-merge-rules "^4.0.3" + postcss-minify-font-values "^4.0.2" + postcss-minify-gradients "^4.0.2" + postcss-minify-params "^4.0.2" + postcss-minify-selectors "^4.0.2" + postcss-normalize-charset "^4.0.1" + postcss-normalize-display-values "^4.0.2" + postcss-normalize-positions "^4.0.2" + postcss-normalize-repeat-style "^4.0.2" + postcss-normalize-string "^4.0.2" + postcss-normalize-timing-functions "^4.0.2" + postcss-normalize-unicode "^4.0.1" + postcss-normalize-url "^4.0.1" + postcss-normalize-whitespace "^4.0.2" + postcss-ordered-values "^4.1.2" + postcss-reduce-initial "^4.0.3" + postcss-reduce-transforms "^4.0.2" + postcss-svgo "^4.0.2" + postcss-unique-selectors "^4.0.1" + +cssnano-util-get-arguments@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/cssnano-util-get-arguments/-/cssnano-util-get-arguments-4.0.0.tgz#ed3a08299f21d75741b20f3b81f194ed49cc150f" + integrity sha1-7ToIKZ8h11dBsg87gfGU7UnMFQ8= + +cssnano-util-get-match@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/cssnano-util-get-match/-/cssnano-util-get-match-4.0.0.tgz#c0e4ca07f5386bb17ec5e52250b4f5961365156d" + integrity sha1-wOTKB/U4a7F+xeUiULT1lhNlFW0= + +cssnano-util-raw-cache@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/cssnano-util-raw-cache/-/cssnano-util-raw-cache-4.0.1.tgz#b26d5fd5f72a11dfe7a7846fb4c67260f96bf282" + integrity sha512-qLuYtWK2b2Dy55I8ZX3ky1Z16WYsx544Q0UWViebptpwn/xDBmog2TLg4f+DBMg1rJ6JDWtn96WHbOKDWt1WQA== + dependencies: + postcss "^7.0.0" + +cssnano-util-same-parent@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/cssnano-util-same-parent/-/cssnano-util-same-parent-4.0.1.tgz#574082fb2859d2db433855835d9a8456ea18bbf3" + integrity sha512-WcKx5OY+KoSIAxBW6UBBRay1U6vkYheCdjyVNDm85zt5K9mHoGOfsOsqIszfAqrQQFIIKgjh2+FDgIj/zsl21Q== + +cssnano@4.1.10: + version "4.1.10" + resolved "https://registry.yarnpkg.com/cssnano/-/cssnano-4.1.10.tgz#0ac41f0b13d13d465487e111b778d42da631b8b2" + integrity sha512-5wny+F6H4/8RgNlaqab4ktc3e0/blKutmq8yNlBFXA//nSFFAqAngjNVRzUvCgYROULmZZUoosL/KSoZo5aUaQ== + dependencies: + cosmiconfig "^5.0.0" + cssnano-preset-default "^4.0.7" + is-resolvable "^1.0.0" + postcss "^7.0.0" + +csso@^4.0.2: + version "4.0.3" + resolved "https://registry.yarnpkg.com/csso/-/csso-4.0.3.tgz#0d9985dc852c7cc2b2cacfbbe1079014d1a8e903" + integrity sha512-NL3spysxUkcrOgnpsT4Xdl2aiEiBG6bXswAABQVHcMrfjjBisFOKwLDOmf4wf32aPdcJws1zds2B0Rg+jqMyHQ== + dependencies: + css-tree "1.0.0-alpha.39" + currently-unhandled@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/currently-unhandled/-/currently-unhandled-0.4.1.tgz#988df33feab191ef799a61369dd76c17adf957ea" + integrity sha1-mI3zP+qxke95mmE2nddsF635V+o= dependencies: array-find-index "^1.0.1" @@ -1760,15 +3092,15 @@ cyclist@~0.2.2: version "0.2.2" resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-0.2.2.tgz#1b33792e11e914a2fd6d6ed6447464444e5fa640" -d@1: - version "1.0.0" - resolved "https://registry.yarnpkg.com/d/-/d-1.0.0.tgz#754bb5bfe55451da69a58b94d45f4c5b0462d58f" - dependencies: - es5-ext "^0.10.9" +damerau-levenshtein@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/damerau-levenshtein/-/damerau-levenshtein-1.0.6.tgz#143c1641cb3d85c60c32329e26899adea8701791" + integrity sha512-JVrozIeElnj3QzfUIt8tB8YMluBJom4Vw9qTPpjGYQ9fYlB3D/rb6OordUxf3xeFB35LKWs0xqcO5U6ySvBtug== dashdash@^1.12.0: version "1.14.1" resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" + integrity sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA= dependencies: assert-plus "^1.0.0" @@ -1776,13 +3108,7 @@ date-now@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/date-now/-/date-now-0.1.4.tgz#eaf439fd4d4848ad74e5cc7dbef200672b9e345b" -debug@*, debug@^4.1.0, debug@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791" - dependencies: - ms "^2.1.1" - -debug@2.6.9, debug@^2.1.2, debug@^2.2.0, debug@^2.3.3, debug@^2.6.8: +debug@2.6.9, debug@^2.1.2, debug@^2.2.0, debug@^2.3.3: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" dependencies: @@ -1794,7 +3120,13 @@ debug@3.1.0, debug@=3.1.0, debug@~3.1.0: dependencies: ms "2.0.0" -debug@^3.0.0, debug@^3.1.0, debug@^3.2.5: +debug@4.1.1, debug@^4.1.0, debug@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791" + dependencies: + ms "^2.1.1" + +debug@^3.0.0, debug@^3.1.0, debug@^3.1.1, debug@^3.2.5: version "3.2.6" resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" dependencies: @@ -1829,7 +3161,14 @@ default-gateway@^4.2.0: execa "^1.0.0" ip-regex "^2.1.0" -define-properties@^1.1.2: +defaults@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/defaults/-/defaults-1.0.3.tgz#c656051e9817d9ff08ed881477f3fe4019f3ef7d" + integrity sha1-xlYFHpgX2f8I7YgUd/P+QBnz730= + dependencies: + clone "^1.0.2" + +define-properties@^1.1.2, define-properties@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" dependencies: @@ -1866,7 +3205,7 @@ del@^2.2.0: pinkie-promise "^2.0.0" rimraf "^2.2.8" -del@^4.1.0: +del@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/del/-/del-4.1.1.tgz#9e8f117222ea44a31ff3a156c049b99052a9f0b4" integrity sha512-QwGuEUouP2kVwQenAsOof5Fv8K9t3D8Ca8NxcXKrIpEHjTXK5J2nXLdP+ALI1cgv8wj7KuwBhTwBkOZSJKM5XQ== @@ -1882,10 +3221,12 @@ del@^4.1.0: delayed-stream@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= delegates@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" + integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o= depd@~1.1.2: version "1.1.2" @@ -1906,12 +3247,6 @@ destroy@~1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" -detect-indent@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-4.0.0.tgz#f76d064352cdf43a1cb6ce619c4ee3a9475de208" - dependencies: - repeating "^2.0.0" - detect-libc@^1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" @@ -1941,6 +3276,11 @@ diffie-hellman@^5.0.0: miller-rabin "^4.0.0" randombytes "^2.0.0" +dijkstrajs@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/dijkstrajs/-/dijkstrajs-1.0.1.tgz#d3cd81221e3ea40742cfcde556d4e99e98ddc71b" + integrity sha1-082BIh4+pAdCz83lVtTpnpjdxxs= + dir-glob@^2.0.0: version "2.2.2" resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-2.2.2.tgz#fa09f0694153c8918b18ba0deafae94769fc50c4" @@ -1964,26 +3304,47 @@ dns-txt@^2.0.2: dependencies: buffer-indexof "^1.0.0" +dom-serializer@0: + version "0.2.2" + resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.2.2.tgz#1afb81f533717175d478655debc5e332d9f9bb51" + integrity sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g== + dependencies: + domelementtype "^2.0.1" + entities "^2.0.0" + domain-browser@^1.1.1: version "1.2.0" resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.2.0.tgz#3d31f50191a6749dd1375a7f522e823d42e54eda" -domain-context@^0.5.1: - version "0.5.1" - resolved "https://registry.yarnpkg.com/domain-context/-/domain-context-0.5.1.tgz#321c66a41055987507b2396acc5f04e53fb997c4" +domelementtype@1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.3.1.tgz#d048c44b37b0d10a7f2a3d5fee3f4333d790481f" + integrity sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w== -domain-task@^3.0.0: - version "3.0.3" - resolved "https://registry.yarnpkg.com/domain-task/-/domain-task-3.0.3.tgz#4fe7d7439acfe792d69bf8e6bfa6b1e356862d45" - dependencies: - domain-context "^0.5.1" - is-absolute-url "^2.1.0" - isomorphic-fetch "^2.2.1" +domelementtype@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.0.1.tgz#1f8bdfe91f5a78063274e803b4bdcedf6e94f94d" + integrity sha512-5HOHUDsYZWV8FGWN0Njbr/Rn7f/eWSQi1v7+HsUVwXgn8nWWlL64zKDkS0n8ZmQ3mlWOMuXOnR+7Nx/5tMO5AQ== domino@^2.1.2: - version "2.1.3" - resolved "https://registry.yarnpkg.com/domino/-/domino-2.1.3.tgz#0ca1ad02cbd316ebe2e99e0ac9fb0010407d4601" - integrity sha512-EwjTbUv1Q/RLQOdn9k7ClHutrQcWGsfXaRQNOnM/KgK4xDBoLFEcIRFuBSxAx13Vfa63X029gXYrNFrSy+DOSg== + version "2.1.4" + resolved "https://registry.yarnpkg.com/domino/-/domino-2.1.4.tgz#78922e7fab7c610f35792b6c745b7962d342e9c4" + integrity sha512-l70mlQ7IjPKC8kT7GljQXJZmt5OqFL+RE91ik5y5WWQtsd9wP8R7gpFnNu96fK5MqAAZRXfLLsnzKtkty5fWGQ== + +domutils@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.7.0.tgz#56ea341e834e06e6748af7a1cb25da67ea9f8c2a" + integrity sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg== + dependencies: + dom-serializer "0" + domelementtype "1" + +dot-prop@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-5.2.0.tgz#c34ecc29556dc45f1f4c22697b6f4904e0cc4fcb" + integrity sha512-uEUyaDKoSQ1M4Oq8l45hSE26SnTxL6snNnqvK/VWx5wJhmff5z0FUVJDKDanor/6w3kzE3i7XZOk+7wC0EXr1A== + dependencies: + is-obj "^2.0.0" duplexify@^3.4.2, duplexify@^3.6.0: version "3.6.1" @@ -1997,6 +3358,7 @@ duplexify@^3.4.2, duplexify@^3.6.0: ecc-jsbn@~0.1.1: version "0.1.2" resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" + integrity sha1-OoOpBOVDUyh4dMVkt1SThoSamMk= dependencies: jsbn "~0.1.0" safer-buffer "^2.1.0" @@ -2005,10 +3367,15 @@ ee-first@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" -electron-to-chromium@^1.3.124, electron-to-chromium@^1.3.150: - version "1.3.151" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.151.tgz#d4099131871ba2448706141162095ab977db805c" - integrity sha512-Lk5HHXw8hSGB6vYJO/yosy4U2JgVFoXn+uDMmZ0sYxltaKon5mKl2AbjNPkY+zBX9asnGDqEJzuzRq1t2aPm1Q== +electron-to-chromium@^1.3.361: + version "1.3.363" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.363.tgz#08756873e49446a92e0cee6c3cd9eb3c52043826" + integrity sha512-4w19wPBkeunBjOA53lNFT36IdOD3Tk1OoIDtTX+VToJUUDX42QfuhtsNKXv25wmSnoBOExM3kTbj7/WDNBwHuQ== + +electron-to-chromium@^1.3.413: + version "1.3.447" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.447.tgz#48372c3eaaf6daccad4f8fa598bdcc455dfe5ff1" + integrity sha512-aXQTgDBUfSejZkwrFIQZ/jJOOevQE9ROsvIs4aSib+l4FknL4qUxGWjCySu4msJFHwVKo9fkX+8bIGSHQp/vTg== elliptic@^6.0.0: version "6.4.1" @@ -2027,10 +3394,20 @@ emoji-regex@^7.0.1: resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA== +emoji-regex@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" + integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== + emojis-list@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-2.1.0.tgz#4daa4d9db00f9819880c79fa457ae5b09a1fd389" +emojis-list@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-3.0.0.tgz#5570662046ad29e2e916e71aae260abdff4f6a78" + integrity sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q== + encodeurl@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" @@ -2047,33 +3424,16 @@ end-of-stream@^1.0.0, end-of-stream@^1.1.0: dependencies: once "^1.4.0" -engine.io-client@~3.3.1: - version "3.3.2" - resolved "https://registry.yarnpkg.com/engine.io-client/-/engine.io-client-3.3.2.tgz#04e068798d75beda14375a264bb3d742d7bc33aa" - dependencies: - component-emitter "1.2.1" - component-inherit "0.0.3" - debug "~3.1.0" - engine.io-parser "~2.1.1" - has-cors "1.1.0" - indexof "0.0.1" - parseqs "0.0.5" - parseuri "0.0.5" - ws "~6.1.0" - xmlhttprequest-ssl "~1.5.4" - yeast "0.1.2" - -engine.io-parser@~2.1.1: - version "2.1.3" - resolved "https://registry.yarnpkg.com/engine.io-parser/-/engine.io-parser-2.1.3.tgz#757ab970fbf2dfb32c7b74b033216d5739ef79a6" +enhanced-resolve@4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-4.1.1.tgz#2937e2b8066cd0fe7ce0990a98f0d71a35189f66" + integrity sha512-98p2zE+rL7/g/DzMHMTF4zZlCgeVdJ7yr6xzEpJRYwFYrGi9ANdn5DnJURg6RpBkyk60XYDnWIv51VfIhfNGuA== dependencies: - after "0.8.2" - arraybuffer.slice "~0.0.7" - base64-arraybuffer "0.1.5" - blob "0.0.5" - has-binary2 "~1.0.2" + graceful-fs "^4.1.2" + memory-fs "^0.5.0" + tapable "^1.0.0" -enhanced-resolve@4.1.0, enhanced-resolve@^4.0.0, enhanced-resolve@^4.1.0: +enhanced-resolve@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-4.1.0.tgz#41c7e0bfdfe74ac1ffe1e57ad6a5c6c9f3742a7f" dependencies: @@ -2081,6 +3441,11 @@ enhanced-resolve@4.1.0, enhanced-resolve@^4.0.0, enhanced-resolve@^4.1.0: memory-fs "^0.4.0" tapable "^1.0.0" +entities@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/entities/-/entities-2.0.2.tgz#ac74db0bba8d33808bbf36809c3a5c3683531436" + integrity sha512-dmD3AvJQBUjKpcNkoqr+x+IF0SdRtPz9Vk0uTy4yWqga9ibB6s4v++QFWNohjiUGoMlF552ZvNyXDxz5iW0qmw== + err-code@^1.0.0: version "1.1.2" resolved "https://registry.yarnpkg.com/err-code/-/err-code-1.1.2.tgz#06e0116d3028f6aef4806849eb0ea6a748ae6960" @@ -2097,21 +3462,48 @@ error-ex@^1.2.0, error-ex@^1.3.1: dependencies: is-arrayish "^0.2.1" -es5-ext@^0.10.35, es5-ext@^0.10.9, es5-ext@~0.10.14: - version "0.10.47" - resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.47.tgz#d24232e1380daad5449a817be19bde9729024a11" +es-abstract@^1.17.0-next.1: + version "1.17.4" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.17.4.tgz#e3aedf19706b20e7c2594c35fc0d57605a79e184" + integrity sha512-Ae3um/gb8F0mui/jPL+QiqmglkUsaQf7FwBEHYIFkztkneosu9imhqHpBzQ3h1vit8t5iQ74t6PEVvphBZiuiQ== + dependencies: + es-to-primitive "^1.2.1" + function-bind "^1.1.1" + has "^1.0.3" + has-symbols "^1.0.1" + is-callable "^1.1.5" + is-regex "^1.0.5" + object-inspect "^1.7.0" + object-keys "^1.1.1" + object.assign "^4.1.0" + string.prototype.trimleft "^2.1.1" + string.prototype.trimright "^2.1.1" + +es-abstract@^1.17.2: + version "1.17.5" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.17.5.tgz#d8c9d1d66c8981fb9200e2251d799eee92774ae9" + integrity sha512-BR9auzDbySxOcfog0tLECW8l28eRGpDpU3Dm3Hp4q/N+VtLTmyj4EUN088XZWQDW/hzj6sYRDXeOFsaAODKvpg== dependencies: - es6-iterator "~2.0.3" - es6-symbol "~3.1.1" - next-tick "1" + es-to-primitive "^1.2.1" + function-bind "^1.1.1" + has "^1.0.3" + has-symbols "^1.0.1" + is-callable "^1.1.5" + is-regex "^1.0.5" + object-inspect "^1.7.0" + object-keys "^1.1.1" + object.assign "^4.1.0" + string.prototype.trimleft "^2.1.1" + string.prototype.trimright "^2.1.1" -es6-iterator@~2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.3.tgz#a7de889141a05a94b0854403b2d0a0fbfa98f3b7" +es-to-primitive@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" + integrity sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA== dependencies: - d "1" - es5-ext "^0.10.35" - es6-symbol "^3.1.1" + is-callable "^1.1.4" + is-date-object "^1.0.1" + is-symbol "^1.0.2" es6-promise@^4.0.3: version "4.2.5" @@ -2127,12 +3519,10 @@ es6-promisify@^5.0.0: dependencies: es6-promise "^4.0.3" -es6-symbol@^3.1.1, es6-symbol@~3.1.1: +escalade@^3.1.1: version "3.1.1" - resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.1.tgz#bf00ef4fdab6ba1b46ecb7b629b4c7ed5715cc77" - dependencies: - d "1" - es5-ext "~0.10.14" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" + integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== escape-html@~1.0.3: version "1.0.3" @@ -2142,9 +3532,10 @@ escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" -eslint-scope@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-4.0.0.tgz#50bf3071e9338bcdc43331794a0cb533f0136172" +eslint-scope@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-4.0.3.tgz#ca03833310f6889a3264781aa82e63eb9cfe7848" + integrity sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg== dependencies: esrecurse "^4.1.0" estraverse "^4.1.1" @@ -2186,6 +3577,7 @@ events@^3.0.0: eventsource@^1.0.7: version "1.0.7" resolved "https://registry.yarnpkg.com/eventsource/-/eventsource-1.0.7.tgz#8fbc72c93fcd34088090bc0a4e64f4b5cee6d8d0" + integrity sha512-4Ln17+vVT0k8aWq+t/bF5arcS3EpT9gYtW66EPacdj/mAFevznsnyoHLPy2BA8gbIQeIHoPsvwmfBftfcG//BQ== dependencies: original "^1.0.0" @@ -2224,7 +3616,7 @@ expand-brackets@^2.1.4: snapdragon "^0.8.1" to-regex "^3.0.1" -express@^4.16.4: +express@^4.17.1: version "4.17.1" resolved "https://registry.yarnpkg.com/express/-/express-4.17.1.tgz#4491fc38605cf51f8629d39c2b5d026f98a4c134" integrity sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g== @@ -2276,6 +3668,7 @@ extend-shallow@^3.0.0, extend-shallow@^3.0.2: extend@^3.0.0, extend@~3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" + integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== external-editor@^3.0.3: version "3.0.3" @@ -2302,24 +3695,29 @@ extglob@^2.0.4: extsprintf@1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" + integrity sha1-lpGEQOMEGnpBT4xS48V06zw+HgU= extsprintf@^1.2.0: version "1.4.0" resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f" - -fast-deep-equal@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz#c053477817c86b51daa853c81e059b733d023614" + integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8= fast-deep-equal@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49" + integrity sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk= -fast-json-stable-stringify@2.0.0, fast-json-stable-stringify@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2" +fast-deep-equal@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz#545145077c501491e33b15ec408c294376e94ae4" + integrity sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA== + +fast-json-stable-stringify@2.1.0, fast-json-stable-stringify@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" + integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== -fastparse@^1.1.1: +fastparse@^1.1.1, fastparse@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/fastparse/-/fastparse-1.1.2.tgz#91728c5a5942eced8531283c79441ee4122c35a9" @@ -2339,19 +3737,20 @@ figgy-pudding@^3.4.1, figgy-pudding@^3.5.1: version "3.5.1" resolved "https://registry.yarnpkg.com/figgy-pudding/-/figgy-pudding-3.5.1.tgz#862470112901c727a0e495a80744bd5baa1d6790" -figures@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/figures/-/figures-2.0.0.tgz#3ab1a2d2a62c8bfb431a0c94cb797a2fce27c962" +figures@^3.0.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/figures/-/figures-3.2.0.tgz#625c18bd293c604dc4a8ddb2febf0c88341746af" + integrity sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg== dependencies: escape-string-regexp "^1.0.5" -file-loader@3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/file-loader/-/file-loader-3.0.1.tgz#f8e0ba0b599918b51adfe45d66d1e771ad560faa" - integrity sha512-4sNIOXgtH/9WZq4NvlfU3Opn5ynUsqBwSLyM+I7UOwdGigTBYfVVQEwe/msZNX/j4pCJTIM14Fsw66Svo1oVrw== +file-loader@6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/file-loader/-/file-loader-6.0.0.tgz#97bbfaab7a2460c07bcbd72d3a6922407f67649f" + integrity sha512-/aMOAYEFXDdjG0wytpTL5YQLfZnnTmLNjn+AIrJ/6HVnTfDqLsVKUUwkDf4I4kgex36BvjuXEn/TX9B/1ESyqQ== dependencies: - loader-utils "^1.0.2" - schema-utils "^1.0.0" + loader-utils "^2.0.0" + schema-utils "^2.6.5" fill-range@^4.0.0: version "4.0.0" @@ -2362,6 +3761,13 @@ fill-range@^4.0.0: repeat-string "^1.6.1" to-regex-range "^2.1.0" +fill-range@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" + integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== + dependencies: + to-regex-range "^5.0.1" + finalhandler@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.2.tgz#b7e7d000ffd11938d0fdb053506f6ebabe9f587d" @@ -2375,27 +3781,53 @@ finalhandler@~1.1.2: statuses "~1.5.0" unpipe "~1.0.0" -find-cache-dir@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-2.0.0.tgz#4c1faed59f45184530fb9d7fa123a4d04a98472d" +find-cache-dir@3.3.1, find-cache-dir@^3.2.0: + version "3.3.1" + resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-3.3.1.tgz#89b33fad4a4670daa94f855f7fbe31d6d84fe880" + integrity sha512-t2GDMt3oGC/v+BMwzmllWDuJF/xcDtE5j/fCGbqDD7OLuJkj0cfh1YSA5VKPvwMeLFLNDBkwOKZ2X85jGLVftQ== + dependencies: + commondir "^1.0.1" + make-dir "^3.0.2" + pkg-dir "^4.1.0" + +find-cache-dir@^2.0.0, find-cache-dir@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-2.1.0.tgz#8d0f94cd13fe43c6c7c261a0d86115ca918c05f7" + integrity sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ== dependencies: commondir "^1.0.1" - make-dir "^1.0.0" + make-dir "^2.0.0" pkg-dir "^3.0.0" find-up@^1.0.0: version "1.1.2" resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f" + integrity sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8= dependencies: path-exists "^2.0.0" pinkie-promise "^2.0.0" +find-up@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" + integrity sha1-RdG35QbHF93UgndaK3eSCjwMV6c= + dependencies: + locate-path "^2.0.0" + find-up@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" dependencies: locate-path "^3.0.0" +find-up@^4.0.0, find-up@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" + integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== + dependencies: + locate-path "^5.0.0" + path-exists "^4.0.0" + flush-write-stream@^1.0.0: version "1.0.3" resolved "https://registry.yarnpkg.com/flush-write-stream/-/flush-write-stream-1.0.3.tgz#c5d586ef38af6097650b49bc41b55fabb19f35bd" @@ -2413,27 +3845,19 @@ font-awesome@^4.7.0: version "4.7.0" resolved "https://registry.yarnpkg.com/font-awesome/-/font-awesome-4.7.0.tgz#8fa8cf0411a1a31afd07b06d2902bb9fc815a133" -for-in@^0.1.3: - version "0.1.8" - resolved "https://registry.yarnpkg.com/for-in/-/for-in-0.1.8.tgz#d8773908e31256109952b1fdb9b3fa867d2775e1" - -for-in@^1.0.1, for-in@^1.0.2: +for-in@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" -for-own@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/for-own/-/for-own-1.0.0.tgz#c63332f415cedc4b04dbfe70cf836494c53cb44b" - dependencies: - for-in "^1.0.1" - forever-agent@~0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" + integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE= form-data@^2.3.1, form-data@~2.3.2: version "2.3.3" resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6" + integrity sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ== dependencies: asynckit "^0.4.0" combined-stream "^1.0.6" @@ -2465,12 +3889,28 @@ from2@^2.1.0: inherits "^2.0.1" readable-stream "^2.0.0" +fs-extra@4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-4.0.2.tgz#f91704c53d1b461f893452b0c307d9997647ab6b" + integrity sha1-+RcExT0bRh+JNFKwwwfZmXZHq2s= + dependencies: + graceful-fs "^4.1.2" + jsonfile "^4.0.0" + universalify "^0.1.0" + fs-minipass@^1.2.5: version "1.2.5" resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.5.tgz#06c277218454ec288df77ada54a03b8702aacb9d" dependencies: minipass "^2.2.1" +fs-minipass@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-2.1.0.tgz#7f5036fdbf12c63c169190cbe4199c852271f9fb" + integrity sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg== + dependencies: + minipass "^3.0.0" + fs-write-stream-atomic@^1.0.8: version "1.0.10" resolved "https://registry.yarnpkg.com/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz#b47df53493ef911df75731e70a9ded0189db40c9" @@ -2483,6 +3923,7 @@ fs-write-stream-atomic@^1.0.8: fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= fsevents@^1.2.2: version "1.2.7" @@ -2499,9 +3940,15 @@ fsevents@^1.2.7: nan "^2.12.1" node-pre-gyp "^0.12.0" -fstream@^1.0.0, fstream@^1.0.2: - version "1.0.11" - resolved "https://registry.yarnpkg.com/fstream/-/fstream-1.0.11.tgz#5c1fb1f117477114f0632a0eb4b71b3cb0fd3171" +fsevents@~2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.1.2.tgz#4c0a1fb34bc68e543b4b82a9ec392bfbda840805" + integrity sha512-R4wDiBwZ0KzpgOWetKDug1FZcYhqYnUYKtfZYt4mD5SBz76q0KR4Q9o7GIPamsVPGmW3EYPPJ0dOOjvx32ldZA== + +fstream@^1.0.0, fstream@^1.0.12: + version "1.0.12" + resolved "https://registry.yarnpkg.com/fstream/-/fstream-1.0.12.tgz#4e8ba8ee2d48be4f7d0de505455548eae5932045" + integrity sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg== dependencies: graceful-fs "^4.1.2" inherits "~2.0.0" @@ -2526,6 +3973,7 @@ function-bind@^1.1.1: gauge@~2.7.3: version "2.7.4" resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" + integrity sha1-LANAXHU4w51+s3sxcCLjJfsBi/c= dependencies: aproba "^1.0.3" console-control-strings "^1.0.0" @@ -2539,6 +3987,7 @@ gauge@~2.7.3: gaze@^1.0.0: version "1.1.3" resolved "https://registry.yarnpkg.com/gaze/-/gaze-1.1.3.tgz#c441733e13b927ac8c0ff0b4c3b033f28812924a" + integrity sha512-BRdNm8hbWzFzWHERTrejLqwHDfS4GibPoq5wjTPIoJHoBtKGPg3xAFfxmM+9ztbXelxcf2hwQcaz1PtmFeue8g== dependencies: globule "^1.0.0" @@ -2546,11 +3995,17 @@ genfun@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/genfun/-/genfun-5.0.0.tgz#9dd9710a06900a5c4a5bf57aca5da4e52fe76537" +gensync@^1.0.0-beta.1: + version "1.0.0-beta.1" + resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.1.tgz#58f4361ff987e5ff6e1e7a210827aa371eaac269" + integrity sha512-r8EC6NO1sngH/zdD9fiRDLdcgnbayXah+mLgManTaIZJqEC1MZstmnox8KpnI2/fxQwrp5OpCOYWLp4rBl4Jcg== + get-caller-file@^1.0.1: version "1.0.3" resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.3.tgz#f978fa4c90d1dfe7ff2d6beda2a515e713bdcf4a" + integrity sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w== -get-caller-file@^2.0.1: +get-caller-file@^2.0.1, get-caller-file@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== @@ -2558,6 +4013,7 @@ get-caller-file@^2.0.1: get-stdin@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-4.0.1.tgz#b968c6b0a04384324902e8bf1a5df32579a450fe" + integrity sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4= get-stream@^4.0.0, get-stream@^4.1.0: version "4.1.0" @@ -2572,6 +4028,7 @@ get-value@^2.0.3, get-value@^2.0.6: getpass@^0.1.1: version "0.1.7" resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" + integrity sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo= dependencies: assert-plus "^1.0.0" @@ -2582,18 +4039,38 @@ glob-parent@^3.1.0: is-glob "^3.1.0" path-dirname "^1.0.0" -glob@7.0.x: - version "7.0.6" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.0.6.tgz#211bafaf49e525b8cd93260d14ab136152b3f57a" +glob-parent@~5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.0.tgz#5f4c1d1e748d30cd73ad2944b3577a81b081e8c2" + integrity sha512-qjtRgnIVmOfnKUE3NJAQEdk+lKrxfw8t5ke7SXtfMTHcjsBfOfWXCQfdb30zfDoZQ2IRSIiidmjtbHZPZ++Ihw== + dependencies: + is-glob "^4.0.1" + +glob@7.1.2: + version "7.1.2" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" + integrity sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + +glob@7.1.6, glob@^7.0.0, glob@^7.0.3, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@~7.1.1: + version "7.1.6" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" + integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== dependencies: fs.realpath "^1.0.0" inflight "^1.0.4" inherits "2" - minimatch "^3.0.2" + minimatch "^3.0.4" once "^1.3.0" path-is-absolute "^1.0.0" -glob@7.1.3, glob@^7.0.0, glob@^7.0.3, glob@^7.0.6, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@~7.1.1: +glob@^7.0.6, glob@^7.1.1: version "7.1.3" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.3.tgz#3960832d3f1574108342dafd3a67b332c0969df1" dependencies: @@ -2604,9 +4081,10 @@ glob@7.1.3, glob@^7.0.0, glob@^7.0.3, glob@^7.0.6, glob@^7.1.1, glob@^7.1.2, glo once "^1.3.0" path-is-absolute "^1.0.0" -globals@^9.18.0: - version "9.18.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a" +globals@^11.1.0: + version "11.12.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" + integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== globby@^5.0.0: version "5.0.0" @@ -2641,20 +4119,27 @@ globby@^7.1.1: slash "^1.0.0" globule@^1.0.0: - version "1.2.1" - resolved "https://registry.yarnpkg.com/globule/-/globule-1.2.1.tgz#5dffb1b191f22d20797a9369b49eab4e9839696d" + version "1.3.0" + resolved "https://registry.yarnpkg.com/globule/-/globule-1.3.0.tgz#41d0e9fb44afd4b80d93a23263714f90b3dec904" + integrity sha512-YlD4kdMqRCQHrhVdonet4TdRtv1/sZKepvoxNT4Nrhrp5HI8XFfc8kFlGlBn2myBo80aGp8Eft259mbcUJhgSg== dependencies: glob "~7.1.1" lodash "~4.17.10" minimatch "~3.0.2" -graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2: +graceful-fs@^4.1.11, graceful-fs@^4.1.15: version "4.1.15" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.15.tgz#ffb703e1066e8a0eeaa4c8b80ba9253eeefbfb00" -hammerjs@^2.0.8: - version "2.0.8" - resolved "https://registry.yarnpkg.com/hammerjs/-/hammerjs-2.0.8.tgz#04ef77862cff2bb79d30f7692095930222bf60f1" +graceful-fs@^4.1.2: + version "4.2.3" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.3.tgz#4a12ff1b60376ef09862c2093edd908328be8423" + integrity sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ== + +graceful-fs@^4.1.6, graceful-fs@^4.2.2: + version "4.2.4" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.4.tgz#2256bde14d3632958c465ebc96dc467ca07a29fb" + integrity sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw== handle-thing@^2.0.0: version "2.0.0" @@ -2664,10 +4149,12 @@ handle-thing@^2.0.0: har-schema@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" + integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI= -har-validator@~5.1.0: +har-validator@~5.1.0, har-validator@~5.1.3: version "5.1.3" resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.3.tgz#1ef89ebd3e4996557675eed9893110dc350fa080" + integrity sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g== dependencies: ajv "^6.5.5" har-schema "^2.0.0" @@ -2675,30 +4162,32 @@ har-validator@~5.1.0: has-ansi@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" + integrity sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE= dependencies: ansi-regex "^2.0.0" -has-binary2@~1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/has-binary2/-/has-binary2-1.0.3.tgz#7776ac627f3ea77250cfc332dab7ddf5e4f5d11d" - dependencies: - isarray "2.0.1" - -has-cors@1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/has-cors/-/has-cors-1.1.0.tgz#5e474793f7ea9843d1bb99c23eef49ff126fff39" - has-flag@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== + has-symbols@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.0.tgz#ba1a8f1af2a0fc39650f5c850367704122063b44" +has-symbols@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.1.tgz#9f5214758a44196c406d9bd76cebf81ec2dd31e8" + integrity sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg== + has-unicode@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" + integrity sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk= has-value@^0.3.1: version "0.3.1" @@ -2727,6 +4216,13 @@ has-values@^1.0.0: is-number "^3.0.0" kind-of "^4.0.0" +has@^1.0.0, has@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" + integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== + dependencies: + function-bind "^1.1.1" + hash-base@^3.0.0: version "3.0.4" resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.0.4.tgz#5fc8686847ecd73499403319a6b0a3f3f6ae4918" @@ -2741,6 +4237,11 @@ hash.js@^1.0.0, hash.js@^1.0.3: inherits "^2.0.3" minimalistic-assert "^1.0.1" +hex-color-regex@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/hex-color-regex/-/hex-color-regex-1.1.0.tgz#4c06fccb4602fe2602b3c93df82d7e7dbf1a8a8e" + integrity sha512-l9sfDFsuqtOqKDsQdqrMRk0U85RZc0RtOR9yPI7mRVOa4FsR/BVnZ0shmQRM96Ji99kYZP/7hn1cedc1+ApsTQ== + hmac-drbg@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" @@ -2749,10 +4250,22 @@ hmac-drbg@^1.0.0: minimalistic-assert "^1.0.0" minimalistic-crypto-utils "^1.0.1" -hosted-git-info@^2.1.4, hosted-git-info@^2.6.0: +hosted-git-info@^2.1.4: + version "2.8.5" + resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.5.tgz#759cfcf2c4d156ade59b0b2dfabddc42a6b9c70c" + integrity sha512-kssjab8CvdXfcXMXVcvsXum4Hwdq9XGtRD3TteMEvEbq0LXyiNQr6AprqKqfeaDXze7SxWvRxdpwE6ku7ikLkg== + +hosted-git-info@^2.6.0: version "2.7.1" resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.7.1.tgz#97f236977bd6e125408930ff6de3eec6281ec047" +hosted-git-info@^3.0.2: + version "3.0.4" + resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-3.0.4.tgz#be4973eb1fd2737b11c9c7c19380739bb249f60d" + integrity sha512-4oT62d2jwSDBbLLFLZE+1vPuQ1h8p9wjrJ8Mqx5TjsyWmBMV5B13eJqn8pvluqubLf3cJPTfiYCIwNwDNmzScQ== + dependencies: + lru-cache "^5.1.1" + hpack.js@^2.1.6: version "2.1.6" resolved "https://registry.yarnpkg.com/hpack.js/-/hpack.js-2.1.6.tgz#87774c0949e513f42e84575b3c45681fade2a0b2" @@ -2762,6 +4275,21 @@ hpack.js@^2.1.6: readable-stream "^2.0.1" wbuf "^1.1.0" +hsl-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/hsl-regex/-/hsl-regex-1.0.0.tgz#d49330c789ed819e276a4c0d272dffa30b18fe6e" + integrity sha1-1JMwx4ntgZ4nakwNJy3/owsY/m4= + +hsla-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/hsla-regex/-/hsla-regex-1.0.0.tgz#c1ce7a3168c8c6614033a4b5f7877f3b225f9c38" + integrity sha1-wc56MWjIxmFAM6S194d/OyJfnDg= + +html-comment-regex@^1.1.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/html-comment-regex/-/html-comment-regex-1.1.2.tgz#97d4688aeb5c81886a364faa0cad1dda14d433a7" + integrity sha512-P+M65QY2JQ5Y0G9KKdlDpo0zK+/OHptU5AaBwUfAIDJZk1MYf32Frm84EcOytfJE0t5JvkAnKlmjsXDnWzCJmQ== + html-entities@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-1.2.1.tgz#0df29351f0721163515dfb9e5543e5f6eed5162f" @@ -2806,7 +4334,7 @@ http-proxy-agent@^2.1.0: agent-base "4" debug "3.1.0" -http-proxy-middleware@^0.19.1: +http-proxy-middleware@0.19.1: version "0.19.1" resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-0.19.1.tgz#183c7dc4aa1479150306498c210cdaf96080a43a" integrity sha512-yHYTgWMQO8VvwNS22eLLloAkvungsKdKTLO8AJlftYIKNfJr3GK3zK0ZCfzDDGUBttdGc8xFy1mCitvNKQtC3Q== @@ -2828,6 +4356,7 @@ http-proxy@^1.17.0: http-signature@~1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" + integrity sha1-muzZJRFHcvPZW2WmCruPfBj7rOE= dependencies: assert-plus "^1.0.0" jsprim "^1.2.2" @@ -2844,6 +4373,14 @@ https-proxy-agent@^2.2.1: agent-base "^4.1.0" debug "^3.1.0" +https-proxy-agent@^2.2.3: + version "2.2.4" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz#4ee7a737abd92678a293d9b34a1af4d0d08c787b" + integrity sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg== + dependencies: + agent-base "^4.3.0" + debug "^3.1.0" + humanize-ms@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/humanize-ms/-/humanize-ms-1.2.1.tgz#c46e3159a293f6b896da29316d8b6fe8bb79bbed" @@ -2856,6 +4393,13 @@ iconv-lite@0.4.24, iconv-lite@^0.4.24, iconv-lite@^0.4.4, iconv-lite@~0.4.13: dependencies: safer-buffer ">= 2.1.2 < 3" +icss-utils@^4.0.0, icss-utils@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/icss-utils/-/icss-utils-4.1.1.tgz#21170b53789ee27447c2f47dd683081403f9a467" + integrity sha512-4aFq7wvWyMHKgxsH8QQtGpvbASCf+eM3wPRLI6R+MgAnTCZ6STYsRvttLvRWK0Nfif5piF394St3HeJDaljGPA== + dependencies: + postcss "^7.0.14" + ieee754@^1.1.4: version "1.1.12" resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.12.tgz#50bf24e5b9c8bb98af4964c941cdb0918da7b60b" @@ -2888,6 +4432,14 @@ import-cwd@^2.0.0: dependencies: import-from "^2.1.0" +import-fresh@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-2.0.0.tgz#d81355c15612d386c61f9ddd3922d4304822a546" + integrity sha1-2BNVwVYS04bGH53dOSLUMEgipUY= + dependencies: + caller-path "^2.0.0" + resolve-from "^3.0.0" + import-from@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/import-from/-/import-from-2.1.0.tgz#335db7f2a7affd53aaa471d4b8021dee36b7f3b1" @@ -2908,56 +4460,75 @@ imurmurhash@^0.1.4: in-publish@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/in-publish/-/in-publish-2.0.0.tgz#e20ff5e3a2afc2690320b6dc552682a9c7fadf51" + integrity sha1-4g/146KvwmkDILbcVSaCqcf631E= indent-string@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-2.1.0.tgz#8e2d48348742121b4a8218b7a137e9a52049dc80" + integrity sha1-ji1INIdCEhtKghi3oTfppSBJ3IA= dependencies: repeating "^2.0.0" -indexof@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/indexof/-/indexof-0.0.1.tgz#82dc336d232b9062179d05ab3293a66059fd435d" +indent-string@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" + integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== + +indexes-of@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/indexes-of/-/indexes-of-1.0.1.tgz#f30f716c8e2bd346c7b67d3df3915566a7c05607" + integrity sha1-8w9xbI4r00bHtn0985FVZqfAVgc= + +infer-owner@^1.0.3, infer-owner@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/infer-owner/-/infer-owner-1.0.4.tgz#c4cefcaa8e51051c2a40ba2ce8a3d27295af9467" + integrity sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A== inflight@^1.0.4: version "1.0.6" resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= dependencies: once "^1.3.0" wrappy "1" -inherits@2, inherits@2.0.3, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.0, inherits@~2.0.1, inherits@~2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" +inherits@2, inherits@~2.0.0, inherits@~2.0.3: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== inherits@2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.1.tgz#b17d08d326b4423e568eff719f91b0b1cbdf69f1" +inherits@2.0.3, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.1: + version "2.0.3" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" + ini@1.3.5, ini@^1.3.4, ini@~1.3.0: version "1.3.5" resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927" -inquirer@6.3.1: - version "6.3.1" - resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-6.3.1.tgz#7a413b5e7950811013a3db491c61d1f3b776e8e7" - integrity sha512-MmL624rfkFt4TG9y/Jvmt8vdmOo836U7Y0Hxr2aFk3RelZEGX4Igk0KabWrcaaZaTv9uzglOqWh1Vly+FAWAXA== +inquirer@7.1.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-7.1.0.tgz#1298a01859883e17c7264b82870ae1034f92dd29" + integrity sha512-5fJMWEmikSYu0nv/flMc475MhGbB7TSPd/2IpFV4I4rMklboCH2rQjYY5kKiYGHqUF9gvaambupcJFFG9dvReg== dependencies: - ansi-escapes "^3.2.0" - chalk "^2.4.2" - cli-cursor "^2.1.0" + ansi-escapes "^4.2.1" + chalk "^3.0.0" + cli-cursor "^3.1.0" cli-width "^2.0.0" external-editor "^3.0.3" - figures "^2.0.0" - lodash "^4.17.11" - mute-stream "0.0.7" - run-async "^2.2.0" - rxjs "^6.4.0" - string-width "^2.1.0" - strip-ansi "^5.1.0" + figures "^3.0.0" + lodash "^4.17.15" + mute-stream "0.0.8" + run-async "^2.4.0" + rxjs "^6.5.3" + string-width "^4.1.0" + strip-ansi "^6.0.0" through "^2.3.6" -internal-ip@^4.2.0: +internal-ip@^4.3.0: version "4.3.0" resolved "https://registry.yarnpkg.com/internal-ip/-/internal-ip-4.3.0.tgz#845452baad9d2ca3b69c635a137acb9a0dad0907" integrity sha512-S1zBo1D6zcsyuC6PMmY5+55YMILQ9av8lotMx447Bq6SAgo/sDK6y6uUKmuYhW7eacnIhFfsPmCNYdDzsnnDCg== @@ -2965,11 +4536,7 @@ internal-ip@^4.2.0: default-gateway "^4.2.0" ipaddr.js "^1.9.0" -interpret@^1.0.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.2.0.tgz#d5061a6224be58e8083985f5014d844359576296" - -invariant@^2.2.2: +invariant@^2.2.2, invariant@^2.2.4: version "2.2.4" resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" dependencies: @@ -2978,6 +4545,7 @@ invariant@^2.2.2: invert-kv@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6" + integrity sha1-EEqOSqym09jNFXqO+L+rLXo//bY= invert-kv@^2.0.0: version "2.0.0" @@ -2996,9 +4564,15 @@ ipaddr.js@1.9.0, ipaddr.js@^1.9.0: resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.0.tgz#37df74e430a0e47550fe54a2defe30d8acd95f65" integrity sha512-M4Sjn6N/+O6/IXSJseKqHoFc+5FdGJ22sXqnjTpdZweHK64MzEPAyQZyEU3R/KRv2GLoa7nNtg/C2Ev6m7z+eA== -is-absolute-url@^2.1.0: +is-absolute-url@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-absolute-url/-/is-absolute-url-2.1.0.tgz#50530dfb84fcc9aa7dbe7852e83a37b93b9f2aa6" + integrity sha1-UFMN+4T8yap9vnhS6Do3uTufKqY= + +is-absolute-url@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/is-absolute-url/-/is-absolute-url-3.0.3.tgz#96c6a22b6a23929b11ea0afb1836c36ad4a5d698" + integrity sha512-opmNIX7uFnS96NtPmhWQgQx6/NYFgsUXYMllcfzwWKUMwfo8kku1TvE6hkNcH+Q1ts5cMVrsY7j0bxXQDciu9Q== is-accessor-descriptor@^0.1.6: version "0.1.6" @@ -3015,6 +4589,12 @@ is-accessor-descriptor@^1.0.0: is-arrayish@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" + integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= + +is-arrayish@^0.3.1: + version "0.3.2" + resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.3.2.tgz#4574a2ae56f7ab206896fb431eaeed066fdf8f03" + integrity sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ== is-binary-path@^1.0.0: version "1.0.1" @@ -3022,6 +4602,13 @@ is-binary-path@^1.0.0: dependencies: binary-extensions "^1.0.0" +is-binary-path@~2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" + integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== + dependencies: + binary-extensions "^2.0.0" + is-buffer@^1.1.5: version "1.1.6" resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" @@ -3029,9 +4616,27 @@ is-buffer@^1.1.5: is-builtin-module@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-builtin-module/-/is-builtin-module-1.0.0.tgz#540572d34f7ac3119f8f76c30cbc1b1e037affbe" + integrity sha1-VAVy0096wxGfj3bDDLwbHgN6/74= dependencies: builtin-modules "^1.0.0" +is-callable@^1.1.4, is-callable@^1.1.5: + version "1.1.5" + resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.5.tgz#f7e46b596890456db74e7f6e976cb3273d06faab" + integrity sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q== + +is-color-stop@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-color-stop/-/is-color-stop-1.1.0.tgz#cfff471aee4dd5c9e158598fbe12967b5cdad345" + integrity sha1-z/9HGu5N1cnhWFmPvhKWe1za00U= + dependencies: + css-color-names "^0.0.4" + hex-color-regex "^1.1.0" + hsl-regex "^1.0.0" + hsla-regex "^1.0.0" + rgb-regex "^1.0.1" + rgba-regex "^1.0.0" + is-data-descriptor@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" @@ -3044,6 +4649,11 @@ is-data-descriptor@^1.0.0: dependencies: kind-of "^6.0.0" +is-date-object@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.2.tgz#bda736f2cd8fd06d32844e7743bfa7494c3bfd7e" + integrity sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g== + is-descriptor@^0.1.0: version "0.1.6" resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca" @@ -3064,6 +4674,11 @@ is-directory@^0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/is-directory/-/is-directory-0.3.1.tgz#61339b6f2475fc772fd9c9d83f5c8575dc154ae1" +is-docker@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.0.0.tgz#2cb0df0e75e2d064fe1864c37cdeacb7b2dcf25b" + integrity sha512-pJEdRugimx4fBMra5z2/5iRdZ63OhYV0vr0Dwm5+xtW4D1FvRkB8hamMIhnWfyJeDdyr/aa7BDyNbtG38VxgoQ== + is-extendable@^0.1.0, is-extendable@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" @@ -3081,18 +4696,26 @@ is-extglob@^2.1.0, is-extglob@^2.1.1: is-finite@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.0.2.tgz#cc6677695602be550ef11e8b4aa6305342b6d0aa" + integrity sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko= dependencies: number-is-nan "^1.0.0" is-fullwidth-code-point@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" + integrity sha1-754xOG8DGn8NZDr4L95QxFfvAMs= dependencies: number-is-nan "^1.0.0" is-fullwidth-code-point@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" + integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= + +is-fullwidth-code-point@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" + integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== is-glob@^3.1.0: version "3.1.0" @@ -3106,12 +4729,34 @@ is-glob@^4.0.0: dependencies: is-extglob "^2.1.1" +is-glob@^4.0.1, is-glob@~4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc" + integrity sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg== + dependencies: + is-extglob "^2.1.1" + +is-interactive@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-interactive/-/is-interactive-1.0.0.tgz#cea6e6ae5c870a7b0a0004070b7b587e0252912e" + integrity sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w== + is-number@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" dependencies: kind-of "^3.0.2" +is-number@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== + +is-obj@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-2.0.0.tgz#473fb05d973705e3fd9620545018ca8e22ef4982" + integrity sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w== + is-path-cwd@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-1.0.0.tgz#d225ec23132e89edd38fda767472e62e65f1106d" @@ -3156,23 +4801,47 @@ is-plain-object@^2.0.1, is-plain-object@^2.0.3, is-plain-object@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" dependencies: - isobject "^3.0.1" + isobject "^3.0.1" + +is-regex@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.5.tgz#39d589a358bf18967f726967120b8fc1aed74eae" + integrity sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ== + dependencies: + has "^1.0.3" -is-promise@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa" +is-resolvable@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-resolvable/-/is-resolvable-1.1.0.tgz#fb18f87ce1feb925169c9a407c19318a3206ed88" + integrity sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg== -is-stream@^1.0.1, is-stream@^1.1.0: +is-stream@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" +is-svg@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-svg/-/is-svg-3.0.0.tgz#9321dbd29c212e5ca99c4fa9794c714bcafa2f75" + integrity sha512-gi4iHK53LR2ujhLVVj+37Ykh9GLqYHX6JOVXbLAucaG/Cqw9xwdFOjDM2qeifLs1sF1npXXFvDu0r5HNgCMrzQ== + dependencies: + html-comment-regex "^1.1.0" + +is-symbol@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.3.tgz#38e1014b9e6329be0de9d24a414fd7441ec61937" + integrity sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ== + dependencies: + has-symbols "^1.0.1" + is-typedarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" + integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= is-utf8@^0.2.0: version "0.2.1" resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" + integrity sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI= is-windows@^1.0.2: version "1.0.2" @@ -3182,17 +4851,26 @@ is-wsl@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-1.1.0.tgz#1f16e4aa22b04d1336b66188a66af3c600c3a66d" +is-wsl@^2.1.1: + version "2.2.0" + resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271" + integrity sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww== + dependencies: + is-docker "^2.0.0" + isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" -isarray@2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.1.tgz#a37d94ed9cda2d59865c9f76fe596ee1f338741e" +isarray@^2.0.1: + version "2.0.5" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.5.tgz#8af1e4c1221244cc62459faf38940d4e644a5723" + integrity sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw== isexe@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= isobject@^2.0.0: version "2.1.0" @@ -3204,41 +4882,25 @@ isobject@^3.0.0, isobject@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" -isomorphic-fetch@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz#611ae1acf14f5e81f729507472819fe9733558a9" - dependencies: - node-fetch "^1.0.1" - whatwg-fetch ">=0.10.0" - isstream@~0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" + integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo= -istanbul-instrumenter-loader@3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/istanbul-instrumenter-loader/-/istanbul-instrumenter-loader-3.0.1.tgz#9957bd59252b373fae5c52b7b5188e6fde2a0949" - dependencies: - convert-source-map "^1.5.0" - istanbul-lib-instrument "^1.7.3" - loader-utils "^1.1.0" - schema-utils "^0.3.0" +istanbul-lib-coverage@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.0.0.tgz#f5944a37c70b550b02a78a5c3b2055b280cec8ec" + integrity sha512-UiUIqxMgRDET6eR+o5HbfRYP1l0hqkWOs7vNxC/mggutCMUIhWMm8gAHb8tHlyfD3/l6rlgNA5cKdDzEAf6hEg== -istanbul-lib-coverage@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-1.2.1.tgz#ccf7edcd0a0bb9b8f729feeb0930470f9af664f0" - -istanbul-lib-instrument@^1.7.3: - version "1.10.2" - resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-1.10.2.tgz#1f55ed10ac3c47f2bdddd5307935126754d0a9ca" - dependencies: - babel-generator "^6.18.0" - babel-template "^6.16.0" - babel-traverse "^6.18.0" - babel-types "^6.18.0" - babylon "^6.18.0" - istanbul-lib-coverage "^1.2.1" - semver "^5.3.0" +istanbul-lib-instrument@^4.0.1: + version "4.0.3" + resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.3.tgz#873c6fff897450118222774696a3f28902d77c1d" + integrity sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ== + dependencies: + "@babel/core" "^7.7.5" + "@istanbuljs/schema" "^0.1.2" + istanbul-lib-coverage "^3.0.0" + semver "^6.3.0" jasmine-core@~2.8.0: version "2.8.0" @@ -3256,6 +4918,22 @@ jasminewd2@^2.1.0: version "2.2.0" resolved "https://registry.yarnpkg.com/jasminewd2/-/jasminewd2-2.2.0.tgz#e37cf0b17f199cce23bea71b2039395246b4ec4e" +jest-worker@25.1.0: + version "25.1.0" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-25.1.0.tgz#75d038bad6fdf58eba0d2ec1835856c497e3907a" + integrity sha512-ZHhHtlxOWSxCoNOKHGbiLzXnl42ga9CxDr27H36Qn+15pQZd3R/F24jrmjDelw9j/iHUIWMWs08/u2QN50HHOg== + dependencies: + merge-stream "^2.0.0" + supports-color "^7.0.0" + +jest-worker@^25.1.0: + version "25.5.0" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-25.5.0.tgz#2611d071b79cea0f43ee57a3d118593ac1547db1" + integrity sha512-/dsSmUkIy5EBGfv/IjjqmFxrNAUpBERfGs1oHROyD7yxjG/w+t0GOJDX8O1k32ySmd7+a5IhnJU2qQFcJ4n1vw== + dependencies: + merge-stream "^2.0.0" + supports-color "^7.0.0" + jquery@3.3.1: version "3.3.1" resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.3.1.tgz#958ce29e81c9790f31be7792df5d4d95fc57fbca" @@ -3263,8 +4941,9 @@ jquery@3.3.1: js-base64@^2.1.8: version "2.5.1" resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.5.1.tgz#1efa39ef2c5f7980bb1784ade4a8af2de3291121" + integrity sha512-M7kLczedRMYX4L8Mdh4MzyAMM9O5osx+4FcOQuTvr3A9F2D9S5JXheN0ewNbrvK2UatkTRhL5ejGmGSjNMiZuw== -"js-tokens@^3.0.0 || ^4.0.0": +"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" @@ -3272,6 +4951,14 @@ js-tokens@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" +js-yaml@^3.13.1: + version "3.13.1" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847" + integrity sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw== + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + js-yaml@^3.7.0, js-yaml@^3.9.0: version "3.12.1" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.12.1.tgz#295c8632a18a23e054cf5c9d3cecafe678167600" @@ -3282,10 +4969,12 @@ js-yaml@^3.7.0, js-yaml@^3.9.0: jsbn@~0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" + integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM= -jsesc@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-1.3.0.tgz#46c3fec8c1892b12b0833db9bc7622176dbab34b" +jsesc@^2.5.1: + version "2.5.2" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" + integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== jsesc@~0.5.0: version "0.5.0" @@ -3295,36 +4984,52 @@ json-parse-better-errors@^1.0.0, json-parse-better-errors@^1.0.1, json-parse-bet version "1.0.2" resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" -json-schema-traverse@^0.3.0: - version "0.3.1" - resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz#349a6d44c53a51de89b40805c5d5e59b417d3340" - json-schema-traverse@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" + integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== json-schema@0.2.3: version "0.2.3" resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" + integrity sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM= json-stringify-safe@~5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" + integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= json3@^3.3.2: version "3.3.2" resolved "https://registry.yarnpkg.com/json3/-/json3-3.3.2.tgz#3c0434743df93e2f5c42aee7b19bcb483575f4e1" -json5@^0.5.0: - version "0.5.1" - resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821" - json5@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.1.tgz#779fb0018604fa854eacbf6252180d83543e3dbe" dependencies: minimist "^1.2.0" +json5@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/json5/-/json5-2.1.1.tgz#81b6cb04e9ba496f1c7005d07b4368a2638f90b6" + integrity sha512-l+3HXD0GEI3huGq1njuqtzYK8OYJyXMkOLtQ53pjWh89tvWS2h6l+1zMkYWqlb57+SiQodKZyvMEFb2X+KrFhQ== + dependencies: + minimist "^1.2.0" + +json5@^2.1.2: + version "2.1.3" + resolved "https://registry.yarnpkg.com/json5/-/json5-2.1.3.tgz#c9b0f7fa9233bfe5807fe66fcf3a5617ed597d43" + integrity sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA== + dependencies: + minimist "^1.2.5" + +jsonfile@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" + integrity sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss= + optionalDependencies: + graceful-fs "^4.1.6" + jsonparse@^1.2.0: version "1.3.1" resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280" @@ -3332,6 +5037,7 @@ jsonparse@^1.2.0: jsprim@^1.2.2: version "1.4.1" resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2" + integrity sha1-MT5mvB5cwG5Di8G3SZwuXFastqI= dependencies: assert-plus "1.0.0" extsprintf "1.3.0" @@ -3383,6 +5089,7 @@ kind-of@^6.0.0, kind-of@^6.0.2: lcid@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/lcid/-/lcid-1.0.0.tgz#308accafa0bc483a3867b4b6f2b9506251d1b835" + integrity sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU= dependencies: invert-kv "^1.0.0" @@ -3392,20 +5099,22 @@ lcid@^2.0.0: dependencies: invert-kv "^2.0.0" -less-loader@4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/less-loader/-/less-loader-4.1.0.tgz#2c1352c5b09a4f84101490274fd51674de41363e" +less-loader@5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/less-loader/-/less-loader-5.0.0.tgz#498dde3a6c6c4f887458ee9ed3f086a12ad1b466" + integrity sha512-bquCU89mO/yWLaUq0Clk7qCsKhsF/TZpJUzETRvJa9KSVEL9SO3ovCvdEHISBhrC81OwC8QSVX7E0bzElZj9cg== dependencies: clone "^2.1.1" loader-utils "^1.1.0" - pify "^3.0.0" + pify "^4.0.1" -less@3.9.0: - version "3.9.0" - resolved "https://registry.yarnpkg.com/less/-/less-3.9.0.tgz#b7511c43f37cf57dc87dffd9883ec121289b1474" - integrity sha512-31CmtPEZraNUtuUREYjSqRkeETFdyEHSEPAGq4erDlUXtda7pzNmctdljdIagSb589d/qXGWiiP31R5JVf+v0w== +less@3.11.1: + version "3.11.1" + resolved "https://registry.yarnpkg.com/less/-/less-3.11.1.tgz#c6bf08e39e02404fe6b307a3dfffafdc55bd36e2" + integrity sha512-tlWX341RECuTOvoDIvtFqXsKj072hm3+9ymRBe76/mD6O5ZZecnlAOVDlWAleF2+aohFrxNidXhv2773f6kY7g== dependencies: clone "^2.1.2" + tslib "^1.10.0" optionalDependencies: errno "^0.1.1" graceful-fs "^4.1.2" @@ -3416,10 +5125,22 @@ less@3.9.0: request "^2.83.0" source-map "~0.6.0" -license-webpack-plugin@2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/license-webpack-plugin/-/license-webpack-plugin-2.1.1.tgz#f0ab760f7f301c76f5af52e480f320656b5721bb" - integrity sha512-TiarZIg5vkQ2rGdYJn2+5YxO/zqlqjpK5IVglr7OfmrN1sBCakS+PQrsP2uC5gtve1ZDb9WMSUMlmHDQ0FoW4w== +leven@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" + integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A== + +levenary@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/levenary/-/levenary-1.1.1.tgz#842a9ee98d2075aa7faeedbe32679e9205f46f77" + integrity sha512-mkAdOIt79FD6irqjYSs4rdbnlT5vRonMEvBVPVb3XmevfS8kgRXwfes0dhPdEtzTWD/1eNE/Bm/G1iRt6DcnQQ== + dependencies: + leven "^3.1.0" + +license-webpack-plugin@2.1.4: + version "2.1.4" + resolved "https://registry.yarnpkg.com/license-webpack-plugin/-/license-webpack-plugin-2.1.4.tgz#c5529a4bb87cc9b4489b486d054ba7cae43a554e" + integrity sha512-1Xq72fmPbTg5KofXs+yI5L4QqPFjQ6mZxoeI6D7gfiEDOtaEIk6PGrdLaej90bpDqKNHNxlQ/MW4tMAL6xMPJQ== dependencies: "@types/webpack-sources" "^0.1.5" webpack-sources "^1.2.0" @@ -3433,6 +5154,7 @@ lie@~3.1.0: load-json-file@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0" + integrity sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA= dependencies: graceful-fs "^4.1.2" parse-json "^2.2.0" @@ -3440,11 +5162,21 @@ load-json-file@^1.0.0: pinkie-promise "^2.0.0" strip-bom "^2.0.0" -loader-runner@^2.3.0: +loader-runner@^2.4.0: version "2.4.0" resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-2.4.0.tgz#ed47066bfe534d7e84c4c7b9998c2a75607d9357" + integrity sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw== + +loader-utils@2.0.0, loader-utils@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-2.0.0.tgz#e4cace5b816d425a166b5f097e10cd12b36064b0" + integrity sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ== + dependencies: + big.js "^5.2.2" + emojis-list "^3.0.0" + json5 "^2.1.2" -loader-utils@1.2.3, loader-utils@^1.0.1, loader-utils@^1.0.2, loader-utils@^1.1.0, loader-utils@^1.2.3: +loader-utils@^1.0.2, loader-utils@^1.1.0, loader-utils@^1.2.3: version "1.2.3" resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.2.3.tgz#1ff5dc6911c9f0a062531a4c04b609406108c2c7" dependencies: @@ -3452,14 +5184,22 @@ loader-utils@1.2.3, loader-utils@^1.0.1, loader-utils@^1.0.2, loader-utils@^1.1. emojis-list "^2.0.0" json5 "^1.0.1" -loader-utils@^0.2.15: - version "0.2.17" - resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-0.2.17.tgz#f86e6374d43205a6e6c60e9196f17c0299bfb348" +loader-utils@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.4.0.tgz#c579b5e34cb34b1a74edc6c1fb36bfa371d5a613" + integrity sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA== dependencies: - big.js "^3.1.3" - emojis-list "^2.0.0" - json5 "^0.5.0" - object-assign "^4.0.1" + big.js "^5.2.2" + emojis-list "^3.0.0" + json5 "^1.0.1" + +locate-path@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" + integrity sha1-K1aLJl7slExtnA3pw9u7ygNUzY4= + dependencies: + p-locate "^2.0.0" + path-exists "^3.0.0" locate-path@^3.0.0: version "3.0.0" @@ -3468,11 +5208,14 @@ locate-path@^3.0.0: p-locate "^3.0.0" path-exists "^3.0.0" -lodash.assign@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/lodash.assign/-/lodash.assign-4.2.0.tgz#0d99f3ccd7a6d261d19bdaeb9245005d285808e7" +locate-path@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" + integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== + dependencies: + p-locate "^4.1.0" -lodash.clonedeep@^4.3.2, lodash.clonedeep@^4.5.0: +lodash.clonedeep@^4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef" @@ -3485,40 +5228,31 @@ lodash.memoize@^4.1.2: resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" integrity sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4= -lodash.mergewith@^4.6.0: - version "4.6.1" - resolved "https://registry.yarnpkg.com/lodash.mergewith/-/lodash.mergewith-4.6.1.tgz#639057e726c3afbdb3e7d42741caa8d6e4335927" - -lodash.tail@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/lodash.tail/-/lodash.tail-4.1.1.tgz#d2333a36d9e7717c8ad2f7cacafec7c32b444664" - lodash.uniq@^4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M= -lodash@^4.0.0, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.4, lodash@^4.17.5, lodash@~4.17.10: +lodash@^4.0.0, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@~4.17.10: + version "4.17.15" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" + integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== + +lodash@^4.17.10, lodash@^4.17.11: version "4.17.11" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.11.tgz#b39ea6229ef607ecd89e2c8df12536891cac9b8d" -log-symbols@^2.1.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-2.2.0.tgz#5740e1c5d6f0dfda4ad9323b5332107ef6b4c40a" +log-symbols@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-3.0.0.tgz#f3a08516a5dea893336a7dee14d18a1cfdab77c4" + integrity sha512-dSkNGuI7iG3mfvDzUuYZyvk5dD9ocYCYzNU6CYDE6+Xqd+gwme6Z00NS3dUh8mq/73HaEtT7m6W+yUPtU6BZnQ== dependencies: - chalk "^2.0.1" - -loglevel@^1.6.1: - version "1.6.2" - resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.6.2.tgz#668c77948a03dbd22502a3513ace1f62a80cc372" - integrity sha512-Jt2MHrCNdtIe1W6co3tF5KXGRkzF+TYffiQstfXa04mrss9IKXzAAXYWak8LbZseAQY03sH2GzMCMU0ZOUc9bg== + chalk "^2.4.2" -loglevelnext@^1.0.1: - version "1.0.5" - resolved "https://registry.yarnpkg.com/loglevelnext/-/loglevelnext-1.0.5.tgz#36fc4f5996d6640f539ff203ba819641680d75a2" - dependencies: - es6-symbol "^3.1.1" - object.assign "^4.1.0" +loglevel@^1.6.6: + version "1.6.8" + resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.6.8.tgz#8a25fb75d092230ecd4457270d80b54e28011171" + integrity sha512-bsU7+gc9AJ2SqpzxwU3+1fedl8zAntbtC5XYlt3s2j1hJcn2PsXSmgN8TaLG/J1/2mod4+cE/3vNL70/c1RNCA== loose-envify@^1.0.0: version "1.4.0" @@ -3529,13 +5263,15 @@ loose-envify@^1.0.0: loud-rejection@^1.0.0: version "1.6.0" resolved "https://registry.yarnpkg.com/loud-rejection/-/loud-rejection-1.6.0.tgz#5b46f80147edee578870f086d04821cf998e551f" + integrity sha1-W0b4AUft7leIcPCG0Eghz5mOVR8= dependencies: currently-unhandled "^0.4.1" signal-exit "^3.0.0" -lru-cache@^4.0.1, lru-cache@^4.1.2, lru-cache@^4.1.3: +lru-cache@^4.0.1: version "4.1.5" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.5.tgz#8bbe50ea85bed59bc9e33dcab8235ee9bcf443cd" + integrity sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g== dependencies: pseudomap "^1.0.2" yallist "^2.1.2" @@ -3556,10 +5292,10 @@ luxon@^1.3.3: resolved "https://registry.yarnpkg.com/luxon/-/luxon-1.12.0.tgz#d02d53c8d8aaebe6b4c00ba1ce1be3913546b2e7" integrity sha512-enPnPIHd5ZnZT0vpj9Xv8aq4j0yueAkhnh4xUKUHpqlgSm1r/8s6xTMjfyp2ugOWP7zivqJqgVTkW+rpHed61w== -magic-string@0.25.2: - version "0.25.2" - resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.25.2.tgz#139c3a729515ec55e96e69e82a11fe890a293ad9" - integrity sha512-iLs9mPjh9IuTtRsqqhNGYcZXGei0Nh/A4xirrsqW7c+QhKVFL2vm7U09ru6cHRD22azaP/wMDgI+HCqbETMTtg== +magic-string@0.25.7: + version "0.25.7" + resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.25.7.tgz#3f497d6fd34c669c6798dcb821f2ef31f5445051" + integrity sha512-4CrMT5DOHTDk4HYDlzmwu4FVCcIYI8gauveasrdCu2IKIFOJ3f0v/8MDGJCDL9oD2ppz/Av1b0Nj345H9M+XIA== dependencies: sourcemap-codec "^1.4.4" @@ -3569,26 +5305,36 @@ magic-string@^0.25.0: dependencies: sourcemap-codec "^1.4.1" -make-dir@^1.0.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.3.0.tgz#79c1033b80515bd6d24ec9933e860ca75ee27f0c" +make-dir@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-2.1.0.tgz#5f0310e18b8be898cc07009295a30ae41e91e6f5" + integrity sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA== dependencies: - pify "^3.0.0" + pify "^4.0.1" + semver "^5.6.0" + +make-dir@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" + integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw== + dependencies: + semver "^6.0.0" make-error@^1.1.1: version "1.3.5" resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.5.tgz#efe4e81f6db28cadd605c70f29c831b58ef776c8" -make-fetch-happen@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/make-fetch-happen/-/make-fetch-happen-4.0.1.tgz#141497cb878f243ba93136c83d8aba12c216c083" +make-fetch-happen@^5.0.0: + version "5.0.2" + resolved "https://registry.yarnpkg.com/make-fetch-happen/-/make-fetch-happen-5.0.2.tgz#aa8387104f2687edca01c8687ee45013d02d19bd" + integrity sha512-07JHC0r1ykIoruKO8ifMXu+xEU8qOXDFETylktdug6vJDACnP+HKevOu3PXyNPzFyTSlz8vrBYlBO1JZRe8Cag== dependencies: agentkeepalive "^3.4.1" - cacache "^11.0.1" + cacache "^12.0.0" http-cache-semantics "^3.8.1" http-proxy-agent "^2.1.0" - https-proxy-agent "^2.2.1" - lru-cache "^4.1.2" + https-proxy-agent "^2.2.3" + lru-cache "^5.1.1" mississippi "^3.0.0" node-fetch-npm "^2.0.2" promise-retry "^1.1.1" @@ -3613,6 +5359,7 @@ map-cache@^0.2.2: map-obj@^1.0.0, map-obj@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d" + integrity sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0= map-visit@^1.0.0: version "1.0.0" @@ -3628,6 +5375,16 @@ md5.js@^1.3.4: inherits "^2.0.1" safe-buffer "^5.1.2" +mdn-data@2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.4.tgz#699b3c38ac6f1d728091a64650b65d388502fd5b" + integrity sha512-iV3XNKw06j5Q7mi6h+9vbx23Tv7JkjEVgKHW4pimwyDGWm0OIQntJJ+u1C6mg6mK1EaTv42XQ7w76yuzH7M2cA== + +mdn-data@2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.6.tgz#852dc60fcaa5daa2e8cf6c9189c440ed3e042978" + integrity sha512-rQvjv71olwNHgiTbfPZFkJtjNMciWgswYeciZhtvWLO8bmX3TnhyA62I6sTWOyZssWHJJjY6/KiWwqQsWWsqOA== + media-typer@0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" @@ -3640,16 +5397,25 @@ mem@^4.0.0: mimic-fn "^1.0.0" p-is-promise "^1.1.0" -memory-fs@^0.4.0, memory-fs@^0.4.1, memory-fs@~0.4.1: +memory-fs@^0.4.0, memory-fs@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.4.1.tgz#3a9a20b8462523e447cfbc7e8bb80ed667bfc552" dependencies: errno "^0.1.3" readable-stream "^2.0.1" +memory-fs@^0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.5.0.tgz#324c01288b88652966d161db77838720845a8e3c" + integrity sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA== + dependencies: + errno "^0.1.3" + readable-stream "^2.0.1" + meow@^3.7.0: version "3.7.0" resolved "https://registry.yarnpkg.com/meow/-/meow-3.7.0.tgz#72cb668b425228290abbfa856892587308a801fb" + integrity sha1-cstmi0JSKCkKu/qFaJJYcwioAfs= dependencies: camelcase-keys "^2.0.0" decamelize "^1.1.2" @@ -3666,11 +5432,23 @@ merge-descriptors@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" +merge-source-map@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/merge-source-map/-/merge-source-map-1.1.0.tgz#2fdde7e6020939f70906a68f2d7ae685e4c8c646" + integrity sha512-Qkcp7P2ygktpMPh2mCQZaf3jhN6D3Z/qVZHSdWvQ+2Ef5HgRAPBO57A77+ENm0CPx2+1Ce/MYKi3ymqdfuqibw== + dependencies: + source-map "^0.6.1" + +merge-stream@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" + integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== + methods@^1.1.1, methods@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" -micromatch@^3.1.10, micromatch@^3.1.4, micromatch@^3.1.8, micromatch@^3.1.9: +micromatch@^3.1.10, micromatch@^3.1.4: version "3.1.10" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" dependencies: @@ -3700,11 +5478,24 @@ mime-db@1.40.0, "mime-db@>= 1.40.0 < 2": resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.40.0.tgz#a65057e998db090f732a68f6c276d387d4126c32" integrity sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA== +mime-db@1.43.0: + version "1.43.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.43.0.tgz#0a12e0502650e473d735535050e7c8f4eb4fae58" + integrity sha512-+5dsGEEovYbT8UY9yD7eE4XTc4UwJ1jBYlgaQQF38ENsKR3wj/8q8RFZrF9WIZpB2V1ArTVFUva8sAul1NzRzQ== + mime-db@~1.37.0: version "1.37.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.37.0.tgz#0b6a0ce6fdbe9576e25f1f2d2fde8830dc0ad0d8" + integrity sha512-R3C4db6bgQhlIhPU48fUtdVmKnflq+hRdad7IyKhtFj06VPNVdk2RhiYL3UjQIlso8L+YxAtFkobT0VK+S/ybg== + +mime-types@^2.1.12, mime-types@~2.1.19: + version "2.1.26" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.26.tgz#9c921fc09b7e149a65dfdc0da4d20997200b0a06" + integrity sha512-01paPWYgLrkqAyrlDorC1uDwl2p3qZT7yl806vW7DvDoxwXi46jsjFbg+WdwotBIk6/MbEhO/dh5aZ5sNj/dWQ== + dependencies: + mime-db "1.43.0" -mime-types@^2.1.12, mime-types@~2.1.17, mime-types@~2.1.18, mime-types@~2.1.19: +mime-types@~2.1.17, mime-types@~2.1.18: version "2.1.21" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.21.tgz#28995aa1ecb770742fe6ae7e58f9181c744b3f96" dependencies: @@ -3721,11 +5512,7 @@ mime@1.6.0, mime@^1.4.1: version "1.6.0" resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" -mime@^2.3.1: - version "2.4.0" - resolved "https://registry.yarnpkg.com/mime/-/mime-2.4.0.tgz#e051fd881358585f3279df333fe694da0bcffdd6" - -mime@^2.4.2: +mime@^2.4.4: version "2.4.4" resolved "https://registry.yarnpkg.com/mime/-/mime-2.4.4.tgz#bd7b91135fc6b01cde3e9bae33d659b63d8857e5" integrity sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA== @@ -3734,13 +5521,18 @@ mimic-fn@^1.0.0: version "1.2.0" resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022" -mini-css-extract-plugin@0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-0.6.0.tgz#a3f13372d6fcde912f3ee4cd039665704801e3b9" - integrity sha512-79q5P7YGI6rdnVyIAV4NXpBQJFWdkzJxCim3Kog4078fM0piAaFlwocqbejdWtLW1cEzCexPrh6EdyFsPgVdAw== +mimic-fn@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" + integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== + +mini-css-extract-plugin@0.9.0: + version "0.9.0" + resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-0.9.0.tgz#47f2cf07aa165ab35733b1fc97d4c46c0564339e" + integrity sha512-lp3GeY7ygcgAmVIcRPBVhIkf8Us7FZjA+ILpal44qLdSu11wmjKQ3d9k15lfD7pO4esu9eUIAW7qiYIBppv40A== dependencies: loader-utils "^1.1.0" - normalize-url "^2.0.1" + normalize-url "1.9.1" schema-utils "^1.0.0" webpack-sources "^1.1.0" @@ -3752,24 +5544,52 @@ minimalistic-crypto-utils@^1.0.0, minimalistic-crypto-utils@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" -minimatch@3.0.4, minimatch@^3.0.2, minimatch@^3.0.4, minimatch@~3.0.2: +minimatch@3.0.4, minimatch@^3.0.4, minimatch@~3.0.2: version "3.0.4" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" + integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== dependencies: brace-expansion "^1.1.7" minimist@0.0.8: version "0.0.8" resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" + integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0= minimist@^1.1.3, minimist@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" +minimist@^1.2.5: + version "1.2.5" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" + integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== + minimist@~0.0.1: version "0.0.10" resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf" +minipass-collect@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/minipass-collect/-/minipass-collect-1.0.2.tgz#22b813bf745dc6edba2576b940022ad6edc8c617" + integrity sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA== + dependencies: + minipass "^3.0.0" + +minipass-flush@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/minipass-flush/-/minipass-flush-1.0.5.tgz#82e7135d7e89a50ffe64610a787953c4c4cbb373" + integrity sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw== + dependencies: + minipass "^3.0.0" + +minipass-pipeline@^1.2.2: + version "1.2.3" + resolved "https://registry.yarnpkg.com/minipass-pipeline/-/minipass-pipeline-1.2.3.tgz#55f7839307d74859d6e8ada9c3ebe72cec216a34" + integrity sha512-cFOknTvng5vqnwOpDsZTWhNll6Jf8o2x+/diplafmxpuIymAjzoOolZG0VvQf3V2HgqzJNhnuKHYp2BqDgz8IQ== + dependencies: + minipass "^3.0.0" + minipass@^2.2.1, minipass@^2.3.4, minipass@^2.3.5: version "2.3.5" resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.3.5.tgz#cacebe492022497f656b0f0f51e2682a9ed2d848" @@ -3777,12 +5597,35 @@ minipass@^2.2.1, minipass@^2.3.4, minipass@^2.3.5: safe-buffer "^5.1.2" yallist "^3.0.0" +minipass@^2.8.6: + version "2.9.0" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.9.0.tgz#e713762e7d3e32fed803115cf93e04bca9fcc9a6" + integrity sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg== + dependencies: + safe-buffer "^5.1.2" + yallist "^3.0.0" + +minipass@^3.0.0, minipass@^3.1.1: + version "3.1.3" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.1.3.tgz#7d42ff1f39635482e15f9cdb53184deebd5815fd" + integrity sha512-Mgd2GdMVzY+x3IJ+oHnVM+KG3lA5c8tnabyJKmHSaG2kAGpudxuOf8ToDkhumF7UzME7DecbQE9uOZhNm7PuJg== + dependencies: + yallist "^4.0.0" + minizlib@^1.1.1, minizlib@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.2.1.tgz#dd27ea6136243c7c880684e8672bb3a45fd9b614" dependencies: minipass "^2.2.1" +minizlib@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-2.1.0.tgz#fd52c645301ef09a63a2c209697c294c6ce02cf3" + integrity sha512-EzTZN/fjSvifSX0SlqUERCN39o6T40AMarPbv0MrarSFtIITCBh7bi+dU8nxGFHuqs9jdIAeoYoKuQAAASsPPA== + dependencies: + minipass "^3.0.0" + yallist "^4.0.0" + mississippi@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/mississippi/-/mississippi-3.0.0.tgz#ea0a3291f97e0b5e8776b363d5f0a12d94c67022" @@ -3805,19 +5648,25 @@ mixin-deep@^1.2.0: for-in "^1.0.2" is-extendable "^1.0.1" -mixin-object@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/mixin-object/-/mixin-object-2.0.1.tgz#4fb949441dab182540f1fe035ba60e1947a5e57e" - dependencies: - for-in "^0.1.3" - is-extendable "^0.1.1" - -mkdirp@0.5.x, "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.0: +"mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1: version "0.5.1" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" + integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM= dependencies: minimist "0.0.8" +mkdirp@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" + integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== + +mkdirp@~0.5.1, mkdirp@~0.5.x: + version "0.5.5" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def" + integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ== + dependencies: + minimist "^1.2.5" + moment-timezone@^0.5.23: version "0.5.26" resolved "https://registry.yarnpkg.com/moment-timezone/-/moment-timezone-0.5.26.tgz#c0267ca09ae84631aa3dc33f65bedbe6e8e0d772" @@ -3825,10 +5674,15 @@ moment-timezone@^0.5.23: dependencies: moment ">= 2.9.0" -"moment@>= 2.9.0", moment@^2.10.6, moment@^2.23.0: +"moment@>= 2.9.0", moment@^2.23.0: version "2.24.0" resolved "https://registry.yarnpkg.com/moment/-/moment-2.24.0.tgz#0d055d53f5052aa653c9f6eb68bb5d12bf5c2b5b" +moment@^2.10.2: + version "2.29.1" + resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.1.tgz#b2be769fa31940be9eeea6469c075e35006fa3d3" + integrity sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ== + move-concurrently@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/move-concurrently/-/move-concurrently-1.0.1.tgz#be2c005fda32e0b29af1f05d7c4b33214c701f92" @@ -3859,19 +5713,20 @@ multicast-dns@^6.0.1: dns-packet "^1.3.1" thunky "^1.0.2" -mute-stream@0.0.7: - version "0.0.7" - resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" - -nan@^2.10.0, nan@^2.9.2: - version "2.12.1" - resolved "https://registry.yarnpkg.com/nan/-/nan-2.12.1.tgz#7b1aa193e9aa86057e3c7bbd0ac448e770925552" +mute-stream@0.0.8: + version "0.0.8" + resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d" + integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA== -nan@^2.12.1: +nan@^2.12.1, nan@^2.13.2: version "2.14.0" resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.0.tgz#7818f722027b2459a86f0295d434d1fc2336c52c" integrity sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg== +nan@^2.9.2: + version "2.12.1" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.12.1.tgz#7b1aa193e9aa86057e3c7bbd0ac448e770925552" + nanomatch@^1.2.9: version "1.2.13" resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" @@ -3909,18 +5764,15 @@ neo-async@^2.5.0: version "2.6.0" resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.0.tgz#b9d15e4d71c6762908654b5183ed38b753340835" -next-tick@1: - version "1.0.0" - resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.0.0.tgz#ca86d1fe8828169b0120208e3dc8424b9db8342c" +neo-async@^2.6.1: + version "2.6.1" + resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.1.tgz#ac27ada66167fa8849a6addd837f6b189ad2081c" + integrity sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw== ng2-cookies@^1.0.12: version "1.0.12" resolved "https://registry.yarnpkg.com/ng2-cookies/-/ng2-cookies-1.0.12.tgz#3f3e613e0137b0649b705c678074b4bd08149ccc" -ngx-bootstrap@^3.1.4: - version "3.1.4" - resolved "https://registry.yarnpkg.com/ngx-bootstrap/-/ngx-bootstrap-3.1.4.tgz#5105c0227da3b51a1972d04efa1504a79474fd57" - ngx-clipboard@^12.1.0: version "12.1.0" resolved "https://registry.yarnpkg.com/ngx-clipboard/-/ngx-clipboard-12.1.0.tgz#41d10c9d031d5d6e854f8c21c85460c96685b10b" @@ -3929,11 +5781,12 @@ ngx-clipboard@^12.1.0: ngx-window-token "^2.0.0" tslib "^1.9.0" -ngx-infinite-scroll@^7.1.0: - version "7.1.0" - resolved "https://registry.yarnpkg.com/ngx-infinite-scroll/-/ngx-infinite-scroll-7.1.0.tgz#87dd5e0c596cd4795d2a487f7e30a0eabbb5e442" - integrity sha512-uytsKxUgGcPQjYMcf7FObcducQHkEsilPHZGJ3AMhOM4mtxP+YramnXXdyp2thEcuMgfNr9fBJjYnP0YcJciEQ== +ngx-infinite-scroll@^9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/ngx-infinite-scroll/-/ngx-infinite-scroll-9.0.0.tgz#8e648c266dd5744ed5aa68568a5479f398c94a2f" + integrity sha512-C8JhvrTip/AKv6f8oiB+GJjW+FGE3EPIc3Kk+v3MICGlW0nkOetyJDe/ejXr8tI8zwbNjbfvAKFRKenibDIW6w== dependencies: + "@scarf/scarf" "0.1.5" opencollective-postinstall "^2.0.2" ngx-moment@^3.0.1: @@ -3946,10 +5799,6 @@ ngx-order-pipe@^2.0.1: version "2.0.2" resolved "https://registry.yarnpkg.com/ngx-order-pipe/-/ngx-order-pipe-2.0.2.tgz#c670ea8008695d728661c1b81bf2d7f2a3792114" -ngx-page-scroll@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/ngx-page-scroll/-/ngx-page-scroll-5.0.1.tgz#e8439ef84694e910fcff70982ce3b5d8b494c5a6" - ngx-window-token@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/ngx-window-token/-/ngx-window-token-2.0.1.tgz#8f91221af4116aa9f49bb3f7a6f1111639884fba" @@ -3969,20 +5818,15 @@ node-fetch-npm@^2.0.2: json-parse-better-errors "^1.0.0" safe-buffer "^5.1.1" -node-fetch@^1.0.1: - version "1.7.3" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.7.3.tgz#980f6f72d85211a5347c6b2bc18c5b84c3eb47ef" - dependencies: - encoding "^0.1.11" - is-stream "^1.0.1" - -node-forge@0.7.5: - version "0.7.5" - resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.7.5.tgz#6c152c345ce11c52f465c2abd957e8639cd674df" +node-forge@0.9.0: + version "0.9.0" + resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.9.0.tgz#d624050edbb44874adca12bb9a52ec63cb782579" + integrity sha512-7ASaDa3pD+lJ3WvXFsxekJQelBKRpne+GOVbLbtHYdd7pFspyeuJHnWfLplGf3SwKGbfs/aYl5V/JCIaHVUKKQ== node-gyp@^3.8.0: version "3.8.0" resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-3.8.0.tgz#540304261c330e80d0d5edce253a68cb3964218c" + integrity sha512-3g8lYefrRRzvGeSowdJKAKyks8oUpLEd/DyPV4eMhVlhJ0aNaZqIrNUIPuEWWTAoPqyFkfGrM67MC69baqn6vA== dependencies: fstream "^1.0.0" glob "^7.0.3" @@ -3997,9 +5841,10 @@ node-gyp@^3.8.0: tar "^2.0.0" which "1" -node-libs-browser@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/node-libs-browser/-/node-libs-browser-2.2.0.tgz#c72f60d9d46de08a940dedbb25f3ffa2f9bbaa77" +node-libs-browser@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/node-libs-browser/-/node-libs-browser-2.2.1.tgz#b64f513d18338625f90346d27b0d235e631f6425" + integrity sha512-h/zcD8H9kaDZ9ALUWwlBUDo6TKF8a7qBSCSEGfjTVIYeqsioSKaAX+BN7NgiMGp6iSIXZ3PxgCu8KS3b71YK5Q== dependencies: assert "^1.1.1" browserify-zlib "^0.2.0" @@ -4011,7 +5856,7 @@ node-libs-browser@^2.0.0: events "^3.0.0" https-browserify "^1.0.0" os-browserify "^0.3.0" - path-browserify "0.0.0" + path-browserify "0.0.1" process "^0.11.10" punycode "^1.2.4" querystring-es3 "^0.2.0" @@ -4023,7 +5868,7 @@ node-libs-browser@^2.0.0: tty-browserify "0.0.0" url "^0.11.0" util "^0.11.0" - vm-browserify "0.0.4" + vm-browserify "^1.0.1" node-pre-gyp@^0.10.0: version "0.10.3" @@ -4056,16 +5901,22 @@ node-pre-gyp@^0.12.0: semver "^5.3.0" tar "^4" -node-releases@^1.1.14, node-releases@^1.1.23: - version "1.1.23" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.23.tgz#de7409f72de044a2fa59c097f436ba89c39997f0" - integrity sha512-uq1iL79YjfYC0WXoHbC/z28q/9pOl8kSHaXdWmAAc8No+bDwqkZbzIJz55g/MUsPgSGm9LZ7QSUbzTcH5tz47w== +node-releases@^1.1.50: + version "1.1.50" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.50.tgz#803c40d2c45db172d0410e4efec83aa8c6ad0592" + integrity sha512-lgAmPv9eYZ0bGwUYAKlr8MG6K4CvWliWqnkcT2P8mMAgVrH3lqfBPorFlxiG1pHQnqmavJZ9vbMXUTNyMLbrgQ== dependencies: - semver "^5.3.0" + semver "^6.3.0" -node-sass@^4.11.0: - version "4.11.0" - resolved "https://registry.yarnpkg.com/node-sass/-/node-sass-4.11.0.tgz#183faec398e9cbe93ba43362e2768ca988a6369a" +node-releases@^1.1.53: + version "1.1.56" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.56.tgz#bc054a417d316e3adac90eafb7e1932802f28705" + integrity sha512-EVo605FhWLygH8a64TjgpjyHYOihkxECwX1bHHr8tETJKWEiWS2YJjPbvsX2jFjnjTNEgBCmk9mLjKG1Mf11cw== + +node-sass@^4.12.0: + version "4.13.0" + resolved "https://registry.yarnpkg.com/node-sass/-/node-sass-4.13.0.tgz#b647288babdd6a1cb726de4545516b31f90da066" + integrity sha512-W1XBrvoJ1dy7VsvTAS5q1V45lREbTlZQqFbiHb3R3OTTCma0XBtuG6xZ6Z4506nR4lmHPTqVRwxT6KgtWC97CA== dependencies: async-foreach "^0.1.3" chalk "^1.1.1" @@ -4074,12 +5925,10 @@ node-sass@^4.11.0: get-stdin "^4.0.1" glob "^7.0.3" in-publish "^2.0.0" - lodash.assign "^4.2.0" - lodash.clonedeep "^4.3.2" - lodash.mergewith "^4.6.0" + lodash "^4.17.15" meow "^3.7.0" mkdirp "^0.5.1" - nan "^2.10.0" + nan "^2.13.2" node-gyp "^3.8.0" npmlog "^4.0.0" request "^2.88.0" @@ -4090,6 +5939,7 @@ node-sass@^4.11.0: "nopt@2 || 3": version "3.0.6" resolved "https://registry.yarnpkg.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9" + integrity sha1-xkZdvwirzU2zWTF/eaxopkayj/k= dependencies: abbrev "1" @@ -4100,7 +5950,7 @@ nopt@^4.0.1: abbrev "1" osenv "^0.1.4" -normalize-package-data@^2.0.0: +normalize-package-data@^2.0.0, normalize-package-data@^2.3.2, normalize-package-data@^2.3.4: version "2.5.0" resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA== @@ -4110,7 +5960,7 @@ normalize-package-data@^2.0.0: semver "2 || 3 || 4 || 5" validate-npm-package-license "^3.0.1" -normalize-package-data@^2.3.2, normalize-package-data@^2.3.4, normalize-package-data@^2.4.0: +normalize-package-data@^2.4.0: version "2.4.0" resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.4.0.tgz#12f95a307d58352075a04907b84ac8be98ac012f" dependencies: @@ -4125,7 +5975,7 @@ normalize-path@^2.1.1: dependencies: remove-trailing-separator "^1.0.1" -normalize-path@^3.0.0: +normalize-path@^3.0.0, normalize-path@~3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== @@ -4134,20 +5984,47 @@ normalize-range@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/normalize-range/-/normalize-range-0.1.2.tgz#2d10c06bdfd312ea9777695a4d28439456b75942" -normalize-url@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-2.0.1.tgz#835a9da1551fa26f70e92329069a23aa6574d7e6" - integrity sha512-D6MUW4K/VzoJ4rJ01JFKxDrtY1v9wrgzCX5f2qj/lzH1m/lW6MhUZFKerVsnyjOhOsYzI9Kqqak+10l4LvLpMw== +normalize-url@1.9.1: + version "1.9.1" + resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-1.9.1.tgz#2cc0d66b31ea23036458436e3620d85954c66c3c" + integrity sha1-LMDWazHqIwNkWENuNiDYWVTGbDw= dependencies: - prepend-http "^2.0.0" - query-string "^5.0.1" - sort-keys "^2.0.0" + object-assign "^4.0.1" + prepend-http "^1.0.0" + query-string "^4.1.0" + sort-keys "^1.0.0" + +normalize-url@^3.0.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-3.3.0.tgz#b2e1c4dc4f7c6d57743df733a4f5978d18650559" + integrity sha512-U+JJi7duF1o+u2pynbp2zXDW2/PADgC30f0GsHZtRh+HOcXHnw137TrNlyxxRvWW5fjKd3bcLHPxofWuCjaeZg== npm-bundled@^1.0.1: version "1.0.5" resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-1.0.5.tgz#3c1732b7ba936b3a10325aef616467c0ccbcc979" -npm-package-arg@6.1.0, npm-package-arg@^6.0.0, npm-package-arg@^6.1.0: +npm-install-checks@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/npm-install-checks/-/npm-install-checks-4.0.0.tgz#a37facc763a2fde0497ef2c6d0ac7c3fbe00d7b4" + integrity sha512-09OmyDkNLYwqKPOnbI8exiOZU2GVVmQp7tgez2BPi5OZC8M82elDAps7sxC4l//uSUtotWqoEIDwjRvWH4qz8w== + dependencies: + semver "^7.1.1" + +npm-normalize-package-bin@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz#6e79a41f23fd235c0623218228da7d9c23b8f6e2" + integrity sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA== + +npm-package-arg@8.0.1, npm-package-arg@^8.0.0: + version "8.0.1" + resolved "https://registry.yarnpkg.com/npm-package-arg/-/npm-package-arg-8.0.1.tgz#9d76f8d7667b2373ffda60bb801a27ef71e3e270" + integrity sha512-/h5Fm6a/exByzFSTm7jAyHbgOqErl9qSNJDQF32Si/ZzgwT2TERVxRxn3Jurw1wflgyVVAxnFR4fRHPM7y1ClQ== + dependencies: + hosted-git-info "^3.0.2" + semver "^7.0.0" + validate-npm-package-name "^3.0.0" + +npm-package-arg@^6.0.0, npm-package-arg@^6.1.0: version "6.1.0" resolved "https://registry.yarnpkg.com/npm-package-arg/-/npm-package-arg-6.1.0.tgz#15ae1e2758a5027efb4c250554b85a737db7fcc1" integrity sha512-zYbhP2k9DbJhA0Z3HKUePUgdB1x7MfIfKssC+WLPFMKTBZKpZh5m13PgexJjCq6KW7j17r0jHWcCpxEqnnncSA== @@ -4164,25 +6041,36 @@ npm-packlist@^1.1.12, npm-packlist@^1.1.6: ignore-walk "^3.0.1" npm-bundled "^1.0.1" -npm-pick-manifest@^2.2.3: - version "2.2.3" - resolved "https://registry.yarnpkg.com/npm-pick-manifest/-/npm-pick-manifest-2.2.3.tgz#32111d2a9562638bb2c8f2bf27f7f3092c8fae40" - integrity sha512-+IluBC5K201+gRU85vFlUwX3PFShZAbAgDNp2ewJdWMVSppdo/Zih0ul2Ecky/X7b51J7LrrUAP+XOmOCvYZqA== +npm-pick-manifest@6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/npm-pick-manifest/-/npm-pick-manifest-6.0.0.tgz#bfde7abe95f2670aed1629a3c18245ccb3cc2eb8" + integrity sha512-PdJpXMvjqt4nftNEDpCgjBUF8yI3Q3MyuAmVB9nemnnCg32F4BPL/JFBfdj8DubgHCYUFQhtLWmBPvdsFtjWMg== + dependencies: + npm-install-checks "^4.0.0" + npm-package-arg "^8.0.0" + semver "^7.0.0" + +npm-pick-manifest@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/npm-pick-manifest/-/npm-pick-manifest-3.0.2.tgz#f4d9e5fd4be2153e5f4e5f9b7be8dc419a99abb7" + integrity sha512-wNprTNg+X5nf+tDi+hbjdHhM4bX+mKqv6XmPh7B5eG+QY9VARfQPfCEH013H5GqfNj6ee8Ij2fg8yk0mzps1Vw== dependencies: figgy-pudding "^3.5.1" npm-package-arg "^6.0.0" semver "^5.4.1" -npm-registry-fetch@^3.8.0: - version "3.8.0" - resolved "https://registry.yarnpkg.com/npm-registry-fetch/-/npm-registry-fetch-3.8.0.tgz#aa7d9a7c92aff94f48dba0984bdef4bd131c88cc" +npm-registry-fetch@^4.0.0: + version "4.0.3" + resolved "https://registry.yarnpkg.com/npm-registry-fetch/-/npm-registry-fetch-4.0.3.tgz#3c2179e39e04f9348b1c2979545951d36bee8766" + integrity sha512-WGvUx0lkKFhu9MbiGFuT9nG2NpfQ+4dCJwRwwtK2HK5izJEvwDxMeUyqbuMS7N/OkpVCqDorV6rO5E4V9F8lJw== dependencies: JSONStream "^1.3.4" bluebird "^3.5.1" figgy-pudding "^3.4.1" - lru-cache "^4.1.3" - make-fetch-happen "^4.0.1" + lru-cache "^5.1.1" + make-fetch-happen "^5.0.0" npm-package-arg "^6.1.0" + safe-buffer "^5.2.0" npm-run-path@^2.0.0: version "2.0.2" @@ -4199,6 +6087,13 @@ npm-run-path@^2.0.0: gauge "~2.7.3" set-blocking "~2.0.0" +nth-check@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-1.0.2.tgz#b2bd295c37e3dd58a3bf0700376663ba4d9cf05c" + integrity sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg== + dependencies: + boolbase "~1.0.0" + num2fraction@^1.2.2: version "1.2.2" resolved "https://registry.yarnpkg.com/num2fraction/-/num2fraction-1.2.2.tgz#6f682b6a027a4e9ddfa4564cd2589d1d4e669ede" @@ -4206,18 +6101,17 @@ num2fraction@^1.2.2: number-is-nan@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" + integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0= oauth-sign@~0.9.0: version "0.9.0" resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" + integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== object-assign@^4.0.1, object-assign@^4.1.0: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" - -object-component@0.0.3: - version "0.0.3" - resolved "https://registry.yarnpkg.com/object-component/-/object-component-0.0.3.tgz#f0c69aa50efc95b866c186f400a33769cb2f1291" + integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= object-copy@^0.1.0: version "0.1.0" @@ -4227,10 +6121,20 @@ object-copy@^0.1.0: define-property "^0.2.5" kind-of "^3.0.3" +object-inspect@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.7.0.tgz#f4f6bd181ad77f006b5ece60bd0b6f398ff74a67" + integrity sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw== + object-keys@^1.0.11, object-keys@^1.0.12: version "1.0.12" resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.0.12.tgz#09c53855377575310cca62f55bb334abff7b3ed2" +object-keys@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" + integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== + object-visit@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb" @@ -4246,12 +6150,30 @@ object.assign@^4.1.0: has-symbols "^1.0.0" object-keys "^1.0.11" +object.getownpropertydescriptors@^2.0.3, object.getownpropertydescriptors@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.0.tgz#369bf1f9592d8ab89d712dced5cb81c7c5352649" + integrity sha512-Z53Oah9A3TdLoblT7VKJaTDdXdT+lQO+cNpKVnya5JDe9uLvzu1YyY1yFDFrcxrlRgWrEFH0jJtD/IbuwjcEVg== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.17.0-next.1" + object.pick@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747" dependencies: isobject "^3.0.1" +object.values@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.1.tgz#68a99ecde356b7e9295a3c5e0ce31dc8c953de5e" + integrity sha512-WTa54g2K8iu0kmS/us18jEmdv1a4Wi//BZ/DTVYEcH0XhLM5NYdpDHja3gt57VrZLcNAO2WGA+KpWsDBaHt6eA== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.17.0-next.1" + function-bind "^1.1.1" + has "^1.0.3" + obuf@^1.0.0, obuf@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/obuf/-/obuf-1.1.2.tgz#09bea3343d41859ebd446292d11c9d4db619084e" @@ -4270,21 +6192,24 @@ on-headers@~1.0.2: once@^1.3.0, once@^1.3.1, once@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= dependencies: wrappy "1" -onetime@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/onetime/-/onetime-2.0.1.tgz#067428230fd67443b2794b22bba528b6867962d4" +onetime@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.0.tgz#fff0f3c91617fe62bb50189636e99ac8a6df7be5" + integrity sha512-5NcSkPHhwTVFIQN+TUqXoS5+dlElHXdpAWu9I0HP20YOtIi+aZ0Ct82jdlILDxjLEAWwvm+qj1m6aEtsDVmm6Q== dependencies: - mimic-fn "^1.0.0" + mimic-fn "^2.1.0" -open@6.2.0: - version "6.2.0" - resolved "https://registry.yarnpkg.com/open/-/open-6.2.0.tgz#7cf92cb961b5d8498b071e64098bf5e27f57230c" - integrity sha512-Vxf6HJkwrqmvh9UAID3MnMYXntbTxKLOSfOnO7LJdzPf3NE3KQYFNV0/Lcz2VAndbRFil58XVCyh8tiX11fiYw== +open@7.0.3: + version "7.0.3" + resolved "https://registry.yarnpkg.com/open/-/open-7.0.3.tgz#db551a1af9c7ab4c7af664139930826138531c48" + integrity sha512-sP2ru2v0P290WFfv49Ap8MF6PkzGNnGlAwHweB4WR4mr5d2d0woiCluUeJ218w7/+PmoBy9JmYgD5A4mLcWOFA== dependencies: - is-wsl "^1.1.0" + is-docker "^2.0.0" + is-wsl "^2.1.1" opencollective-postinstall@^2.0.2: version "2.0.2" @@ -4305,9 +6230,24 @@ optimist@~0.6.0: minimist "~0.0.1" wordwrap "~0.0.2" +ora@4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/ora/-/ora-4.0.3.tgz#752a1b7b4be4825546a7a3d59256fa523b6b6d05" + integrity sha512-fnDebVFyz309A73cqCipVL1fBZewq4vwgSHfxh43vVy31mbyoQ8sCH3Oeaog/owYOs/lLlGVPCISQonTneg6Pg== + dependencies: + chalk "^3.0.0" + cli-cursor "^3.1.0" + cli-spinners "^2.2.0" + is-interactive "^1.0.0" + log-symbols "^3.0.0" + mute-stream "0.0.8" + strip-ansi "^6.0.0" + wcwidth "^1.0.1" + original@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/original/-/original-1.0.2.tgz#e442a61cffe1c5fd20a65f3261c26663b303f25f" + integrity sha512-hyBVl6iqqUOJ8FqRe+l/gS8H+kKYjrEndd5Pm1MfBtsEKA038HkkdbAl/72EAXGyonD/PFsvmVG+EvcIpliMBg== dependencies: url-parse "^1.4.3" @@ -4318,14 +6258,16 @@ os-browserify@^0.3.0: os-homedir@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" + integrity sha1-/7xJiDNuDoM94MFox+8VISGqf7M= os-locale@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-1.4.0.tgz#20f9f17ae29ed345e8bde583b13d2009803c14d9" + integrity sha1-IPnxeuKe00XoveWDsT0gCYA8FNk= dependencies: lcid "^1.0.0" -os-locale@^3.0.0, os-locale@^3.1.0: +os-locale@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-3.1.0.tgz#a802a6ee17f24c10483ab9935719cef4ed16bf1a" dependencies: @@ -4356,59 +6298,105 @@ p-is-promise@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/p-is-promise/-/p-is-promise-1.1.0.tgz#9c9456989e9f6588017b0434d56097675c3da05e" +p-limit@^1.1.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8" + integrity sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q== + dependencies: + p-try "^1.0.0" + p-limit@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.1.0.tgz#1d5a0d20fb12707c758a655f6bbc4386b5930d68" dependencies: p-try "^2.0.0" -p-limit@^2.1.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.2.0.tgz#417c9941e6027a9abcba5092dd2904e255b5fbc2" - integrity sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ== +p-limit@^2.2.0, p-limit@^2.2.1: + version "2.2.2" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.2.2.tgz#61279b67721f5287aa1c13a9a7fbbc48c9291b1e" + integrity sha512-WGR+xHecKTr7EbUEhyLSh5Dube9JtdiG78ufaeLxTgpudf/20KqyMioIUZJAezlTIi6evxuoUs9YXc11cU+yzQ== + dependencies: + p-try "^2.0.0" + +p-limit@^2.2.2: + version "2.3.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" + integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== dependencies: p-try "^2.0.0" +p-locate@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" + integrity sha1-IKAQOyIqcMj9OcwuWAaA893l7EM= + dependencies: + p-limit "^1.1.0" + p-locate@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4" dependencies: p-limit "^2.0.0" +p-locate@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" + integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== + dependencies: + p-limit "^2.2.0" + p-map@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/p-map/-/p-map-2.1.0.tgz#310928feef9c9ecc65b68b17693018a665cea175" integrity sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw== +p-map@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/p-map/-/p-map-3.0.0.tgz#d704d9af8a2ba684e2600d9a215983d4141a979d" + integrity sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ== + dependencies: + aggregate-error "^3.0.0" + +p-retry@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/p-retry/-/p-retry-3.0.1.tgz#316b4c8893e2c8dc1cfa891f406c4b422bebf328" + integrity sha512-XE6G4+YTTkT2a0UWb2kjZe8xNwf8bIbnqpc/IS/idOBVhyves0mK5OJgeocjx7q5pvX/6m23xuzVPYT1uGM73w== + dependencies: + retry "^0.12.0" + +p-try@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" + integrity sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M= + p-try@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.0.0.tgz#85080bb87c64688fa47996fe8f7dfbe8211760b1" -"pace@github:HubSpot/pace#v1.0.2": - version "1.0.2" - resolved "https://codeload.github.com/HubSpot/pace/tar.gz/c6846cbf6b928e9903b569269fa9fbf32f2554f4" - -pacote@9.5.0: - version "9.5.0" - resolved "https://registry.yarnpkg.com/pacote/-/pacote-9.5.0.tgz#85f3013a3f6dd51c108b0ccabd3de8102ddfaeda" - integrity sha512-aUplXozRbzhaJO48FaaeClmN+2Mwt741MC6M3bevIGZwdCaP7frXzbUOfOWa91FPHoLITzG0hYaKY363lxO3bg== +pacote@9.5.12: + version "9.5.12" + resolved "https://registry.yarnpkg.com/pacote/-/pacote-9.5.12.tgz#1e11dd7a8d736bcc36b375a9804d41bb0377bf66" + integrity sha512-BUIj/4kKbwWg4RtnBncXPJd15piFSVNpTzY0rysSr3VnMowTYgkGKcaHrbReepAkjTr8lH2CVWRi58Spg2CicQ== dependencies: bluebird "^3.5.3" - cacache "^11.3.2" + cacache "^12.0.2" + chownr "^1.1.2" figgy-pudding "^3.5.1" get-stream "^4.1.0" glob "^7.1.3" + infer-owner "^1.0.4" lru-cache "^5.1.1" - make-fetch-happen "^4.0.1" + make-fetch-happen "^5.0.0" minimatch "^3.0.4" minipass "^2.3.5" mississippi "^3.0.0" mkdirp "^0.5.1" normalize-package-data "^2.4.0" + npm-normalize-package-bin "^1.0.0" npm-package-arg "^6.1.0" npm-packlist "^1.1.12" - npm-pick-manifest "^2.2.3" - npm-registry-fetch "^3.8.0" + npm-pick-manifest "^3.0.0" + npm-registry-fetch "^4.0.0" osenv "^0.1.5" promise-inflight "^1.0.1" promise-retry "^1.1.1" @@ -4417,7 +6405,7 @@ pacote@9.5.0: safe-buffer "^5.1.2" semver "^5.6.0" ssri "^6.0.1" - tar "^4.4.8" + tar "^4.4.10" unique-filename "^1.1.1" which "^1.3.1" @@ -4447,6 +6435,7 @@ parse-asn1@^5.0.0: parse-json@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9" + integrity sha1-9ID0BDTvgHQfhGkJn43qGPVaTck= dependencies: error-ex "^1.2.0" @@ -4462,20 +6451,9 @@ parse5@4.0.0: resolved "https://registry.yarnpkg.com/parse5/-/parse5-4.0.0.tgz#6d78656e3da8d78b4ec0b906f7c08ef1dfe3f608" parse5@^5.0.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/parse5/-/parse5-5.1.0.tgz#c59341c9723f414c452975564c7c00a68d58acd2" - -parseqs@0.0.5: - version "0.0.5" - resolved "https://registry.yarnpkg.com/parseqs/-/parseqs-0.0.5.tgz#d5208a3738e46766e291ba2ea173684921a8b89d" - dependencies: - better-assert "~1.0.0" - -parseuri@0.0.5: - version "0.0.5" - resolved "https://registry.yarnpkg.com/parseuri/-/parseuri-0.0.5.tgz#80204a50d4dbb779bfdc6ebe2778d90e4bce320a" - dependencies: - better-assert "~1.0.0" + version "5.1.1" + resolved "https://registry.yarnpkg.com/parse5/-/parse5-5.1.1.tgz#f68e4e5ba1852ac2cadc00f4555fff6c2abb6178" + integrity sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug== parseurl@~1.3.2: version "1.3.2" @@ -4490,9 +6468,10 @@ pascalcase@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" -path-browserify@0.0.0: - version "0.0.0" - resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-0.0.0.tgz#a0b870729aae214005b7d5032ec2cbbb0fb4451a" +path-browserify@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-0.0.1.tgz#e6c4ddd7ed3aa27c68a20cc4e50e1a4ee83bbc4a" + integrity sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ== path-dirname@^1.0.0: version "1.0.2" @@ -4501,6 +6480,7 @@ path-dirname@^1.0.0: path-exists@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b" + integrity sha1-D+tsZPD8UY2adU3V77YscCJ2H0s= dependencies: pinkie-promise "^2.0.0" @@ -4508,9 +6488,15 @@ path-exists@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" +path-exists@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" + integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== + path-is-absolute@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= path-is-inside@^1.0.1, path-is-inside@^1.0.2: version "1.0.2" @@ -4531,6 +6517,7 @@ path-to-regexp@0.1.7: path-type@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441" + integrity sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE= dependencies: graceful-fs "^4.1.2" pify "^2.0.0" @@ -4555,6 +6542,17 @@ pbkdf2@^3.0.3: performance-now@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" + integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns= + +picomatch@^2.0.4, picomatch@^2.0.7: + version "2.2.1" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.1.tgz#21bac888b6ed8601f831ce7816e335bc779f0a4a" + integrity sha512-ISBaA8xQNmwELC7eOjqFKMESB2VIqt4PPDD0nsS95b/9dZXvVKOlz9keMSnoGGKcOHXfTvDD6WMaRoSc9UuhRA== + +picomatch@^2.2.1: + version "2.2.2" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.2.tgz#21f333e9b6b8eaff02468f5146ea406d345f4dad" + integrity sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg== pify@^2.0.0, pify@^2.3.0: version "2.3.0" @@ -4572,12 +6570,14 @@ pify@^4.0.1: pinkie-promise@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" + integrity sha1-ITXW36ejWMBprJsXh3YogihFD/o= dependencies: pinkie "^2.0.0" pinkie@^2.0.0: version "2.0.4" resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" + integrity sha1-clVrgM+g1IqXToDnckjoDtT3+HA= pkg-dir@^3.0.0: version "3.0.0" @@ -4585,28 +6585,103 @@ pkg-dir@^3.0.0: dependencies: find-up "^3.0.0" +pkg-dir@^4.1.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" + integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== + dependencies: + find-up "^4.0.0" + +pkg-up@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/pkg-up/-/pkg-up-2.0.0.tgz#c819ac728059a461cab1c3889a2be3c49a004d7f" + integrity sha1-yBmscoBZpGHKscOImivjxJoATX8= + dependencies: + find-up "^2.1.0" + please-wait@^0.0.5: version "0.0.5" resolved "https://registry.yarnpkg.com/please-wait/-/please-wait-0.0.5.tgz#67098ce6260e92e0809e2d3b7c23f1d167dad960" integrity sha1-ZwmM5iYOkuCAni07fCPx0Wfa2WA= +pngjs@^3.3.0: + version "3.4.0" + resolved "https://registry.yarnpkg.com/pngjs/-/pngjs-3.4.0.tgz#99ca7d725965fb655814eaf65f38f12bbdbf555f" + integrity sha512-NCrCHhWmnQklfH4MtJMRjZ2a8c80qXeMlQMv2uVp9ISJMTt562SbGd6n2oq0PaPgKm7Z6pL9E2UlLIhC+SHL3w== + popper.js@^1.14.3: version "1.14.6" resolved "https://registry.yarnpkg.com/popper.js/-/popper.js-1.14.6.tgz#ab20dd4edf9288b8b3b6531c47c361107b60b4b0" -portfinder@^1.0.20: - version "1.0.20" - resolved "https://registry.yarnpkg.com/portfinder/-/portfinder-1.0.20.tgz#bea68632e54b2e13ab7b0c4775e9b41bf270e44a" - integrity sha512-Yxe4mTyDzTd59PZJY4ojZR8F+E5e97iq2ZOHPz3HDgSvYC5siNad2tLooQ5y5QHyQhc3xVqvyk/eNA3wuoa7Sw== +portfinder@^1.0.25: + version "1.0.25" + resolved "https://registry.yarnpkg.com/portfinder/-/portfinder-1.0.25.tgz#254fd337ffba869f4b9d37edc298059cb4d35eca" + integrity sha512-6ElJnHBbxVA1XSLgBp7G1FiCkQdlqGzuF7DswL5tcea+E8UpuvPU7beVAjjRwCioTS9ZluNbu+ZyRvgTsmqEBg== dependencies: - async "^1.5.2" - debug "^2.2.0" - mkdirp "0.5.x" + async "^2.6.2" + debug "^3.1.1" + mkdirp "^0.5.1" posix-character-classes@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" +postcss-calc@^7.0.1: + version "7.0.2" + resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-7.0.2.tgz#504efcd008ca0273120568b0792b16cdcde8aac1" + integrity sha512-rofZFHUg6ZIrvRwPeFktv06GdbDYLcGqh9EwiMutZg+a0oePCCw1zHOEiji6LCpyRcjTREtPASuUqeAvYlEVvQ== + dependencies: + postcss "^7.0.27" + postcss-selector-parser "^6.0.2" + postcss-value-parser "^4.0.2" + +postcss-colormin@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/postcss-colormin/-/postcss-colormin-4.0.3.tgz#ae060bce93ed794ac71264f08132d550956bd381" + integrity sha512-WyQFAdDZpExQh32j0U0feWisZ0dmOtPl44qYmJKkq9xFWY3p+4qnRzCHeNrkeRhwPHz9bQ3mo0/yVkaply0MNw== + dependencies: + browserslist "^4.0.0" + color "^3.0.0" + has "^1.0.0" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + +postcss-convert-values@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/postcss-convert-values/-/postcss-convert-values-4.0.1.tgz#ca3813ed4da0f812f9d43703584e449ebe189a7f" + integrity sha512-Kisdo1y77KUC0Jmn0OXU/COOJbzM8cImvw1ZFsBgBgMgb1iL23Zs/LXRe3r+EZqM3vGYKdQ2YJVQ5VkJI+zEJQ== + dependencies: + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + +postcss-discard-comments@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-discard-comments/-/postcss-discard-comments-4.0.2.tgz#1fbabd2c246bff6aaad7997b2b0918f4d7af4033" + integrity sha512-RJutN259iuRf3IW7GZyLM5Sw4GLTOH8FmsXBnv8Ab/Tc2k4SR4qbV4DNbyyY4+Sjo362SyDmW2DQ7lBSChrpkg== + dependencies: + postcss "^7.0.0" + +postcss-discard-duplicates@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-discard-duplicates/-/postcss-discard-duplicates-4.0.2.tgz#3fe133cd3c82282e550fc9b239176a9207b784eb" + integrity sha512-ZNQfR1gPNAiXZhgENFfEglF93pciw0WxMkJeVmw8eF+JZBbMD7jp6C67GqJAXVZP2BWbOztKfbsdmMp/k8c6oQ== + dependencies: + postcss "^7.0.0" + +postcss-discard-empty@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/postcss-discard-empty/-/postcss-discard-empty-4.0.1.tgz#c8c951e9f73ed9428019458444a02ad90bb9f765" + integrity sha512-B9miTzbznhDjTfjvipfHoqbWKwd0Mj+/fL5s1QOz06wufguil+Xheo4XpOnc4NqKYBCNqqEzgPv2aPBIJLox0w== + dependencies: + postcss "^7.0.0" + +postcss-discard-overridden@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/postcss-discard-overridden/-/postcss-discard-overridden-4.0.1.tgz#652aef8a96726f029f5e3e00146ee7a4e755ff57" + integrity sha512-IYY2bEDD7g1XM1IDEsUT4//iEYCxAmP5oDSFMVU/JVvT7gh+l4fmjciLqGgwjdWpQIdb0Che2VX00QObS5+cTg== + dependencies: + postcss "^7.0.0" + postcss-import@12.0.1: version "12.0.1" resolved "https://registry.yarnpkg.com/postcss-import/-/postcss-import-12.0.1.tgz#cf8c7ab0b5ccab5649024536e565f841928b7153" @@ -4633,11 +6708,272 @@ postcss-loader@3.0.0: postcss-load-config "^2.0.0" schema-utils "^1.0.0" -postcss-value-parser@^3.2.3, postcss-value-parser@^3.3.1: +postcss-merge-longhand@^4.0.11: + version "4.0.11" + resolved "https://registry.yarnpkg.com/postcss-merge-longhand/-/postcss-merge-longhand-4.0.11.tgz#62f49a13e4a0ee04e7b98f42bb16062ca2549e24" + integrity sha512-alx/zmoeXvJjp7L4mxEMjh8lxVlDFX1gqWHzaaQewwMZiVhLo42TEClKaeHbRf6J7j82ZOdTJ808RtN0ZOZwvw== + dependencies: + css-color-names "0.0.4" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + stylehacks "^4.0.0" + +postcss-merge-rules@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/postcss-merge-rules/-/postcss-merge-rules-4.0.3.tgz#362bea4ff5a1f98e4075a713c6cb25aefef9a650" + integrity sha512-U7e3r1SbvYzO0Jr3UT/zKBVgYYyhAz0aitvGIYOYK5CPmkNih+WDSsS5tvPrJ8YMQYlEMvsZIiqmn7HdFUaeEQ== + dependencies: + browserslist "^4.0.0" + caniuse-api "^3.0.0" + cssnano-util-same-parent "^4.0.0" + postcss "^7.0.0" + postcss-selector-parser "^3.0.0" + vendors "^1.0.0" + +postcss-minify-font-values@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-minify-font-values/-/postcss-minify-font-values-4.0.2.tgz#cd4c344cce474343fac5d82206ab2cbcb8afd5a6" + integrity sha512-j85oO6OnRU9zPf04+PZv1LYIYOprWm6IA6zkXkrJXyRveDEuQggG6tvoy8ir8ZwjLxLuGfNkCZEQG7zan+Hbtg== + dependencies: + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + +postcss-minify-gradients@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-minify-gradients/-/postcss-minify-gradients-4.0.2.tgz#93b29c2ff5099c535eecda56c4aa6e665a663471" + integrity sha512-qKPfwlONdcf/AndP1U8SJ/uzIJtowHlMaSioKzebAXSG4iJthlWC9iSWznQcX4f66gIWX44RSA841HTHj3wK+Q== + dependencies: + cssnano-util-get-arguments "^4.0.0" + is-color-stop "^1.0.0" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + +postcss-minify-params@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-minify-params/-/postcss-minify-params-4.0.2.tgz#6b9cef030c11e35261f95f618c90036d680db874" + integrity sha512-G7eWyzEx0xL4/wiBBJxJOz48zAKV2WG3iZOqVhPet/9geefm/Px5uo1fzlHu+DOjT+m0Mmiz3jkQzVHe6wxAWg== + dependencies: + alphanum-sort "^1.0.0" + browserslist "^4.0.0" + cssnano-util-get-arguments "^4.0.0" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + uniqs "^2.0.0" + +postcss-minify-selectors@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-minify-selectors/-/postcss-minify-selectors-4.0.2.tgz#e2e5eb40bfee500d0cd9243500f5f8ea4262fbd8" + integrity sha512-D5S1iViljXBj9kflQo4YutWnJmwm8VvIsU1GeXJGiG9j8CIg9zs4voPMdQDUmIxetUOh60VilsNzCiAFTOqu3g== + dependencies: + alphanum-sort "^1.0.0" + has "^1.0.0" + postcss "^7.0.0" + postcss-selector-parser "^3.0.0" + +postcss-modules-extract-imports@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/postcss-modules-extract-imports/-/postcss-modules-extract-imports-2.0.0.tgz#818719a1ae1da325f9832446b01136eeb493cd7e" + integrity sha512-LaYLDNS4SG8Q5WAWqIJgdHPJrDDr/Lv775rMBFUbgjTz6j34lUznACHcdRWroPvXANP2Vj7yNK57vp9eFqzLWQ== + dependencies: + postcss "^7.0.5" + +postcss-modules-local-by-default@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-3.0.2.tgz#e8a6561be914aaf3c052876377524ca90dbb7915" + integrity sha512-jM/V8eqM4oJ/22j0gx4jrp63GSvDH6v86OqyTHHUvk4/k1vceipZsaymiZ5PvocqZOl5SFHiFJqjs3la0wnfIQ== + dependencies: + icss-utils "^4.1.1" + postcss "^7.0.16" + postcss-selector-parser "^6.0.2" + postcss-value-parser "^4.0.0" + +postcss-modules-scope@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/postcss-modules-scope/-/postcss-modules-scope-2.2.0.tgz#385cae013cc7743f5a7d7602d1073a89eaae62ee" + integrity sha512-YyEgsTMRpNd+HmyC7H/mh3y+MeFWevy7V1evVhJWewmMbjDHIbZbOXICC2y+m1xI1UVfIT1HMW/O04Hxyu9oXQ== + dependencies: + postcss "^7.0.6" + postcss-selector-parser "^6.0.0" + +postcss-modules-values@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/postcss-modules-values/-/postcss-modules-values-3.0.0.tgz#5b5000d6ebae29b4255301b4a3a54574423e7f10" + integrity sha512-1//E5jCBrZ9DmRX+zCtmQtRSV6PV42Ix7Bzj9GbwJceduuf7IqP8MgeTXuRDHOWj2m0VzZD5+roFWDuU8RQjcg== + dependencies: + icss-utils "^4.0.0" + postcss "^7.0.6" + +postcss-normalize-charset@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/postcss-normalize-charset/-/postcss-normalize-charset-4.0.1.tgz#8b35add3aee83a136b0471e0d59be58a50285dd4" + integrity sha512-gMXCrrlWh6G27U0hF3vNvR3w8I1s2wOBILvA87iNXaPvSNo5uZAMYsZG7XjCUf1eVxuPfyL4TJ7++SGZLc9A3g== + dependencies: + postcss "^7.0.0" + +postcss-normalize-display-values@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-normalize-display-values/-/postcss-normalize-display-values-4.0.2.tgz#0dbe04a4ce9063d4667ed2be476bb830c825935a" + integrity sha512-3F2jcsaMW7+VtRMAqf/3m4cPFhPD3EFRgNs18u+k3lTJJlVe7d0YPO+bnwqo2xg8YiRpDXJI2u8A0wqJxMsQuQ== + dependencies: + cssnano-util-get-match "^4.0.0" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + +postcss-normalize-positions@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-normalize-positions/-/postcss-normalize-positions-4.0.2.tgz#05f757f84f260437378368a91f8932d4b102917f" + integrity sha512-Dlf3/9AxpxE+NF1fJxYDeggi5WwV35MXGFnnoccP/9qDtFrTArZ0D0R+iKcg5WsUd8nUYMIl8yXDCtcrT8JrdA== + dependencies: + cssnano-util-get-arguments "^4.0.0" + has "^1.0.0" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + +postcss-normalize-repeat-style@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-4.0.2.tgz#c4ebbc289f3991a028d44751cbdd11918b17910c" + integrity sha512-qvigdYYMpSuoFs3Is/f5nHdRLJN/ITA7huIoCyqqENJe9PvPmLhNLMu7QTjPdtnVf6OcYYO5SHonx4+fbJE1+Q== + dependencies: + cssnano-util-get-arguments "^4.0.0" + cssnano-util-get-match "^4.0.0" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + +postcss-normalize-string@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-normalize-string/-/postcss-normalize-string-4.0.2.tgz#cd44c40ab07a0c7a36dc5e99aace1eca4ec2690c" + integrity sha512-RrERod97Dnwqq49WNz8qo66ps0swYZDSb6rM57kN2J+aoyEAJfZ6bMx0sx/F9TIEX0xthPGCmeyiam/jXif0eA== + dependencies: + has "^1.0.0" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + +postcss-normalize-timing-functions@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-4.0.2.tgz#8e009ca2a3949cdaf8ad23e6b6ab99cb5e7d28d9" + integrity sha512-acwJY95edP762e++00Ehq9L4sZCEcOPyaHwoaFOhIwWCDfik6YvqsYNxckee65JHLKzuNSSmAdxwD2Cud1Z54A== + dependencies: + cssnano-util-get-match "^4.0.0" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + +postcss-normalize-unicode@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/postcss-normalize-unicode/-/postcss-normalize-unicode-4.0.1.tgz#841bd48fdcf3019ad4baa7493a3d363b52ae1cfb" + integrity sha512-od18Uq2wCYn+vZ/qCOeutvHjB5jm57ToxRaMeNuf0nWVHaP9Hua56QyMF6fs/4FSUnVIw0CBPsU0K4LnBPwYwg== + dependencies: + browserslist "^4.0.0" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + +postcss-normalize-url@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/postcss-normalize-url/-/postcss-normalize-url-4.0.1.tgz#10e437f86bc7c7e58f7b9652ed878daaa95faae1" + integrity sha512-p5oVaF4+IHwu7VpMan/SSpmpYxcJMtkGppYf0VbdH5B6hN8YNmVyJLuY9FmLQTzY3fag5ESUUHDqM+heid0UVA== + dependencies: + is-absolute-url "^2.0.0" + normalize-url "^3.0.0" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + +postcss-normalize-whitespace@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-normalize-whitespace/-/postcss-normalize-whitespace-4.0.2.tgz#bf1d4070fe4fcea87d1348e825d8cc0c5faa7d82" + integrity sha512-tO8QIgrsI3p95r8fyqKV+ufKlSHh9hMJqACqbv2XknufqEDhDvbguXGBBqxw9nsQoXWf0qOqppziKJKHMD4GtA== + dependencies: + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + +postcss-ordered-values@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/postcss-ordered-values/-/postcss-ordered-values-4.1.2.tgz#0cf75c820ec7d5c4d280189559e0b571ebac0eee" + integrity sha512-2fCObh5UanxvSxeXrtLtlwVThBvHn6MQcu4ksNT2tsaV2Fg76R2CV98W7wNSlX+5/pFwEyaDwKLLoEV7uRybAw== + dependencies: + cssnano-util-get-arguments "^4.0.0" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + +postcss-reduce-initial@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/postcss-reduce-initial/-/postcss-reduce-initial-4.0.3.tgz#7fd42ebea5e9c814609639e2c2e84ae270ba48df" + integrity sha512-gKWmR5aUulSjbzOfD9AlJiHCGH6AEVLaM0AV+aSioxUDd16qXP1PCh8d1/BGVvpdWn8k/HiK7n6TjeoXN1F7DA== + dependencies: + browserslist "^4.0.0" + caniuse-api "^3.0.0" + has "^1.0.0" + postcss "^7.0.0" + +postcss-reduce-transforms@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-reduce-transforms/-/postcss-reduce-transforms-4.0.2.tgz#17efa405eacc6e07be3414a5ca2d1074681d4e29" + integrity sha512-EEVig1Q2QJ4ELpJXMZR8Vt5DQx8/mo+dGWSR7vWXqcob2gQLyQGsionYcGKATXvQzMPn6DSN1vTN7yFximdIAg== + dependencies: + cssnano-util-get-match "^4.0.0" + has "^1.0.0" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + +postcss-selector-parser@^3.0.0: + version "3.1.2" + resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-3.1.2.tgz#b310f5c4c0fdaf76f94902bbaa30db6aa84f5270" + integrity sha512-h7fJ/5uWuRVyOtkO45pnt1Ih40CEleeyCHzipqAZO2e5H20g25Y48uYnFUiShvY4rZWNJ/Bib/KVPmanaCtOhA== + dependencies: + dot-prop "^5.2.0" + indexes-of "^1.0.1" + uniq "^1.0.1" + +postcss-selector-parser@^6.0.0, postcss-selector-parser@^6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.2.tgz#934cf799d016c83411859e09dcecade01286ec5c" + integrity sha512-36P2QR59jDTOAiIkqEprfJDsoNrvwFei3eCqKd1Y0tUsBimsq39BLp7RD+JWny3WgB1zGhJX8XVePwm9k4wdBg== + dependencies: + cssesc "^3.0.0" + indexes-of "^1.0.1" + uniq "^1.0.1" + +postcss-svgo@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-svgo/-/postcss-svgo-4.0.2.tgz#17b997bc711b333bab143aaed3b8d3d6e3d38258" + integrity sha512-C6wyjo3VwFm0QgBy+Fu7gCYOkCmgmClghO+pjcxvrcBKtiKt0uCF+hvbMO1fyv5BMImRK90SMb+dwUnfbGd+jw== + dependencies: + is-svg "^3.0.0" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + svgo "^1.0.0" + +postcss-unique-selectors@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/postcss-unique-selectors/-/postcss-unique-selectors-4.0.1.tgz#9446911f3289bfd64c6d680f073c03b1f9ee4bac" + integrity sha512-+JanVaryLo9QwZjKrmJgkI4Fn8SBgRO6WXQBJi7KiAVPlmxikB5Jzc4EvXMT2H0/m0RjrVVm9rGNhZddm/8Spg== + dependencies: + alphanum-sort "^1.0.0" + postcss "^7.0.0" + uniqs "^2.0.0" + +postcss-value-parser@^3.0.0, postcss-value-parser@^3.2.3: version "3.3.1" resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz#9ff822547e2893213cf1c30efa51ac5fd1ba8281" -postcss@7.0.14, postcss@^7.0.0, postcss@^7.0.1: +postcss-value-parser@^4.0.0: + version "4.0.3" + resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.0.3.tgz#651ff4593aa9eda8d5d0d66593a2417aeaeb325d" + integrity sha512-N7h4pG+Nnu5BEIzyeaaIYWs0LI5XC40OrRh5L60z0QjFsqGWcHcbkBvpe1WYpcIS9yQ8sOi/vIPt1ejQCrMVrg== + +postcss-value-parser@^4.0.2, postcss-value-parser@^4.0.3: + version "4.1.0" + resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.1.0.tgz#443f6a20ced6481a2bda4fa8532a6e55d789a2cb" + integrity sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ== + +postcss@7.0.27: + version "7.0.27" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.27.tgz#cc67cdc6b0daa375105b7c424a85567345fc54d9" + integrity sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ== + dependencies: + chalk "^2.4.2" + source-map "^0.6.1" + supports-color "^6.1.0" + +postcss@^7.0.0, postcss@^7.0.1: version "7.0.14" resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.14.tgz#4527ed6b1ca0d82c53ce5ec1a2041c2346bbd6e5" dependencies: @@ -4645,36 +6981,45 @@ postcss@7.0.14, postcss@^7.0.0, postcss@^7.0.1: source-map "^0.6.1" supports-color "^6.1.0" -postcss@^7.0.14: - version "7.0.17" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.17.tgz#4da1bdff5322d4a0acaab4d87f3e782436bad31f" - integrity sha512-546ZowA+KZ3OasvQZHsbuEpysvwTZNGJv9EfyCQdsIDltPSWHAeTQ5fQy/Npi2ZDtLI3zs7Ps/p6wThErhm9fQ== +postcss@^7.0.14, postcss@^7.0.16, postcss@^7.0.26, postcss@^7.0.27, postcss@^7.0.5, postcss@^7.0.6: + version "7.0.30" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.30.tgz#cc9378beffe46a02cbc4506a0477d05fcea9a8e2" + integrity sha512-nu/0m+NtIzoubO+xdAlwZl/u5S5vi/y6BCsoL8D+8IxsD3XvBS8X4YEADNIVXKVuQvduiucnRv+vPIqj56EGMQ== dependencies: chalk "^2.4.2" source-map "^0.6.1" supports-color "^6.1.0" -prepend-http@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-2.0.0.tgz#e92434bfa5ea8c19f41cdfd401d741a3c819d897" - integrity sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc= +prepend-http@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc" + integrity sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw= -primeicons@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/primeicons/-/primeicons-1.0.0.tgz#90061f168ef6227f21f0a7db8204ffa85cd27aec" - integrity sha512-p/hzIjUVccW4eJPhuORHI3AUkDpqfvCQVrjxbFEejnTEdWY4C8fomVfjiaA9jCu83fSQnBHuRIGB96iAR8R6uA== +primeicons@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/primeicons/-/primeicons-4.0.0.tgz#a3594b3af213dcf8c4c3d6fc99eea05b7c92f57c" + integrity sha512-JQBIswGSItn8I0Pq21RchENpKJxSi1MjfBDfggMQpXtoKNKblJoHmol/7tCV3CAV2Dlb94ht8TD8qdIAW01pGg== -primeng@^7.0.3: - version "7.0.4" - resolved "https://registry.yarnpkg.com/primeng/-/primeng-7.0.4.tgz#4aee9b0dfd61d23f474f80e420f4375be583abc9" +primeng@^10.0.3: + version "10.0.3" + resolved "https://registry.yarnpkg.com/primeng/-/primeng-10.0.3.tgz#e9d0ea425b9c5023bc9eef2cb014941939d0c35e" + integrity sha512-Nsiwpmy3RlFPBlxabdzeAYxFn4fXEyZjj7iAi1X5J4RRGD7NoB67+NbnOInE1rXTnNVHYxCca91OvaNiHSWWrg== + dependencies: + tslib "^2.0.0" + +private@^0.1.8: + version "0.1.8" + resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff" + integrity sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg== process-nextick-args@~1.0.6: version "1.0.7" resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz#150e20b756590ad3f91093f25a4f2ad8bff30ba3" process-nextick-args@~2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.0.tgz#a37d732f4271b4ab1ad070d35508e8290788ffaa" + version "2.0.1" + resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" + integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== process@^0.11.10: version "0.11.10" @@ -4738,10 +7083,12 @@ prr@~1.0.1: pseudomap@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" + integrity sha1-8FKijacOYYkX7wqKw0wa5aaChrM= -psl@^1.1.24: - version "1.1.31" - resolved "https://registry.yarnpkg.com/psl/-/psl-1.1.31.tgz#e9aa86d0101b5b105cbe93ac6b784cd547276184" +psl@^1.1.24, psl@^1.1.28: + version "1.7.0" + resolved "https://registry.yarnpkg.com/psl/-/psl-1.7.0.tgz#f1c4c47a8ef97167dea5d6bbf4816d736e884a3c" + integrity sha512-5NsSEDv8zY70ScRnOTn7bK7eanl2MvFrOrS/R6x+dBt5g1ghnj9Zv90kO8GwT8gxcu2ANyFprnFYB85IogIJOQ== public-encrypt@^4.0.0: version "4.0.3" @@ -4783,18 +7130,31 @@ punycode@1.3.2: punycode@^1.2.4, punycode@^1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" + integrity sha1-wNWmOycYgArY4esPpSachN1BhF4= -punycode@^2.1.0: +punycode@^2.1.0, punycode@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" + integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== q@1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/q/-/q-1.4.1.tgz#55705bcd93c5f3673530c2c2cbc0c2b3addc286e" -q@^1.4.1: +q@^1.1.2, q@^1.4.1: version "1.5.1" resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7" + integrity sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc= + +qrcode@1.4.2: + version "1.4.2" + resolved "https://registry.yarnpkg.com/qrcode/-/qrcode-1.4.2.tgz#e7c82a60140916d666541043bd2b0b72ee4e38a6" + integrity sha512-eR6RgxFYPDFH+zFLTJKtoNP/RlsHANQb52AUmQ2bGDPMuUw7jJb0F+DNEgx7qQGIElrbFxWYMc0/B91zLZPF9Q== + dependencies: + dijkstrajs "^1.0.1" + isarray "^2.0.1" + pngjs "^3.3.0" + yargs "^13.2.4" qs@6.7.0, qs@^6.5.1: version "6.7.0" @@ -4804,13 +7164,13 @@ qs@6.7.0, qs@^6.5.1: qs@~6.5.2: version "6.5.2" resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" + integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA== -query-string@^5.0.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/query-string/-/query-string-5.1.1.tgz#a78c012b71c17e05f2e3fa2319dd330682efb3cb" - integrity sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw== +query-string@^4.1.0: + version "4.3.4" + resolved "https://registry.yarnpkg.com/query-string/-/query-string-4.3.4.tgz#bbb693b9ca915c232515b228b1a02b609043dbeb" + integrity sha1-u7aTucqRXCMlFbIosaArYJBD2+s= dependencies: - decode-uri-component "^0.2.0" object-assign "^4.1.0" strict-uri-encode "^1.0.0" @@ -4822,9 +7182,10 @@ querystring@0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" -querystringify@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.1.0.tgz#7ded8dfbf7879dcc60d0a644ac6754b283ad17ef" +querystringify@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.1.1.tgz#60e5a5fd64a7f8bfa4d2ab2ed6fdf4c85bad154e" + integrity sha512-w7fLxIRCRT7U8Qu53jQnJyPkYZIaR4n5151KMfcJlO/A9397Wxb1amJvROTK6TOnp7PfoAmg/qXiNHI+08jRfA== randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5: version "2.0.6" @@ -4839,10 +7200,6 @@ randomfill@^1.0.3: randombytes "^2.0.5" safe-buffer "^5.1.0" -range-parser@^1.0.3: - version "1.2.0" - resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.0.tgz#f49be6b487894ddc40dcc94a322f611092e00d5e" - range-parser@^1.2.1, range-parser@~1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" @@ -4858,13 +7215,13 @@ raw-body@2.4.0: iconv-lite "0.4.24" unpipe "1.0.0" -raw-loader@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/raw-loader/-/raw-loader-1.0.0.tgz#3f9889e73dadbda9a424bce79809b4133ad46405" - integrity sha512-Uqy5AqELpytJTRxYT4fhltcKPj0TyaEpzJDcGz7DFJi+pQOOi3GjR/DOdxTkTsF+NzhnldIoG6TORaBlInUuqA== +raw-loader@4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/raw-loader/-/raw-loader-4.0.0.tgz#d639c40fb9d72b5c7f8abc1fb2ddb25b29d3d540" + integrity sha512-iINUOYvl1cGEmfoaLjnZXt4bKfT2LJnZZib5N/LLyAphC+Dd11vNP9CNVb38j+SAJpFI1uo8j9frmih53ASy7Q== dependencies: - loader-utils "^1.1.0" - schema-utils "^1.0.0" + loader-utils "^1.2.3" + schema-utils "^2.5.0" rc@^1.2.7: version "1.2.8" @@ -4893,20 +7250,19 @@ read-package-json@^2.0.0: optionalDependencies: graceful-fs "^4.1.2" -read-package-tree@5.2.2: - version "5.2.2" - resolved "https://registry.yarnpkg.com/read-package-tree/-/read-package-tree-5.2.2.tgz#4b6a0ef2d943c1ea36a578214c9a7f6b7424f7a8" - integrity sha512-rW3XWUUkhdKmN2JKB4FL563YAgtINifso5KShykufR03nJ5loGFlkUMe1g/yxmqX073SoYYTsgXu7XdDinKZuA== +read-package-tree@5.3.1: + version "5.3.1" + resolved "https://registry.yarnpkg.com/read-package-tree/-/read-package-tree-5.3.1.tgz#a32cb64c7f31eb8a6f31ef06f9cedf74068fe636" + integrity sha512-mLUDsD5JVtlZxjSlPPx1RETkNjjvQYuweKwNVt1Sn8kP5Jh44pvYuUHCp6xSVDZWbNxVxG5lyZJ921aJH61sTw== dependencies: - debuglog "^1.0.1" - dezalgo "^1.0.0" - once "^1.3.0" read-package-json "^2.0.0" readdir-scoped-modules "^1.0.0" + util-promisify "^2.1.0" read-pkg-up@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02" + integrity sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI= dependencies: find-up "^1.0.0" read-pkg "^1.0.0" @@ -4914,6 +7270,7 @@ read-pkg-up@^1.0.1: read-pkg@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-1.1.0.tgz#f5ffaa5ecd29cb31c0474bca7d756b6bb29e3f28" + integrity sha1-9f+qXs0pyzHAR0vKfXVra7KePyg= dependencies: load-json-file "^1.0.0" normalize-package-data "^2.3.2" @@ -4922,6 +7279,7 @@ read-pkg@^1.0.0: "readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.4, readable-stream@^2.0.6, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.3, readable-stream@^2.3.5, readable-stream@^2.3.6, readable-stream@~2.3.6: version "2.3.6" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf" + integrity sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw== dependencies: core-util-is "~1.0.0" inherits "~2.0.3" @@ -4969,15 +7327,24 @@ readdirp@^2.0.0, readdirp@^2.2.1: micromatch "^3.1.10" readable-stream "^2.0.2" -rechoir@^0.6.2: - version "0.6.2" - resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384" +readdirp@~3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.3.0.tgz#984458d13a1e42e2e9f5841b129e162f369aff17" + integrity sha512-zz0pAkSPOXXm1viEwygWIPSPkcBYjW1xU5j/JBh5t9bGCJwa6f9+BJa6VaB2g+b55yVrmXzqkyLf4xaWYM0IkQ== + dependencies: + picomatch "^2.0.7" + +readdirp@~3.4.0: + version "3.4.0" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.4.0.tgz#9fdccdf9e9155805449221ac645e8303ab5b9ada" + integrity sha512-0xe001vZBnJEK+uKcj8qOhyAKPzIT+gStxWr3LCB0DwcXR5NZJ3IaC+yGnHCYzB/S7ov3m3EEbZI2zeNvX+hGQ== dependencies: - resolve "^1.1.6" + picomatch "^2.2.1" redent@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/redent/-/redent-1.0.0.tgz#cf916ab1fd5f1f16dfb20822dd6ec7f730c2afde" + integrity sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94= dependencies: indent-string "^2.1.0" strip-indent "^1.0.1" @@ -4986,13 +7353,36 @@ reflect-metadata@^0.1.2: version "0.1.13" resolved "https://registry.yarnpkg.com/reflect-metadata/-/reflect-metadata-0.1.13.tgz#67ae3ca57c972a2aa1642b10fe363fe32d49dc08" -regenerate@^1.2.1: +regenerate-unicode-properties@^8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-8.1.0.tgz#ef51e0f0ea4ad424b77bf7cb41f3e015c70a3f0e" + integrity sha512-LGZzkgtLY79GeXLm8Dp0BVLdQlWICzBnJz/ipWUgo59qBaZ+BHtq51P2q1uVZlppMuUAT37SDk39qUbjTWB7bA== + dependencies: + regenerate "^1.4.0" + +regenerate-unicode-properties@^8.2.0: + version "8.2.0" + resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-8.2.0.tgz#e5de7111d655e7ba60c057dbe9ff37c87e65cdec" + integrity sha512-F9DjY1vKLo/tPePDycuH3dn9H1OTPIkVD9Kz4LODu+F2C75mgjAJ7x/gwy6ZcSNRAAkhNlJSOHRe8k3p+K9WhA== + dependencies: + regenerate "^1.4.0" + +regenerate@^1.2.1, regenerate@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.0.tgz#4a856ec4b56e4077c557589cae85e7a4c8869a11" -regenerator-runtime@^0.11.0: - version "0.11.1" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9" +regenerator-runtime@0.13.5, regenerator-runtime@^0.13.4: + version "0.13.5" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.5.tgz#d878a1d094b4306d10b9096484b33ebd55e26697" + integrity sha512-ZS5w8CpKFinUzOwW3c83oPeVXoNsrLsaCoLtJvAClH135j/R77RuymhiSErhm2lKcwSCIpmvIWSbDkIfAqKQlA== + +regenerator-transform@^0.14.2: + version "0.14.4" + resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.14.4.tgz#5266857896518d1616a78a0479337a30ea974cc7" + integrity sha512-EaJaKPBI9GvKpvUz2mz4fhx7WPgvwRLY9v3hlNHWmAuJHI13T4nwKnNvm5RWJzEdnI5g5UwtOww+S8IdoUC2bw== + dependencies: + "@babel/runtime" "^7.8.4" + private "^0.1.8" regex-not@^1.0.0, regex-not@^1.0.2: version "1.0.2" @@ -5009,16 +7399,59 @@ regexpu-core@^1.0.0: regjsgen "^0.2.0" regjsparser "^0.1.4" +regexpu-core@^4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-4.6.0.tgz#2037c18b327cfce8a6fea2a4ec441f2432afb8b6" + integrity sha512-YlVaefl8P5BnFYOITTNzDvan1ulLOiXJzCNZxduTIosN17b87h3bvG9yHMoHaRuo88H4mQ06Aodj5VtYGGGiTg== + dependencies: + regenerate "^1.4.0" + regenerate-unicode-properties "^8.1.0" + regjsgen "^0.5.0" + regjsparser "^0.6.0" + unicode-match-property-ecmascript "^1.0.4" + unicode-match-property-value-ecmascript "^1.1.0" + +regexpu-core@^4.7.0: + version "4.7.0" + resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-4.7.0.tgz#fcbf458c50431b0bb7b45d6967b8192d91f3d938" + integrity sha512-TQ4KXRnIn6tz6tjnrXEkD/sshygKH/j5KzK86X8MkeHyZ8qst/LZ89j3X4/8HEIfHANTFIP/AbXakeRhWIl5YQ== + dependencies: + regenerate "^1.4.0" + regenerate-unicode-properties "^8.2.0" + regjsgen "^0.5.1" + regjsparser "^0.6.4" + unicode-match-property-ecmascript "^1.0.4" + unicode-match-property-value-ecmascript "^1.2.0" + regjsgen@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.2.0.tgz#6c016adeac554f75823fe37ac05b92d5a4edb1f7" +regjsgen@^0.5.0, regjsgen@^0.5.1: + version "0.5.1" + resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.5.1.tgz#48f0bf1a5ea205196929c0d9798b42d1ed98443c" + integrity sha512-5qxzGZjDs9w4tzT3TPhCJqWdCc3RLYwy9J2NB0nm5Lz+S273lvWcpjaTGHsT1dc6Hhfq41uSEOw8wBmxrKOuyg== + regjsparser@^0.1.4: version "0.1.5" resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.1.5.tgz#7ee8f84dc6fa792d3fd0ae228d24bd949ead205c" dependencies: jsesc "~0.5.0" +regjsparser@^0.6.0: + version "0.6.3" + resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.6.3.tgz#74192c5805d35e9f5ebe3c1fb5b40d40a8a38460" + integrity sha512-8uZvYbnfAtEm9Ab8NTb3hdLwL4g/LQzEYP7Xs27T96abJCCE2d6r3cPZPQEsLKy0vRSGVNG+/zVGtLr86HQduA== + dependencies: + jsesc "~0.5.0" + +regjsparser@^0.6.4: + version "0.6.4" + resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.6.4.tgz#a769f8684308401a66e9b529d2436ff4d0666272" + integrity sha512-64O87/dPDgfk8/RQqC4gkZoGyyWFIEUTTh80CU6CWuK5vkCGyekIx+oKcEIYtP/RAxSQltCZHCNu/mdd7fqlJw== + dependencies: + jsesc "~0.5.0" + remove-trailing-separator@^1.0.1: version "1.1.0" resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" @@ -5034,12 +7467,14 @@ repeat-string@^1.6.1: repeating@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/repeating/-/repeating-2.0.1.tgz#5214c53a926d3552707527fbab415dbc08d06dda" + integrity sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo= dependencies: is-finite "^1.0.0" -request@^2.83.0, request@^2.87.0, request@^2.88.0: +request@^2.83.0, request@^2.87.0: version "2.88.0" resolved "https://registry.yarnpkg.com/request/-/request-2.88.0.tgz#9c2fca4f7d35b592efe57c7f0a55e81052124fef" + integrity sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg== dependencies: aws-sign2 "~0.7.0" aws4 "^1.8.0" @@ -5062,9 +7497,36 @@ request@^2.83.0, request@^2.87.0, request@^2.88.0: tunnel-agent "^0.6.0" uuid "^3.3.2" +request@^2.88.0: + version "2.88.2" + resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3" + integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw== + dependencies: + aws-sign2 "~0.7.0" + aws4 "^1.8.0" + caseless "~0.12.0" + combined-stream "~1.0.6" + extend "~3.0.2" + forever-agent "~0.6.1" + form-data "~2.3.2" + har-validator "~5.1.3" + http-signature "~1.2.0" + is-typedarray "~1.0.0" + isstream "~0.1.2" + json-stringify-safe "~5.0.1" + mime-types "~2.1.19" + oauth-sign "~0.9.0" + performance-now "^2.1.0" + qs "~6.5.2" + safe-buffer "^5.1.2" + tough-cookie "~2.5.0" + tunnel-agent "^0.6.0" + uuid "^3.3.2" + require-directory@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I= require-from-string@^2.0.1: version "2.0.2" @@ -5073,6 +7535,7 @@ require-from-string@^2.0.1: require-main-filename@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1" + integrity sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE= require-main-filename@^2.0.0: version "2.0.0" @@ -5082,6 +7545,7 @@ require-main-filename@^2.0.0: requires-port@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" + integrity sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8= resolve-cwd@^2.0.0: version "2.0.0" @@ -5097,7 +7561,7 @@ resolve-url@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" -resolve@^1.1.6, resolve@^1.1.7, resolve@^1.3.2: +resolve@^1.1.7, resolve@^1.3.2: version "1.10.0" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.10.0.tgz#3bdaaeaf45cc07f375656dfd2e54ed0810b101ba" dependencies: @@ -5110,11 +7574,12 @@ resolve@^1.10.0: dependencies: path-parse "^1.0.6" -restore-cursor@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf" +restore-cursor@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-3.1.0.tgz#39f67c54b3a7a58cea5236d95cf0034239631f7e" + integrity sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA== dependencies: - onetime "^2.0.0" + onetime "^5.1.0" signal-exit "^3.0.2" ret@~0.1.10: @@ -5125,7 +7590,36 @@ retry@^0.10.0: version "0.10.1" resolved "https://registry.yarnpkg.com/retry/-/retry-0.10.1.tgz#e76388d217992c252750241d3d3956fed98d8ff4" -rimraf@2, rimraf@^2.2.8, rimraf@^2.5.2, rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2.6.2, rimraf@^2.6.3: +retry@^0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/retry/-/retry-0.12.0.tgz#1b42a6266a21f07421d1b0b54b7dc167b01c013b" + integrity sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs= + +rgb-regex@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/rgb-regex/-/rgb-regex-1.0.1.tgz#c0e0d6882df0e23be254a475e8edd41915feaeb1" + integrity sha1-wODWiC3w4jviVKR16O3UGRX+rrE= + +rgba-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/rgba-regex/-/rgba-regex-1.0.0.tgz#43374e2e2ca0968b0ef1523460b7d730ff22eeb3" + integrity sha1-QzdOLiyglosO8VI0YLfXMP8i7rM= + +rimraf@2, rimraf@^2.7.1: + version "2.7.1" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" + integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== + dependencies: + glob "^7.1.3" + +rimraf@3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" + integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== + dependencies: + glob "^7.1.3" + +rimraf@^2.2.8, rimraf@^2.5.2, rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2.6.2, rimraf@^2.6.3: version "2.6.3" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" dependencies: @@ -5138,6 +7632,13 @@ ripemd160@^2.0.0, ripemd160@^2.0.1: hash-base "^3.0.0" inherits "^2.0.1" +rollup@2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.1.0.tgz#552e248e397a06b9c6db878c0564ca4ee06729c9" + integrity sha512-gfE1455AEazVVTJoeQtcOq/U6GSxwoj4XPSWVsuWmgIxj7sBQNLDOSA82PbdMe+cP8ql8fR1jogPFe8Wg8g4SQ== + optionalDependencies: + fsevents "~2.1.2" + rrule@^2.6.0: version "2.6.2" resolved "https://registry.yarnpkg.com/rrule/-/rrule-2.6.2.tgz#f175c6c0b20d6f798739e4e1d979ffb3d79589e8" @@ -5147,11 +7648,10 @@ rrule@^2.6.0: optionalDependencies: luxon "^1.3.3" -run-async@^2.2.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.3.0.tgz#0371ab4ae0bdd720d4166d7dfda64ff7a445a6c0" - dependencies: - is-promise "^2.1.0" +run-async@^2.4.0: + version "2.4.1" + resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.4.1.tgz#8440eccf99ea3e70bd409d49aab88e10c189a455" + integrity sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ== run-queue@^1.0.0, run-queue@^1.0.3: version "1.0.3" @@ -5159,23 +7659,29 @@ run-queue@^1.0.0, run-queue@^1.0.3: dependencies: aproba "^1.1.1" -rxjs@6.4.0: - version "6.4.0" - resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.4.0.tgz#f3bb0fe7bda7fb69deac0c16f17b50b0b8790504" - integrity sha512-Z9Yfa11F6B9Sg/BK9MnqnQ+aQYicPLtilXBp2yUtDt2JRCE0h26d33EnfO3ZxoNxG0T92OUucP3Ct7cpfkdFfw== +rxjs@6.5.4, rxjs@^6.5.2: + version "6.5.4" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.5.4.tgz#e0777fe0d184cec7872df147f303572d414e211c" + integrity sha512-naMQXcgEo3csAEGvw/NydRA0fuS2nDZJiw1YUWFKU7aPPAPGZEsD4Iimit96qwCieH6y614MCLYwdkrWx7z/7Q== dependencies: tslib "^1.9.0" -rxjs@^6.4.0, rxjs@^6.5.2: - version "6.5.2" - resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.5.2.tgz#2e35ce815cd46d84d02a209fb4e5921e051dbec7" - integrity sha512-HUb7j3kvb7p7eCUHE3FqjoDsC1xfZQ4AHFWfTKSpZ+sAhhz5X1WX0ZuUqWbzB2QhSLp3DoLUG+hMdEDKqWo2Zg== +rxjs@^6.5.3: + version "6.5.5" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.5.5.tgz#c5c884e3094c8cfee31bf27eb87e54ccfc87f9ec" + integrity sha512-WfQI+1gohdf0Dai/Bbmk5L5ItH5tYqm3ki2c5GdWhKjalzjg93N3avFjVStyZZz+A2Em+ZxKH5bNghw9UeylGQ== dependencies: tslib "^1.9.0" -safe-buffer@5.1.2, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: +safe-buffer@5.1.2, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@~5.1.0, safe-buffer@~5.1.1: version "5.1.2" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" + integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== + +safe-buffer@^5.0.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.0.tgz#b74daec49b1148f88c64b68d49b1e815c1f2f519" + integrity sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg== safe-regex@^1.1.0: version "1.1.0" @@ -5183,36 +7689,38 @@ safe-regex@^1.1.0: dependencies: ret "~0.1.10" -"safer-buffer@>= 2.1.2 < 3", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: +"safer-buffer@>= 2.1.2 < 3", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@^2.1.2, safer-buffer@~2.1.0: version "2.1.2" resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== sass-graph@^2.2.4: version "2.2.4" resolved "https://registry.yarnpkg.com/sass-graph/-/sass-graph-2.2.4.tgz#13fbd63cd1caf0908b9fd93476ad43a51d1e0b49" + integrity sha1-E/vWPNHK8JCLn9k0dq1DpR0eC0k= dependencies: glob "^7.0.0" lodash "^4.0.0" scss-tokenizer "^0.2.3" yargs "^7.0.0" -sass-loader@7.1.0: - version "7.1.0" - resolved "https://registry.yarnpkg.com/sass-loader/-/sass-loader-7.1.0.tgz#16fd5138cb8b424bf8a759528a1972d72aad069d" +sass-loader@8.0.2: + version "8.0.2" + resolved "https://registry.yarnpkg.com/sass-loader/-/sass-loader-8.0.2.tgz#debecd8c3ce243c76454f2e8290482150380090d" + integrity sha512-7o4dbSK8/Ol2KflEmSco4jTjQoV988bM82P9CZdmo9hR3RLnvNc0ufMNdMrB0caq38JQ/FgF4/7RcbcfKzxoFQ== dependencies: - clone-deep "^2.0.1" - loader-utils "^1.0.1" - lodash.tail "^4.1.1" - neo-async "^2.5.0" - pify "^3.0.0" - semver "^5.5.0" + clone-deep "^4.0.1" + loader-utils "^1.2.3" + neo-async "^2.6.1" + schema-utils "^2.6.1" + semver "^6.3.0" -sass@1.19.0: - version "1.19.0" - resolved "https://registry.yarnpkg.com/sass/-/sass-1.19.0.tgz#5de82c713d4299fac57384ef5219534a37fe3e6c" - integrity sha512-8kzKCgxCzh8/zEn3AuRwzLWVSSFj8omkiGwqdJdeOufjM+I88dXxu9LYJ/Gw4rRTHXesN0r1AixBuqM6yLQUJw== +sass@1.26.3: + version "1.26.3" + resolved "https://registry.yarnpkg.com/sass/-/sass-1.26.3.tgz#412df54486143b76b5a65cdf7569e86f44659f46" + integrity sha512-5NMHI1+YFYw4sN3yfKjpLuV9B5l7MqQ6FlkTcC4FT+oHbBRUZoSjHrrt/mE0nFXJyY2kQtU9ou9HxvFVjLFuuw== dependencies: - chokidar "^2.0.0" + chokidar ">=2.0.0 <4.0.0" saucelabs@^1.5.0: version "1.5.0" @@ -5220,20 +7728,10 @@ saucelabs@^1.5.0: dependencies: https-proxy-agent "^2.2.1" -sax@0.5.x: - version "0.5.8" - resolved "https://registry.yarnpkg.com/sax/-/sax-0.5.8.tgz#d472db228eb331c2506b0e8c15524adb939d12c1" - -sax@>=0.6.0, sax@^1.2.4: +sax@>=0.6.0, sax@^1.2.4, sax@~1.2.4: version "1.2.4" resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" -schema-utils@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-0.3.0.tgz#f5877222ce3e931edae039f17eb3716e7137f8cf" - dependencies: - ajv "^5.0.0" - schema-utils@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-1.0.0.tgz#0b79a93204d7b600d4b2850d1f66c2a34951c770" @@ -5242,9 +7740,26 @@ schema-utils@^1.0.0: ajv-errors "^1.0.0" ajv-keywords "^3.1.0" +schema-utils@^2.5.0, schema-utils@^2.6.4, schema-utils@^2.6.5: + version "2.6.6" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-2.6.6.tgz#299fe6bd4a3365dc23d99fd446caff8f1d6c330c" + integrity sha512-wHutF/WPSbIi9x6ctjGGk2Hvl0VOz5l3EKEuKbjPlB30mKZUzb9A5k9yEXRX3pwyqVLPvpfZZEllaFq/M718hA== + dependencies: + ajv "^6.12.0" + ajv-keywords "^3.4.1" + +schema-utils@^2.6.1: + version "2.6.4" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-2.6.4.tgz#a27efbf6e4e78689d91872ee3ccfa57d7bdd0f53" + integrity sha512-VNjcaUxVnEeun6B2fiiUDjXXBtD4ZSH7pdbfIu1pOFwgptDPLMo/z9jr4sUfsjFVPqDCEin/F7IYlq7/E6yDbQ== + dependencies: + ajv "^6.10.2" + ajv-keywords "^3.4.1" + scss-tokenizer@^0.2.3: version "0.2.3" resolved "https://registry.yarnpkg.com/scss-tokenizer/-/scss-tokenizer-0.2.3.tgz#8eb06db9a9723333824d3f5530641149847ce5d1" + integrity sha1-jrBtualyMzOCTT9VMGQRSYR85dE= dependencies: js-base64 "^2.1.8" source-map "^0.4.2" @@ -5262,12 +7777,12 @@ selenium-webdriver@3.6.0, selenium-webdriver@^3.0.1: tmp "0.0.30" xml2js "^0.4.17" -selfsigned@^1.10.4: - version "1.10.4" - resolved "https://registry.yarnpkg.com/selfsigned/-/selfsigned-1.10.4.tgz#cdd7eccfca4ed7635d47a08bf2d5d3074092e2cd" - integrity sha512-9AukTiDmHXGXWtWjembZ5NDmVvP2695EtpgbCsxCa68w3c88B+alqbmZ4O3hZ4VWGXeGWzEVdvqgAJD8DQPCDw== +selfsigned@^1.10.7: + version "1.10.7" + resolved "https://registry.yarnpkg.com/selfsigned/-/selfsigned-1.10.7.tgz#da5819fd049d5574f28e88a9bcc6dbc6e6f3906b" + integrity sha512-8M3wBCzeWIJnQfl43IKwOmC4H/RAp50S8DF60znzjW5GVqTcSe2vWclt7hmYVPkKPlHWOu5EaWOMZ2Y6W8ZXTA== dependencies: - node-forge "0.7.5" + node-forge "0.9.0" semver-dsl@^1.0.1: version "1.0.1" @@ -5281,23 +7796,44 @@ semver-intersect@1.4.0: dependencies: semver "^5.0.0" -"semver@2 || 3 || 4 || 5", semver@^5.0.0, semver@^5.3.0, semver@^5.4.1, semver@^5.5.0, semver@^5.6.0: +"semver@2 || 3 || 4 || 5": + version "5.7.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" + integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== + +semver@7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.0.0.tgz#5f3ca35761e47e05b206c6daff2cf814f0316b8e" + integrity sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A== + +semver@7.1.3: + version "7.1.3" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.1.3.tgz#e4345ce73071c53f336445cfc19efb1c311df2a6" + integrity sha512-ekM0zfiA9SCBlsKa2X1hxyxiI4L3B6EbVJkkdgQXnSEEaHlGdvyodMruTiulSRWMMB4NeIuYNMC9rTKTz97GxA== + +semver@^5.0.0, semver@^5.3.0, semver@^5.4.1, semver@^5.5.0, semver@^5.6.0: version "5.6.0" resolved "https://registry.yarnpkg.com/semver/-/semver-5.6.0.tgz#7e74256fbaa49c75aa7c7a205cc22799cac80004" -semver@6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-6.0.0.tgz#05e359ee571e5ad7ed641a6eec1e547ba52dea65" - integrity sha512-0UewU+9rFapKFnlbirLi3byoOuhrSsli/z/ihNnvM24vgF+8sNBiI1LZPBSH9wJKUwaUbw+s3hToDLCXkrghrQ== - semver@^6.0.0: version "6.1.1" resolved "https://registry.yarnpkg.com/semver/-/semver-6.1.1.tgz#53f53da9b30b2103cd4f15eab3a18ecbcb210c9b" integrity sha512-rWYq2e5iYW+fFe/oPPtYJxYgjBm8sC4rmoGdUOgBB7VnwKt6HrL793l2voH1UlsyYZpJ4g0wfjnTEO1s1NP2eQ== +semver@^6.3.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" + integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== + +semver@^7.0.0, semver@^7.1.1: + version "7.3.2" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.2.tgz#604962b052b81ed0786aae84389ffba70ffd3938" + integrity sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ== + semver@~5.3.0: version "5.3.0" resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f" + integrity sha1-myzl094C0XxgEq0yaqa00M9U+U8= send@0.17.1: version "0.17.1" @@ -5318,14 +7854,10 @@ send@0.17.1: range-parser "~1.2.1" statuses "~1.5.0" -serialize-javascript@^1.4.0: - version "1.6.1" - resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-1.6.1.tgz#4d1f697ec49429a847ca6f442a2a755126c4d879" - -serialize-javascript@^1.7.0: - version "1.7.0" - resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-1.7.0.tgz#d6e0dfb2a3832a8c94468e6eb1db97e55a192a65" - integrity sha512-ke8UG8ulpFOxO8f8gRYabHQe/ZntKlcig2Mp+8+URDP1D8vJZ0KUt7LYo07q25Z/+JVSgpr/cui9PIp5H6/+nA== +serialize-javascript@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-2.1.2.tgz#ecec53b0e0317bdc95ef76ab7074b7384785fa61" + integrity sha512-rs9OggEUF0V4jUSecXazOYsLfu7OGK2qIn3c7IPBiffz32XniEp/TX9Xmc9LQfK2nQ2QKHvZ2oygKUGU0lG4jQ== serve-index@^1.9.1: version "1.9.1" @@ -5353,6 +7885,7 @@ serve-static@1.14.1: set-blocking@^2.0.0, set-blocking@~2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" + integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= set-value@^0.4.3: version "0.4.3" @@ -5392,13 +7925,12 @@ sha.js@^2.4.0, sha.js@^2.4.8: inherits "^2.0.1" safe-buffer "^5.0.1" -shallow-clone@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/shallow-clone/-/shallow-clone-1.0.0.tgz#4480cd06e882ef68b2ad88a3ea54832e2c48b571" +shallow-clone@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/shallow-clone/-/shallow-clone-3.0.1.tgz#8f2981ad92531f55035b01fb230769a40e02efa3" + integrity sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA== dependencies: - is-extendable "^0.1.1" - kind-of "^5.0.0" - mixin-object "^2.0.1" + kind-of "^6.0.2" shebang-command@^1.2.0: version "1.2.0" @@ -5410,18 +7942,17 @@ shebang-regex@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" -shelljs@^0.8.1: - version "0.8.3" - resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.8.3.tgz#a7f3319520ebf09ee81275b2368adb286659b097" - dependencies: - glob "^7.0.0" - interpret "^1.0.0" - rechoir "^0.6.2" - signal-exit@^3.0.0, signal-exit@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" +simple-swizzle@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/simple-swizzle/-/simple-swizzle-0.2.2.tgz#a4da6b635ffcccca33f70d17cb92592de95e557a" + integrity sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo= + dependencies: + is-arrayish "^0.3.1" + slash@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55" @@ -5457,36 +7988,10 @@ snapdragon@^0.8.1: source-map-resolve "^0.5.0" use "^3.1.0" -socket.io-client@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/socket.io-client/-/socket.io-client-2.2.0.tgz#84e73ee3c43d5020ccc1a258faeeb9aec2723af7" - dependencies: - backo2 "1.0.2" - base64-arraybuffer "0.1.5" - component-bind "1.0.0" - component-emitter "1.2.1" - debug "~3.1.0" - engine.io-client "~3.3.1" - has-binary2 "~1.0.2" - has-cors "1.1.0" - indexof "0.0.1" - object-component "0.0.3" - parseqs "0.0.5" - parseuri "0.0.5" - socket.io-parser "~3.3.0" - to-array "0.1.4" - -socket.io-parser@~3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/socket.io-parser/-/socket.io-parser-3.3.0.tgz#2b52a96a509fdf31440ba40fed6094c7d4f1262f" - dependencies: - component-emitter "1.2.1" - debug "~3.1.0" - isarray "2.0.1" - -sockjs-client@1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/sockjs-client/-/sockjs-client-1.3.0.tgz#12fc9d6cb663da5739d3dc5fb6e8687da95cb177" +sockjs-client@1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/sockjs-client/-/sockjs-client-1.4.0.tgz#c9f2568e19c8fd8173b4997ea3420e0bb306c7d5" + integrity sha512-5zaLyO8/nri5cua0VtOrFXBPK1jbL4+1cebT/mmKA1E1ZXOvJrII75bPu0l0k843G/+iAbhEqzyKr0w/eCCj7g== dependencies: debug "^3.2.5" eventsource "^1.0.7" @@ -5516,10 +8021,10 @@ socks@~2.2.0: ip "^1.1.5" smart-buffer "^4.0.1" -sort-keys@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/sort-keys/-/sort-keys-2.0.0.tgz#658535584861ec97d730d6cf41822e1f56684128" - integrity sha1-ZYU1WEhh7JfXMNbPQYIuH1ZoQSg= +sort-keys@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/sort-keys/-/sort-keys-1.1.2.tgz#441b6d4d346798f1b4e49e8920adfba0e543f9ad" + integrity sha1-RBttTTRnmPG05J6JIK37oOVD+a0= dependencies: is-plain-obj "^1.0.0" @@ -5527,10 +8032,6 @@ source-list-map@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.1.tgz#3993bd873bfc48479cca9ea3a547835c7c154b34" -source-list-map@~0.1.7: - version "0.1.8" - resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-0.1.8.tgz#c550b2ab5427f6b3f21f5afead88c4f5587b2106" - source-map-loader@0.2.4: version "0.2.4" resolved "https://registry.yarnpkg.com/source-map-loader/-/source-map-loader-0.2.4.tgz#c18b0dc6e23bf66f6792437557c569a11e072271" @@ -5548,13 +8049,16 @@ source-map-resolve@^0.5.0: source-map-url "^0.4.0" urix "^0.1.0" -source-map-support@0.5.12, source-map-support@~0.5.10: - version "0.5.12" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.12.tgz#b4f3b10d51857a5af0138d3ce8003b201613d599" - integrity sha512-4h2Pbvyy15EE02G+JOZpUCmqWJuqrs+sEkzewTm++BPi7Hvn/HwcqLAcNxYAyI0x13CpPPn+kMjl+hplXMHITQ== +source-map-resolve@^0.5.2: + version "0.5.3" + resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.3.tgz#190866bece7553e1f8f267a2ee82c606b5509a1a" + integrity sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw== dependencies: - buffer-from "^1.0.0" - source-map "^0.6.0" + atob "^2.1.2" + decode-uri-component "^0.2.0" + resolve-url "^0.2.1" + source-map-url "^0.4.0" + urix "^0.1.0" source-map-support@^0.5.3, source-map-support@^0.5.5: version "0.5.10" @@ -5569,31 +8073,29 @@ source-map-support@~0.4.0: dependencies: source-map "^0.5.6" +source-map-support@~0.5.12: + version "0.5.16" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.16.tgz#0ae069e7fe3ba7538c64c98515e35339eac5a042" + integrity sha512-efyLRJDr68D9hBBNIPWFjhpFzURh+KJykQwvMyW5UiZzYwoF6l4YMMDIJJEyFWxWCqfyxLzz6tSfUFR+kXXsVQ== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + source-map-url@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3" -source-map@0.1.x: - version "0.1.43" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.1.43.tgz#c24bc146ca517c1471f5dacbe2571b2b7f9e3346" - dependencies: - amdefine ">=0.0.4" - -source-map@0.5.6: - version "0.5.6" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.6.tgz#75ce38f52bf0733c5a7f0c118d81334a2bb5f412" - -source-map@0.7.3: +source-map@0.7.3, source-map@^0.7.3: version "0.7.3" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383" -source-map@^0.4.2, source-map@~0.4.1: +source-map@^0.4.2: version "0.4.4" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.4.4.tgz#eba4f5da9c0dc999de68032d8b4f76173652036b" dependencies: amdefine ">=0.0.4" -source-map@^0.5.6, source-map@^0.5.7: +source-map@^0.5.0, source-map@^0.5.6, source-map@^0.5.7: version "0.5.7" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" @@ -5606,9 +8108,15 @@ sourcemap-codec@^1.4.1, sourcemap-codec@^1.4.4: resolved "https://registry.yarnpkg.com/sourcemap-codec/-/sourcemap-codec-1.4.4.tgz#c63ea927c029dd6bd9a2b7fa03b3fec02ad56e9f" integrity sha512-CYAPYdBu34781kLHkaW3m6b/uUSyMOC2R61gcYMWooeuaGtjof86ZA/8T+qVPPt7np1085CR9hmMGrySwEc8Xg== +sourcemap-codec@^1.4.8: + version "1.4.8" + resolved "https://registry.yarnpkg.com/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz#ea804bd94857402e6992d05a38ef1ae35a9ab4c4" + integrity sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA== + spdx-correct@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.0.tgz#fb83e504445268f154b074e218c87c003cd31df4" + integrity sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q== dependencies: spdx-expression-parse "^3.0.0" spdx-license-ids "^3.0.0" @@ -5616,17 +8124,20 @@ spdx-correct@^3.0.0: spdx-exceptions@^2.1.0: version "2.2.0" resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz#2ea450aee74f2a89bfb94519c07fcd6f41322977" + integrity sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA== spdx-expression-parse@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz#99e119b7a5da00e05491c9fa338b7904823b41d0" + integrity sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg== dependencies: spdx-exceptions "^2.1.0" spdx-license-ids "^3.0.0" spdx-license-ids@^3.0.0: - version "3.0.3" - resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.3.tgz#81c0ce8f21474756148bbb5f3bfc0f36bf15d76e" + version "3.0.5" + resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz#3694b5804567a458d3c8045842a6358632f62654" + integrity sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q== spdy-transport@^3.0.0: version "3.0.0" @@ -5640,10 +8151,10 @@ spdy-transport@^3.0.0: readable-stream "^3.0.6" wbuf "^1.7.3" -spdy@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/spdy/-/spdy-4.0.0.tgz#81f222b5a743a329aa12cea6a390e60e9b613c52" - integrity sha512-ot0oEGT/PGUpzf/6uk4AWLqkq+irlqHXkrdbk51oWONh3bxQmBuljxPNl66zlRRcIJStWq0QkLUCPOPjgjvU0Q== +spdy@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/spdy/-/spdy-4.0.1.tgz#6f12ed1c5db7ea4f24ebb8b89ba58c87c08257f2" + integrity sha512-HeZS3PBdMA+sZSu0qwpCxl3DeALD5ASx8pAX0jZdKXSpPWbQ6SYGnlg3BBmYLx5LtiZrmkAZfErCm2oECBcioA== dependencies: debug "^4.1.0" handle-thing "^2.0.0" @@ -5669,7 +8180,7 @@ split-string@^3.0.1, split-string@^3.0.2: dependencies: extend-shallow "^3.0.0" -sprintf-js@^1.1.1: +sprintf-js@^1.1.1, sprintf-js@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.1.2.tgz#da1765262bf8c0f571749f2ad6c26300207ae673" @@ -5678,8 +8189,9 @@ sprintf-js@~1.0.2: resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" sshpk@^1.7.0: - version "1.16.0" - resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.16.0.tgz#1d4963a2fbffe58050aa9084ca20be81741c07de" + version "1.16.1" + resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.16.1.tgz#fb661c0bef29b39db40769ee39fa70093d6f6877" + integrity sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg== dependencies: asn1 "~0.2.3" assert-plus "^1.0.0" @@ -5697,6 +8209,26 @@ ssri@^6.0.0, ssri@^6.0.1: dependencies: figgy-pudding "^3.5.1" +ssri@^7.0.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/ssri/-/ssri-7.1.0.tgz#92c241bf6de82365b5c7fb4bd76e975522e1294d" + integrity sha512-77/WrDZUWocK0mvA5NTRQyveUf+wsrIc6vyrxpS8tVvYBcX215QbafrJR3KtkpskIzoFLqqNuuYQvxaMjXJ/0g== + dependencies: + figgy-pudding "^3.5.1" + minipass "^3.1.1" + +ssri@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/ssri/-/ssri-8.0.0.tgz#79ca74e21f8ceaeddfcb4b90143c458b8d988808" + integrity sha512-aq/pz989nxVYwn16Tsbj1TqFpD5LLrQxHf5zaHuieFV+R0Bbr4y8qUsOA45hXT/N4/9UNXTarBjnjVmjSOVaAA== + dependencies: + minipass "^3.1.1" + +stable@^0.1.8: + version "0.1.8" + resolved "https://registry.yarnpkg.com/stable/-/stable-0.1.8.tgz#836eb3c8382fe2936feaf544631017ce7d47a3cf" + integrity sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w== + static-extend@^0.1.1: version "0.1.2" resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6" @@ -5704,12 +8236,6 @@ static-extend@^0.1.1: define-property "^0.2.5" object-copy "^0.1.0" -stats-webpack-plugin@0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/stats-webpack-plugin/-/stats-webpack-plugin-0.7.0.tgz#ccffe9b745de8bbb155571e063f8263fc0e2bc06" - dependencies: - lodash "^4.17.4" - "statuses@>= 1.4.0 < 2", "statuses@>= 1.5.0 < 2", statuses@~1.5.0: version "1.5.0" resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" @@ -5717,6 +8243,7 @@ stats-webpack-plugin@0.7.0: stdout-stream@^1.4.0: version "1.4.1" resolved "https://registry.yarnpkg.com/stdout-stream/-/stdout-stream-1.4.1.tgz#5ac174cdd5cd726104aa0c0b2bd83815d8d535de" + integrity sha512-j4emi03KXqJWcIeF8eIXkjMFN1Cmb8gUlDYGeBALLPo5qdyTfA9bOtl8m33lRoC+vFMkP3gl0WsDr6+gzxbbTA== dependencies: readable-stream "^2.0.1" @@ -5760,19 +8287,20 @@ strict-uri-encode@^1.0.0: string-width@^1.0.1, string-width@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" + integrity sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M= dependencies: code-point-at "^1.0.0" is-fullwidth-code-point "^1.0.0" strip-ansi "^3.0.0" -"string-width@^1.0.2 || 2", string-width@^2.0.0, string-width@^2.1.0, string-width@^2.1.1: +"string-width@^1.0.2 || 2", string-width@^2.0.0, string-width@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" dependencies: is-fullwidth-code-point "^2.0.0" strip-ansi "^4.0.0" -string-width@^3.0.0: +string-width@^3.0.0, string-width@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961" integrity sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w== @@ -5781,6 +8309,31 @@ string-width@^3.0.0: is-fullwidth-code-point "^2.0.0" strip-ansi "^5.1.0" +string-width@^4.1.0, string-width@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.0.tgz#952182c46cc7b2c313d1596e623992bd163b72b5" + integrity sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.0" + +string.prototype.trimleft@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/string.prototype.trimleft/-/string.prototype.trimleft-2.1.1.tgz#9bdb8ac6abd6d602b17a4ed321870d2f8dcefc74" + integrity sha512-iu2AGd3PuP5Rp7x2kEZCrB2Nf41ehzh+goo8TV7z8/XDBbsvc6HQIlUl9RjkZ4oyrW1XM5UwlGl1oVEaDjg6Ag== + dependencies: + define-properties "^1.1.3" + function-bind "^1.1.1" + +string.prototype.trimright@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/string.prototype.trimright/-/string.prototype.trimright-2.1.1.tgz#440314b15996c866ce8a0341894d45186200c5d9" + integrity sha512-qFvWL3/+QIgZXVmJBfpHmxLB7xsUXz6HsUmP8+5dRaC3Q7oKUv9Vo6aMCRZC1smrtyECFsIT30PqBJ1gTjAs+g== + dependencies: + define-properties "^1.1.3" + function-bind "^1.1.1" + string_decoder@^1.0.0, string_decoder@^1.1.1: version "1.2.0" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.2.0.tgz#fe86e738b19544afe70469243b2a1ee9240eae8d" @@ -5794,31 +8347,42 @@ string_decoder@~0.10.x: string_decoder@~1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" + integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== dependencies: safe-buffer "~5.1.0" strip-ansi@^3.0.0, strip-ansi@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" + integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8= dependencies: ansi-regex "^2.0.0" strip-ansi@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" + integrity sha1-qEeQIusaw2iocTibY1JixQXuNo8= dependencies: ansi-regex "^3.0.0" -strip-ansi@^5.1.0: +strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA== dependencies: ansi-regex "^4.1.0" +strip-ansi@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.0.tgz#0b1571dd7669ccd4f3e06e14ef1eed26225ae532" + integrity sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w== + dependencies: + ansi-regex "^5.0.0" + strip-bom@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e" + integrity sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4= dependencies: is-utf8 "^0.2.0" @@ -5829,6 +8393,7 @@ strip-eof@^1.0.0: strip-indent@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-1.0.1.tgz#0c7962a6adefa7bbd4ac366460a638552ae1a0a2" + integrity sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI= dependencies: get-stdin "^4.0.1" @@ -5836,12 +8401,22 @@ strip-json-comments@~2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" -style-loader@0.23.1: - version "0.23.1" - resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-0.23.1.tgz#cb9154606f3e771ab6c4ab637026a1049174d925" +style-loader@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-1.1.3.tgz#9e826e69c683c4d9bf9db924f85e9abb30d5e200" + integrity sha512-rlkH7X/22yuwFYK357fMN/BxYOorfnfq0eD7+vqlemSK4wEcejFF1dg4zxP0euBW8NrYx2WZzZ8PPFevr7D+Kw== dependencies: - loader-utils "^1.1.0" - schema-utils "^1.0.0" + loader-utils "^1.2.3" + schema-utils "^2.6.4" + +stylehacks@^4.0.0: + version "4.0.3" + resolved "https://registry.yarnpkg.com/stylehacks/-/stylehacks-4.0.3.tgz#6718fcaf4d1e07d8a1318690881e8d96726a71d5" + integrity sha512-7GlLk9JwlElY4Y6a/rmbH2MhVlTyVmiJd1PfTCqFaIBEGMYNsrO/v3SeGTdhBThLg4Z+NbOk/qFMwCa+J+3p/g== + dependencies: + browserslist "^4.0.0" + postcss "^7.0.0" + postcss-selector-parser "^3.0.0" stylus-loader@3.0.2: version "3.0.2" @@ -5851,16 +8426,19 @@ stylus-loader@3.0.2: lodash.clonedeep "^4.5.0" when "~3.6.x" -stylus@0.54.5: - version "0.54.5" - resolved "https://registry.yarnpkg.com/stylus/-/stylus-0.54.5.tgz#42b9560931ca7090ce8515a798ba9e6aa3d6dc79" +stylus@0.54.7: + version "0.54.7" + resolved "https://registry.yarnpkg.com/stylus/-/stylus-0.54.7.tgz#c6ce4793965ee538bcebe50f31537bfc04d88cd2" + integrity sha512-Yw3WMTzVwevT6ZTrLCYNHAFmanMxdylelL3hkWNgPMeTCpMwpV3nXjpOHuBXtFv7aiO2xRuQS6OoAdgkNcSNug== dependencies: - css-parse "1.7.x" - debug "*" - glob "7.0.x" - mkdirp "0.5.x" - sax "0.5.x" - source-map "0.1.x" + css-parse "~2.0.0" + debug "~3.1.0" + glob "^7.1.3" + mkdirp "~0.5.x" + safer-buffer "^2.1.2" + sax "~1.2.4" + semver "^6.0.0" + source-map "^0.7.3" superagent@^3.8.3: version "3.8.3" @@ -5881,6 +8459,7 @@ superagent@^3.8.3: supports-color@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" + integrity sha1-U10EXOa2Nj+kARcIRimZXp3zJMc= supports-color@^5.3.0: version "5.5.0" @@ -5894,24 +8473,52 @@ supports-color@^6.1.0: dependencies: has-flag "^3.0.0" -sweetalert2@^7.33.1: - version "7.33.1" - resolved "https://registry.yarnpkg.com/sweetalert2/-/sweetalert2-7.33.1.tgz#7e3534d2c2962f875f419cfea5d75ee526d65cd4" +supports-color@^7.0.0, supports-color@^7.1.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.1.0.tgz#68e32591df73e25ad1c4b49108a2ec507962bfd1" + integrity sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g== + dependencies: + has-flag "^4.0.0" + +svgo@^1.0.0: + version "1.3.2" + resolved "https://registry.yarnpkg.com/svgo/-/svgo-1.3.2.tgz#b6dc511c063346c9e415b81e43401145b96d4167" + integrity sha512-yhy/sQYxR5BkC98CY7o31VGsg014AKLEPxdfhora76l36hD9Rdy5NZA/Ocn6yayNPgSamYdtX2rFJdcv07AYVw== + dependencies: + chalk "^2.4.1" + coa "^2.0.2" + css-select "^2.0.0" + css-select-base-adapter "^0.1.1" + css-tree "1.0.0-alpha.37" + csso "^4.0.2" + js-yaml "^3.13.1" + mkdirp "~0.5.1" + object.values "^1.1.0" + sax "~1.2.4" + stable "^0.1.8" + unquote "~1.1.1" + util.promisify "~1.0.0" symbol-observable@1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.2.0.tgz#c22688aed4eab3cdc2dfeacbb561660560a00804" -tapable@^1.0.0, tapable@^1.1.0: +tapable@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.1.1.tgz#4d297923c5a72a42360de2ab52dadfaaec00018e" +tapable@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.1.3.tgz#a1fccc06b58db61fd7a45da2da44f5f3a3e67ba2" + integrity sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA== + tar@^2.0.0: - version "2.2.1" - resolved "https://registry.yarnpkg.com/tar/-/tar-2.2.1.tgz#8e4d2a256c0e2185c6b18ad694aec968b83cb1d1" + version "2.2.2" + resolved "https://registry.yarnpkg.com/tar/-/tar-2.2.2.tgz#0ca8848562c7299b8b446ff6a4d60cdbb23edc40" + integrity sha512-FCEhQ/4rE1zYv9rYXJw/msRqsnmlje5jHP6huWeBZ704jUTy02c5AZyWujpMR1ax6mVw9NyJMfuK2CMDWVIfgA== dependencies: block-stream "*" - fstream "^1.0.2" + fstream "^1.0.12" inherits "2" tar@^4: @@ -5926,66 +8533,87 @@ tar@^4: safe-buffer "^5.1.2" yallist "^3.0.2" -tar@^4.4.8: - version "4.4.10" - resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.10.tgz#946b2810b9a5e0b26140cf78bea6b0b0d689eba1" - integrity sha512-g2SVs5QIxvo6OLp0GudTqEf05maawKUxXru104iaayWA09551tFCTI8f1Asb4lPfkBr91k07iL4c11XO3/b0tA== +tar@^4.4.10: + version "4.4.13" + resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.13.tgz#43b364bc52888d555298637b10d60790254ab525" + integrity sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA== dependencies: chownr "^1.1.1" fs-minipass "^1.2.5" - minipass "^2.3.5" + minipass "^2.8.6" minizlib "^1.2.1" mkdirp "^0.5.0" safe-buffer "^5.1.2" yallist "^3.0.3" -terser-webpack-plugin@1.2.3: - version "1.2.3" - resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-1.2.3.tgz#3f98bc902fac3e5d0de730869f50668561262ec8" - integrity sha512-GOK7q85oAb/5kE12fMuLdn2btOS9OBZn4VsecpHDywoUC/jLhSAKOiYo0ezx7ss2EXPMzyEWFoE0s1WLE+4+oA== +tar@^6.0.1: + version "6.0.2" + resolved "https://registry.yarnpkg.com/tar/-/tar-6.0.2.tgz#5df17813468a6264ff14f766886c622b84ae2f39" + integrity sha512-Glo3jkRtPcvpDlAs/0+hozav78yoXKFr+c4wgw62NNMO3oo4AaJdCo21Uu7lcwr55h39W2XD1LMERc64wtbItg== dependencies: - cacache "^11.0.2" - find-cache-dir "^2.0.0" - schema-utils "^1.0.0" - serialize-javascript "^1.4.0" + chownr "^2.0.0" + fs-minipass "^2.0.0" + minipass "^3.0.0" + minizlib "^2.1.0" + mkdirp "^1.0.3" + yallist "^4.0.0" + +terser-webpack-plugin@2.3.5: + version "2.3.5" + resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-2.3.5.tgz#5ad971acce5c517440ba873ea4f09687de2f4a81" + integrity sha512-WlWksUoq+E4+JlJ+h+U+QUzXpcsMSSNXkDy9lBVkSqDn1w23Gg29L/ary9GeJVYCGiNJJX7LnVc4bwL1N3/g1w== + dependencies: + cacache "^13.0.1" + find-cache-dir "^3.2.0" + jest-worker "^25.1.0" + p-limit "^2.2.2" + schema-utils "^2.6.4" + serialize-javascript "^2.1.2" source-map "^0.6.1" - terser "^3.16.1" - webpack-sources "^1.1.0" - worker-farm "^1.5.2" + terser "^4.4.3" + webpack-sources "^1.4.3" -terser-webpack-plugin@^1.1.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-1.3.0.tgz#69aa22426299f4b5b3775cbed8cb2c5d419aa1d4" - integrity sha512-W2YWmxPjjkUcOWa4pBEv4OP4er1aeQJlSo2UhtCFQCuRXEHjOFscO8VyWHj9JLlA0RzQb8Y2/Ta78XZvT54uGg== +terser-webpack-plugin@^1.4.3: + version "1.4.3" + resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-1.4.3.tgz#5ecaf2dbdc5fb99745fd06791f46fc9ddb1c9a7c" + integrity sha512-QMxecFz/gHQwteWwSo5nTc6UaICqN1bMedC5sMtUc7y3Ha3Q8y6ZO0iCR8pq4RJC8Hjf0FEPEHZqcMB/+DFCrA== dependencies: - cacache "^11.3.2" - find-cache-dir "^2.0.0" + cacache "^12.0.2" + find-cache-dir "^2.1.0" is-wsl "^1.1.0" - loader-utils "^1.2.3" schema-utils "^1.0.0" - serialize-javascript "^1.7.0" + serialize-javascript "^2.1.2" source-map "^0.6.1" - terser "^4.0.0" - webpack-sources "^1.3.0" + terser "^4.1.2" + webpack-sources "^1.4.0" worker-farm "^1.7.0" -terser@^3.16.1: - version "3.17.0" - resolved "https://registry.yarnpkg.com/terser/-/terser-3.17.0.tgz#f88ffbeda0deb5637f9d24b0da66f4e15ab10cb2" - integrity sha512-/FQzzPJmCpjAH9Xvk2paiWrFq+5M6aVOf+2KRbwhByISDX/EujxsK+BAvrhb6H+2rtrLCHK9N01wO014vrIwVQ== +terser@4.6.10: + version "4.6.10" + resolved "https://registry.yarnpkg.com/terser/-/terser-4.6.10.tgz#90f5bd069ff456ddbc9503b18e52f9c493d3b7c2" + integrity sha512-qbF/3UOo11Hggsbsqm2hPa6+L4w7bkr+09FNseEe8xrcVD3APGLFqE+Oz1ZKAxjYnFsj80rLOfgAtJ0LNJjtTA== dependencies: - commander "^2.19.0" + commander "^2.20.0" source-map "~0.6.1" - source-map-support "~0.5.10" + source-map-support "~0.5.12" -terser@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/terser/-/terser-4.0.0.tgz#ef356f6f359a963e2cc675517f21c1c382877374" - integrity sha512-dOapGTU0hETFl1tCo4t56FN+2jffoKyER9qBGoUFyZ6y7WLoKT0bF+lAYi6B6YsILcGF3q1C2FBh8QcKSCgkgA== +terser@^4.1.2: + version "4.6.4" + resolved "https://registry.yarnpkg.com/terser/-/terser-4.6.4.tgz#40a0b37afbe5b57e494536815efa68326840fc00" + integrity sha512-5fqgBPLgVHZ/fVvqRhhUp9YUiGXhFJ9ZkrZWD9vQtFBR4QIGTnbsb+/kKqSqfgp3WnBwGWAFnedGTtmX1YTn0w== + dependencies: + commander "^2.20.0" + source-map "~0.6.1" + source-map-support "~0.5.12" + +terser@^4.4.3: + version "4.7.0" + resolved "https://registry.yarnpkg.com/terser/-/terser-4.7.0.tgz#15852cf1a08e3256a80428e865a2fa893ffba006" + integrity sha512-Lfb0RiZcjRDXCC3OSHJpEkxJ9Qeqs6mp2v4jf2MHfy8vGERmVDuvjXdd/EnP5Deme5F2yBRBymKmKHCBg2echw== dependencies: - commander "^2.19.0" + commander "^2.20.0" source-map "~0.6.1" - source-map-support "~0.5.10" + source-map-support "~0.5.12" through2@^2.0.0: version "2.0.5" @@ -6008,6 +8636,11 @@ timers-browserify@^2.0.4: dependencies: setimmediate "^1.0.4" +timsort@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/timsort/-/timsort-0.3.0.tgz#405411a8e7e6339fe64db9a234de11dc31e02bd4" + integrity sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q= + tmp@0.0.30: version "0.0.30" resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.30.tgz#72419d4a8be7d6ce75148fd8b324e593a711c2ed" @@ -6020,17 +8653,14 @@ tmp@^0.0.33: dependencies: os-tmpdir "~1.0.2" -to-array@0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/to-array/-/to-array-0.1.4.tgz#17e6c11f73dd4f3d74cda7a4ff3238e9ad9bf890" - to-arraybuffer@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43" -to-fast-properties@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47" +to-fast-properties@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" + integrity sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4= to-object-path@^0.3.0: version "0.3.0" @@ -6045,6 +8675,13 @@ to-regex-range@^2.1.0: is-number "^3.0.0" repeat-string "^1.6.1" +to-regex-range@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== + dependencies: + is-number "^7.0.0" + to-regex@^3.0.1, to-regex@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce" @@ -6062,29 +8699,41 @@ toidentifier@1.0.0: tough-cookie@~2.4.3: version "2.4.3" resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.4.3.tgz#53f36da3f47783b0925afa06ff9f3b165280f781" + integrity sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ== dependencies: psl "^1.1.24" punycode "^1.4.1" -tree-kill@1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/tree-kill/-/tree-kill-1.2.1.tgz#5398f374e2f292b9dcc7b2e71e30a5c3bb6c743a" - integrity sha512-4hjqbObwlh2dLyW4tcz0Ymw0ggoaVDMveUB9w8kFSQScdRLo0gxO9J7WFcUBo+W3C1TLdFIEwNOWebgZZ0RH9Q== +tough-cookie@~2.5.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2" + integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g== + dependencies: + psl "^1.1.28" + punycode "^2.1.1" + +tree-kill@1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/tree-kill/-/tree-kill-1.2.2.tgz#4ca09a9092c88b73a7cdc5e8a01b507b0790a0cc" + integrity sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A== trim-newlines@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-1.0.0.tgz#5887966bb582a4503a41eb524f7d35011815a613" - -trim-right@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003" + integrity sha1-WIeWa7WCpFA6QetST301ARgVphM= "true-case-path@^1.0.2": version "1.0.3" resolved "https://registry.yarnpkg.com/true-case-path/-/true-case-path-1.0.3.tgz#f813b5a8c86b40da59606722b144e3225799f47d" + integrity sha512-m6s2OdQe5wgpFMC+pAJ+q9djG82O2jcHPOI6RNg1yy9rCYR+WD6Nbpl32fDpfC56nirdRy+opFa/Vk7HYhqaew== dependencies: glob "^7.1.2" +ts-md5@^1.2.7: + version "1.2.7" + resolved "https://registry.yarnpkg.com/ts-md5/-/ts-md5-1.2.7.tgz#b76471fc2fd38f0502441f6c3b9494ed04537401" + integrity sha512-emODogvKGWi1KO1l9c6YxLMBn6CEH3VrH5mVPIyOtxBG52BvV4jP3GWz6bOZCz61nLgBc3ffQYE4+EHfCD+V7w== + ts-node@~5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-5.0.1.tgz#78e5d1cb3f704de1b641e43b76be2d4094f06f81" @@ -6098,10 +8747,25 @@ ts-node@~5.0.1: source-map-support "^0.5.3" yn "^2.0.0" -tslib@^1.7.1, tslib@^1.8.0, tslib@^1.8.1, tslib@^1.9.0: +tslib@1.11.1, tslib@^1.9.0: + version "1.11.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.11.1.tgz#eb15d128827fbee2841549e171f45ed338ac7e35" + integrity sha512-aZW88SY8kQbU7gpV19lN24LtXh/yD4ZZg6qieAJDDg+YBsJcSmLGK9QpnUjAKVG/xefmvJGd1WUmfpT/g6AJGA== + +tslib@^1.10.0: + version "1.13.0" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.13.0.tgz#c881e13cc7015894ed914862d276436fa9a47043" + integrity sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q== + +tslib@^1.8.0, tslib@^1.8.1: version "1.9.3" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.3.tgz#d7e4dd79245d85428c4d7e4822a79917954ca286" +tslib@^2.0.0: + version "2.0.3" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.0.3.tgz#8e0741ac45fc0c226e58a17bfc3e64b9bc6ca61c" + integrity sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ== + tslint-angular@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/tslint-angular/-/tslint-angular-1.1.2.tgz#5ce7020968e3b9dc7a40b6d15dadd6da34787309" @@ -6139,12 +8803,19 @@ tty-browserify@0.0.0: tunnel-agent@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" + integrity sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0= dependencies: safe-buffer "^5.0.1" tweetnacl@^0.14.3, tweetnacl@~0.14.0: version "0.14.5" resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" + integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q= + +type-fest@^0.8.1: + version "0.8.1" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" + integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== type-is@~1.6.17, type-is@~1.6.18: version "1.6.18" @@ -6158,15 +8829,43 @@ typedarray@^0.0.6: version "0.0.6" resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" -typescript@3.4.4: - version "3.4.4" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.4.4.tgz#aac4a08abecab8091a75f10842ffa0631818f785" - integrity sha512-xt5RsIRCEaf6+j9AyOBgvVuAec0i92rgCaS3S+UVf5Z/vF2Hvtsw08wtUTJqp4djwznoAgjSxeCcU4r+CcDBJA== +typescript@3.6.5: + version "3.6.5" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.6.5.tgz#dae20114a7b4ff4bd642db9c8c699f2953e8bbdb" + integrity sha512-BEjlc0Z06ORZKbtcxGrIvvwYs5hAnuo6TKdNFL55frVDlB+na3z5bsLhFaIxmT+dPWgBIjMo6aNnTOgHHmHgiQ== + +typescript@~3.8.3: + version "3.8.3" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.8.3.tgz#409eb8544ea0335711205869ec458ab109ee1061" + integrity sha512-MYlEfn5VrLNsgudQTVJeNaQFUAI7DkhnOjdpAp4T+ku1TfQClewlbSuTVHiA+8skNBgaf02TL/kLOvig4y3G8w== + +unicode-canonical-property-names-ecmascript@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz#2619800c4c825800efdd8343af7dd9933cbe2818" + integrity sha512-jDrNnXWHd4oHiTZnx/ZG7gtUTVp+gCcTTKr8L0HjlwphROEW3+Him+IpvC+xcJEFegapiMZyZe02CyuOnRmbnQ== + +unicode-match-property-ecmascript@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-1.0.4.tgz#8ed2a32569961bce9227d09cd3ffbb8fed5f020c" + integrity sha512-L4Qoh15vTfntsn4P1zqnHulG0LdXgjSO035fEpdtp6YxXhMT51Q6vgM5lYdG/5X3MjS+k/Y9Xw4SFCY9IkR0rg== + dependencies: + unicode-canonical-property-names-ecmascript "^1.0.4" + unicode-property-aliases-ecmascript "^1.0.4" + +unicode-match-property-value-ecmascript@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.1.0.tgz#5b4b426e08d13a80365e0d657ac7a6c1ec46a277" + integrity sha512-hDTHvaBk3RmFzvSl0UVrUmC3PuW9wKVnpoUDYH0JDkSIovzw+J5viQmeYHxVSBptubnr7PbH2e0fnpDRQnQl5g== -typescript@~3.4.5: - version "3.4.5" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.4.5.tgz#2d2618d10bb566572b8d7aad5180d84257d70a99" - integrity sha512-YycBxUb49UUhdNMU5aJ7z5Ej2XGmaIBL0x34vZ82fn3hGvD+bgrMrVDpatgz2f7YxUMJxMkbWxJZeAvDxVe7Vw== +unicode-match-property-value-ecmascript@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.2.0.tgz#0d91f600eeeb3096aa962b1d6fc88876e64ea531" + integrity sha512-wjuQHGQVofmSJv1uVISKLE5zO2rNGzM/KCYZch/QQvez7C1hUhBIuZ701fYXExuufJFMPhv2SyL8CyoIfMLbIQ== + +unicode-property-aliases-ecmascript@^1.0.4: + version "1.0.5" + resolved "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.0.5.tgz#a9cc6cc7ce63a0a3023fc99e341b94431d405a57" + integrity sha512-L5RAqCfXqAwR3RriF8pM0lU0w4Ryf/GgzONwi6KnL1taJQa7x1TCxdJnILX59WIGOwR57IVxn7Nej0fz1Ny6fw== union-value@^1.0.0: version "1.0.0" @@ -6177,6 +8876,16 @@ union-value@^1.0.0: is-extendable "^0.1.1" set-value "^0.4.3" +uniq@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/uniq/-/uniq-1.0.1.tgz#b31c5ae8254844a3a8281541ce2b04b865a734ff" + integrity sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8= + +uniqs@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/uniqs/-/uniqs-2.0.0.tgz#ffede4b36b25290696e6e165d4a59edb998e6b02" + integrity sha1-/+3ks2slKQaW5uFl1KWe25mOawI= + unique-filename@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/unique-filename/-/unique-filename-1.1.1.tgz#1d69769369ada0583103a1e6ae87681b56573230" @@ -6189,7 +8898,7 @@ unique-slug@^2.0.0: dependencies: imurmurhash "^0.1.4" -universal-analytics@^0.4.20: +universal-analytics@0.4.20: version "0.4.20" resolved "https://registry.yarnpkg.com/universal-analytics/-/universal-analytics-0.4.20.tgz#d6b64e5312bf74f7c368e3024a922135dbf24b03" integrity sha512-gE91dtMvNkjO+kWsPstHRtSwHXz0l2axqptGYp5ceg4MsuurloM0PU3pdOfpb5zBXUvyjT4PwhWK2m39uczZuw== @@ -6198,10 +8907,20 @@ universal-analytics@^0.4.20: request "^2.88.0" uuid "^3.0.0" +universalify@^0.1.0: + version "0.1.2" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" + integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== + unpipe@1.0.0, unpipe@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" +unquote@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/unquote/-/unquote-1.1.1.tgz#8fded7324ec6e88a0ff8b905e7c098cdc086d544" + integrity sha1-j97XMk7G6IoP+LkF58CYzcCG1UQ= + unset-value@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559" @@ -6221,6 +8940,7 @@ upath@^1.1.1: uri-js@^4.2.2: version "4.2.2" resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.2.2.tgz#94c540e1ff772956e2299507c010aea6c8838eb0" + integrity sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ== dependencies: punycode "^2.1.0" @@ -6229,10 +8949,11 @@ urix@^0.1.0: resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" url-parse@^1.4.3: - version "1.4.4" - resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.4.4.tgz#cac1556e95faa0303691fec5cf9d5a1bc34648f8" + version "1.4.7" + resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.4.7.tgz#a8a83535e8c00a316e403a5db4ac1b9b853ae278" + integrity sha512-d3uaVyzDB9tQoSXFvuSUNFibTd9zxd2bkVrDRvF5TmvWWQwqE4lgYJ5m+x1DbecWkw+LK4RNl2CU1hHuOKPVlg== dependencies: - querystringify "^2.0.0" + querystringify "^2.1.1" requires-port "^1.0.0" url@^0.11.0: @@ -6249,6 +8970,24 @@ use@^3.1.0: util-deprecate@^1.0.1, util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= + +util-promisify@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/util-promisify/-/util-promisify-2.1.0.tgz#3c2236476c4d32c5ff3c47002add7c13b9a82a53" + integrity sha1-PCI2R2xNMsX/PEcAKt18E7moKlM= + dependencies: + object.getownpropertydescriptors "^2.0.3" + +util.promisify@~1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/util.promisify/-/util.promisify-1.0.1.tgz#6baf7774b80eeb0f7520d8b81d07982a59abbaee" + integrity sha512-g9JpC/3He3bm38zsLupWryXHoEcS22YHthuPQSJdMy6KNrzIRzWqcsHzD/WUnqe45whVou4VIsPew37DoXWNrA== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.17.2" + has-symbols "^1.0.1" + object.getownpropertydescriptors "^2.1.0" util@0.10.3: version "0.10.3" @@ -6266,13 +9005,24 @@ utils-merge@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" -uuid@^3.0.0, uuid@^3.0.1, uuid@^3.1.0, uuid@^3.3.2: +uuid@7.0.2: + version "7.0.2" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-7.0.2.tgz#7ff5c203467e91f5e0d85cfcbaaf7d2ebbca9be6" + integrity sha512-vy9V/+pKG+5ZTYKf+VcphF5Oc6EFiu3W8Nv3P3zIh0EqVI80ZxOzuPfe9EHjkFNvf8+xuTHVeei4Drydlx4zjw== + +uuid@^3.0.0, uuid@^3.0.1: version "3.3.2" resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131" +uuid@^3.3.2: + version "3.4.0" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" + integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== + validate-npm-package-license@^3.0.1: version "3.0.4" resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" + integrity sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew== dependencies: spdx-correct "^3.0.0" spdx-expression-parse "^3.0.0" @@ -6287,23 +9037,29 @@ vary@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" +vendors@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/vendors/-/vendors-1.0.4.tgz#e2b800a53e7a29b93506c3cf41100d16c4c4ad8e" + integrity sha512-/juG65kTL4Cy2su4P8HjtkTxk6VmJDiOPBufWniqQ6wknac6jNiXS9vU+hO3wgusiyqWlzTbVHi0dyJqRONg3w== + verror@1.10.0: version "1.10.0" resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" + integrity sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA= dependencies: assert-plus "^1.0.0" core-util-is "1.0.2" extsprintf "^1.2.0" -vm-browserify@0.0.4: - version "0.0.4" - resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-0.0.4.tgz#5d7ea45bbef9e4a6ff65f95438e0a87c357d5a73" - dependencies: - indexof "0.0.1" +vm-browserify@^1.0.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-1.1.2.tgz#78641c488b8e6ca91a75f511e7a3b32a86e5dda0" + integrity sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ== -watchpack@^1.5.0: +watchpack@^1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-1.6.0.tgz#4bc12c2ebe8aa277a71f1d3f14d685c7b446cd00" + integrity sha512-i6dHe3EyLjMmDlU1/bGQpEw25XSjkJULPuAVKCbNRefQVq48yXKUpwg538F7AZTf9kyr57zj++pQFltUa5H7yA== dependencies: chokidar "^2.0.2" graceful-fs "^4.1.2" @@ -6315,6 +9071,13 @@ wbuf@^1.1.0, wbuf@^1.7.3: dependencies: minimalistic-assert "^1.0.0" +wcwidth@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/wcwidth/-/wcwidth-1.0.1.tgz#f0b0dcf915bc5ff1528afadb2c0e17b532da2fe8" + integrity sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g= + dependencies: + defaults "^1.0.3" + webdriver-js-extender@2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/webdriver-js-extender/-/webdriver-js-extender-2.1.0.tgz#57d7a93c00db4cc8d556e4d3db4b5db0a80c3bb7" @@ -6338,78 +9101,56 @@ webdriver-manager@^12.0.6: semver "^5.3.0" xml2js "^0.4.17" -webpack-core@^0.6.8: - version "0.6.9" - resolved "https://registry.yarnpkg.com/webpack-core/-/webpack-core-0.6.9.tgz#fc571588c8558da77be9efb6debdc5a3b172bdc2" - dependencies: - source-list-map "~0.1.7" - source-map "~0.4.1" - -webpack-dev-middleware@3.6.2: - version "3.6.2" - resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-3.6.2.tgz#f37a27ad7c09cd7dc67cd97655413abaa1f55942" - integrity sha512-A47I5SX60IkHrMmZUlB0ZKSWi29TZTcPz7cha1Z75yYOsgWh/1AcPmQEbC8ZIbU3A1ytSv1PMU0PyPz2Lmz2jg== - dependencies: - memory-fs "^0.4.1" - mime "^2.3.1" - range-parser "^1.0.3" - webpack-log "^2.0.0" - -webpack-dev-middleware@^3.6.2: - version "3.7.0" - resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-3.7.0.tgz#ef751d25f4e9a5c8a35da600c5fda3582b5c6cff" - integrity sha512-qvDesR1QZRIAZHOE3iQ4CXLZZSQ1lAUsSpnQmlB1PBfoN/xdRjmge3Dok0W4IdaVLJOGJy3sGI4sZHwjRU0PCA== +webpack-dev-middleware@3.7.2, webpack-dev-middleware@^3.7.2: + version "3.7.2" + resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-3.7.2.tgz#0019c3db716e3fa5cecbf64f2ab88a74bab331f3" + integrity sha512-1xC42LxbYoqLNAhV6YzTYacicgMZQTqRd27Sim9wn5hJrX3I5nxYy1SxSd4+gjUFsz1dQFj+yEe6zEVmSkeJjw== dependencies: memory-fs "^0.4.1" - mime "^2.4.2" + mime "^2.4.4" + mkdirp "^0.5.1" range-parser "^1.2.1" webpack-log "^2.0.0" -webpack-dev-server@3.3.1: - version "3.3.1" - resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-3.3.1.tgz#7046e49ded5c1255a82c5d942bcdda552b72a62d" - integrity sha512-jY09LikOyGZrxVTXK0mgIq9y2IhCoJ05848dKZqX1gAGLU1YDqgpOT71+W53JH/wI4v6ky4hm+KvSyW14JEs5A== +webpack-dev-server@3.10.3: + version "3.10.3" + resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-3.10.3.tgz#f35945036813e57ef582c2420ef7b470e14d3af0" + integrity sha512-e4nWev8YzEVNdOMcNzNeCN947sWJNd43E5XvsJzbAL08kGc2frm1tQ32hTJslRS+H65LCb/AaUCYU7fjHCpDeQ== dependencies: ansi-html "0.0.7" bonjour "^3.5.0" - chokidar "^2.1.5" + chokidar "^2.1.8" compression "^1.7.4" connect-history-api-fallback "^1.6.0" debug "^4.1.1" - del "^4.1.0" - express "^4.16.4" + del "^4.1.1" + express "^4.17.1" html-entities "^1.2.1" - http-proxy-middleware "^0.19.1" + http-proxy-middleware "0.19.1" import-local "^2.0.0" - internal-ip "^4.2.0" + internal-ip "^4.3.0" ip "^1.1.5" + is-absolute-url "^3.0.3" killable "^1.0.1" - loglevel "^1.6.1" + loglevel "^1.6.6" opn "^5.5.0" - portfinder "^1.0.20" + p-retry "^3.0.1" + portfinder "^1.0.25" schema-utils "^1.0.0" - selfsigned "^1.10.4" - semver "^6.0.0" + selfsigned "^1.10.7" + semver "^6.3.0" serve-index "^1.9.1" sockjs "0.3.19" - sockjs-client "1.3.0" - spdy "^4.0.0" + sockjs-client "1.4.0" + spdy "^4.0.1" strip-ansi "^3.0.1" supports-color "^6.1.0" url "^0.11.0" - webpack-dev-middleware "^3.6.2" + webpack-dev-middleware "^3.7.2" webpack-log "^2.0.0" + ws "^6.2.1" yargs "12.0.5" -webpack-log@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/webpack-log/-/webpack-log-1.2.0.tgz#a4b34cda6b22b518dbb0ab32e567962d5c72a43d" - dependencies: - chalk "^2.1.0" - log-symbols "^2.1.0" - loglevelnext "^1.0.1" - uuid "^3.1.0" - webpack-log@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/webpack-log/-/webpack-log-2.0.0.tgz#5b7928e0637593f119d32f6227c1e0ac31e1b47f" @@ -6417,55 +9158,63 @@ webpack-log@^2.0.0: ansi-colors "^3.0.0" uuid "^3.3.2" -webpack-merge@4.2.1: - version "4.2.1" - resolved "https://registry.yarnpkg.com/webpack-merge/-/webpack-merge-4.2.1.tgz#5e923cf802ea2ace4fd5af1d3247368a633489b4" - integrity sha512-4p8WQyS98bUJcCvFMbdGZyZmsKuWjWVnVHnAS3FFg0HDaRVrPbkivx2RYCre8UiemD67RsiFFLfn4JhLAin8Vw== +webpack-merge@4.2.2: + version "4.2.2" + resolved "https://registry.yarnpkg.com/webpack-merge/-/webpack-merge-4.2.2.tgz#a27c52ea783d1398afd2087f547d7b9d2f43634d" + integrity sha512-TUE1UGoTX2Cd42j3krGYqObZbOD+xF7u28WB7tfUordytSjbWTIjK/8V0amkBfTYN4/pB/GIDlJZZ657BGG19g== dependencies: - lodash "^4.17.5" + lodash "^4.17.15" + +webpack-sources@1.4.3, webpack-sources@^1.3.0, webpack-sources@^1.4.0, webpack-sources@^1.4.1, webpack-sources@^1.4.3: + version "1.4.3" + resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-1.4.3.tgz#eedd8ec0b928fbf1cbfe994e22d2d890f330a933" + integrity sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ== + dependencies: + source-list-map "^2.0.0" + source-map "~0.6.1" -webpack-sources@1.3.0, webpack-sources@^1.1.0, webpack-sources@^1.2.0, webpack-sources@^1.3.0: +webpack-sources@^1.1.0, webpack-sources@^1.2.0: version "1.3.0" resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-1.3.0.tgz#2a28dcb9f1f45fe960d8f1493252b5ee6530fa85" dependencies: source-list-map "^2.0.0" source-map "~0.6.1" -webpack-subresource-integrity@1.1.0-rc.6: - version "1.1.0-rc.6" - resolved "https://registry.yarnpkg.com/webpack-subresource-integrity/-/webpack-subresource-integrity-1.1.0-rc.6.tgz#37f6f1264e1eb378e41465a98da80fad76ab8886" +webpack-subresource-integrity@1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/webpack-subresource-integrity/-/webpack-subresource-integrity-1.4.0.tgz#44963a64c9a214ad729158e7f46d52c2525cc88a" + integrity sha512-GB1kB/LwAWC3CxwcedGhMkxGpNZxSheCe1q+KJP1bakuieAdX/rGHEcf5zsEzhKXpqsGqokgsDoD9dIkr61VDQ== dependencies: - webpack-core "^0.6.8" + webpack-sources "^1.3.0" -webpack@4.30.0: - version "4.30.0" - resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.30.0.tgz#aca76ef75630a22c49fcc235b39b4c57591d33a9" - integrity sha512-4hgvO2YbAFUhyTdlR4FNyt2+YaYBYHavyzjCMbZzgglo02rlKi/pcsEzwCuCpsn1ryzIl1cq/u8ArIKu8JBYMg== +webpack@4.42.0: + version "4.42.0" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.42.0.tgz#b901635dd6179391d90740a63c93f76f39883eb8" + integrity sha512-EzJRHvwQyBiYrYqhyjW9AqM90dE4+s1/XtCfn7uWg6cS72zH+2VPFAlsnW0+W0cDi0XRjNKUMoJtpSi50+Ph6w== dependencies: "@webassemblyjs/ast" "1.8.5" "@webassemblyjs/helper-module-context" "1.8.5" "@webassemblyjs/wasm-edit" "1.8.5" "@webassemblyjs/wasm-parser" "1.8.5" - acorn "^6.0.5" - acorn-dynamic-import "^4.0.0" - ajv "^6.1.0" - ajv-keywords "^3.1.0" - chrome-trace-event "^1.0.0" + acorn "^6.2.1" + ajv "^6.10.2" + ajv-keywords "^3.4.1" + chrome-trace-event "^1.0.2" enhanced-resolve "^4.1.0" - eslint-scope "^4.0.0" + eslint-scope "^4.0.3" json-parse-better-errors "^1.0.2" - loader-runner "^2.3.0" - loader-utils "^1.1.0" - memory-fs "~0.4.1" - micromatch "^3.1.8" - mkdirp "~0.5.0" - neo-async "^2.5.0" - node-libs-browser "^2.0.0" + loader-runner "^2.4.0" + loader-utils "^1.2.3" + memory-fs "^0.4.1" + micromatch "^3.1.10" + mkdirp "^0.5.1" + neo-async "^2.6.1" + node-libs-browser "^2.2.1" schema-utils "^1.0.0" - tapable "^1.1.0" - terser-webpack-plugin "^1.1.0" - watchpack "^1.5.0" - webpack-sources "^1.3.0" + tapable "^1.1.3" + terser-webpack-plugin "^1.4.3" + watchpack "^1.6.0" + webpack-sources "^1.4.1" websocket-driver@>=0.5.1: version "0.7.0" @@ -6478,10 +9227,6 @@ websocket-extensions@>=0.1.1: version "0.1.3" resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.3.tgz#5d2ff22977003ec687a4b87073dfbbac146ccf29" -whatwg-fetch@>=0.10.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.0.0.tgz#fc804e458cc460009b1a2b966bc8817d2578aefb" - when@~3.6.x: version "3.6.4" resolved "https://registry.yarnpkg.com/when/-/when-3.6.4.tgz#473b517ec159e2b85005497a13983f095412e34e" @@ -6489,6 +9234,7 @@ when@~3.6.x: which-module@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/which-module/-/which-module-1.0.0.tgz#bba63ca861948994ff307736089e3b96026c2a4f" + integrity sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8= which-module@^2.0.0: version "2.0.0" @@ -6497,12 +9243,14 @@ which-module@^2.0.0: which@1, which@^1.2.9, which@^1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" + integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== dependencies: isexe "^2.0.0" wide-align@^1.1.0: version "1.1.3" resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" + integrity sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA== dependencies: string-width "^1.0.2 || 2" @@ -6510,12 +9258,6 @@ wordwrap@~0.0.2: version "0.0.3" resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107" -worker-farm@^1.5.2: - version "1.6.0" - resolved "https://registry.yarnpkg.com/worker-farm/-/worker-farm-1.6.0.tgz#aecc405976fab5a95526180846f0dba288f3a4a0" - dependencies: - errno "~0.1.7" - worker-farm@^1.7.0: version "1.7.0" resolved "https://registry.yarnpkg.com/worker-farm/-/worker-farm-1.7.0.tgz#26a94c5391bbca926152002f69b84a4bf772e5a8" @@ -6523,33 +9265,64 @@ worker-farm@^1.7.0: dependencies: errno "~0.1.7" -worker-plugin@3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/worker-plugin/-/worker-plugin-3.1.0.tgz#6311778f3514a87c273510ee3f809cc3fe161e6f" - integrity sha512-iQ9KTTmmN5fhfc2KMR7CcDblvcrg1QQ4pXymqZ3cRZF8L0890YLBcEqlIsGPdxoFwghyN8RA1pCEhCKuTF4Lkw== +worker-plugin@4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/worker-plugin/-/worker-plugin-4.0.3.tgz#7c42e600d5931ad154d3d5f187a32446df64db0f" + integrity sha512-7hFDYWiKcE3yHZvemsoM9lZis/PzurHAEX1ej8PLCu818Rt6QqUAiDdxHPCKZctzmhqzPpcFSgvMCiPbtooqAg== dependencies: loader-utils "^1.1.0" wrap-ansi@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85" + integrity sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU= dependencies: string-width "^1.0.1" strip-ansi "^3.0.1" +wrap-ansi@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-5.1.0.tgz#1fd1f67235d5b6d0fee781056001bfb694c03b09" + integrity sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q== + dependencies: + ansi-styles "^3.2.0" + string-width "^3.0.0" + strip-ansi "^5.0.0" + +wrap-ansi@^6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53" + integrity sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= -ws@^6.0.0, ws@~6.1.0: - version "6.1.2" - resolved "https://registry.yarnpkg.com/ws/-/ws-6.1.2.tgz#3cc7462e98792f0ac679424148903ded3b9c3ad8" +ws@^6.0.0, ws@^6.2.1: + version "6.2.1" + resolved "https://registry.yarnpkg.com/ws/-/ws-6.2.1.tgz#442fdf0a47ed64f59b6a5d8ff130f4748ed524fb" + integrity sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA== dependencies: async-limiter "~1.0.0" -xhr2@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/xhr2/-/xhr2-0.1.4.tgz#7f87658847716db5026323812f818cadab387a5f" +xhr2@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/xhr2/-/xhr2-0.2.0.tgz#eddeff782f3b7551061b8d75645085269396e521" + integrity sha512-BDtiD0i2iKPK/S8OAZfpk6tyzEDnKKSjxWHcMBVmh+LuqJ8A32qXTyOx+TVOg2dKvq6zGBq2sgKPkEeRs1qTRA== xml2js@^0.4.17: version "0.4.19" @@ -6562,10 +9335,6 @@ xmlbuilder@~9.0.1: version "9.0.7" resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-9.0.7.tgz#132ee63d2ec5565c557e20f4c22df9aca686b10d" -xmlhttprequest-ssl@~1.5.4: - version "1.5.5" - resolved "https://registry.yarnpkg.com/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz#c2876b06168aadc40e57d97e81191ac8f4398b3e" - xtend@^4.0.0, xtend@~4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" @@ -6573,19 +9342,31 @@ xtend@^4.0.0, xtend@~4.0.1: y18n@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.1.tgz#6d15fba884c08679c0d77e88e7759e811e07fa41" + integrity sha1-bRX7qITAhnnA136I53WegR4H+kE= "y18n@^3.2.1 || ^4.0.0", y18n@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b" +y18n@^5.0.5: + version "5.0.5" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.5.tgz#8769ec08d03b1ea2df2500acef561743bbb9ab18" + integrity sha512-hsRUr4FFrvhhRH12wOdfs38Gy7k2FFzB9qgN9v3aLykRq0dRcdcpz5C9FxdS2NuhOrI/628b/KSTJ3rwHysYSg== + yallist@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" + integrity sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI= yallist@^3.0.0, yallist@^3.0.2, yallist@^3.0.3: version "3.0.3" resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.0.3.tgz#b4b049e314be545e3ce802236d6cd22cd91c3de9" +yallist@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" + integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== + yargs-parser@^11.1.1: version "11.1.1" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-11.1.1.tgz#879a0865973bca9f6bab5cbdf3b1c67ec7d3bcf4" @@ -6594,17 +9375,31 @@ yargs-parser@^11.1.1: camelcase "^5.0.0" decamelize "^1.2.0" -yargs-parser@^13.0.0: - version "13.1.0" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.0.tgz#7016b6dd03e28e1418a510e258be4bff5a31138f" - integrity sha512-Yq+32PrijHRri0vVKQEm+ys8mbqWjLiwQkMFNXEENutzLPP0bE4Lcd4iA3OQY5HF+GD3xXxf0MEHb8E4/SA3AA== +yargs-parser@^13.1.1: + version "13.1.1" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.1.tgz#d26058532aa06d365fe091f6a1fc06b2f7e5eca0" + integrity sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ== + dependencies: + camelcase "^5.0.0" + decamelize "^1.2.0" + +yargs-parser@^18.1.0: + version "18.1.3" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-18.1.3.tgz#be68c4975c6b2abf469236b0c870362fab09a7b0" + integrity sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ== dependencies: camelcase "^5.0.0" decamelize "^1.2.0" +yargs-parser@^20.2.2: + version "20.2.4" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.4.tgz#b42890f14566796f85ae8e3a25290d205f154a54" + integrity sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA== + yargs-parser@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-5.0.0.tgz#275ecf0d7ffe05c77e64e7c86e4cd94bf0e1228a" + integrity sha1-J17PDX/+Bcd+ZOfIbkzZS/DhIoo= dependencies: camelcase "^3.0.0" @@ -6626,26 +9421,56 @@ yargs@12.0.5: y18n "^3.2.1 || ^4.0.0" yargs-parser "^11.1.1" -yargs@13.1.0: - version "13.1.0" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.1.0.tgz#b2729ce4bfc0c584939719514099d8a916ad2301" - integrity sha512-1UhJbXfzHiPqkfXNHYhiz79qM/kZqjTE8yGlEjZa85Q+3+OwcV6NRkV7XOV1W2Eom2bzILeUn55pQYffjVOLAg== +yargs@15.3.0: + version "15.3.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.3.0.tgz#403af6edc75b3ae04bf66c94202228ba119f0976" + integrity sha512-g/QCnmjgOl1YJjGsnUg2SatC7NUYEiLXJqxNOQU9qSpjzGtGXda9b+OKccr1kLTy8BN9yqEyqfq5lxlwdc13TA== dependencies: - cliui "^4.0.0" + cliui "^6.0.0" + decamelize "^1.2.0" + find-up "^4.1.0" + get-caller-file "^2.0.1" + require-directory "^2.1.1" + require-main-filename "^2.0.0" + set-blocking "^2.0.0" + string-width "^4.2.0" + which-module "^2.0.0" + y18n "^4.0.0" + yargs-parser "^18.1.0" + +yargs@^13.2.4: + version "13.3.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.3.0.tgz#4c657a55e07e5f2cf947f8a366567c04a0dedc83" + integrity sha512-2eehun/8ALW8TLoIl7MVaRUrg+yCnenu8B4kBlRxj3GJGDKU1Og7sMXPNm1BYyM1DOJmTZ4YeN/Nwxv+8XJsUA== + dependencies: + cliui "^5.0.0" find-up "^3.0.0" get-caller-file "^2.0.1" - os-locale "^3.1.0" require-directory "^2.1.1" require-main-filename "^2.0.0" set-blocking "^2.0.0" string-width "^3.0.0" which-module "^2.0.0" y18n "^4.0.0" - yargs-parser "^13.0.0" + yargs-parser "^13.1.1" + +yargs@^16.1.1: + version "16.1.1" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.1.1.tgz#5a4a095bd1ca806b0a50d0c03611d38034d219a1" + integrity sha512-hAD1RcFP/wfgfxgMVswPE+z3tlPFtxG8/yWUrG2i17sTWGCGqWnxKcLTF4cUKDUK8fzokwsmO9H0TDkRbMHy8w== + dependencies: + cliui "^7.0.2" + escalade "^3.1.1" + get-caller-file "^2.0.5" + require-directory "^2.1.1" + string-width "^4.2.0" + y18n "^5.0.5" + yargs-parser "^20.2.2" yargs@^7.0.0: version "7.1.0" resolved "https://registry.yarnpkg.com/yargs/-/yargs-7.1.0.tgz#6ba318eb16961727f5d284f8ea003e8d6154d0c8" + integrity sha1-a6MY6xaWFyf10oT46gA+jWFU0Mg= dependencies: camelcase "^3.0.0" cliui "^3.2.0" @@ -6661,15 +9486,11 @@ yargs@^7.0.0: y18n "^3.2.1" yargs-parser "^5.0.0" -yeast@0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/yeast/-/yeast-0.1.2.tgz#008e06d8094320c372dbc2f8ed76a0ca6c8ac419" - yn@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/yn/-/yn-2.0.0.tgz#e5adabc8acf408f6385fc76495684c88e6af689a" -zone.js@^0.9.1: - version "0.9.1" - resolved "https://registry.yarnpkg.com/zone.js/-/zone.js-0.9.1.tgz#e37c6e5c54c13fae4de26b5ffe8d8e9212da6d9b" - integrity sha512-GkPiJL8jifSrKReKaTZ5jkhrMEgXbXYC+IPo1iquBjayRa0q86w3Dipjn8b415jpitMExe9lV8iTsv8tk3DGag== +zone.js@~0.10.2: + version "0.10.3" + resolved "https://registry.yarnpkg.com/zone.js/-/zone.js-0.10.3.tgz#3e5e4da03c607c9dcd92e37dd35687a14a140c16" + integrity sha512-LXVLVEq0NNOqK/fLJo3d0kfzd4sxwn2/h67/02pjCjfKDxgx1i9QqpvtHD8CrBnSSwMw5+dy11O7FRX5mkO7Cg== diff --git a/src/Ombi/Config/UserSettings.cs b/src/Ombi/Config/UserSettings.cs deleted file mode 100644 index 49ccadb95..000000000 --- a/src/Ombi/Config/UserSettings.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace Ombi.Config -{ - public class UserSettings - { - public string WebsiteUrl { get; set; } - public bool UseHttps { get; set; } - } -} \ No newline at end of file diff --git a/src/Ombi/Controllers/V1/External/EmbyController.cs b/src/Ombi/Controllers/V1/External/EmbyController.cs index d8ef5c158..29ad84eb2 100644 --- a/src/Ombi/Controllers/V1/External/EmbyController.cs +++ b/src/Ombi/Controllers/V1/External/EmbyController.cs @@ -19,18 +19,14 @@ namespace Ombi.Controllers.V1.External [Produces("application/json")] public class EmbyController : Controller { - /// - /// - /// - /// - /// - public EmbyController(IEmbyApi emby, ISettingsService embySettings) + + public EmbyController(IEmbyApiFactory emby, ISettingsService embySettings) { EmbyApi = emby; EmbySettings = embySettings; } - private IEmbyApi EmbyApi { get; } + private IEmbyApiFactory EmbyApi { get; } private ISettingsService EmbySettings { get; } /// @@ -46,10 +42,11 @@ namespace Ombi.Controllers.V1.External var settings = await EmbySettings.GetSettingsAsync(); if (settings?.Servers?.Any() ?? false) return null; + var client = await EmbyApi.CreateClient(); request.Enable = true; var firstServer = request.Servers.FirstOrDefault(); // Test that we can connect - var result = await EmbyApi.GetUsers(firstServer.FullUri, firstServer.ApiKey); + var result = await client.GetUsers(firstServer.FullUri, firstServer.ApiKey); if (result != null && result.Any()) { @@ -64,7 +61,8 @@ namespace Ombi.Controllers.V1.External [HttpPost("info")] public async Task GetServerInfo([FromBody] EmbyServers server) { - var result = await EmbyApi.GetPublicInformation(server.FullUri); + var client = await EmbyApi.CreateClient(); + var result = await client.GetPublicInformation(server.FullUri); return result; } @@ -77,9 +75,10 @@ namespace Ombi.Controllers.V1.External { var vm = new List(); var s = await EmbySettings.GetSettingsAsync(); + var client = EmbyApi.CreateClient(s); foreach (var server in s?.Servers ?? new List()) { - var users = await EmbyApi.GetUsers(server.FullUri, server.ApiKey); + var users = await client.GetUsers(server.FullUri, server.ApiKey); if (users != null && users.Any()) { vm.AddRange(users.Select(u => new UsersViewModel diff --git a/src/Ombi/Controllers/V1/External/RadarrController.cs b/src/Ombi/Controllers/V1/External/RadarrController.cs index 1f3cf3118..993b37d41 100644 --- a/src/Ombi/Controllers/V1/External/RadarrController.cs +++ b/src/Ombi/Controllers/V1/External/RadarrController.cs @@ -16,18 +16,21 @@ namespace Ombi.Controllers.V1.External [ApiController] [Produces("application/json")] public class RadarrController : ControllerBase - { + { + public RadarrController(IRadarrApi radarr, ISettingsService settings, - ICacheService mem) + ICacheService mem, IRadarrV3Api radarrV3Api) { - RadarrApi = radarr; - RadarrSettings = settings; - Cache = mem; + _radarrApi = radarr; + _radarrSettings = settings; + _cache = mem; + _radarrV3Api = radarrV3Api; } - private IRadarrApi RadarrApi { get; } - private ISettingsService RadarrSettings { get; } - private ICacheService Cache { get; } + private readonly IRadarrApi _radarrApi; + private readonly ISettingsService _radarrSettings; + private readonly ICacheService _cache; + private readonly IRadarrV3Api _radarrV3Api; /// /// Gets the Radarr profiles. /// @@ -35,16 +38,20 @@ namespace Ombi.Controllers.V1.External /// [HttpPost("Profiles")] [PowerUser] - public async Task> GetProfiles([FromBody] RadarrSettings settings) + public async Task GetProfiles([FromBody] RadarrSettings settings) { - return await RadarrApi.GetProfiles(settings.ApiKey, settings.FullUri); + if (settings.V3) + { + return Ok(await _radarrV3Api.GetProfiles(settings.ApiKey, settings.FullUri)); + } + return Ok(await _radarrApi.GetProfiles(settings.ApiKey, settings.FullUri)); } [HttpGet("enabled")] [PowerUser] public async Task Enabled() { - var settings = await RadarrSettings.GetSettingsAsync(); + var settings = await _radarrSettings.GetSettingsAsync(); return settings.Enabled; } @@ -57,7 +64,11 @@ namespace Ombi.Controllers.V1.External [PowerUser] public async Task> GetRootFolders([FromBody] RadarrSettings settings) { - return await RadarrApi.GetRootFolders(settings.ApiKey, settings.FullUri); + if (settings.V3) + { + return await _radarrV3Api.GetRootFolders(settings.ApiKey, settings.FullUri); + } + return await _radarrApi.GetRootFolders(settings.ApiKey, settings.FullUri); } /// @@ -67,12 +78,16 @@ namespace Ombi.Controllers.V1.External /// [HttpGet("Profiles")] [PowerUser] - public async Task> GetProfiles() + public async Task GetProfiles() { - var settings = await RadarrSettings.GetSettingsAsync(); + var settings = await _radarrSettings.GetSettingsAsync(); if (settings.Enabled) { - return await RadarrApi.GetProfiles(settings.ApiKey, settings.FullUri); + if (settings.V3) + { + return Ok(await _radarrV3Api.GetProfiles(settings.ApiKey, settings.FullUri)); + } + return Ok(await _radarrApi.GetProfiles(settings.ApiKey, settings.FullUri)); } return null; } @@ -86,14 +101,18 @@ namespace Ombi.Controllers.V1.External [PowerUser] public async Task> GetRootFolders() { - var settings = await RadarrSettings.GetSettingsAsync(); + var settings = await _radarrSettings.GetSettingsAsync(); if (settings.Enabled) { - return await RadarrApi.GetRootFolders(settings.ApiKey, settings.FullUri); + if (settings.V3) + { + return await _radarrV3Api.GetRootFolders(settings.ApiKey, settings.FullUri); + } + return await _radarrApi.GetRootFolders(settings.ApiKey, settings.FullUri); } return null; } - + /// /// Gets the Radarr tags /// @@ -103,23 +122,22 @@ namespace Ombi.Controllers.V1.External [PowerUser] public async Task> GetTags([FromBody] SonarrSettings settings) { - return await RadarrApi.GetTags(settings.ApiKey, settings.FullUri); + return await _radarrV3Api.GetTags(settings.ApiKey, settings.FullUri); } - + /// /// Gets the Radarr tags /// - /// The settings. /// - [HttpPost("tags")] + [HttpGet("tags")] [PowerUser] public async Task> GetTags() { - var settings = await RadarrSettings.GetSettingsAsync(); + var settings = await _radarrSettings.GetSettingsAsync(); if (settings.Enabled) { - return await RadarrApi.GetTags(settings.ApiKey, settings.FullUri); + return await _radarrV3Api.GetTags(settings.ApiKey, settings.FullUri); } return null; diff --git a/src/Ombi/Controllers/V1/External/SonarrController.cs b/src/Ombi/Controllers/V1/External/SonarrController.cs index 97b2bde0f..bdcbb7edb 100644 --- a/src/Ombi/Controllers/V1/External/SonarrController.cs +++ b/src/Ombi/Controllers/V1/External/SonarrController.cs @@ -117,9 +117,8 @@ namespace Ombi.Controllers.V1.External /// /// Gets the Sonarr tags /// - /// The settings. /// - [HttpPost("tags")] + [HttpGet("tags")] [PowerUser] public async Task> GetTags() { @@ -144,5 +143,13 @@ namespace Ombi.Controllers.V1.External return await SonarrV3Api.LanguageProfiles(settings.ApiKey, settings.FullUri); } + [HttpGet("enabled")] + [PowerUser] + public async Task Enabled() + { + var settings = await SonarrSettings.GetSettingsAsync(); + return settings.Enabled; + } + } } \ No newline at end of file diff --git a/src/Ombi/Controllers/V1/External/TesterController.cs b/src/Ombi/Controllers/V1/External/TesterController.cs index 5a52adfb1..0dbaac688 100644 --- a/src/Ombi/Controllers/V1/External/TesterController.cs +++ b/src/Ombi/Controllers/V1/External/TesterController.cs @@ -2,6 +2,7 @@ using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; using Ombi.Api.CouchPotato; using Ombi.Api.Emby; @@ -10,7 +11,9 @@ using Ombi.Api.Plex; using Ombi.Api.Radarr; using Ombi.Api.SickRage; using Ombi.Api.Sonarr; +using Ombi.Api.Twilio; using Ombi.Attributes; +using Ombi.Core.Authentication; using Ombi.Core.Models.UI; using Ombi.Core.Notifications; using Ombi.Core.Settings.Models.External; @@ -22,6 +25,7 @@ using Ombi.Notifications.Models; using Ombi.Schedule.Jobs.Ombi; using Ombi.Settings.Settings.Models.External; using Ombi.Settings.Settings.Models.Notifications; +using Ombi.Store.Entities; namespace Ombi.Controllers.V1.External { @@ -38,9 +42,9 @@ namespace Ombi.Controllers.V1.External /// public TesterController(INotificationService service, IDiscordNotification notification, IEmailNotification emailN, IPushbulletNotification pushbullet, ISlackNotification slack, IPushoverNotification po, IMattermostNotification mm, - IPlexApi plex, IEmbyApi emby, IRadarrApi radarr, ISonarrApi sonarr, ILogger log, IEmailProvider provider, - ICouchPotatoApi cpApi, ITelegramNotification telegram, ISickRageApi srApi, INewsletterJob newsletter, IMobileNotification mobileNotification, - ILidarrApi lidarrApi, IGotifyNotification gotifyNotification) + IPlexApi plex, IEmbyApiFactory emby, IRadarrApi radarr, ISonarrApi sonarr, ILogger log, IEmailProvider provider, + ICouchPotatoApi cpApi, ITelegramNotification telegram, ISickRageApi srApi, INewsletterJob newsletter, ILegacyMobileNotification mobileNotification, + ILidarrApi lidarrApi, IGotifyNotification gotifyNotification, IWhatsAppApi whatsAppApi, OmbiUserManager um, IWebhookNotification webhookNotification) { Service = service; DiscordNotification = notification; @@ -62,6 +66,9 @@ namespace Ombi.Controllers.V1.External MobileNotification = mobileNotification; LidarrApi = lidarrApi; GotifyNotification = gotifyNotification; + WhatsAppApi = whatsAppApi; + UserManager = um; + WebhookNotification = webhookNotification; } private INotificationService Service { get; } @@ -71,10 +78,11 @@ namespace Ombi.Controllers.V1.External private ISlackNotification SlackNotification { get; } private IPushoverNotification PushoverNotification { get; } private IGotifyNotification GotifyNotification { get; } + private IWebhookNotification WebhookNotification { get; } private IMattermostNotification MattermostNotification { get; } private IPlexApi PlexApi { get; } private IRadarrApi RadarrApi { get; } - private IEmbyApi EmbyApi { get; } + private IEmbyApiFactory EmbyApi { get; } private ISonarrApi SonarrApi { get; } private ICouchPotatoApi CouchPotatoApi { get; } private ILogger Log { get; } @@ -82,9 +90,10 @@ namespace Ombi.Controllers.V1.External private ITelegramNotification TelegramNotification { get; } private ISickRageApi SickRageApi { get; } private INewsletterJob Newsletter { get; } - private IMobileNotification MobileNotification { get; } + private ILegacyMobileNotification MobileNotification { get; } private ILidarrApi LidarrApi { get; } - + private IWhatsAppApi WhatsAppApi { get; } + private OmbiUserManager UserManager {get;} /// /// Sends a test message to discord using the provided settings @@ -181,6 +190,30 @@ namespace Ombi.Controllers.V1.External } + /// + /// Sends a test message to configured webhook using the provided settings + /// + /// The settings. + /// + [HttpPost("webhook")] + public bool Webhook([FromBody] WebhookSettings settings) + { + try + { + settings.Enabled = true; + WebhookNotification.NotifyAsync( + new NotificationOptions { NotificationType = NotificationType.Test, RequestId = -1 }, settings); + + return true; + } + catch (Exception e) + { + Log.LogError(LoggingEvents.Api, e, "Could not test your webhook"); + return false; + } + + } + /// /// Sends a test message to mattermost using the provided settings /// @@ -289,8 +322,8 @@ namespace Ombi.Controllers.V1.External { try { - - var result = await EmbyApi.GetUsers(settings.FullUri, settings.ApiKey); + var client = await EmbyApi.CreateClient(); + var result = await client.GetUsers(settings.FullUri, settings.ApiKey); return result.Any(); } catch (Exception e) @@ -459,5 +492,35 @@ namespace Ombi.Controllers.V1.External return false; } } + + [HttpPost("whatsapp")] + public async Task WhatsAppTest([FromBody] WhatsAppSettingsViewModel settings) + { + try + { + + var user = await UserManager.Users.Include(x => x.UserNotificationPreferences).FirstOrDefaultAsync(x => x.UserName == HttpContext.User.Identity.Name); + + + var status = await WhatsAppApi.SendMessage(new WhatsAppModel { + From = settings.From, + Message = "This is a test from Ombi!", + To = user.UserNotificationPreferences.FirstOrDefault(x => x.Agent == NotificationAgent.WhatsApp).Value + }, settings.AccountSid, settings.AuthToken); + if (status.HasValue()) + { + return true; + } + else + { + return false; + } + } + catch (Exception e) + { + Log.LogError(LoggingEvents.Api, e, "Could not test Lidarr"); + return false; + } + } } } \ No newline at end of file diff --git a/src/Ombi/Controllers/V1/IdentityController.cs b/src/Ombi/Controllers/V1/IdentityController.cs index e24bdb87d..b348c1d06 100644 --- a/src/Ombi/Controllers/V1/IdentityController.cs +++ b/src/Ombi/Controllers/V1/IdentityController.cs @@ -4,7 +4,6 @@ using System.Linq; using System.Net; using System.Threading.Tasks; using AutoMapper; -using Hangfire; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Mvc; @@ -66,7 +65,8 @@ namespace Ombi.Controllers.V1 IMusicRequestRepository musicRepo, IMovieRequestEngine movieRequestEngine, ITvRequestEngine tvRequestEngine, - IMusicRequestEngine musicEngine) + IMusicRequestEngine musicEngine, + IUserDeletionEngine deletionEngine) { UserManager = user; Mapper = mapper; @@ -93,9 +93,11 @@ namespace Ombi.Controllers.V1 _userNotificationPreferences = notificationPreferences; _userQualityProfiles = userProfiles; MusicRequestEngine = musicEngine; + _deletionEngine = deletionEngine; } private OmbiUserManager UserManager { get; } + private readonly IUserDeletionEngine _deletionEngine; private RoleManager RoleManager { get; } private IMapper Mapper { get; } private IEmailProvider EmailProvider { get; } @@ -136,7 +138,7 @@ namespace Ombi.Controllers.V1 public async Task CreateWizardUser([FromBody] CreateUserWizardModel user) { var users = UserManager.Users; - if (users.Any(x => !x.UserName.Equals("api", StringComparison.InvariantCultureIgnoreCase))) + if (users.Any(x => x.NormalizedUserName != "API")) { // No one should be calling this. Only the wizard return new SaveWizardResult { Result = false, Errors = new List { "Looks like there is an existing user!" } }; @@ -281,11 +283,27 @@ namespace Ombi.Controllers.V1 [Authorize] public async Task GetCurrentUser() { - var user = await UserManager.Users.FirstOrDefaultAsync(x => x.UserName.Equals(User.Identity.Name, StringComparison.InvariantCultureIgnoreCase)); + var username = User.Identity.Name.ToUpper(); + var user = await UserManager.Users.FirstOrDefaultAsync(x => x.NormalizedUserName == username); return await GetUserWithRoles(user); } + /// + /// Sets the current users language + /// + [HttpPost("language")] + [Authorize] + public async Task SetCurrentUserLanguage([FromBody] UserLanguage model) + { + var username = User.Identity.Name.ToUpper(); + var user = await UserManager.Users.FirstOrDefaultAsync(x => x.NormalizedUserName == username); + user.Language = model.Lang; + + await UserManager.UpdateAsync(user); + return Ok(); + } + /// /// Gets the user by the user id. /// @@ -315,6 +333,7 @@ namespace Ombi.Controllers.V1 EpisodeRequestLimit = user.EpisodeRequestLimit ?? 0, MovieRequestLimit = user.MovieRequestLimit ?? 0, MusicRequestLimit = user.MusicRequestLimit ?? 0, + Language = user.Language }; foreach (var role in userRoles) @@ -639,7 +658,6 @@ namespace Ombi.Controllers.V1 var userToDelete = await UserManager.Users.FirstOrDefaultAsync(x => x.Id == userId); if (userToDelete != null) { - // Can we delete this user? var userRoles = await UserManager.GetRolesAsync(userToDelete); if (!CanModifyUser(userRoles)) @@ -647,65 +665,8 @@ namespace Ombi.Controllers.V1 return Error("You do not have the correct permissions to delete this user"); } - // We need to delete all the requests first - var moviesUserRequested = MovieRepo.GetAll().Where(x => x.RequestedUserId == userId); - var tvUserRequested = TvRepo.GetChild().Where(x => x.RequestedUserId == userId); - var musicRequested = MusicRepo.GetAll().Where(x => x.RequestedUserId == userId); - var notificationPreferences = _userNotificationPreferences.GetAll().Where(x => x.UserId == userId); - var userQuality = await _userQualityProfiles.GetAll().FirstOrDefaultAsync(x => x.UserId == userId); + var result = await _deletionEngine.DeleteUser(userToDelete); - if (moviesUserRequested.Any()) - { - await MovieRepo.DeleteRange(moviesUserRequested); - } - if (tvUserRequested.Any()) - { - await TvRepo.DeleteChildRange(tvUserRequested); - } - if (musicRequested.Any()) - { - await MusicRepo.DeleteRange(musicRequested); - } - if (notificationPreferences.Any()) - { - await _userNotificationPreferences.DeleteRange(notificationPreferences); - } - if (userQuality != null) - { - await _userQualityProfiles.Delete(userQuality); - } - - // Delete any issues and request logs - var issues = _issuesRepository.GetAll().Where(x => x.UserReportedId == userId); - var issueComments = _issueCommentsRepository.GetAll().Where(x => x.UserId == userId); - var requestLog = _requestLogRepository.GetAll().Where(x => x.UserId == userId); - if (issues.Any()) - { - await _issuesRepository.DeleteRange(issues); - } - if (requestLog.Any()) - { - await _requestLogRepository.DeleteRange(requestLog); - } - if (issueComments.Any()) - { - await _issueCommentsRepository.DeleteRange(issueComments); - } - - // Delete the Subscriptions and mobile notification ids - var subs = _requestSubscriptionRepository.GetAll().Where(x => x.UserId == userId); - var mobileIds = _notificationRepository.GetAll().Where(x => x.UserId == userId); - if (subs.Any()) - { - await _requestSubscriptionRepository.DeleteRange(subs); - } - - if (mobileIds.Any()) - { - await _notificationRepository.DeleteRange(mobileIds); - } - - var result = await UserManager.DeleteAsync(userToDelete); if (result.Succeeded) { return new OmbiIdentityResult @@ -777,8 +738,10 @@ namespace Ombi.Controllers.V1 var emailSettings = await EmailSettings.GetSettingsAsync(); - customizationSettings.AddToUrl("/token?token="); - var url = customizationSettings.ApplicationUrl; + var appUrl = customizationSettings.AddToUrl("/token?token="); + var url = (string.IsNullOrEmpty(appUrl) + ? $"{HttpContext.Request.Scheme}://{HttpContext.Request.Host}/token?token=" + : appUrl); if (user.UserType == UserType.PlexUser) { @@ -860,7 +823,7 @@ namespace Ombi.Controllers.V1 [HttpPost("welcomeEmail")] [PowerUser] - public void SendWelcomeEmail([FromBody] UserViewModel user) + public async Task SendWelcomeEmail([FromBody] UserViewModel user) { var ombiUser = new OmbiUser { @@ -868,14 +831,17 @@ namespace Ombi.Controllers.V1 Email = user.EmailAddress, UserName = user.UserName }; - BackgroundJob.Enqueue(() => WelcomeEmail.SendEmail(ombiUser)); + await WelcomeEmail.SendEmail(ombiUser); + return Ok(); } [HttpGet("accesstoken")] [ApiExplorerSettings(IgnoreApi = true)] public async Task GetUserAccessToken() { - var user = await UserManager.Users.FirstOrDefaultAsync(x => x.UserName.Equals(User.Identity.Name, StringComparison.InvariantCultureIgnoreCase)); + + var username = User.Identity.Name.ToUpper(); + var user = await UserManager.Users.FirstOrDefaultAsync(x => x.NormalizedUserName == username); if (user == null) { return Guid.Empty.ToString("N"); @@ -897,7 +863,8 @@ namespace Ombi.Controllers.V1 [HttpGet("notificationpreferences")] public async Task> GetUserPreferences() { - var user = await UserManager.Users.FirstOrDefaultAsync(x => x.UserName.Equals(User.Identity.Name, StringComparison.InvariantCultureIgnoreCase)); + var username = User.Identity.Name.ToUpper(); + var user = await UserManager.Users.FirstOrDefaultAsync(x => x.NormalizedUserName == username); return await GetPreferences(user); } @@ -911,8 +878,10 @@ namespace Ombi.Controllers.V1 private readonly List _excludedAgents = new List { NotificationAgent.Email, - NotificationAgent.Mobile + NotificationAgent.Mobile, + NotificationAgent.Webhook }; + private async Task> GetPreferences(OmbiUser user) { var userPreferences = await _userNotificationPreferences.GetAll().Where(x => x.UserId == user.Id).ToListAsync(); @@ -950,7 +919,9 @@ namespace Ombi.Controllers.V1 return NotFound(); } // Check if we are editing a different user than ourself, if we are then we need to power user role - var me = await UserManager.Users.FirstOrDefaultAsync(x => x.UserName.Equals(User.Identity.Name, StringComparison.InvariantCultureIgnoreCase)); + + var username = User.Identity.Name.ToUpper(); + var me = await UserManager.Users.FirstOrDefaultAsync(x => x.NormalizedUserName == username); if (!me.Id.Equals(user.Id, StringComparison.InvariantCultureIgnoreCase)) { var isPowerUser = await UserManager.IsInRoleAsync(me, OmbiRoles.PowerUser); diff --git a/src/Ombi/Controllers/V1/ImagesController.cs b/src/Ombi/Controllers/V1/ImagesController.cs index 44594b6d8..249a6e9bd 100644 --- a/src/Ombi/Controllers/V1/ImagesController.cs +++ b/src/Ombi/Controllers/V1/ImagesController.cs @@ -5,6 +5,7 @@ using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Options; using Ombi.Api.FanartTv; using Ombi.Config; +using Ombi.Core; using Ombi.Helpers; using Ombi.Store.Repository; @@ -16,18 +17,20 @@ namespace Ombi.Controllers.V1 public class ImagesController : ControllerBase { public ImagesController(IFanartTvApi fanartTvApi, IApplicationConfigRepository config, - IOptions options, ICacheService c) + IOptions options, ICacheService c, IImageService imageService) { FanartTvApi = fanartTvApi; Config = config; Options = options.Value; _cache = c; + _imageService = imageService; } private IFanartTvApi FanartTvApi { get; } private IApplicationConfigRepository Config { get; } private LandingPageBackground Options { get; } private readonly ICacheService _cache; + private readonly IImageService _imageService; [HttpGet("tv/{tvdbid}")] public async Task GetTvBanner(int tvdbid) @@ -38,7 +41,7 @@ namespace Ombi.Controllers.V1 } var key = await _cache.GetOrAdd(CacheKeys.FanartTv, async () => await Config.GetAsync(Store.Entities.ConfigurationTypes.FanartTv), DateTime.Now.AddDays(1)); - var images = await FanartTvApi.GetTvImages(tvdbid, key.Value); + var images = await _cache.GetOrAdd($"{CacheKeys.FanartTv}tv{tvdbid}", async () => await FanartTvApi.GetTvImages(tvdbid, key.Value), DateTime.Now.AddDays(1)); if (images == null) { return string.Empty; @@ -63,7 +66,7 @@ namespace Ombi.Controllers.V1 { var key = await _cache.GetOrAdd(CacheKeys.FanartTv, async () => await Config.GetAsync(Store.Entities.ConfigurationTypes.FanartTv), DateTime.Now.AddDays(1)); - var images = await FanartTvApi.GetMovieImages(movieDbId, key.Value); + var images = await _cache.GetOrAdd($"{CacheKeys.FanartTv}movie{movieDbId}", async () => await FanartTvApi.GetMovieImages(movieDbId, key.Value), DateTime.Now.AddDays(1)); if (images == null) { @@ -97,7 +100,7 @@ namespace Ombi.Controllers.V1 } var key = await _cache.GetOrAdd(CacheKeys.FanartTv, async () => await Config.GetAsync(Store.Entities.ConfigurationTypes.FanartTv), DateTime.Now.AddDays(1)); - var images = await FanartTvApi.GetTvImages(tvdbid, key.Value); + var images = await _cache.GetOrAdd($"{CacheKeys.FanartTv}tv{tvdbid}", async () => await FanartTvApi.GetTvImages(tvdbid, key.Value), DateTime.Now.AddDays(1)); if (images == null) { @@ -127,8 +130,8 @@ namespace Ombi.Controllers.V1 { var key = await _cache.GetOrAdd(CacheKeys.FanartTv, async () => await Config.GetAsync(Store.Entities.ConfigurationTypes.FanartTv), DateTime.Now.AddDays(1)); - var images = await FanartTvApi.GetMovieImages(movieDbId, key.Value); - + var images = await _cache.GetOrAdd($"{CacheKeys.FanartTv}movie{movieDbId}", async () => await FanartTvApi.GetMovieImages(movieDbId, key.Value), DateTime.Now.AddDays(1)); + if (images == null) { return string.Empty; @@ -152,7 +155,7 @@ namespace Ombi.Controllers.V1 { var key = await _cache.GetOrAdd(CacheKeys.FanartTv, async () => await Config.GetAsync(Store.Entities.ConfigurationTypes.FanartTv), DateTime.Now.AddDays(1)); - var images = await FanartTvApi.GetMovieImages(movieDbId, key.Value); + var images = await _cache.GetOrAdd($"{CacheKeys.FanartTv}movie{movieDbId}", async () => await FanartTvApi.GetMovieImages(movieDbId, key.Value), DateTime.Now.AddDays(1)); if (images == null) { @@ -179,26 +182,8 @@ namespace Ombi.Controllers.V1 { return string.Empty; } - var key = await _cache.GetOrAdd(CacheKeys.FanartTv, async () => await Config.GetAsync(Store.Entities.ConfigurationTypes.FanartTv), DateTime.Now.AddDays(1)); - - var images = await FanartTvApi.GetTvImages(tvdbid, key.Value); - if (images == null) - { - return string.Empty; - } - - if (images.showbackground?.Any() ?? false) - { - var enImage = images.showbackground.Where(x => x.lang == "en").OrderByDescending(x => x.likes).Select(x => x.url).FirstOrDefault(); - if (enImage == null) - { - return images.showbackground.OrderByDescending(x => x.likes).Select(x => x.url).FirstOrDefault(); - } - return enImage; - } - - return string.Empty; + return await _imageService.GetTvBackground(tvdbid.ToString()); } [HttpGet("background")] @@ -216,11 +201,13 @@ namespace Ombi.Controllers.V1 if (moviesArray.Length > 0) { var item = rand.Next(moviesArray.Length); - var result = await FanartTvApi.GetMovieImages(moviesArray[item].ToString(), key.Value); + var result = await _cache.GetOrAdd($"{CacheKeys.FanartTv}movie{moviesArray[item]}", async () => await FanartTvApi.GetMovieImages(moviesArray[item].ToString(), key.Value), DateTime.Now.AddDays(1)); while (!result.moviebackground.Any()) { - result = await FanartTvApi.GetMovieImages(moviesArray[item].ToString(), key.Value); + item = rand.Next(moviesArray.Length); + result = await _cache.GetOrAdd($"{CacheKeys.FanartTv}movie{moviesArray[item]}", async () => await FanartTvApi.GetMovieImages(moviesArray[item].ToString(), key.Value), DateTime.Now.AddDays(1)); + } var otherRand = new Random(); @@ -231,11 +218,12 @@ namespace Ombi.Controllers.V1 if (tvArray.Length > 0) { var item = rand.Next(tvArray.Length); - var result = await FanartTvApi.GetTvImages(tvArray[item], key.Value); + var result = await _cache.GetOrAdd($"{CacheKeys.FanartTv}tv{tvArray[item]}", async () => await FanartTvApi.GetTvImages(tvArray[item], key.Value), DateTime.Now.AddDays(1)); while (!result.showbackground.Any()) { - result = await FanartTvApi.GetTvImages(tvArray[item], key.Value); + item = rand.Next(tvArray.Length); + result = await _cache.GetOrAdd($"{CacheKeys.FanartTv}tv{tvArray[item]}", async () => await FanartTvApi.GetTvImages(tvArray[item], key.Value), DateTime.Now.AddDays(1)); } var otherRand = new Random(); var res = otherRand.Next(result.showbackground.Length); diff --git a/src/Ombi/Controllers/V1/IssuesController.cs b/src/Ombi/Controllers/V1/IssuesController.cs index cca139b89..4dfd3781a 100644 --- a/src/Ombi/Controllers/V1/IssuesController.cs +++ b/src/Ombi/Controllers/V1/IssuesController.cs @@ -2,12 +2,12 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -using Hangfire; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using Ombi.Attributes; +using Ombi.Core; using Ombi.Core.Notifications; using Ombi.Helpers; using Ombi.Models; @@ -25,7 +25,7 @@ namespace Ombi.Controllers.V1 public class IssuesController : ControllerBase { public IssuesController(IRepository categories, IRepository issues, IRepository comments, - UserManager userManager, INotificationService notify) + UserManager userManager, INotificationHelper notify) { _categories = categories; _issues = issues; @@ -38,7 +38,7 @@ namespace Ombi.Controllers.V1 private readonly IRepository _issues; private readonly IRepository _issueComments; private readonly UserManager _userManager; - private readonly INotificationService _notification; + private readonly INotificationHelper _notification; /// /// Get's all categories @@ -130,7 +130,9 @@ namespace Ombi.Controllers.V1 public async Task CreateIssue([FromBody]Issues i) { i.IssueCategory = null; - i.UserReportedId = (await _userManager.Users.FirstOrDefaultAsync(x => x.UserName.Equals(User.Identity.Name, StringComparison.InvariantCultureIgnoreCase))).Id; + i.CreatedDate = DateTime.UtcNow; + var username = User.Identity.Name.ToUpper(); + i.UserReportedId = (await _userManager.Users.FirstOrDefaultAsync(x => x.NormalizedUserName == username)).Id; await _issues.Add(i); var category = await _categories.GetAll().FirstOrDefaultAsync(x => i.IssueCategoryId == x.Id); if (category != null) @@ -146,11 +148,12 @@ namespace Ombi.Controllers.V1 Recipient = string.Empty, AdditionalInformation = $"{i.Subject} | {i.Description}", UserId = i.UserReportedId, + }; AddIssueNotificationSubstitutes(notificationModel, i, User.Identity.Name); - BackgroundJob.Enqueue(() => _notification.Publish(notificationModel)); + await _notification.Notify(notificationModel); return i.Id; } @@ -166,6 +169,23 @@ namespace Ombi.Controllers.V1 .Include(x => x.UserReported) .FirstOrDefaultAsync(); } + + [HttpGet("request/{id}")] + public async Task GetIssueByRequestId([FromRoute] int id) + { + return new OkObjectResult(await _issues.GetAll().Where(x => x.RequestId == id) + .Include(x => x.IssueCategory) + .Include(x => x.UserReported).ToListAsync()); + } + + + [HttpGet("provider/{id}")] + public async Task GetIssueByProviderId([FromRoute] string id) + { + return new OkObjectResult(await _issues.GetAll().Where(x => x.ProviderId == id) + .Include(x => x.IssueCategory) + .Include(x => x.UserReported).ToListAsync()); + } /// /// Get's all the issue comments by id @@ -197,7 +217,7 @@ namespace Ombi.Controllers.V1 [HttpPost("comments")] public async Task AddComment([FromBody] NewIssueCommentViewModel comment) { - var user = await _userManager.Users.Where(x => User.Identity.Name.Equals(x.UserName, StringComparison.InvariantCultureIgnoreCase)) + var user = await _userManager.Users.Where(x => User.Identity.Name == x.UserName) .FirstOrDefaultAsync(); var issue = await _issues.GetAll().Include(x => x.UserReported).Include(x => x.IssueCategory).FirstOrDefaultAsync(x => x.Id == comment.IssueId); if (issue == null) @@ -237,14 +257,14 @@ namespace Ombi.Controllers.V1 notificationModel.Recipient = user.Email; } - BackgroundJob.Enqueue(() => _notification.Publish(notificationModel)); + await _notification.Notify(notificationModel); return await _issueComments.Add(newComment); } /// /// Deletes a comment on a issue /// - [HttpDelete("comments/{id:int}")] + [HttpDelete("comments/{id}")] [PowerUser] public async Task DeleteComment(int id) { @@ -254,10 +274,21 @@ namespace Ombi.Controllers.V1 return true; } + [HttpDelete("{id}")] + [PowerUser] + public async Task DeleteIssue(int id) + { + var issue = await _issues.GetAll().FirstOrDefaultAsync(x => x.Id == id); + + await _issues.Delete(issue); + return true; + } + [HttpPost("status")] public async Task UpdateStatus([FromBody] IssueStateViewModel model) { - var user = await _userManager.Users.Where(x => User.Identity.Name.Equals(x.UserName, StringComparison.InvariantCultureIgnoreCase)) + var username = User.Identity.Name.ToUpper(); + var user = await _userManager.Users.Where(x => username == x.NormalizedUserName) .FirstOrDefaultAsync(); var issue = await _issues.GetAll().Include(x => x.UserReported).Include(x => x.IssueCategory).FirstOrDefaultAsync(x => x.Id == model.IssueId); if (issue == null) @@ -290,7 +321,7 @@ namespace Ombi.Controllers.V1 }; AddIssueNotificationSubstitutes(notificationModel, issue, issue.UserReported?.UserAlias ?? string.Empty); - BackgroundJob.Enqueue(() => _notification.Publish(notificationModel)); + await _notification.Notify(notificationModel); } diff --git a/src/Ombi/Controllers/V1/JobController.cs b/src/Ombi/Controllers/V1/JobController.cs index a501da2ec..6ffbf8486 100644 --- a/src/Ombi/Controllers/V1/JobController.cs +++ b/src/Ombi/Controllers/V1/JobController.cs @@ -1,15 +1,14 @@ using System; using System.Collections.Generic; using System.Threading.Tasks; -using Hangfire; using Microsoft.AspNetCore.Mvc; using Ombi.Attributes; using Ombi.Helpers; -using Ombi.Schedule; using Ombi.Schedule.Jobs; using Ombi.Schedule.Jobs.Emby; using Ombi.Schedule.Jobs.Ombi; using Ombi.Schedule.Jobs.Plex; +using Ombi.Schedule.Jobs.Radarr; using Quartz; namespace Ombi.Controllers.V1 @@ -69,11 +68,14 @@ namespace Ombi.Controllers.V1 var val = await _memCache.GetOrAdd(CacheKeys.Update, async () => { var productArray = _updater.GetVersion(); - var version = productArray[0]; - var branch = productArray[1]; - var updateAvailable = await _updater.UpdateAvailable(branch, version); + if (productArray.Length > 1) + { + var version = productArray[0]; + var branch = productArray[1]; + var updateAvailable = await _updater.UpdateAvailable(branch, version); + } - return updateAvailable; + return true; }); return val; } @@ -133,6 +135,25 @@ namespace Ombi.Controllers.V1 return true; } + /// + /// Runs the Arr Availability Checker + /// + /// + [HttpPost("arrAvailability")] + public async Task StartArrAvailabiltityChecker() + { + await OmbiQuartz.TriggerJob(nameof(IArrAvailabilityChecker), "DVR"); + return true; + } + + + [HttpPost("autodeleterequests")] + public async Task StartAutoDeleteRequests() + { + await OmbiQuartz.TriggerJob(nameof(IAutoDeleteRequests), "System"); + return true; + } + /// /// Runs the newsletter /// diff --git a/src/Ombi/Controllers/V1/LandingPageController.cs b/src/Ombi/Controllers/V1/LandingPageController.cs index 48d10d727..54e1638b4 100644 --- a/src/Ombi/Controllers/V1/LandingPageController.cs +++ b/src/Ombi/Controllers/V1/LandingPageController.cs @@ -18,7 +18,7 @@ namespace Ombi.Controllers.V1 public class LandingPageController : ControllerBase { public LandingPageController(ISettingsService plex, ISettingsService emby, - IPlexApi plexApi, IEmbyApi embyApi) + IPlexApi plexApi, IEmbyApiFactory embyApi) { _plexSettings = plex; _embySettings = emby; @@ -27,7 +27,7 @@ namespace Ombi.Controllers.V1 } private readonly IPlexApi _plexApi; - private readonly IEmbyApi _embyApi; + private readonly IEmbyApiFactory _embyApi; private readonly ISettingsService _plexSettings; private readonly ISettingsService _embySettings; @@ -65,11 +65,12 @@ namespace Ombi.Controllers.V1 var emby = await _embySettings.GetSettingsAsync(); if (emby.Enable) { + var client = _embyApi.CreateClient(emby); foreach (var server in emby.Servers) { try { - var result = await _embyApi.GetUsers(server.FullUri, server.ApiKey); + var result = await client.GetUsers(server.FullUri, server.ApiKey); if (result.Any()) { model.ServersAvailable++; diff --git a/src/Ombi/Controllers/V1/MobileController.cs b/src/Ombi/Controllers/V1/MobileController.cs index a2b1f05e3..2bae31c9d 100644 --- a/src/Ombi/Controllers/V1/MobileController.cs +++ b/src/Ombi/Controllers/V1/MobileController.cs @@ -40,7 +40,8 @@ namespace Ombi.Controllers.V1 { if (body?.PlayerId.HasValue() ?? false) { - var user = await _userManager.Users.FirstOrDefaultAsync(x => x.UserName.Equals(User.Identity.Name, StringComparison.InvariantCultureIgnoreCase)); + var username = User.Identity.Name.ToUpper(); + var user = await _userManager.Users.FirstOrDefaultAsync(x => x.NormalizedUserName == username); // Check if we already have this notification id var alreadyExists = await _notification.GetAll().AnyAsync(x => x.PlayerId == body.PlayerId && x.UserId == user.Id); diff --git a/src/Ombi/Controllers/V1/SettingsController.cs b/src/Ombi/Controllers/V1/SettingsController.cs index d2a145c39..1d340b4cd 100644 --- a/src/Ombi/Controllers/V1/SettingsController.cs +++ b/src/Ombi/Controllers/V1/SettingsController.cs @@ -7,10 +7,8 @@ using System.Reflection; using System.Runtime.InteropServices; using System.Threading.Tasks; using AutoMapper; -using Hangfire; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; -using NCrontab; using Ombi.Api.Emby; using Ombi.Api.Github; using Ombi.Attributes; @@ -27,11 +25,12 @@ using Ombi.Settings.Settings.Models.External; using Ombi.Settings.Settings.Models.Notifications; using Ombi.Store.Entities; using Ombi.Store.Repository; -using Ombi.Api.Github; -using Ombi.Core.Engine; using Ombi.Extensions; -using Ombi.Schedule; using Quartz; +using Ombi.Schedule.Jobs; +using Ombi.Schedule.Jobs.Emby; +using Ombi.Schedule.Jobs.Sonarr; +using Ombi.Schedule.Jobs.Lidarr; namespace Ombi.Controllers.V1 { @@ -48,7 +47,7 @@ namespace Ombi.Controllers.V1 public SettingsController(ISettingsResolver resolver, IMapper mapper, INotificationTemplatesRepository templateRepo, - IEmbyApi embyApi, + IEmbyApiFactory embyApi, ICacheService memCache, IGithubApi githubApi, IRecentlyAddedEngine engine) @@ -65,7 +64,7 @@ namespace Ombi.Controllers.V1 private ISettingsResolver SettingsResolver { get; } private IMapper Mapper { get; } private INotificationTemplatesRepository TemplateRepository { get; } - private readonly IEmbyApi _embyApi; + private readonly IEmbyApiFactory _embyApi; private readonly ICacheService _cache; private readonly IGithubApi _githubApi; private readonly IRecentlyAddedEngine _recentlyAdded; @@ -118,7 +117,7 @@ namespace Ombi.Controllers.V1 public AboutViewModel About() { var dbConfiguration = DatabaseExtensions.GetDatabaseConfiguration(); - var storage = StoragePathSingleton.Instance; + var storage = StartupSingleton.Instance; var model = new AboutViewModel { FrameworkDescription = RuntimeInformation.FrameworkDescription, @@ -126,11 +125,8 @@ namespace Ombi.Controllers.V1 OsDescription = RuntimeInformation.OSDescription, ProcessArchitecture = RuntimeInformation.ProcessArchitecture.ToString(), ApplicationBasePath = Directory.GetCurrentDirectory(), - ExternalConnectionString = dbConfiguration.ExternalDatabase.ConnectionString, ExternalDatabaseType = dbConfiguration.ExternalDatabase.Type, - OmbiConnectionString = dbConfiguration.OmbiDatabase.ConnectionString, OmbiDatabaseType = dbConfiguration.OmbiDatabase.Type, - SettingsConnectionString = dbConfiguration.SettingsDatabase.ConnectionString, SettingsDatabaseType = dbConfiguration.SettingsDatabase.Type, StoragePath = storage.StoragePath.HasValue() ? storage.StoragePath : "None Specified", NotSupported = Directory.GetCurrentDirectory().Contains("qpkg") @@ -140,7 +136,7 @@ namespace Ombi.Controllers.V1 var version = AssemblyHelper.GetRuntimeVersion(); var productArray = version.Split('-'); model.Version = productArray[0]; - model.Branch = productArray[1]; + //model.Branch = productArray[1]; return model; } @@ -187,11 +183,18 @@ namespace Ombi.Controllers.V1 [HttpPost("plex")] public async Task PlexSettings([FromBody]PlexSettings plex) { - if (plex.InstallId == null || plex.InstallId == Guid.Empty) + if (plex?.InstallId == Guid.Empty || plex.InstallId == Guid.Empty) { plex.InstallId = Guid.NewGuid(); } var result = await Save(plex); + + if (result) + { + // Kick off the plex sync + await OmbiQuartz.TriggerJob(nameof(IPlexContentSync), "Plex"); + } + return result; } @@ -215,14 +218,19 @@ namespace Ombi.Controllers.V1 { if (emby.Enable) { + var client = await _embyApi.CreateClient(); foreach (var server in emby.Servers) { - var users = await _embyApi.GetUsers(server.FullUri, server.ApiKey); + var users = await client.GetUsers(server.FullUri, server.ApiKey); var admin = users.FirstOrDefault(x => x.Policy.IsAdministrator); server.AdministratorId = admin?.Id; } } var result = await Save(emby); + if (result) + { + await OmbiQuartz.TriggerJob(nameof(IEmbyContentSync), "Emby"); + } return result; } @@ -340,7 +348,12 @@ namespace Ombi.Controllers.V1 [HttpPost("sonarr")] public async Task SonarrSettings([FromBody]SonarrSettings settings) { - return await Save(settings); + var result = await Save(settings); + if (result) + { + await OmbiQuartz.TriggerJob(nameof(ISonarrSync), "DVR"); + } + return result; } /// @@ -383,7 +396,12 @@ namespace Ombi.Controllers.V1 [HttpPost("lidarr")] public async Task LidarrSettings([FromBody]LidarrSettings settings) { - return await Save(settings); + var lidarr = await Save(settings); + if (lidarr) + { + await OmbiQuartz.TriggerJob(nameof(ILidarrArtistSync), "DVR"); + } + return lidarr; } /// @@ -551,13 +569,13 @@ namespace Ombi.Controllers.V1 j.PlexContentSync = j.PlexContentSync.HasValue() ? j.PlexContentSync : JobSettingsHelper.PlexContent(j); j.UserImporter = j.UserImporter.HasValue() ? j.UserImporter : JobSettingsHelper.UserImporter(j); j.SickRageSync = j.SickRageSync.HasValue() ? j.SickRageSync : JobSettingsHelper.SickRageSync(j); - j.RefreshMetadata = j.RefreshMetadata.HasValue() ? j.RefreshMetadata : JobSettingsHelper.RefreshMetadata(j); j.PlexRecentlyAddedSync = j.PlexRecentlyAddedSync.HasValue() ? j.PlexRecentlyAddedSync : JobSettingsHelper.PlexRecentlyAdded(j); j.Newsletter = j.Newsletter.HasValue() ? j.Newsletter : JobSettingsHelper.Newsletter(j); j.LidarrArtistSync = j.LidarrArtistSync.HasValue() ? j.LidarrArtistSync : JobSettingsHelper.LidarrArtistSync(j); j.IssuesPurge = j.IssuesPurge.HasValue() ? j.IssuesPurge : JobSettingsHelper.IssuePurge(j); j.RetryRequests = j.RetryRequests.HasValue() ? j.RetryRequests : JobSettingsHelper.ResendFailedRequests(j); j.MediaDatabaseRefresh = j.MediaDatabaseRefresh.HasValue() ? j.MediaDatabaseRefresh : JobSettingsHelper.MediaDatabaseRefresh(j); + j.AutoDeleteRequests = j.AutoDeleteRequests.HasValue() ? j.AutoDeleteRequests : JobSettingsHelper.AutoDeleteRequests(j); return j; } @@ -966,6 +984,44 @@ namespace Ombi.Controllers.V1 return model; } + /// + /// Gets the Twilio Notification Settings. + /// + /// + [HttpGet("notifications/twilio")] + public async Task TwilioNotificationSettings() + { + var settings = await Get(); + var model = Mapper.Map(settings); + + // Lookup to see if we have any templates saved + if (model.WhatsAppSettings == null) + { + model.WhatsAppSettings = new WhatsAppSettingsViewModel(); + } + model.WhatsAppSettings.NotificationTemplates = BuildTemplates(NotificationAgent.WhatsApp); + + return model; + } + + /// + /// Saves the Mattermost notification settings. + /// + /// The model. + /// + [HttpPost("notifications/twilio")] + public async Task TwilioNotificationSettings([FromBody] TwilioSettingsViewModel model) + { + // Save the email settings + var settings = Mapper.Map(model); + var result = await Save(settings); + + // Save the templates + await TemplateRepository.UpdateRange(model.WhatsAppSettings.NotificationTemplates); + + return result; + } + /// /// Saves the Mobile notification settings. /// @@ -1034,6 +1090,33 @@ namespace Ombi.Controllers.V1 return model; } + /// + /// Saves the webhook notification settings. + /// + /// The model. + /// + [HttpPost("notifications/webhook")] + public async Task WebhookNotificationSettings([FromBody] WebhookNotificationViewModel model) + { + var settings = Mapper.Map(model); + var result = await Save(settings); + + return result; + } + + /// + /// Gets the webhook notification settings. + /// + /// + [HttpGet("notifications/webhook")] + public async Task WebhookNotificationSettings() + { + var settings = await Get(); + var model = Mapper.Map(settings); + + return model; + } + /// /// Saves the Newsletter notification settings. /// @@ -1083,7 +1166,13 @@ namespace Ombi.Controllers.V1 // Make sure we do not display the newsletter templates = templates.Where(x => x.NotificationType != NotificationType.Newsletter); } - return templates.OrderBy(x => x.NotificationType.ToString()).ToList(); + if (agent != NotificationAgent.Email) + { + templates = templates.Where(x => x.NotificationType != NotificationType.WelcomeEmail); + } + + var tem = templates.ToList(); + return tem.OrderBy(x => x.NotificationType.ToString()).ToList(); } private async Task Get() diff --git a/src/Ombi/Controllers/V1/TokenController.cs b/src/Ombi/Controllers/V1/TokenController.cs index d706434f8..66013ecf5 100644 --- a/src/Ombi/Controllers/V1/TokenController.cs +++ b/src/Ombi/Controllers/V1/TokenController.cs @@ -7,6 +7,7 @@ using System.Text; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Options; +using Microsoft.Extensions.Logging; using Microsoft.IdentityModel.Tokens; using Ombi.Core.Authentication; using Ombi.Helpers; @@ -24,18 +25,20 @@ namespace Ombi.Controllers.V1 public class TokenController : ControllerBase { public TokenController(OmbiUserManager um, IOptions ta, ITokenRepository token, - IPlexOAuthManager oAuthManager) + IPlexOAuthManager oAuthManager, ILogger logger) { _userManager = um; _tokenAuthenticationOptions = ta.Value; _token = token; _plexOAuthManager = oAuthManager; + _log = logger; } private readonly TokenAuthentication _tokenAuthenticationOptions; private readonly ITokenRepository _token; private readonly OmbiUserManager _userManager; private readonly IPlexOAuthManager _plexOAuthManager; + private readonly ILogger _log; /// /// Gets the token. @@ -57,6 +60,7 @@ namespace Ombi.Controllers.V1 if (user == null) { + _log.LogWarning(string.Format("Failed login attempt by IP: {0}", GetRequestIP())); return new UnauthorizedResult(); } @@ -88,6 +92,7 @@ namespace Ombi.Controllers.V1 return new JsonResult(new { url = url.ToString(), pinId = model.PlexTvPin.id }); } + _log.LogWarning(string.Format("Failed login attempt by IP: {0}", GetRequestIP())); return new UnauthorizedResult(); } @@ -130,8 +135,12 @@ namespace Ombi.Controllers.V1 new Claim("Id", user.Id) }; claims.AddRange(roles.Select(role => new Claim("role", role))); + if (user.Email.HasValue()) + { + claims.Add(new Claim("Email", user.Email)); + } - var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_tokenAuthenticationOptions.SecretKey)); + var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(StartupSingleton.Instance.SecurityKey)); var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256); @@ -149,14 +158,8 @@ namespace Ombi.Controllers.V1 } user.LastLoggedIn = DateTime.UtcNow; - try - { - await _userManager.UpdateAsync(user); - } - catch (Exception) - { - - } + + await _userManager.UpdateAsync(user); return new JsonResult(new { @@ -248,5 +251,26 @@ namespace Ombi.Controllers.V1 public string Userename { get; set; } } + private string GetRequestIP() + { + string ip = null; + + if (Request.HttpContext?.Request?.Headers != null && Request.HttpContext.Request.Headers.ContainsKey("X-Forwarded-For")) + { + var forwardedip = Request.HttpContext.Request.Headers["X-Forwarded-For"].ToString(); + ip = forwardedip.TrimEnd(',').Split(",").Select(s => s.Trim()).FirstOrDefault(); + } + + if (string.IsNullOrWhiteSpace(ip) && Request.HttpContext?.Connection?.RemoteIpAddress != null) + ip = Request.HttpContext.Connection.RemoteIpAddress.ToString(); + + if (string.IsNullOrWhiteSpace(ip) && Request.HttpContext?.Request?.Headers != null && Request.HttpContext.Request.Headers.ContainsKey("REMOTE_ADDR")) + { + var remoteip = Request.HttpContext.Request.Headers["REMOTE_ADDR"].ToString(); + ip = remoteip.TrimEnd(',').Split(",").Select(s => s.Trim()).FirstOrDefault(); + } + + return ip; + } } -} \ No newline at end of file +} diff --git a/src/Ombi/Controllers/V2/HubController.cs b/src/Ombi/Controllers/V2/HubController.cs index 73804531a..3520595a6 100644 --- a/src/Ombi/Controllers/V2/HubController.cs +++ b/src/Ombi/Controllers/V2/HubController.cs @@ -32,7 +32,7 @@ namespace Ombi.Controllers.V2 var model = new List(); foreach (var user in users) { - var ombiUser = await allUsers.FirstOrDefaultAsync(x => x.Id.Equals(user.UserId, StringComparison.InvariantCultureIgnoreCase)); + var ombiUser = await allUsers.FirstOrDefaultAsync(x => x.Id == user.UserId); if (ombiUser == null) { diff --git a/src/Ombi/Controllers/V2/MobileController.cs b/src/Ombi/Controllers/V2/MobileController.cs new file mode 100644 index 000000000..ffd00b988 --- /dev/null +++ b/src/Ombi/Controllers/V2/MobileController.cs @@ -0,0 +1,141 @@ +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Logging; +using Ombi.Api.CloudService; +using Ombi.Attributes; +using Ombi.Core.Authentication; +using Ombi.Helpers; +using Ombi.Models.V2; +using Ombi.Store.Entities; +using Ombi.Store.Repository; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace Ombi.Controllers.V2 +{ + [ApiV2] + [Authorize] + [Produces("application/json")] + [ApiController] + public class MobileController : ControllerBase + { + public MobileController(IRepository mobileDevices, OmbiUserManager user, ICloudMobileNotification mobileNotificationService) + { + _mobileDevices = mobileDevices; + _userManager = user; + _mobileNotificationService = mobileNotificationService; + } + + private readonly IRepository _mobileDevices; + private readonly OmbiUserManager _userManager; + private readonly ICloudMobileNotification _mobileNotificationService; + + [HttpPost("Notification")] + [ApiExplorerSettings(IgnoreApi = true)] + [ProducesResponseType(400)] + [ProducesResponseType(200)] + public async Task AddNotitficationId([FromBody] MobileNotificationBody body) + { + if (!string.IsNullOrEmpty(body?.Token)) + { + + var username = User.Identity.Name.ToUpper(); + var user = await _userManager.Users.FirstOrDefaultAsync(x => x.NormalizedUserName == username); + if (user == null) + { + return Ok(); + } + // Check if we already have this notification id + var alreadyExists = await _mobileDevices.GetAll().AnyAsync(x => x.Token == body.Token && x.UserId == user.Id); + + if (alreadyExists) + { + return Ok(); + } + // Ensure we don't have too many already for this user + var tokens = await _mobileDevices.GetAll().Where(x => x.UserId == user.Id).OrderBy(x => x.AddedAt).ToListAsync(); + if (tokens.Count() > 5) + { + var toDelete = tokens.Take(tokens.Count() - 5); + await _mobileDevices.DeleteRange(toDelete); + } + + await _mobileDevices.Add(new MobileDevices + { + Token = body.Token, + UserId = user.Id, + AddedAt = DateTime.Now, + }); + return Ok(); + } + return BadRequest(); + } + + [HttpDelete("Notification")] + [ApiExplorerSettings(IgnoreApi = true)] + [ProducesResponseType(400)] + [ProducesResponseType(200)] + public async Task RemoveNotifications() + { + + var username = User.Identity.Name.ToUpper(); + var user = await _userManager.Users.FirstOrDefaultAsync(x => x.NormalizedUserName == username); + // Check if we already have this notification id + var currentDevices = await _mobileDevices.GetAll().Where(x => x.UserId == user.Id).ToListAsync(); + + if (currentDevices == null || !currentDevices.Any()) + { + return Ok(); + } + + await _mobileDevices.DeleteRange(currentDevices); + + return Ok(); + } + + + [HttpPost("Send")] + [ApiExplorerSettings(IgnoreApi = true)] + [Admin] + public async Task SendNotification([FromBody] SendMobileNotification model) + { + + var user = await _userManager.Users.FirstOrDefaultAsync(x => x.Id == model.UserId); + if (user == null) + { + return Ok(); + } + // Check if we already have this notification id + var currentDevices = await _mobileDevices.GetAll().Where(x => x.UserId == model.UserId).ToListAsync(); + + if (currentDevices == null || !currentDevices.Any()) + { + return Ok(); + } + + + foreach (var d in currentDevices) + { + await _mobileNotificationService.SendMessage(new MobileNotificationRequest + { + To = d.Token, + Body = model.Message, + }); + } + + return Ok(); + } + + [HttpGet("Users")] [ApiExplorerSettings(IgnoreApi = true)] + [Admin] + public async Task GetUsers() + { + var devices = await _mobileDevices.GetAll().Include(x => x.User).ToListAsync(); + var unique = devices.GroupBy(x => x.UserId, (key, g) => new { UserId = key, Username = g.Select(x => x.User.UserName).FirstOrDefault(), Devices = g.ToList() }); + return Ok(unique); + } + } +} diff --git a/src/Ombi/Controllers/V2/RequestsController.cs b/src/Ombi/Controllers/V2/RequestsController.cs index 73b4f26af..95ab96367 100644 --- a/src/Ombi/Controllers/V2/RequestsController.cs +++ b/src/Ombi/Controllers/V2/RequestsController.cs @@ -14,15 +14,18 @@ namespace Ombi.Controllers.V2 { public class RequestsController : V2Controller { - public RequestsController(IMovieRequestEngine movieRequestEngine, ITvRequestEngine tvRequestEngine) + + private readonly IMovieRequestEngine _movieRequestEngine; + private readonly ITvRequestEngine _tvRequestEngine; + private readonly IMusicRequestEngine _musicRequestEngine; + + public RequestsController(IMovieRequestEngine movieRequestEngine, ITvRequestEngine tvRequestEngine, IMusicRequestEngine musicRequestEngine) { _movieRequestEngine = movieRequestEngine; _tvRequestEngine = tvRequestEngine; + _musicRequestEngine = musicRequestEngine; } - private readonly IMovieRequestEngine _movieRequestEngine; - private readonly ITvRequestEngine _tvRequestEngine; - /// /// Gets movie requests. /// @@ -35,6 +38,31 @@ namespace Ombi.Controllers.V2 { return await _movieRequestEngine.GetRequests(count, position, sort, sortOrder); } + + [HttpGet("movie/availble/{count:int}/{position:int}/{sort}/{sortOrder}")] + [HttpGet("movie/available/{count:int}/{position:int}/{sort}/{sortOrder}")] + public async Task> GetAvailableRequests(int count, int position, string sort, string sortOrder) + { + return await _movieRequestEngine.GetRequestsByStatus(count, position, sort, sortOrder, RequestStatus.Available); + } + + [HttpGet("movie/processing/{count:int}/{position:int}/{sort}/{sortOrder}")] + public async Task> GetProcessingRequests(int count, int position, string sort, string sortOrder) + { + return await _movieRequestEngine.GetRequestsByStatus(count, position, sort, sortOrder, RequestStatus.ProcessingRequest); + } + + [HttpGet("movie/pending/{count:int}/{position:int}/{sort}/{sortOrder}")] + public async Task> GetPendingRequests(int count, int position, string sort, string sortOrder) + { + return await _movieRequestEngine.GetRequestsByStatus(count, position, sort, sortOrder, RequestStatus.PendingApproval); + } + + [HttpGet("movie/denied/{count:int}/{position:int}/{sort}/{sortOrder}")] + public async Task> GetDeniedRequests(int count, int position, string sort, string sortOrder) + { + return await _movieRequestEngine.GetRequestsByStatus(count, position, sort, sortOrder, RequestStatus.Denied); + } /// /// Gets the unavailable movie requests. @@ -62,6 +90,30 @@ namespace Ombi.Controllers.V2 return await _tvRequestEngine.GetRequests(count, position, sort, sortOrder); } + [HttpGet("tv/pending/{count:int}/{position:int}/{sort}/{sortOrder}")] + public async Task> GetPendingTvRequests(int count, int position, string sort, string sortOrder) + { + return await _tvRequestEngine.GetRequests(count, position, sort, sortOrder, RequestStatus.PendingApproval); + } + + [HttpGet("tv/processing/{count:int}/{position:int}/{sort}/{sortOrder}")] + public async Task> GetProcessingTvRequests(int count, int position, string sort, string sortOrder) + { + return await _tvRequestEngine.GetRequests(count, position, sort, sortOrder, RequestStatus.ProcessingRequest); + } + + [HttpGet("tv/available/{count:int}/{position:int}/{sort}/{sortOrder}")] + public async Task> GetAvailableTvRequests(int count, int position, string sort, string sortOrder) + { + return await _tvRequestEngine.GetRequests(count, position, sort, sortOrder, RequestStatus.Available); + } + + [HttpGet("tv/denied/{count:int}/{position:int}/{sort}/{sortOrder}")] + public async Task> GetDeniedTvRequests(int count, int position, string sort, string sortOrder) + { + return await _tvRequestEngine.GetRequests(count, position, sort, sortOrder, RequestStatus.Denied); + } + /// /// Gets unavailable Tv requests. /// @@ -76,9 +128,45 @@ namespace Ombi.Controllers.V2 } [HttpPost("movie/advancedoptions")] - public async Task UpdateAdvancedOptions([FromBody] MovieAdvancedOptions options) + public async Task UpdateAdvancedOptions([FromBody] MediaAdvancedOptions options) { return await _movieRequestEngine.UpdateAdvancedOptions(options); } + + [HttpPost("tv/advancedoptions")] + public async Task UpdateTvAdvancedOptions([FromBody] MediaAdvancedOptions options) + { + return await _tvRequestEngine.UpdateAdvancedOptions(options); + } + + [HttpGet("album/available/{count:int}/{position:int}/{sort}/{sortOrder}")] + public async Task> GetAvailableAlbumRequests(int count, int position, string sort, string sortOrder) + { + return await _musicRequestEngine.GetRequestsByStatus(count, position, sort, sortOrder, RequestStatus.Available); + } + + [HttpGet("album/processing/{count:int}/{position:int}/{sort}/{sortOrder}")] + public async Task> GetProcessingAlbumRequests(int count, int position, string sort, string sortOrder) + { + return await _musicRequestEngine.GetRequestsByStatus(count, position, sort, sortOrder, RequestStatus.ProcessingRequest); + } + + [HttpGet("album/pending/{count:int}/{position:int}/{sort}/{sortOrder}")] + public async Task> GetPendingAlbumRequests(int count, int position, string sort, string sortOrder) + { + return await _musicRequestEngine.GetRequestsByStatus(count, position, sort, sortOrder, RequestStatus.PendingApproval); + } + + [HttpGet("album/denied/{count:int}/{position:int}/{sort}/{sortOrder}")] + public async Task> GetDeniedAlbumRequests(int count, int position, string sort, string sortOrder) + { + return await _musicRequestEngine.GetRequestsByStatus(count, position, sort, sortOrder, RequestStatus.Denied); + } + + [HttpGet("album/{count:int}/{position:int}/{sort}/{sortOrder}")] + public async Task> GetAlbumRequests(int count, int position, string sort, string sortOrder) + { + return await _musicRequestEngine.GetRequests(count, position, sort, sortOrder); + } } } \ No newline at end of file diff --git a/src/Ombi/Controllers/V2/SearchController.cs b/src/Ombi/Controllers/V2/SearchController.cs index 1e2f9776c..652ff15eb 100644 --- a/src/Ombi/Controllers/V2/SearchController.cs +++ b/src/Ombi/Controllers/V2/SearchController.cs @@ -44,11 +44,12 @@ namespace Ombi.Controllers.V2 /// Show information using the MovieDbId. /// The search you want, this can be for a movie or TV show e.g. Star Wars will return /// all Star Wars movies and Star Wars Rebels the TV Sho + /// Filter for the search /// - [HttpGet("multi/{searchTerm}")] - public async Task> MultiSearch(string searchTerm) + [HttpPost("multi/{searchTerm}")] + public async Task> MultiSearch(string searchTerm, [FromBody] MultiSearchFilter filter) { - return await _multiSearchEngine.MultiSearch(searchTerm, Request.HttpContext.RequestAborted); + return await _multiSearchEngine.MultiSearch(searchTerm, filter, Request.HttpContext.RequestAborted); } /// @@ -61,6 +62,21 @@ namespace Ombi.Controllers.V2 return await _movieEngineV2.GetFullMovieInformation(movieDbId, Request.HttpContext.RequestAborted); } + [HttpGet("movie/imdb/{imdbid}")] + public async Task GetMovieInfoByImdbId(string imdbId) + { + return await _movieEngineV2.GetMovieInfoByImdbId(imdbId, Request.HttpContext.RequestAborted); + } + + /// + /// Returns details for a single movie + /// + [HttpGet("movie/request/{requestId}")] + public async Task GetMovieByRequest(int requestId) + { + return await _movieEngineV2.GetMovieInfoByRequestId(requestId, Request.HttpContext.RequestAborted); + } + /// /// Returns basic information about the provided collection /// @@ -83,6 +99,17 @@ namespace Ombi.Controllers.V2 return await _tvEngineV2.GetShowInformation(tvdbid); } + /// + /// Returns details for a single show + /// + /// TVMaze is the TV Show Provider + /// + [HttpGet("tv/request/{requestId}")] + public async Task GetTvInfoByRequest(int requestId) + { + return await _tvEngineV2.GetShowByRequest(requestId); + } + /// /// Returns details for a single show /// @@ -240,6 +267,19 @@ namespace Ombi.Controllers.V2 return await _tvSearchEngine.Popular(currentPosition, amountToLoad); } + /// + /// Returns Popular Tv Shows + /// + /// We use Trakt.tv as the Provider + /// + [HttpGet("tv/popular/{currentPosition}/{amountToLoad}/images")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesDefaultResponseType] + public async Task> PopularTvWithImages(int currentPosition, int amountToLoad) + { + return await _tvSearchEngine.Popular(currentPosition, amountToLoad, true); + } + /// /// Returns most Anticipated tv shows. /// @@ -321,7 +361,7 @@ namespace Ombi.Controllers.V2 return await _tvSearchEngine.Trending(currentPosition, amountToLoad); } - + /// /// Returns all the movies that is by the actor id /// @@ -332,7 +372,7 @@ namespace Ombi.Controllers.V2 [ProducesDefaultResponseType] public async Task GetMoviesByActor(int actorId) { - return await _movieEngineV2.GetMoviesByActor(actorId, null); + return await _movieEngineV2.GetMoviesByActor(actorId, null); } @@ -344,6 +384,14 @@ namespace Ombi.Controllers.V2 return await _musicEngine.GetArtistInformation(artistId); } + [HttpGet("artist/request/{requestId}")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesDefaultResponseType] + public async Task GetArtistInformationByRequestId(int requestId) + { + return await _musicEngine.GetArtistInformationByRequestId(requestId); + } + [HttpGet("releasegroupart/{musicBrainzId}")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesDefaultResponseType] diff --git a/src/Ombi/Controllers/V2/SystemController.cs b/src/Ombi/Controllers/V2/SystemController.cs index ab1e89578..d172eb37a 100644 --- a/src/Ombi/Controllers/V2/SystemController.cs +++ b/src/Ombi/Controllers/V2/SystemController.cs @@ -1,7 +1,9 @@ using System.IO; using System.Linq; +using System.Net.Http; using System.Threading; using System.Threading.Tasks; +using Markdig; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Mvc; using Ombi.Attributes; @@ -12,19 +14,31 @@ namespace Ombi.Controllers.V2 public class SystemController : V2Controller { private readonly IWebHostEnvironment _hosting; + private readonly HttpClient _client; - public SystemController(IWebHostEnvironment hosting) + public SystemController(IWebHostEnvironment hosting, IHttpClientFactory httpClientFactory) { _hosting = hosting; + _client = httpClientFactory.CreateClient(); + } + + [HttpGet("news")] + public async Task GetNews() + { + var result = await _client.GetAsync("https://raw.githubusercontent.com/tidusjar/Ombi.News/main/README.md"); + var content = await result.Content.ReadAsStringAsync(); + var md = Markdown.ToHtml(content); + return Ok(md); } [HttpGet("logs")] public IActionResult GetLogFiles() { - var logsFolder = Path.Combine(_hosting.ContentRootPath, "Logs"); + var logsFolder = Path.Combine(string.IsNullOrEmpty(Ombi.Helpers.StartupSingleton.Instance.StoragePath) ? _hosting.ContentRootPath : Helpers.StartupSingleton.Instance.StoragePath, "Logs"); var files = Directory .EnumerateFiles(logsFolder, "*.txt", SearchOption.TopDirectoryOnly) - .Select(Path.GetFileName); + .Select(Path.GetFileName) + .OrderByDescending(name => name); return Ok(files); } @@ -32,19 +46,23 @@ namespace Ombi.Controllers.V2 [HttpGet("logs/{logFileName}")] public async Task ReadLogFile(string logFileName, CancellationToken token) { - var logFile = Path.Combine(_hosting.ContentRootPath, "Logs", logFileName); - await using var fs = new FileStream(logFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); - using StreamReader reader = new StreamReader(fs); - return Ok(await reader.ReadToEndAsync()); + var logFile = Path.Combine(string.IsNullOrEmpty(Ombi.Helpers.StartupSingleton.Instance.StoragePath) ? _hosting.ContentRootPath : Helpers.StartupSingleton.Instance.StoragePath, "Logs", logFileName); + using (var fs = new FileStream(logFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) + using (StreamReader reader = new StreamReader(fs)) + { + return Ok(await reader.ReadToEndAsync()); + } } - + [HttpGet("logs/download/{logFileName}")] public IActionResult Download(string logFileName, CancellationToken token) { - var logFile = Path.Combine(_hosting.ContentRootPath, "Logs", logFileName); - using var fs = new FileStream(logFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); - using StreamReader reader = new StreamReader(fs); - return File(reader.BaseStream, "application/octet-stream", logFileName); + var logFile = Path.Combine(string.IsNullOrEmpty(Ombi.Helpers.StartupSingleton.Instance.StoragePath) ? _hosting.ContentRootPath : Helpers.StartupSingleton.Instance.StoragePath, "Logs", logFileName); + using (var fs = new FileStream(logFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) + using (StreamReader reader = new StreamReader(fs)) + { + return File(reader.BaseStream, "application/octet-stream", logFileName); + } } } } \ No newline at end of file diff --git a/src/Ombi/Extensions/DatabaseExtensions.cs b/src/Ombi/Extensions/DatabaseExtensions.cs index 2c6d13d06..4d82031ef 100644 --- a/src/Ombi/Extensions/DatabaseExtensions.cs +++ b/src/Ombi/Extensions/DatabaseExtensions.cs @@ -2,6 +2,7 @@ using System.IO; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Diagnostics.HealthChecks; using Newtonsoft.Json; using Ombi.Helpers; using Ombi.Store.Context; @@ -17,7 +18,7 @@ namespace Ombi.Extensions public const string SqliteDatabase = "Sqlite"; public const string MySqlDatabase = "MySQL"; - public static void ConfigureDatabases(this IServiceCollection services) + public static void ConfigureDatabases(this IServiceCollection services, IHealthChecksBuilder hcBuilder) { var configuration = GetDatabaseConfiguration(); @@ -26,9 +27,11 @@ namespace Ombi.Extensions { case var type when type.Equals(SqliteDatabase, StringComparison.InvariantCultureIgnoreCase): services.AddDbContext(x => ConfigureSqlite(x, configuration.OmbiDatabase)); + AddSqliteHealthCheck(hcBuilder, "Ombi Database", configuration.OmbiDatabase); break; case var type when type.Equals(MySqlDatabase, StringComparison.InvariantCultureIgnoreCase): services.AddDbContext(x => ConfigureMySql(x, configuration.OmbiDatabase)); + AddMySqlHealthCheck(hcBuilder, "Ombi Database", configuration.OmbiDatabase); break; } @@ -36,9 +39,11 @@ namespace Ombi.Extensions { case var type when type.Equals(SqliteDatabase, StringComparison.InvariantCultureIgnoreCase): services.AddDbContext(x => ConfigureSqlite(x, configuration.ExternalDatabase)); + AddSqliteHealthCheck(hcBuilder, "External Database", configuration.ExternalDatabase); break; case var type when type.Equals(MySqlDatabase, StringComparison.InvariantCultureIgnoreCase): services.AddDbContext(x => ConfigureMySql(x, configuration.ExternalDatabase)); + AddMySqlHealthCheck(hcBuilder, "External Database", configuration.ExternalDatabase); break; } @@ -46,23 +51,25 @@ namespace Ombi.Extensions { case var type when type.Equals(SqliteDatabase, StringComparison.InvariantCultureIgnoreCase): services.AddDbContext(x => ConfigureSqlite(x, configuration.SettingsDatabase)); + AddSqliteHealthCheck(hcBuilder, "Settings Database", configuration.SettingsDatabase); break; case var type when type.Equals(MySqlDatabase, StringComparison.InvariantCultureIgnoreCase): services.AddDbContext(x => ConfigureMySql(x, configuration.SettingsDatabase)); + AddMySqlHealthCheck(hcBuilder, "Settings Database", configuration.SettingsDatabase); break; } } public static DatabaseConfiguration GetDatabaseConfiguration() { - var i = StoragePathSingleton.Instance; + var i = StartupSingleton.Instance; if (string.IsNullOrEmpty(i.StoragePath)) { i.StoragePath = string.Empty; } var databaseFileLocation = Path.Combine(i.StoragePath, "database.json"); - + var configuration = new DatabaseConfiguration(i.StoragePath); if (File.Exists(databaseFileLocation)) { @@ -78,17 +85,45 @@ namespace Ombi.Extensions return configuration; } + + private static void AddSqliteHealthCheck(IHealthChecksBuilder builder, string dbName, PerDatabaseConfiguration config) + { + if (builder != null) + { + builder.AddSqlite( + sqliteConnectionString: config.ConnectionString, + name: dbName, + failureStatus: HealthStatus.Unhealthy, + tags: new string[] { "db" }); + } + } + + private static void AddMySqlHealthCheck(IHealthChecksBuilder builder, string dbName, PerDatabaseConfiguration config) + { + if (builder != null) + { + builder.AddMySql( + connectionString: config.ConnectionString, + name: dbName, + failureStatus: HealthStatus.Unhealthy, + tags: new string[] { "db" } + ); + } + } + public static void ConfigureSqlite(DbContextOptionsBuilder options, PerDatabaseConfiguration config) { SQLitePCL.Batteries.Init(); SQLitePCL.raw.sqlite3_config(raw.SQLITE_CONFIG_MULTITHREAD); - options.UseSqlite(config.ConnectionString); } public static void ConfigureMySql(DbContextOptionsBuilder options, PerDatabaseConfiguration config) { - options.UseMySql(config.ConnectionString); + options.UseMySql(config.ConnectionString, b => + { + b.CharSetBehavior(Pomelo.EntityFrameworkCore.MySql.Infrastructure.CharSetBehavior.NeverAppend); + }); } public class DatabaseConfiguration diff --git a/src/Ombi/Extensions/StartupExtensions.cs b/src/Ombi/Extensions/StartupExtensions.cs index c493a3ccf..e42dfb609 100644 --- a/src/Ombi/Extensions/StartupExtensions.cs +++ b/src/Ombi/Extensions/StartupExtensions.cs @@ -1,13 +1,9 @@ using System; -using System.Collections.Generic; using System.IO; using System.Reflection; using System.Text; using System.Threading.Tasks; using Microsoft.AspNetCore.Authentication.JwtBearer; -using Microsoft.AspNetCore.JsonPatch.Operations; -using Microsoft.AspNetCore.Mvc.ApiExplorer; -using Microsoft.AspNetCore.SignalR; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.IdentityModel.Tokens; @@ -15,18 +11,16 @@ using Microsoft.OpenApi.Models; using Ombi.Config; using Ombi.Helpers; using Ombi.Models.Identity; -using Swashbuckle.AspNetCore.Swagger; -using Swashbuckle.AspNetCore.SwaggerGen; namespace Ombi { - public static class StartupExtensions + public static class StartupExtensions { public static void AddSwagger(this IServiceCollection services) { services.AddSwaggerGen(c => { - c.SwaggerDoc("v1", new OpenApiInfo() + c.SwaggerDoc("v1", new OpenApiInfo { Version = "v1", Title = "Ombi Api V1", @@ -37,39 +31,42 @@ namespace Ombi } }); - - - c.AddSecurityDefinition("ApiKey", new OpenApiSecurityScheme { Description = "API Key provided by Ombi. Example: \"ApiKey: {token}\"", Name = "ApiKey", - In = ParameterLocation.Header, + In = ParameterLocation.Header, Type = SecuritySchemeType.ApiKey }); + c.CustomSchemaIds(x => x.FullName); - var basePath = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location); - var xmlPath = Path.Combine(basePath, "Swagger.xml"); + try { - c.IncludeXmlComments(xmlPath); + string basePath = Path.GetDirectoryName(AppContext.BaseDirectory); + string assemblyName = Assembly.GetExecutingAssembly().GetName().Name; + string xmlPath = Path.Combine(basePath ?? string.Empty, $"{assemblyName}.xml"); + if (File.Exists(xmlPath)) + { + c.IncludeXmlComments(xmlPath); + } + else + { + Console.WriteLine($"Swagger failed to find documentation file at '{xmlPath}'."); + } } catch (Exception e) { Console.WriteLine(e); } - c.DescribeAllParametersInCamelCase(); }); } - - public static void AddAppSettingsValues(this IServiceCollection services, IConfigurationRoot configuration) { services.Configure(configuration.GetSection("ApplicationSettings")); - services.Configure(configuration.GetSection("UserSettings")); services.Configure(configuration.GetSection("TokenAuthentication")); services.Configure(configuration.GetSection("LandingPageBackground")); services.Configure(configuration.GetSection("Demo")); @@ -79,13 +76,10 @@ namespace Ombi public static void AddJwtAuthentication(this IServiceCollection services, IConfigurationRoot configuration) { - var tokenOptions = configuration.GetSection("TokenAuthentication"); - var tokenValidationParameters = new TokenValidationParameters { ValidateIssuerSigningKey = true, - IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(tokenOptions.GetValue("SecretKey", string.Empty))), - + IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(StartupSingleton.Instance.SecurityKey)), RequireExpirationTime = true, ValidateLifetime = true, ValidAudience = "Ombi", @@ -93,33 +87,35 @@ namespace Ombi ClockSkew = TimeSpan.Zero, }; - services.AddAuthentication(options => - { - options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; - options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; - }).AddJwtBearer(x => - { - x.Audience = "Ombi"; - x.TokenValidationParameters = tokenValidationParameters; - x.Events = new JwtBearerEvents + services + .AddAuthentication(options => { - OnMessageReceived = context => + options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; + options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; + }) + .AddJwtBearer(x => + { + x.Audience = "Ombi"; + x.TokenValidationParameters = tokenValidationParameters; + x.Events = new JwtBearerEvents { - var accessToken = context.Request.Query["access_token"]; - - // If the request is for our hub... - var path = context.HttpContext.Request.Path; - if (!string.IsNullOrEmpty(accessToken) && - (path.StartsWithSegments("/hubs"))) + OnMessageReceived = context => { - // Read the token out of the query string - context.Token = accessToken; - } - return Task.CompletedTask; - } - }; - }); + var accessToken = context.Request.Query["access_token"]; + + // If the request is for our hub... + var path = context.HttpContext.Request.Path; + if (!string.IsNullOrEmpty(accessToken) && + (path.StartsWithSegments("/hubs"))) + { + // Read the token out of the query string + context.Token = accessToken; + } + return Task.CompletedTask; + } + }; + }); } } } \ No newline at end of file diff --git a/src/Ombi/HealthCheck.css b/src/Ombi/HealthCheck.css new file mode 100644 index 000000000..fc303c8c9 --- /dev/null +++ b/src/Ombi/HealthCheck.css @@ -0,0 +1,14 @@ +:root { + --primaryColor: #424242; + --secondaryColor: #f9dc43; + --bgMenuActive: #f9dc43; + --bgButton: #f9dc43; + --logoImageUrl: url('https://ombi.io/img/logo-orange-small.png'); + --bgAside: var(--primaryColor); + +} + +#outer-container > aside > nav > a:nth-child(2) { + display: none; +} + diff --git a/src/Ombi/Middleware/ApiKeyMiddlewear.cs b/src/Ombi/Middleware/ApiKeyMiddlewear.cs index e8fa02d78..0efe5b860 100644 --- a/src/Ombi/Middleware/ApiKeyMiddlewear.cs +++ b/src/Ombi/Middleware/ApiKeyMiddlewear.cs @@ -102,10 +102,16 @@ namespace Ombi if (username.IsNullOrEmpty()) { UseApiUser(context); + } + else + { + username = username.ToUpper(); } + var um = context.RequestServices.GetService(); + var user = await um.Users.FirstOrDefaultAsync(x => - x.UserName.Equals(username, StringComparison.InvariantCultureIgnoreCase)); + x.NormalizedUserName == username); if (user == null) { context.Response.StatusCode = (int)HttpStatusCode.Unauthorized; diff --git a/src/Ombi/Models/Identity/UserLanguage.cs b/src/Ombi/Models/Identity/UserLanguage.cs new file mode 100644 index 000000000..12be749d1 --- /dev/null +++ b/src/Ombi/Models/Identity/UserLanguage.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace Ombi.Models.Identity +{ + public class UserLanguage + { + public string Lang { get; set; } + } +} diff --git a/src/Ombi/Models/V2/MobileNotificationBody.cs b/src/Ombi/Models/V2/MobileNotificationBody.cs new file mode 100644 index 000000000..c6a361d65 --- /dev/null +++ b/src/Ombi/Models/V2/MobileNotificationBody.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace Ombi.Models.V2 +{ + public class MobileNotificationBody + { + public string Token { get; set; } + } +} diff --git a/src/Ombi/Models/V2/SendMobileNotification.cs b/src/Ombi/Models/V2/SendMobileNotification.cs new file mode 100644 index 000000000..fc551bd44 --- /dev/null +++ b/src/Ombi/Models/V2/SendMobileNotification.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace Ombi.Models.V2 +{ + public class SendMobileNotification + { + public string UserId { get; set; } + public string Message { get; set; } + } +} diff --git a/src/Ombi/Ombi.csproj b/src/Ombi/Ombi.csproj index 6b280a2da..9ac73264c 100644 --- a/src/Ombi/Ombi.csproj +++ b/src/Ombi/Ombi.csproj @@ -1,9 +1,11 @@  - netcoreapp3.0 + net5.0 win10-x64;win10-x86;osx-x64;linux-x64;linux-arm;linux-arm64; false Latest + $(SemVer) $(SemVer) $(FullVer) @@ -12,28 +14,18 @@ ClientApp\ $(DefaultItemExcludes);$(SpaRoot)node_modules\** true + bin\$(Configuration)\$(TargetFramework)\$(AssemblyName).xml false - - bin\Debug\netcoreapp2.2\Swagger.xml - 1701;1702;1705;1591; - - - - - bin\Release\netcoreapp2.2\Swagger.xml - 1701;1702;1705;1591; - TRACE;RELEASE;NETCOREAPP2_0 - @@ -56,26 +48,25 @@ - + + + - - + - - + + - + - - - + - - - + + + @@ -83,8 +74,10 @@ + + @@ -93,7 +86,6 @@ - @@ -104,17 +96,4 @@ - - - - - - - - %(DistFiles.Identity) - PreserveNewest - - - - diff --git a/src/Ombi/Program.cs b/src/Ombi/Program.cs index ac9c5bea0..4eae1c7f3 100644 --- a/src/Ombi/Program.cs +++ b/src/Ombi/Program.cs @@ -1,5 +1,4 @@ using System; -using System.IO; using System.Linq; using System.Text; using Microsoft.AspNetCore.Hosting; @@ -7,22 +6,21 @@ using Ombi.Store.Context; using Ombi.Store.Entities; using CommandLine; using CommandLine.Text; -using Microsoft.AspNetCore; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.DependencyInjection; using Ombi.Extensions; using Ombi.Helpers; -using Ombi.Store.Context.MySql; -using Ombi.Store.Context.Sqlite; +using System.Threading.Tasks; +using System.Collections.Generic; namespace Ombi { - public class Program + public static class Program { private static string UrlArgs { get; set; } - public static void Main(string[] args) + public static async Task Main(string[] args) { Console.Title = "Ombi"; @@ -30,6 +28,7 @@ namespace Ombi var storagePath = string.Empty; var baseUrl = string.Empty; var demo = false; + var migrate = false; var result = Parser.Default.ParseArguments(args) .WithParsed(o => { @@ -37,6 +36,7 @@ namespace Ombi storagePath = o.StoragePath; baseUrl = o.BaseUrl; demo = o.Demo; + migrate = o.Migrate; }).WithNotParsed(err => { foreach (var e in err) @@ -50,23 +50,37 @@ namespace Ombi UrlArgs = host; var urlValue = string.Empty; - var instance = StoragePathSingleton.Instance; + var instance = StartupSingleton.Instance; var demoInstance = DemoSingleton.Instance; demoInstance.Demo = demo; instance.StoragePath = storagePath ?? string.Empty; - // Check if we need to migrate the settings - DeleteSchedules(); - //CheckAndMigrate(); + var services = new ServiceCollection(); - services.ConfigureDatabases(); + services.ConfigureDatabases(null); using (var provider = services.BuildServiceProvider()) { var settingsDb = provider.GetRequiredService(); - var config = settingsDb.ApplicationConfigurations.ToList(); + if (migrate) + { + var migrationTasks = new List(); + var externalDb = provider.GetRequiredService(); + var ombiDb = provider.GetRequiredService(); + migrationTasks.Add(settingsDb.Database.MigrateAsync()); + migrationTasks.Add(ombiDb.Database.MigrateAsync()); + migrationTasks.Add(externalDb.Database.MigrateAsync()); + + Task.WaitAll(migrationTasks.ToArray()); + + Environment.Exit(0); + } + + var config = await settingsDb.ApplicationConfigurations.ToListAsync(); var url = config.FirstOrDefault(x => x.Type == ConfigurationTypes.Url); var dbBaseUrl = config.FirstOrDefault(x => x.Type == ConfigurationTypes.BaseUrl); + var securityToken = config.FirstOrDefault(x => x.Type == ConfigurationTypes.SecurityToken); + await CheckSecurityToken(securityToken, settingsDb, instance); if (url == null) { url = new ApplicationConfiguration @@ -74,11 +88,11 @@ namespace Ombi Type = ConfigurationTypes.Url, Value = "http://*:5000" }; - using (var tran = settingsDb.Database.BeginTransaction()) + using (var tran = await settingsDb.Database.BeginTransactionAsync()) { settingsDb.ApplicationConfigurations.Add(url); - settingsDb.SaveChanges(); - tran.Commit(); + await settingsDb.SaveChangesAsync(); + await tran.CommitAsync(); } urlValue = url.Value; @@ -88,14 +102,18 @@ namespace Ombi { url.Value = UrlArgs; - using (var tran = settingsDb.Database.BeginTransaction()) + using (var tran = await settingsDb.Database.BeginTransactionAsync()) { - settingsDb.SaveChanges(); - tran.Commit(); + await settingsDb.SaveChangesAsync(); + await tran.CommitAsync(); } urlValue = url.Value; } + else if (string.IsNullOrEmpty(urlValue)) + { + urlValue = host; + } if (dbBaseUrl == null) { @@ -107,11 +125,11 @@ namespace Ombi Value = baseUrl }; - using (var tran = settingsDb.Database.BeginTransaction()) + using (var tran = await settingsDb.Database.BeginTransactionAsync()) { settingsDb.ApplicationConfigurations.Add(dbBaseUrl); - settingsDb.SaveChanges(); - tran.Commit(); + await settingsDb.SaveChangesAsync(); + await tran.CommitAsync(); } } } @@ -119,10 +137,10 @@ namespace Ombi { dbBaseUrl.Value = baseUrl; - using (var tran = settingsDb.Database.BeginTransaction()) + using (var tran = await settingsDb.Database.BeginTransactionAsync()) { - settingsDb.SaveChanges(); - tran.Commit(); + await settingsDb.SaveChangesAsync(); + await tran.CommitAsync(); } } @@ -132,18 +150,25 @@ namespace Ombi } } - private static void DeleteSchedules() + private static async Task CheckSecurityToken(ApplicationConfiguration securityToken, SettingsContext ctx, StartupSingleton instance) { - try + if (securityToken == null || string.IsNullOrEmpty(securityToken.Value)) { - if (File.Exists("Schedules.db")) + securityToken = new ApplicationConfiguration + { + Type = ConfigurationTypes.SecurityToken, + Value = Guid.NewGuid().ToString("N") + }; + + using (var tran = await ctx.Database.BeginTransactionAsync()) { - File.Delete("Schedules.db"); + ctx.ApplicationConfigurations.Add(securityToken); + await ctx.SaveChangesAsync(); + await tran.CommitAsync(); } } - catch (Exception) - { - } + + instance.SecurityKey = securityToken.Value; } public static IHostBuilder CreateHostBuilder(string[] args) => @@ -175,7 +200,7 @@ namespace Ombi { [Option("host", Required = false, HelpText = "Set to a semicolon-separated (;) list of URL prefixes to which the server should respond. For example, http://localhost:123." + - " Use \"*\" to indicate that the server should listen for requests on any IP address or hostname using the specified port and protocol (for example, http://*:5000). " + + " Use \"localhost\" to indicate that the server should listen for requests on any IP address or hostname using the specified port and protocol (for example, http://localhost:5000). " + "The protocol (http:// or https://) must be included with each URL. Supported formats vary between servers.", Default = "http://*:5000")] public string Host { get; set; } @@ -188,5 +213,8 @@ namespace Ombi [Option("demo", Required = false, HelpText = "Demo mode, you will never need to use this, fuck that fruit company...")] public bool Demo { get; set; } + [Option("migrate", Required = false, HelpText = "Will run the migrations then exit the application")] + public bool Migrate { get; set; } + } } diff --git a/src/Ombi/Properties/launchSettings.json b/src/Ombi/Properties/launchSettings.json index e979c0ea0..ab355f92a 100644 --- a/src/Ombi/Properties/launchSettings.json +++ b/src/Ombi/Properties/launchSettings.json @@ -21,8 +21,11 @@ } }, "Ombi": { - "commandName": "IISExpress", - "commandLineArgs": "--host http://*:3577", + "commandName": "Project", + "commandLineArgs": "--host http://localhost:3577 ", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, "applicationUrl": "http://localhost:3577/" } } diff --git a/src/Ombi/Startup.cs b/src/Ombi/Startup.cs index ea61dfd37..49227a344 100644 --- a/src/Ombi/Startup.cs +++ b/src/Ombi/Startup.cs @@ -1,16 +1,11 @@ using AutoMapper; using AutoMapper.EquivalencyExpression; -using Hangfire; -using Hangfire.Dashboard; -using Hangfire.MemoryStorage; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.HttpOverrides; using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.StaticFiles; -using Microsoft.Extensions.Caching.Memory; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; @@ -27,25 +22,27 @@ using Ombi.Store.Context; using Ombi.Store.Entities; using Ombi.Store.Repository; using Serilog; -using SQLitePCL; using System; using System.IO; +using Microsoft.AspNetCore.StaticFiles.Infrastructure; using Microsoft.Extensions.Hosting; using Newtonsoft.Json; using ILogger = Serilog.ILogger; +using Microsoft.AspNetCore.Diagnostics.HealthChecks; +using Ombi.HealthChecks; namespace Ombi { public class Startup { - public static StoragePathSingleton StoragePath => StoragePathSingleton.Instance; + public static StartupSingleton StoragePath => StartupSingleton.Instance; public Startup(IWebHostEnvironment env) { Console.WriteLine(env.ContentRootPath); var builder = new ConfigurationBuilder() .SetBasePath(env.ContentRootPath) - .AddJsonFile("appsettings.json", false, false) + .AddJsonFile("appsettings.json", false, true) .AddJsonFile($"appsettings.{env.EnvironmentName}.json", true) .AddEnvironmentVariables(); Configuration = builder.Build(); @@ -65,6 +62,7 @@ namespace Ombi { services.AddIdentity() .AddEntityFrameworkStores() + .AddRoles() .AddDefaultTokenProviders() .AddUserManager(); @@ -78,9 +76,15 @@ namespace Ombi options.User.AllowedUserNameCharacters = string.Empty; }); - services.ConfigureDatabases(); - services.AddHealthChecks(); + var hcBuilder = services.AddHealthChecks(); + hcBuilder.AddOmbiHealthChecks(); + services.ConfigureDatabases(hcBuilder); + //services.AddHealthChecksUI(setupSettings: setup => + //{ + // setup.AddHealthCheckEndpoint("Ombi", "/health"); + //}); services.AddMemoryCache(); + services.AddHttpClient(); services.AddJwtAuthentication(Configuration); @@ -94,15 +98,6 @@ namespace Ombi services.AddSwagger(); services.AddAppSettingsValues(Configuration); - services.AddHangfire(x => - { - x.UseMemoryStorage(); -#pragma warning disable ASP0000 // Do not call 'IServiceCollection.BuildServiceProvider' in 'ConfigureServices' - x.UseActivator(new IoCJobActivator(services.BuildServiceProvider())); -#pragma warning restore ASP0000 // Do not call 'IServiceCollection.BuildServiceProvider' in 'ConfigureServices' - }); - - services.AddCors(o => o.AddPolicy("MyPolicy", builder => { builder.AllowAnyHeader() @@ -121,7 +116,7 @@ namespace Ombi } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. - public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILoggerFactory loggerFactory, IServiceProvider serviceProvider) + public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory, IServiceProvider serviceProvider) { app.UseForwardedHeaders(new ForwardedHeadersOptions { @@ -132,12 +127,23 @@ namespace Ombi var ctx = serviceProvider.GetService(); loggerFactory.AddSerilog(); - - app.UseSpaStaticFiles(); - var ombiService = serviceProvider.GetService>(); var settings = ombiService.GetSettings(); + + var sharedOptions = new SharedOptions(); + if (settings.BaseUrl.HasValue()) + { + if (settings.BaseUrl.EndsWith("/")) + { + settings.BaseUrl = settings.BaseUrl.Remove(settings.BaseUrl.Length - 1, 1); + } + sharedOptions.RequestPath = settings.BaseUrl; + } + + app.UseSpaStaticFiles(new StaticFileOptions(sharedOptions)); + + if (settings.ApiKey.IsNullOrEmpty()) { // Generate a API Key @@ -171,27 +177,27 @@ namespace Ombi app.UsePathBase(settings.BaseUrl); } - app.UseHangfireServer(new BackgroundJobServerOptions - {WorkerCount = 1, ServerTimeout = TimeSpan.FromDays(1), ShutdownTimeout = TimeSpan.FromDays(1)}); - + // Setup the scheduler + //var jobSetup = app.ApplicationServices.GetService(); + //jobSetup.Setup(); ctx.Seed(); var settingsctx = serviceProvider.GetService(); settingsctx.Seed(); - var provider = new FileExtensionContentTypeProvider {Mappings = {[".map"] = "application/octet-stream"}}; + var provider = new FileExtensionContentTypeProvider { Mappings = { [".map"] = "application/octet-stream" } }; app.UseStaticFiles(new StaticFileOptions() { ContentTypeProvider = provider, }); + app.UseMiddleware(); + app.UseMiddleware(); app.UseRouting(); app.UseAuthentication(); app.UseAuthorization(); - app.UseMiddleware(); - app.UseMiddleware(); app.UseCors("MyPolicy"); app.UseSwagger(); @@ -211,18 +217,28 @@ namespace Ombi { endpoints.MapControllers(); endpoints.MapHub("/hubs/notification"); - endpoints.MapHealthChecks("/health"); + if (!settings.DisableHealthChecks) + { + endpoints.MapHealthChecks("/health", new HealthCheckOptions + { + Predicate = _ => true, + //ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse + }); + //endpoints.MapHealthChecksUI(opts => + //{ + // opts.AddCustomStylesheet("HealthCheck.css"); + //}); + } }); app.UseSpa(spa => { - if (env.IsDevelopment()) - { - spa.Options.SourcePath = "ClientApp"; - spa.UseProxyToSpaDevelopmentServer("http://localhost:3578"); - } +#if DEBUG + spa.Options.SourcePath = "ClientApp"; + spa.UseProxyToSpaDevelopmentServer("http://localhost:3578"); +#endif }); - + } } } diff --git a/src/Ombi/Views/Shared/_Layout.cshtml b/src/Ombi/Views/Shared/_Layout.cshtml index 824175250..22c6c98f1 100644 --- a/src/Ombi/Views/Shared/_Layout.cshtml +++ b/src/Ombi/Views/Shared/_Layout.cshtml @@ -78,17 +78,17 @@ @appName - + - + diff --git a/src/Ombi/appsettings.Development.json b/src/Ombi/appsettings.Development.json index 6fa76219e..e53bccc77 100644 --- a/src/Ombi/appsettings.Development.json +++ b/src/Ombi/appsettings.Development.json @@ -4,7 +4,9 @@ "LogLevel": { "Default": "Trace", "System": "Trace", - "Microsoft": "Warning" + "Microsoft": "Warning", + "System.Net.Http.HttpClient.health-checks": "Information", + "HealthChecks": "Information" } } } diff --git a/src/Ombi/appsettings.json b/src/Ombi/appsettings.json index 8a9e38008..9dcf5523a 100644 --- a/src/Ombi/appsettings.json +++ b/src/Ombi/appsettings.json @@ -5,20 +5,14 @@ "Default": "Information", "System": "Information", "Microsoft": "None", - "Hangfire": "None" + "Hangfire": "None", + "System.Net.Http.HttpClient.health-checks": "Warning", + "HealthChecks": "Warning" } }, "ApplicationSettings": { - "Verison": "{{VERSIONNUMBER}}", - "Branch": "{{BRANCH}}", - "FriendlyVersion": "v3.0.0" - }, - "UserSettings": { - "WebsiteUrl": "http://localhost:52038", - "UseHttps": false - }, - "TokenAuthentication": { - "SecretKey": "secretkey_secretkey1234!" + "NotificationService": "https://ombinotifications.azurewebsites.net/api/", + "OmbiService": "?" }, "LandingPageBackground": { "Movies": [ @@ -34,7 +28,12 @@ 260513, 372058, 299536, - 383498 + 383498, + 330457, + 429617, + 475557, + 420818, + 283995 ], "TvShows": [ 121361, @@ -45,7 +44,10 @@ 275274, 305288, 296762, - 280619 + 280619, + 305074, + 277165, + 362696 ] }, // Please ignore the below diff --git a/src/Ombi/wwwroot/translations/bg.json b/src/Ombi/wwwroot/translations/bg.json index 7fabf59d9..13d352ae5 100644 --- a/src/Ombi/wwwroot/translations/bg.json +++ b/src/Ombi/wwwroot/translations/bg.json @@ -1,186 +1,301 @@ { - "Login": { - "SignInButton": "Sign in", - "UsernamePlaceholder": "Username", - "PasswordPlaceholder": "Password", - "RememberMe": "Remember Me", - "ForgottenPassword": "Forgot your password?", - "Errors": { - "IncorrectCredentials": "Incorrect username or password" - } - }, - "Common": { - "ContinueButton": "Continue", - "Available": "Available", - "PartiallyAvailable": "Partially Available", - "Monitored": "Monitored", - "NotAvailable": "Not Available", - "ProcessingRequest": "Processing Request", - "PendingApproval": "Pending Approval", - "RequestDenied": "Request Denied", - "NotRequested": "Not Requested", - "Requested": "Requested", - "Request": "Request", - "Denied": "Denied", - "Approve": "Approve", - "PartlyAvailable": "Partly Available", - "Errors": { - "Validation": "Please check your entered values" - } - }, - "PasswordReset": { - "EmailAddressPlaceholder": "Email Address", - "ResetPasswordButton": "Reset Password" - }, - "LandingPage": { - "OnlineHeading": "Currently Online", - "OnlineParagraph": "The media server is currently online", - "PartiallyOnlineHeading": "Partially Online", - "PartiallyOnlineParagraph": "The media server is partially online.", - "MultipleServersUnavailable": "There are {{serversUnavailable}} servers offline out of {{totalServers}}.", - "SingleServerUnavailable": "There is {{serversUnavailable}} server offline out of {{totalServers}}.", - "OfflineHeading": "Currently Offline", - "OfflineParagraph": "The media server is currently offline.", - "CheckPageForUpdates": "Check this page for continuous site updates." - }, - "NavigationBar": { - "Search": "Search", - "Requests": "Requests", - "UserManagement": "User Management", - "Issues": "Issues", - "Vote": "Vote", - "Donate": "Donate!", - "DonateLibraryMaintainer": "Donate to Library Maintainer", - "DonateTooltip": "This is how I convince my wife to let me spend my spare time developing Ombi ;)", - "UpdateAvailableTooltip": "Update Available!", - "Settings": "Settings", - "Welcome": "Welcome {{username}}", - "UpdateDetails": "Update Details", - "Logout": "Logout", - "OpenMobileApp": "Open Mobile App", - "RecentlyAdded": "Recently Added" - }, - "Search": { - "Title": "Search", - "Paragraph": "Want to watch something that is not currently available? No problem, just search for it below and request it!", - "MoviesTab": "Movies", - "TvTab": "TV Shows", - "MusicTab": "Music", - "Suggestions": "Suggestions", - "NoResults": "Sorry, we didn't find any results!", - "DigitalDate": "Digital Release: {{date}}", - "TheatricalRelease": "Theatrical Release: {{date}}", - "ViewOnPlex": "View On Plex", - "ViewOnEmby": "View On Emby", - "RequestAdded": "Request for {{title}} has been added successfully", - "Similar": "Similar", - "Refine": "Refine", - "SearchBarPlaceholder": "Type Here to Search", - "Movies": { - "PopularMovies": "Popular Movies", - "UpcomingMovies": "Upcoming Movies", - "TopRatedMovies": "Top Rated Movies", - "NowPlayingMovies": "Now Playing Movies", - "HomePage": "Home Page", - "Trailer": "Trailer" + "Login": { + "SignInButton": "Вход", + "UsernamePlaceholder": "Потребителско име", + "PasswordPlaceholder": "Парола", + "RememberMe": "Запомнете ме", + "SignInWith": "Sign in with {{appName}}", + "SignInWithPlex": "Sign in with Plex", + "ForgottenPassword": "Забравили сте паролата си?", + "Errors": { + "IncorrectCredentials": "Неправилно потребителско име или парола" + } }, - "TvShows": { - "Popular": "Popular", - "Trending": "Trending", - "MostWatched": "Most Watched", - "MostAnticipated": "Most Anticipated", - "Results": "Results", - "AirDate": "Air Date:", - "AllSeasons": "All Seasons", - "FirstSeason": "First Season", - "LatestSeason": "Latest Season", - "Select": "Select ...", - "SubmitRequest": "Submit Request", - "Season": "Season: {{seasonNumber}}", - "SelectAllInSeason": "Select All in Season {{seasonNumber}}" - } - }, - "Requests": { - "Title": "Requests", - "Paragraph": "Below you can see yours and all other requests, as well as their download and approval status.", - "MoviesTab": "Movies", - "TvTab": "TV Shows", - "MusicTab": "Music", - "RequestedBy": "Requested By:", - "Status": "Status:", - "RequestStatus": "Request status:", - "Denied": " Denied:", - "TheatricalRelease": "Theatrical Release: {{date}}", - "ReleaseDate": "Released: {{date}}", - "TheatricalReleaseSort": "Theatrical Release", - "DigitalRelease": "Digital Release: {{date}}", - "RequestDate": "Request Date:", - "QualityOverride": "Quality Override:", - "RootFolderOverride": "Root Folder Override:", - "ChangeRootFolder": "Root Folder", - "ChangeQualityProfile": "Quality Profile", - "MarkUnavailable": "Mark Unavailable", - "MarkAvailable": "Mark Available", - "Remove": "Remove", - "Deny": "Deny", - "Season": "Season:", - "GridTitle": "Title", - "AirDate": "AirDate", - "GridStatus": "Status", - "ReportIssue": "Report Issue", - "Filter": "Filter", - "Sort": "Sort", - "SeasonNumberHeading": "Season: {seasonNumber}", - "SortTitleAsc": "Title ▲", - "SortTitleDesc": "Title ▼", - "SortRequestDateAsc": "Request Date ▲", - "SortRequestDateDesc": "Request Date ▼", - "SortStatusAsc": "Status ▲", - "SortStatusDesc": "Status ▼", - "Remaining": { - "Quota": "{{remaining}}/{{total}} requests remaining", - "NextDays": "Another request will be added in {{time}} days", - "NextHours": "Another request will be added in {{time}} hours", - "NextMinutes": "Another request will be added in {{time}} minutes", - "NextMinute": "Another request will be added in {{time}} minute" + "Common": { + "ContinueButton": "Продължаване", + "Available": "Налично", + "PartiallyAvailable": "Частично налично", + "Monitored": "Наблюдавано", + "NotAvailable": "Не е налично", + "ProcessingRequest": "Обработка на заявката", + "PendingApproval": "Чака одобрение", + "RequestDenied": "Заявката отказана", + "NotRequested": "Не е заявено", + "Requested": "Заявено", + "Request": "Заявка", + "Denied": "Отказано", + "Approve": "Одобряване", + "PartlyAvailable": "Частично налично", + "ViewDetails": "View Details", + "Errors": { + "Validation": "Проверете си въведените стойности" + }, + "Cancel": "Cancel", + "Submit": "Submit" + }, + "PasswordReset": { + "EmailAddressPlaceholder": "Адрес на имейла", + "ResetPasswordButton": "Нулиране на паролата" + }, + "LandingPage": { + "OnlineHeading": "В момента на линия", + "OnlineParagraph": "Медийният сървър в момента е на линия", + "PartiallyOnlineHeading": "Частично в мрежата", + "PartiallyOnlineParagraph": "Медийният сървър е частично на линия.", + "MultipleServersUnavailable": "В мрежата няма {{serversUnavailable}} сървъра от {{totalServers}} общо.", + "SingleServerUnavailable": "В мрежата няма {{serversUnavailable}} сървъра от {{totalServers}}.", + "OfflineHeading": "В момента извън линия", + "OfflineParagraph": "Медийният сървър в момента е извън линия.", + "CheckPageForUpdates": "Проверете тази страница за последни новини на сайта." + }, + "NavigationBar": { + "Discover": "Discover", + "Search": "Търсене", + "Requests": "Заявки", + "UserManagement": "Управление на потребителите", + "Issues": "Проблеми", + "Vote": "Гласуване", + "Donate": "Дарете!", + "DonateLibraryMaintainer": "Дарете на библиотекаря", + "DonateTooltip": "This is how I convince my wife to let me spend my spare time developing Ombi ;)", + "UpdateAvailableTooltip": "Има налично обновяване!", + "Settings": "Настройки", + "Welcome": "Добре дошли, {{username}}", + "UpdateDetails": "Подробности за обновяването", + "Logout": "Изход", + "OpenMobileApp": "Отваряне на приложение за мобилни", + "RecentlyAdded": "Наскоро добавено", + "ChangeTheme": "Change Theme", + "Calendar": "Calendar", + "UserPreferences": "Preferences", + "FeatureSuggestion": "Feature Suggestion", + "FeatureSuggestionTooltip": "Have a great new idea? Suggest it here!", + "Filter": { + "Movies": "Филми", + "TvShows": "Тв предавания", + "Music": "Музика", + "People": "People" + }, + "MorningWelcome": "Good morning!", + "AfternoonWelcome": "Good afternoon!", + "EveningWelcome": "Good evening!" + }, + "Search": { + "Title": "Търсене", + "Paragraph": "Искате ли да гледате нещо, което в момента не е налично? Няма проблем, просто го потърсете долу и заявете!", + "MoviesTab": "Филми", + "TvTab": "Тв предавания", + "MusicTab": "Музика", + "Suggestions": "Предложения", + "NoResults": "Съжаляваме, не намерихме никакви резултати!", + "DigitalDate": "Цифрово пускане: {{date}}", + "TheatricalRelease": "Кинопремиера: {{date}}", + "ViewOnPlex": "Преглед в Plex", + "ViewOnEmby": "Преглед в Emby", + "RequestAdded": "Заявката за {{title}} е успешно добавена", + "Similar": "Подобно", + "Refine": "Уточнете", + "SearchBarPlaceholder": "Пишете тук за търсене", + "Movies": { + "PopularMovies": "Популярни филми", + "UpcomingMovies": "Предстоящи филми", + "TopRatedMovies": "Високо оценени филми", + "NowPlayingMovies": "Сега в кината", + "HomePage": "Начална страница", + "Trailer": "Трейлър" + }, + "TvShows": { + "Popular": "Популярно", + "Trending": "Вървежно", + "MostWatched": "Най-гледано", + "MostAnticipated": "Най-очаквано", + "Results": "Резултати", + "AirDate": "Дата излъчване:", + "AllSeasons": "Всички сезони", + "FirstSeason": "Първи сезон", + "LatestSeason": "Последен сезон", + "Select": "Изберете...", + "SubmitRequest": "Подаване на заявка", + "Season": "Сезон: {{seasonNumber}}", + "SelectAllInSeason": "Избиране на всичко в сезона {{seasonNumber}}" + } + }, + "Requests": { + "Title": "Заявки", + "Paragraph": "Долу можете да видите ваши и всички други заявки, както и състоянието им на изтегляне и одобрение.", + "MoviesTab": "Филми", + "ArtistName": "Artist", + "AlbumName": "Album Name", + "TvTab": "Тв предавания", + "MusicTab": "Музика", + "RequestedBy": "Заявено от", + "Status": "Състояние", + "RequestStatus": "Състояние на заявката", + "Denied": " Отказано:", + "TheatricalRelease": "Кинопремиера: {{date}}", + "ReleaseDate": "Пуснато: {{date}}", + "TheatricalReleaseSort": "Кинопремиера", + "DigitalRelease": "Цифрово пускане: {{date}}", + "RequestDate": "Дата на заявка", + "QualityOverride": "Преопределяне на качеството:", + "RootFolderOverride": "Преопределяне на кореновата папка:", + "ChangeRootFolder": "Коренова папка", + "ChangeQualityProfile": "Профил на качеството", + "MarkUnavailable": "Означаване като неналично", + "MarkAvailable": "Означаване като налично", + "Remove": "Премахване", + "Deny": "Отказване", + "DenyReason": "Deny Reason", + "Season": "Сезон:", + "GridTitle": "Заглавие", + "AirDate": "Дата на излъчване", + "GridStatus": "Състояние", + "ReportIssue": "Докладване на проблем", + "Filter": "Филтър", + "Sort": "Подредба", + "SeasonNumberHeading": "Сезон: {seasonNumber}", + "SortTitleAsc": "Заглавие ▲", + "SortTitleDesc": "Заглавие ▼", + "SortRequestDateAsc": "Дата на заявка▲", + "SortRequestDateDesc": "Дата на заявка▼", + "SortStatusAsc": "Състояние ▲", + "SortStatusDesc": "Състояние ▼", + "Remaining": { + "Quota": "{{remaining}}/{{total}} заявки остават", + "NextDays": "Друга заявка ще бъде добавена след {{time}} дни", + "NextHours": "Друга заявка ще бъде добавена след {{time}} часа", + "NextMinutes": "Друга заявка ще бъде добавена след {{time}} минути", + "NextMinute": "Друга заявка ще бъде добавена след {{time}} минута" + }, + "AllRequests": "All Requests", + "PendingRequests": "Pending Requests", + "ProcessingRequests": "Processing Requests", + "AvailableRequests": "Available Requests", + "DeniedRequests": "Denied Requests", + "RequestsToDisplay": "Requests to display", + "RequestsTitle": "Заглавие", + "Details": "Подробности", + "Options": "Options", + "RequestPanel": { + "Delete": "Delete Request", + "Approve": "Approve Request", + "ChangeAvailability": "Mark Available" + } + }, + "Issues": { + "Title": "Проблеми", + "PendingTitle": "Проблеми в очакване", + "InProgressTitle": "Проблеми в ход", + "ResolvedTitle": "Решени проблеми", + "ColumnTitle": "Заглавие", + "Category": "Категория", + "Status": "Състояние", + "Details": "Подробности", + "Description": "Описание", + "NoComments": "Няма коментари!", + "MarkInProgress": "Маркиране в ход", + "MarkResolved": "Маркиране като решено", + "SendMessageButton": "Изпращане", + "Subject": "Тема", + "Comments": "Коментари", + "WriteMessagePlaceholder": "Напишете съобщението си тук...", + "ReportedBy": "Докладвано от", + "IssueDialog": { + "Title": "Report an issue", + "DescriptionPlaceholder": "Please describe the issue", + "TitlePlaceholder": "Short title of your issue", + "SelectCategory": "Select Category", + "IssueCreated": "Issue has been created" + }, + "Outstanding": "There are outstanding issues", + "ResolvedDate": "Resolved date", + "CreatedDate": "Raised on", + "MarkedAsResolved": "This issue has now been marked as resolved!", + "MarkedAsInProgress": "This issue has now been marked as in progress!", + "Delete": "Delete issue", + "DeletedIssue": "Issue has been deleted" + }, + "Filter": { + "ClearFilter": "Изчистване на филтъра", + "FilterHeaderAvailability": "Наличност", + "FilterHeaderRequestStatus": "Състояние", + "Approved": "Одобрено", + "PendingApproval": "Чака одобрение" + }, + "UserManagment": { + "TvRemaining": "Тв: {{remaining}}/{{total}} остават", + "MovieRemaining": "Филми: {{remaining}}/{{total}} остават", + "MusicRemaining": "Музика: {{remaining}}/{{total}} остават", + "TvDue": "ТВ: {{date}}", + "MovieDue": "Филм: {{date}}", + "MusicDue": "Музика: {{date}}" + }, + "Votes": { + "CompletedVotesTab": "Гласувано", + "VotesTab": "Трябват гласове" + }, + "MediaDetails": { + "Denied": "Отказано", + "RecommendationsTitle": "Recommendations", + "SimilarTitle": "Подобно", + "VideosTitle": "Videos", + "AlbumsTitle": "Albums", + "RequestAllAlbums": "Request All Albums", + "ClearSelection": "Clear Selection", + "RequestSelectedAlbums": "Request Selected Albums", + "ViewCollection": "View Collection", + "NotEnoughInfo": "Unfortunately there is not enough information about this show yet!", + "AdvancedOptions": "Advanced Options", + "QualityProfilesSelect": "Select A Quality Profile", + "RootFolderSelect": "Select A Root Folder", + "Status": "Състояние", + "Availability": "Наличност", + "RequestStatus": "Request Status", + "Quality": "Quality", + "RootFolderOverride": "Преопределяне на кореновата папка", + "QualityOverride": "Преопределяне на качеството", + "Genres": "Genres", + "TheatricalRelease": "Кинопремиера", + "DigitalRelease": "Digital Release", + "UserScore": "User Score", + "Votes": "Votes", + "Runtime": "Runtime", + "Minutes": "{{runtime}} Minutes", + "Revenue": "Revenue", + "Budget": "Budget", + "Keywords": "Keywords/Tags", + "Casts": { + "CastTitle": "Cast" + }, + "EpisodeSelector": { + "AllSeasonsTooltip": "This will request every season for this show", + "FirstSeasonTooltip": "This will only request the First Season for this show", + "LatestSeasonTooltip": "This will only request the Latest Season for this show" + } + }, + "Discovery": { + "PopularTab": "Популярно", + "TrendingTab": "Вървежно", + "UpcomingTab": "Upcoming", + "Movies": "Филми", + "Combined": "Combined", + "Tv": "TV", + "CardDetails": { + "Availability": "Наличност", + "Studio": "Studio", + "Network": "Network", + "UnknownNetwork": "Unknown", + "RequestStatus": "Request Status", + "Director": "Director", + "InCinemas": "In Cinemas", + "FirstAired": "First Aired", + "Writer": "Writer", + "ExecProducer": "Exec Producer" + } + }, + "UserPreferences": { + "Welcome": "Добре дошли, {{username}}!", + "OmbiLanguage": "Език", + "DarkMode": "Тъмен режим" } - }, - "Issues": { - "Title": "Issues", - "PendingTitle": "Pending Issues", - "InProgressTitle": "In Progress Issues", - "ResolvedTitle": "Resolved Issues", - "ColumnTitle": "Title", - "Category": "Category", - "Status": "Status", - "Details": "Details", - "Description": "Description", - "NoComments": "No Comments!", - "MarkInProgress": "Mark In Progress", - "MarkResolved": "Mark Resolved", - "SendMessageButton": "Send", - "Subject": "Subject", - "Comments": "Comments", - "WriteMessagePlaceholder": "Write your message here...", - "ReportedBy": "Reported By" - }, - "Filter": { - "ClearFilter": "Clear Filter", - "FilterHeaderAvailability": "Availability", - "FilterHeaderRequestStatus": "Status", - "Approved": "Approved", - "PendingApproval": "Pending Approval" - }, - "UserManagment": { - "TvRemaining": "TV: {{remaining}}/{{total}} remaining", - "MovieRemaining": "Movies: {{remaining}}/{{total}} remaining", - "MusicRemaining": "Music: {{remaining}}/{{total}} remaining", - "TvDue": "TV: {{date}}", - "MovieDue": "Movie: {{date}}", - "MusicDue": "Music: {{date}}" - }, - "Votes": { - "CompletedVotesTab": "Voted", - "VotesTab": "Votes Needed" - } -} +} \ No newline at end of file diff --git a/src/Ombi/wwwroot/translations/da.json b/src/Ombi/wwwroot/translations/da.json index a37e925fa..917882e24 100644 --- a/src/Ombi/wwwroot/translations/da.json +++ b/src/Ombi/wwwroot/translations/da.json @@ -1,186 +1,301 @@ { - "Login": { - "SignInButton": "Log ind", - "UsernamePlaceholder": "Brugernavn", - "PasswordPlaceholder": "Adgangskode", - "RememberMe": "Husk mig", - "ForgottenPassword": "Glemt adgangskode?", - "Errors": { - "IncorrectCredentials": "Forkert brugernavn eller adgangskode" - } - }, - "Common": { - "ContinueButton": "Fortsæt", - "Available": "Tilgængelig", - "PartiallyAvailable": "Delvist tilgængelig", - "Monitored": "Overvåget", - "NotAvailable": "Ikke tilgængelig", - "ProcessingRequest": "Behandler anmodning", - "PendingApproval": "Afventer godkendelse", - "RequestDenied": "Anmodning afvist", - "NotRequested": "Ikke anmodet", - "Requested": "Anmodet", - "Request": "Anmod", - "Denied": "Afvist", - "Approve": "Godkendt", - "PartlyAvailable": "Delvist tilgængelig", - "Errors": { - "Validation": "Tjek venligst dine indtastede værdier" - } - }, - "PasswordReset": { - "EmailAddressPlaceholder": "E-mail-adresse", - "ResetPasswordButton": "Nulstil adgangskode" - }, - "LandingPage": { - "OnlineHeading": "Online nu", - "OnlineParagraph": "Medieserveren er online", - "PartiallyOnlineHeading": "Delvist online", - "PartiallyOnlineParagraph": "Medieserveren er delvist online.", - "MultipleServersUnavailable": "Der er {{serversUnavailable}} servere offline ud af {{totalServers}}.", - "SingleServerUnavailable": "Der er {{serversUnavailable}} server offline ud af {{totalServers}}.", - "OfflineHeading": "Offline nu", - "OfflineParagraph": "Medieserveren er offline.", - "CheckPageForUpdates": "Tjek denne side for løbende opdateringer." - }, - "NavigationBar": { - "Search": "Søg", - "Requests": "Anmodninger", - "UserManagement": "Brugeradministration", - "Issues": "Problemer", - "Vote": "Stem", - "Donate": "Donér!", - "DonateLibraryMaintainer": "Donér til vedligeholder af bibliotek", - "DonateTooltip": "Sådan overbeviser jeg min kone om, at jeg skal bruge min fritid på at udvikle Ombi :)", - "UpdateAvailableTooltip": "Ny opdatering venter!", - "Settings": "Indstillinger", - "Welcome": "Velkommen til {{username}}", - "UpdateDetails": "Opdater loginoplysninger", - "Logout": "Log af", - "OpenMobileApp": "Åbn mobilapp", - "RecentlyAdded": "Senest tilføjet" - }, - "Search": { - "Title": "Søg", - "Paragraph": "Ønsker du at se noget, som er utilgængeligt? intet problem, bare søg efter det nedenfor og anmod om det!", - "MoviesTab": "Film", - "TvTab": "Tv-serier", - "MusicTab": "Musik", - "Suggestions": "Forslag", - "NoResults": "Beklager, vi fandt ingen resultater!", - "DigitalDate": "Digital udgivelse: {{date}}", - "TheatricalRelease": "Biografudgivelse: {{date}}", - "ViewOnPlex": "Se på Plex", - "ViewOnEmby": "Se på Emby", - "RequestAdded": "{{title}} er anmodet med succes", - "Similar": "Lignende", - "Refine": "Refine", - "SearchBarPlaceholder": "Type Here to Search", - "Movies": { - "PopularMovies": "Populære film", - "UpcomingMovies": "Kommende film", - "TopRatedMovies": "Bedst bedømte film", - "NowPlayingMovies": "Aktuelle film", - "HomePage": "Startside", - "Trailer": "Trailer" + "Login": { + "SignInButton": "Log ind", + "UsernamePlaceholder": "Brugernavn", + "PasswordPlaceholder": "Adgangskode", + "RememberMe": "Husk mig", + "SignInWith": "Sign in with {{appName}}", + "SignInWithPlex": "Sign in with Plex", + "ForgottenPassword": "Glemt adgangskode?", + "Errors": { + "IncorrectCredentials": "Forkert brugernavn eller adgangskode" + } }, - "TvShows": { - "Popular": "Populære", - "Trending": "Aktuelle", - "MostWatched": "Mest sete", - "MostAnticipated": "Mest ventede", - "Results": "Resultat", - "AirDate": "Sendt den:", - "AllSeasons": "Alle sæsoner", - "FirstSeason": "Første sæson", - "LatestSeason": "Seneste sæson", - "Select": "Vælg ...", - "SubmitRequest": "Send anmodning", - "Season": "Sæson: {{seasonNumber}}", - "SelectAllInSeason": "Vælg alle i sæson {{seasonNumber}}" - } - }, - "Requests": { - "Title": "Anmodninger", - "Paragraph": "Herunder kan du se dine og alle andre anmodninger, samt status for download og godkendelse.", - "MoviesTab": "Film", - "TvTab": "Tv-serier", - "MusicTab": "Musik", - "RequestedBy": "Anmodet af:", - "Status": "Status:", - "RequestStatus": "Status for anmodning:", - "Denied": " Afvist:", - "TheatricalRelease": "Biografudgivelse: {{date}}", - "ReleaseDate": "Udgivet: {{date}}", - "TheatricalReleaseSort": "Biografudgivelse", - "DigitalRelease": "Digital udgivelse: {{date}}", - "RequestDate": "Dato for anmodning:", - "QualityOverride": "Tilsidesæt kvalitet:", - "RootFolderOverride": "Tilsidesæt rodmappe:", - "ChangeRootFolder": "Skift rodmappe", - "ChangeQualityProfile": "Skift kvalitetsprofil", - "MarkUnavailable": "Markér som utilgængelig", - "MarkAvailable": "Markér som tilgængelig", - "Remove": "Fjern", - "Deny": "Afvis", - "Season": "Sæson:", - "GridTitle": "Titel", - "AirDate": "Sendt", - "GridStatus": "Status", - "ReportIssue": "Rapportér problem", - "Filter": "Filter", - "Sort": "Sorter", - "SeasonNumberHeading": "Sæson: {seasonNumber}", - "SortTitleAsc": "Titel ▲", - "SortTitleDesc": "Titel ▼", - "SortRequestDateAsc": "Dato for anmodning ▲", - "SortRequestDateDesc": "Dato for anmodning ▼", - "SortStatusAsc": "Status ▲", - "SortStatusDesc": "Status ▼", - "Remaining": { - "Quota": "{{remaining}}/{{total}} anmodninger, der er tilbage", - "NextDays": "En anden anmodning vil blive tilføjet i {{time}} Dage", - "NextHours": "En anden anmodning vil blive tilføjet i {{time}} Timer", - "NextMinutes": "En anden anmodning vil blive tilføjet i {{time}} Minutter", - "NextMinute": "En anden anmodning vil blive tilføjet i {{time}} Minut" + "Common": { + "ContinueButton": "Fortsæt", + "Available": "Tilgængelig", + "PartiallyAvailable": "Delvist tilgængelig", + "Monitored": "Overvåget", + "NotAvailable": "Ikke tilgængelig", + "ProcessingRequest": "Behandler anmodning", + "PendingApproval": "Afventer godkendelse", + "RequestDenied": "Anmodning afvist", + "NotRequested": "Ikke anmodet", + "Requested": "Anmodet", + "Request": "Anmod", + "Denied": "Afvist", + "Approve": "Godkendt", + "PartlyAvailable": "Delvist tilgængelig", + "ViewDetails": "View Details", + "Errors": { + "Validation": "Tjek venligst dine indtastede værdier" + }, + "Cancel": "Cancel", + "Submit": "Submit" + }, + "PasswordReset": { + "EmailAddressPlaceholder": "E-mail-adresse", + "ResetPasswordButton": "Nulstil adgangskode" + }, + "LandingPage": { + "OnlineHeading": "Online nu", + "OnlineParagraph": "Medieserveren er online", + "PartiallyOnlineHeading": "Delvist online", + "PartiallyOnlineParagraph": "Medieserveren er delvist online.", + "MultipleServersUnavailable": "Der er {{serversUnavailable}} servere offline ud af {{totalServers}}.", + "SingleServerUnavailable": "Der er {{serversUnavailable}} server offline ud af {{totalServers}}.", + "OfflineHeading": "Offline nu", + "OfflineParagraph": "Medieserveren er offline.", + "CheckPageForUpdates": "Tjek denne side for løbende opdateringer." + }, + "NavigationBar": { + "Discover": "Discover", + "Search": "Søg", + "Requests": "Anmodninger", + "UserManagement": "Brugeradministration", + "Issues": "Problemer", + "Vote": "Stem", + "Donate": "Donér!", + "DonateLibraryMaintainer": "Donér til vedligeholder af bibliotek", + "DonateTooltip": "Sådan overbeviser jeg min kone om, at jeg skal bruge min fritid på at udvikle Ombi :)", + "UpdateAvailableTooltip": "Ny opdatering venter!", + "Settings": "Indstillinger", + "Welcome": "Velkommen til {{username}}", + "UpdateDetails": "Opdater loginoplysninger", + "Logout": "Log af", + "OpenMobileApp": "Åbn mobilapp", + "RecentlyAdded": "Senest tilføjet", + "ChangeTheme": "Change Theme", + "Calendar": "Calendar", + "UserPreferences": "Preferences", + "FeatureSuggestion": "Feature Suggestion", + "FeatureSuggestionTooltip": "Have a great new idea? Suggest it here!", + "Filter": { + "Movies": "Film", + "TvShows": "Tv-serier", + "Music": "Musik", + "People": "People" + }, + "MorningWelcome": "Good morning!", + "AfternoonWelcome": "Good afternoon!", + "EveningWelcome": "Good evening!" + }, + "Search": { + "Title": "Søg", + "Paragraph": "Ønsker du at se noget, som er utilgængeligt? intet problem, bare søg efter det nedenfor og anmod om det!", + "MoviesTab": "Film", + "TvTab": "Tv-serier", + "MusicTab": "Musik", + "Suggestions": "Forslag", + "NoResults": "Beklager, vi fandt ingen resultater!", + "DigitalDate": "Digital udgivelse: {{date}}", + "TheatricalRelease": "Biografudgivelse: {{date}}", + "ViewOnPlex": "Se på Plex", + "ViewOnEmby": "Se på Emby", + "RequestAdded": "{{title}} er anmodet med succes", + "Similar": "Lignende", + "Refine": "Refine", + "SearchBarPlaceholder": "Type Here to Search", + "Movies": { + "PopularMovies": "Populære film", + "UpcomingMovies": "Kommende film", + "TopRatedMovies": "Bedst bedømte film", + "NowPlayingMovies": "Aktuelle film", + "HomePage": "Startside", + "Trailer": "Trailer" + }, + "TvShows": { + "Popular": "Populære", + "Trending": "Aktuelle", + "MostWatched": "Mest sete", + "MostAnticipated": "Mest ventede", + "Results": "Resultat", + "AirDate": "Sendt den:", + "AllSeasons": "Alle sæsoner", + "FirstSeason": "Første sæson", + "LatestSeason": "Seneste sæson", + "Select": "Vælg ...", + "SubmitRequest": "Send anmodning", + "Season": "Sæson: {{seasonNumber}}", + "SelectAllInSeason": "Vælg alle i sæson {{seasonNumber}}" + } + }, + "Requests": { + "Title": "Anmodninger", + "Paragraph": "Herunder kan du se dine og alle andre anmodninger, samt status for download og godkendelse.", + "MoviesTab": "Film", + "ArtistName": "Artist", + "AlbumName": "Album Name", + "TvTab": "Tv-serier", + "MusicTab": "Musik", + "RequestedBy": "Anmodet af", + "Status": "Status", + "RequestStatus": "Status for anmodning", + "Denied": " Afvist:", + "TheatricalRelease": "Biografudgivelse: {{date}}", + "ReleaseDate": "Udgivet: {{date}}", + "TheatricalReleaseSort": "Biografudgivelse", + "DigitalRelease": "Digital udgivelse: {{date}}", + "RequestDate": "Dato for anmodning", + "QualityOverride": "Tilsidesæt kvalitet:", + "RootFolderOverride": "Tilsidesæt rodmappe:", + "ChangeRootFolder": "Skift rodmappe", + "ChangeQualityProfile": "Skift kvalitetsprofil", + "MarkUnavailable": "Markér som utilgængelig", + "MarkAvailable": "Markér som tilgængelig", + "Remove": "Fjern", + "Deny": "Afvis", + "DenyReason": "Deny Reason", + "Season": "Sæson:", + "GridTitle": "Titel", + "AirDate": "Sendt", + "GridStatus": "Status", + "ReportIssue": "Rapportér problem", + "Filter": "Filter", + "Sort": "Sorter", + "SeasonNumberHeading": "Sæson: {seasonNumber}", + "SortTitleAsc": "Titel ▲", + "SortTitleDesc": "Titel ▼", + "SortRequestDateAsc": "Dato for anmodning ▲", + "SortRequestDateDesc": "Dato for anmodning ▼", + "SortStatusAsc": "Status ▲", + "SortStatusDesc": "Status ▼", + "Remaining": { + "Quota": "{{remaining}}/{{total}} anmodninger, der er tilbage", + "NextDays": "En anden anmodning vil blive tilføjet i {{time}} Dage", + "NextHours": "En anden anmodning vil blive tilføjet i {{time}} Timer", + "NextMinutes": "En anden anmodning vil blive tilføjet i {{time}} Minutter", + "NextMinute": "En anden anmodning vil blive tilføjet i {{time}} Minut" + }, + "AllRequests": "All Requests", + "PendingRequests": "Pending Requests", + "ProcessingRequests": "Processing Requests", + "AvailableRequests": "Available Requests", + "DeniedRequests": "Denied Requests", + "RequestsToDisplay": "Requests to display", + "RequestsTitle": "Titel", + "Details": "Detaljer", + "Options": "Options", + "RequestPanel": { + "Delete": "Delete Request", + "Approve": "Approve Request", + "ChangeAvailability": "Mark Available" + } + }, + "Issues": { + "Title": "Problemer", + "PendingTitle": "Afventende problemer", + "InProgressTitle": "Igangværende probemer", + "ResolvedTitle": "Løste problemer", + "ColumnTitle": "Titel", + "Category": "Kategori", + "Status": "Status", + "Details": "Detaljer", + "Description": "Beskrivelse", + "NoComments": "Ingen kommentarer!", + "MarkInProgress": "Markér som igangværende", + "MarkResolved": "Markér som løst", + "SendMessageButton": "Send", + "Subject": "Emne", + "Comments": "Kommentarer", + "WriteMessagePlaceholder": "Indtast din besked her...", + "ReportedBy": "Anmeldt af", + "IssueDialog": { + "Title": "Report an issue", + "DescriptionPlaceholder": "Please describe the issue", + "TitlePlaceholder": "Short title of your issue", + "SelectCategory": "Select Category", + "IssueCreated": "Issue has been created" + }, + "Outstanding": "There are outstanding issues", + "ResolvedDate": "Resolved date", + "CreatedDate": "Raised on", + "MarkedAsResolved": "This issue has now been marked as resolved!", + "MarkedAsInProgress": "This issue has now been marked as in progress!", + "Delete": "Delete issue", + "DeletedIssue": "Issue has been deleted" + }, + "Filter": { + "ClearFilter": "Nulstil filter", + "FilterHeaderAvailability": "Tilgængelighed", + "FilterHeaderRequestStatus": "Status", + "Approved": "Godkendt", + "PendingApproval": "Afventer godkendelse" + }, + "UserManagment": { + "TvRemaining": "Tv: {{remaining}}/{{total}} Resterende", + "MovieRemaining": "Film: {{remaining}}/{{total}} Resterende", + "MusicRemaining": "Musik: {{remaining}}/{{total}} Resterende", + "TvDue": "Tv: {{date}}", + "MovieDue": "Film: {{date}}", + "MusicDue": "Musik: {{date}}" + }, + "Votes": { + "CompletedVotesTab": "Stemt", + "VotesTab": "Nødvendige stemmer" + }, + "MediaDetails": { + "Denied": "Afvist", + "RecommendationsTitle": "Recommendations", + "SimilarTitle": "Lignende", + "VideosTitle": "Videos", + "AlbumsTitle": "Albums", + "RequestAllAlbums": "Request All Albums", + "ClearSelection": "Clear Selection", + "RequestSelectedAlbums": "Request Selected Albums", + "ViewCollection": "View Collection", + "NotEnoughInfo": "Unfortunately there is not enough information about this show yet!", + "AdvancedOptions": "Advanced Options", + "QualityProfilesSelect": "Select A Quality Profile", + "RootFolderSelect": "Select A Root Folder", + "Status": "Status", + "Availability": "Tilgængelighed", + "RequestStatus": "Request Status", + "Quality": "Quality", + "RootFolderOverride": "Tilsidesæt rodmappe", + "QualityOverride": "Tilsidesæt kvalitet", + "Genres": "Genres", + "TheatricalRelease": "Biografudgivelse", + "DigitalRelease": "Digital Release", + "UserScore": "User Score", + "Votes": "Votes", + "Runtime": "Runtime", + "Minutes": "{{runtime}} Minutes", + "Revenue": "Revenue", + "Budget": "Budget", + "Keywords": "Keywords/Tags", + "Casts": { + "CastTitle": "Cast" + }, + "EpisodeSelector": { + "AllSeasonsTooltip": "This will request every season for this show", + "FirstSeasonTooltip": "This will only request the First Season for this show", + "LatestSeasonTooltip": "This will only request the Latest Season for this show" + } + }, + "Discovery": { + "PopularTab": "Populære", + "TrendingTab": "Aktuelle", + "UpcomingTab": "Upcoming", + "Movies": "Film", + "Combined": "Combined", + "Tv": "TV", + "CardDetails": { + "Availability": "Tilgængelighed", + "Studio": "Studio", + "Network": "Network", + "UnknownNetwork": "Unknown", + "RequestStatus": "Request Status", + "Director": "Director", + "InCinemas": "In Cinemas", + "FirstAired": "First Aired", + "Writer": "Writer", + "ExecProducer": "Exec Producer" + } + }, + "UserPreferences": { + "Welcome": "Velkommen til {{username}}!", + "OmbiLanguage": "Language", + "DarkMode": "Dark Mode" } - }, - "Issues": { - "Title": "Problemer", - "PendingTitle": "Afventende problemer", - "InProgressTitle": "Igangværende probemer", - "ResolvedTitle": "Løste problemer", - "ColumnTitle": "Titel", - "Category": "Kategori", - "Status": "Status", - "Details": "Detaljer", - "Description": "Beskrivelse", - "NoComments": "Ingen kommentarer!", - "MarkInProgress": "Markér som igangværende", - "MarkResolved": "Markér som løst", - "SendMessageButton": "Send", - "Subject": "Emne", - "Comments": "Kommentarer", - "WriteMessagePlaceholder": "Indtast din besked her...", - "ReportedBy": "Anmeldt af" - }, - "Filter": { - "ClearFilter": "Nulstil filter", - "FilterHeaderAvailability": "Tilgængelighed", - "FilterHeaderRequestStatus": "Status", - "Approved": "Godkendt", - "PendingApproval": "Afventer godkendelse" - }, - "UserManagment": { - "TvRemaining": "Tv: {{remaining}}/{{total}} Resterende", - "MovieRemaining": "Film: {{remaining}}/{{total}} Resterende", - "MusicRemaining": "Musik: {{remaining}}/{{total}} Resterende", - "TvDue": "Tv: {{date}}", - "MovieDue": "Film: {{date}}", - "MusicDue": "Musik: {{date}}" - }, - "Votes": { - "CompletedVotesTab": "Stemt", - "VotesTab": "Nødvendige stemmer" - } -} +} \ No newline at end of file diff --git a/src/Ombi/wwwroot/translations/de.json b/src/Ombi/wwwroot/translations/de.json index 55356306f..b661f874d 100644 --- a/src/Ombi/wwwroot/translations/de.json +++ b/src/Ombi/wwwroot/translations/de.json @@ -1,186 +1,301 @@ { - "Login": { - "SignInButton": "Anmelden", - "UsernamePlaceholder": "Benutzername", - "PasswordPlaceholder": "Passwort", - "RememberMe": "Eingeloggt bleiben", - "ForgottenPassword": "Passwort vergessen?", - "Errors": { - "IncorrectCredentials": "Falscher Benutzername oder falsches Passwort" - } - }, - "Common": { - "ContinueButton": "Weiter", - "Available": "Verfügbar", - "PartiallyAvailable": "Teilweise verfügbar", - "Monitored": "Überwacht", - "NotAvailable": "Nicht verfügbar", - "ProcessingRequest": "Anfrage wird bearbeitet", - "PendingApproval": "Genehmigung ausstehend", - "RequestDenied": "Anfrage abgelehnt", - "NotRequested": "Nicht angefragt", - "Requested": "Angefordert", - "Request": "Anfrage", - "Denied": "Abgelehnt", - "Approve": "Genehmigen", - "PartlyAvailable": "Teilweise verfügbar", - "Errors": { - "Validation": "Bitte überprüfen Sie die eingegebenen Werte" - } - }, - "PasswordReset": { - "EmailAddressPlaceholder": "E-Mail-Adresse", - "ResetPasswordButton": "Passwort zurücksetzen" - }, - "LandingPage": { - "OnlineHeading": "Gerade Online", - "OnlineParagraph": "Der Mediaserver ist gerade online", - "PartiallyOnlineHeading": "Teilweise Online", - "PartiallyOnlineParagraph": "Der Mediaserver ist teilweise online.", - "MultipleServersUnavailable": "Es sind {{serversUnavailable}} von {{totalServers}} Servern offline.", - "SingleServerUnavailable": "Es sind {{serversUnavailable}} von {{totalServers}} Servern offline.", - "OfflineHeading": "Derzeit Offline", - "OfflineParagraph": "Der Mediaserver ist derzeit offline.", - "CheckPageForUpdates": "Überprüfe diese Seite für kontinuierliche Website-Updates." - }, - "NavigationBar": { - "Search": "Suche", - "Requests": "Anfragen", - "UserManagement": "Benutzerverwaltung", - "Issues": "Probleme", - "Vote": "Bewerten", - "Donate": "Spenden!", - "DonateLibraryMaintainer": "Spende sie an den Bibliotheks Betreuer", - "DonateTooltip": "So überzeuge ich meine Frau, meine Freizeit mit der Entwicklung von Ombi zu verbringen ;)", - "UpdateAvailableTooltip": "Update verfügbar!", - "Settings": "Einstellungen", - "Welcome": "Willkommen {{username}}", - "UpdateDetails": "Update-Details", - "Logout": "Ausloggen", - "OpenMobileApp": "Mobile App", - "RecentlyAdded": "Kürzlich hinzugefügt" - }, - "Search": { - "Title": "Suche", - "Paragraph": "Möchtest du etwas sehen, das nicht verfügbar ist? Kein Problem, benutze einfach die Suchbox und fordere es an!", - "MoviesTab": "Filme", - "TvTab": "Serien", - "MusicTab": "Musik", - "Suggestions": "Vorschläge", - "NoResults": "Es tut uns leid, wir haben keine Ergebnisse gefunden!", - "DigitalDate": "Veröffentlichung der digitalen Version: {{date}}", - "TheatricalRelease": "Kinostart: {{date}}", - "ViewOnPlex": "In Plex anschauen", - "ViewOnEmby": "In Emby anschauen", - "RequestAdded": "Anfrage für {{title}} wurde erfolgreich hinzugefügt", - "Similar": "Ähnliche", - "Refine": "Auswahl verfeinern", - "SearchBarPlaceholder": "Suchwort eingeben", - "Movies": { - "PopularMovies": "Beliebte Filme", - "UpcomingMovies": "Kommende Filme", - "TopRatedMovies": "Am besten bewertete Filme", - "NowPlayingMovies": "Im Kino", - "HomePage": "Startseite", - "Trailer": "Trailer" + "Login": { + "SignInButton": "Anmelden", + "UsernamePlaceholder": "Benutzername", + "PasswordPlaceholder": "Passwort", + "RememberMe": "Eingeloggt bleiben", + "SignInWith": "Sign in with {{appName}}", + "SignInWithPlex": "Sign in with Plex", + "ForgottenPassword": "Passwort vergessen?", + "Errors": { + "IncorrectCredentials": "Falscher Benutzername oder falsches Passwort" + } }, - "TvShows": { - "Popular": "Beliebt", - "Trending": "im Trend", - "MostWatched": "Meist gesehen", - "MostAnticipated": "Meist erwartet", - "Results": "Ergebnisse", - "AirDate": "Veröffentlicht am:", - "AllSeasons": "Alle Staffeln", - "FirstSeason": "erste Staffel", - "LatestSeason": "aktuellste Staffel", - "Select": "Wähle...", - "SubmitRequest": "Anfrage einreichen", - "Season": "Staffel: {{seasonNumber}}", - "SelectAllInSeason": "Markiere alles in Staffel {{seasonNumber}}" - } - }, - "Requests": { - "Title": "Anfragen", - "Paragraph": "Unten sehen Sie Ihre und alle anderen Anfragen, sowie deren Download und Genehmigungsstatus.", - "MoviesTab": "Filme", - "TvTab": "Serien", - "MusicTab": "Musik", - "RequestedBy": "Angefordert von:", - "Status": "Status:", - "RequestStatus": "Anfrage Status:", - "Denied": " Abgelehnt:", - "TheatricalRelease": "Kinostart: {{date}}", - "ReleaseDate": "Veröffentlicht: {{date}}", - "TheatricalReleaseSort": "Kinostart", - "DigitalRelease": "Veröffentlichung der digitalen Version: {{date}}", - "RequestDate": "Datum der Anfrage:", - "QualityOverride": "Qualitäts Überschreiben:", - "RootFolderOverride": "Stammverzeichnis Überschreiben:", - "ChangeRootFolder": "Stammordner ändern", - "ChangeQualityProfile": "Qualitätsprofil ändern", - "MarkUnavailable": "Als Nicht verfügbar markieren", - "MarkAvailable": "Als verfügbar markieren", - "Remove": "Entfernen", - "Deny": "Ablehnen", - "Season": "Staffel:", - "GridTitle": "Titel", - "AirDate": "Erstausstrahlung", - "GridStatus": "Status", - "ReportIssue": "Problem melden", - "Filter": "Filter", - "Sort": "Sortieren", - "SeasonNumberHeading": "Staffel: {seasonNumber}", - "SortTitleAsc": "Titel ▲", - "SortTitleDesc": "Titel ▼", - "SortRequestDateAsc": "Datum der Anfrage ▲", - "SortRequestDateDesc": "Datum der Anfrage ▼", - "SortStatusAsc": "Status ▲", - "SortStatusDesc": "Status ▼", - "Remaining": { - "Quota": "{{remaining}}/{{total}} Anfragen verbleiben", - "NextDays": "Eine weitere Anfrage wird in {{time}} Tagen hinzugefügt", - "NextHours": "Eine weitere Anfrage wird in {{time}} Stunden hinzugefügt", - "NextMinutes": "Eine weitere Anfrage wird in {{time}} Minuten hinzugefügt", - "NextMinute": "Eine weitere Anfrage wird in {{time}} Minute hinzugefügt" + "Common": { + "ContinueButton": "Weiter", + "Available": "Verfügbar", + "PartiallyAvailable": "Teilweise verfügbar", + "Monitored": "Überwacht", + "NotAvailable": "Nicht verfügbar", + "ProcessingRequest": "Anfrage wird bearbeitet", + "PendingApproval": "Genehmigung ausstehend", + "RequestDenied": "Anfrage abgelehnt", + "NotRequested": "Nicht angefragt", + "Requested": "Angefordert", + "Request": "Anfrage", + "Denied": "Abgelehnt", + "Approve": "Genehmigen", + "PartlyAvailable": "Teilweise verfügbar", + "ViewDetails": "Details anzeigen", + "Errors": { + "Validation": "Bitte überprüfen Sie die eingegebenen Werte" + }, + "Cancel": "Cancel", + "Submit": "Submit" + }, + "PasswordReset": { + "EmailAddressPlaceholder": "E-Mail-Adresse", + "ResetPasswordButton": "Passwort zurücksetzen" + }, + "LandingPage": { + "OnlineHeading": "Gerade Online", + "OnlineParagraph": "Der Mediaserver ist gerade online", + "PartiallyOnlineHeading": "Teilweise Online", + "PartiallyOnlineParagraph": "Der Mediaserver ist teilweise online.", + "MultipleServersUnavailable": "Es sind {{serversUnavailable}} von {{totalServers}} Servern offline.", + "SingleServerUnavailable": "Es sind {{serversUnavailable}} von {{totalServers}} Servern offline.", + "OfflineHeading": "Derzeit Offline", + "OfflineParagraph": "Der Mediaserver ist derzeit offline.", + "CheckPageForUpdates": "Überprüfe diese Seite für kontinuierliche Website-Updates." + }, + "NavigationBar": { + "Discover": "Entdecken", + "Search": "Suche", + "Requests": "Anfragen", + "UserManagement": "Benutzerverwaltung", + "Issues": "Probleme", + "Vote": "Bewerten", + "Donate": "Spenden!", + "DonateLibraryMaintainer": "Spende sie an den Bibliotheks Betreuer", + "DonateTooltip": "So überzeuge ich meine Frau, meine Freizeit mit der Entwicklung von Ombi zu verbringen ;)", + "UpdateAvailableTooltip": "Update verfügbar!", + "Settings": "Einstellungen", + "Welcome": "Willkommen {{username}}", + "UpdateDetails": "Update-Details", + "Logout": "Ausloggen", + "OpenMobileApp": "Mobile App", + "RecentlyAdded": "Kürzlich hinzugefügt", + "ChangeTheme": "Theme ändern", + "Calendar": "Kalneder", + "UserPreferences": "Einstellungen", + "FeatureSuggestion": "Feature Suggestion", + "FeatureSuggestionTooltip": "Have a great new idea? Suggest it here!", + "Filter": { + "Movies": "Filme", + "TvShows": "Serien", + "Music": "Musik", + "People": "People" + }, + "MorningWelcome": "Good morning!", + "AfternoonWelcome": "Good afternoon!", + "EveningWelcome": "Good evening!" + }, + "Search": { + "Title": "Suche", + "Paragraph": "Möchtest du etwas sehen, das nicht verfügbar ist? Kein Problem, benutze einfach die Suchbox und fordere es an!", + "MoviesTab": "Filme", + "TvTab": "Serien", + "MusicTab": "Musik", + "Suggestions": "Vorschläge", + "NoResults": "Es tut uns leid, wir haben keine Ergebnisse gefunden!", + "DigitalDate": "Veröffentlichung der digitalen Version: {{date}}", + "TheatricalRelease": "Kinostart: {{date}}", + "ViewOnPlex": "In Plex anschauen", + "ViewOnEmby": "In Emby anschauen", + "RequestAdded": "Anfrage für {{title}} wurde erfolgreich hinzugefügt", + "Similar": "Ähnliche", + "Refine": "Auswahl verfeinern", + "SearchBarPlaceholder": "Suchwort eingeben", + "Movies": { + "PopularMovies": "Beliebte Filme", + "UpcomingMovies": "Kommende Filme", + "TopRatedMovies": "Am besten bewertete Filme", + "NowPlayingMovies": "Im Kino", + "HomePage": "Startseite", + "Trailer": "Trailer" + }, + "TvShows": { + "Popular": "Beliebt", + "Trending": "im Trend", + "MostWatched": "Meist gesehen", + "MostAnticipated": "Meist erwartet", + "Results": "Ergebnisse", + "AirDate": "Veröffentlicht am:", + "AllSeasons": "Alle Staffeln", + "FirstSeason": "erste Staffel", + "LatestSeason": "aktuellste Staffel", + "Select": "Wähle...", + "SubmitRequest": "Anfrage einreichen", + "Season": "Staffel: {{seasonNumber}}", + "SelectAllInSeason": "Markiere alles in Staffel {{seasonNumber}}" + } + }, + "Requests": { + "Title": "Anfragen", + "Paragraph": "Unten sehen Sie Ihre und alle anderen Anfragen, sowie deren Download und Genehmigungsstatus.", + "MoviesTab": "Filme", + "ArtistName": "Artist", + "AlbumName": "Album Name", + "TvTab": "Serien", + "MusicTab": "Musik", + "RequestedBy": "Angefordert von", + "Status": "Status", + "RequestStatus": "Anfrage Status", + "Denied": " Abgelehnt:", + "TheatricalRelease": "Kinostart: {{date}}", + "ReleaseDate": "Veröffentlicht: {{date}}", + "TheatricalReleaseSort": "Kinostart", + "DigitalRelease": "Veröffentlichung der digitalen Version: {{date}}", + "RequestDate": "Datum der Anfrage", + "QualityOverride": "Qualitäts Überschreiben:", + "RootFolderOverride": "Stammverzeichnis Überschreiben:", + "ChangeRootFolder": "Stammordner ändern", + "ChangeQualityProfile": "Qualitätsprofil ändern", + "MarkUnavailable": "Als Nicht verfügbar markieren", + "MarkAvailable": "Als verfügbar markieren", + "Remove": "Entfernen", + "Deny": "Ablehnen", + "DenyReason": "Ablehnungsgrund", + "Season": "Staffel:", + "GridTitle": "Titel", + "AirDate": "Erstausstrahlung", + "GridStatus": "Status", + "ReportIssue": "Problem melden", + "Filter": "Filter", + "Sort": "Sortieren", + "SeasonNumberHeading": "Staffel: {seasonNumber}", + "SortTitleAsc": "Titel ▲", + "SortTitleDesc": "Titel ▼", + "SortRequestDateAsc": "Datum der Anfrage ▲", + "SortRequestDateDesc": "Datum der Anfrage ▼", + "SortStatusAsc": "Status ▲", + "SortStatusDesc": "Status ▼", + "Remaining": { + "Quota": "{{remaining}}/{{total}} Anfragen verbleiben", + "NextDays": "Eine weitere Anfrage wird in {{time}} Tagen hinzugefügt", + "NextHours": "Eine weitere Anfrage wird in {{time}} Stunden hinzugefügt", + "NextMinutes": "Eine weitere Anfrage wird in {{time}} Minuten hinzugefügt", + "NextMinute": "Eine weitere Anfrage wird in {{time}} Minute hinzugefügt" + }, + "AllRequests": "All Requests", + "PendingRequests": "Pending Requests", + "ProcessingRequests": "Processing Requests", + "AvailableRequests": "Available Requests", + "DeniedRequests": "Denied Requests", + "RequestsToDisplay": "Requests to display", + "RequestsTitle": "Titel", + "Details": "Details", + "Options": "Options", + "RequestPanel": { + "Delete": "Delete Request", + "Approve": "Approve Request", + "ChangeAvailability": "Mark Available" + } + }, + "Issues": { + "Title": "Probleme", + "PendingTitle": "Ausstehende Probleme", + "InProgressTitle": "Probleme in bearbeitung", + "ResolvedTitle": "Behobene Probleme", + "ColumnTitle": "Titel", + "Category": "Kategorie", + "Status": "Status", + "Details": "Details", + "Description": "Beschreibung", + "NoComments": "Keine Kommentare!", + "MarkInProgress": "Als in Bearbeitung markieren", + "MarkResolved": "Als gelöst markieren", + "SendMessageButton": "Senden", + "Subject": "Betreff", + "Comments": "Kommentare", + "WriteMessagePlaceholder": "Nachricht eingeben...", + "ReportedBy": "Gemeldet von", + "IssueDialog": { + "Title": "Report an issue", + "DescriptionPlaceholder": "Please describe the issue", + "TitlePlaceholder": "Short title of your issue", + "SelectCategory": "Select Category", + "IssueCreated": "Issue has been created" + }, + "Outstanding": "There are outstanding issues", + "ResolvedDate": "Resolved date", + "CreatedDate": "Raised on", + "MarkedAsResolved": "This issue has now been marked as resolved!", + "MarkedAsInProgress": "This issue has now been marked as in progress!", + "Delete": "Delete issue", + "DeletedIssue": "Issue has been deleted" + }, + "Filter": { + "ClearFilter": "Filter zurücksetzen", + "FilterHeaderAvailability": "Verfügbarkeit", + "FilterHeaderRequestStatus": "Status", + "Approved": "Bestätigt", + "PendingApproval": "Genehmigung ausstehend" + }, + "UserManagment": { + "TvRemaining": "TV: {{remaining}}/{{total}} verbleibend", + "MovieRemaining": "Filme: {{remaining}}/{{total}} verbleibend", + "MusicRemaining": "Musik: {{remaining}}/{{total}} verbleibend", + "TvDue": "TV: {{date}}", + "MovieDue": "Film: {{date}}", + "MusicDue": "Musik: {{date}}" + }, + "Votes": { + "CompletedVotesTab": "Bewertet", + "VotesTab": "Erforderliche Bewertungen" + }, + "MediaDetails": { + "Denied": "Abgelehnt", + "RecommendationsTitle": "Empfehlungen", + "SimilarTitle": "Ähnliche", + "VideosTitle": "Videos", + "AlbumsTitle": "Albums", + "RequestAllAlbums": "Request All Albums", + "ClearSelection": "Clear Selection", + "RequestSelectedAlbums": "Request Selected Albums", + "ViewCollection": "View Collection", + "NotEnoughInfo": "Unfortunately there is not enough information about this show yet!", + "AdvancedOptions": "Advanced Options", + "QualityProfilesSelect": "Select A Quality Profile", + "RootFolderSelect": "Select A Root Folder", + "Status": "Status", + "Availability": "Verfügbarkeit", + "RequestStatus": "Anfrage Status", + "Quality": "Quality", + "RootFolderOverride": "Stammverzeichnis Überschreiben", + "QualityOverride": "Qualitäts Überschreiben", + "Genres": "Genres", + "TheatricalRelease": "Kinostart", + "DigitalRelease": "Digital Release", + "UserScore": "User Score", + "Votes": "Votes", + "Runtime": "Runtime", + "Minutes": "{{runtime}} Minutes", + "Revenue": "Revenue", + "Budget": "Budget", + "Keywords": "Keywords/Tags", + "Casts": { + "CastTitle": "Besetzung" + }, + "EpisodeSelector": { + "AllSeasonsTooltip": "Dies wird jede Saison für diese Show anfordern", + "FirstSeasonTooltip": "Dies wird nur die erste Saison für diese Show anfordern", + "LatestSeasonTooltip": "Dies wird nur die letzte Saison für diese Show anfordern" + } + }, + "Discovery": { + "PopularTab": "Beliebt", + "TrendingTab": "Angesagt", + "UpcomingTab": "Demnächst", + "Movies": "Filme", + "Combined": "Combined", + "Tv": "TV", + "CardDetails": { + "Availability": "Verfügbarkeit", + "Studio": "Studio", + "Network": "Netzwerk", + "UnknownNetwork": "Unbekannt", + "RequestStatus": "Anfrage Status", + "Director": "Director", + "InCinemas": "In Kinos", + "FirstAired": "Erstausstrahlung", + "Writer": "AutorIn", + "ExecProducer": "Ausführender Produzent" + } + }, + "UserPreferences": { + "Welcome": "Willkommen {{username}}!", + "OmbiLanguage": "Language", + "DarkMode": "Dark Mode" } - }, - "Issues": { - "Title": "Probleme", - "PendingTitle": "Ausstehende Probleme", - "InProgressTitle": "Probleme in bearbeitung", - "ResolvedTitle": "Behobene Probleme", - "ColumnTitle": "Titel", - "Category": "Kategorie", - "Status": "Status", - "Details": "Details", - "Description": "Beschreibung", - "NoComments": "Keine Kommentare!", - "MarkInProgress": "Als in Bearbeitung markieren", - "MarkResolved": "Als gelöst markieren", - "SendMessageButton": "Senden", - "Subject": "Betreff", - "Comments": "Kommentare", - "WriteMessagePlaceholder": "Nachricht eingeben...", - "ReportedBy": "Gemeldet von" - }, - "Filter": { - "ClearFilter": "Filter zurücksetzen", - "FilterHeaderAvailability": "Verfügbarkeit", - "FilterHeaderRequestStatus": "Status", - "Approved": "Bestätigt", - "PendingApproval": "Genehmigung ausstehend" - }, - "UserManagment": { - "TvRemaining": "TV: {{remaining}}/{{total}} verbleibend", - "MovieRemaining": "Filme: {{remaining}}/{{total}} verbleibend", - "MusicRemaining": "Musik: {{remaining}}/{{total}} verbleibend", - "TvDue": "TV: {{date}}", - "MovieDue": "Film: {{date}}", - "MusicDue": "Musik: {{date}}" - }, - "Votes": { - "CompletedVotesTab": "Bewertet", - "VotesTab": "Erforderliche Bewertungen" - } -} +} \ No newline at end of file diff --git a/src/Ombi/wwwroot/translations/en.json b/src/Ombi/wwwroot/translations/en.json index db241b62d..665811489 100644 --- a/src/Ombi/wwwroot/translations/en.json +++ b/src/Ombi/wwwroot/translations/en.json @@ -1,242 +1,301 @@ { - "Login": { - "SignInButton": "Sign in", - "UsernamePlaceholder": "Username", - "PasswordPlaceholder": "Password", - "RememberMe": "Remember Me", - "SignInWith": "Sign in with {{appName}}", - "SignInWithPlex": "Sign in with Plex", - "ForgottenPassword": "Forgot your password?", - "Errors": { - "IncorrectCredentials": "Incorrect username or password" - } - }, - "Common": { - "ContinueButton": "Continue", - "Available": "Available", - "PartiallyAvailable": "Partially Available", - "Monitored": "Monitored", - "NotAvailable": "Not Available", - "ProcessingRequest": "Processing Request", - "PendingApproval": "Pending Approval", - "RequestDenied": "Request Denied", - "NotRequested": "Not Requested", - "Requested": "Requested", - "Request": "Request", - "Denied": "Denied", - "Approve": "Approve", - "PartlyAvailable": "Partly Available", - "ViewDetails": "View Details", - "Errors": { - "Validation": "Please check your entered values" + "Login": { + "SignInButton": "Sign in", + "UsernamePlaceholder": "Username", + "PasswordPlaceholder": "Password", + "RememberMe": "Remember Me", + "SignInWith": "Sign in with {{appName}}", + "SignInWithPlex": "Sign in with Plex", + "ForgottenPassword": "Forgot your password?", + "Errors": { + "IncorrectCredentials": "Incorrect username or password" + } }, - "Cancel":"Cancel", - "Submit":"Submit" - }, - "PasswordReset": { - "EmailAddressPlaceholder": "Email Address", - "ResetPasswordButton": "Reset Password" - }, - "LandingPage": { - "OnlineHeading": "Currently Online", - "OnlineParagraph": "The media server is currently online", - "PartiallyOnlineHeading": "Partially Online", - "PartiallyOnlineParagraph": "The media server is partially online.", - "MultipleServersUnavailable": "There are {{serversUnavailable}} servers offline out of {{totalServers}}.", - "SingleServerUnavailable": "There is {{serversUnavailable}} server offline out of {{totalServers}}.", - "OfflineHeading": "Currently Offline", - "OfflineParagraph": "The media server is currently offline.", - "CheckPageForUpdates": "Check this page for continuous site updates." - }, - "NavigationBar": { - "Discover": "Discover", - "Search": "Search", - "Requests": "Requests", - "UserManagement": "User Management", - "Issues": "Issues", - "Vote": "Vote", - "Donate": "Donate!", - "DonateLibraryMaintainer": "Donate to Library Maintainer", - "DonateTooltip": "This is how I convince my wife to let me spend my spare time developing Ombi ;)", - "UpdateAvailableTooltip": "Update Available!", - "Settings": "Settings", - "Welcome": "Welcome {{username}}", - "UpdateDetails": "Update Details", - "Logout": "Logout", - "OpenMobileApp": "Open Mobile App", - "RecentlyAdded": "Recently Added", - "ChangeTheme":"Change Theme", - "Calendar":"Calendar", - "UserPreferences": "Preferences" - }, - "Search": { - "Title": "Search", - "Paragraph": "Want to watch something that is not currently available? No problem, just search for it below and request it!", - "MoviesTab": "Movies", - "TvTab": "TV Shows", - "MusicTab": "Music", - "Suggestions": "Suggestions", - "NoResults": "Sorry, we didn't find any results!", - "DigitalDate": "Digital Release: {{date}}", - "TheatricalRelease": "Theatrical Release: {{date}}", - "ViewOnPlex": "View On Plex", - "ViewOnEmby": "View On Emby", - "RequestAdded": "Request for {{title}} has been added successfully", - "Similar":"Similar", - "Refine":"Refine", - "SearchBarPlaceholder":"Type Here to Search", - "Movies": { - "PopularMovies": "Popular Movies", - "UpcomingMovies": "Upcoming Movies", - "TopRatedMovies": "Top Rated Movies", - "NowPlayingMovies": "Now Playing Movies", - "HomePage": "Home Page", - "Trailer": "Trailer" + "Common": { + "ContinueButton": "Continue", + "Available": "Available", + "PartiallyAvailable": "Partially Available", + "Monitored": "Monitored", + "NotAvailable": "Not Available", + "ProcessingRequest": "Processing Request", + "PendingApproval": "Pending Approval", + "RequestDenied": "Request Denied", + "NotRequested": "Not Requested", + "Requested": "Requested", + "Request": "Request", + "Denied": "Denied", + "Approve": "Approve", + "PartlyAvailable": "Partly Available", + "ViewDetails": "View Details", + "Errors": { + "Validation": "Please check your entered values" + }, + "Cancel": "Cancel", + "Submit": "Submit" }, - "TvShows": { - "Popular": "Popular", - "Trending": "Trending", - "MostWatched": "Most Watched", - "MostAnticipated": "Most Anticipated", - "Results": "Results", - "AirDate": "Air Date:", - "AllSeasons": "All Seasons", - "FirstSeason": "First Season", - "LatestSeason": "Latest Season", - "Select": "Select ...", - "SubmitRequest": "Submit Request", - "Season": "Season: {{seasonNumber}}", - "SelectAllInSeason": "Select All in Season {{seasonNumber}}" - } - }, - "Requests": { - "Title": "Requests", - "Paragraph": "Below you can see yours and all other requests, as well as their download and approval status.", - "MoviesTab": "Movies", - "TvTab": "TV Shows", - "MusicTab": "Music", - "RequestedBy": "Requested By:", - "Status": "Status:", - "RequestStatus": "Request status:", - "Denied": " Denied:", - "TheatricalRelease": "Theatrical Release: {{date}}", - "ReleaseDate": "Released: {{date}}", - "TheatricalReleaseSort": "Theatrical Release", - "DigitalRelease": "Digital Release: {{date}}", - "RequestDate": "Request Date:", - "QualityOverride": "Quality Override:", - "RootFolderOverride": "Root Folder Override:", - "ChangeRootFolder": "Root Folder", - "ChangeQualityProfile": "Quality Profile", - "MarkUnavailable": "Mark Unavailable", - "MarkAvailable": "Mark Available", - "Remove": "Remove", - "Deny": "Deny", - "DenyReason": "Deny Reason", - "Season": "Season:", - "GridTitle": "Title", - "AirDate": "AirDate", - "GridStatus": "Status", - "ReportIssue": "Report Issue", - "Filter": "Filter", - "Sort": "Sort", - "SeasonNumberHeading": "Season: {seasonNumber}", - "SortTitleAsc": "Title ▲", - "SortTitleDesc": "Title ▼", - "SortRequestDateAsc": "Request Date ▲", - "SortRequestDateDesc": "Request Date ▼", - "SortStatusAsc": "Status ▲", - "SortStatusDesc": "Status ▼", - "Remaining": { - "Quota": "{{remaining}}/{{total}} requests remaining", - "NextDays": "Another request will be added in {{time}} days", - "NextHours": "Another request will be added in {{time}} hours", - "NextMinutes": "Another request will be added in {{time}} minutes", - "NextMinute": "Another request will be added in {{time}} minute" - } - }, - "Issues": { - "Title": "Issues", - "PendingTitle": "Pending Issues", - "InProgressTitle": "In Progress Issues", - "ResolvedTitle": "Resolved Issues", - "ColumnTitle": "Title", - "Category": "Category", - "Status": "Status", - "Details": "Details", - "Description": "Description", - "NoComments": "No Comments!", - "MarkInProgress": "Mark In Progress", - "MarkResolved": "Mark Resolved", - "SendMessageButton": "Send", - "Subject": "Subject", - "Comments": "Comments", - "WriteMessagePlaceholder": "Write your message here...", - "ReportedBy": "Reported By", - "IssueDialog": { - "Title":"Report an issue", - "DescriptionPlaceholder":"Please describe the issue", - "TitlePlaceholder":"Short title of your issue", - "SelectCategory": "Select Category", - "IssueCreated":"Issue has been created" - } - }, - "Filter": { - "ClearFilter": "Clear Filter", - "FilterHeaderAvailability": "Availability", - "FilterHeaderRequestStatus": "Status", - "Approved": "Approved", - "PendingApproval": "Pending Approval" - }, - "UserManagment": { - "TvRemaining": "TV: {{remaining}}/{{total}} remaining", - "MovieRemaining": "Movies: {{remaining}}/{{total}} remaining", - "MusicRemaining": "Music: {{remaining}}/{{total}} remaining", - "TvDue": "TV: {{date}}", - "MovieDue": "Movie: {{date}}", - "MusicDue": "Music: {{date}}" - }, - "Votes": { - "CompletedVotesTab": "Voted", - "VotesTab": "Votes Needed" - }, - "MediaDetails": { - "Denied": "Denied", - "RecommendationsTitle": "Recommendations", - "SimilarTitle": "Similar", - "VideosTitle": "Videos", - "AlbumsTitle":"Albums", - "RequestAllAlbums":"Request All Albums", - "Casts": { - "CastTitle": "Cast", - "Character": "Character", - "Actor": "Actor" + "PasswordReset": { + "EmailAddressPlaceholder": "Email Address", + "ResetPasswordButton": "Reset Password" }, - "EpisodeSelector":{ - "AllSeasonsTooltip":"This will request every season for this show", - "FirstSeasonTooltip":"This will only request the First Season for this show", - "LatestSeasonTooltip":"This will only request the Latest Season for this show" - } - }, - "Discovery": { - "PopularTab": "Popular", - "TrendingTab": "Trending", - "UpcomingTab": "Upcoming", - "CardDetails": { - "Availability": "Availability", - "Studio": "Studio", - "Network": "Network", - "UnknownNetwork": "Unknown", - "RequestStatus": "Request Status", - "Director": "Director", - "InCinemas": "In Cinemas", - "FirstAired": "First Aired", - "Writer": "Writer", - "ExecProducer": "Exec Producer" + "LandingPage": { + "OnlineHeading": "Currently Online", + "OnlineParagraph": "The media server is currently online", + "PartiallyOnlineHeading": "Partially Online", + "PartiallyOnlineParagraph": "The media server is partially online.", + "MultipleServersUnavailable": "There are {{serversUnavailable}} servers offline out of {{totalServers}}.", + "SingleServerUnavailable": "There is {{serversUnavailable}} server offline out of {{totalServers}}.", + "OfflineHeading": "Currently Offline", + "OfflineParagraph": "The media server is currently offline.", + "CheckPageForUpdates": "Check this page for continuous site updates." + }, + "NavigationBar": { + "Discover": "Discover", + "Search": "Search", + "Requests": "Requests", + "UserManagement": "User Management", + "Issues": "Issues", + "Vote": "Vote", + "Donate": "Donate!", + "DonateLibraryMaintainer": "Donate to Library Maintainer", + "DonateTooltip": "This is how I convince my wife to let me spend my spare time developing Ombi 😁", + "UpdateAvailableTooltip": "Update Available!", + "Settings": "Settings", + "Welcome": "Welcome {{username}}", + "UpdateDetails": "Update Details", + "Logout": "Logout", + "OpenMobileApp": "Open Mobile App", + "RecentlyAdded": "Recently Added", + "ChangeTheme": "Change Theme", + "Calendar": "Calendar", + "UserPreferences": "Preferences", + "FeatureSuggestion":"Feature Suggestion", + "FeatureSuggestionTooltip":"Have a great new idea? Suggest it here!", + "Filter": { + "Movies":"Movies", + "TvShows":"TV Shows", + "Music":"Music", + "People":"People" + }, + "MorningWelcome":"Good morning!", + "AfternoonWelcome":"Good afternoon!", + "EveningWelcome":"Good evening!" + }, + "Search": { + "Title": "Search", + "Paragraph": "Want to watch something that is not currently available? No problem, just search for it below and request it!", + "MoviesTab": "Movies", + "TvTab": "TV Shows", + "MusicTab": "Music", + "Suggestions": "Suggestions", + "NoResults": "Sorry, we didn't find any results!", + "DigitalDate": "Digital Release: {{date}}", + "TheatricalRelease": "Theatrical Release: {{date}}", + "ViewOnPlex": "View On Plex", + "ViewOnEmby": "View On Emby", + "RequestAdded": "Request for {{title}} has been added successfully", + "Similar": "Similar", + "Refine": "Refine", + "SearchBarPlaceholder": "Type Here to Search", + "Movies": { + "PopularMovies": "Popular Movies", + "UpcomingMovies": "Upcoming Movies", + "TopRatedMovies": "Top Rated Movies", + "NowPlayingMovies": "Now Playing Movies", + "HomePage": "Home Page", + "Trailer": "Trailer" + }, + "TvShows": { + "Popular": "Popular", + "Trending": "Trending", + "MostWatched": "Most Watched", + "MostAnticipated": "Most Anticipated", + "Results": "Results", + "AirDate": "Air Date:", + "AllSeasons": "All Seasons", + "FirstSeason": "First Season", + "LatestSeason": "Latest Season", + "Select": "Select ...", + "SubmitRequest": "Submit Request", + "Season": "Season: {{seasonNumber}}", + "SelectAllInSeason": "Select All in Season {{seasonNumber}}" + } + }, + "Requests": { + "Title": "Requests", + "Paragraph": "Below you can see yours and all other requests, as well as their download and approval status.", + "MoviesTab": "Movies", + "ArtistName": "Artist", + "AlbumName": "Album Name", + "TvTab": "TV Shows", + "MusicTab": "Music", + "RequestedBy": "Requested By", + "Status": "Status", + "RequestStatus": "Request status", + "Denied": " Denied:", + "TheatricalRelease": "Theatrical Release: {{date}}", + "ReleaseDate": "Released: {{date}}", + "TheatricalReleaseSort": "Theatrical Release", + "DigitalRelease": "Digital Release: {{date}}", + "RequestDate": "Request Date", + "QualityOverride": "Quality Override:", + "RootFolderOverride": "Root Folder Override:", + "ChangeRootFolder": "Root Folder", + "ChangeQualityProfile": "Quality Profile", + "MarkUnavailable": "Mark Unavailable", + "MarkAvailable": "Mark Available", + "Remove": "Remove", + "Deny": "Deny", + "DenyReason": "Deny Reason", + "Season": "Season:", + "GridTitle": "Title", + "AirDate": "AirDate", + "GridStatus": "Status", + "ReportIssue": "Report Issue", + "Filter": "Filter", + "Sort": "Sort", + "SeasonNumberHeading": "Season: {seasonNumber}", + "SortTitleAsc": "Title ▲", + "SortTitleDesc": "Title ▼", + "SortRequestDateAsc": "Request Date ▲", + "SortRequestDateDesc": "Request Date ▼", + "SortStatusAsc": "Status ▲", + "SortStatusDesc": "Status ▼", + "Remaining": { + "Quota": "{{remaining}}/{{total}} requests remaining", + "NextDays": "Another request will be added in {{time}} days", + "NextHours": "Another request will be added in {{time}} hours", + "NextMinutes": "Another request will be added in {{time}} minutes", + "NextMinute": "Another request will be added in {{time}} minute" + }, + "AllRequests": "All Requests", + "PendingRequests": "Pending Requests", + "ProcessingRequests": "Processing Requests", + "AvailableRequests": "Available Requests", + "DeniedRequests": "Denied Requests", + "RequestsToDisplay": "Requests to display", + "RequestsTitle": "Title", + "Details": "Details", + "Options": "Options", + "RequestPanel": { + "Delete":"Delete Request", + "Approve":"Approve Request", + "ChangeAvailability":"Mark Available" + } + }, + "Issues": { + "Title": "Issues", + "PendingTitle": "Pending Issues", + "InProgressTitle": "In Progress Issues", + "ResolvedTitle": "Resolved Issues", + "ColumnTitle": "Title", + "Category": "Category", + "Status": "Status", + "Details": "Details", + "Description": "Description", + "NoComments": "No Comments!", + "MarkInProgress": "Mark In Progress", + "MarkResolved": "Mark Resolved", + "SendMessageButton": "Send", + "Subject": "Subject", + "Comments": "Comments", + "WriteMessagePlaceholder": "Write your message here...", + "ReportedBy": "Reported By", + "IssueDialog": { + "Title": "Report an issue", + "DescriptionPlaceholder": "Please describe the issue", + "TitlePlaceholder": "Short title of your issue", + "SelectCategory": "Select Category", + "IssueCreated": "Issue has been created" + }, + "Outstanding": "There are outstanding issues", + "ResolvedDate": "Resolved date", + "CreatedDate": "Raised on", + "MarkedAsResolved": "This issue has now been marked as resolved!", + "MarkedAsInProgress": "This issue has now been marked as in progress!", + "Delete": "Delete issue", + "DeletedIssue": "Issue has been deleted" + }, + "Filter": { + "ClearFilter": "Clear Filter", + "FilterHeaderAvailability": "Availability", + "FilterHeaderRequestStatus": "Status", + "Approved": "Approved", + "PendingApproval": "Pending Approval" + }, + "UserManagment": { + "TvRemaining": "TV: {{remaining}}/{{total}} remaining", + "MovieRemaining": "Movies: {{remaining}}/{{total}} remaining", + "MusicRemaining": "Music: {{remaining}}/{{total}} remaining", + "TvDue": "TV: {{date}}", + "MovieDue": "Movie: {{date}}", + "MusicDue": "Music: {{date}}" + }, + "Votes": { + "CompletedVotesTab": "Voted", + "VotesTab": "Votes Needed" + }, + "MediaDetails": { + "Denied": "Denied", + "RecommendationsTitle": "Recommendations", + "SimilarTitle": "Similar", + "VideosTitle": "Videos", + "AlbumsTitle": "Albums", + "RequestAllAlbums": "Request All Albums", + "ClearSelection": "Clear Selection", + "RequestSelectedAlbums": "Request Selected Albums", + "ViewCollection":"View Collection", + "NotEnoughInfo": "Unfortunately there is not enough information about this show yet!", + "AdvancedOptions":"Advanced Options", + "QualityProfilesSelect":"Select A Quality Profile", + "RootFolderSelect":"Select A Root Folder", + "Status":"Status", + "Availability":"Availability", + "RequestStatus":"Request Status", + "Quality":"Quality", + "RootFolderOverride":"Root Folder Override", + "QualityOverride":"Quality Override", + "Genres":"Genres", + "TheatricalRelease":"Theatrical Release", + "DigitalRelease":"Digital Release", + "UserScore":"User Score", + "Votes":"Votes", + "Runtime":"Runtime", + "Minutes": "{{runtime}} Minutes", + "Revenue":"Revenue", + "Budget":"Budget", + "Keywords":"Keywords/Tags", + "Casts": { + "CastTitle": "Cast" + }, + "EpisodeSelector": { + "AllSeasonsTooltip": "This will request every season for this show", + "FirstSeasonTooltip": "This will only request the First Season for this show", + "LatestSeasonTooltip": "This will only request the Latest Season for this show" + } + }, + "Discovery": { + "PopularTab": "Popular", + "TrendingTab": "Trending", + "UpcomingTab": "Upcoming", + "Movies": "Movies", + "Combined": "Combined", + "Tv": "TV", + "CardDetails": { + "Availability": "Availability", + "Studio": "Studio", + "Network": "Network", + "UnknownNetwork": "Unknown", + "RequestStatus": "Request Status", + "Director": "Director", + "InCinemas": "In Cinemas", + "FirstAired": "First Aired", + "Writer": "Writer", + "ExecProducer": "Exec Producer" + } + }, + "UserPreferences": { + "Welcome": "Welcome {{username}}!", + "OmbiLanguage": "Language", + "DarkMode": "Dark Mode" } - }, - "UserPreferences": { - "Welcome":"Welcome {{username}}!", - "OmbiLanguage":"Ombi Language" - } -} +} \ No newline at end of file diff --git a/src/Ombi/wwwroot/translations/es.json b/src/Ombi/wwwroot/translations/es.json index 61087033d..f0684f01e 100644 --- a/src/Ombi/wwwroot/translations/es.json +++ b/src/Ombi/wwwroot/translations/es.json @@ -1,186 +1,301 @@ { - "Login": { - "SignInButton": "Iniciar sesión", - "UsernamePlaceholder": "Usuario", - "PasswordPlaceholder": "Contraseña", - "RememberMe": "Recuérdame", - "ForgottenPassword": "¿Has olvidado tu contraseña?", - "Errors": { - "IncorrectCredentials": "Nombre de usuario o contraseña\nincorrectos" - } - }, - "Common": { - "ContinueButton": "Continuar", - "Available": "Disponible", - "PartiallyAvailable": "Disponible parcialmente", - "Monitored": "Monitoreado", - "NotAvailable": "No disponible", - "ProcessingRequest": "Procesando solicitud", - "PendingApproval": "Pendiente de aprobación", - "RequestDenied": "Solicitud denegada", - "NotRequested": "No solicitado", - "Requested": "Solicitado", - "Request": "Solicitar", - "Denied": "Denegado", - "Approve": "Aprobar", - "PartlyAvailable": "Disponible parcialmente", - "Errors": { - "Validation": "Por favor, comprueba los datos introducidos" - } - }, - "PasswordReset": { - "EmailAddressPlaceholder": "Correo electrónico", - "ResetPasswordButton": "Restablecer contraseña" - }, - "LandingPage": { - "OnlineHeading": "En línea", - "OnlineParagraph": "El servidor de medios está en línea", - "PartiallyOnlineHeading": "Parcialmente en línea", - "PartiallyOnlineParagraph": "El servidor de medios está parcialmente en línea.", - "MultipleServersUnavailable": "Hay {{serversUnavailable}} de {{totalServers}} servidores fuera de línea.", - "SingleServerUnavailable": "Hay {{serversUnavailable}} de {{totalServers}} servidores fuera de línea.", - "OfflineHeading": "Fuera de línea", - "OfflineParagraph": "El servidor de medios está fuera de línea.", - "CheckPageForUpdates": "Consulta esta página para ver las últimas novedades." - }, - "NavigationBar": { - "Search": "Buscar", - "Requests": "Solicitudes", - "UserManagement": "Gestión de usuarios", - "Issues": "Problemas", - "Vote": "Votar", - "Donate": "¡Donar!", - "DonateLibraryMaintainer": "Donar al desarrollador de la biblioteca", - "DonateTooltip": "Así es como convenzo a mi esposa para que me deje pasar mi tiempo libre desarrollando Ombi ;)", - "UpdateAvailableTooltip": "¡Actualización disponible!", - "Settings": "Ajustes", - "Welcome": "Bienvenido {{username}}", - "UpdateDetails": "Editar cuenta usuario", - "Logout": "Cerrar sesión", - "OpenMobileApp": "Abrir aplicación móvil", - "RecentlyAdded": "Añadido recientemente" - }, - "Search": { - "Title": "Buscar", - "Paragraph": "¿Quieres ver algo que no está disponible? ¡No hay problema, búscalo y solicítalo!", - "MoviesTab": "Películas", - "TvTab": "Series", - "MusicTab": "Música", - "Suggestions": "Sugerencias", - "NoResults": "¡Lo sentimos, no encontramos ningún resultado!", - "DigitalDate": "Versión digital: {{date}}", - "TheatricalRelease": "En cines: {{date}}", - "ViewOnPlex": "Ver en Plex", - "ViewOnEmby": "Ver en Emby", - "RequestAdded": "La solicitud de {{title}} se ha añadido correctamente", - "Similar": "Similar", - "Refine": "Filtros", - "SearchBarPlaceholder": "Escribe aquí para buscar", - "Movies": { - "PopularMovies": "Películas populares", - "UpcomingMovies": "Próximas películas", - "TopRatedMovies": "Mejores películas", - "NowPlayingMovies": "Películas en cartelera", - "HomePage": "Inicio", - "Trailer": "Tráiler" + "Login": { + "SignInButton": "Iniciar sesión", + "UsernamePlaceholder": "Usuario", + "PasswordPlaceholder": "Contraseña", + "RememberMe": "Recuérdame", + "SignInWith": "Iniciar sesión con {{appName}}", + "SignInWithPlex": "Inicia sesión con Plex", + "ForgottenPassword": "¿Has olvidado tu contraseña?", + "Errors": { + "IncorrectCredentials": "Nombre de usuario o contraseña\nincorrectos" + } }, - "TvShows": { - "Popular": "Popular", - "Trending": "Tendencias", - "MostWatched": "Más visto", - "MostAnticipated": "Lo más esperado", - "Results": "Resultados", - "AirDate": "Fecha de emisión:", - "AllSeasons": "Todas las temporadas", - "FirstSeason": "Primera temporada", - "LatestSeason": "Última temporada", - "Select": "Selecciona...", - "SubmitRequest": "Enviar solicitud", - "Season": "Temporada: {{seasonNumber}}", - "SelectAllInSeason": "Seleccionar todo en temporada {{seasonNumber}}" - } - }, - "Requests": { - "Title": "Solicitudes", - "Paragraph": "A continuación puedes ver tanto las tuyas como las demás solicitudes, así como su estado de descarga y aprobación.", - "MoviesTab": "Películas", - "TvTab": "Series", - "MusicTab": "Música", - "RequestedBy": "Solicitado por:", - "Status": "Estado:", - "RequestStatus": "Estado de la solicitud:", - "Denied": " Denegado:", - "TheatricalRelease": "En cines: {{date}}", - "ReleaseDate": "Publicado: {{date}}", - "TheatricalReleaseSort": "En cines", - "DigitalRelease": "Versión digital: {{date}}", - "RequestDate": "Fecha de solicitud:", - "QualityOverride": "Sobreescribir calidad:", - "RootFolderOverride": "Sobreescribir carpeta raíz:", - "ChangeRootFolder": "Carpeta raíz", - "ChangeQualityProfile": "Perfil de calidad", - "MarkUnavailable": "Marcar como no disponible", - "MarkAvailable": "Marcar como disponible", - "Remove": "Eliminar", - "Deny": "Denegar", - "Season": "Temporada:", - "GridTitle": "Título", - "AirDate": "Fecha de estreno", - "GridStatus": "Estado", - "ReportIssue": "Reportar problema", - "Filter": "Filtrar", - "Sort": "Ordenar", - "SeasonNumberHeading": "Temporada: {seasonNumber}", - "SortTitleAsc": "Título ▲", - "SortTitleDesc": "Título ▼", - "SortRequestDateAsc": "Fecha de solicitud ▲", - "SortRequestDateDesc": "Fecha de solicitud ▼", - "SortStatusAsc": "Estado ▲", - "SortStatusDesc": "Estado ▼", - "Remaining": { - "Quota": "{{remaining}}/{{total}} solicitudes restantes", - "NextDays": "Se añadirá otra solicitud en {{time}} días", - "NextHours": "Se añadirá otra solicitud en {{time}} horas", - "NextMinutes": "Se añadirá otra solicitud en {{time}} minutos", - "NextMinute": "Se añadirá otra solicitud en {{time}} minuto" + "Common": { + "ContinueButton": "Continuar", + "Available": "Disponible", + "PartiallyAvailable": "Disponible parcialmente", + "Monitored": "Monitoreado", + "NotAvailable": "No disponible", + "ProcessingRequest": "Procesando solicitud", + "PendingApproval": "Pendiente de aprobación", + "RequestDenied": "Solicitud denegada", + "NotRequested": "No solicitado", + "Requested": "Solicitado", + "Request": "Solicitar", + "Denied": "Denegado", + "Approve": "Aprobar", + "PartlyAvailable": "Disponible parcialmente", + "ViewDetails": "Más Detalles", + "Errors": { + "Validation": "Por favor, comprueba los datos introducidos" + }, + "Cancel": "Cancelar", + "Submit": "Enviar" + }, + "PasswordReset": { + "EmailAddressPlaceholder": "Correo electrónico", + "ResetPasswordButton": "Restablecer contraseña" + }, + "LandingPage": { + "OnlineHeading": "En línea", + "OnlineParagraph": "El servidor de medios está en línea", + "PartiallyOnlineHeading": "Parcialmente en línea", + "PartiallyOnlineParagraph": "El servidor de medios está parcialmente en línea.", + "MultipleServersUnavailable": "Hay {{serversUnavailable}} de {{totalServers}} servidores fuera de línea.", + "SingleServerUnavailable": "Hay {{serversUnavailable}} de {{totalServers}} servidores fuera de línea.", + "OfflineHeading": "Fuera de línea", + "OfflineParagraph": "El servidor de medios está fuera de línea.", + "CheckPageForUpdates": "Consulta esta página para ver las últimas novedades." + }, + "NavigationBar": { + "Discover": "Descubre", + "Search": "Buscar", + "Requests": "Solicitudes", + "UserManagement": "Gestión de usuarios", + "Issues": "Problemas", + "Vote": "Votar", + "Donate": "¡Donar!", + "DonateLibraryMaintainer": "Donar al desarrollador de la biblioteca", + "DonateTooltip": "Así es como convenzo a mi esposa para que me deje pasar mi tiempo libre desarrollando Ombi ;)", + "UpdateAvailableTooltip": "¡Actualización disponible!", + "Settings": "Ajustes", + "Welcome": "Bienvenido {{username}}", + "UpdateDetails": "Editar cuenta usuario", + "Logout": "Cerrar sesión", + "OpenMobileApp": "Abrir aplicación móvil", + "RecentlyAdded": "Añadido recientemente", + "ChangeTheme": "Cambiar Tema", + "Calendar": "Calendario", + "UserPreferences": "Configuración", + "FeatureSuggestion": "Sugerencia de Características", + "FeatureSuggestionTooltip": "¿Tienes una idea nueva genial? ¡Sugiérala aquí!", + "Filter": { + "Movies": "Películas", + "TvShows": "Series", + "Music": "Música", + "People": "Personas" + }, + "MorningWelcome": "¡Buenos días!", + "AfternoonWelcome": "¡Buenas tardes!", + "EveningWelcome": "¡Buenas noches!" + }, + "Search": { + "Title": "Buscar", + "Paragraph": "¿Quieres ver algo que no está disponible? ¡No hay problema, búscalo y solicítalo!", + "MoviesTab": "Películas", + "TvTab": "Series", + "MusicTab": "Música", + "Suggestions": "Sugerencias", + "NoResults": "¡Lo sentimos, no encontramos ningún resultado!", + "DigitalDate": "Versión digital: {{date}}", + "TheatricalRelease": "En cines: {{date}}", + "ViewOnPlex": "Ver en Plex", + "ViewOnEmby": "Ver en Emby", + "RequestAdded": "La solicitud de {{title}} se ha añadido correctamente", + "Similar": "Similar", + "Refine": "Filtros", + "SearchBarPlaceholder": "Escribe aquí para buscar", + "Movies": { + "PopularMovies": "Películas populares", + "UpcomingMovies": "Próximas películas", + "TopRatedMovies": "Mejores películas", + "NowPlayingMovies": "Películas en cartelera", + "HomePage": "Inicio", + "Trailer": "Tráiler" + }, + "TvShows": { + "Popular": "Popular", + "Trending": "Tendencias", + "MostWatched": "Más visto", + "MostAnticipated": "Lo más esperado", + "Results": "Resultados", + "AirDate": "Fecha de emisión:", + "AllSeasons": "Todas las temporadas", + "FirstSeason": "Primera temporada", + "LatestSeason": "Última temporada", + "Select": "Selecciona...", + "SubmitRequest": "Enviar solicitud", + "Season": "Temporada: {{seasonNumber}}", + "SelectAllInSeason": "Seleccionar todo en temporada {{seasonNumber}}" + } + }, + "Requests": { + "Title": "Solicitudes", + "Paragraph": "A continuación puedes ver tanto las tuyas como las demás solicitudes, así como su estado de descarga y aprobación.", + "MoviesTab": "Películas", + "ArtistName": "Artista", + "AlbumName": "Nombre del Álbum", + "TvTab": "Series", + "MusicTab": "Música", + "RequestedBy": "Solicitado por", + "Status": "Estado", + "RequestStatus": "Estado de la solicitud", + "Denied": " Denegado:", + "TheatricalRelease": "En cines: {{date}}", + "ReleaseDate": "Publicado: {{date}}", + "TheatricalReleaseSort": "En cines", + "DigitalRelease": "Versión digital: {{date}}", + "RequestDate": "Fecha de solicitud", + "QualityOverride": "Sobreescribir calidad:", + "RootFolderOverride": "Sobreescribir carpeta raíz:", + "ChangeRootFolder": "Carpeta raíz", + "ChangeQualityProfile": "Perfil de calidad", + "MarkUnavailable": "Marcar como no disponible", + "MarkAvailable": "Marcar como disponible", + "Remove": "Eliminar", + "Deny": "Denegar", + "DenyReason": "Razón Denegada", + "Season": "Temporada:", + "GridTitle": "Título", + "AirDate": "Fecha de estreno", + "GridStatus": "Estado", + "ReportIssue": "Reportar problema", + "Filter": "Filtrar", + "Sort": "Ordenar", + "SeasonNumberHeading": "Temporada: {seasonNumber}", + "SortTitleAsc": "Título ▲", + "SortTitleDesc": "Título ▼", + "SortRequestDateAsc": "Fecha de solicitud ▲", + "SortRequestDateDesc": "Fecha de solicitud ▼", + "SortStatusAsc": "Estado ▲", + "SortStatusDesc": "Estado ▼", + "Remaining": { + "Quota": "{{remaining}}/{{total}} solicitudes restantes", + "NextDays": "Se añadirá otra solicitud en {{time}} días", + "NextHours": "Se añadirá otra solicitud en {{time}} horas", + "NextMinutes": "Se añadirá otra solicitud en {{time}} minutos", + "NextMinute": "Se añadirá otra solicitud en {{time}} minuto" + }, + "AllRequests": "Todas las Solicitudes", + "PendingRequests": "Solicitudes Pendientes", + "ProcessingRequests": "Procesándose Solicitudes", + "AvailableRequests": "Solicitudes Disponibles", + "DeniedRequests": "Solicitudes Denegadas", + "RequestsToDisplay": "Solicitudes a Mostrar", + "RequestsTitle": "Título", + "Details": "Detalles", + "Options": "Opciones", + "RequestPanel": { + "Delete": "Delete Request", + "Approve": "Approve Request", + "ChangeAvailability": "Mark Available" + } + }, + "Issues": { + "Title": "Problemas", + "PendingTitle": "Problemas pendientes", + "InProgressTitle": "Problemas en curso", + "ResolvedTitle": "Problemas resueltos", + "ColumnTitle": "Título", + "Category": "Categoría", + "Status": "Estado", + "Details": "Detalles", + "Description": "Descripción", + "NoComments": "¡Sin comentarios!", + "MarkInProgress": "Marcar en progreso", + "MarkResolved": "Marcar como resuelto", + "SendMessageButton": "Enviar", + "Subject": "Asunto", + "Comments": "Comentarios", + "WriteMessagePlaceholder": "Escribe tu mensaje aquí...", + "ReportedBy": "Reportado por", + "IssueDialog": { + "Title": "Reportar problema", + "DescriptionPlaceholder": "Por favor, describe el problema", + "TitlePlaceholder": "Título corto de tu problema", + "SelectCategory": "Seleccionar Categoría", + "IssueCreated": "El problema ha sido creado" + }, + "Outstanding": "Hay problemas pendientes", + "ResolvedDate": "Fecha de resolución", + "CreatedDate": "Creado", + "MarkedAsResolved": "¡Este problema ha sido marcado como resuelto!", + "MarkedAsInProgress": "¡Este problema se ha marcado como en progreso!", + "Delete": "Borrar problema", + "DeletedIssue": "El problema ha sido borrado" + }, + "Filter": { + "ClearFilter": "Reiniciar filtro", + "FilterHeaderAvailability": "Disponibilidad", + "FilterHeaderRequestStatus": "Estado", + "Approved": "Aprobado", + "PendingApproval": "Pendiente de aprobación" + }, + "UserManagment": { + "TvRemaining": "TV: {{remaining}}/{{total}} restantes", + "MovieRemaining": "Películas: {{remaining}}/{{total}} restantes", + "MusicRemaining": "Música: {{remaining}}/{{total}} restantes", + "TvDue": "TV: {{date}}", + "MovieDue": "Película: {{date}}", + "MusicDue": "Música: {{date}}" + }, + "Votes": { + "CompletedVotesTab": "Votado", + "VotesTab": "Votos necesarios" + }, + "MediaDetails": { + "Denied": "Denegado", + "RecommendationsTitle": "Recomendaciones", + "SimilarTitle": "Similar", + "VideosTitle": "Vídeos", + "AlbumsTitle": "Álbumes", + "RequestAllAlbums": "Solicitar Todos los Álbumes", + "ClearSelection": "Clear Selection", + "RequestSelectedAlbums": "Solicitar Álbumes Seleccionados", + "ViewCollection": "Ver Colección", + "NotEnoughInfo": "Desafortunadamente todavía no hay suficiente información sobre este programa!", + "AdvancedOptions": "Opciones Avanzadas", + "QualityProfilesSelect": "Seleccione un Perfil de Calidad", + "RootFolderSelect": "Seleccione una Carpeta Raíz", + "Status": "Estado", + "Availability": "Disponibilidad", + "RequestStatus": "Estado de solicitud", + "Quality": "Calidad", + "RootFolderOverride": "Sobreescribir carpeta raíz", + "QualityOverride": "Sobreescribir calidad", + "Genres": "Géneros", + "TheatricalRelease": "En cines", + "DigitalRelease": "Estreno Digital", + "UserScore": "Puntuación de Usuarios", + "Votes": "Votos", + "Runtime": "Duración", + "Minutes": "{{runtime}} Minutos", + "Revenue": "Ingresos", + "Budget": "Presupuesto", + "Keywords": "Palabras Clave/Etiquetas", + "Casts": { + "CastTitle": "Enviar pantalla" + }, + "EpisodeSelector": { + "AllSeasonsTooltip": "Esto solicitará cada temporada para este programa", + "FirstSeasonTooltip": "Esto solo solicitará la primera temporada para este programa", + "LatestSeasonTooltip": "Esto solo solicitará la última temporada para este programa" + } + }, + "Discovery": { + "PopularTab": "Popular", + "TrendingTab": "Tendencias", + "UpcomingTab": "Próximamente", + "Movies": "Películas", + "Combined": "Combinado", + "Tv": "TV", + "CardDetails": { + "Availability": "Disponibilidad", + "Studio": "Estudio", + "Network": "Red", + "UnknownNetwork": "Desconocido", + "RequestStatus": "Estado de solicitud", + "Director": "Director", + "InCinemas": "En Cines", + "FirstAired": "Emitido por primera vez", + "Writer": "Guionistas", + "ExecProducer": "Productor ejecutivo" + } + }, + "UserPreferences": { + "Welcome": "Bienvenido {{username}}!", + "OmbiLanguage": "Idioma", + "DarkMode": "Modo Oscuro" } - }, - "Issues": { - "Title": "Problemas", - "PendingTitle": "Problemas pendientes", - "InProgressTitle": "Problemas en curso", - "ResolvedTitle": "Problemas resueltos", - "ColumnTitle": "Título", - "Category": "Categoría", - "Status": "Estado", - "Details": "Detalles", - "Description": "Descripción", - "NoComments": "¡Sin comentarios!", - "MarkInProgress": "Marcar en progreso", - "MarkResolved": "Marcar como resuelto", - "SendMessageButton": "Enviar", - "Subject": "Asunto", - "Comments": "Comentarios", - "WriteMessagePlaceholder": "Escribe tu mensaje aquí...", - "ReportedBy": "Reportado por" - }, - "Filter": { - "ClearFilter": "Reiniciar filtro", - "FilterHeaderAvailability": "Disponibilidad", - "FilterHeaderRequestStatus": "Estado", - "Approved": "Aprobado", - "PendingApproval": "Pendiente de aprobación" - }, - "UserManagment": { - "TvRemaining": "TV: {{remaining}}/{{total}} restantes", - "MovieRemaining": "Películas: {{remaining}}/{{total}} restantes", - "MusicRemaining": "Música: {{remaining}}/{{total}} restantes", - "TvDue": "TV: {{date}}", - "MovieDue": "Película: {{date}}", - "MusicDue": "Música: {{date}}" - }, - "Votes": { - "CompletedVotesTab": "Votado", - "VotesTab": "Votos necesarios" - } -} +} \ No newline at end of file diff --git a/src/Ombi/wwwroot/translations/fr.json b/src/Ombi/wwwroot/translations/fr.json index e2530f95a..86ee34fbd 100644 --- a/src/Ombi/wwwroot/translations/fr.json +++ b/src/Ombi/wwwroot/translations/fr.json @@ -1,186 +1,301 @@ { - "Login": { - "SignInButton": "Se connecter", - "UsernamePlaceholder": "Nom d’utilisateur", - "PasswordPlaceholder": "Mot de passe", - "RememberMe": "Se souvenir de moi", - "ForgottenPassword": "Mot de passe oublié ?", - "Errors": { - "IncorrectCredentials": "Nom d'utilisateur ou mot de passe incorrect" - } - }, - "Common": { - "ContinueButton": "Continuer", - "Available": "Disponible", - "PartiallyAvailable": "Partiellement disponible", - "Monitored": "Suivi", - "NotAvailable": "Non disponible", - "ProcessingRequest": "En cours de traitement", - "PendingApproval": "En attente d'approbation", - "RequestDenied": "Demande refusée", - "NotRequested": "Non demandé", - "Requested": "Demandé", - "Request": "Demander", - "Denied": "Refusé", - "Approve": "Approuver", - "PartlyAvailable": "Partiellement disponible", - "Errors": { - "Validation": "Veuillez vérifier les valeurs entrées" - } - }, - "PasswordReset": { - "EmailAddressPlaceholder": "Courriel", - "ResetPasswordButton": "Réinitialiser le mot de passe" - }, - "LandingPage": { - "OnlineHeading": "Actuellement en ligne", - "OnlineParagraph": "Le serveur média est actuellement en ligne", - "PartiallyOnlineHeading": "Partiellement en ligne", - "PartiallyOnlineParagraph": "Le serveur média est partiellement en ligne.", - "MultipleServersUnavailable": "Il y a {{serversUnavailable}} serveurs hors-ligne sur {{totalServers}}.", - "SingleServerUnavailable": "Il y a {{serversUnavailable}} serveur hors-ligne sur {{totalServers}}.", - "OfflineHeading": "Actuellement hors-ligne", - "OfflineParagraph": "Le serveur média est actuellement hors-ligne.", - "CheckPageForUpdates": "Consultez cette page pour voir les mises à jour du site." - }, - "NavigationBar": { - "Search": "Rechercher", - "Requests": "En attente", - "UserManagement": "Gestion des utilisateurs", - "Issues": "Problèmes", - "Vote": "Vote", - "Donate": "Faire un don !", - "DonateLibraryMaintainer": "Faire un don au mainteneur de la bibliothèque", - "DonateTooltip": "C’est pour convaincre ma femme de me laisser passer mon temps libre à développer Ombi ;)", - "UpdateAvailableTooltip": "Mise à jour disponible !", - "Settings": "Paramètres", - "Welcome": "Bienvenue {{username}}", - "UpdateDetails": "Détails de la mise à jour", - "Logout": "Déconnexion", - "OpenMobileApp": "Ouvrir l'application mobile", - "RecentlyAdded": "Ajouts récents" - }, - "Search": { - "Title": "Rechercher", - "Paragraph": "Vous voulez regarder quelque chose qui n'est pas disponible actuellement ? Pas de problème, recherchez-le ci-dessous et demandez-le !", - "MoviesTab": "Films", - "TvTab": "Séries", - "MusicTab": "Musique", - "Suggestions": "Suggestions", - "NoResults": "Désolé, nous n'avons trouvé aucun résultat !", - "DigitalDate": "Sortie numérique: {{date}}", - "TheatricalRelease": "Sortie en salle: {{date}}", - "ViewOnPlex": "Regarder sur Plex", - "ViewOnEmby": "Regarder sur Emby", - "RequestAdded": "La demande pour {{title}} a été ajoutée avec succès", - "Similar": "Similaires", - "Refine": "Affiner", - "SearchBarPlaceholder": "Tapez ici pour rechercher", - "Movies": { - "PopularMovies": "Films populaires", - "UpcomingMovies": "Films à venir", - "TopRatedMovies": "Films les mieux notés", - "NowPlayingMovies": "Films à l'affiche", - "HomePage": "Accueil", - "Trailer": "Bande-annonce" + "Login": { + "SignInButton": "Se connecter", + "UsernamePlaceholder": "Nom d’utilisateur", + "PasswordPlaceholder": "Mot de passe", + "RememberMe": "Se souvenir de moi", + "SignInWith": "Se Connecter avec {{appName}}", + "SignInWithPlex": "Se Connecter avec Plex", + "ForgottenPassword": "Mot de passe oublié ?", + "Errors": { + "IncorrectCredentials": "Nom d'utilisateur ou mot de passe incorrect" + } }, - "TvShows": { - "Popular": "Populaire", - "Trending": "Tendances", - "MostWatched": "Les plus visionnées", - "MostAnticipated": "Les plus attendus", - "Results": "Résultats", - "AirDate": "Date de diffusion:", - "AllSeasons": "Toutes les saisons", - "FirstSeason": "Première saison", - "LatestSeason": "Dernière saison", - "Select": "Sélectionner...", - "SubmitRequest": "Envoyer la demande", - "Season": "Saison: {{seasonNumber}}", - "SelectAllInSeason": "Tout sélectionner dans la saison {{seasonNumber}}" - } - }, - "Requests": { - "Title": "Demandes", - "Paragraph": "Vous pouvez voir ci-dessous vos demandes et celles des autres, ainsi que leur statut de téléchargement et d'approbation.", - "MoviesTab": "Films", - "TvTab": "Séries", - "MusicTab": "Musique", - "RequestedBy": "Demandé par :", - "Status": "Statut :", - "RequestStatus": "Statut de la demande :", - "Denied": " Refusé :", - "TheatricalRelease": "Sortie en salle: {{date}}", - "ReleaseDate": "Sortie : {{date}}", - "TheatricalReleaseSort": "Sortie en salle", - "DigitalRelease": "Sortie numérique: {{date}}", - "RequestDate": "Date de la demande :", - "QualityOverride": "Remplacement de la qualité :", - "RootFolderOverride": "Remplacement du répertoire racine :", - "ChangeRootFolder": "Modifier le répertoire racine", - "ChangeQualityProfile": "Changer le profil de qualité", - "MarkUnavailable": "Marquer comme non disponible", - "MarkAvailable": "Marquer comme disponible", - "Remove": "Supprimer", - "Deny": "Refuser", - "Season": "Saison :", - "GridTitle": "Titre", - "AirDate": "Date de diffusion", - "GridStatus": "Statut", - "ReportIssue": "Signaler un problème", - "Filter": "Filtre", - "Sort": "Trier", - "SeasonNumberHeading": "Saison: {seasonNumber}", - "SortTitleAsc": "Titre ▲", - "SortTitleDesc": "Titre ▼", - "SortRequestDateAsc": "Date de la demande ▲", - "SortRequestDateDesc": "Date de la demande ▼", - "SortStatusAsc": "Statut ▲", - "SortStatusDesc": "Statut ▼", - "Remaining": { - "Quota": "{{remaining}}/{{total}} demande(s) restante(s)", - "NextDays": "Une autre demande sera ajoutée dans {{time}} jours", - "NextHours": "Une autre demande sera ajoutée dans {{time}} heures", - "NextMinutes": "Une autre demande sera ajoutée dans {{time}} minutes", - "NextMinute": "Une autre demande sera ajoutée dans {{time}} minute" + "Common": { + "ContinueButton": "Continuer", + "Available": "Disponible", + "PartiallyAvailable": "Partiellement disponible", + "Monitored": "Suivi", + "NotAvailable": "Non disponible", + "ProcessingRequest": "En cours de traitement", + "PendingApproval": "En attente d'approbation", + "RequestDenied": "Demande refusée", + "NotRequested": "Non demandé", + "Requested": "Demandé", + "Request": "Demander", + "Denied": "Refusé", + "Approve": "Approuver", + "PartlyAvailable": "Partiellement disponible", + "ViewDetails": "Voir les détails", + "Errors": { + "Validation": "Veuillez vérifier les valeurs entrées" + }, + "Cancel": "Annuler", + "Submit": "Envoyer" + }, + "PasswordReset": { + "EmailAddressPlaceholder": "Adresse Email", + "ResetPasswordButton": "Réinitialiser le mot de passe" + }, + "LandingPage": { + "OnlineHeading": "Actuellement en ligne", + "OnlineParagraph": "Le serveur média est actuellement en ligne", + "PartiallyOnlineHeading": "Partiellement en ligne", + "PartiallyOnlineParagraph": "Le serveur média est partiellement en ligne.", + "MultipleServersUnavailable": "Il y a {{serversUnavailable}} serveurs hors-ligne sur {{totalServers}}.", + "SingleServerUnavailable": "Il y a {{serversUnavailable}} serveur hors-ligne sur {{totalServers}}.", + "OfflineHeading": "Actuellement hors-ligne", + "OfflineParagraph": "Le serveur média est actuellement hors-ligne.", + "CheckPageForUpdates": "Consultez cette page pour voir les mises à jour du site." + }, + "NavigationBar": { + "Discover": "Découvrir", + "Search": "Rechercher", + "Requests": "En attente", + "UserManagement": "Gestion des utilisateurs", + "Issues": "Problèmes", + "Vote": "Vote", + "Donate": "Faire un don !", + "DonateLibraryMaintainer": "Faire un don au mainteneur de la bibliothèque", + "DonateTooltip": "C’est pour convaincre ma femme de me laisser passer mon temps libre à développer Ombi ;)", + "UpdateAvailableTooltip": "Mise à jour disponible !", + "Settings": "Paramètres", + "Welcome": "Bienvenue {{username}}", + "UpdateDetails": "Détails de la mise à jour", + "Logout": "Déconnexion", + "OpenMobileApp": "Ouvrir l'application mobile", + "RecentlyAdded": "Ajouts récents", + "ChangeTheme": "Changer de thème", + "Calendar": "Calendrier", + "UserPreferences": "Paramètres", + "FeatureSuggestion": "Suggérer une fonctionnalité", + "FeatureSuggestionTooltip": "Vous avez une bonne idée ? Suggérez-la ici !", + "Filter": { + "Movies": "Films", + "TvShows": "Séries", + "Music": "Musique", + "People": "Casting" + }, + "MorningWelcome": "Bonjour !", + "AfternoonWelcome": "Bon après-midi !", + "EveningWelcome": "Bonsoir !" + }, + "Search": { + "Title": "Rechercher", + "Paragraph": "Vous voulez regarder quelque chose qui n'est pas disponible actuellement ? Pas de problème, recherchez-le ci-dessous et demandez-le !", + "MoviesTab": "Films", + "TvTab": "Séries", + "MusicTab": "Musique", + "Suggestions": "Suggestions", + "NoResults": "Désolé, nous n'avons trouvé aucun résultat !", + "DigitalDate": "Sortie numérique: {{date}}", + "TheatricalRelease": "Sortie en salle: {{date}}", + "ViewOnPlex": "Regarder sur Plex", + "ViewOnEmby": "Regarder sur Emby", + "RequestAdded": "La demande pour {{title}} a été ajoutée avec succès", + "Similar": "Similaires", + "Refine": "Affiner", + "SearchBarPlaceholder": "Tapez ici pour rechercher", + "Movies": { + "PopularMovies": "Films populaires", + "UpcomingMovies": "Films à venir", + "TopRatedMovies": "Films les mieux notés", + "NowPlayingMovies": "Films à l'affiche", + "HomePage": "Accueil", + "Trailer": "Bande-annonce" + }, + "TvShows": { + "Popular": "Populaire", + "Trending": "Tendances", + "MostWatched": "Les plus visionnées", + "MostAnticipated": "Les plus attendus", + "Results": "Résultats", + "AirDate": "Date de diffusion:", + "AllSeasons": "Toutes les saisons", + "FirstSeason": "Première saison", + "LatestSeason": "Dernière saison", + "Select": "Sélectionner...", + "SubmitRequest": "Envoyer la demande", + "Season": "Saison: {{seasonNumber}}", + "SelectAllInSeason": "Tout sélectionner dans la saison {{seasonNumber}}" + } + }, + "Requests": { + "Title": "Demandes", + "Paragraph": "Vous pouvez voir ci-dessous vos demandes et celles des autres, ainsi que leur statut de téléchargement et d'approbation.", + "MoviesTab": "Films", + "ArtistName": "Artiste", + "AlbumName": "Nom de l’Album", + "TvTab": "Séries", + "MusicTab": "Musique", + "RequestedBy": "Demandé par", + "Status": "Statut", + "RequestStatus": "Statut de la demande", + "Denied": " Refusé :", + "TheatricalRelease": "Sortie en salle: {{date}}", + "ReleaseDate": "Sortie : {{date}}", + "TheatricalReleaseSort": "Sortie en salle", + "DigitalRelease": "Sortie numérique: {{date}}", + "RequestDate": "Date de la demande", + "QualityOverride": "Remplacement de la qualité :", + "RootFolderOverride": "Remplacement du répertoire racine :", + "ChangeRootFolder": "Modifier le répertoire racine", + "ChangeQualityProfile": "Changer le profil de qualité", + "MarkUnavailable": "Marquer comme non disponible", + "MarkAvailable": "Marquer comme disponible", + "Remove": "Supprimer", + "Deny": "Refuser", + "DenyReason": "Raison de refus", + "Season": "Saison :", + "GridTitle": "Titre", + "AirDate": "Date de diffusion", + "GridStatus": "Statut", + "ReportIssue": "Signaler un problème", + "Filter": "Filtre", + "Sort": "Trier", + "SeasonNumberHeading": "Saison: {seasonNumber}", + "SortTitleAsc": "Titre ▲", + "SortTitleDesc": "Titre ▼", + "SortRequestDateAsc": "Date de la demande ▲", + "SortRequestDateDesc": "Date de la demande ▼", + "SortStatusAsc": "Statut ▲", + "SortStatusDesc": "Statut ▼", + "Remaining": { + "Quota": "{{remaining}}/{{total}} demande(s) restante(s)", + "NextDays": "Une autre demande sera ajoutée dans {{time}} jours", + "NextHours": "Une autre demande sera ajoutée dans {{time}} heures", + "NextMinutes": "Une autre demande sera ajoutée dans {{time}} minutes", + "NextMinute": "Une autre demande sera ajoutée dans {{time}} minute" + }, + "AllRequests": "Toutes les requêtes", + "PendingRequests": "Requêtes en attente", + "ProcessingRequests": "Requêtes en cours", + "AvailableRequests": "Requêtes disponibles", + "DeniedRequests": "Requêtes refusées", + "RequestsToDisplay": "Requêtes à afficher", + "RequestsTitle": "Titre", + "Details": "Détails", + "Options": "Options", + "RequestPanel": { + "Delete": "Supprimer la demande", + "Approve": "Autoriser la demande", + "ChangeAvailability": "Marquer comme Disponible" + } + }, + "Issues": { + "Title": "Problèmes", + "PendingTitle": "Problèmes en attente", + "InProgressTitle": "Problèmes en cours", + "ResolvedTitle": "Problèmes résolus", + "ColumnTitle": "Titre", + "Category": "Catégorie", + "Status": "Statut", + "Details": "Détails", + "Description": "Description", + "NoComments": "Aucun commentaire !", + "MarkInProgress": "Marquer en cours de traitement", + "MarkResolved": "Marquer comme résolu", + "SendMessageButton": "Envoyer", + "Subject": "Sujet", + "Comments": "Commentaires", + "WriteMessagePlaceholder": "Écrivez votre message ici...", + "ReportedBy": "Signalé par", + "IssueDialog": { + "Title": "Signaler un problème", + "DescriptionPlaceholder": "Veuillez décrire le problème rencontré", + "TitlePlaceholder": "Titre court de votre problème", + "SelectCategory": "Sélectionner une catégorie", + "IssueCreated": "Votre rapport d'erreur a été créée" + }, + "Outstanding": "Des rapports d'erreurs sont en attente", + "ResolvedDate": "Date de résolution", + "CreatedDate": "Signalé le", + "MarkedAsResolved": "Ce problème a maintenant été marqué comme résolu !", + "MarkedAsInProgress": "Ce problème a maintenant été marqué comme en cours de traitement !", + "Delete": "Supprimer rapport d'erreur", + "DeletedIssue": "Votre rapport d'erreur a été supprimé" + }, + "Filter": { + "ClearFilter": "Effacer les filtres", + "FilterHeaderAvailability": "Disponibilité", + "FilterHeaderRequestStatus": "Statut", + "Approved": "Validée", + "PendingApproval": "En attente de validation" + }, + "UserManagment": { + "TvRemaining": "TV : {{remaining}}/{{total}} restant(s)", + "MovieRemaining": "Films : {{remaining}}/{{total}} restant(s)", + "MusicRemaining": "Musique : {{remaining}}/{{total}} restant(s)", + "TvDue": "TV : {{date}}", + "MovieDue": "Film : {{date}}", + "MusicDue": "Musique : {{date}}" + }, + "Votes": { + "CompletedVotesTab": "Voté", + "VotesTab": "Votes nécessaires" + }, + "MediaDetails": { + "Denied": "Refusé", + "RecommendationsTitle": "Suggestions", + "SimilarTitle": "Similaires", + "VideosTitle": "Vidéos", + "AlbumsTitle": "Albums", + "RequestAllAlbums": "Demander tous les Albums", + "ClearSelection": "Désélectionner", + "RequestSelectedAlbums": "Demander les Albums sélectionnés", + "ViewCollection": "Afficher la Collection", + "NotEnoughInfo": "Malheureusement, il n'y a pas encore assez d'informations à propos de ce média !", + "AdvancedOptions": "Options Avancées", + "QualityProfilesSelect": "Sélectionner un Profil de Qualité", + "RootFolderSelect": "Sélectionner un Dossier Racine", + "Status": "Statut", + "Availability": "Disponibilité", + "RequestStatus": "Statut de la Demande", + "Quality": "Qualité", + "RootFolderOverride": "Remplacer le Dossier Racine", + "QualityOverride": "Remplacer la Qualité", + "Genres": "Genres", + "TheatricalRelease": "Sortie en salle", + "DigitalRelease": "Sorti en Numérique", + "UserScore": "Note des Spectateurs", + "Votes": "Votes", + "Runtime": "Durée de visionnage", + "Minutes": "{{runtime}} Minutes", + "Revenue": "Recettes", + "Budget": "Coût de Production", + "Keywords": "Mots Clés / Tags", + "Casts": { + "CastTitle": "Casting" + }, + "EpisodeSelector": { + "AllSeasonsTooltip": "Cette action demandera toutes les saisons de cette série", + "FirstSeasonTooltip": "Cette action ne demandera que la Première Saison de cette série", + "LatestSeasonTooltip": "Cette action ne demandera que la Dernière Saison de cette série" + } + }, + "Discovery": { + "PopularTab": "Populaire", + "TrendingTab": "Tendances", + "UpcomingTab": "Prochainement", + "Movies": "Films", + "Combined": "Tous", + "Tv": "TV", + "CardDetails": { + "Availability": "Disponibilité", + "Studio": "Studio", + "Network": "Diffuseur", + "UnknownNetwork": "Inconnu", + "RequestStatus": "Statut de la Demande", + "Director": "Réalisateur", + "InCinemas": "En Salles", + "FirstAired": "Première Diffusion", + "Writer": "Scénariste", + "ExecProducer": "Producteur Exécutif" + } + }, + "UserPreferences": { + "Welcome": "Bienvenue {{username}}!", + "OmbiLanguage": "Langue", + "DarkMode": "Mode Sombre" } - }, - "Issues": { - "Title": "Problèmes", - "PendingTitle": "Problèmes en attente", - "InProgressTitle": "Problèmes en cours", - "ResolvedTitle": "Problèmes résolus", - "ColumnTitle": "Titre", - "Category": "Catégorie", - "Status": "Statut", - "Details": "Détails", - "Description": "Description", - "NoComments": "Aucun commentaire !", - "MarkInProgress": "Marquer en cours de traitement", - "MarkResolved": "Marquer comme résolu", - "SendMessageButton": "Envoyer", - "Subject": "Sujet", - "Comments": "Commentaires", - "WriteMessagePlaceholder": "Écrivez votre message ici...", - "ReportedBy": "Signalé par" - }, - "Filter": { - "ClearFilter": "Effacer les filtres", - "FilterHeaderAvailability": "Disponibilité", - "FilterHeaderRequestStatus": "Statut", - "Approved": "Validée", - "PendingApproval": "En attente de validation" - }, - "UserManagment": { - "TvRemaining": "TV : {{remaining}}/{{total}} restant(s)", - "MovieRemaining": "Films : {{remaining}}/{{total}} restant(s)", - "MusicRemaining": "Musique : {{remaining}}/{{total}} restant(s)", - "TvDue": "TV : {{date}}", - "MovieDue": "Film : {{date}}", - "MusicDue": "Musique : {{date}}" - }, - "Votes": { - "CompletedVotesTab": "Voté", - "VotesTab": "Votes nécessaires" - } -} +} \ No newline at end of file diff --git a/src/Ombi/wwwroot/translations/hu.json b/src/Ombi/wwwroot/translations/hu.json index 1414f0ea0..8c1c3f3e5 100644 --- a/src/Ombi/wwwroot/translations/hu.json +++ b/src/Ombi/wwwroot/translations/hu.json @@ -1,186 +1,301 @@ { - "Login": { - "SignInButton": "Bejelentkezés", - "UsernamePlaceholder": "Felhasználónév", - "PasswordPlaceholder": "Jelszó", - "RememberMe": "Emlékezz rám", - "ForgottenPassword": "Elfelejtetted a jelszavad?", - "Errors": { - "IncorrectCredentials": "Helytelen felhasználónév vagy jelszó" - } - }, - "Common": { - "ContinueButton": "Tovább", - "Available": "Elérhető", - "PartiallyAvailable": "Részlegesen elérhető", - "Monitored": "Figyelve", - "NotAvailable": "Nem elérhető", - "ProcessingRequest": "Kérés feldolgozása", - "PendingApproval": "Jóváhagyásra vár", - "RequestDenied": "Kérés megtagadva", - "NotRequested": "Nincs kérve", - "Requested": "Kérve", - "Request": "Kérés", - "Denied": "Megtagadva", - "Approve": "Jóváhagyva", - "PartlyAvailable": "Részlegesen elérhető", - "Errors": { - "Validation": "Kérjük, ellenőrizze a beírt értékeket" - } - }, - "PasswordReset": { - "EmailAddressPlaceholder": "E-mail cím", - "ResetPasswordButton": "Jelszó visszaállítása" - }, - "LandingPage": { - "OnlineHeading": "Jelenleg elérhető", - "OnlineParagraph": "A médiaszerver jelenleg elérhető", - "PartiallyOnlineHeading": "Részben elérhető", - "PartiallyOnlineParagraph": "A médiaszerver részben elérhető.", - "MultipleServersUnavailable": "{{serversUnavailable}} szerver nem érhető el ennyiből: {{totalServers}}.", - "SingleServerUnavailable": "{{serversUnavailable}} szerver nem érhető el ennyiből: {{totalServers}}.", - "OfflineHeading": "Jelenleg nem elérhető", - "OfflineParagraph": "A médiaszerver jelenleg nem elérhető.", - "CheckPageForUpdates": "Látogasd meg ezt az oldalt a frissítésekhez." - }, - "NavigationBar": { - "Search": "Keresés", - "Requests": "Kérések", - "UserManagement": "Felhasználók kezelése", - "Issues": "Problémák", - "Vote": "Szavazás", - "Donate": "Adakozás!", - "DonateLibraryMaintainer": "Adakozz a könyvtár fenntartónak", - "DonateTooltip": "Ezzel győzöm meg a feleségem, hogy a szabadidőmben fejleszthessem az Ombi-t ;)", - "UpdateAvailableTooltip": "Frissítés elérhető!", - "Settings": "Beállítások", - "Welcome": "Üdv {{username}}", - "UpdateDetails": "Fiók beállításai", - "Logout": "Kilépés", - "OpenMobileApp": "Mobil app megnyitása", - "RecentlyAdded": "Nemrég hozzáadott" - }, - "Search": { - "Title": "Keresés", - "Paragraph": "Szeretnél nézni valamit ami jelenleg nem elérhető? Semmi gond, csak keress rá lentebb és kérd!", - "MoviesTab": "Filmek", - "TvTab": "Sorozatok", - "MusicTab": "Zene", - "Suggestions": "Javaslatok", - "NoResults": "Sajnáljuk, nem találtunk semmit!", - "DigitalDate": "Digitális kiadás: {{date}}", - "TheatricalRelease": "Mozis kiadás: {{date}}", - "ViewOnPlex": "Megnézés Plexen", - "ViewOnEmby": "Megnézés Emby-n", - "RequestAdded": "Kérés sikeresen leadva erre: {{title}}", - "Similar": "Hasonló", - "Refine": "Finomítás", - "SearchBarPlaceholder": "Type Here to Search", - "Movies": { - "PopularMovies": "Népszerű filmek", - "UpcomingMovies": "Közelgő filmek", - "TopRatedMovies": "Legjobbra értékelt filmek", - "NowPlayingMovies": "Most játszott filmek", - "HomePage": "Főoldal", - "Trailer": "Előzetes" + "Login": { + "SignInButton": "Bejelentkezés", + "UsernamePlaceholder": "Felhasználónév", + "PasswordPlaceholder": "Jelszó", + "RememberMe": "Emlékezz rám", + "SignInWith": "Sign in with {{appName}}", + "SignInWithPlex": "Sign in with Plex", + "ForgottenPassword": "Elfelejtetted a jelszavad?", + "Errors": { + "IncorrectCredentials": "Helytelen felhasználónév vagy jelszó" + } }, - "TvShows": { - "Popular": "Népszerű", - "Trending": "Felkapott", - "MostWatched": "Legnézettebb", - "MostAnticipated": "Leginkább várt", - "Results": "Eredmények", - "AirDate": "Bemutató:", - "AllSeasons": "Összes Évad", - "FirstSeason": "Első évad", - "LatestSeason": "Utolsó évad", - "Select": "Kiválasztás...", - "SubmitRequest": "Kérés küldése", - "Season": "Évad: {{seasonNumber}}", - "SelectAllInSeason": "Egész {{seasonNumber}}. évad kiválasztása" - } - }, - "Requests": { - "Title": "Kérések", - "Paragraph": "Lentebb láthatod a saját és egyéb kéréseket, valamint a letöltési és jóváhagyási állapotukat.", - "MoviesTab": "Filmek", - "TvTab": "Sorozatok", - "MusicTab": "Zene", - "RequestedBy": "Kérte:", - "Status": "Állapot:", - "RequestStatus": "Kérés állapota:", - "Denied": " Megtagadta:", - "TheatricalRelease": "Mozis kiadás: {{date}}", - "ReleaseDate": "Kiadva: {{date}}", - "TheatricalReleaseSort": "Mozis kiadás", - "DigitalRelease": "Digitális kiadás: {{date}}", - "RequestDate": "Kérés ideje:", - "QualityOverride": "Minőség felülírása:", - "RootFolderOverride": "Gyökér mappa felülírása:", - "ChangeRootFolder": "Gyökér mappa", - "ChangeQualityProfile": "Minőség profil", - "MarkUnavailable": "Megjelölés nem elérhetőnek", - "MarkAvailable": "Megjelölés elérhetőnek", - "Remove": "Törlés", - "Deny": "Elutasítás", - "Season": "Évad:", - "GridTitle": "Cím", - "AirDate": "Bemutató", - "GridStatus": "Állapot", - "ReportIssue": "Probléma jelentése", - "Filter": "Szűrő", - "Sort": "Rendezés", - "SeasonNumberHeading": "Évad: {seasonNumber}", - "SortTitleAsc": "Cím ▲", - "SortTitleDesc": "Cím ▼", - "SortRequestDateAsc": "Kérés ideje ▲", - "SortRequestDateDesc": "Kérés ideje ▼", - "SortStatusAsc": "Állapot ▲", - "SortStatusDesc": "Állapot ▼", - "Remaining": { - "Quota": "{{remaining}}/{{total}} kérés van még", - "NextDays": "Újabb kérés lesz hozzáadva {{time}} nap múlva", - "NextHours": "Újabb kérés lesz hozzáadva {{time}} óra múlva", - "NextMinutes": "Újabb kérés lesz hozzáadva {{time}} perc múlva", - "NextMinute": "Újabb kérés lesz hozzáadva {{time}} perc múlva" + "Common": { + "ContinueButton": "Tovább", + "Available": "Elérhető", + "PartiallyAvailable": "Részlegesen elérhető", + "Monitored": "Figyelve", + "NotAvailable": "Nem elérhető", + "ProcessingRequest": "Kérés feldolgozása", + "PendingApproval": "Jóváhagyásra vár", + "RequestDenied": "Kérés megtagadva", + "NotRequested": "Nincs kérve", + "Requested": "Kérve", + "Request": "Kérés", + "Denied": "Megtagadva", + "Approve": "Jóváhagyva", + "PartlyAvailable": "Részlegesen elérhető", + "ViewDetails": "View Details", + "Errors": { + "Validation": "Kérjük, ellenőrizze a beírt értékeket" + }, + "Cancel": "Cancel", + "Submit": "Submit" + }, + "PasswordReset": { + "EmailAddressPlaceholder": "E-mail cím", + "ResetPasswordButton": "Jelszó visszaállítása" + }, + "LandingPage": { + "OnlineHeading": "Jelenleg elérhető", + "OnlineParagraph": "A médiaszerver jelenleg elérhető", + "PartiallyOnlineHeading": "Részben elérhető", + "PartiallyOnlineParagraph": "A médiaszerver részben elérhető.", + "MultipleServersUnavailable": "{{serversUnavailable}} szerver nem érhető el ennyiből: {{totalServers}}.", + "SingleServerUnavailable": "{{serversUnavailable}} szerver nem érhető el ennyiből: {{totalServers}}.", + "OfflineHeading": "Jelenleg nem elérhető", + "OfflineParagraph": "A médiaszerver jelenleg nem elérhető.", + "CheckPageForUpdates": "Látogasd meg ezt az oldalt a frissítésekhez." + }, + "NavigationBar": { + "Discover": "Discover", + "Search": "Keresés", + "Requests": "Kérések", + "UserManagement": "Felhasználók kezelése", + "Issues": "Problémák", + "Vote": "Szavazás", + "Donate": "Adakozás!", + "DonateLibraryMaintainer": "Adakozz a könyvtár fenntartónak", + "DonateTooltip": "Ezzel győzöm meg a feleségem, hogy a szabadidőmben fejleszthessem az Ombi-t ;)", + "UpdateAvailableTooltip": "Frissítés elérhető!", + "Settings": "Beállítások", + "Welcome": "Üdv {{username}}", + "UpdateDetails": "Fiók beállításai", + "Logout": "Kilépés", + "OpenMobileApp": "Mobil app megnyitása", + "RecentlyAdded": "Nemrég hozzáadott", + "ChangeTheme": "Change Theme", + "Calendar": "Calendar", + "UserPreferences": "Preferences", + "FeatureSuggestion": "Feature Suggestion", + "FeatureSuggestionTooltip": "Have a great new idea? Suggest it here!", + "Filter": { + "Movies": "Filmek", + "TvShows": "Sorozatok", + "Music": "Zene", + "People": "People" + }, + "MorningWelcome": "Good morning!", + "AfternoonWelcome": "Good afternoon!", + "EveningWelcome": "Good evening!" + }, + "Search": { + "Title": "Keresés", + "Paragraph": "Szeretnél nézni valamit ami jelenleg nem elérhető? Semmi gond, csak keress rá lentebb és kérd!", + "MoviesTab": "Filmek", + "TvTab": "Sorozatok", + "MusicTab": "Zene", + "Suggestions": "Javaslatok", + "NoResults": "Sajnáljuk, nem találtunk semmit!", + "DigitalDate": "Digitális kiadás: {{date}}", + "TheatricalRelease": "Mozis kiadás: {{date}}", + "ViewOnPlex": "Megnézés Plexen", + "ViewOnEmby": "Megnézés Emby-n", + "RequestAdded": "Kérés sikeresen leadva erre: {{title}}", + "Similar": "Hasonló", + "Refine": "Finomítás", + "SearchBarPlaceholder": "A kereséshez írj be valamit", + "Movies": { + "PopularMovies": "Népszerű filmek", + "UpcomingMovies": "Közelgő filmek", + "TopRatedMovies": "Legjobbra értékelt filmek", + "NowPlayingMovies": "Most játszott filmek", + "HomePage": "Főoldal", + "Trailer": "Előzetes" + }, + "TvShows": { + "Popular": "Népszerű", + "Trending": "Felkapott", + "MostWatched": "Legnézettebb", + "MostAnticipated": "Leginkább várt", + "Results": "Eredmények", + "AirDate": "Bemutató:", + "AllSeasons": "Összes Évad", + "FirstSeason": "Első évad", + "LatestSeason": "Utolsó évad", + "Select": "Kiválasztás...", + "SubmitRequest": "Kérés küldése", + "Season": "Évad: {{seasonNumber}}", + "SelectAllInSeason": "Egész {{seasonNumber}}. évad kiválasztása" + } + }, + "Requests": { + "Title": "Kérések", + "Paragraph": "Lentebb láthatod a saját és egyéb kéréseket, valamint a letöltési és jóváhagyási állapotukat.", + "MoviesTab": "Filmek", + "ArtistName": "Artist", + "AlbumName": "Album Name", + "TvTab": "Sorozatok", + "MusicTab": "Zene", + "RequestedBy": "Kérte", + "Status": "Állapot", + "RequestStatus": "Kérés állapota", + "Denied": " Megtagadta:", + "TheatricalRelease": "Mozis kiadás: {{date}}", + "ReleaseDate": "Kiadva: {{date}}", + "TheatricalReleaseSort": "Mozis kiadás", + "DigitalRelease": "Digitális kiadás: {{date}}", + "RequestDate": "Kérés ideje", + "QualityOverride": "Minőség felülírása:", + "RootFolderOverride": "Gyökér mappa felülírása:", + "ChangeRootFolder": "Gyökér mappa", + "ChangeQualityProfile": "Minőség profil", + "MarkUnavailable": "Megjelölés nem elérhetőnek", + "MarkAvailable": "Megjelölés elérhetőnek", + "Remove": "Törlés", + "Deny": "Elutasítás", + "DenyReason": "Deny Reason", + "Season": "Évad:", + "GridTitle": "Cím", + "AirDate": "Bemutató", + "GridStatus": "Állapot", + "ReportIssue": "Probléma jelentése", + "Filter": "Szűrő", + "Sort": "Rendezés", + "SeasonNumberHeading": "Évad: {seasonNumber}", + "SortTitleAsc": "Cím ▲", + "SortTitleDesc": "Cím ▼", + "SortRequestDateAsc": "Kérés ideje ▲", + "SortRequestDateDesc": "Kérés ideje ▼", + "SortStatusAsc": "Állapot ▲", + "SortStatusDesc": "Állapot ▼", + "Remaining": { + "Quota": "{{remaining}}/{{total}} kérés van még", + "NextDays": "Újabb kérés lesz hozzáadva {{time}} nap múlva", + "NextHours": "Újabb kérés lesz hozzáadva {{time}} óra múlva", + "NextMinutes": "Újabb kérés lesz hozzáadva {{time}} perc múlva", + "NextMinute": "Újabb kérés lesz hozzáadva {{time}} perc múlva" + }, + "AllRequests": "All Requests", + "PendingRequests": "Pending Requests", + "ProcessingRequests": "Processing Requests", + "AvailableRequests": "Available Requests", + "DeniedRequests": "Denied Requests", + "RequestsToDisplay": "Requests to display", + "RequestsTitle": "Cím", + "Details": "Részletek", + "Options": "Options", + "RequestPanel": { + "Delete": "Delete Request", + "Approve": "Approve Request", + "ChangeAvailability": "Mark Available" + } + }, + "Issues": { + "Title": "Problémák", + "PendingTitle": "Várakozó problémák", + "InProgressTitle": "Folyamatban lévő problémák", + "ResolvedTitle": "Megoldott problémák", + "ColumnTitle": "Cím", + "Category": "Kategória", + "Status": "Állapot", + "Details": "Részletek", + "Description": "Leírás", + "NoComments": "Nincs megjegyzés!", + "MarkInProgress": "Folyamatban lévőre jelölés", + "MarkResolved": "Megjelölés megoldottként", + "SendMessageButton": "Küldés", + "Subject": "Tárgy", + "Comments": "Hozzászólások", + "WriteMessagePlaceholder": "Írd ide az üzeneted...", + "ReportedBy": "Jelentette", + "IssueDialog": { + "Title": "Report an issue", + "DescriptionPlaceholder": "Please describe the issue", + "TitlePlaceholder": "Short title of your issue", + "SelectCategory": "Select Category", + "IssueCreated": "Issue has been created" + }, + "Outstanding": "There are outstanding issues", + "ResolvedDate": "Resolved date", + "CreatedDate": "Raised on", + "MarkedAsResolved": "This issue has now been marked as resolved!", + "MarkedAsInProgress": "This issue has now been marked as in progress!", + "Delete": "Delete issue", + "DeletedIssue": "Issue has been deleted" + }, + "Filter": { + "ClearFilter": "Szűrő törlése", + "FilterHeaderAvailability": "Elérhetőség", + "FilterHeaderRequestStatus": "Állapot", + "Approved": "Jóváhagyva", + "PendingApproval": "Jóváhagyásra vár" + }, + "UserManagment": { + "TvRemaining": "TV: {{remaining}}/{{total}} maradt", + "MovieRemaining": "Filmek: {{remaining}}/{{total}} maradt", + "MusicRemaining": "Zene: {{remaining}}/{{total}} maradt", + "TvDue": "TV: {{date}}", + "MovieDue": "Film: {{date}}", + "MusicDue": "Zene: {{date}}" + }, + "Votes": { + "CompletedVotesTab": "Szavazott", + "VotesTab": "Szavazat szükséges" + }, + "MediaDetails": { + "Denied": "Megtagadva", + "RecommendationsTitle": "Recommendations", + "SimilarTitle": "Hasonló", + "VideosTitle": "Videos", + "AlbumsTitle": "Albums", + "RequestAllAlbums": "Request All Albums", + "ClearSelection": "Clear Selection", + "RequestSelectedAlbums": "Request Selected Albums", + "ViewCollection": "View Collection", + "NotEnoughInfo": "Unfortunately there is not enough information about this show yet!", + "AdvancedOptions": "Advanced Options", + "QualityProfilesSelect": "Select A Quality Profile", + "RootFolderSelect": "Select A Root Folder", + "Status": "Állapot", + "Availability": "Elérhetőség", + "RequestStatus": "Request Status", + "Quality": "Quality", + "RootFolderOverride": "Gyökér mappa felülírása", + "QualityOverride": "Minőség felülírása", + "Genres": "Genres", + "TheatricalRelease": "Mozis kiadás", + "DigitalRelease": "Digital Release", + "UserScore": "User Score", + "Votes": "Votes", + "Runtime": "Runtime", + "Minutes": "{{runtime}} Minutes", + "Revenue": "Revenue", + "Budget": "Budget", + "Keywords": "Keywords/Tags", + "Casts": { + "CastTitle": "Cast" + }, + "EpisodeSelector": { + "AllSeasonsTooltip": "This will request every season for this show", + "FirstSeasonTooltip": "This will only request the First Season for this show", + "LatestSeasonTooltip": "This will only request the Latest Season for this show" + } + }, + "Discovery": { + "PopularTab": "Népszerű", + "TrendingTab": "Felkapott", + "UpcomingTab": "Upcoming", + "Movies": "Filmek", + "Combined": "Combined", + "Tv": "TV", + "CardDetails": { + "Availability": "Elérhetőség", + "Studio": "Studio", + "Network": "Network", + "UnknownNetwork": "Unknown", + "RequestStatus": "Request Status", + "Director": "Director", + "InCinemas": "In Cinemas", + "FirstAired": "First Aired", + "Writer": "Writer", + "ExecProducer": "Exec Producer" + } + }, + "UserPreferences": { + "Welcome": "Üdv {{username}}!", + "OmbiLanguage": "Language", + "DarkMode": "Dark Mode" } - }, - "Issues": { - "Title": "Problémák", - "PendingTitle": "Várakozó problémák", - "InProgressTitle": "Folyamatban lévő problémák", - "ResolvedTitle": "Megoldott problémák", - "ColumnTitle": "Cím", - "Category": "Kategória", - "Status": "Állapot", - "Details": "Részletek", - "Description": "Leírás", - "NoComments": "Nincs megjegyzés!", - "MarkInProgress": "Folyamatban lévőre jelölés", - "MarkResolved": "Megjelölés megoldottként", - "SendMessageButton": "Küldés", - "Subject": "Tárgy", - "Comments": "Hozzászólások", - "WriteMessagePlaceholder": "Írd ide az üzeneted...", - "ReportedBy": "Jelentette" - }, - "Filter": { - "ClearFilter": "Szűrő törlése", - "FilterHeaderAvailability": "Elérhetőség", - "FilterHeaderRequestStatus": "Állapot", - "Approved": "Jóváhagyva", - "PendingApproval": "Jóváhagyásra vár" - }, - "UserManagment": { - "TvRemaining": "TV: {{remaining}}/{{total}} maradt", - "MovieRemaining": "Filmek: {{remaining}}/{{total}} maradt", - "MusicRemaining": "Zene: {{remaining}}/{{total}} maradt", - "TvDue": "TV: {{date}}", - "MovieDue": "Film: {{date}}", - "MusicDue": "Zene: {{date}}" - }, - "Votes": { - "CompletedVotesTab": "Szavazott", - "VotesTab": "Szavazat szükséges" - } -} +} \ No newline at end of file diff --git a/src/Ombi/wwwroot/translations/it.json b/src/Ombi/wwwroot/translations/it.json index 38fbf4b99..2f168bc23 100644 --- a/src/Ombi/wwwroot/translations/it.json +++ b/src/Ombi/wwwroot/translations/it.json @@ -1,186 +1,301 @@ { - "Login": { - "SignInButton": "Accedi", - "UsernamePlaceholder": "Nome utente", - "PasswordPlaceholder": "Password", - "RememberMe": "Ricordati di me", - "ForgottenPassword": "Hai dimenticato la password?", - "Errors": { - "IncorrectCredentials": "Username o password non corretta" - } - }, - "Common": { - "ContinueButton": "Continua", - "Available": "Disponibile", - "PartiallyAvailable": "Partially Available", - "Monitored": "Monitored", - "NotAvailable": "Not Available", - "ProcessingRequest": "Richiesta in elaborazione", - "PendingApproval": "In attesa di approvazione", - "RequestDenied": "Richiesta negata", - "NotRequested": "Non richiesto", - "Requested": "Richiesto", - "Request": "Richiesta", - "Denied": "Rifiutato", - "Approve": "Approva", - "PartlyAvailable": "Partly Available", - "Errors": { - "Validation": "Per favore, controlla i valori che hai inserito" - } - }, - "PasswordReset": { - "EmailAddressPlaceholder": "Indirizzo e-mail", - "ResetPasswordButton": "Reimposta la password" - }, - "LandingPage": { - "OnlineHeading": "Attualmente Online", - "OnlineParagraph": "Il media server è attualmente online", - "PartiallyOnlineHeading": "Parzialmente in linea", - "PartiallyOnlineParagraph": "Il media server è parzialmente in linea.", - "MultipleServersUnavailable": "Ci sono {{serversUnavailable}} server offline su {{totalServers}}.", - "SingleServerUnavailable": "C'è {{serversUnavailable}} server offline su {{totalServers}}.", - "OfflineHeading": "Attualmente Offline", - "OfflineParagraph": "Il media server è attualmente offline.", - "CheckPageForUpdates": "Controlla questa pagina per ottenere aggiornamenti del sito." - }, - "NavigationBar": { - "Search": "Cerca", - "Requests": "Richieste", - "UserManagement": "Gestione degli utenti", - "Issues": "Problemi", - "Vote": "Vote", - "Donate": "Fai una donazione!", - "DonateLibraryMaintainer": "Dona al manutentore della libreria", - "DonateTooltip": "Questo è come convinco mia moglie a farmi spendere il mio tempo libero nello sviluppo di Ombi ;)", - "UpdateAvailableTooltip": "Aggiornamento disponibile!", - "Settings": "Impostazioni", - "Welcome": "Benvenuto {{username}}", - "UpdateDetails": "Aggiorna i tuoi dati", - "Logout": "Logout", - "OpenMobileApp": "Apri l'applicazione mobile", - "RecentlyAdded": "Recently Added" - }, - "Search": { - "Title": "Cerca", - "Paragraph": "Vuoi vedere qualcosa che non è attualmente disponibile? Nessun problema, basta cercare qui sotto e richiederlo!", - "MoviesTab": "Film", - "TvTab": "Serie TV", - "MusicTab": "Music", - "Suggestions": "Suggerimenti", - "NoResults": "Ci dispiace, non abbiamo trovato alcun risultato!", - "DigitalDate": "Digital Release: {{date}}", - "TheatricalRelease": "Theatrical Release: {{date}}", - "ViewOnPlex": "Guarda su Plex", - "ViewOnEmby": "Guarda su Emby", - "RequestAdded": "La richiesta per {{title}} è stata aggiunta correttamente", - "Similar": "Similar", - "Refine": "Refine", - "SearchBarPlaceholder": "Type Here to Search", - "Movies": { - "PopularMovies": "Film popolari", - "UpcomingMovies": "Film in arrivo", - "TopRatedMovies": "Film più votati", - "NowPlayingMovies": "Film ora in riproduzione", - "HomePage": "Pagina iniziale", - "Trailer": "Trailer" + "Login": { + "SignInButton": "Accedi", + "UsernamePlaceholder": "Nome utente", + "PasswordPlaceholder": "Password", + "RememberMe": "Ricordati di me", + "SignInWith": "Accedi con {{appName}}", + "SignInWithPlex": "Accedi con Plex", + "ForgottenPassword": "Hai dimenticato la password?", + "Errors": { + "IncorrectCredentials": "Username o password non corretta" + } }, - "TvShows": { - "Popular": "Popular", - "Trending": "Trending", - "MostWatched": "Most Watched", - "MostAnticipated": "Most Anticipated", - "Results": "Results", - "AirDate": "Air Date:", - "AllSeasons": "All Seasons", - "FirstSeason": "First Season", - "LatestSeason": "Latest Season", - "Select": "Select ...", - "SubmitRequest": "Submit Request", - "Season": "Season: {{seasonNumber}}", - "SelectAllInSeason": "Select All in Season {{seasonNumber}}" - } - }, - "Requests": { - "Title": "Richieste", - "Paragraph": "Qui sotto puoi vedere le tue e tutte le altre richieste con il loro stato di download e approvazione.", - "MoviesTab": "Film", - "TvTab": "Serie TV", - "MusicTab": "Music", - "RequestedBy": "Richiesta da:", - "Status": "Stato:", - "RequestStatus": "Stato della richiesta:", - "Denied": " Rifiutato:", - "TheatricalRelease": "Theatrical Release: {{date}}", - "ReleaseDate": "Released: {{date}}", - "TheatricalReleaseSort": "Theatrical Release", - "DigitalRelease": "Digital Release: {{date}}", - "RequestDate": "Data della richiesta:", - "QualityOverride": "Sovrascrivi qualità:", - "RootFolderOverride": "Sovrascrivi cartella principale:", - "ChangeRootFolder": "Modifica cartella principale", - "ChangeQualityProfile": "Modifica il profilo della qualità", - "MarkUnavailable": "Segna come Non disponibile", - "MarkAvailable": "Segna come Disponibile", - "Remove": "Elimina", - "Deny": "Nega", - "Season": "Stagione:", - "GridTitle": "Titolo", - "AirDate": "Data di trasmissione", - "GridStatus": "Stato", - "ReportIssue": "Report Issue", - "Filter": "Filter", - "Sort": "Sort", - "SeasonNumberHeading": "Season: {seasonNumber}", - "SortTitleAsc": "Title ▲", - "SortTitleDesc": "Title ▼", - "SortRequestDateAsc": "Request Date ▲", - "SortRequestDateDesc": "Request Date ▼", - "SortStatusAsc": "Status ▲", - "SortStatusDesc": "Status ▼", - "Remaining": { - "Quota": "{{remaining}}/{{total}} requests remaining", - "NextDays": "Another request will be added in {{time}} days", - "NextHours": "Another request will be added in {{time}} hours", - "NextMinutes": "Another request will be added in {{time}} minutes", - "NextMinute": "Another request will be added in {{time}} minute" + "Common": { + "ContinueButton": "Continua", + "Available": "Disponibile", + "PartiallyAvailable": "Parzialmente Disponibile", + "Monitored": "Monitorato", + "NotAvailable": "Non Disponibile", + "ProcessingRequest": "Richiesta in elaborazione", + "PendingApproval": "In attesa di approvazione", + "RequestDenied": "Richiesta negata", + "NotRequested": "Non richiesto", + "Requested": "Richiesto", + "Request": "Richiesta", + "Denied": "Rifiutato", + "Approve": "Approva", + "PartlyAvailable": "Parzialmente Disponibile", + "ViewDetails": "Visualizza Dettagli", + "Errors": { + "Validation": "Per favore, controlla i valori che hai inserito" + }, + "Cancel": "Annulla", + "Submit": "Invia" + }, + "PasswordReset": { + "EmailAddressPlaceholder": "Indirizzo e-mail", + "ResetPasswordButton": "Reimposta la password" + }, + "LandingPage": { + "OnlineHeading": "Attualmente Online", + "OnlineParagraph": "Il media server è attualmente online", + "PartiallyOnlineHeading": "Parzialmente in linea", + "PartiallyOnlineParagraph": "Il media server è parzialmente in linea.", + "MultipleServersUnavailable": "Ci sono {{serversUnavailable}} server offline su {{totalServers}}.", + "SingleServerUnavailable": "C'è {{serversUnavailable}} server offline su {{totalServers}}.", + "OfflineHeading": "Attualmente Offline", + "OfflineParagraph": "Il media server è attualmente offline.", + "CheckPageForUpdates": "Controlla questa pagina per ottenere aggiornamenti del sito." + }, + "NavigationBar": { + "Discover": "Scopri", + "Search": "Cerca", + "Requests": "Richieste", + "UserManagement": "Gestione degli utenti", + "Issues": "Problemi", + "Vote": "Vota", + "Donate": "Fai una donazione!", + "DonateLibraryMaintainer": "Dona al manutentore della libreria", + "DonateTooltip": "Questo è come convinco mia moglie a farmi spendere il mio tempo libero nello sviluppo di Ombi ;)", + "UpdateAvailableTooltip": "Aggiornamento disponibile!", + "Settings": "Impostazioni", + "Welcome": "Benvenuto {{username}}", + "UpdateDetails": "Aggiorna i tuoi dati", + "Logout": "Esci", + "OpenMobileApp": "Apri l'applicazione mobile", + "RecentlyAdded": "Aggiunto di recente", + "ChangeTheme": "Cambia Tema", + "Calendar": "Calendario", + "UserPreferences": "Preferenze", + "FeatureSuggestion": "Suggerimenti di Funzione", + "FeatureSuggestionTooltip": "Hai una nuova grande idea? Suggeriscila qui!", + "Filter": { + "Movies": "Film", + "TvShows": "Serie TV", + "Music": "Musica", + "People": "Persone" + }, + "MorningWelcome": "Buona mattina!", + "AfternoonWelcome": "Buon pomeriggio!", + "EveningWelcome": "Buona sera!" + }, + "Search": { + "Title": "Cerca", + "Paragraph": "Vuoi vedere qualcosa che non è attualmente disponibile? Nessun problema, basta cercare qui sotto e richiederlo!", + "MoviesTab": "Film", + "TvTab": "Serie TV", + "MusicTab": "Musica", + "Suggestions": "Suggerimenti", + "NoResults": "Ci dispiace, non abbiamo trovato alcun risultato!", + "DigitalDate": "Rilascio digitale {{date}}", + "TheatricalRelease": "Rilascio Teatrale: {{date}}", + "ViewOnPlex": "Guarda su Plex", + "ViewOnEmby": "Guarda su Emby", + "RequestAdded": "La richiesta per {{title}} è stata aggiunta correttamente", + "Similar": "Simili", + "Refine": "Affina", + "SearchBarPlaceholder": "Digita qui per cercare", + "Movies": { + "PopularMovies": "Film popolari", + "UpcomingMovies": "Film in arrivo", + "TopRatedMovies": "Film più votati", + "NowPlayingMovies": "Film ora in riproduzione", + "HomePage": "Pagina iniziale", + "Trailer": "Trailer" + }, + "TvShows": { + "Popular": "Popolare", + "Trending": "Tendenze", + "MostWatched": "Più Visti", + "MostAnticipated": "Più attese", + "Results": "Risultati", + "AirDate": "Data di trasmissione:", + "AllSeasons": "Tutte le stagioni", + "FirstSeason": "Prima Stagione", + "LatestSeason": "Ultima Stagione", + "Select": "Seleziona ...", + "SubmitRequest": "Invia richiesta", + "Season": "Stagione: {{seasonNumber}}", + "SelectAllInSeason": "Seleziona Tutto nella Stagione {{seasonNumber}}" + } + }, + "Requests": { + "Title": "Richieste", + "Paragraph": "Qui sotto puoi vedere le tue e tutte le altre richieste con il loro stato di download e approvazione.", + "MoviesTab": "Film", + "ArtistName": "Artista", + "AlbumName": "Nome Album", + "TvTab": "Serie TV", + "MusicTab": "Musica", + "RequestedBy": "Richiesta da", + "Status": "Stato", + "RequestStatus": "Stato della richiesta", + "Denied": " Rifiutato:", + "TheatricalRelease": "Rilascio Teatrale: {{date}}", + "ReleaseDate": "Rilasciato: {{date}}", + "TheatricalReleaseSort": "Rilascio Teatrale", + "DigitalRelease": "Rilascio digitale {{date}}", + "RequestDate": "Data della richiesta", + "QualityOverride": "Sovrascrivi qualità:", + "RootFolderOverride": "Sovrascrivi cartella principale:", + "ChangeRootFolder": "Modifica cartella principale", + "ChangeQualityProfile": "Modifica il profilo della qualità", + "MarkUnavailable": "Segna come Non disponibile", + "MarkAvailable": "Segna come Disponibile", + "Remove": "Elimina", + "Deny": "Nega", + "DenyReason": "Nega Motivo", + "Season": "Stagione:", + "GridTitle": "Titolo", + "AirDate": "Data di trasmissione", + "GridStatus": "Stato", + "ReportIssue": "Segnala Problema", + "Filter": "Filtra", + "Sort": "Ordina", + "SeasonNumberHeading": "Stagione: {seasonNumber}", + "SortTitleAsc": "Titolo ▲", + "SortTitleDesc": "Titolo ▼", + "SortRequestDateAsc": "Data Richiesta", + "SortRequestDateDesc": "Data Richiesta", + "SortStatusAsc": "Stato ▲", + "SortStatusDesc": "Status ▼", + "Remaining": { + "Quota": "{{remaining}}/{{total}} richieste rimanenti", + "NextDays": "Un'altra richiesta verrà aggiunta tra {{time}} giorni", + "NextHours": "Un'altra richiesta verrà aggiunta tra {{time}} ore", + "NextMinutes": "Un'altra richiesta verrà aggiunta tra {{time}} minuti", + "NextMinute": "Un'altra richiesta verrà aggiunta tra {{time}} minuti" + }, + "AllRequests": "Tutte le Richieste", + "PendingRequests": "Richieste in Attesa", + "ProcessingRequests": "Richieste di Elaborazione", + "AvailableRequests": "Richieste Disponibili", + "DeniedRequests": "Richieste Negate", + "RequestsToDisplay": "Richieste da mostrare", + "RequestsTitle": "Titolo", + "Details": "Dettagli", + "Options": "Opzioni", + "RequestPanel": { + "Delete": "Elimina Richiesta", + "Approve": "Approva Richiesta", + "ChangeAvailability": "Segna come Disponibile" + } + }, + "Issues": { + "Title": "Problemi", + "PendingTitle": "Problemi in sospeso", + "InProgressTitle": "Problemi in risoluzione", + "ResolvedTitle": "Problemi risolti", + "ColumnTitle": "Titolo", + "Category": "Categoria", + "Status": "Stato", + "Details": "Dettagli", + "Description": "Descrizione", + "NoComments": "Non ci sono commenti!", + "MarkInProgress": "Segna come in risoluzione", + "MarkResolved": "Segna come risolto", + "SendMessageButton": "Invia", + "Subject": "Oggetto", + "Comments": "Commenti", + "WriteMessagePlaceholder": "Scrivi qui il tuo messaggio...", + "ReportedBy": "Segnalato da", + "IssueDialog": { + "Title": "Segnala un problema", + "DescriptionPlaceholder": "Sei pregato di descrivere il problema", + "TitlePlaceholder": "Titolo breve del tuo problema", + "SelectCategory": "Seleziona Categoria", + "IssueCreated": "Il problema è stato creato" + }, + "Outstanding": "Ci sono problemi in sospeso", + "ResolvedDate": "Data risolta", + "CreatedDate": "Cresciuto il", + "MarkedAsResolved": "Questo problema è stato ora segnato come risolto!", + "MarkedAsInProgress": "Questo problema è stato ora segnato come in corso!", + "Delete": "Elimina problema", + "DeletedIssue": "Il problema è stato eliminato" + }, + "Filter": { + "ClearFilter": "Rimuovi filtro", + "FilterHeaderAvailability": "Disponibilità", + "FilterHeaderRequestStatus": "Stato", + "Approved": "Approvato", + "PendingApproval": "In attesa di approvazione" + }, + "UserManagment": { + "TvRemaining": "TV: {{remaining}}/{{total}} rimanenti", + "MovieRemaining": "Film: {{remaining}}/{{total}} rimanenti", + "MusicRemaining": "Musica: {{remaining}}/{{total}} rimanenti", + "TvDue": "TV: {{date}}", + "MovieDue": "Film: {{date}}", + "MusicDue": "Musica: {{date}}" + }, + "Votes": { + "CompletedVotesTab": "Votati", + "VotesTab": "Voti Necessari" + }, + "MediaDetails": { + "Denied": "Rifiutato", + "RecommendationsTitle": "Raccomandazioni", + "SimilarTitle": "Simili", + "VideosTitle": "Video", + "AlbumsTitle": "Album", + "RequestAllAlbums": "Richiedi Tutti gli Album", + "ClearSelection": "Cancella Selezione", + "RequestSelectedAlbums": "Richiesta degli Album Selezionati", + "ViewCollection": "Visualizza Raccolta", + "NotEnoughInfo": "Sfortunatamente ancora non ci sono abbastanza informazioni su questo show!", + "AdvancedOptions": "Opzioni Avanzate", + "QualityProfilesSelect": "Seleziona Un Profilo di Qualità", + "RootFolderSelect": "Seleziona Una Cartella di Root", + "Status": "Stato", + "Availability": "Disponibilità", + "RequestStatus": "Stato Richiesta", + "Quality": "Qualità", + "RootFolderOverride": "Sovrascrivi cartella principale", + "QualityOverride": "Sovrascrivi qualità", + "Genres": "Generi", + "TheatricalRelease": "Rilascio Teatrale", + "DigitalRelease": "Rilascio Digitale", + "UserScore": "Punteggio Utente", + "Votes": "Voti", + "Runtime": "Durata", + "Minutes": "{{runtime}} Minuti", + "Revenue": "Entrate", + "Budget": "Budget", + "Keywords": "Parole Chiave/Tag", + "Casts": { + "CastTitle": "Trasmetti" + }, + "EpisodeSelector": { + "AllSeasonsTooltip": "Questo richiederà ogni stagione per questo show", + "FirstSeasonTooltip": "Questo richiederà solo la Prima Stagione per questo show", + "LatestSeasonTooltip": "Questo richiederà solo l'Ultima Stagione per questo show" + } + }, + "Discovery": { + "PopularTab": "Popolare", + "TrendingTab": "Tendenze", + "UpcomingTab": "In arrivo", + "Movies": "Film", + "Combined": "Combinato", + "Tv": "TV", + "CardDetails": { + "Availability": "Disponibilità", + "Studio": "Studio", + "Network": "Rete", + "UnknownNetwork": "Sconosciuto", + "RequestStatus": "Stato Richiesta", + "Director": "Direttore", + "InCinemas": "Nei Cinema", + "FirstAired": "Prima Trasmissione", + "Writer": "Scrittore", + "ExecProducer": "Produttore Esecutivo" + } + }, + "UserPreferences": { + "Welcome": "Benvenuto {{username}}!", + "OmbiLanguage": "Lingua", + "DarkMode": "Modalità Scura" } - }, - "Issues": { - "Title": "Problemi", - "PendingTitle": "Problemi in sospeso", - "InProgressTitle": "Problemi in risoluzione", - "ResolvedTitle": "Problemi risolti", - "ColumnTitle": "Titolo", - "Category": "Categoria", - "Status": "Stato", - "Details": "Dettagli", - "Description": "Descrizione", - "NoComments": "Non ci sono commenti!", - "MarkInProgress": "Segna come in risoluzione", - "MarkResolved": "Segna come risolto", - "SendMessageButton": "Invia", - "Subject": "Oggetto", - "Comments": "Commenti", - "WriteMessagePlaceholder": "Scrivi qui il tuo messaggio...", - "ReportedBy": "Segnalato da" - }, - "Filter": { - "ClearFilter": "Clear Filter", - "FilterHeaderAvailability": "Availability", - "FilterHeaderRequestStatus": "Status", - "Approved": "Approved", - "PendingApproval": "Pending Approval" - }, - "UserManagment": { - "TvRemaining": "TV: {{remaining}}/{{total}} remaining", - "MovieRemaining": "Movies: {{remaining}}/{{total}} remaining", - "MusicRemaining": "Music: {{remaining}}/{{total}} remaining", - "TvDue": "TV: {{date}}", - "MovieDue": "Movie: {{date}}", - "MusicDue": "Music: {{date}}" - }, - "Votes": { - "CompletedVotesTab": "Voted", - "VotesTab": "Votes Needed" - } -} +} \ No newline at end of file diff --git a/src/Ombi/wwwroot/translations/nl.json b/src/Ombi/wwwroot/translations/nl.json index 7bacfd142..0490be1e5 100644 --- a/src/Ombi/wwwroot/translations/nl.json +++ b/src/Ombi/wwwroot/translations/nl.json @@ -1,186 +1,301 @@ { - "Login": { - "SignInButton": "Aanmelden", - "UsernamePlaceholder": "Gebruikersnaam", - "PasswordPlaceholder": "Wachtwoord", - "RememberMe": "Onthoud Mij", - "ForgottenPassword": "Wachtwoord vergeten?", - "Errors": { - "IncorrectCredentials": "Onjuiste gebruikersnaam of wachtwoord" - } - }, - "Common": { - "ContinueButton": "Doorgaan", - "Available": "Beschikbaar", - "PartiallyAvailable": "Deels Beschikbaar", - "Monitored": "Gemonitord", - "NotAvailable": "Niet Beschikbaar", - "ProcessingRequest": "Verzoek wordt verwerkt", - "PendingApproval": "Wacht op goedkeuring", - "RequestDenied": "Verzoek geweigerd", - "NotRequested": "Niet verzocht", - "Requested": "Aangevraagd", - "Request": "Aanvragen", - "Denied": "Afgewezen", - "Approve": "Accepteer", - "PartlyAvailable": "Deels Beschikbaar", - "Errors": { - "Validation": "Controleer de ingevulde waardes" - } - }, - "PasswordReset": { - "EmailAddressPlaceholder": "E-mail adres", - "ResetPasswordButton": "Herstel wachtwoord" - }, - "LandingPage": { - "OnlineHeading": "Online", - "OnlineParagraph": "De mediaserver is momenteel online", - "PartiallyOnlineHeading": "Gedeeltelijk Online", - "PartiallyOnlineParagraph": "De mediaserver is gedeeltelijk online.", - "MultipleServersUnavailable": "Er zijn {{serversUnavailable}} van de {{totalServers}} servers offline.", - "SingleServerUnavailable": "Er is {{serversUnavailable}} van de {{totalServers}} server offline.", - "OfflineHeading": "Momenteel Offline", - "OfflineParagraph": "De mediaserver is momenteel offline.", - "CheckPageForUpdates": "Controleer deze pagina voor updates." - }, - "NavigationBar": { - "Search": "Zoeken", - "Requests": "Verzoeken", - "UserManagement": "Gebruikersmanagement", - "Issues": "Problemen", - "Vote": "Stem", - "Donate": "Doneer!", - "DonateLibraryMaintainer": "Doneren aan Ombi beheerder", - "DonateTooltip": "Zo heb ik mijn vrouw overtuigd dat ik Ombi mag ontwikkelen ;)", - "UpdateAvailableTooltip": "Update beschikbaar!", - "Settings": "Instellingen", - "Welcome": "Welkom {{username}}", - "UpdateDetails": "Gegevens updaten", - "Logout": "Afmelden", - "OpenMobileApp": "Mobiele App Openen", - "RecentlyAdded": "Onlangs Toegevoegd" - }, - "Search": { - "Title": "Zoeken", - "Paragraph": "Wil je iets kijken dat momenteel niet beschikbaar is? Geen probleem, zoek het hieronder op en vraag het aan!", - "MoviesTab": "Films", - "TvTab": "TV Series", - "MusicTab": "Muziek", - "Suggestions": "Suggesties", - "NoResults": "Sorry, er zijn geen resultaten gevonden!", - "DigitalDate": "Digitale Uitgave: {{date}}", - "TheatricalRelease": "Bioscoop Uitgave: {{date}}", - "ViewOnPlex": "Bekijk op Plex", - "ViewOnEmby": "Bekijk op Emby", - "RequestAdded": "Aanvraag voor {{title}} is succesvol toegevoegd", - "Similar": "Vergelijkbaar", - "Refine": "Verfijn", - "SearchBarPlaceholder": "Voer zoekterm in", - "Movies": { - "PopularMovies": "Populaire films", - "UpcomingMovies": "Aankomende Films", - "TopRatedMovies": "Best Beoordeelde Films", - "NowPlayingMovies": "Nu in de bioscoop", - "HomePage": "Startpagina", - "Trailer": "Trailer" + "Login": { + "SignInButton": "Aanmelden", + "UsernamePlaceholder": "Gebruikersnaam", + "PasswordPlaceholder": "Wachtwoord", + "RememberMe": "Onthoud Mij", + "SignInWith": "Sign in with {{appName}}", + "SignInWithPlex": "Sign in with Plex", + "ForgottenPassword": "Wachtwoord vergeten?", + "Errors": { + "IncorrectCredentials": "Onjuiste gebruikersnaam of wachtwoord" + } }, - "TvShows": { - "Popular": "Populair", - "Trending": "Trending", - "MostWatched": "Meest Bekeken", - "MostAnticipated": "Meest Verwacht", - "Results": "Resultaten", - "AirDate": "Uitzenddatum:", - "AllSeasons": "Alle Seizoenen", - "FirstSeason": "Eerste Seizoen", - "LatestSeason": "Laatste Seizoen", - "Select": "Selecteer...", - "SubmitRequest": "Verzoek Indienen", - "Season": "Seizoen: {{seasonNumber}}", - "SelectAllInSeason": "Selecteer Alles in het Seizoen {{seasonNumber}}" - } - }, - "Requests": { - "Title": "Verzoeken", - "Paragraph": "Hieronder zie je jouw en alle andere verzoeken, evenals hun download en goedkeuring status.", - "MoviesTab": "Films", - "TvTab": "TV Series", - "MusicTab": "Muziek", - "RequestedBy": "Verzocht Door:", - "Status": "Status:", - "RequestStatus": "Aanvraagstatus:", - "Denied": " Geweigerd:", - "TheatricalRelease": "Cinema Uitgave: {{date}}", - "ReleaseDate": "Uitgekomen: {{date}}", - "TheatricalReleaseSort": "Bioscoop Uitgave", - "DigitalRelease": "Digitale Uitgave: {{date}}", - "RequestDate": "Aanvraag Datum:", - "QualityOverride": "Kwaliteit overschrijven:", - "RootFolderOverride": "Hoofdmap overschrijven:", - "ChangeRootFolder": "Hoofdmap wijzigen", - "ChangeQualityProfile": "Kwaliteitsprofiel wijzigen", - "MarkUnavailable": "Markeren als onbeschikbaar", - "MarkAvailable": "Markeren als beschikbaar", - "Remove": "Verwijderen", - "Deny": "Weigeren", - "Season": "Seizoen:", - "GridTitle": "Titel", - "AirDate": "Uitzenddatum", - "GridStatus": "Status", - "ReportIssue": "Probleem Melden", - "Filter": "Filter", - "Sort": "Sorteer", - "SeasonNumberHeading": "Seizoen: {seasonNumber}", - "SortTitleAsc": "Titel ▲", - "SortTitleDesc": "Titel ▼", - "SortRequestDateAsc": "Aanvraag Datum ▲", - "SortRequestDateDesc": "Aanvraag Datum ▼", - "SortStatusAsc": "Status ▲", - "SortStatusDesc": "Status ▼", - "Remaining": { - "Quota": "{{remaining}}/{{total}} resterende aanvragen", - "NextDays": "Een ander verzoek zal worden toegevoegd in {{time}} Dagen", - "NextHours": "Een ander verzoek zal worden toegevoegd in {{time}} Uren", - "NextMinutes": "Een ander verzoek zal worden toegevoegd in {{time}} Minuten", - "NextMinute": "Een ander verzoek zal worden toegevoegd in {{time}} Minuut" + "Common": { + "ContinueButton": "Doorgaan", + "Available": "Beschikbaar", + "PartiallyAvailable": "Deels Beschikbaar", + "Monitored": "Gemonitord", + "NotAvailable": "Niet Beschikbaar", + "ProcessingRequest": "Verzoek wordt verwerkt", + "PendingApproval": "Wacht op goedkeuring", + "RequestDenied": "Verzoek geweigerd", + "NotRequested": "Niet verzocht", + "Requested": "Aangevraagd", + "Request": "Aanvragen", + "Denied": "Afgewezen", + "Approve": "Accepteer", + "PartlyAvailable": "Deels Beschikbaar", + "ViewDetails": "Eigenschappen bekijken", + "Errors": { + "Validation": "Controleer de ingevulde waardes" + }, + "Cancel": "Cancel", + "Submit": "Submit" + }, + "PasswordReset": { + "EmailAddressPlaceholder": "E-mail adres", + "ResetPasswordButton": "Herstel wachtwoord" + }, + "LandingPage": { + "OnlineHeading": "Online", + "OnlineParagraph": "De mediaserver is momenteel online", + "PartiallyOnlineHeading": "Gedeeltelijk Online", + "PartiallyOnlineParagraph": "De mediaserver is gedeeltelijk online.", + "MultipleServersUnavailable": "Er zijn {{serversUnavailable}} van de {{totalServers}} servers offline.", + "SingleServerUnavailable": "Er is {{serversUnavailable}} van de {{totalServers}} server offline.", + "OfflineHeading": "Momenteel Offline", + "OfflineParagraph": "De mediaserver is momenteel offline.", + "CheckPageForUpdates": "Controleer deze pagina voor updates." + }, + "NavigationBar": { + "Discover": "Ontdekken", + "Search": "Zoeken", + "Requests": "Verzoeken", + "UserManagement": "Gebruikersmanagement", + "Issues": "Problemen", + "Vote": "Stem", + "Donate": "Doneer!", + "DonateLibraryMaintainer": "Doneren aan Ombi beheerder", + "DonateTooltip": "Zo heb ik mijn vrouw overtuigd dat ik Ombi mag ontwikkelen ;)", + "UpdateAvailableTooltip": "Update beschikbaar!", + "Settings": "Instellingen", + "Welcome": "Welkom {{username}}", + "UpdateDetails": "Gegevens updaten", + "Logout": "Afmelden", + "OpenMobileApp": "Mobiele App Openen", + "RecentlyAdded": "Onlangs Toegevoegd", + "ChangeTheme": "Thema wijzigen", + "Calendar": "Agenda", + "UserPreferences": "Instellingen", + "FeatureSuggestion": "Feature Suggestion", + "FeatureSuggestionTooltip": "Have a great new idea? Suggest it here!", + "Filter": { + "Movies": "Films", + "TvShows": "TV Series", + "Music": "Muziek", + "People": "People" + }, + "MorningWelcome": "Good morning!", + "AfternoonWelcome": "Good afternoon!", + "EveningWelcome": "Good evening!" + }, + "Search": { + "Title": "Zoeken", + "Paragraph": "Wil je iets kijken dat momenteel niet beschikbaar is? Geen probleem, zoek het hieronder op en vraag het aan!", + "MoviesTab": "Films", + "TvTab": "TV Series", + "MusicTab": "Muziek", + "Suggestions": "Suggesties", + "NoResults": "Sorry, er zijn geen resultaten gevonden!", + "DigitalDate": "Digitale Uitgave: {{date}}", + "TheatricalRelease": "Bioscoop Uitgave: {{date}}", + "ViewOnPlex": "Bekijk op Plex", + "ViewOnEmby": "Bekijk op Emby", + "RequestAdded": "Aanvraag voor {{title}} is succesvol toegevoegd", + "Similar": "Vergelijkbaar", + "Refine": "Verfijn", + "SearchBarPlaceholder": "Voer zoekterm in", + "Movies": { + "PopularMovies": "Populaire films", + "UpcomingMovies": "Aankomende Films", + "TopRatedMovies": "Best Beoordeelde Films", + "NowPlayingMovies": "Nu in de bioscoop", + "HomePage": "Startpagina", + "Trailer": "Trailer" + }, + "TvShows": { + "Popular": "Populair", + "Trending": "Trending", + "MostWatched": "Meest Bekeken", + "MostAnticipated": "Meest Verwacht", + "Results": "Resultaten", + "AirDate": "Uitzenddatum:", + "AllSeasons": "Alle Seizoenen", + "FirstSeason": "Eerste Seizoen", + "LatestSeason": "Laatste Seizoen", + "Select": "Selecteer...", + "SubmitRequest": "Verzoek Indienen", + "Season": "Seizoen: {{seasonNumber}}", + "SelectAllInSeason": "Selecteer Alles in het Seizoen {{seasonNumber}}" + } + }, + "Requests": { + "Title": "Verzoeken", + "Paragraph": "Hieronder zie je jouw en alle andere verzoeken, evenals hun download en goedkeuring status.", + "MoviesTab": "Films", + "ArtistName": "Artist", + "AlbumName": "Album Name", + "TvTab": "TV Series", + "MusicTab": "Muziek", + "RequestedBy": "Verzocht Door", + "Status": "Status", + "RequestStatus": "Aanvraagstatus", + "Denied": " Geweigerd:", + "TheatricalRelease": "Cinema Uitgave: {{date}}", + "ReleaseDate": "Uitgekomen: {{date}}", + "TheatricalReleaseSort": "Bioscoop Uitgave", + "DigitalRelease": "Digitale Uitgave: {{date}}", + "RequestDate": "Aanvraag Datum", + "QualityOverride": "Kwaliteit overschrijven:", + "RootFolderOverride": "Hoofdmap overschrijven:", + "ChangeRootFolder": "Hoofdmap wijzigen", + "ChangeQualityProfile": "Kwaliteitsprofiel wijzigen", + "MarkUnavailable": "Markeren als onbeschikbaar", + "MarkAvailable": "Markeren als beschikbaar", + "Remove": "Verwijderen", + "Deny": "Weigeren", + "DenyReason": "Reden van afwijzing", + "Season": "Seizoen:", + "GridTitle": "Titel", + "AirDate": "Uitzenddatum", + "GridStatus": "Status", + "ReportIssue": "Probleem Melden", + "Filter": "Filter", + "Sort": "Sorteer", + "SeasonNumberHeading": "Seizoen: {seasonNumber}", + "SortTitleAsc": "Titel ▲", + "SortTitleDesc": "Titel ▼", + "SortRequestDateAsc": "Aanvraag Datum ▲", + "SortRequestDateDesc": "Aanvraag Datum ▼", + "SortStatusAsc": "Status ▲", + "SortStatusDesc": "Status ▼", + "Remaining": { + "Quota": "{{remaining}}/{{total}} resterende aanvragen", + "NextDays": "Een ander verzoek zal worden toegevoegd in {{time}} Dagen", + "NextHours": "Een ander verzoek zal worden toegevoegd in {{time}} Uren", + "NextMinutes": "Een ander verzoek zal worden toegevoegd in {{time}} Minuten", + "NextMinute": "Een ander verzoek zal worden toegevoegd in {{time}} Minuut" + }, + "AllRequests": "All Requests", + "PendingRequests": "Pending Requests", + "ProcessingRequests": "Processing Requests", + "AvailableRequests": "Available Requests", + "DeniedRequests": "Denied Requests", + "RequestsToDisplay": "Requests to display", + "RequestsTitle": "Titel", + "Details": "Details", + "Options": "Options", + "RequestPanel": { + "Delete": "Delete Request", + "Approve": "Approve Request", + "ChangeAvailability": "Mark Available" + } + }, + "Issues": { + "Title": "Problemen", + "PendingTitle": "Onopgeloste Problemen", + "InProgressTitle": "Problemen in Behandeling", + "ResolvedTitle": "Opgeloste Problemen", + "ColumnTitle": "Titel", + "Category": "Categorie", + "Status": "Status", + "Details": "Details", + "Description": "Beschrijving", + "NoComments": "Geen reacties!", + "MarkInProgress": "Markeer In Behandeling", + "MarkResolved": "Markeer Opgelost", + "SendMessageButton": "Verstuur", + "Subject": "Onderwerp", + "Comments": "Opmerkingen", + "WriteMessagePlaceholder": "Schrijf hier je bericht...", + "ReportedBy": "Gerapporteerd door", + "IssueDialog": { + "Title": "Report an issue", + "DescriptionPlaceholder": "Please describe the issue", + "TitlePlaceholder": "Short title of your issue", + "SelectCategory": "Select Category", + "IssueCreated": "Issue has been created" + }, + "Outstanding": "There are outstanding issues", + "ResolvedDate": "Resolved date", + "CreatedDate": "Raised on", + "MarkedAsResolved": "This issue has now been marked as resolved!", + "MarkedAsInProgress": "This issue has now been marked as in progress!", + "Delete": "Delete issue", + "DeletedIssue": "Issue has been deleted" + }, + "Filter": { + "ClearFilter": "Verwijder Filter", + "FilterHeaderAvailability": "Beschikbaarheid", + "FilterHeaderRequestStatus": "Status", + "Approved": "Goedgekeurd", + "PendingApproval": "In afwachting van goedkeuring" + }, + "UserManagment": { + "TvRemaining": "Tv: {{remaining}}/{{total}} Resterend", + "MovieRemaining": "Tv: {{remaining}}/{{total}} Resterend", + "MusicRemaining": "Muziek: {{remaining}}/{{total}} Resterend", + "TvDue": "Tv: {{date}}", + "MovieDue": "Film: {{date}}", + "MusicDue": "Muziek: {{date}}" + }, + "Votes": { + "CompletedVotesTab": "Gestemd", + "VotesTab": "Stemmen nodig" + }, + "MediaDetails": { + "Denied": "Afgewezen", + "RecommendationsTitle": "Aanbevelingen", + "SimilarTitle": "Vergelijkbaar", + "VideosTitle": "Video's", + "AlbumsTitle": "Albums", + "RequestAllAlbums": "Request All Albums", + "ClearSelection": "Clear Selection", + "RequestSelectedAlbums": "Request Selected Albums", + "ViewCollection": "View Collection", + "NotEnoughInfo": "Unfortunately there is not enough information about this show yet!", + "AdvancedOptions": "Advanced Options", + "QualityProfilesSelect": "Select A Quality Profile", + "RootFolderSelect": "Select A Root Folder", + "Status": "Status", + "Availability": "Beschikbaarheid", + "RequestStatus": "Aanvraagstatus", + "Quality": "Quality", + "RootFolderOverride": "Hoofdmap overschrijven", + "QualityOverride": "Kwaliteit overschrijven", + "Genres": "Genres", + "TheatricalRelease": "Bioscoop Uitgave", + "DigitalRelease": "Digital Release", + "UserScore": "User Score", + "Votes": "Votes", + "Runtime": "Runtime", + "Minutes": "{{runtime}} Minutes", + "Revenue": "Revenue", + "Budget": "Budget", + "Keywords": "Keywords/Tags", + "Casts": { + "CastTitle": "Acteurs" + }, + "EpisodeSelector": { + "AllSeasonsTooltip": "Dit verzoekt ieder seizoen van deze serie", + "FirstSeasonTooltip": "Dit verzoekt alleen het eerste seizoen van deze serie", + "LatestSeasonTooltip": "Dit verzoekt alleen het laatste seizoen van deze show" + } + }, + "Discovery": { + "PopularTab": "Populair", + "TrendingTab": "Populair", + "UpcomingTab": "Aankomend", + "Movies": "Films", + "Combined": "Combined", + "Tv": "TV", + "CardDetails": { + "Availability": "Beschikbaarheid", + "Studio": "Studio", + "Network": "Netwerk", + "UnknownNetwork": "Niet bekend", + "RequestStatus": "Aanvraagstatus", + "Director": "Regisseur", + "InCinemas": "In de bioscoop", + "FirstAired": "Eerste uitzending", + "Writer": "Schrijver", + "ExecProducer": "Uitvoerende producent" + } + }, + "UserPreferences": { + "Welcome": "Welkom {{username}}!", + "OmbiLanguage": "Language", + "DarkMode": "Dark Mode" } - }, - "Issues": { - "Title": "Problemen", - "PendingTitle": "Onopgeloste Problemen", - "InProgressTitle": "Problemen in Behandeling", - "ResolvedTitle": "Opgeloste Problemen", - "ColumnTitle": "Titel", - "Category": "Categorie", - "Status": "Status", - "Details": "Details", - "Description": "Beschrijving", - "NoComments": "Geen reacties!", - "MarkInProgress": "Markeer In Behandeling", - "MarkResolved": "Markeer Opgelost", - "SendMessageButton": "Verstuur", - "Subject": "Onderwerp", - "Comments": "Opmerkingen", - "WriteMessagePlaceholder": "Schrijf hier je bericht...", - "ReportedBy": "Gerapporteerd door" - }, - "Filter": { - "ClearFilter": "Verwijder Filter", - "FilterHeaderAvailability": "Beschikbaarheid", - "FilterHeaderRequestStatus": "Status", - "Approved": "Goedgekeurd", - "PendingApproval": "In afwachting van goedkeuring" - }, - "UserManagment": { - "TvRemaining": "Tv: {{remaining}}/{{total}} Resterend", - "MovieRemaining": "Tv: {{remaining}}/{{total}} Resterend", - "MusicRemaining": "Muziek: {{remaining}}/{{total}} Resterend", - "TvDue": "Tv: {{date}}", - "MovieDue": "Film: {{date}}", - "MusicDue": "Muziek: {{date}}" - }, - "Votes": { - "CompletedVotesTab": "Gestemd", - "VotesTab": "Stemmen nodig" - } -} +} \ No newline at end of file diff --git a/src/Ombi/wwwroot/translations/no.json b/src/Ombi/wwwroot/translations/no.json index 91e69facb..f74766883 100644 --- a/src/Ombi/wwwroot/translations/no.json +++ b/src/Ombi/wwwroot/translations/no.json @@ -1,186 +1,301 @@ { - "Login": { - "SignInButton": "Logg på", - "UsernamePlaceholder": "Brukernavn", - "PasswordPlaceholder": "Passord", - "RememberMe": "Husk meg", - "ForgottenPassword": "Glemt passord?", - "Errors": { - "IncorrectCredentials": "Ugyldig brukernavn eller passord" - } - }, - "Common": { - "ContinueButton": "Gå videre", - "Available": "Tilgjengelig", - "PartiallyAvailable": "Delvis tilgjengelig", - "Monitored": "Overvåket", - "NotAvailable": "Ikke tilgjengelig", - "ProcessingRequest": "Behandler forespørsel", - "PendingApproval": "Venter på godkjenning", - "RequestDenied": "Forespørsel avslått", - "NotRequested": "Ikke forespurt", - "Requested": "Forespurt", - "Request": "Forespørsel", - "Denied": "Avslått", - "Approve": "Godkjenn", - "PartlyAvailable": "Delvis tilgjengelig", - "Errors": { - "Validation": "Kontroller de angitte verdiene" - } - }, - "PasswordReset": { - "EmailAddressPlaceholder": "E-postadresse", - "ResetPasswordButton": "Tilbakestill passord" - }, - "LandingPage": { - "OnlineHeading": "For øyeblikket online", - "OnlineParagraph": "Medieserveren er online", - "PartiallyOnlineHeading": "Delvis online", - "PartiallyOnlineParagraph": "Medieserveren er delvis utilgjengelig.", - "MultipleServersUnavailable": "Det er {{serversUnavailable}} servere offline av totalt {{totalServers}}.", - "SingleServerUnavailable": "Det er {{serversUnavailable}} server offline av totalt {{totalServers}}.", - "OfflineHeading": "For øyeblikket offline", - "OfflineParagraph": "Medieserveren er for øyeblikket utilgjengelig.", - "CheckPageForUpdates": "Sjekk denne siden for kontinuerlige oppdateringer." - }, - "NavigationBar": { - "Search": "Søk", - "Requests": "Forespørsler", - "UserManagement": "Brukeradministrasjon", - "Issues": "Mangler", - "Vote": "Stem", - "Donate": "Doner!", - "DonateLibraryMaintainer": "Doner til vedlikeholderen av biblioteket", - "DonateTooltip": "Dette er hvordan jeg overbevise min kone til å la meg bruke min fritid til å utvikle Ombi ;)", - "UpdateAvailableTooltip": "Ny opdatering venter!", - "Settings": "Innstillinger", - "Welcome": "Velkommen {{username}}", - "UpdateDetails": "Oppdater detaljer", - "Logout": "Logg av", - "OpenMobileApp": "Åpne mobilapp", - "RecentlyAdded": "Nylig lagt til" - }, - "Search": { - "Title": "Søk", - "Paragraph": "Vil du se noe som foreløpig ikke er tilgjengelig? Ikke noe problem, bare søk etter det nedenfor og be om det!", - "MoviesTab": "Filmer", - "TvTab": "TV serier", - "MusicTab": "Musikk", - "Suggestions": "Forslag", - "NoResults": "Beklager, vi fant ingen resultater!", - "DigitalDate": "Digital utgivelse: {{date}}", - "TheatricalRelease": "Kinopremiere: {{date}}", - "ViewOnPlex": "Spill av på Plex", - "ViewOnEmby": "Spill av på Emby", - "RequestAdded": "Forespørsel om {{title}} er lagt til", - "Similar": "Lignende", - "Refine": "Spesifiser", - "SearchBarPlaceholder": "Angi nøkkelord for søk", - "Movies": { - "PopularMovies": "Populære filmer", - "UpcomingMovies": "Kommende filmer", - "TopRatedMovies": "Kritikerroste filmer", - "NowPlayingMovies": "Aktuelle Filmer", - "HomePage": "Startside", - "Trailer": "Trailer" + "Login": { + "SignInButton": "Logg på", + "UsernamePlaceholder": "Brukernavn", + "PasswordPlaceholder": "Passord", + "RememberMe": "Husk meg", + "SignInWith": "Sign in with {{appName}}", + "SignInWithPlex": "Sign in with Plex", + "ForgottenPassword": "Glemt passord?", + "Errors": { + "IncorrectCredentials": "Ugyldig brukernavn eller passord" + } }, - "TvShows": { - "Popular": "Populært", - "Trending": "På vei opp", - "MostWatched": "Mest sett", - "MostAnticipated": "Mest etterlengtede", - "Results": "Resultater", - "AirDate": "Sendingsdato:", - "AllSeasons": "Alle Sesonger", - "FirstSeason": "Første sesong", - "LatestSeason": "Siste sesong", - "Select": "Velg...", - "SubmitRequest": "Send forespørsel", - "Season": "Sesong: {{seasonNumber}}", - "SelectAllInSeason": "Velg alle i sesong {{seasonNumber}}" - } - }, - "Requests": { - "Title": "Forespørsler", - "Paragraph": "Nedenfor kan du se dine og alle andres forespørsler, du ser også status for nedlasting og godkjenning.", - "MoviesTab": "Filmer", - "TvTab": "TV serier", - "MusicTab": "Musikk", - "RequestedBy": "Etterspurt av:", - "Status": "Status:", - "RequestStatus": "Status for forespørsel:", - "Denied": " Avslått:", - "TheatricalRelease": "Kinopremiere: {{date}}", - "ReleaseDate": "Utgitt: {{date}}", - "TheatricalReleaseSort": "Kinopremiere", - "DigitalRelease": "Digital utgivelse: {{date}}", - "RequestDate": "Dato for forespørsel:", - "QualityOverride": "Overstyr kvalitet:", - "RootFolderOverride": "Overstyring av rotmappe:", - "ChangeRootFolder": "Endre rotmappe", - "ChangeQualityProfile": "Endre kvalitetsprofil", - "MarkUnavailable": "Merk utilgjengelig", - "MarkAvailable": "Merk tilgjengelig", - "Remove": "Fjern", - "Deny": "Avslå", - "Season": "Sesong:", - "GridTitle": "Tittel", - "AirDate": "Sendedato", - "GridStatus": "Status", - "ReportIssue": "Rapportér en feil", - "Filter": "Filter", - "Sort": "Sorter", - "SeasonNumberHeading": "Sesong: {seasonNumber}", - "SortTitleAsc": "Tittel ▲", - "SortTitleDesc": "Tittel ▼", - "SortRequestDateAsc": "Dato for forespørsel ▲", - "SortRequestDateDesc": "Dato for forespørsel ▼", - "SortStatusAsc": "Status ▲", - "SortStatusDesc": "Status ▼", - "Remaining": { - "Quota": "{{remaining}}/{{total}} forespørsler igjen", - "NextDays": "En ny foresøprel vil bli lagt til om {{time}} dager", - "NextHours": "En ny foresøprel vil bli lagt til om {{time}} timer", - "NextMinutes": "En ny foresøprel vil bli lagt til om {{time}} minutter", - "NextMinute": "En ny foresøprel vil bli lagt til om {{time}} minutt" + "Common": { + "ContinueButton": "Gå videre", + "Available": "Tilgjengelig", + "PartiallyAvailable": "Delvis tilgjengelig", + "Monitored": "Overvåket", + "NotAvailable": "Ikke tilgjengelig", + "ProcessingRequest": "Behandler forespørsel", + "PendingApproval": "Venter på godkjenning", + "RequestDenied": "Forespørsel avslått", + "NotRequested": "Ikke forespurt", + "Requested": "Forespurt", + "Request": "Forespørsel", + "Denied": "Avslått", + "Approve": "Godkjenn", + "PartlyAvailable": "Delvis tilgjengelig", + "ViewDetails": "View Details", + "Errors": { + "Validation": "Kontroller de angitte verdiene" + }, + "Cancel": "Cancel", + "Submit": "Submit" + }, + "PasswordReset": { + "EmailAddressPlaceholder": "E-postadresse", + "ResetPasswordButton": "Tilbakestill passord" + }, + "LandingPage": { + "OnlineHeading": "For øyeblikket online", + "OnlineParagraph": "Medieserveren er online", + "PartiallyOnlineHeading": "Delvis online", + "PartiallyOnlineParagraph": "Medieserveren er delvis utilgjengelig.", + "MultipleServersUnavailable": "Det er {{serversUnavailable}} servere offline av totalt {{totalServers}}.", + "SingleServerUnavailable": "Det er {{serversUnavailable}} server offline av totalt {{totalServers}}.", + "OfflineHeading": "For øyeblikket offline", + "OfflineParagraph": "Medieserveren er for øyeblikket utilgjengelig.", + "CheckPageForUpdates": "Sjekk denne siden for kontinuerlige oppdateringer." + }, + "NavigationBar": { + "Discover": "Discover", + "Search": "Søk", + "Requests": "Forespørsler", + "UserManagement": "Brukeradministrasjon", + "Issues": "Mangler", + "Vote": "Stem", + "Donate": "Doner!", + "DonateLibraryMaintainer": "Doner til vedlikeholderen av biblioteket", + "DonateTooltip": "Dette er hvordan jeg overbevise min kone til å la meg bruke min fritid til å utvikle Ombi ;)", + "UpdateAvailableTooltip": "Ny opdatering venter!", + "Settings": "Innstillinger", + "Welcome": "Velkommen {{username}}", + "UpdateDetails": "Oppdater detaljer", + "Logout": "Logg av", + "OpenMobileApp": "Åpne mobilapp", + "RecentlyAdded": "Nylig lagt til", + "ChangeTheme": "Change Theme", + "Calendar": "Calendar", + "UserPreferences": "Preferences", + "FeatureSuggestion": "Feature Suggestion", + "FeatureSuggestionTooltip": "Have a great new idea? Suggest it here!", + "Filter": { + "Movies": "Filmer", + "TvShows": "TV serier", + "Music": "Musikk", + "People": "People" + }, + "MorningWelcome": "Good morning!", + "AfternoonWelcome": "Good afternoon!", + "EveningWelcome": "Good evening!" + }, + "Search": { + "Title": "Søk", + "Paragraph": "Vil du se noe som foreløpig ikke er tilgjengelig? Ikke noe problem, bare søk etter det nedenfor og be om det!", + "MoviesTab": "Filmer", + "TvTab": "TV serier", + "MusicTab": "Musikk", + "Suggestions": "Forslag", + "NoResults": "Beklager, vi fant ingen resultater!", + "DigitalDate": "Digital utgivelse: {{date}}", + "TheatricalRelease": "Kinopremiere: {{date}}", + "ViewOnPlex": "Spill av på Plex", + "ViewOnEmby": "Spill av på Emby", + "RequestAdded": "Forespørsel om {{title}} er lagt til", + "Similar": "Lignende", + "Refine": "Spesifiser", + "SearchBarPlaceholder": "Angi nøkkelord for søk", + "Movies": { + "PopularMovies": "Populære filmer", + "UpcomingMovies": "Kommende filmer", + "TopRatedMovies": "Kritikerroste filmer", + "NowPlayingMovies": "Aktuelle Filmer", + "HomePage": "Startside", + "Trailer": "Trailer" + }, + "TvShows": { + "Popular": "Populært", + "Trending": "På vei opp", + "MostWatched": "Mest sett", + "MostAnticipated": "Mest etterlengtede", + "Results": "Resultater", + "AirDate": "Sendingsdato:", + "AllSeasons": "Alle Sesonger", + "FirstSeason": "Første sesong", + "LatestSeason": "Siste sesong", + "Select": "Velg...", + "SubmitRequest": "Send forespørsel", + "Season": "Sesong: {{seasonNumber}}", + "SelectAllInSeason": "Velg alle i sesong {{seasonNumber}}" + } + }, + "Requests": { + "Title": "Forespørsler", + "Paragraph": "Nedenfor kan du se dine og alle andres forespørsler, du ser også status for nedlasting og godkjenning.", + "MoviesTab": "Filmer", + "ArtistName": "Artist", + "AlbumName": "Album Name", + "TvTab": "TV serier", + "MusicTab": "Musikk", + "RequestedBy": "Etterspurt av", + "Status": "Status", + "RequestStatus": "Status for forespørsel", + "Denied": " Avslått:", + "TheatricalRelease": "Kinopremiere: {{date}}", + "ReleaseDate": "Utgitt: {{date}}", + "TheatricalReleaseSort": "Kinopremiere", + "DigitalRelease": "Digital utgivelse: {{date}}", + "RequestDate": "Dato for forespørsel", + "QualityOverride": "Overstyr kvalitet:", + "RootFolderOverride": "Overstyring av rotmappe:", + "ChangeRootFolder": "Endre rotmappe", + "ChangeQualityProfile": "Endre kvalitetsprofil", + "MarkUnavailable": "Merk utilgjengelig", + "MarkAvailable": "Merk tilgjengelig", + "Remove": "Fjern", + "Deny": "Avslå", + "DenyReason": "Deny Reason", + "Season": "Sesong:", + "GridTitle": "Tittel", + "AirDate": "Sendedato", + "GridStatus": "Status", + "ReportIssue": "Rapportér en feil", + "Filter": "Filter", + "Sort": "Sorter", + "SeasonNumberHeading": "Sesong: {seasonNumber}", + "SortTitleAsc": "Tittel ▲", + "SortTitleDesc": "Tittel ▼", + "SortRequestDateAsc": "Dato for forespørsel ▲", + "SortRequestDateDesc": "Dato for forespørsel ▼", + "SortStatusAsc": "Status ▲", + "SortStatusDesc": "Status ▼", + "Remaining": { + "Quota": "{{remaining}}/{{total}} forespørsler igjen", + "NextDays": "En ny foresøprel vil bli lagt til om {{time}} dager", + "NextHours": "En ny foresøprel vil bli lagt til om {{time}} timer", + "NextMinutes": "En ny foresøprel vil bli lagt til om {{time}} minutter", + "NextMinute": "En ny foresøprel vil bli lagt til om {{time}} minutt" + }, + "AllRequests": "All Requests", + "PendingRequests": "Pending Requests", + "ProcessingRequests": "Processing Requests", + "AvailableRequests": "Available Requests", + "DeniedRequests": "Denied Requests", + "RequestsToDisplay": "Requests to display", + "RequestsTitle": "Tittel", + "Details": "Detaljer", + "Options": "Options", + "RequestPanel": { + "Delete": "Delete Request", + "Approve": "Approve Request", + "ChangeAvailability": "Mark Available" + } + }, + "Issues": { + "Title": "Mangler", + "PendingTitle": "Ventende løsninger", + "InProgressTitle": "Mangler under behandling", + "ResolvedTitle": "Løste mangler", + "ColumnTitle": "Tittel", + "Category": "Kategori", + "Status": "Status", + "Details": "Detaljer", + "Description": "Beskrivelse", + "NoComments": "Ingen kommentarer!", + "MarkInProgress": "Marker som pågår", + "MarkResolved": "Marker som løst", + "SendMessageButton": "Send", + "Subject": "Emne", + "Comments": "Kommentarer", + "WriteMessagePlaceholder": "Skriv meldingen din her...", + "ReportedBy": "Rapportert av", + "IssueDialog": { + "Title": "Report an issue", + "DescriptionPlaceholder": "Please describe the issue", + "TitlePlaceholder": "Short title of your issue", + "SelectCategory": "Select Category", + "IssueCreated": "Issue has been created" + }, + "Outstanding": "There are outstanding issues", + "ResolvedDate": "Resolved date", + "CreatedDate": "Raised on", + "MarkedAsResolved": "This issue has now been marked as resolved!", + "MarkedAsInProgress": "This issue has now been marked as in progress!", + "Delete": "Delete issue", + "DeletedIssue": "Issue has been deleted" + }, + "Filter": { + "ClearFilter": "Tøm filter", + "FilterHeaderAvailability": "Tilgjengelighet", + "FilterHeaderRequestStatus": "Status", + "Approved": "Godkjent", + "PendingApproval": "Venter på godkjenning" + }, + "UserManagment": { + "TvRemaining": "TV: {{remaining}}/{{total}} gjenstående", + "MovieRemaining": "Filmer: {{remaining}}/{{total}} gjenstående", + "MusicRemaining": "Musikk: {{remaining}}/{{total}} gjenstående", + "TvDue": "TV: {{date}}", + "MovieDue": "Film:{{date}}", + "MusicDue": "Musikk:{{date}}" + }, + "Votes": { + "CompletedVotesTab": "Stemt", + "VotesTab": "Stemmer som trengs" + }, + "MediaDetails": { + "Denied": "Avslått", + "RecommendationsTitle": "Recommendations", + "SimilarTitle": "Lignende", + "VideosTitle": "Videos", + "AlbumsTitle": "Albums", + "RequestAllAlbums": "Request All Albums", + "ClearSelection": "Clear Selection", + "RequestSelectedAlbums": "Request Selected Albums", + "ViewCollection": "View Collection", + "NotEnoughInfo": "Unfortunately there is not enough information about this show yet!", + "AdvancedOptions": "Advanced Options", + "QualityProfilesSelect": "Select A Quality Profile", + "RootFolderSelect": "Select A Root Folder", + "Status": "Status", + "Availability": "Tilgjengelighet", + "RequestStatus": "Request Status", + "Quality": "Quality", + "RootFolderOverride": "Overstyring av rotmappe", + "QualityOverride": "Overstyr kvalitet", + "Genres": "Genres", + "TheatricalRelease": "Kinopremiere", + "DigitalRelease": "Digital Release", + "UserScore": "User Score", + "Votes": "Votes", + "Runtime": "Runtime", + "Minutes": "{{runtime}} Minutes", + "Revenue": "Revenue", + "Budget": "Budget", + "Keywords": "Keywords/Tags", + "Casts": { + "CastTitle": "Cast" + }, + "EpisodeSelector": { + "AllSeasonsTooltip": "This will request every season for this show", + "FirstSeasonTooltip": "This will only request the First Season for this show", + "LatestSeasonTooltip": "This will only request the Latest Season for this show" + } + }, + "Discovery": { + "PopularTab": "Populært", + "TrendingTab": "På vei opp", + "UpcomingTab": "Upcoming", + "Movies": "Filmer", + "Combined": "Combined", + "Tv": "TV", + "CardDetails": { + "Availability": "Tilgjengelighet", + "Studio": "Studio", + "Network": "Network", + "UnknownNetwork": "Unknown", + "RequestStatus": "Request Status", + "Director": "Director", + "InCinemas": "In Cinemas", + "FirstAired": "First Aired", + "Writer": "Writer", + "ExecProducer": "Exec Producer" + } + }, + "UserPreferences": { + "Welcome": "Velkommen {{username}}!", + "OmbiLanguage": "Language", + "DarkMode": "Dark Mode" } - }, - "Issues": { - "Title": "Mangler", - "PendingTitle": "Ventende løsninger", - "InProgressTitle": "Mangler under behandling", - "ResolvedTitle": "Løste mangler", - "ColumnTitle": "Tittel", - "Category": "Kategori", - "Status": "Status", - "Details": "Detaljer", - "Description": "Beskrivelse", - "NoComments": "Ingen kommentarer!", - "MarkInProgress": "Marker som pågår", - "MarkResolved": "Marker som løst", - "SendMessageButton": "Send", - "Subject": "Emne", - "Comments": "Kommentarer", - "WriteMessagePlaceholder": "Skriv meldingen din her...", - "ReportedBy": "Rapportert av" - }, - "Filter": { - "ClearFilter": "Tøm filter", - "FilterHeaderAvailability": "Tilgjengelighet", - "FilterHeaderRequestStatus": "Status", - "Approved": "Godkjent", - "PendingApproval": "Venter på godkjenning" - }, - "UserManagment": { - "TvRemaining": "TV: {{remaining}}/{{total}} gjenstående", - "MovieRemaining": "Filmer: {{remaining}}/{{total}} gjenstående", - "MusicRemaining": "Musikk: {{remaining}}/{{total}} gjenstående", - "TvDue": "TV: {{date}}", - "MovieDue": "Film:{{date}}", - "MusicDue": "Musikk:{{date}}" - }, - "Votes": { - "CompletedVotesTab": "Stemt", - "VotesTab": "Stemmer som trengs" - } -} +} \ No newline at end of file diff --git a/src/Ombi/wwwroot/translations/pl.json b/src/Ombi/wwwroot/translations/pl.json index 1e495087d..ca8ed5410 100644 --- a/src/Ombi/wwwroot/translations/pl.json +++ b/src/Ombi/wwwroot/translations/pl.json @@ -1,186 +1,301 @@ { - "Login": { - "SignInButton": "Zaloguj się", - "UsernamePlaceholder": "Nazwa użytkownika", - "PasswordPlaceholder": "Hasło", - "RememberMe": "Zapamiętaj mnie", - "ForgottenPassword": "Nie pamiętasz hasła?", - "Errors": { - "IncorrectCredentials": "Nieprawidłowa nazwa użytkownika lub hasło" - } - }, - "Common": { - "ContinueButton": "Kontynuuj", - "Available": "Dostępne", - "PartiallyAvailable": "Częściowo dostępne", - "Monitored": "Monitorowane", - "NotAvailable": "Niedostępne", - "ProcessingRequest": "Przetwarzanie zgłoszenia", - "PendingApproval": "Oczekujące na zatwierdzenie", - "RequestDenied": "Zgłoszenie odrzucone", - "NotRequested": "Niezgłoszone", - "Requested": "Zgłoszone", - "Request": "Zgłoszenie", - "Denied": "Odrzucone", - "Approve": "Zatwierdź", - "PartlyAvailable": "Częściowo dostępne", - "Errors": { - "Validation": "Proszę sprawdzić wprowadzone wartości" - } - }, - "PasswordReset": { - "EmailAddressPlaceholder": "Adres e-mail", - "ResetPasswordButton": "Zresetuj hasło" - }, - "LandingPage": { - "OnlineHeading": "Aktualnie online", - "OnlineParagraph": "Serwer multimediów jest aktualnie online", - "PartiallyOnlineHeading": "Częściowo online", - "PartiallyOnlineParagraph": "Serwer multimediów jest częściowo online.", - "MultipleServersUnavailable": "{{serversUnavailable}} serwery(ów) spośród {{totalServers}} jest offline.", - "SingleServerUnavailable": "{{serversUnavailable}} serwer z {{totalServers}} jest w offline.", - "OfflineHeading": "Aktualnie offline", - "OfflineParagraph": "Serwer multimediów jest aktualnie offline.", - "CheckPageForUpdates": "Tutaj znajdziesz aktualizacje dotyczące tej strony." - }, - "NavigationBar": { - "Search": "Szukaj", - "Requests": "Zgłoszenia", - "UserManagement": "Zarządzanie użytkownikami", - "Issues": "Problemy", - "Vote": "Głosowania", - "Donate": "Wesprzyj!", - "DonateLibraryMaintainer": "Wesprzyj właściciela biblioteki", - "DonateTooltip": "Tak przekonuję moją żonę, aby pozwalała mi w wolnym czasie rozwijać Ombi ;)", - "UpdateAvailableTooltip": "Dostępna aktualizacja!", - "Settings": "Ustawienia", - "Welcome": "Witaj {{username}}", - "UpdateDetails": "Podaj szczegóły", - "Logout": "Wyloguj", - "OpenMobileApp": "Otwórz aplikację mobilną", - "RecentlyAdded": "Ostatnio dodane" - }, - "Search": { - "Title": "Szukaj", - "Paragraph": "Chcesz obejrzeć coś, co nie jest obecnie dostępne? Żaden problem! Po prostu wyszukaj poniżej i dodaj zgłoszenie!", - "MoviesTab": "Filmy", - "TvTab": "Seriale", - "MusicTab": "Muzyka", - "Suggestions": "Sugestie", - "NoResults": "Niestety nic nie znaleziono!", - "DigitalDate": "Wydanie cyfrowe: {{date}}", - "TheatricalRelease": "Premiera kinowa: {{date}}", - "ViewOnPlex": "Obejrzyj w Plex", - "ViewOnEmby": "Obejrzyj w Emby", - "RequestAdded": "Zgłoszenie dla {{title}} zostało pomyślnie dodane", - "Similar": "Podobne", - "Refine": "Zawęź", - "SearchBarPlaceholder": "Wpisz tutaj, aby wyszukać", - "Movies": { - "PopularMovies": "Popularne filmy", - "UpcomingMovies": "Nadchodzące filmy", - "TopRatedMovies": "Najwyżej oceniane filmy", - "NowPlayingMovies": "W kinach", - "HomePage": "Strona główna", - "Trailer": "Zwiastun" + "Login": { + "SignInButton": "Zaloguj się", + "UsernamePlaceholder": "Nazwa użytkownika", + "PasswordPlaceholder": "Hasło", + "RememberMe": "Zapamiętaj mnie", + "SignInWith": "Sign in with {{appName}}", + "SignInWithPlex": "Sign in with Plex", + "ForgottenPassword": "Nie pamiętasz hasła?", + "Errors": { + "IncorrectCredentials": "Nieprawidłowa nazwa użytkownika lub hasło" + } }, - "TvShows": { - "Popular": "Popularne", - "Trending": "Zyskujące popularność", - "MostWatched": "Najczęściej oglądane", - "MostAnticipated": "Najbardziej oczekiwane", - "Results": "Wyniki", - "AirDate": "Data emisji:", - "AllSeasons": "Wszystkie sezony", - "FirstSeason": "Pierwszy sezon", - "LatestSeason": "Najnowszy sezon", - "Select": "Wybierz…", - "SubmitRequest": "Dodaj zgłoszenie", - "Season": "Sezon: {{seasonNumber}}", - "SelectAllInSeason": "Wybierz wszystkie w sezonie {{seasonNumber}}" - } - }, - "Requests": { - "Title": "Zgłoszenia", - "Paragraph": "Poniżej znajdują się Twoje i wszystkie inne zgłoszenia, a także ich status akceptacji i pobierania.", - "MoviesTab": "Filmy", - "TvTab": "Seriale", - "MusicTab": "Muzyka", - "RequestedBy": "Zgłoszone przez:", - "Status": "Status:", - "RequestStatus": "Status zgłoszenia:", - "Denied": "Odrzucono:", - "TheatricalRelease": "Premiera kinowa: {{date}}", - "ReleaseDate": "Wydany: {{date}}", - "TheatricalReleaseSort": "Premiera kinowa", - "DigitalRelease": "Wydanie cyfrowe: {{date}}", - "RequestDate": "Data zgłoszenia:", - "QualityOverride": "Wymuszenie jakości:", - "RootFolderOverride": "Wymuszenie folderu głównego:", - "ChangeRootFolder": "Folder główny", - "ChangeQualityProfile": "Profil jakości", - "MarkUnavailable": "Oznacz jako niedostępne", - "MarkAvailable": "Oznacz jako dostępne", - "Remove": "Usuń", - "Deny": "Odrzuć", - "Season": "Sezon:", - "GridTitle": "Tytuł", - "AirDate": "Data emisji", - "GridStatus": "Status", - "ReportIssue": "Zgłoś problem", - "Filter": "Filtr", - "Sort": "Sortuj", - "SeasonNumberHeading": "Sezon: {seasonNumber}", - "SortTitleAsc": "Tytuł ▲", - "SortTitleDesc": "Tytuł ▼", - "SortRequestDateAsc": "Data zgłoszenia ▲", - "SortRequestDateDesc": "Data zgłoszenia ▼", - "SortStatusAsc": "Status ▲", - "SortStatusDesc": "Status ▼", - "Remaining": { - "Quota": "{{remaining}}/{{total}} pozostałych zgłoszeń", - "NextDays": "Kolejne zgłoszenie zostanie dodane za {{time}} dni", - "NextHours": "Kolejne zgłoszenie zostanie dodane za {{time}} godzin(y)", - "NextMinutes": "Kolejne zgłoszenie zostanie dodane za {{time}} minut(y)", - "NextMinute": "Kolejne zgłoszenie zostanie dodane za {{time}} minut(y)" + "Common": { + "ContinueButton": "Kontynuuj", + "Available": "Dostępne", + "PartiallyAvailable": "Częściowo dostępne", + "Monitored": "Monitorowane", + "NotAvailable": "Niedostępne", + "ProcessingRequest": "Przetwarzanie zgłoszenia", + "PendingApproval": "Oczekujące na zatwierdzenie", + "RequestDenied": "Zgłoszenie odrzucone", + "NotRequested": "Niezgłoszone", + "Requested": "Zgłoszone", + "Request": "Zgłoszenie", + "Denied": "Odrzucone", + "Approve": "Zatwierdź", + "PartlyAvailable": "Częściowo dostępne", + "ViewDetails": "Pokaż szczegóły", + "Errors": { + "Validation": "Proszę sprawdzić wprowadzone wartości" + }, + "Cancel": "Cancel", + "Submit": "Submit" + }, + "PasswordReset": { + "EmailAddressPlaceholder": "Adres e-mail", + "ResetPasswordButton": "Zresetuj hasło" + }, + "LandingPage": { + "OnlineHeading": "Aktualnie online", + "OnlineParagraph": "Serwer multimediów jest aktualnie online", + "PartiallyOnlineHeading": "Częściowo online", + "PartiallyOnlineParagraph": "Serwer multimediów jest częściowo online.", + "MultipleServersUnavailable": "{{serversUnavailable}} serwery(ów) spośród {{totalServers}} jest offline.", + "SingleServerUnavailable": "{{serversUnavailable}} serwer z {{totalServers}} jest w offline.", + "OfflineHeading": "Aktualnie offline", + "OfflineParagraph": "Serwer multimediów jest aktualnie offline.", + "CheckPageForUpdates": "Tutaj znajdziesz aktualizacje dotyczące tej strony." + }, + "NavigationBar": { + "Discover": "Odkryj", + "Search": "Szukaj", + "Requests": "Zgłoszenia", + "UserManagement": "Zarządzanie użytkownikami", + "Issues": "Problemy", + "Vote": "Głosowania", + "Donate": "Wesprzyj!", + "DonateLibraryMaintainer": "Wesprzyj właściciela biblioteki", + "DonateTooltip": "Tak przekonuję moją żonę, aby pozwalała mi w wolnym czasie rozwijać Ombi ;)", + "UpdateAvailableTooltip": "Dostępna aktualizacja!", + "Settings": "Ustawienia", + "Welcome": "Witaj {{username}}", + "UpdateDetails": "Podaj szczegóły", + "Logout": "Wyloguj", + "OpenMobileApp": "Otwórz aplikację mobilną", + "RecentlyAdded": "Ostatnio dodane", + "ChangeTheme": "Zmień motyw", + "Calendar": "Kalendarz", + "UserPreferences": "Preferencje", + "FeatureSuggestion": "Feature Suggestion", + "FeatureSuggestionTooltip": "Have a great new idea? Suggest it here!", + "Filter": { + "Movies": "Filmy", + "TvShows": "Programy TV", + "Music": "Muzyka", + "People": "People" + }, + "MorningWelcome": "Good morning!", + "AfternoonWelcome": "Good afternoon!", + "EveningWelcome": "Good evening!" + }, + "Search": { + "Title": "Szukaj", + "Paragraph": "Chcesz obejrzeć coś, co nie jest obecnie dostępne? Żaden problem! Po prostu wyszukaj poniżej i dodaj zgłoszenie!", + "MoviesTab": "Filmy", + "TvTab": "Seriale", + "MusicTab": "Muzyka", + "Suggestions": "Sugestie", + "NoResults": "Niestety nic nie znaleziono!", + "DigitalDate": "Wydanie cyfrowe: {{date}}", + "TheatricalRelease": "Premiera kinowa: {{date}}", + "ViewOnPlex": "Obejrzyj w Plex", + "ViewOnEmby": "Obejrzyj w Emby", + "RequestAdded": "Zgłoszenie dla {{title}} zostało pomyślnie dodane", + "Similar": "Podobne", + "Refine": "Zawęź", + "SearchBarPlaceholder": "Wpisz tutaj, aby wyszukać", + "Movies": { + "PopularMovies": "Popularne filmy", + "UpcomingMovies": "Nadchodzące filmy", + "TopRatedMovies": "Najwyżej oceniane filmy", + "NowPlayingMovies": "W kinach", + "HomePage": "Strona główna", + "Trailer": "Zwiastun" + }, + "TvShows": { + "Popular": "Popularne", + "Trending": "Zyskujące popularność", + "MostWatched": "Najczęściej oglądane", + "MostAnticipated": "Najbardziej oczekiwane", + "Results": "Wyniki", + "AirDate": "Data emisji:", + "AllSeasons": "Wszystkie sezony", + "FirstSeason": "Pierwszy sezon", + "LatestSeason": "Najnowszy sezon", + "Select": "Wybierz…", + "SubmitRequest": "Dodaj zgłoszenie", + "Season": "Sezon: {{seasonNumber}}", + "SelectAllInSeason": "Wybierz wszystkie w sezonie {{seasonNumber}}" + } + }, + "Requests": { + "Title": "Zgłoszenia", + "Paragraph": "Poniżej znajdują się Twoje i wszystkie inne zgłoszenia, a także ich status akceptacji i pobierania.", + "MoviesTab": "Filmy", + "ArtistName": "Artist", + "AlbumName": "Album Name", + "TvTab": "Seriale", + "MusicTab": "Muzyka", + "RequestedBy": "Zgłoszone przez", + "Status": "Stan", + "RequestStatus": "Status zgłoszenia", + "Denied": "Odrzucono:", + "TheatricalRelease": "Premiera kinowa: {{date}}", + "ReleaseDate": "Wydany: {{date}}", + "TheatricalReleaseSort": "Premiera kinowa", + "DigitalRelease": "Wydanie cyfrowe: {{date}}", + "RequestDate": "Data zgłoszenia", + "QualityOverride": "Wymuszenie jakości:", + "RootFolderOverride": "Wymuszenie folderu głównego:", + "ChangeRootFolder": "Folder główny", + "ChangeQualityProfile": "Profil jakości", + "MarkUnavailable": "Oznacz jako niedostępne", + "MarkAvailable": "Oznacz jako dostępne", + "Remove": "Usuń", + "Deny": "Odrzuć", + "DenyReason": "Powód odrzucenia", + "Season": "Sezon:", + "GridTitle": "Tytuł", + "AirDate": "Data emisji", + "GridStatus": "Status", + "ReportIssue": "Zgłoś problem", + "Filter": "Filtr", + "Sort": "Sortuj", + "SeasonNumberHeading": "Sezon: {seasonNumber}", + "SortTitleAsc": "Tytuł ▲", + "SortTitleDesc": "Tytuł ▼", + "SortRequestDateAsc": "Data zgłoszenia ▲", + "SortRequestDateDesc": "Data zgłoszenia ▼", + "SortStatusAsc": "Status ▲", + "SortStatusDesc": "Status ▼", + "Remaining": { + "Quota": "{{remaining}}/{{total}} pozostałych zgłoszeń", + "NextDays": "Kolejne zgłoszenie zostanie dodane za {{time}} dni", + "NextHours": "Kolejne zgłoszenie zostanie dodane za {{time}} godzin(y)", + "NextMinutes": "Kolejne zgłoszenie zostanie dodane za {{time}} minut(y)", + "NextMinute": "Kolejne zgłoszenie zostanie dodane za {{time}} minut(y)" + }, + "AllRequests": "All Requests", + "PendingRequests": "Pending Requests", + "ProcessingRequests": "Processing Requests", + "AvailableRequests": "Available Requests", + "DeniedRequests": "Denied Requests", + "RequestsToDisplay": "Requests to display", + "RequestsTitle": "Tytuł", + "Details": "Szczegóły", + "Options": "Options", + "RequestPanel": { + "Delete": "Delete Request", + "Approve": "Approve Request", + "ChangeAvailability": "Mark Available" + } + }, + "Issues": { + "Title": "Problemy", + "PendingTitle": "Oczekujące problemy", + "InProgressTitle": "Problemy w trakcie", + "ResolvedTitle": "Problemy rozwiązane", + "ColumnTitle": "Tytuł", + "Category": "Kategoria", + "Status": "Stan", + "Details": "Szczegóły", + "Description": "Opis", + "NoComments": "Brak komentarzy!", + "MarkInProgress": "Oznacz jako \"w trakcie\"", + "MarkResolved": "Oznacz jako rozwiązane", + "SendMessageButton": "Wyślij", + "Subject": "Temat", + "Comments": "Komentarze", + "WriteMessagePlaceholder": "Tutaj wpisz swoją wiadomość…", + "ReportedBy": "Zgłoszone przez", + "IssueDialog": { + "Title": "Report an issue", + "DescriptionPlaceholder": "Please describe the issue", + "TitlePlaceholder": "Short title of your issue", + "SelectCategory": "Select Category", + "IssueCreated": "Issue has been created" + }, + "Outstanding": "There are outstanding issues", + "ResolvedDate": "Resolved date", + "CreatedDate": "Raised on", + "MarkedAsResolved": "This issue has now been marked as resolved!", + "MarkedAsInProgress": "This issue has now been marked as in progress!", + "Delete": "Delete issue", + "DeletedIssue": "Issue has been deleted" + }, + "Filter": { + "ClearFilter": "Wyczyść filtr", + "FilterHeaderAvailability": "Dostępność", + "FilterHeaderRequestStatus": "Stan", + "Approved": "Zatwierdzone", + "PendingApproval": "Oczekujące na zatwierdzenie" + }, + "UserManagment": { + "TvRemaining": "Seriale: pozostało {{remaining}}/{{total}}", + "MovieRemaining": "Filmy: pozostało {{remaining}}/{{total}}", + "MusicRemaining": "Muzyka: pozostało {{remaining}}/{{total}}", + "TvDue": "Serial: {{date}}", + "MovieDue": "Film: {{date}}", + "MusicDue": "Muzyka: {{date}}" + }, + "Votes": { + "CompletedVotesTab": "Zagłosowano", + "VotesTab": "Potrzebne głosy" + }, + "MediaDetails": { + "Denied": "Odrzucone", + "RecommendationsTitle": "Rekomendacje", + "SimilarTitle": "Podobne", + "VideosTitle": "Wideo", + "AlbumsTitle": "Albums", + "RequestAllAlbums": "Request All Albums", + "ClearSelection": "Clear Selection", + "RequestSelectedAlbums": "Request Selected Albums", + "ViewCollection": "View Collection", + "NotEnoughInfo": "Unfortunately there is not enough information about this show yet!", + "AdvancedOptions": "Advanced Options", + "QualityProfilesSelect": "Select A Quality Profile", + "RootFolderSelect": "Select A Root Folder", + "Status": "Stan", + "Availability": "Dostępność", + "RequestStatus": "Status zgłoszenia", + "Quality": "Quality", + "RootFolderOverride": "Wymuszenie folderu głównego", + "QualityOverride": "Wymuszenie jakości", + "Genres": "Genres", + "TheatricalRelease": "Premiera kinowa", + "DigitalRelease": "Digital Release", + "UserScore": "User Score", + "Votes": "Votes", + "Runtime": "Runtime", + "Minutes": "{{runtime}} Minutes", + "Revenue": "Revenue", + "Budget": "Budget", + "Keywords": "Keywords/Tags", + "Casts": { + "CastTitle": "Obsada" + }, + "EpisodeSelector": { + "AllSeasonsTooltip": "Zgłoszenie obejmie wszystkie sezony tego serialu", + "FirstSeasonTooltip": "Zgłoszenie obejmie pierwszy sezon tego serialu", + "LatestSeasonTooltip": "Zgłoszenie obejmie najnowszy sezon tego serialu" + } + }, + "Discovery": { + "PopularTab": "Popularne", + "TrendingTab": "Zyskujące popularność", + "UpcomingTab": "Nadchodzące", + "Movies": "Filmy", + "Combined": "Combined", + "Tv": "TV", + "CardDetails": { + "Availability": "Dostępność", + "Studio": "Studio", + "Network": "Stacja", + "UnknownNetwork": "Nieznane", + "RequestStatus": "Status zgłoszenia", + "Director": "Reżyser", + "InCinemas": "W kinach", + "FirstAired": "Pierwsza emisja", + "Writer": "Scenarzysta", + "ExecProducer": "Producent wykonawczy" + } + }, + "UserPreferences": { + "Welcome": "Witaj {{username}}!", + "OmbiLanguage": "Language", + "DarkMode": "Dark Mode" } - }, - "Issues": { - "Title": "Problemy", - "PendingTitle": "Oczekujące problemy", - "InProgressTitle": "Problemy w trakcie", - "ResolvedTitle": "Problemy rozwiązane", - "ColumnTitle": "Tytuł", - "Category": "Kategoria", - "Status": "Status", - "Details": "Szczegóły", - "Description": "Opis", - "NoComments": "Brak komentarzy!", - "MarkInProgress": "Oznacz jako \"w trakcie\"", - "MarkResolved": "Oznacz jako rozwiązane", - "SendMessageButton": "Wyślij", - "Subject": "Temat", - "Comments": "Komentarze", - "WriteMessagePlaceholder": "Tutaj wpisz swoją wiadomość…", - "ReportedBy": "Zgłoszone przez" - }, - "Filter": { - "ClearFilter": "Wyczyść filtr", - "FilterHeaderAvailability": "Dostępność", - "FilterHeaderRequestStatus": "Status", - "Approved": "Zatwierdzone", - "PendingApproval": "Oczekujące na zatwierdzenie" - }, - "UserManagment": { - "TvRemaining": "Seriale: pozostało {{remaining}}/{{total}}", - "MovieRemaining": "Filmy: pozostało {{remaining}}/{{total}}", - "MusicRemaining": "Muzyka: pozostało {{remaining}}/{{total}}", - "TvDue": "Serial: {{date}}", - "MovieDue": "Film: {{date}}", - "MusicDue": "Muzyka: {{date}}" - }, - "Votes": { - "CompletedVotesTab": "Zagłosowano", - "VotesTab": "Potrzebne głosy" - } -} +} \ No newline at end of file diff --git a/src/Ombi/wwwroot/translations/pt.json b/src/Ombi/wwwroot/translations/pt.json index b0b3783ef..ddef26615 100644 --- a/src/Ombi/wwwroot/translations/pt.json +++ b/src/Ombi/wwwroot/translations/pt.json @@ -1,186 +1,301 @@ { - "Login": { - "SignInButton": "Iniciar sessão", - "UsernamePlaceholder": "Nome de usuário", - "PasswordPlaceholder": "Palavra-passe", - "RememberMe": "Guardar a minha autênticação", - "ForgottenPassword": "Esqueceu-se da sua palavra-passe?", - "Errors": { - "IncorrectCredentials": "Nome de usuário ou palavra-passe incorretos" - } - }, - "Common": { - "ContinueButton": "Continuar", - "Available": "Disponível", - "PartiallyAvailable": "Parcialmente Disponível", - "Monitored": "Monitorado", - "NotAvailable": "Não Disponível", - "ProcessingRequest": "A processar o pedido", - "PendingApproval": "Aprovação Pendente", - "RequestDenied": "Pedido negado", - "NotRequested": "Não pedido", - "Requested": "Pedido", - "Request": "Pedir", - "Denied": "Negado", - "Approve": "Aprovar", - "PartlyAvailable": "Parcialmente Disponível", - "Errors": { - "Validation": "Por favor, verifique os dados inseridos" - } - }, - "PasswordReset": { - "EmailAddressPlaceholder": "Endereço de e-mail", - "ResetPasswordButton": "Redefinir palavra-passe" - }, - "LandingPage": { - "OnlineHeading": "Online Agora", - "OnlineParagraph": "O servidor de media está actualmente online", - "PartiallyOnlineHeading": "Parcialmente Online", - "PartiallyOnlineParagraph": "O servidor de media está parcialmente online.", - "MultipleServersUnavailable": "Existem {{serversUnavailable}} servidores offline de um total de {{totalServers}}.", - "SingleServerUnavailable": "Existe {{serversUnavailable}} servidor offline de um total de {{totalServers}}.", - "OfflineHeading": "Actualmente Offline", - "OfflineParagraph": "O servidor de media está actualmente offline.", - "CheckPageForUpdates": "Verifique esta página para acompanhar as atualizações do site." - }, - "NavigationBar": { - "Search": "Pesquisar", - "Requests": "Pedidos", - "UserManagement": "Gestor de utilizadores", - "Issues": "Incidentes", - "Vote": "Votar", - "Donate": "Fazer uma doação!", - "DonateLibraryMaintainer": "Doar para o Dono da Biblioteca", - "DonateTooltip": "É assim que eu convenço a minha mulher a deixar-me passar o meu tempo livre a desenvolver o Ombi ;)", - "UpdateAvailableTooltip": "Atualização Disponível!", - "Settings": "Configurações", - "Welcome": "Bem-vindo, {{username}}", - "UpdateDetails": "Detalhes da Actualização", - "Logout": "Sair", - "OpenMobileApp": "Abrir app móvel", - "RecentlyAdded": "Recentemente adicionado" - }, - "Search": { - "Title": "Pesquisar", - "Paragraph": "Quer assistir a algo que não está disponível? Não há problema, basta procurar abaixo e solicitar!", - "MoviesTab": "Filmes", - "TvTab": "Séries", - "MusicTab": "Músicas", - "Suggestions": "Sugestões", - "NoResults": "Desculpe, não encontramos nenhum resultado!", - "DigitalDate": "Lançamento digital: {{date}}", - "TheatricalRelease": "Lançamento nos Cinemas: {{date}}", - "ViewOnPlex": "Assistir no Plex", - "ViewOnEmby": "Assistir no Emby", - "RequestAdded": "Pedido de {{title}} foi adicionado com sucesso", - "Similar": "Semelhante", - "Refine": "Filtro", - "SearchBarPlaceholder": "Digite aqui para pesquisar", - "Movies": { - "PopularMovies": "Filmes populares", - "UpcomingMovies": "Próximos filmes", - "TopRatedMovies": "Filmes mais votados", - "NowPlayingMovies": "Filmes em cartazes", - "HomePage": "Home Page", - "Trailer": "Trailer" + "Login": { + "SignInButton": "Iniciar sessão", + "UsernamePlaceholder": "Nome de Usuário", + "PasswordPlaceholder": "Palavra-passe", + "RememberMe": "Recorde-me", + "SignInWith": "Entre com {{appName}}", + "SignInWithPlex": "Iniciar sessão com Plex", + "ForgottenPassword": "Esqueceu sua senha?", + "Errors": { + "IncorrectCredentials": "Usuário ou senha incorretos" + } }, - "TvShows": { - "Popular": "Popular", - "Trending": "Mais populares", - "MostWatched": "Mais assistidos", - "MostAnticipated": "Mais esperados", - "Results": "Resultados", - "AirDate": "Data de exibição:", - "AllSeasons": "Todas as temporadas", - "FirstSeason": "Primeira temporada", - "LatestSeason": "Última temporada", - "Select": "Selecione...", - "SubmitRequest": "Enviar solicitação", - "Season": "Temporada: {{seasonNumber}}", - "SelectAllInSeason": "Selecione tudo na temporada {{seasonNumber}}" - } - }, - "Requests": { - "Title": "Solicitações", - "Paragraph": "Abaixo, você pode ver o seu e todos os outros pedidos, bem como o seu download e status de aprovação.", - "MoviesTab": "Filmes", - "TvTab": "Séries", - "MusicTab": "Músicas", - "RequestedBy": "Solicitado por:", - "Status": "Status:", - "RequestStatus": "Status da solicitação:", - "Denied": " Negados:", - "TheatricalRelease": "Lançamento nos Cinemas: {{date}}", - "ReleaseDate": "Lançado: {{date}}", - "TheatricalReleaseSort": "Lançamento nos Cinemas", - "DigitalRelease": "Lançamento digital: {{date}}", - "RequestDate": "Data da Solicitação:", - "QualityOverride": "Substituição de qualidade:", - "RootFolderOverride": "Substituição da pasta raiz:", - "ChangeRootFolder": "Pasta raiz", - "ChangeQualityProfile": "Perfil de qualidade", - "MarkUnavailable": "Marcar como Indisponível", - "MarkAvailable": "Marcar como Disponível", - "Remove": "Remover", - "Deny": "Negar", - "Season": "Temporada:", - "GridTitle": "Título", - "AirDate": "Data de exibição", - "GridStatus": "Status", - "ReportIssue": "Relatar Problema", - "Filter": "Filtro", - "Sort": "Ordenar por", - "SeasonNumberHeading": "Temporada: {seasonNumber}", - "SortTitleAsc": "Título ▲", - "SortTitleDesc": "Título ▼", - "SortRequestDateAsc": "Data da Solicitação", - "SortRequestDateDesc": "Data da Solicitação", - "SortStatusAsc": "Status ▲", - "SortStatusDesc": "Status ▼", - "Remaining": { - "Quota": "{{remaining}}/{{total}} solicitações restantes", - "NextDays": "Outro pedido será adicionado em {{time}} dias", - "NextHours": "Outro pedido será adicionado em {{time}} horas", - "NextMinutes": "Outro pedido será adicionado em {{time}} minutos", - "NextMinute": "Outro pedido será adicionado em {{time}} minuto" + "Common": { + "ContinueButton": "Continuar", + "Available": "Disponível", + "PartiallyAvailable": "Parcialmente Disponível", + "Monitored": "Monitored", + "NotAvailable": "Não disponível", + "ProcessingRequest": "Processando o pedido", + "PendingApproval": "Aprovação Pendente", + "RequestDenied": "Pedido Negado", + "NotRequested": "Não Solicitado", + "Requested": "Pedido", + "Request": "Solicitar", + "Denied": "Recusado", + "Approve": "Aprovar", + "PartlyAvailable": "Parcialmente Disponível", + "ViewDetails": "Ver detalhes", + "Errors": { + "Validation": "Por favor, verifique os valores inseridos" + }, + "Cancel": "Cancelar", + "Submit": "Submeter" + }, + "PasswordReset": { + "EmailAddressPlaceholder": "Email Address", + "ResetPasswordButton": "Nova senha" + }, + "LandingPage": { + "OnlineHeading": "Online no momento", + "OnlineParagraph": "The media server is currently online", + "PartiallyOnlineHeading": "Partially Online", + "PartiallyOnlineParagraph": "The media server is partially online.", + "MultipleServersUnavailable": "There are {{serversUnavailable}} servers offline out of {{totalServers}}.", + "SingleServerUnavailable": "There is {{serversUnavailable}} server offline out of {{totalServers}}.", + "OfflineHeading": "Currently Offline", + "OfflineParagraph": "The media server is currently offline.", + "CheckPageForUpdates": "Check this page for continuous site updates." + }, + "NavigationBar": { + "Discover": "Discover", + "Search": "Search", + "Requests": "Requests", + "UserManagement": "User Management", + "Issues": "Issues", + "Vote": "Vote", + "Donate": "Donate!", + "DonateLibraryMaintainer": "Donate to Library Maintainer", + "DonateTooltip": "This is how I convince my wife to let me spend my spare time developing Ombi 😁", + "UpdateAvailableTooltip": "Update Available!", + "Settings": "Settings", + "Welcome": "Welcome {{username}}", + "UpdateDetails": "Update Details", + "Logout": "Logout", + "OpenMobileApp": "Open Mobile App", + "RecentlyAdded": "Recently Added", + "ChangeTheme": "Change Theme", + "Calendar": "Calendar", + "UserPreferences": "Preferences", + "FeatureSuggestion": "Feature Suggestion", + "FeatureSuggestionTooltip": "Have a great new idea? Suggest it here!", + "Filter": { + "Movies": "Movies", + "TvShows": "TV Shows", + "Music": "Music", + "People": "People" + }, + "MorningWelcome": "Good morning!", + "AfternoonWelcome": "Good afternoon!", + "EveningWelcome": "Good evening!" + }, + "Search": { + "Title": "Search", + "Paragraph": "Want to watch something that is not currently available? No problem, just search for it below and request it!", + "MoviesTab": "Movies", + "TvTab": "TV Shows", + "MusicTab": "Music", + "Suggestions": "Suggestions", + "NoResults": "Sorry, we didn't find any results!", + "DigitalDate": "Digital Release: {{date}}", + "TheatricalRelease": "Theatrical Release: {{date}}", + "ViewOnPlex": "View On Plex", + "ViewOnEmby": "View On Emby", + "RequestAdded": "Request for {{title}} has been added successfully", + "Similar": "Similar", + "Refine": "Refine", + "SearchBarPlaceholder": "Type Here to Search", + "Movies": { + "PopularMovies": "Popular Movies", + "UpcomingMovies": "Upcoming Movies", + "TopRatedMovies": "Top Rated Movies", + "NowPlayingMovies": "Now Playing Movies", + "HomePage": "Home Page", + "Trailer": "Trailer" + }, + "TvShows": { + "Popular": "Popular", + "Trending": "Trending", + "MostWatched": "Most Watched", + "MostAnticipated": "Most Anticipated", + "Results": "Results", + "AirDate": "Air Date:", + "AllSeasons": "All Seasons", + "FirstSeason": "First Season", + "LatestSeason": "Latest Season", + "Select": "Select ...", + "SubmitRequest": "Submit Request", + "Season": "Season: {{seasonNumber}}", + "SelectAllInSeason": "Select All in Season {{seasonNumber}}" + } + }, + "Requests": { + "Title": "Requests", + "Paragraph": "Below you can see yours and all other requests, as well as their download and approval status.", + "MoviesTab": "Movies", + "ArtistName": "Artist", + "AlbumName": "Album Name", + "TvTab": "TV Shows", + "MusicTab": "Music", + "RequestedBy": "Requested By", + "Status": "Status", + "RequestStatus": "Request status", + "Denied": " Denied:", + "TheatricalRelease": "Theatrical Release: {{date}}", + "ReleaseDate": "Released: {{date}}", + "TheatricalReleaseSort": "Theatrical Release", + "DigitalRelease": "Digital Release: {{date}}", + "RequestDate": "Request Date", + "QualityOverride": "Quality Override:", + "RootFolderOverride": "Root Folder Override:", + "ChangeRootFolder": "Root Folder", + "ChangeQualityProfile": "Quality Profile", + "MarkUnavailable": "Mark Unavailable", + "MarkAvailable": "Mark Available", + "Remove": "Remove", + "Deny": "Deny", + "DenyReason": "Deny Reason", + "Season": "Season:", + "GridTitle": "Title", + "AirDate": "AirDate", + "GridStatus": "Status", + "ReportIssue": "Report Issue", + "Filter": "Filter", + "Sort": "Sort", + "SeasonNumberHeading": "Season: {seasonNumber}", + "SortTitleAsc": "Title ▲", + "SortTitleDesc": "Title ▼", + "SortRequestDateAsc": "Request Date ▲", + "SortRequestDateDesc": "Request Date ▼", + "SortStatusAsc": "Status ▲", + "SortStatusDesc": "Status ▼", + "Remaining": { + "Quota": "{{remaining}}/{{total}} requests remaining", + "NextDays": "Another request will be added in {{time}} days", + "NextHours": "Another request will be added in {{time}} hours", + "NextMinutes": "Another request will be added in {{time}} minutes", + "NextMinute": "Another request will be added in {{time}} minute" + }, + "AllRequests": "All Requests", + "PendingRequests": "Pending Requests", + "ProcessingRequests": "Processing Requests", + "AvailableRequests": "Available Requests", + "DeniedRequests": "Denied Requests", + "RequestsToDisplay": "Requests to display", + "RequestsTitle": "Title", + "Details": "Details", + "Options": "Options", + "RequestPanel": { + "Delete": "Delete Request", + "Approve": "Approve Request", + "ChangeAvailability": "Mark Available" + } + }, + "Issues": { + "Title": "Issues", + "PendingTitle": "Pending Issues", + "InProgressTitle": "In Progress Issues", + "ResolvedTitle": "Resolved Issues", + "ColumnTitle": "Title", + "Category": "Category", + "Status": "Status", + "Details": "Details", + "Description": "Description", + "NoComments": "No Comments!", + "MarkInProgress": "Mark In Progress", + "MarkResolved": "Mark Resolved", + "SendMessageButton": "Send", + "Subject": "Subject", + "Comments": "Comments", + "WriteMessagePlaceholder": "Write your message here...", + "ReportedBy": "Reported By", + "IssueDialog": { + "Title": "Report an issue", + "DescriptionPlaceholder": "Please describe the issue", + "TitlePlaceholder": "Short title of your issue", + "SelectCategory": "Select Category", + "IssueCreated": "Issue has been created" + }, + "Outstanding": "There are outstanding issues", + "ResolvedDate": "Resolved date", + "CreatedDate": "Raised on", + "MarkedAsResolved": "This issue has now been marked as resolved!", + "MarkedAsInProgress": "This issue has now been marked as in progress!", + "Delete": "Delete issue", + "DeletedIssue": "Issue has been deleted" + }, + "Filter": { + "ClearFilter": "Clear Filter", + "FilterHeaderAvailability": "Availability", + "FilterHeaderRequestStatus": "Status", + "Approved": "Approved", + "PendingApproval": "Pending Approval" + }, + "UserManagment": { + "TvRemaining": "TV: {{remaining}}/{{total}} remaining", + "MovieRemaining": "Movies: {{remaining}}/{{total}} remaining", + "MusicRemaining": "Music: {{remaining}}/{{total}} remaining", + "TvDue": "TV: {{date}}", + "MovieDue": "Movie: {{date}}", + "MusicDue": "Music: {{date}}" + }, + "Votes": { + "CompletedVotesTab": "Voted", + "VotesTab": "Votes Needed" + }, + "MediaDetails": { + "Denied": "Denied", + "RecommendationsTitle": "Recommendations", + "SimilarTitle": "Similar", + "VideosTitle": "Videos", + "AlbumsTitle": "Albums", + "RequestAllAlbums": "Request All Albums", + "ClearSelection": "Clear Selection", + "RequestSelectedAlbums": "Request Selected Albums", + "ViewCollection": "View Collection", + "NotEnoughInfo": "Unfortunately there is not enough information about this show yet!", + "AdvancedOptions": "Advanced Options", + "QualityProfilesSelect": "Select A Quality Profile", + "RootFolderSelect": "Select A Root Folder", + "Status": "Status", + "Availability": "Availability", + "RequestStatus": "Request Status", + "Quality": "Quality", + "RootFolderOverride": "Root Folder Override", + "QualityOverride": "Quality Override", + "Genres": "Genres", + "TheatricalRelease": "Theatrical Release", + "DigitalRelease": "Digital Release", + "UserScore": "User Score", + "Votes": "Votes", + "Runtime": "Runtime", + "Minutes": "{{runtime}} Minutes", + "Revenue": "Revenue", + "Budget": "Budget", + "Keywords": "Keywords/Tags", + "Casts": { + "CastTitle": "Cast" + }, + "EpisodeSelector": { + "AllSeasonsTooltip": "This will request every season for this show", + "FirstSeasonTooltip": "This will only request the First Season for this show", + "LatestSeasonTooltip": "This will only request the Latest Season for this show" + } + }, + "Discovery": { + "PopularTab": "Popular", + "TrendingTab": "Trending", + "UpcomingTab": "Upcoming", + "Movies": "Movies", + "Combined": "Combined", + "Tv": "TV", + "CardDetails": { + "Availability": "Availability", + "Studio": "Studio", + "Network": "Network", + "UnknownNetwork": "Unknown", + "RequestStatus": "Request Status", + "Director": "Director", + "InCinemas": "In Cinemas", + "FirstAired": "First Aired", + "Writer": "Writer", + "ExecProducer": "Exec Producer" + } + }, + "UserPreferences": { + "Welcome": "Welcome {{username}}!", + "OmbiLanguage": "Language", + "DarkMode": "Dark Mode" } - }, - "Issues": { - "Title": "Problemas", - "PendingTitle": "Problemas pendentes", - "InProgressTitle": "Resolvendo Problemas", - "ResolvedTitle": "Problemas Resolvidos", - "ColumnTitle": "Título", - "Category": "Categoria", - "Status": "Status", - "Details": "Detalhes", - "Description": "Descrição", - "NoComments": "Sem Comentários!", - "MarkInProgress": "Marcar como em andamento", - "MarkResolved": "Marcar como resolvido", - "SendMessageButton": "Enviar", - "Subject": "Assunto", - "Comments": "Comentários", - "WriteMessagePlaceholder": "Escreva sua mensagem aqui...", - "ReportedBy": "Reportado por" - }, - "Filter": { - "ClearFilter": "Limpar Filtro", - "FilterHeaderAvailability": "Disponibilidade", - "FilterHeaderRequestStatus": "Status", - "Approved": "Aprovado", - "PendingApproval": "Aprovação Pendente" - }, - "UserManagment": { - "TvRemaining": "Tv: {{remaining}}/{{total}} restantes", - "MovieRemaining": "Filmes: {{remaining}}/{{total}} restantes", - "MusicRemaining": "Música: {{remaining}}/{{total}} restantes", - "TvDue": "TV: {{date}}", - "MovieDue": "Filme: {{date}}", - "MusicDue": "Música: {{date}}" - }, - "Votes": { - "CompletedVotesTab": "Votado", - "VotesTab": "Votos necessários" - } -} +} \ No newline at end of file diff --git a/src/Ombi/wwwroot/translations/ru.json b/src/Ombi/wwwroot/translations/ru.json index 092689584..0d31783ee 100644 --- a/src/Ombi/wwwroot/translations/ru.json +++ b/src/Ombi/wwwroot/translations/ru.json @@ -1,186 +1,301 @@ { - "Login": { - "SignInButton": "Войти", - "UsernamePlaceholder": "Имя пользователя", - "PasswordPlaceholder": "Пароль", - "RememberMe": "Запомнить Меня", - "ForgottenPassword": "Забыли пароль?", - "Errors": { - "IncorrectCredentials": "Неверное имя пользователя или пароль" - } - }, - "Common": { - "ContinueButton": "Продолжить", - "Available": "Доступно", - "PartiallyAvailable": "Частично доступно", - "Monitored": "Мониторинг", - "NotAvailable": "Недоступно", - "ProcessingRequest": "Обработка запроса", - "PendingApproval": "В ожидании одобрения", - "RequestDenied": "Запрос отклонен", - "NotRequested": "Не запрошено", - "Requested": "Запрошено", - "Request": "Запросить", - "Denied": "Отказано", - "Approve": "Одобрить", - "PartlyAvailable": "Частично доступно", - "Errors": { - "Validation": "Пожалуйста, проверьте введенные значения" - } - }, - "PasswordReset": { - "EmailAddressPlaceholder": "Адрес эл. почты", - "ResetPasswordButton": "Сбросить пароль" - }, - "LandingPage": { - "OnlineHeading": "Сейчас в сети", - "OnlineParagraph": "Медиа-сервер в настоящее время в сети", - "PartiallyOnlineHeading": "Частично в сети", - "PartiallyOnlineParagraph": "Медиа-сервер частично в сети.", - "MultipleServersUnavailable": "В сети нет {{serversUnavailable}} серверов из {{totalServers}}.", - "SingleServerUnavailable": "В сети нет {{serversUnavailable}} серверов из {{totalServers}}.", - "OfflineHeading": "В настоящее время в offline", - "OfflineParagraph": "Медиа-сервер в настоящее время не в сети.", - "CheckPageForUpdates": "Проверьте эту страницу для получения последних новостей сайта." - }, - "NavigationBar": { - "Search": "Поиск", - "Requests": "Запросы", - "UserManagement": "Управление пользователями", - "Issues": "Проблемы", - "Vote": "Голосование", - "Donate": "Поддержать!", - "DonateLibraryMaintainer": "Поддержать библиотекаря", - "DonateTooltip": "Так я убедил свою жену позволить мне тратить своё свободное время на разработку Ombi ;)", - "UpdateAvailableTooltip": "Доступно обновление!", - "Settings": "Настройки", - "Welcome": "Добро пожаловать, {{username}}", - "UpdateDetails": "Обновить детали", - "Logout": "Выйти", - "OpenMobileApp": "Открыть моб. приложение", - "RecentlyAdded": "Недавно добавленные" - }, - "Search": { - "Title": "Поиск", - "Paragraph": "Хотите посмотреть что-то, чего нет в доступе? Нет проблем, просто вбейте название и запросите!", - "MoviesTab": "Фильмы", - "TvTab": "Сериалы", - "MusicTab": "Музыка", - "Suggestions": "Рекомендации", - "NoResults": "Извините, мы ничего не нашли!", - "DigitalDate": "Дигитальный релиз: {{date}}", - "TheatricalRelease": "Релиз в кинотеатрах: {{date}}", - "ViewOnPlex": "Смотреть в Plex", - "ViewOnEmby": "Смотреть в Emby", - "RequestAdded": "Запрос на {{title}} успешно добавлен", - "Similar": "Похожие", - "Refine": "Уточнить", - "SearchBarPlaceholder": "Поиск...", - "Movies": { - "PopularMovies": "Популярные фильмы", - "UpcomingMovies": "В скором времени", - "TopRatedMovies": "Фильмы с высоким рейтингом", - "NowPlayingMovies": "Сейчас в кинотеатрах", - "HomePage": "Главная страница", - "Trailer": "Трейлер" + "Login": { + "SignInButton": "Войти", + "UsernamePlaceholder": "Имя пользователя", + "PasswordPlaceholder": "Пароль", + "RememberMe": "Запомнить меня", + "SignInWith": "Sign in with {{appName}}", + "SignInWithPlex": "Sign in with Plex", + "ForgottenPassword": "Забыли пароль?", + "Errors": { + "IncorrectCredentials": "Неверное имя пользователя или пароль" + } }, - "TvShows": { - "Popular": "Популярное", - "Trending": "Сейчас смотрят", - "MostWatched": "Самые просматриваемые", - "MostAnticipated": "Самые ожидаемые", - "Results": "Результаты", - "AirDate": "Дата выхода:", - "AllSeasons": "Все сезоны", - "FirstSeason": "Первый сезон", - "LatestSeason": "Последний сезон", - "Select": "Выбрать...", - "SubmitRequest": "Подать запрос", - "Season": "Сезон: {{seasonNumber}}", - "SelectAllInSeason": "Выбрать все в сезоне {{seasonNumber}}" - } - }, - "Requests": { - "Title": "Запросы", - "Paragraph": "Ниже вы можете увидеть ваши и все другие запросы, а также их статус загрузки и одобрения.", - "MoviesTab": "Фильмы", - "TvTab": "Сериалы", - "MusicTab": "Музыка", - "RequestedBy": "Автор запроса:", - "Status": "Статус:", - "RequestStatus": "Статус запроса:", - "Denied": " Отказано:", - "TheatricalRelease": "Релиз в кинотеатрах: {{date}}", - "ReleaseDate": "Дата выхода: {{date}}", - "TheatricalReleaseSort": "Релиз в кинотеатрах", - "DigitalRelease": "Дигитальный релиз: {{date}}", - "RequestDate": "Дата запроса:", - "QualityOverride": "Переопределение качества:", - "RootFolderOverride": "Переопределение корневой папки:", - "ChangeRootFolder": "Корневая папка", - "ChangeQualityProfile": "Профиль качества", - "MarkUnavailable": "Отметить недоступным", - "MarkAvailable": "Отметить доступным", - "Remove": "Удалить", - "Deny": "Отклонить", - "Season": "Сезон:", - "GridTitle": "Название", - "AirDate": "Дата", - "GridStatus": "Статус", - "ReportIssue": "Сообщить о проблеме", - "Filter": "Фильтр", - "Sort": "Сортировать", - "SeasonNumberHeading": "Сезон: {seasonNumber}", - "SortTitleAsc": "Название ▲", - "SortTitleDesc": "Название ▼", - "SortRequestDateAsc": "Дата запроса ▲", - "SortRequestDateDesc": "Дата запроса ▼", - "SortStatusAsc": "Статус ▲", - "SortStatusDesc": "Статус ▼", - "Remaining": { - "Quota": "Осталось запросов: {{remaining}}/{{total}}", - "NextDays": "Следующий запрос будет добавлен через {{time}} дней", - "NextHours": "Следующий запрос будет добавлен через {{time}} часов", - "NextMinutes": "Следующий запрос будет добавлен через {{time}} минут", - "NextMinute": "Следующий запрос будет добавлен через {{time}} минуту" + "Common": { + "ContinueButton": "Продолжить", + "Available": "Доступно", + "PartiallyAvailable": "Частично доступно", + "Monitored": "Мониторинг", + "NotAvailable": "Недоступно", + "ProcessingRequest": "Обработка запроса", + "PendingApproval": "В ожидании одобрения", + "RequestDenied": "Запрос отклонен", + "NotRequested": "Не запрошено", + "Requested": "Запрошено", + "Request": "Запросить", + "Denied": "Отказано", + "Approve": "Одобрить", + "PartlyAvailable": "Частично доступно", + "ViewDetails": "View Details", + "Errors": { + "Validation": "Пожалуйста, проверьте введенные значения" + }, + "Cancel": "Cancel", + "Submit": "Submit" + }, + "PasswordReset": { + "EmailAddressPlaceholder": "Адрес эл. почты", + "ResetPasswordButton": "Сбросить пароль" + }, + "LandingPage": { + "OnlineHeading": "Сейчас в сети", + "OnlineParagraph": "Медиа-сервер в настоящее время в сети", + "PartiallyOnlineHeading": "Частично в сети", + "PartiallyOnlineParagraph": "Медиа-сервер частично в сети.", + "MultipleServersUnavailable": "В сети нет {{serversUnavailable}} серверов из {{totalServers}}.", + "SingleServerUnavailable": "В сети нет {{serversUnavailable}} серверов из {{totalServers}}.", + "OfflineHeading": "В настоящее время в offline", + "OfflineParagraph": "Медиа-сервер в настоящее время не в сети.", + "CheckPageForUpdates": "Проверьте эту страницу для получения последних новостей сайта." + }, + "NavigationBar": { + "Discover": "Discover", + "Search": "Поиск", + "Requests": "Запросы", + "UserManagement": "Управление пользователями", + "Issues": "Проблемы", + "Vote": "Голосование", + "Donate": "Поддержать!", + "DonateLibraryMaintainer": "Поддержать библиотекаря", + "DonateTooltip": "Так я убедил свою жену позволить мне тратить своё свободное время на разработку Ombi ;)", + "UpdateAvailableTooltip": "Доступно обновление!", + "Settings": "Настройки", + "Welcome": "Добро пожаловать, {{username}}", + "UpdateDetails": "Обновить детали", + "Logout": "Выйти", + "OpenMobileApp": "Открыть моб. приложение", + "RecentlyAdded": "Недавно добавленные", + "ChangeTheme": "Change Theme", + "Calendar": "Calendar", + "UserPreferences": "Preferences", + "FeatureSuggestion": "Feature Suggestion", + "FeatureSuggestionTooltip": "Have a great new idea? Suggest it here!", + "Filter": { + "Movies": "Фильмы", + "TvShows": "Сериалы", + "Music": "Музыка", + "People": "People" + }, + "MorningWelcome": "Good morning!", + "AfternoonWelcome": "Good afternoon!", + "EveningWelcome": "Good evening!" + }, + "Search": { + "Title": "Поиск", + "Paragraph": "Хотите посмотреть что-то, чего нет в доступе? Нет проблем, просто вбейте название и запросите!", + "MoviesTab": "Фильмы", + "TvTab": "Сериалы", + "MusicTab": "Музыка", + "Suggestions": "Рекомендации", + "NoResults": "Извините, мы ничего не нашли!", + "DigitalDate": "Дигитальный релиз: {{date}}", + "TheatricalRelease": "Релиз в кинотеатрах: {{date}}", + "ViewOnPlex": "Смотреть в Plex", + "ViewOnEmby": "Смотреть в Emby", + "RequestAdded": "Запрос на {{title}} успешно добавлен", + "Similar": "Похожие", + "Refine": "Уточнить", + "SearchBarPlaceholder": "Поиск...", + "Movies": { + "PopularMovies": "Популярные фильмы", + "UpcomingMovies": "В скором времени", + "TopRatedMovies": "Фильмы с высоким рейтингом", + "NowPlayingMovies": "Сейчас в кинотеатрах", + "HomePage": "Главная страница", + "Trailer": "Трейлер" + }, + "TvShows": { + "Popular": "Популярное", + "Trending": "Сейчас смотрят", + "MostWatched": "Самые просматриваемые", + "MostAnticipated": "Самые ожидаемые", + "Results": "Результаты", + "AirDate": "Дата выхода:", + "AllSeasons": "Все сезоны", + "FirstSeason": "Первый сезон", + "LatestSeason": "Последний сезон", + "Select": "Выбрать...", + "SubmitRequest": "Подать запрос", + "Season": "Сезон: {{seasonNumber}}", + "SelectAllInSeason": "Выбрать все в сезоне {{seasonNumber}}" + } + }, + "Requests": { + "Title": "Запросы", + "Paragraph": "Ниже вы можете увидеть ваши и все другие запросы, а также их статус загрузки и одобрения.", + "MoviesTab": "Фильмы", + "ArtistName": "Artist", + "AlbumName": "Album Name", + "TvTab": "Сериалы", + "MusicTab": "Музыка", + "RequestedBy": "Автор запроса", + "Status": "Статус", + "RequestStatus": "Статус запроса", + "Denied": " Отказано:", + "TheatricalRelease": "Релиз в кинотеатрах: {{date}}", + "ReleaseDate": "Дата выхода: {{date}}", + "TheatricalReleaseSort": "Релиз в кинотеатрах", + "DigitalRelease": "Дигитальный релиз: {{date}}", + "RequestDate": "Дата запроса", + "QualityOverride": "Переопределение качества:", + "RootFolderOverride": "Переопределение корневой папки:", + "ChangeRootFolder": "Корневая папка", + "ChangeQualityProfile": "Профиль качества", + "MarkUnavailable": "Отметить недоступным", + "MarkAvailable": "Отметить доступным", + "Remove": "Удалить", + "Deny": "Отклонить", + "DenyReason": "Deny Reason", + "Season": "Сезон:", + "GridTitle": "Название", + "AirDate": "Дата", + "GridStatus": "Статус", + "ReportIssue": "Сообщить о проблеме", + "Filter": "Фильтр", + "Sort": "Сортировать", + "SeasonNumberHeading": "Сезон: {seasonNumber}", + "SortTitleAsc": "Название ▲", + "SortTitleDesc": "Название ▼", + "SortRequestDateAsc": "Дата запроса ▲", + "SortRequestDateDesc": "Дата запроса ▼", + "SortStatusAsc": "Статус ▲", + "SortStatusDesc": "Статус ▼", + "Remaining": { + "Quota": "Осталось запросов: {{remaining}}/{{total}}", + "NextDays": "Следующий запрос будет добавлен через {{time}} дней", + "NextHours": "Следующий запрос будет добавлен через {{time}} часов", + "NextMinutes": "Следующий запрос будет добавлен через {{time}} минут", + "NextMinute": "Следующий запрос будет добавлен через {{time}} минуту" + }, + "AllRequests": "All Requests", + "PendingRequests": "Pending Requests", + "ProcessingRequests": "Processing Requests", + "AvailableRequests": "Available Requests", + "DeniedRequests": "Denied Requests", + "RequestsToDisplay": "Requests to display", + "RequestsTitle": "Название", + "Details": "Подробная информация", + "Options": "Options", + "RequestPanel": { + "Delete": "Delete Request", + "Approve": "Approve Request", + "ChangeAvailability": "Mark Available" + } + }, + "Issues": { + "Title": "Проблемы", + "PendingTitle": "Проблемы в ожидании", + "InProgressTitle": "Проблемы в процессе", + "ResolvedTitle": "Решенные проблемы", + "ColumnTitle": "Название", + "Category": "Категория", + "Status": "Статус", + "Details": "Подробная информация", + "Description": "Описание", + "NoComments": "Нет комментариев!", + "MarkInProgress": "Отметить в процессе", + "MarkResolved": "Отметить как решенное", + "SendMessageButton": "Отправить", + "Subject": "Тема", + "Comments": "Комментарии", + "WriteMessagePlaceholder": "Введите текст сообщения здесь...", + "ReportedBy": "Жалоба поступила от", + "IssueDialog": { + "Title": "Report an issue", + "DescriptionPlaceholder": "Please describe the issue", + "TitlePlaceholder": "Short title of your issue", + "SelectCategory": "Select Category", + "IssueCreated": "Issue has been created" + }, + "Outstanding": "There are outstanding issues", + "ResolvedDate": "Resolved date", + "CreatedDate": "Raised on", + "MarkedAsResolved": "This issue has now been marked as resolved!", + "MarkedAsInProgress": "This issue has now been marked as in progress!", + "Delete": "Delete issue", + "DeletedIssue": "Issue has been deleted" + }, + "Filter": { + "ClearFilter": "Сбросить фильтр", + "FilterHeaderAvailability": "Доступность", + "FilterHeaderRequestStatus": "Статус", + "Approved": "Одобрено", + "PendingApproval": "В ожидании одобрения" + }, + "UserManagment": { + "TvRemaining": "Сериалы: {{remaining}}/{{total}} осталось", + "MovieRemaining": "Фильмы: {{remaining}}/{{total}} осталось", + "MusicRemaining": "Музыка: {{remaining}}/{{total}} осталось", + "TvDue": "Сериалы: {{date}}", + "MovieDue": "Фильм: {{date}}", + "MusicDue": "Музыка: {{date}}" + }, + "Votes": { + "CompletedVotesTab": "Проголосовано", + "VotesTab": "Необходимы голоса" + }, + "MediaDetails": { + "Denied": "Отказано", + "RecommendationsTitle": "Recommendations", + "SimilarTitle": "Похожие", + "VideosTitle": "Videos", + "AlbumsTitle": "Albums", + "RequestAllAlbums": "Request All Albums", + "ClearSelection": "Clear Selection", + "RequestSelectedAlbums": "Request Selected Albums", + "ViewCollection": "View Collection", + "NotEnoughInfo": "Unfortunately there is not enough information about this show yet!", + "AdvancedOptions": "Advanced Options", + "QualityProfilesSelect": "Select A Quality Profile", + "RootFolderSelect": "Select A Root Folder", + "Status": "Статус", + "Availability": "Доступность", + "RequestStatus": "Request Status", + "Quality": "Quality", + "RootFolderOverride": "Переопределение корневой папки", + "QualityOverride": "Переопределение качества", + "Genres": "Genres", + "TheatricalRelease": "Релиз в кинотеатрах", + "DigitalRelease": "Digital Release", + "UserScore": "User Score", + "Votes": "Votes", + "Runtime": "Runtime", + "Minutes": "{{runtime}} Minutes", + "Revenue": "Revenue", + "Budget": "Budget", + "Keywords": "Keywords/Tags", + "Casts": { + "CastTitle": "Cast" + }, + "EpisodeSelector": { + "AllSeasonsTooltip": "This will request every season for this show", + "FirstSeasonTooltip": "This will only request the First Season for this show", + "LatestSeasonTooltip": "This will only request the Latest Season for this show" + } + }, + "Discovery": { + "PopularTab": "Популярное", + "TrendingTab": "Сейчас смотрят", + "UpcomingTab": "Upcoming", + "Movies": "Фильмы", + "Combined": "Combined", + "Tv": "TV", + "CardDetails": { + "Availability": "Доступность", + "Studio": "Studio", + "Network": "Network", + "UnknownNetwork": "Unknown", + "RequestStatus": "Request Status", + "Director": "Director", + "InCinemas": "In Cinemas", + "FirstAired": "First Aired", + "Writer": "Writer", + "ExecProducer": "Exec Producer" + } + }, + "UserPreferences": { + "Welcome": "Добро пожаловать, {{username}}!", + "OmbiLanguage": "Language", + "DarkMode": "Dark Mode" } - }, - "Issues": { - "Title": "Проблемы", - "PendingTitle": "Проблемы в ожидании", - "InProgressTitle": "Проблемы в процессе", - "ResolvedTitle": "Решенные проблемы", - "ColumnTitle": "Название", - "Category": "Категория", - "Status": "Статус", - "Details": "Подробная информация", - "Description": "Описание", - "NoComments": "Нет комментариев!", - "MarkInProgress": "Отметить в процессе", - "MarkResolved": "Отметить как решенное", - "SendMessageButton": "Отправить", - "Subject": "Тема", - "Comments": "Комментарии", - "WriteMessagePlaceholder": "Введите текст сообщения здесь...", - "ReportedBy": "Жалоба поступила от" - }, - "Filter": { - "ClearFilter": "Сбросить фильтр", - "FilterHeaderAvailability": "Доступность", - "FilterHeaderRequestStatus": "Статус", - "Approved": "Одобрено", - "PendingApproval": "В ожидании одобрения" - }, - "UserManagment": { - "TvRemaining": "Сериалы: {{remaining}}/{{total}} осталось", - "MovieRemaining": "Фильмы: {{remaining}}/{{total}} осталось", - "MusicRemaining": "Музыка: {{remaining}}/{{total}} осталось", - "TvDue": "Сериалы: {{date}}", - "MovieDue": "Фильм: {{date}}", - "MusicDue": "Музыка: {{date}}" - }, - "Votes": { - "CompletedVotesTab": "Проголосовано", - "VotesTab": "Необходимы голоса" - } -} +} \ No newline at end of file diff --git a/src/Ombi/wwwroot/translations/sk.json b/src/Ombi/wwwroot/translations/sk.json index d7c3e376a..3ab7f6257 100644 --- a/src/Ombi/wwwroot/translations/sk.json +++ b/src/Ombi/wwwroot/translations/sk.json @@ -1,186 +1,301 @@ { - "Login": { - "SignInButton": "Prihláste sa", - "UsernamePlaceholder": "Užívateľské meno", - "PasswordPlaceholder": "Heslo", - "RememberMe": "Zapamätať prihlásenie", - "ForgottenPassword": "Zabudli ste heslo?", - "Errors": { - "IncorrectCredentials": "Nesprávne meno alebo heslo" - } - }, - "Common": { - "ContinueButton": "Pokračovať", - "Available": "Dostupné", - "PartiallyAvailable": "Čiastočne dostupné", - "Monitored": "Sledované", - "NotAvailable": "Nie je k dispozícii", - "ProcessingRequest": "Spracovávanie požiadavky", - "PendingApproval": "Čaká na schválenie", - "RequestDenied": "Požiadavka zamietnutá", - "NotRequested": "Nepožiadané", - "Requested": "Požiadané", - "Request": "Požiadať", - "Denied": "Zamietnuté", - "Approve": "Schválené", - "PartlyAvailable": "Čiastočne dostupné", - "Errors": { - "Validation": "Skontrolujte zadaný obsah" - } - }, - "PasswordReset": { - "EmailAddressPlaceholder": "Emailová adresa", - "ResetPasswordButton": "Nastaviť nové heslo" - }, - "LandingPage": { - "OnlineHeading": "Momentálne online", - "OnlineParagraph": "Mediálny server je momentálne online", - "PartiallyOnlineHeading": "Čiastočne online", - "PartiallyOnlineParagraph": "Mediálny server je momentálne online.", - "MultipleServersUnavailable": "Momntálne je {{serversUnavailable}} serverov offline z {{totalServers}}.", - "SingleServerUnavailable": "Momntálne je {{serversUnavailable}} server offline z {{totalServers}}.", - "OfflineHeading": "Momentálne offline", - "OfflineParagraph": "Mediálny server je momentálne offline.", - "CheckPageForUpdates": "Prezrite túto stránku pre aktualizácie." - }, - "NavigationBar": { - "Search": "Hľadať", - "Requests": "Požiadavky", - "UserManagement": "Správa užívateľov", - "Issues": "Problémy", - "Vote": "Hlasovať", - "Donate": "Prispieť!", - "DonateLibraryMaintainer": "Darovať správcovi knižnice", - "DonateTooltip": "Takto som presvedčil svoju manželku, aby mi umožnila tráviť svoj voľný čas vývojom Ombi ;)", - "UpdateAvailableTooltip": "K dispozícii je aktualizácia!", - "Settings": "Nastavenie", - "Welcome": "Vitaj {{username}}", - "UpdateDetails": "Aktualizovať údaje", - "Logout": "Odhlásiť sa", - "OpenMobileApp": "Otvoriť mobilnú aplikáciu", - "RecentlyAdded": "Nedávno pridané" - }, - "Search": { - "Title": "Hľadať", - "Paragraph": "Chcete sledovať niečo, čo v súčasnosti nie je k dispozícii? Žiadny problém. Vyhľadajte to nižšie a požiadajte o to!", - "MoviesTab": "Filmy", - "TvTab": "Seriály", - "MusicTab": "Hudba", - "Suggestions": "Návrhy", - "NoResults": "Ľutujeme, nenašli sme žiadne výsledky!", - "DigitalDate": "Online vydanie: {{date}}", - "TheatricalRelease": "Kino vydanie: {{date}}", - "ViewOnPlex": "Zobraziť na Plex", - "ViewOnEmby": "Zobraziť na Emby", - "RequestAdded": "Žiadosť o {{title}} bola úspešne pridaná", - "Similar": "Podobné", - "Refine": "Filtrovať", - "SearchBarPlaceholder": "Tu zadajte pre vyhľadávanie", - "Movies": { - "PopularMovies": "Populárne filmy", - "UpcomingMovies": "Očakávané filmy", - "TopRatedMovies": "Najlepšie hodnotené filmy", - "NowPlayingMovies": "Teraz prehrávané filmy", - "HomePage": "Úvodná stránka", - "Trailer": "Upútavka" + "Login": { + "SignInButton": "Prihláste sa", + "UsernamePlaceholder": "Užívateľské meno", + "PasswordPlaceholder": "Heslo", + "RememberMe": "Zapamätať prihlásenie", + "SignInWith": "Sign in with {{appName}}", + "SignInWithPlex": "Sign in with Plex", + "ForgottenPassword": "Zabudli ste heslo?", + "Errors": { + "IncorrectCredentials": "Nesprávne meno alebo heslo" + } }, - "TvShows": { - "Popular": "Populárne", - "Trending": "Trendy", - "MostWatched": "Najsledovanejšie", - "MostAnticipated": "Najočakávanejšie", - "Results": "Výsledky", - "AirDate": "Dátum vysielania:", - "AllSeasons": "Všetky série", - "FirstSeason": "Prvá séria", - "LatestSeason": "Posledná séria", - "Select": "Vybrať ...", - "SubmitRequest": "Poslať žiadosť", - "Season": "Séria: {{seasonNumber}}", - "SelectAllInSeason": "Vybrať všetko v danej sérii {{seasonNumber}}" - } - }, - "Requests": { - "Title": "Požiadavky", - "Paragraph": "Nižšie nájdete svoje a všetky ďalšie žiadosti, ako aj stav ich sťahovania a schvaľovania.", - "MoviesTab": "Filmy", - "TvTab": "Seriály", - "MusicTab": "Hudba", - "RequestedBy": "Vyžiadané od:", - "Status": "Stav:", - "RequestStatus": "Stav požiadavky:", - "Denied": " Zamietnuté:", - "TheatricalRelease": "Kino vydanie: {{date}}", - "ReleaseDate": "Vydané: {{date}}", - "TheatricalReleaseSort": "Kino vydanie", - "DigitalRelease": "Online vydanie: {{date}}", - "RequestDate": "Dátum požiadavky:", - "QualityOverride": "Prepísanie kvality:", - "RootFolderOverride": "Prepísanie Root priečinku:", - "ChangeRootFolder": "Koreňový priečinok", - "ChangeQualityProfile": "Profil kvality", - "MarkUnavailable": "Označiť nedostupné", - "MarkAvailable": "Označiť dostupné", - "Remove": "Odstrániť", - "Deny": "Odmietnuť", - "Season": "Séria:", - "GridTitle": "Názov", - "AirDate": "Dátum vysielania", - "GridStatus": "Stav", - "ReportIssue": "Nahlásiť problém", - "Filter": "Filter", - "Sort": "Triediť", - "SeasonNumberHeading": "Séria: {seasonNumber}", - "SortTitleAsc": "Názov ▲", - "SortTitleDesc": "Názov ▼", - "SortRequestDateAsc": "Dátum požiadavky ▲", - "SortRequestDateDesc": "Dátum požiadavky ▼", - "SortStatusAsc": "Stav ▲", - "SortStatusDesc": "Stav ▼", - "Remaining": { - "Quota": "{{remaining}}/{{total}} zostávajúce žiadosti", - "NextDays": "Ďalšia žiadosť bude pridaná o {{time}} dní", - "NextHours": "Ďalšia žiadosť bude pridaná o {{time}} hodín", - "NextMinutes": "Ďalšia žiadosť bude pridaná o {{time}} minút", - "NextMinute": "Ďalšia žiadosť bude pridaná o {{time}} minútu" + "Common": { + "ContinueButton": "Pokračovať", + "Available": "Dostupné", + "PartiallyAvailable": "Čiastočne dostupné", + "Monitored": "Sledované", + "NotAvailable": "Nie je k dispozícii", + "ProcessingRequest": "Spracovávanie požiadavky", + "PendingApproval": "Čaká na schválenie", + "RequestDenied": "Požiadavka zamietnutá", + "NotRequested": "Nepožiadané", + "Requested": "Požiadané", + "Request": "Požiadať", + "Denied": "Zamietnuté", + "Approve": "Schválené", + "PartlyAvailable": "Čiastočne dostupné", + "ViewDetails": "View Details", + "Errors": { + "Validation": "Skontrolujte zadaný obsah" + }, + "Cancel": "Cancel", + "Submit": "Submit" + }, + "PasswordReset": { + "EmailAddressPlaceholder": "Emailová adresa", + "ResetPasswordButton": "Nastaviť nové heslo" + }, + "LandingPage": { + "OnlineHeading": "Momentálne online", + "OnlineParagraph": "Mediálny server je momentálne online", + "PartiallyOnlineHeading": "Čiastočne online", + "PartiallyOnlineParagraph": "Mediálny server je momentálne online.", + "MultipleServersUnavailable": "Momntálne je {{serversUnavailable}} serverov offline z {{totalServers}}.", + "SingleServerUnavailable": "Momntálne je {{serversUnavailable}} server offline z {{totalServers}}.", + "OfflineHeading": "Momentálne offline", + "OfflineParagraph": "Mediálny server je momentálne offline.", + "CheckPageForUpdates": "Prezrite túto stránku pre aktualizácie." + }, + "NavigationBar": { + "Discover": "Discover", + "Search": "Hľadať", + "Requests": "Požiadavky", + "UserManagement": "Správa užívateľov", + "Issues": "Problémy", + "Vote": "Hlasovať", + "Donate": "Prispieť!", + "DonateLibraryMaintainer": "Darovať správcovi knižnice", + "DonateTooltip": "Takto som presvedčil svoju manželku, aby mi umožnila tráviť svoj voľný čas vývojom Ombi ;)", + "UpdateAvailableTooltip": "K dispozícii je aktualizácia!", + "Settings": "Nastavenie", + "Welcome": "Vitaj {{username}}", + "UpdateDetails": "Aktualizovať údaje", + "Logout": "Odhlásiť sa", + "OpenMobileApp": "Otvoriť mobilnú aplikáciu", + "RecentlyAdded": "Nedávno pridané", + "ChangeTheme": "Change Theme", + "Calendar": "Calendar", + "UserPreferences": "Preferences", + "FeatureSuggestion": "Feature Suggestion", + "FeatureSuggestionTooltip": "Have a great new idea? Suggest it here!", + "Filter": { + "Movies": "Filmy", + "TvShows": "Seriály", + "Music": "Hudba", + "People": "People" + }, + "MorningWelcome": "Good morning!", + "AfternoonWelcome": "Good afternoon!", + "EveningWelcome": "Good evening!" + }, + "Search": { + "Title": "Hľadať", + "Paragraph": "Chcete sledovať niečo, čo v súčasnosti nie je k dispozícii? Žiadny problém. Vyhľadajte to nižšie a požiadajte o to!", + "MoviesTab": "Filmy", + "TvTab": "Seriály", + "MusicTab": "Hudba", + "Suggestions": "Návrhy", + "NoResults": "Ľutujeme, nenašli sme žiadne výsledky!", + "DigitalDate": "Online vydanie: {{date}}", + "TheatricalRelease": "Kino vydanie: {{date}}", + "ViewOnPlex": "Zobraziť na Plex", + "ViewOnEmby": "Zobraziť na Emby", + "RequestAdded": "Žiadosť o {{title}} bola úspešne pridaná", + "Similar": "Podobné", + "Refine": "Filtrovať", + "SearchBarPlaceholder": "Tu zadajte pre vyhľadávanie", + "Movies": { + "PopularMovies": "Populárne filmy", + "UpcomingMovies": "Očakávané filmy", + "TopRatedMovies": "Najlepšie hodnotené filmy", + "NowPlayingMovies": "Teraz prehrávané filmy", + "HomePage": "Úvodná stránka", + "Trailer": "Upútavka" + }, + "TvShows": { + "Popular": "Populárne", + "Trending": "Trendy", + "MostWatched": "Najsledovanejšie", + "MostAnticipated": "Najočakávanejšie", + "Results": "Výsledky", + "AirDate": "Dátum vysielania:", + "AllSeasons": "Všetky série", + "FirstSeason": "Prvá séria", + "LatestSeason": "Posledná séria", + "Select": "Vybrať ...", + "SubmitRequest": "Poslať žiadosť", + "Season": "Séria: {{seasonNumber}}", + "SelectAllInSeason": "Vybrať všetko v danej sérii {{seasonNumber}}" + } + }, + "Requests": { + "Title": "Požiadavky", + "Paragraph": "Nižšie nájdete svoje a všetky ďalšie žiadosti, ako aj stav ich sťahovania a schvaľovania.", + "MoviesTab": "Filmy", + "ArtistName": "Artist", + "AlbumName": "Album Name", + "TvTab": "Seriály", + "MusicTab": "Hudba", + "RequestedBy": "Vyžiadané od", + "Status": "Stav", + "RequestStatus": "Stav požiadavky", + "Denied": " Zamietnuté:", + "TheatricalRelease": "Kino vydanie: {{date}}", + "ReleaseDate": "Vydané: {{date}}", + "TheatricalReleaseSort": "Kino vydanie", + "DigitalRelease": "Online vydanie: {{date}}", + "RequestDate": "Dátum požiadavky", + "QualityOverride": "Prepísanie kvality:", + "RootFolderOverride": "Prepísanie Root priečinku:", + "ChangeRootFolder": "Koreňový priečinok", + "ChangeQualityProfile": "Profil kvality", + "MarkUnavailable": "Označiť nedostupné", + "MarkAvailable": "Označiť dostupné", + "Remove": "Odstrániť", + "Deny": "Odmietnuť", + "DenyReason": "Deny Reason", + "Season": "Séria:", + "GridTitle": "Názov", + "AirDate": "Dátum vysielania", + "GridStatus": "Stav", + "ReportIssue": "Nahlásiť problém", + "Filter": "Filter", + "Sort": "Triediť", + "SeasonNumberHeading": "Séria: {seasonNumber}", + "SortTitleAsc": "Názov ▲", + "SortTitleDesc": "Názov ▼", + "SortRequestDateAsc": "Dátum požiadavky ▲", + "SortRequestDateDesc": "Dátum požiadavky ▼", + "SortStatusAsc": "Stav ▲", + "SortStatusDesc": "Stav ▼", + "Remaining": { + "Quota": "{{remaining}}/{{total}} zostávajúce žiadosti", + "NextDays": "Ďalšia žiadosť bude pridaná o {{time}} dní", + "NextHours": "Ďalšia žiadosť bude pridaná o {{time}} hodín", + "NextMinutes": "Ďalšia žiadosť bude pridaná o {{time}} minút", + "NextMinute": "Ďalšia žiadosť bude pridaná o {{time}} minútu" + }, + "AllRequests": "All Requests", + "PendingRequests": "Pending Requests", + "ProcessingRequests": "Processing Requests", + "AvailableRequests": "Available Requests", + "DeniedRequests": "Denied Requests", + "RequestsToDisplay": "Requests to display", + "RequestsTitle": "Názov", + "Details": "Podrobnosti", + "Options": "Options", + "RequestPanel": { + "Delete": "Delete Request", + "Approve": "Approve Request", + "ChangeAvailability": "Mark Available" + } + }, + "Issues": { + "Title": "Problémy", + "PendingTitle": "Nevyriešené problémy", + "InProgressTitle": "Riešené problémy", + "ResolvedTitle": "Vyiešené problémy", + "ColumnTitle": "Názov", + "Category": "Kategória", + "Status": "Stav", + "Details": "Podrobnosti", + "Description": "Popis", + "NoComments": "Žiadne komentáre!", + "MarkInProgress": "Označiť ako prebiehajúce", + "MarkResolved": "Označiť ako vyriešené", + "SendMessageButton": "Odoslať", + "Subject": "Predmet", + "Comments": "Komentáre", + "WriteMessagePlaceholder": "Napíšte správu sem...", + "ReportedBy": "Nahlásené od", + "IssueDialog": { + "Title": "Report an issue", + "DescriptionPlaceholder": "Please describe the issue", + "TitlePlaceholder": "Short title of your issue", + "SelectCategory": "Select Category", + "IssueCreated": "Issue has been created" + }, + "Outstanding": "There are outstanding issues", + "ResolvedDate": "Resolved date", + "CreatedDate": "Raised on", + "MarkedAsResolved": "This issue has now been marked as resolved!", + "MarkedAsInProgress": "This issue has now been marked as in progress!", + "Delete": "Delete issue", + "DeletedIssue": "Issue has been deleted" + }, + "Filter": { + "ClearFilter": "Vymazať filter", + "FilterHeaderAvailability": "Dostupnosť", + "FilterHeaderRequestStatus": "Stav", + "Approved": "Schválené", + "PendingApproval": "Čaká na schválenie" + }, + "UserManagment": { + "TvRemaining": "TV: {{remaining}}/{{total}} zostávajúce", + "MovieRemaining": "Filmy: {{remaining}}/{{total}} zostávajúce", + "MusicRemaining": "Hudba: {{remaining}}/{{total}} zostávajúce", + "TvDue": "TV: {{date}}", + "MovieDue": "Film: {{date}}", + "MusicDue": "Hudba: {{date}}" + }, + "Votes": { + "CompletedVotesTab": "Hlasované", + "VotesTab": "Potrebné hlasovanie" + }, + "MediaDetails": { + "Denied": "Zamietnuté", + "RecommendationsTitle": "Recommendations", + "SimilarTitle": "Podobné", + "VideosTitle": "Videos", + "AlbumsTitle": "Albums", + "RequestAllAlbums": "Request All Albums", + "ClearSelection": "Clear Selection", + "RequestSelectedAlbums": "Request Selected Albums", + "ViewCollection": "View Collection", + "NotEnoughInfo": "Unfortunately there is not enough information about this show yet!", + "AdvancedOptions": "Advanced Options", + "QualityProfilesSelect": "Select A Quality Profile", + "RootFolderSelect": "Select A Root Folder", + "Status": "Stav", + "Availability": "Dostupnosť", + "RequestStatus": "Request Status", + "Quality": "Quality", + "RootFolderOverride": "Prepísanie Root priečinku", + "QualityOverride": "Prepísanie kvality", + "Genres": "Genres", + "TheatricalRelease": "Kino vydanie", + "DigitalRelease": "Digital Release", + "UserScore": "User Score", + "Votes": "Votes", + "Runtime": "Runtime", + "Minutes": "{{runtime}} Minutes", + "Revenue": "Revenue", + "Budget": "Budget", + "Keywords": "Keywords/Tags", + "Casts": { + "CastTitle": "Cast" + }, + "EpisodeSelector": { + "AllSeasonsTooltip": "This will request every season for this show", + "FirstSeasonTooltip": "This will only request the First Season for this show", + "LatestSeasonTooltip": "This will only request the Latest Season for this show" + } + }, + "Discovery": { + "PopularTab": "Populárne", + "TrendingTab": "Trendy", + "UpcomingTab": "Upcoming", + "Movies": "Filmy", + "Combined": "Combined", + "Tv": "TV", + "CardDetails": { + "Availability": "Dostupnosť", + "Studio": "Studio", + "Network": "Network", + "UnknownNetwork": "Unknown", + "RequestStatus": "Request Status", + "Director": "Director", + "InCinemas": "In Cinemas", + "FirstAired": "First Aired", + "Writer": "Writer", + "ExecProducer": "Exec Producer" + } + }, + "UserPreferences": { + "Welcome": "Vitaj {{username}}!", + "OmbiLanguage": "Language", + "DarkMode": "Dark Mode" } - }, - "Issues": { - "Title": "Problémy", - "PendingTitle": "Nevyriešené problémy", - "InProgressTitle": "Riešené problémy", - "ResolvedTitle": "Vyiešené problémy", - "ColumnTitle": "Názov", - "Category": "Kategória", - "Status": "Stav", - "Details": "Podrobnosti", - "Description": "Popis", - "NoComments": "Žiadne komentáre!", - "MarkInProgress": "Označiť ako prebiehajúce", - "MarkResolved": "Označiť ako vyriešené", - "SendMessageButton": "Odoslať", - "Subject": "Predmet", - "Comments": "Komentáre", - "WriteMessagePlaceholder": "Napíšte správu sem...", - "ReportedBy": "Nahlásené od" - }, - "Filter": { - "ClearFilter": "Vymazať filter", - "FilterHeaderAvailability": "Dostupnosť", - "FilterHeaderRequestStatus": "Stav", - "Approved": "Schválené", - "PendingApproval": "Čaká na schválenie" - }, - "UserManagment": { - "TvRemaining": "TV: {{remaining}}/{{total}} zostávajúce", - "MovieRemaining": "Filmy: {{remaining}}/{{total}} zostávajúce", - "MusicRemaining": "Hudba: {{remaining}}/{{total}} zostávajúce", - "TvDue": "TV: {{date}}", - "MovieDue": "Film: {{date}}", - "MusicDue": "Hudba: {{date}}" - }, - "Votes": { - "CompletedVotesTab": "Hlasované", - "VotesTab": "Potrebné hlasovanie" - } -} +} \ No newline at end of file diff --git a/src/Ombi/wwwroot/translations/sv.json b/src/Ombi/wwwroot/translations/sv.json index 766804ba9..4984b658d 100644 --- a/src/Ombi/wwwroot/translations/sv.json +++ b/src/Ombi/wwwroot/translations/sv.json @@ -1,186 +1,301 @@ { - "Login": { - "SignInButton": "Logga in", - "UsernamePlaceholder": "Användarnamn", - "PasswordPlaceholder": "Lösenord", - "RememberMe": "Kom ihåg mig", - "ForgottenPassword": "Glömt ditt lösenord?", - "Errors": { - "IncorrectCredentials": "Felaktigt användarnamn eller lösenord" - } - }, - "Common": { - "ContinueButton": "Fortsätt", - "Available": "Tillgänglig", - "PartiallyAvailable": "Delvis tillgänglig", - "Monitored": "Övervakad", - "NotAvailable": "Inte tillgänglig", - "ProcessingRequest": "Bearbetar förfrågan", - "PendingApproval": "Väntar på godkännande", - "RequestDenied": "Efterfrågan nekas", - "NotRequested": "Inte begärd", - "Requested": "Begärd", - "Request": "Begär", - "Denied": "Nekad", - "Approve": "Godkänn", - "PartlyAvailable": "Delvis tillgänglig", - "Errors": { - "Validation": "Vänligen kontrollera din angivna värden" - } - }, - "PasswordReset": { - "EmailAddressPlaceholder": "E-postadress", - "ResetPasswordButton": "Återställ lösenord" - }, - "LandingPage": { - "OnlineHeading": "Online just nu", - "OnlineParagraph": "Medieservern är för närvarande online", - "PartiallyOnlineHeading": "Delvis online", - "PartiallyOnlineParagraph": "Medieservern är delvis online.", - "MultipleServersUnavailable": "Servrar offline: {{serversUnavailable}}, av totalt {{totalServers}}.", - "SingleServerUnavailable": "Servrar offline: {{serversUnavailable}}, av totalt {{totalServers}}.", - "OfflineHeading": "För närvarande Offline", - "OfflineParagraph": "Medieservern är för närvarande offline.", - "CheckPageForUpdates": "Håll utkik här för uppdateringar på denna sida." - }, - "NavigationBar": { - "Search": "Sök", - "Requests": "Förfrågningar", - "UserManagement": "Användarhantering", - "Issues": "Problem", - "Vote": "Rösta", - "Donate": "Donera!", - "DonateLibraryMaintainer": "Donera till bibliotekets utvecklare", - "DonateTooltip": "Det är så här jag övertygar min fru att låta mig spendera min fritid att utveckla Ombi ;)", - "UpdateAvailableTooltip": "Uppdatering tillgänglig!", - "Settings": "Inställningar", - "Welcome": "Välkommen {{username}}", - "UpdateDetails": "Uppdatera information", - "Logout": "Logga ut", - "OpenMobileApp": "Öppna Mobil App", - "RecentlyAdded": "Nyligen tillagda" - }, - "Search": { - "Title": "Sök", - "Paragraph": "Vill du titta på något som inte är tillgängligt? Inga problem, Sök efter det nedan och önska det!", - "MoviesTab": "Filmer", - "TvTab": "TV-serier", - "MusicTab": "Musik", - "Suggestions": "Förslag", - "NoResults": "Tyvärr hittade vi inte några resultat!", - "DigitalDate": "Digitalt releasedatum: {{date}}", - "TheatricalRelease": "Biopremiär: {{date}}", - "ViewOnPlex": "Visa på Plex", - "ViewOnEmby": "Visa på Emby", - "RequestAdded": "Begäran av {{title}} har lagts till", - "Similar": "Liknande", - "Refine": "Förfina", - "SearchBarPlaceholder": "Skriv här för att söka", - "Movies": { - "PopularMovies": "Populära filmer", - "UpcomingMovies": "Kommande filmer", - "TopRatedMovies": "Topprankade filmer", - "NowPlayingMovies": "Aktuella Filmer", - "HomePage": "Hemsida", - "Trailer": "Trailer" + "Login": { + "SignInButton": "Logga in", + "UsernamePlaceholder": "Användarnamn", + "PasswordPlaceholder": "Lösenord", + "RememberMe": "Kom ihåg mig", + "SignInWith": "Logga in med {{appName}}", + "SignInWithPlex": "Logga in med Plex", + "ForgottenPassword": "Glömt ditt lösenord?", + "Errors": { + "IncorrectCredentials": "Felaktigt användarnamn eller lösenord" + } }, - "TvShows": { - "Popular": "Populära", - "Trending": "Hetast just nu", - "MostWatched": "Mest sedda", - "MostAnticipated": "Mest efterlängtade", - "Results": "Resultat", - "AirDate": "Sändningsdatum:", - "AllSeasons": "Alla Säsonger", - "FirstSeason": "Första säsongen", - "LatestSeason": "Senaste säsongen", - "Select": "Välj...", - "SubmitRequest": "Skicka begäran", - "Season": "Säsong: {{seasonNumber}}", - "SelectAllInSeason": "Välj alla avsnitt i säsong {{seasonNumber}}" - } - }, - "Requests": { - "Title": "Efterfrågningar", - "Paragraph": "Nedan kan du se dina och alla andras förfrågningar, samt deras nedladdnings-och godkännandestatus.", - "MoviesTab": "Filmer", - "TvTab": "TV-serier", - "MusicTab": "Musik", - "RequestedBy": "Efterfrågats av:", - "Status": "Status:", - "RequestStatus": "Status för begäran:", - "Denied": " Nekad:", - "TheatricalRelease": "Biopremiär: {{date}}", - "ReleaseDate": "Releasedatum: {{date}}", - "TheatricalReleaseSort": "Biopremiär", - "DigitalRelease": "Digitalt Releasedatum: {{date}}", - "RequestDate": "Datum för begäran:", - "QualityOverride": "Kvalitétsöverskridande:", - "RootFolderOverride": "Rotmappsöverskridande:", - "ChangeRootFolder": "Byt rotmapp", - "ChangeQualityProfile": "Byt kvalitétsprofil", - "MarkUnavailable": "Markera Otillgänglig", - "MarkAvailable": "Markera Tillgänglig", - "Remove": "Ta bort", - "Deny": "Neka", - "Season": "Säsong:", - "GridTitle": "Titel", - "AirDate": "Releasedatum", - "GridStatus": "Status", - "ReportIssue": "Rapportera problem", - "Filter": "Filtrera", - "Sort": "Sortera", - "SeasonNumberHeading": "Säsong: {seasonNumber}", - "SortTitleAsc": "Titel ▲", - "SortTitleDesc": "Titel ▼", - "SortRequestDateAsc": "Datum för begäran ▲", - "SortRequestDateDesc": "Datum för begäran ▼", - "SortStatusAsc": "Status ▲", - "SortStatusDesc": "Status ▼", - "Remaining": { - "Quota": "{{remaining}}/{{total}} återstående förfrågningar", - "NextDays": "En ny begäran kommer att läggas till om {{time}} Dagar", - "NextHours": "En ny begäran kommer att läggas till om {{time}} Timmar", - "NextMinutes": "En ny begäran kommer att läggas till om {{time}} Minuter", - "NextMinute": "En ny begäran kommer att läggas till om {{time}} Minut" + "Common": { + "ContinueButton": "Fortsätt", + "Available": "Tillgänglig", + "PartiallyAvailable": "Delvis tillgänglig", + "Monitored": "Övervakad", + "NotAvailable": "Inte tillgänglig", + "ProcessingRequest": "Bearbetar förfrågan", + "PendingApproval": "Väntar på godkännande", + "RequestDenied": "Efterfrågan nekas", + "NotRequested": "Inte begärd", + "Requested": "Begärd", + "Request": "Begär", + "Denied": "Nekad", + "Approve": "Godkänn", + "PartlyAvailable": "Delvis tillgänglig", + "ViewDetails": "Visa detaljer", + "Errors": { + "Validation": "Vänligen kontrollera din angivna värden" + }, + "Cancel": "Avbryt", + "Submit": "Skicka in" + }, + "PasswordReset": { + "EmailAddressPlaceholder": "E-postadress", + "ResetPasswordButton": "Återställ lösenord" + }, + "LandingPage": { + "OnlineHeading": "Online just nu", + "OnlineParagraph": "Medieservern är för närvarande online", + "PartiallyOnlineHeading": "Delvis online", + "PartiallyOnlineParagraph": "Medieservern är delvis online.", + "MultipleServersUnavailable": "Servrar offline: {{serversUnavailable}}, av totalt {{totalServers}}.", + "SingleServerUnavailable": "Servrar offline: {{serversUnavailable}}, av totalt {{totalServers}}.", + "OfflineHeading": "För närvarande Offline", + "OfflineParagraph": "Medieservern är för närvarande offline.", + "CheckPageForUpdates": "Håll utkik här för uppdateringar på denna sida." + }, + "NavigationBar": { + "Discover": "Upptäck", + "Search": "Sök", + "Requests": "Förfrågningar", + "UserManagement": "Användarhantering", + "Issues": "Problem", + "Vote": "Rösta", + "Donate": "Donera!", + "DonateLibraryMaintainer": "Donera till bibliotekets utvecklare", + "DonateTooltip": "Det är så här jag övertygar min fru att låta mig spendera min fritid att utveckla Ombi ;)", + "UpdateAvailableTooltip": "Uppdatering tillgänglig!", + "Settings": "Inställningar", + "Welcome": "Välkommen {{username}}", + "UpdateDetails": "Uppdatera information", + "Logout": "Logga ut", + "OpenMobileApp": "Öppna Mobil App", + "RecentlyAdded": "Nyligen tillagda", + "ChangeTheme": "Ändra tema", + "Calendar": "Kalender", + "UserPreferences": "Preferens", + "FeatureSuggestion": "Föreslå nya funktioner", + "FeatureSuggestionTooltip": "Har du en bra ny idé? Föreslå det här!", + "Filter": { + "Movies": "Filmer", + "TvShows": "TV-serier", + "Music": "Musik", + "People": "Personer" + }, + "MorningWelcome": "God morgon!", + "AfternoonWelcome": "God eftermiddag!", + "EveningWelcome": "God kväll!" + }, + "Search": { + "Title": "Sök", + "Paragraph": "Vill du titta på något som inte är tillgängligt? Inga problem, Sök efter det nedan och önska det!", + "MoviesTab": "Filmer", + "TvTab": "TV-serier", + "MusicTab": "Musik", + "Suggestions": "Förslag", + "NoResults": "Tyvärr hittade vi inte några resultat!", + "DigitalDate": "Digitalt releasedatum: {{date}}", + "TheatricalRelease": "Biopremiär: {{date}}", + "ViewOnPlex": "Visa på Plex", + "ViewOnEmby": "Visa på Emby", + "RequestAdded": "Begäran av {{title}} har lagts till", + "Similar": "Liknande", + "Refine": "Förfina", + "SearchBarPlaceholder": "Skriv här för att söka", + "Movies": { + "PopularMovies": "Populära filmer", + "UpcomingMovies": "Kommande filmer", + "TopRatedMovies": "Topprankade filmer", + "NowPlayingMovies": "Aktuella Filmer", + "HomePage": "Hemsida", + "Trailer": "Trailer" + }, + "TvShows": { + "Popular": "Populära", + "Trending": "Hetast just nu", + "MostWatched": "Mest sedda", + "MostAnticipated": "Mest efterlängtade", + "Results": "Resultat", + "AirDate": "Sändningsdatum:", + "AllSeasons": "Alla Säsonger", + "FirstSeason": "Första säsongen", + "LatestSeason": "Senaste säsongen", + "Select": "Välj...", + "SubmitRequest": "Skicka begäran", + "Season": "Säsong: {{seasonNumber}}", + "SelectAllInSeason": "Välj alla avsnitt i säsong {{seasonNumber}}" + } + }, + "Requests": { + "Title": "Efterfrågningar", + "Paragraph": "Nedan kan du se dina och alla andras förfrågningar, samt deras nedladdnings-och godkännandestatus.", + "MoviesTab": "Filmer", + "ArtistName": "Artist", + "AlbumName": "Albumnamn", + "TvTab": "TV-serier", + "MusicTab": "Musik", + "RequestedBy": "Efterfrågats av", + "Status": "Status", + "RequestStatus": "Status för begäran", + "Denied": " Nekad:", + "TheatricalRelease": "Biopremiär: {{date}}", + "ReleaseDate": "Releasedatum: {{date}}", + "TheatricalReleaseSort": "Biopremiär", + "DigitalRelease": "Digitalt Releasedatum: {{date}}", + "RequestDate": "Datum för begäran", + "QualityOverride": "Kvalitétsöverskridande:", + "RootFolderOverride": "Rotmappsöverskridande:", + "ChangeRootFolder": "Byt rotmapp", + "ChangeQualityProfile": "Byt kvalitétsprofil", + "MarkUnavailable": "Markera Otillgänglig", + "MarkAvailable": "Markera Tillgänglig", + "Remove": "Ta bort", + "Deny": "Neka", + "DenyReason": "Anledning för nekande", + "Season": "Säsong:", + "GridTitle": "Titel", + "AirDate": "Releasedatum", + "GridStatus": "Status", + "ReportIssue": "Rapportera problem", + "Filter": "Filtrera", + "Sort": "Sortera", + "SeasonNumberHeading": "Säsong: {seasonNumber}", + "SortTitleAsc": "Titel ▲", + "SortTitleDesc": "Titel ▼", + "SortRequestDateAsc": "Datum för begäran ▲", + "SortRequestDateDesc": "Datum för begäran ▼", + "SortStatusAsc": "Status ▲", + "SortStatusDesc": "Status ▼", + "Remaining": { + "Quota": "{{remaining}}/{{total}} återstående förfrågningar", + "NextDays": "En ny begäran kommer att läggas till om {{time}} Dagar", + "NextHours": "En ny begäran kommer att läggas till om {{time}} Timmar", + "NextMinutes": "En ny begäran kommer att läggas till om {{time}} Minuter", + "NextMinute": "En ny begäran kommer att läggas till om {{time}} Minut" + }, + "AllRequests": "Alla förfrågningar", + "PendingRequests": "Väntande förfrågningar", + "ProcessingRequests": "Bearbetar förfrågningar", + "AvailableRequests": "Tillgängliga förfrågningar", + "DeniedRequests": "Nekade förfrågningar", + "RequestsToDisplay": "Förfrågningar att visa", + "RequestsTitle": "Titel", + "Details": "Detaljer", + "Options": "Alternativ", + "RequestPanel": { + "Delete": "Ta bort förfrågan", + "Approve": "Godkänn begäran", + "ChangeAvailability": "Markera Tillgänglig" + } + }, + "Issues": { + "Title": "Problem", + "PendingTitle": "Väntande problem", + "InProgressTitle": "Pågående problem", + "ResolvedTitle": "Lösta problem", + "ColumnTitle": "Titel", + "Category": "Kategori", + "Status": "Status", + "Details": "Detaljer", + "Description": "Beskrivning", + "NoComments": "Inga Kommentarer!", + "MarkInProgress": "Markera som pågående", + "MarkResolved": "Markera som löst", + "SendMessageButton": "Skicka", + "Subject": "Ämne", + "Comments": "Kommentarer", + "WriteMessagePlaceholder": "Skriv ditt meddelande här...", + "ReportedBy": "Rapporterad av", + "IssueDialog": { + "Title": "Rapportera ett problem", + "DescriptionPlaceholder": "Vänligen beskriv ditt problem", + "TitlePlaceholder": "Kort titel på ditt ärende", + "SelectCategory": "Välj kategori", + "IssueCreated": "Problemet har skapats" + }, + "Outstanding": "Det finns kvarstående problem", + "ResolvedDate": "Löst den", + "CreatedDate": "Skapad den", + "MarkedAsResolved": "Detta problem har nu markerats som löst!", + "MarkedAsInProgress": "Detta problem har nu markerats som på pågående!", + "Delete": "Ta bort problem", + "DeletedIssue": "Problemet har tagits bort" + }, + "Filter": { + "ClearFilter": "Rensa filter", + "FilterHeaderAvailability": "Tillgänglighet", + "FilterHeaderRequestStatus": "Status", + "Approved": "Godkänd", + "PendingApproval": "Väntar på godkännande" + }, + "UserManagment": { + "TvRemaining": "TV: {{remaining}}/{{total}} återstående", + "MovieRemaining": "Movies: {{remaining}}/{{total}} återstående", + "MusicRemaining": "Music: {{remaining}}/{{total}} återstående", + "TvDue": "TV: {{date}}", + "MovieDue": "Movie: {{date}}", + "MusicDue": "Music: {{date}}" + }, + "Votes": { + "CompletedVotesTab": "Röstat", + "VotesTab": "Röster krävs" + }, + "MediaDetails": { + "Denied": "Nekad", + "RecommendationsTitle": "Rekommendationer", + "SimilarTitle": "Liknande", + "VideosTitle": "Videor", + "AlbumsTitle": "Album", + "RequestAllAlbums": "Begär alla album", + "ClearSelection": "Rensa markering", + "RequestSelectedAlbums": "Begär markerade album", + "ViewCollection": "Visa samling", + "NotEnoughInfo": "Tyvärr finns det inte tillräckligt med information om denna serie ännu!", + "AdvancedOptions": "Avancerade inställningar", + "QualityProfilesSelect": "Välj en kvalitetsprofil", + "RootFolderSelect": "Välj en rotmapp", + "Status": "Status", + "Availability": "Tillgänglighet", + "RequestStatus": "Status för begäran", + "Quality": "Kvalitet", + "RootFolderOverride": "Rotmappsöverskridande", + "QualityOverride": "Kvalitétsöverskridande", + "Genres": "Genrer", + "TheatricalRelease": "Biopremiär", + "DigitalRelease": "Digital release", + "UserScore": "Användarbetyg", + "Votes": "Röster", + "Runtime": "Speltid", + "Minutes": "{{runtime}} minuter", + "Revenue": "Intäkter", + "Budget": "Budget", + "Keywords": "Nyckelord/Taggar", + "Casts": { + "CastTitle": "Rollista" + }, + "EpisodeSelector": { + "AllSeasonsTooltip": "Detta kommer att begära varje säsong för denna serie", + "FirstSeasonTooltip": "Detta kommer endast att begära den första säsongen för denna serie", + "LatestSeasonTooltip": "Detta kommer endast att begära den senaste säsongen för denna serie" + } + }, + "Discovery": { + "PopularTab": "Populära", + "TrendingTab": "Hetast just nu", + "UpcomingTab": "Kommande", + "Movies": "Filmer", + "Combined": "Kombinerad", + "Tv": "TV", + "CardDetails": { + "Availability": "Tillgänglighet", + "Studio": "Filmstudio", + "Network": "Tv-nätverk", + "UnknownNetwork": "Okänd", + "RequestStatus": "Status för begäran", + "Director": "Regissör", + "InCinemas": "På bio", + "FirstAired": "Sändes första gången", + "Writer": "Författare", + "ExecProducer": "Exekutiv producent" + } + }, + "UserPreferences": { + "Welcome": "Välkommen {{username}}!", + "OmbiLanguage": "Språk", + "DarkMode": "Mörkt läge" } - }, - "Issues": { - "Title": "Problem", - "PendingTitle": "Väntande problem", - "InProgressTitle": "Pågående problem", - "ResolvedTitle": "Lösta problem", - "ColumnTitle": "Titel", - "Category": "Kategori", - "Status": "Status", - "Details": "Detaljer", - "Description": "Beskrivning", - "NoComments": "Inga Kommentarer!", - "MarkInProgress": "Markera som pågående", - "MarkResolved": "Markera som löst", - "SendMessageButton": "Skicka", - "Subject": "Ämne", - "Comments": "Kommentarer", - "WriteMessagePlaceholder": "Skriv ditt meddelande här...", - "ReportedBy": "Rapporterad av" - }, - "Filter": { - "ClearFilter": "Rensa filter", - "FilterHeaderAvailability": "Tillgänglighet", - "FilterHeaderRequestStatus": "Status", - "Approved": "Godkänd", - "PendingApproval": "Väntar på godkännande" - }, - "UserManagment": { - "TvRemaining": "TV: {{remaining}}/{{total}} återstående", - "MovieRemaining": "Movies: {{remaining}}/{{total}} återstående", - "MusicRemaining": "Music: {{remaining}}/{{total}} återstående", - "TvDue": "TV: {{date}}", - "MovieDue": "Movie: {{date}}", - "MusicDue": "Music: {{date}}" - }, - "Votes": { - "CompletedVotesTab": "Röstat", - "VotesTab": "Röster krävs" - } -} +} \ No newline at end of file