Compare commits

...

190 Commits

Author SHA1 Message Date
KodeStar
1745100705 fix @CHBMB 's fsckup 2018-04-25 22:58:14 +01:00
KodeStar
28501944c5 Merge pull request #172 from CHBMB/master
Add StartPage support
2018-04-25 22:46:50 +01:00
chbmb
c5c1a68f5c Merge pull request #3 from CHBMB/patch-4
Update SettingsSeeder.php
2018-04-25 22:41:54 +01:00
chbmb
e2ed7fbd28 Merge pull request #2 from CHBMB/patch-3
Update app.php
2018-04-25 22:41:36 +01:00
chbmb
ab0675055c Merge pull request #1 from CHBMB/patch-2
Update Setting.php
2018-04-25 22:41:14 +01:00
chbmb
2b65559f36 Update SettingsSeeder.php 2018-04-25 22:40:15 +01:00
chbmb
b8beb07df5 Update app.php 2018-04-25 22:39:29 +01:00
chbmb
01748fec49 Update Setting.php 2018-04-25 22:38:30 +01:00
KodeStar
42a50b1a02 Merge pull request #169 from ferrymanders/master
AllowOverride explained for apache .htaccess
2018-04-17 09:03:41 +01:00
Ferry Manders
d81595f43f AllowOverride explained for apache .htaccess
added extra example so users have a reference
2018-04-12 10:36:45 +02:00
Ferry Manders
71fa2d867f AllowOverride explained for apache .htaccess
In some apache installations .htaccess is disallowed by default. explained a few fixes/work arounds.
2018-04-12 10:32:32 +02:00
KodeStar
f55dbb0002 Merge pull request #165 from kimpenhaus/master
added autofocus to search input #149
2018-04-11 15:02:19 +01:00
KodeStar
3e4d623786 Update readme.md 2018-04-06 09:13:30 +01:00
KodeStar
1b109aac3a Merge pull request #166 from halorrr/patch-1
SupportedApp: Syncthing
2018-04-06 09:02:50 +01:00
KodeStar
8558975d55 Merge pull request #164 from albertsj1/fix_cp_icon
fix couchpotato icon capitalization
2018-04-04 09:45:20 +01:00
halorrr
0e895089c7 Create Syncthing.php 2018-04-04 01:31:43 -04:00
halorrr
5dd44f66c1 Update Item.php 2018-04-04 01:26:08 -04:00
halorrr
a1cfea46c6 Add files via upload 2018-04-04 07:25:18 +02:00
halorrr
42c492c85a Update readme.md 2018-04-04 01:24:07 -04:00
Marcus Kimpenhaus
9e8794a39f added autofocus to search input #149 2018-04-02 11:13:49 +02:00
John Alberts
66c3604b2a fix couchpotato icon capitalization 2018-03-31 22:29:59 -07:00
KodeStar
c0ee1ee27b Update app.php 2018-03-27 10:57:49 +01:00
KodeStar
a3e669e433 Merge pull request #162 from halorrr/master
Bug Fix On Newly Added Apps
2018-03-27 10:52:29 +01:00
halorrr
8a83b4fff5 Capitalized first letter of filename to fix link 2018-03-26 09:29:26 -04:00
halorrr
69c48d3f5d Deleted extra space at beginning of file 2018-03-26 09:28:53 -04:00
halorrr
88504a335e Deleted extra space at beginning of file 2018-03-26 09:28:39 -04:00
halorrr
a44a433807 Deleted extra space at beginning of file 2018-03-26 09:28:26 -04:00
halorrr
9c03a8ae28 Deleted extra space at beginning of file 2018-03-26 09:28:12 -04:00
halorrr
767a5f3a94 Deleted extra space at beginning of file 2018-03-26 09:27:57 -04:00
halorrr
db1e138d36 Deleted extra space at beginning of file 2018-03-26 09:27:36 -04:00
halorrr
84aa05f9a9 Deleted extra space at beginning of file 2018-03-26 09:27:19 -04:00
KodeStar
1071b85472 Merge pull request #160 from LiamAkkerman/master
SupportedApp: Grafana
2018-03-26 08:34:56 +01:00
KodeStar
479412b190 Merge pull request #157 from halorrr/patch-2
SupportedApp: Cardigann
2018-03-26 08:34:26 +01:00
KodeStar
ac4fc5b0ba Merge pull request #156 from halorrr/patch-1
SupportedApp: pyLoad
2018-03-26 08:33:28 +01:00
KodeStar
4a8770232d Merge pull request #158 from rigrassm/mobile-app-compatible
Add html needed to allow the site to load as a mobile app
2018-03-26 08:31:40 +01:00
Liam B. Akkerman
2ea983bdae rename grafana icon file 2018-03-24 21:40:52 -07:00
Liam B. Akkerman
ffce8fa505 add grafana to readme 2018-03-24 21:37:07 -07:00
Liam B. Akkerman
cb9e529eb7 add grafana to Item.php 2018-03-24 21:35:23 -07:00
Liam B. Akkerman
7f0ee208fa add grafana icon 2018-03-24 21:29:46 -07:00
Liam B. Akkerman
2d38652034 add grafana app php 2018-03-24 21:23:15 -07:00
Ricky Grassmuck
4a2076a550 One more indentation fix
This time I really did fix it I swear!
2018-03-23 18:25:36 -05:00
Ricky Grassmuck
35049b26fe Fix Indentation
Fixed indentation of newly added lines to match existing lines.
2018-03-23 18:24:40 -05:00
Ricky Grassmuck
39648ba372 Add html needed to allow the site to load as a mobile app 2018-03-23 18:11:04 -05:00
KodeStar
44ce0bbffd Merge pull request #155 from imcdona/master
Document adding a supported application
2018-03-22 15:01:44 +00:00
halorrr
a634472873 Create Cardigann.php 2018-03-21 11:28:30 -04:00
halorrr
a98c30f7fa Update Item.php 2018-03-21 11:25:31 -04:00
halorrr
43d4b80e11 Add files via upload 2018-03-21 16:24:47 +01:00
halorrr
09926fcc53 Update readme.md 2018-03-21 11:24:14 -04:00
halorrr
17eef7a4aa Update pyLoad.php 2018-03-21 11:17:12 -04:00
halorrr
4738d7c951 Create pyLoad.php 2018-03-21 11:07:16 -04:00
halorrr
4be0af5fa3 Update Item.php 2018-03-21 11:06:33 -04:00
halorrr
8aaa0900e5 Add files via upload 2018-03-21 16:05:38 +01:00
halorrr
49b5d9b886 Update readme.md 2018-03-21 11:03:40 -04:00
Isaac McDonald
7a3912767b Document adding a supported application
If you type the name of a supported application quickly enough in the title field, you'll never see the option to select that application from the list. Long term I think this needs to be addressed. In the short term, an explanation will suffice.
2018-03-21 07:52:47 -07:00
KodeStar
d1e473aafe Merge pull request #151 from halorrr/patch-3
SupportedApp: Watcher3
2018-03-21 12:59:41 +00:00
KodeStar
c91eb7ed47 Merge branch 'master' into patch-3 2018-03-21 12:59:21 +00:00
KodeStar
443f631bac Merge pull request #146 from halorrr/patch-1
SupportedApp: AirSonic
2018-03-21 12:57:53 +00:00
KodeStar
95be8d4698 Merge branch 'master' into patch-1 2018-03-21 12:57:39 +00:00
KodeStar
f3926d020f Merge pull request #154 from imcdona/master
Changed pFsense to the proper pfSense. Changed Ttrss to tt-rss
2018-03-21 12:56:13 +00:00
KodeStar
b48eb5fdd3 Merge pull request #153 from albertsj1/better_transmission_icon
New Transmission icon with transparent background
2018-03-21 12:55:41 +00:00
KodeStar
b0fecdd017 Merge pull request #147 from halorrr/patch-2
SupportedApp: OpenVaultMedia
2018-03-21 12:55:08 +00:00
KodeStar
793483b6e9 Merge pull request #145 from halorrr/master
SupportedApp: WebTools
2018-03-21 12:54:21 +00:00
Isaac McDonald
c99c7fa9af Changed pFsense to the proper pfSense. Changed Ttrss to tt-rss 2018-03-20 14:15:01 -07:00
John Alberts
59449a73e1 New Transmission icon with transparent background 2018-03-20 08:31:12 -07:00
halorrr
dc86d636ac Create Watcher3.php 2018-03-18 09:20:39 -04:00
halorrr
27dd2dd5f3 Update Item.php 2018-03-18 09:18:27 -04:00
halorrr
494ae1a47f Add files via upload 2018-03-18 14:17:25 +01:00
halorrr
7d1e1e5ff1 Update readme.md 2018-03-18 09:09:10 -04:00
KodeStar
bcd1567b7d Merge pull request #133 from albertsj1/couchpotato
Add Couchpotato as an enhanced app
2018-03-17 13:18:03 +00:00
KodeStar
ae391b885b added missing dataonly attribute so it polls every 20 seconds 2018-03-17 13:17:45 +00:00
KodeStar
226bc84a4c removed duplicate semi-colon 2018-03-17 13:15:39 +00:00
halorrr
e60a0c8f61 Logo for OpenMediaVault 2018-03-17 07:07:50 +01:00
halorrr
218c90a306 Delete openvaultmedia.png 2018-03-17 02:07:29 -04:00
halorrr
2a60c80194 Create OpenMediaVault.php 2018-03-17 02:06:26 -04:00
halorrr
35b1c55564 Update Item.php 2018-03-17 02:05:32 -04:00
halorrr
20476387ff Add files via upload 2018-03-17 07:04:23 +01:00
halorrr
a787748a00 Update readme.md 2018-03-17 02:03:43 -04:00
halorrr
34ee540c30 Changed default colour for AirSonic 2018-03-17 02:02:35 -04:00
halorrr
975a5ffc82 Create AirSonic.php 2018-03-17 01:52:17 -04:00
halorrr
dee0870bf6 Airsonic added 2018-03-17 01:48:40 -04:00
halorrr
96ec3bd44e Airsonic logo added 2018-03-17 06:47:20 +01:00
halorrr
e4cf4096a6 Adding AirSonic to readme 2018-03-17 01:46:12 -04:00
halorrr
3d79694c0a Create WebTools.php 2018-03-17 01:24:14 -04:00
halorrr
eab3e4e6f7 Update Item.php 2018-03-17 01:19:30 -04:00
halorrr
462152bab2 Update readme.md 2018-03-17 01:17:33 -04:00
halorrr
766a455db0 Add files via upload 2018-03-17 06:16:06 +01:00
John Alberts
30200ac219 Get rid off aggressive polling option and always use inactive status 2018-03-16 15:08:04 -07:00
KodeStar
90a9113971 Merge pull request #140 from halorrr/master
FoundationApp: Krusader closes #144
2018-03-16 22:00:17 +00:00
KodeStar
ad1834568f Merge pull request #141 from halorrr/patch-1
Adding Tautulli to Enhanced Apps
2018-03-16 21:58:19 +00:00
KodeStar
6231500b4a Merge pull request #142 from grOGH/master
Add a readme section about using self-signed certificates with enhanced apps
2018-03-15 13:04:38 +00:00
grOGH
b2dbc08ea0 Add a readme section about using self-signed certificates with enhanced
apps
2018-03-15 08:48:56 +01:00
KodeStar
4700f68f4d Update readme.md 2018-03-13 21:09:59 +00:00
halorrr
fa73738309 Update readme.md 2018-03-13 16:01:44 -04:00
halorrr
25f92ec438 Create tautulli.blade.php 2018-03-13 16:01:14 -04:00
halorrr
6a59c1dfd6 Update Item.php 2018-03-13 15:58:37 -04:00
halorrr
bad6e9d2fe Create Tautulli.php 2018-03-13 15:57:14 -04:00
halorrr
e544972c1d Add files via upload 2018-03-13 20:56:12 +01:00
halorrr
f1e5de0d58 Update readme.md 2018-03-13 15:52:44 -04:00
halorrr
e434e1effb Update readme.md 2018-03-13 15:32:54 -04:00
halorrr
ca04b210e6 Update Item.php 2018-03-13 12:38:29 -04:00
halorrr
51275af41d Create Krusader.php 2018-03-13 12:35:26 -04:00
halorrr
c2417ac5b3 Add files via upload 2018-03-13 17:32:04 +01:00
John Alberts
72831d413b update couchpotato icon 2018-03-13 08:14:18 -07:00
John Alberts
5cb4bd5819 Icon name should be lower case. 2018-03-13 06:49:05 -07:00
KodeStar
2d9bbca9a9 Merge pull request #135 from albertsj1/fix_transmission_pic
Fix capitalization of tranmission icon name
2018-03-13 09:36:29 +00:00
KodeStar
7b54c4e969 Merge pull request #134 from albertsj1/update_readme
add some apps to the enhanced app section of the readme that were mis…
2018-03-13 09:35:54 +00:00
Chris
b50f4ec5ce Merge branch 'master' of https://github.com/linuxserver/Heimdall 2018-03-12 09:59:43 +00:00
Chris
86cc7534c2 fix html error in link, but replaced target _blank to a named window to keep the experience 2018-03-12 09:59:37 +00:00
John Alberts
1ab2565244 Fix capitalization of tranmission icon name 2018-03-11 21:23:01 -07:00
John Alberts
d2089a9344 add some apps to the enhanced app section of the readme that were missing. 2018-03-11 21:12:25 -07:00
John Alberts
39153c6936 Add Couchpotato as an enhanced app 2018-03-11 20:48:58 -07:00
KodeStar
1a8e2b92de closes #128 2018-03-11 17:47:05 +00:00
KodeStar
cf63e751bf Merge pull request #127 from albertsj1/add_transmission
Add Enhanced App Transmission
2018-03-11 17:41:02 +00:00
KodeStar
0c51bc2771 fix multiple tags 2018-03-11 17:40:08 +00:00
John Alberts
5f278cce3e cleanup a couple symlinks I didn't intend to commit and some errant whitespace 2018-03-09 07:59:01 -08:00
KodeStar
f8cf3ac832 Merge pull request #125 from frenos/foundation_glances
Foundation App for Glances
2018-03-09 08:05:07 +00:00
John Alberts
50bdd02a72 Add Enhanced App Transmission 2018-03-08 16:18:39 -08:00
frenos
424155e5cd Foundation App for Glances
Default color is the backgroundcolor of the official site.
2018-03-07 17:39:45 +01:00
Chris
c4a4d25f7e change js version to break cache 2018-03-06 09:43:54 +00:00
KodeStar
ca2e135cba closes #122, closes #82, 2018-03-05 19:38:23 +00:00
KodeStar
8b4583c59c update version 2018-03-01 19:21:18 +00:00
KodeStar
6a836f9151 Merge pull request #118 from Futos/add-new-foundationApps
Add new foundation apps
2018-03-01 10:16:43 +00:00
Futos
c7b92ad945 fix(SupportedApps): fixed class name 2018-02-28 13:04:45 +01:00
Futos
a05b7a43bd feat(SupportedApps): Added DokuWiki to Foundation Apps
Closes #104
2018-02-28 13:03:17 +01:00
Futos
929346b2f1 feat(SupportedApps): Added SickRage to Foundation Apps
Closes #102
2018-02-28 12:58:00 +01:00
Futos
23ceed01cb feat(SupportedApps): Added Gitea to Foundation Apps
Closes #101
2018-02-28 12:52:11 +01:00
KodeStar
2ccf9a1110 Merge pull request #115 from mrquatsch/runeaudio
Add Runeaudio to list of foundation apps
2018-02-26 12:02:35 +00:00
mrquatsch
4917d8e47b updated runeaudio scss to bump keyframes outside of the title-marquee 2018-02-25 20:44:24 -06:00
mrquatsch
a0963e5d92 add Runeaudio to app/Item list 2018-02-25 20:41:19 -06:00
KodeStar
e2731b532a Update readme.md 2018-02-25 20:26:33 +00:00
KodeStar
eccd6056bd Merge pull request #112 from mrquatsch/runeaudio
enhanced runeaudio app - displays artist and song
2018-02-25 16:39:20 +00:00
mrquatsch
c1273a4b01 new rune scss - imported in app.scss 2018-02-25 08:23:45 -06:00
KodeStar
017752b06e Merge pull request #113 from Ephelyon/master
Add Dutch translation
2018-02-25 11:45:13 +00:00
KodeStar
9abb7a04ac Merge pull request #114 from mrquatsch/patch-1
Rename plexpy.blade.app to plexpy.blade.php
2018-02-25 11:44:37 +00:00
mrquatsch
9533b9d887 Rename plexpy.blade.app to plexpy.blade.php 2018-02-24 13:58:54 -06:00
Ephelyon
f1a6feeb8f Add Dutch translation 2018-02-24 18:54:31 +00:00
KodeStar
35930f2ffb Merge pull request #111 from mrquatsch/enhanced_plexpy
Enhanced Plexpy - display stream count via api token
2018-02-23 11:18:56 +00:00
mrquatsch
0a1e8a2f8b enhanced runeaudio app - displays artist and song 2018-02-22 13:41:30 -06:00
mrquatsch
4f9315132b Enhanced Plexpy - display stream count via api token 2018-02-22 13:27:44 -06:00
KodeStar
196a843148 Merge pull request #105 from Attoy/master
Update readme.md
2018-02-20 12:23:21 +00:00
KodeStar
9778875d52 Merge branch 'master' into master 2018-02-20 12:23:10 +00:00
KodeStar
fdeb812333 Merge pull request #106 from kehator/master
Add PL translation
2018-02-20 11:51:35 +00:00
KodeStar
e21e12e737 Update SettingsSeeder.php 2018-02-20 11:51:18 +00:00
nuc
52d2322955 Rough translation based on EN translation 2018-02-20 05:40:50 +00:00
KodeStar
5ea8f7df33 Fix target link 2018-02-19 23:15:09 +00:00
Attoy
7a9c73df3f Update readme.md 2018-02-19 20:18:46 +01:00
KodeStar
1f38de989b fix routes 2018-02-18 22:36:32 +00:00
KodeStar
c4f119de9c Fix routes in controllers for RP support 2018-02-18 22:15:14 +00:00
KodeStar
fa2afa856a change release number 2018-02-18 19:23:17 +00:00
KodeStar
4c83680ae9 remove apps from tags 2018-02-18 19:21:42 +00:00
KodeStar
981665e3e3 Update readme.md 2018-02-18 19:04:19 +00:00
KodeStar
b3185292b3 Merge pull request #100 from linuxserver/v1.4
fixes to RP
2018-02-18 18:39:35 +00:00
KodeStar
249f437ff5 fixes to RP 2018-02-18 18:38:43 +00:00
KodeStar
a7563ab499 Merge pull request #99 from linuxserver/v1.4
V1.4
2018-02-18 17:51:26 +00:00
KodeStar
38f8143fd2 closes #46, #47, #77, #89 2018-02-18 17:48:52 +00:00
KodeStar
a051c17010 style the tags + close #47 2018-02-18 17:23:05 +00:00
KodeStar
0b62f8a1c8 change icon for tags 2018-02-18 17:04:18 +00:00
KodeStar
b803d4f49d fix mix 2018-02-17 23:18:20 +00:00
KodeStar
78e368f406 Merge branch 'master' into v1.4 2018-02-17 23:17:34 +00:00
KodeStar
90e613ab26 Update readme.md 2018-02-17 23:15:07 +00:00
KodeStar
e15914dc2e Update readme.md 2018-02-17 23:09:21 +00:00
KodeStar
ebe6c39237 Closes #86 2018-02-17 22:23:30 +00:00
KodeStar
3369de9660 possible fix for RP for forms 2018-02-17 20:37:23 +00:00
KodeStar
98b831bc22 folder support 2018-02-17 00:13:38 +00:00
KodeStar
c0f741d914 Merge pull request #95 from cheesemarathon/master
feat: added Deluge to supported Apps - Closes #70
2018-02-16 17:37:35 +00:00
KodeStar
4c27a0cb5c Update Item.php 2018-02-16 17:37:09 +00:00
KodeStar
4ff5f139f7 fix indentation 2018-02-16 17:36:36 +00:00
cheesemarathon
59910ecadc Add Graylog 2018-02-16 16:28:48 +00:00
Chris
4e37176436 changes to allow preview of image first 2018-02-16 15:27:48 +00:00
Chris
35085248b6 some changes to test droppable 2018-02-16 15:15:22 +00:00
nuc
3ad8a366a6 Add Polish Translation 2018-02-16 11:22:11 +00:00
KodeStar
b1660c92cc changed opening a link to new tab 2018-02-15 20:52:04 +00:00
KodeStar
6ec1a3d4cb Merge pull request #90 from Futos/adding-new-foundation-apps
Adding new foundation apps
2018-02-15 20:45:57 +00:00
KodeStar
86ffa86800 Merge branch 'master' into adding-new-foundation-apps 2018-02-15 20:45:08 +00:00
KodeStar
22ad29c92f crap image 2018-02-15 20:42:53 +00:00
KodeStar
ebc1046ba6 Merge pull request #88 from cheesemarathon/master
feat: added Deluge to supported Apps - Closes #63
2018-02-15 20:41:50 +00:00
KodeStar
43e23b15dc update version 2018-02-15 20:33:36 +00:00
KodeStar
c8effe757b fix for nzbget on new apps 2018-02-15 20:33:07 +00:00
Futos
40b5cd3cff feat(SupportedApps): added TT-RSS Application to Foundation Apps
Closes #72
2018-02-15 19:59:53 +01:00
Futos
26435d85e8 feat(SupportedApps): added NZBHydra Application to Foundation Apps
Closes #66
2018-02-15 19:51:38 +01:00
Futos
b6d5e73708 feat(SupportedApps): added Deluge Application to Foundation Apps
Closes #63
2018-02-15 19:32:10 +01:00
Futos
2f193e0c83 feat(SupportedApps): added Medusa Application to Foundation Apps
Closes #64
2018-02-15 19:25:37 +01:00
Futos
4897c80646 feat(.gitignore): added MacOS generated files to ignore 2018-02-15 19:23:57 +01:00
cheesemarathon
601a455e08 Add Deluge 2018-02-15 15:03:41 +00:00
KodeStar
d37f4fd77b Merge pull request #84 from cheesemarathon/master
feat: added ruTorrent to supported Apps - Closes #35
2018-02-15 14:07:37 +00:00
cheesemarathon
c395cb2206 Replace with better logo 2018-02-15 14:01:18 +00:00
cheesemarathon
b6f8c612f1 Removes icon background 2018-02-15 08:36:19 +00:00
cheesemarathon
18551528ca Removes icon background 2018-02-15 08:27:34 +00:00
cheesemarathon
bbc7782f40 Adds ruTorrent 2018-02-15 08:22:37 +00:00
KodeStar
c121341911 Update readme.md 2018-02-15 08:22:14 +00:00
116 changed files with 7311 additions and 115 deletions

