Compare commits
4 Commits
develop
...
phantom-ad
Author | SHA1 | Date |
---|---|---|
Taloth Saldono | 808836a65f | |
Taloth Saldono | 6f7e505bed | |
Jacob | ecf1d75954 | |
netpok | c5257de436 |
|
@ -1,13 +0,0 @@
|
||||||
// This file is used to open the backend and frontend in the same workspace, which is necessary as
|
|
||||||
// the frontend has vscode settings that are distinct from the backend
|
|
||||||
{
|
|
||||||
"folders": [
|
|
||||||
{
|
|
||||||
"path": ".."
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"path": "../frontend"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"settings": {}
|
|
||||||
}
|
|
|
@ -1,19 +0,0 @@
|
||||||
// For format details, see https://aka.ms/devcontainer.json. For config options, see the
|
|
||||||
// README at: https://github.com/devcontainers/templates/tree/main/src/dotnet
|
|
||||||
{
|
|
||||||
"name": "Sonarr",
|
|
||||||
"image": "mcr.microsoft.com/devcontainers/dotnet:1-6.0",
|
|
||||||
"features": {
|
|
||||||
"ghcr.io/devcontainers/features/node:1": {
|
|
||||||
"nodeGypDependencies": true,
|
|
||||||
"version": "16",
|
|
||||||
"nvmVersion": "latest"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"forwardPorts": [8989],
|
|
||||||
"customizations": {
|
|
||||||
"vscode": {
|
|
||||||
"extensions": ["esbenp.prettier-vscode"]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
264
.editorconfig
264
.editorconfig
|
@ -2,274 +2,14 @@
|
||||||
# editorconfig.org
|
# editorconfig.org
|
||||||
root = true
|
root = true
|
||||||
|
|
||||||
# NOTE: Requires **VS2019 16.3** or later
|
[*.{cs}]
|
||||||
|
|
||||||
# Stylecop.ruleset
|
|
||||||
# Description: Rules for Sonarr
|
|
||||||
|
|
||||||
# Code files
|
|
||||||
[*.cs]
|
|
||||||
charset = utf-8
|
charset = utf-8
|
||||||
trim_trailing_whitespace = true
|
trim_trailing_whitespace = true
|
||||||
insert_final_newline = true
|
insert_final_newline = true
|
||||||
indent_style = space
|
indent_style = space
|
||||||
indent_size = 4
|
indent_size = 4
|
||||||
|
|
||||||
# Sort using and Import directives with System.* appearing first
|
[*.{js,html,js,hbs,less,css}]
|
||||||
dotnet_sort_system_directives_first = true
|
|
||||||
|
|
||||||
# Avoid "this." and "Me." if not necessary
|
|
||||||
dotnet_style_qualification_for_field = false:refactoring
|
|
||||||
dotnet_style_qualification_for_property = false:refactoring
|
|
||||||
dotnet_style_qualification_for_method = false:refactoring
|
|
||||||
dotnet_style_qualification_for_event = false:refactoring
|
|
||||||
|
|
||||||
# Indentation preferences
|
|
||||||
csharp_indent_block_contents = true
|
|
||||||
csharp_indent_braces = false
|
|
||||||
csharp_indent_case_contents = true
|
|
||||||
csharp_indent_case_contents_when_block = true
|
|
||||||
csharp_indent_switch_labels = true
|
|
||||||
csharp_indent_labels = flush_left
|
|
||||||
|
|
||||||
dotnet_style_qualification_for_field = false:suggestion
|
|
||||||
dotnet_style_qualification_for_property = false:suggestion
|
|
||||||
dotnet_style_qualification_for_method = false:suggestion
|
|
||||||
dotnet_style_qualification_for_event = false:suggestion
|
|
||||||
dotnet_naming_style.instance_field_style.capitalization = camel_case
|
|
||||||
dotnet_naming_style.instance_field_style.required_prefix = _
|
|
||||||
|
|
||||||
# Prefer "var" everywhere
|
|
||||||
csharp_style_var_for_built_in_types = true
|
|
||||||
csharp_style_var_when_type_is_apparent = true
|
|
||||||
csharp_style_var_elsewhere = true
|
|
||||||
# Prefer "out" variables to be declared inline
|
|
||||||
csharp_style_inlined_variable_declaration = true
|
|
||||||
|
|
||||||
# Using directive is unnecessary.
|
|
||||||
dotnet_diagnostic.IDE0005.severity = error
|
|
||||||
# Use var instead of explicit type
|
|
||||||
dotnet_diagnostic.IDE0007.severity = error
|
|
||||||
# Inline variable declaration
|
|
||||||
dotnet_diagnostic.IDE0018.severity = error
|
|
||||||
|
|
||||||
# Stylecop Rules
|
|
||||||
dotnet_diagnostic.SA0001.severity = none
|
|
||||||
dotnet_diagnostic.SA1025.severity = none
|
|
||||||
dotnet_diagnostic.SA1101.severity = none
|
|
||||||
dotnet_diagnostic.SA1116.severity = none
|
|
||||||
dotnet_diagnostic.SA1118.severity = none
|
|
||||||
dotnet_diagnostic.SA1122.severity = none
|
|
||||||
dotnet_diagnostic.SA1201.severity = suggestion
|
|
||||||
dotnet_diagnostic.SA1202.severity = suggestion
|
|
||||||
dotnet_diagnostic.SA1204.severity = suggestion
|
|
||||||
dotnet_diagnostic.SA1300.severity = none
|
|
||||||
dotnet_diagnostic.SA1303.severity = none
|
|
||||||
dotnet_diagnostic.SA1304.severity = none
|
|
||||||
dotnet_diagnostic.SA1306.severity = none
|
|
||||||
dotnet_diagnostic.SA1309.severity = none
|
|
||||||
dotnet_diagnostic.SA1310.severity = none
|
|
||||||
dotnet_diagnostic.SA1401.severity = none
|
|
||||||
dotnet_diagnostic.SA1402.severity = none
|
|
||||||
dotnet_diagnostic.SA1404.severity = suggestion
|
|
||||||
dotnet_diagnostic.SA1405.severity = suggestion
|
|
||||||
dotnet_diagnostic.SA1406.severity = suggestion
|
|
||||||
dotnet_diagnostic.SA1410.severity = suggestion
|
|
||||||
dotnet_diagnostic.SA1411.severity = suggestion
|
|
||||||
dotnet_diagnostic.SA1413.severity = none
|
|
||||||
dotnet_diagnostic.SA1512.severity = none
|
|
||||||
dotnet_diagnostic.SA1516.severity = none
|
|
||||||
dotnet_diagnostic.SA1600.severity = none
|
|
||||||
dotnet_diagnostic.SA1601.severity = none
|
|
||||||
dotnet_diagnostic.SA1602.severity = none
|
|
||||||
dotnet_diagnostic.SA1604.severity = none
|
|
||||||
dotnet_diagnostic.SA1605.severity = none
|
|
||||||
dotnet_diagnostic.SA1606.severity = none
|
|
||||||
dotnet_diagnostic.SA1607.severity = none
|
|
||||||
dotnet_diagnostic.SA1608.severity = none
|
|
||||||
dotnet_diagnostic.SA1610.severity = none
|
|
||||||
dotnet_diagnostic.SA1611.severity = none
|
|
||||||
dotnet_diagnostic.SA1612.severity = none
|
|
||||||
dotnet_diagnostic.SA1613.severity = none
|
|
||||||
dotnet_diagnostic.SA1614.severity = none
|
|
||||||
dotnet_diagnostic.SA1615.severity = none
|
|
||||||
dotnet_diagnostic.SA1616.severity = none
|
|
||||||
dotnet_diagnostic.SA1617.severity = none
|
|
||||||
dotnet_diagnostic.SA1618.severity = none
|
|
||||||
dotnet_diagnostic.SA1619.severity = none
|
|
||||||
dotnet_diagnostic.SA1620.severity = none
|
|
||||||
dotnet_diagnostic.SA1621.severity = none
|
|
||||||
dotnet_diagnostic.SA1622.severity = none
|
|
||||||
dotnet_diagnostic.SA1623.severity = none
|
|
||||||
dotnet_diagnostic.SA1624.severity = none
|
|
||||||
dotnet_diagnostic.SA1625.severity = none
|
|
||||||
dotnet_diagnostic.SA1626.severity = none
|
|
||||||
dotnet_diagnostic.SA1627.severity = none
|
|
||||||
dotnet_diagnostic.SA1629.severity = none
|
|
||||||
dotnet_diagnostic.SA1633.severity = none
|
|
||||||
dotnet_diagnostic.SA1634.severity = none
|
|
||||||
dotnet_diagnostic.SA1635.severity = none
|
|
||||||
dotnet_diagnostic.SA1636.severity = none
|
|
||||||
dotnet_diagnostic.SA1637.severity = none
|
|
||||||
dotnet_diagnostic.SA1638.severity = none
|
|
||||||
dotnet_diagnostic.SA1640.severity = none
|
|
||||||
dotnet_diagnostic.SA1641.severity = none
|
|
||||||
dotnet_diagnostic.SA1642.severity = none
|
|
||||||
dotnet_diagnostic.SA1643.severity = none
|
|
||||||
dotnet_diagnostic.SA1648.severity = none
|
|
||||||
dotnet_diagnostic.SA1649.severity = none
|
|
||||||
dotnet_diagnostic.SA1651.severity = none
|
|
||||||
dotnet_diagnostic.SX1309.severity = warning
|
|
||||||
|
|
||||||
# Microsoft Analyzers that fail and need to be sorted thru
|
|
||||||
dotnet_diagnostic.ASP0000.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA1000.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA1001.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA1002.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA1003.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA1008.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA1010.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA1012.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA1014.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA1016.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA1017.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA1018.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA1019.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA1021.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA1024.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA1027.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA1028.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA1030.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA1031.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA1032.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA1033.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA1034.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA1036.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA1040.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA1041.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA1043.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA1044.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA1050.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA1051.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA1052.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA1054.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA1055.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA1056.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA1058.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA1060.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA1061.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA1062.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA1063.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA1064.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA1065.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA1066.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA1067.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA1068.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA1069.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA1200.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA1303.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA1304.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA1305.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA1307.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA1308.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA1309.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA1310.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA1401.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA1416.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA1419.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA1507.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA1508.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA1707.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA1708.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA1710.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA1711.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA1712.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA1714.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA1715.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA1716.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA1717.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA1720.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA1721.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA1724.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA1725.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA1806.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA1810.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA1812.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA1813.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA1814.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA1815.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA1816.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA1819.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA1822.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA1823.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA1824.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA1825.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA2000.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA2002.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA2007.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA2008.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA2012.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA2013.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA2100.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA2101.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA2119.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA2153.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA2200.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA2201.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA2207.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA2208.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA2211.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA2213.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA2214.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA2215.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA2216.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA2219.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA2225.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA2226.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA2227.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA2229.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA2231.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA2234.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA2235.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA2237.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA2241.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA2242.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA2243.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA2244.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA2245.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA2246.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA2249.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA2251.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA3061.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA3075.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA3076.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA3077.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA3147.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA5350.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA5351.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA5359.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA5360.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA5363.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA5364.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA5365.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA5366.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA5368.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA5369.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA5370.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA5371.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA5372.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA5373.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA5374.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA5379.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA5384.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA5385.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA5392.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA5394.severity = suggestion
|
|
||||||
dotnet_diagnostic.CA5397.severity = suggestion
|
|
||||||
|
|
||||||
dotnet_diagnostic.SYSLIB0006.severity = none
|
|
||||||
|
|
||||||
[*.{js,html,hbs,less,css,ts,tsx}]
|
|
||||||
charset = utf-8
|
charset = utf-8
|
||||||
trim_trailing_whitespace = true
|
trim_trailing_whitespace = true
|
||||||
insert_final_newline = true
|
insert_final_newline = true
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
{
|
||||||
|
"paths": [
|
||||||
|
"frontend/src/**/*.js"
|
||||||
|
],
|
||||||
|
"ignored": [
|
||||||
|
"**/node_modules/**/*"
|
||||||
|
],
|
||||||
|
"port": 5004
|
||||||
|
}
|
|
@ -5,7 +5,7 @@
|
||||||
# when checked out on windows
|
# when checked out on windows
|
||||||
*.sh text eol=lf
|
*.sh text eol=lf
|
||||||
distribution/debian/* text eol=lf
|
distribution/debian/* text eol=lf
|
||||||
distribution/osx/Sonarr text eol=lf
|
macOS/Sonarr text eol=lf
|
||||||
|
|
||||||
# Custom for Visual Studio
|
# Custom for Visual Studio
|
||||||
*.cs diff=csharp
|
*.cs diff=csharp
|
||||||
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
<!--
|
||||||
|
Before opening a new issue, please ensure:
|
||||||
|
- You use the forums for support/questions
|
||||||
|
- You search for existing bugs/feature requests
|
||||||
|
- Remove extraneous template details
|
||||||
|
- Do not prefix title with type of issue (Feature Request, Bug, etc.) The appropriate labels will be added during triage.
|
||||||
|
-->
|
||||||
|
|
||||||
|
## Support / Questions
|
||||||
|
|
||||||
|
Please use https://forums.sonarr.tv/ for support. Support requests or questions will be redirected to the forums and the issue will be closed.
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Remove if not opening a bug report
|
||||||
|
-->
|
||||||
|
|
||||||
|
## Bug Report
|
||||||
|
|
||||||
|
### System Information/Logs
|
||||||
|
|
||||||
|
**Sonarr Version:**
|
||||||
|
|
||||||
|
**Operating System:**
|
||||||
|
|
||||||
|
**.net Framework (Windows) or mono (macOS/Linux) Version:**
|
||||||
|
|
||||||
|
**Link to Log Files (debug or trace):**
|
||||||
|
|
||||||
|
**Browser (for UI bugs):**
|
||||||
|
|
||||||
|
### Additional Information
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Remove if not opening a feature request
|
||||||
|
-->
|
||||||
|
|
||||||
|
## Feature Request
|
||||||
|
|
||||||
|
### What problem are you looking to solve?
|
||||||
|
|
||||||
|
### Other Information
|
|
@ -0,0 +1,28 @@
|
||||||
|
---
|
||||||
|
name: Bug report
|
||||||
|
about: Create a report to help us improve Sonarr
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Describe the bug**
|
||||||
|
A clear and concise description of what the bug is.
|
||||||
|
|
||||||
|
**Screenshots**
|
||||||
|
If applicable, add screenshots to help explain your problem.
|
||||||
|
|
||||||
|
**Logs**
|
||||||
|
Link to debug or trace log files.
|
||||||
|
|
||||||
|
**System Information**
|
||||||
|
|
||||||
|
- Sonarr Version: [e.g. 2.0.0.1]
|
||||||
|
- Operating System: [e.g. Windows 10]
|
||||||
|
- .net Framework (Windows) or mono (macOS/Linux) Version: [e.g. 4.5 or 5.12]
|
||||||
|
|
||||||
|
**UI Bugs:**
|
||||||
|
- OS: [e.g. Windows]
|
||||||
|
- Browser: [e.g. chrome, firefox]
|
||||||
|
- Version: [e.g. 22]
|
||||||
|
|
||||||
|
**Additional context**
|
||||||
|
Add any other context about the problem here.
|
|
@ -1,81 +0,0 @@
|
||||||
name: Bug Report
|
|
||||||
description: 'Only bug reports for v4 will be accepted, older versions are no longer receiving bug fixes and support issues will be closed immediately.'
|
|
||||||
labels: ['needs-triage']
|
|
||||||
body:
|
|
||||||
- type: checkboxes
|
|
||||||
attributes:
|
|
||||||
label: Is there an existing issue for this?
|
|
||||||
description: Please search to see if an open or closed issue already exists for the bug you encountered. If a bug exists and it is closed as complete it may not yet be in a stable release.
|
|
||||||
options:
|
|
||||||
- label: I have searched the existing open and closed issues
|
|
||||||
required: true
|
|
||||||
- type: textarea
|
|
||||||
attributes:
|
|
||||||
label: Current Behavior
|
|
||||||
description: A concise description of what you're experiencing.
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
- type: textarea
|
|
||||||
attributes:
|
|
||||||
label: Expected Behavior
|
|
||||||
description: A concise description of what you expected to happen.
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
- type: textarea
|
|
||||||
attributes:
|
|
||||||
label: Steps To Reproduce
|
|
||||||
description: Steps to reproduce the behavior.
|
|
||||||
placeholder: |
|
|
||||||
1. In this environment...
|
|
||||||
2. With this config...
|
|
||||||
3. Run '...'
|
|
||||||
4. See error...
|
|
||||||
validations:
|
|
||||||
required: false
|
|
||||||
- type: textarea
|
|
||||||
attributes:
|
|
||||||
label: Environment
|
|
||||||
description: |
|
|
||||||
examples:
|
|
||||||
- **OS**: Ubuntu 22.04
|
|
||||||
- **Sonarr**: Sonarr 4.0.0.766
|
|
||||||
- **Docker Install**: Yes
|
|
||||||
- **Using Reverse Proxy**: No
|
|
||||||
- **Browser**: Firefox 90 (If UI related)
|
|
||||||
- **Database**: Sqlite 3.41.2
|
|
||||||
value: |
|
|
||||||
- OS:
|
|
||||||
- Sonarr:
|
|
||||||
- Docker Install:
|
|
||||||
- Using Reverse Proxy:
|
|
||||||
- Browser:
|
|
||||||
- Database:
|
|
||||||
render: markdown
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
- type: dropdown
|
|
||||||
attributes:
|
|
||||||
label: What branch are you running?
|
|
||||||
options:
|
|
||||||
- Main
|
|
||||||
- Develop
|
|
||||||
- Other (This issue will be closed)
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
- type: textarea
|
|
||||||
attributes:
|
|
||||||
label: Trace Logs?
|
|
||||||
description: |
|
|
||||||
Trace Logs (https://wiki.servarr.com/sonarr/troubleshooting#logging-and-log-files)
|
|
||||||
***Generally speaking, all bug reports must have trace logs provided.***
|
|
||||||
*** Info Logs are not trace logs. If the logs do not say trace and are not from a file like `*.trace.*.txt` they are not trace logs.***
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
- type: textarea
|
|
||||||
attributes:
|
|
||||||
label: Anything else?
|
|
||||||
description: |
|
|
||||||
Links? Screenshots? References? Anything that will give us more context about the issue you are encountering!
|
|
||||||
Tip: You can attach images or log files by clicking this area to highlight it and then dragging files in.
|
|
||||||
validations:
|
|
||||||
required: false
|
|
|
@ -1,14 +0,0 @@
|
||||||
blank_issues_enabled: false
|
|
||||||
contact_links:
|
|
||||||
- name: Support via Discord
|
|
||||||
url: https://discord.gg/M6BvZn5
|
|
||||||
about: Chat with users and devs on support and setup related topics.
|
|
||||||
- name: Support via Reddit
|
|
||||||
url: https://reddit.com/r/Sonarr
|
|
||||||
about: Discuss and search through support topics.
|
|
||||||
- name: Support via Forums
|
|
||||||
url: https://forums.sonarr.tv/
|
|
||||||
about: Discuss and search through support topics.
|
|
||||||
- name: Support via IRC
|
|
||||||
url: https://web.libera.chat/?channels=#sonarr
|
|
||||||
about: Chat with users and devs on support and setup related topics.
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
---
|
||||||
|
name: Feature request
|
||||||
|
about: Suggest an idea for Sonarr
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Describe the problem**
|
||||||
|
A clear and concise description of the problem you're looking to solve.
|
||||||
|
|
||||||
|
**Describe any solutions you think might work**
|
||||||
|
A clear and concise description of any solutions or features you've considered.
|
||||||
|
|
||||||
|
**Additional context**
|
||||||
|
Add any other context or screenshots about the feature request here.
|
|
@ -1,37 +0,0 @@
|
||||||
name: Feature Request
|
|
||||||
description: 'Suggest an idea for Sonarr'
|
|
||||||
labels: ['needs-triage']
|
|
||||||
body:
|
|
||||||
- type: checkboxes
|
|
||||||
attributes:
|
|
||||||
label: Is there an existing issue for this?
|
|
||||||
description: Please search to see if an open or closed issue already exists for the feature you are requesting. If a feature request exists and it is closed as complete it may not yet be in a stable release.
|
|
||||||
options:
|
|
||||||
- label: I have searched the existing open and closed issues
|
|
||||||
required: true
|
|
||||||
- type: textarea
|
|
||||||
attributes:
|
|
||||||
label: Is your feature request related to a problem? Please describe
|
|
||||||
description: A clear and concise description of what the problem is.
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
- type: textarea
|
|
||||||
attributes:
|
|
||||||
label: Describe the solution you'd like
|
|
||||||
description: A clear and concise description of what you want to happen.
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
- type: textarea
|
|
||||||
attributes:
|
|
||||||
label: Describe alternatives you've considered
|
|
||||||
description: A clear and concise description of any alternative solutions or features you've considered.
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
- type: textarea
|
|
||||||
attributes:
|
|
||||||
label: Anything else?
|
|
||||||
description: |
|
|
||||||
Links? References? Mockups? Anything that will give us more context about the feature you are encountering!
|
|
||||||
Tip: You can attach images or log files by clicking this area to highlight it and then dragging files in.
|
|
||||||
validations:
|
|
||||||
required: false
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
---
|
||||||
|
name: Other issues
|
||||||
|
about: How to get support or ask questions
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Please use https://forums.sonarr.tv/ for support. Support requests or questions will be redirected to the forums and the issue will be closed.
|
|
@ -1,15 +1,14 @@
|
||||||
|
#### Database Migration
|
||||||
|
YES | NO
|
||||||
|
|
||||||
#### Description
|
#### Description
|
||||||
A few sentences describing the overall goals of the pull request's commits.
|
A few sentences describing the overall goals of the pull request's commits.
|
||||||
|
|
||||||
<!-- Remove any of the following sections if they are not used -->
|
#### Todos
|
||||||
|
- [ ] Tests
|
||||||
#### Screenshots for UI Changes
|
- [ ] Documentation
|
||||||
|
|
||||||
|
|
||||||
#### Database Migration
|
|
||||||
YES - ###
|
|
||||||
|
|
||||||
|
|
||||||
#### Issues Fixed or Closed by this PR
|
#### Issues Fixed or Closed by this PR
|
||||||
* Closes #
|
|
||||||
|
|
||||||
|
*
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
## Support
|
||||||
|
|
||||||
|
There are a number of frequently asked questions that have been answered in our [FAQ](https://github.com/Sonarr/Sonarr/wiki/FAQ)
|
||||||
|
|
||||||
|
The [wiki](https://github.com/Sonarr/Sonarr/wiki) contains other information and guides
|
||||||
|
|
||||||
|
If you have a support question, please use the [support forums](https://forums.sonarr.tv/).
|
|
@ -1,29 +0,0 @@
|
||||||
name: Archive
|
|
||||||
description: Archive binaries for deployment
|
|
||||||
|
|
||||||
inputs:
|
|
||||||
os:
|
|
||||||
description: 'OS that the packaging is running on'
|
|
||||||
required: true
|
|
||||||
artifact:
|
|
||||||
description: 'Binary artifact'
|
|
||||||
required: true
|
|
||||||
archive_type:
|
|
||||||
description: 'File type to use for the final package'
|
|
||||||
required: true
|
|
||||||
branch:
|
|
||||||
description: 'Git branch used for this build'
|
|
||||||
required: true
|
|
||||||
major_version:
|
|
||||||
description: 'Sonarr major version'
|
|
||||||
required: true
|
|
||||||
version:
|
|
||||||
description: 'Sonarr version'
|
|
||||||
required: true
|
|
||||||
|
|
||||||
runs:
|
|
||||||
using: 'composite'
|
|
||||||
steps:
|
|
||||||
- name: Archive Artifact
|
|
||||||
uses: thedoctor0/zip-release@0.7.5
|
|
||||||
|
|
|
@ -1,78 +0,0 @@
|
||||||
name: Package
|
|
||||||
description: Packages binaries for deployment
|
|
||||||
|
|
||||||
inputs:
|
|
||||||
platform:
|
|
||||||
description: 'Binary platform'
|
|
||||||
required: true
|
|
||||||
framework:
|
|
||||||
description: '.net framework'
|
|
||||||
required: true
|
|
||||||
artifact:
|
|
||||||
description: 'Binary artifact'
|
|
||||||
required: true
|
|
||||||
branch:
|
|
||||||
description: 'Git branch used for this build'
|
|
||||||
required: true
|
|
||||||
major_version:
|
|
||||||
description: 'Sonarr major version'
|
|
||||||
required: true
|
|
||||||
version:
|
|
||||||
description: 'Sonarr version'
|
|
||||||
required: true
|
|
||||||
|
|
||||||
runs:
|
|
||||||
using: 'composite'
|
|
||||||
steps:
|
|
||||||
- name: Download Artifact
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: ${{ inputs.artifact }}
|
|
||||||
path: _output
|
|
||||||
|
|
||||||
- name: Download UI Artifact
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: build_ui
|
|
||||||
path: _output/UI
|
|
||||||
|
|
||||||
- name: Configure Environment Variables
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
echo "FRAMEWORK=${{ inputs.framework }}" >> "$GITHUB_ENV"
|
|
||||||
echo "BRANCH=${{ inputs.branch }}" >> "$GITHUB_ENV"
|
|
||||||
echo "SONARR_MAJOR_VERSION=${{ inputs.major_version }}" >> "$GITHUB_ENV"
|
|
||||||
echo "SONARR_VERSION=${{ inputs.version }}" >> "$GITHUB_ENV"
|
|
||||||
|
|
||||||
- name: Create Packages
|
|
||||||
shell: bash
|
|
||||||
run: $GITHUB_ACTION_PATH/package.sh
|
|
||||||
|
|
||||||
- name: Create Windows Installer (x64)
|
|
||||||
if: ${{ inputs.platform == 'windows' }}
|
|
||||||
working-directory: distribution/windows/setup
|
|
||||||
shell: cmd
|
|
||||||
run: |
|
|
||||||
SET RUNTIME=win-x64
|
|
||||||
|
|
||||||
build.bat
|
|
||||||
|
|
||||||
- name: Create Windows Installer (x86)
|
|
||||||
if: ${{ inputs.platform == 'windows' }}
|
|
||||||
working-directory: distribution/windows/setup
|
|
||||||
shell: cmd
|
|
||||||
run: |
|
|
||||||
SET RUNTIME=win-x86
|
|
||||||
|
|
||||||
build.bat
|
|
||||||
|
|
||||||
- name: Upload Artifact
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: release_${{ inputs.platform }}
|
|
||||||
compression-level: 0
|
|
||||||
if-no-files-found: error
|
|
||||||
path: |
|
|
||||||
_artifacts/*.exe
|
|
||||||
_artifacts/*.tar.gz
|
|
||||||
_artifacts/*.zip
|
|
|
@ -1,67 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
|
|
||||||
outputFolder=_output
|
|
||||||
artifactsFolder=_artifacts
|
|
||||||
uiFolder="$outputFolder/UI"
|
|
||||||
framework="${FRAMEWORK:=net6.0}"
|
|
||||||
|
|
||||||
rm -rf $artifactsFolder
|
|
||||||
mkdir $artifactsFolder
|
|
||||||
|
|
||||||
for runtime in _output/*
|
|
||||||
do
|
|
||||||
name="${runtime##*/}"
|
|
||||||
folderName="$runtime/$framework"
|
|
||||||
sonarrFolder="$folderName/Sonarr"
|
|
||||||
archiveName="Sonarr.$BRANCH.$SONARR_VERSION.$name"
|
|
||||||
|
|
||||||
if [[ "$name" == 'UI' ]]; then
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "Creating package for $name"
|
|
||||||
|
|
||||||
echo "Copying UI"
|
|
||||||
cp -r $uiFolder $sonarrFolder
|
|
||||||
|
|
||||||
echo "Setting permissions"
|
|
||||||
find $sonarrFolder -name "ffprobe" -exec chmod a+x {} \;
|
|
||||||
find $sonarrFolder -name "Sonarr" -exec chmod a+x {} \;
|
|
||||||
find $sonarrFolder -name "Sonarr.Update" -exec chmod a+x {} \;
|
|
||||||
|
|
||||||
if [[ "$name" == *"osx"* ]]; then
|
|
||||||
echo "Creating macOS package"
|
|
||||||
|
|
||||||
packageName="$name-app"
|
|
||||||
packageFolder="$outputFolder/$packageName"
|
|
||||||
|
|
||||||
rm -rf $packageFolder
|
|
||||||
mkdir $packageFolder
|
|
||||||
|
|
||||||
cp -r distribution/macOS/Sonarr.app $packageFolder
|
|
||||||
mkdir -p $packageFolder/Sonarr.app/Contents/MacOS
|
|
||||||
|
|
||||||
echo "Copying Binaries"
|
|
||||||
cp -r $sonarrFolder/* $packageFolder/Sonarr.app/Contents/MacOS
|
|
||||||
|
|
||||||
echo "Removing Update Folder"
|
|
||||||
rm -r $packageFolder/Sonarr.app/Contents/MacOS/Sonarr.Update
|
|
||||||
|
|
||||||
echo "Packaging macOS app Artifact"
|
|
||||||
(cd $packageFolder; zip -rq "../../$artifactsFolder/$archiveName-app.zip" ./Sonarr.app)
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "Packaging Artifact"
|
|
||||||
if [[ "$name" == *"linux"* ]] || [[ "$name" == *"osx"* ]] || [[ "$name" == *"freebsd"* ]]; then
|
|
||||||
tar -zcf "./$artifactsFolder/$archiveName.tar.gz" -C $folderName Sonarr
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ "$name" == *"win"* ]]; then
|
|
||||||
if [ "$RUNNER_OS" = "Windows" ]
|
|
||||||
then
|
|
||||||
(cd $folderName; 7z a -tzip "../../../$artifactsFolder/$archiveName.zip" ./Sonarr)
|
|
||||||
else
|
|
||||||
(cd $folderName; zip -rq "../../../$artifactsFolder/$archiveName.zip" ./Sonarr)
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
done
|
|
|
@ -1,18 +0,0 @@
|
||||||
name: Publish Test Artifact
|
|
||||||
description: Publishes a test artifact
|
|
||||||
|
|
||||||
inputs:
|
|
||||||
framework:
|
|
||||||
description: '.net framework'
|
|
||||||
required: true
|
|
||||||
runtime:
|
|
||||||
description: '.net runtime'
|
|
||||||
required: true
|
|
||||||
|
|
||||||
runs:
|
|
||||||
using: 'composite'
|
|
||||||
steps:
|
|
||||||
- uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: tests-${{ inputs.runtime }}
|
|
||||||
path: _tests/${{ inputs.framework }}/${{ inputs.runtime }}/publish/**/*
|
|
|
@ -1,87 +0,0 @@
|
||||||
name: Test
|
|
||||||
description: Runs unit/integration tests
|
|
||||||
|
|
||||||
inputs:
|
|
||||||
use_postgres:
|
|
||||||
description: 'Whether postgres should be used for the database'
|
|
||||||
os:
|
|
||||||
description: 'OS that the tests are running on'
|
|
||||||
required: true
|
|
||||||
artifact:
|
|
||||||
description: 'Test binary artifact'
|
|
||||||
required: true
|
|
||||||
pattern:
|
|
||||||
description: 'Pattern for DLLs'
|
|
||||||
required: true
|
|
||||||
filter:
|
|
||||||
description: 'Filter for tests'
|
|
||||||
required: true
|
|
||||||
integration_tests:
|
|
||||||
description: 'True if running integration tests'
|
|
||||||
binary_artifact:
|
|
||||||
description: 'Binary artifact for integration tests'
|
|
||||||
binary_path:
|
|
||||||
description: 'Path witin binary artifact for integration tests'
|
|
||||||
|
|
||||||
runs:
|
|
||||||
using: 'composite'
|
|
||||||
steps:
|
|
||||||
- name: Setup .NET
|
|
||||||
uses: actions/setup-dotnet@v4
|
|
||||||
|
|
||||||
- name: Setup Postgres
|
|
||||||
if: ${{ inputs.use_postgres }}
|
|
||||||
uses: ikalnytskyi/action-setup-postgres@v4
|
|
||||||
|
|
||||||
- name: Setup Test Variables
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
echo "RESULTS_NAME=${{ inputs.integration_tests && 'integation-' || 'unit-' }}${{ inputs.artifact }}${{ inputs.use_postgres && '-postgres' }}" >> "$GITHUB_ENV"
|
|
||||||
|
|
||||||
- name: Setup Postgres Environment Variables
|
|
||||||
if: ${{ inputs.use_postgres }}
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
echo "Sonarr__Postgres__Host=localhost" >> "$GITHUB_ENV"
|
|
||||||
echo "Sonarr__Postgres__Port=5432" >> "$GITHUB_ENV"
|
|
||||||
echo "Sonarr__Postgres__User=postgres" >> "$GITHUB_ENV"
|
|
||||||
echo "Sonarr__Postgres__Password=postgres" >> "$GITHUB_ENV"
|
|
||||||
|
|
||||||
- name: Download Artifact
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: ${{ inputs.artifact }}
|
|
||||||
path: _tests
|
|
||||||
|
|
||||||
- name: Download Binary Artifact
|
|
||||||
if: ${{ inputs.integration_tests }}
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: ${{ inputs.binary_artifact }}
|
|
||||||
path: _output
|
|
||||||
|
|
||||||
- name: Set up binary artifact
|
|
||||||
if: ${{ inputs.binary_path != '' }}
|
|
||||||
shell: bash
|
|
||||||
run: mv ./_output/${{inputs.binary_path}} _tests/bin
|
|
||||||
|
|
||||||
- name: Make executable
|
|
||||||
if: startsWith(inputs.os, 'windows') != true
|
|
||||||
shell: bash
|
|
||||||
run: chmod +x ./_tests/Sonarr.Test.Dummy && chmod +x ./_tests/ffprobe
|
|
||||||
|
|
||||||
- name: Make Sonarr binary executable
|
|
||||||
if: ${{ inputs.integration_tests && !startsWith(inputs.os, 'windows') }}
|
|
||||||
shell: bash
|
|
||||||
run: chmod +x ./_tests/bin/Sonarr
|
|
||||||
|
|
||||||
- name: Run tests
|
|
||||||
shell: bash
|
|
||||||
run: dotnet test ./_tests/Sonarr.*.Test.dll --filter "${{ inputs.filter }}" --logger "trx;LogFileName=${{ env.RESULTS_NAME }}.trx" --logger "GitHubActions;summary.includePassedTests=true;summary.includeSkippedTests=true"
|
|
||||||
|
|
||||||
- name: Upload Test Results
|
|
||||||
if: ${{ !cancelled() }}
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: results-${{ env.RESULTS_NAME }}
|
|
||||||
path: TestResults/*.trx
|
|
|
@ -1,12 +0,0 @@
|
||||||
# To get started with Dependabot version updates, you'll need to specify which
|
|
||||||
# package ecosystems to update and where the package manifests are located.
|
|
||||||
# Please see the documentation for more information:
|
|
||||||
# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
|
|
||||||
# https://containers.dev/guide/dependabot
|
|
||||||
|
|
||||||
version: 2
|
|
||||||
updates:
|
|
||||||
- package-ecosystem: "devcontainers"
|
|
||||||
directory: "/"
|
|
||||||
schedule:
|
|
||||||
interval: weekly
|
|
|
@ -1,23 +0,0 @@
|
||||||
'connection':
|
|
||||||
- changed-files:
|
|
||||||
- any-glob-to-any-file: src/NzbDrone.Core/Notifications/**/*
|
|
||||||
|
|
||||||
'db-migration':
|
|
||||||
- changed-files:
|
|
||||||
- any-glob-to-any-file: src/NzbDrone.Core/Datastore/Migration/*
|
|
||||||
|
|
||||||
'download-client':
|
|
||||||
- changed-files:
|
|
||||||
- any-glob-to-any-file: src/NzbDrone.Core/Download/Clients/**/*
|
|
||||||
|
|
||||||
'indexer':
|
|
||||||
- changed-files:
|
|
||||||
- any-glob-to-any-file: src/NzbDrone.Core/Indexers/**/*
|
|
||||||
|
|
||||||
'parsing':
|
|
||||||
- changed-files:
|
|
||||||
- any-glob-to-any-file: src/NzbDrone.Core/Parser/**/*
|
|
||||||
|
|
||||||
'ui-only':
|
|
||||||
- changed-files:
|
|
||||||
- any-glob-to-all-files: frontend/**/*
|
|
|
@ -1,9 +0,0 @@
|
||||||
changelog:
|
|
||||||
exclude:
|
|
||||||
authors:
|
|
||||||
- Weblate
|
|
||||||
- SonarrBot
|
|
||||||
categories:
|
|
||||||
- title: Changes
|
|
||||||
labels:
|
|
||||||
- '*'
|
|
|
@ -1,52 +0,0 @@
|
||||||
name: 'API Docs'
|
|
||||||
|
|
||||||
on:
|
|
||||||
workflow_dispatch:
|
|
||||||
schedule:
|
|
||||||
- cron: '0 0 * * 1'
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- develop
|
|
||||||
paths:
|
|
||||||
- ".github/workflows/api_docs.yml"
|
|
||||||
- "docs.sh"
|
|
||||||
- "src/Sonarr.Api.*/**"
|
|
||||||
- "src/Sonarr.Http/**"
|
|
||||||
- "src/**/*.csproj"
|
|
||||||
- "src/*"
|
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: ${{ github.workflow }}-${{ github.ref }}
|
|
||||||
cancel-in-progress: true
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
api_docs:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
if: github.repository == 'Sonarr/Sonarr'
|
|
||||||
permissions:
|
|
||||||
contents: write
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Setup dotnet
|
|
||||||
uses: actions/setup-dotnet@v4
|
|
||||||
id: setup-dotnet
|
|
||||||
|
|
||||||
- name: Create openapi.json
|
|
||||||
run: ./docs.sh Linux
|
|
||||||
|
|
||||||
- name: Commit API Docs Change
|
|
||||||
continue-on-error: true
|
|
||||||
run: |
|
|
||||||
git config --global user.email "development@sonarr.tv"
|
|
||||||
git config --global user.name "Sonarr"
|
|
||||||
git checkout -b api-docs
|
|
||||||
git add src
|
|
||||||
if git status | grep -q modified
|
|
||||||
then
|
|
||||||
git commit -am 'Automated API Docs update' -m "ignore-downstream"
|
|
||||||
git push -f --set-upstream origin api-docs
|
|
||||||
curl -X POST -H "Authorization: Bearer ${{ secrets.OPENAPI_PAT }}" -H "Accept: application/vnd.github+json" https://api.github.com/repos/sonarr/sonarr/pulls -d '{"head":"api-docs","base":"develop","title":"Update API docs"}'
|
|
||||||
else
|
|
||||||
echo "No changes since last run"
|
|
||||||
fi
|
|
|
@ -1,257 +0,0 @@
|
||||||
name: Build
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- develop
|
|
||||||
- main
|
|
||||||
paths-ignore:
|
|
||||||
- "src/Sonarr.Api.*/openapi.json"
|
|
||||||
pull_request:
|
|
||||||
branches:
|
|
||||||
- develop
|
|
||||||
paths-ignore:
|
|
||||||
- "src/NzbDrone.Core/Localization/Core/**"
|
|
||||||
- "src/Sonarr.Api.*/openapi.json"
|
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
|
||||||
cancel-in-progress: true
|
|
||||||
|
|
||||||
env:
|
|
||||||
FRAMEWORK: net6.0
|
|
||||||
RAW_BRANCH_NAME: ${{ github.head_ref || github.ref_name }}
|
|
||||||
SONARR_MAJOR_VERSION: 4
|
|
||||||
VERSION: 4.0.8
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
backend:
|
|
||||||
runs-on: windows-latest
|
|
||||||
outputs:
|
|
||||||
framework: ${{ steps.variables.outputs.framework }}
|
|
||||||
major_version: ${{ steps.variables.outputs.major_version }}
|
|
||||||
version: ${{ steps.variables.outputs.version }}
|
|
||||||
steps:
|
|
||||||
- name: Check out
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Setup .NET
|
|
||||||
uses: actions/setup-dotnet@v4
|
|
||||||
|
|
||||||
- name: Setup Environment Variables
|
|
||||||
id: variables
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
# Add 800 to the build number because GitHub won't let us pick an arbitrary starting point
|
|
||||||
SONARR_VERSION="${{ env.VERSION }}.$((${{ github.run_number }}+800))"
|
|
||||||
DOTNET_VERSION=$(jq -r '.sdk.version' global.json)
|
|
||||||
|
|
||||||
echo "SDK_PATH=${{ env.DOTNET_ROOT }}/sdk/${DOTNET_VERSION}" >> "$GITHUB_ENV"
|
|
||||||
echo "SONARR_VERSION=$SONARR_VERSION" >> "$GITHUB_ENV"
|
|
||||||
echo "BRANCH=${RAW_BRANCH_NAME//\//-}" >> "$GITHUB_ENV"
|
|
||||||
|
|
||||||
echo "framework=${{ env.FRAMEWORK }}" >> "$GITHUB_OUTPUT"
|
|
||||||
echo "major_version=${{ env.SONARR_MAJOR_VERSION }}" >> "$GITHUB_OUTPUT"
|
|
||||||
echo "version=$SONARR_VERSION" >> "$GITHUB_OUTPUT"
|
|
||||||
|
|
||||||
- name: Enable Extra Platforms In SDK
|
|
||||||
shell: bash
|
|
||||||
run: ./build.sh --enable-extra-platforms-in-sdk
|
|
||||||
|
|
||||||
- name: Build Backend
|
|
||||||
shell: bash
|
|
||||||
run: ./build.sh --backend --enable-extra-platforms --packages
|
|
||||||
|
|
||||||
# Test Artifacts
|
|
||||||
|
|
||||||
- name: Publish win-x64 Test Artifact
|
|
||||||
uses: ./.github/actions/publish-test-artifact
|
|
||||||
with:
|
|
||||||
framework: ${{ env.FRAMEWORK }}
|
|
||||||
runtime: win-x64
|
|
||||||
|
|
||||||
- name: Publish linux-x64 Test Artifact
|
|
||||||
uses: ./.github/actions/publish-test-artifact
|
|
||||||
with:
|
|
||||||
framework: ${{ env.FRAMEWORK }}
|
|
||||||
runtime: linux-x64
|
|
||||||
|
|
||||||
- name: Publish osx-arm64 Test Artifact
|
|
||||||
uses: ./.github/actions/publish-test-artifact
|
|
||||||
with:
|
|
||||||
framework: ${{ env.FRAMEWORK }}
|
|
||||||
runtime: osx-arm64
|
|
||||||
|
|
||||||
# Build Artifacts (grouped by OS)
|
|
||||||
|
|
||||||
- name: Publish FreeBSD Artifact
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: build_freebsd
|
|
||||||
path: _artifacts/freebsd-*/**/*
|
|
||||||
- name: Publish Linux Artifact
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: build_linux
|
|
||||||
path: _artifacts/linux-*/**/*
|
|
||||||
- name: Publish macOS Artifact
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: build_macos
|
|
||||||
path: _artifacts/osx-*/**/*
|
|
||||||
- name: Publish Windows Artifact
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: build_windows
|
|
||||||
path: _artifacts/win-*/**/*
|
|
||||||
|
|
||||||
frontend:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Check out
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Volta
|
|
||||||
uses: volta-cli/action@v4
|
|
||||||
|
|
||||||
- name: Yarn Install
|
|
||||||
run: yarn install
|
|
||||||
|
|
||||||
- name: Lint
|
|
||||||
run: yarn lint
|
|
||||||
|
|
||||||
- name: Stylelint
|
|
||||||
run: yarn stylelint -f github
|
|
||||||
|
|
||||||
- name: Build
|
|
||||||
run: yarn build --env production
|
|
||||||
|
|
||||||
- name: Publish UI Artifact
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: build_ui
|
|
||||||
path: _output/UI/**/*
|
|
||||||
|
|
||||||
unit_test:
|
|
||||||
needs: backend
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
os: [ubuntu-latest, macos-latest, windows-latest]
|
|
||||||
include:
|
|
||||||
- os: ubuntu-latest
|
|
||||||
artifact: tests-linux-x64
|
|
||||||
filter: TestCategory!=ManualTest&TestCategory!=WINDOWS&TestCategory!=IntegrationTest&TestCategory!=AutomationTest
|
|
||||||
- os: macos-latest
|
|
||||||
artifact: tests-osx-arm64
|
|
||||||
filter: TestCategory!=ManualTest&TestCategory!=WINDOWS&TestCategory!=IntegrationTest&TestCategory!=AutomationTest
|
|
||||||
- os: windows-latest
|
|
||||||
artifact: tests-win-x64
|
|
||||||
filter: TestCategory!=ManualTest&TestCategory!=LINUX&TestCategory!=IntegrationTest&TestCategory!=AutomationTest
|
|
||||||
runs-on: ${{ matrix.os }}
|
|
||||||
steps:
|
|
||||||
- name: Check out
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Test
|
|
||||||
uses: ./.github/actions/test
|
|
||||||
with:
|
|
||||||
os: ${{ matrix.os }}
|
|
||||||
artifact: ${{ matrix.artifact }}
|
|
||||||
pattern: Sonarr.*.Test.dll
|
|
||||||
filter: ${{ matrix.filter }}
|
|
||||||
|
|
||||||
unit_test_postgres:
|
|
||||||
needs: backend
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Check out
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Test
|
|
||||||
uses: ./.github/actions/test
|
|
||||||
with:
|
|
||||||
os: ubuntu-latest
|
|
||||||
artifact: tests-linux-x64
|
|
||||||
pattern: Sonarr.*.Test.dll
|
|
||||||
filter: TestCategory!=ManualTest&TestCategory!=WINDOWS&TestCategory!=IntegrationTest&TestCategory!=AutomationTest
|
|
||||||
use_postgres: true
|
|
||||||
|
|
||||||
integration_test:
|
|
||||||
needs: backend
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
os: [ubuntu-latest, macos-latest, windows-latest]
|
|
||||||
include:
|
|
||||||
- os: ubuntu-latest
|
|
||||||
artifact: tests-linux-x64
|
|
||||||
filter: TestCategory!=ManualTest&TestCategory!=WINDOWS&TestCategory=IntegrationTest
|
|
||||||
binary_artifact: build_linux
|
|
||||||
binary_path: linux-x64/${{ needs.backend.outputs.framework }}/Sonarr
|
|
||||||
- os: macos-latest
|
|
||||||
artifact: tests-osx-arm64
|
|
||||||
filter: TestCategory!=ManualTest&TestCategory!=WINDOWS&TestCategory=IntegrationTest
|
|
||||||
binary_artifact: build_macos
|
|
||||||
binary_path: osx-arm64/${{ needs.backend.outputs.framework }}/Sonarr
|
|
||||||
- os: windows-latest
|
|
||||||
artifact: tests-win-x64
|
|
||||||
filter: TestCategory!=ManualTest&TestCategory!=LINUX&TestCategory=IntegrationTest
|
|
||||||
binary_artifact: build_windows
|
|
||||||
binary_path: win-x64/${{ needs.backend.outputs.framework }}/Sonarr
|
|
||||||
runs-on: ${{ matrix.os }}
|
|
||||||
steps:
|
|
||||||
- name: Check out
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Test
|
|
||||||
uses: ./.github/actions/test
|
|
||||||
with:
|
|
||||||
os: ${{ matrix.os }}
|
|
||||||
artifact: ${{ matrix.artifact }}
|
|
||||||
pattern: Sonarr.*.Test.dll
|
|
||||||
filter: ${{ matrix.filter }}
|
|
||||||
integration_tests: true
|
|
||||||
binary_artifact: ${{ matrix.binary_artifact }}
|
|
||||||
binary_path: ${{ matrix.binary_path }}
|
|
||||||
|
|
||||||
deploy:
|
|
||||||
if: ${{ github.ref_name == 'develop' || github.ref_name == 'main' }}
|
|
||||||
needs: [backend, frontend, unit_test, unit_test_postgres, integration_test]
|
|
||||||
secrets: inherit
|
|
||||||
uses: ./.github/workflows/deploy.yml
|
|
||||||
with:
|
|
||||||
framework: ${{ needs.backend.outputs.framework }}
|
|
||||||
branch: ${{ github.ref_name }}
|
|
||||||
major_version: ${{ needs.backend.outputs.major_version }}
|
|
||||||
version: ${{ needs.backend.outputs.version }}
|
|
||||||
|
|
||||||
notify:
|
|
||||||
name: Discord Notification
|
|
||||||
needs:
|
|
||||||
[
|
|
||||||
backend,
|
|
||||||
frontend,
|
|
||||||
unit_test,
|
|
||||||
unit_test_postgres,
|
|
||||||
integration_test,
|
|
||||||
deploy,
|
|
||||||
]
|
|
||||||
if: ${{ !cancelled() && (github.ref_name == 'develop' || github.ref_name == 'main') }}
|
|
||||||
env:
|
|
||||||
STATUS: ${{ contains(needs.*.result, 'failure') && 'failure' || 'success' }}
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Notify
|
|
||||||
uses: tsickert/discord-webhook@v6.0.0
|
|
||||||
with:
|
|
||||||
webhook-url: ${{ secrets.DISCORD_WEBHOOK_URL }}
|
|
||||||
username: "GitHub Actions"
|
|
||||||
avatar-url: "https://github.githubassets.com/images/modules/logos_page/GitHub-Mark.png"
|
|
||||||
embed-title: "${{ github.workflow }}: ${{ env.STATUS == 'success' && 'Success' || 'Failure' }}"
|
|
||||||
embed-url: "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}"
|
|
||||||
embed-description: |
|
|
||||||
**Branch** ${{ github.ref }}
|
|
||||||
**Build** ${{ needs.backend.outputs.version }}
|
|
||||||
embed-color: ${{ env.STATUS == 'success' && '3066993' || '15158332' }}
|
|
|
@ -1,26 +0,0 @@
|
||||||
name: Merge Conflict Labeler
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- develop
|
|
||||||
pull_request_target:
|
|
||||||
branches:
|
|
||||||
- develop
|
|
||||||
types: [synchronize]
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
label:
|
|
||||||
name: Labeling
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
if: ${{ github.repository == 'Sonarr/Sonarr' }}
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
pull-requests: write
|
|
||||||
steps:
|
|
||||||
- name: Apply label
|
|
||||||
uses: eps1lon/actions-label-merge-conflict@v3
|
|
||||||
with:
|
|
||||||
dirtyLabel: 'merge-conflict'
|
|
||||||
repoToken: '${{ secrets.GITHUB_TOKEN }}'
|
|
||||||
|
|
|
@ -1,160 +0,0 @@
|
||||||
name: Deploy
|
|
||||||
|
|
||||||
on:
|
|
||||||
workflow_call:
|
|
||||||
inputs:
|
|
||||||
framework:
|
|
||||||
description: '.net framework'
|
|
||||||
type: string
|
|
||||||
required: true
|
|
||||||
branch:
|
|
||||||
description: 'Git branch used for this build'
|
|
||||||
type: string
|
|
||||||
required: true
|
|
||||||
major_version:
|
|
||||||
description: 'Sonarr major version'
|
|
||||||
type: string
|
|
||||||
required: true
|
|
||||||
version:
|
|
||||||
description: 'Sonarr version'
|
|
||||||
type: string
|
|
||||||
required: true
|
|
||||||
secrets:
|
|
||||||
SERVICES_API_KEY:
|
|
||||||
required: true
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
package:
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
platform: [freebsd, linux, macos, windows]
|
|
||||||
include:
|
|
||||||
- platform: freebsd
|
|
||||||
os: ubuntu-latest
|
|
||||||
- platform: linux
|
|
||||||
os: ubuntu-latest
|
|
||||||
- platform: macos
|
|
||||||
os: ubuntu-latest
|
|
||||||
- platform: windows
|
|
||||||
os: windows-latest
|
|
||||||
|
|
||||||
runs-on: ${{ matrix.os }}
|
|
||||||
steps:
|
|
||||||
- name: Check out
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Package
|
|
||||||
uses: ./.github/actions/package
|
|
||||||
with:
|
|
||||||
framework: ${{ inputs.framework }}
|
|
||||||
platform: ${{ matrix.platform }}
|
|
||||||
artifact: build_${{ matrix.platform }}
|
|
||||||
branch: ${{ inputs.branch }}
|
|
||||||
major_version: ${{ inputs.major_version }}
|
|
||||||
version: ${{ inputs.version }}
|
|
||||||
|
|
||||||
release:
|
|
||||||
needs: package
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
permissions:
|
|
||||||
contents: write
|
|
||||||
steps:
|
|
||||||
- name: Check out
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Download release artifacts
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
path: _artifacts
|
|
||||||
pattern: release_*
|
|
||||||
merge-multiple: true
|
|
||||||
|
|
||||||
- name: Get Previous Release
|
|
||||||
id: previous-release
|
|
||||||
uses: cardinalby/git-get-release-action@v1
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ github.token }}
|
|
||||||
with:
|
|
||||||
latest: true
|
|
||||||
prerelease: ${{ inputs.branch != 'main' }}
|
|
||||||
|
|
||||||
- name: Generate Release Notes
|
|
||||||
id: generate-release-notes
|
|
||||||
uses: actions/github-script@v7
|
|
||||||
with:
|
|
||||||
github-token: ${{ github.token }}
|
|
||||||
result-encoding: string
|
|
||||||
script: |
|
|
||||||
const { data } = await github.rest.repos.generateReleaseNotes({
|
|
||||||
owner: context.repo.owner,
|
|
||||||
repo: context.repo.repo,
|
|
||||||
tag_name: 'v${{ inputs.version }}',
|
|
||||||
target_commitish: '${{ github.sha }}',
|
|
||||||
previous_tag_name: '${{ steps.previous-release.outputs.tag_name }}',
|
|
||||||
})
|
|
||||||
return data.body
|
|
||||||
|
|
||||||
- name: Create release
|
|
||||||
uses: ncipollo/release-action@v1
|
|
||||||
with:
|
|
||||||
artifacts: _artifacts/Sonarr.*
|
|
||||||
commit: ${{ github.sha }}
|
|
||||||
generateReleaseNotes: false
|
|
||||||
body: ${{ steps.generate-release-notes.outputs.result }}
|
|
||||||
name: ${{ inputs.version }}
|
|
||||||
prerelease: ${{ inputs.branch != 'main' }}
|
|
||||||
skipIfReleaseExists: true
|
|
||||||
tag: v${{ inputs.version }}
|
|
||||||
|
|
||||||
- name: Publish to Services
|
|
||||||
shell: bash
|
|
||||||
working-directory: _artifacts
|
|
||||||
run: |
|
|
||||||
branch=${{ inputs.branch }}
|
|
||||||
version=${{ inputs.version }}
|
|
||||||
lastCommit=${{ github.sha }}
|
|
||||||
|
|
||||||
hashes="["
|
|
||||||
|
|
||||||
addHash() {
|
|
||||||
path=$1
|
|
||||||
os=$2
|
|
||||||
arch=$3
|
|
||||||
type=$4
|
|
||||||
|
|
||||||
local hash=$(sha256sum *.$version.$path | awk '{ print $1; }')
|
|
||||||
echo "{ \""Os\"": \""$os\"", \""Arch\"": \""$arch\"", \""Type\"": \""$type\"", \""Hash\"": \""$hash\"" }"
|
|
||||||
}
|
|
||||||
|
|
||||||
hashes="$hashes $(addHash "linux-arm.tar.gz" "linux" "arm" "archive")"
|
|
||||||
hashes="$hashes, $(addHash "linux-arm64.tar.gz" "linux" "arm64" "archive")"
|
|
||||||
hashes="$hashes, $(addHash "linux-x64.tar.gz" "linux" "x64" "archive")"
|
|
||||||
# hashes="$hashes, $(addHash "linux-x86.tar.gz" "linux" "x86" "archive")"
|
|
||||||
|
|
||||||
# hashes="$hashes, $(addHash "linux-musl-arm.tar.gz" "linuxmusl" "arm" "archive")"
|
|
||||||
hashes="$hashes, $(addHash "linux-musl-arm64.tar.gz" "linuxmusl" "arm64" "archive")"
|
|
||||||
hashes="$hashes, $(addHash "linux-musl-x64.tar.gz" "linuxmusl" "x64" "archive")"
|
|
||||||
|
|
||||||
hashes="$hashes, $(addHash "osx-arm64.tar.gz" "osx" "arm64" "archive")"
|
|
||||||
hashes="$hashes, $(addHash "osx-x64.tar.gz" "osx" "x64" "archive")"
|
|
||||||
|
|
||||||
hashes="$hashes, $(addHash "osx-arm64-app.zip" "osx" "arm64" "installer")"
|
|
||||||
hashes="$hashes, $(addHash "osx-x64-app.zip" "osx" "x64" "installer")"
|
|
||||||
|
|
||||||
hashes="$hashes, $(addHash "win-x64.zip" "windows" "x64" "archive")"
|
|
||||||
hashes="$hashes, $(addHash "win-x86.zip" "windows" "x86" "archive")"
|
|
||||||
|
|
||||||
hashes="$hashes, $(addHash "win-x64-installer.exe" "windows" "x64" "installer")"
|
|
||||||
hashes="$hashes, $(addHash "win-x86-installer.exe" "windows" "x86" "installer")"
|
|
||||||
|
|
||||||
hashes="$hashes, $(addHash "freebsd-x64.tar.gz" "freebsd" "x64" "archive")"
|
|
||||||
|
|
||||||
hashes="$hashes ]"
|
|
||||||
|
|
||||||
json="{\""branch\"":\""$branch\"", \""version\"":\""$version\"", \""lastCommit\"":\""$lastCommit\"", \""hashes\"":$hashes, \""gitHubRelease\"":true}"
|
|
||||||
url="https://services.sonarr.tv/v1/update"
|
|
||||||
|
|
||||||
echo "Publishing update $version ($branch) to: $url"
|
|
||||||
echo "$json"
|
|
||||||
|
|
||||||
curl -H "Content-Type: application/json" -H "X-Api-Key: ${{ secrets.SERVICES_API_KEY }}" -X POST -d "$json" --fail-with-body $url
|
|
|
@ -1,13 +0,0 @@
|
||||||
name: "Pull Request Labeler"
|
|
||||||
on:
|
|
||||||
- pull_request_target
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
triage:
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
pull-requests: write
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
if: github.repository == 'Sonarr/Sonarr'
|
|
||||||
steps:
|
|
||||||
- uses: actions/labeler@v5
|
|
|
@ -1,22 +0,0 @@
|
||||||
name: 'Lock threads'
|
|
||||||
|
|
||||||
on:
|
|
||||||
workflow_dispatch:
|
|
||||||
schedule:
|
|
||||||
- cron: '0 0 * * *'
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
lock:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
if: github.repository == 'Sonarr/Sonarr'
|
|
||||||
steps:
|
|
||||||
- uses: dessant/lock-threads@v5
|
|
||||||
with:
|
|
||||||
github-token: ${{ github.token }}
|
|
||||||
issue-inactive-days: '90'
|
|
||||||
exclude-issue-created-before: ''
|
|
||||||
exclude-any-issue-labels: 'one-day-maybe'
|
|
||||||
add-issue-labels: ''
|
|
||||||
issue-comment: ''
|
|
||||||
issue-lock-reason: 'resolved'
|
|
||||||
process-only: ''
|
|
|
@ -84,6 +84,7 @@ TestResults
|
||||||
[Tt]est[Rr]esult*
|
[Tt]est[Rr]esult*
|
||||||
*.Cache
|
*.Cache
|
||||||
ClientBin
|
ClientBin
|
||||||
|
[Ss]tyle[Cc]op.*
|
||||||
~$*
|
~$*
|
||||||
*.dbmdl
|
*.dbmdl
|
||||||
Generated_Code #added for RIA/Silverlight projects
|
Generated_Code #added for RIA/Silverlight projects
|
||||||
|
@ -116,49 +117,27 @@ src/UI/.idea/*
|
||||||
*log.txt
|
*log.txt
|
||||||
node_modules/
|
node_modules/
|
||||||
_output*
|
_output*
|
||||||
_artifacts
|
|
||||||
_rawPackage/
|
_rawPackage/
|
||||||
_dotTrace*
|
_dotTrace*
|
||||||
_tests*
|
_tests*
|
||||||
_publish*
|
_publish*
|
||||||
_temp*
|
_temp*
|
||||||
*.Result.xml
|
*.Result.xml
|
||||||
coverage*.xml
|
|
||||||
coverage*.json
|
|
||||||
setup/Output/
|
setup/Output/
|
||||||
*.~is
|
*.~is
|
||||||
.mono
|
|
||||||
|
UI/
|
||||||
|
|
||||||
#VS outout folders
|
#VS outout folders
|
||||||
bin
|
bin
|
||||||
obj
|
obj
|
||||||
output/*
|
output/*
|
||||||
|
|
||||||
# .NET Core
|
|
||||||
project.lock.json
|
|
||||||
project.fragment.lock.json
|
|
||||||
artifacts/
|
|
||||||
**/Properties/launchSettings.json
|
|
||||||
|
|
||||||
# Packages
|
|
||||||
Sonarr_*/
|
|
||||||
Sonarr_*.zip
|
|
||||||
Sonarr_*.gz
|
|
||||||
gecko.zip
|
|
||||||
geckodriver.exe
|
|
||||||
|
|
||||||
#OS X metadata files
|
#OS X metadata files
|
||||||
._*
|
._*
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
|
||||||
_start
|
_start
|
||||||
_temp_*/**/*
|
|
||||||
|
|
||||||
# Windows thumbnail cache files
|
|
||||||
Thumbs.db
|
|
||||||
|
|
||||||
src/.idea/
|
src/.idea/
|
||||||
/distribution/windows/setup/output/*
|
|
||||||
|
|
||||||
# API doc generation
|
|
||||||
.config/
|
|
||||||
|
|
|
@ -1,7 +0,0 @@
|
||||||
{
|
|
||||||
"recommendations": [
|
|
||||||
"esbenp.prettier-vscode",
|
|
||||||
"ms-dotnettools.csdevkit",
|
|
||||||
"ms-vscode-remote.remote-containers"
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,26 +0,0 @@
|
||||||
{
|
|
||||||
"version": "0.2.0",
|
|
||||||
"configurations": [
|
|
||||||
{
|
|
||||||
// Use IntelliSense to find out which attributes exist for C# debugging
|
|
||||||
// Use hover for the description of the existing attributes
|
|
||||||
// For further information visit https://github.com/dotnet/vscode-csharp/blob/main/debugger-launchjson.md
|
|
||||||
"name": "Run Sonarr",
|
|
||||||
"type": "coreclr",
|
|
||||||
"request": "launch",
|
|
||||||
"preLaunchTask": "build dotnet",
|
|
||||||
// If you have changed target frameworks, make sure to update the program path.
|
|
||||||
"program": "${workspaceFolder}/_output/net6.0/Sonarr",
|
|
||||||
"args": [],
|
|
||||||
"cwd": "${workspaceFolder}",
|
|
||||||
// For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console
|
|
||||||
"console": "integratedTerminal",
|
|
||||||
"stopAtEntry": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": ".NET Core Attach",
|
|
||||||
"type": "coreclr",
|
|
||||||
"request": "attach"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,3 +0,0 @@
|
||||||
{
|
|
||||||
"typescript.tsdk": "node_modules\\typescript\\lib"
|
|
||||||
}
|
|
|
@ -1,44 +0,0 @@
|
||||||
{
|
|
||||||
"version": "2.0.0",
|
|
||||||
"tasks": [
|
|
||||||
{
|
|
||||||
"label": "build dotnet",
|
|
||||||
"command": "dotnet",
|
|
||||||
"type": "process",
|
|
||||||
"args": [
|
|
||||||
"msbuild",
|
|
||||||
"-restore",
|
|
||||||
"${workspaceFolder}/src/Sonarr.sln",
|
|
||||||
"-p:GenerateFullPaths=true",
|
|
||||||
"-p:Configuration=Debug",
|
|
||||||
"-p:Platform=Posix",
|
|
||||||
"-consoleloggerparameters:NoSummary;ForceNoAlign"
|
|
||||||
],
|
|
||||||
"problemMatcher": "$msCompile"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "publish",
|
|
||||||
"command": "dotnet",
|
|
||||||
"type": "process",
|
|
||||||
"args": [
|
|
||||||
"publish",
|
|
||||||
"${workspaceFolder}/src/Sonarr.sln",
|
|
||||||
"-property:GenerateFullPaths=true",
|
|
||||||
"-consoleloggerparameters:NoSummary;ForceNoAlign"
|
|
||||||
],
|
|
||||||
"problemMatcher": "$msCompile"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "watch",
|
|
||||||
"command": "dotnet",
|
|
||||||
"type": "process",
|
|
||||||
"args": [
|
|
||||||
"watch",
|
|
||||||
"run",
|
|
||||||
"--project",
|
|
||||||
"${workspaceFolder}/src/Sonarr.sln"
|
|
||||||
],
|
|
||||||
"problemMatcher": "$msCompile"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -3,40 +3,25 @@
|
||||||
We're always looking for people to help make Sonarr even better, there are a number of ways to contribute.
|
We're always looking for people to help make Sonarr even better, there are a number of ways to contribute.
|
||||||
|
|
||||||
## Documentation ##
|
## Documentation ##
|
||||||
Setup guides, [FAQ](https://wiki.servarr.com/sonarr/faq), the more information we have on the [wiki](https://wiki.servarr.com/sonarr) the better.
|
Setup guides, FAQ, the more information we have on the wiki the better.
|
||||||
|
|
||||||
## Development ##
|
## Development ##
|
||||||
|
|
||||||
### Tools required ###
|
See the readme for information on setting up your development environment.
|
||||||
- Visual Studio 2019 or higher (https://www.visualstudio.com/vs/). The community version is free and works (https://www.visualstudio.com/downloads/).
|
|
||||||
- HTML/Javascript editor of choice (VS Code/Sublime Text/Webstorm/Atom/etc)
|
|
||||||
- [Git](https://git-scm.com/downloads)
|
|
||||||
- [NodeJS](https://nodejs.org/en/download/) (Node 10.X.X or higher)
|
|
||||||
- [Yarn](https://yarnpkg.com/)
|
|
||||||
|
|
||||||
### Getting started ###
|
|
||||||
|
|
||||||
1. Fork Sonarr
|
|
||||||
2. Clone the repository into your development machine. [*info*](https://docs.github.com/en/get-started/quickstart/fork-a-repo)
|
|
||||||
3. Install the required Node Packages `yarn install`
|
|
||||||
4. Start webpack to monitor your dev environment for any frontend changes that need post processing using `yarn start` command.
|
|
||||||
5. Build the project in Visual Studio, Setting startup project to `Sonarr.Console` and framework to `x86`
|
|
||||||
6. Debug the project in Visual Studio
|
|
||||||
7. Open http://localhost:8989
|
|
||||||
|
|
||||||
### Contributing Code ###
|
### Contributing Code ###
|
||||||
- If you're adding a new, already requested feature, please comment on [Github Issues](https://github.com/Sonarr/Sonarr/issues "Github Issues") so work is not duplicated (If you want to add something not already on there, please talk to us first)
|
- If you're adding a new, already requested feature, please comment on [Github Issues](https://github.com/Sonarr/Sonarr/issues "Github Issues") so work is not duplicated (If you want to add something not already on there, please talk to us first)
|
||||||
- Rebase from Sonarr's `develop` branch, don't merge
|
- Rebase from Sonarr's develop branch, don't merge
|
||||||
- Make meaningful commits, or squash them
|
- Make meaningful commits, or squash them
|
||||||
- Feel free to make a pull request before work is complete, this will let us see where its at and make comments/suggest improvements
|
- Feel free to make a pull request before work is complete, this will let us see where its at and make comments/suggest improvements
|
||||||
- Reach out to us on our [forums](https://forums.sonarr.tv/), [subreddit](https://www.reddit.com/r/sonarr/), [discord](https://discord.gg/Ex7FmFK), or [IRC](https://web.libera.chat/?channels=#sonarr) if you have any questions
|
- Reach out to us on the forums or on IRC if you have any questions
|
||||||
- Add tests (unit/integration)
|
- Add tests (unit/integration)
|
||||||
- Commit with *nix line endings for consistency (We checkout Windows and commit *nix)
|
- Commit with *nix line endings for consistency (We checkout Windows and commit *nix)
|
||||||
- One feature/bug fix per pull request to keep things clean and easy to understand
|
- One feature/bug fix per pull request to keep things clean and easy to understand
|
||||||
- Use 4 spaces instead of tabs, this should be the default for VS 2019 and WebStorm
|
- Use 4 spaces instead of tabs, this is the default for VS 2012 and WebStorm (to my knowledge)
|
||||||
|
|
||||||
### Pull Requesting ###
|
### Pull Requesting ###
|
||||||
- Only make pull requests to develop (currently `develop`), never `main`, if you make a PR to master we'll comment on it and close it
|
- Only make pull requests to develop, never master, if you make a PR to master we'll comment on it and close it
|
||||||
- You're probably going to get some comments or questions from us, they will be to ensure consistency and maintainability
|
- You're probably going to get some comments or questions from us, they will be to ensure consistency and maintainability
|
||||||
- We'll try to respond to pull requests as soon as possible, if its been a day or two, please reach out to us, we may have missed it
|
- We'll try to respond to pull requests as soon as possible, if its been a day or two, please reach out to us, we may have missed it
|
||||||
- Each PR should come from its own [feature branch](http://martinfowler.com/bliki/FeatureBranch.html) not develop in your fork, it should have a meaningful branch name (what is being added/fixed)
|
- Each PR should come from its own [feature branch](http://martinfowler.com/bliki/FeatureBranch.html) not develop in your fork, it should have a meaningful branch name (what is being added/fixed)
|
||||||
|
|
12
FUNDING.yml
12
FUNDING.yml
|
@ -1,12 +0,0 @@
|
||||||
# These are supported funding model platforms
|
|
||||||
|
|
||||||
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
|
|
||||||
patreon: # Replace with a single Patreon username
|
|
||||||
open_collective: sonarr
|
|
||||||
ko_fi: # Replace with a single Ko-fi username
|
|
||||||
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
|
|
||||||
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
|
|
||||||
liberapay: # Replace with a single Liberapay username
|
|
||||||
issuehunt: # Replace with a single IssueHunt username
|
|
||||||
otechie: # Replace with a single Otechie username
|
|
||||||
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
|
|
|
@ -1,33 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!-- Generator: Adobe Illustrator 19.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
|
||||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
|
||||||
width="70px" height="70px" viewBox="0 0 70 70" style="enable-background:new 0 0 70 70;" xml:space="preserve">
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="-1.3318" y1="43.7371" x2="67.0419" y2="26.0967">
|
|
||||||
<stop offset="0.1237" style="stop-color:#7866FF"/>
|
|
||||||
<stop offset="0.5376" style="stop-color:#FE2EB6"/>
|
|
||||||
<stop offset="0.8548" style="stop-color:#FD0486"/>
|
|
||||||
</linearGradient>
|
|
||||||
<polygon style="fill:url(#SVGID_1_);" points="67.3,16 43.7,0 0,31.1 11.1,70 58.9,60.3 "/>
|
|
||||||
<linearGradient id="SVGID_2_" gradientUnits="userSpaceOnUse" x1="45.9148" y1="38.9098" x2="67.6577" y2="9.0989">
|
|
||||||
<stop offset="0.1237" style="stop-color:#FF0080"/>
|
|
||||||
<stop offset="0.2587" style="stop-color:#FE0385"/>
|
|
||||||
<stop offset="0.4109" style="stop-color:#FA0C92"/>
|
|
||||||
<stop offset="0.5713" style="stop-color:#F41BA9"/>
|
|
||||||
<stop offset="0.7363" style="stop-color:#EB2FC8"/>
|
|
||||||
<stop offset="0.8656" style="stop-color:#E343E6"/>
|
|
||||||
</linearGradient>
|
|
||||||
<polygon style="fill:url(#SVGID_2_);" points="67.3,16 43.7,0 38,15.7 38,47.8 70,47.8 "/>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<rect x="13.4" y="13.4" style="fill:#000000;" width="43.2" height="43.2"/>
|
|
||||||
<rect x="17.4" y="48.5" style="fill:#FFFFFF;" width="16.2" height="2.7"/>
|
|
||||||
<g>
|
|
||||||
<path style="fill:#FFFFFF;" d="M17.4,19.1h6.9c5.6,0,9.5,3.8,9.5,8.9V28c0,5-3.9,8.9-9.5,8.9h-6.9V19.1z M21.4,22.7v10.7h3
|
|
||||||
c3.2,0,5.4-2.2,5.4-5.3V28c0-3.2-2.2-5.4-5.4-5.4H21.4z"/>
|
|
||||||
<polygon style="fill:#FFFFFF;" points="40.3,22.7 34.9,22.7 34.9,19.1 49.6,19.1 49.6,22.7 44.2,22.7 44.2,37 40.3,37 "/>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 1.8 KiB |
|
@ -1,66 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!-- Generator: Adobe Illustrator 19.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
|
||||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
|
||||||
width="120.1px" height="130.2px" viewBox="0 0 120.1 130.2" style="enable-background:new 0 0 120.1 130.2;" xml:space="preserve"
|
|
||||||
>
|
|
||||||
<g>
|
|
||||||
<linearGradient id="XMLID_2_" gradientUnits="userSpaceOnUse" x1="31.8412" y1="120.5578" x2="110.2402" y2="73.24">
|
|
||||||
<stop offset="0" style="stop-color:#FCEE39"/>
|
|
||||||
<stop offset="1" style="stop-color:#F37B3D"/>
|
|
||||||
</linearGradient>
|
|
||||||
<path id="XMLID_3041_" style="fill:url(#XMLID_2_);" d="M118.6,71.8c0.9-0.8,1.4-1.9,1.5-3.2c0.1-2.6-1.8-4.7-4.4-4.9
|
|
||||||
c-1.2-0.1-2.4,0.4-3.3,1.1l0,0l-83.8,45.9c-1.9,0.8-3.6,2.2-4.7,4.1c-2.9,4.8-1.3,11,3.6,13.9c3.4,2,7.5,1.8,10.7-0.2l0,0l0,0
|
|
||||||
c0.2-0.2,0.5-0.3,0.7-0.5l78-54.8C117.3,72.9,118.4,72.1,118.6,71.8L118.6,71.8L118.6,71.8z"/>
|
|
||||||
<linearGradient id="XMLID_3_" gradientUnits="userSpaceOnUse" x1="48.3607" y1="6.9083" x2="119.9179" y2="69.5546">
|
|
||||||
<stop offset="0" style="stop-color:#EF5A6B"/>
|
|
||||||
<stop offset="0.57" style="stop-color:#F26F4E"/>
|
|
||||||
<stop offset="1" style="stop-color:#F37B3D"/>
|
|
||||||
</linearGradient>
|
|
||||||
<path id="XMLID_3049_" style="fill:url(#XMLID_3_);" d="M118.8,65.1L118.8,65.1L55,2.5C53.6,1,51.6,0,49.3,0
|
|
||||||
c-4.3,0-7.7,3.5-7.7,7.7v0c0,2.1,0.8,3.9,2.1,5.3l0,0l0,0c0.4,0.4,0.8,0.7,1.2,1l67.4,57.7l0,0c0.8,0.7,1.8,1.2,3,1.3
|
|
||||||
c2.6,0.1,4.7-1.8,4.9-4.4C120.2,67.3,119.7,66,118.8,65.1z"/>
|
|
||||||
<linearGradient id="XMLID_4_" gradientUnits="userSpaceOnUse" x1="52.9467" y1="63.6407" x2="10.5379" y2="37.1562">
|
|
||||||
<stop offset="0" style="stop-color:#7C59A4"/>
|
|
||||||
<stop offset="0.3852" style="stop-color:#AF4C92"/>
|
|
||||||
<stop offset="0.7654" style="stop-color:#DC4183"/>
|
|
||||||
<stop offset="0.957" style="stop-color:#ED3D7D"/>
|
|
||||||
</linearGradient>
|
|
||||||
<path id="XMLID_3042_" style="fill:url(#XMLID_4_);" d="M57.1,59.5C57,59.5,17.7,28.5,16.9,28l0,0l0,0c-0.6-0.3-1.2-0.6-1.8-0.9
|
|
||||||
c-5.8-2.2-12.2,0.8-14.4,6.6c-1.9,5.1,0.2,10.7,4.6,13.4l0,0l0,0C6,47.5,6.6,47.8,7.3,48c0.4,0.2,45.4,18.8,45.4,18.8l0,0
|
|
||||||
c1.8,0.8,3.9,0.3,5.1-1.2C59.3,63.7,59,61,57.1,59.5z"/>
|
|
||||||
<linearGradient id="XMLID_5_" gradientUnits="userSpaceOnUse" x1="52.1736" y1="3.7019" x2="10.7706" y2="37.8971">
|
|
||||||
<stop offset="0" style="stop-color:#EF5A6B"/>
|
|
||||||
<stop offset="0.364" style="stop-color:#EE4E72"/>
|
|
||||||
<stop offset="1" style="stop-color:#ED3D7D"/>
|
|
||||||
</linearGradient>
|
|
||||||
<path id="XMLID_3057_" style="fill:url(#XMLID_5_);" d="M49.3,0c-1.7,0-3.3,0.6-4.6,1.5L4.9,28.3c-0.1,0.1-0.2,0.1-0.2,0.2l-0.1,0
|
|
||||||
l0,0c-1.7,1.2-3.1,3-3.9,5.1C-1.5,39.4,1.5,45.9,7.3,48c3.6,1.4,7.5,0.7,10.4-1.4l0,0l0,0c0.7-0.5,1.3-1,1.8-1.6l34.6-31.2l0,0
|
|
||||||
c1.8-1.4,3-3.6,3-6.1v0C57.1,3.5,53.6,0,49.3,0z"/>
|
|
||||||
<g id="XMLID_3008_">
|
|
||||||
<rect id="XMLID_3033_" x="34.6" y="37.4" style="fill:#000000;" width="51" height="51"/>
|
|
||||||
<rect id="XMLID_3032_" x="39" y="78.8" style="fill:#FFFFFF;" width="19.1" height="3.2"/>
|
|
||||||
<g id="XMLID_3009_">
|
|
||||||
<path id="XMLID_3030_" style="fill:#FFFFFF;" d="M38.8,50.8l1.5-1.4c0.4,0.5,0.8,0.8,1.3,0.8c0.6,0,0.9-0.4,0.9-1.2l0-5.3l2.3,0
|
|
||||||
l0,5.3c0,1-0.3,1.8-0.8,2.3c-0.5,0.5-1.3,0.8-2.3,0.8C40.2,52.2,39.4,51.6,38.8,50.8z"/>
|
|
||||||
<path id="XMLID_3028_" style="fill:#FFFFFF;" d="M45.3,43.8l6.7,0v1.9l-4.4,0V47l4,0l0,1.8l-4,0l0,1.3l4.5,0l0,2l-6.7,0
|
|
||||||
L45.3,43.8z"/>
|
|
||||||
<path id="XMLID_3026_" style="fill:#FFFFFF;" d="M55,45.8l-2.5,0l0-2l7.3,0l0,2l-2.5,0l0,6.3l-2.3,0L55,45.8z"/>
|
|
||||||
<path id="XMLID_3022_" style="fill:#FFFFFF;" d="M39,54l4.3,0c1,0,1.8,0.3,2.3,0.7c0.3,0.3,0.5,0.8,0.5,1.4v0
|
|
||||||
c0,1-0.5,1.5-1.3,1.9c1,0.3,1.6,0.9,1.6,2v0c0,1.4-1.2,2.3-3.1,2.3l-4.3,0L39,54z M43.8,56.6c0-0.5-0.4-0.7-1-0.7l-1.5,0l0,1.5
|
|
||||||
l1.4,0C43.4,57.3,43.8,57.1,43.8,56.6L43.8,56.6z M43,59l-1.8,0l0,1.5H43c0.7,0,1.1-0.3,1.1-0.8v0C44.1,59.2,43.7,59,43,59z"/>
|
|
||||||
<path id="XMLID_3019_" style="fill:#FFFFFF;" d="M46.8,54l3.9,0c1.3,0,2.1,0.3,2.7,0.9c0.5,0.5,0.7,1.1,0.7,1.9v0
|
|
||||||
c0,1.3-0.7,2.1-1.7,2.6l2,2.9l-2.6,0l-1.7-2.5h-1l0,2.5l-2.3,0L46.8,54z M50.6,58c0.8,0,1.2-0.4,1.2-1v0c0-0.7-0.5-1-1.2-1
|
|
||||||
l-1.5,0v2H50.6z"/>
|
|
||||||
<path id="XMLID_3016_" style="fill:#FFFFFF;" d="M56.8,54l2.2,0l3.5,8.4l-2.5,0l-0.6-1.5l-3.2,0l-0.6,1.5l-2.4,0L56.8,54z
|
|
||||||
M58.8,59l-0.9-2.3L57,59L58.8,59z"/>
|
|
||||||
<path id="XMLID_3014_" style="fill:#FFFFFF;" d="M62.8,54l2.3,0l0,8.3l-2.3,0L62.8,54z"/>
|
|
||||||
<path id="XMLID_3012_" style="fill:#FFFFFF;" d="M65.7,54l2.1,0l3.4,4.4l0-4.4l2.3,0l0,8.3l-2,0L68,57.8l0,4.6l-2.3,0L65.7,54z"
|
|
||||||
/>
|
|
||||||
<path id="XMLID_3010_" style="fill:#FFFFFF;" d="M73.7,61.1l1.3-1.5c0.8,0.7,1.7,1,2.7,1c0.6,0,1-0.2,1-0.6v0
|
|
||||||
c0-0.4-0.3-0.5-1.4-0.8c-1.8-0.4-3.1-0.9-3.1-2.6v0c0-1.5,1.2-2.7,3.2-2.7c1.4,0,2.5,0.4,3.4,1.1l-1.2,1.6
|
|
||||||
c-0.8-0.5-1.6-0.8-2.3-0.8c-0.6,0-0.8,0.2-0.8,0.5v0c0,0.4,0.3,0.5,1.4,0.8c1.9,0.4,3.1,1,3.1,2.6v0c0,1.7-1.3,2.7-3.4,2.7
|
|
||||||
C76.1,62.5,74.7,62,73.7,61.1z"/>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 4.8 KiB |
|
@ -1,50 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!-- Generator: Adobe Illustrator 19.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
|
||||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
|
||||||
width="70px" height="70px" viewBox="0 0 70 70" style="enable-background:new 0 0 70 70;" xml:space="preserve">
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="22.9451" y1="75.7869" x2="74.7868" y2="20.6415">
|
|
||||||
<stop offset="1.612903e-002" style="stop-color:#B35BA3"/>
|
|
||||||
<stop offset="0.4044" style="stop-color:#C41E57"/>
|
|
||||||
<stop offset="0.4677" style="stop-color:#C41E57"/>
|
|
||||||
<stop offset="0.6505" style="stop-color:#EB8523"/>
|
|
||||||
<stop offset="0.9516" style="stop-color:#FEBD11"/>
|
|
||||||
</linearGradient>
|
|
||||||
<polygon style="fill:url(#SVGID_1_);" points="49.8,15.2 36,36.7 58.4,70 70,23.1 "/>
|
|
||||||
<linearGradient id="SVGID_2_" gradientUnits="userSpaceOnUse" x1="17.7187" y1="73.2922" x2="69.5556" y2="18.1519">
|
|
||||||
<stop offset="1.612903e-002" style="stop-color:#B35BA3"/>
|
|
||||||
<stop offset="0.4044" style="stop-color:#C41E57"/>
|
|
||||||
<stop offset="0.4677" style="stop-color:#C41E57"/>
|
|
||||||
<stop offset="0.7043" style="stop-color:#EB8523"/>
|
|
||||||
</linearGradient>
|
|
||||||
<polygon style="fill:url(#SVGID_2_);" points="51.1,15.7 49,0 18.8,33.6 27.6,42.3 20.8,70 58.4,70 "/>
|
|
||||||
</g>
|
|
||||||
<linearGradient id="SVGID_3_" gradientUnits="userSpaceOnUse" x1="1.8281" y1="53.4275" x2="48.8245" y2="9.2255">
|
|
||||||
<stop offset="1.612903e-002" style="stop-color:#B35BA3"/>
|
|
||||||
<stop offset="0.6613" style="stop-color:#C41E57"/>
|
|
||||||
</linearGradient>
|
|
||||||
<polygon style="fill:url(#SVGID_3_);" points="49,0 11.6,0 0,47.1 55.6,47.1 "/>
|
|
||||||
<linearGradient id="SVGID_4_" gradientUnits="userSpaceOnUse" x1="49.8935" y1="-11.5569" x2="48.8588" y2="24.0352">
|
|
||||||
<stop offset="0.5" style="stop-color:#C41E57"/>
|
|
||||||
<stop offset="0.6668" style="stop-color:#D13F48"/>
|
|
||||||
<stop offset="0.7952" style="stop-color:#D94F39"/>
|
|
||||||
<stop offset="0.8656" style="stop-color:#DD5433"/>
|
|
||||||
</linearGradient>
|
|
||||||
<polygon style="fill:url(#SVGID_4_);" points="55.3,47.1 51.1,15.7 49,0 41.7,23 "/>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
|
|
||||||
<rect x="13.4" y="13.5" transform="matrix(-1 2.577289e-003 -2.577289e-003 -1 70.0288 70.081)" style="fill:#000000;" width="43.2" height="43.2"/>
|
|
||||||
|
|
||||||
<rect x="17.6" y="48.6" transform="matrix(1 -2.577289e-003 2.577289e-003 1 -0.1287 6.634109e-002)" style="fill:#FFFFFF;" width="16.2" height="2.7"/>
|
|
||||||
<path style="fill:#FFFFFF;" d="M17.4,19.1l8.2,0c2.3,0,4,0.6,5.2,1.8c1,1,1.5,2.4,1.5,4.1l0,0.1c0,1.5-0.3,2.6-1.1,3.5
|
|
||||||
c-0.7,0.9-1.6,1.6-2.8,2l4.4,6.4l-4.6,0l-3.7-5.5l-3.3,0l0,5.5l-3.9,0L17.4,19.1z M25.3,27.8c1,0,1.7-0.2,2.2-0.7
|
|
||||||
c0.5-0.5,0.8-1.1,0.8-1.8l0-0.1c0-0.9-0.3-1.5-0.8-1.9c-0.5-0.4-1.3-0.6-2.3-0.6l-3.9,0l0,5.1L25.3,27.8z"/>
|
|
||||||
<path style="fill:#FFFFFF;" d="M36,33.2l-1.9,0l0-3.3l2.5,0l0.6-3.8l-2.3,0l0-3.3l2.8,0l0.6-3.7l3.4,0l-0.6,3.7l3.7,0l0.6-3.7
|
|
||||||
l3.4,0l-0.6,3.7l1.9,0l0,3.3l-2.5,0L47,29.9l2.3,0l0,3.3l-2.8,0L45.8,37l-3.4,0l0.7-3.8l-3.7,0L38.7,37l-3.4,0L36,33.2z
|
|
||||||
M43.7,29.9l0.6-3.8l-3.7,0L40,29.9L43.7,29.9z"/>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 3.1 KiB |
|
@ -1,64 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!-- Generator: Adobe Illustrator 19.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
|
||||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 70 70" style="enable-background:new 0 0 70 70;" xml:space="preserve">
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="1.7738" y1="31.2729" x2="40.1662" y2="31.2729">
|
|
||||||
<stop offset="0" style="stop-color:#905CFB"/>
|
|
||||||
<stop offset="6.772543e-002" style="stop-color:#776CF9"/>
|
|
||||||
<stop offset="0.1729" style="stop-color:#5681F7"/>
|
|
||||||
<stop offset="0.2865" style="stop-color:#3B92F5"/>
|
|
||||||
<stop offset="0.4097" style="stop-color:#269FF4"/>
|
|
||||||
<stop offset="0.5474" style="stop-color:#17A9F3"/>
|
|
||||||
<stop offset="0.7111" style="stop-color:#0FAEF2"/>
|
|
||||||
<stop offset="0.9677" style="stop-color:#0CB0F2"/>
|
|
||||||
</linearGradient>
|
|
||||||
<path style="fill:url(#SVGID_1_);" d="M39.7,47.9l-6.1-34c-0.4-2.4-1.2-4.8-2.7-7.1c-2-3.2-5.2-5.4-8.8-6.3
|
|
||||||
C7.9-2.9-2.6,11.3,3.6,23.9c0,0,0,0,0,0l14.8,31.7c0.4,1,1,2,1.7,2.9c1.2,1.6,2.8,2.8,4.7,3.4C34.4,64.9,42.1,56.4,39.7,47.9z"/>
|
|
||||||
<linearGradient id="SVGID_2_" gradientUnits="userSpaceOnUse" x1="5.3113" y1="9.6691" x2="69.2278" y2="43.8664">
|
|
||||||
<stop offset="0" style="stop-color:#905CFB"/>
|
|
||||||
<stop offset="6.772543e-002" style="stop-color:#776CF9"/>
|
|
||||||
<stop offset="0.1729" style="stop-color:#5681F7"/>
|
|
||||||
<stop offset="0.2865" style="stop-color:#3B92F5"/>
|
|
||||||
<stop offset="0.4097" style="stop-color:#269FF4"/>
|
|
||||||
<stop offset="0.5474" style="stop-color:#17A9F3"/>
|
|
||||||
<stop offset="0.7111" style="stop-color:#0FAEF2"/>
|
|
||||||
<stop offset="0.9677" style="stop-color:#0CB0F2"/>
|
|
||||||
</linearGradient>
|
|
||||||
<path style="fill:url(#SVGID_2_);" d="M67.4,26.5c-1.4-2.2-3.4-3.9-5.7-4.9L25.5,1.7l0,0c-1-0.5-2.1-1-3.3-1.3
|
|
||||||
C6.7-3.2-4.4,13.8,5.5,27c1.5,2,3.6,3.6,6,4.5L48,47.9c0.8,0.5,1.6,0.8,2.5,1.1C64.5,53.4,75.1,38.6,67.4,26.5z"/>
|
|
||||||
<linearGradient id="SVGID_3_" gradientUnits="userSpaceOnUse" x1="-19.2836" y1="70.8198" x2="55.9833" y2="33.1863">
|
|
||||||
<stop offset="0" style="stop-color:#3BEA62"/>
|
|
||||||
<stop offset="0.117" style="stop-color:#31DE80"/>
|
|
||||||
<stop offset="0.3025" style="stop-color:#24CEA8"/>
|
|
||||||
<stop offset="0.4844" style="stop-color:#1AC1C9"/>
|
|
||||||
<stop offset="0.6592" style="stop-color:#12B7DF"/>
|
|
||||||
<stop offset="0.8238" style="stop-color:#0EB2ED"/>
|
|
||||||
<stop offset="0.9677" style="stop-color:#0CB0F2"/>
|
|
||||||
</linearGradient>
|
|
||||||
<path style="fill:url(#SVGID_3_);" d="M67.4,26.5c-1.8-2.8-4.6-4.8-7.9-5.6c-3.5-0.8-6.8-0.5-9.6,0.7L11.4,36.1
|
|
||||||
c0,0-0.2,0.1-0.6,0.4C0.9,40.4-4,53.3,4,64c1.8,2.4,4.3,4.2,7.1,5c5.3,1.6,10.1,1,14-1.1c0,0,0.1,0,0.1,0l37.6-20.1
|
|
||||||
c0,0,0,0,0.1-0.1C69.5,43.9,72.6,34.6,67.4,26.5z"/>
|
|
||||||
<linearGradient id="SVGID_4_" gradientUnits="userSpaceOnUse" x1="38.9439" y1="5.8503" x2="5.4232" y2="77.5093">
|
|
||||||
<stop offset="0" style="stop-color:#3BEA62"/>
|
|
||||||
<stop offset="9.397750e-002" style="stop-color:#2FDB87"/>
|
|
||||||
<stop offset="0.196" style="stop-color:#24CEA8"/>
|
|
||||||
<stop offset="0.3063" style="stop-color:#1BC3C3"/>
|
|
||||||
<stop offset="0.4259" style="stop-color:#14BAD8"/>
|
|
||||||
<stop offset="0.5596" style="stop-color:#10B5E7"/>
|
|
||||||
<stop offset="0.7185" style="stop-color:#0DB1EF"/>
|
|
||||||
<stop offset="0.9677" style="stop-color:#0CB0F2"/>
|
|
||||||
</linearGradient>
|
|
||||||
<path style="fill:url(#SVGID_4_);" d="M50.3,12.8c1.2-2.7,1.1-6-0.9-9c-1.1-1.8-2.9-3-4.9-3.5c-4.5-1.1-8.3,1-10.1,4.2L3.5,42
|
|
||||||
c0,0,0,0,0,0.1C-0.9,47.9-1.6,56.5,4,64c1.8,2.4,4.3,4.2,7.1,5c10.5,3.3,19.3-2.5,22.1-10.8L50.3,12.8z"/>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<rect x="13.4" y="13.4" style="fill:#000000;" width="43.2" height="43.2"/>
|
|
||||||
<rect x="17.5" y="48.5" style="fill:#FFFFFF;" width="16.2" height="2.7"/>
|
|
||||||
<polygon style="fill:#FFFFFF;" points="22.9,22.7 17.5,22.7 17.5,19.1 32.3,19.1 32.3,22.7 26.8,22.7 26.8,37 22.9,37 "/>
|
|
||||||
<path style="fill:#FFFFFF;" d="M32.5,28.1L32.5,28.1c0-5.1,3.8-9.3,9.3-9.3c3.4,0,5.4,1.1,7.1,2.8l-2.5,2.9c-1.4-1.3-2.8-2-4.6-2
|
|
||||||
c-3,0-5.2,2.5-5.2,5.6V28c0,3.1,2.1,5.6,5.2,5.6c2,0,3.3-0.8,4.7-2.1l2.5,2.5c-1.8,2-3.9,3.2-7.3,3.2
|
|
||||||
C36.4,37.3,32.5,33.2,32.5,28.1"/>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 4.0 KiB |
103
README.md
103
README.md
|
@ -1,81 +1,58 @@
|
||||||
# <img width="24px" src="./Logo/256.png" alt="Sonarr"></img> Sonarr
|
# Sonarr
|
||||||
|
|
||||||
[![Translated](https://translate.servarr.com/widgets/servarr/-/sonarr/svg-badge.svg)](https://translate.servarr.com/engage/servarr/)
|
|
||||||
[![Backers on Open Collective](https://opencollective.com/Sonarr/backers/badge.svg)](#backers)
|
|
||||||
[![Sponsors on Open Collective](https://opencollective.com/Sonarr/sponsors/badge.svg)](#sponsors)
|
|
||||||
[![Mega Sponsors on Open Collective](https://opencollective.com/Sonarr/megasponsors/badge.svg)](#mega-sponsors)
|
|
||||||
|
|
||||||
Sonarr is a PVR for Usenet and BitTorrent users. It can monitor multiple RSS feeds for new episodes of your favorite shows and will grab, sort and rename them. It can also be configured to automatically upgrade the quality of files already downloaded when a better quality format becomes available.
|
Sonarr is a PVR for Usenet and BitTorrent users. It can monitor multiple RSS feeds for new episodes of your favorite shows and will grab, sort and rename them. It can also be configured to automatically upgrade the quality of files already downloaded when a better quality format becomes available.
|
||||||
|
|
||||||
## Getting Started
|
## Major Features Include:
|
||||||
|
|
||||||
- [Download/Installation](https://sonarr.tv/#downloads-v3)
|
* Support for major platforms: Windows, Linux, macOS, Raspberry Pi, etc.
|
||||||
- [FAQ](https://wiki.servarr.com/sonarr/faq)
|
* Automatically detects new episodes
|
||||||
- [Wiki](https://wiki.servarr.com/Sonarr)
|
* Can scan your existing library and download any missing episodes
|
||||||
- [v4 Beta API Documentation](https://sonarr.tv/docs/api)
|
* Can watch for better quality of the episodes you already have and do an automatic upgrade. *eg. from DVD to Blu-Ray*
|
||||||
- [Donate](https://sonarr.tv/donate)
|
* Automatic failed download handling will try another release if one fails
|
||||||
|
* Manual search so you can pick any release or to see why a release was not downloaded automatically
|
||||||
|
* Fully configurable episode renaming
|
||||||
|
* Full integration with SABnzbd and NZBGet
|
||||||
|
* Full integration with Kodi, Plex (notification, library update, metadata)
|
||||||
|
* Full support for specials and multi-episode releases
|
||||||
|
* And a beautiful UI
|
||||||
|
|
||||||
## Support
|
## Configuring Development Environment:
|
||||||
|
|
||||||
Note: GitHub Issues are for Bugs and Feature Requests Only
|
### Requirements
|
||||||
|
|
||||||
- [Forums](https://forums.sonarr.tv/)
|
* [Visual Studio 2017](https://www.visualstudio.com/vs/)
|
||||||
- [Discord](https://discord.gg/M6BvZn5)
|
* [Git](https://git-scm.com/downloads)
|
||||||
- [GitHub - Bugs and Feature Requests Only](https://github.com/Sonarr/Sonarr/issues)
|
* [NodeJS](https://nodejs.org/en/download/)
|
||||||
- [IRC](https://web.libera.chat/?channels=#sonarr)
|
* [Yarn](https://yarnpkg.com/)
|
||||||
- [Reddit](https://www.reddit.com/r/sonarr)
|
|
||||||
- [Wiki](https://wiki.servarr.com/sonarr)
|
|
||||||
|
|
||||||
## Features
|
### Setup
|
||||||
|
|
||||||
### Current Features
|
* Make sure all the required software mentioned above are installed
|
||||||
|
* Clone the repository into your development machine. [*info*](https://help.github.com/en/articles/working-with-forks)
|
||||||
|
* Grab the submodules `git submodule init && git submodule update`
|
||||||
|
* Install the required Node Packages `yarn`
|
||||||
|
|
||||||
- Support for major platforms: Windows, Linux, macOS, Raspberry Pi, etc.
|
### Backend Development
|
||||||
- Automatically detects new episodes
|
|
||||||
- Can scan your existing library and download any missing episodes
|
|
||||||
- Can watch for better quality of the episodes you already have and do an automatic upgrade. *eg. from DVD to Blu-Ray*
|
|
||||||
- Automatic failed download handling will try another release if one fails
|
|
||||||
- Manual search so you can pick any release or to see why a release was not downloaded automatically
|
|
||||||
- Fully configurable episode renaming
|
|
||||||
- Full integration with SABnzbd and NZBGet
|
|
||||||
- Full integration with Kodi, Plex (notification, library update, metadata)
|
|
||||||
- Full support for specials and multi-episode releases
|
|
||||||
- And a beautiful UI
|
|
||||||
|
|
||||||
## Contributing
|
* Run `yarn build` to build the UI
|
||||||
|
* Open `Sonarr.sln` in Visual Studio
|
||||||
|
* Make sure `NzbDrone.Console` is set as the startup project
|
||||||
|
* Build `NzbDrone.Windows` and `NzbDrone.Mono` projects
|
||||||
|
* Build Solution
|
||||||
|
|
||||||
### Development
|
### UI Development
|
||||||
|
|
||||||
This project exists thanks to all the people who contribute. [Contribute](CONTRIBUTING.md).
|
* Run `yarn watch` to build UI and rebuild automatically when changes are detected
|
||||||
|
* Run Sonarr.Console.exe (or debug in Visual Studio)
|
||||||
|
|
||||||
<a href="https://github.com/Sonarr/Sonarr/graphs/contributors"><img src="https://opencollective.com/Sonarr/contributors.svg?width=890&button=false" /></a>
|
### License
|
||||||
|
|
||||||
### Supporters
|
|
||||||
|
|
||||||
This project would not be possible without the support of our users and software providers.
|
* [GNU GPL v3](http://www.gnu.org/licenses/gpl.html)
|
||||||
[**Become a sponsor or backer**](https://opencollective.com/sonarr) to help us out!
|
* Copyright 2010-2019
|
||||||
|
|
||||||
#### Mega Sponsors
|
### Sponsors
|
||||||
|
|
||||||
[![Sponsors](https://opencollective.com/sonarr/tiers/mega-sponsor.svg?width=890)](https://opencollective.com/sonarr/contribute/mega-sponsor-21443/checkout)
|
* [JetBrains](http://www.jetbrains.com/) for providing us with free licenses to their great tools
|
||||||
|
* [ReSharper](http://www.jetbrains.com/resharper/)
|
||||||
#### Sponsors
|
* [TeamCity](http://www.jetbrains.com/teamcity/)
|
||||||
|
|
||||||
[![Flexible Sponsors](https://opencollective.com/sonarr/sponsors.svg?width=890)](https://opencollective.com/sonarr/contribute/sponsor-21457/checkout)
|
|
||||||
|
|
||||||
#### Backers
|
|
||||||
|
|
||||||
[![Backers](https://opencollective.com/sonarr/backers.svg?width=890)](https://opencollective.com/sonarr/contribute/backer-21442/checkout)
|
|
||||||
|
|
||||||
#### JetBrains
|
|
||||||
|
|
||||||
Thank you to [<img src="/Logo/Jetbrains/jetbrains.svg" alt="JetBrains" width="32"> JetBrains](http://www.jetbrains.com/) for providing us with free licenses to their great tools
|
|
||||||
|
|
||||||
* [<img src="/Logo/Jetbrains/teamcity.svg" alt="TeamCity" width="32"> TeamCity](http://www.jetbrains.com/teamcity/)
|
|
||||||
* [<img src="/Logo/Jetbrains/resharper.svg" alt="ReSharper" width="32"> ReSharper](http://www.jetbrains.com/resharper/)
|
|
||||||
* [<img src="/Logo/Jetbrains/dottrace.svg" alt="dotTrace" width="32"> dotTrace](http://www.jetbrains.com/dottrace/)
|
|
||||||
|
|
||||||
### Licenses
|
|
||||||
|
|
||||||
- [GNU GPL v3](http://www.gnu.org/licenses/gpl.html)
|
|
||||||
- Copyright 2010-2023
|
|
||||||
|
|
|
@ -1,9 +0,0 @@
|
||||||
# Security Policy
|
|
||||||
|
|
||||||
## Reporting a Vulnerability
|
|
||||||
|
|
||||||
Please report (suspected) security vulnerabilities on Discord (preferred) to
|
|
||||||
either markus101
|
|
||||||
#2148 or Taloth#7357 or via email: security@sonarr.tv. You will receive a response from
|
|
||||||
us within 72 hours. If the issue is confirmed, we will release a patch as soon
|
|
||||||
as possible depending on complexity/severity.
|
|
641
build.sh
641
build.sh
|
@ -1,59 +1,122 @@
|
||||||
#! /usr/bin/env bash
|
#! /bin/bash
|
||||||
set -e
|
msBuildVersion='15.0'
|
||||||
|
outputFolder='./_output'
|
||||||
|
outputFolderWindows='./_output_windows'
|
||||||
|
outputFolderLinux='./_output_linux'
|
||||||
|
outputFolderMacOS='./_output_macos'
|
||||||
|
outputFolderMacOSApp='./_output_macos_app'
|
||||||
|
testPackageFolder='./_tests'
|
||||||
|
testPackageFolderWindows='./_tests_windows'
|
||||||
|
testPackageFolderLinux='./_tests_linux'
|
||||||
|
sourceFolder='./src'
|
||||||
|
slnFile=$sourceFolder/Sonarr.sln
|
||||||
|
updateSubFolder=Sonarr.Update
|
||||||
|
|
||||||
outputFolder='_output'
|
nuget='tools/nuget/nuget.exe';
|
||||||
testPackageFolder='_tests'
|
vswhere='tools/vswhere/vswhere.exe';
|
||||||
artifactsFolder="_artifacts";
|
|
||||||
framework="${FRAMEWORK:=net6.0}"
|
. ./version.sh
|
||||||
|
|
||||||
|
CheckExitCode()
|
||||||
|
{
|
||||||
|
"$@"
|
||||||
|
local status=$?
|
||||||
|
if [ $status -ne 0 ]; then
|
||||||
|
echo "error with $1" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
return $status
|
||||||
|
}
|
||||||
|
|
||||||
ProgressStart()
|
ProgressStart()
|
||||||
{
|
{
|
||||||
echo "::group::$1"
|
echo "##teamcity[blockOpened name='$1']"
|
||||||
echo "Start '$1'"
|
echo "##teamcity[progressStart '$1']"
|
||||||
}
|
}
|
||||||
|
|
||||||
ProgressEnd()
|
ProgressEnd()
|
||||||
{
|
{
|
||||||
echo "Finish '$1'"
|
echo "##teamcity[progressFinish '$1']"
|
||||||
echo "::endgroup::"
|
echo "##teamcity[blockClosed name='$1']"
|
||||||
}
|
}
|
||||||
|
|
||||||
UpdateVersionNumber()
|
UpdateVersionNumber()
|
||||||
{
|
{
|
||||||
if [ "$SONARR_VERSION" != "" ]; then
|
if [ "$BUILD_NUMBER" != "" ]; then
|
||||||
echo "Updating version info to: $SONARR_VERSION"
|
echo "Updating Version Info"
|
||||||
sed -i'' -e "s/<AssemblyVersion>[0-9.*]\+<\/AssemblyVersion>/<AssemblyVersion>$SONARR_VERSION<\/AssemblyVersion>/g" src/Directory.Build.props
|
verMajorMinorRevision=`echo "$buildVersion" | cut -d. -f1,2,3`
|
||||||
sed -i'' -e "s/<AssemblyConfiguration>[\$()A-Za-z-]\+<\/AssemblyConfiguration>/<AssemblyConfiguration>${BRANCH}<\/AssemblyConfiguration>/g" src/Directory.Build.props
|
verBuild=`echo "${BUILD_NUMBER}" | cut -d. -f4`
|
||||||
sed -i'' -e "s/<string>10.0.0.0<\/string>/<string>$SONARR_VERSION<\/string>/g" distribution/macOS/Sonarr.app/Contents/Info.plist
|
BUILD_NUMBER=$verMajorMinorRevision.$verBuild
|
||||||
|
echo "##teamcity[buildNumber '$BUILD_NUMBER']"
|
||||||
|
sed -i "s/<AssemblyVersion>[0-9.*]\+<\/AssemblyVersion>/<AssemblyVersion>$BUILD_NUMBER<\/AssemblyVersion>/g" ./src/Directory.Build.props
|
||||||
|
sed -i "s/<AssemblyConfiguration>[\$()A-Za-z-]\+<\/AssemblyConfiguration>/<AssemblyConfiguration>${BRANCH:-dev}<\/AssemblyConfiguration>/g" ./src/Directory.Build.props
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
EnableExtraPlatformsInSDK()
|
CreateReleaseInfo()
|
||||||
{
|
{
|
||||||
BUNDLEDVERSIONS="${SDK_PATH}/Microsoft.NETCoreSdk.BundledVersions.props"
|
if [ "$BUILD_NUMBER" != "" ]; then
|
||||||
if grep -q freebsd-x64 "$BUNDLEDVERSIONS"; then
|
echo "Create Release Info"
|
||||||
echo "Extra platforms already enabled"
|
echo -e "# Do Not Edit\nReleaseVersion=$BUILD_NUMBER\nBranch=${BRANCH:-dev}" > $outputFolder/release_info
|
||||||
else
|
|
||||||
echo "Enabling extra platform support"
|
|
||||||
sed -i.ORI 's/osx-x64/osx-x64;freebsd-x64/' "$BUNDLEDVERSIONS"
|
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
EnableExtraPlatforms()
|
CleanFolder()
|
||||||
{
|
{
|
||||||
if grep -qv freebsd-x64 src/Directory.Build.props; then
|
local path=$1
|
||||||
sed -i'' -e "s^<RuntimeIdentifiers>\(.*\)</RuntimeIdentifiers>^<RuntimeIdentifiers>\1;freebsd-x64</RuntimeIdentifiers>^g" src/Directory.Build.props
|
local keepConfigFiles=$2
|
||||||
|
|
||||||
|
find $path -name "*.transform" -exec rm "{}" \;
|
||||||
|
|
||||||
|
if [ $keepConfigFiles != true ] ; then
|
||||||
|
find $path -name "*.dll.config" -exec rm "{}" \;
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
echo "Removing FluentValidation.Resources files"
|
||||||
|
find $path -name "FluentValidation.resources.dll" -exec rm "{}" \;
|
||||||
|
find $path -name "App.config" -exec rm "{}" \;
|
||||||
|
|
||||||
|
echo "Removing vshost files"
|
||||||
|
find $path -name "*.vshost.exe" -exec rm "{}" \;
|
||||||
|
|
||||||
|
echo "Removing dylib files"
|
||||||
|
find $path -name "*.dylib" -exec rm "{}" \;
|
||||||
|
|
||||||
|
echo "Removing Empty folders"
|
||||||
|
find $path -depth -empty -type d -exec rm -r "{}" \;
|
||||||
|
}
|
||||||
|
|
||||||
|
BuildWithMSBuild()
|
||||||
|
{
|
||||||
|
msBuildPath=`$vswhere -latest -products \* -requires Microsoft.Component.MSBuild -find MSBuild\\\\\*\*\\\\Bin\\\\MSBuild.exe`
|
||||||
|
msBuildPath=${msBuildPath/C:\\/\/c\/}
|
||||||
|
msBuildPath=${msBuildPath//\\/\/}
|
||||||
|
msBuildDir=$(dirname "$msBuildPath")
|
||||||
|
|
||||||
|
echo $msBuildDir
|
||||||
|
|
||||||
|
export PATH=$msBuildDir:$PATH
|
||||||
|
CheckExitCode MSBuild.exe $slnFile //p:Configuration=Release //p:Platform=x86 //t:Clean //m
|
||||||
|
$nuget restore $slnFile
|
||||||
|
CheckExitCode MSBuild.exe $slnFile //p:Configuration=Release //p:Platform=x86 //t:Build //m //p:AllowedReferenceRelatedFileExtensions=.pdb
|
||||||
|
}
|
||||||
|
|
||||||
|
BuildWithXbuild()
|
||||||
|
{
|
||||||
|
export MONO_IOMAP=case
|
||||||
|
CheckExitCode msbuild /t:Clean $slnFile
|
||||||
|
mono $nuget restore $slnFile
|
||||||
|
CheckExitCode msbuild /p:Configuration=Release /p:Platform=x86 /t:Build /p:AllowedReferenceRelatedFileExtensions=.pdb $slnFile
|
||||||
}
|
}
|
||||||
|
|
||||||
LintUI()
|
LintUI()
|
||||||
{
|
{
|
||||||
ProgressStart 'ESLint'
|
ProgressStart 'ESLint'
|
||||||
yarn lint
|
CheckExitCode yarn lint
|
||||||
ProgressEnd 'ESLint'
|
ProgressEnd 'ESLint'
|
||||||
|
|
||||||
ProgressStart 'Stylelint'
|
ProgressStart 'Stylelint'
|
||||||
yarn stylelint
|
CheckExitCode yarn stylelint
|
||||||
ProgressEnd 'Stylelint'
|
ProgressEnd 'Stylelint'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,392 +127,318 @@ Build()
|
||||||
rm -rf $outputFolder
|
rm -rf $outputFolder
|
||||||
rm -rf $testPackageFolder
|
rm -rf $testPackageFolder
|
||||||
|
|
||||||
slnFile=src/Sonarr.sln
|
if [ $runtime = "dotnet" ] ; then
|
||||||
|
BuildWithMSBuild
|
||||||
if [ $os = "windows" ]; then
|
|
||||||
platform=Windows
|
|
||||||
else
|
else
|
||||||
platform=Posix
|
BuildWithXbuild
|
||||||
fi
|
fi
|
||||||
|
|
||||||
dotnet clean $slnFile -c Debug
|
CleanFolder $outputFolder false
|
||||||
dotnet clean $slnFile -c Release
|
|
||||||
|
|
||||||
if [[ -z "$RID" || -z "$FRAMEWORK" ]];
|
echo "Removing Mono.Posix.dll"
|
||||||
then
|
rm $outputFolder/Mono.Posix.dll
|
||||||
dotnet msbuild -restore $slnFile -p:Configuration=Release -p:Platform=$platform -t:PublishAllRids
|
|
||||||
else
|
|
||||||
dotnet msbuild -restore $slnFile -p:Configuration=Release -p:Platform=$platform -p:RuntimeIdentifiers=$RID -t:PublishAllRids
|
|
||||||
fi
|
|
||||||
|
|
||||||
ProgressEnd 'Build'
|
ProgressEnd 'Build'
|
||||||
}
|
}
|
||||||
|
|
||||||
YarnInstall()
|
RunGulp()
|
||||||
{
|
{
|
||||||
ProgressStart 'yarn install'
|
ProgressStart 'yarn install'
|
||||||
yarn install --frozen-lockfile --network-timeout 120000
|
yarn install
|
||||||
ProgressEnd 'yarn install'
|
ProgressEnd 'yarn install'
|
||||||
|
|
||||||
|
LintUI
|
||||||
|
|
||||||
|
ProgressStart 'Running gulp'
|
||||||
|
CheckExitCode yarn run build --production
|
||||||
|
ProgressEnd 'Running gulp'
|
||||||
}
|
}
|
||||||
|
|
||||||
RunWebpack()
|
CreateMdbs()
|
||||||
{
|
{
|
||||||
ProgressStart 'Running webpack'
|
local path=$1
|
||||||
yarn run build --env production
|
if [ $runtime = "dotnet" ] ; then
|
||||||
ProgressEnd 'Running webpack'
|
local pdbFiles=( $(find $path -name "*.pdb") )
|
||||||
|
for filename in "${pdbFiles[@]}"
|
||||||
|
do
|
||||||
|
if [ -e ${filename%.pdb}.dll ] ; then
|
||||||
|
tools/pdb2mdb/pdb2mdb.exe ${filename%.pdb}.dll
|
||||||
|
fi
|
||||||
|
if [ -e ${filename%.pdb}.exe ] ; then
|
||||||
|
tools/pdb2mdb/pdb2mdb.exe ${filename%.pdb}.exe
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
PackageFiles()
|
PatchMono()
|
||||||
{
|
{
|
||||||
local folder="$1"
|
local path=$1
|
||||||
local framework="$2"
|
|
||||||
local runtime="$3"
|
|
||||||
|
|
||||||
rm -rf $folder
|
# Below we deal with some mono incompatibilities with windows-only dotnet core/standard libs
|
||||||
mkdir -p $folder
|
# See: https://github.com/mono/mono/blob/master/tools/nuget-hash-extractor/download.sh
|
||||||
cp -r $outputFolder/$framework/$runtime/publish/* $folder
|
# That list defines assemblies that are prohibited from being loaded from the appdir, instead loading from mono GAC.
|
||||||
cp -r $outputFolder/Sonarr.Update/$framework/$runtime/publish $folder/Sonarr.Update
|
|
||||||
|
|
||||||
if [ "$FRONTEND" = "YES" ];
|
# We have debian dependencies to get these installed or facades from mono 5.10+
|
||||||
then
|
for assembly in System.IO.Compression System.Runtime.InteropServices.RuntimeInformation System.Net.Http System.Globalization.Extensions System.Text.Encoding.CodePages System.Threading.Overlapped
|
||||||
cp -r $outputFolder/UI $folder
|
do
|
||||||
|
if [ -e $path/$assembly.dll ]; then
|
||||||
|
if [ -e $sourceFolder/Libraries/Mono/$assembly.dll ]; then
|
||||||
|
echo "Copy Mono-specific facade $assembly.dll (uses win32 interop)"
|
||||||
|
cp $sourceFolder/Libraries/Mono/$assembly.dll $path/$assembly.dll
|
||||||
|
else
|
||||||
|
echo "Remove $assembly.dll (uses win32 interop)"
|
||||||
|
rm $path/$assembly.dll
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "Adding LICENSE"
|
fi
|
||||||
cp LICENSE.md $folder
|
done
|
||||||
|
|
||||||
|
# Copy more stable version of Vectors for mono <5.12
|
||||||
|
if [ -e $path/System.Numerics.Vectors.dll ]; then
|
||||||
|
packageDir="$HOME/.nuget/packages/system.numerics.vectors/4.5.0"
|
||||||
|
|
||||||
|
if [ ! -d "$HOME/.nuget/packages/system.numerics.vectors/4.5.0" ]; then
|
||||||
|
# May reside in the NuGetFallback folder, which is harder to find
|
||||||
|
# Download somewhere to get the real cache populated
|
||||||
|
if [ $runtime = "dotnet" ] ; then
|
||||||
|
$nuget install System.Numerics.Vectors -Version 4.5.0 -Output ./_temp/System.Numerics.Vectors
|
||||||
|
else
|
||||||
|
mono $nuget install System.Numerics.Vectors -Version 4.5.0 -Output ./_temp/System.Numerics.Vectors
|
||||||
|
fi
|
||||||
|
rm -rf ./_temp/System.Numerics.Vectors
|
||||||
|
fi
|
||||||
|
# Copy the netstandard2.0 version rather than net46
|
||||||
|
cp "$packageDir/lib/netstandard2.0/System.Numerics.Vectors.dll" $path/
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
PackageLinux()
|
PackageMono()
|
||||||
{
|
{
|
||||||
local framework="$1"
|
ProgressStart 'Creating Mono Package'
|
||||||
local runtime="$2"
|
|
||||||
|
|
||||||
ProgressStart "Creating $runtime Package for $framework"
|
rm -rf $outputFolderLinux
|
||||||
|
|
||||||
local folder=$artifactsFolder/$runtime/$framework/Sonarr
|
echo "Copying Binaries"
|
||||||
|
cp -r $outputFolder $outputFolderLinux
|
||||||
|
|
||||||
PackageFiles "$folder" "$framework" "$runtime"
|
echo "Creating MDBs"
|
||||||
|
CreateMdbs $outputFolderLinux
|
||||||
|
|
||||||
|
echo "Removing PDBs"
|
||||||
|
find $outputFolderLinux -name "*.pdb" -exec rm "{}" \;
|
||||||
|
|
||||||
echo "Removing Service helpers"
|
echo "Removing Service helpers"
|
||||||
rm -f $folder/ServiceUninstall.*
|
rm -f $outputFolderLinux/ServiceUninstall.*
|
||||||
rm -f $folder/ServiceInstall.*
|
rm -f $outputFolderLinux/ServiceInstall.*
|
||||||
|
|
||||||
|
echo "Removing native windows binaries Sqlite, MediaInfo"
|
||||||
|
rm -f $outputFolderLinux/sqlite3.*
|
||||||
|
rm -f $outputFolderLinux/MediaInfo.*
|
||||||
|
|
||||||
|
PatchMono $outputFolderLinux
|
||||||
|
|
||||||
|
echo "Adding Sonarr.Core.dll.config (for dllmap)"
|
||||||
|
cp $sourceFolder/NzbDrone.Core/Sonarr.Core.dll.config $outputFolderLinux
|
||||||
|
|
||||||
|
# Remove Http binding redirect by renaming it
|
||||||
|
# We don't need this anymore once our minimum mono version is 5.10
|
||||||
|
sed -i "s/System.Net.Http/System.Net.Http.Mono/g" $outputFolderLinux/Sonarr.Console.exe.config
|
||||||
|
|
||||||
|
echo "Renaming Sonarr.Console.exe to Sonarr.exe"
|
||||||
|
rm $outputFolderLinux/Sonarr.exe*
|
||||||
|
for file in $outputFolderLinux/Sonarr.Console.exe*; do
|
||||||
|
mv "$file" "${file//.Console/}"
|
||||||
|
done
|
||||||
|
|
||||||
echo "Removing Sonarr.Windows"
|
echo "Removing Sonarr.Windows"
|
||||||
rm $folder/Sonarr.Windows.*
|
rm $outputFolderLinux/Sonarr.Windows.*
|
||||||
|
|
||||||
echo "Adding Sonarr.Mono to UpdatePackage"
|
echo "Adding Sonarr.Mono to UpdatePackage"
|
||||||
cp $folder/Sonarr.Mono.* $folder/Sonarr.Update
|
cp $outputFolderLinux/Sonarr.Mono.* $outputFolderLinux/$updateSubFolder/
|
||||||
if [ "$framework" = "$framework" ]; then
|
|
||||||
cp $folder/Mono.Posix.NETStandard.* $folder/Sonarr.Update
|
|
||||||
cp $folder/libMonoPosixHelper.* $folder/Sonarr.Update
|
|
||||||
fi
|
|
||||||
|
|
||||||
ProgressEnd "Creating $runtime Package for $framework"
|
ProgressEnd 'Creating Mono Package'
|
||||||
}
|
}
|
||||||
|
|
||||||
PackageMacOS()
|
PackageMacOS()
|
||||||
{
|
{
|
||||||
local framework="$1"
|
ProgressStart 'Creating MacOS Package'
|
||||||
local runtime="$2"
|
|
||||||
|
|
||||||
ProgressStart "Creating $runtime Package for $framework"
|
rm -rf $outputFolderMacOS
|
||||||
|
mkdir $outputFolderMacOS
|
||||||
|
|
||||||
local folder=$artifactsFolder/$runtime/$framework/Sonarr
|
echo "Adding Startup script"
|
||||||
|
cp ./macOS/Sonarr $outputFolderMacOS
|
||||||
|
dos2unix $outputFolderMacOS/Sonarr
|
||||||
|
|
||||||
PackageFiles "$folder" "$framework" "$runtime"
|
echo "Copying Binaries"
|
||||||
|
cp -r $outputFolderLinux/* $outputFolderMacOS
|
||||||
|
|
||||||
echo "Removing Service helpers"
|
echo "Adding sqlite dylibs"
|
||||||
rm -f $folder/ServiceUninstall.*
|
cp $sourceFolder/Libraries/Sqlite/*.dylib $outputFolderMacOS
|
||||||
rm -f $folder/ServiceInstall.*
|
|
||||||
|
|
||||||
echo "Removing Sonarr.Windows"
|
echo "Adding MediaInfo dylib"
|
||||||
rm $folder/Sonarr.Windows.*
|
cp $sourceFolder/Libraries/MediaInfo/*.dylib $outputFolderMacOS
|
||||||
|
|
||||||
echo "Adding Sonarr.Mono to UpdatePackage"
|
ProgressEnd 'Creating MacOS Package'
|
||||||
cp $folder/Sonarr.Mono.* $folder/Sonarr.Update
|
|
||||||
if [ "$framework" = "$framework" ]; then
|
|
||||||
cp $folder/Mono.Posix.NETStandard.* $folder/Sonarr.Update
|
|
||||||
cp $folder/libMonoPosixHelper.* $folder/Sonarr.Update
|
|
||||||
fi
|
|
||||||
|
|
||||||
ProgressEnd "Creating $runtime Package for $framework"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PackageMacOSApp()
|
PackageMacOSApp()
|
||||||
{
|
{
|
||||||
local framework="$1"
|
ProgressStart 'Creating macOS App Package'
|
||||||
local runtime="$2"
|
|
||||||
|
|
||||||
ProgressStart "Creating $runtime App Package for $framework"
|
rm -rf $outputFolderMacOSApp
|
||||||
|
mkdir $outputFolderMacOSApp
|
||||||
|
cp -r ./macOS/Sonarr.app $outputFolderMacOSApp
|
||||||
|
mkdir -p $outputFolderMacOSApp/Sonarr.app/Contents/MacOS
|
||||||
|
|
||||||
local folder=$artifactsFolder/$runtime-app/$framework
|
echo "Adding Startup script"
|
||||||
|
cp ./macOS/Sonarr $outputFolderMacOSApp/Sonarr.app/Contents/MacOS
|
||||||
rm -rf $folder
|
dos2unix $outputFolderMacOSApp/Sonarr.app/Contents/MacOS/Sonarr
|
||||||
mkdir -p $folder
|
|
||||||
cp -r distribution/macOS/Sonarr.app $folder
|
|
||||||
mkdir -p $folder/Sonarr.app/Contents/MacOS
|
|
||||||
|
|
||||||
echo "Copying Binaries"
|
echo "Copying Binaries"
|
||||||
cp -r $artifactsFolder/$runtime/$framework/Sonarr/* $folder/Sonarr.app/Contents/MacOS
|
cp -r $outputFolderLinux/* $outputFolderMacOSApp/Sonarr.app/Contents/MacOS
|
||||||
|
|
||||||
|
echo "Adding sqlite dylibs"
|
||||||
|
cp $sourceFolder/Libraries/Sqlite/*.dylib $outputFolderMacOSApp/Sonarr.app/Contents/MacOS
|
||||||
|
|
||||||
|
echo "Adding MediaInfo dylib"
|
||||||
|
cp $sourceFolder/Libraries/MediaInfo/*.dylib $outputFolderMacOSApp/Sonarr.app/Contents/MacOS
|
||||||
|
|
||||||
echo "Removing Update Folder"
|
echo "Removing Update Folder"
|
||||||
rm -r $folder/Sonarr.app/Contents/MacOS/Sonarr.Update
|
rm -r $outputFolderMacOSApp/Sonarr.app/Contents/MacOS/Sonarr.Update
|
||||||
|
|
||||||
ProgressEnd "Creating $runtime App Package for $framework"
|
ProgressEnd 'Creating macOS App Package'
|
||||||
|
}
|
||||||
|
|
||||||
|
PackageTestsMono()
|
||||||
|
{
|
||||||
|
ProgressStart 'Creating Mono Test Package'
|
||||||
|
|
||||||
|
rm -rf $testPackageFolderLinux
|
||||||
|
|
||||||
|
echo "Copying Binaries"
|
||||||
|
cp -r $testPackageFolder $testPackageFolderLinux
|
||||||
|
|
||||||
|
if [ $runtime = "dotnet" ] ; then
|
||||||
|
$nuget install NUnit.ConsoleRunner -Version 3.10.0 -Output $testPackageFolderLinux
|
||||||
|
else
|
||||||
|
mono $nuget install NUnit.ConsoleRunner -Version 3.10.0 -Output $testPackageFolderLinux
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Creating MDBs"
|
||||||
|
CreateMdbs $testPackageFolderLinux
|
||||||
|
|
||||||
|
echo "Removing PDBs"
|
||||||
|
find $testPackageFolderLinux -name "*.pdb" -exec rm "{}" \;
|
||||||
|
|
||||||
|
PatchMono $testPackageFolderLinux
|
||||||
|
|
||||||
|
echo "Adding Sonarr.Core.dll.config (for dllmap)"
|
||||||
|
cp $sourceFolder/NzbDrone.Core/Sonarr.Core.dll.config $testPackageFolderLinux
|
||||||
|
|
||||||
|
# Remove Http binding redirect by renaming it
|
||||||
|
# We don't need this anymore once our minimum mono version is 5.10
|
||||||
|
sed -i "s/System.Net.Http/System.Net.Http.Mono/g" $testPackageFolderLinux/Sonarr.Common.Test.dll.config
|
||||||
|
|
||||||
|
cp ./test.sh $testPackageFolderLinux/
|
||||||
|
dos2unix $testPackageFolderLinux/test.sh
|
||||||
|
|
||||||
|
echo "Removing Sonarr.Windows"
|
||||||
|
rm $testPackageFolderLinux/Sonarr.Windows.*
|
||||||
|
|
||||||
|
rm -f $testPackageFolderLinux/*.log.config
|
||||||
|
|
||||||
|
CleanFolder $testPackageFolderLinux true
|
||||||
|
|
||||||
|
ProgressEnd 'Creating Linux Test Package'
|
||||||
|
}
|
||||||
|
|
||||||
|
PackageTestsWindows()
|
||||||
|
{
|
||||||
|
ProgressStart 'Creating Windows Test Package'
|
||||||
|
|
||||||
|
rm -rf $testPackageFolderWindows
|
||||||
|
|
||||||
|
echo "Copying Binaries"
|
||||||
|
cp -r $testPackageFolder $testPackageFolderWindows
|
||||||
|
|
||||||
|
if [ $runtime = "dotnet" ] ; then
|
||||||
|
$nuget install NUnit.ConsoleRunner -Version 3.10.0 -Output $testPackageFolderWindows
|
||||||
|
else
|
||||||
|
mono $nuget install NUnit.ConsoleRunner -Version 3.10.0 -Output $testPackageFolderWindows
|
||||||
|
fi
|
||||||
|
|
||||||
|
cp ./test.sh $testPackageFolderWindows
|
||||||
|
|
||||||
|
echo "Removing Sonarr.Mono"
|
||||||
|
rm -f $testPackageFolderWindows/Sonarr.Mono.*
|
||||||
|
|
||||||
|
rm -f $testPackageFolderWindows/*.log.config
|
||||||
|
|
||||||
|
CleanFolder $testPackageFolderWindows true
|
||||||
|
|
||||||
|
ProgressEnd 'Creating Windows Test Package'
|
||||||
}
|
}
|
||||||
|
|
||||||
PackageWindows()
|
PackageWindows()
|
||||||
{
|
{
|
||||||
local framework="$1"
|
ProgressStart 'Creating Windows Package'
|
||||||
local runtime="$2"
|
|
||||||
|
|
||||||
ProgressStart "Creating Windows Package for $framework"
|
rm -rf $outputFolderWindows
|
||||||
|
|
||||||
local folder=$artifactsFolder/$runtime/$framework/Sonarr
|
echo "Copying Binaries"
|
||||||
|
cp -r $outputFolder $outputFolderWindows
|
||||||
PackageFiles "$folder" "$framework" "$runtime"
|
|
||||||
cp -r $outputFolder/$framework-windows/$runtime/publish/* $folder
|
|
||||||
|
|
||||||
echo "Removing Sonarr.Mono"
|
echo "Removing Sonarr.Mono"
|
||||||
rm -f $folder/Sonarr.Mono.*
|
rm -f $outputFolderWindows/Sonarr.Mono.*
|
||||||
rm -f $folder/Mono.Posix.NETStandard.*
|
|
||||||
rm -f $folder/libMonoPosixHelper.*
|
|
||||||
|
|
||||||
echo "Adding Sonarr.Windows to UpdatePackage"
|
echo "Adding Sonarr.Windows to UpdatePackage"
|
||||||
cp $folder/Sonarr.Windows.* $folder/Sonarr.Update
|
cp $outputFolderWindows/Sonarr.Windows.* $outputFolderWindows/$updateSubFolder/
|
||||||
|
|
||||||
ProgressEnd "Creating Windows Package for $framework"
|
ProgressEnd 'Creating Windows Package'
|
||||||
}
|
}
|
||||||
|
|
||||||
Package()
|
PublishArtifacts()
|
||||||
{
|
{
|
||||||
local framework="$1"
|
|
||||||
local runtime="$2"
|
|
||||||
local SPLIT
|
|
||||||
|
|
||||||
IFS='-' read -ra SPLIT <<< "$runtime"
|
|
||||||
|
|
||||||
case "${SPLIT[0]}" in
|
|
||||||
linux|freebsd*)
|
|
||||||
PackageLinux "$framework" "$runtime"
|
|
||||||
;;
|
|
||||||
win)
|
|
||||||
PackageWindows "$framework" "$runtime"
|
|
||||||
;;
|
|
||||||
osx)
|
|
||||||
PackageMacOS "$framework" "$runtime"
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
}
|
|
||||||
|
|
||||||
PackageTests()
|
|
||||||
{
|
|
||||||
local framework="$1"
|
|
||||||
local runtime="$2"
|
|
||||||
|
|
||||||
ProgressStart "Creating $runtime Test Package for $framework"
|
|
||||||
|
|
||||||
cp test.sh "$testPackageFolder/$framework/$runtime/publish"
|
|
||||||
|
|
||||||
rm -f $testPackageFolder/$framework/$runtime/*.log.config
|
|
||||||
|
|
||||||
ProgressEnd "Creating $runtime Test Package for $framework"
|
|
||||||
}
|
|
||||||
|
|
||||||
UploadTestArtifacts()
|
|
||||||
{
|
|
||||||
local framework="$1"
|
|
||||||
|
|
||||||
ProgressStart 'Publishing Test Artifacts'
|
|
||||||
|
|
||||||
# Tests
|
|
||||||
for dir in $testPackageFolder/$framework/*
|
|
||||||
do
|
|
||||||
local runtime=$(basename "$dir")
|
|
||||||
echo "##teamcity[publishArtifacts '$testPackageFolder/$framework/$runtime/publish/** => tests.$runtime.zip']"
|
|
||||||
done
|
|
||||||
|
|
||||||
ProgressEnd 'Publishing Test Artifacts'
|
|
||||||
}
|
|
||||||
|
|
||||||
UploadArtifacts()
|
|
||||||
{
|
|
||||||
local framework="$1"
|
|
||||||
|
|
||||||
ProgressStart 'Publishing Artifacts'
|
ProgressStart 'Publishing Artifacts'
|
||||||
|
|
||||||
|
# Tests
|
||||||
|
echo "##teamcity[publishArtifacts '$testPackageFolderWindows/** => tests.windows.zip']"
|
||||||
|
echo "##teamcity[publishArtifacts '$testPackageFolderLinux/** => tests.linux.zip']"
|
||||||
|
|
||||||
# Releases
|
# Releases
|
||||||
for dir in $artifactsFolder/*
|
echo "##teamcity[publishArtifacts '$outputFolderWindows/** => Sonarr.$BRANCH.$BUILD_NUMBER.windows.zip!Sonarr']"
|
||||||
do
|
echo "##teamcity[publishArtifacts '$outputFolderLinux/** => Sonarr.$BRANCH.$BUILD_NUMBER.linux.tar.gz!Sonarr']"
|
||||||
local runtime=$(basename "$dir")
|
echo "##teamcity[publishArtifacts '$outputFolderMacOS/** => Sonarr.$BRANCH.$BUILD_NUMBER.macos.tar.gz!Sonarr']"
|
||||||
|
echo "##teamcity[publishArtifacts '$outputFolderMacOSApp/** => Sonarr.$BRANCH.$BUILD_NUMBER.macos.zip']"
|
||||||
|
|
||||||
echo "##teamcity[publishArtifacts '$artifactsFolder/$runtime/$framework/** => Sonarr.$BRANCH.$SONARR_VERSION.$runtime.zip']"
|
# Debian Package
|
||||||
done
|
|
||||||
|
|
||||||
# Debian Package / Windows installer / macOS app
|
|
||||||
echo "##teamcity[publishArtifacts 'distribution/** => distribution.zip']"
|
echo "##teamcity[publishArtifacts 'distribution/** => distribution.zip']"
|
||||||
|
|
||||||
ProgressEnd 'Publishing Artifacts'
|
ProgressEnd 'Publishing Artifacts'
|
||||||
}
|
}
|
||||||
|
|
||||||
UploadUIArtifacts()
|
|
||||||
{
|
|
||||||
local framework="$1"
|
|
||||||
|
|
||||||
ProgressStart 'Publishing UI Artifacts'
|
|
||||||
|
|
||||||
# UI folder
|
|
||||||
echo "##teamcity[publishArtifacts '$outputFolder/UI/** => UI.zip']"
|
|
||||||
|
|
||||||
ProgressEnd 'Publishing UI Artifacts'
|
|
||||||
}
|
|
||||||
|
|
||||||
# Use mono or .net depending on OS
|
# Use mono or .net depending on OS
|
||||||
case "$(uname -s)" in
|
case "$(uname -s)" in
|
||||||
CYGWIN*|MINGW32*|MINGW64*|MSYS*)
|
CYGWIN*|MINGW32*|MINGW64*|MSYS*)
|
||||||
# on windows, use dotnet
|
# on windows, use dotnet
|
||||||
os="windows"
|
runtime="dotnet"
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
# otherwise use mono
|
# otherwise use mono
|
||||||
os="posix"
|
runtime="mono"
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
POSITIONAL=()
|
|
||||||
|
|
||||||
if [ $# -eq 0 ]; then
|
|
||||||
echo "No arguments provided, building everything"
|
|
||||||
BACKEND=YES
|
|
||||||
FRONTEND=YES
|
|
||||||
PACKAGES=YES
|
|
||||||
LINT=YES
|
|
||||||
ENABLE_EXTRA_PLATFORMS=NO
|
|
||||||
ENABLE_EXTRA_PLATFORMS_IN_SDK=NO
|
|
||||||
fi
|
|
||||||
|
|
||||||
while [[ $# -gt 0 ]]
|
|
||||||
do
|
|
||||||
key="$1"
|
|
||||||
|
|
||||||
case $key in
|
|
||||||
--backend)
|
|
||||||
BACKEND=YES
|
|
||||||
shift # past argument
|
|
||||||
;;
|
|
||||||
--enable-bsd|--enable-extra-platforms)
|
|
||||||
ENABLE_EXTRA_PLATFORMS=YES
|
|
||||||
shift # past argument
|
|
||||||
;;
|
|
||||||
--enable-extra-platforms-in-sdk)
|
|
||||||
ENABLE_EXTRA_PLATFORMS_IN_SDK=YES
|
|
||||||
shift # past argument
|
|
||||||
;;
|
|
||||||
-r|--runtime)
|
|
||||||
RID="$2"
|
|
||||||
shift # past argument
|
|
||||||
shift # past value
|
|
||||||
;;
|
|
||||||
-f|--framework)
|
|
||||||
FRAMEWORK="$2"
|
|
||||||
shift # past argument
|
|
||||||
shift # past value
|
|
||||||
;;
|
|
||||||
--frontend)
|
|
||||||
FRONTEND=YES
|
|
||||||
shift # past argument
|
|
||||||
;;
|
|
||||||
--packages)
|
|
||||||
PACKAGES=YES
|
|
||||||
shift # past argument
|
|
||||||
;;
|
|
||||||
--lint)
|
|
||||||
LINT=YES
|
|
||||||
shift # past argument
|
|
||||||
;;
|
|
||||||
--all)
|
|
||||||
BACKEND=YES
|
|
||||||
FRONTEND=YES
|
|
||||||
PACKAGES=YES
|
|
||||||
LINT=YES
|
|
||||||
shift # past argument
|
|
||||||
;;
|
|
||||||
*) # unknown option
|
|
||||||
POSITIONAL+=("$1") # save it in an array for later
|
|
||||||
shift # past argument
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
set -- "${POSITIONAL[@]}" # restore positional parameters
|
|
||||||
|
|
||||||
if [ "$ENABLE_EXTRA_PLATFORMS_IN_SDK" = "YES" ];
|
|
||||||
then
|
|
||||||
EnableExtraPlatformsInSDK
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ "$BACKEND" = "YES" ];
|
|
||||||
then
|
|
||||||
UpdateVersionNumber
|
UpdateVersionNumber
|
||||||
if [ "$ENABLE_EXTRA_PLATFORMS" = "YES" ];
|
|
||||||
then
|
|
||||||
EnableExtraPlatforms
|
|
||||||
fi
|
|
||||||
|
|
||||||
Build
|
Build
|
||||||
|
CreateReleaseInfo
|
||||||
if [[ -z "$RID" || -z "$FRAMEWORK" ]];
|
RunGulp
|
||||||
then
|
PackageMono
|
||||||
PackageTests "$framework" "win-x64"
|
PackageMacOS
|
||||||
PackageTests "$framework" "win-x86"
|
PackageMacOSApp
|
||||||
PackageTests "$framework" "linux-x64"
|
PackageTestsMono
|
||||||
PackageTests "$framework" "linux-musl-x64"
|
PackageTestsWindows
|
||||||
PackageTests "$framework" "osx-x64"
|
PackageWindows
|
||||||
if [ "$ENABLE_EXTRA_PLATFORMS" = "YES" ];
|
PublishArtifacts
|
||||||
then
|
|
||||||
PackageTests "$framework" "freebsd-x64"
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
PackageTests "$FRAMEWORK" "$RID"
|
|
||||||
fi
|
|
||||||
|
|
||||||
UploadTestArtifacts "$framework"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ "$FRONTEND" = "YES" ];
|
|
||||||
then
|
|
||||||
YarnInstall
|
|
||||||
|
|
||||||
if [ "$LINT" = "YES" ];
|
|
||||||
then
|
|
||||||
LintUI
|
|
||||||
fi
|
|
||||||
|
|
||||||
RunWebpack
|
|
||||||
UploadUIArtifacts
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ "$PACKAGES" = "YES" ];
|
|
||||||
then
|
|
||||||
UpdateVersionNumber
|
|
||||||
|
|
||||||
if [[ -z "$RID" || -z "$FRAMEWORK" ]];
|
|
||||||
then
|
|
||||||
Package "$framework" "win-x64"
|
|
||||||
Package "$framework" "win-x86"
|
|
||||||
Package "$framework" "linux-x64"
|
|
||||||
Package "$framework" "linux-musl-x64"
|
|
||||||
Package "$framework" "linux-arm64"
|
|
||||||
Package "$framework" "linux-musl-arm64"
|
|
||||||
Package "$framework" "linux-arm"
|
|
||||||
Package "$framework" "osx-x64"
|
|
||||||
Package "$framework" "osx-arm64"
|
|
||||||
if [ "$ENABLE_EXTRA_PLATFORMS" = "YES" ];
|
|
||||||
then
|
|
||||||
Package "$framework" "freebsd-x64"
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
Package "$FRAMEWORK" "$RID"
|
|
||||||
fi
|
|
||||||
|
|
||||||
UploadArtifacts "$framework"
|
|
||||||
fi
|
|
||||||
|
|
|
@ -0,0 +1,63 @@
|
||||||
|
fromdos ./debian/*
|
||||||
|
cp -r ./debian ./debian_backup
|
||||||
|
|
||||||
|
BuildVersion=${dependent_build_number:-3.10.0.999}
|
||||||
|
BuildBranch=${dependent_build_branch:-master}
|
||||||
|
BootstrapVersion=`echo "$BuildVersion" | cut -d. -f1,2,3`
|
||||||
|
BootstrapUpdater="BuiltIn"
|
||||||
|
PackageUpdater="apt"
|
||||||
|
|
||||||
|
echo Version: "$BuildVersion" Branch: "$BuildBranch"
|
||||||
|
|
||||||
|
rm -r ./sonarr_bin/Sonarr.Update
|
||||||
|
chmod -R ugo-x,ugo+rwX,go-w ./sonarr_bin/*
|
||||||
|
|
||||||
|
echo Updating changelog for $BuildVersion
|
||||||
|
sed -i "s:{version}:$BuildVersion:g; s:{branch}:$BuildBranch:g;" debian/changelog
|
||||||
|
sed -i "s:{version}:$BuildVersion:g; s:{updater}:$PackageUpdater:g" debian/preinst debian/postinst debian/postrm
|
||||||
|
sed -i '/#BEGIN BUILTIN UPDATER/,/#END BUILTIN UPDATER/d' debian/preinst debian/postinst debian/postrm
|
||||||
|
echo "# Do Not Edit\nPackageVersion=$BuildVersion\nReleaseVersion=$BuildVersion\nUpdateMethod=$PackageUpdater\nBranch=$BuildBranch" > package_info
|
||||||
|
|
||||||
|
echo Running debuild for $BuildVersion
|
||||||
|
if [ -z "${TEST_OUTPUT}" ]; then
|
||||||
|
debuild -b
|
||||||
|
else
|
||||||
|
debuild -us -uc -b
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Restore debian directory to the original files
|
||||||
|
rm -rf ./debian
|
||||||
|
mv ./debian_backup ./debian
|
||||||
|
|
||||||
|
echo Updating changelog for $BootstrapVersion
|
||||||
|
sed -i "s:{version}:$BootstrapVersion:g; s:{branch}:$BuildBranch:g;" debian/changelog
|
||||||
|
sed -i "s:{version}:$BuildVersion:g; s:{updater}:$BootstrapUpdater:g" debian/preinst debian/postinst debian/postrm
|
||||||
|
sed -i '/#BEGIN BUILTIN UPDATER/d; /#END BUILTIN UPDATER/d' debian/preinst debian/postinst debian/postrm
|
||||||
|
echo "# Do Not Edit\nPackageVersion=$BootstrapVersion\nReleaseVersion=$BuildVersion\nUpdateMethod=$BootstrapUpdater\nBranch=$BuildBranch" > package_info
|
||||||
|
|
||||||
|
echo Running debuild for $BootstrapVersion
|
||||||
|
if [ -z "${TEST_OUTPUT}" ]; then
|
||||||
|
debuild -b
|
||||||
|
else
|
||||||
|
debuild -us -uc -b
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo Moving stuff around
|
||||||
|
mv ../sonarr_*.deb ./
|
||||||
|
mv ../sonarr_*.changes ./
|
||||||
|
rm ../sonarr_*.build
|
||||||
|
|
||||||
|
if [ -z "${TEST_OUTPUT}" ]; then
|
||||||
|
echo Signing Package
|
||||||
|
dpkg-sig -k 884589CE --sign builder "sonarr_${BuildVersion}_all.deb"
|
||||||
|
dpkg-sig -k 884589CE --sign builder "sonarr_${BootstrapVersion}_all.deb"
|
||||||
|
|
||||||
|
echo running alien
|
||||||
|
alien -r -v ./*.deb
|
||||||
|
else
|
||||||
|
echo "Exporting packages to ${TEST_OUTPUT}"
|
||||||
|
dpkg -e "sonarr_${BuildVersion}_all.deb" ${TEST_OUTPUT}/sonarr-build
|
||||||
|
dpkg -e "sonarr_${BootstrapVersion}_all.deb" ${TEST_OUTPUT}/sonarr-release
|
||||||
|
|
||||||
|
cp *.deb ${TEST_OUTPUT}/
|
||||||
|
fi
|
|
@ -0,0 +1,6 @@
|
||||||
|
[*]
|
||||||
|
charset = utf-8
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
insert_final_newline = true
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 2
|
|
@ -0,0 +1,5 @@
|
||||||
|
sonarr ({version}) {branch}; urgency=low
|
||||||
|
|
||||||
|
* Automatic Release.
|
||||||
|
|
||||||
|
-- Sonarr <hello@sonarr.tv> Sun, 28 Jan 2018 00:00:00 -0700
|
|
@ -0,0 +1 @@
|
||||||
|
8
|
|
@ -0,0 +1,14 @@
|
||||||
|
#!/bin/sh -e
|
||||||
|
|
||||||
|
. /usr/share/debconf/confmodule
|
||||||
|
|
||||||
|
db_beginblock
|
||||||
|
db_input high sonarr/owning_user || true
|
||||||
|
db_input high sonarr/owning_group || true
|
||||||
|
db_endblock
|
||||||
|
db_go
|
||||||
|
|
||||||
|
db_input low sonarr/config_directory || true
|
||||||
|
db_go
|
||||||
|
|
||||||
|
exit 0
|
|
@ -0,0 +1,22 @@
|
||||||
|
Section: web
|
||||||
|
Priority: optional
|
||||||
|
Maintainer: Sonarr <hello@sonarr.tv>
|
||||||
|
Source: sonarr
|
||||||
|
Homepage: https://sonarr.tv
|
||||||
|
Vcs-Git: git@github.com:Sonarr/Sonarr.git
|
||||||
|
Vcs-Browser: https://github.com/Sonarr/Sonarr
|
||||||
|
Build-Depends: debhelper (>= 9),
|
||||||
|
dh-systemd (>= 1.5),
|
||||||
|
mono-devel (>= 5.4),
|
||||||
|
libmono-cil-dev (>= 5.4),
|
||||||
|
cli-common-dev (>= 0.9+xamarin5)
|
||||||
|
|
||||||
|
Package: sonarr
|
||||||
|
Architecture: all
|
||||||
|
Provides: nzbdrone
|
||||||
|
Conflicts: nzbdrone
|
||||||
|
Replaces: nzbdrone
|
||||||
|
Depends: adduser, libsqlite3-0 (>= 3.7), libmediainfo0v5 (>= 0.7.52) | libmediainfo0 (>= 0.7.52), mono-runtime (>= 5.4), ca-certificates-mono, libmono-system-net-http4.0-cil (>= 4.0.0~alpha1), ${cli:Depends}, ${misc:Depends}
|
||||||
|
Recommends: libmediainfo0v5 (>= 18.03) | libmediainfo0 (>= 18.03)
|
||||||
|
Suggests: sqlite3 (>= 3.7), mediainfo (>= 0.7.52)
|
||||||
|
Description: Internet PVR
|
|
@ -0,0 +1,24 @@
|
||||||
|
Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
|
||||||
|
Upstream-Name: sonarr
|
||||||
|
Source: https://github.com/Sonarr/Sonarr
|
||||||
|
|
||||||
|
Files: *
|
||||||
|
Copyright: 2010-2016 Sonarr <hello@sonarr.tv>
|
||||||
|
|
||||||
|
License: GPL-3.0+
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
.
|
||||||
|
This package is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
.
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
.
|
||||||
|
On Debian systems, the complete text of the GNU General
|
||||||
|
Public License version 3 can be found in "/usr/share/common-licenses/GPL-3".
|
|
@ -0,0 +1 @@
|
||||||
|
sonarr_3.0.0.0_all.deb web optional
|
|
@ -0,0 +1,2 @@
|
||||||
|
sonarr_bin/* usr/lib/sonarr/bin
|
||||||
|
package_info usr/lib/sonarr
|
|
@ -1,182 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
### Description: Sonarr .NET Debian install
|
|
||||||
### Originally written for Radarr by: DoctorArr - doctorarr@the-rowlands.co.uk on 2021-10-01 v1.0
|
|
||||||
### Updates for servarr suite made by Bakerboy448, DoctorArr, brightghost, aeramor and VP-EN
|
|
||||||
### Version v1.0.0 2023-12-29 - StevieTV - adapted from servarr script for Sonarr installs
|
|
||||||
### Version V1.0.1 2024-01-02 - StevieTV - remove UTF8-BOM
|
|
||||||
### Version V1.0.2 2024-01-03 - markus101 - Get user input from /dev/tty
|
|
||||||
### Version V1.0.3 2024-01-06 - StevieTV - exit script when it is ran from install directory
|
|
||||||
|
|
||||||
### Boilerplate Warning
|
|
||||||
#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
||||||
#EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
||||||
#MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
#NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
||||||
#LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
#OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
||||||
#WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
|
|
||||||
scriptversion="1.0.3"
|
|
||||||
scriptdate="2024-01-06"
|
|
||||||
|
|
||||||
set -euo pipefail
|
|
||||||
|
|
||||||
echo "Running Sonarr Install Script - Version [$scriptversion] as of [$scriptdate]"
|
|
||||||
|
|
||||||
# Am I root?, need root!
|
|
||||||
|
|
||||||
if [ "$EUID" -ne 0 ]; then
|
|
||||||
echo "Please run as root."
|
|
||||||
exit
|
|
||||||
fi
|
|
||||||
|
|
||||||
app="sonarr"
|
|
||||||
app_port="8989"
|
|
||||||
app_prereq="curl sqlite3 wget"
|
|
||||||
app_umask="0002"
|
|
||||||
branch="main"
|
|
||||||
|
|
||||||
# Constants
|
|
||||||
### Update these variables as required for your specific instance
|
|
||||||
installdir="/opt" # {Update me if needed} Install Location
|
|
||||||
bindir="${installdir}/${app^}" # Full Path to Install Location
|
|
||||||
datadir="/var/lib/$app/" # {Update me if needed} AppData directory to use
|
|
||||||
app_bin=${app^} # Binary Name of the app
|
|
||||||
|
|
||||||
# This script should not be ran from installdir, otherwise later in the script the extracted files will be removed before they can be moved to installdir.
|
|
||||||
if [ "$installdir" == "$(dirname -- "$( readlink -f -- "$0"; )")" ] || [ "$bindir" == "$(dirname -- "$( readlink -f -- "$0"; )")" ]; then
|
|
||||||
echo "You should not run this script from the intended install directory. The script will exit. Please re-run it from another directory"
|
|
||||||
exit
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Prompt User
|
|
||||||
read -r -p "What user should ${app^} run as? (Default: $app): " app_uid < /dev/tty
|
|
||||||
app_uid=$(echo "$app_uid" | tr -d ' ')
|
|
||||||
app_uid=${app_uid:-$app}
|
|
||||||
# Prompt Group
|
|
||||||
read -r -p "What group should ${app^} run as? (Default: media): " app_guid < /dev/tty
|
|
||||||
app_guid=$(echo "$app_guid" | tr -d ' ')
|
|
||||||
app_guid=${app_guid:-media}
|
|
||||||
|
|
||||||
echo "This will install [${app^}] to [$bindir] and use [$datadir] for the AppData Directory"
|
|
||||||
echo "${app^} will run as the user [$app_uid] and group [$app_guid]. By continuing, you've confirmed that the selected user and group will have READ and WRITE access to your Media Library and Download Client Completed Download directories"
|
|
||||||
read -n 1 -r -s -p $'Press enter to continue or ctrl+c to exit...\n' < /dev/tty
|
|
||||||
|
|
||||||
# Create User / Group as needed
|
|
||||||
if [ "$app_guid" != "$app_uid" ]; then
|
|
||||||
if ! getent group "$app_guid" >/dev/null; then
|
|
||||||
groupadd "$app_guid"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
if ! getent passwd "$app_uid" >/dev/null; then
|
|
||||||
adduser --system --no-create-home --ingroup "$app_guid" "$app_uid"
|
|
||||||
echo "Created and added User [$app_uid] to Group [$app_guid]"
|
|
||||||
fi
|
|
||||||
if ! getent group "$app_guid" | grep -qw "$app_uid"; then
|
|
||||||
echo "User [$app_uid] did not exist in Group [$app_guid]"
|
|
||||||
usermod -a -G "$app_guid" "$app_uid"
|
|
||||||
echo "Added User [$app_uid] to Group [$app_guid]"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Stop the App if running
|
|
||||||
if service --status-all | grep -Fq "$app"; then
|
|
||||||
systemctl stop "$app"
|
|
||||||
systemctl disable "$app".service
|
|
||||||
echo "Stopped existing $app"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Create Appdata Directory
|
|
||||||
|
|
||||||
# AppData
|
|
||||||
mkdir -p "$datadir"
|
|
||||||
chown -R "$app_uid":"$app_guid" "$datadir"
|
|
||||||
chmod 775 "$datadir"
|
|
||||||
echo "Directories created"
|
|
||||||
# Download and install the App
|
|
||||||
|
|
||||||
# prerequisite packages
|
|
||||||
echo ""
|
|
||||||
echo "Installing pre-requisite Packages"
|
|
||||||
# shellcheck disable=SC2086
|
|
||||||
apt update && apt install -y $app_prereq
|
|
||||||
echo ""
|
|
||||||
ARCH=$(dpkg --print-architecture)
|
|
||||||
# get arch
|
|
||||||
dlbase="https://services.sonarr.tv/v1/download/$branch/latest?version=4&os=linux"
|
|
||||||
case "$ARCH" in
|
|
||||||
"amd64") DLURL="${dlbase}&arch=x64" ;;
|
|
||||||
"armhf") DLURL="${dlbase}&arch=arm" ;;
|
|
||||||
"arm64") DLURL="${dlbase}&arch=arm64" ;;
|
|
||||||
*)
|
|
||||||
echo "Arch not supported"
|
|
||||||
exit 1
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
echo ""
|
|
||||||
echo "Removing previous tarballs"
|
|
||||||
# -f to Force so we fail if it doesn't exist
|
|
||||||
rm -f "${app^}".*.tar.gz
|
|
||||||
echo ""
|
|
||||||
echo "Downloading..."
|
|
||||||
wget --content-disposition "$DLURL"
|
|
||||||
tar -xvzf "${app^}".*.tar.gz
|
|
||||||
echo ""
|
|
||||||
echo "Installation files downloaded and extracted"
|
|
||||||
|
|
||||||
# remove existing installs
|
|
||||||
echo "Removing existing installation"
|
|
||||||
rm -rf "$bindir"
|
|
||||||
echo "Installing..."
|
|
||||||
mv "${app^}" $installdir
|
|
||||||
chown "$app_uid":"$app_guid" -R "$bindir"
|
|
||||||
chmod 775 "$bindir"
|
|
||||||
rm -rf "${app^}.*.tar.gz"
|
|
||||||
# Ensure we check for an update in case user installs older version or different branch
|
|
||||||
touch "$datadir"/update_required
|
|
||||||
chown "$app_uid":"$app_guid" "$datadir"/update_required
|
|
||||||
echo "App Installed"
|
|
||||||
# Configure Autostart
|
|
||||||
|
|
||||||
# Remove any previous app .service
|
|
||||||
echo "Removing old service file"
|
|
||||||
rm -rf /etc/systemd/system/"$app".service
|
|
||||||
|
|
||||||
# Create app .service with correct user startup
|
|
||||||
echo "Creating service file"
|
|
||||||
cat <<EOF | tee /etc/systemd/system/"$app".service >/dev/null
|
|
||||||
[Unit]
|
|
||||||
Description=${app^} Daemon
|
|
||||||
After=syslog.target network.target
|
|
||||||
[Service]
|
|
||||||
User=$app_uid
|
|
||||||
Group=$app_guid
|
|
||||||
UMask=$app_umask
|
|
||||||
Type=simple
|
|
||||||
ExecStart=$bindir/$app_bin -nobrowser -data=$datadir
|
|
||||||
TimeoutStopSec=20
|
|
||||||
KillMode=process
|
|
||||||
Restart=on-failure
|
|
||||||
[Install]
|
|
||||||
WantedBy=multi-user.target
|
|
||||||
EOF
|
|
||||||
|
|
||||||
# Start the App
|
|
||||||
echo "Service file created. Attempting to start the app"
|
|
||||||
systemctl -q daemon-reload
|
|
||||||
systemctl enable --now -q "$app"
|
|
||||||
|
|
||||||
# Finish Update/Installation
|
|
||||||
host=$(hostname -I)
|
|
||||||
ip_local=$(grep -oP '^\S*' <<<"$host")
|
|
||||||
echo ""
|
|
||||||
echo "Install complete"
|
|
||||||
sleep 10
|
|
||||||
STATUS="$(systemctl is-active "$app")"
|
|
||||||
if [ "${STATUS}" = "active" ]; then
|
|
||||||
echo "Browse to http://$ip_local:$app_port for the ${app^} GUI"
|
|
||||||
else
|
|
||||||
echo "${app^} failed to start"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Exit
|
|
||||||
exit 0
|
|
|
@ -0,0 +1,107 @@
|
||||||
|
#!/bin/sh
|
||||||
|
set -e
|
||||||
|
|
||||||
|
BUILD_VERSION={version}
|
||||||
|
UPDATER={updater}
|
||||||
|
|
||||||
|
. /usr/share/debconf/confmodule
|
||||||
|
db_get sonarr/owning_user
|
||||||
|
USER="$RET"
|
||||||
|
db_get sonarr/owning_group
|
||||||
|
GROUP="$RET"
|
||||||
|
db_get sonarr/config_directory
|
||||||
|
CONFDIR="$RET"
|
||||||
|
|
||||||
|
# Add User and Group
|
||||||
|
if ! getent group "$GROUP" >/dev/null; then
|
||||||
|
groupadd "$GROUP"
|
||||||
|
fi
|
||||||
|
if ! getent passwd "$USER" >/dev/null; then
|
||||||
|
adduser --system --no-create-home --ingroup "$GROUP" "$USER"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ $1 = "configure" ]; then
|
||||||
|
# Migrate old Sonarr v3 alpha data dir from /var/opt/sonarr or user home
|
||||||
|
if [ -d "/var/opt/sonarr" ] && [ "$CONFDIR" != "/var/opt/sonarr" ] && [ ! -d "$CONFDIR" ]; then
|
||||||
|
varoptRoot="/var/opt/sonarr"
|
||||||
|
varoptAppData="$varoptRoot/.config/Sonarr"
|
||||||
|
sonarrUserHome=`getent passwd $USER | cut -d ':' -f 6`
|
||||||
|
sonarrAppData="$sonarrUserHome/.config/Sonarr"
|
||||||
|
if [ -f "$varoptRoot/sonarr.db" ]; then
|
||||||
|
# Handle /var/opt/sonarr/sonarr.db
|
||||||
|
mv "$varoptRoot" "$CONFDIR"
|
||||||
|
elif [ -f "$varoptAppData/sonarr.db" ]; then
|
||||||
|
# Handle /var/opt/sonarr/.config/Sonarr/sonarr.db
|
||||||
|
mv "$varoptAppData" "$CONFDIR"
|
||||||
|
rm -rf "$varoptRoot"
|
||||||
|
elif [ -f "$sonarrAppData/sonarr.db" ]; then
|
||||||
|
# Handle ~/.config/Sonarr/sonarr.db
|
||||||
|
mv "$sonarrAppData" "$CONFDIR"
|
||||||
|
rm -rf "$sonarrAppData"
|
||||||
|
else
|
||||||
|
mv "$varoptRoot" "$CONFDIR"
|
||||||
|
fi
|
||||||
|
chown -R $USER:$GROUP "$CONFDIR"
|
||||||
|
chmod -R 775 "$CONFDIR"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Migrate old NzbDrone data dir
|
||||||
|
if [ -d "/usr/lib/sonarr/nzbdrone-appdata" ] && [ ! -d "$CONFDIR" ]; then
|
||||||
|
NZBDRONE_DATA=`readlink /usr/lib/sonarr/nzbdrone-appdata`
|
||||||
|
if [ -f "$NZBDRONE_DATA/config.xml" ] && [ -f "$NZBDRONE_DATA/nzbdrone.db" ]; then
|
||||||
|
echo "Found NzbDrone database in $NZBDRONE_DATA, copying to $CONFDIR."
|
||||||
|
mkdir -p "$CONFDIR"
|
||||||
|
cp $NZBDRONE_DATA/config.xml $NZBDRONE_DATA/nzbdrone.db* "$CONFDIR/"
|
||||||
|
chown -R $USER:$GROUP "$CONFDIR"
|
||||||
|
chmod -R 775 "$CONFDIR"
|
||||||
|
else
|
||||||
|
echo "Missing NzbDrone database in $NZBDRONE_DATA, skipping migration."
|
||||||
|
fi
|
||||||
|
rm /usr/lib/sonarr/nzbdrone-appdata
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Create data directory
|
||||||
|
if [ ! -d "$CONFDIR" ]; then
|
||||||
|
mkdir -p "$CONFDIR"
|
||||||
|
chown -R $USER:$GROUP "$CONFDIR"
|
||||||
|
fi
|
||||||
|
|
||||||
|
#BEGIN BUILTIN UPDATER
|
||||||
|
# Apply patch if present
|
||||||
|
if [ "$UPDATER" = "BuiltIn" ] && [ -f /usr/lib/sonarr/bin_patch/release_info ]; then
|
||||||
|
# It shouldn't be possible to get a wrong bin_patch, but let's check anyway and throw it away if it's wrong
|
||||||
|
currentVersion=`cat /usr/lib/sonarr/bin_patch/release_info | grep 'ReleaseVersion=' | cut -d= -f 2`
|
||||||
|
currentRelease=`echo "$currentVersion" | cut -d. -f1,2,3`
|
||||||
|
currentBuild=`echo "$currentVersion" | cut -d. -f4`
|
||||||
|
targetVersion=$BUILD_VERSION
|
||||||
|
targetRelease=`echo "$targetVersion" | cut -d. -f1,2,3`
|
||||||
|
targetBuild=`echo "$targetVersion" | cut -d. -f4`
|
||||||
|
|
||||||
|
if [ "$currentRelease" = "$targetRelease" ] && [ "$currentBuild" -gt "$targetBuild" ]; then
|
||||||
|
echo "Applying $currentVersion from BuiltIn updater instead of downgrading to $targetVersion"
|
||||||
|
rm -rf /usr/lib/sonarr/bin
|
||||||
|
mv /usr/lib/sonarr/bin_patch /usr/lib/sonarr/bin
|
||||||
|
else
|
||||||
|
rm -rf /usr/lib/sonarr/bin_patch
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
#END BUILTIN UPDATER
|
||||||
|
|
||||||
|
# Set permissions on /usr/lib/sonarr
|
||||||
|
chown -R $USER:$GROUP /usr/lib/sonarr
|
||||||
|
|
||||||
|
# Update sonarr.service file
|
||||||
|
sed -i "s:User=sonarr:User=$USER:g; s:Group=sonarr:Group=$GROUP:g; s:-data=/var/lib/sonarr:-data=$CONFDIR:g" /lib/systemd/system/sonarr.service
|
||||||
|
|
||||||
|
#BEGIN BUILTIN UPDATER
|
||||||
|
if [ $1 = "upgrade" ] && [ "$UPDATER" = "BuiltIn" ]; then
|
||||||
|
# If we upgraded, signal Sonarr to do an update check on startup instead of scheduled.
|
||||||
|
touch $CONFDIR/update_required
|
||||||
|
chown $USER:$GROUP $CONFDIR/update_required
|
||||||
|
fi
|
||||||
|
#END BUILTIN UPDATER
|
||||||
|
|
||||||
|
#DEBHELPER#
|
||||||
|
|
||||||
|
exit 0
|
|
@ -0,0 +1,36 @@
|
||||||
|
#!/bin/sh
|
||||||
|
set -e
|
||||||
|
|
||||||
|
BUILD_VERSION={version}
|
||||||
|
UPDATER={updater}
|
||||||
|
|
||||||
|
if [ $1 = "abort-install" ]; then
|
||||||
|
# preinst was aborted, possibly due to NzbDrone still running.
|
||||||
|
# Nothing to do here
|
||||||
|
:
|
||||||
|
fi
|
||||||
|
|
||||||
|
# The bin directory is expected to be empty, unless the BuiltIn updater added files.
|
||||||
|
if [ $1 = "remove" ] && [ -d /usr/lib/sonarr/bin ]; then
|
||||||
|
rm -rf /usr/lib/sonarr/bin
|
||||||
|
fi
|
||||||
|
|
||||||
|
#BEGIN BUILTIN UPDATER
|
||||||
|
# Remove any existing patch if still present
|
||||||
|
if [ $1 = "remove" ] && [ -d /usr/lib/sonarr/bin_patch ]; then
|
||||||
|
rm -rf /usr/lib/sonarr/bin_patch
|
||||||
|
fi
|
||||||
|
#END BUILTIN UPDATER
|
||||||
|
|
||||||
|
# Purge the entire sonarr configuration directory.
|
||||||
|
# TODO: Maybe move a minimal backup to tmp?
|
||||||
|
if [ $1 = "purge" ] && [ -e /usr/share/debconf/confmodule ]; then
|
||||||
|
. /usr/share/debconf/confmodule
|
||||||
|
db_get sonarr/config_directory
|
||||||
|
CONFDIR="$RET"
|
||||||
|
if [ -d "$CONFDIR" ]; then
|
||||||
|
rm -rf "$CONFDIR"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
#DEBHELPER#
|
|
@ -0,0 +1,91 @@
|
||||||
|
#!/bin/sh
|
||||||
|
set -e
|
||||||
|
|
||||||
|
BUILD_VERSION={version}
|
||||||
|
UPDATER={updater}
|
||||||
|
|
||||||
|
# Deal with existing nzbdrone installs
|
||||||
|
#
|
||||||
|
# Existing nzbdrone packages do not have startup scripts and the process might still be running.
|
||||||
|
# If the user manually installed nzbdrone then the process might still be running too.
|
||||||
|
if [ $1 = "install" ]; then
|
||||||
|
psNzbDrone=`ps ax -o'user,pid,ppid,unit,args' | grep mono.*NzbDrone\\\\.exe || true`
|
||||||
|
if [ ! -z "$psNzbDrone" ]; then
|
||||||
|
# Get the user and optional systemd unit
|
||||||
|
psNzbDroneUser=`echo "$psNzbDrone" | tr -s ' ' | cut -d ' ' -f 1`
|
||||||
|
psNzbDroneUnit=`echo "$psNzbDrone" | tr -s ' ' | cut -d ' ' -f 4`
|
||||||
|
# Get the appdata from the cmdline or get it from the user dir
|
||||||
|
droneAppData=`echo "$psNzbDrone" | tr ' ' '\n' | grep -- "-data=" | cut -d= -f 2`
|
||||||
|
if [ "$droneAppData" = "" ]; then
|
||||||
|
droneUserHome=`getent passwd $psNzbDroneUser | cut -d ':' -f 6`
|
||||||
|
droneAppData="$droneUserHome/.config/NzbDrone"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$psNzbDroneUnit" != "-" ] && [ -d /run/systemd/system ]; then
|
||||||
|
if [ "$psNzbDroneUnit" = "sonarr.service" ]; then
|
||||||
|
# Conflicts with our new sonarr.service so we have to remove it
|
||||||
|
echo "NzbDrone systemd startup detected at $psNzbDroneUnit, stopping and removing..."
|
||||||
|
deb-systemd-invoke stop $psNzbDroneUnit >/dev/null
|
||||||
|
if [ -f "/etc/systemd/system/$psNzbDroneUnit" ]; then
|
||||||
|
rm /etc/systemd/system/$psNzbDroneUnit
|
||||||
|
fi
|
||||||
|
if [ -f "/usr/lib/systemd/system/$psNzbDroneUnit" ]; then
|
||||||
|
rm /usr/lib/systemd/system/$psNzbDroneUnit
|
||||||
|
fi
|
||||||
|
deb-systemd-helper purge $psNzbDroneUnit >/dev/null
|
||||||
|
deb-systemd-helper unmask $psNzbDroneUnit >/dev/null
|
||||||
|
systemctl --system daemon-reload >/dev/null || true
|
||||||
|
else
|
||||||
|
# Just disable it, so the user can revisit the settings later
|
||||||
|
echo "NzbDrone systemd startup detected at $psNzbDroneUnit, stopping and disabling..."
|
||||||
|
deb-systemd-invoke stop $psNzbDroneUnit >/dev/null
|
||||||
|
deb-systemd-invoke mask $psNzbDroneUnit >/dev/null
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
# We don't support auto migration for other startup methods, so bail.
|
||||||
|
# This leaves the sonarr package in an incomplete state.
|
||||||
|
echo "ps: $psNzbDrone"
|
||||||
|
echo "Error: An existing Sonarr v2 (NzbDrone) process is running. Remove the NzbDrone auto-startup prior to installing sonarr."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# We don't have the debconf configuration yet so we can't migrate the data.
|
||||||
|
# Instead we symlink so postinst knows where it's at.
|
||||||
|
if [ -f "/usr/lib/sonarr/nzbdrone-appdata" ]; then
|
||||||
|
rm "/usr/lib/sonarr/nzbdrone-appdata"
|
||||||
|
else
|
||||||
|
mkdir -p "/usr/lib/sonarr"
|
||||||
|
fi
|
||||||
|
ln -s $droneAppData /usr/lib/sonarr/nzbdrone-appdata
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
#BEGIN BUILTIN UPDATER
|
||||||
|
# Check for supported upgrade paths
|
||||||
|
if [ $1 = "upgrade" ] && [ "$UPDATER" = "BuiltIn" ] && [ -f /usr/lib/sonarr/bin/release_info ]; then
|
||||||
|
# If we allow the Built-In updater to upgrade from 3.0.1.123 to 3.0.2.500 and now apt is catching up to 3.0.2.425
|
||||||
|
# then we need to deal with that 500->425 'downgrade'.
|
||||||
|
# We do that by preserving the binaries and using those instead for postinst.
|
||||||
|
|
||||||
|
currentVersion=`cat /usr/lib/sonarr/bin/release_info | grep 'ReleaseVersion=' | cut -d= -f 2`
|
||||||
|
currentRelease=`echo "$currentVersion" | cut -d. -f1,2,3`
|
||||||
|
currentBuild=`echo "$currentVersion" | cut -d. -f4`
|
||||||
|
targetVersion=$BUILD_VERSION
|
||||||
|
targetRelease=`echo "$targetVersion" | cut -d. -f1,2,3`
|
||||||
|
targetBuild=`echo "$targetVersion" | cut -d. -f4`
|
||||||
|
|
||||||
|
if [ -d /usr/lib/sonarr/bin_patch ]; then
|
||||||
|
rm -rf /usr/lib/sonarr/bin_patch
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check if the existing version is already an upgrade for the included build
|
||||||
|
if [ "$currentRelease" = "$targetRelease" ] && [ "$currentBuild" -gt "$targetBuild" ]; then
|
||||||
|
echo "Preserving $currentVersion from BuiltIn updater instead of downgrading to $targetVersion"
|
||||||
|
cp -r /usr/lib/sonarr/bin /usr/lib/sonarr/bin_patch
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
#END BUILTIN UPDATER
|
||||||
|
|
||||||
|
#DEBHELPER#
|
||||||
|
|
||||||
|
exit 0
|
|
@ -0,0 +1,21 @@
|
||||||
|
#!/usr/bin/make -f
|
||||||
|
|
||||||
|
# Uncomment this to turn on verbose mode.
|
||||||
|
#export DH_VERBOSE=1
|
||||||
|
|
||||||
|
EXCLUDE_MODULEREFS = crypt32 httpapi
|
||||||
|
|
||||||
|
%:
|
||||||
|
dh $@ --with=systemd --with=cli
|
||||||
|
|
||||||
|
# No init script, only systemd
|
||||||
|
override_dh_installinit:
|
||||||
|
true
|
||||||
|
|
||||||
|
# Sonarr likes debug symbols for logging
|
||||||
|
override_dh_clistrip:
|
||||||
|
|
||||||
|
override_dh_makeclilibs:
|
||||||
|
|
||||||
|
override_dh_clideps:
|
||||||
|
dh_clideps -d -r $(patsubst %,--exclude-moduleref=%,$(EXCLUDE_MODULEREFS))
|
|
@ -0,0 +1,2 @@
|
||||||
|
ignores msbuild
|
||||||
|
ignores libmediainfo0v5
|
|
@ -1,6 +1,3 @@
|
||||||
# This file is owned by the sonarr package, DO NOT MODIFY MANUALLY
|
|
||||||
# Instead use 'dpkg-reconfigure -plow sonarr' to modify User/Group/UMask/-data
|
|
||||||
# Or use systemd built-in override functionality using 'systemctl edit sonarr'
|
|
||||||
[Unit]
|
[Unit]
|
||||||
Description=Sonarr Daemon
|
Description=Sonarr Daemon
|
||||||
After=network.target
|
After=network.target
|
||||||
|
@ -11,7 +8,7 @@ Group=sonarr
|
||||||
UMask=002
|
UMask=002
|
||||||
|
|
||||||
Type=simple
|
Type=simple
|
||||||
ExecStart=/opt/Sonarr/Sonarr -nobrowser -data=/var/lib/sonarr
|
ExecStart=/usr/bin/mono --debug /usr/lib/sonarr/bin/Sonarr.exe -nobrowser -data=/var/lib/sonarr
|
||||||
TimeoutStopSec=20
|
TimeoutStopSec=20
|
||||||
KillMode=process
|
KillMode=process
|
||||||
Restart=on-failure
|
Restart=on-failure
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
Template: sonarr/owning_user
|
||||||
|
Type: string
|
||||||
|
Default: sonarr
|
||||||
|
Description: Sonarr user:
|
||||||
|
Specify the user that is used to run Sonarr. The user will be created if it does not already exist.
|
||||||
|
The default 'sonarr' should work fine for most users. You can specify the user group next.
|
||||||
|
|
||||||
|
Template: sonarr/owning_group
|
||||||
|
Type: string
|
||||||
|
Default: sonarr
|
||||||
|
Description: Sonarr group:
|
||||||
|
Specify the group that is used to run Sonarr. The group will be created if it does not already exist.
|
||||||
|
If the user doesn't already exist then this group will be used as the user's primary group.
|
||||||
|
Any media files created by Sonarr will be writeable by this group.
|
||||||
|
It's advisable to keep the group the same between download client, Sonarr and media centers.
|
||||||
|
|
||||||
|
Template: sonarr/config_directory
|
||||||
|
Type: string
|
||||||
|
Default: /var/lib/sonarr
|
||||||
|
Description: Config directory:
|
||||||
|
Specify the directory where Sonarr stores the internal database and metadata. Media content will be stored elsewhere.
|
|
@ -1,25 +1,16 @@
|
||||||
FROM ubuntu:focal AS builder
|
FROM ubuntu:xenial AS builder
|
||||||
|
|
||||||
ENV DEBIAN_FRONTEND noninteractive
|
ENV DEBIAN_FRONTEND noninteractive
|
||||||
ENV MONO_VERSION 5.18
|
ENV MONO_VERSION 5.14
|
||||||
|
|
||||||
RUN apt-get update && \
|
|
||||||
apt-get -y -o Dpkg::Options::="--force-confold" install --no-install-recommends \
|
|
||||||
apt-transport-https \
|
|
||||||
wget dirmngr gpg gpg-agent \
|
|
||||||
# add-apt-repository for PPAs
|
|
||||||
software-properties-common && \
|
|
||||||
rm -rf /var/lib/apt/lists/*
|
|
||||||
|
|
||||||
RUN apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF && \
|
RUN apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF && \
|
||||||
echo "deb http://download.mono-project.com/repo/debian stable-focal main" > /etc/apt/sources.list.d/mono-official-stable.list && \
|
echo "deb http://download.mono-project.com/repo/debian stable-xenial/snapshots/$MONO_VERSION main" > /etc/apt/sources.list.d/mono-official-stable.list && \
|
||||||
apt-get update && apt-get install -y \
|
apt-get update && apt-get install -y \
|
||||||
devscripts build-essential tofrodos \
|
devscripts build-essential tofrodos \
|
||||||
dh-make dh-systemd \
|
dh-make dh-systemd \
|
||||||
cli-common-dev \
|
cli-common-dev \
|
||||||
mono-complete \
|
mono-complete \
|
||||||
sqlite3 libcurl4 mediainfo
|
sqlite3 libcurl3 mediainfo
|
||||||
RUN apt-get upgrade -y
|
|
||||||
|
|
||||||
RUN apt-cache policy mono-complete
|
RUN apt-cache policy mono-complete
|
||||||
RUN apt-cache policy cli-common-dev
|
RUN apt-cache policy cli-common-dev
|
||||||
|
|
|
@ -1,7 +0,0 @@
|
||||||
@REM SET SONARR_MAJOR_VERSION=4
|
|
||||||
@REM SET SONARR_VERSION=4.0.0.5
|
|
||||||
@REM SET BRANCH=develop
|
|
||||||
@REM SET FRAMEWORK=net6.0
|
|
||||||
@REM SET RUNTIME=win-x64
|
|
||||||
|
|
||||||
inno\ISCC.exe sonarr.iss
|
|
|
@ -1,86 +0,0 @@
|
||||||
; Script generated by the Inno Setup Script Wizard.
|
|
||||||
; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!
|
|
||||||
|
|
||||||
#define AppName "Sonarr"
|
|
||||||
#define AppPublisher "Team Sonarr"
|
|
||||||
#define AppURL "https://sonarr.tv/"
|
|
||||||
#define ForumsURL "https://forums.sonarr.tv/"
|
|
||||||
#define AppExeName "Sonarr.exe"
|
|
||||||
#define BuildNumber "4.0"
|
|
||||||
#define BuildNumber GetEnv('SONARR_VERSION')
|
|
||||||
#define MajorVersion GetEnv('SONARR_MAJOR_VERSION')
|
|
||||||
#define BranchName GetEnv('BRANCH')
|
|
||||||
#define Framework GetEnv('FRAMEWORK')
|
|
||||||
#define Runtime GetEnv('RUNTIME')
|
|
||||||
|
|
||||||
[Setup]
|
|
||||||
; NOTE: The value of AppId uniquely identifies this appl ication.
|
|
||||||
; Do not use the same AppId value in installers for other applications.
|
|
||||||
; (To generate a new GUID, click Tools | Generate GUID inside the IDE.)
|
|
||||||
AppId={{56C1065D-3523-4025-B76D-6F73F67F7F71}
|
|
||||||
AppName={#AppName}
|
|
||||||
AppVersion={#MajorVersion}
|
|
||||||
AppPublisher={#AppPublisher}
|
|
||||||
AppPublisherURL={#AppURL}
|
|
||||||
AppSupportURL={#ForumsURL}
|
|
||||||
AppUpdatesURL={#AppURL}
|
|
||||||
UsePreviousAppDir=no
|
|
||||||
DefaultDirName={commonappdata}\Sonarr\bin
|
|
||||||
DisableDirPage=yes
|
|
||||||
DefaultGroupName={#AppName}
|
|
||||||
DisableProgramGroupPage=yes
|
|
||||||
OutputBaseFilename=Sonarr.{#BranchName}.{#BuildNumber}.{#Runtime}-installer
|
|
||||||
SolidCompression=yes
|
|
||||||
AppCopyright=Creative Commons 3.0 License
|
|
||||||
AllowUNCPath=False
|
|
||||||
UninstallDisplayIcon={app}\Sonarr.exe
|
|
||||||
DisableReadyPage=True
|
|
||||||
CompressionThreads=2
|
|
||||||
Compression=lzma2/normal
|
|
||||||
AppContact={#ForumsURL}
|
|
||||||
VersionInfoVersion={#MajorVersion}
|
|
||||||
SetupLogging=yes
|
|
||||||
OutputDir="..\..\..\_artifacts"
|
|
||||||
AppverName={#AppName}
|
|
||||||
|
|
||||||
[Languages]
|
|
||||||
Name: "english"; MessagesFile: "compiler:Default.isl"
|
|
||||||
|
|
||||||
[Tasks]
|
|
||||||
Name: "desktopIcon"; Description: "{cm:CreateDesktopIcon}"
|
|
||||||
Name: "windowsService"; Description: "Install Windows Service (Starts when the computer starts as the LocalService user, you will need to change the user to access network shares)"; GroupDescription: "Start automatically"; Flags: exclusive unchecked
|
|
||||||
Name: "startupShortcut"; Description: "Create shortcut in Startup folder (Starts when you log into Windows)"; GroupDescription: "Start automatically"; Flags: exclusive
|
|
||||||
Name: "none"; Description: "Do not start automatically"; GroupDescription: "Start automatically"; Flags: exclusive unchecked
|
|
||||||
|
|
||||||
[Files]
|
|
||||||
Source: "..\..\..\_output\{#Runtime}\{#Framework}\Sonarr\Sonarr.exe"; DestDir: "{app}"; Flags: ignoreversion
|
|
||||||
Source: "..\..\..\_output\{#Runtime}\{#Framework}\Sonarr\*"; Excludes: "Sonarr.Update"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
|
|
||||||
; NOTE: Don't use "Flags: ignoreversion" on any shared system files
|
|
||||||
|
|
||||||
[Icons]
|
|
||||||
Name: "{group}\{#AppName}"; Filename: "{app}\{#AppExeName}"; Parameters: "/icon"
|
|
||||||
Name: "{commondesktop}\{#AppName}"; Filename: "{app}\{#AppExeName}"; Parameters: "/icon"; Tasks: desktopIcon
|
|
||||||
Name: "{userstartup}\{#AppName}"; Filename: "{app}\Sonarr.exe"; WorkingDir: "{app}"; Tasks: startupShortcut
|
|
||||||
|
|
||||||
[InstallDelete]
|
|
||||||
Name: "{commonappdata}\NzbDrone\bin"; Type: filesandordirs
|
|
||||||
Name: "{app}"; Type: filesandordirs
|
|
||||||
|
|
||||||
[Run]
|
|
||||||
Filename: "{app}\Sonarr.Console.exe"; StatusMsg: "Removing previous Windows Service"; Parameters: "/u /exitimmediately"; Flags: runhidden waituntilterminated;
|
|
||||||
Filename: "{app}\Sonarr.Console.exe"; Description: "Enable Access from Other Devices"; StatusMsg: "Enabling Remote access"; Parameters: "/registerurl /exitimmediately"; Flags: postinstall runascurrentuser runhidden waituntilterminated; Tasks: startupShortcut none;
|
|
||||||
Filename: "{app}\Sonarr.Console.exe"; StatusMsg: "Installing Windows Service"; Parameters: "/i /exitimmediately"; Flags: runhidden waituntilterminated; Tasks: windowsService
|
|
||||||
Filename: "{app}\Sonarr.exe"; Description: "Open Sonarr Web UI"; Flags: postinstall skipifsilent nowait; Tasks: windowsService;
|
|
||||||
Filename: "{app}\Sonarr.exe"; Description: "Start Sonarr"; Flags: postinstall skipifsilent nowait; Tasks: startupShortcut none;
|
|
||||||
|
|
||||||
[UninstallRun]
|
|
||||||
Filename: "{app}\Sonarr.Console.exe"; Parameters: "/u"; Flags: runhidden waituntilterminated skipifdoesntexist
|
|
||||||
|
|
||||||
[Code]
|
|
||||||
function PrepareToInstall(var NeedsRestart: Boolean): String;
|
|
||||||
var
|
|
||||||
ResultCode: Integer;
|
|
||||||
begin
|
|
||||||
Exec('net', 'stop nzbdrone', '', 0, ewWaitUntilTerminated, ResultCode)
|
|
||||||
Exec('sc', 'delete nzbdrone', '', 0, ewWaitUntilTerminated, ResultCode)
|
|
||||||
end;
|
|
|
@ -18,8 +18,5 @@ RUN fromdos /startup.sh
|
||||||
WORKDIR /data/
|
WORKDIR /data/
|
||||||
VOLUME ["/data/_tests_linux", "/data/_output_linux", "/data/_tests_results"]
|
VOLUME ["/data/_tests_linux", "/data/_output_linux", "/data/_tests_results"]
|
||||||
|
|
||||||
RUN groupadd sonarrtst -g 4020 && useradd sonarrtst -u 4021 -g 4020 -m -s /bin/bash
|
|
||||||
USER sonarrtst
|
|
||||||
|
|
||||||
CMD bash /startup.sh
|
CMD bash /startup.sh
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,6 @@ RUN apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 3FA7E03280
|
||||||
|
|
||||||
RUN apt-get update && apt-get install -y \
|
RUN apt-get update && apt-get install -y \
|
||||||
libmono-system-runtime4.0-cil \
|
libmono-system-runtime4.0-cil \
|
||||||
libmono-system-net-http4.0-cil \
|
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
COPY startup.sh /startup.sh
|
COPY startup.sh /startup.sh
|
||||||
|
@ -25,8 +24,5 @@ RUN fromdos /startup.sh
|
||||||
WORKDIR /data/
|
WORKDIR /data/
|
||||||
VOLUME ["/data/_tests_linux", "/data/_output_linux", "/data/_tests_results"]
|
VOLUME ["/data/_tests_linux", "/data/_output_linux", "/data/_tests_results"]
|
||||||
|
|
||||||
RUN groupadd sonarrtst -g 4020 && useradd sonarrtst -u 4021 -g 4020 -m -s /bin/bash
|
|
||||||
USER sonarrtst
|
|
||||||
|
|
||||||
CMD bash /startup.sh
|
CMD bash /startup.sh
|
||||||
|
|
||||||
|
|
|
@ -2,18 +2,16 @@
|
||||||
opt_parallel=
|
opt_parallel=
|
||||||
opt_version=
|
opt_version=
|
||||||
opt_mode=both
|
opt_mode=both
|
||||||
while getopts 'pv:m:r?h' c
|
while getopts 'pv:m:?h' c
|
||||||
do
|
do
|
||||||
case $c in
|
case $c in
|
||||||
p) opt_parallel=1 ;;
|
p) opt_parallel=1 ;;
|
||||||
v) opt_version=$OPTARG ;;
|
v) opt_version=$OPTARG ;;
|
||||||
m) opt_mode=$OPTARG ;;
|
m) opt_mode=$OPTARG ;;
|
||||||
r) opt_report=1 ;;
|
|
||||||
?|h) printf "Usage: %s [-p] [-v mono-ver] [-m sonarr|complete]\n" $0
|
?|h) printf "Usage: %s [-p] [-v mono-ver] [-m sonarr|complete]\n" $0
|
||||||
printf " -p run parallel\n"
|
printf " -p run parallel\n"
|
||||||
printf " -v run specified mono version\n"
|
printf " -v run specified mono version\n"
|
||||||
printf " -m run only mono-'complete' or 'sonarr' package variants\n"
|
printf " -m run only mono-'complete' or 'sonarr' package variants\n"
|
||||||
printf " -r only report\n"
|
|
||||||
exit 2
|
exit 2
|
||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
|
@ -22,22 +20,17 @@ done
|
||||||
# make sure that the docker host has enough memory to handle about ~300 MB per container, so 2-3 GB total
|
# make sure that the docker host has enough memory to handle about ~300 MB per container, so 2-3 GB total
|
||||||
# excess goes to the swap and will slow down the entire system
|
# excess goes to the swap and will slow down the entire system
|
||||||
|
|
||||||
MONO_VERSIONS=""
|
# Preferred versions
|
||||||
|
MONO_VERSIONS="6.8 6.6 6.4 6.0 5.20 5.18"
|
||||||
|
|
||||||
# Future versions
|
# Future versions
|
||||||
MONO_VERSIONS="$MONO_VERSIONS 6.10=preview-xenial"
|
MONO_VERSIONS="$MONO_VERSIONS 6.10=preview-xenial"
|
||||||
|
|
||||||
# Semi-Supported versions
|
|
||||||
MONO_VERSIONS="$MONO_VERSIONS 6.8 6.6 6.4 6.0"
|
|
||||||
|
|
||||||
# Supported versions
|
# Supported versions
|
||||||
MONO_VERSIONS="$MONO_VERSIONS 5.20 5.18"
|
MONO_VERSIONS="$MONO_VERSIONS 5.16 5.14 5.12 5.10 5.8 5.4"
|
||||||
|
|
||||||
# Legacy unsupported versions (but appear to work)
|
|
||||||
MONO_VERSIONS="$MONO_VERSIONS 5.16 5.14 5.12"
|
|
||||||
|
|
||||||
# Legacy unsupported versions
|
# Legacy unsupported versions
|
||||||
MONO_VERSIONS="$MONO_VERSIONS 5.10 5.8 5.4 5.0"
|
MONO_VERSIONS="$MONO_VERSIONS 5.0"
|
||||||
#MONO_VERSIONS="$MONO_VERSIONS 4.8=stable-wheezy/snapshots/4.8"
|
#MONO_VERSIONS="$MONO_VERSIONS 4.8=stable-wheezy/snapshots/4.8"
|
||||||
|
|
||||||
if [ "$opt_version" != "" ]; then
|
if [ "$opt_version" != "" ]; then
|
||||||
|
@ -93,8 +86,6 @@ runOne() {
|
||||||
echo "Finished Test Docker for mono $MONO_VERSION"
|
echo "Finished Test Docker for mono $MONO_VERSION"
|
||||||
}
|
}
|
||||||
|
|
||||||
if [ "$opt_report" != "1" ]; then
|
|
||||||
|
|
||||||
if [ "$opt_parallel" == "1" ]; then
|
if [ "$opt_parallel" == "1" ]; then
|
||||||
for MONO_VERSION_PAIR in $MONO_VERSIONS; do
|
for MONO_VERSION_PAIR in $MONO_VERSIONS; do
|
||||||
prepOne "$MONO_VERSION_PAIR"
|
prepOne "$MONO_VERSION_PAIR"
|
||||||
|
@ -115,7 +106,3 @@ if [ "$opt_report" != "1" ]; then
|
||||||
wait
|
wait
|
||||||
echo "Finished all runs"
|
echo "Finished all runs"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
fi
|
|
||||||
|
|
||||||
grep "<test-run" ../../_tests_results/**/*.xml | sed -r 's/.*?mono-([0-9.]+(-s)?).*?_([IU]).*?\.xml.*?failed="([0-9]*)".*/\1\t\3:\tfailed \4/g' | sort -V -t.
|
|
48
docs.sh
48
docs.sh
|
@ -1,48 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
set -e
|
|
||||||
|
|
||||||
FRAMEWORK="net6.0"
|
|
||||||
PLATFORM=$1
|
|
||||||
|
|
||||||
if [ "$PLATFORM" = "Windows" ]; then
|
|
||||||
RUNTIME="win-x64"
|
|
||||||
elif [ "$PLATFORM" = "Linux" ]; then
|
|
||||||
RUNTIME="linux-x64"
|
|
||||||
elif [ "$PLATFORM" = "Mac" ]; then
|
|
||||||
RUNTIME="osx-x64"
|
|
||||||
else
|
|
||||||
echo "Platform must be provided as first argument: Windows, Linux or Mac"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
outputFolder='_output'
|
|
||||||
testPackageFolder='_tests'
|
|
||||||
|
|
||||||
rm -rf $outputFolder
|
|
||||||
rm -rf $testPackageFolder
|
|
||||||
|
|
||||||
slnFile=src/Sonarr.sln
|
|
||||||
|
|
||||||
platform=Posix
|
|
||||||
|
|
||||||
if [ "$PLATFORM" = "Windows" ]; then
|
|
||||||
application=Sonarr.Console.dll
|
|
||||||
else
|
|
||||||
application=Sonarr.dll
|
|
||||||
fi
|
|
||||||
|
|
||||||
dotnet clean $slnFile -c Debug
|
|
||||||
dotnet clean $slnFile -c Release
|
|
||||||
|
|
||||||
dotnet msbuild -restore $slnFile -p:Configuration=Debug -p:Platform=$platform -p:RuntimeIdentifiers=$RUNTIME -t:PublishAllRids
|
|
||||||
|
|
||||||
dotnet new tool-manifest
|
|
||||||
dotnet tool install --version 6.6.2 Swashbuckle.AspNetCore.Cli
|
|
||||||
|
|
||||||
dotnet tool run swagger tofile --output ./src/Sonarr.Api.V3/openapi.json "$outputFolder/$FRAMEWORK/$RUNTIME/$application" v3 &
|
|
||||||
|
|
||||||
sleep 45
|
|
||||||
|
|
||||||
kill %1
|
|
||||||
|
|
||||||
exit 0
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
{
|
||||||
|
"remove-empty-rulesets": true,
|
||||||
|
"always-semicolon": true,
|
||||||
|
"color-case": "lower",
|
||||||
|
"block-indent": " ",
|
||||||
|
"color-shorthand": false,
|
||||||
|
"element-case": "lower",
|
||||||
|
"eof-newline": true,
|
||||||
|
"leading-zero": true,
|
||||||
|
"quotes": "double",
|
||||||
|
"sort-order-fallback": "abc",
|
||||||
|
"space-before-colon": "",
|
||||||
|
"space-after-colon": " ",
|
||||||
|
"space-before-combinator": " ",
|
||||||
|
"space-after-combinator": " ",
|
||||||
|
"space-between-declarations": "\n",
|
||||||
|
"space-before-opening-brace": " ",
|
||||||
|
"space-after-opening-brace": "\n",
|
||||||
|
"space-after-selector-delimiter": " ",
|
||||||
|
"space-before-selector-delimiter": "",
|
||||||
|
"space-before-closing-brace": "\n",
|
||||||
|
"strip-spaces": true,
|
||||||
|
"tab-size": true,
|
||||||
|
"unitless-zero": false
|
||||||
|
}
|
|
@ -0,0 +1,335 @@
|
||||||
|
{
|
||||||
|
"indent": {
|
||||||
|
"value": " ",
|
||||||
|
"FunctionExpression": 1,
|
||||||
|
"ArrayExpression": 1,
|
||||||
|
"ObjectExpression": 1
|
||||||
|
},
|
||||||
|
"lineBreak": {
|
||||||
|
"value": "\n",
|
||||||
|
|
||||||
|
"before": {
|
||||||
|
"ArrayPatternClosing": 0,
|
||||||
|
"ArrayPatternComma": 0,
|
||||||
|
"ArrayPatternOpening": 0,
|
||||||
|
"ArrowFunctionExpressionArrow": 0,
|
||||||
|
"ArrowFunctionExpressionClosingBrace": ">=1",
|
||||||
|
"ArrowFunctionExpressionOpeningBrace": 0,
|
||||||
|
"AssignmentExpression": ">=1",
|
||||||
|
"AssignmentOperator": 0,
|
||||||
|
"BlockStatement": 0,
|
||||||
|
"BreakKeyword": ">=1",
|
||||||
|
"CallExpression": -1,
|
||||||
|
"CallExpressionClosingParentheses": -1,
|
||||||
|
"CallExpressionOpeningParentheses": 0,
|
||||||
|
"CatchClosingBrace": ">=1",
|
||||||
|
"CatchKeyword": 0,
|
||||||
|
"CatchOpeningBrace": 0,
|
||||||
|
"ClassDeclaration": ">=1",
|
||||||
|
"ClassDeclarationClosingBrace": ">=1",
|
||||||
|
"ClassDeclarationOpeningBrace": 0,
|
||||||
|
"ConditionalExpression": ">=1",
|
||||||
|
"DeleteOperator": ">=1",
|
||||||
|
"DoWhileStatement": ">=1",
|
||||||
|
"DoWhileStatementClosingBrace": ">=1",
|
||||||
|
"DoWhileStatementOpeningBrace": 0,
|
||||||
|
"ElseIfStatement": 0,
|
||||||
|
"ElseIfStatementClosingBrace": ">=1",
|
||||||
|
"ElseIfStatementOpeningBrace": 0,
|
||||||
|
"ElseStatement": 0,
|
||||||
|
"ElseStatementClosingBrace": ">=1",
|
||||||
|
"ElseStatementOpeningBrace": 0,
|
||||||
|
"EmptyStatement": -1,
|
||||||
|
"EndOfFile": -1,
|
||||||
|
"FinallyClosingBrace": ">=1",
|
||||||
|
"FinallyKeyword": -1,
|
||||||
|
"FinallyOpeningBrace": 0,
|
||||||
|
"ForInStatement": ">=1",
|
||||||
|
"ForInStatementClosingBrace": ">=1",
|
||||||
|
"ForInStatementExpressionClosing": 0,
|
||||||
|
"ForInStatementExpressionOpening": 0,
|
||||||
|
"ForInStatementOpeningBrace": 0,
|
||||||
|
"ForStatement": ">=1",
|
||||||
|
"ForStatementClosingBrace": ">=1",
|
||||||
|
"ForStatementExpressionClosing": "<2",
|
||||||
|
"ForStatementExpressionOpening": 0,
|
||||||
|
"ForStatementOpeningBrace": 0,
|
||||||
|
"FunctionDeclaration": ">=1",
|
||||||
|
"FunctionDeclarationClosingBrace": ">=1",
|
||||||
|
"FunctionDeclarationOpeningBrace": 0,
|
||||||
|
"FunctionExpression": 0,
|
||||||
|
"FunctionExpressionClosingBrace": 1,
|
||||||
|
"FunctionExpressionOpeningBrace":0,
|
||||||
|
"IIFEClosingParentheses": 0,
|
||||||
|
"IfStatement": ">=1",
|
||||||
|
"IfStatementClosingBrace": ">=1",
|
||||||
|
"IfStatementOpeningBrace": 0,
|
||||||
|
"LogicalExpression": -1,
|
||||||
|
"MemberExpressionClosing": 0,
|
||||||
|
"MemberExpressionOpening": 0,
|
||||||
|
"MemberExpressionPeriod": -1,
|
||||||
|
"MethodDefinition": ">=1",
|
||||||
|
"ObjectExpressionClosingBrace": "<=1",
|
||||||
|
"ObjectPatternClosingBrace": 0,
|
||||||
|
"ObjectPatternComma": 0,
|
||||||
|
"ObjectPatternOpeningBrace": 0,
|
||||||
|
"ParameterDefault": 0,
|
||||||
|
"Property": "<=2",
|
||||||
|
"PropertyValue": 0,
|
||||||
|
"ReturnStatement": -1,
|
||||||
|
"SwitchClosingBrace": ">=1",
|
||||||
|
"SwitchOpeningBrace": 0,
|
||||||
|
"ThisExpression": -1,
|
||||||
|
"ThrowStatement": ">=1",
|
||||||
|
"TryClosingBrace": ">=1",
|
||||||
|
"TryKeyword": -1,
|
||||||
|
"TryOpeningBrace": 0,
|
||||||
|
"VariableDeclaration": ">=1",
|
||||||
|
"VariableDeclarationSemiColon": 0,
|
||||||
|
"VariableDeclarationWithoutInit": ">=1",
|
||||||
|
"VariableName": ">=1",
|
||||||
|
"VariableValue": 0,
|
||||||
|
"WhileStatement": ">=1",
|
||||||
|
"WhileStatementClosingBrace": ">=1",
|
||||||
|
"WhileStatementOpeningBrace": 0
|
||||||
|
},
|
||||||
|
|
||||||
|
"after": {
|
||||||
|
"ArrayPatternClosing": 0,
|
||||||
|
"ArrayPatternComma": 0,
|
||||||
|
"ArrayPatternOpening": 0,
|
||||||
|
"ArrowFunctionExpressionArrow": 0,
|
||||||
|
"ArrowFunctionExpressionClosingBrace": -1,
|
||||||
|
"ArrowFunctionExpressionOpeningBrace": ">=1",
|
||||||
|
"AssignmentExpression": ">=1",
|
||||||
|
"AssignmentOperator": 0,
|
||||||
|
"BlockStatement": 0,
|
||||||
|
"BreakKeyword": -1,
|
||||||
|
"CallExpression": -1,
|
||||||
|
"CallExpressionClosingParentheses": -1,
|
||||||
|
"CallExpressionOpeningParentheses": -1,
|
||||||
|
"CatchClosingBrace": ">=0",
|
||||||
|
"CatchKeyword": 0,
|
||||||
|
"CatchOpeningBrace": ">=1",
|
||||||
|
"ClassDeclaration": ">=1",
|
||||||
|
"ClassDeclarationClosingBrace": ">=1",
|
||||||
|
"ClassDeclarationOpeningBrace": ">=1",
|
||||||
|
"ConditionalExpression": ">=1",
|
||||||
|
"DeleteOperator": ">=1",
|
||||||
|
"DoWhileStatement": ">=1",
|
||||||
|
"DoWhileStatementClosingBrace": 0,
|
||||||
|
"DoWhileStatementOpeningBrace": ">=1",
|
||||||
|
"ElseIfStatement": ">=1",
|
||||||
|
"ElseIfStatementClosingBrace": ">=1",
|
||||||
|
"ElseIfStatementOpeningBrace": ">=1",
|
||||||
|
"ElseStatement": ">=1",
|
||||||
|
"ElseStatementClosingBrace": ">=1",
|
||||||
|
"ElseStatementOpeningBrace": ">=1",
|
||||||
|
"EmptyStatement": -1,
|
||||||
|
"FinallyClosingBrace": ">=1",
|
||||||
|
"FinallyKeyword": -1,
|
||||||
|
"FinallyOpeningBrace": ">=1",
|
||||||
|
"ForInStatement": ">=1",
|
||||||
|
"ForInStatementClosingBrace": ">=1",
|
||||||
|
"ForInStatementExpressionClosing": -1,
|
||||||
|
"ForInStatementExpressionOpening": "<2",
|
||||||
|
"ForInStatementOpeningBrace": ">=1",
|
||||||
|
"ForStatement": ">=1",
|
||||||
|
"ForStatementClosingBrace": ">=1",
|
||||||
|
"ForStatementExpressionClosing": -1,
|
||||||
|
"ForStatementExpressionOpening": "<2",
|
||||||
|
"ForStatementOpeningBrace": ">=1",
|
||||||
|
"FunctionDeclaration": ">=1",
|
||||||
|
"FunctionDeclarationClosingBrace": ">=1",
|
||||||
|
"FunctionDeclarationOpeningBrace": ">=1",
|
||||||
|
"FunctionExpression": 0,
|
||||||
|
"FunctionExpressionClosingBrace": -1,
|
||||||
|
"FunctionExpressionOpeningBrace": 1,
|
||||||
|
"IIFEOpeningParentheses": 0,
|
||||||
|
"IfStatement": ">=1",
|
||||||
|
"IfStatementClosingBrace": ">=1",
|
||||||
|
"IfStatementOpeningBrace": ">=1",
|
||||||
|
"LogicalExpression": -1,
|
||||||
|
"MemberExpressionClosing": 0,
|
||||||
|
"MemberExpressionOpening": 0,
|
||||||
|
"MemberExpressionPeriod": 0,
|
||||||
|
"MethodDefinition": ">=1",
|
||||||
|
"ObjectExpressionOpeningBrace": "<=1",
|
||||||
|
"ObjectPatternClosingBrace": 0,
|
||||||
|
"ObjectPatternComma": 0,
|
||||||
|
"ObjectPatternOpeningBrace": 0,
|
||||||
|
"ParameterDefault": 0,
|
||||||
|
"Property": -1,
|
||||||
|
"PropertyName": 0,
|
||||||
|
"ReturnStatement": -1,
|
||||||
|
"SwitchCaseColon": ">=1",
|
||||||
|
"SwitchClosingBrace": ">=1",
|
||||||
|
"SwitchOpeningBrace": ">=1",
|
||||||
|
"ThisExpression": 0,
|
||||||
|
"ThrowStatement": ">=1",
|
||||||
|
"TryClosingBrace": 0,
|
||||||
|
"TryKeyword": -1,
|
||||||
|
"TryOpeningBrace": ">=1",
|
||||||
|
"VariableDeclaration": ">=1",
|
||||||
|
"VariableDeclarationSemiColon": ">=1",
|
||||||
|
"VariableValue": -1,
|
||||||
|
"WhileStatement": ">=1",
|
||||||
|
"WhileStatementClosingBrace": ">=1",
|
||||||
|
"WhileStatementOpeningBrace": ">=1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"whiteSpace": {
|
||||||
|
"value": " ",
|
||||||
|
"removeTrailing": 1,
|
||||||
|
"before": {
|
||||||
|
"ArgumentComma": 0,
|
||||||
|
"ArgumentList": 0,
|
||||||
|
"ArgumentListArrayExpression": 0,
|
||||||
|
"ArgumentListFunctionExpression": 1,
|
||||||
|
"ArgumentListObjectExpression": 0,
|
||||||
|
"ArrayExpressionClosing": 0,
|
||||||
|
"ArrayExpressionComma": 0,
|
||||||
|
"ArrayExpressionOpening": 1,
|
||||||
|
"AssignmentOperator": 1,
|
||||||
|
"BinaryExpression": 0,
|
||||||
|
"BinaryExpressionOperator": 1,
|
||||||
|
"BlockComment": 1,
|
||||||
|
"CallExpression": 1,
|
||||||
|
"CatchClosingBrace": 1,
|
||||||
|
"CatchKeyword": 1,
|
||||||
|
"CatchOpeningBrace": 1,
|
||||||
|
"CatchParameterList": 0,
|
||||||
|
"CommaOperator": 0,
|
||||||
|
"ConditionalExpressionAlternate": 1,
|
||||||
|
"ConditionalExpressionConsequent": 1,
|
||||||
|
"DoWhileStatementClosingBrace": 1,
|
||||||
|
"DoWhileStatementConditional": 1,
|
||||||
|
"DoWhileStatementOpeningBrace": 1,
|
||||||
|
"ElseIfStatementClosingBrace": 1,
|
||||||
|
"ElseIfStatementOpeningBrace": 1,
|
||||||
|
"ElseStatementClosingBrace": 1,
|
||||||
|
"ElseStatementOpeningBrace": 1,
|
||||||
|
"EmptyStatement": 0,
|
||||||
|
"ExpressionClosingParentheses": 0,
|
||||||
|
"FinallyClosingBrace": 1,
|
||||||
|
"FinallyKeyword": -1,
|
||||||
|
"FinallyOpeningBrace": 1,
|
||||||
|
"ForInStatement": 1,
|
||||||
|
"ForInStatementClosingBrace": 1,
|
||||||
|
"ForInStatementExpressionClosing": 0,
|
||||||
|
"ForInStatementExpressionOpening": 1,
|
||||||
|
"ForInStatementOpeningBrace": 1,
|
||||||
|
"ForStatement": 1,
|
||||||
|
"ForStatementClosingBrace": 1,
|
||||||
|
"ForStatementExpressionClosing": 0,
|
||||||
|
"ForStatementExpressionOpening": 1,
|
||||||
|
"ForStatementOpeningBrace": 1,
|
||||||
|
"ForStatementSemicolon": 0,
|
||||||
|
"FunctionDeclarationClosingBrace": 1,
|
||||||
|
"FunctionDeclarationOpeningBrace": 1,
|
||||||
|
"FunctionExpressionClosingBrace": 1,
|
||||||
|
"FunctionExpressionOpeningBrace": 1,
|
||||||
|
"IfStatementClosingBrace": 1,
|
||||||
|
"IfStatementConditionalClosing": 0,
|
||||||
|
"IfStatementConditionalOpening": 1,
|
||||||
|
"IfStatementOpeningBrace": 1,
|
||||||
|
"LineComment": 1,
|
||||||
|
"LogicalExpressionOperator": 1,
|
||||||
|
"MemberExpressionClosing": 0,
|
||||||
|
"ObjectExpressionClosingBrace": 1,
|
||||||
|
"ParameterComma": 0,
|
||||||
|
"ParameterList": 0,
|
||||||
|
"Property": 1,
|
||||||
|
"PropertyName": 1,
|
||||||
|
"PropertyValue": 1,
|
||||||
|
"SwitchDiscriminantClosing": 0,
|
||||||
|
"SwitchDiscriminantOpening": 1,
|
||||||
|
"ThrowKeyword": 1,
|
||||||
|
"TryClosingBrace": 1,
|
||||||
|
"TryKeyword": -1,
|
||||||
|
"TryOpeningBrace": 1,
|
||||||
|
"UnaryExpressionOperator": 0,
|
||||||
|
"VariableName": 1,
|
||||||
|
"VariableValue": 1,
|
||||||
|
"WhileStatementClosingBrace": 1,
|
||||||
|
"WhileStatementConditionalClosing": 0,
|
||||||
|
"WhileStatementConditionalOpening": 1,
|
||||||
|
"WhileStatementOpeningBrace": 1
|
||||||
|
},
|
||||||
|
"after": {
|
||||||
|
"ArgumentComma": 1,
|
||||||
|
"ArgumentList": 0,
|
||||||
|
"ArgumentListArrayExpression": 1,
|
||||||
|
"ArgumentListFunctionExpression": 1,
|
||||||
|
"ArgumentListObjectExpression": 0,
|
||||||
|
"ArrayExpressionClosing": 0,
|
||||||
|
"ArrayExpressionComma": 1,
|
||||||
|
"ArrayExpressionOpening": 0,
|
||||||
|
"AssignmentOperator": 1,
|
||||||
|
"BinaryExpression": 0,
|
||||||
|
"BinaryExpressionOperator": 1,
|
||||||
|
"BlockComment": 1,
|
||||||
|
"CallExpression": 0,
|
||||||
|
"CatchClosingBrace": 1,
|
||||||
|
"CatchKeyword": 1,
|
||||||
|
"CatchOpeningBrace": 1,
|
||||||
|
"CatchParameterList": 0,
|
||||||
|
"CommaOperator": 1,
|
||||||
|
"ConditionalExpressionConsequent": 1,
|
||||||
|
"ConditionalExpressionTest": 1,
|
||||||
|
"DoWhileStatementBody": 1,
|
||||||
|
"DoWhileStatementClosingBrace": 1,
|
||||||
|
"DoWhileStatementOpeningBrace": 1,
|
||||||
|
"ElseIfStatementClosingBrace": 1,
|
||||||
|
"ElseIfStatementOpeningBrace": 1,
|
||||||
|
"ElseStatementClosingBrace": 1,
|
||||||
|
"ElseStatementOpeningBrace": 1,
|
||||||
|
"EmptyStatement": 0,
|
||||||
|
"ExpressionOpeningParentheses": 0,
|
||||||
|
"FinallyClosingBrace": 1,
|
||||||
|
"FinallyKeyword": -1,
|
||||||
|
"FinallyOpeningBrace": 1,
|
||||||
|
"ForInStatement": 1,
|
||||||
|
"ForInStatementClosingBrace": 1,
|
||||||
|
"ForInStatementExpressionClosing": 1,
|
||||||
|
"ForInStatementExpressionOpening": 0,
|
||||||
|
"ForInStatementOpeningBrace": 1,
|
||||||
|
"ForStatement": 1,
|
||||||
|
"ForStatementClosingBrace": 1,
|
||||||
|
"ForStatementExpressionClosing": 1,
|
||||||
|
"ForStatementExpressionOpening": 0,
|
||||||
|
"ForStatementOpeningBrace": 1,
|
||||||
|
"ForStatementSemicolon": 1,
|
||||||
|
"FunctionDeclarationClosingBrace": 0,
|
||||||
|
"FunctionDeclarationOpeningBrace": 0,
|
||||||
|
"FunctionExpressionClosingBrace": 0,
|
||||||
|
"FunctionExpressionOpeningBrace": 0,
|
||||||
|
"FunctionName": 0,
|
||||||
|
"FunctionReservedWord": 0,
|
||||||
|
"IfStatementClosingBrace": 1,
|
||||||
|
"IfStatementConditionalClosing": 0,
|
||||||
|
"IfStatementConditionalOpening": 0,
|
||||||
|
"IfStatementOpeningBrace": 1,
|
||||||
|
"LogicalExpressionOperator": 1,
|
||||||
|
"MemberExpressionOpening": 0,
|
||||||
|
"ObjectExpressionClosingBrace": 0,
|
||||||
|
"ObjectExpressionOpeningBrace": 1,
|
||||||
|
"ParameterComma": 1,
|
||||||
|
"ParameterList": 0,
|
||||||
|
"PropertyName": 0,
|
||||||
|
"PropertyValue": 0,
|
||||||
|
"SwitchDiscriminantClosing": 1,
|
||||||
|
"SwitchDiscriminantOpening": 0,
|
||||||
|
"ThrowKeyword": 1,
|
||||||
|
"TryClosingBrace": 1,
|
||||||
|
"TryKeyword": -1,
|
||||||
|
"TryOpeningBrace": 1,
|
||||||
|
"UnaryExpressionOperator": 0,
|
||||||
|
"VariableName": 1,
|
||||||
|
"WhileStatementClosingBrace": 1,
|
||||||
|
"WhileStatementConditionalClosing": 1,
|
||||||
|
"WhileStatementConditionalOpening": 0,
|
||||||
|
"WhileStatementOpeningBrace": 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,2 +1 @@
|
||||||
**/JsLibraries/**
|
**/JsLibraries/**
|
||||||
**/*.css.d.ts
|
|
||||||
|
|
|
@ -0,0 +1,293 @@
|
||||||
|
{
|
||||||
|
"parser": "babel-eslint",
|
||||||
|
|
||||||
|
"env": {
|
||||||
|
"browser": true,
|
||||||
|
"commonjs": true,
|
||||||
|
"node": true,
|
||||||
|
"es6": true
|
||||||
|
},
|
||||||
|
|
||||||
|
"globals": {
|
||||||
|
"expect": false,
|
||||||
|
"chai": false,
|
||||||
|
"sinon": false
|
||||||
|
},
|
||||||
|
|
||||||
|
"parserOptions": {
|
||||||
|
"ecmaVersion": 6,
|
||||||
|
"sourceType": "module",
|
||||||
|
"ecmaFeatures": {
|
||||||
|
"modules": true,
|
||||||
|
"impliedStrict": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
"plugins": [
|
||||||
|
"filenames",
|
||||||
|
"react"
|
||||||
|
],
|
||||||
|
|
||||||
|
"settings": {
|
||||||
|
"react": {
|
||||||
|
"version": "detect"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
"rules": {
|
||||||
|
"filenames/match-exported": ["error"],
|
||||||
|
|
||||||
|
# ECMAScript 6
|
||||||
|
|
||||||
|
"arrow-body-style": [0],
|
||||||
|
"arrow-parens": ["error", "always"],
|
||||||
|
"arrow-spacing": ["error", { "before": true, "after": true }],
|
||||||
|
"constructor-super": "error",
|
||||||
|
"generator-star-spacing": "off",
|
||||||
|
"no-class-assign": "error",
|
||||||
|
"no-confusing-arrow": "error",
|
||||||
|
"no-const-assign": "error",
|
||||||
|
"no-dupe-class-members": "error",
|
||||||
|
"no-duplicate-imports": "error",
|
||||||
|
"no-new-symbol": "error",
|
||||||
|
"no-this-before-super": "error",
|
||||||
|
"no-useless-escape": "error",
|
||||||
|
"no-useless-computed-key": "error",
|
||||||
|
"no-useless-constructor": "error",
|
||||||
|
"no-var": "warn",
|
||||||
|
"object-shorthand": ["error", "properties"],
|
||||||
|
"prefer-arrow-callback": "error",
|
||||||
|
"prefer-const": "warn",
|
||||||
|
"prefer-reflect": "off",
|
||||||
|
"prefer-rest-params": "off",
|
||||||
|
"prefer-spread": "warn",
|
||||||
|
"prefer-template": "error",
|
||||||
|
"require-yield": "off",
|
||||||
|
"template-curly-spacing": ["error", "never"],
|
||||||
|
"yield-star-spacing": "off",
|
||||||
|
|
||||||
|
# Possible Errors
|
||||||
|
|
||||||
|
"comma-dangle": "error",
|
||||||
|
"no-cond-assign": "error",
|
||||||
|
"no-console": "off",
|
||||||
|
"no-constant-condition": "warn",
|
||||||
|
"no-control-regex": "error",
|
||||||
|
"no-debugger": "off",
|
||||||
|
"no-dupe-args": "error",
|
||||||
|
"no-dupe-keys": "error",
|
||||||
|
"no-duplicate-case": "error",
|
||||||
|
"no-empty": "warn",
|
||||||
|
"no-empty-character-class": "error",
|
||||||
|
"no-ex-assign": "error",
|
||||||
|
"no-extra-boolean-cast": "error",
|
||||||
|
"no-extra-parens": ["error", "functions"],
|
||||||
|
"no-extra-semi": "error",
|
||||||
|
"no-func-assign": "error",
|
||||||
|
"no-inner-declarations": "error",
|
||||||
|
"no-invalid-regexp": "error",
|
||||||
|
"no-irregular-whitespace": "error",
|
||||||
|
"no-negated-in-lhs": "error",
|
||||||
|
"no-obj-calls": "error",
|
||||||
|
"no-regex-spaces": "error",
|
||||||
|
"no-sparse-arrays": "error",
|
||||||
|
"no-unexpected-multiline": "error",
|
||||||
|
"no-unreachable": "warn",
|
||||||
|
"no-unsafe-finally": "error",
|
||||||
|
"use-isnan": "error",
|
||||||
|
"valid-jsdoc": "off",
|
||||||
|
"valid-typeof": "error",
|
||||||
|
|
||||||
|
# Best Practices
|
||||||
|
|
||||||
|
"accessor-pairs": "off",
|
||||||
|
"array-callback-return": "warn",
|
||||||
|
"block-scoped-var": "warn",
|
||||||
|
"consistent-return": "off",
|
||||||
|
"curly": "error",
|
||||||
|
"default-case": "error",
|
||||||
|
"dot-location": ["error", "property"],
|
||||||
|
"dot-notation": "error",
|
||||||
|
"eqeqeq": ["error", "smart"],
|
||||||
|
"guard-for-in": "error",
|
||||||
|
"no-alert": "warn",
|
||||||
|
"no-caller": "error",
|
||||||
|
"no-case-declarations": "error",
|
||||||
|
"no-div-regex": "error",
|
||||||
|
"no-else-return": "error",
|
||||||
|
"no-empty-function": ["error", {"allow": ["arrowFunctions"]}],
|
||||||
|
"no-empty-pattern": "error",
|
||||||
|
"no-eval": "error",
|
||||||
|
"no-extend-native": "error",
|
||||||
|
"no-extra-bind": "error",
|
||||||
|
"no-fallthrough": "error",
|
||||||
|
"no-floating-decimal": "error",
|
||||||
|
"no-implicit-coercion": ["error", {
|
||||||
|
"boolean": false,
|
||||||
|
"number": true,
|
||||||
|
"string": true,
|
||||||
|
"allow": [/* "!!", "~", "*", "+" */]
|
||||||
|
}],
|
||||||
|
"no-implicit-globals": "error",
|
||||||
|
"no-implied-eval": "error",
|
||||||
|
"no-invalid-this": "off",
|
||||||
|
"no-iterator": "error",
|
||||||
|
"no-labels": "error",
|
||||||
|
"no-lone-blocks": "error",
|
||||||
|
"no-loop-func": "error",
|
||||||
|
"no-magic-numbers": ["off", {"ignoreArrayIndexes": true, "ignore": [0, 1] }],
|
||||||
|
"no-multi-spaces": "error",
|
||||||
|
"no-multi-str": "error",
|
||||||
|
"no-native-reassign": ["error", {"exceptions": ["console"]}],
|
||||||
|
"no-new": "off",
|
||||||
|
"no-new-func": "error",
|
||||||
|
"no-new-wrappers": "error",
|
||||||
|
"no-octal": "error",
|
||||||
|
"no-octal-escape": "error",
|
||||||
|
"no-param-reassign": "off",
|
||||||
|
"no-process-env": "off",
|
||||||
|
"no-proto": "error",
|
||||||
|
"no-redeclare": "error",
|
||||||
|
"no-return-assign": "warn",
|
||||||
|
"no-script-url": "error",
|
||||||
|
"no-self-assign": "error",
|
||||||
|
"no-self-compare": "error",
|
||||||
|
"no-sequences": "error",
|
||||||
|
"no-throw-literal": "error",
|
||||||
|
"no-unmodified-loop-condition": "error",
|
||||||
|
"no-unused-expressions": "error",
|
||||||
|
"no-unused-labels": "error",
|
||||||
|
"no-useless-call": "error",
|
||||||
|
"no-useless-concat": "error",
|
||||||
|
"no-void": "error",
|
||||||
|
"no-warning-comments": "off",
|
||||||
|
"no-with": "error",
|
||||||
|
"radix": ["error", "as-needed"],
|
||||||
|
"vars-on-top": "off",
|
||||||
|
"wrap-iife": ["error", "inside"],
|
||||||
|
"yoda": "error",
|
||||||
|
|
||||||
|
# Strict Mode
|
||||||
|
|
||||||
|
"strict": ["error", "never"],
|
||||||
|
|
||||||
|
# Variables
|
||||||
|
|
||||||
|
"init-declarations": ["error", "always"],
|
||||||
|
"no-catch-shadow": "error",
|
||||||
|
"no-delete-var": "error",
|
||||||
|
"no-label-var": "error",
|
||||||
|
"no-restricted-globals": "off",
|
||||||
|
"no-shadow": "error",
|
||||||
|
"no-shadow-restricted-names": "error",
|
||||||
|
"no-undef": "error",
|
||||||
|
"no-undef-init": "off",
|
||||||
|
"no-undefined": "off",
|
||||||
|
"no-unused-vars": ["error", { "args": "none", "ignoreRestSiblings": true }],
|
||||||
|
"no-use-before-define": "error",
|
||||||
|
|
||||||
|
# Node.js and CommonJS
|
||||||
|
|
||||||
|
"callback-return": "warn",
|
||||||
|
"global-require": "error",
|
||||||
|
"handle-callback-err": "warn",
|
||||||
|
"no-mixed-requires": "error",
|
||||||
|
"no-new-require": "error",
|
||||||
|
"no-path-concat": "error",
|
||||||
|
"no-process-exit": "error",
|
||||||
|
|
||||||
|
# Stylistic Issues
|
||||||
|
|
||||||
|
"array-bracket-spacing": ["error", "never"],
|
||||||
|
"block-spacing": ["error", "always"],
|
||||||
|
"brace-style": ["error", "1tbs", { "allowSingleLine": false }],
|
||||||
|
"camelcase": "off",
|
||||||
|
"comma-spacing": ["error", {"before": false, "after": true}],
|
||||||
|
"comma-style": ["error", "last"],
|
||||||
|
"computed-property-spacing": ["error", "never"],
|
||||||
|
"consistent-this": ["error", "self"],
|
||||||
|
"eol-last": "error",
|
||||||
|
"func-names": "off",
|
||||||
|
"func-style": ["error", "declaration"],
|
||||||
|
"indent": ["error", 2, {"SwitchCase": 1}],
|
||||||
|
"key-spacing": ["error", {"beforeColon": false, "afterColon": true}],
|
||||||
|
"keyword-spacing": ["error", { "before": true, "after": true}],
|
||||||
|
"lines-around-comment": ["error", { "beforeBlockComment": true, "afterBlockComment": false }],
|
||||||
|
"max-depth": ["error", {"maximum": 5}],
|
||||||
|
"max-nested-callbacks": ["error", 4],
|
||||||
|
"max-statements": "off",
|
||||||
|
"max-statements-per-line": ["error", { "max": 1 }],
|
||||||
|
"new-cap": ["error", {"capIsNewExceptions": ["$.Deferred", "DragDropContext", "DragLayer", "DragSource", "DropTarget"]}],
|
||||||
|
"new-parens": "error",
|
||||||
|
"newline-after-var": "off",
|
||||||
|
"newline-before-return": "off",
|
||||||
|
"newline-per-chained-call": "off",
|
||||||
|
"no-array-constructor": "error",
|
||||||
|
"no-bitwise": "error",
|
||||||
|
"no-continue": "error",
|
||||||
|
"no-inline-comments": "off",
|
||||||
|
"no-lonely-if": "warn",
|
||||||
|
"no-mixed-spaces-and-tabs": "error",
|
||||||
|
"no-multiple-empty-lines": ["error", { "max": 1 }],
|
||||||
|
"no-negated-condition": "warn",
|
||||||
|
"no-nested-ternary": "error",
|
||||||
|
"no-new-object": "error",
|
||||||
|
"no-plusplus": "off",
|
||||||
|
"no-restricted-syntax": "off",
|
||||||
|
"no-spaced-func": "error",
|
||||||
|
"no-ternary": "off",
|
||||||
|
"no-trailing-spaces": "error",
|
||||||
|
"no-underscore-dangle": ["error", { "allowAfterThis": true }],
|
||||||
|
"no-unneeded-ternary": "error",
|
||||||
|
"no-whitespace-before-property": "error",
|
||||||
|
"object-curly-spacing": ["error", "always"],
|
||||||
|
"one-var": ["error", "never"],
|
||||||
|
"one-var-declaration-per-line": ["error", "always"],
|
||||||
|
"operator-assignment": ["off", "never"],
|
||||||
|
"operator-linebreak": ["error", "after"],
|
||||||
|
"quote-props": ["error", "as-needed"],
|
||||||
|
"quotes": ["error", "single"],
|
||||||
|
"require-jsdoc": "off",
|
||||||
|
"semi": "error",
|
||||||
|
"semi-spacing": ["error", { "before": false, "after": true }],
|
||||||
|
"sort-vars": "off",
|
||||||
|
"space-before-blocks": ["error", "always"],
|
||||||
|
"space-before-function-paren": ["error", "never"],
|
||||||
|
"space-in-parens": "off",
|
||||||
|
"space-infix-ops": "off",
|
||||||
|
"space-unary-ops": "off",
|
||||||
|
"spaced-comment": "error",
|
||||||
|
"wrap-regex": "error",
|
||||||
|
|
||||||
|
# React
|
||||||
|
|
||||||
|
"react/jsx-boolean-value": [2, "always"],
|
||||||
|
"react/jsx-uses-vars": 2,
|
||||||
|
"react/jsx-closing-bracket-location": 2,
|
||||||
|
"react/jsx-tag-spacing": ["error"],
|
||||||
|
"react/jsx-curly-spacing": [2, "never"],
|
||||||
|
"react/jsx-equals-spacing": [2, "never"],
|
||||||
|
"react/jsx-indent-props": [2, 2],
|
||||||
|
"react/jsx-indent": [2, 2],
|
||||||
|
"react/jsx-key": 2,
|
||||||
|
"react/jsx-no-bind": [2, { "allowArrowFunctions": true }],
|
||||||
|
"react/jsx-no-duplicate-props": [2, { "ignoreCase": true }],
|
||||||
|
"react/jsx-max-props-per-line": [2, { "maximum": 2 }],
|
||||||
|
"react/jsx-handler-names": [2, { "eventHandlerPrefix": "(on|dispatch)", "eventHandlerPropPrefix": "on" }],
|
||||||
|
"react/jsx-no-undef": 2,
|
||||||
|
"react/jsx-pascal-case": 2,
|
||||||
|
"react/jsx-uses-react": 2,
|
||||||
|
// Explicitly disabled in case we want to enable them again
|
||||||
|
"react/no-did-mount-set-state": 0,
|
||||||
|
"react/no-did-update-set-state": 0,
|
||||||
|
"react/no-direct-mutation-state": 2,
|
||||||
|
"react/no-multi-comp": [2, { "ignoreStateless": true }],
|
||||||
|
"react/no-unknown-property": 2,
|
||||||
|
"react/prefer-es6-class": 2,
|
||||||
|
"react/prop-types": 2,
|
||||||
|
"react/react-in-jsx-scope": 2,
|
||||||
|
"react/self-closing-comp": 2,
|
||||||
|
"react/sort-comp": 2,
|
||||||
|
"react/jsx-wrap-multilines": 2
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,432 +0,0 @@
|
||||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
||||||
const fs = require('fs');
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
||||||
const path = require('path');
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
||||||
const typescriptEslintRecommended = require('@typescript-eslint/eslint-plugin').configs.recommended;
|
|
||||||
|
|
||||||
const frontendFolder = __dirname;
|
|
||||||
|
|
||||||
const dirs = fs
|
|
||||||
.readdirSync(path.join(frontendFolder, 'src'), { withFileTypes: true })
|
|
||||||
.filter((dirent) => dirent.isDirectory())
|
|
||||||
.map((dirent) => dirent.name)
|
|
||||||
.join('|');
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
root: true,
|
|
||||||
|
|
||||||
parser: '@babel/eslint-parser',
|
|
||||||
|
|
||||||
env: {
|
|
||||||
browser: true,
|
|
||||||
commonjs: true,
|
|
||||||
node: true,
|
|
||||||
es6: true
|
|
||||||
},
|
|
||||||
|
|
||||||
globals: {
|
|
||||||
expect: false,
|
|
||||||
chai: false,
|
|
||||||
sinon: false,
|
|
||||||
JSX: true
|
|
||||||
},
|
|
||||||
|
|
||||||
parserOptions: {
|
|
||||||
ecmaVersion: 6,
|
|
||||||
sourceType: 'module',
|
|
||||||
babelOptions: {
|
|
||||||
configFile: `${frontendFolder}/babel.config.js`
|
|
||||||
},
|
|
||||||
ecmaFeatures: {
|
|
||||||
modules: true,
|
|
||||||
impliedStrict: true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
plugins: [
|
|
||||||
'filenames',
|
|
||||||
'react',
|
|
||||||
'react-hooks',
|
|
||||||
'simple-import-sort',
|
|
||||||
'import',
|
|
||||||
'@typescript-eslint',
|
|
||||||
'prettier'
|
|
||||||
],
|
|
||||||
|
|
||||||
settings: {
|
|
||||||
react: {
|
|
||||||
version: 'detect'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
rules: {
|
|
||||||
'filenames/match-exported': ['error'],
|
|
||||||
|
|
||||||
// ECMAScript 6
|
|
||||||
|
|
||||||
'arrow-body-style': [0],
|
|
||||||
'arrow-parens': ['error', 'always'],
|
|
||||||
'arrow-spacing': ['error', { before: true, after: true }],
|
|
||||||
'constructor-super': 'error',
|
|
||||||
'generator-star-spacing': 'off',
|
|
||||||
'no-class-assign': 'error',
|
|
||||||
'no-confusing-arrow': 'error',
|
|
||||||
'no-const-assign': 'error',
|
|
||||||
'no-dupe-class-members': 'error',
|
|
||||||
'no-duplicate-imports': 'error',
|
|
||||||
'no-new-symbol': 'error',
|
|
||||||
'no-this-before-super': 'error',
|
|
||||||
'no-useless-escape': 'error',
|
|
||||||
'no-useless-computed-key': 'error',
|
|
||||||
'no-useless-constructor': 'error',
|
|
||||||
'no-var': 'warn',
|
|
||||||
'object-shorthand': ['error', 'properties'],
|
|
||||||
'prefer-arrow-callback': 'error',
|
|
||||||
'prefer-const': 'warn',
|
|
||||||
'prefer-reflect': 'off',
|
|
||||||
'prefer-rest-params': 'off',
|
|
||||||
'prefer-spread': 'warn',
|
|
||||||
'prefer-template': 'error',
|
|
||||||
'require-yield': 'off',
|
|
||||||
'template-curly-spacing': ['error', 'never'],
|
|
||||||
'yield-star-spacing': 'off',
|
|
||||||
|
|
||||||
// Possible Errors
|
|
||||||
|
|
||||||
'comma-dangle': 'error',
|
|
||||||
'no-cond-assign': 'error',
|
|
||||||
'no-console': 'off',
|
|
||||||
'no-constant-condition': 'warn',
|
|
||||||
'no-control-regex': 'error',
|
|
||||||
'no-debugger': 'off',
|
|
||||||
'no-dupe-args': 'error',
|
|
||||||
'no-dupe-keys': 'error',
|
|
||||||
'no-duplicate-case': 'error',
|
|
||||||
'no-empty': 'warn',
|
|
||||||
'no-empty-character-class': 'error',
|
|
||||||
'no-ex-assign': 'error',
|
|
||||||
'no-extra-boolean-cast': 'error',
|
|
||||||
'no-extra-parens': ['error', 'functions'],
|
|
||||||
'no-extra-semi': 'error',
|
|
||||||
'no-func-assign': 'error',
|
|
||||||
'no-inner-declarations': 'error',
|
|
||||||
'no-invalid-regexp': 'error',
|
|
||||||
'no-irregular-whitespace': 'error',
|
|
||||||
'no-negated-in-lhs': 'error',
|
|
||||||
'no-obj-calls': 'error',
|
|
||||||
'no-regex-spaces': 'error',
|
|
||||||
'no-sparse-arrays': 'error',
|
|
||||||
'no-unexpected-multiline': 'error',
|
|
||||||
'no-unreachable': 'warn',
|
|
||||||
'no-unsafe-finally': 'error',
|
|
||||||
'use-isnan': 'error',
|
|
||||||
'valid-jsdoc': 'off',
|
|
||||||
'valid-typeof': 'error',
|
|
||||||
|
|
||||||
// Best Practices
|
|
||||||
|
|
||||||
'accessor-pairs': 'off',
|
|
||||||
'array-callback-return': 'warn',
|
|
||||||
'block-scoped-var': 'warn',
|
|
||||||
'consistent-return': 'off',
|
|
||||||
curly: 'error',
|
|
||||||
'default-case': 'error',
|
|
||||||
'dot-location': ['error', 'property'],
|
|
||||||
'dot-notation': 'error',
|
|
||||||
eqeqeq: ['error', 'smart'],
|
|
||||||
'guard-for-in': 'error',
|
|
||||||
'no-alert': 'warn',
|
|
||||||
'no-caller': 'error',
|
|
||||||
'no-case-declarations': 'error',
|
|
||||||
'no-div-regex': 'error',
|
|
||||||
'no-else-return': 'error',
|
|
||||||
'no-empty-function': ['error', { allow: ['arrowFunctions'] }],
|
|
||||||
'no-empty-pattern': 'error',
|
|
||||||
'no-eval': 'error',
|
|
||||||
'no-extend-native': 'error',
|
|
||||||
'no-extra-bind': 'error',
|
|
||||||
'no-fallthrough': 'error',
|
|
||||||
'no-floating-decimal': 'error',
|
|
||||||
'no-implicit-coercion': ['error', {
|
|
||||||
boolean: false,
|
|
||||||
number: true,
|
|
||||||
string: true,
|
|
||||||
allow: [/* "!!", "~", "*", "+" */]
|
|
||||||
}],
|
|
||||||
'no-implicit-globals': 'error',
|
|
||||||
'no-implied-eval': 'error',
|
|
||||||
'no-invalid-this': 'off',
|
|
||||||
'no-iterator': 'error',
|
|
||||||
'no-labels': 'error',
|
|
||||||
'no-lone-blocks': 'error',
|
|
||||||
'no-loop-func': 'error',
|
|
||||||
'no-magic-numbers': ['off', { ignoreArrayIndexes: true, ignore: [0, 1] }],
|
|
||||||
'no-multi-spaces': 'error',
|
|
||||||
'no-multi-str': 'error',
|
|
||||||
'no-native-reassign': ['error', { exceptions: ['console'] }],
|
|
||||||
'no-new': 'off',
|
|
||||||
'no-new-func': 'error',
|
|
||||||
'no-new-wrappers': 'error',
|
|
||||||
'no-octal': 'error',
|
|
||||||
'no-octal-escape': 'error',
|
|
||||||
'no-param-reassign': 'off',
|
|
||||||
'no-process-env': 'off',
|
|
||||||
'no-proto': 'error',
|
|
||||||
'no-redeclare': 'error',
|
|
||||||
'no-return-assign': 'warn',
|
|
||||||
'no-script-url': 'error',
|
|
||||||
'no-self-assign': 'error',
|
|
||||||
'no-self-compare': 'error',
|
|
||||||
'no-sequences': 'error',
|
|
||||||
'no-throw-literal': 'error',
|
|
||||||
'no-unmodified-loop-condition': 'error',
|
|
||||||
'no-unused-expressions': 'error',
|
|
||||||
'no-unused-labels': 'error',
|
|
||||||
'no-useless-call': 'error',
|
|
||||||
'no-useless-concat': 'error',
|
|
||||||
'no-void': 'error',
|
|
||||||
'no-warning-comments': 'off',
|
|
||||||
'no-with': 'error',
|
|
||||||
radix: ['error', 'as-needed'],
|
|
||||||
'vars-on-top': 'off',
|
|
||||||
'wrap-iife': ['error', 'inside'],
|
|
||||||
yoda: 'error',
|
|
||||||
|
|
||||||
// Strict Mode
|
|
||||||
|
|
||||||
strict: ['error', 'never'],
|
|
||||||
|
|
||||||
// Variables
|
|
||||||
|
|
||||||
'init-declarations': ['error', 'always'],
|
|
||||||
'no-catch-shadow': 'error',
|
|
||||||
'no-delete-var': 'error',
|
|
||||||
'no-label-var': 'error',
|
|
||||||
'no-restricted-globals': 'off',
|
|
||||||
'no-shadow': 'error',
|
|
||||||
'no-shadow-restricted-names': 'error',
|
|
||||||
'no-undef': 'error',
|
|
||||||
'no-undef-init': 'off',
|
|
||||||
'no-undefined': 'off',
|
|
||||||
'no-unused-vars': ['error', { args: 'none', ignoreRestSiblings: true }],
|
|
||||||
'no-use-before-define': 'error',
|
|
||||||
|
|
||||||
// Node.js and CommonJS
|
|
||||||
|
|
||||||
'callback-return': 'warn',
|
|
||||||
'global-require': 'error',
|
|
||||||
'handle-callback-err': 'warn',
|
|
||||||
'no-mixed-requires': 'error',
|
|
||||||
'no-new-require': 'error',
|
|
||||||
'no-path-concat': 'error',
|
|
||||||
'no-process-exit': 'error',
|
|
||||||
|
|
||||||
// Stylistic Issues
|
|
||||||
|
|
||||||
'array-bracket-spacing': ['error', 'never'],
|
|
||||||
'block-spacing': ['error', 'always'],
|
|
||||||
'brace-style': ['error', '1tbs', { allowSingleLine: false }],
|
|
||||||
camelcase: 'off',
|
|
||||||
'comma-spacing': ['error', { before: false, after: true }],
|
|
||||||
'comma-style': ['error', 'last'],
|
|
||||||
'computed-property-spacing': ['error', 'never'],
|
|
||||||
'consistent-this': ['error', 'self'],
|
|
||||||
'eol-last': 'error',
|
|
||||||
'func-names': 'off',
|
|
||||||
'func-style': ['error', 'declaration', { allowArrowFunctions: true }],
|
|
||||||
indent: ['error', 2, { SwitchCase: 1 }],
|
|
||||||
'key-spacing': ['error', { beforeColon: false, afterColon: true }],
|
|
||||||
'keyword-spacing': ['error', { before: true, after: true }],
|
|
||||||
'lines-around-comment': ['error', { beforeBlockComment: true, afterBlockComment: false }],
|
|
||||||
'max-depth': ['error', { maximum: 5 }],
|
|
||||||
'max-nested-callbacks': ['error', 4],
|
|
||||||
'max-statements': 'off',
|
|
||||||
'max-statements-per-line': ['error', { max: 1 }],
|
|
||||||
'new-cap': ['error', { capIsNewExceptions: ['$.Deferred', 'DragDropContext', 'DragLayer', 'DragSource', 'DropTarget'] }],
|
|
||||||
'new-parens': 'error',
|
|
||||||
'newline-after-var': 'off',
|
|
||||||
'newline-before-return': 'off',
|
|
||||||
'newline-per-chained-call': 'off',
|
|
||||||
'no-array-constructor': 'error',
|
|
||||||
'no-bitwise': 'error',
|
|
||||||
'no-continue': 'error',
|
|
||||||
'no-inline-comments': 'off',
|
|
||||||
'no-lonely-if': 'warn',
|
|
||||||
'no-mixed-spaces-and-tabs': 'error',
|
|
||||||
'no-multiple-empty-lines': ['error', { max: 1 }],
|
|
||||||
'no-negated-condition': 'warn',
|
|
||||||
'no-nested-ternary': 'error',
|
|
||||||
'no-new-object': 'error',
|
|
||||||
'no-plusplus': 'off',
|
|
||||||
'no-restricted-syntax': 'off',
|
|
||||||
'no-spaced-func': 'error',
|
|
||||||
'no-ternary': 'off',
|
|
||||||
'no-trailing-spaces': 'error',
|
|
||||||
'no-underscore-dangle': ['error', { allowAfterThis: true }],
|
|
||||||
'no-unneeded-ternary': 'error',
|
|
||||||
'no-whitespace-before-property': 'error',
|
|
||||||
'object-curly-spacing': ['error', 'always'],
|
|
||||||
'one-var': ['error', 'never'],
|
|
||||||
'one-var-declaration-per-line': ['error', 'always'],
|
|
||||||
'operator-assignment': ['off', 'never'],
|
|
||||||
'operator-linebreak': ['error', 'after'],
|
|
||||||
'quote-props': ['error', 'as-needed'],
|
|
||||||
quotes: ['error', 'single'],
|
|
||||||
'require-jsdoc': 'off',
|
|
||||||
semi: 'error',
|
|
||||||
'semi-spacing': ['error', { before: false, after: true }],
|
|
||||||
'sort-vars': 'off',
|
|
||||||
'space-before-blocks': ['error', 'always'],
|
|
||||||
'space-before-function-paren': ['error', 'never'],
|
|
||||||
'space-in-parens': 'off',
|
|
||||||
'space-infix-ops': 'off',
|
|
||||||
'space-unary-ops': 'off',
|
|
||||||
'spaced-comment': 'error',
|
|
||||||
'wrap-regex': 'error',
|
|
||||||
|
|
||||||
// ImportSort
|
|
||||||
|
|
||||||
'simple-import-sort/imports': 'error',
|
|
||||||
'import/newline-after-import': 'error',
|
|
||||||
|
|
||||||
// React
|
|
||||||
|
|
||||||
'react/jsx-boolean-value': [2, 'always'],
|
|
||||||
'react/jsx-uses-vars': 2,
|
|
||||||
'react/jsx-closing-bracket-location': 2,
|
|
||||||
'react/jsx-tag-spacing': ['error'],
|
|
||||||
'react/jsx-curly-spacing': [2, 'never'],
|
|
||||||
'react/jsx-equals-spacing': [2, 'never'],
|
|
||||||
'react/jsx-indent-props': [2, 2],
|
|
||||||
'react/jsx-indent': [2, 2, { indentLogicalExpressions: true }],
|
|
||||||
'react/jsx-key': 2,
|
|
||||||
'react/jsx-no-bind': [2, { allowArrowFunctions: true }],
|
|
||||||
'react/jsx-no-duplicate-props': [2, { ignoreCase: true }],
|
|
||||||
'react/jsx-max-props-per-line': [2, { maximum: 2 }],
|
|
||||||
'react/jsx-handler-names': [2, { eventHandlerPrefix: '(on|dispatch)', eventHandlerPropPrefix: 'on' }],
|
|
||||||
'react/jsx-no-undef': 2,
|
|
||||||
'react/jsx-pascal-case': 2,
|
|
||||||
'react/jsx-uses-react': 2,
|
|
||||||
// Explicitly disabled in case we want to enable them again
|
|
||||||
'react/no-did-mount-set-state': 0,
|
|
||||||
'react/no-did-update-set-state': 0,
|
|
||||||
'react/no-direct-mutation-state': 2,
|
|
||||||
'react/no-multi-comp': [2, { ignoreStateless: true }],
|
|
||||||
'react/no-unknown-property': 2,
|
|
||||||
'react/prefer-es6-class': 2,
|
|
||||||
'react/prop-types': 2,
|
|
||||||
'react/react-in-jsx-scope': 2,
|
|
||||||
'react/self-closing-comp': 2,
|
|
||||||
'react/sort-comp': 2,
|
|
||||||
'react/jsx-wrap-multilines': 2,
|
|
||||||
'react-hooks/rules-of-hooks': 'error',
|
|
||||||
'react-hooks/exhaustive-deps': 'error'
|
|
||||||
},
|
|
||||||
overrides: [
|
|
||||||
{
|
|
||||||
files: [
|
|
||||||
'*.js'
|
|
||||||
],
|
|
||||||
rules: {
|
|
||||||
'simple-import-sort/imports': [
|
|
||||||
'error',
|
|
||||||
{
|
|
||||||
groups: [
|
|
||||||
// Packages
|
|
||||||
// Absolute Paths
|
|
||||||
// Relative Paths
|
|
||||||
// Css
|
|
||||||
['^@?\\w', `^(${dirs})(/.*|$)`, '^\\.', '^\\..*css$']
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
files: [
|
|
||||||
'*.ts',
|
|
||||||
'*.tsx'
|
|
||||||
],
|
|
||||||
|
|
||||||
parser: '@typescript-eslint/parser',
|
|
||||||
parserOptions: {
|
|
||||||
project: './tsconfig.json'
|
|
||||||
},
|
|
||||||
|
|
||||||
extends: [
|
|
||||||
'prettier'
|
|
||||||
],
|
|
||||||
|
|
||||||
rules: Object.assign(typescriptEslintRecommended.rules, {
|
|
||||||
'@typescript-eslint/no-unused-vars': [
|
|
||||||
'error',
|
|
||||||
{
|
|
||||||
args: 'after-used',
|
|
||||||
argsIgnorePattern: '^_',
|
|
||||||
ignoreRestSiblings: true
|
|
||||||
}
|
|
||||||
],
|
|
||||||
'@typescript-eslint/explicit-function-return-type': 'off',
|
|
||||||
'no-shadow': 'off',
|
|
||||||
'prettier/prettier': 'error',
|
|
||||||
'simple-import-sort/imports': [
|
|
||||||
'error',
|
|
||||||
{
|
|
||||||
groups: [
|
|
||||||
// Packages
|
|
||||||
// Absolute Paths
|
|
||||||
// Relative Paths
|
|
||||||
// Css
|
|
||||||
['^@?\\w', `^(${dirs})(/.*|$)`, '^\\.', '^\\..*css$']
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
|
|
||||||
// React Hooks
|
|
||||||
'react-hooks/rules-of-hooks': 'error',
|
|
||||||
'react-hooks/exhaustive-deps': 'error',
|
|
||||||
|
|
||||||
// React
|
|
||||||
'react/function-component-definition': 'error',
|
|
||||||
'react/hook-use-state': 'error',
|
|
||||||
'react/jsx-boolean-value': ['error', 'always'],
|
|
||||||
'react/jsx-curly-brace-presence': [
|
|
||||||
'error',
|
|
||||||
{ props: 'never', children: 'never' }
|
|
||||||
],
|
|
||||||
'react/jsx-fragments': 'error',
|
|
||||||
'react/jsx-handler-names': [
|
|
||||||
'error',
|
|
||||||
{
|
|
||||||
eventHandlerPrefix: 'on',
|
|
||||||
eventHandlerPropPrefix: 'on'
|
|
||||||
}
|
|
||||||
],
|
|
||||||
'react/jsx-no-bind': ['error', { ignoreRefs: true }],
|
|
||||||
'react/jsx-no-useless-fragment': ['error', { allowExpressions: true }],
|
|
||||||
'react/jsx-pascal-case': ['error', { allowAllCaps: true }],
|
|
||||||
'react/jsx-sort-props': [
|
|
||||||
'error',
|
|
||||||
{
|
|
||||||
callbacksLast: true,
|
|
||||||
noSortAlphabetically: true,
|
|
||||||
reservedFirst: true
|
|
||||||
}
|
|
||||||
],
|
|
||||||
'react/prop-types': 'off',
|
|
||||||
'react/self-closing-comp': 'error'
|
|
||||||
})
|
|
||||||
},
|
|
||||||
{
|
|
||||||
files: [
|
|
||||||
'*.css.d.ts'
|
|
||||||
],
|
|
||||||
rules: {
|
|
||||||
'filenames/match-exported': 'off',
|
|
||||||
'init-declarations': 'off',
|
|
||||||
'prettier/prettier': 'off'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
};
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
{
|
||||||
|
"js": {
|
||||||
|
"indent_size": 2,
|
||||||
|
"indent_char": " ",
|
||||||
|
"indent_level": 2,
|
||||||
|
"indent_with_tabs": false,
|
||||||
|
"preserve_newlines": true,
|
||||||
|
"brace_style": "collapse",
|
||||||
|
"max_preserve_newlines": 2,
|
||||||
|
"jslint_happy": true
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,10 +0,0 @@
|
||||||
# Ignore everything recursively
|
|
||||||
*
|
|
||||||
|
|
||||||
# But not the .ts files
|
|
||||||
!*.ts*
|
|
||||||
|
|
||||||
*css.d.ts
|
|
||||||
|
|
||||||
# Check subdirectories too
|
|
||||||
!*/
|
|
|
@ -1,6 +0,0 @@
|
||||||
{
|
|
||||||
"arrowParens": "always",
|
|
||||||
"endOfLine": "auto",
|
|
||||||
"singleQuote": true,
|
|
||||||
"trailingComma": "es5"
|
|
||||||
}
|
|
|
@ -15,6 +15,9 @@
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"at-rule-name-case": "lower",
|
||||||
|
"at-rule-name-newline-after": "always-multi-line",
|
||||||
|
"at-rule-name-space-after": "always",
|
||||||
"at-rule-no-unknown": [
|
"at-rule-no-unknown": [
|
||||||
true,
|
true,
|
||||||
{
|
{
|
||||||
|
@ -25,11 +28,25 @@
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"at-rule-no-vendor-prefix": true,
|
"at-rule-no-vendor-prefix": true,
|
||||||
|
"at-rule-semicolon-newline-after": "always",
|
||||||
|
"at-rule-semicolon-space-before": "never",
|
||||||
|
"block-closing-brace-empty-line-before": "never",
|
||||||
|
"block-closing-brace-newline-after": "always",
|
||||||
|
"block-closing-brace-newline-before": "always",
|
||||||
|
"block-closing-brace-space-after": "always-single-line",
|
||||||
|
"block-closing-brace-space-before": "always-single-line",
|
||||||
"block-no-empty": true,
|
"block-no-empty": true,
|
||||||
|
"block-opening-brace-newline-after": "always",
|
||||||
|
"block-opening-brace-newline-before": "never-single-line",
|
||||||
|
"block-opening-brace-space-after": "always-single-line",
|
||||||
|
"block-opening-brace-space-before": "always",
|
||||||
|
"color-hex-case": "lower",
|
||||||
"color-hex-length": "short",
|
"color-hex-length": "short",
|
||||||
"color-named": "never",
|
"color-named": "never",
|
||||||
"color-no-invalid-hex": true,
|
"color-no-invalid-hex": true,
|
||||||
"comment-whitespace-inside": "always",
|
"comment-whitespace-inside": "always",
|
||||||
|
"declaration-bang-space-after": "never",
|
||||||
|
"declaration-bang-space-before": "always",
|
||||||
"declaration-block-no-duplicate-properties": [
|
"declaration-block-no-duplicate-properties": [
|
||||||
true,
|
true,
|
||||||
{
|
{
|
||||||
|
@ -40,21 +57,54 @@
|
||||||
],
|
],
|
||||||
"declaration-block-no-redundant-longhand-properties": true,
|
"declaration-block-no-redundant-longhand-properties": true,
|
||||||
"declaration-block-no-shorthand-property-overrides": true,
|
"declaration-block-no-shorthand-property-overrides": true,
|
||||||
|
"declaration-block-semicolon-newline-after": "always",
|
||||||
|
"declaration-block-semicolon-newline-before": "never-multi-line",
|
||||||
|
"declaration-block-semicolon-space-before": "never",
|
||||||
"declaration-block-single-line-max-declarations": 1,
|
"declaration-block-single-line-max-declarations": 1,
|
||||||
|
"declaration-block-trailing-semicolon": "always",
|
||||||
|
"declaration-colon-space-after": "always",
|
||||||
|
"declaration-colon-space-before": "never",
|
||||||
"font-family-name-quotes": "always-unless-keyword",
|
"font-family-name-quotes": "always-unless-keyword",
|
||||||
"function-calc-no-unspaced-operator": true,
|
"function-calc-no-unspaced-operator": true,
|
||||||
|
"function-comma-newline-after": "never-multi-line",
|
||||||
|
"function-comma-newline-before": "never-multi-line",
|
||||||
|
"function-comma-space-after": "always",
|
||||||
|
"function-comma-space-before": "never",
|
||||||
"function-linear-gradient-no-nonstandard-direction": true,
|
"function-linear-gradient-no-nonstandard-direction": true,
|
||||||
"function-name-case": "lower",
|
"function-name-case": "lower",
|
||||||
|
"function-parentheses-newline-inside": "never-multi-line",
|
||||||
|
"function-parentheses-space-inside": "never",
|
||||||
"function-url-quotes": "always",
|
"function-url-quotes": "always",
|
||||||
"function-url-scheme-disallowed-list": [
|
"function-url-scheme-blacklist": [
|
||||||
"data"
|
"data"
|
||||||
],
|
],
|
||||||
|
"function-whitespace-after": "always",
|
||||||
|
"indentation": 2,
|
||||||
"keyframe-declaration-no-important": true,
|
"keyframe-declaration-no-important": true,
|
||||||
"length-zero-no-unit": true,
|
"length-zero-no-unit": true,
|
||||||
|
"max-empty-lines": 1,
|
||||||
|
"max-line-length": [
|
||||||
|
100,
|
||||||
|
{
|
||||||
|
"ignore": [
|
||||||
|
"non-comments"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
"max-nesting-depth": 2,
|
"max-nesting-depth": 2,
|
||||||
|
"media-feature-colon-space-after": "always",
|
||||||
|
"media-feature-colon-space-before": "never",
|
||||||
|
"media-feature-name-case": "lower",
|
||||||
"media-feature-name-no-vendor-prefix": true,
|
"media-feature-name-no-vendor-prefix": true,
|
||||||
|
"media-feature-range-operator-space-after": "always",
|
||||||
|
"media-feature-range-operator-space-before": "always",
|
||||||
"no-empty-source": true,
|
"no-empty-source": true,
|
||||||
|
"no-eol-whitespace": true,
|
||||||
|
"no-extra-semicolons": true,
|
||||||
"no-invalid-double-slash-comments": true,
|
"no-invalid-double-slash-comments": true,
|
||||||
|
"no-missing-end-of-source-newline": true,
|
||||||
|
"number-leading-zero": "always",
|
||||||
|
"number-no-trailing-zeros": true,
|
||||||
"order/order": [
|
"order/order": [
|
||||||
"custom-properties",
|
"custom-properties",
|
||||||
"dollar-variables",
|
"dollar-variables",
|
||||||
|
@ -82,7 +132,6 @@
|
||||||
"right",
|
"right",
|
||||||
"bottom",
|
"bottom",
|
||||||
"left",
|
"left",
|
||||||
"inset",
|
|
||||||
"z-index",
|
"z-index",
|
||||||
"display",
|
"display",
|
||||||
"visibility",
|
"visibility",
|
||||||
|
@ -294,6 +343,7 @@
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"property-case": "lower",
|
||||||
"property-no-vendor-prefix": true,
|
"property-no-vendor-prefix": true,
|
||||||
"rule-empty-line-before": [
|
"rule-empty-line-before": [
|
||||||
"always",
|
"always",
|
||||||
|
@ -306,21 +356,41 @@
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"selector-attribute-brackets-space-inside": "never",
|
||||||
|
"selector-attribute-operator-space-after": "never",
|
||||||
|
"selector-attribute-operator-space-before": "never",
|
||||||
"selector-attribute-quotes": "never",
|
"selector-attribute-quotes": "never",
|
||||||
"selector-class-pattern": "^[A-Za-z0-9]+$",
|
"selector-class-pattern": "^[A-Za-z0-9]+$",
|
||||||
|
"selector-combinator-space-after": "always",
|
||||||
|
"selector-combinator-space-before": "always",
|
||||||
|
"selector-descendant-combinator-no-non-space": true,
|
||||||
|
"selector-list-comma-newline-after": "always",
|
||||||
|
"selector-list-comma-newline-before": "never-multi-line",
|
||||||
|
"selector-list-comma-space-before": "never",
|
||||||
"selector-max-attribute": 0,
|
"selector-max-attribute": 0,
|
||||||
"selector-max-class": 3,
|
"selector-max-class": 3,
|
||||||
"selector-max-compound-selectors": 3,
|
"selector-max-compound-selectors": 3,
|
||||||
|
"selector-max-empty-lines": 0,
|
||||||
"selector-max-id": 0,
|
"selector-max-id": 0,
|
||||||
"selector-max-universal": 0,
|
"selector-max-universal": 0,
|
||||||
|
"selector-pseudo-class-case": "lower",
|
||||||
|
"selector-pseudo-class-parentheses-space-inside": "never",
|
||||||
|
"selector-pseudo-element-case": "lower",
|
||||||
"selector-pseudo-element-colon-notation": "double",
|
"selector-pseudo-element-colon-notation": "double",
|
||||||
"selector-pseudo-element-no-unknown": true,
|
"selector-pseudo-element-no-unknown": true,
|
||||||
"selector-type-case": "lower",
|
"selector-type-case": "lower",
|
||||||
"selector-type-no-unknown": true,
|
"selector-type-no-unknown": true,
|
||||||
"shorthand-property-no-redundant-values": true,
|
"shorthand-property-no-redundant-values": true,
|
||||||
"string-no-newline": true,
|
"string-no-newline": true,
|
||||||
|
"string-quotes": "single",
|
||||||
"time-min-milliseconds": 100,
|
"time-min-milliseconds": 100,
|
||||||
|
"unit-case": "lower",
|
||||||
"unit-no-unknown": true,
|
"unit-no-unknown": true,
|
||||||
|
"value-list-comma-newline-after": "never-multi-line",
|
||||||
|
"value-list-comma-newline-before": "never-multi-line",
|
||||||
|
"value-list-comma-space-after": "always",
|
||||||
|
"value-list-comma-space-before": "never",
|
||||||
|
"value-list-max-empty-lines": 0,
|
||||||
"value-no-vendor-prefix": true
|
"value-no-vendor-prefix": true
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,7 +0,0 @@
|
||||||
{
|
|
||||||
"recommendations": [
|
|
||||||
"stylelint.vscode-stylelint",
|
|
||||||
"dbaeumer.vscode-eslint",
|
|
||||||
"esbenp.prettier-vscode"
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,23 +0,0 @@
|
||||||
// Place your settings in this file to overwrite default and user settings.
|
|
||||||
{
|
|
||||||
"files.insertFinalNewline": true,
|
|
||||||
|
|
||||||
"files.exclude": {
|
|
||||||
"**/node_modules": true,
|
|
||||||
"**/*.d.css": true
|
|
||||||
},
|
|
||||||
|
|
||||||
"editor.formatOnSave": false,
|
|
||||||
"editor.codeActionsOnSave": {
|
|
||||||
"source.fixAll": true
|
|
||||||
},
|
|
||||||
|
|
||||||
"typescript.preferences.quoteStyle": "single",
|
|
||||||
|
|
||||||
"eslint.validate": [
|
|
||||||
"javascript",
|
|
||||||
"javascriptreact",
|
|
||||||
"typescript",
|
|
||||||
"typescriptreact"
|
|
||||||
],
|
|
||||||
}
|
|
|
@ -2,25 +2,22 @@ const loose = true;
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
plugins: [
|
plugins: [
|
||||||
'@babel/plugin-transform-logical-assignment-operators',
|
|
||||||
|
|
||||||
// Stage 1
|
// Stage 1
|
||||||
'@babel/plugin-proposal-export-default-from',
|
'@babel/plugin-proposal-export-default-from',
|
||||||
['@babel/plugin-transform-optional-chaining', { loose }],
|
['@babel/plugin-proposal-optional-chaining', { loose }],
|
||||||
['@babel/plugin-transform-nullish-coalescing-operator', { loose }],
|
['@babel/plugin-proposal-nullish-coalescing-operator', { loose }],
|
||||||
|
|
||||||
// Stage 2
|
// Stage 2
|
||||||
'@babel/plugin-transform-export-namespace-from',
|
'@babel/plugin-proposal-export-namespace-from',
|
||||||
|
|
||||||
// Stage 3
|
// Stage 3
|
||||||
['@babel/plugin-transform-class-properties', { loose }],
|
['@babel/plugin-proposal-class-properties', { loose }],
|
||||||
'@babel/plugin-syntax-dynamic-import'
|
'@babel/plugin-syntax-dynamic-import'
|
||||||
],
|
],
|
||||||
env: {
|
env: {
|
||||||
development: {
|
development: {
|
||||||
presets: [
|
presets: [
|
||||||
['@babel/preset-react', { development: true }],
|
['@babel/preset-react', { development: true }]
|
||||||
'@babel/preset-typescript'
|
|
||||||
],
|
],
|
||||||
plugins: [
|
plugins: [
|
||||||
'babel-plugin-inline-classnames'
|
'babel-plugin-inline-classnames'
|
||||||
|
@ -28,8 +25,7 @@ module.exports = {
|
||||||
},
|
},
|
||||||
production: {
|
production: {
|
||||||
presets: [
|
presets: [
|
||||||
'@babel/preset-react',
|
'@babel/preset-react'
|
||||||
'@babel/preset-typescript'
|
|
||||||
],
|
],
|
||||||
plugins: [
|
plugins: [
|
||||||
'babel-plugin-transform-react-remove-prop-types'
|
'babel-plugin-transform-react-remove-prop-types'
|
||||||
|
|
|
@ -1,284 +0,0 @@
|
||||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
|
||||||
const path = require('path');
|
|
||||||
const webpack = require('webpack');
|
|
||||||
const FileManagerPlugin = require('filemanager-webpack-plugin');
|
|
||||||
const HtmlWebpackPlugin = require('html-webpack-plugin');
|
|
||||||
const LiveReloadPlugin = require('webpack-livereload-plugin');
|
|
||||||
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
|
|
||||||
const TerserPlugin = require('terser-webpack-plugin');
|
|
||||||
const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');
|
|
||||||
|
|
||||||
module.exports = (env) => {
|
|
||||||
const uiFolder = 'UI';
|
|
||||||
const frontendFolder = path.join(__dirname, '..');
|
|
||||||
const srcFolder = path.join(frontendFolder, 'src');
|
|
||||||
const isProduction = !!env.production;
|
|
||||||
const isProfiling = isProduction && !!env.profile;
|
|
||||||
const inlineWebWorkers = 'no-fallback';
|
|
||||||
|
|
||||||
const distFolder = path.resolve(frontendFolder, '..', '_output', uiFolder);
|
|
||||||
|
|
||||||
console.log('Source Folder:', srcFolder);
|
|
||||||
console.log('Output Folder:', distFolder);
|
|
||||||
console.log('isProduction:', isProduction);
|
|
||||||
console.log('isProfiling:', isProfiling);
|
|
||||||
|
|
||||||
const config = {
|
|
||||||
mode: isProduction ? 'production' : 'development',
|
|
||||||
devtool: isProduction ? 'source-map' : 'eval-source-map',
|
|
||||||
|
|
||||||
stats: {
|
|
||||||
children: false
|
|
||||||
},
|
|
||||||
|
|
||||||
watchOptions: {
|
|
||||||
ignored: /node_modules/
|
|
||||||
},
|
|
||||||
|
|
||||||
entry: {
|
|
||||||
index: 'index.ts'
|
|
||||||
},
|
|
||||||
|
|
||||||
resolve: {
|
|
||||||
extensions: [
|
|
||||||
'.ts',
|
|
||||||
'.tsx',
|
|
||||||
'.js'
|
|
||||||
],
|
|
||||||
modules: [
|
|
||||||
srcFolder,
|
|
||||||
path.join(srcFolder, 'Shims'),
|
|
||||||
'node_modules'
|
|
||||||
],
|
|
||||||
alias: {
|
|
||||||
jquery: 'jquery/dist/jquery.min',
|
|
||||||
'react-middle-truncate': 'react-middle-truncate/lib/react-middle-truncate'
|
|
||||||
},
|
|
||||||
fallback: {
|
|
||||||
buffer: false,
|
|
||||||
http: false,
|
|
||||||
https: false,
|
|
||||||
url: false,
|
|
||||||
util: false,
|
|
||||||
net: false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
output: {
|
|
||||||
path: distFolder,
|
|
||||||
publicPath: '/',
|
|
||||||
filename: isProduction ? '[name]-[contenthash].js' : '[name].js',
|
|
||||||
sourceMapFilename: '[file].map'
|
|
||||||
},
|
|
||||||
|
|
||||||
optimization: {
|
|
||||||
moduleIds: 'deterministic',
|
|
||||||
chunkIds: isProduction ? 'deterministic' : 'named'
|
|
||||||
},
|
|
||||||
|
|
||||||
performance: {
|
|
||||||
hints: false
|
|
||||||
},
|
|
||||||
|
|
||||||
experiments: {
|
|
||||||
topLevelAwait: true
|
|
||||||
},
|
|
||||||
|
|
||||||
plugins: [
|
|
||||||
new webpack.DefinePlugin({
|
|
||||||
__DEV__: !isProduction,
|
|
||||||
'process.env.NODE_ENV': isProduction ? JSON.stringify('production') : JSON.stringify('development')
|
|
||||||
}),
|
|
||||||
|
|
||||||
new MiniCssExtractPlugin({
|
|
||||||
filename: 'Content/styles.css',
|
|
||||||
chunkFilename: isProduction ? 'Content/[id]-[chunkhash].css' : 'Content/[id].css'
|
|
||||||
}),
|
|
||||||
|
|
||||||
new HtmlWebpackPlugin({
|
|
||||||
template: 'frontend/src/index.ejs',
|
|
||||||
filename: 'index.html',
|
|
||||||
publicPath: '/',
|
|
||||||
inject: false
|
|
||||||
}),
|
|
||||||
|
|
||||||
new FileManagerPlugin({
|
|
||||||
events: {
|
|
||||||
onEnd: {
|
|
||||||
copy: [
|
|
||||||
// HTML
|
|
||||||
{
|
|
||||||
source: 'frontend/src/*.html',
|
|
||||||
destination: distFolder
|
|
||||||
},
|
|
||||||
|
|
||||||
// Fonts
|
|
||||||
{
|
|
||||||
source: 'frontend/src/Content/Fonts/*.*',
|
|
||||||
destination: path.join(distFolder, 'Content/Fonts')
|
|
||||||
},
|
|
||||||
|
|
||||||
// Icon Images
|
|
||||||
{
|
|
||||||
source: 'frontend/src/Content/Images/Icons/*.*',
|
|
||||||
destination: path.join(distFolder, 'Content/Images/Icons')
|
|
||||||
},
|
|
||||||
|
|
||||||
// Images
|
|
||||||
{
|
|
||||||
source: 'frontend/src/Content/Images/*.*',
|
|
||||||
destination: path.join(distFolder, 'Content/Images')
|
|
||||||
},
|
|
||||||
|
|
||||||
// Robots
|
|
||||||
{
|
|
||||||
source: 'frontend/src/Content/robots.txt',
|
|
||||||
destination: path.join(distFolder, 'Content/robots.txt')
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
|
|
||||||
new ForkTsCheckerWebpackPlugin(),
|
|
||||||
|
|
||||||
new LiveReloadPlugin()
|
|
||||||
],
|
|
||||||
|
|
||||||
resolveLoader: {
|
|
||||||
modules: [
|
|
||||||
'node_modules',
|
|
||||||
'frontend/build/webpack/'
|
|
||||||
]
|
|
||||||
},
|
|
||||||
|
|
||||||
module: {
|
|
||||||
rules: [
|
|
||||||
{
|
|
||||||
test: /\.worker\.js$/,
|
|
||||||
use: {
|
|
||||||
loader: 'worker-loader',
|
|
||||||
options: {
|
|
||||||
filename: '[name].js',
|
|
||||||
inline: inlineWebWorkers
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
test: [/\.jsx?$/, /\.tsx?$/],
|
|
||||||
exclude: /(node_modules|JsLibraries)/,
|
|
||||||
use: [
|
|
||||||
{
|
|
||||||
loader: 'babel-loader',
|
|
||||||
options: {
|
|
||||||
configFile: `${frontendFolder}/babel.config.js`,
|
|
||||||
envName: isProduction ? 'production' : 'development',
|
|
||||||
presets: [
|
|
||||||
[
|
|
||||||
'@babel/preset-env',
|
|
||||||
{
|
|
||||||
modules: false,
|
|
||||||
loose: true,
|
|
||||||
debug: false,
|
|
||||||
useBuiltIns: 'entry',
|
|
||||||
corejs: 3
|
|
||||||
}
|
|
||||||
]
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
|
|
||||||
// CSS Modules
|
|
||||||
{
|
|
||||||
test: /\.css$/,
|
|
||||||
exclude: /(node_modules|globals.css)/,
|
|
||||||
use: [
|
|
||||||
{ loader: MiniCssExtractPlugin.loader },
|
|
||||||
{ loader: 'css-modules-typescript-loader' },
|
|
||||||
{
|
|
||||||
loader: 'css-loader',
|
|
||||||
options: {
|
|
||||||
importLoaders: 1,
|
|
||||||
modules: {
|
|
||||||
localIdentName: isProduction ? '[name]/[local]/[hash:base64:5]' : '[name]/[local]'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
loader: 'postcss-loader',
|
|
||||||
options: {
|
|
||||||
postcssOptions: {
|
|
||||||
config: 'frontend/postcss.config.js'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
|
|
||||||
// Global styles
|
|
||||||
{
|
|
||||||
test: /\.css$/,
|
|
||||||
include: /(node_modules|globals.css)/,
|
|
||||||
use: [
|
|
||||||
'style-loader',
|
|
||||||
{
|
|
||||||
loader: 'css-loader'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
|
|
||||||
// Fonts
|
|
||||||
{
|
|
||||||
test: /\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$/,
|
|
||||||
use: [
|
|
||||||
{
|
|
||||||
loader: 'url-loader',
|
|
||||||
options: {
|
|
||||||
limit: 10240,
|
|
||||||
mimetype: 'application/font-woff',
|
|
||||||
emitFile: false,
|
|
||||||
name: 'Content/Fonts/[name].[ext]'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
test: /\.(ttf|eot|eot?#iefix|svg)(\?v=[0-9]\.[0-9]\.[0-9])?$/,
|
|
||||||
use: [
|
|
||||||
{
|
|
||||||
loader: 'file-loader',
|
|
||||||
options: {
|
|
||||||
emitFile: false,
|
|
||||||
name: 'Content/Fonts/[name].[ext]'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if (isProfiling) {
|
|
||||||
config.resolve.alias['react-dom$'] = 'react-dom/profiling';
|
|
||||||
config.resolve.alias['scheduler/tracing'] = 'scheduler/tracing-profiling';
|
|
||||||
|
|
||||||
config.optimization = {
|
|
||||||
minimize: true,
|
|
||||||
minimizer: [
|
|
||||||
new TerserPlugin({
|
|
||||||
terserOptions: {
|
|
||||||
sourceMap: true, // Must be set to true if using source-maps in production
|
|
||||||
mangle: false,
|
|
||||||
keep_classnames: true,
|
|
||||||
keep_fnames: true
|
|
||||||
}
|
|
||||||
})
|
|
||||||
]
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
return config;
|
|
||||||
};
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
const gulp = require('gulp');
|
||||||
|
|
||||||
|
require('./clean');
|
||||||
|
require('./copy');
|
||||||
|
require('./webpack');
|
||||||
|
|
||||||
|
gulp.task('build',
|
||||||
|
gulp.series('clean',
|
||||||
|
gulp.parallel(
|
||||||
|
'webpack',
|
||||||
|
'copyHtml',
|
||||||
|
'copyFonts',
|
||||||
|
'copyImages',
|
||||||
|
'copyJs'
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
const gulp = require('gulp');
|
||||||
|
const del = require('del');
|
||||||
|
|
||||||
|
const paths = require('./helpers/paths');
|
||||||
|
|
||||||
|
gulp.task('clean', () => {
|
||||||
|
return del([paths.dest.root]);
|
||||||
|
});
|
|
@ -0,0 +1,45 @@
|
||||||
|
const path = require('path');
|
||||||
|
const gulp = require('gulp');
|
||||||
|
const print = require('gulp-print').default;
|
||||||
|
const cache = require('gulp-cached');
|
||||||
|
const livereload = require('gulp-livereload');
|
||||||
|
const paths = require('./helpers/paths.js');
|
||||||
|
|
||||||
|
gulp.task('copyJs', () => {
|
||||||
|
return gulp.src(
|
||||||
|
[
|
||||||
|
path.join(paths.src.root, 'polyfills.js')
|
||||||
|
], { base: paths.src.root })
|
||||||
|
.pipe(cache('copyJs'))
|
||||||
|
.pipe(print())
|
||||||
|
.pipe(gulp.dest(paths.dest.root))
|
||||||
|
.pipe(livereload());
|
||||||
|
});
|
||||||
|
|
||||||
|
gulp.task('copyHtml', () => {
|
||||||
|
return gulp.src(paths.src.html, { base: paths.src.root })
|
||||||
|
.pipe(cache('copyHtml'))
|
||||||
|
.pipe(print())
|
||||||
|
.pipe(gulp.dest(paths.dest.root))
|
||||||
|
.pipe(livereload());
|
||||||
|
});
|
||||||
|
|
||||||
|
gulp.task('copyFonts', () => {
|
||||||
|
return gulp.src(
|
||||||
|
path.join(paths.src.fonts, '**', '*.*'), { base: paths.src.root }
|
||||||
|
)
|
||||||
|
.pipe(cache('copyFonts'))
|
||||||
|
.pipe(print())
|
||||||
|
.pipe(gulp.dest(paths.dest.root))
|
||||||
|
.pipe(livereload());
|
||||||
|
});
|
||||||
|
|
||||||
|
gulp.task('copyImages', () => {
|
||||||
|
return gulp.src(
|
||||||
|
path.join(paths.src.images, '**', '*.*'), { base: paths.src.root }
|
||||||
|
)
|
||||||
|
.pipe(cache('copyImages'))
|
||||||
|
.pipe(print())
|
||||||
|
.pipe(gulp.dest(paths.dest.root))
|
||||||
|
.pipe(livereload());
|
||||||
|
});
|
|
@ -0,0 +1,5 @@
|
||||||
|
require('./build.js');
|
||||||
|
require('./clean.js');
|
||||||
|
require('./copy.js');
|
||||||
|
require('./watch.js');
|
||||||
|
require('./webpack.js');
|
|
@ -0,0 +1,6 @@
|
||||||
|
const colors = require('ansi-colors');
|
||||||
|
|
||||||
|
module.exports = function errorHandler(error) {
|
||||||
|
console.log(colors.red(`Error (${error.plugin}): ${error.message}`));
|
||||||
|
this.emit('end');
|
||||||
|
};
|
|
@ -0,0 +1,23 @@
|
||||||
|
const root = './frontend/src';
|
||||||
|
|
||||||
|
const paths = {
|
||||||
|
src: {
|
||||||
|
root,
|
||||||
|
html: `${root}/*.html`,
|
||||||
|
scripts: `${root}/**/*.js`,
|
||||||
|
content: `${root}/Content/`,
|
||||||
|
fonts: `${root}/Content/Fonts/`,
|
||||||
|
images: `${root}/Content/Images/`,
|
||||||
|
exclude: {
|
||||||
|
libs: `!${root}/JsLibraries/**`
|
||||||
|
}
|
||||||
|
},
|
||||||
|
dest: {
|
||||||
|
root: './_output/UI/',
|
||||||
|
content: './_output/UI/Content/',
|
||||||
|
fonts: './_output/UI/Content/Fonts/',
|
||||||
|
images: './_output/UI/Content/Images/'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = paths;
|
|
@ -0,0 +1,18 @@
|
||||||
|
const gulp = require('gulp');
|
||||||
|
const livereload = require('gulp-livereload');
|
||||||
|
const gulpWatch = require('gulp-watch');
|
||||||
|
const paths = require('./helpers/paths.js');
|
||||||
|
|
||||||
|
require('./copy.js');
|
||||||
|
require('./webpack.js');
|
||||||
|
|
||||||
|
function watch() {
|
||||||
|
livereload.listen({ start: true });
|
||||||
|
|
||||||
|
gulp.task('webpackWatch')();
|
||||||
|
gulpWatch(paths.src.html, gulp.series('copyHtml'));
|
||||||
|
gulpWatch(`${paths.src.fonts}**/*.*`, gulp.series('copyFonts'));
|
||||||
|
gulpWatch(`${paths.src.images}**/*.*`, gulp.series('copyImages'));
|
||||||
|
}
|
||||||
|
|
||||||
|
gulp.task('watch', gulp.series('build', watch));
|
|
@ -0,0 +1,230 @@
|
||||||
|
const gulp = require('gulp');
|
||||||
|
const webpackStream = require('webpack-stream');
|
||||||
|
const livereload = require('gulp-livereload');
|
||||||
|
const path = require('path');
|
||||||
|
const webpack = require('webpack');
|
||||||
|
const errorHandler = require('./helpers/errorHandler');
|
||||||
|
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
|
||||||
|
const HtmlWebpackPlugin = require('html-webpack-plugin');
|
||||||
|
|
||||||
|
const uiFolder = 'UI';
|
||||||
|
const frontendFolder = path.join(__dirname, '..');
|
||||||
|
const srcFolder = path.join(frontendFolder, 'src');
|
||||||
|
const isProduction = process.argv.indexOf('--production') > -1;
|
||||||
|
|
||||||
|
const distFolder = path.resolve(frontendFolder, '..', '_output', uiFolder);
|
||||||
|
|
||||||
|
console.log('Source Folder:', srcFolder);
|
||||||
|
console.log('Output Folder:', distFolder);
|
||||||
|
console.log('isProduction:', isProduction);
|
||||||
|
|
||||||
|
const cssVarsFiles = [
|
||||||
|
'../src/Styles/Variables/colors',
|
||||||
|
'../src/Styles/Variables/dimensions',
|
||||||
|
'../src/Styles/Variables/fonts',
|
||||||
|
'../src/Styles/Variables/animations',
|
||||||
|
'../src/Styles/Variables/zIndexes'
|
||||||
|
].map(require.resolve);
|
||||||
|
|
||||||
|
// Override the way HtmlWebpackPlugin injects the scripts
|
||||||
|
HtmlWebpackPlugin.prototype.injectAssetsIntoHtml = function(html, assets, assetTags) {
|
||||||
|
const head = assetTags.head.map((v) => {
|
||||||
|
v.attributes = { rel: 'stylesheet', type: 'text/css', href: `/${v.attributes.href.replace('\\', '/')}` };
|
||||||
|
return this.createHtmlTag(v);
|
||||||
|
});
|
||||||
|
const body = assetTags.body.map((v) => {
|
||||||
|
v.attributes = { src: `/${v.attributes.src}` };
|
||||||
|
return this.createHtmlTag(v);
|
||||||
|
});
|
||||||
|
|
||||||
|
return html
|
||||||
|
.replace('<!-- webpack bundles head -->', head.join('\r\n '))
|
||||||
|
.replace('<!-- webpack bundles body -->', body.join('\r\n '));
|
||||||
|
};
|
||||||
|
|
||||||
|
const plugins = [
|
||||||
|
new webpack.DefinePlugin({
|
||||||
|
__DEV__: !isProduction,
|
||||||
|
'process.env.NODE_ENV': isProduction ? JSON.stringify('production') : JSON.stringify('development')
|
||||||
|
}),
|
||||||
|
|
||||||
|
new MiniCssExtractPlugin({
|
||||||
|
filename: path.join('Content', 'styles.css')
|
||||||
|
}),
|
||||||
|
|
||||||
|
new HtmlWebpackPlugin({
|
||||||
|
template: 'frontend/src/index.html',
|
||||||
|
filename: 'index.html'
|
||||||
|
})
|
||||||
|
];
|
||||||
|
|
||||||
|
const config = {
|
||||||
|
mode: isProduction ? 'production' : 'development',
|
||||||
|
devtool: '#source-map',
|
||||||
|
|
||||||
|
stats: {
|
||||||
|
children: false
|
||||||
|
},
|
||||||
|
|
||||||
|
watchOptions: {
|
||||||
|
ignored: /node_modules/
|
||||||
|
},
|
||||||
|
|
||||||
|
entry: {
|
||||||
|
index: 'index.js'
|
||||||
|
},
|
||||||
|
|
||||||
|
resolve: {
|
||||||
|
modules: [
|
||||||
|
srcFolder,
|
||||||
|
path.join(srcFolder, 'Shims'),
|
||||||
|
'node_modules'
|
||||||
|
],
|
||||||
|
alias: {
|
||||||
|
jquery: 'jquery/src/jquery'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
output: {
|
||||||
|
path: distFolder,
|
||||||
|
filename: '[name].js',
|
||||||
|
sourceMapFilename: '[file].map'
|
||||||
|
},
|
||||||
|
|
||||||
|
optimization: {
|
||||||
|
chunkIds: 'named',
|
||||||
|
splitChunks: {
|
||||||
|
chunks: 'initial'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
performance: {
|
||||||
|
hints: false
|
||||||
|
},
|
||||||
|
|
||||||
|
plugins,
|
||||||
|
|
||||||
|
resolveLoader: {
|
||||||
|
modules: [
|
||||||
|
'node_modules',
|
||||||
|
'frontend/gulp/webpack/'
|
||||||
|
]
|
||||||
|
},
|
||||||
|
|
||||||
|
module: {
|
||||||
|
rules: [
|
||||||
|
{
|
||||||
|
test: /\.js?$/,
|
||||||
|
exclude: /(node_modules|JsLibraries)/,
|
||||||
|
use: [
|
||||||
|
{
|
||||||
|
loader: 'babel-loader',
|
||||||
|
options: {
|
||||||
|
configFile: `${frontendFolder}/babel.config.js`,
|
||||||
|
envName: isProduction ? 'production' : 'development',
|
||||||
|
presets: [
|
||||||
|
[
|
||||||
|
'@babel/preset-env',
|
||||||
|
{
|
||||||
|
modules: false,
|
||||||
|
loose: true,
|
||||||
|
debug: false,
|
||||||
|
useBuiltIns: 'entry',
|
||||||
|
corejs: 3
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
|
||||||
|
// CSS Modules
|
||||||
|
{
|
||||||
|
test: /\.css$/,
|
||||||
|
exclude: /(node_modules|globals.css)/,
|
||||||
|
use: [
|
||||||
|
{ loader: MiniCssExtractPlugin.loader },
|
||||||
|
{
|
||||||
|
loader: 'css-loader',
|
||||||
|
options: {
|
||||||
|
importLoaders: 1,
|
||||||
|
modules: {
|
||||||
|
localIdentName: '[name]/[local]/[hash:base64:5]'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
loader: 'postcss-loader',
|
||||||
|
options: {
|
||||||
|
ident: 'postcss',
|
||||||
|
config: {
|
||||||
|
ctx: {
|
||||||
|
cssVarsFiles
|
||||||
|
},
|
||||||
|
path: 'frontend/postcss.config.js'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
|
||||||
|
// Global styles
|
||||||
|
{
|
||||||
|
test: /\.css$/,
|
||||||
|
include: /(node_modules|globals.css)/,
|
||||||
|
use: [
|
||||||
|
'style-loader',
|
||||||
|
{
|
||||||
|
loader: 'css-loader'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
|
||||||
|
// Fonts
|
||||||
|
{
|
||||||
|
test: /\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$/,
|
||||||
|
use: [
|
||||||
|
{
|
||||||
|
loader: 'url-loader',
|
||||||
|
options: {
|
||||||
|
limit: 10240,
|
||||||
|
mimetype: 'application/font-woff',
|
||||||
|
emitFile: false,
|
||||||
|
name: 'Content/Fonts/[name].[ext]'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
test: /\.(ttf|eot|eot?#iefix|svg)(\?v=[0-9]\.[0-9]\.[0-9])?$/,
|
||||||
|
use: [
|
||||||
|
{
|
||||||
|
loader: 'file-loader',
|
||||||
|
options: {
|
||||||
|
emitFile: false,
|
||||||
|
name: 'Content/Fonts/[name].[ext]'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
gulp.task('webpack', () => {
|
||||||
|
return webpackStream(config)
|
||||||
|
.pipe(gulp.dest('_output/UI'));
|
||||||
|
});
|
||||||
|
|
||||||
|
gulp.task('webpackWatch', () => {
|
||||||
|
config.watch = true;
|
||||||
|
|
||||||
|
return webpackStream(config)
|
||||||
|
.on('error', errorHandler)
|
||||||
|
.pipe(gulp.dest('_output/UI'))
|
||||||
|
.on('error', errorHandler)
|
||||||
|
.pipe(livereload())
|
||||||
|
.on('error', errorHandler);
|
||||||
|
});
|
|
@ -1,4 +1,3 @@
|
||||||
// eslint-disable-next-line filenames/match-exported
|
|
||||||
const loaderUtils = require('loader-utils');
|
const loaderUtils = require('loader-utils');
|
||||||
|
|
||||||
module.exports = function cssVariablesLoader(source) {
|
module.exports = function cssVariablesLoader(source) {
|
|
@ -1,31 +1,23 @@
|
||||||
const reload = require('require-nocache')(module);
|
const reload = require('require-nocache')(module);
|
||||||
|
|
||||||
const cssVarsFiles = [
|
module.exports = (ctx, configPath, options) => {
|
||||||
'./src/Styles/Variables/dimensions',
|
const config = {
|
||||||
'./src/Styles/Variables/fonts',
|
plugins: {
|
||||||
'./src/Styles/Variables/animations',
|
'postcss-mixins': {
|
||||||
'./src/Styles/Variables/zIndexes'
|
mixinsDir: [
|
||||||
].map(require.resolve);
|
'frontend/src/Styles/Mixins'
|
||||||
|
]
|
||||||
const mixinsFiles = [
|
},
|
||||||
'frontend/src/Styles/Mixins/cover.css',
|
'postcss-simple-vars': {
|
||||||
'frontend/src/Styles/Mixins/linkOverlay.css',
|
|
||||||
'frontend/src/Styles/Mixins/scroller.css',
|
|
||||||
'frontend/src/Styles/Mixins/truncate.css'
|
|
||||||
];
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
plugins: [
|
|
||||||
['postcss-mixins', {
|
|
||||||
mixinsFiles
|
|
||||||
}],
|
|
||||||
['postcss-simple-vars', {
|
|
||||||
variables: () =>
|
variables: () =>
|
||||||
cssVarsFiles.reduce((acc, vars) => {
|
ctx.options.cssVarsFiles.reduce((acc, vars) => {
|
||||||
return Object.assign(acc, reload(vars));
|
return Object.assign(acc, reload(vars));
|
||||||
}, {})
|
}, {})
|
||||||
}],
|
},
|
||||||
'postcss-color-function',
|
'postcss-color-function': {},
|
||||||
'postcss-nested'
|
'postcss-nested': {}
|
||||||
]
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return config;
|
||||||
};
|
};
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
// Place your settings in this file to overwrite default and user settings.
|
||||||
|
{
|
||||||
|
"files.insertFinalNewline": true
|
||||||
|
}
|
|
@ -0,0 +1,123 @@
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import React, { Component } from 'react';
|
||||||
|
import { align, icons } from 'Helpers/Props';
|
||||||
|
import LoadingIndicator from 'Components/Loading/LoadingIndicator';
|
||||||
|
import Table from 'Components/Table/Table';
|
||||||
|
import TableBody from 'Components/Table/TableBody';
|
||||||
|
import TableOptionsModalWrapper from 'Components/Table/TableOptions/TableOptionsModalWrapper';
|
||||||
|
import TablePager from 'Components/Table/TablePager';
|
||||||
|
import PageContent from 'Components/Page/PageContent';
|
||||||
|
import PageContentBodyConnector from 'Components/Page/PageContentBodyConnector';
|
||||||
|
import PageToolbar from 'Components/Page/Toolbar/PageToolbar';
|
||||||
|
import PageToolbarSection from 'Components/Page/Toolbar/PageToolbarSection';
|
||||||
|
import PageToolbarButton from 'Components/Page/Toolbar/PageToolbarButton';
|
||||||
|
import BlacklistRowConnector from './BlacklistRowConnector';
|
||||||
|
|
||||||
|
class Blacklist extends Component {
|
||||||
|
|
||||||
|
//
|
||||||
|
// Render
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const {
|
||||||
|
isFetching,
|
||||||
|
isPopulated,
|
||||||
|
error,
|
||||||
|
items,
|
||||||
|
columns,
|
||||||
|
totalRecords,
|
||||||
|
isClearingBlacklistExecuting,
|
||||||
|
onClearBlacklistPress,
|
||||||
|
...otherProps
|
||||||
|
} = this.props;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<PageContent title="Blacklist">
|
||||||
|
<PageToolbar>
|
||||||
|
<PageToolbarSection>
|
||||||
|
<PageToolbarButton
|
||||||
|
label="Clear"
|
||||||
|
iconName={icons.CLEAR}
|
||||||
|
isSpinning={isClearingBlacklistExecuting}
|
||||||
|
onPress={onClearBlacklistPress}
|
||||||
|
/>
|
||||||
|
</PageToolbarSection>
|
||||||
|
|
||||||
|
<PageToolbarSection alignContent={align.RIGHT}>
|
||||||
|
<TableOptionsModalWrapper
|
||||||
|
{...otherProps}
|
||||||
|
columns={columns}
|
||||||
|
>
|
||||||
|
<PageToolbarButton
|
||||||
|
label="Options"
|
||||||
|
iconName={icons.TABLE}
|
||||||
|
/>
|
||||||
|
</TableOptionsModalWrapper>
|
||||||
|
</PageToolbarSection>
|
||||||
|
</PageToolbar>
|
||||||
|
|
||||||
|
<PageContentBodyConnector>
|
||||||
|
{
|
||||||
|
isFetching && !isPopulated &&
|
||||||
|
<LoadingIndicator />
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
!isFetching && !!error &&
|
||||||
|
<div>Unable to load blacklist</div>
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
isPopulated && !error && !items.length &&
|
||||||
|
<div>
|
||||||
|
No history blacklist
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
isPopulated && !error && !!items.length &&
|
||||||
|
<div>
|
||||||
|
<Table
|
||||||
|
columns={columns}
|
||||||
|
{...otherProps}
|
||||||
|
>
|
||||||
|
<TableBody>
|
||||||
|
{
|
||||||
|
items.map((item) => {
|
||||||
|
return (
|
||||||
|
<BlacklistRowConnector
|
||||||
|
key={item.id}
|
||||||
|
columns={columns}
|
||||||
|
{...item}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</TableBody>
|
||||||
|
</Table>
|
||||||
|
|
||||||
|
<TablePager
|
||||||
|
totalRecords={totalRecords}
|
||||||
|
isFetching={isFetching}
|
||||||
|
{...otherProps}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</PageContentBodyConnector>
|
||||||
|
</PageContent>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Blacklist.propTypes = {
|
||||||
|
isFetching: PropTypes.bool.isRequired,
|
||||||
|
isPopulated: PropTypes.bool.isRequired,
|
||||||
|
error: PropTypes.object,
|
||||||
|
items: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||||
|
columns: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||||
|
totalRecords: PropTypes.number,
|
||||||
|
isClearingBlacklistExecuting: PropTypes.bool.isRequired,
|
||||||
|
onClearBlacklistPress: PropTypes.func.isRequired
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Blacklist;
|
|
@ -0,0 +1,154 @@
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import React, { Component } from 'react';
|
||||||
|
import { connect } from 'react-redux';
|
||||||
|
import { createSelector } from 'reselect';
|
||||||
|
import { registerPagePopulator, unregisterPagePopulator } from 'Utilities/pagePopulator';
|
||||||
|
import withCurrentPage from 'Components/withCurrentPage';
|
||||||
|
import createCommandExecutingSelector from 'Store/Selectors/createCommandExecutingSelector';
|
||||||
|
import * as blacklistActions from 'Store/Actions/blacklistActions';
|
||||||
|
import { executeCommand } from 'Store/Actions/commandActions';
|
||||||
|
import * as commandNames from 'Commands/commandNames';
|
||||||
|
import Blacklist from './Blacklist';
|
||||||
|
|
||||||
|
function createMapStateToProps() {
|
||||||
|
return createSelector(
|
||||||
|
(state) => state.blacklist,
|
||||||
|
createCommandExecutingSelector(commandNames.CLEAR_BLACKLIST),
|
||||||
|
(blacklist, isClearingBlacklistExecuting) => {
|
||||||
|
return {
|
||||||
|
isClearingBlacklistExecuting,
|
||||||
|
...blacklist
|
||||||
|
};
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const mapDispatchToProps = {
|
||||||
|
...blacklistActions,
|
||||||
|
executeCommand
|
||||||
|
};
|
||||||
|
|
||||||
|
class BlacklistConnector extends Component {
|
||||||
|
|
||||||
|
//
|
||||||
|
// Lifecycle
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
const {
|
||||||
|
useCurrentPage,
|
||||||
|
fetchBlacklist,
|
||||||
|
gotoBlacklistFirstPage
|
||||||
|
} = this.props;
|
||||||
|
|
||||||
|
registerPagePopulator(this.repopulate);
|
||||||
|
|
||||||
|
if (useCurrentPage) {
|
||||||
|
fetchBlacklist();
|
||||||
|
} else {
|
||||||
|
gotoBlacklistFirstPage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidUpdate(prevProps) {
|
||||||
|
if (prevProps.isClearingBlacklistExecuting && !this.props.isClearingBlacklistExecuting) {
|
||||||
|
this.props.gotoBlacklistFirstPage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillUnmount() {
|
||||||
|
this.props.clearBlacklist();
|
||||||
|
unregisterPagePopulator(this.repopulate);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Control
|
||||||
|
|
||||||
|
repopulate = () => {
|
||||||
|
this.props.fetchBlacklist();
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Listeners
|
||||||
|
|
||||||
|
onFirstPagePress = () => {
|
||||||
|
this.props.gotoBlacklistFirstPage();
|
||||||
|
}
|
||||||
|
|
||||||
|
onPreviousPagePress = () => {
|
||||||
|
this.props.gotoBlacklistPreviousPage();
|
||||||
|
}
|
||||||
|
|
||||||
|
onNextPagePress = () => {
|
||||||
|
this.props.gotoBlacklistNextPage();
|
||||||
|
}
|
||||||
|
|
||||||
|
onLastPagePress = () => {
|
||||||
|
this.props.gotoBlacklistLastPage();
|
||||||
|
}
|
||||||
|
|
||||||
|
onPageSelect = (page) => {
|
||||||
|
this.props.gotoBlacklistPage({ page });
|
||||||
|
}
|
||||||
|
|
||||||
|
onSortPress = (sortKey) => {
|
||||||
|
this.props.setBlacklistSort({ sortKey });
|
||||||
|
}
|
||||||
|
|
||||||
|
onTableOptionChange = (payload) => {
|
||||||
|
this.props.setBlacklistTableOption(payload);
|
||||||
|
|
||||||
|
if (payload.pageSize) {
|
||||||
|
this.props.gotoBlacklistFirstPage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onClearBlacklistPress = () => {
|
||||||
|
this.props.executeCommand({ name: commandNames.CLEAR_BLACKLIST });
|
||||||
|
}
|
||||||
|
|
||||||
|
onTableOptionChange = (payload) => {
|
||||||
|
this.props.setBlacklistTableOption(payload);
|
||||||
|
|
||||||
|
if (payload.pageSize) {
|
||||||
|
this.props.gotoBlacklistFirstPage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Render
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<Blacklist
|
||||||
|
onFirstPagePress={this.onFirstPagePress}
|
||||||
|
onPreviousPagePress={this.onPreviousPagePress}
|
||||||
|
onNextPagePress={this.onNextPagePress}
|
||||||
|
onLastPagePress={this.onLastPagePress}
|
||||||
|
onPageSelect={this.onPageSelect}
|
||||||
|
onSortPress={this.onSortPress}
|
||||||
|
onTableOptionChange={this.onTableOptionChange}
|
||||||
|
onClearBlacklistPress={this.onClearBlacklistPress}
|
||||||
|
{...this.props}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BlacklistConnector.propTypes = {
|
||||||
|
useCurrentPage: PropTypes.bool.isRequired,
|
||||||
|
isClearingBlacklistExecuting: PropTypes.bool.isRequired,
|
||||||
|
items: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||||
|
fetchBlacklist: PropTypes.func.isRequired,
|
||||||
|
gotoBlacklistFirstPage: PropTypes.func.isRequired,
|
||||||
|
gotoBlacklistPreviousPage: PropTypes.func.isRequired,
|
||||||
|
gotoBlacklistNextPage: PropTypes.func.isRequired,
|
||||||
|
gotoBlacklistLastPage: PropTypes.func.isRequired,
|
||||||
|
gotoBlacklistPage: PropTypes.func.isRequired,
|
||||||
|
setBlacklistSort: PropTypes.func.isRequired,
|
||||||
|
setBlacklistTableOption: PropTypes.func.isRequired,
|
||||||
|
clearBlacklist: PropTypes.func.isRequired,
|
||||||
|
executeCommand: PropTypes.func.isRequired
|
||||||
|
};
|
||||||
|
|
||||||
|
export default withCurrentPage(
|
||||||
|
connect(createMapStateToProps, mapDispatchToProps)(BlacklistConnector)
|
||||||
|
);
|
|
@ -0,0 +1,89 @@
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import React, { Component } from 'react';
|
||||||
|
import Button from 'Components/Link/Button';
|
||||||
|
import DescriptionList from 'Components/DescriptionList/DescriptionList';
|
||||||
|
import DescriptionListItem from 'Components/DescriptionList/DescriptionListItem';
|
||||||
|
import Modal from 'Components/Modal/Modal';
|
||||||
|
import ModalContent from 'Components/Modal/ModalContent';
|
||||||
|
import ModalHeader from 'Components/Modal/ModalHeader';
|
||||||
|
import ModalBody from 'Components/Modal/ModalBody';
|
||||||
|
import ModalFooter from 'Components/Modal/ModalFooter';
|
||||||
|
|
||||||
|
class BlacklistDetailsModal extends Component {
|
||||||
|
|
||||||
|
//
|
||||||
|
// Render
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const {
|
||||||
|
isOpen,
|
||||||
|
sourceTitle,
|
||||||
|
protocol,
|
||||||
|
indexer,
|
||||||
|
message,
|
||||||
|
onModalClose
|
||||||
|
} = this.props;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Modal
|
||||||
|
isOpen={isOpen}
|
||||||
|
onModalClose={onModalClose}
|
||||||
|
>
|
||||||
|
<ModalContent
|
||||||
|
onModalClose={onModalClose}
|
||||||
|
>
|
||||||
|
<ModalHeader>
|
||||||
|
Details
|
||||||
|
</ModalHeader>
|
||||||
|
|
||||||
|
<ModalBody>
|
||||||
|
<DescriptionList>
|
||||||
|
<DescriptionListItem
|
||||||
|
title="Name"
|
||||||
|
data={sourceTitle}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<DescriptionListItem
|
||||||
|
title="Protocol"
|
||||||
|
data={protocol}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{
|
||||||
|
!!message &&
|
||||||
|
<DescriptionListItem
|
||||||
|
title="Indexer"
|
||||||
|
data={indexer}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
!!message &&
|
||||||
|
<DescriptionListItem
|
||||||
|
title="Message"
|
||||||
|
data={message}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
</DescriptionList>
|
||||||
|
</ModalBody>
|
||||||
|
|
||||||
|
<ModalFooter>
|
||||||
|
<Button onPress={onModalClose}>
|
||||||
|
Close
|
||||||
|
</Button>
|
||||||
|
</ModalFooter>
|
||||||
|
</ModalContent>
|
||||||
|
</Modal>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BlacklistDetailsModal.propTypes = {
|
||||||
|
isOpen: PropTypes.bool.isRequired,
|
||||||
|
sourceTitle: PropTypes.string.isRequired,
|
||||||
|
protocol: PropTypes.string.isRequired,
|
||||||
|
indexer: PropTypes.string,
|
||||||
|
message: PropTypes.string,
|
||||||
|
onModalClose: PropTypes.func.isRequired
|
||||||
|
};
|
||||||
|
|
||||||
|
export default BlacklistDetailsModal;
|
|
@ -0,0 +1,18 @@
|
||||||
|
.language,
|
||||||
|
.quality {
|
||||||
|
composes: cell from '~Components/Table/Cells/TableRowCell.css';
|
||||||
|
|
||||||
|
width: 100px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.indexer {
|
||||||
|
composes: cell from '~Components/Table/Cells/TableRowCell.css';
|
||||||
|
|
||||||
|
width: 80px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.actions {
|
||||||
|
composes: cell from '~Components/Table/Cells/TableRowCell.css';
|
||||||
|
|
||||||
|
width: 70px;
|
||||||
|
}
|
|
@ -0,0 +1,186 @@
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import React, { Component } from 'react';
|
||||||
|
import { icons, kinds } from 'Helpers/Props';
|
||||||
|
import IconButton from 'Components/Link/IconButton';
|
||||||
|
import RelativeDateCellConnector from 'Components/Table/Cells/RelativeDateCellConnector';
|
||||||
|
import TableRow from 'Components/Table/TableRow';
|
||||||
|
import TableRowCell from 'Components/Table/Cells/TableRowCell';
|
||||||
|
import EpisodeLanguage from 'Episode/EpisodeLanguage';
|
||||||
|
import EpisodeQuality from 'Episode/EpisodeQuality';
|
||||||
|
import SeriesTitleLink from 'Series/SeriesTitleLink';
|
||||||
|
import BlacklistDetailsModal from './BlacklistDetailsModal';
|
||||||
|
import styles from './BlacklistRow.css';
|
||||||
|
|
||||||
|
class BlacklistRow extends Component {
|
||||||
|
|
||||||
|
//
|
||||||
|
// Lifecycle
|
||||||
|
|
||||||
|
constructor(props, context) {
|
||||||
|
super(props, context);
|
||||||
|
|
||||||
|
this.state = {
|
||||||
|
isDetailsModalOpen: false
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Listeners
|
||||||
|
|
||||||
|
onDetailsPress = () => {
|
||||||
|
this.setState({ isDetailsModalOpen: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
onDetailsModalClose = () => {
|
||||||
|
this.setState({ isDetailsModalOpen: false });
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Render
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const {
|
||||||
|
series,
|
||||||
|
sourceTitle,
|
||||||
|
language,
|
||||||
|
quality,
|
||||||
|
date,
|
||||||
|
protocol,
|
||||||
|
indexer,
|
||||||
|
message,
|
||||||
|
columns,
|
||||||
|
onRemovePress
|
||||||
|
} = this.props;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<TableRow>
|
||||||
|
{
|
||||||
|
columns.map((column) => {
|
||||||
|
const {
|
||||||
|
name,
|
||||||
|
isVisible
|
||||||
|
} = column;
|
||||||
|
|
||||||
|
if (!isVisible) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (name === 'series.sortTitle') {
|
||||||
|
return (
|
||||||
|
<TableRowCell key={name}>
|
||||||
|
<SeriesTitleLink
|
||||||
|
titleSlug={series.titleSlug}
|
||||||
|
title={series.title}
|
||||||
|
/>
|
||||||
|
</TableRowCell>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (name === 'sourceTitle') {
|
||||||
|
return (
|
||||||
|
<TableRowCell key={name}>
|
||||||
|
{sourceTitle}
|
||||||
|
</TableRowCell>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (name === 'language') {
|
||||||
|
return (
|
||||||
|
<TableRowCell
|
||||||
|
key={name}
|
||||||
|
className={styles.language}
|
||||||
|
>
|
||||||
|
<EpisodeLanguage
|
||||||
|
language={language}
|
||||||
|
/>
|
||||||
|
</TableRowCell>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (name === 'quality') {
|
||||||
|
return (
|
||||||
|
<TableRowCell
|
||||||
|
key={name}
|
||||||
|
className={styles.quality}
|
||||||
|
>
|
||||||
|
<EpisodeQuality
|
||||||
|
quality={quality}
|
||||||
|
/>
|
||||||
|
</TableRowCell>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (name === 'date') {
|
||||||
|
return (
|
||||||
|
<RelativeDateCellConnector
|
||||||
|
key={name}
|
||||||
|
date={date}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (name === 'indexer') {
|
||||||
|
return (
|
||||||
|
<TableRowCell
|
||||||
|
key={name}
|
||||||
|
className={styles.indexer}
|
||||||
|
>
|
||||||
|
{indexer}
|
||||||
|
</TableRowCell>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (name === 'actions') {
|
||||||
|
return (
|
||||||
|
<TableRowCell
|
||||||
|
key={name}
|
||||||
|
className={styles.actions}
|
||||||
|
>
|
||||||
|
<IconButton
|
||||||
|
name={icons.INFO}
|
||||||
|
onPress={this.onDetailsPress}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<IconButton
|
||||||
|
title="Remove from blacklist"
|
||||||
|
name={icons.REMOVE}
|
||||||
|
kind={kinds.DANGER}
|
||||||
|
onPress={onRemovePress}
|
||||||
|
/>
|
||||||
|
</TableRowCell>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
<BlacklistDetailsModal
|
||||||
|
isOpen={this.state.isDetailsModalOpen}
|
||||||
|
sourceTitle={sourceTitle}
|
||||||
|
protocol={protocol}
|
||||||
|
indexer={indexer}
|
||||||
|
message={message}
|
||||||
|
onModalClose={this.onDetailsModalClose}
|
||||||
|
/>
|
||||||
|
</TableRow>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
BlacklistRow.propTypes = {
|
||||||
|
id: PropTypes.number.isRequired,
|
||||||
|
series: PropTypes.object.isRequired,
|
||||||
|
sourceTitle: PropTypes.string.isRequired,
|
||||||
|
language: PropTypes.object.isRequired,
|
||||||
|
quality: PropTypes.object.isRequired,
|
||||||
|
date: PropTypes.string.isRequired,
|
||||||
|
protocol: PropTypes.string.isRequired,
|
||||||
|
indexer: PropTypes.string,
|
||||||
|
message: PropTypes.string,
|
||||||
|
columns: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||||
|
onRemovePress: PropTypes.func.isRequired
|
||||||
|
};
|
||||||
|
|
||||||
|
export default BlacklistRow;
|
|
@ -0,0 +1,26 @@
|
||||||
|
import { connect } from 'react-redux';
|
||||||
|
import { createSelector } from 'reselect';
|
||||||
|
import { removeFromBlacklist } from 'Store/Actions/blacklistActions';
|
||||||
|
import createSeriesSelector from 'Store/Selectors/createSeriesSelector';
|
||||||
|
import BlacklistRow from './BlacklistRow';
|
||||||
|
|
||||||
|
function createMapStateToProps() {
|
||||||
|
return createSelector(
|
||||||
|
createSeriesSelector(),
|
||||||
|
(series) => {
|
||||||
|
return {
|
||||||
|
series
|
||||||
|
};
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function createMapDispatchToProps(dispatch, props) {
|
||||||
|
return {
|
||||||
|
onRemovePress() {
|
||||||
|
dispatch(removeFromBlacklist({ id: props.id }));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export default connect(createMapStateToProps, createMapDispatchToProps)(BlacklistRow);
|
|
@ -1,329 +0,0 @@
|
||||||
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
|
||||||
import { useDispatch, useSelector } from 'react-redux';
|
|
||||||
import { SelectProvider } from 'App/SelectContext';
|
|
||||||
import AppState from 'App/State/AppState';
|
|
||||||
import * as commandNames from 'Commands/commandNames';
|
|
||||||
import Alert from 'Components/Alert';
|
|
||||||
import LoadingIndicator from 'Components/Loading/LoadingIndicator';
|
|
||||||
import FilterMenu from 'Components/Menu/FilterMenu';
|
|
||||||
import ConfirmModal from 'Components/Modal/ConfirmModal';
|
|
||||||
import PageContent from 'Components/Page/PageContent';
|
|
||||||
import PageContentBody from 'Components/Page/PageContentBody';
|
|
||||||
import PageToolbar from 'Components/Page/Toolbar/PageToolbar';
|
|
||||||
import PageToolbarButton from 'Components/Page/Toolbar/PageToolbarButton';
|
|
||||||
import PageToolbarSection from 'Components/Page/Toolbar/PageToolbarSection';
|
|
||||||
import Table from 'Components/Table/Table';
|
|
||||||
import TableBody from 'Components/Table/TableBody';
|
|
||||||
import TableOptionsModalWrapper from 'Components/Table/TableOptions/TableOptionsModalWrapper';
|
|
||||||
import TablePager from 'Components/Table/TablePager';
|
|
||||||
import usePaging from 'Components/Table/usePaging';
|
|
||||||
import useCurrentPage from 'Helpers/Hooks/useCurrentPage';
|
|
||||||
import usePrevious from 'Helpers/Hooks/usePrevious';
|
|
||||||
import useSelectState from 'Helpers/Hooks/useSelectState';
|
|
||||||
import { align, icons, kinds } from 'Helpers/Props';
|
|
||||||
import {
|
|
||||||
clearBlocklist,
|
|
||||||
fetchBlocklist,
|
|
||||||
gotoBlocklistPage,
|
|
||||||
removeBlocklistItems,
|
|
||||||
setBlocklistFilter,
|
|
||||||
setBlocklistSort,
|
|
||||||
setBlocklistTableOption,
|
|
||||||
} from 'Store/Actions/blocklistActions';
|
|
||||||
import { executeCommand } from 'Store/Actions/commandActions';
|
|
||||||
import { createCustomFiltersSelector } from 'Store/Selectors/createClientSideCollectionSelector';
|
|
||||||
import createCommandExecutingSelector from 'Store/Selectors/createCommandExecutingSelector';
|
|
||||||
import { CheckInputChanged } from 'typings/inputs';
|
|
||||||
import { SelectStateInputProps } from 'typings/props';
|
|
||||||
import { TableOptionsChangePayload } from 'typings/Table';
|
|
||||||
import {
|
|
||||||
registerPagePopulator,
|
|
||||||
unregisterPagePopulator,
|
|
||||||
} from 'Utilities/pagePopulator';
|
|
||||||
import translate from 'Utilities/String/translate';
|
|
||||||
import getSelectedIds from 'Utilities/Table/getSelectedIds';
|
|
||||||
import BlocklistFilterModal from './BlocklistFilterModal';
|
|
||||||
import BlocklistRow from './BlocklistRow';
|
|
||||||
|
|
||||||
function Blocklist() {
|
|
||||||
const requestCurrentPage = useCurrentPage();
|
|
||||||
|
|
||||||
const {
|
|
||||||
isFetching,
|
|
||||||
isPopulated,
|
|
||||||
error,
|
|
||||||
items,
|
|
||||||
columns,
|
|
||||||
selectedFilterKey,
|
|
||||||
filters,
|
|
||||||
sortKey,
|
|
||||||
sortDirection,
|
|
||||||
page,
|
|
||||||
pageSize,
|
|
||||||
totalPages,
|
|
||||||
totalRecords,
|
|
||||||
isRemoving,
|
|
||||||
} = useSelector((state: AppState) => state.blocklist);
|
|
||||||
|
|
||||||
const customFilters = useSelector(createCustomFiltersSelector('blocklist'));
|
|
||||||
const isClearingBlocklistExecuting = useSelector(
|
|
||||||
createCommandExecutingSelector(commandNames.CLEAR_BLOCKLIST)
|
|
||||||
);
|
|
||||||
const dispatch = useDispatch();
|
|
||||||
|
|
||||||
const [isConfirmRemoveModalOpen, setIsConfirmRemoveModalOpen] =
|
|
||||||
useState(false);
|
|
||||||
const [isConfirmClearModalOpen, setIsConfirmClearModalOpen] = useState(false);
|
|
||||||
|
|
||||||
const [selectState, setSelectState] = useSelectState();
|
|
||||||
const { allSelected, allUnselected, selectedState } = selectState;
|
|
||||||
|
|
||||||
const selectedIds = useMemo(() => {
|
|
||||||
return getSelectedIds(selectedState);
|
|
||||||
}, [selectedState]);
|
|
||||||
|
|
||||||
const wasClearingBlocklistExecuting = usePrevious(
|
|
||||||
isClearingBlocklistExecuting
|
|
||||||
);
|
|
||||||
|
|
||||||
const handleSelectAllChange = useCallback(
|
|
||||||
({ value }: CheckInputChanged) => {
|
|
||||||
setSelectState({ type: value ? 'selectAll' : 'unselectAll', items });
|
|
||||||
},
|
|
||||||
[items, setSelectState]
|
|
||||||
);
|
|
||||||
|
|
||||||
const handleSelectedChange = useCallback(
|
|
||||||
({ id, value, shiftKey = false }: SelectStateInputProps) => {
|
|
||||||
setSelectState({
|
|
||||||
type: 'toggleSelected',
|
|
||||||
items,
|
|
||||||
id,
|
|
||||||
isSelected: value,
|
|
||||||
shiftKey,
|
|
||||||
});
|
|
||||||
},
|
|
||||||
[items, setSelectState]
|
|
||||||
);
|
|
||||||
|
|
||||||
const handleRemoveSelectedPress = useCallback(() => {
|
|
||||||
setIsConfirmRemoveModalOpen(true);
|
|
||||||
}, [setIsConfirmRemoveModalOpen]);
|
|
||||||
|
|
||||||
const handleRemoveSelectedConfirmed = useCallback(() => {
|
|
||||||
dispatch(removeBlocklistItems({ ids: selectedIds }));
|
|
||||||
setIsConfirmRemoveModalOpen(false);
|
|
||||||
}, [selectedIds, setIsConfirmRemoveModalOpen, dispatch]);
|
|
||||||
|
|
||||||
const handleConfirmRemoveModalClose = useCallback(() => {
|
|
||||||
setIsConfirmRemoveModalOpen(false);
|
|
||||||
}, [setIsConfirmRemoveModalOpen]);
|
|
||||||
|
|
||||||
const handleClearBlocklistPress = useCallback(() => {
|
|
||||||
setIsConfirmClearModalOpen(true);
|
|
||||||
}, [setIsConfirmClearModalOpen]);
|
|
||||||
|
|
||||||
const handleClearBlocklistConfirmed = useCallback(() => {
|
|
||||||
dispatch(executeCommand({ name: commandNames.CLEAR_BLOCKLIST }));
|
|
||||||
setIsConfirmClearModalOpen(false);
|
|
||||||
}, [setIsConfirmClearModalOpen, dispatch]);
|
|
||||||
|
|
||||||
const handleConfirmClearModalClose = useCallback(() => {
|
|
||||||
setIsConfirmClearModalOpen(false);
|
|
||||||
}, [setIsConfirmClearModalOpen]);
|
|
||||||
|
|
||||||
const {
|
|
||||||
handleFirstPagePress,
|
|
||||||
handlePreviousPagePress,
|
|
||||||
handleNextPagePress,
|
|
||||||
handleLastPagePress,
|
|
||||||
handlePageSelect,
|
|
||||||
} = usePaging({
|
|
||||||
page,
|
|
||||||
totalPages,
|
|
||||||
gotoPage: gotoBlocklistPage,
|
|
||||||
});
|
|
||||||
|
|
||||||
const handleFilterSelect = useCallback(
|
|
||||||
(selectedFilterKey: string) => {
|
|
||||||
dispatch(setBlocklistFilter({ selectedFilterKey }));
|
|
||||||
},
|
|
||||||
[dispatch]
|
|
||||||
);
|
|
||||||
|
|
||||||
const handleSortPress = useCallback(
|
|
||||||
(sortKey: string) => {
|
|
||||||
dispatch(setBlocklistSort({ sortKey }));
|
|
||||||
},
|
|
||||||
[dispatch]
|
|
||||||
);
|
|
||||||
|
|
||||||
const handleTableOptionChange = useCallback(
|
|
||||||
(payload: TableOptionsChangePayload) => {
|
|
||||||
dispatch(setBlocklistTableOption(payload));
|
|
||||||
|
|
||||||
if (payload.pageSize) {
|
|
||||||
dispatch(gotoBlocklistPage({ page: 1 }));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
[dispatch]
|
|
||||||
);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (requestCurrentPage) {
|
|
||||||
dispatch(fetchBlocklist());
|
|
||||||
} else {
|
|
||||||
dispatch(gotoBlocklistPage({ page: 1 }));
|
|
||||||
}
|
|
||||||
|
|
||||||
return () => {
|
|
||||||
dispatch(clearBlocklist());
|
|
||||||
};
|
|
||||||
}, [requestCurrentPage, dispatch]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const repopulate = () => {
|
|
||||||
dispatch(fetchBlocklist());
|
|
||||||
};
|
|
||||||
|
|
||||||
registerPagePopulator(repopulate);
|
|
||||||
|
|
||||||
return () => {
|
|
||||||
unregisterPagePopulator(repopulate);
|
|
||||||
};
|
|
||||||
}, [dispatch]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (wasClearingBlocklistExecuting && !isClearingBlocklistExecuting) {
|
|
||||||
dispatch(gotoBlocklistPage({ page: 1 }));
|
|
||||||
}
|
|
||||||
}, [isClearingBlocklistExecuting, wasClearingBlocklistExecuting, dispatch]);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<SelectProvider items={items}>
|
|
||||||
<PageContent title={translate('Blocklist')}>
|
|
||||||
<PageToolbar>
|
|
||||||
<PageToolbarSection>
|
|
||||||
<PageToolbarButton
|
|
||||||
label={translate('RemoveSelected')}
|
|
||||||
iconName={icons.REMOVE}
|
|
||||||
isDisabled={!selectedIds.length}
|
|
||||||
isSpinning={isRemoving}
|
|
||||||
onPress={handleRemoveSelectedPress}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<PageToolbarButton
|
|
||||||
label={translate('Clear')}
|
|
||||||
iconName={icons.CLEAR}
|
|
||||||
isDisabled={!items.length}
|
|
||||||
isSpinning={isClearingBlocklistExecuting}
|
|
||||||
onPress={handleClearBlocklistPress}
|
|
||||||
/>
|
|
||||||
</PageToolbarSection>
|
|
||||||
|
|
||||||
<PageToolbarSection alignContent={align.RIGHT}>
|
|
||||||
<TableOptionsModalWrapper
|
|
||||||
columns={columns}
|
|
||||||
pageSize={pageSize}
|
|
||||||
onTableOptionChange={handleTableOptionChange}
|
|
||||||
>
|
|
||||||
<PageToolbarButton
|
|
||||||
label={translate('Options')}
|
|
||||||
iconName={icons.TABLE}
|
|
||||||
/>
|
|
||||||
</TableOptionsModalWrapper>
|
|
||||||
|
|
||||||
<FilterMenu
|
|
||||||
alignMenu={align.RIGHT}
|
|
||||||
selectedFilterKey={selectedFilterKey}
|
|
||||||
filters={filters}
|
|
||||||
customFilters={customFilters}
|
|
||||||
filterModalConnectorComponent={BlocklistFilterModal}
|
|
||||||
onFilterSelect={handleFilterSelect}
|
|
||||||
/>
|
|
||||||
</PageToolbarSection>
|
|
||||||
</PageToolbar>
|
|
||||||
|
|
||||||
<PageContentBody>
|
|
||||||
{isFetching && !isPopulated ? <LoadingIndicator /> : null}
|
|
||||||
|
|
||||||
{!isFetching && !!error ? (
|
|
||||||
<Alert kind={kinds.DANGER}>{translate('BlocklistLoadError')}</Alert>
|
|
||||||
) : null}
|
|
||||||
|
|
||||||
{isPopulated && !error && !items.length ? (
|
|
||||||
<Alert kind={kinds.INFO}>
|
|
||||||
{selectedFilterKey === 'all'
|
|
||||||
? translate('NoBlocklistItems')
|
|
||||||
: translate('BlocklistFilterHasNoItems')}
|
|
||||||
</Alert>
|
|
||||||
) : null}
|
|
||||||
|
|
||||||
{isPopulated && !error && !!items.length ? (
|
|
||||||
<div>
|
|
||||||
<Table
|
|
||||||
selectAll={true}
|
|
||||||
allSelected={allSelected}
|
|
||||||
allUnselected={allUnselected}
|
|
||||||
columns={columns}
|
|
||||||
pageSize={pageSize}
|
|
||||||
sortKey={sortKey}
|
|
||||||
sortDirection={sortDirection}
|
|
||||||
onTableOptionChange={handleTableOptionChange}
|
|
||||||
onSelectAllChange={handleSelectAllChange}
|
|
||||||
onSortPress={handleSortPress}
|
|
||||||
>
|
|
||||||
<TableBody>
|
|
||||||
{items.map((item) => {
|
|
||||||
return (
|
|
||||||
<BlocklistRow
|
|
||||||
key={item.id}
|
|
||||||
isSelected={selectedState[item.id] || false}
|
|
||||||
columns={columns}
|
|
||||||
{...item}
|
|
||||||
onSelectedChange={handleSelectedChange}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</TableBody>
|
|
||||||
</Table>
|
|
||||||
<TablePager
|
|
||||||
page={page}
|
|
||||||
totalPages={totalPages}
|
|
||||||
totalRecords={totalRecords}
|
|
||||||
isFetching={isFetching}
|
|
||||||
onFirstPagePress={handleFirstPagePress}
|
|
||||||
onPreviousPagePress={handlePreviousPagePress}
|
|
||||||
onNextPagePress={handleNextPagePress}
|
|
||||||
onLastPagePress={handleLastPagePress}
|
|
||||||
onPageSelect={handlePageSelect}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
) : null}
|
|
||||||
</PageContentBody>
|
|
||||||
|
|
||||||
<ConfirmModal
|
|
||||||
isOpen={isConfirmRemoveModalOpen}
|
|
||||||
kind={kinds.DANGER}
|
|
||||||
title={translate('RemoveSelected')}
|
|
||||||
message={translate('RemoveSelectedBlocklistMessageText')}
|
|
||||||
confirmLabel={translate('RemoveSelected')}
|
|
||||||
onConfirm={handleRemoveSelectedConfirmed}
|
|
||||||
onCancel={handleConfirmRemoveModalClose}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<ConfirmModal
|
|
||||||
isOpen={isConfirmClearModalOpen}
|
|
||||||
kind={kinds.DANGER}
|
|
||||||
title={translate('ClearBlocklist')}
|
|
||||||
message={translate('ClearBlocklistMessageText')}
|
|
||||||
confirmLabel={translate('Clear')}
|
|
||||||
onConfirm={handleClearBlocklistConfirmed}
|
|
||||||
onCancel={handleConfirmClearModalClose}
|
|
||||||
/>
|
|
||||||
</PageContent>
|
|
||||||
</SelectProvider>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default Blocklist;
|
|
|
@ -1,64 +0,0 @@
|
||||||
import React from 'react';
|
|
||||||
import DescriptionList from 'Components/DescriptionList/DescriptionList';
|
|
||||||
import DescriptionListItem from 'Components/DescriptionList/DescriptionListItem';
|
|
||||||
import Button from 'Components/Link/Button';
|
|
||||||
import Modal from 'Components/Modal/Modal';
|
|
||||||
import ModalBody from 'Components/Modal/ModalBody';
|
|
||||||
import ModalContent from 'Components/Modal/ModalContent';
|
|
||||||
import ModalFooter from 'Components/Modal/ModalFooter';
|
|
||||||
import ModalHeader from 'Components/Modal/ModalHeader';
|
|
||||||
import DownloadProtocol from 'DownloadClient/DownloadProtocol';
|
|
||||||
import translate from 'Utilities/String/translate';
|
|
||||||
|
|
||||||
interface BlocklistDetailsModalProps {
|
|
||||||
isOpen: boolean;
|
|
||||||
sourceTitle: string;
|
|
||||||
protocol: DownloadProtocol;
|
|
||||||
indexer?: string;
|
|
||||||
message?: string;
|
|
||||||
onModalClose: () => void;
|
|
||||||
}
|
|
||||||
|
|
||||||
function BlocklistDetailsModal(props: BlocklistDetailsModalProps) {
|
|
||||||
const { isOpen, sourceTitle, protocol, indexer, message, onModalClose } =
|
|
||||||
props;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Modal isOpen={isOpen} onModalClose={onModalClose}>
|
|
||||||
<ModalContent onModalClose={onModalClose}>
|
|
||||||
<ModalHeader>Details</ModalHeader>
|
|
||||||
|
|
||||||
<ModalBody>
|
|
||||||
<DescriptionList>
|
|
||||||
<DescriptionListItem title={translate('Name')} data={sourceTitle} />
|
|
||||||
|
|
||||||
<DescriptionListItem
|
|
||||||
title={translate('Protocol')}
|
|
||||||
data={protocol}
|
|
||||||
/>
|
|
||||||
|
|
||||||
{message ? (
|
|
||||||
<DescriptionListItem
|
|
||||||
title={translate('Indexer')}
|
|
||||||
data={indexer}
|
|
||||||
/>
|
|
||||||
) : null}
|
|
||||||
|
|
||||||
{message ? (
|
|
||||||
<DescriptionListItem
|
|
||||||
title={translate('Message')}
|
|
||||||
data={message}
|
|
||||||
/>
|
|
||||||
) : null}
|
|
||||||
</DescriptionList>
|
|
||||||
</ModalBody>
|
|
||||||
|
|
||||||
<ModalFooter>
|
|
||||||
<Button onPress={onModalClose}>{translate('Close')}</Button>
|
|
||||||
</ModalFooter>
|
|
||||||
</ModalContent>
|
|
||||||
</Modal>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default BlocklistDetailsModal;
|
|
|
@ -1,54 +0,0 @@
|
||||||
import React, { useCallback } from 'react';
|
|
||||||
import { useDispatch, useSelector } from 'react-redux';
|
|
||||||
import { createSelector } from 'reselect';
|
|
||||||
import AppState from 'App/State/AppState';
|
|
||||||
import FilterModal from 'Components/Filter/FilterModal';
|
|
||||||
import { setBlocklistFilter } from 'Store/Actions/blocklistActions';
|
|
||||||
|
|
||||||
function createBlocklistSelector() {
|
|
||||||
return createSelector(
|
|
||||||
(state: AppState) => state.blocklist.items,
|
|
||||||
(blocklistItems) => {
|
|
||||||
return blocklistItems;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function createFilterBuilderPropsSelector() {
|
|
||||||
return createSelector(
|
|
||||||
(state: AppState) => state.blocklist.filterBuilderProps,
|
|
||||||
(filterBuilderProps) => {
|
|
||||||
return filterBuilderProps;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
interface BlocklistFilterModalProps {
|
|
||||||
isOpen: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function BlocklistFilterModal(props: BlocklistFilterModalProps) {
|
|
||||||
const sectionItems = useSelector(createBlocklistSelector());
|
|
||||||
const filterBuilderProps = useSelector(createFilterBuilderPropsSelector());
|
|
||||||
const customFilterType = 'blocklist';
|
|
||||||
|
|
||||||
const dispatch = useDispatch();
|
|
||||||
|
|
||||||
const dispatchSetFilter = useCallback(
|
|
||||||
(payload: unknown) => {
|
|
||||||
dispatch(setBlocklistFilter(payload));
|
|
||||||
},
|
|
||||||
[dispatch]
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<FilterModal
|
|
||||||
// TODO: Don't spread all the props
|
|
||||||
{...props}
|
|
||||||
sectionItems={sectionItems}
|
|
||||||
filterBuilderProps={filterBuilderProps}
|
|
||||||
customFilterType={customFilterType}
|
|
||||||
dispatchSetFilter={dispatchSetFilter}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
|
@ -1,18 +0,0 @@
|
||||||
.languages,
|
|
||||||
.quality {
|
|
||||||
composes: cell from '~Components/Table/Cells/TableRowCell.css';
|
|
||||||
|
|
||||||
width: 100px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.indexer {
|
|
||||||
composes: cell from '~Components/Table/Cells/TableRowCell.css';
|
|
||||||
|
|
||||||
width: 80px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.actions {
|
|
||||||
composes: cell from '~Components/Table/Cells/TableRowCell.css';
|
|
||||||
|
|
||||||
width: 70px;
|
|
||||||
}
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue