Compare commits
424 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c8a6c89036 | ||
|
|
cafe386cc4 | ||
|
|
0184c9695b | ||
|
|
19536edf28 | ||
|
|
045e4a20fa | ||
|
|
6cb8487a52 | ||
|
|
c39e9aa13f | ||
|
|
0203440b06 | ||
|
|
7f7bf60456 | ||
|
|
e8673634bc | ||
|
|
53e52c93ee | ||
|
|
c239c0ea5a | ||
|
|
7142f755f5 | ||
|
|
9fbc8dc1f9 | ||
|
|
d3819a6a88 | ||
|
|
6e93ed8e5f | ||
|
|
98543d49a9 | ||
|
|
9195eead27 | ||
|
|
e5b384736d | ||
|
|
4def720d1a | ||
|
|
2a0404ea17 | ||
|
|
6d22c4f02e | ||
|
|
24ac12da65 | ||
|
|
3f19882df8 | ||
|
|
dd54c16c1f | ||
|
|
223e9289dc | ||
|
|
2e301bdd51 | ||
|
|
e3ec7de23a | ||
|
|
18ec208381 | ||
|
|
8666daa07d | ||
|
|
926a9bdb03 | ||
|
|
fc2d837a2c | ||
|
|
3f69ccab99 | ||
|
|
b6ee82ee52 | ||
|
|
da1eb859a9 | ||
|
|
2b5269b823 | ||
|
|
6c8eeb0ced | ||
|
|
c5e0f3abc8 | ||
|
|
c6dbe22c57 | ||
|
|
51776e2aa3 | ||
|
|
c9d24607f6 | ||
|
|
46f7a3d4f3 | ||
|
|
56cf450c89 | ||
|
|
38c350b020 | ||
|
|
1f46040f1b | ||
|
|
63b95319cd | ||
|
|
a25d92be9e | ||
|
|
a161210a4a | ||
|
|
24469eb2fa | ||
|
|
a93fb49875 | ||
|
|
08d7cdf95b | ||
|
|
a9334bc247 | ||
|
|
2357d0c466 | ||
|
|
b003d51276 | ||
|
|
503cbf9830 | ||
|
|
2466058c5a | ||
|
|
6b1f422456 | ||
|
|
1d16d67733 | ||
|
|
6f9d15aed8 | ||
|
|
8725f974da | ||
|
|
2551c949ae | ||
|
|
30c6020ce7 | ||
|
|
d00b1ce1a1 | ||
|
|
2c43d79585 | ||
|
|
3e4aacb2b0 | ||
|
|
67cd22371b | ||
|
|
586941ece7 | ||
|
|
32a57cbfa6 | ||
|
|
1837a69b3e | ||
|
|
aa8bfcfd92 | ||
|
|
9e0c658470 | ||
|
|
66aefff4f3 | ||
|
|
bd0fdeecee | ||
|
|
1055eeb01b | ||
|
|
263a4578d4 | ||
|
|
c446b8a5af | ||
|
|
847b34cdcb | ||
|
|
5a57f90b8f | ||
|
|
f8eb9f5bd0 | ||
|
|
c8c336b574 | ||
|
|
43f1410974 | ||
|
|
1df110b3fb | ||
|
|
9bedce0df5 | ||
|
|
ae1d879e5a | ||
|
|
caab2e0952 | ||
|
|
a29d6517d3 | ||
|
|
dae2781818 | ||
|
|
c1de609b1a | ||
|
|
4e84807950 | ||
|
|
41c9cb45d6 | ||
|
|
2d72772f86 | ||
|
|
1cf1f0e04d | ||
|
|
324b88ec2b | ||
|
|
ec64c7ba0b | ||
|
|
67e0f8570e | ||
|
|
1745100705 | ||
|
|
28501944c5 | ||
|
|
c5c1a68f5c | ||
|
|
e2ed7fbd28 | ||
|
|
ab0675055c | ||
|
|
2b65559f36 | ||
|
|
b8beb07df5 | ||
|
|
01748fec49 | ||
|
|
42a50b1a02 | ||
|
|
d81595f43f | ||
|
|
71fa2d867f | ||
|
|
f55dbb0002 | ||
|
|
3e4d623786 | ||
|
|
1b109aac3a | ||
|
|
8558975d55 | ||
|
|
0e895089c7 | ||
|
|
5dd44f66c1 | ||
|
|
a1cfea46c6 | ||
|
|
42c492c85a | ||
|
|
9e8794a39f | ||
|
|
66c3604b2a | ||
|
|
c0ee1ee27b | ||
|
|
a3e669e433 | ||
|
|
8a83b4fff5 | ||
|
|
69c48d3f5d | ||
|
|
88504a335e | ||
|
|
a44a433807 | ||
|
|
9c03a8ae28 | ||
|
|
767a5f3a94 | ||
|
|
db1e138d36 | ||
|
|
84aa05f9a9 | ||
|
|
1071b85472 | ||
|
|
479412b190 | ||
|
|
ac4fc5b0ba | ||
|
|
4a8770232d | ||
|
|
2ea983bdae | ||
|
|
ffce8fa505 | ||
|
|
cb9e529eb7 | ||
|
|
7f0ee208fa | ||
|
|
2d38652034 | ||
|
|
4a2076a550 | ||
|
|
35049b26fe | ||
|
|
39648ba372 | ||
|
|
44ce0bbffd | ||
|
|
a634472873 | ||
|
|
a98c30f7fa | ||
|
|
43d4b80e11 | ||
|
|
09926fcc53 | ||
|
|
17eef7a4aa | ||
|
|
4738d7c951 | ||
|
|
4be0af5fa3 | ||
|
|
8aaa0900e5 | ||
|
|
49b5d9b886 | ||
|
|
7a3912767b | ||
|
|
d1e473aafe | ||
|
|
c91eb7ed47 | ||
|
|
443f631bac | ||
|
|
95be8d4698 | ||
|
|
f3926d020f | ||
|
|
b48eb5fdd3 | ||
|
|
b0fecdd017 | ||
|
|
793483b6e9 | ||
|
|
c99c7fa9af | ||
|
|
59449a73e1 | ||
|
|
dc86d636ac | ||
|
|
27dd2dd5f3 | ||
|
|
494ae1a47f | ||
|
|
7d1e1e5ff1 | ||
|
|
bcd1567b7d | ||
|
|
ae391b885b | ||
|
|
226bc84a4c | ||
|
|
e60a0c8f61 | ||
|
|
218c90a306 | ||
|
|
2a60c80194 | ||
|
|
35b1c55564 | ||
|
|
20476387ff | ||
|
|
a787748a00 | ||
|
|
34ee540c30 | ||
|
|
975a5ffc82 | ||
|
|
dee0870bf6 | ||
|
|
96ec3bd44e | ||
|
|
e4cf4096a6 | ||
|
|
3d79694c0a | ||
|
|
eab3e4e6f7 | ||
|
|
462152bab2 | ||
|
|
766a455db0 | ||
|
|
30200ac219 | ||
|
|
90a9113971 | ||
|
|
ad1834568f | ||
|
|
6231500b4a | ||
|
|
b2dbc08ea0 | ||
|
|
4700f68f4d | ||
|
|
fa73738309 | ||
|
|
25f92ec438 | ||
|
|
6a59c1dfd6 | ||
|
|
bad6e9d2fe | ||
|
|
e544972c1d | ||
|
|
f1e5de0d58 | ||
|
|
e434e1effb | ||
|
|
ca04b210e6 | ||
|
|
51275af41d | ||
|
|
c2417ac5b3 | ||
|
|
72831d413b | ||
|
|
5cb4bd5819 | ||
|
|
2d9bbca9a9 | ||
|
|
7b54c4e969 | ||
|
|
b50f4ec5ce | ||
|
|
86cc7534c2 | ||
|
|
1ab2565244 | ||
|
|
d2089a9344 | ||
|
|
39153c6936 | ||
|
|
1a8e2b92de | ||
|
|
cf63e751bf | ||
|
|
0c51bc2771 | ||
|
|
5f278cce3e | ||
|
|
f8cf3ac832 | ||
|
|
50bdd02a72 | ||
|
|
424155e5cd | ||
|
|
c4a4d25f7e | ||
|
|
ca2e135cba | ||
|
|
8b4583c59c | ||
|
|
6a836f9151 | ||
|
|
c7b92ad945 | ||
|
|
a05b7a43bd | ||
|
|
929346b2f1 | ||
|
|
23ceed01cb | ||
|
|
2ccf9a1110 | ||
|
|
4917d8e47b | ||
|
|
a0963e5d92 | ||
|
|
e2731b532a | ||
|
|
eccd6056bd | ||
|
|
c1273a4b01 | ||
|
|
017752b06e | ||
|
|
9abb7a04ac | ||
|
|
9533b9d887 | ||
|
|
f1a6feeb8f | ||
|
|
35930f2ffb | ||
|
|
0a1e8a2f8b | ||
|
|
4f9315132b | ||
|
|
196a843148 | ||
|
|
9778875d52 | ||
|
|
fdeb812333 | ||
|
|
e21e12e737 | ||
|
|
52d2322955 | ||
|
|
5ea8f7df33 | ||
|
|
7a9c73df3f | ||
|
|
1f38de989b | ||
|
|
c4f119de9c | ||
|
|
fa2afa856a | ||
|
|
4c83680ae9 | ||
|
|
981665e3e3 | ||
|
|
b3185292b3 | ||
|
|
249f437ff5 | ||
|
|
a7563ab499 | ||
|
|
38f8143fd2 | ||
|
|
a051c17010 | ||
|
|
0b62f8a1c8 | ||
|
|
b803d4f49d | ||
|
|
78e368f406 | ||
|
|
90e613ab26 | ||
|
|
e15914dc2e | ||
|
|
ebe6c39237 | ||
|
|
3369de9660 | ||
|
|
98b831bc22 | ||
|
|
c0f741d914 | ||
|
|
4c27a0cb5c | ||
|
|
4ff5f139f7 | ||
|
|
59910ecadc | ||
|
|
4e37176436 | ||
|
|
35085248b6 | ||
|
|
3ad8a366a6 | ||
|
|
b1660c92cc | ||
|
|
6ec1a3d4cb | ||
|
|
86ffa86800 | ||
|
|
22ad29c92f | ||
|
|
ebc1046ba6 | ||
|
|
43e23b15dc | ||
|
|
c8effe757b | ||
|
|
40b5cd3cff | ||
|
|
26435d85e8 | ||
|
|
b6d5e73708 | ||
|
|
2f193e0c83 | ||
|
|
4897c80646 | ||
|
|
601a455e08 | ||
|
|
d37f4fd77b | ||
|
|
c395cb2206 | ||
|
|
b6f8c612f1 | ||
|
|
18551528ca | ||
|
|
bbc7782f40 | ||
|
|
c121341911 | ||
|
|
990a256e40 | ||
|
|
89e3caf4f2 | ||
|
|
3e4a458fac | ||
|
|
25d2897fb9 | ||
|
|
a2151d0b93 | ||
|
|
5b9dcd829c | ||
|
|
e2e1471dfa | ||
|
|
a664c9abe9 | ||
|
|
0f9b1cdf25 | ||
|
|
7cfd6e7493 | ||
|
|
592f8f0831 | ||
|
|
88c36d2b2d | ||
|
|
dbe5f1dfb2 | ||
|
|
1297ae7bb3 | ||
|
|
ba48a45d39 | ||
|
|
12b5de5cea | ||
|
|
a7b33647ea | ||
|
|
3a7467e6f7 | ||
|
|
8c47ce9b0e | ||
|
|
11f623cc35 | ||
|
|
5365f4b867 | ||
|
|
260a88623e | ||
|
|
2143cab1fa | ||
|
|
5be3662b35 | ||
|
|
c8ab62f9fe | ||
|
|
114c16a36f | ||
|
|
8ac33ceb4c | ||
|
|
9290c20c43 | ||
|
|
c302c26d87 | ||
|
|
f04c6c2032 | ||
|
|
9d35d567ae | ||
|
|
3549ebc5b9 | ||
|
|
68c2dcf67d | ||
|
|
cb4ab20249 | ||
|
|
effafe7b2d | ||
|
|
a2aac1f33c | ||
|
|
7c30f0c236 | ||
|
|
39c71b6f26 | ||
|
|
bc5c1ebb1e | ||
|
|
800470f7fa | ||
|
|
a0195e2e08 | ||
|
|
f60aee8072 | ||
|
|
92b54d18a9 | ||
|
|
aeae6a6ebe | ||
|
|
cf674629cb | ||
|
|
650ba498e1 | ||
|
|
8cbd6b7001 | ||
|
|
096ceb47ea | ||
|
|
d0708ea8fb | ||
|
|
d299e1dbb9 | ||
|
|
ee96a2c625 | ||
|
|
4c8477c4a9 | ||
|
|
aa97c8fd3a | ||
|
|
995eb6b557 | ||
|
|
7f0a33e36a | ||
|
|
2100075972 | ||
|
|
6735401302 | ||
|
|
443e18e84f | ||
|
|
679313e58c | ||
|
|
3b817c20fa | ||
|
|
5baedc39bc | ||
|
|
11177b73a5 | ||
|
|
83263c0b1b | ||
|
|
076d51c6eb | ||
|
|
18e1d962b8 | ||
|
|
989989bda7 | ||
|
|
5c5f204545 | ||
|
|
40e7431b98 | ||
|
|
6a933ffc1d | ||
|
|
a79d47f161 | ||
|
|
887e5c9d49 | ||
|
|
309eb4ac33 | ||
|
|
67f4590942 | ||
|
|
fcadb2443e | ||
|
|
9776825506 | ||
|
|
ee089d0761 | ||
|
|
19e739196c | ||
|
|
a6484b801c | ||
|
|
d07fb5ea99 | ||
|
|
095c4f5181 | ||
|
|
0c7842a3d6 | ||
|
|
01ac523e60 | ||
|
|
6feff6441e | ||
|
|
7229d32e8b | ||
|
|
bbd85d2516 | ||
|
|
803ab459b1 | ||
|
|
256648e682 | ||
|
|
758599804c | ||
|
|
b2dd3f803e | ||
|
|
912c6512fb | ||
|
|
fff44f4681 | ||
|
|
79f4a6cc07 | ||
|
|
b910a933fb | ||
|
|
e0d08c60d0 | ||
|
|
33394c2f07 | ||
|
|
4fc2bbd1af | ||
|
|
e4e815dc40 | ||
|
|
482831b9f9 | ||
|
|
30aea8e361 | ||
|
|
dfc3c2194c | ||
|
|
7376aef136 | ||
|
|
18a45863bd | ||
|
|
9c5cf150e7 | ||
|
|
c08dcab1d8 | ||
|
|
c9d9d50fa0 | ||
|
|
9bb0304620 | ||
|
|
7b5bc24a6d | ||
|
|
1d390d7966 | ||
|
|
528b317552 | ||
|
|
116ff2dd46 | ||
|
|
3d8483f9bb | ||
|
|
6d1d723df2 | ||
|
|
3a93b4f0e1 | ||
|
|
f7286bb38f | ||
|
|
764222c901 | ||
|
|
6409e291be | ||
|
|
cb719be3ad | ||
|
|
9e93ac10f4 | ||
|
|
dce553c587 | ||
|
|
3ab91cc0e1 | ||
|
|
6adbcb8d1c | ||
|
|
211da7cb09 | ||
|
|
beb12147e0 | ||
|
|
0f3087ab7d | ||
|
|
a5e99545d7 | ||
|
|
a8a7e56da7 | ||
|
|
57ac6bc680 | ||
|
|
3a3446151e | ||
|
|
fd5ca1914c | ||
|
|
ade028767a | ||
|
|
983cf98b9e | ||
|
|
3e02d92105 | ||
|
|
0cd8f551a1 | ||
|
|
bd8bac162f | ||
|
|
91ecd03c4e | ||
|
|
5a0321cd4f | ||
|
|
b9d212ed58 | ||
|
|
83f2a81e91 | ||
|
|
3f20fe75c6 |
44
.gitattributes
vendored
@@ -1,5 +1,49 @@
|
||||
# Configuration file for Git attributes
|
||||
|
||||
# Core Settings {{{
|
||||
# .gitattributes
|
||||
.gitattributes !filter !diff
|
||||
|
||||
# Line Endings
|
||||
* text=auto
|
||||
|
||||
# Set binary to none-text files
|
||||
*.png -text
|
||||
|
||||
# }}}
|
||||
|
||||
|
||||
# GitHub Linguist {{{
|
||||
|
||||
# Exclude files/folder from being detected by the GitHub linguist
|
||||
# statistic.
|
||||
node_modules/* linguist-vendored
|
||||
public/* linguist-generated=true
|
||||
vendor/* linguist-vendored
|
||||
|
||||
# Remove Vue as it's currently not used in the project.
|
||||
resources/assets/js/components/ExampleComponent.vue linguist-vendored
|
||||
|
||||
# System Wide
|
||||
*.css linguist-vendored
|
||||
*.scss linguist-vendored
|
||||
*.js linguist-vendored
|
||||
|
||||
# Include user generated files that's removed bu the setting above.
|
||||
resources/assets/js/app.js linguist-vendored=false
|
||||
resources/assets/sass/_app.scss linguist-vendored=false
|
||||
resources/assets/sass/_rune.scss linguist-vendored=false
|
||||
resources/assets/sass/_variables.scss linguist-vendored=false
|
||||
|
||||
# }}}
|
||||
|
||||
|
||||
# Archive Exlude {{{
|
||||
# Exclude files/folders from being exported when creating an archive.
|
||||
|
||||
.gitattributes export-ignore
|
||||
.gitignore export-ignore
|
||||
.travis.yml export-ignore
|
||||
CHANGELOG.md export-ignore
|
||||
|
||||
# }}}
|
||||
|
||||
16
.gitignore
vendored
@@ -8,3 +8,19 @@ Homestead.json
|
||||
Homestead.yaml
|
||||
npm-debug.log
|
||||
yarn-error.log
|
||||
|
||||
### macOS ###
|
||||
*.DS_Store
|
||||
.AppleDouble
|
||||
.LSOverride
|
||||
|
||||
# Thumbnails
|
||||
._*
|
||||
|
||||
# Files that might appear in the root of a volume
|
||||
.DocumentRevisions-V100
|
||||
.fseventsd
|
||||
.Spotlight-V100
|
||||
.TemporaryItems
|
||||
.Trashes
|
||||
.VolumeIcon.icns
|
||||
61
CHANGELOG.md
@@ -1,5 +1,66 @@
|
||||
# Release Notes
|
||||
|
||||
## v1.4.0 (2018-02-18)
|
||||
|
||||
### Added
|
||||
- Tag(folder) support
|
||||
- Image preview for uploading icons
|
||||
- A load of supported apps, full list of apps https://github.com/linuxserver/Heimdall/projects/1
|
||||
|
||||
### Changed
|
||||
- Edited vendor/laravelcollective/html/src/FormBuilder.php to allow relative links #3369de9
|
||||
- Changed links to use relative links for reverse proxy support
|
||||
- Links open in new tab
|
||||
|
||||
### Fixed
|
||||
- adds all the fixes in the 1.3.x point releases and on master
|
||||
|
||||
## v1.3.0 (2018-02-09)
|
||||
|
||||
### Added
|
||||
- guzzlehttp/guzzle as a dependency
|
||||
- Variable polling, so interval is increased when an app is idle and decreased when it's active
|
||||
- Turkish language translation
|
||||
- Added Sabnzbd enhanced application
|
||||
|
||||
### Changed
|
||||
- Updated composer dependencies
|
||||
- Added live stats to Nzbget supported application
|
||||
- Changed Pihole to an enhanced application
|
||||
- Changed NZBGet to an enhanced application
|
||||
|
||||
### Fixed
|
||||
- Fixed autocomplete being hard to see
|
||||
- Fixed checkboxes not working on edge
|
||||
|
||||
|
||||
## v1.2.0 (2018-02-07)
|
||||
|
||||
### Added
|
||||
- Translation support
|
||||
- Initial "Supported" application support
|
||||
- Finnish translation
|
||||
- Swedish translation
|
||||
- German translation
|
||||
- French translation
|
||||
- Spanish translation
|
||||
- Duplicati supported application
|
||||
- Emby supported application
|
||||
- Nzbget supported application
|
||||
- Pfsense supported application
|
||||
- Pihole supported application
|
||||
- Plex supported application
|
||||
- Portainer supported application
|
||||
- Unifi supported application
|
||||
|
||||
### Changed
|
||||
- button layout and behaviour
|
||||
|
||||
### Fixed
|
||||
- Bottom of button too short in some browsers
|
||||
- Icon not loading back in when required fields not filled in
|
||||
|
||||
|
||||
## v1.1.0 (2018-02-05)
|
||||
|
||||
### Added
|
||||
|
||||
36
app/Helper.php
Normal file
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
function format_bytes($bytes, $is_drive_size = true, $beforeunit = '', $afterunit = '')
|
||||
{
|
||||
$btype = ($is_drive_size === true) ? 1000 : 1024;
|
||||
$labels = array('B','KB','MB','GB','TB');
|
||||
for($x = 0; $bytes >= $btype && $x < (count($labels) - 1); $bytes /= $btype, $x++); // use 1000 rather than 1024 to simulate HD size not real size
|
||||
if($labels[$x] == "TB") return(round($bytes, 3).$beforeunit.$labels[$x].$afterunit);
|
||||
elseif($labels[$x] == "GB") return(round($bytes, 2).$beforeunit.$labels[$x].$afterunit);
|
||||
elseif($labels[$x] == "MB") return(round($bytes, 2).$beforeunit.$labels[$x].$afterunit);
|
||||
else return(round($bytes, 0).$beforeunit.$labels[$x].$afterunit);
|
||||
}
|
||||
|
||||
function get_brightness($hex) {
|
||||
// returns brightness value from 0 to 255
|
||||
// strip off any leading #
|
||||
$hex = str_replace('#', '', $hex);
|
||||
if(strlen($hex) == 3) {
|
||||
$hex = $hex[0].$hex[0].$hex[1].$hex[1].$hex[2].$hex[2];
|
||||
}
|
||||
|
||||
$c_r = hexdec(substr($hex, 0, 2));
|
||||
$c_g = hexdec(substr($hex, 2, 2));
|
||||
$c_b = hexdec(substr($hex, 4, 2));
|
||||
|
||||
return (($c_r * 299) + ($c_g * 587) + ($c_b * 114)) / 1000;
|
||||
}
|
||||
|
||||
function title_color($hex)
|
||||
{
|
||||
if(get_brightness($hex) > 130) {
|
||||
return ' black';
|
||||
} else {
|
||||
return ' white';
|
||||
}
|
||||
}
|
||||
@@ -18,8 +18,8 @@ class ItemController extends Controller
|
||||
*/
|
||||
public function dash()
|
||||
{
|
||||
$data['apps'] = Item::pinned()->orderBy('order', 'asc')->get();
|
||||
$data['all_apps'] = Item::all();
|
||||
$data['apps'] = Item::doesntHave('parents')->pinned()->orderBy('order', 'asc')->get();
|
||||
$data['all_apps'] = Item::doesntHave('parents')->get();
|
||||
return view('welcome', $data);
|
||||
}
|
||||
|
||||
@@ -49,7 +49,8 @@ class ItemController extends Controller
|
||||
$item = Item::findOrFail($id);
|
||||
$item->pinned = true;
|
||||
$item->save();
|
||||
return redirect()->route('dash');
|
||||
$route = route('dash', [], false);
|
||||
return redirect($route);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -62,7 +63,8 @@ class ItemController extends Controller
|
||||
$item = Item::findOrFail($id);
|
||||
$item->pinned = false;
|
||||
$item->save();
|
||||
return redirect()->route('dash');
|
||||
$route = route('dash', [], false);
|
||||
return redirect($route);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -81,8 +83,9 @@ class ItemController extends Controller
|
||||
$data['ajax'] = true;
|
||||
return view('sortable', $data);
|
||||
} else {
|
||||
return redirect()->route('dash');
|
||||
}
|
||||
$route = route('dash', [], false);
|
||||
return redirect($route);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -95,8 +98,8 @@ class ItemController extends Controller
|
||||
{
|
||||
$trash = (bool)$request->input('trash');
|
||||
|
||||
$data['apps'] = Item::orderBy('title', 'asc')->get();
|
||||
$data['trash'] = Item::onlyTrashed()->get();
|
||||
$data['apps'] = Item::ofType('item')->orderBy('title', 'asc')->get();
|
||||
$data['trash'] = Item::ofType('item')->onlyTrashed()->get();
|
||||
if($trash) {
|
||||
return view('items.trash', $data);
|
||||
} else {
|
||||
@@ -113,7 +116,8 @@ class ItemController extends Controller
|
||||
public function create()
|
||||
{
|
||||
//
|
||||
$data = [];
|
||||
$data['tags'] = Item::ofType('tag')->orderBy('title', 'asc')->pluck('title', 'id');
|
||||
$data['current_tags'] = [];
|
||||
return view('items.create', $data);
|
||||
|
||||
}
|
||||
@@ -129,7 +133,7 @@ class ItemController extends Controller
|
||||
//
|
||||
$validatedData = $request->validate([
|
||||
'title' => 'required|max:255',
|
||||
'url' => 'required',
|
||||
'url' => 'required|url',
|
||||
]);
|
||||
|
||||
if($request->hasFile('file')) {
|
||||
@@ -138,11 +142,21 @@ class ItemController extends Controller
|
||||
'icon' => $path
|
||||
]);
|
||||
}
|
||||
|
||||
Item::create($request->all());
|
||||
|
||||
return redirect()->route('dash')
|
||||
->with('success','Item created successfully');
|
||||
$config = Item::checkConfig($request->input('config'));
|
||||
$request->merge([
|
||||
'description' => $config
|
||||
]);
|
||||
|
||||
//die(print_r($request->input('config')));
|
||||
|
||||
$item = Item::create($request->all());
|
||||
|
||||
$item->parents()->sync($request->tags);
|
||||
|
||||
$route = route('dash', [], false);
|
||||
return redirect($route)
|
||||
->with('success', __('app.alert.success.item_created'));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -165,11 +179,12 @@ class ItemController extends Controller
|
||||
public function edit($id)
|
||||
{
|
||||
// Get the item
|
||||
$item = Item::find($id);
|
||||
$data['item'] = Item::find($id);
|
||||
$data['tags'] = Item::ofType('tag')->orderBy('title', 'asc')->pluck('title', 'id');
|
||||
$data['current_tags'] = $data['item']->parents;
|
||||
|
||||
// show the edit form and pass the nerd
|
||||
return view('items.edit')
|
||||
->with('item', $item);
|
||||
return view('items.edit', $data);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -183,9 +198,9 @@ class ItemController extends Controller
|
||||
{
|
||||
$validatedData = $request->validate([
|
||||
'title' => 'required|max:255',
|
||||
'url' => 'required',
|
||||
'url' => 'required|url',
|
||||
]);
|
||||
|
||||
//die(print_r($request->all()));
|
||||
if($request->hasFile('file')) {
|
||||
$path = $request->file('file')->store('icons');
|
||||
$request->merge([
|
||||
@@ -193,11 +208,19 @@ class ItemController extends Controller
|
||||
]);
|
||||
}
|
||||
|
||||
$config = Item::checkConfig($request->input('config'));
|
||||
$request->merge([
|
||||
'description' => $config
|
||||
]);
|
||||
|
||||
Item::find($id)->update($request->all());
|
||||
$item = Item::find($id);
|
||||
$item->update($request->all());
|
||||
|
||||
return redirect()->route('dash')
|
||||
->with('success','Item updated successfully');
|
||||
$item->parents()->sync($request->tags);
|
||||
|
||||
$route = route('dash', [], false);
|
||||
return redirect($route)
|
||||
->with('success',__('app.alert.success.item_updated'));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -217,9 +240,10 @@ class ItemController extends Controller
|
||||
} else {
|
||||
Item::find($id)->delete();
|
||||
}
|
||||
|
||||
return redirect()->route('items.index')
|
||||
->with('success','Item deleted successfully');
|
||||
|
||||
$route = route('items.index', [], false);
|
||||
return redirect($route)
|
||||
->with('success',__('app.alert.success.item_deleted'));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -233,8 +257,77 @@ class ItemController extends Controller
|
||||
//
|
||||
Item::withTrashed()
|
||||
->where('id', $id)
|
||||
->restore();
|
||||
return redirect()->route('items.index')
|
||||
->with('success','Item restored successfully');
|
||||
->restore();
|
||||
|
||||
$route = route('items.inded', [], false);
|
||||
return redirect($route)
|
||||
->with('success',__('app.alert.success.item_restored'));
|
||||
}
|
||||
|
||||
public function isSupportedAppByKey($app)
|
||||
{
|
||||
$output = false;
|
||||
$all_supported = Item::supportedList();
|
||||
if(array_key_exists($app, $all_supported)) {
|
||||
$output = new $all_supported[$app];
|
||||
}
|
||||
return $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return details for supported apps
|
||||
*
|
||||
* @return Json
|
||||
*/
|
||||
public function appload(Request $request)
|
||||
{
|
||||
$output = [];
|
||||
$app = $request->input('app');
|
||||
|
||||
if(($app_details = $this->isSupportedAppByKey($app)) !== false) {
|
||||
// basic details
|
||||
$output['icon'] = $app_details->icon();
|
||||
$output['colour'] = $app_details->defaultColour();
|
||||
|
||||
// live details
|
||||
if($app_details instanceof \App\SupportedApps\Contracts\Livestats) {
|
||||
$output['config'] = $app_details->configDetails();
|
||||
} else {
|
||||
$output['config'] = null;
|
||||
}
|
||||
}
|
||||
|
||||
return json_encode($output);
|
||||
}
|
||||
|
||||
public function testConfig(Request $request)
|
||||
{
|
||||
$data = $request->input('data');
|
||||
//$url = $data[array_search('url', array_column($data, 'name'))]['value'];
|
||||
|
||||
$app = $data['type'];
|
||||
|
||||
$app_details = new $app();
|
||||
$app_details->config = (object)$data;
|
||||
$app_details->testConfig();
|
||||
}
|
||||
|
||||
public function getStats($id)
|
||||
{
|
||||
$item = Item::find($id);
|
||||
|
||||
$config = json_decode($item->description);
|
||||
if(isset($config->type)) {
|
||||
$config->url = $item->url;
|
||||
if(isset($config->override_url) && !empty($config->override_url)) {
|
||||
$config->url = $config->override_url;
|
||||
}
|
||||
$app_details = new $config->type;
|
||||
$app_details->config = $config;
|
||||
echo $app_details->executeConfig();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -39,8 +39,10 @@ class SettingsController extends Controller
|
||||
'setting' => $setting,
|
||||
]);
|
||||
} else {
|
||||
return redirect()->route('settings.list')->with([
|
||||
'error' => 'This Setting does not exist.',
|
||||
$route = route('settings.list', [], false);
|
||||
return redirect($route)
|
||||
->with([
|
||||
'error' => __('app.alert.error.not_exist'),
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -73,12 +75,16 @@ class SettingsController extends Controller
|
||||
|
||||
$setting->save();
|
||||
|
||||
return redirect()->route('settings.index')->with([
|
||||
'success' => 'You have successfully edited this Setting!',
|
||||
$route = route('settings.index', [], false);
|
||||
return redirect($route)
|
||||
->with([
|
||||
'success' => __('app.alert.success.setting_updated'),
|
||||
]);
|
||||
} else {
|
||||
return redirect()->route('settings.index')->with([
|
||||
'error' => 'This Setting does not exist.',
|
||||
$route = route('settings.index', [], false);
|
||||
return redirect($route)
|
||||
->with([
|
||||
'error' => __('app.alert.error.not_exist'),
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -94,8 +100,10 @@ class SettingsController extends Controller
|
||||
$setting->value = '';
|
||||
$setting->save();
|
||||
}
|
||||
return redirect()->route('settings.index')->with([
|
||||
'success' => 'You have successfully edited this Setting!',
|
||||
$route = route('settings.index', [], false);
|
||||
return redirect($route)
|
||||
->with([
|
||||
'success' => __('app.alert.success.setting_updated'),
|
||||
]);
|
||||
|
||||
}
|
||||
|
||||
193
app/Http/Controllers/TagController.php
Normal file
@@ -0,0 +1,193 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use App\Item;
|
||||
use DB;
|
||||
|
||||
class TagController extends Controller
|
||||
{
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function index(Request $request)
|
||||
{
|
||||
$trash = (bool)$request->input('trash');
|
||||
|
||||
$data['apps'] = Item::ofType('tag')->orderBy('title', 'asc')->get();
|
||||
$data['trash'] = Item::ofType('tag')->onlyTrashed()->get();
|
||||
if($trash) {
|
||||
return view('tags.trash', $data);
|
||||
} else {
|
||||
return view('tags.list', $data);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for creating a new resource.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function create()
|
||||
{
|
||||
$data = [];
|
||||
return view('tags.create', $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function store(Request $request)
|
||||
{
|
||||
$validatedData = $request->validate([
|
||||
'title' => 'required|max:255',
|
||||
]);
|
||||
|
||||
if($request->hasFile('file')) {
|
||||
$path = $request->file('file')->store('icons');
|
||||
$request->merge([
|
||||
'icon' => $path
|
||||
]);
|
||||
}
|
||||
|
||||
$slug = str_slug($request->title, '-');
|
||||
|
||||
// set item type to tag
|
||||
$request->merge([
|
||||
'type' => '1',
|
||||
'url' => $slug
|
||||
]);
|
||||
//die(print_r($request->all()));
|
||||
Item::create($request->all());
|
||||
|
||||
$route = route('dash', [], false);
|
||||
return redirect($route)
|
||||
->with('success', __('app.alert.success.tag_created'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the specified resource.
|
||||
*
|
||||
* @param int $id
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function show($slug)
|
||||
{
|
||||
$item = Item::whereUrl($slug)->first();
|
||||
//print_r($item);
|
||||
$data['apps'] = $item->children()->pinned()->orderBy('order', 'asc')->get();
|
||||
$data['all_apps'] = $item->children;
|
||||
return view('welcome', $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for editing the specified resource.
|
||||
*
|
||||
* @param int $id
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function edit($id)
|
||||
{
|
||||
// Get the item
|
||||
$item = Item::find($id);
|
||||
|
||||
// show the edit form and pass the nerd
|
||||
return view('tags.edit')
|
||||
->with('item', $item);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param int $id
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function update(Request $request, $id)
|
||||
{
|
||||
$validatedData = $request->validate([
|
||||
'title' => 'required|max:255',
|
||||
]);
|
||||
|
||||
if($request->hasFile('file')) {
|
||||
$path = $request->file('file')->store('icons');
|
||||
$request->merge([
|
||||
'icon' => $path
|
||||
]);
|
||||
}
|
||||
|
||||
$slug = str_slug($request->title, '-');
|
||||
// set item type to tag
|
||||
$request->merge([
|
||||
'url' => $slug
|
||||
]);
|
||||
|
||||
Item::find($id)->update($request->all());
|
||||
|
||||
$route = route('dash', [], false);
|
||||
return redirect($route)
|
||||
->with('success',__('app.alert.success.tag_updated'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*
|
||||
* @param int $id
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function destroy(Request $request, $id)
|
||||
{
|
||||
//
|
||||
$force = (bool)$request->input('force');
|
||||
if($force) {
|
||||
Item::withTrashed()
|
||||
->where('id', $id)
|
||||
->forceDelete();
|
||||
} else {
|
||||
Item::find($id)->delete();
|
||||
}
|
||||
|
||||
$route = route('tags.index', [], false);
|
||||
return redirect($route)
|
||||
->with('success',__('app.alert.success.item_deleted'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore the specified resource from soft deletion.
|
||||
*
|
||||
* @param int $id
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function restore($id)
|
||||
{
|
||||
//
|
||||
Item::withTrashed()
|
||||
->where('id', $id)
|
||||
->restore();
|
||||
$route = route('tags.index', [], false);
|
||||
return redirect($route)
|
||||
->with('success',__('app.alert.success.item_restored'));
|
||||
}
|
||||
|
||||
public function add($tag, $item)
|
||||
{
|
||||
$output = 0;
|
||||
$tag = Item::find($tag);
|
||||
$item = Item::find($item);
|
||||
if($tag && $item) {
|
||||
// only add items, not cats
|
||||
if((int)$item->type === 0) {
|
||||
$tag->children()->attach($item);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return $output;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -13,6 +13,9 @@ class VerifyCsrfToken extends Middleware
|
||||
*/
|
||||
protected $except = [
|
||||
//
|
||||
'order'
|
||||
'order',
|
||||
'appload',
|
||||
'test_config',
|
||||
//'get_stats'
|
||||
];
|
||||
}
|
||||
|
||||
174
app/Item.php
@@ -13,7 +13,7 @@ class Item extends Model
|
||||
|
||||
//
|
||||
protected $fillable = [
|
||||
'title', 'url', 'colour', 'icon', 'description', 'pinned', 'order'
|
||||
'title', 'url', 'colour', 'icon', 'description', 'pinned', 'order', 'type'
|
||||
];
|
||||
|
||||
/**
|
||||
@@ -26,8 +26,63 @@ class Item extends Model
|
||||
public static function supportedList()
|
||||
{
|
||||
return [
|
||||
'NZBGet' => App\SupportedApps\Nzbget::class,
|
||||
'Plex' => App\SupportedApps\Plex::class,
|
||||
'AirSonic' => \App\SupportedApps\AirSonic::class,
|
||||
'Cardigann' => \App\SupportedApps\Cardigann::class,
|
||||
'CouchPotato' => \App\SupportedApps\CouchPotato::class,
|
||||
'Booksonic' => \App\SupportedApps\Booksonic::class,
|
||||
'Deluge' => \App\SupportedApps\Deluge::class,
|
||||
'Dokuwiki' => \App\SupportedApps\Dokuwiki::class,
|
||||
'Duplicati' => \App\SupportedApps\Duplicati::class,
|
||||
'Emby' => \App\SupportedApps\Emby::class,
|
||||
'Flood' => \App\SupportedApps\Flood::class,
|
||||
'Gitea' => \App\SupportedApps\Gitea::class,
|
||||
'Glances' => \App\SupportedApps\Glances::class,
|
||||
'Grafana' => \App\SupportedApps\Grafana::class,
|
||||
'Graylog' => \App\SupportedApps\Graylog::class,
|
||||
'Headphones' => \App\SupportedApps\Headphones::class,
|
||||
'Home Assistant' => \App\SupportedApps\HomeAssistant::class,
|
||||
'Jackett' => \App\SupportedApps\Jackett::class,
|
||||
'Jdownloader' => \App\SupportedApps\Jdownloader::class,
|
||||
'Krusader' => \App\SupportedApps\Krusader::class,
|
||||
'LibreNMS' => \App\SupportedApps\LibreNMS::class,
|
||||
'Lidarr' => \App\SupportedApps\Lidarr::class,
|
||||
'Mcmyadmin' => \App\SupportedApps\Mcmyadmin::class,
|
||||
'Medusa' => \App\SupportedApps\Medusa::class,
|
||||
'MusicBrainz' => \App\SupportedApps\MusicBrainz::class,
|
||||
'Mylar' => \App\SupportedApps\Mylar::class,
|
||||
'NZBGet' => \App\SupportedApps\Nzbget::class,
|
||||
'Netdata' => \App\SupportedApps\Netdata::class,
|
||||
'Nextcloud' => \App\SupportedApps\Nextcloud::class,
|
||||
'Now Showing' => \App\SupportedApps\NowShowing::class,
|
||||
'Nzbhydra' => \App\SupportedApps\Nzbhydra::class,
|
||||
'OPNSense' => \App\SupportedApps\Opnsense::class,
|
||||
'Ombi' => \App\SupportedApps\Ombi::class,
|
||||
'Openhab' => \App\SupportedApps\Openhab::class,
|
||||
'OpenMediaVault' => \App\SupportedApps\OpenMediaVault::class,
|
||||
'Pihole' => \App\SupportedApps\Pihole::class,
|
||||
'Plex' => \App\SupportedApps\Plex::class,
|
||||
'Plexpy' => \App\SupportedApps\Plexpy::class,
|
||||
'Plexrequests' => \App\SupportedApps\Plexrequests::class,
|
||||
'Portainer' => \App\SupportedApps\Portainer::class,
|
||||
'Proxmox' => \App\SupportedApps\Proxmox::class,
|
||||
'Radarr' => \App\SupportedApps\Radarr::class,
|
||||
'Rancher' => \App\SupportedApps\Rancher::class,
|
||||
'Runeaudio' => \App\SupportedApps\Runeaudio::class,
|
||||
'Sabnzbd' => \App\SupportedApps\Sabnzbd::class,
|
||||
'Sickrage' => \App\SupportedApps\Sickrage::class,
|
||||
'Sonarr' => \App\SupportedApps\Sonarr::class,
|
||||
'Syncthing' => \App\SupportedApps\Syncthing::class,
|
||||
'Tautulli' => \App\SupportedApps\Tautulli::class,
|
||||
'Transmission' => \App\SupportedApps\Transmission::class,
|
||||
'Traefik' => \App\SupportedApps\Traefik::class,
|
||||
'tt-rss' => \App\SupportedApps\Ttrss::class,
|
||||
'UniFi' => \App\SupportedApps\Unifi::class,
|
||||
'unRAID' => \App\SupportedApps\Unraid::class,
|
||||
'pfSense' => \App\SupportedApps\Pfsense::class,
|
||||
'pyLoad' => \App\SupportedApps\pyLoad::class,
|
||||
'ruTorrent' => \App\SupportedApps\ruTorrent::class,
|
||||
'Watcher3' => \App\SupportedApps\Watcher3::class,
|
||||
'WebTools' => \App\SupportedApps\WebTools::class,
|
||||
];
|
||||
}
|
||||
public static function supportedOptions()
|
||||
@@ -45,4 +100,117 @@ class Item extends Model
|
||||
{
|
||||
return $query->where('pinned', 1);
|
||||
}
|
||||
|
||||
public function getConfigAttribute()
|
||||
{
|
||||
$output = null;
|
||||
$view = null;
|
||||
if(isset($this->description) && !empty($this->description)){
|
||||
$output = json_decode($this->description);
|
||||
$output = is_object($output) ? $output : new \stdClass();
|
||||
if(isset($output->type) && !empty($output->type)) {
|
||||
$class = $output->type;
|
||||
$sap = new $class();
|
||||
$view = $sap->configDetails();
|
||||
$output->view = $view;
|
||||
}
|
||||
if(!isset($output->dataonly)) $output->dataonly = '0';
|
||||
|
||||
}
|
||||
return (object)$output;
|
||||
}
|
||||
public static function checkConfig($config)
|
||||
{
|
||||
if(empty($config)) {
|
||||
$config = null;
|
||||
} else {
|
||||
$store = false;
|
||||
//die(var_dump($config));
|
||||
foreach($config as $key => $check) {
|
||||
if($key == 'type') continue;
|
||||
if($key == 'dataonly') continue;
|
||||
if(!empty($check) && $check != '0') {
|
||||
$store = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
//die(var_dump($store))
|
||||
|
||||
$config['enabled'] = ($store) ? true : false;
|
||||
$config = json_encode($config);
|
||||
}
|
||||
return $config;
|
||||
|
||||
}
|
||||
|
||||
public function parents()
|
||||
{
|
||||
return $this->belongsToMany('App\Item', 'item_tag', 'item_id', 'tag_id');
|
||||
}
|
||||
public function children()
|
||||
{
|
||||
return $this->belongsToMany('App\Item', 'item_tag', 'tag_id', 'item_id');
|
||||
}
|
||||
|
||||
public function getLinkAttribute()
|
||||
{
|
||||
if((int)$this->type === 1) {
|
||||
return '/tag/'.$this->url;
|
||||
} else {
|
||||
return $this->url;
|
||||
}
|
||||
}
|
||||
|
||||
public function getDroppableAttribute()
|
||||
{
|
||||
if((int)$this->type === 1) {
|
||||
return ' droppable';
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
public function getLinkTargetAttribute()
|
||||
{
|
||||
$target = Setting::fetch('window_target');
|
||||
|
||||
if((int)$this->type === 1 || $target === 'current') {
|
||||
return '';
|
||||
} else {
|
||||
return ' target="' . $target . '"';
|
||||
}
|
||||
}
|
||||
|
||||
public function getLinkIconAttribute()
|
||||
{
|
||||
if((int)$this->type === 1) {
|
||||
return 'fa-tag';
|
||||
} else {
|
||||
return 'fa-arrow-alt-to-right';
|
||||
}
|
||||
}
|
||||
public function getLinkTypeAttribute()
|
||||
{
|
||||
if((int)$this->type === 1) {
|
||||
return 'tags';
|
||||
} else {
|
||||
return 'items';
|
||||
}
|
||||
}
|
||||
|
||||
public function scopeOfType($query, $type)
|
||||
{
|
||||
switch($type) {
|
||||
case 'item':
|
||||
$typeid = 0;
|
||||
break;
|
||||
case 'tag':
|
||||
$typeid = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
return $query->where('type', $typeid);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -26,7 +26,6 @@ class AppServiceProvider extends ServiceProvider
|
||||
// first time setup
|
||||
touch(database_path('app.sqlite'));
|
||||
Artisan::call('migrate', array('--path' => 'database/migrations', '--force' => true, '--seed' => true));
|
||||
Artisan::call('storage:link');
|
||||
//Cache
|
||||
//Artisan::call('config:cache');
|
||||
//Artisan::call('route:cache');
|
||||
@@ -34,7 +33,7 @@ class AppServiceProvider extends ServiceProvider
|
||||
if(is_file(database_path('app.sqlite'))) {
|
||||
if(Schema::hasTable('settings')) {
|
||||
if($bg_image = Setting::fetch('background_image')) {
|
||||
$alt_bg = ' style="background-image: url('.asset('storage/'.$bg_image).')"';
|
||||
$alt_bg = ' style="background-image: url(/storage/'.$bg_image.')"';
|
||||
}
|
||||
|
||||
// check version to see if an upgrade is needed
|
||||
@@ -46,6 +45,12 @@ class AppServiceProvider extends ServiceProvider
|
||||
} else {
|
||||
Artisan::call('migrate', array('--path' => 'database/migrations', '--force' => true, '--seed' => true));
|
||||
}
|
||||
$lang = Setting::fetch('language');
|
||||
\App::setLocale($lang);
|
||||
|
||||
}
|
||||
if(!is_file(public_path('storage'))) {
|
||||
Artisan::call('storage:link');
|
||||
}
|
||||
view()->share('alt_bg', $alt_bg);
|
||||
|
||||
|
||||
@@ -15,6 +15,10 @@ class Setting extends Model
|
||||
*/
|
||||
protected $table = 'settings';
|
||||
|
||||
protected $fillable = [
|
||||
'id', 'group_id', 'key', 'type', 'options', 'label', 'value', 'order', 'system'
|
||||
];
|
||||
|
||||
/**
|
||||
* Tell the Model this Table doesn't support timestamps.
|
||||
*
|
||||
@@ -45,28 +49,28 @@ class Setting extends Model
|
||||
switch($this->type) {
|
||||
case 'image':
|
||||
if(!empty($this->value)) {
|
||||
$value = '<a href="'.asset('storage/'.$this->value).'" title="View" target="_blank">View</a>';
|
||||
$value = '<a href="'.asset('storage/'.$this->value).'" title="'.__('app.settings.view').'" target="_blank">'.__('app.settings.view').'</a>';
|
||||
} else {
|
||||
$value = '- not set -';
|
||||
$value = __('app.options.none');
|
||||
}
|
||||
break;
|
||||
case 'boolean':
|
||||
if((bool)$this->value === true) {
|
||||
$value = 'Yes';
|
||||
$value = __('app.options.yes');
|
||||
} else {
|
||||
$value = 'No';
|
||||
$value = __('app.options.no');
|
||||
}
|
||||
break;
|
||||
case 'select':
|
||||
if(!empty($this->value) && $this->value !== 'none') {
|
||||
$options = (array)json_decode($this->options);
|
||||
$value = $options[$this->value];
|
||||
$value = __($options[$this->value]);
|
||||
} else {
|
||||
$value = '- not set -';
|
||||
$value = __('app.options.none');
|
||||
}
|
||||
break;
|
||||
default:
|
||||
$value = $this->value;
|
||||
$value = __($this->value);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -80,11 +84,11 @@ class Setting extends Model
|
||||
case 'image':
|
||||
$value = '';
|
||||
if(isset($this->value) && !empty($this->value)) {
|
||||
$value .= '<a class="setting-view-image" href="'.asset('storage/'.$this->value).'" title="View" target="_blank"><img src="'.asset('storage/'.$this->value).'" /></a>';
|
||||
$value .= '<a class="setting-view-image" href="'.asset('storage/'.$this->value).'" title="'.__('app.settings.view').'" target="_blank"><img src="'.asset('storage/'.$this->value).'" /></a>';
|
||||
}
|
||||
$value .= Form::file('value', ['class' => 'form-control']);
|
||||
if(isset($this->value) && !empty($this->value)) {
|
||||
$value .= '<a class="settinglink" href="'.route('settings.clear', $this->id).'" title="Remove">Reset back to default</a>';
|
||||
$value .= '<a class="settinglink" href="'.route('settings.clear', $this->id).'" title="'.__('app.settings.remove').'">'.__('app.settings.reset').'</a>';
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -93,8 +97,8 @@ class Setting extends Model
|
||||
if(isset($this->value) && (bool)$this->value === true) $checked = true;
|
||||
$set_checked = ($checked) ? ' checked="checked"' : '';
|
||||
$value = '
|
||||
<input type="hidden" name="value" value="0" />
|
||||
<label class="switch">
|
||||
<input type="hidden" name="value" value="0" />
|
||||
<input type="checkbox" name="value" value="1"'.$set_checked.' />
|
||||
<span class="slider round"></span>
|
||||
</label>';
|
||||
@@ -102,6 +106,9 @@ class Setting extends Model
|
||||
break;
|
||||
case 'select':
|
||||
$options = json_decode($this->options);
|
||||
foreach($options as $key => $opt) {
|
||||
$options->$key = __($opt);
|
||||
}
|
||||
$value = Form::select('value', $options, null, ['class' => 'form-control']);
|
||||
break;
|
||||
default:
|
||||
@@ -195,12 +202,15 @@ class Setting extends Model
|
||||
$url = 'https://www.bing.com/search';
|
||||
$var = 'q';
|
||||
break;
|
||||
case 'startpage':
|
||||
$url = 'https://www.startpage.com/';
|
||||
$var = 'q';
|
||||
}
|
||||
$output .= '<div class="searchform">';
|
||||
$output .= Form::open(['url' => $url, 'method' => 'get']);
|
||||
$output .= '<div class="input-container">';
|
||||
$output .= Form::text($var, null, ['class' => 'homesearch', 'placeholder' => $name.' search...']);
|
||||
$output .= '<button type="submit">Search</button>';
|
||||
$output .= Form::text($var, null, ['class' => 'homesearch', 'autofocus' => 'autofocus', 'placeholder' => __($name).' '.__('app.settings.search').'...']);
|
||||
$output .= '<button type="submit">'.ucwords(__('app.settings.search')).'</button>';
|
||||
$output .= '</div>';
|
||||
$output .= Form::close();
|
||||
$output .= '</div>';
|
||||
|
||||
11
app/SupportedApps/AirSonic.php
Normal file
@@ -0,0 +1,11 @@
|
||||
<?php namespace App\SupportedApps;
|
||||
class AirSonic implements Contracts\Applications {
|
||||
public function defaultColour()
|
||||
{
|
||||
return '#08F';
|
||||
}
|
||||
public function icon()
|
||||
{
|
||||
return 'supportedapps/airsonic.png';
|
||||
}
|
||||
}
|
||||
12
app/SupportedApps/Booksonic.php
Normal file
@@ -0,0 +1,12 @@
|
||||
<?php namespace App\SupportedApps;
|
||||
|
||||
class Booksonic implements Contracts\Applications {
|
||||
public function defaultColour()
|
||||
{
|
||||
return '#58a';
|
||||
}
|
||||
public function icon()
|
||||
{
|
||||
return 'supportedapps/booksonic.png';
|
||||
}
|
||||
}
|
||||
11
app/SupportedApps/Cardigann.php
Normal file
@@ -0,0 +1,11 @@
|
||||
<?php namespace App\SupportedApps;
|
||||
class Cardigann implements Contracts\Applications {
|
||||
public function defaultColour()
|
||||
{
|
||||
return '#753';
|
||||
}
|
||||
public function icon()
|
||||
{
|
||||
return 'supportedapps/cardigann.png';
|
||||
}
|
||||
}
|
||||
@@ -3,5 +3,7 @@
|
||||
interface Applications {
|
||||
|
||||
public function defaultColour();
|
||||
|
||||
public function icon();
|
||||
|
||||
}
|
||||
11
app/SupportedApps/Contracts/Livestats.php
Normal file
@@ -0,0 +1,11 @@
|
||||
<?php namespace App\SupportedApps\Contracts;
|
||||
|
||||
interface Livestats {
|
||||
|
||||
public function configDetails();
|
||||
|
||||
public function testConfig();
|
||||
|
||||
public function executeConfig();
|
||||
|
||||
}
|
||||
122
app/SupportedApps/CouchPotato.php
Normal file
@@ -0,0 +1,122 @@
|
||||
<?php namespace App\SupportedApps;
|
||||
|
||||
use GuzzleHttp\Exception\GuzzleException;
|
||||
use GuzzleHttp\Client;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class CouchPotato implements Contracts\Applications, Contracts\Livestats
|
||||
{
|
||||
|
||||
private $_client;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->_client = new Client(
|
||||
['http_errors' => false,
|
||||
'timeout' => 10]
|
||||
);
|
||||
}
|
||||
|
||||
public function defaultColour()
|
||||
{
|
||||
return '#363840';
|
||||
}
|
||||
public function icon()
|
||||
{
|
||||
return 'supportedapps/couchpotato.png';
|
||||
}
|
||||
public function configDetails()
|
||||
{
|
||||
return 'couchpotato';
|
||||
}
|
||||
public function testConfig()
|
||||
{
|
||||
$res = $this->sendRequest();
|
||||
if ($res == null) {
|
||||
echo 'CouchPotato connection failed';
|
||||
return;
|
||||
}
|
||||
switch($res->getStatusCode()) {
|
||||
case 200:
|
||||
echo "Successfully connected to CouchPotato";
|
||||
break;
|
||||
case 401:
|
||||
echo 'Failed: Invalid credentials';
|
||||
break;
|
||||
case 404:
|
||||
echo 'Failed: Please make sure your URL is correct and includes the port';
|
||||
break;
|
||||
case 409:
|
||||
echo 'Failed: Incorrect session id';
|
||||
break;
|
||||
default:
|
||||
echo 'Something went wrong... Code: '.$res->getStatusCode();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public function executeConfig()
|
||||
{
|
||||
$html = '';
|
||||
$res = $this->sendRequest();
|
||||
if ($res == null) {
|
||||
Log::debug('CouchPotato connection failed');
|
||||
return '';
|
||||
}
|
||||
$data = json_decode($res->getBody());
|
||||
if (! isset($data->movies)) {
|
||||
Log::debug('Failed to fetch data from CouchPotato');
|
||||
return '';
|
||||
}
|
||||
$movies = $data->movies;
|
||||
$wantedMovies = $availableMovies = 0;
|
||||
foreach ($movies as $v) {
|
||||
switch ($v->status) {
|
||||
case 'active':
|
||||
$wantedMovies++;
|
||||
break;
|
||||
case 'done':
|
||||
$availableMovies++;
|
||||
break;
|
||||
default:
|
||||
Log::warning('Unexpected CouchPotato status received: '.$v['status']);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$html = '
|
||||
<ul class="livestats">
|
||||
<li><span class="title">Wanted</span><sub>'.$wantedMovies.'</sub></li>
|
||||
<li><span class="title">Available</span><sub>'.$availableMovies.'</sub></li>
|
||||
</ul>
|
||||
';
|
||||
return json_encode(['status' => 'inactive', 'html' => $html]);
|
||||
}
|
||||
|
||||
private function sendRequest()
|
||||
{
|
||||
$res = null;
|
||||
try{
|
||||
$res = $this->_client->request(
|
||||
'GET',
|
||||
$this->getApiUrl()
|
||||
);
|
||||
}catch(\GuzzleHttp\Exception\BadResponseException $e){
|
||||
Log::error("Connection to {$e->getRequest()->getUrl()} failed");
|
||||
Log::debug($e->getMessage());
|
||||
$res = $e->getRequest();
|
||||
}catch(\GuzzleHttp\Exception\ConnectException $e) {
|
||||
Log::error("CouchPotato connection refused");
|
||||
Log::debug($e->getMessage());
|
||||
}
|
||||
return $res;
|
||||
}
|
||||
|
||||
private function getApiUrl()
|
||||
{
|
||||
$url = $this->config->url;
|
||||
$url = rtrim($url, '/');
|
||||
$apiUrl = $url.'/api/'.$this->config->apikey.'/movie.list';
|
||||
return $apiUrl;
|
||||
}
|
||||
}
|
||||
109
app/SupportedApps/Deluge.php
Normal file
@@ -0,0 +1,109 @@
|
||||
<?php namespace App\SupportedApps;
|
||||
use GuzzleHttp\Exception\GuzzleException;
|
||||
use GuzzleHttp\Client;
|
||||
class Deluge implements Contracts\Applications, Contracts\Livestats {
|
||||
public function defaultColour()
|
||||
{
|
||||
return '#357';
|
||||
}
|
||||
public function icon()
|
||||
{
|
||||
return 'supportedapps/deluge.png';
|
||||
}
|
||||
|
||||
public function configDetails()
|
||||
{
|
||||
return 'deluge';
|
||||
}
|
||||
|
||||
public function testConfig()
|
||||
{
|
||||
$res = $this->login()[0];
|
||||
switch($res->getStatusCode()) {
|
||||
case 200:
|
||||
$data = json_decode($res->getBody());
|
||||
if(!isset($data->result) || is_null($data->result) || $data->result == false) {
|
||||
echo 'Failed: Invalid Credentials';
|
||||
} else {
|
||||
echo 'Successfully connected to the API';
|
||||
}
|
||||
break;
|
||||
case 401:
|
||||
echo 'Failed: Invalid credentials';
|
||||
break;
|
||||
case 404:
|
||||
echo 'Failed: Please make sure your URL is correct and that there is a trailing slash';
|
||||
break;
|
||||
default:
|
||||
echo 'Something went wrong... Code: '.$res->getStatusCode();
|
||||
break;
|
||||
}
|
||||
}
|
||||
public function executeConfig()
|
||||
{
|
||||
$html = '';
|
||||
$active = 'active';
|
||||
$jar = $this->login()[1];
|
||||
$res = $this->getDetails($jar);
|
||||
$data = json_decode($res->getBody());
|
||||
$download_rate = $data->result->stats->download_rate;
|
||||
$upload_rate = $data->result->stats->upload_rate;
|
||||
$seed_count = $data->result->filters->state[2];
|
||||
$leech_count = $data->result->filters->state[1];
|
||||
$html = '
|
||||
<ul class="livestats">
|
||||
<li><span class="title"><i class="fas fa-arrow-down"></i> '.$this->formatBytes($download_rate).'</span></li>
|
||||
<li><span class="title"><i class="fas fa-arrow-up"></i> '.$this->formatBytes($upload_rate).'</span></li>
|
||||
</ul>
|
||||
<ul class="livestats">
|
||||
<li><span class="title">Leech: '.$leech_count[1].'</span></li>
|
||||
<li><span class="title">Seed: '.$seed_count[1].'</span></li>
|
||||
</ul>
|
||||
';
|
||||
return json_encode(['status' => $active, 'html' => $html]);
|
||||
}
|
||||
public function getDetails($jar)
|
||||
{
|
||||
$config = $this->config;
|
||||
$url = $config->url;
|
||||
$url = rtrim($url, '/');
|
||||
$api_url = $url.'/json';
|
||||
$client = new Client(['http_errors' => false, 'timeout' => 15, 'connect_timeout' => 15]);
|
||||
$res = $client->request('POST', $api_url, [
|
||||
'body' => '{"method": "web.update_ui", "params": [["none"], {}], "id": 1}',
|
||||
'cookies' => $jar,
|
||||
'headers' => ['content-type' => 'application/json', 'Accept' => 'application/json']
|
||||
]);
|
||||
return $res;
|
||||
}
|
||||
public function login()
|
||||
{
|
||||
$config = $this->config;
|
||||
$url = $config->url;
|
||||
$password = $config->password;
|
||||
$url = rtrim($url, '/');
|
||||
$api_url = $url.'/json';
|
||||
$jar = new \GuzzleHttp\Cookie\CookieJar();
|
||||
$client = new Client(['http_errors' => false, 'timeout' => 15, 'connect_timeout' => 15]);
|
||||
$res = $client->request('POST', $api_url, [
|
||||
'body' => '{"method": "auth.login", "params": ["'.$password.'"], "id": 1}',
|
||||
'cookies' => $jar,
|
||||
'headers' => ['content-type' => 'application/json', 'Accept' => 'application/json']
|
||||
]);
|
||||
return array($res,$jar);
|
||||
}
|
||||
|
||||
function formatBytes($bytes, $precision = 2) {
|
||||
$units = array('B', 'KB', 'MB', 'GB', 'TB');
|
||||
|
||||
$bytes = max($bytes, 0);
|
||||
$pow = floor(($bytes ? log($bytes) : 0) / log(1024));
|
||||
$pow = min($pow, count($units) - 1);
|
||||
|
||||
// Uncomment one of the following alternatives
|
||||
$bytes /= pow(1024, $pow);
|
||||
// $bytes /= (1 << (10 * $pow));
|
||||
|
||||
return round($bytes, $precision) . ' ' . $units[$pow] . 'ps';
|
||||
}
|
||||
}
|
||||
12
app/SupportedApps/Dokuwiki.php
Normal file
@@ -0,0 +1,12 @@
|
||||
<?php namespace App\SupportedApps;
|
||||
|
||||
class Dokuwiki implements Contracts\Applications {
|
||||
public function defaultColour()
|
||||
{
|
||||
return '#9d7056';
|
||||
}
|
||||
public function icon()
|
||||
{
|
||||
return 'supportedapps/dokuwiki.png';
|
||||
}
|
||||
}
|
||||
12
app/SupportedApps/Duplicati.php
Normal file
@@ -0,0 +1,12 @@
|
||||
<?php namespace App\SupportedApps;
|
||||
|
||||
class Duplicati implements Contracts\Applications {
|
||||
public function defaultColour()
|
||||
{
|
||||
return '#2c3744';
|
||||
}
|
||||
public function icon()
|
||||
{
|
||||
return 'supportedapps/duplicati.png';
|
||||
}
|
||||
}
|
||||
12
app/SupportedApps/Emby.php
Normal file
@@ -0,0 +1,12 @@
|
||||
<?php namespace App\SupportedApps;
|
||||
|
||||
class Emby implements Contracts\Applications {
|
||||
public function defaultColour()
|
||||
{
|
||||
return '#222';
|
||||
}
|
||||
public function icon()
|
||||
{
|
||||
return 'supportedapps/emby.png';
|
||||
}
|
||||
}
|
||||
12
app/SupportedApps/Flood.php
Normal file
@@ -0,0 +1,12 @@
|
||||
<?php namespace App\SupportedApps;
|
||||
|
||||
class Flood implements Contracts\Applications {
|
||||
public function defaultColour()
|
||||
{
|
||||
return '##00D091';
|
||||
}
|
||||
public function icon()
|
||||
{
|
||||
return 'supportedapps/Flood.png';
|
||||
}
|
||||
}
|
||||
12
app/SupportedApps/Gitea.php
Normal file
@@ -0,0 +1,12 @@
|
||||
<?php namespace App\SupportedApps;
|
||||
|
||||
class Gitea implements Contracts\Applications {
|
||||
public function defaultColour()
|
||||
{
|
||||
return '#585e52';
|
||||
}
|
||||
public function icon()
|
||||
{
|
||||
return 'supportedapps/gitea.png';
|
||||
}
|
||||
}
|
||||
14
app/SupportedApps/Glances.php
Normal file
@@ -0,0 +1,14 @@
|
||||
<?php namespace App\SupportedApps;
|
||||
|
||||
class Glances implements Contracts\Applications {
|
||||
|
||||
public function defaultColour()
|
||||
{
|
||||
return '#2c363f';
|
||||
}
|
||||
public function icon()
|
||||
{
|
||||
return 'supportedapps/glances.png';
|
||||
}
|
||||
|
||||
}
|
||||
12
app/SupportedApps/Grafana.php
Normal file
@@ -0,0 +1,12 @@
|
||||
<?php namespace App\SupportedApps;
|
||||
|
||||
class Grafana implements Contracts\Applications {
|
||||
public function defaultColour()
|
||||
{
|
||||
return '#a56e4d';
|
||||
}
|
||||
public function icon()
|
||||
{
|
||||
return 'supportedapps/grafana.png';
|
||||
}
|
||||
}
|
||||
12
app/SupportedApps/Graylog.php
Normal file
@@ -0,0 +1,12 @@
|
||||
<?php namespace App\SupportedApps;
|
||||
|
||||
class Graylog implements Contracts\Applications {
|
||||
public function defaultColour()
|
||||
{
|
||||
return '#158';
|
||||
}
|
||||
public function icon()
|
||||
{
|
||||
return 'supportedapps/graylog.png';
|
||||
}
|
||||
}
|
||||
12
app/SupportedApps/Headphones.php
Normal file
@@ -0,0 +1,12 @@
|
||||
<?php namespace App\SupportedApps;
|
||||
|
||||
class Headphones implements Contracts\Applications {
|
||||
public function defaultColour()
|
||||
{
|
||||
return '#185';
|
||||
}
|
||||
public function icon()
|
||||
{
|
||||
return 'supportedapps/headphones.png';
|
||||
}
|
||||
}
|
||||
12
app/SupportedApps/HomeAssistant.php
Normal file
@@ -0,0 +1,12 @@
|
||||
<?php namespace App\SupportedApps;
|
||||
|
||||
class HomeAssistant implements Contracts\Applications {
|
||||
public function defaultColour()
|
||||
{
|
||||
return '#073c52';
|
||||
}
|
||||
public function icon()
|
||||
{
|
||||
return 'supportedapps/homeassistant.png';
|
||||
}
|
||||
}
|
||||
12
app/SupportedApps/Jackett.php
Normal file
@@ -0,0 +1,12 @@
|
||||
<?php namespace App\SupportedApps;
|
||||
|
||||
class Jackett implements Contracts\Applications {
|
||||
public function defaultColour()
|
||||
{
|
||||
return '#484814';
|
||||
}
|
||||
public function icon()
|
||||
{
|
||||
return 'supportedapps/jackett.png';
|
||||
}
|
||||
}
|
||||
12
app/SupportedApps/Jdownloader.php
Normal file
@@ -0,0 +1,12 @@
|
||||
<?php namespace App\SupportedApps;
|
||||
|
||||
class Jdownloader implements Contracts\Applications {
|
||||
public function defaultColour()
|
||||
{
|
||||
return '#2b494f';
|
||||
}
|
||||
public function icon()
|
||||
{
|
||||
return 'supportedapps/jdownloader.png';
|
||||
}
|
||||
}
|
||||
11
app/SupportedApps/Krusader.php
Normal file
@@ -0,0 +1,11 @@
|
||||
<?php namespace App\SupportedApps;
|
||||
class Krusader implements Contracts\Applications {
|
||||
public function defaultColour()
|
||||
{
|
||||
return '#5A5';
|
||||
}
|
||||
public function icon()
|
||||
{
|
||||
return 'supportedapps/krusader.png';
|
||||
}
|
||||
}
|
||||
12
app/SupportedApps/Lidarr.php
Normal file
@@ -0,0 +1,12 @@
|
||||
<?php namespace App\SupportedApps;
|
||||
|
||||
class Lidarr implements Contracts\Applications {
|
||||
public function defaultColour()
|
||||
{
|
||||
return '#183c18';
|
||||
}
|
||||
public function icon()
|
||||
{
|
||||
return 'supportedapps/lidarr.png';
|
||||
}
|
||||
}
|
||||
12
app/SupportedApps/Mcmyadmin.php
Normal file
@@ -0,0 +1,12 @@
|
||||
<?php namespace App\SupportedApps;
|
||||
|
||||
class Mcmyadmin implements Contracts\Applications {
|
||||
public function defaultColour()
|
||||
{
|
||||
return '#30404b';
|
||||
}
|
||||
public function icon()
|
||||
{
|
||||
return 'supportedapps/mcmyadmin.png';
|
||||
}
|
||||
}
|
||||
12
app/SupportedApps/Medusa.php
Normal file
@@ -0,0 +1,12 @@
|
||||
<?php namespace App\SupportedApps;
|
||||
|
||||
class Medusa implements Contracts\Applications {
|
||||
public function defaultColour()
|
||||
{
|
||||
return '#4b5e55';
|
||||
}
|
||||
public function icon()
|
||||
{
|
||||
return 'supportedapps/medusa.png';
|
||||
}
|
||||
}
|
||||
12
app/SupportedApps/MusicBrainz.php
Normal file
@@ -0,0 +1,12 @@
|
||||
<?php namespace App\SupportedApps;
|
||||
|
||||
class MusicBrainz implements Contracts\Applications {
|
||||
public function defaultColour()
|
||||
{
|
||||
return '#a0a';
|
||||
}
|
||||
public function icon()
|
||||
{
|
||||
return 'supportedapps/musicbrainz.png';
|
||||
}
|
||||
}
|
||||
12
app/SupportedApps/Mylar.php
Normal file
@@ -0,0 +1,12 @@
|
||||
<?php namespace App\SupportedApps;
|
||||
|
||||
class Mylar implements Contracts\Applications {
|
||||
public function defaultColour()
|
||||
{
|
||||
return '#aa0';
|
||||
}
|
||||
public function icon()
|
||||
{
|
||||
return 'supportedapps/mylar.png';
|
||||
}
|
||||
}
|
||||
12
app/SupportedApps/Netdata.php
Normal file
@@ -0,0 +1,12 @@
|
||||
<?php namespace App\SupportedApps;
|
||||
|
||||
class Netdata implements Contracts\Applications {
|
||||
public function defaultColour()
|
||||
{
|
||||
return '#543737';
|
||||
}
|
||||
public function icon()
|
||||
{
|
||||
return 'supportedapps/netdata.png';
|
||||
}
|
||||
}
|
||||
12
app/SupportedApps/Nextcloud.php
Normal file
@@ -0,0 +1,12 @@
|
||||
<?php namespace App\SupportedApps;
|
||||
|
||||
class Nextcloud implements Contracts\Applications {
|
||||
public function defaultColour()
|
||||
{
|
||||
return '#0e2c3e';
|
||||
}
|
||||
public function icon()
|
||||
{
|
||||
return 'supportedapps/nextcloud.png';
|
||||
}
|
||||
}
|
||||
11
app/SupportedApps/NowShowing.php
Normal file
@@ -0,0 +1,11 @@
|
||||
<?php namespace App\SupportedApps;
|
||||
class NowShowing implements Contracts\Applications {
|
||||
public function defaultColour()
|
||||
{
|
||||
return '#690000';
|
||||
}
|
||||
public function icon()
|
||||
{
|
||||
return 'supportedapps/nowshowing.png';
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,84 @@
|
||||
<?php namespace App\SupportedApps;
|
||||
|
||||
class Nzbget implements Contracts\Applications {
|
||||
use GuzzleHttp\Exception\GuzzleException;
|
||||
use GuzzleHttp\Client;
|
||||
|
||||
class Nzbget implements Contracts\Applications, Contracts\Livestats {
|
||||
|
||||
public $config;
|
||||
|
||||
public function defaultColour()
|
||||
{
|
||||
return '#ccc';
|
||||
return '#253827';
|
||||
}
|
||||
public function icon()
|
||||
{
|
||||
return 'supportedapps/nzbget.png';
|
||||
}
|
||||
public function configDetails()
|
||||
{
|
||||
return 'nzbget';
|
||||
}
|
||||
public function testConfig()
|
||||
{
|
||||
$res = $this->buildRequest('status');
|
||||
switch($res->getStatusCode()) {
|
||||
case 200:
|
||||
echo 'Successfully connected to the API';
|
||||
break;
|
||||
case 401:
|
||||
echo 'Failed: Invalid credentials';
|
||||
break;
|
||||
case 404:
|
||||
echo 'Failed: Please make sure your URL is correct and that there is a trailing slash';
|
||||
break;
|
||||
default:
|
||||
echo 'Something went wrong... Code: '.$res->getStatusCode();
|
||||
break;
|
||||
}
|
||||
}
|
||||
public function executeConfig()
|
||||
{
|
||||
$html = '';
|
||||
$active = 'inactive';
|
||||
$res = $this->buildRequest('status');
|
||||
$data = json_decode($res->getBody());
|
||||
//$data->result->RemainingSizeMB = '10000000';
|
||||
//$data->result->DownloadRate = '100000000';
|
||||
if($data) {
|
||||
$size = $data->result->RemainingSizeMB;
|
||||
$rate = $data->result->DownloadRate;
|
||||
$queue_size = format_bytes($size*1000*1000, false, ' <span>', '</span>');
|
||||
$current_speed = format_bytes($rate, false, ' <span>');
|
||||
|
||||
$active = ($size > 0 || $rate > 0) ? 'active' : 'inactive';
|
||||
$html = '
|
||||
<ul class="livestats">
|
||||
<li><span class="title">Queue</span><strong>'.$queue_size.'</strong></li>
|
||||
<li><span class="title">Speed</span><strong>'.$current_speed.'/s</span></strong></li>
|
||||
</ul>
|
||||
';
|
||||
}
|
||||
return json_encode(['status' => $active, 'html' => $html]);
|
||||
}
|
||||
public function buildRequest($endpoint)
|
||||
{
|
||||
$config = $this->config;
|
||||
$url = $config->url;
|
||||
$username = $config->username;
|
||||
$password = $config->password;
|
||||
|
||||
$rebuild_url = str_replace('http://', 'http://'.$username.':'.$password.'@', $url);
|
||||
$rebuild_url = str_replace('https://', 'https://'.$username.':'.$password.'@', $rebuild_url);
|
||||
$rebuild_url = rtrim($rebuild_url, '/');
|
||||
|
||||
|
||||
$api_url = $rebuild_url.'/jsonrpc/'.$endpoint;
|
||||
|
||||
$client = new Client(['http_errors' => false, 'timeout' => 15, 'connect_timeout' => 15]);
|
||||
$res = $client->request('GET', $api_url);
|
||||
return $res;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
12
app/SupportedApps/Nzbhydra.php
Normal file
@@ -0,0 +1,12 @@
|
||||
<?php namespace App\SupportedApps;
|
||||
|
||||
class Nzbhydra implements Contracts\Applications {
|
||||
public function defaultColour()
|
||||
{
|
||||
return '#53644d';
|
||||
}
|
||||
public function icon()
|
||||
{
|
||||
return 'supportedapps/nzbhydra.png';
|
||||
}
|
||||
}
|
||||
12
app/SupportedApps/Ombi.php
Normal file
@@ -0,0 +1,12 @@
|
||||
<?php namespace App\SupportedApps;
|
||||
|
||||
class Ombi implements Contracts\Applications {
|
||||
public function defaultColour()
|
||||
{
|
||||
return '#150f09';
|
||||
}
|
||||
public function icon()
|
||||
{
|
||||
return 'supportedapps/ombi.png';
|
||||
}
|
||||
}
|
||||
11
app/SupportedApps/OpenMediaVault.php
Normal file
@@ -0,0 +1,11 @@
|
||||
<?php namespace App\SupportedApps;
|
||||
class OpenMediaVault implements Contracts\Applications {
|
||||
public function defaultColour()
|
||||
{
|
||||
return '#5AF';
|
||||
}
|
||||
public function icon()
|
||||
{
|
||||
return 'supportedapps/openmediavault.png';
|
||||
}
|
||||
}
|
||||
12
app/SupportedApps/Openhab.php
Normal file
@@ -0,0 +1,12 @@
|
||||
<?php namespace App\SupportedApps;
|
||||
|
||||
class Openhab implements Contracts\Applications {
|
||||
public function defaultColour()
|
||||
{
|
||||
return '#2b2525';
|
||||
}
|
||||
public function icon()
|
||||
{
|
||||
return 'supportedapps/openhab.png';
|
||||
}
|
||||
}
|
||||
12
app/SupportedApps/Opnsense.php
Normal file
@@ -0,0 +1,12 @@
|
||||
<?php namespace App\SupportedApps;
|
||||
|
||||
class Opnsense implements Contracts\Applications {
|
||||
public function defaultColour()
|
||||
{
|
||||
return '#211914';
|
||||
}
|
||||
public function icon()
|
||||
{
|
||||
return 'supportedapps/opnsense.png';
|
||||
}
|
||||
}
|
||||
12
app/SupportedApps/Pfsense.php
Normal file
@@ -0,0 +1,12 @@
|
||||
<?php namespace App\SupportedApps;
|
||||
|
||||
class Pfsense implements Contracts\Applications {
|
||||
public function defaultColour()
|
||||
{
|
||||
return '#4e4742';
|
||||
}
|
||||
public function icon()
|
||||
{
|
||||
return 'supportedapps/pfsense.png';
|
||||
}
|
||||
}
|
||||
73
app/SupportedApps/Pihole.php
Normal file
@@ -0,0 +1,73 @@
|
||||
<?php namespace App\SupportedApps;
|
||||
|
||||
use GuzzleHttp\Exception\GuzzleException;
|
||||
use GuzzleHttp\Client;
|
||||
|
||||
class Pihole implements Contracts\Applications, Contracts\Livestats {
|
||||
public function defaultColour()
|
||||
{
|
||||
return '#352222';
|
||||
}
|
||||
public function icon()
|
||||
{
|
||||
return 'supportedapps/pihole.png';
|
||||
}
|
||||
|
||||
public function configDetails()
|
||||
{
|
||||
return 'pihole';
|
||||
}
|
||||
|
||||
public function testConfig()
|
||||
{
|
||||
$res = $this->buildRequest();
|
||||
switch($res->getStatusCode()) {
|
||||
case 200:
|
||||
echo 'Successfully connected to the API';
|
||||
break;
|
||||
case 401:
|
||||
echo 'Failed: Invalid credentials';
|
||||
break;
|
||||
case 404:
|
||||
echo 'Failed: Please make sure your URL is correct and that there is a trailing slash';
|
||||
break;
|
||||
default:
|
||||
echo 'Something went wrong... Code: '.$res->getStatusCode();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public function executeConfig()
|
||||
{
|
||||
$html = '';
|
||||
$active = 'active';
|
||||
$res = $this->buildRequest();
|
||||
$data = json_decode($res->getBody());
|
||||
|
||||
$html = '
|
||||
<ul class="livestats">
|
||||
<li><span class="title">Domains<br />Blocked</span><strong>'.$data->domains_being_blocked.'</strong></li>
|
||||
<li><span class="title">Blocked<br />Today</span><strong>'.$data->ads_blocked_today.'</span></strong></li>
|
||||
</ul>
|
||||
';
|
||||
return json_encode(['status' => $active, 'html' => $html]);
|
||||
}
|
||||
|
||||
public function buildRequest()
|
||||
{
|
||||
$config = $this->config;
|
||||
$url = $config->url;
|
||||
|
||||
$url = rtrim($url, '/');
|
||||
|
||||
$api_url = $url.'/api.php';
|
||||
//die( $api_url.' --- ');
|
||||
|
||||
$client = new Client(['http_errors' => false, 'timeout' => 15, 'connect_timeout' => 15]);
|
||||
$res = $client->request('GET', $api_url);
|
||||
return $res;
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -3,6 +3,10 @@
|
||||
class Plex implements Contracts\Applications {
|
||||
public function defaultColour()
|
||||
{
|
||||
return '#ccc';
|
||||
return '#222';
|
||||
}
|
||||
public function icon()
|
||||
{
|
||||
return 'supportedapps/plex.png';
|
||||
}
|
||||
}
|
||||
77
app/SupportedApps/Plexpy.php
Normal file
@@ -0,0 +1,77 @@
|
||||
<?php namespace App\SupportedApps;
|
||||
|
||||
use GuzzleHttp\Exception\GuzzleException;
|
||||
use GuzzleHttp\Client;
|
||||
|
||||
class Plexpy implements Contracts\Applications, Contracts\Livestats {
|
||||
|
||||
public $config;
|
||||
|
||||
public function defaultColour()
|
||||
{
|
||||
return '#2d2208';
|
||||
}
|
||||
public function icon()
|
||||
{
|
||||
return 'supportedapps/plexpy.png';
|
||||
}
|
||||
public function configDetails()
|
||||
{
|
||||
return 'plexpy';
|
||||
}
|
||||
public function testConfig()
|
||||
{
|
||||
$res = $this->buildRequest('arnold');
|
||||
switch($res->getStatusCode()) {
|
||||
case 200:
|
||||
$data = json_decode($res->getBody());
|
||||
if(isset($data->error) && !empty($data->error)) {
|
||||
echo 'Failed: '.$data->error;
|
||||
} else {
|
||||
echo 'Successfully connected to the API';
|
||||
}
|
||||
break;
|
||||
case 401:
|
||||
echo 'Failed: Invalid credentials';
|
||||
break;
|
||||
case 404:
|
||||
echo 'Failed: Please make sure your URL is correct and that there is a trailing slash';
|
||||
break;
|
||||
default:
|
||||
echo 'Something went wrong... Code: '.$res->getStatusCode();
|
||||
break;
|
||||
}
|
||||
}
|
||||
public function executeConfig()
|
||||
{
|
||||
$html = '';
|
||||
$active = 'active';
|
||||
$res = $this->buildRequest('get_activity');
|
||||
$data = json_decode($res->getBody());
|
||||
$stream_count = $data->response->data->stream_count;
|
||||
|
||||
$html = '
|
||||
<ul class="livestats">
|
||||
<li><span class="title">Stream Count</span><strong>'.$stream_count.'</strong></li>
|
||||
</ul>
|
||||
';
|
||||
|
||||
return json_encode(['status' => $active, 'html' => $html]);
|
||||
}
|
||||
public function buildRequest($endpoint)
|
||||
{
|
||||
$config = $this->config;
|
||||
$url = $config->url;
|
||||
$apikey = $config->apikey;
|
||||
|
||||
$url = rtrim($url, '/');
|
||||
|
||||
$api_url = $url.'/api/v2?apikey='.$apikey.'&cmd='.$endpoint;
|
||||
|
||||
$client = new Client(['http_errors' => false, 'timeout' => 15, 'connect_timeout' => 15]);
|
||||
$res = $client->request('GET', $api_url);
|
||||
return $res;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
12
app/SupportedApps/Plexrequests.php
Normal file
@@ -0,0 +1,12 @@
|
||||
<?php namespace App\SupportedApps;
|
||||
|
||||
class Plexrequests implements Contracts\Applications {
|
||||
public function defaultColour()
|
||||
{
|
||||
return '#3c2d1c';
|
||||
}
|
||||
public function icon()
|
||||
{
|
||||
return 'supportedapps/plexrequests.png';
|
||||
}
|
||||
}
|
||||
12
app/SupportedApps/Portainer.php
Normal file
@@ -0,0 +1,12 @@
|
||||
<?php namespace App\SupportedApps;
|
||||
|
||||
class Portainer implements Contracts\Applications {
|
||||
public function defaultColour()
|
||||
{
|
||||
return '#283f44';
|
||||
}
|
||||
public function icon()
|
||||
{
|
||||
return 'supportedapps/portainer.png';
|
||||
}
|
||||
}
|
||||
80
app/SupportedApps/Proxmox.php
Normal file
@@ -0,0 +1,80 @@
|
||||
<?php namespace App\SupportedApps;
|
||||
|
||||
use GuzzleHttp\Exception\GuzzleException;
|
||||
use GuzzleHttp\Client;
|
||||
|
||||
class Proxmox implements Contracts\Applications, Contracts\Livestats {
|
||||
public function defaultColour()
|
||||
{
|
||||
return '#542e0a';
|
||||
}
|
||||
public function icon()
|
||||
{
|
||||
return 'supportedapps/proxmox.png';
|
||||
}
|
||||
|
||||
public function configDetails()
|
||||
{
|
||||
//return 'proxmox';
|
||||
return null;
|
||||
}
|
||||
|
||||
public function testConfig()
|
||||
{
|
||||
/*$res = $this->buildRequest();
|
||||
switch($res->getStatusCode()) {
|
||||
case 200:
|
||||
echo 'Successfully connected to the API';
|
||||
break;
|
||||
case 401:
|
||||
echo 'Failed: Invalid credentials';
|
||||
break;
|
||||
case 404:
|
||||
echo 'Failed: Please make sure your URL is correct and that there is a trailing slash';
|
||||
break;
|
||||
default:
|
||||
echo 'Something went wrong... Code: '.$res->getStatusCode();
|
||||
break;
|
||||
}*/
|
||||
return null;
|
||||
}
|
||||
|
||||
public function executeConfig()
|
||||
{
|
||||
/*
|
||||
$output = '';
|
||||
$res = $this->buildRequest();
|
||||
$data = json_decode($res->getBody());
|
||||
|
||||
$output = '
|
||||
<ul class="livestats">
|
||||
<li><span class="title">Domains<br />Blocked</span><strong>'.$data->domains_being_blocked.'</strong></li>
|
||||
<li><span class="title">Blocked<br />Today</span><strong>'.$data->ads_blocked_today.'</span></strong></li>
|
||||
</ul>
|
||||
';
|
||||
return $output;
|
||||
*/
|
||||
return null;
|
||||
}
|
||||
|
||||
public function buildRequest($endpoint='')
|
||||
{
|
||||
$config = $this->config;
|
||||
|
||||
$username = $config->username;
|
||||
$password = $config->password;
|
||||
|
||||
$url = $config->url;
|
||||
$url = rtrim($url, '/');
|
||||
|
||||
$api_url = $url.'/api2/json/'.$endpoint.'?username='.$username.'&password='.$password;
|
||||
//die( $api_url.' --- ');
|
||||
|
||||
$client = new Client(['http_errors' => false, 'verify' => false ]);
|
||||
$res = $client->request('GET', $api_url);
|
||||
return $res;
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
12
app/SupportedApps/Radarr.php
Normal file
@@ -0,0 +1,12 @@
|
||||
<?php namespace App\SupportedApps;
|
||||
|
||||
class Radarr implements Contracts\Applications {
|
||||
public function defaultColour()
|
||||
{
|
||||
return '#3e3726';
|
||||
}
|
||||
public function icon()
|
||||
{
|
||||
return 'supportedapps/radarr.png';
|
||||
}
|
||||
}
|
||||
12
app/SupportedApps/Rancher.php
Normal file
@@ -0,0 +1,12 @@
|
||||
<?php namespace App\SupportedApps;
|
||||
|
||||
class Rancher implements Contracts\Applications {
|
||||
public function defaultColour()
|
||||
{
|
||||
return '#78c9cf';
|
||||
}
|
||||
public function icon()
|
||||
{
|
||||
return 'supportedapps/rancher.png';
|
||||
}
|
||||
}
|
||||
95
app/SupportedApps/Runeaudio.php
Normal file
@@ -0,0 +1,95 @@
|
||||
<?php namespace App\SupportedApps;
|
||||
|
||||
use GuzzleHttp\Exception\GuzzleException;
|
||||
use GuzzleHttp\Client;
|
||||
|
||||
class Runeaudio implements Contracts\Applications, Contracts\Livestats {
|
||||
public function defaultColour()
|
||||
{
|
||||
return '#05A';
|
||||
}
|
||||
public function icon()
|
||||
{
|
||||
return 'supportedapps/runeaudio.png';
|
||||
}
|
||||
|
||||
public function configDetails()
|
||||
{
|
||||
return 'runeaudio';
|
||||
}
|
||||
|
||||
public function testConfig()
|
||||
{
|
||||
$res = $this->buildRequest('status');
|
||||
switch($res->getStatusCode()) {
|
||||
case 200:
|
||||
echo 'Successfully connected to the API';
|
||||
break;
|
||||
case 401:
|
||||
echo 'Failed: Invalid credentials';
|
||||
break;
|
||||
case 404:
|
||||
echo 'Failed: Please make sure your URL is correct and that there is a trailing slash';
|
||||
break;
|
||||
default:
|
||||
echo 'Something went wrong... Code: '.$res->getStatusCode();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public function executeConfig()
|
||||
{
|
||||
$output = '';
|
||||
$active = 'active';
|
||||
$artist = '';
|
||||
$song_title = '';
|
||||
$res = $this->buildRequest('currentsong');
|
||||
$array = explode("\n", $res->getBody());
|
||||
foreach($array as $item) {
|
||||
$item_array = explode(": ", $item);
|
||||
if ($item_array[0] == 'Artist') {
|
||||
$artist = $item_array[1];
|
||||
} elseif ($item_array[0] == 'Title') {
|
||||
$song_title = $item_array[1];
|
||||
}
|
||||
}
|
||||
|
||||
$output = '<ul class="livestats">';
|
||||
|
||||
if (strlen($artist) > 12) {
|
||||
$output = $output.'<li><span class="title-marquee"><span>'.$artist.'</span></span></li>';
|
||||
} else {
|
||||
$output = $output.'<li><span class="title">'.$artist.'</span></li>';
|
||||
}
|
||||
|
||||
$output = $output.'</ul><ul class="livestats">';
|
||||
|
||||
if (strlen($song_title) > 12) {
|
||||
$output = $output.'<li><span class="title-marquee"><span>'.$song_title.'</span></span></li>';
|
||||
} else {
|
||||
$output = $output.'<li><span class="title">'.$song_title.'</span></li>';
|
||||
}
|
||||
|
||||
$output = $output.'</ul>';
|
||||
|
||||
return json_encode(['status' => $active, 'html' => $output]);
|
||||
}
|
||||
|
||||
public function buildRequest($endpoint)
|
||||
{
|
||||
$config = $this->config;
|
||||
$url = $config->url;
|
||||
|
||||
$url = rtrim($url, '/');
|
||||
|
||||
$api_url = $url.'/command/?cmd='.$endpoint;
|
||||
//die( $api_url.' --- ');
|
||||
|
||||
$client = new Client(['http_errors' => false, 'timeout' => 15, 'connect_timeout' => 15]);
|
||||
$res = $client->request('GET', $api_url);
|
||||
return $res;
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
89
app/SupportedApps/Sabnzbd.php
Normal file
@@ -0,0 +1,89 @@
|
||||
<?php namespace App\SupportedApps;
|
||||
|
||||
use GuzzleHttp\Exception\GuzzleException;
|
||||
use GuzzleHttp\Client;
|
||||
|
||||
class Sabnzbd implements Contracts\Applications, Contracts\Livestats {
|
||||
|
||||
public $config;
|
||||
|
||||
public function defaultColour()
|
||||
{
|
||||
return '#3e3924';
|
||||
}
|
||||
public function icon()
|
||||
{
|
||||
return 'supportedapps/sabnzbd.png';
|
||||
}
|
||||
public function configDetails()
|
||||
{
|
||||
return 'sabnzbd';
|
||||
}
|
||||
public function testConfig()
|
||||
{
|
||||
$res = $this->buildRequest('queue');
|
||||
switch($res->getStatusCode()) {
|
||||
case 200:
|
||||
$data = json_decode($res->getBody());
|
||||
if(isset($data->error) && !empty($data->error)) {
|
||||
echo 'Failed: '.$data->error;
|
||||
} else {
|
||||
echo 'Successfully connected to the API';
|
||||
}
|
||||
break;
|
||||
case 401:
|
||||
echo 'Failed: Invalid credentials';
|
||||
break;
|
||||
case 404:
|
||||
echo 'Failed: Please make sure your URL is correct and that there is a trailing slash';
|
||||
break;
|
||||
default:
|
||||
echo 'Something went wrong... Code: '.$res->getStatusCode();
|
||||
break;
|
||||
}
|
||||
}
|
||||
public function executeConfig()
|
||||
{
|
||||
$html = '';
|
||||
$active = 'inactive';
|
||||
$res = $this->buildRequest('queue');
|
||||
$data = json_decode($res->getBody());
|
||||
//$data->result->RemainingSizeMB = '10000000';
|
||||
//$data->result->DownloadRate = '100000000';
|
||||
if($data) {
|
||||
$size = $data->queue->mbleft;
|
||||
$rate = $data->queue->kbpersec;
|
||||
$queue_size = format_bytes($size*1000*1000, false, ' <span>', '</span>');
|
||||
$current_speed = format_bytes($rate*1000, false, ' <span>');
|
||||
|
||||
$active = ($size > 0 || $rate > 0) ? 'active' : 'inactive';
|
||||
$html = '
|
||||
<ul class="livestats">
|
||||
<li><span class="title">Queue</span><strong>'.$queue_size.'</strong></li>
|
||||
<li><span class="title">Speed</span><strong>'.$current_speed.'/s</span></strong></li>
|
||||
</ul>
|
||||
';
|
||||
}
|
||||
return json_encode(['status' => $active, 'html' => $html]);
|
||||
}
|
||||
public function buildRequest($endpoint)
|
||||
{
|
||||
$config = $this->config;
|
||||
$url = $config->url;
|
||||
$apikey = $config->apikey;
|
||||
|
||||
//print_r($config);
|
||||
//die();
|
||||
|
||||
$url = rtrim($url, '/');
|
||||
|
||||
$api_url = $url.'/api?output=json&apikey='.$apikey.'&mode='.$endpoint;
|
||||
//die( $api_url.' --- ');
|
||||
|
||||
$client = new Client(['http_errors' => false, 'timeout' => 15, 'connect_timeout' => 15]);
|
||||
$res = $client->request('GET', $api_url);
|
||||
return $res;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
12
app/SupportedApps/Sickrage.php
Normal file
@@ -0,0 +1,12 @@
|
||||
<?php namespace App\SupportedApps;
|
||||
|
||||
class Sickrage implements Contracts\Applications {
|
||||
public function defaultColour()
|
||||
{
|
||||
return '#6185a6';
|
||||
}
|
||||
public function icon()
|
||||
{
|
||||
return 'supportedapps/sickrage.png';
|
||||
}
|
||||
}
|
||||
12
app/SupportedApps/Sonarr.php
Normal file
@@ -0,0 +1,12 @@
|
||||
<?php namespace App\SupportedApps;
|
||||
|
||||
class Sonarr implements Contracts\Applications {
|
||||
public function defaultColour()
|
||||
{
|
||||
return '#163740';
|
||||
}
|
||||
public function icon()
|
||||
{
|
||||
return 'supportedapps/sonarr.png';
|
||||
}
|
||||
}
|
||||
11
app/SupportedApps/Syncthing.php
Normal file
@@ -0,0 +1,11 @@
|
||||
<?php namespace App\SupportedApps;
|
||||
class Syncthing implements Contracts\Applications {
|
||||
public function defaultColour()
|
||||
{
|
||||
return '#888';
|
||||
}
|
||||
public function icon()
|
||||
{
|
||||
return 'supportedapps/syncthing.png';
|
||||
}
|
||||
}
|
||||
77
app/SupportedApps/Tautulli.php
Normal file
@@ -0,0 +1,77 @@
|
||||
<?php namespace App\SupportedApps;
|
||||
|
||||
use GuzzleHttp\Exception\GuzzleException;
|
||||
use GuzzleHttp\Client;
|
||||
|
||||
class Tautulli implements Contracts\Applications, Contracts\Livestats {
|
||||
|
||||
public $config;
|
||||
|
||||
public function defaultColour()
|
||||
{
|
||||
return '#2d2208';
|
||||
}
|
||||
public function icon()
|
||||
{
|
||||
return 'supportedapps/tautulli.png';
|
||||
}
|
||||
public function configDetails()
|
||||
{
|
||||
return 'tautulli';
|
||||
}
|
||||
public function testConfig()
|
||||
{
|
||||
$res = $this->buildRequest('arnold');
|
||||
switch($res->getStatusCode()) {
|
||||
case 200:
|
||||
$data = json_decode($res->getBody());
|
||||
if(isset($data->error) && !empty($data->error)) {
|
||||
echo 'Failed: '.$data->error;
|
||||
} else {
|
||||
echo 'Successfully connected to the API';
|
||||
}
|
||||
break;
|
||||
case 401:
|
||||
echo 'Failed: Invalid credentials';
|
||||
break;
|
||||
case 404:
|
||||
echo 'Failed: Please make sure your URL is correct and that there is a trailing slash';
|
||||
break;
|
||||
default:
|
||||
echo 'Something went wrong... Code: '.$res->getStatusCode();
|
||||
break;
|
||||
}
|
||||
}
|
||||
public function executeConfig()
|
||||
{
|
||||
$html = '';
|
||||
$active = 'active';
|
||||
$res = $this->buildRequest('get_activity');
|
||||
$data = json_decode($res->getBody());
|
||||
$stream_count = $data->response->data->stream_count;
|
||||
|
||||
$html = '
|
||||
<ul class="livestats">
|
||||
<li><span class="title">Stream Count</span><strong>'.$stream_count.'</strong></li>
|
||||
</ul>
|
||||
';
|
||||
|
||||
return json_encode(['status' => $active, 'html' => $html]);
|
||||
}
|
||||
public function buildRequest($endpoint)
|
||||
{
|
||||
$config = $this->config;
|
||||
$url = $config->url;
|
||||
$apikey = $config->apikey;
|
||||
|
||||
$url = rtrim($url, '/');
|
||||
|
||||
$api_url = $url.'/api/v2?apikey='.$apikey.'&cmd='.$endpoint;
|
||||
|
||||
$client = new Client(['http_errors' => false, 'timeout' => 15, 'connect_timeout' => 15]);
|
||||
$res = $client->request('GET', $api_url);
|
||||
return $res;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
78
app/SupportedApps/Traefik.php
Normal file
@@ -0,0 +1,78 @@
|
||||
<?php namespace App\SupportedApps;
|
||||
|
||||
use GuzzleHttp\Client;
|
||||
use GuzzleHttp\Exception\GuzzleException;
|
||||
|
||||
class Traefik implements Contracts\Applications, Contracts\Livestats
|
||||
{
|
||||
|
||||
public function defaultColour()
|
||||
{
|
||||
return '#28434a';
|
||||
}
|
||||
|
||||
public function icon()
|
||||
{
|
||||
return 'supportedapps/traefik.png';
|
||||
}
|
||||
|
||||
public function configDetails()
|
||||
{
|
||||
return 'traefik';
|
||||
}
|
||||
|
||||
public function testConfig()
|
||||
{
|
||||
$res = $this->sendRequest();
|
||||
if ($res == null) {
|
||||
echo 'Traefik connection failed';
|
||||
return;
|
||||
}
|
||||
switch($res->getStatusCode()) {
|
||||
case 200:
|
||||
$data = json_decode($res->getBody());
|
||||
echo "Successfully connected with status: ".$data->result."\n";
|
||||
break;
|
||||
case 404:
|
||||
echo 'Failed: Please make sure your URL is correct and includes the port';
|
||||
break;
|
||||
default:
|
||||
echo 'Something went wrong... Code: '.$res->getStatusCode();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public function executeConfig()
|
||||
{
|
||||
$html = '';
|
||||
$active = 'inactive';
|
||||
$res = $this->sendRequest();
|
||||
$data = json_decode($res->getBody());
|
||||
if ($data) {
|
||||
$avg_response_time = $data->average_response_time_sec;
|
||||
$time = $avg_response_time*1000;
|
||||
$time_output = number_format($time, 2);
|
||||
$active = ($time > 0) ? 'active' : 'inactive';
|
||||
$html = '
|
||||
<ul class="livestats">
|
||||
<li><span class="title">Avg. Response Time</span><sub><i class="fas fa-heartbeat"></i> '.$time_output.' ms</sub></li>
|
||||
</ul>
|
||||
';
|
||||
}
|
||||
return json_encode(['status' => $active, 'html' => $html]);
|
||||
}
|
||||
|
||||
public function sendRequest()
|
||||
{
|
||||
$config = $this->config;
|
||||
$url = $config->url;
|
||||
|
||||
$url = rtrim($url, '/');
|
||||
$api_url = $url.'/health';
|
||||
|
||||
$client = new Client(['http_errors' => false, 'timeout' => 15, 'connect_timeout' => 15]);
|
||||
$res = $client->request('GET', $api_url);
|
||||
|
||||
return $res;
|
||||
}
|
||||
}
|
||||
169
app/SupportedApps/Transmission.php
Normal file
@@ -0,0 +1,169 @@
|
||||
<?php namespace App\SupportedApps;
|
||||
|
||||
use GuzzleHttp\Exception\GuzzleException;
|
||||
use GuzzleHttp\Client;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class Transmission implements Contracts\Applications, Contracts\Livestats
|
||||
{
|
||||
|
||||
private $_client;
|
||||
private $_clientOptions = array();
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$body = array();
|
||||
$body["method"] = "torrent-get";
|
||||
$body["arguments"] = array("fields" => ["percentDone","status","rateDownload","rateUpload"]);
|
||||
$this->_client = new Client(
|
||||
['http_errors' => false,
|
||||
'timeout' => 10,
|
||||
'body' => json_encode($body)]
|
||||
);
|
||||
}
|
||||
|
||||
public function defaultColour()
|
||||
{
|
||||
return '#950003';
|
||||
}
|
||||
public function icon()
|
||||
{
|
||||
return 'supportedapps/transmission.png';
|
||||
}
|
||||
public function configDetails()
|
||||
{
|
||||
return 'transmission';
|
||||
}
|
||||
public function testConfig()
|
||||
{
|
||||
$res = $this->sendRequest();
|
||||
if ($res == null) {
|
||||
echo 'Transmission connection failed';
|
||||
return;
|
||||
}
|
||||
switch($res->getStatusCode()) {
|
||||
case 200:
|
||||
$data = json_decode($res->getBody());
|
||||
echo "Successfully connected with status: ".$data->result."\n";
|
||||
break;
|
||||
case 401:
|
||||
echo 'Failed: Invalid credentials';
|
||||
break;
|
||||
case 404:
|
||||
echo 'Failed: Please make sure your URL is correct and includes the port';
|
||||
break;
|
||||
case 409:
|
||||
echo 'Failed: Incorrect session id';
|
||||
break;
|
||||
default:
|
||||
echo 'Something went wrong... Code: '.$res->getStatusCode();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public function executeConfig()
|
||||
{
|
||||
$html = '';
|
||||
$active = 'active';
|
||||
$res = $this->sendRequest();
|
||||
if ($res == null) {
|
||||
Log::debug('Transmission connection failed');
|
||||
return '';
|
||||
}
|
||||
$data = json_decode($res->getBody());
|
||||
if (! isset($data->arguments)) {
|
||||
Log::debug('Failed to fetch data from Transmission');
|
||||
return '';
|
||||
}
|
||||
$torrents = $data->arguments->torrents;
|
||||
$torrentCount = count($torrents);
|
||||
$rateDownload = $rateUpload = $completedTorrents = 0;
|
||||
foreach ($torrents as $thisTorrent) {
|
||||
$rateDownload += $thisTorrent->rateDownload;
|
||||
$rateUpload += $thisTorrent->rateUpload;
|
||||
if ($thisTorrent->percentDone == 1) {
|
||||
$completedTorrents += 1;
|
||||
}
|
||||
}
|
||||
if ($torrentCount - $completedTorrents == 0) {
|
||||
// Don't poll as frequently if we don't have any active torrents
|
||||
$active = 'inactive';
|
||||
}
|
||||
|
||||
$html = '
|
||||
<ul class="livestats">
|
||||
<li><span class="title">Done</span><sub>'.$completedTorrents.' / '.$torrentCount.'</sub></li>
|
||||
<li><span class="title">Down</span><sub>'.format_bytes($rateDownload).'</sub></li>
|
||||
<li><span class="title">Up</span><sub>'.format_bytes($rateUpload).'</sub></li>
|
||||
</ul>
|
||||
';
|
||||
return json_encode(['status' => $active, 'html' => $html]);;
|
||||
}
|
||||
|
||||
private function sendRequest()
|
||||
{
|
||||
$optionsSet = $this->setClientOptions();
|
||||
if (! $optionsSet) {
|
||||
// Pass the failed response back up the chain
|
||||
return null;
|
||||
}
|
||||
$res = $this->torrentGet();
|
||||
if ($res->getStatusCode() == 409) {
|
||||
$this->setClientOptions();
|
||||
$res = $this->torrentGet();
|
||||
}
|
||||
return $res;
|
||||
}
|
||||
|
||||
private function torrentGet()
|
||||
{
|
||||
$res = null;
|
||||
try{
|
||||
$res = $this->_client->request(
|
||||
'POST',
|
||||
$this->getApiUrl(),
|
||||
$this->_clientOptions
|
||||
);
|
||||
}catch(\GuzzleHttp\Exception\BadResponseException $e){
|
||||
Log::error("Connection to {$e->getRequest()->getUrl()} failed");
|
||||
Log::debug($e->getMessage());
|
||||
$res = $e->getRequest();
|
||||
}catch(\GuzzleHttp\Exception\ConnectException $e) {
|
||||
Log::error("Transmission connection refused");
|
||||
Log::debug($e->getMessage());
|
||||
}
|
||||
return $res;
|
||||
}
|
||||
|
||||
private function setClientOptions()
|
||||
{
|
||||
if ($this->config->username != '' || $this->config->password != '') {
|
||||
$this->_clientOptions = ['auth'=> [$this->config->username, $this->config->password, 'Basic']];
|
||||
}
|
||||
try{
|
||||
$res = $this->_client->request('HEAD', $this->getApiUrl(), $this->_clientOptions);
|
||||
$xtId = $res->getHeaderLine('X-Transmission-Session-Id');
|
||||
if ($xtId != null) {
|
||||
$this->_clientOptions['headers'] = ['X-Transmission-Session-Id' => $xtId];
|
||||
} else {
|
||||
Log::error("Unable to get Transmission session information");
|
||||
Log::debug("Status Code: ".$res->getStatusCode());
|
||||
}
|
||||
}catch(\GuzzleHttp\Exception\ConnectException $e){
|
||||
Log::error("Failed connection to Transmission");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private function getApiUrl()
|
||||
{
|
||||
$config = $this->config;
|
||||
$url = $config->url;
|
||||
|
||||
$url = rtrim($url, '/');
|
||||
$api_url = $url.'/transmission/rpc';
|
||||
|
||||
return $api_url;
|
||||
}
|
||||
}
|
||||
12
app/SupportedApps/Ttrss.php
Normal file
@@ -0,0 +1,12 @@
|
||||
<?php namespace App\SupportedApps;
|
||||
|
||||
class Ttrss implements Contracts\Applications {
|
||||
public function defaultColour()
|
||||
{
|
||||
return '#9d704c';
|
||||
}
|
||||
public function icon()
|
||||
{
|
||||
return 'supportedapps/tt-rss.png';
|
||||
}
|
||||
}
|
||||
12
app/SupportedApps/Unifi.php
Normal file
@@ -0,0 +1,12 @@
|
||||
<?php namespace App\SupportedApps;
|
||||
|
||||
class Unifi implements Contracts\Applications {
|
||||
public function defaultColour()
|
||||
{
|
||||
return '#363840';
|
||||
}
|
||||
public function icon()
|
||||
{
|
||||
return 'supportedapps/unifi.png';
|
||||
}
|
||||
}
|
||||
12
app/SupportedApps/Unraid.php
Normal file
@@ -0,0 +1,12 @@
|
||||
<?php namespace App\SupportedApps;
|
||||
|
||||
class Unraid implements Contracts\Applications {
|
||||
public function defaultColour()
|
||||
{
|
||||
return '#3B5E1F';
|
||||
}
|
||||
public function icon()
|
||||
{
|
||||
return 'supportedapps/unraid.png';
|
||||
}
|
||||
}
|
||||
11
app/SupportedApps/Watcher3.php
Normal file
@@ -0,0 +1,11 @@
|
||||
<?php namespace App\SupportedApps;
|
||||
class Watcher3 implements Contracts\Applications {
|
||||
public function defaultColour()
|
||||
{
|
||||
return '#500';
|
||||
}
|
||||
public function icon()
|
||||
{
|
||||
return 'supportedapps/watcher3.png';
|
||||
}
|
||||
}
|
||||
11
app/SupportedApps/WebTools.php
Normal file
@@ -0,0 +1,11 @@
|
||||
<?php namespace App\SupportedApps;
|
||||
class WebTools implements Contracts\Applications {
|
||||
public function defaultColour()
|
||||
{
|
||||
return '#555';
|
||||
}
|
||||
public function icon()
|
||||
{
|
||||
return 'supportedapps/webtools.png';
|
||||
}
|
||||
}
|
||||
11
app/SupportedApps/pyLoad.php
Normal file
@@ -0,0 +1,11 @@
|
||||
<?php namespace App\SupportedApps;
|
||||
class pyLoad implements Contracts\Applications {
|
||||
public function defaultColour()
|
||||
{
|
||||
return '#881';
|
||||
}
|
||||
public function icon()
|
||||
{
|
||||
return 'supportedapps/pyload.png';
|
||||
}
|
||||
}
|
||||
12
app/SupportedApps/ruTorrent.php
Normal file
@@ -0,0 +1,12 @@
|
||||
<?php namespace App\SupportedApps;
|
||||
|
||||
class ruTorrent implements Contracts\Applications {
|
||||
public function defaultColour()
|
||||
{
|
||||
return '#004';
|
||||
}
|
||||
public function icon()
|
||||
{
|
||||
return 'supportedapps/rutorrent.png';
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,7 @@
|
||||
"require": {
|
||||
"php": ">=7.0.0",
|
||||
"fideloper/proxy": "~3.3",
|
||||
"guzzlehttp/guzzle": "^6.3",
|
||||
"laravel/framework": "5.5.*",
|
||||
"laravel/tinker": "~1.0",
|
||||
"laravelcollective/html": "^5.5"
|
||||
@@ -23,6 +24,9 @@
|
||||
"database/seeds",
|
||||
"database/factories"
|
||||
],
|
||||
"files": [
|
||||
"app/Helper.php"
|
||||
],
|
||||
"psr-4": {
|
||||
"App\\": "app/"
|
||||
}
|
||||
|
||||
724
composer.lock
generated
@@ -14,7 +14,7 @@ return [
|
||||
*/
|
||||
|
||||
'name' => env('APP_NAME', 'Heimdall'),
|
||||
'version' => '1.1.0',
|
||||
'version' => '1.4.14',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
|
||||
3698
css/app.css
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
|
||||
class AddColumnsToItemsForGroups extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('items', function (Blueprint $table) {
|
||||
$table->integer('type')->default(0)->index(); // 0 = item, 1 = category
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('items', function (Blueprint $table) {
|
||||
$table->dropColumn(['type']);
|
||||
});
|
||||
}
|
||||
}
|
||||
35
database/migrations/2018_02_16_193703_item_tag.php
Normal file
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
|
||||
class ItemTag extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('item_tag', function (Blueprint $table) {
|
||||
$table->integer('item_id')->unsigned()->index();
|
||||
$table->foreign('item_id')->references('id')->on('items')->onDelete('cascade');
|
||||
|
||||
$table->integer('tag_id')->unsigned()->index();
|
||||
$table->foreign('tag_id')->references('id')->on('items')->onDelete('cascade');
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('item_tag');
|
||||
}
|
||||
}
|
||||
@@ -14,29 +14,39 @@ class SettingsSeeder extends Seeder
|
||||
public function run()
|
||||
{
|
||||
// Groups
|
||||
if(!SettingGroup::find(1)) {
|
||||
if(!$setting_group = SettingGroup::find(1)) {
|
||||
$setting_group = new SettingGroup;
|
||||
$setting_group->id = 1;
|
||||
$setting_group->title = 'System';
|
||||
$setting_group->title = 'app.settings.system';
|
||||
$setting_group->order = 0;
|
||||
$setting_group->save();
|
||||
}
|
||||
if(!SettingGroup::find(2)) {
|
||||
$setting_group = new SettingGroup;
|
||||
$setting_group->id = 2;
|
||||
$setting_group->title = 'Appearance';
|
||||
$setting_group->order = 1;
|
||||
} else {
|
||||
$setting_group->title = 'app.settings.system';
|
||||
$setting_group->save();
|
||||
}
|
||||
if(!SettingGroup::find(3)) {
|
||||
if(!$setting_group = SettingGroup::find(2)) {
|
||||
$setting_group = new SettingGroup;
|
||||
$setting_group->id = 2;
|
||||
$setting_group->title = 'app.settings.appearance';
|
||||
$setting_group->order = 1;
|
||||
$setting_group->save();
|
||||
} else {
|
||||
$setting_group->title = 'app.settings.appearance';
|
||||
$setting_group->save();
|
||||
}
|
||||
if(!$setting_group = SettingGroup::find(3)) {
|
||||
$setting_group = new SettingGroup;
|
||||
$setting_group->id = 3;
|
||||
$setting_group->title = 'Miscellaneous';
|
||||
$setting_group->title = 'app.settings.miscellaneous';
|
||||
$setting_group->order = 2;
|
||||
$setting_group->save();
|
||||
} else {
|
||||
$setting_group->title = 'app.settings.miscellaneous';
|
||||
$setting_group->save();
|
||||
}
|
||||
|
||||
if($version = Setting::find(1)) {
|
||||
$version->label = 'app.settings.version';
|
||||
$version->value = config('app.version');
|
||||
$version->save();
|
||||
} else {
|
||||
@@ -45,37 +55,46 @@ class SettingsSeeder extends Seeder
|
||||
$setting->group_id = 1;
|
||||
$setting->key = 'version';
|
||||
$setting->type = 'text';
|
||||
$setting->label = 'Version';
|
||||
$setting->label = 'app.settings.version';
|
||||
$setting->value = config('app.version');
|
||||
$setting->system = true;
|
||||
$setting->save();
|
||||
}
|
||||
|
||||
if(!Setting::find(2)) {
|
||||
if(!$setting = Setting::find(2)) {
|
||||
$setting = new Setting;
|
||||
$setting->id = 2;
|
||||
$setting->group_id = 2;
|
||||
$setting->key = 'background_image';
|
||||
$setting->type = 'image';
|
||||
$setting->label = 'Background Image';
|
||||
$setting->label = 'app.settings.background_image';
|
||||
$setting->save();
|
||||
} else {
|
||||
$setting->label = 'app.settings.background_image';
|
||||
$setting->save();
|
||||
}
|
||||
if(!Setting::find(3)) {
|
||||
if(!$setting = Setting::find(3)) {
|
||||
$setting = new Setting;
|
||||
$setting->id = 3;
|
||||
$setting->group_id = 3;
|
||||
$setting->key = 'homepage_search';
|
||||
$setting->type = 'boolean';
|
||||
$setting->label = 'Homepage Search';
|
||||
$setting->label = 'app.settings.homepage_search';
|
||||
$setting->save();
|
||||
} else {
|
||||
$setting->label = 'app.settings.homepage_search';
|
||||
$setting->save();
|
||||
}
|
||||
if(!Setting::find(4)) {
|
||||
$options = json_encode([
|
||||
'none' => '- not set -',
|
||||
'google' => 'Google',
|
||||
'ddg' => 'DuckDuckGo',
|
||||
'bing' => 'Bing'
|
||||
]);
|
||||
|
||||
$options = json_encode([
|
||||
'none' => 'app.options.none',
|
||||
'google' => 'app.options.google',
|
||||
'ddg' => 'app.options.ddg',
|
||||
'bing' => 'app.options.bing',
|
||||
'startpage' => 'app.options.startpage',
|
||||
]);
|
||||
|
||||
if(!$setting = Setting::find(4)) {
|
||||
|
||||
$setting = new Setting;
|
||||
$setting->id = 4;
|
||||
@@ -83,9 +102,63 @@ class SettingsSeeder extends Seeder
|
||||
$setting->key = 'search_provider';
|
||||
$setting->type = 'select';
|
||||
$setting->options = $options;
|
||||
$setting->label = 'Search Provider';
|
||||
$setting->label = 'app.settings.search_provider';
|
||||
$setting->save();
|
||||
} else {
|
||||
$setting->options = $options;
|
||||
$setting->label = 'app.settings.search_provider';
|
||||
$setting->save();
|
||||
}
|
||||
|
||||
|
||||
$language_options = json_encode([
|
||||
'de' => 'Deutsch (German)',
|
||||
'en' => 'English',
|
||||
'fi' => 'Suomi (Finnish)',
|
||||
'fr' => 'Français (French)',
|
||||
'it' => 'Italiano (Italian)',
|
||||
'no' => 'Norsk (Norwegian)',
|
||||
'pl' => 'Polski (Polish)',
|
||||
'sv' => 'Svenska (Swedish)',
|
||||
'es' => 'Español (Spanish)',
|
||||
'tr' => 'Türkçe (Turkish)',
|
||||
]);
|
||||
if($languages = Setting::find(5)) {
|
||||
$languages->options = $language_options;
|
||||
$languages->save();
|
||||
} else {
|
||||
$setting = new Setting;
|
||||
$setting->id = 5;
|
||||
$setting->group_id = 1;
|
||||
$setting->key = 'language';
|
||||
$setting->type = 'select';
|
||||
$setting->label = 'app.settings.language';
|
||||
$setting->options = $language_options;
|
||||
$setting->value = 'en';
|
||||
$setting->save();
|
||||
}
|
||||
|
||||
$window_target_options = json_encode([
|
||||
'current' => 'app.settings.window_target.current',
|
||||
'heimdall' => 'app.settings.window_target.one',
|
||||
'_blank' => 'app.settings.window_target.new',
|
||||
]);
|
||||
|
||||
if(!$setting = Setting::find(7)) {
|
||||
|
||||
$setting = new Setting;
|
||||
$setting->id = 7;
|
||||
$setting->group_id = 3;
|
||||
$setting->key = 'window_target';
|
||||
$setting->type = 'select';
|
||||
$setting->options = $window_target_options;
|
||||
$setting->label = 'app.settings.window_target';
|
||||
$setting->value = 'heimdall';
|
||||
$setting->save();
|
||||
} else {
|
||||
$setting->options = $window_target_options;
|
||||
$setting->label = 'app.settings.window_target';
|
||||
$setting->save();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
3
mix-manifest.json
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"/css/app.css": "/css/app.css"
|
||||
}
|
||||
9568
package-lock.json
generated
@@ -12,13 +12,13 @@
|
||||
"devDependencies": {
|
||||
"axios": "^0.17",
|
||||
"bootstrap-sass": "^3.3.7",
|
||||
"cross-env": "^5.1.3",
|
||||
"cross-env": "^5.1",
|
||||
"jquery": "^3.2",
|
||||
"laravel-mix": "^1.0",
|
||||
"laravel-mix": "^2.0",
|
||||
"lodash": "^4.17.4",
|
||||
"vue": "^2.5.7"
|
||||
},
|
||||
"dependencies": {
|
||||
"node-sass": "^4.7.2"
|
||||
"select2": "^4.0.6-rc.1"
|
||||
}
|
||||
}
|
||||
|
||||
BIN
public/android-icon-144x144.png
generated
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
public/android-icon-192x192.png
generated
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
public/android-icon-36x36.png
generated
Normal file
|
After Width: | Height: | Size: 2.1 KiB |
BIN
public/android-icon-48x48.png
generated
Normal file
|
After Width: | Height: | Size: 2.5 KiB |
BIN
public/android-icon-72x72.png
generated
Normal file
|
After Width: | Height: | Size: 5.1 KiB |
BIN
public/android-icon-96x96.png
generated
Normal file
|
After Width: | Height: | Size: 7.1 KiB |
BIN
public/apple-icon-114x114.png
generated
Normal file
|
After Width: | Height: | Size: 8.6 KiB |
BIN
public/apple-icon-120x120.png
generated
Normal file
|
After Width: | Height: | Size: 9.1 KiB |
BIN
public/apple-icon-144x144.png
generated
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
public/apple-icon-152x152.png
generated
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
public/apple-icon-180x180.png
generated
Normal file
|
After Width: | Height: | Size: 15 KiB |
BIN
public/apple-icon-57x57.png
generated
Normal file
|
After Width: | Height: | Size: 3.0 KiB |
BIN
public/apple-icon-60x60.png
generated
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
BIN
public/apple-icon-72x72.png
generated
Normal file
|
After Width: | Height: | Size: 5.1 KiB |
BIN
public/apple-icon-76x76.png
generated
Normal file
|
After Width: | Height: | Size: 5.4 KiB |
BIN
public/apple-icon-precomposed.png
generated
Normal file
|
After Width: | Height: | Size: 15 KiB |
BIN
public/apple-icon.png
generated
Normal file
|
After Width: | Height: | Size: 15 KiB |
2
public/browserconfig.xml
generated
Normal file
@@ -0,0 +1,2 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<browserconfig><msapplication><tile><square70x70logo src="/ms-icon-70x70.png"/><square150x150logo src="/ms-icon-150x150.png"/><square310x310logo src="/ms-icon-310x310.png"/><TileColor>#ffffff</TileColor></tile></msapplication></browserconfig>
|
||||
940
public/css/app.css
vendored
BIN
public/favicon-16x16.png
generated
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
public/favicon-32x32.png
generated
Normal file
|
After Width: | Height: | Size: 1.9 KiB |