16
.gitignore vendored
View File

@@ -9,4 +9,18 @@ Homestead.yaml
npm-debug.log
yarn-error.log
storage/app/public/.DS_Store
### 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

View File

@@ -1,5 +1,20 @@
# 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

View File

@@ -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);
}
@@ -146,9 +150,12 @@ class ItemController extends Controller
//die(print_r($request->input('config')));
Item::create($request->all());
$item = Item::create($request->all());
return redirect()->route('dash')
$item->parents()->sync($request->tags);
$route = route('dash', [], false);
return redirect($route)
->with('success', __('app.alert.success.item_created'));
}
@@ -172,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);
}
/**
@@ -205,9 +213,13 @@ class ItemController extends Controller
'description' => $config
]);
Item::find($id)->update($request->all());
$item = Item::find($id);
$item->update($request->all());
return redirect()->route('dash')
$item->parents()->sync($request->tags);
$route = route('dash', [], false);
return redirect($route)
->with('success',__('app.alert.success.item_updated'));
}
@@ -228,8 +240,9 @@ class ItemController extends Controller
} else {
Item::find($id)->delete();
}
return redirect()->route('items.index')
$route = route('items.index', [], false);
return redirect($route)
->with('success',__('app.alert.success.item_deleted'));
}
@@ -244,8 +257,10 @@ class ItemController extends Controller
//
Item::withTrashed()
->where('id', $id)
->restore();
return redirect()->route('items.index')
->restore();
$route = route('items.inded', [], false);
return redirect($route)
->with('success',__('app.alert.success.item_restored'));
}

View File

@@ -39,7 +39,9 @@ class SettingsController extends Controller
'setting' => $setting,
]);
} else {
return redirect()->route('settings.list')->with([
$route = route('settings.list', [], false);
return redirect($route)
->with([
'error' => __('app.alert.error.not_exist'),
]);
}
@@ -73,11 +75,15 @@ class SettingsController extends Controller
$setting->save();
return redirect()->route('settings.index')->with([
$route = route('settings.index', [], false);
return redirect($route)
->with([
'success' => __('app.alert.success.setting_updated'),
]);
} else {
return redirect()->route('settings.index')->with([
$route = route('settings.index', [], false);
return redirect($route)
->with([
'error' => __('app.alert.error.not_exist'),
]);
}
@@ -94,7 +100,9 @@ class SettingsController extends Controller
$setting->value = '';
$setting->save();
}
return redirect()->route('settings.index')->with([
$route = route('settings.index', [], false);
return redirect($route)
->with([
'success' => __('app.alert.success.setting_updated'),
]);

View 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;
}
}

View File

@@ -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,19 +26,32 @@ class Item extends Model
public static function supportedList()
{
return [
'AirSonic' => \App\SupportedApps\AirSonic::class,
'Cardigann' => \App\SupportedApps\Cardigann::class,
'CouchPotato' => \App\SupportedApps\CouchPotato::class,
'Deluge' => \App\SupportedApps\Deluge::class,
'Dokuwiki' => \App\SupportedApps\Dokuwiki::class,
'Duplicati' => \App\SupportedApps\Duplicati::class,
'Emby' => \App\SupportedApps\Emby::class,
'Gitea' => \App\SupportedApps\Gitea::class,
'Glances' => \App\SupportedApps\Glances::class,
'Grafana' => \App\SupportedApps\Grafana::class,
'Graylog' => \App\SupportedApps\Graylog::class,
'Home Assistant' => \App\SupportedApps\HomeAssistant::class,
'Jackett' => \App\SupportedApps\Jackett::class,
'Jdownloader' => \App\SupportedApps\Jdownloader::class,
'Krusader' => \App\SupportedApps\Krusader::class,
'Lidarr' => \App\SupportedApps\Lidarr::class,
'Mcmyadmin' => \App\SupportedApps\Mcmyadmin::class,
'Nextcloud' => \App\SupportedApps\Nextcloud::class,
'Medusa' => \App\SupportedApps\Medusa::class,
'NZBGet' => \App\SupportedApps\Nzbget::class,
'Openhab' => \App\SupportedApps\Openhab::class,
'pFsense' => \App\SupportedApps\Pfsense::class,
'Netdata' => \App\SupportedApps\Netdata::class,
'Nextcloud' => \App\SupportedApps\Nextcloud::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,
@@ -46,10 +59,21 @@ class Item extends Model
'Portainer' => \App\SupportedApps\Portainer::class,
'Proxmox' => \App\SupportedApps\Proxmox::class,
'Radarr' => \App\SupportedApps\Radarr::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,
'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()
@@ -109,4 +133,73 @@ class Item extends Model
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()
{
if((int)$this->type === 1) {
return '';
} else {
return ' target="heimdallapp"';
}
}
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);
}
}

View File

@@ -33,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

View File

@@ -202,11 +202,14 @@ 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).' '.__('app.settings.search').'...']);
$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();

View 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';
}
}

View 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';
}
}

View 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;
}
}

View File

@@ -0,0 +1,12 @@
<?php namespace App\SupportedApps;
class Deluge implements Contracts\Applications {
public function defaultColour()
{
return '#357';
}
public function icon()
{
return 'supportedapps/deluge.png';
}
}

View 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';
}
}

View 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';
}
}

View 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';
}
}

View 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';
}
}

View 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';
}
}

View 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';
}
}

View 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';
}
}

View File

@@ -39,25 +39,27 @@ class Nzbget implements Contracts\Applications, Contracts\Livestats {
}
public function executeConfig()
{
$output = '';
$html = '';
$active = 'inactive';
$res = $this->buildRequest('status');
$data = json_decode($res->getBody());
//$data->result->RemainingSizeMB = '10000000';
//$data->result->DownloadRate = '100000000';
$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>');
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>');
if($size > 0 || $rate > 0) {
$output = '
$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 $output;
return json_encode(['status' => $active, 'html' => $html]);
}
public function buildRequest($endpoint)
{
@@ -73,7 +75,7 @@ class Nzbget implements Contracts\Applications, Contracts\Livestats {
$api_url = $rebuild_url.'/jsonrpc/'.$endpoint;
$client = new Client(['http_errors' => false]);
$client = new Client(['http_errors' => false, 'timeout' => 15, 'connect_timeout' => 15]);
$res = $client->request('GET', $api_url);
return $res;

View 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';
}
}

View 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';
}
}

View 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';
}
}

View File

@@ -39,17 +39,18 @@ class Pihole implements Contracts\Applications, Contracts\Livestats {
public function executeConfig()
{
$output = '';
$html = '';
$active = 'active';
$res = $this->buildRequest();
$data = json_decode($res->getBody());
$output = '
$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 $output;
return json_encode(['status' => $active, 'html' => $html]);
}
public function buildRequest()
@@ -62,7 +63,7 @@ class Pihole implements Contracts\Applications, Contracts\Livestats {
$api_url = $url.'/api.php';
//die( $api_url.' --- ');
$client = new Client(['http_errors' => false]);
$client = new Client(['http_errors' => false, 'timeout' => 15, 'connect_timeout' => 15]);
$res = $client->request('GET', $api_url);
return $res;

View File

@@ -1,6 +1,12 @@
<?php namespace App\SupportedApps;
class Plexpy implements Contracts\Applications {
use GuzzleHttp\Exception\GuzzleException;
use GuzzleHttp\Client;
class Plexpy implements Contracts\Applications, Contracts\Livestats {
public $config;
public function defaultColour()
{
return '#2d2208';
@@ -9,4 +15,63 @@ class Plexpy implements Contracts\Applications {
{
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;
}
}

View 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;
}
}

View File

@@ -44,25 +44,27 @@ class Sabnzbd implements Contracts\Applications, Contracts\Livestats {
}
public function executeConfig()
{
$output = '';
$html = '';
$active = 'inactive';
$res = $this->buildRequest('queue');
$data = json_decode($res->getBody());
//$data->result->RemainingSizeMB = '10000000';
//$data->result->DownloadRate = '100000000';
$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>');
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>');
if($size > 0 || $rate > 0) {
$output = '
<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>
$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 $output;
return json_encode(['status' => $active, 'html' => $html]);
}
public function buildRequest($endpoint)
{
@@ -70,12 +72,15 @@ class Sabnzbd implements Contracts\Applications, Contracts\Livestats {
$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]);
$client = new Client(['http_errors' => false, 'timeout' => 15, 'connect_timeout' => 15]);
$res = $client->request('GET', $api_url);
return $res;

View 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';
}
}

View 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';
}
}

View 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;
}
}

View File

@@ -0,0 +1,166 @@
<?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()
{
$url = $this->config->url;
$url = rtrim($url, '/');
$apiUrl = $url.'/transmission/rpc';
return $apiUrl;
}
}

View 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';
}
}

View 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';
}
}

View 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';
}
}

View 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';
}
}

View 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';
}
}

View File

@@ -14,7 +14,7 @@ return [
*/
'name' => env('APP_NAME', 'Heimdall'),
'version' => '1.3.3',
'version' => '1.4.9',
/*
|--------------------------------------------------------------------------

3698
css/app.css vendored Normal file

File diff suppressed because it is too large Load Diff

View 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']);
});
}
}

View 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');
}
}

View File

@@ -90,7 +90,8 @@ class SettingsSeeder extends Seeder
'none' => 'app.options.none',
'google' => 'app.options.google',
'ddg' => 'app.options.ddg',
'bing' => 'app.options.bing'
'bing' => 'app.options.bing',
'startpage' => 'app.options.startpage',
]);
if(!$setting = Setting::find(4)) {
@@ -116,7 +117,8 @@ class SettingsSeeder extends Seeder
'fi' => 'Suomi (Finnish)',
'fr' => 'Français (French)',
'it' => 'Italiano (Italian)',
'no' => 'Norsk (Norwegian)',
'no' => 'Norsk (Norwegian)',
'pl' => 'Polski (Polish)',
'sv' => 'Svenska (Swedish)',
'es' => 'Español (Spanish)',
'tr' => 'Türkçe (Turkish)',

3
mix-manifest.json Normal file
View File

@@ -0,0 +1,3 @@
{
"/css/app.css": "/css/app.css"
}

19
package-lock.json generated
View File

@@ -115,6 +115,11 @@
"repeat-string": "1.6.1"
}
},
"almond": {
"version": "0.3.3",
"resolved": "https://registry.npmjs.org/almond/-/almond-0.3.3.tgz",
"integrity": "sha1-oOfJWsdiTWQXtElLHmi/9pMWiiA="
},
"alphanum-sort": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/alphanum-sort/-/alphanum-sort-1.0.2.tgz",
@@ -6237,6 +6242,11 @@
"integrity": "sha512-Ubldcmxp5np52/ENotGxlLe6aGMvmF4R8S6tZjsP6Knsaxd/xp3Zrh50cG93lR6nPXyUFwzN3ZSOQI0wRJNdGg==",
"dev": true
},
"jquery-mousewheel": {
"version": "3.1.13",
"resolved": "https://registry.npmjs.org/jquery-mousewheel/-/jquery-mousewheel-3.1.13.tgz",
"integrity": "sha1-BvAzXxbjU6aV5yBr9QUDy1I6buU="
},
"js-base64": {
"version": "2.4.2",
"resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.4.2.tgz",
@@ -10696,6 +10706,15 @@
"integrity": "sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo=",
"dev": true
},
"select2": {
"version": "4.0.6-rc.1",
"resolved": "https://registry.npmjs.org/select2/-/select2-4.0.6-rc.1.tgz",
"integrity": "sha1-qmwwOKfw8ukf+t448KIcFeGBMnY=",
"requires": {
"almond": "0.3.3",
"jquery-mousewheel": "3.1.13"
}
},
"selfsigned": {
"version": "1.10.1",
"resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-1.10.1.tgz",

View File

@@ -19,6 +19,7 @@
"vue": "^2.5.7"
},
"dependencies": {
"node-sass": "^4.7.2"
"node-sass": "^4.7.2",
"select2": "^4.0.6-rc.1"
}
}

708
public/css/app.css vendored
View File

@@ -1169,6 +1169,63 @@ select:-webkit-autofill:focus {
color: #2f313a !important;
}
.title-marquee {
width: 125px;
overflow: hidden;
}
.title-marquee span {
white-space: nowrap;
-webkit-transform: translate(0, 0);
transform: translate(0, 0);
-webkit-animation: marquee 8s linear;
animation: marquee 8s linear;
}
@-webkit-keyframes marquee {
0% {
-webkit-transform: translate(0, 0);
transform: translate(0, 0);
}
20% {
-webkit-transform: translate(0, 0);
transform: translate(0, 0);
}
95% {
-webkit-transform: translate(-200%, 0);
transform: translate(-200%, 0);
}
100% {
-webkit-transform: translate(-200%, 0);
transform: translate(-200%, 0);
}
}
@keyframes marquee {
0% {
-webkit-transform: translate(0, 0);
transform: translate(0, 0);
}
20% {
-webkit-transform: translate(0, 0);
transform: translate(0, 0);
}
95% {
-webkit-transform: translate(-200%, 0);
transform: translate(-200%, 0);
}
100% {
-webkit-transform: translate(-200%, 0);
transform: translate(-200%, 0);
}
}
/*! Huebee v2.0.0
http://huebee.buzz
---------------------------------------------- */
@@ -5312,3 +5369,654 @@ readers do not read off random characters that represent icons */
font-weight: 900;
}
.select2-container {
-webkit-box-sizing: border-box;
box-sizing: border-box;
display: inline-block;
margin: 0;
position: relative;
vertical-align: middle;
}
.select2-container .select2-selection--single {
-webkit-box-sizing: border-box;
box-sizing: border-box;
cursor: pointer;
display: block;
height: 28px;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
-webkit-user-select: none;
}
.select2-container .select2-selection--single .select2-selection__rendered {
display: block;
padding-left: 8px;
padding-right: 20px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.select2-container .select2-selection--single .select2-selection__clear {
position: relative;
}
.select2-container[dir="rtl"] .select2-selection--single .select2-selection__rendered {
padding-right: 8px;
padding-left: 20px;
}
.select2-container .select2-selection--multiple {
-webkit-box-sizing: border-box;
box-sizing: border-box;
cursor: pointer;
display: block;
min-height: 39px;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
-webkit-user-select: none;
}
.select2-container .select2-selection--multiple .select2-selection__rendered {
display: inline-block;
overflow: hidden;
padding-left: 8px;
text-overflow: ellipsis;
white-space: nowrap;
}
.select2-container .select2-search--inline {
float: left;
}
.select2-container .select2-search--inline .select2-search__field {
-webkit-box-sizing: border-box;
box-sizing: border-box;
border: none;
font-size: 100%;
margin-top: 5px;
padding: 0;
}
.select2-container .select2-search--inline .select2-search__field::-webkit-search-cancel-button {
-webkit-appearance: none;
}
.select2-dropdown {
background-color: white;
border: 1px solid #aaa;
border-radius: 4px;
-webkit-box-sizing: border-box;
box-sizing: border-box;
display: block;
position: absolute;
left: -100000px;
width: 100%;
z-index: 1051;
}
.select2-results {
display: block;
}
.select2-results__options {
list-style: none;
margin: 0;
padding: 0;
}
.select2-results__option {
padding: 6px;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
-webkit-user-select: none;
}
.select2-results__option[aria-selected] {
cursor: pointer;
}
.select2-container--open .select2-dropdown {
left: 0;
}
.select2-container--open .select2-dropdown--above {
border-bottom: none;
border-bottom-left-radius: 0;
border-bottom-right-radius: 0;
}
.select2-container--open .select2-dropdown--below {
border-top: none;
border-top-left-radius: 0;
border-top-right-radius: 0;
}
.select2-search--dropdown {
display: block;
padding: 4px;
}
.select2-search--dropdown .select2-search__field {
padding: 4px;
width: 100%;
-webkit-box-sizing: border-box;
box-sizing: border-box;
}
.select2-search--dropdown .select2-search__field::-webkit-search-cancel-button {
-webkit-appearance: none;
}
.select2-search--dropdown.select2-search--hide {
display: none;
}
.select2-close-mask {
border: 0;
margin: 0;
padding: 0;
display: block;
position: fixed;
left: 0;
top: 0;
min-height: 100%;
min-width: 100%;
height: auto;
width: auto;
opacity: 0;
z-index: 99;
background-color: #fff;
filter: alpha(opacity=0);
}
.select2-hidden-accessible {
border: 0 !important;
clip: rect(0 0 0 0) !important;
-webkit-clip-path: inset(50%) !important;
clip-path: inset(50%) !important;
height: 1px !important;
overflow: hidden !important;
padding: 0 !important;
position: absolute !important;
width: 1px !important;
white-space: nowrap !important;
}
.select2-container--default .select2-selection--single {
background-color: #fff;
border: 1px solid #aaa;
border-radius: 4px;
}
.select2-container--default .select2-selection--single .select2-selection__rendered {
color: #444;
line-height: 28px;
}
.select2-container--default .select2-selection--single .select2-selection__clear {
cursor: pointer;
float: right;
font-weight: bold;
}
.select2-container--default .select2-selection--single .select2-selection__placeholder {
color: #999;
}
.select2-container--default .select2-selection--single .select2-selection__arrow {
height: 26px;
position: absolute;
top: 1px;
right: 1px;
width: 20px;
}
.select2-container--default .select2-selection--single .select2-selection__arrow b {
border-color: #888 transparent transparent transparent;
border-style: solid;
border-width: 5px 4px 0 4px;
height: 0;
left: 50%;
margin-left: -4px;
margin-top: -2px;
position: absolute;
top: 50%;
width: 0;
}
.select2-container--default[dir="rtl"] .select2-selection--single .select2-selection__clear {
float: left;
}
.select2-container--default[dir="rtl"] .select2-selection--single .select2-selection__arrow {
left: 1px;
right: auto;
}
.select2-container--default.select2-container--disabled .select2-selection--single {
background-color: #eee;
cursor: default;
}
.select2-container--default.select2-container--disabled .select2-selection--single .select2-selection__clear {
display: none;
}
.select2-container--default.select2-container--open .select2-selection--single .select2-selection__arrow b {
border-color: transparent transparent #888 transparent;
border-width: 0 4px 5px 4px;
}
.select2-container--default .select2-selection--multiple {
background-color: white;
border: 1px solid #dedfe2;
border-radius: 4px;
cursor: text;
}
.select2-container--default .select2-selection--multiple .select2-selection__rendered {
-webkit-box-sizing: border-box;
box-sizing: border-box;
list-style: none;
margin: 0;
padding: 0 5px;
width: 100%;
}
.select2-container--default .select2-selection--multiple .select2-selection__rendered li {
list-style: none;
}
.select2-container--default .select2-selection--multiple .select2-selection__placeholder {
color: #999;
margin-top: 5px;
float: left;
}
.select2-container--default .select2-selection--multiple .select2-selection__clear {
cursor: pointer;
float: right;
font-weight: bold;
margin-top: 5px;
margin-right: 10px;
}
.select2-container--default .select2-selection--multiple .select2-selection__choice {
background-color: #f2f3f6;
border: 1px solid #dedfe2;
border-radius: 4px;
cursor: default;
float: left;
margin-right: 5px;
font-size: 13px;
font-weight: 300;
margin-top: 5px;
padding: 5px;
}
.select2-container--default .select2-selection--multiple .select2-selection__choice__remove {
color: #999;
cursor: pointer;
display: inline-block;
font-weight: bold;
margin-right: 2px;
}
.select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover {
color: #333;
}
.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice,
.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__placeholder,
.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-search--inline {
float: right;
}
.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice {
margin-left: 5px;
margin-right: auto;
}
.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice__remove {
margin-left: 2px;
margin-right: auto;
}
.select2-container--default.select2-container--focus .select2-selection--multiple {
border: solid #dedfe2 1px;
outline: 0;
}
.select2-container--default.select2-container--disabled .select2-selection--multiple {
background-color: #eee;
cursor: default;
}
.select2-container--default.select2-container--disabled .select2-selection__choice__remove {
display: none;
}
.select2-container--default.select2-container--open.select2-container--above .select2-selection--single,
.select2-container--default.select2-container--open.select2-container--above .select2-selection--multiple {
border-top-left-radius: 0;
border-top-right-radius: 0;
}
.select2-container--default.select2-container--open.select2-container--below .select2-selection--single,
.select2-container--default.select2-container--open.select2-container--below .select2-selection--multiple {
border-bottom-left-radius: 0;
border-bottom-right-radius: 0;
}
.select2-container--default .select2-search--dropdown .select2-search__field {
border: 1px solid #aaa;
}
.select2-container--default .select2-search--inline .select2-search__field {
background: transparent;
border: none;
outline: 0;
-webkit-box-shadow: none;
box-shadow: none;
-webkit-appearance: textfield;
}
.select2-container--default .select2-results > .select2-results__options {
max-height: 200px;
overflow-y: auto;
}
.select2-container--default .select2-results__option[role=group] {
padding: 0;
}
.select2-container--default .select2-results__option[aria-disabled=true] {
color: #999;
}
.select2-container--default .select2-results__option[aria-selected=true] {
background-color: #ddd;
}
.select2-container--default .select2-results__option .select2-results__option {
padding-left: 1em;
}
.select2-container--default .select2-results__option .select2-results__option .select2-results__group {
padding-left: 0;
}
.select2-container--default .select2-results__option .select2-results__option .select2-results__option {
margin-left: -1em;
padding-left: 2em;
}
.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option {
margin-left: -2em;
padding-left: 3em;
}
.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option {
margin-left: -3em;
padding-left: 4em;
}
.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option {
margin-left: -4em;
padding-left: 5em;
}
.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option {
margin-left: -5em;
padding-left: 6em;
}
.select2-container--default .select2-results__option--highlighted[aria-selected] {
background-color: #5897fb;
color: white;
}
.select2-container--default .select2-results__group {
cursor: default;
display: block;
padding: 6px;
}
.select2-container--classic .select2-selection--single {
background-color: #f7f7f7;
border: 1px solid #aaa;
border-radius: 4px;
outline: 0;
background-image: -webkit-gradient(linear, left top, left bottom, color-stop(50%, white), to(#eeeeee));
background-image: linear-gradient(to bottom, white 50%, #eeeeee 100%);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFFFFFFF', endColorstr='#FFEEEEEE', GradientType=0);
}
.select2-container--classic .select2-selection--single:focus {
border: 1px solid #5897fb;
}
.select2-container--classic .select2-selection--single .select2-selection__rendered {
color: #444;
line-height: 28px;
}
.select2-container--classic .select2-selection--single .select2-selection__clear {
cursor: pointer;
float: right;
font-weight: bold;
margin-right: 10px;
}
.select2-container--classic .select2-selection--single .select2-selection__placeholder {
color: #999;
}
.select2-container--classic .select2-selection--single .select2-selection__arrow {
background-color: #ddd;
border: none;
border-left: 1px solid #aaa;
border-top-right-radius: 4px;
border-bottom-right-radius: 4px;
height: 26px;
position: absolute;
top: 1px;
right: 1px;
width: 20px;
background-image: -webkit-gradient(linear, left top, left bottom, color-stop(50%, #eeeeee), to(#cccccc));
background-image: linear-gradient(to bottom, #eeeeee 50%, #cccccc 100%);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFEEEEEE', endColorstr='#FFCCCCCC', GradientType=0);
}
.select2-container--classic .select2-selection--single .select2-selection__arrow b {
border-color: #888 transparent transparent transparent;
border-style: solid;
border-width: 5px 4px 0 4px;
height: 0;
left: 50%;
margin-left: -4px;
margin-top: -2px;
position: absolute;
top: 50%;
width: 0;
}
.select2-container--classic[dir="rtl"] .select2-selection--single .select2-selection__clear {
float: left;
}
.select2-container--classic[dir="rtl"] .select2-selection--single .select2-selection__arrow {
border: none;
border-right: 1px solid #aaa;
border-radius: 0;
border-top-left-radius: 4px;
border-bottom-left-radius: 4px;
left: 1px;
right: auto;
}
.select2-container--classic.select2-container--open .select2-selection--single {
border: 1px solid #5897fb;
}
.select2-container--classic.select2-container--open .select2-selection--single .select2-selection__arrow {
background: transparent;
border: none;
}
.select2-container--classic.select2-container--open .select2-selection--single .select2-selection__arrow b {
border-color: transparent transparent #888 transparent;
border-width: 0 4px 5px 4px;
}
.select2-container--classic.select2-container--open.select2-container--above .select2-selection--single {
border-top: none;
border-top-left-radius: 0;
border-top-right-radius: 0;
background-image: -webkit-gradient(linear, left top, left bottom, from(white), color-stop(50%, #eeeeee));
background-image: linear-gradient(to bottom, white 0%, #eeeeee 50%);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFFFFFFF', endColorstr='#FFEEEEEE', GradientType=0);
}
.select2-container--classic.select2-container--open.select2-container--below .select2-selection--single {
border-bottom: none;
border-bottom-left-radius: 0;
border-bottom-right-radius: 0;
background-image: -webkit-gradient(linear, left top, left bottom, color-stop(50%, #eeeeee), to(white));
background-image: linear-gradient(to bottom, #eeeeee 50%, white 100%);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFEEEEEE', endColorstr='#FFFFFFFF', GradientType=0);
}
.select2-container--classic .select2-selection--multiple {
background-color: white;
border: 1px solid #aaa;
border-radius: 4px;
cursor: text;
outline: 0;
}
.select2-container--classic .select2-selection--multiple:focus {
border: 1px solid #5897fb;
}
.select2-container--classic .select2-selection--multiple .select2-selection__rendered {
list-style: none;
margin: 0;
padding: 0 5px;
}
.select2-container--classic .select2-selection--multiple .select2-selection__clear {
display: none;
}
.select2-container--classic .select2-selection--multiple .select2-selection__choice {
background-color: #e4e4e4;
border: 1px solid #aaa;
border-radius: 4px;
cursor: default;
float: left;
margin-right: 5px;
margin-top: 5px;
padding: 0 5px;
}
.select2-container--classic .select2-selection--multiple .select2-selection__choice__remove {
color: #888;
cursor: pointer;
display: inline-block;
font-weight: bold;
margin-right: 2px;
}
.select2-container--classic .select2-selection--multiple .select2-selection__choice__remove:hover {
color: #555;
}
.select2-container--classic[dir="rtl"] .select2-selection--multiple .select2-selection__choice {
float: right;
margin-left: 5px;
margin-right: auto;
}
.select2-container--classic[dir="rtl"] .select2-selection--multiple .select2-selection__choice__remove {
margin-left: 2px;
margin-right: auto;
}
.select2-container--classic.select2-container--open .select2-selection--multiple {
border: 1px solid #5897fb;
}
.select2-container--classic.select2-container--open.select2-container--above .select2-selection--multiple {
border-top: none;
border-top-left-radius: 0;
border-top-right-radius: 0;
}
.select2-container--classic.select2-container--open.select2-container--below .select2-selection--multiple {
border-bottom: none;
border-bottom-left-radius: 0;
border-bottom-right-radius: 0;
}
.select2-container--classic .select2-search--dropdown .select2-search__field {
border: 1px solid #aaa;
outline: 0;
}
.select2-container--classic .select2-search--inline .select2-search__field {
outline: 0;
-webkit-box-shadow: none;
box-shadow: none;
}
.select2-container--classic .select2-dropdown {
background-color: white;
border: 1px solid transparent;
}
.select2-container--classic .select2-dropdown--above {
border-bottom: none;
}
.select2-container--classic .select2-dropdown--below {
border-top: none;
}
.select2-container--classic .select2-results > .select2-results__options {
max-height: 200px;
overflow-y: auto;
}
.select2-container--classic .select2-results__option[role=group] {
padding: 0;
}
.select2-container--classic .select2-results__option[aria-disabled=true] {
color: grey;
}
.select2-container--classic .select2-results__option--highlighted[aria-selected] {
background-color: #3875d7;
color: white;
}
.select2-container--classic .select2-results__group {
cursor: default;
display: block;
padding: 6px;
}
.select2-container--classic.select2-container--open .select2-dropdown {
border-color: #5897fb;
}

41
public/js/app.js vendored
View File

@@ -28,9 +28,10 @@ $.when( $.ready ).then(function() {
(function worker() {
$.ajax({
url: '/get_stats/'+id,
dataType: 'json',
success: function(data) {
container.html(data);
if(data != '') timer = increaseby;
container.html(data.html);
if(data.status == 'active') timer = increaseby;
else {
if(timer < max_timer) timer += 2000;
}
@@ -45,6 +46,39 @@ $.when( $.ready ).then(function() {
}
function readURL(input) {
if (input.files && input.files[0]) {
var reader = new FileReader();
reader.onload = function(e) {
$('#appimage img').attr('src', e.target.result);
}
reader.readAsDataURL(input.files[0]);
}
}
$("#upload").change(function() {
readURL(this);
});
/*$(".droppable").droppable({
tolerance: "intersect",
drop: function( event, ui ) {
var tag = $( this ).data('id');
var item = $( ui.draggable ).data('id');
$.get('tag/add/'+tag+'/'+item, function(data) {
if(data == 1) {
$( ui.draggable ).remove();
} else {
alert('not added');
}
});
}
});*/
$( "#sortable" ).sortable({
stop: function (event, ui) {
var idsInOrder = $("#sortable").sortable('toArray', {
@@ -59,6 +93,7 @@ $.when( $.ready ).then(function() {
});
$("#sortable").sortable("disable");
$('#app').on('click', '#config-button', function(e) {
e.preventDefault();
@@ -96,7 +131,7 @@ $.when( $.ready ).then(function() {
var apiurl = $('#create input[name=url]').val();
var override_url = $('#create input[name=override_url]');
var override_url = $('#override_url');
if(override_url.length && override_url.val() != '') {
apiurl = override_url;
}

1
public/js/select2.min.js vendored Normal file

File diff suppressed because one or more lines are too long

View File

@@ -1,4 +1,4 @@
{
"/css/app.css": "/css/app.css?id=a571eeda02c71a01f251",
"/js/app.js": "/js/app.js?id=b38be2e595ece6fcef81"
"/css/app.css": "/css/app.css?id=7e76b8c135b6dbd38363",
"/js/app.js": "/js/app.js?id=24ea5e5c1fbea3461a14"
}

101
readme.md
View File

@@ -1,5 +1,17 @@
![alt text](https://i.imgur.com/iuV8w3y.png)
____
[![Discord](https://img.shields.io/discord/354974912613449730.svg)](https://discord.gg/CCjHKn4)
[![Docker Pulls](https://img.shields.io/docker/pulls/linuxserver/heimdall.svg)](https://hub.docker.com/r/linuxserver/heimdall/)
[![firsttimersonly](http://img.shields.io/badge/first--timers--only-friendly-blue.svg?style=flat-square)](http://www.firsttimersonly.com/)
[![Paypal](https://heimdall.site/img/paypaldonate.svg)](https://paypal.me/pools/c/81ZR4dfBGo)
___
Visit the website - https://heimdall.site
___
## About
As the name suggests Heimdall Application Dashboard is a dashboard for all your web applications. It doesn't need to be limited to applications though, you can add links to anything you like.
@@ -15,34 +27,60 @@ If you want to see a quick video of it in use, go to https://youtu.be/GXnnMAxPzM
## Supported applications
You can use the app to link to any site or application, but Foundation apps will auto fill in the icon for the app and supply a default color for the tile. In addition Enhanced apps allow you provide details to an apps API, allowing you to view live stats directly on the dashboad. For example, the NZBGet and Sabnzbd Enhanced apps will display the queue size and download speed while something is downloading.
Supported applications are recognized by the title of the application as entered in the title field when adding an application. For example, to add a link to pfSense, begin by typing "p" in the title field and then select "pfSense" from the list of supported applications.
**Enhanced**
- CouchPotato
- NZBGet
- Pihole
- PlexPy
- Proxmox
- Runeaudio
- Sabnzbd
- Tautulli
- Transmission
**Foundation**
- AirSonic
- Cardigann
- Deluge
- DokuWiki
- Duplicati
- Emby
- Gitea
- Grafana
- Graylog
- Jdownloader
- Mcmyadmin
- NZBGet
- Krusader
- Lidarr
- McMyAdmin
- Medusa
- NZBhydra & NZBhydra2
- Netdata
- Nextcloud
- Openhab
- Pihole
- Ombi
- OpenHAB
- OpenMediaVault
- Plex
- Plexpy
- Plexrequests
- Portainer
- Sabnzbd
- Radarr
- SickRage
- Sonarr
- TT-RSS
- Traefik
- UniFi
- pFsense
- UniFI
- pfSense
- pyLoad
- rTorrent/ruTorrent
- Syncthing
- Watcher3
- WebTools
## Installing
Apart from the Laravel dependencies, namely PHP >= 7.0.0, OpenSSL PHP Extension, PDO PHP Extension, Mbstring PHP Extension, Tokenizer PHP Extension and XML PHP Extension, the only other thing Heimdall needs is sqlite support.
Installation is as simple as cloning the repository somewhere, or downloading and extracting the zip/tar and pointing your httpd document root to it. For simple testing you could just go to the folder and type `php artisan serve`
Installation is as simple as cloning the repository somewhere, or downloading and extracting the zip/tar and pointing your httpd document root to the `/public` folder. For simple testing you could just go to the folder and type `php artisan serve`
There are also dockers and instructions on how to use them at
@@ -52,6 +90,11 @@ for armhf: https://hub.docker.com/r/lsioarmhf/heimdall/
and for arm64: https://hub.docker.com/r/lsioarmhf/heimdall-aarch64/
## Docker and enhanced apps
If you are running the docker and the EnhancedApps you are using are also in dockers, you may need to use the docker networking addresses to communicate with them.
You can do this by using `http(s)://docker_name:port` in the config section. Instead of the name you can use the internal docker ip, this usually starts with `172.`
## Languages
The app has been translated into several languages, however the quality of the translations could do with work, if you would like to improve them or help with other translations they are stored in /resources/lang/
@@ -72,8 +115,19 @@ Currently added languages are
## Web Server Configuration
### Apache
A .htaccess file ships with the app, however, if it does not work with your Apache installation, try this alternative:
A .htaccess file ships with the app, however, a lot of apache installations disallow .htaccess files by default.
You will notice this due to some links not working like ``/settings``.
#### Fixes & work around options
##### - Apache global allow .htaccess
Find the ``AllowOverride None`` line in your apache configuration and change this to ``AllowOverride All``
##### - Apache vhost configuration allow .htaccess
In the apache vhost configuration in the ``<Directory />`` block add ``AllowOverride All``
##### - Add .htaccess content in apache configuration
You can add the full .htaccess into your apache configuration, this way you do not need to allow .htaccess files.
You can even shorten the content of the .htaccess when inserting it into the apache configuration to :
```
Options +FollowSymLinks
RewriteEngine On
@@ -82,6 +136,11 @@ RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L]
```
#### More info
More info about AllowOverride can be found here :
https://httpd.apache.org/docs/2.4/mod/core.html#allowoverride
### Nginx
If you are using Nginx, the following directive in your site configuration will direct all requests to the index.php front controller:
@@ -114,6 +173,28 @@ location / {
}
```
### Self-signed certificates and local CAs
Per default Heimdall uses the standard certificate bundle file (ca-certificates.crt) to verify HTTPS sites and will ignore additional certificates placed in /etc/ssl/certs. If you wish to use enhanced apps with HTTPS sites that use a self-signed certificate or certs signed with your own local CA, you can override the default bundle:
- Create a unified certificate .pem-file that contains all CAs and certificates that Heimdall has to verify. For example, if you use both LetsEncrypt and a local CA for your internal apps, concatenate the LetsEncrypt intermediate CA (export via browser) and your local CA cert.pem (or any number of self-signed certs) into one heimdall.pem file.
- Place the heimdall.pem into the container (if you use Docker), for example by placing it in the path that you mapped to /config. Make sure that the Heimdall user has read access (chmod a+r).
- Set the openssl.cafile setting in /config/php/php-local.ini to your cert bundle:
```
# /config/php/php-local.ini
openssl.cafile = /config/heimdall.pem
```
Restart the container and the enhanced apps should now be able to access your local HTTP websites. This configuration will survive updating or recreating the Heimdall container.
## Support
https://discord.gg/CCjHKn4 or through Github issues
## Donate
If you would like to show your appreciation, feel free to use the link below.
[![Paypal](https://heimdall.site/img/paypaldonate.svg)](https://paypal.me/pools/c/81ZR4dfBGo)
## Credits
- PHP Framework - [Laravel](https://laravel.com/)
- Icons - [FonteAwesome 5](https://fontawesome.com/)

View File

@@ -19,9 +19,10 @@ $.when( $.ready ).then(function() {
(function worker() {
$.ajax({
url: '/get_stats/'+id,
dataType: 'json',
success: function(data) {
container.html(data);
if(data != '') timer = increaseby;
container.html(data.html);
if(data.status == 'active') timer = increaseby;
else {
if(timer < max_timer) timer += 2000;
}
@@ -36,6 +37,39 @@ $.when( $.ready ).then(function() {
}
function readURL(input) {
if (input.files && input.files[0]) {
var reader = new FileReader();
reader.onload = function(e) {
$('#appimage img').attr('src', e.target.result);
}
reader.readAsDataURL(input.files[0]);
}
}
$("#upload").change(function() {
readURL(this);
});
/*$(".droppable").droppable({
tolerance: "intersect",
drop: function( event, ui ) {
var tag = $( this ).data('id');
var item = $( ui.draggable ).data('id');
$.get('tag/add/'+tag+'/'+item, function(data) {
if(data == 1) {
$( ui.draggable ).remove();
} else {
alert('not added');
}
});
}
});*/
$( "#sortable" ).sortable({
stop: function (event, ui) {
var idsInOrder = $("#sortable").sortable('toArray', {
@@ -50,6 +84,7 @@ $.when( $.ready ).then(function() {
});
$("#sortable").sortable("disable");
$('#app').on('click', '#config-button', function(e) {
e.preventDefault();
@@ -87,7 +122,7 @@ $.when( $.ready ).then(function() {
var apiurl = $('#create input[name=url]').val();
var override_url = $('#create input[name=override_url]');
var override_url = $('#override_url');
if(override_url.length && override_url.val() != '') {
apiurl = override_url;
}

16
resources/assets/sass/_rune.scss vendored Normal file
View File

@@ -0,0 +1,16 @@
.title-marquee {
width: 125px;
overflow: hidden;
span {
white-space: nowrap;
transform: translate(0, 0);
animation: marquee 8s linear;
}
}
@keyframes marquee {
0% { transform: translate(0, 0); }
20% { transform: translate(0, 0); }
95% { transform: translate(-200%, 0); }
100% { transform: translate(-200%, 0); }
}

486
resources/assets/sass/_select2.scss vendored Normal file
View File

@@ -0,0 +1,486 @@
.select2-container {
box-sizing: border-box;
display: inline-block;
margin: 0;
position: relative;
vertical-align: middle; }
.select2-container .select2-selection--single {
box-sizing: border-box;
cursor: pointer;
display: block;
height: 28px;
user-select: none;
-webkit-user-select: none; }
.select2-container .select2-selection--single .select2-selection__rendered {
display: block;
padding-left: 8px;
padding-right: 20px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap; }
.select2-container .select2-selection--single .select2-selection__clear {
position: relative; }
.select2-container[dir="rtl"] .select2-selection--single .select2-selection__rendered {
padding-right: 8px;
padding-left: 20px; }
.select2-container .select2-selection--multiple {
box-sizing: border-box;
cursor: pointer;
display: block;
min-height: 39px;
user-select: none;
-webkit-user-select: none; }
.select2-container .select2-selection--multiple .select2-selection__rendered {
display: inline-block;
overflow: hidden;
padding-left: 8px;
text-overflow: ellipsis;
white-space: nowrap; }
.select2-container .select2-search--inline {
float: left; }
.select2-container .select2-search--inline .select2-search__field {
box-sizing: border-box;
border: none;
font-size: 100%;
margin-top: 5px;
padding: 0; }
.select2-container .select2-search--inline .select2-search__field::-webkit-search-cancel-button {
-webkit-appearance: none; }
.select2-dropdown {
background-color: white;
border: 1px solid #aaa;
border-radius: 4px;
box-sizing: border-box;
display: block;
position: absolute;
left: -100000px;
width: 100%;
z-index: 1051; }
.select2-results {
display: block; }
.select2-results__options {
list-style: none;
margin: 0;
padding: 0; }
.select2-results__option {
padding: 6px;
user-select: none;
-webkit-user-select: none; }
.select2-results__option[aria-selected] {
cursor: pointer; }
.select2-container--open .select2-dropdown {
left: 0; }
.select2-container--open .select2-dropdown--above {
border-bottom: none;
border-bottom-left-radius: 0;
border-bottom-right-radius: 0; }
.select2-container--open .select2-dropdown--below {
border-top: none;
border-top-left-radius: 0;
border-top-right-radius: 0; }
.select2-search--dropdown {
display: block;
padding: 4px; }
.select2-search--dropdown .select2-search__field {
padding: 4px;
width: 100%;
box-sizing: border-box; }
.select2-search--dropdown .select2-search__field::-webkit-search-cancel-button {
-webkit-appearance: none; }
.select2-search--dropdown.select2-search--hide {
display: none; }
.select2-close-mask {
border: 0;
margin: 0;
padding: 0;
display: block;
position: fixed;
left: 0;
top: 0;
min-height: 100%;
min-width: 100%;
height: auto;
width: auto;
opacity: 0;
z-index: 99;
background-color: #fff;
filter: alpha(opacity=0); }
.select2-hidden-accessible {
border: 0 !important;
clip: rect(0 0 0 0) !important;
-webkit-clip-path: inset(50%) !important;
clip-path: inset(50%) !important;
height: 1px !important;
overflow: hidden !important;
padding: 0 !important;
position: absolute !important;
width: 1px !important;
white-space: nowrap !important; }
.select2-container--default .select2-selection--single {
background-color: #fff;
border: 1px solid #aaa;
border-radius: 4px; }
.select2-container--default .select2-selection--single .select2-selection__rendered {
color: #444;
line-height: 28px; }
.select2-container--default .select2-selection--single .select2-selection__clear {
cursor: pointer;
float: right;
font-weight: bold; }
.select2-container--default .select2-selection--single .select2-selection__placeholder {
color: #999; }
.select2-container--default .select2-selection--single .select2-selection__arrow {
height: 26px;
position: absolute;
top: 1px;
right: 1px;
width: 20px; }
.select2-container--default .select2-selection--single .select2-selection__arrow b {
border-color: #888 transparent transparent transparent;
border-style: solid;
border-width: 5px 4px 0 4px;
height: 0;
left: 50%;
margin-left: -4px;
margin-top: -2px;
position: absolute;
top: 50%;
width: 0; }
.select2-container--default[dir="rtl"] .select2-selection--single .select2-selection__clear {
float: left; }
.select2-container--default[dir="rtl"] .select2-selection--single .select2-selection__arrow {
left: 1px;
right: auto; }
.select2-container--default.select2-container--disabled .select2-selection--single {
background-color: #eee;
cursor: default; }
.select2-container--default.select2-container--disabled .select2-selection--single .select2-selection__clear {
display: none; }
.select2-container--default.select2-container--open .select2-selection--single .select2-selection__arrow b {
border-color: transparent transparent #888 transparent;
border-width: 0 4px 5px 4px; }
.select2-container--default .select2-selection--multiple {
background-color: white;
border: 1px solid #dedfe2;
border-radius: 4px;
cursor: text; }
.select2-container--default .select2-selection--multiple .select2-selection__rendered {
box-sizing: border-box;
list-style: none;
margin: 0;
padding: 0 5px;
width: 100%; }
.select2-container--default .select2-selection--multiple .select2-selection__rendered li {
list-style: none; }
.select2-container--default .select2-selection--multiple .select2-selection__placeholder {
color: #999;
margin-top: 5px;
float: left; }
.select2-container--default .select2-selection--multiple .select2-selection__clear {
cursor: pointer;
float: right;
font-weight: bold;
margin-top: 5px;
margin-right: 10px; }
.select2-container--default .select2-selection--multiple .select2-selection__choice {
background-color: #f2f3f6;
border: 1px solid #dedfe2;
border-radius: 4px;
cursor: default;
float: left;
margin-right: 5px;
font-size: 13px;
font-weight: 300;
margin-top: 5px;
padding: 5px; }
.select2-container--default .select2-selection--multiple .select2-selection__choice__remove {
color: #999;
cursor: pointer;
display: inline-block;
font-weight: bold;
margin-right: 2px; }
.select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover {
color: #333; }
.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice, .select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__placeholder, .select2-container--default[dir="rtl"] .select2-selection--multiple .select2-search--inline {
float: right; }
.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice {
margin-left: 5px;
margin-right: auto; }
.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice__remove {
margin-left: 2px;
margin-right: auto; }
.select2-container--default.select2-container--focus .select2-selection--multiple {
border: solid #dedfe2 1px;
outline: 0; }
.select2-container--default.select2-container--disabled .select2-selection--multiple {
background-color: #eee;
cursor: default; }
.select2-container--default.select2-container--disabled .select2-selection__choice__remove {
display: none; }
.select2-container--default.select2-container--open.select2-container--above .select2-selection--single, .select2-container--default.select2-container--open.select2-container--above .select2-selection--multiple {
border-top-left-radius: 0;
border-top-right-radius: 0; }
.select2-container--default.select2-container--open.select2-container--below .select2-selection--single, .select2-container--default.select2-container--open.select2-container--below .select2-selection--multiple {
border-bottom-left-radius: 0;
border-bottom-right-radius: 0; }
.select2-container--default .select2-search--dropdown .select2-search__field {
border: 1px solid #aaa; }
.select2-container--default .select2-search--inline .select2-search__field {
background: transparent;
border: none;
outline: 0;
box-shadow: none;
-webkit-appearance: textfield; }
.select2-container--default .select2-results > .select2-results__options {
max-height: 200px;
overflow-y: auto; }
.select2-container--default .select2-results__option[role=group] {
padding: 0; }
.select2-container--default .select2-results__option[aria-disabled=true] {
color: #999; }
.select2-container--default .select2-results__option[aria-selected=true] {
background-color: #ddd; }
.select2-container--default .select2-results__option .select2-results__option {
padding-left: 1em; }
.select2-container--default .select2-results__option .select2-results__option .select2-results__group {
padding-left: 0; }
.select2-container--default .select2-results__option .select2-results__option .select2-results__option {
margin-left: -1em;
padding-left: 2em; }
.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option {
margin-left: -2em;
padding-left: 3em; }
.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option {
margin-left: -3em;
padding-left: 4em; }
.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option {
margin-left: -4em;
padding-left: 5em; }
.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option {
margin-left: -5em;
padding-left: 6em; }
.select2-container--default .select2-results__option--highlighted[aria-selected] {
background-color: #5897fb;
color: white; }
.select2-container--default .select2-results__group {
cursor: default;
display: block;
padding: 6px; }
.select2-container--classic .select2-selection--single {
background-color: #f7f7f7;
border: 1px solid #aaa;
border-radius: 4px;
outline: 0;
background-image: -webkit-linear-gradient(top, white 50%, #eeeeee 100%);
background-image: -o-linear-gradient(top, white 50%, #eeeeee 100%);
background-image: linear-gradient(to bottom, white 50%, #eeeeee 100%);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFFFFFFF', endColorstr='#FFEEEEEE', GradientType=0); }
.select2-container--classic .select2-selection--single:focus {
border: 1px solid #5897fb; }
.select2-container--classic .select2-selection--single .select2-selection__rendered {
color: #444;
line-height: 28px; }
.select2-container--classic .select2-selection--single .select2-selection__clear {
cursor: pointer;
float: right;
font-weight: bold;
margin-right: 10px; }
.select2-container--classic .select2-selection--single .select2-selection__placeholder {
color: #999; }
.select2-container--classic .select2-selection--single .select2-selection__arrow {
background-color: #ddd;
border: none;
border-left: 1px solid #aaa;
border-top-right-radius: 4px;
border-bottom-right-radius: 4px;
height: 26px;
position: absolute;
top: 1px;
right: 1px;
width: 20px;
background-image: -webkit-linear-gradient(top, #eeeeee 50%, #cccccc 100%);
background-image: -o-linear-gradient(top, #eeeeee 50%, #cccccc 100%);
background-image: linear-gradient(to bottom, #eeeeee 50%, #cccccc 100%);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFEEEEEE', endColorstr='#FFCCCCCC', GradientType=0); }
.select2-container--classic .select2-selection--single .select2-selection__arrow b {
border-color: #888 transparent transparent transparent;
border-style: solid;
border-width: 5px 4px 0 4px;
height: 0;
left: 50%;
margin-left: -4px;
margin-top: -2px;
position: absolute;
top: 50%;
width: 0; }
.select2-container--classic[dir="rtl"] .select2-selection--single .select2-selection__clear {
float: left; }
.select2-container--classic[dir="rtl"] .select2-selection--single .select2-selection__arrow {
border: none;
border-right: 1px solid #aaa;
border-radius: 0;
border-top-left-radius: 4px;
border-bottom-left-radius: 4px;
left: 1px;
right: auto; }
.select2-container--classic.select2-container--open .select2-selection--single {
border: 1px solid #5897fb; }
.select2-container--classic.select2-container--open .select2-selection--single .select2-selection__arrow {
background: transparent;
border: none; }
.select2-container--classic.select2-container--open .select2-selection--single .select2-selection__arrow b {
border-color: transparent transparent #888 transparent;
border-width: 0 4px 5px 4px; }
.select2-container--classic.select2-container--open.select2-container--above .select2-selection--single {
border-top: none;
border-top-left-radius: 0;
border-top-right-radius: 0;
background-image: -webkit-linear-gradient(top, white 0%, #eeeeee 50%);
background-image: -o-linear-gradient(top, white 0%, #eeeeee 50%);
background-image: linear-gradient(to bottom, white 0%, #eeeeee 50%);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFFFFFFF', endColorstr='#FFEEEEEE', GradientType=0); }
.select2-container--classic.select2-container--open.select2-container--below .select2-selection--single {
border-bottom: none;
border-bottom-left-radius: 0;
border-bottom-right-radius: 0;
background-image: -webkit-linear-gradient(top, #eeeeee 50%, white 100%);
background-image: -o-linear-gradient(top, #eeeeee 50%, white 100%);
background-image: linear-gradient(to bottom, #eeeeee 50%, white 100%);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFEEEEEE', endColorstr='#FFFFFFFF', GradientType=0); }
.select2-container--classic .select2-selection--multiple {
background-color: white;
border: 1px solid #aaa;
border-radius: 4px;
cursor: text;
outline: 0; }
.select2-container--classic .select2-selection--multiple:focus {
border: 1px solid #5897fb; }
.select2-container--classic .select2-selection--multiple .select2-selection__rendered {
list-style: none;
margin: 0;
padding: 0 5px; }
.select2-container--classic .select2-selection--multiple .select2-selection__clear {
display: none; }
.select2-container--classic .select2-selection--multiple .select2-selection__choice {
background-color: #e4e4e4;
border: 1px solid #aaa;
border-radius: 4px;
cursor: default;
float: left;
margin-right: 5px;
margin-top: 5px;
padding: 0 5px; }
.select2-container--classic .select2-selection--multiple .select2-selection__choice__remove {
color: #888;
cursor: pointer;
display: inline-block;
font-weight: bold;
margin-right: 2px; }
.select2-container--classic .select2-selection--multiple .select2-selection__choice__remove:hover {
color: #555; }
.select2-container--classic[dir="rtl"] .select2-selection--multiple .select2-selection__choice {
float: right;
margin-left: 5px;
margin-right: auto; }
.select2-container--classic[dir="rtl"] .select2-selection--multiple .select2-selection__choice__remove {
margin-left: 2px;
margin-right: auto; }
.select2-container--classic.select2-container--open .select2-selection--multiple {
border: 1px solid #5897fb; }
.select2-container--classic.select2-container--open.select2-container--above .select2-selection--multiple {
border-top: none;
border-top-left-radius: 0;
border-top-right-radius: 0; }
.select2-container--classic.select2-container--open.select2-container--below .select2-selection--multiple {
border-bottom: none;
border-bottom-left-radius: 0;
border-bottom-right-radius: 0; }
.select2-container--classic .select2-search--dropdown .select2-search__field {
border: 1px solid #aaa;
outline: 0; }
.select2-container--classic .select2-search--inline .select2-search__field {
outline: 0;
box-shadow: none; }
.select2-container--classic .select2-dropdown {
background-color: white;
border: 1px solid transparent; }
.select2-container--classic .select2-dropdown--above {
border-bottom: none; }
.select2-container--classic .select2-dropdown--below {
border-top: none; }
.select2-container--classic .select2-results > .select2-results__options {
max-height: 200px;
overflow-y: auto; }
.select2-container--classic .select2-results__option[role=group] {
padding: 0; }
.select2-container--classic .select2-results__option[aria-disabled=true] {
color: grey; }
.select2-container--classic .select2-results__option--highlighted[aria-selected] {
background-color: #3875d7;
color: white; }
.select2-container--classic .select2-results__group {
cursor: default;
display: block;
padding: 6px; }
.select2-container--classic.select2-container--open .select2-dropdown {
border-color: #5897fb; }

View File

@@ -10,10 +10,14 @@
// Bootstrap
@import "app";
@import "rune";
// Huebee
@import "huebee";
// fontawesome
@import "fontawesome/fontawesome";
@import "fontawesome/fa-solid";
@import "fontawesome/fa-solid";
@import "select2";

View File

@@ -33,6 +33,7 @@ return [
'options.google' => 'Google',
'options.ddg' => 'DuckDuckGo',
'options.bing' => 'Bing',
'options.startpage' => 'StartPage',
'options.yes' => 'Yes',
'options.no' => 'No',
@@ -61,6 +62,11 @@ return [
'apps.config' => 'Config',
'apps.apikey' => 'Api Key',
'apps.enable' => 'Enable',
'apps.tag_list' => 'Tags list',
'apps.add_tag' => 'Add tag',
'apps.tag_name' => 'Tag name',
'apps.tags' => 'Tags',
'apps.override' => 'If different to main url',
'url' => 'Url',
'title' => 'Title',
@@ -73,6 +79,11 @@ return [
'alert.success.item_deleted' => 'Item deleted successfully',
'alert.success.item_restored' => 'Item restored successfully',
'alert.success.tag_created' => 'Tag created successfully',
'alert.success.tag_updated' => 'Tag updated successfully',
'alert.success.tag_deleted' => 'Tag deleted successfully',
'alert.success.tag_restored' => 'Tag restored successfully',
'alert.success.setting_updated' => 'You have successfully edited this Setting',
'alert.error.not_exist' => 'This Setting does not exist.',

89
resources/lang/nl/app.php Normal file
View File

@@ -0,0 +1,89 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| App Language Lines
|--------------------------------------------------------------------------
|
*/
'settings.system' => 'Systeem',
'settings.appearance' => 'Uiterlijk',
'settings.miscellaneous' => 'Overige',
'settings.version' => 'Versie',
'settings.background_image' => 'Achtergrondafbeelding',
'settings.homepage_search' => 'Zoeken op thuispagina',
'settings.search_provider' => 'Zoekaanbieder',
'settings.language' => 'Taal',
'settings.reset' => 'Op standaard instellen',
'settings.remove' => 'Verwijderen',
'settings.search' => 'zoeken',
'settings.no_items' => 'Geen items gevonden',
'settings.label' => 'Label',
'settings.value' => 'Waarde',
'settings.edit' => 'Bewerken',
'settings.view' => 'Weergeven',
'options.none' => '- niet ingesteld -',
'options.google' => 'Google',
'options.ddg' => 'DuckDuckGo',
'options.bing' => 'Bing',
'options.yes' => 'Ja',
'options.no' => 'Nee',
'buttons.save' => 'Opslaan',
'buttons.cancel' => 'Annuleren',
'buttons.add' => 'Toevoegen',
'buttons.upload' => 'Bestand uploaden',
'dash.pin_item' => 'Item aan dashboard vastmaken',
'dash.no_apps' => 'Er zijn momenteel geen vastgemaakte toepassingen, :link1 of :link2',
'dash.link1' => 'Voeg hier een toepassing toe',
'dash.link2' => 'Een item aan het dashboard vastmaken',
'dash.pinned_items' => 'Vastgemaakte Items',
'apps.app_list' => 'Lijst met toepassingen',
'apps.view_trash' => 'Prullenbak weergeven',
'apps.add_application' => 'Toepassing toevoegen',
'apps.application_name' => 'Naam van toepassing',
'apps.colour' => 'Kleur',
'apps.icon' => 'Pictogram',
'apps.pinned' => 'Vastgemaakt',
'apps.title' => 'Titel',
'apps.hex' => 'Hex-kleur',
'apps.username' => 'Gebruikersnaam',
'apps.password' => 'Wachtwoord',
'apps.config' => 'Configuratie',
'apps.apikey' => 'API-sleutel',
'apps.enable' => 'Inschakalen',
'apps.tag_list' => 'Lijst met tags',
'apps.add_tag' => 'Tag toevoegen',
'apps.tag_name' => 'Naam van tag',
'apps.tags' => 'Tags',
'url' => 'URL',
'title' => 'Titel',
'delete' => 'Verwijderen',
'optional' => 'Optioneel',
'restore' => 'Herstellen',
'alert.success.item_created' => 'Item met succes aangemaakt',
'alert.success.item_updated' => 'Item met succes bewerkt',
'alert.success.item_deleted' => 'Item met succes verwijderd',
'alert.success.item_restored' => 'Item met succes hersteld',
'alert.success.tag_created' => 'Tag met succes aangemaakt',
'alert.success.tag_updated' => 'Tag met succes bewerkt',
'alert.success.tag_deleted' => 'Tag met succes verwijderd',
'alert.success.tag_restored' => 'Tag met succes hersteld',
'alert.success.setting_updated' => 'Deze instelling is met succes gewijzigd',
'alert.error.not_exist' => 'Deze instelling bestaat niet.',
];

View File

@@ -0,0 +1,19 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Authentication Language Lines
|--------------------------------------------------------------------------
|
| The following language lines are used during authentication for various
| messages that we need to display to the user. You are free to modify
| these language lines according to your application's requirements.
|
*/
'failed' => 'De door u opgegeven referenties komen niet overeen met onze gegevens.',
'throttle' => 'Te veel aanmeldpogingen. Probeer het over :seconds seconden opnieuw.',
];

View File

@@ -0,0 +1,19 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Pagination Language Lines
|--------------------------------------------------------------------------
|
| The following language lines are used by the paginator library to build
| the simple pagination links. You are free to change them to anything
| you want to customize your views to better match your application.
|
*/
'previous' => '&laquo; Vorige',
'next' => 'Volgende &raquo;',
];

View File

@@ -0,0 +1,22 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Password Reset Language Lines
|--------------------------------------------------------------------------
|
| The following language lines are the default lines which match reasons
| that are given by the password broker for a password update attempt
| has failed, such as for an invalid token or invalid new password.
|
*/
'password' => 'Wachtwoorden moeten tenminste zes karakters bevatten en overeenkomen met de bevestiging.',
'reset' => 'Uw wachtwoord is opnieuw ingesteld!',
'sent' => 'De link voor het opnieuw instellen van uw wachtwoord is naar u gemaild!',
'token' => 'Deze token voor het opnieuw instellen van een wachtwoord is ongeldig.',
'user' => "Er bestaat geen gebruiker met het opgegeven e-mailadres.",
];

View File

@@ -0,0 +1,121 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Validation Language Lines
|--------------------------------------------------------------------------
|
| The following language lines contain the default error messages used by
| the validator class. Some of these rules have multiple versions such
| as the size rules. Feel free to tweak each of these messages here.
|
*/
'accepted' => ':attribute moet geaccepteerd worden.',
'active_url' => ':attribute is geen geldige URL.',
'after' => ':attribute moet een datum na :date zijn.',
'after_or_equal' => ':attribute moet een datum op of na :date zijn.',
'alpha' => ':attribute mag alleen letters bevatten.',
'alpha_dash' => ':attribute mag alleen letters, cijfers en streepjes bevatten.',
'alpha_num' => ':attribute mag alleen letters en cijfers bevatten.',
'array' => ':attribute moet een array zijn.',
'before' => ':attribute moet een datum voor :date zijn.',
'before_or_equal' => ':attribute moet een datum op of voor :date zijn.',
'between' => [
'numeric' => ':attribute moet tussen :min en :max liggen.',
'file' => ':attribute moet tussen :min en :max kilobyte in omvang zijn.',
'string' => ':attribute moet tussen :min en :max karakters bevatten.',
'array' => ':attribute moet tussen :min en :max items bevatten.',
],
'boolean' => 'Het veld :attribute moet waar of onwaar zijn.',
'confirmed' => 'De bevestiging voor :attribute komt niet overeen.',
'date' => ':attribute is geen geldige datum.',
'date_format' => ':attribute komt niet overeen met het formaat :format.',
'different' => ':attribute en :other moeten verschillen.',
'digits' => ':attribute moet :digits getallen bevatten.',
'digits_between' => ':attribute moet tussen :min en :max getallen bevatten.',
'dimensions' => ':attribute heeft ongeldige afbeeldingsafmetingen.',
'distinct' => 'Het veld :attribute heeft een dubbele waarde.',
'email' => ':attribute moet een geldig e-mailadres zijn.',
'exists' => 'Geselecteerde :attribute is ongeldig.',
'file' => ':attribute moet een bestand zijn.',
'filled' => 'Het veld :attribute moet een waarde bevatten.',
'image' => ':attribute moet een afbeelding zijn.',
'in' => 'Geselecteerde :attribute is ongeldig.',
'in_array' => 'Het veld :attribute bestaat niet in :other.',
'integer' => ':attribute moet een geheel getal zijn.',
'ip' => ':attribute moet een geldig IP-adres zijn.',
'ipv4' => ':attribute moet een geldig IPv4-adres zijn.',
'ipv6' => ':attribute moet een geldig IPv6-adres zijn.',
'json' => ':attribute moet een geldige JSON-reeks zijn.',
'max' => [
'numeric' => ':attribute mag niet groter dan :max zijn.',
'file' => ':attribute mag niet groter dan :max kilobyte in omvang zijn.',
'string' => ':attribute mag niet meer dan :max karakters bevatten.',
'array' => ':attribute mag niet meer dan :max items bevatten.',
],
'mimes' => ':attribute moet een bestand zijn van type: :values.',
'mimetypes' => ':attribute moet een bestand zijn van type: :values.',
'min' => [
'numeric' => ':attribute moet tenminste :min zijn.',
'file' => ':attribute moet tenminste :min kilobyte in omvang zijn.',
'string' => ':attribute moet tenminste :min karakters bevatten.',
'array' => ':attribute moet tenminste :min items bevatten.',
],
'not_in' => 'Geselecteerde :attribute is ongeldig.',
'numeric' => ':attribute moet een getal zijn.',
'present' => 'Het veld :attribute moet aanwezig zijn.',
'regex' => 'Het formaat van :attribute is ongeldig.',
'required' => 'Het veld :attribute is vereist.',
'required_if' => 'Het veld :attribute is vereist wanneer :other :value is.',
'required_unless' => 'Het veld :attribute is vereist tenzij :other in :values aanwezig is.',
'required_with' => 'Het veld :attribute is vereist wanneer :values aanwezig is.',
'required_with_all' => 'Het veld :attribute is vereist wanneer :values aanwezig is.',
'required_without' => 'Het veld :attribute is vereist wanneer :values niet aanwezig is.',
'required_without_all' => 'Het veld :attribute is vereist wanneer geen van :values aanwezig zijn.',
'same' => ':attribute en :other moeten overeenkomen.',
'size' => [
'numeric' => ':attribute moet :size zijn.',
'file' => ':attribute moet :size kilobyte in omvang zijn.',
'string' => ':attribute moet :size karakters bevatten.',
'array' => ':attribute moet :size items bevatten.',
],
'string' => ':attribute moet een reekswaarde zijn.',
'timezone' => ':attribute moet een geldige zone bevatten.',
'unique' => ':attribute is reeds in gebruik.',
'uploaded' => 'Het uploaden van :attribute is niet gelukt.',
'url' => 'Het formaat van :attribute is ongeldig.',
/*
|--------------------------------------------------------------------------
| Custom Validation Language Lines
|--------------------------------------------------------------------------
|
| Here you may specify custom validation messages for attributes using the
| convention "attribute.rule" to name the lines. This makes it quick to
| specify a specific custom language line for a given attribute rule.
|
*/
'custom' => [
'attribute-name' => [
'rule-name' => 'custom-message',
],
],
/*
|--------------------------------------------------------------------------
| Custom Validation Attributes
|--------------------------------------------------------------------------
|
| The following language lines are used to swap attribute place-holders
| with something more reader friendly such as E-Mail Address instead
| of "email". This simply helps us make messages a little cleaner.
|
*/
'attributes' => [],
];

80
resources/lang/pl/app.php Normal file
View File

@@ -0,0 +1,80 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| App Language Lines
|--------------------------------------------------------------------------
|
*/
'settings.system' => 'System',
'settings.appearance' => 'Wygląd',
'settings.miscellaneous' => 'Różne',
'settings.version' => 'Wersja',
'settings.background_image' => 'Tapeta Pulpitu',
'settings.homepage_search' => 'Strona Domowa Wyszukiwanie',
'settings.search_provider' => 'Operator Wyszukiwania',
'settings.language' => 'Język',
'settings.reset' => 'Przywróć ustawienia domyślne',
'settings.remove' => 'Usuń',
'settings.search' => 'szukaj',
'settings.no_items' => 'Nic nie znaleziono',
'settings.label' => 'Etykieta',
'settings.value' => 'Wartość',
'settings.edit' => 'Edytuj',
'settings.view' => 'Widok',
'options.none' => '- not set -',
'options.google' => 'Google',
'options.ddg' => 'DuckDuckGo',
'options.bing' => 'Bing',
'options.yes' => 'Tak',
'options.no' => 'Nie',
'buttons.save' => 'Zapisz',
'buttons.cancel' => 'Anuluj',
'buttons.add' => 'Dodaj',
'buttons.upload' => 'Prześlij plik',
'dash.pin_item' => 'Przypnij element do pulpitu',
'dash.no_apps' => 'Obecnie nie ma przypiętych aplikacji, :link1 or :link2',
'dash.link1' => 'Dodaj aplikację tutaj',
'dash.link2' => 'Przypnij element do pulpitu',
'dash.pinned_items' => 'Przypięte elementy',
'apps.app_list' => 'Lista aplikacji',
'apps.view_trash' => 'Widok kosza',
'apps.add_application' => 'Dodaj Aplikacje',
'apps.application_name' => 'Nazwa Aplikacji',
'apps.colour' => 'Kolor',
'apps.icon' => 'Ikona',
'apps.pinned' => 'Przypięty',
'apps.title' => 'Tytuł',
'apps.hex' => 'Kolor HEX',
'apps.username' => 'Nazwa Użytkownika',
'apps.password' => 'Hasło',
'apps.config' => 'Ustawienia',
'apps.apikey' => 'Klucz API',
'apps.enable' => 'Włącz',
'url' => 'URL',
'title' => 'Tytuł',
'delete' => 'Usuń',
'optional' => 'Opcjonalny',
'restore' => 'Przywróć',
'alert.success.item_created' => 'Element utworzony',
'alert.success.item_updated' => 'Element zaktualizowany',
'alert.success.item_deleted' => 'Element usunięty',
'alert.success.item_restored' => 'Przywrócono element',
'alert.success.setting_updated' => 'Ustawienie zostało zaktualizowane',
'alert.error.not_exist' => 'Takie ustawienie nie istnieje',
];

View File

@@ -0,0 +1,19 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Authentication Language Lines
|--------------------------------------------------------------------------
|
| The following language lines are used during authentication for various
| messages that we need to display to the user. You are free to modify
| these language lines according to your application's requirements.
|
*/
'failed' => 'Nieprawidłowe dane uwierzytelnienia',
'throttle' => 'Zbyt wiele prób logowania. Spróbuj ponownie za :seconds sekund.',
];

View File

@@ -0,0 +1,19 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Pagination Language Lines
|--------------------------------------------------------------------------
|
| The following language lines are used by the paginator library to build
| the simple pagination links. You are free to change them to anything
| you want to customize your views to better match your application.
|
*/
'previous' => '&laquo; Poprzedni',
'next' => 'Następny &raquo;',
];

View File

@@ -0,0 +1,22 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Password Reset Language Lines
|--------------------------------------------------------------------------
|
| The following language lines are the default lines which match reasons
| that are given by the password broker for a password update attempt
| has failed, such as for an invalid token or invalid new password.
|
*/
'password' => 'Hasła muszą mieć co najmniej sześć znaków i być zgodne z potwierdzeniem.',
'reset' => 'Twoje hasło zostało zresetowane!',
'sent' => 'Wysłaliśmy e-mailem link do resetowania hasła!',
'token' => 'Ten token resetowania hasła jest nieprawidłowy',
'user' => 'Nie możemy znaleźć użytkownika z tym adresem e-mail',
];

View File

@@ -0,0 +1,121 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Validation Language Lines
|--------------------------------------------------------------------------
|
| The following language lines contain the default error messages used by
| the validator class. Some of these rules have multiple versions such
| as the size rules. Feel free to tweak each of these messages here.
|
*/
'accepted' => ':attribute musi zostać zaakceptowany.',
'active_url' => ':attribute nie jest prawidłowym adresem URL.',
'after' => ':attribute musi być datą następną po :date.',
'after_or_equal' => ':attribute musi być datą następną lub równą dacie :date.',
'alpha' => ':attribute może zawierać tylko litery.',
'alpha_dash' => ':attribute mogą zawierać tylko litery, cyfry i myślniki.',
'alpha_num' => ':attribute może zawierać tylko litery i cyfry.',
'array' => ':attribute musi być tablicą.',
'before' => ':attribute musi być datą wcześniejszą od daty :date.',
'before_or_equal' => ':attribute musi być datą wcześniejszą lub równą dacie :date.',
'between' => [
'numeric' => 'Numer :attribute musi byc większy niż :min oraz mniejszy niż :max.',
'file' => 'Rozmiar pliku :attribute musi byc większy niż :min oraz mniejszy niż :max kilobajtów.',
'string' => 'Tekst :attribute musi posiadać więcej niż :min oraz mniej niż :max znaków.',
'array' => 'Tablica :attribute musi zawierać więcej niż :min oraz mniej niż :max elementów.',
],
'boolean' => ':attribute musi zwracac wartość logiczną TRUE lub FALSE.',
'confirmed' => ':attribute nie jest zgodny z polem potwierdzenia.',
'date' => ':attribute nieprawidłowy format daty.',
'date_format' => 'Format daty :attribute musi byc zgodny z formatem :format.',
'different' => 'Wartości :attribute oraz :other muszą być różne.',
'digits' => 'Wartość :attribute musi być liczbą o długość :digits znaków.',
'digits_between' => 'Wartość :attribute musi być liczbą o długość co najmniej :min oraz nie więcej niz :max digits.',
'dimensions' => ':attribute ma nieprawidłowe wymiary obrazu.',
'distinct' => 'Pole :attribute ma zduplikowaną wartość.',
'email' => ':attribute musi być prawidłowym adresem e-mail.',
'exists' => 'Wybrnay :attribute nie istnieje.',
'file' => ':attribute musi być plikiem.',
'filled' => 'Pole :attribute nie może być puste.',
'image' => ':attribute musi być obrazem.',
'in' => 'Wybrany :attribute jest nieprawidłowy.',
'in_array' => 'Pole :attribute nie istnieje w :other.',
'integer' => ':attribute musi być liczbą całkowitą.',
'ip' => ':attribute musi być prawidłowym adresem IP.',
'ipv4' => ':attribute musi być prawidłowym adresem IPv4.',
'ipv6' => ':attribute musi być prawidłowym adresem IPv6.',
'json' => ':attribute musi być poprawnym łańcuchem JSON.',
'max' => [
'numeric' => ':attribute nie może być większa niż :max.',
'file' => 'Rozmiar :attribute nie może być większy niż :max kilobajtów.',
'string' => ':attribute nie może zawierać więcej niż :max znaków.',
'array' => ':attribute nie może zawierać więcej niż :max elementów.',
],
'mimes' => ':attribute musi być plikiem typu: :values.',
'mimetypes' => ':attribute musi być plikiem typu: :values.',
'min' => [
'numeric' => ':attribute musi wynosić conajmniej :min.',
'file' => 'Rozmiar :attribute musi być rowny lub większy niż :min kilobajtów.',
'string' => ':attribute musi zawierać conajmniej :min znaków.',
'array' => ':attribute musi zawierać conajmniej :min elementów.',
],
'not_in' => ':attribute jest nieprawidłowy.',
'numeric' => ':attribute musi być liczbą.',
'present' => 'Obecność pola :attribute jest obowiązkowa.',
'regex' => 'Format :attribute jest nieprawidłowy.',
'required' => ':attribute jest wymagany.',
'required_if' => 'Pole :attribute jest wymagane gdy :other wynosi :value.',
'required_unless' => 'Pole :attribute jest wymagane, chyba że :other jest zawarte w :values.',
'required_with' => 'Pole :attribute jest wymagane gdy pole :values jest obecne.',
'required_with_all' => 'Pole :attribute jest wymagane gdy :values jest obecne.',
'required_without' => 'Pole :attribute jest wymagane gdy pole :values NIE jest obecne.',
'required_without_all' => 'Pole :attribute jest wymagane gdy żadne z pól :values NIE jest obecne.',
'same' => 'Pole :attribute oraz :other muszą być takie same.',
'size' => [
'numeric' => ':attribute musi wynosić dokladnie :size.',
'file' => 'Rozmiar :attribute musi być równy :size kilobajtów.',
'string' => ':attribute musi składać się dokładnie z :size znaków.',
'array' => ':attribute musi składać się dokładnie z :size elementów.',
],
'string' => ':attribute musi być łańcuchem znaków.',
'timezone' => ':attribute musi być prawidłową strefą czasową.',
'unique' => ':attribute jest już zajety.',
'uploaded' => 'Nie udało się przesłać :attribute.',
'url' => ':attribute ma nieprawidłowy format.',
/*
|--------------------------------------------------------------------------
| Custom Validation Language Lines
|--------------------------------------------------------------------------
|
| Here you may specify custom validation messages for attributes using the
| convention "attribute.rule" to name the lines. This makes it quick to
| specify a specific custom language line for a given attribute rule.
|
*/
'custom' => [
'attribute-name' => [
'rule-name' => 'dowlona-wiadomosc',
],
],
/*
|--------------------------------------------------------------------------
| Custom Validation Attributes
|--------------------------------------------------------------------------
|
| The following language lines are used to swap attribute place-holders
| with something more reader friendly such as E-Mail Address instead
| of "email". This simply helps us make messages a little cleaner.
|
*/
'attributes' => [],
];

View File

@@ -23,6 +23,8 @@
<meta name="msapplication-TileColor" content="#ffffff">
<meta name="msapplication-TileImage" content="/ms-icon-144x144.png">
<meta name="theme-color" content="#ffffff">
<meta name="mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-capable" content="yes">
<link rel="stylesheet" href="{{ mix('css/app.css') }}" type="text/css" />
</head>
@@ -37,7 +39,7 @@
<?php
$active = ((bool)$app->pinned === true) ? 'active' : '';
?>
<li>{{ $app->title }}<a class="{{ $active }}" data-id="{{ $app->id }}" href="{{ route('items.pintoggle', $app->id) }}"><i class="fas fa-thumbtack"></i></a></li>
<li>{{ $app->title }}<a class="{{ $active }}" data-id="{{ $app->id }}" href="{{ route('items.pintoggle', [$app->id], false) }}"><i class="fas fa-thumbtack"></i></a></li>
@endforeach
</ul>
@@ -46,8 +48,8 @@
<div class="content">
<header class="appheader">
<ul>
<li><a href="{{ route('dash') }}">Dash</a></li><li>
<a href="{{ route('items.index') }}">Items</a></li>
<li><a href="{{ route('dash', [], false) }}">Dash</a></li><li>
<a href="{{ route('items.index', [], false) }}">Items</a></li>
</ul>
</header>
<main>
@@ -72,13 +74,14 @@
@yield('content')
<div id="config-buttons">
@if(Route::is('dash'))
@if(Route::is('dash') || Route::is('tags.show'))
<a id="config-button" class="config" href=""><i class="fas fa-exchange"></i></a>
@endif
<a id="dash" class="config" href="{{ route('dash') }}"><i class="fas fa-th"></i></a>
<a id="items" class="config" href="{{ route('items.index') }}"><i class="fas fa-list"></i></a>
<a id="settings" class="config" href="{{ route('settings.index') }}"><i class="fas fa-cogs"></i></a>
<a id="dash" class="config" href="{{ route('dash', [], false) }}"><i class="fas fa-th"></i></a>
<a id="items" class="config" href="{{ route('items.index', [], false) }}"><i class="fas fa-list"></i></a>
<a id="folder" class="config" href="{{ route('tags.index', [], false) }}"><i class="fas fa-tag"></i></a>
<a id="settings" class="config" href="{{ route('settings.index', [], false) }}"><i class="fas fa-cogs"></i></a>
</div>
</main>
@@ -87,7 +90,7 @@
<script src="//ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script>!window.jQuery && document.write('<script src="/js/jquery-3.3.1.min.js"><\/script>')</script>
<script src="//ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
<script src="{{ asset('js/app.js') }}"></script>
<script src="/js/app.js?v=2"></script>
@yield('scripts')
</body>

View File

@@ -1,9 +1,9 @@
<section class="item-container" data-id="{{ $app->id }}">
<section class="item-container{{ $app->droppable }}" data-id="{{ $app->id }}">
<div class="item" style="background-color: {{ $app->colour }}">
@if($app->icon)
<img class="app-icon" src="{{ asset('storage/'.$app->icon) }}" />
<img class="app-icon" src="/storage/{{ $app->icon }}" />
@else
<img class="app-icon" src="{{ asset('img/heimdall-icon-small.png') }}" />
<img class="app-icon" src="/img/heimdall-icon-small.png" />
@endif
<div class="details">
<div class="title">{{ $app->title }}</div>
@@ -11,8 +11,8 @@
<div data-id="{{ $app->id }}" data-dataonly="{{ $app->config->dataonly or '0' }}" class="livestats-container"></div>
@endif
</div>
<a class="link" href="{{ $app->url }}"><i class="fas fa-arrow-alt-to-right"></i></a>
<a class="link"{!! $app->link_target !!} href="{{ $app->link }}"><i class="fas {{ $app->link_icon }}"></i></a>
</div>
<a class="item-edit" href="{{ route('items.edit', $app->id) }}"><i class="fas fa-pencil"></i></a>
<a class="item-edit" href="{{ route($app->link_type.'.edit', [ $app->id ], false) }}"><i class="fas fa-pencil"></i></a>
</section>

View File

@@ -3,7 +3,7 @@
<div class="section-title">{{ __('app.apps.add_application') }}</div>
<div class="module-actions">
<button type="submit"class="button"><i class="fa fa-save"></i><span>{{ __('app.buttons.save') }}</span></button>
<a href="{{ route('items.index') }}" class="button"><i class="fa fa-ban"></i><span>{{ __('app.buttons.cancel') }}</span></a>
<a href="{{ route('items.index', [], false) }}" class="button"><i class="fa fa-ban"></i><span>{{ __('app.buttons.cancel') }}</span></a>
</div>
</header>
<div id="create" class="create">
@@ -15,10 +15,6 @@
<hr />
<label>{{ strtoupper(__('app.url')) }}</label>
{!! Form::text('url', null, array('placeholder' => __('app.url'), 'id' => 'appurl', 'class' => 'form-control')) !!}
</div>
<div class="input">
<label>{{ __('app.apps.colour') }} *</label>
{!! Form::text('colour', null, array('placeholder' => __('app.apps.hex'),'class' => 'form-control color-picker')) !!}
<hr />
<label>{{ __('app.apps.pinned') }}</label>
{!! Form::hidden('pinned', '0') !!}
@@ -31,6 +27,14 @@
<input type="checkbox" name="pinned" value="1"<?php echo $set_checked;?> />
<span class="slider round"></span>
</label>
</div>
<div class="input">
<label>{{ __('app.apps.colour') }} *</label>
{!! Form::text('colour', null, array('placeholder' => __('app.apps.hex'),'class' => 'form-control color-picker')) !!}
<hr />
<label>{{ __('app.apps.tags') }} ({{ __('app.optional') }})</label>
{!! Form::select('tags[]', $tags, $current_tags, ['class' => 'tags', 'multiple']) !!}
</div>
<div class="input">
<label>{{ __('app.apps.icon') }}</label>
@@ -43,11 +47,13 @@
?>
<img src="{{ asset('storage/'.$icon) }}" />
{!! Form::hidden('icon', $icon, ['class' => 'form-control']) !!}
@else
<img src="/img/heimdall-icon-small.png" />
@endif
</div>
<div class="upload-btn-wrapper">
<button class="btn">{{ __('app.buttons.upload')}} </button>
<input type="file" name="file" />
<input type="file" id="upload" name="file" />
</div>
</div>
</div>
@@ -67,7 +73,7 @@
<div class="section-title">&nbsp;</div>
<div class="module-actions">
<button type="submit"class="button"><i class="fa fa-save"></i><span>{{ __('app.buttons.save') }}</span></button>
<a href="{{ route('items.index') }}" class="button"><i class="fa fa-ban"></i><span>{{ __('app.buttons.cancel') }}</span></a>
<a href="{{ route('items.index', [], false) }}" class="button"><i class="fa fa-ban"></i><span>{{ __('app.buttons.cancel') }}</span></a>
</div>
</footer>

View File

@@ -6,12 +6,13 @@
<div class="section-title">
{{ __('app.apps.app_list') }}
@if( isset($trash) && $trash->count() > 0 )
<a class="trashed" href="{{ route('items.index', ['trash' => true]) }}">{{ __('app.apps.view_trash') }} ({{ $trash->count() }})</a>
<a class="trashed" href="{{ route('items.index', ['trash' => true], false) }}">{{ __('app.apps.view_trash') }} ({{ $trash->count() }})</a>
@endif
</div>
<div class="module-actions">
<a href="{{ route('items.create') }}" title="" class="button"><i class="fa fa-plus"></i><span>{{ __('app.buttons.add') }}</span></a>
<a href="{{ route('items.create', [], false) }}" title="" class="button"><i class="fa fa-plus"></i><span>{{ __('app.buttons.add') }}</span></a>
<a href="{{ route('dash', [], false) }}" class="button"><i class="fa fa-ban"></i><span>{{ __('app.buttons.cancel') }}</span></a>
</div>
</header>
@@ -29,8 +30,8 @@
@foreach($apps as $app)
<tr>
<td>{{ $app->title }}</td>
<td><a href="{{ $app->url }}">{{ $app->url }}</a></td>
<td class="text-center"><a href="{!! route('items.edit', $app->id) !!}" title="{{ __('app.settings.edit') }} {!! $app->title !!}"><i class="fas fa-edit"></i></a></td>
<td><a href="{{ $app->url }}">{{ $app->link }}</a></td>
<td class="text-center"><a{{ $app->target }} href="{!! route('items.edit', [$app->id], false) !!}" title="{{ __('app.settings.edit') }} {!! $app->title !!}"><i class="fas fa-edit"></i></a></td>
<td class="text-center">
{!! Form::open(['method' => 'DELETE','route' => ['items.destroy', $app->id],'style'=>'display:inline']) !!}
<button class="link" type="submit"><i class="fa fa-trash-alt"></i></button>

View File

@@ -1,3 +1,4 @@
<script src="/js/select2.min.js"></script>
<script>
$( function() {
@@ -30,5 +31,8 @@
}, "json");
}
});
$('.tags').select2();
});
</script>

View File

@@ -7,7 +7,7 @@
Showing Deleted Applications
</div>
<div class="module-actions">
<a href="{{ route('items.index') }}" title="" class="button"><i class="fa fa-ban"></i><span>{{ __('app.buttons.cancel') }}</span></a>
<a href="{{ route('items.index', [], false) }}" title="" class="button"><i class="fa fa-ban"></i><span>{{ __('app.buttons.cancel') }}</span></a>
</div>
</header>
@@ -26,7 +26,7 @@
<tr>
<td>{{ $app->title }}</td>
<td>{{ __('app.url') }}</td>
<td class="text-center"><a href="{!! route('items.restore', $app->id) !!}" title="{{ __('app.restore') }} {!! $app->title !!}"><i class="fas fa-undo"></i></a></td>
<td class="text-center"><a href="{!! route('items.restore', [$app->id], false) !!}" title="{{ __('app.restore') }} {!! $app->title !!}"><i class="fas fa-undo"></i></a></td>
<td class="text-center">
{!! Form::open(['method' => 'DELETE','route' => ['items.destroy', $app->id],'style'=>'display:inline']) !!}
<input type="hidden" name="force" value="1" />

View File

@@ -3,7 +3,7 @@
<div class="section-title">{{ __($setting->label) }}</div>
<div class="module-actions">
<button type="submit"class="button"><i class="fa fa-save"></i><span>{{ __('app.buttons.save') }}</span></button>
<a href="{{ route('settings.index') }}" class="button"><i class="fa fa-ban"></i><span>{{ __('app.buttons.cancel') }}</span></a>
<a href="{{ route('settings.index', [], false) }}" class="button"><i class="fa fa-ban"></i><span>{{ __('app.buttons.cancel') }}</span></a>
</div>
</header>
<div class="create">
@@ -23,7 +23,7 @@
<div class="section-title">&nbsp;</div>
<div class="module-actions">
<button type="submit"class="button"><i class="fa fa-save"></i><span>{{ __('app.buttons.save') }}</span></button>
<a href="{{ route('settings.index') }}" class="button"><i class="fa fa-ban"></i><span>{{ __('app.buttons.cancel') }}</span></a>
<a href="{{ route('settings.index', [], false) }}" class="button"><i class="fa fa-ban"></i><span>{{ __('app.buttons.cancel') }}</span></a>
</div>
</footer>

View File

@@ -29,7 +29,7 @@
</td>
<td class="text-center">
@if((bool)$setting->system !== true)
<a href="{!! route('settings.edit', ['id' => $setting->id]) !!}" title="{{ __('app.settings.edit') }} {!! $setting->label !!}" class="secondary"><i class="fa fa-pencil"></i></a>
<a href="{!! route('settings.edit', ['id' => $setting->id], false) !!}" title="{{ __('app.settings.edit') }} {!! $setting->label !!}" class="secondary"><i class="fa fa-pencil"></i></a>
@endif
</td>
</tr>

View File

@@ -0,0 +1,13 @@
<h2>{{ __('app.apps.config') }} ({{ __('app.optional') }})</h2>
<div class="items">
<input type="hidden" name="config[enabled]" value="1" />
<input type="hidden" data-config="dataonly" class="config-item" name="config[dataonly]" value="1" />
<input type="hidden" data-config="type" class="config-item" name="config[type]" value="\App\SupportedApps\CouchPotato" />
<div class="input">
<label>{{ __('app.apps.apikey') }}</label>
{!! Form::text('config[apikey]', null, array('placeholder' => __('app.apps.apikey'), 'data-config' => 'apikey', 'class' => 'form-control config-item')) !!}
</div>
<div class="input">
<button style="margin-top: 32px;" class="btn test" id="test_config">Test</button>
</div>
</div>

View File

@@ -1,13 +1,18 @@
<h2>{{ __('app.apps.config') }} ({{ __('app.optional') }})</h2>
<div class="items">
<input type="hidden" data-config="type" class="config-item" name="config[type]" value="\App\SupportedApps\Nzbget" />
<div class="input">
<label>{{ strtoupper(__('app.url')) }}</label>
{!! Form::text('config[override_url]', null, array('placeholder' => __('app.apps.override'), 'id' => 'override_url', 'class' => 'form-control')) !!}
</div>
<div class="input">
<label>{{ __('app.apps.username') }}</label>
{!! Form::text('config[username]', null, array('placeholder' => __('app.apps.username'), 'data-config' => 'username', 'class' => 'form-control config-item')) !!}
</div>
<div class="input">
<label>{{ __('app.apps.password') }}</label>
<input type="password" name="config[password]" value="{{ $item->config->password }}" placeholder="{{ __('app.apps.password') }}" class="form-control config-item" data-config="password" />
<input type="password" name="config[password]" value="{{ $item->config->password or '' }}" placeholder="{{ __('app.apps.password') }}" class="form-control config-item" data-config="password" />
</div>
<div class="input">
<button style="margin-top: 32px;" class="btn test" id="test_config">Test</button>

View File

@@ -2,6 +2,11 @@
<div class="items">
<input type="hidden" data-config="type" class="config-item" name="config[type]" value="\App\SupportedApps\Pihole" />
<input type="hidden" data-config="dataonly" class="config-item" name="config[dataonly]" value="1" />
<div class="input">
<label>{{ strtoupper(__('app.url')) }}</label>
{!! Form::text('config[override_url]', null, array('placeholder' => __('app.apps.override'), 'id' => 'override_url', 'class' => 'form-control')) !!}
</div>
<div class="input">
<label>{{ __('app.apps.enable') }}</label>
{!! Form::hidden('config[enabled]', '0') !!}

View File

@@ -0,0 +1,15 @@
<h2>{{ __('app.apps.config') }} ({{ __('app.optional') }})</h2>
<div class="items">
<input type="hidden" data-config="type" class="config-item" name="config[type]" value="\App\SupportedApps\Plexpy" />
<div class="input">
<label>{{ strtoupper(__('app.url')) }}</label>
{!! Form::text('config[override_url]', null, array('placeholder' => __('app.apps.override'), 'id' => 'override_url', 'class' => 'form-control')) !!}
</div>
<div class="input">
<label>{{ __('app.apps.apikey') }}</label>
{!! Form::text('config[apikey]', null, array('placeholder' => __('app.apps.apikey'), 'data-config' => 'apikey', 'class' => 'form-control config-item')) !!}
</div>
<div class="input">
<button style="margin-top: 32px;" class="btn test" id="test_config">Test</button>
</div>
</div>

View File

@@ -1,6 +1,11 @@
<h2>{{ __('app.apps.config') }} ({{ __('app.optional') }})</h2>
<div class="items">
<input type="hidden" data-config="type" class="config-item" name="config[type]" value="\App\SupportedApps\Proxmox" />
<div class="input">
<label>{{ strtoupper(__('app.url')) }}</label>
{!! Form::text('config[override_url]', null, array('placeholder' => __('app.apps.override'), 'id' => 'override_url', 'class' => 'form-control')) !!}
</div>
<div class="input">
<label>{{ __('app.apps.username') }}</label>
{!! Form::text('config[username]', null, array('placeholder' => __('app.apps.username'), 'data-config' => 'username', 'class' => 'form-control config-item')) !!}

View File

@@ -0,0 +1,26 @@
<h2>{{ __('app.apps.config') }} ({{ __('app.optional') }})</h2>
<div class="items">
<input type="hidden" data-config="type" class="config-item" name="config[type]" value="\App\SupportedApps\Runeaudio" />
<input type="hidden" data-config="dataonly" class="config-item" name="config[dataonly]" value="1" />
<div class="input">
<label>{{ strtoupper(__('app.url')) }}</label>
{!! Form::text('config[override_url]', null, array('placeholder' => __('app.apps.override'), 'id' => 'override_url', 'class' => 'form-control')) !!}
</div>
<div class="input">
<label>{{ __('app.apps.enable') }}</label>
{!! Form::hidden('config[enabled]', '0') !!}
<label class="switch">
<?php
$checked = false;
if(isset($item->config->enabled) && (bool)$item->config->enabled === true) $checked = true;
$set_checked = ($checked) ? ' checked="checked"' : '';
?>
<input type="checkbox" name="config[enabled]" value="1"<?php echo $set_checked;?> />
<span class="slider round"></span>
</label>
</div>
<div class="input">
<button style="margin-top: 32px;" class="btn test" id="test_config">Test</button>
</div>
</div>

View File

@@ -1,6 +1,12 @@
<h2>{{ __('app.apps.config') }} ({{ __('app.optional') }})</h2>
<div class="items">
<input type="hidden" data-config="type" class="config-item" name="config[type]" value="\App\SupportedApps\Sabnzbd" />
<div class="input">
<label>{{ strtoupper(__('app.url')) }}</label>
{!! Form::text('config[override_url]', null, array('placeholder' => __('app.apps.override'), 'id' => 'override_url', 'class' => 'form-control')) !!}
</div>
<div class="input">
<label>{{ __('app.apps.apikey') }}</label>
{!! Form::text('config[apikey]', null, array('placeholder' => __('app.apps.apikey'), 'data-config' => 'apikey', 'class' => 'form-control config-item')) !!}

View File

@@ -0,0 +1,15 @@
<h2>{{ __('app.apps.config') }} ({{ __('app.optional') }})</h2>
<div class="items">
<input type="hidden" data-config="type" class="config-item" name="config[type]" value="\App\SupportedApps\Tautulli" />
<div class="input">
<label>{{ strtoupper(__('app.url')) }}</label>
{!! Form::text('config[override_url]', null, array('placeholder' => __('app.apps.override'), 'id' => 'override_url', 'class' => 'form-control')) !!}
</div>
<div class="input">
<label>{{ __('app.apps.apikey') }}</label>
{!! Form::text('config[apikey]', null, array('placeholder' => __('app.apps.apikey'), 'data-config' => 'apikey', 'class' => 'form-control config-item')) !!}
</div>
<div class="input">
<button style="margin-top: 32px;" class="btn test" id="test_config">Test</button>
</div>
</div>

View File

@@ -0,0 +1,16 @@
<h2>{{ __('app.apps.config') }} ({{ __('app.optional') }})</h2>
<div class="items">
<input type="hidden" name="config[enabled]" value="1" />
<input type="hidden" data-config="type" class="config-item" name="config[type]" value="\App\SupportedApps\Transmission" />
<div class="input">
<label>{{ __('app.apps.username') }}</label>
{!! Form::text('config[username]', null, array('placeholder' => __('app.apps.username'), 'data-config' => 'username', 'class' => 'form-control config-item')) !!}
</div>
<div class="input">
<label>{{ __('app.apps.password') }}</label>
{!! Form::text('config[password]', null, array('placeholder' => __('app.apps.password'), 'data-config' => 'password', 'class' => 'form-control config-item')) !!}
</div>
<div class="input">
<button style="margin-top: 32px;" class="btn test" id="test_config">Test</button>
</div>
</div>

View File

@@ -0,0 +1,12 @@
@extends('app')
@section('content')
{!! Form::open(array('route' => 'tags.store', 'id' => 'itemform', 'files' => true, 'method'=>'POST')) !!}
@include('tags.form')
{!! Form::close() !!}
@endsection
@section('scripts')
@include('tags.scripts')
@endsection

View File

@@ -0,0 +1,12 @@
@extends('app')
@section('content')
{!! Form::model($item, ['method' => 'PATCH', 'id' => 'itemform', 'files' => true, 'route' => ['tags.update', $item->id]]) !!}
@include('tags.form')
{!! Form::close() !!}
@endsection
@section('scripts')
@include('tags.scripts')
@endsection

View File

@@ -0,0 +1,76 @@
<section class="module-container">
<header>
<div class="section-title">{{ __('app.apps.add_tag') }}</div>
<div class="module-actions">
<button type="submit"class="button"><i class="fa fa-save"></i><span>{{ __('app.buttons.save') }}</span></button>
<a href="{{ route('tags.index', [], false) }}" class="button"><i class="fa fa-ban"></i><span>{{ __('app.buttons.cancel') }}</span></a>
</div>
</header>
<div id="create" class="create">
{!! csrf_field() !!}
<div class="input">
<label>{{ __('app.apps.tag_name') }} *</label>
{!! Form::text('title', null, array('placeholder' => __('app.apps.title'), 'class' => 'form-control')) !!}
<hr />
<label>{{ __('app.apps.pinned') }}</label>
{!! Form::hidden('pinned', '0') !!}
<label class="switch">
<?php
$checked = false;
if(isset($item->pinned) && (bool)$item->pinned === true) $checked = true;
$set_checked = ($checked) ? ' checked="checked"' : '';
?>
<input type="checkbox" name="pinned" value="1"<?php echo $set_checked;?> />
<span class="slider round"></span>
</label>
</div>
<div class="input">
<label>{{ __('app.apps.colour') }} *</label>
{!! Form::text('colour', null, array('placeholder' => __('app.apps.hex'),'class' => 'form-control color-picker')) !!}
<hr />
</div>
<div class="input">
<label>{{ __('app.apps.icon') }}</label>
<div class="icon-container">
<div id="appimage">
@if(isset($item->icon) && !empty($item->icon) || old('icon'))
<?php
if(isset($item->icon)) $icon = $item->icon;
else $icon = old('icon');
?>
<img src="{{ asset('storage/'.$icon) }}" />
{!! Form::hidden('icon', $icon, ['class' => 'form-control']) !!}
@else
<img src="/img/heimdall-icon-small.png" />
@endif
</div>
<div class="upload-btn-wrapper">
<button class="btn">{{ __('app.buttons.upload')}} </button>
<input type="file" id="upload" name="file" />
</div>
</div>
</div>
@if(isset($item) && isset($item->config->view))
<div id="sapconfig" style="display: block;">
@if(isset($item))
@include('supportedapps.'.$item->config->view)
@endif
</div>
@else
<div id="sapconfig"></div>
@endif
</div>
<footer>
<div class="section-title">&nbsp;</div>
<div class="module-actions">
<button type="submit"class="button"><i class="fa fa-save"></i><span>{{ __('app.buttons.save') }}</span></button>
<a href="{{ route('tags.index', [], false) }}" class="button"><i class="fa fa-ban"></i><span>{{ __('app.buttons.cancel') }}</span></a>
</div>
</footer>
</section>

View File

@@ -0,0 +1,56 @@
@extends('app')
@section('content')
<section class="module-container">
<header>
<div class="section-title">
{{ __('app.apps.tag_list') }}
@if( isset($trash) && $trash->count() > 0 )
<a class="trashed" href="{{ route('tags.index', ['trash' => true], false) }}">{{ __('app.apps.view_trash') }} ({{ $trash->count() }})</a>
@endif
</div>
<div class="module-actions">
<a href="{{ route('tags.create', [], false) }}" title="" class="button"><i class="fa fa-plus"></i><span>{{ __('app.buttons.add') }}</span></a>
<a href="{{ route('dash', [], false) }}" class="button"><i class="fa fa-ban"></i><span>{{ __('app.buttons.cancel') }}</span></a>
</div>
</header>
<table class="table table-hover">
<thead>
<tr>
<th>{{ __('app.title') }}</th>
<th>{{ __('app.url') }}</th>
<th class="text-center" width="100">{{ __('app.settings.edit') }}</th>
<th class="text-center" width="100">{{ __('app.delete') }}</th>
</tr>
</thead>
<tbody>
@if($apps->first())
@foreach($apps as $app)
<tr>
<td>{{ $app->title }}</td>
<td><a{{ $app->target }} href="{{ $app->url }}">{{ $app->link }}</a></td>
<td class="text-center"><a href="{!! route('tags.edit', [$app->id], false) !!}" title="{{ __('app.settings.edit') }} {!! $app->title !!}"><i class="fas fa-edit"></i></a></td>
<td class="text-center">
{!! Form::open(['method' => 'DELETE','route' => ['tags.destroy', $app->id],'style'=>'display:inline']) !!}
<button class="link" type="submit"><i class="fa fa-trash-alt"></i></button>
{!! Form::close() !!}
</td>
</tr>
@endforeach
@else
<tr>
<td colspan="4" class="form-error text-center">
<strong>{{ __('app.settings.no_items') }}</strong>
</td>
</tr>
@endif
</tbody>
</table>
</section>
@endsection

View File

@@ -0,0 +1,10 @@
<script>
$( function() {
var elem = $('.color-picker')[0];
var hueb = new Huebee( elem, {
// options
});
});
</script>

View File

@@ -0,0 +1,52 @@
@extends('app')
@section('content')
<section class="module-container">
<header>
<div class="section-title">
Showing Deleted Applications
</div>
<div class="module-actions">
<a href="{{ route('tags.index', [], false) }}" title="" class="button"><i class="fa fa-ban"></i><span>{{ __('app.buttons.cancel') }}</span></a>
</div>
</header>
<table class="table table-hover">
<thead>
<tr>
<th>{{ __('app.title') }}</th>
<th>Url</th>
<th class="text-center" width="100">{{ __('app.restore') }}</th>
<th class="text-center" width="100">{{ __('app.delete') }}</th>
</tr>
</thead>
<tbody>
@if($trash->first())
@foreach($trash as $app)
<tr>
<td>{{ $app->title }}</td>
<td>{{ __('app.url') }}</td>
<td class="text-center"><a href="{!! route('tags.restore', [ $app->id ], false) !!}" title="{{ __('app.restore') }} {!! $app->title !!}"><i class="fas fa-undo"></i></a></td>
<td class="text-center">
{!! Form::open(['method' => 'DELETE','route' => ['tags.destroy', $app->id],'style'=>'display:inline']) !!}
<input type="hidden" name="force" value="1" />
<button type="submit"><i class="fa fa-trash-alt"></i></button>
{!! Form::close() !!}
</td>
</tr>
@endforeach
@else
<tr>
<td colspan="5" class="form-error text-center">
<strong>{{ __('app.settings.no_items') }}</strong>
</td>
</tr>
@endif
</tbody>
</table>
</section>
@endsection

View File

@@ -10,7 +10,7 @@
<div class="alert alert-danger">
<p>{!! __('app.dash.no_apps',
[
'link1' => '<a href="'.route('items.create').'">'.__('app.dash.link1').'</a>',
'link1' => '<a href="'.route('items.create', [], false).'">'.__('app.dash.link1').'</a>',
'link2' => '<a id="pin-item" href="">'.__('app.dash.link2').'</a>'
]) !!}</p>
</div>

View File

@@ -15,7 +15,13 @@ Route::get('/', 'ItemController@dash')->name('dash');
Route::resources([
'items' => 'ItemController',
'tags' => 'TagController',
]);
Route::get('tag/{slug}', 'TagController@show')->name('tags.show');
Route::get('tag/add/{tag}/{item}', 'TagController@add')->name('tags.add');
Route::get('items/pin/{id}', 'ItemController@pin')->name('items.pin');
Route::get('items/restore/{id}', 'ItemController@restore')->name('items.restore');
Route::get('items/unpin/{id}', 'ItemController@unpin')->name('items.unpin');

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

Some files were not shown because too many files have changed in this diff Show More