Compare commits

...

119 Commits

Author SHA1 Message Date
Yusuke Arakawa
662f6ac3eb chore: Sort the supported language list of readme.md (#1062) 2022-12-09 09:40:52 +01:00
Attila Kerekes
11257a272e feat: Introduce queue based live stat refresh (#1059) 2022-12-05 16:29:06 +01:00
Attila Kerekes
6b93f8ed5c test: Add item create test (#1058) 2022-12-05 16:28:18 +01:00
Attila Kerekes
8f9b2959b2 feat: Add basic import screen (#1056)
Co-authored-by: Chris Hunt <chris.hunt@kasmweb.com>
2022-12-04 22:12:54 +01:00
Attila Kerekes
45cc84c99c test: Add feature tests 2022-12-04 17:21:03 +00:00
Attila Kerekes
52620bc331 chore: Add laravel ide helper 2022-12-01 09:17:54 +00:00
Attila Kerekes
bd76efc613 chore: Migrate route definition to Laravel 8 format 2022-11-29 21:34:11 +00:00
Attila Kerekes
6dead1c529 fix: Make supportedApps legacy interface compatible 2022-11-29 19:26:07 +00:00
Attila Kerekes
bb5a078f35 feat: Add export import 2022-11-29 17:32:46 +00:00
Attila Kerekes
2ee5d07e48 fix: Make supportedapps compatible with legacy interface 2022-11-29 17:26:40 +00:00
Attila Kerekes
d30edb6749 chore: Add eslint prettier phpcs config PSR2 2022-11-28 19:47:10 +00:00
Chris Hunt
a53192beeb FIx: Blur onauxclick as well 2022-11-28 08:33:05 +00:00
Chris Hunt
ef1ffe880d Update version to 2.5.4 2022-11-28 08:30:34 +00:00
KodeStar
877b31f947 Merge pull request #1041 from linuxserver/bug/links_opening_in_new_tab_keep_focus
Blur tiles after clicking on them
2022-11-26 17:02:45 +00:00
Chris Hunt
827088df76 Blur tiles after clicking on them 2022-11-26 14:48:54 +00:00
Attila Kerekes
a12c1d559d fix: Use correct appTest argument type 2022-11-26 13:31:05 +00:00
KodeStar
f0b60fc19a Merge pull request #1039 from linuxserver/fix/1038
fix: Enter should open search when not tile search is selected
2022-11-26 12:00:43 +00:00
Attila Kerekes
7c4619adb9 fix: Enter should open search when not tile search is selected 2022-11-26 12:22:12 +01:00
KodeStar
aa49a5fb42 Fixes #371 Tagged items when pinning/unpinning (#1036) 2022-11-25 23:21:45 +00:00
Attila Jozsef Kerekes
7565bd4028 chore: Add php code sniffer and apply fixes 2022-11-25 23:05:58 +00:00
Chris Hunt
181b7564e8 Merge branch '2.x' of github.com:linuxserver/Heimdall into 2.x 2022-11-25 16:23:40 +00:00
Chris Hunt
0d3640b67a Fix asset links 2022-11-25 16:23:34 +00:00
Attila Kerekes
82b209d4b5 fix: Test enhanced app with apikey 2022-11-25 16:11:39 +00:00
Chris Hunt
f576a82803 Fix: Change default logging to daily 2022-11-24 22:56:27 +00:00
Attila Kerekes
bb07ba5964 feat: Add db connection example config 2022-11-24 14:28:16 +00:00
Attila Kerekes
9aaa900a3e fix: New package lock with node 18.12 2022-11-24 08:36:20 +00:00
KodeStar
07f07449b9 Update: Updated npm dependencies + using mix (#1026) 2022-11-23 19:39:00 +00:00
Attila Kerekes
2836dadf1a fix: Disable saerch submit when tile search is active 2022-11-23 18:12:21 +00:00
KodeStar
4a90fdf22d Merge pull request #1024 from KodeStar/2.x
Updated translations using lokalise.com
2022-11-23 15:11:54 +00:00
KodeStar
0de56e5876 Merge pull request #5 from KodeStar/lokalise-2022-11-23_16-08-41
Lokalise: Translations update
2022-11-23 15:10:37 +00:00
KodeStar
d886b44c1e Updated translations using lokalise.com 2022-11-23 15:09:10 +00:00
Chris Hunt
898ee6915d Merge branch '2.x' of github.com:linuxserver/Heimdall into 2.x 2022-11-23 13:25:10 +00:00
Chris Hunt
f6eae7f25f FIx: Use mix version rather than app version 2022-11-23 13:24:36 +00:00
KodeStar
c1255280aa Merge pull request #1023 from linuxserver/feature/focus_and_sidebar_tooltips
Feature - focus and sidebar tooltips
2022-11-23 10:50:07 +00:00
Chris Hunt
5514d893f8 Fix: Add translations to sidebar tooltips 2022-11-23 10:19:27 +00:00
Chris Hunt
c4d5ca43dd Feature: Add focus styling 2022-11-23 10:09:16 +00:00
Chris Hunt
a90bcb1151 Fix: Move tooltips in from right 2022-11-23 09:42:33 +00:00
Chris Hunt
ffc736ada6 Fix: Added nicer tooltips to sidebar 2022-11-23 09:29:52 +00:00
KodeStar
966027faf5 Merge pull request #1022 from keriati/feat/kbr 2022-11-23 08:41:21 +00:00
Attila Kerekes
1111bf72d6 feat: Add basic keyboard navigation 2022-11-22 22:53:07 +01:00
KodeStar
cc6e47372e Merge pull request #1020 from keriati/feat/nopwsubmit
feat: Prevent password submission when password is not changed.
2022-11-22 17:06:16 +00:00
KodeStar
256160727c Merge pull request #1019 from keriati/feat/uniqueappupdate
feat: Make app update job unique
2022-11-22 17:05:28 +00:00
Attila Kerekes
0299ee6fa9 feat: Prevent password submission when password is not changed. 2022-11-22 17:52:10 +01:00
Attila Kerekes
8957a2f49f feat: Make app update job unique 2022-11-22 17:23:26 +01:00
KodeStar
756ab353f3 Merge pull request #1018 from keriati/feat/appupdatejob
feat: Move app update to background job
2022-11-22 09:12:16 +00:00
Attila Kerekes
76f0b84827 feat: Move app update to background job 2022-11-22 00:05:57 +01:00
KodeStar
68c8dbc33a Merge pull request #1017 from keriati/fix/appupdatereduce
fix: Throttle app updates when updating to new version.
2022-11-20 20:44:43 +00:00
Attila Kerekes
b1e856ccfc fix: Throttle app updates when updating to new version. 2022-11-20 21:37:13 +01:00
KodeStar
44fb923b7f Merge pull request #1015 from keriati/feat/testpwinject
feat: Inject password from db during testing when editing enhanced apps
2022-11-19 19:53:32 +00:00
Attila Kerekes
8bad474808 feat: Inject password from db during testing when editing enhanced apps 2022-11-19 20:48:31 +01:00
KodeStar
9a80064a50 Merge pull request #1014 from KodeStar/2.x
Automated missing translation strings using lokalise.com
2022-11-19 13:22:28 +00:00
KodeStar
e86c5e601d Merge pull request #4 from KodeStar/lokalise-2022-11-19_14-15-24
Lokalise: Translations update
2022-11-19 13:18:05 +00:00
KodeStar
c4bf619be4 Updated translations using lokalise.com 2022-11-19 13:15:51 +00:00
KodeStar
4b29b476df Merge pull request #1012 from keriati/feat/appupdateon
feat: Trigger app update when new version is deployed
2022-11-19 12:41:09 +00:00
KodeStar
3a39809585 Merge pull request #1013 from keriati/fix/fri18n
fix: Add missing FR translations
2022-11-19 12:04:58 +00:00
Attila Kerekes
157b972ff5 feat: Trigger app update when new version is deployed 2022-11-18 17:35:55 +01:00
Attila Kerekes
71b15a5aed fix: Add missing FR translations 2022-11-18 17:12:50 +01:00
KodeStar
b50bf716dc Merge pull request #1010 from keriati/feat/enhancedapppw
feat: Keep stored password when Enhanced App is updated
2022-11-17 21:20:16 +00:00
KodeStar
722d00df5f Merge pull request #1009 from keriati/feat/eslangupdate
feat: Add more ES translations. fixes #961
2022-11-17 21:18:49 +00:00
Attila Kerekes
54679ff9eb feat: Keep stored password when Enhanced App is updated 2022-11-17 21:13:10 +01:00
Attila Kerekes
4c7e56e6fe feat: Add more ES translations fixes #961 2022-11-17 21:05:50 +01:00
KodeStar
7b0ae66101 Merge pull request #1008 from keriati/fix/stoppollonerror
fix: Stop polling enhanced apps when api returns error
2022-11-17 17:30:26 +00:00
Attila Kerekes
48616e87bd fix: Stop polling enhanced apps when api returns error 2022-11-17 18:00:35 +01:00
Chris Hunt
f9280cd4c0 Don't commit debugbar json files 2022-11-17 16:20:21 +00:00
KodeStar
3124a01011 Merge pull request #1007 from keriati/fix/userlang
fix: User language setting
2022-11-17 16:17:36 +00:00
Attila Kerekes
ec27889086 fix: User language setting 2022-11-17 17:12:24 +01:00
KodeStar
aba1f37b1c Merge pull request #1006 from smelikmartin/2.x
Added czech language resources
2022-11-17 09:51:01 +00:00
Martin Smelik
6565dfde07 Added czech language 2022-11-17 10:27:43 +01:00
KodeStar
aa98c3505c Don't break if default search provider deleted from yaml
Fixes #904
2022-11-17 00:20:54 +00:00
KodeStar
15f5c3e5be Merge pull request #999 from keriati/fix/sessionexpired
fix: Expired session setCookie issue #379
2022-11-16 22:54:59 +00:00
Attila Kerekes
fc2d153ded fix: Expired session setCookie issue #379 2022-11-16 23:53:34 +01:00
KodeStar
4a7690147e Update readme.md 2022-11-15 21:29:39 +00:00
KodeStar
7d32e6edb0 Merge pull request #975 from keriati/feat/langit
feat: add missing IT translations
2022-11-15 18:33:58 +00:00
Attila Kerekes
3d1fc80d64 feat: add missing IT translations 2022-11-15 14:07:12 +01:00
KodeStar
8b0700e9ef Merge pull request #974 from keriati/feat/langderu
Add missing DE and RU translations
2022-11-15 11:56:29 +00:00
Attila Kerekes
cc241f1bd6 feat: Add DE and RU translations 2022-11-15 12:51:34 +01:00
Attila Kerekes
810ee03965 test: improve lang test debug output 2022-11-15 11:09:57 +01:00
KodeStar
7809abb376 Merge pull request #956 from keriati/chore/php7432
chore: set min php version 7.4.32
2022-11-14 23:49:15 +00:00
Attila Kerekes
2f3b7e52db chore: set min php version 7.4.32 2022-11-14 23:34:32 +01:00
KodeStar
fdd5a78eb8 Merge pull request #955 from keriati/fix/php74dep
fix: install dependencies on php 7.4
2022-11-14 20:42:41 +00:00
Attila Jozsef Kerekes
98401f20a2 reinstall dependencies on php 7.4 2022-11-14 21:39:27 +01:00
Chris Hunt
30663e4d5e Change php version 2022-11-14 20:28:46 +00:00
Chris Hunt
8972a11c0a SImplify action 2022-11-14 19:43:43 +00:00
Chris Hunt
bf349eec7a Merge branch '2.x' of github.com:linuxserver/Heimdall into 2.x 2022-11-14 19:42:43 +00:00
Chris Hunt
cb314a4fd9 Change action to pull request 2022-11-14 19:42:37 +00:00
KodeStar
1a78c8077a Merge pull request #954 from keriati/feat/lang-support
feat: Dynamically add all languages to db
2022-11-14 19:38:26 +00:00
Attila Kerekes
a3c75b2dd4 fix: Fall back to english only if intl is missing. 2022-11-14 20:35:25 +01:00
Chris Hunt
ee77d09c58 Update dependencies 2022-11-14 19:35:16 +00:00
Chris Hunt
0966639699 Add actions 2022-11-14 19:22:46 +00:00
Attila Jozsef Kerekes
153bb0e91d chore: update readme.md with intl dependency 2022-11-14 20:02:51 +01:00
Attila Kerekes
0c7a60a5c7 fix: Add missing hungarian translations
Improve some existing translation keys
2022-11-14 19:56:10 +01:00
Attila Kerekes
edb51e56f1 feat: Dynamically add all languages to db
Add unit test to find missing translations
2022-11-14 19:31:07 +01:00
KodeStar
99193a578e Merge pull request #818 from everaldofilho/language-pt-br
Change: added language pt in configuration, translated validation for pt-br
2022-11-14 15:07:45 +00:00
KodeStar
49b5d57e14 Delete SettingsSeeder.php 2022-11-14 15:07:22 +00:00
KodeStar
716d5a2f69 Merge pull request #880 from Yoshi315161/patch-1
Update German Translation
2022-11-14 15:05:07 +00:00
KodeStar
62340b07a9 Merge pull request #854 from bsciretti/2.x
Lombard translation
2022-11-14 15:04:36 +00:00
KodeStar
2312e8b648 Merge pull request #953 from keriati/refactor/ideafixes
refactor: apply auto fixes from idea
2022-11-14 14:53:14 +00:00
Attila Kerekes
b390a719e9 refactor: apply auto fixes from idea 2022-11-14 14:48:38 +01:00
KodeStar
d4f7ad842c Merge pull request #951 from keriati/fix/950-env-db
fix: change how database type is checked #950
2022-11-14 09:57:49 +00:00
Attila Kerekes
5c2501c1a7 fix: change how database type is checked #950 2022-11-14 10:24:58 +01:00
KodeStar
198ffd7665 Merge pull request #949 from keriati/fix/554-private-app-icon
fix: Don't write existing icons to disk
2022-11-13 23:22:54 +00:00
Attila Kerekes
7cf9d46eb3 fix: Don't write existing icons to disk 2022-11-14 00:08:09 +01:00
KodeStar
66dbbc835e Update app.php 2022-11-13 22:08:41 +00:00
KodeStar
178e46ca05 Merge pull request #947 from keriati/chore/laravel8
upgrade to laravel 8.0
2022-11-13 21:54:08 +00:00
Attila Kerekes
27f58c0866 upgrade to laravel 8.0 2022-11-13 21:18:38 +01:00
KodeStar
43f894b58d Merge pull request #946 from keriati/chore/db-setup
Remove sqlite db file creation when mysql or pgsql is used
2022-11-13 15:12:18 +00:00
Attila Kerekes
b83f24c6f3 remove sqlite db file creation when mysql or pgsql is used 2022-11-13 11:34:58 +01:00
KodeStar
b22fbdbad1 Merge pull request #944 from keriati/fix/429
fix: adjust home tag index for mysql/mariadb in database seeder
2022-11-11 20:30:54 +00:00
Attila Kerekes
6552a8c061 fix: adjust user id for postgresql in database seeder 2022-11-11 20:28:57 +00:00
Attila Kerekes
bcd6f72b72 fix: adjust home tag index for mysql/mariadb in database seeder 2022-11-11 19:22:50 +00:00
KodeStar
d4fe699029 Merge pull request #941 from keriati/fix/886
fix: disable tooltips while reordering items
2022-11-07 16:35:40 +00:00
Attila Kerekes
db8fa38665 fix: disable tooltips while reordering items 2022-11-07 16:32:19 +00:00
KodeStar
df41de3a9a Update app.php 2022-11-07 15:43:08 +00:00
Yoshi315161
ca557fcaf1 Update app.php
Add missing translations
2022-07-21 12:34:22 +02:00
Brian Sciretti
1a4b6da3ea Update app.php 2022-05-28 02:08:43 +02:00
Brian Sciretti
02b82dc740 Update app.php 2022-05-28 02:06:25 +02:00
Brian Sciretti
4e5129ab8f Update app.php 2022-05-28 01:58:34 +02:00
Brian Sciretti
62d9b0cc76 Create app.php 2022-05-28 01:56:47 +02:00
Everaldo da costa filho
1ca403cc6e change: added language pt in configuration, translated validation for pt-br 2022-04-02 21:20:17 -03:00
5937 changed files with 420665 additions and 138766 deletions

View File

@@ -9,6 +9,13 @@ LOG_CHANNEL=daily
DB_CONNECTION=sqlite
DB_DATABASE=app.sqlite
#DB_CONNECTION=<mysql | pgsql>
#DB_HOST=<hostname | ip>
#DB_PORT=<port number>
#DB_DATABASE=<database>
#DB_USERNAME=<user>
#DB_PASSWORD=<password>
BROADCAST_DRIVER=log
CACHE_DRIVER=file
QUEUE_CONNECTION=sync

3
.eslintignore Normal file
View File

@@ -0,0 +1,3 @@
huebee.js
jquery-ui.min.js
bootstrap.js

13
.eslintrc Normal file
View File

@@ -0,0 +1,13 @@
{
"extends": ["airbnb-base", "prettier"],
"plugins": ["prettier"],
"rules": {
"prettier/prettier": ["error"]
},
"env": {
"browser": true
},
"globals": {
"$": true
}
}

53
.github/workflows/ci.yml vendored Normal file
View File

@@ -0,0 +1,53 @@
name: Tests (PHP)
on: [pull_request]
jobs:
tests:
name: Run tests
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- name: Setup PHP, with composer and extensions
uses: shivammathur/setup-php@v2 #https://github.com/shivammathur/setup-php
with:
php-version: '7.4'
extensions: mbstring, dom, fileinfo, mysql, libxml, xml, xmlwriter, dom, tokenizer, filter, json, phar, pcre, openssl, pdo, intl, curl
- name: Cache composer dependencies
uses: actions/cache@v1
with:
path: vendor
key: composer-${{ hashFiles('composer.lock') }}
- name: Run composer install
run: composer install -n --prefer-dist
env:
APP_ENV: testing
- name: Prepare Laravel Application
run: |
cp .env.example .env
php artisan key:generate
- name: Cache yarn dependencies
uses: actions/cache@v1
with:
path: node_modules
key: yarn-${{ hashFiles('yarn.lock') }}
- name: Run yarn
run: yarn && yarn dev
- name: Run tests
run: php artisan test
env:
APP_ENV: testing
- name: Upload artifacts
uses: actions/upload-artifact@master
if: failure()
with:
name: Logs
path: ./storage/logs

2
.gitignore vendored
View File

@@ -3,6 +3,7 @@
/public/hot
/public/storage
/storage/*.key
/storage/debugbar
/.idea
/.vagrant
Homestead.json
@@ -27,3 +28,4 @@ yarn-error.log
.VolumeIcon.icns
storage/app/public/avatars/*
.env
.phpunit.result.cache

2080
.phpstorm.meta.php Normal file

File diff suppressed because it is too large Load Diff

20867
_ide_helper.php Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -2,15 +2,58 @@
namespace App;
use GuzzleHttp\Exception\GuzzleException;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Log;
/**
* App\Application
*
* @property string $appid
* @property string $name
* @property string|null $sha
* @property string|null $icon
* @property string|null $website
* @property string|null $license
* @property string|null $description
* @property int $enhanced
* @property string $tile_background
* @property \Illuminate\Support\Carbon|null $created_at
* @property \Illuminate\Support\Carbon|null $updated_at
* @property string|null $class
* @method static Builder|Application newModelQuery()
* @method static Builder|Application newQuery()
* @method static Builder|Application query()
* @method static Builder|Application whereAppid($value)
* @method static Builder|Application whereClass($value)
* @method static Builder|Application whereCreatedAt($value)
* @method static Builder|Application whereDescription($value)
* @method static Builder|Application whereEnhanced($value)
* @method static Builder|Application whereIcon($value)
* @method static Builder|Application whereLicense($value)
* @method static Builder|Application whereName($value)
* @method static Builder|Application whereSha($value)
* @method static Builder|Application whereTileBackground($value)
* @method static Builder|Application whereUpdatedAt($value)
* @method static Builder|Application whereWebsite($value)
*/
class Application extends Model
{
/**
* @var bool
*/
public $incrementing = false;
/**
* @var string
*/
protected $primaryKey = 'appid';
//
/**
* @return mixed
*/
public function icon()
{
if (! file_exists(storage_path('app/public/'.$this->icon))) {
@@ -23,12 +66,18 @@ class Application extends Model
return $this->icon;
}
public function iconView()
/**
* @return string
*/
public function iconView(): string
{
return asset('storage/'.$this->icon);
}
public function defaultColour()
/**
* @return string
*/
public function defaultColour(): string
{
// check if light or dark
if ($this->tile_background == 'light') {
@@ -38,17 +87,22 @@ class Application extends Model
return '#161b1f';
}
public function class()
/**
* @return string
*/
public function class(): string
{
$name = $this->name;
$name = preg_replace('/[^\p{L}\p{N}]/u', '', $name);
$class = '\App\SupportedApps\\'.$name.'\\'.$name;
return $class;
return '\App\SupportedApps\\'.$name.'\\'.$name;
}
public static function classFromName($name)
/**
* @param $name
* @return string
*/
public static function classFromName($name): string
{
$name = preg_replace('/[^\p{L}\p{N}]/u', '', $name);
@@ -57,16 +111,21 @@ class Application extends Model
return $class;
}
public static function apps()
/**
* @return Collection
*/
public static function apps(): Collection
{
$json = json_decode(file_get_contents(storage_path('app/supportedapps.json'))) ?? [];
$apps = collect($json->apps);
$sorted = $apps->sortBy('name', SORT_NATURAL | SORT_FLAG_CASE);
return $sorted;
return $apps->sortBy('name', SORT_NATURAL | SORT_FLAG_CASE);
}
public static function autocomplete()
/**
* @return array
*/
public static function autocomplete(): array
{
$apps = self::apps();
$list = [];
@@ -80,25 +139,27 @@ class Application extends Model
return $list;
}
/**
* @param $appid
* @return mixed|null
* @throws GuzzleException
*/
public static function getApp($appid)
{
Log::debug("Get app triggered for: $appid");
$localapp = self::where('appid', $appid)->first();
$app = self::single($appid);
$application = ($localapp) ? $localapp : new self;
if (! file_exists(app_path('SupportedApps/'.className($app->name)))) {
SupportedApps::getFiles($app);
SupportedApps::saveApp($app, $application);
} else {
// check if there has been an update for this app
if ($localapp) {
if ($localapp->sha !== $app->sha) {
SupportedApps::getFiles($app);
$app = SupportedApps::saveApp($app, $application);
}
} else {
SupportedApps::getFiles($app);
// Files missing? || app not in db || old sha version
if (! file_exists(app_path('SupportedApps/'.className($app->name))) ||
! $localapp ||
$localapp->sha !== $app->sha
) {
$gotFiles = SupportedApps::getFiles($app);
if ($gotFiles) {
$app = SupportedApps::saveApp($app, $application);
}
}
@@ -106,6 +167,10 @@ class Application extends Model
return $app;
}
/**
* @param $appid
* @return mixed|null
*/
public static function single($appid)
{
$apps = self::apps();
@@ -114,7 +179,7 @@ class Application extends Model
if ($app === null) {
// Try in db for Private App
$appModel = self::where('appid', $appid)->first();
if($appModel) {
if ($appModel) {
$app = json_decode($appModel->toJson());
}
}
@@ -128,7 +193,10 @@ class Application extends Model
return $app;
}
public static function applist()
/**
* @return array
*/
public static function applist(): array
{
$list = [];
$list['null'] = 'None';
@@ -140,7 +208,7 @@ class Application extends Model
// Check for private apps in the db
$appsListFromDB = self::all(['appid', 'name']);
foreach($appsListFromDB as $app) {
foreach ($appsListFromDB as $app) {
// Already existing keys are overwritten,
// only private apps should be added at the end
$list[$app->appid] = $app->name;

View File

@@ -36,7 +36,7 @@ class RegisterApp extends Command
/**
* Execute the console command.
*
* @return mixed
* @return void
*/
public function handle()
{
@@ -54,7 +54,12 @@ class RegisterApp extends Command
}
}
public function addApp($folder, $remove = false)
/**
* @param $folder
* @param bool $remove
* @return void
*/
public function addApp($folder, bool $remove = false)
{
$json = app_path('SupportedApps/'.$folder.'/app.json');
@@ -88,7 +93,13 @@ class RegisterApp extends Command
$this->info('Application Added - ' . $app->name . ' - ' . $app->appid);
}
private function saveIcon($appFolder, $icon) {
/**
* @param $appFolder
* @param $icon
* @return void
*/
private function saveIcon($appFolder, $icon)
{
$iconPath = app_path('SupportedApps/' . $appFolder . '/' . $icon);
$contents = file_get_contents($iconPath);
Storage::disk('public')->put('icons/'.$icon, $contents);

View File

@@ -19,7 +19,7 @@ class Kernel extends ConsoleKernel
/**
* Define the application's command schedule.
*
* @param \Illuminate\Console\Scheduling\Schedule $schedule
* @param Schedule $schedule
* @return void
*/
protected function schedule(Schedule $schedule)

View File

@@ -2,9 +2,6 @@
namespace App;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\GuzzleException;
interface EnhancedApps
{
public function test();

View File

@@ -2,7 +2,14 @@
use Illuminate\Support\Str;
function format_bytes($bytes, $is_drive_size = true, $beforeunit = '', $afterunit = '')
/**
* @param $bytes
* @param bool $is_drive_size
* @param string $beforeunit
* @param string $afterunit
* @return string
*/
function format_bytes($bytes, bool $is_drive_size = true, string $beforeunit = '', string $afterunit = ''): string
{
$btype = ($is_drive_size === true) ? 1000 : 1024;
$labels = ['B', 'KB', 'MB', 'GB', 'TB'];
@@ -18,7 +25,13 @@ function format_bytes($bytes, $is_drive_size = true, $beforeunit = '', $afteruni
}
}
function str_slug($title, $separator = '-', $language = 'en')
/**
* @param $title
* @param string $separator
* @param string $language
* @return string
*/
function str_slug($title, string $separator = '-', string $language = 'en'): string
{
return Str::slug($title, $separator, $language);
}
@@ -28,17 +41,21 @@ if (! function_exists('str_is')) {
* Determine if a given string matches a given pattern.
*
* @param string|array $pattern
* @param string $value
* @param string $value
* @return bool
*
* @deprecated Str::is() should be used directly instead. Will be removed in Laravel 6.0.
*/
function str_is($pattern, $value)
function str_is($pattern, string $value): bool
{
return Str::is($pattern, $value);
}
}
/**
* @param $hex
* @return float|int
*/
function get_brightness($hex)
{
// returns brightness value from 0 to 255
@@ -56,7 +73,11 @@ function get_brightness($hex)
return (($c_r * 299) + ($c_g * 587) + ($c_b * 114)) / 1000;
}
function title_color($hex)
/**
* @param $hex
* @return string
*/
function title_color($hex): string
{
if (get_brightness($hex) > 130) {
return ' black';
@@ -65,7 +86,10 @@ function title_color($hex)
}
}
function getLinkTargetAttribute()
/**
* @return string
*/
function getLinkTargetAttribute(): string
{
$target = \App\Setting::fetch('window_target');
@@ -76,9 +100,11 @@ function getLinkTargetAttribute()
}
}
/**
* @param $name
* @return array|string|string[]|null
*/
function className($name)
{
$name = preg_replace('/[^\p{L}\p{N}]/u', '', $name);
return $name;
return preg_replace('/[^\p{L}\p{N}]/u', '', $name);
}

View File

@@ -4,11 +4,17 @@ namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use App\User;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Contracts\View\Factory;
use Illuminate\Contracts\View\View;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Session;
use Illuminate\Support\Facades\URL;
use Illuminate\Validation\ValidationException;
use Symfony\Component\HttpFoundation\Response;
class LoginController extends Controller
{
@@ -30,7 +36,7 @@ class LoginController extends Controller
*
* @var string
*/
protected $redirectTo = '/';
protected string $redirectTo = '/';
/**
* Create a new controller instance.
@@ -43,7 +49,10 @@ class LoginController extends Controller
$this->middleware('guest')->except('logout');
}
public function username()
/**
* @return string
*/
public function username(): string
{
return 'username';
}
@@ -51,12 +60,12 @@ class LoginController extends Controller
/**
* Handle a login request to the application.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Http\Response|\Illuminate\Http\JsonResponse
* @param Request $request
* @return Response
*
* @throws \Illuminate\Validation\ValidationException
* @throws ValidationException
*/
public function login(Request $request)
public function login(Request $request): Response
{
$current_user = User::currentUser();
$request->merge(['username' => $current_user->username, 'remember' => true]);
@@ -88,7 +97,11 @@ class LoginController extends Controller
{
}
public function setUser(User $user)
/**
* @param User $user
* @return RedirectResponse
*/
public function setUser(User $user): RedirectResponse
{
Auth::logout();
session(['current_user' => $user]);
@@ -96,7 +109,11 @@ class LoginController extends Controller
return redirect()->route('dash');
}
public function autologin($uuid)
/**
* @param $uuid
* @return RedirectResponse
*/
public function autologin($uuid): RedirectResponse
{
$user = User::where('autologin', $uuid)->first();
Auth::login($user, true);
@@ -108,18 +125,26 @@ class LoginController extends Controller
/**
* Show the application's login form.
*
* @return \Illuminate\Http\Response
* @return Application|Factory|View
*/
public function showLoginForm()
{
return view('auth.login');
}
protected function authenticated(Request $request, $user)
/**
* @param Request $request
* @param $user
* @return RedirectResponse
*/
protected function authenticated(Request $request, $user): RedirectResponse
{
return back();
}
/**
* @return mixed|string
*/
public function redirectTo()
{
return Session::get('url.intended') ? Session::get('url.intended') : $this->redirectTo;

View File

@@ -27,7 +27,7 @@ class RegisterController extends Controller
*
* @var string
*/
protected $redirectTo = '/';
protected string $redirectTo = '/';
/**
* Create a new controller instance.
@@ -45,7 +45,7 @@ class RegisterController extends Controller
* @param array $data
* @return \Illuminate\Contracts\Validation\Validator
*/
protected function validator(array $data)
protected function validator(array $data): \Illuminate\Contracts\Validation\Validator
{
return Validator::make($data, [
'name' => 'required|string|max:255',
@@ -58,7 +58,7 @@ class RegisterController extends Controller
* Create a new user instance after a valid registration.
*
* @param array $data
* @return \App\User
* @return User
*/
protected function create(array $data)
{

View File

@@ -25,7 +25,7 @@ class ResetPasswordController extends Controller
*
* @var string
*/
protected $redirectTo = '/';
protected string $redirectTo = '/';
/**
* Create a new controller instance.

View File

@@ -7,7 +7,6 @@ use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Routing\Controller as BaseController;
use Illuminate\Support\Facades\Auth;
class Controller extends BaseController
{

View File

@@ -2,7 +2,7 @@
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Http\RedirectResponse;
class HomeController extends Controller
{
@@ -13,15 +13,16 @@ class HomeController extends Controller
*/
public function __construct()
{
parent::__construct();
$this->middleware('auth');
}
/**
* Show the application dashboard.
*
* @return \Illuminate\Http\Response
* @return RedirectResponse
*/
public function index()
public function index(): RedirectResponse
{
return redirect()->route('dash');
}

View File

@@ -0,0 +1,31 @@
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\View\View;
class ImportController extends Controller
{
/**
* Instantiate a new controller instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
$this->middleware('allowed');
}
/**
* Handle the incoming request.
*
* @param Request $request
* @return View
*/
public function __invoke(Request $request): View
{
return view('items.import');
}
}

View File

@@ -5,33 +5,36 @@ namespace App\Http\Controllers;
use App\Application;
use App\Item;
use App\Jobs\ProcessApps;
use App\Search;
use App\Setting;
use App\SupportedApps;
use App\User;
use Artisan;
use GrahamCampbell\GitHub\Facades\GitHub;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\ConnectException;
use GuzzleHttp\Exception\GuzzleException;
use GuzzleHttp\Exception\ServerException;
use Illuminate\Contracts\View\View;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Routing\Redirector;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Route;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\URL;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\StreamInterface;
class ItemController extends Controller
{
public function __construct()
{
parent::__construct();
$this->middleware('allowed');
}
/**
* Display a listing of the resource on the dashboard.
*
* @return \Illuminate\Http\Response
* @return View
*/
public function dash()
public function dash(): View
{
$data['apps'] = Item::whereHas('parents', function ($query) {
$query->where('id', 0);
@@ -49,7 +52,7 @@ class ItemController extends Controller
/**
* Set order on the dashboard.
*
* @return \Illuminate\Http\Response
* @return void
*/
public function setOrder(Request $request)
{
@@ -64,9 +67,10 @@ class ItemController extends Controller
/**
* Pin item on the dashboard.
*
* @return \Illuminate\Http\Response
* @param $id
* @return RedirectResponse
*/
public function pin($id)
public function pin($id): RedirectResponse
{
$item = Item::findOrFail($id);
$item->pinned = true;
@@ -79,9 +83,10 @@ class ItemController extends Controller
/**
* Unpin item on the dashboard.
*
* @return \Illuminate\Http\Response
* @param $id
* @return RedirectResponse
*/
public function unpin($id)
public function unpin($id): RedirectResponse
{
$item = Item::findOrFail($id);
$item->pinned = false;
@@ -94,21 +99,29 @@ class ItemController extends Controller
/**
* Unpin item on the dashboard.
*
* @return \Illuminate\Http\Response
* @return RedirectResponse|View
*/
public function pinToggle($id, $ajax = false, $tag = false)
{
$item = Item::findOrFail($id);
$new = ((bool) $item->pinned === true) ? false : true;
$new = !(((bool)$item->pinned === true));
$item->pinned = $new;
$item->save();
if ($ajax) {
if (is_numeric($tag) && $tag > 0) {
$item = Item::whereId($tag)->first();
$data['apps'] = $item->children()->pinned()->orderBy('order', 'asc')->get();
} else {
$data['apps'] = Item::pinned()->orderBy('order', 'asc')->get();
$item = Item::whereId($tag)->first();
$data['apps'] = new Collection;
if ((int)$tag === 0) {
$tags = Item::where('type', 1)->pinned()->orderBy('order', 'asc')->get();
$data['apps'] = $data['apps']->merge($tags);
}
$apps = $item->children()->pinned()->orderBy('order', 'asc')->get();
$data['apps'] = $data['apps']->merge($apps);
$data['ajax'] = true;
return view('sortable', $data);
@@ -122,9 +135,10 @@ class ItemController extends Controller
/**
* Display a listing of the resource.
*
* @return \Illuminate\Http\Response
* @param Request $request
* @return View
*/
public function index(Request $request)
public function index(Request $request): View
{
$trash = (bool) $request->input('trash');
@@ -140,9 +154,9 @@ class ItemController extends Controller
/**
* Show the form for creating a new resource.
*
* @return \Illuminate\Http\Response
* @return View
*/
public function create()
public function create(): View
{
//
$data['tags'] = Item::ofType('tag')->orderBy('title', 'asc')->pluck('title', 'id');
@@ -155,10 +169,10 @@ class ItemController extends Controller
/**
* Show the form for editing the specified resource.
*
* @param int $id
* @return \Illuminate\Http\Response
* @param int $id
* @return View
*/
public function edit($id)
public function edit(int $id): View
{
// Get the item
$item = Item::find($id);
@@ -178,7 +192,12 @@ class ItemController extends Controller
return view('items.edit', $data);
}
public function storelogic($request, $id = null)
/**
* @param Request $request
* @param null $id
* @return Item
*/
public static function storelogic(Request $request, $id = null): Item
{
$application = Application::single($request->input('appid'));
$validatedData = $request->validate([
@@ -192,12 +211,12 @@ class ItemController extends Controller
'icon' => $path,
]);
} elseif (strpos($request->input('icon'), 'http') === 0) {
$options=array(
"ssl"=>array(
"verify_peer"=>false,
"verify_peer_name"=>false,
$options = array(
"ssl" => array(
"verify_peer" => false,
"verify_peer_name" => false,
),
);
);
$contents = file_get_contents($request->input('icon'), false, stream_context_create($options));
if ($application) {
@@ -206,25 +225,39 @@ class ItemController extends Controller
$file = $request->input('icon');
$path_parts = pathinfo($file);
$icon = md5($contents);
$icon .= '.'.$path_parts['extension'];
$icon .= '.' . $path_parts['extension'];
}
$path = 'icons/'.$icon;
$path = 'icons/' . $icon;
// Private apps could have here duplicated icons folder
if (strpos($path, 'icons/icons/') !== false) {
$path = str_replace('icons/icons/','icons/',$path);
$path = str_replace('icons/icons/', 'icons/', $path);
}
if (!Storage::disk('public')->exists($path)) {
Storage::disk('public')->put($path, $contents);
}
Storage::disk('public')->put($path, $contents);
$request->merge([
'icon' => $path,
]);
}
$config = Item::checkConfig($request->input('config'));
// Don't overwrite the stored password if it wasn't submitted when updating the item
if ($id !== null && strpos($config, '"password":null') !== false) {
$storedItem = Item::find($id);
$storedConfigObject = json_decode($storedItem->getAttribute('description'));
$configObject = json_decode($config);
$configObject->password = $storedConfigObject->password;
$config = json_encode($configObject);
}
$current_user = User::currentUser();
$request->merge([
'description' => $config,
'user_id' => $current_user->id,
'user_id' => $current_user->getId(),
]);
if ($request->input('appid') === 'null') {
@@ -245,17 +278,18 @@ class ItemController extends Controller
}
$item->parents()->sync($request->tags);
return $item;
}
/**
* Store a newly created resource in storage.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
* @param Request $request
* @return RedirectResponse
*/
public function store(Request $request)
public function store(Request $request): RedirectResponse
{
$this->storelogic($request);
self::storelogic($request);
$route = route('dash', []);
@@ -266,10 +300,10 @@ class ItemController extends Controller
/**
* Display the specified resource.
*
* @param int $id
* @return \Illuminate\Http\Response
* @param int $id
* @return void
*/
public function show($id)
public function show(int $id): void
{
//
}
@@ -277,13 +311,13 @@ class ItemController extends Controller
/**
* Update the specified resource in storage.
*
* @param \Illuminate\Http\Request $request
* @param int $id
* @return \Illuminate\Http\Response
* @param Request $request
* @param int $id
* @return RedirectResponse
*/
public function update(Request $request, $id)
public function update(Request $request, int $id): RedirectResponse
{
$this->storelogic($request, $id);
self::storelogic($request, $id);
$route = route('dash', []);
return redirect($route)
@@ -293,10 +327,11 @@ class ItemController extends Controller
/**
* Remove the specified resource from storage.
*
* @param int $id
* @return \Illuminate\Http\Response
* @param Request $request
* @param int $id
* @return RedirectResponse
*/
public function destroy(Request $request, $id)
public function destroy(Request $request, int $id): RedirectResponse
{
//
$force = (bool) $request->input('force');
@@ -317,15 +352,15 @@ class ItemController extends Controller
/**
* Restore the specified resource from soft deletion.
*
* @param int $id
* @return \Illuminate\Http\Response
* @param int $id
* @return RedirectResponse
*/
public function restore($id)
public function restore(int $id): RedirectResponse
{
//
Item::withTrashed()
->where('id', $id)
->restore();
->where('id', $id)
->restore();
$route = route('items.index', []);
@@ -336,9 +371,11 @@ class ItemController extends Controller
/**
* Return details for supported apps
*
* @return Json
* @param Request $request
* @return string|null
* @throws GuzzleException
*/
public function appload(Request $request)
public function appload(Request $request): ?string
{
$output = [];
$appid = $request->input('app');
@@ -346,26 +383,6 @@ class ItemController extends Controller
if ($appid === 'null') {
return null;
}
/*$appname = $request->input('app');
//die($appname);
$app_details = Application::where('name', $appname)->firstOrFail();
$appclass = $app_details->class();
$app = new $appclass;
// basic details
$output['icon'] = $app_details->icon();
$output['name'] = $app_details->name;
$output['iconview'] = $app_details->iconView();
$output['colour'] = $app_details->defaultColour();
$output['class'] = $appclass;
// live details
if($app instanceof \App\EnhancedApps) {
$output['config'] = className($app_details->name).'.config';
} else {
$output['config'] = null;
}*/
$output['config'] = null;
$output['custom'] = null;
@@ -377,26 +394,30 @@ class ItemController extends Controller
if ((bool) $app->enhanced === true) {
// if(!isset($app->config)) { // class based config
$output['custom'] = className($appdetails->name).'.config';
$output['custom'] = className($appdetails->name) . '.config';
// }
}
$output['colour'] = ($app->tile_background == 'light') ? '#fafbfc' : '#161b1f';
if(strpos($app->icon, '://') !== false) {
if (strpos($app->icon, '://') !== false) {
$output['iconview'] = $app->icon;
} elseif(strpos($app->icon, 'icons/') !== false) {
} elseif (strpos($app->icon, 'icons/') !== false) {
// Private apps have the icon locally
$output['iconview'] = URL::to('/').'/storage/'.$app->icon;
$output['iconview'] = URL::to('/') . '/storage/' . $app->icon;
$output['icon'] = str_replace('icons/', '', $output['icon']);
} else {
$output['iconview'] = config('app.appsource').'icons/'.$app->icon;
$output['iconview'] = config('app.appsource') . 'icons/' . $app->icon;
}
return json_encode($output);
}
/**
* @param Request $request
* @return void
*/
public function testConfig(Request $request)
{
$data = $request->input('data');
@@ -404,22 +425,39 @@ class ItemController extends Controller
$single = Application::single($data['type']);
$app = $single->class;
// If password is not resubmitted fill it from the database when in edit mode
if (array_key_exists('password', $data) &&
$data['password'] === null &&
array_key_exists('id', $data)
) {
$item = Item::find($data['id']);
if ($item) {
$itemConfig = $item->getConfig();
$data['password'] = $itemConfig->password;
}
}
$app_details = new $app();
$app_details->config = (object) $data;
$app_details->test();
}
public function execute($url, $attrs = [], $overridevars = false)
/**
* @param $url
* @param array $attrs
* @param array|bool $overridevars
* @return ResponseInterface|null
* @throws GuzzleException
*/
public function execute($url, array $attrs = [], $overridevars = false): ?ResponseInterface
{
$res = null;
$vars = ($overridevars !== false) ?
$overridevars : [
'http_errors' => false,
'timeout' => 15,
'connect_timeout' => 15,
'verify' => false,
];
$overridevars : [
'http_errors' => false,
'timeout' => 15,
'connect_timeout' => 15,
'verify' => false,
];
$client = new Client($vars);
@@ -427,24 +465,33 @@ class ItemController extends Controller
try {
return $client->request($method, $url, $attrs);
} catch (\GuzzleHttp\Exception\ConnectException $e) {
} catch (ConnectException $e) {
Log::error('Connection refused');
Log::debug($e->getMessage());
} catch (\GuzzleHttp\Exception\ServerException $e) {
} catch (ServerException $e) {
Log::debug($e->getMessage());
}
return $res;
return null;
}
public function websitelookup($url)
/**
* @param $url
* @return StreamInterface
* @throws GuzzleException
*/
public function websitelookup($url): StreamInterface
{
$url = \base64_decode($url);
$url = base64_decode($url);
$data = $this->execute($url);
return $data->getBody();
}
/**
* @param $id
* @return void
*/
public function getStats($id)
{
$item = Item::find($id);
@@ -457,6 +504,9 @@ class ItemController extends Controller
}
}
/**
* @return \Illuminate\Contracts\Foundation\Application|RedirectResponse|Redirector
*/
public function checkAppList()
{
ProcessApps::dispatch();

View File

@@ -0,0 +1,112 @@
<?php
namespace App\Http\Controllers;
use App\Item;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\Support\Collection;
class ItemRestController extends Controller
{
public function __construct()
{
parent::__construct();
$this->middleware('allowed');
}
/**
* Display a listing of the resource.
*
* @return Collection
*/
public function index()
{
$columns = [
'title',
'colour',
'url',
'description',
'appid',
'appdescription',
];
return Item::select($columns)
->where('deleted_at', null)
->where('type', '0')
->orderBy('order', 'asc')
->get();
}
/**
* Show the form for creating a new resource.
*
* @return Response
*/
public function create()
{
}
/**
* Store a newly created resource in storage.
*
* @param Request $request
* @return object
*/
public function store(Request $request): object
{
$item = ItemController::storelogic($request);
if ($item) {
return (object) ['status' => 'OK'];
}
return (object) ['status' => 'FAILED'];
}
/**
* Display the specified resource.
*
* @param Item $item
* @return Response
*/
public function show(Item $item)
{
//
}
/**
* Show the form for editing the specified resource.
*
* @param Item $item
* @return Response
*/
public function edit(Item $item)
{
//
}
/**
* Update the specified resource in storage.
*
* @param Request $request
* @param Item $item
* @return Response
*/
public function update(Request $request, Item $item)
{
//
}
/**
* Remove the specified resource from storage.
*
* @param Item $item
* @return Response
*/
public function destroy(Item $item)
{
//
}
}

View File

@@ -2,12 +2,18 @@
namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
use App\Search;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Routing\Redirector;
class SearchController extends Controller
{
/**
* @param Request $request
* @return Application|RedirectResponse|Redirector|mixed|void
*/
public function index(Request $request)
{
$requestprovider = $request->input('provider');

View File

@@ -2,24 +2,24 @@
namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
use App\Setting;
use App\SettingGroup;
use App\User;
use Illuminate\Contracts\View\View;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
class SettingsController extends Controller
{
public function __construct()
{
parent::__construct();
$this->middleware('allowed');
}
/**
* @return \Illuminate\View\View
* @return View
*/
public function index()
public function index(): View
{
$settings = SettingGroup::with([
'settings',
@@ -33,9 +33,9 @@ class SettingsController extends Controller
/**
* @param int $id
*
* @return \Illuminate\Http\RedirectResponse
* @return RedirectResponse|View
*/
public function edit($id)
public function edit(int $id)
{
$setting = Setting::find($id);
//die("s: ".$setting->label);
@@ -59,11 +59,12 @@ class SettingsController extends Controller
}
/**
* @param Request $request
* @param int $id
*
* @return \Illuminate\Http\RedirectResponse
* @return RedirectResponse
*/
public function update(Request $request, $id)
public function update(Request $request, int $id): RedirectResponse
{
$setting = Setting::find($id);
$user = $this->user();
@@ -104,9 +105,9 @@ class SettingsController extends Controller
/**
* @param int $id
*
* @return \Illuminate\Http\RedirectResponse
* @return RedirectResponse
*/
public function clear($id)
public function clear(int $id): RedirectResponse
{
$user = $this->user();
$setting = Setting::find($id);

View File

@@ -5,7 +5,12 @@ namespace App\Http\Controllers;
use App\Item;
use App\User;
use DB;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Contracts\View\Factory;
use Illuminate\Contracts\View\View;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
class TagController extends Controller
{
@@ -17,7 +22,7 @@ class TagController extends Controller
/**
* Display a listing of the resource.
*
* @return \Illuminate\Http\Response
* @return Application|Factory|View
*/
public function index(Request $request)
{
@@ -35,7 +40,7 @@ class TagController extends Controller
/**
* Show the form for creating a new resource.
*
* @return \Illuminate\Http\Response
* @return Application|Factory|View
*/
public function create()
{
@@ -47,10 +52,10 @@ class TagController extends Controller
/**
* Store a newly created resource in storage.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
* @param Request $request
* @return RedirectResponse
*/
public function store(Request $request)
public function store(Request $request): RedirectResponse
{
$validatedData = $request->validate([
'title' => 'required|max:255',
@@ -71,7 +76,7 @@ class TagController extends Controller
$request->merge([
'type' => '1',
'url' => $slug,
'user_id' => $current_user->id,
'user_id' => $current_user->getId(),
]);
//die(print_r($request->all()));
Item::create($request->all());
@@ -85,10 +90,10 @@ class TagController extends Controller
/**
* Display the specified resource.
*
* @param int $id
* @return \Illuminate\Http\Response
* @param $slug
* @return View
*/
public function show($slug)
public function show($slug): View
{
$item = Item::whereUrl($slug)->first();
//print_r($item);
@@ -102,10 +107,10 @@ class TagController extends Controller
/**
* Show the form for editing the specified resource.
*
* @param int $id
* @return \Illuminate\Http\Response
* @param int $id
* @return View
*/
public function edit($id)
public function edit(int $id): View
{
// Get the item
$item = Item::find($id);
@@ -118,11 +123,11 @@ class TagController extends Controller
/**
* Update the specified resource in storage.
*
* @param \Illuminate\Http\Request $request
* @param int $id
* @return \Illuminate\Http\Response
* @param Request $request
* @param int $id
* @return RedirectResponse
*/
public function update(Request $request, $id)
public function update(Request $request, int $id): RedirectResponse
{
$validatedData = $request->validate([
'title' => 'required|max:255',
@@ -152,10 +157,11 @@ class TagController extends Controller
/**
* Remove the specified resource from storage.
*
* @param int $id
* @return \Illuminate\Http\Response
* @param Request $request
* @param int $id
* @return RedirectResponse
*/
public function destroy(Request $request, $id)
public function destroy(Request $request, int $id): RedirectResponse
{
//
$force = (bool) $request->input('force');
@@ -176,10 +182,10 @@ class TagController extends Controller
/**
* Restore the specified resource from soft deletion.
*
* @param int $id
* @return \Illuminate\Http\Response
* @param int $id
* @return RedirectResponse
*/
public function restore($id)
public function restore(int $id): RedirectResponse
{
//
Item::withTrashed()
@@ -191,9 +197,15 @@ class TagController extends Controller
->with('success', __('app.alert.success.item_restored'));
}
public function add($tag, $item)
/**
* Add item to tag
*
* @param $tag
* @param $item
* @return int 1|0
*/
public function add($tag, $item): int
{
$output = 0;
$tag = Item::find($tag);
$item = Item::find($item);
if ($tag && $item) {
@@ -205,6 +217,6 @@ class TagController extends Controller
}
}
return $output;
return 0;
}
}

View File

@@ -2,8 +2,9 @@
namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
use App\User;
use Illuminate\Contracts\View\View;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Str;
@@ -12,15 +13,16 @@ class UserController extends Controller
{
public function __construct()
{
parent::__construct();
$this->middleware('allowed')->except(['selectUser']);
}
/**
* Display a listing of the resource.
*
* @return \Illuminate\Http\Response
* @return View
*/
public function index()
public function index(): View
{
$data['users'] = User::all();
@@ -30,9 +32,9 @@ class UserController extends Controller
/**
* Show the form for creating a new resource.
*
* @return \Illuminate\Http\Response
* @return View
*/
public function create()
public function create(): View
{
$data = [];
@@ -50,10 +52,10 @@ class UserController extends Controller
/**
* Store a newly created resource in storage.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
* @param Request $request
* @return RedirectResponse
*/
public function store(Request $request)
public function store(Request $request): RedirectResponse
{
$validatedData = $request->validate([
'username' => 'required|max:255|unique:users',
@@ -92,10 +94,10 @@ class UserController extends Controller
/**
* Display the specified resource.
*
* @param int $id
* @return \Illuminate\Http\Response
* @param int $id
* @return void
*/
public function show($id)
public function show(int $id): void
{
//
}
@@ -103,10 +105,10 @@ class UserController extends Controller
/**
* Show the form for editing the specified resource.
*
* @param int $id
* @return \Illuminate\Http\Response
* @param User $user
* @return View
*/
public function edit(User $user)
public function edit(User $user): View
{
$data['user'] = $user;
@@ -116,11 +118,11 @@ class UserController extends Controller
/**
* Update the specified resource in storage.
*
* @param \Illuminate\Http\Request $request
* @param int $id
* @return \Illuminate\Http\Response
* @param Request $request
* @param User $user
* @return RedirectResponse
*/
public function update(Request $request, User $user)
public function update(Request $request, User $user): RedirectResponse
{
$validatedData = $request->validate([
'username' => 'required|max:255|unique:users,username,'.$user->id,
@@ -163,10 +165,10 @@ class UserController extends Controller
/**
* Remove the specified resource from storage.
*
* @param int $id
* @return \Illuminate\Http\Response
* @param User $user
* @return RedirectResponse | void
*/
public function destroy(User $user)
public function destroy(User $user): RedirectResponse
{
if ($user->id !== 1) {
$user->delete();

View File

@@ -4,6 +4,8 @@ namespace App\Http\Middleware;
use App\User;
use Closure;
use Illuminate\Auth\AuthenticationException;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Route;
use Session;
@@ -13,29 +15,33 @@ class CheckAllowed
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @param Request $request
* @param Closure $next
* @return mixed
* @throws AuthenticationException
*/
public function handle($request, Closure $next)
public function handle(Request $request, Closure $next)
{
$route = Route::currentRouteName();
$current_user = User::currentUser();
// Non admin users can't access users management
if (str_is('users*', $route)) {
if ($current_user->id !== 1) {
if ($current_user->getId() !== 1) {
return redirect()->route('dash');
}
}
// Public access to frontpage
if ($route == 'dash') {
//print_r(User::all());
//die("here".var_dump($current_user->password));
if ((bool) $current_user->public_front === true) {
if ((bool)$current_user->public_front === true) {
return $next($request);
}
}
// Continue with passwordless user
if (empty($current_user->password)) {
return $next($request);
}
@@ -43,11 +49,13 @@ class CheckAllowed
// Check if user is logged in as $current_user
if (Auth::check()) {
$loggedin_user = Auth::user();
if ($loggedin_user->id === $current_user->id) {
if ($loggedin_user->id === $current_user->getId()) {
return $next($request);
}
}
return Auth::authenticate();
// Redirect to login
Auth::authenticate();
return redirect()->route('user.select');
}
}

View File

@@ -3,6 +3,7 @@
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
class RedirectIfAuthenticated
@@ -10,12 +11,12 @@ class RedirectIfAuthenticated
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @param string|null $guard
* @param Request $request
* @param Closure $next
* @param string|null $guard
* @return mixed
*/
public function handle($request, Closure $next, $guard = null)
public function handle(Request $request, Closure $next, string $guard = null)
{
if (Auth::guard($guard)->check()) {
return redirect()->intended();

View File

@@ -3,7 +3,6 @@
namespace App\Http\Middleware;
use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as Middleware;
use Symfony\Component\HttpFoundation\Cookie;
class VerifyCsrfToken extends Middleware
{

View File

@@ -2,18 +2,81 @@
namespace App;
use App\Application;
use App\ItemTag;
use App\User;
use Illuminate\Contracts\Routing\UrlGenerator;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Database\Eloquent\SoftDeletes;
use stdClass;
use Symfony\Component\ClassLoader\ClassMapGenerator;
/**
* App\Item
*
* @property int $id
* @property string $title
* @property string|null $colour
* @property string|null $icon
* @property string $url
* @property string|null $description
* @property int $pinned
* @property int $order
* @property \Illuminate\Support\Carbon|null $deleted_at
* @property \Illuminate\Support\Carbon|null $created_at
* @property \Illuminate\Support\Carbon|null $updated_at
* @property int $type
* @property int $user_id
* @property string|null $class
* @property string|null $appid
* @property string|null $appdescription
* @property-read \Illuminate\Database\Eloquent\Collection|Item[] $children
* @property-read int|null $children_count
* @property-read string $droppable
* @property-read \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\Routing\UrlGenerator|mixed|string $link
* @property-read string $link_icon
* @property-read string $link_target
* @property-read string $link_type
* @property-read \Illuminate\Database\Eloquent\Collection|Item[] $parents
* @property-read int|null $parents_count
* @property-read \App\User|null $user
* @method static \Database\Factories\ItemFactory factory(...$parameters)
* @method static Builder|Item newModelQuery()
* @method static Builder|Item newQuery()
* @method static Builder|Item ofType($type)
* @method static \Illuminate\Database\Query\Builder|Item onlyTrashed()
* @method static Builder|Item pinned()
* @method static Builder|Item query()
* @method static Builder|Item whereAppdescription($value)
* @method static Builder|Item whereAppid($value)
* @method static Builder|Item whereClass($value)
* @method static Builder|Item whereColour($value)
* @method static Builder|Item whereCreatedAt($value)
* @method static Builder|Item whereDeletedAt($value)
* @method static Builder|Item whereDescription($value)
* @method static Builder|Item whereIcon($value)
* @method static Builder|Item whereId($value)
* @method static Builder|Item whereOrder($value)
* @method static Builder|Item wherePinned($value)
* @method static Builder|Item whereTitle($value)
* @method static Builder|Item whereType($value)
* @method static Builder|Item whereUpdatedAt($value)
* @method static Builder|Item whereUrl($value)
* @method static Builder|Item whereUserId($value)
* @method static \Illuminate\Database\Query\Builder|Item withTrashed()
* @method static \Illuminate\Database\Query\Builder|Item withoutTrashed()
* @mixin \Eloquent
*/
class Item extends Model
{
use SoftDeletes;
use HasFactory;
/**
* @return void
*/
protected static function boot()
{
parent::boot();
@@ -21,16 +84,27 @@ class Item extends Model
static::addGlobalScope('user_id', function (Builder $builder) {
$current_user = User::currentUser();
if ($current_user) {
$builder->where('user_id', $current_user->id)->orWhere('user_id', 0);
$builder->where('user_id', $current_user->getId())->orWhere('user_id', 0);
} else {
$builder->where('user_id', 0);
}
});
}
//
protected $fillable = [
'title', 'url', 'colour', 'icon', 'appdescription', 'description', 'pinned', 'order', 'type', 'class', 'user_id', 'tag_id', 'appid',
'title',
'url',
'colour',
'icon',
'appdescription',
'description',
'pinned',
'order',
'type',
'class',
'user_id',
'tag_id',
'appid',
];
@@ -38,10 +112,10 @@ class Item extends Model
/**
* Scope a query to only include pinned items.
*
* @param \Illuminate\Database\Eloquent\Builder $query
* @return \Illuminate\Database\Eloquent\Builder
* @param Builder $query
* @return Builder
*/
public function scopePinned($query)
public function scopePinned(Builder $query): Builder
{
return $query->where('pinned', 1);
}
@@ -77,16 +151,25 @@ class Item extends Model
return $tagdetails;
}
public function parents()
/**
* @return BelongsToMany
*/
public function parents(): BelongsToMany
{
return $this->belongsToMany(\App\Item::class, 'item_tag', 'item_id', 'tag_id');
return $this->belongsToMany(Item::class, 'item_tag', 'item_id', 'tag_id');
}
public function children()
/**
* @return BelongsToMany
*/
public function children(): BelongsToMany
{
return $this->belongsToMany(\App\Item::class, 'item_tag', 'tag_id', 'item_id');
return $this->belongsToMany(Item::class, 'item_tag', 'tag_id', 'item_id');
}
/**
* @return \Illuminate\Contracts\Foundation\Application|UrlGenerator|mixed|string
*/
public function getLinkAttribute()
{
if ((int) $this->type === 1) {
@@ -96,7 +179,10 @@ class Item extends Model
}
}
public function getDroppableAttribute()
/**
* @return string
*/
public function getDroppableAttribute(): string
{
if ((int) $this->type === 1) {
return ' droppable';
@@ -105,7 +191,10 @@ class Item extends Model
}
}
public function getLinkTargetAttribute()
/**
* @return string
*/
public function getLinkTargetAttribute(): string
{
$target = Setting::fetch('window_target');
@@ -116,7 +205,10 @@ class Item extends Model
}
}
public function getLinkIconAttribute()
/**
* @return string
*/
public function getLinkIconAttribute(): string
{
if ((int) $this->type === 1) {
return 'fa-tag';
@@ -125,7 +217,10 @@ class Item extends Model
}
}
public function getLinkTypeAttribute()
/**
* @return string
*/
public function getLinkTypeAttribute(): string
{
if ((int) $this->type === 1) {
return 'tags';
@@ -134,6 +229,10 @@ class Item extends Model
}
}
/**
* @param $class
* @return false|mixed|string
*/
public static function nameFromClass($class)
{
$explode = explode('\\', $class);
@@ -142,6 +241,11 @@ class Item extends Model
return $name;
}
/**
* @param $query
* @param $type
* @return mixed
*/
public function scopeOfType($query, $type)
{
switch ($type) {
@@ -156,7 +260,10 @@ class Item extends Model
return $query->where('type', $typeid);
}
public function enhanced()
/**
* @return bool
*/
public function enhanced(): bool
{
/*if(isset($this->class) && !empty($this->class)) {
$app = new $this->class;
@@ -167,16 +274,24 @@ class Item extends Model
return $this->description !== null;
}
public static function isEnhanced($class)
/**
* @param $class
* @return bool
*/
public static function isEnhanced($class): bool
{
if (!class_exists($class, false) || $class === null || $class === 'null') {
return false;
}
$app = new $class;
return (bool) ($app instanceof \App\EnhancedApps);
return (bool) ($app instanceof EnhancedApps);
}
/**
* @param $class
* @return false|mixed
*/
public static function isSearchProvider($class)
{
if (!class_exists($class, false) || $class === null || $class === 'null') {
@@ -184,10 +299,13 @@ class Item extends Model
}
$app = new $class;
return ((bool) ($app instanceof \App\SearchInterface)) ? $app : false;
return ((bool) ($app instanceof SearchInterface)) ? $app : false;
}
public function enabled()
/**
* @return bool
*/
public function enabled(): bool
{
if ($this->enhanced()) {
$config = $this->getconfig();
@@ -199,12 +317,15 @@ class Item extends Model
return false;
}
/**
* @return mixed|stdClass
*/
public function getconfig()
{
// $explode = explode('\\', $this->class);
if (! isset($this->description) || empty($this->description)) {
$config = new \stdClass;
$config = new stdClass;
// $config->name = end($explode);
$config->enabled = false;
$config->override_url = null;
@@ -227,7 +348,11 @@ class Item extends Model
return $config;
}
public static function applicationDetails($class)
/**
* @param $class
* @return Application|null
*/
public static function applicationDetails($class): ?Application
{
if (! empty($class)) {
$name = self::nameFromClass($class);
@@ -237,13 +362,17 @@ class Item extends Model
}
}
return false;
return null;
}
public static function getApplicationDescription($class)
/**
* @param $class
* @return string
*/
public static function getApplicationDescription($class): string
{
$details = self::applicationDetails($class);
if ($details !== false) {
if ($details !== null) {
return $details->description.' - '.$details->license;
}
@@ -252,9 +381,11 @@ class Item extends Model
/**
* Get the user that owns the item.
*
* @return BelongsTo
*/
public function user()
public function user(): BelongsTo
{
return $this->belongsTo(\App\User::class);
return $this->belongsTo(User::class);
}
}

View File

@@ -2,8 +2,26 @@
namespace App;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Relations\Pivot;
/**
* App\ItemTag
*
* @property int $item_id
* @property int $tag_id
* @property \Illuminate\Support\Carbon|null $created_at
* @property \Illuminate\Support\Carbon|null $updated_at
* @method static \Illuminate\Database\Eloquent\Builder|ItemTag newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder|ItemTag newQuery()
* @method static \Illuminate\Database\Eloquent\Builder|ItemTag query()
* @method static \Illuminate\Database\Eloquent\Builder|ItemTag whereCreatedAt($value)
* @method static \Illuminate\Database\Eloquent\Builder|ItemTag whereItemId($value)
* @method static \Illuminate\Database\Eloquent\Builder|ItemTag whereTagId($value)
* @method static \Illuminate\Database\Eloquent\Builder|ItemTag whereUpdatedAt($value)
* @mixin \Eloquent
*/
class ItemTag extends Pivot
{
use HasFactory;
}

View File

@@ -5,14 +5,17 @@ namespace App\Jobs;
use App\Application;
use App\Item;
use App\SupportedApps;
use GuzzleHttp\Exception\GuzzleException;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldBeUnique;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Storage;
class ProcessApps implements ShouldQueue
class ProcessApps implements ShouldQueue, ShouldBeUnique
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
@@ -30,9 +33,11 @@ class ProcessApps implements ShouldQueue
* Execute the job.
*
* @return void
* @throws GuzzleException
*/
public function handle()
{
Log::debug('Process Apps dispatched');
$localapps = Application::whereNull('class')->get();
$json = SupportedApps::getList()->getBody();

60
app/Jobs/UpdateApps.php Normal file
View File

@@ -0,0 +1,60 @@
<?php
namespace App\Jobs;
use App\Application;
use GuzzleHttp\Exception\GuzzleException;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldBeUnique;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Log;
class UpdateApps implements ShouldQueue, ShouldBeUnique
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
/**
* Create a new job instance.
*
* @return void
*/
public function __construct()
{
//
}
/**
* Execute the job.
*
* @return void
* @throws GuzzleException
*/
public function handle()
{
Log::debug('Update of all apps triggered!');
$apps = Application::all('appid')->toArray();
// We onl update the apps that are actually in use by items
// 1 sec delay after each update to throttle the requests
foreach ($apps as $appKey => $app) {
Application::getApp($app['appid']);
sleep(1);
}
Log::debug('Update of all apps finished!');
Cache::lock('updateApps')->forceRelease();
}
/**
* @return void
*/
public function failed($exception)
{
Cache::lock('updateApps')->forceRelease();
}
}

View File

@@ -4,11 +4,16 @@ namespace App\Providers;
use App\Application;
use App\Jobs\ProcessApps;
use App\Jobs\UpdateApps;
use App\Setting;
use App\User;
use Artisan;
use Barryvdh\LaravelIdeHelper\IdeHelperServiceProvider;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\ServiceProvider;
use Schema;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;
class AppServiceProvider extends ServiceProvider
{
@@ -19,48 +24,23 @@ class AppServiceProvider extends ServiceProvider
*/
public function boot()
{
if (! is_file(base_path('.env'))) {
copy(base_path('.env.example'), base_path('.env'));
if (! class_exists('ZipArchive')) {
die('You are missing php-zip');
}
$this->genKey();
if (! is_file(database_path('app.sqlite'))) {
// first time setup
touch(database_path('app.sqlite'));
Artisan::call('migrate', ['--path' => 'database/migrations', '--force' => true, '--seed' => true]);
//Cache
//Artisan::call('config:cache');
//Artisan::call('route:cache');
}
if (is_file(database_path('app.sqlite'))) {
if (Schema::hasTable('settings')) {
// check version to see if an upgrade is needed
$db_version = Setting::_fetch('version');
$app_version = config('app.version');
if (version_compare($app_version, $db_version) == 1) { // app is higher than db, so need to run migrations etc
Artisan::call('migrate', ['--path' => 'database/migrations', '--force' => true, '--seed' => true]);
ProcessApps::dispatch();
}
} else {
Artisan::call('migrate', ['--path' => 'database/migrations', '--force' => true, '--seed' => true]);
}
}
$this->createEnvFile();
$this->setupDatabase();
if (! is_file(public_path('storage/.gitignore'))) {
Artisan::call('storage:link');
\Session::put('current_user', null);
}
$lang = Setting::fetch('language');
\App::setLocale($lang);
$applications = Application::all();
if ($applications->count() <= 0) {
if (class_exists('ZipArchive')) {
ProcessApps::dispatch();
} else {
die('You are missing php-zip');
}
ProcessApps::dispatch();
}
// User specific settings need to go here as session isn't available at this point in the app
@@ -97,6 +77,9 @@ class AppServiceProvider extends ServiceProvider
$allusers = User::all();
$current_user = User::currentUser();
$lang = Setting::fetch('language');
\App::setLocale($lang);
$view->with('alt_bg', $alt_bg);
$view->with('allusers', $allusers);
$view->with('current_user', $current_user);
@@ -134,8 +117,78 @@ class AppServiceProvider extends ServiceProvider
*/
public function register()
{
if ($this->app->isLocal()) {
$this->app->register(IdeHelperServiceProvider::class);
}
$this->app->singleton('settings', function () {
return new Setting();
});
}
/**
* Check if database needs an update or do first time database setup
*
* @return void
* @throws ContainerExceptionInterface
* @throws NotFoundExceptionInterface
*/
public function setupDatabase(): void
{
$db_type = config()->get('database.default');
if ($db_type == 'sqlite') {
$db_file = database_path(env('DB_DATABASE', 'app.sqlite'));
if (! is_file($db_file)) {
touch($db_file);
}
}
if ($this->needsDBUpdate()) {
Artisan::call('migrate', ['--path' => 'database/migrations', '--force' => true, '--seed' => true]);
ProcessApps::dispatchSync();
$this->updateApps();
}
}
/**
* @return void
*/
public function createEnvFile(): void
{
if (!is_file(base_path('.env'))) {
copy(base_path('.env.example'), base_path('.env'));
}
$this->genKey();
}
/**
* @return bool
*/
private function needsDBUpdate(): bool
{
if (!Schema::hasTable('settings')) {
return true;
}
$db_version = Setting::_fetch('version');
$app_version = config('app.version');
return version_compare($app_version, $db_version) === 1;
}
/**
* @return void
*/
private function updateApps()
{
// This lock ensures that the job is not invoked multiple times.
// In 5 minutes all app updates should be finished.
$lock = Cache::lock('updateApps', 5*60);
if ($lock->get()) {
UpdateApps::dispatchAfterResponse();
}
}
}

View File

@@ -3,7 +3,6 @@
namespace App\Providers;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
use Illuminate\Support\Facades\Gate;
class AuthServiceProvider extends ServiceProvider
{

View File

@@ -3,7 +3,6 @@
namespace App\Providers;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
use Illuminate\Support\Facades\Event;
class EventServiceProvider extends ServiceProvider
{

View File

@@ -12,9 +12,9 @@ class RouteServiceProvider extends ServiceProvider
*
* In addition, it is set as the URL generator's root namespace.
*
* @var string
* REMOVED WITH LARAVEL 8 UPGRADE
*/
protected $namespace = 'App\Http\Controllers';
// protected $namespace = 'App\Http\Controllers';
/**
* Define your route model bindings, pattern filters, etc.

View File

@@ -2,12 +2,9 @@
namespace App;
use App\Item;
use App\Setting;
use Cache;
use Form;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\GuzzleException;
use Illuminate\Support\Collection;
use Yaml;
abstract class Search
@@ -15,9 +12,9 @@ abstract class Search
/**
* List of all search providers
*
* @return array
* @return Collection
*/
public static function providers()
public static function providers(): Collection
{
$providers = self::standardProviders();
$providers = $providers + self::appProviders();
@@ -28,7 +25,7 @@ abstract class Search
/**
* Gets details for a single provider
*
* @return object
* @return false|object
*/
public static function providerDetails($provider)
{
@@ -45,7 +42,7 @@ abstract class Search
*
* @return array
*/
public static function standardProviders()
public static function standardProviders(): array
{
// $providers = json_decode(file_get_contents(storage_path('app/searchproviders.json')));
// print_r($providers);
@@ -65,7 +62,7 @@ abstract class Search
*
* @return array
*/
public static function appProviders()
public static function appProviders(): array
{
$providers = [];
$userapps = Item::all();
@@ -94,9 +91,9 @@ abstract class Search
/**
* Outputs the search form
*
* @return html
* @return string
*/
public static function form()
public static function form(): string
{
$output = '';
$homepage_search = Setting::fetch('homepage_search');
@@ -111,7 +108,7 @@ abstract class Search
}
$user_search_provider = $user_search_provider ?? 'none';
if ((bool) $homepage_search && (bool) $search_provider) {
if ((bool) $search_provider) {
if ((bool) $user_search_provider) {
$name = 'app.options.'.$user_search_provider;
$provider = self::providerDetails($user_search_provider);
@@ -125,7 +122,15 @@ abstract class Search
$output .= '<option value="'.$key.'"'.$selected.'>'.$searchprovider['name'].'</option>';
}
$output .= '</select>';
$output .= Form::text('q', null, ['class' => 'homesearch', 'autofocus' => 'autofocus', 'placeholder' => __('app.settings.search').'...']);
$output .= Form::text(
'q',
null,
[
'class' => 'homesearch',
'autofocus' => 'autofocus',
'placeholder' => __('app.settings.search').'...'
]
);
$output .= '<button type="submit">'.ucwords(__('app.settings.search')).'</button>';
$output .= '</div>';
$output .= '</form>';

View File

@@ -2,9 +2,6 @@
namespace App;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\GuzzleException;
interface SearchInterface
{
public function getResults($query, $providerdetails);

View File

@@ -2,14 +2,47 @@
namespace App;
use App\Search;
use App\User;
use Form;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Session\SessionManager;
use Illuminate\Session\Store;
use Illuminate\Support\Facades\Input;
/**
* App\Setting
*
* @mixin Builder
* @property int $id
* @property int $group_id
* @property string $key
* @property string $type
* @property string|null $options
* @property string $label
* @property string|null $value
* @property string $order
* @property int $system
* @property-read mixed $edit_value
* @property-read mixed $list_value
* @property-read \App\SettingGroup|null $group
* @property-read \Illuminate\Database\Eloquent\Collection|\App\User[] $users
* @property-read int|null $users_count
* @method static Builder|Setting newModelQuery()
* @method static Builder|Setting newQuery()
* @method static Builder|Setting query()
* @method static Builder|Setting whereGroupId($value)
* @method static Builder|Setting whereId($value)
* @method static Builder|Setting whereKey($value)
* @method static Builder|Setting whereLabel($value)
* @method static Builder|Setting whereOptions($value)
* @method static Builder|Setting whereOrder($value)
* @method static Builder|Setting whereSystem($value)
* @method static Builder|Setting whereType($value)
* @method static Builder|Setting whereValue($value)
*/
class Setting extends Model
{
/**
@@ -38,9 +71,10 @@ class Setting extends Model
protected static $cache = [];
/**
* @return array
* @param Request $request
* @return object
*/
public static function getInput(Request $request)
public static function getInput(Request $request): object
{
return (object) [
'value' => $request->input('value'),
@@ -59,7 +93,11 @@ class Setting extends Model
switch ($this->type) {
case 'image':
if (! empty($this->value)) {
$value = '<a href="'.asset('storage/'.$this->value).'" title="'.__('app.settings.view').'" target="_blank">'.__('app.settings.view').'</a>';
$value = '<a href="'.asset('storage/'.$this->value).'" title="'.
__('app.settings.view').
'" target="_blank">'.
__('app.settings.view').
'</a>';
} else {
$value = __('app.options.none');
}
@@ -77,7 +115,9 @@ class Setting extends Model
if ($this->key === 'search_provider') {
$options = Search::providers()->pluck('name', 'id')->toArray();
}
$value = __($options[$this->value]);
$value = (array_key_exists($this->value, $options))
? __($options[$this->value])
: __('app.options.none');
} else {
$value = __('app.options.none');
}
@@ -102,11 +142,24 @@ class Setting extends Model
case 'image':
$value = '';
if (isset($this->value) && ! empty($this->value)) {
$value .= '<a class="setting-view-image" href="'.asset('storage/'.$this->value).'" title="'.__('app.settings.view').'" target="_blank"><img src="'.asset('storage/'.$this->value).'" /></a>';
$value .= '<a class="setting-view-image" href="'.
asset('storage/'.$this->value).
'" title="'.
__('app.settings.view').
'" target="_blank"><img src="'.
asset('storage/'.
$this->value).
'" /></a>';
}
$value .= Form::file('value', ['class' => 'form-control']);
if (isset($this->value) && ! empty($this->value)) {
$value .= '<a class="settinglink" href="'.route('settings.clear', $this->id).'" title="'.__('app.settings.remove').'">'.__('app.settings.reset').'</a>';
$value .= '<a class="settinglink" href="'.
route('settings.clear', $this->id).
'" title="'.
__('app.settings.remove').
'">'.
__('app.settings.reset').
'</a>';
}
break;
@@ -145,7 +198,10 @@ class Setting extends Model
return $value;
}
public function group()
/**
* @return BelongsTo
*/
public function group(): BelongsTo
{
return $this->belongsTo(\App\SettingGroup::class, 'group_id');
}
@@ -155,7 +211,7 @@ class Setting extends Model
*
* @return mixed
*/
public static function fetch($key)
public static function fetch(string $key)
{
$user = self::user();
@@ -222,7 +278,7 @@ class Setting extends Model
*
* @return bool
*/
public static function cached($key)
public static function cached($key): bool
{
return array_key_exists($key, self::$cache);
}
@@ -230,11 +286,14 @@ class Setting extends Model
/**
* The users that belong to the setting.
*/
public function users()
public function users(): BelongsToMany
{
return $this->belongsToMany(\App\User::class)->using(\App\SettingUser::class)->withPivot('uservalue');
}
/**
* @return \Illuminate\Contracts\Foundation\Application|SessionManager|Store|mixed
*/
public static function user()
{
return User::currentUser();

View File

@@ -3,7 +3,24 @@
namespace App;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;
/**
* App\SettingGroup
*
* @property int $id
* @property string $title
* @property int $order
* @property-read \Illuminate\Database\Eloquent\Collection|\App\Setting[] $settings
* @property-read int|null $settings_count
* @method static \Illuminate\Database\Eloquent\Builder|SettingGroup newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder|SettingGroup newQuery()
* @method static \Illuminate\Database\Eloquent\Builder|SettingGroup query()
* @method static \Illuminate\Database\Eloquent\Builder|SettingGroup whereId($value)
* @method static \Illuminate\Database\Eloquent\Builder|SettingGroup whereOrder($value)
* @method static \Illuminate\Database\Eloquent\Builder|SettingGroup whereTitle($value)
* @mixin \Eloquent
*/
class SettingGroup extends Model
{
/**
@@ -20,7 +37,10 @@ class SettingGroup extends Model
*/
public $timestamps = false;
public function settings()
/**
* @return HasMany
*/
public function settings(): HasMany
{
return $this->hasMany(\App\Setting::class, 'group_id');
}

View File

@@ -4,6 +4,20 @@ namespace App;
use Illuminate\Database\Eloquent\Relations\Pivot;
/**
* App\SettingUser
*
* @property int $setting_id
* @property int $user_id
* @property string|null $uservalue
* @method static \Illuminate\Database\Eloquent\Builder|SettingUser newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder|SettingUser newQuery()
* @method static \Illuminate\Database\Eloquent\Builder|SettingUser query()
* @method static \Illuminate\Database\Eloquent\Builder|SettingUser whereSettingId($value)
* @method static \Illuminate\Database\Eloquent\Builder|SettingUser whereUserId($value)
* @method static \Illuminate\Database\Eloquent\Builder|SettingUser whereUservalue($value)
* @mixin \Eloquent
*/
class SettingUser extends Pivot
{
//

View File

@@ -3,8 +3,11 @@
namespace App;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\ConnectException;
use GuzzleHttp\Exception\GuzzleException;
use GuzzleHttp\Exception\ServerException;
use Illuminate\Support\Facades\Log;
use Psr\Http\Message\ResponseInterface;
abstract class SupportedApps
{
@@ -14,7 +17,13 @@ abstract class SupportedApps
protected $error;
public function appTest($url, $attrs = [], $overridevars = false)
/**
* @param $url
* @param array $attrs
* @return object
* @throws GuzzleException
*/
public function appTest($url, array $attrs = []): object
{
if (empty($this->config->url)) {
return (object) [
@@ -53,28 +62,41 @@ abstract class SupportedApps
];
}
public function execute($url, $attrs = [], $overridevars = false, $overridemethod = false)
{
/**
* @param $url
* @param array $attrs
* @param array|bool|null $overridevars
* @param string|bool|null $overridemethod
* @return ResponseInterface|null
* @throws GuzzleException
*/
public function execute(
$url,
array $attrs = [],
$overridevars = null,
$overridemethod = null
): ?ResponseInterface {
$res = null;
$vars = ($overridevars !== false) ?
$overridevars : [
$vars = ($overridevars === null || $overridevars === false) ?
[
'http_errors' => false,
'timeout' => 15,
'connect_timeout' => 15,
];
] : $overridevars;
$client = new Client($vars);
$method = ($overridemethod !== false) ? $overridemethod : $this->method;
$method = ($overridemethod === null || $overridemethod === false) ? $this->method : $overridemethod;
try {
return $client->request($method, $url, $attrs);
} catch (\GuzzleHttp\Exception\ConnectException $e) {
} catch (ConnectException $e) {
Log::error('Connection refused');
Log::debug($e->getMessage());
$this->error = 'Connection refused - '.(string) $e->getMessage();
} catch (\GuzzleHttp\Exception\ServerException $e) {
} catch (ServerException $e) {
Log::debug($e->getMessage());
$this->error = (string) $e->getResponse()->getBody();
}
@@ -83,11 +105,19 @@ abstract class SupportedApps
return $res;
}
/**
* @return void
*/
public function login()
{
}
public function normaliseurl($url, $addslash = true)
/**
* @param string $url
* @param bool $addslash
* @return string
*/
public function normaliseurl(string $url, bool $addslash = true): string
{
$url = rtrim($url, '/');
if ($addslash) {
@@ -97,6 +127,11 @@ abstract class SupportedApps
return $url;
}
/**
* @param $status
* @param $data
* @return false|string
*/
public function getLiveStats($status, $data)
{
$className = get_class($this);
@@ -109,7 +144,11 @@ abstract class SupportedApps
//return
}
public static function getList()
/**
* @return ResponseInterface
* @throws GuzzleException
*/
public static function getList(): ResponseInterface
{
// $list_url = 'https://apps.heimdall.site/list';
$list_url = config('app.appsource').'list.json';
@@ -127,13 +166,25 @@ abstract class SupportedApps
}
}
public static function getFiles($app)
/**
* @param $app
* @return bool|false
* @throws GuzzleException
*/
public static function getFiles($app): bool
{
Log::debug("Download triggered for ".print_r($app, true));
$zipurl = config('app.appsource').'files/'.$app->sha.'.zip';
$client = new Client(['http_errors' => false, 'timeout' => 60, 'connect_timeout' => 15, 'verify' => false]);
$res = $client->request('GET', $zipurl);
// Something went wrong?
if ($res->getStatusCode() !== 200) {
return false;
}
if (! file_exists(app_path('SupportedApps'))) {
mkdir(app_path('SupportedApps'), 0777, true);
}
@@ -149,9 +200,16 @@ abstract class SupportedApps
unlink($src); //Deleting the Zipped file
} else {
var_dump($x);
return false;
}
return true;
}
/**
* @param $details
* @param $app
* @return mixed
*/
public static function saveApp($details, $app)
{
$app->appid = $details->appid;

View File

@@ -2,13 +2,52 @@
namespace App;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
/**
* App\User
*
* @property int $id
* @property string $username
* @property string $email
* @property string|null $avatar
* @property string|null $password
* @property string|null $autologin
* @property int $public_front
* @property string|null $remember_token
* @property \Illuminate\Support\Carbon|null $created_at
* @property \Illuminate\Support\Carbon|null $updated_at
* @property-read \Illuminate\Database\Eloquent\Collection|\App\Item[] $items
* @property-read int|null $items_count
* @property-read \Illuminate\Notifications\DatabaseNotificationCollection|\Illuminate\Notifications\DatabaseNotification[] $notifications
* @property-read int|null $notifications_count
* @property-read \Illuminate\Database\Eloquent\Collection|\App\Setting[] $settings
* @property-read int|null $settings_count
* @method static \Illuminate\Database\Eloquent\Builder|User newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder|User newQuery()
* @method static \Illuminate\Database\Eloquent\Builder|User query()
* @method static \Illuminate\Database\Eloquent\Builder|User whereAutologin($value)
* @method static \Illuminate\Database\Eloquent\Builder|User whereAvatar($value)
* @method static \Illuminate\Database\Eloquent\Builder|User whereCreatedAt($value)
* @method static \Illuminate\Database\Eloquent\Builder|User whereEmail($value)
* @method static \Illuminate\Database\Eloquent\Builder|User whereId($value)
* @method static \Illuminate\Database\Eloquent\Builder|User wherePassword($value)
* @method static \Illuminate\Database\Eloquent\Builder|User wherePublicFront($value)
* @method static \Illuminate\Database\Eloquent\Builder|User whereRememberToken($value)
* @method static \Illuminate\Database\Eloquent\Builder|User whereUpdatedAt($value)
* @method static \Illuminate\Database\Eloquent\Builder|User whereUsername($value)
* @mixin \Eloquent
*/
class User extends Authenticatable
{
use Notifiable;
use HasFactory;
/**
* The attributes that are mass assignable.
*
@@ -27,20 +66,28 @@ class User extends Authenticatable
'password', 'remember_token',
];
/**
* @return mixed
*/
public function getId()
{
return $this->id;
}
/**
* Get the items for the user.
*/
public function items()
public function items(): HasMany
{
return $this->hasMany(\App\Item::class);
return $this->hasMany(Item::class);
}
/**
* The settings that belong to the user.
*/
public function settings()
public function settings(): BelongsToMany
{
return $this->belongsToMany(\App\Setting::class)->withPivot('uservalue');
return $this->belongsToMany(Setting::class)->withPivot('uservalue');
}
public static function currentUser()

View File

@@ -1,37 +1,48 @@
{
"name": "laravel/laravel",
"description": "The Laravel Framework.",
"keywords": ["framework", "laravel"],
"keywords": [
"framework",
"laravel"
],
"license": "MIT",
"type": "project",
"require": {
"php": ">=7.2.5",
"php": ">=7.4.32",
"facade/ignition": "^2.3.6",
"fideloper/proxy": "^4.0",
"graham-campbell/github": "^10.5",
"guzzlehttp/guzzle": "^7.4",
"laravel/framework": "^7.0",
"laravel/framework": "^8.0",
"laravel/tinker": "^2.0",
"laravel/ui": "^2.4",
"laravel/ui": "^3.0",
"laravelcollective/html": "^6.0",
"symfony/yaml": "^5.4"
"nunomaduro/collision": "^5.0",
"symfony/yaml": "^5.4",
"ext-json": "*",
"ext-intl": "*"
},
"require-dev": {
"barryvdh/laravel-ide-helper": "^2.12",
"filp/whoops": "~2.0",
"fzaninotto/faker": "~1.4",
"mockery/mockery": "~1.0",
"phpunit/phpunit": "~6.0",
"phpunit/phpunit": "~9.0",
"squizlabs/php_codesniffer": "3.*",
"symfony/thanks": "^1.0"
},
"autoload": {
"classmap": [
"database/seeds",
"database/seeders",
"database/factories"
],
"files": [
"app/Helper.php"
],
"psr-4": {
"App\\": "app/"
"App\\": "app/",
"Database\\Factories\\": "database/factories/",
"Database\\Seeders\\": "database/seeders/"
}
},
"autoload-dev": {
@@ -42,6 +53,7 @@
"extra": {
"laravel": {
"dont-discover": [
"barryvdh/laravel-ide-helper"
]
}
},
@@ -55,6 +67,11 @@
"post-autoload-dump": [
"Illuminate\\Foundation\\ComposerScripts::postAutoloadDump",
"@php artisan package:discover"
],
"post-update-cmd": [
"Illuminate\\Foundation\\ComposerScripts::postUpdate",
"@php artisan ide-helper:generate",
"@php artisan ide-helper:meta"
]
},
"config": {

3525
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

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

View File

@@ -17,7 +17,7 @@ return [
|
*/
'default' => env('LOG_CHANNEL', 'stack'),
'default' => env('LOG_CHANNEL', 'daily'),
/*
|--------------------------------------------------------------------------

View File

@@ -0,0 +1,29 @@
<?php
namespace Database\Factories;
use App\Item;
use Illuminate\Database\Eloquent\Factories\Factory;
class ItemFactory extends Factory
{
/**
* The name of the factory's corresponding model.
*
* @var string
*/
protected $model = Item::class;
/**
* Define the model's default state.
*
* @return array
*/
public function definition(): array
{
return [
'title' => $this->faker->unique()->text(),
'url' => $this->faker->unique()->url(),
];
}
}

View File

@@ -0,0 +1,27 @@
<?php
namespace Database\Factories;
use App\Item;
use App\ItemTag;
use Illuminate\Database\Eloquent\Factories\Factory;
class ItemTagFactory extends Factory
{
/**
* The name of the factory's corresponding model.
*
* @var string
*/
protected $model = ItemTag::class;
/**
* Define the model's default state.
*
* @return array
*/
public function definition(): array
{
return [];
}
}

View File

@@ -1,23 +1,47 @@
<?php
use Faker\Generator as Faker;
namespace Database\Factories;
/*
|--------------------------------------------------------------------------
| Model Factories
|--------------------------------------------------------------------------
|
| This directory should contain each of the model factory definitions for
| your application. Factories provide a convenient way to generate new
| model instances for testing / seeding your application's database.
|
*/
use App\User;
use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Support\Str;
$factory->define(App\User::class, function (Faker $faker) {
return [
'name' => $faker->name,
'email' => $faker->unique()->safeEmail,
'password' => '$2y$10$TKh8H1.PfQx37YgCzwiKb.KjNyWgaHb9cbcoQgdIVFlYg7B77UdFm', // secret
'remember_token' => str_random(10),
];
});
class UserFactory extends Factory
{
/**
* The name of the factory's corresponding model.
*
* @var string
*/
protected $model = User::class;
/**
* Define the model's default state.
*
* @return array
*/
public function definition()
{
return [
'username' => $this->faker->name(),
'email' => $this->faker->unique()->safeEmail(),
'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password
'public_front' => 1,
'remember_token' => Str::random(10),
];
}
/**
* Indicate that the model's email address should be unverified.
*
* @return \Illuminate\Database\Eloquent\Factories\Factory
*/
public function unverified()
{
return $this->state(function (array $attributes) {
return [
'email_verified_at' => null,
];
});
}
}

View File

@@ -1,5 +1,7 @@
<?php
namespace Database\Seeders;
use Illuminate\Database\Seeder;
class DatabaseSeeder extends Seeder

View File

@@ -1,11 +1,51 @@
<?php
namespace Database\Seeders;
use App\Setting;
use App\SettingGroup;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Locale;
class SettingsSeeder extends Seeder
{
/**
* @return false|string
*/
public static function getSupportedLanguageMap()
{
if (! class_exists('Locale')) {
Log::info('PHP Extension Intl not found. Falling back to English language support only.');
return json_encode(['en' => 'English']);
}
$languageDirectories = array_filter(glob(resource_path().'/lang/*'), 'is_dir');
$result = [];
foreach ($languageDirectories as $languageDirectory) {
$language = self::getLanguageFromDirectory($languageDirectory);
$resultNative = mb_convert_case(Locale::getDisplayLanguage($language.'-', $language), MB_CASE_TITLE, 'UTF-8');
$resultEn = ucfirst(Locale::getDisplayLanguage($language, 'en'));
$result[$language] = "$resultNative ($resultEn)";
}
return json_encode($result);
}
/**
* @param $languageDirectory
* @return false|string[]
*/
public static function getLanguageFromDirectory($languageDirectory)
{
$directories = explode('/', $languageDirectory);
return $directories[array_key_last($directories)];
}
/**
* Run the database seeds.
*
@@ -120,20 +160,8 @@ class SettingsSeeder extends Seeder
$setting->save();
}
$language_options = json_encode([
'de' => 'Deutsch (German)',
'en' => 'English',
'cn' => '简体中文 (Simplified Chinese)',
'fi' => 'Suomi (Finnish)',
'fr' => 'Français (French)',
'el' => 'Ελληνικά (Greek)',
'it' => 'Italiano (Italian)',
'no' => 'Norsk (Norwegian)',
'pl' => 'Polski (Polish)',
'sv' => 'Svenska (Swedish)',
'es' => 'Español (Spanish)',
'tr' => 'Türkçe (Turkish)',
]);
$language_options = SettingsSeeder::getSupportedLanguageMap();
if ($languages = Setting::find(5)) {
$languages->options = $language_options;
$languages->save();
@@ -243,7 +271,15 @@ class SettingsSeeder extends Seeder
$home_tag->url = '';
$home_tag->type = 1;
$home_tag->user_id = 0;
$home_tag->save();
$home_tag_id = $home_tag->id;
if($home_tag_id != 0) {
Log::info("Home Tag returned with id $home_tag_id from db! Changing to 0.");
DB::update('update items set id = 0 where id = ?', [$home_tag_id]);
}
$homeapps = \App\Item::withoutGlobalScope('user_id')->doesntHave('parents')->get();
foreach ($homeapps as $app) {

View File

@@ -0,0 +1,36 @@
<?php
namespace Database\Seeders;
use App\User;
use Illuminate\Database\Seeder;
class UsersSeeder extends Seeder
{
/**
* Run the database seeds.
*
* @return void
*/
public function run()
{
// Groups
if (! $user = User::find(1)) {
$user = new User;
$user->username = 'admin';
$user->email = 'admin@test.com';
$user->password = null;
$user->save();
$user_id = $user->id;
if($user_id != 1) {
Log::info("First User returned with id $user_id from db! Changing to 1.");
DB::update('update users set id = 1 where id = ?', [$user_id]);
}
} else {
//$user->save();
}
}
}

View File

@@ -1,27 +0,0 @@
<?php
use App\User;
use Illuminate\Database\Seeder;
class UsersSeeder extends Seeder
{
/**
* Run the database seeds.
*
* @return void
*/
public function run()
{
// Groups
if (! $user = User::find(1)) {
$user = new User;
$user->id = 1;
$user->username = 'admin';
$user->email = 'admin@test.com';
$user->password = null;
$user->save();
} else {
//$user->save();
}
}
}

16155
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -2,22 +2,27 @@
"private": true,
"scripts": {
"dev": "npm run development",
"development": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
"watch": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --watch --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
"watch-poll": "npm run watch -- --watch-poll",
"hot": "cross-env NODE_ENV=development node_modules/webpack-dev-server/bin/webpack-dev-server.js --inline --hot --config=node_modules/laravel-mix/setup/webpack.config.js",
"development": "mix",
"watch": "mix watch",
"watch-poll": "mix watch -- --watch-options-poll=1000",
"hot": "mix watch --hot",
"prod": "npm run production",
"production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --no-progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js"
"production": "mix --production",
"lint": "eslint 'resources/assets/js/*'"
},
"devDependencies": {
"bootstrap-sass": "^3.4.1",
"cross-env": "^5.2.0",
"jquery": "^3.4.1",
"laravel-mix": "^4.0.16",
"sass": "^1.21.0",
"sass-loader": "7.*"
"bootstrap-sass": "^3.4.3",
"eslint": "^8.28.0",
"eslint-config-airbnb-base": "^15.0.0",
"eslint-config-prettier": "^8.5.0",
"eslint-plugin-import": "^2.26.0",
"eslint-plugin-prettier": "^4.2.1",
"jquery": "^3.6.1",
"laravel-mix": "^6.0.49",
"sass": "^1.56.1",
"sass-loader": "13.*"
},
"dependencies": {
"select2": "^4.0.7"
"select2": "^4.0.13"
}
}

23
phpcs.xml Normal file
View File

@@ -0,0 +1,23 @@
<?xml version="1.0"?>
<ruleset name="PHP_CodeSniffer">
<description>The coding standard for our project.</description>
<rule ref="PSR2"/>
<file>app</file>
<file>bootstrap</file>
<file>config</file>
<file>database</file>
<file>resources</file>
<file>routes</file>
<file>tests</file>
<exclude-pattern>bootstrap/cache/*</exclude-pattern>
<exclude-pattern>bootstrap/autoload.php</exclude-pattern>
<exclude-pattern>*/migrations/*</exclude-pattern>
<exclude-pattern>*/seeds/*</exclude-pattern>
<exclude-pattern>*.blade.php</exclude-pattern>
<exclude-pattern>*.js</exclude-pattern>
<!-- Show progression -->
<arg value="p"/>
</ruleset>

View File

@@ -1,31 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="./vendor/phpunit/phpunit/phpunit.xsd"
bootstrap="vendor/autoload.php"
colors="true"
>
<testsuites>
<testsuite name="Unit">
<directory suffix="Test.php">./tests/Unit</directory>
</testsuite>
<testsuite name="Feature">
<directory suffix="Test.php">./tests/Feature</directory>
</testsuite>
</testsuites>
<filter>
<whitelist processUncoveredFilesFromWhitelist="true">
<directory suffix=".php">./app</directory>
</whitelist>
</filter>
<php>
<server name="APP_ENV" value="testing"/>
<server name="BCRYPT_ROUNDS" value="4"/>
<server name="CACHE_DRIVER" value="array"/>
<!-- <server name="DB_CONNECTION" value="sqlite"/> -->
<!-- <server name="DB_DATABASE" value=":memory:"/> -->
<server name="MAIL_MAILER" value="array"/>
<server name="QUEUE_CONNECTION" value="sync"/>
<server name="SESSION_DRIVER" value="array"/>
<server name="TELESCOPE_ENABLED" value="false"/>
</php>
</phpunit>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.3/phpunit.xsd" bootstrap="vendor/autoload.php" colors="true">
<coverage processUncoveredFiles="true">
<include>
<directory suffix=".php">./app</directory>
</include>
</coverage>
<testsuites>
<testsuite name="Unit">
<directory suffix="Test.php">./tests/Unit</directory>
</testsuite>
<testsuite name="Feature">
<directory suffix="Test.php">./tests/Feature</directory>
</testsuite>
</testsuites>
<php>
<server name="APP_ENV" value="testing"/>
<server name="BCRYPT_ROUNDS" value="4"/>
<server name="CACHE_DRIVER" value="array"/>
<!-- <server name="DB_CONNECTION" value="sqlite"/> -->
<!-- <server name="DB_DATABASE" value=":memory:"/> -->
<server name="MAIL_MAILER" value="array"/>
<server name="QUEUE_CONNECTION" value="sync"/>
<server name="SESSION_DRIVER" value="array"/>
<server name="TELESCOPE_ENABLED" value="false"/>
</php>
</phpunit>

2068
public/css/app.css vendored

File diff suppressed because one or more lines are too long

749
public/js/app.js vendored

File diff suppressed because one or more lines are too long

View File

@@ -483,10 +483,14 @@ var icons = {
"arrow-rotate-right": [512, 512, [8635, "arrow-right-rotate", "arrow-rotate-forward", "redo"], "f01e", "M496 48V192c0 17.69-14.31 32-32 32H320c-17.69 0-32-14.31-32-32s14.31-32 32-32h63.39c-29.97-39.7-77.25-63.78-127.6-63.78C167.7 96.22 96 167.9 96 256s71.69 159.8 159.8 159.8c34.88 0 68.03-11.03 95.88-31.94c14.22-10.53 34.22-7.75 44.81 6.375c10.59 14.16 7.75 34.22-6.375 44.81c-39.03 29.28-85.36 44.86-134.2 44.86C132.5 479.9 32 379.4 32 256s100.5-223.9 223.9-223.9c69.15 0 134 32.47 176.1 86.12V48c0-17.69 14.31-32 32-32S496 30.31 496 48z"],
"ban": [512, 512, [], "f05e", "M256 8C119.034 8 8 119.033 8 256s111.034 248 248 248 248-111.034 248-248S392.967 8 256 8zm130.108 117.892c65.448 65.448 70 165.481 20.677 235.637L150.47 105.216c70.204-49.356 170.226-44.735 235.638 20.676zM125.892 386.108c-65.448-65.448-70-165.481-20.677-235.637L361.53 406.784c-70.203 49.356-170.226 44.736-235.638-20.676z"],
"check": [512, 512, [], "f00c", "M173.898 439.404l-166.4-166.4c-9.997-9.997-9.997-26.206 0-36.204l36.203-36.204c9.997-9.998 26.207-9.998 36.204 0L192 312.69 432.095 72.596c9.997-9.997 26.207-9.997 36.204 0l36.203 36.204c9.997 9.997 9.997 26.206 0 36.204l-294.4 294.401c-9.998 9.997-26.207 9.997-36.204-.001z"],
"circle-check": [512, 512, [61533, "check-circle"], "f058", ["M0 256C0 114.6 114.6 0 256 0C397.4 0 512 114.6 512 256C512 397.4 397.4 512 256 512C114.6 512 0 397.4 0 256zM371.8 211.8C382.7 200.9 382.7 183.1 371.8 172.2C360.9 161.3 343.1 161.3 332.2 172.2L224 280.4L179.8 236.2C168.9 225.3 151.1 225.3 140.2 236.2C129.3 247.1 129.3 264.9 140.2 275.8L204.2 339.8C215.1 350.7 232.9 350.7 243.8 339.8L371.8 211.8z", "M371.8 172.2C382.7 183.1 382.7 200.9 371.8 211.8L243.8 339.8C232.9 350.7 215.1 350.7 204.2 339.8L140.2 275.8C129.3 264.9 129.3 247.1 140.2 236.2C151.1 225.3 168.9 225.3 179.8 236.2L224 280.4L332.2 172.2C343.1 161.3 360.9 161.3 371.8 172.2V172.2z"]],
"circle-xmark": [512, 512, [61532, "times-circle", "xmark-circle"], "f057", ["M0 256C0 114.6 114.6 0 256 0C397.4 0 512 114.6 512 256C512 397.4 397.4 512 256 512C114.6 512 0 397.4 0 256zM175 208.1L222.1 255.1L175 303C165.7 312.4 165.7 327.6 175 336.1C184.4 346.3 199.6 346.3 208.1 336.1L255.1 289.9L303 336.1C312.4 346.3 327.6 346.3 336.1 336.1C346.3 327.6 346.3 312.4 336.1 303L289.9 255.1L336.1 208.1C346.3 199.6 346.3 184.4 336.1 175C327.6 165.7 312.4 165.7 303 175L255.1 222.1L208.1 175C199.6 165.7 184.4 165.7 175 175C165.7 184.4 165.7 199.6 175 208.1V208.1z", "M255.1 222.1L303 175C312.4 165.7 327.6 165.7 336.1 175C346.3 184.4 346.3 199.6 336.1 208.1L289.9 255.1L336.1 303C346.3 312.4 346.3 327.6 336.1 336.1C327.6 346.3 312.4 346.3 303 336.1L255.1 289.9L208.1 336.1C199.6 346.3 184.4 346.3 175 336.1C165.7 327.6 165.7 312.4 175 303L222.1 255.1L175 208.1C165.7 199.6 165.7 184.4 175 175C184.4 165.7 199.6 165.7 208.1 175L255.1 222.1z"]],
"cloud-download": [640, 512, [], "f0ed", "M537.6 226.6c4.1-10.7 6.4-22.4 6.4-34.6 0-53-43-96-96-96-19.7 0-38.1 6-53.3 16.2C367 64.2 315.3 32 256 32c-88.4 0-160 71.6-160 160 0 2.7.1 5.4.2 8.1C40.2 219.8 0 273.2 0 336c0 79.5 64.5 144 144 144h368c70.7 0 128-57.3 128-128 0-61.9-44-113.6-102.4-125.4zm-139.9 93L305 412.3c-9.4 9.4-24.6 9.4-33.9 0l-92.7-92.7c-9.4-9.4-9.4-24.6 0-33.9l10.8-10.8c9.6-9.6 25.2-9.3 34.5.5l32.4 34.5V184c0-13.3 10.7-24 24-24h16c13.3 0 24 10.7 24 24v125.9l32.4-34.5c9.3-9.9 24.9-10.1 34.5-.5l10.8 10.8c9.2 9.3 9.2 24.5-.1 33.9z"],
"cogs": [640, 512, [], "f085", "M512.1 191l-8.2 14.3c-3 5.3-9.4 7.5-15.1 5.4-11.8-4.4-22.6-10.7-32.1-18.6-4.6-3.8-5.8-10.5-2.8-15.7l8.2-14.3c-6.9-8-12.3-17.3-15.9-27.4h-16.5c-6 0-11.2-4.3-12.2-10.3-2-12-2.1-24.6 0-37.1 1-6 6.2-10.4 12.2-10.4h16.5c3.6-10.1 9-19.4 15.9-27.4l-8.2-14.3c-3-5.2-1.9-11.9 2.8-15.7 9.5-7.9 20.4-14.2 32.1-18.6 5.7-2.1 12.1.1 15.1 5.4l8.2 14.3c10.5-1.9 21.2-1.9 31.7 0L552 6.3c3-5.3 9.4-7.5 15.1-5.4 11.8 4.4 22.6 10.7 32.1 18.6 4.6 3.8 5.8 10.5 2.8 15.7l-8.2 14.3c6.9 8 12.3 17.3 15.9 27.4h16.5c6 0 11.2 4.3 12.2 10.3 2 12 2.1 24.6 0 37.1-1 6-6.2 10.4-12.2 10.4h-16.5c-3.6 10.1-9 19.4-15.9 27.4l8.2 14.3c3 5.2 1.9 11.9-2.8 15.7-9.5 7.9-20.4 14.2-32.1 18.6-5.7 2.1-12.1-.1-15.1-5.4l-8.2-14.3c-10.4 1.9-21.2 1.9-31.7 0zm-10.5-58.8c38.5 29.6 82.4-14.3 52.8-52.8-38.5-29.7-82.4 14.3-52.8 52.8zM386.3 286.1l33.7 16.8c10.1 5.8 14.5 18.1 10.5 29.1-8.9 24.2-26.4 46.4-42.6 65.8-7.4 8.9-20.2 11.1-30.3 5.3l-29.1-16.8c-16 13.7-34.6 24.6-54.9 31.7v33.6c0 11.6-8.3 21.6-19.7 23.6-24.6 4.2-50.4 4.4-75.9 0-11.5-2-20-11.9-20-23.6V418c-20.3-7.2-38.9-18-54.9-31.7L74 403c-10 5.8-22.9 3.6-30.3-5.3-16.2-19.4-33.3-41.6-42.2-65.7-4-10.9.4-23.2 10.5-29.1l33.3-16.8c-3.9-20.9-3.9-42.4 0-63.4L12 205.8c-10.1-5.8-14.6-18.1-10.5-29 8.9-24.2 26-46.4 42.2-65.8 7.4-8.9 20.2-11.1 30.3-5.3l29.1 16.8c16-13.7 34.6-24.6 54.9-31.7V57.1c0-11.5 8.2-21.5 19.6-23.5 24.6-4.2 50.5-4.4 76-.1 11.5 2 20 11.9 20 23.6v33.6c20.3 7.2 38.9 18 54.9 31.7l29.1-16.8c10-5.8 22.9-3.6 30.3 5.3 16.2 19.4 33.2 41.6 42.1 65.8 4 10.9.1 23.2-10 29.1l-33.7 16.8c3.9 21 3.9 42.5 0 63.5zm-117.6 21.1c59.2-77-28.7-164.9-105.7-105.7-59.2 77 28.7 164.9 105.7 105.7zm243.4 182.7l-8.2 14.3c-3 5.3-9.4 7.5-15.1 5.4-11.8-4.4-22.6-10.7-32.1-18.6-4.6-3.8-5.8-10.5-2.8-15.7l8.2-14.3c-6.9-8-12.3-17.3-15.9-27.4h-16.5c-6 0-11.2-4.3-12.2-10.3-2-12-2.1-24.6 0-37.1 1-6 6.2-10.4 12.2-10.4h16.5c3.6-10.1 9-19.4 15.9-27.4l-8.2-14.3c-3-5.2-1.9-11.9 2.8-15.7 9.5-7.9 20.4-14.2 32.1-18.6 5.7-2.1 12.1.1 15.1 5.4l8.2 14.3c10.5-1.9 21.2-1.9 31.7 0l8.2-14.3c3-5.3 9.4-7.5 15.1-5.4 11.8 4.4 22.6 10.7 32.1 18.6 4.6 3.8 5.8 10.5 2.8 15.7l-8.2 14.3c6.9 8 12.3 17.3 15.9 27.4h16.5c6 0 11.2 4.3 12.2 10.3 2 12 2.1 24.6 0 37.1-1 6-6.2 10.4-12.2 10.4h-16.5c-3.6 10.1-9 19.4-15.9 27.4l8.2 14.3c3 5.2 1.9 11.9-2.8 15.7-9.5 7.9-20.4 14.2-32.1 18.6-5.7 2.1-12.1-.1-15.1-5.4l-8.2-14.3c-10.4 1.9-21.2 1.9-31.7 0zM501.6 431c38.5 29.6 82.4-14.3 52.8-52.8-38.5-29.6-82.4 14.3-52.8 52.8z"],
"edit": [576, 512, [], "f044", "M402.6 83.2l90.2 90.2c3.8 3.8 3.8 10 0 13.8L274.4 405.6l-92.8 10.3c-12.4 1.4-22.9-9.1-21.5-21.5l10.3-92.8L388.8 83.2c3.8-3.8 10-3.8 13.8 0zm162-22.9l-48.8-48.8c-15.2-15.2-39.9-15.2-55.2 0l-35.4 35.4c-3.8 3.8-3.8 10 0 13.8l90.2 90.2c3.8 3.8 10 3.8 13.8 0l35.4-35.4c15.2-15.3 15.2-40 0-55.2zM384 346.2V448H64V128h229.8c3.2 0 6.2-1.3 8.5-3.5l40-40c7.6-7.6 2.2-20.5-8.5-20.5H48C21.5 64 0 85.5 0 112v352c0 26.5 21.5 48 48 48h352c26.5 0 48-21.5 48-48V306.2c0-10.7-12.9-16-20.5-8.5l-40 40c-2.2 2.3-3.5 5.3-3.5 8.5z"],
"exchange": [512, 512, [], "f0ec", "M0 168v-16c0-13.255 10.745-24 24-24h381.97l-30.467-27.728c-9.815-9.289-10.03-24.846-.474-34.402l10.84-10.84c9.373-9.373 24.568-9.373 33.941 0l82.817 82.343c12.497 12.497 12.497 32.758 0 45.255l-82.817 82.343c-9.373 9.373-24.569 9.373-33.941 0l-10.84-10.84c-9.556-9.556-9.341-25.114.474-34.402L405.97 192H24c-13.255 0-24-10.745-24-24zm488 152H106.03l30.467-27.728c9.815-9.289 10.03-24.846.474-34.402l-10.84-10.84c-9.373-9.373-24.568-9.373-33.941 0L9.373 329.373c-12.497 12.497-12.497 32.758 0 45.255l82.817 82.343c9.373 9.373 24.569 9.373 33.941 0l10.84-10.84c9.556-9.556 9.341-25.113-.474-34.402L106.03 384H488c13.255 0 24-10.745 24-24v-16c0-13.255-10.745-24-24-24z"],
"file-arrow-down": [384, 512, ["file-download"], "f56d", ["M256 128V0H48C21.49 0 0 21.49 0 48v416C0 490.5 21.49 512 48 512h288c26.51 0 48-21.49 48-48V128H256zM288.1 360.1l-80 80c-9.375 9.375-24.56 9.375-33.94 0l-80-80c-9.375-9.375-9.375-24.56 0-33.94C99.72 322.3 105.8 320 112 320s12.28 2.344 16.97 7.031L168 366.1V248C168 234.8 178.8 224 192 224s24 10.75 24 24v118.1l39.03-39.03c9.375-9.375 24.56-9.375 33.94 0S298.3 351.6 288.1 360.1z", "M256 0v128h128L256 0zM255 327L216 366.1V248C216 234.8 205.3 224 192 224S168 234.8 168 248v118.1l-39.03-39.03C124.3 322.3 118.2 320 112 320s-12.28 2.344-16.97 7.031c-9.375 9.375-9.375 24.56 0 33.94l80 80c9.375 9.375 24.56 9.375 33.94 0l80-80c9.375-9.375 9.375-24.56 0-33.94S264.4 317.7 255 327z"]],
"file-arrow-up": [384, 512, ["file-upload"], "f574", ["M256 128V0H48C21.49 0 0 21.49 0 48v416C0 490.5 21.49 512 48 512h288c26.51 0 48-21.49 48-48V128H256zM288.1 344.1C284.3 349.7 278.2 352 272 352s-12.28-2.344-16.97-7.031L216 305.9V424c0 13.25-10.75 24-24 24s-24-10.75-24-24V305.9l-39.03 39.03c-9.375 9.375-24.56 9.375-33.94 0s-9.375-24.56 0-33.94l80-80c9.375-9.375 24.56-9.375 33.94 0l80 80C298.3 320.4 298.3 335.6 288.1 344.1z", "M256 0v128h128L256 0zM208.1 231c-9.375-9.375-24.56-9.375-33.94 0l-80 80c-9.375 9.375-9.375 24.56 0 33.94s24.56 9.375 33.94 0L168 305.9V424C168 437.3 178.8 448 192 448s24-10.75 24-24V305.9l39.03 39.03C259.7 349.7 265.8 352 272 352s12.28-2.344 16.97-7.031c9.375-9.375 9.375-24.56 0-33.94L208.1 231z"]],
"list": [512, 512, [], "f03a", "M128 116V76c0-8.837 7.163-16 16-16h352c8.837 0 16 7.163 16 16v40c0 8.837-7.163 16-16 16H144c-8.837 0-16-7.163-16-16zm16 176h352c8.837 0 16-7.163 16-16v-40c0-8.837-7.163-16-16-16H144c-8.837 0-16 7.163-16 16v40c0 8.837 7.163 16 16 16zm0 160h352c8.837 0 16-7.163 16-16v-40c0-8.837-7.163-16-16-16H144c-8.837 0-16 7.163-16 16v40c0 8.837 7.163 16 16 16zM16 144h64c8.837 0 16-7.163 16-16V64c0-8.837-7.163-16-16-16H16C7.163 48 0 55.163 0 64v64c0 8.837 7.163 16 16 16zm0 160h64c8.837 0 16-7.163 16-16v-64c0-8.837-7.163-16-16-16H16c-8.837 0-16 7.163-16 16v64c0 8.837 7.163 16 16 16zm0 160h64c8.837 0 16-7.163 16-16v-64c0-8.837-7.163-16-16-16H16c-8.837 0-16 7.163-16 16v64c0 8.837 7.163 16 16 16z"],
"pencil": [512, 512, [], "f040", "M497.9 142.1l-46.1 46.1c-4.7 4.7-12.3 4.7-17 0l-111-111c-4.7-4.7-4.7-12.3 0-17l46.1-46.1c18.7-18.7 49.1-18.7 67.9 0l60.1 60.1c18.8 18.7 18.8 49.1 0 67.9zM284.2 99.8L21.6 362.4.4 483.9c-2.9 16.4 11.4 30.6 27.8 27.8l121.5-21.3 262.6-262.6c4.7-4.7 4.7-12.3 0-17l-111-111c-4.8-4.7-12.4-4.7-17.1 0zM88 424h48v36.3l-64.5 11.3-31.1-31.1L51.7 376H88v48z"],
"plus": [448, 512, [], "f067", "M416 208H272V64c0-17.67-14.33-32-32-32h-32c-17.67 0-32 14.33-32 32v144H32c-17.67 0-32 14.33-32 32v32c0 17.67 14.33 32 32 32h144v144c0 17.67 14.33 32 32 32h32c17.67 0 32-14.33 32-32V304h144c17.67 0 32-14.33 32-32v-32c0-17.67-14.33-32-32-32z"],

View File

@@ -1,4 +1,4 @@
{
"/css/app.css": "/css/app.css?id=ad45b1705b7f7906db0b",
"/js/app.js": "/js/app.js?id=5446aeb4aa754e641c77"
"/css/app.css": "/css/app.css?id=910562b0b11f9731ff1cdded5e57f7b5",
"/js/app.js": "/js/app.js?id=86f896ef6c2066036a4e2b946e07750d"
}

View File

@@ -34,7 +34,7 @@ Supported applications are recognized by the title of the application as entered
[![foundationapps](https://img.shields.io/badge/dynamic/json.svg?label=Foundation%20Apps&url=https%3A%2F%2Fapps.heimdall.site%2Fstats&query=foundation_apps&colorB=3f8483&style=for-the-badge&logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABwAAAAjCAMAAACw/5reAAAAnFBMVEUAAADu7u7u7u7u7u7u7u7x8fHu7u7u7u7u7u7u7u7u7u7u7u7r6+vu7u7v7+/u7u7t7e3v7+/v7+/u7u7u7u7u7u7u7u7u7u7u7u7u7u7v7+/u7u7p6ent7e3v7+/v7+/v7+/u7u7u7u7u7u7u7u7t7e3////u7u7u7u7u7u7u7u7w8PDw8PDt7e3u7u7t7e3s7Ozu7u7t7e3u7u4TnCP6AAAAM3RSTlMA+9n3phHw3czC088M5Y5zG6mflWdJFumyfj4sB2NeTi7hiWlDOQPGt5lsMiG9hFQntpFqxQJtAAABnElEQVQoz2WRh3KrQAxFtYWO6ZhucItrynv6/3/LFnA24c6wurpnYBkJZvXduNix6+GXTo8qWnxUPU4m2w0O1ktTozPsftiZpejGlm7C2MWUnRcWOohIo36+PaKyDZdLUOgDXvqQfaT9kwkfvP3AN18E7Kl8hkJHMHSXSSadxaTtTNjJhMkfjFHKMqGlolg4T7mtCbcq8gBCotxkwklFLIQSlQoTHnVWQqzNxYQuzpfmqGVMc5ijHK5yAuIhxbZ5p/S92RZkjv5BKs6aosSIr0JrcXBo1FtICVINKRKK6u0GnraoN84O5KbhjRwYzxCJnQCMtotkdNxjq2F7dJ2RoGuXIBTvc3ROthdmat6hZ7cOyfcxKGV+wTxBkxQxTQTzWOFny/7qS2nzx37T7nbtZj9xu7zUr/323nVy0sQnhwMJktSZrl5v7CjgSQmWi+haUCY8sH4tyc/FGSKGouS+WqBJm8U2NIE/+nLu2tzpF/xVNGy02QzRClafC/ysVpDzQJuA8xXsKl8bv+pgpXz57H9Yy3J1lQNY62wUrW+mdzrylWS0QwAAAABJRU5ErkJggg==)](https://apps.heimdall.site/applications/foundation)
## Installing
Apart from the Laravel dependencies, namely PHP >= 7.2.5, BCMath PHP Extension, Ctype PHP Extension, Fileinfo PHP extension, JSON PHP Extension, Mbstring PHP Extension, OpenSSL PHP Extension, PDO PHP Extension, Tokenizer PHP Extension, XML PHP Extension, the only other thing Heimdall needs is sqlite support and zip support (php-zip).
Apart from the Laravel 8 dependencies, namely PHP >= 7.4.32, BCMath PHP Extension, INTL PHP Extension, Ctype PHP Extension, Fileinfo PHP extension, JSON PHP Extension, Mbstring PHP Extension, OpenSSL PHP Extension, PDO PHP Extension, Tokenizer PHP Extension, XML PHP Extension, the only other thing Heimdall needs is sqlite support and zip support (php-zip).
If you find you can't change the background make sure `php_fileinfo` is enabled in your php.ini. I believe it should be by default, but one user came across the issue on a windows system.
@@ -83,15 +83,27 @@ When you are finished, create a pull request.
Currently added languages are
- Breton
- Chinese
- Danish
- Dutch
- English
- German
- Finnish
- French
- Swedish
- Spanish
- Turkish
- German
- Greek
- Hungarian
- Italian
- Korean
- Lombard
- Norwegian
- Polish
- Portuguese
- Russian
- Chinese
- Slovenian
- Spanish
- Swedish
- Turkish
## Web Server Configuration
@@ -170,6 +182,14 @@ 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.
## Running offline
The apps list is hosted on github, you have a couple of options if you want to run without a connection to the outside world:
1) Clone the repository and host it yourself, look at the .github actions file to see how to generate the apps list.
2) Download the apps list and store it as a json accessible to heimdall named `list.json`
With both options all you need to do is add the following to your `.env`
`APP_SOURCE=http://localhost/` Where `http://localhost/` is the path to the apps list without the name of the file, so if your file is stored at `https://heimdall.local/list.json` you would put `APP_SOURCE=https://heimdall.local/`
## Support
https://discord.gg/CCjHKn4 or through GitHub issues

View File

@@ -1,103 +1,40 @@
$.when( $.ready ).then(function() {
$.when($.ready).then(() => {
const base = (document.querySelector("base") || {}).href;
var base = (document.querySelector('base') || {}).href;
const itemID = $("form[data-item-id]").data("item-id");
const fakePassword = "*****";
if($('.message-container').length) {
setTimeout(
function()
{
$('.message-container').fadeOut();
}, 3500);
// If in edit mode and password field is present, fill it with stars
if (itemID) {
const passwordField = $('input[name="config[password]"]').first();
if (passwordField.length > 0) {
passwordField.attr("value", fakePassword);
}
}
// from https://developer.mozilla.org/en-US/docs/Web/API/Page_Visibility_API
// Set the name of the hidden property and the change event for visibility
var hidden, visibilityChange;
if (typeof document.hidden !== "undefined") { // Opera 12.10 and Firefox 18 and later support
hidden = "hidden";
visibilityChange = "visibilitychange";
} else if (typeof document.msHidden !== "undefined") {
hidden = "msHidden";
visibilityChange = "msvisibilitychange";
} else if (typeof document.webkitHidden !== "undefined") {
hidden = "webkitHidden";
visibilityChange = "webkitvisibilitychange";
if ($(".message-container").length) {
setTimeout(() => {
$(".message-container").fadeOut();
}, 3500);
}
function readURL(input) {
if (input.files && input.files[0]) {
const reader = new FileReader();
reader.onload = function (e) {
$("#appimage img").attr("src", e.target.result);
};
reader.readAsDataURL(input.files[0]);
}
}
var livestatsRefreshTimeouts = [];
var livestatsFuncs = [];
var livestatsContainers = $('.livestats-container');
function stopLivestatsRefresh() {
for (var timeoutId of livestatsRefreshTimeouts) {
window.clearTimeout(timeoutId);
}
}
function startLivestatsRefresh() {
for (var fun of livestatsFuncs) {
fun();
}
}
if (livestatsContainers.length > 0) {
if (typeof document.addEventListener === "undefined" || hidden === undefined) {
console.log("This browser does not support visibilityChange");
} else {
document.addEventListener(visibilityChange, function() {
if (document[hidden]) {
stopLivestatsRefresh();
} else {
startLivestatsRefresh();
}
}, false);
}
livestatsContainers.each(function(index){
var id = $(this).data('id');
var dataonly = $(this).data('dataonly');
var increaseby = (dataonly == 1) ? 20000 : 1000;
var container = $(this);
var max_timer = 30000;
var timer = 5000;
var fun = function worker() {
$.ajax({
url: base+'get_stats/'+id,
dataType: 'json',
success: function(data) {
container.html(data.html);
if(data.status == 'active') timer = increaseby;
else {
if(timer < max_timer) timer += 2000;
}
},
complete: function() {
// Schedule the next request when the current one's complete
livestatsRefreshTimeouts[index] = window.setTimeout(worker, timer);
}
});
};
livestatsFuncs[index] = fun;
fun();
});
}
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({
$("#upload").change(function () {
readURL(this);
});
/* $(".droppable").droppable({
tolerance: "intersect",
drop: function( event, ui ) {
var tag = $( this ).data('id');
@@ -112,126 +49,160 @@ $.when( $.ready ).then(function() {
});
}
});*/
}); */
$( '#sortable' ).sortable({
stop: function (event, ui) {
var idsInOrder = $('#sortable').sortable('toArray', {
attribute: 'data-id'
});
$.post(
base+'order',
{ order:idsInOrder }
);
}
$("#sortable").sortable({
stop() {
const idsInOrder = $("#sortable").sortable("toArray", {
attribute: "data-id",
});
$.post(`${base}order`, { order: idsInOrder });
},
});
$("#sortable").sortable("disable");
});
$('#sortable').sortable('disable');
$('#sortable').on('mouseenter', '.item', function () {
$(this).siblings('.tooltip').addClass('active')
$('.refresh', this).addClass('active')
}).on('mouseleave', '.item', function () {
$(this).siblings('.tooltip').removeClass('active')
$('.refresh', this).removeClass('active')
$("#main")
.on("mouseenter", "#sortable.ui-sortable-disabled .item", function () {
$(this).siblings(".tooltip").addClass("active");
$(".refresh", this).addClass("active");
})
$('#search-container').on('input', 'input[name=q]', function () {
const search = this.value
const items = $('#sortable').children('.item-container')
if($('#search-container select[name=provider]').val() === 'tiles') {
if(search.length > 0) {
items.hide()
items.filter(function () {
const name = $(this).data('name').toLowerCase();
return name.includes(search.toLowerCase())
}).show()
} else {
items.show()
}
} else {
items.show()
}
}).on('change', 'select[name=provider]', function () {
const items = $('#sortable').children('.item-container')
if($(this).val() === 'tiles') {
$('#search-container button').hide()
const search = $('#search-container input[name=q]').val()
if(search.length > 0) {
items.hide()
items.filter(function () {
const name = $(this).data('name').toLowerCase();
return name.includes(search.toLowerCase())
}).show()
} else {
items.show()
}
} else {
$('#search-container button').show()
items.show()
}
.on("mouseleave", ".item", function () {
$(this).siblings(".tooltip").removeClass("active");
$(".refresh", this).removeClass("active");
});
$("#config-buttons")
.on("mouseenter", "a", function () {
$(".tooltip", this).addClass("active");
})
.on("mouseleave", "a", function () {
$(".tooltip", this).removeClass("active");
});
$('#app').on('click', '#config-button', function(e) {
e.preventDefault();
var app = $('#app');
var active = (app.hasClass('header'));
app.toggleClass('header');
if(active) {
$('.add-item').hide();
$('.item-edit').hide();
$('#app').removeClass('sidebar');
$('#sortable').sortable('disable');
$(".searchform > form").on("submit", (event) => {
if ($("#search-container select[name=provider]").val() === "tiles") {
event.preventDefault();
}
});
$("#search-container")
.on("input", "input[name=q]", function () {
const search = this.value;
const items = $("#sortable").children(".item-container");
if ($("#search-container select[name=provider]").val() === "tiles") {
if (search.length > 0) {
items.hide();
items
.filter(function () {
const name = $(this).data("name").toLowerCase();
return name.includes(search.toLowerCase());
})
.show();
} else {
$('#sortable').sortable('enable');
setTimeout(function() {
$('.add-item').fadeIn();
$('.item-edit').fadeIn();
}, 350);
items.show();
}
}).on('click', '#add-item, #pin-item', function(e) {
e.preventDefault();
var app = $('#app');
var active = (app.hasClass('sidebar'));
app.toggleClass('sidebar');
}).on('click', '.close-sidenav', function(e) {
e.preventDefault();
var app = $('#app');
app.removeClass('sidebar');
}).on('click', '#test_config', function(e) {
e.preventDefault();
var apiurl = $('#create input[name=url]').val();
var override_url = $('#sapconfig input[name="config[override_url]"]').val();
if(override_url.length && override_url != '') {
apiurl = override_url;
} else {
items.show();
}
})
.on("change", "select[name=provider]", function () {
const items = $("#sortable").children(".item-container");
if ($(this).val() === "tiles") {
$("#search-container button").hide();
const search = $("#search-container input[name=q]").val();
if (search.length > 0) {
items.hide();
items
.filter(function () {
const name = $(this).data("name").toLowerCase();
return name.includes(search.toLowerCase());
})
.show();
} else {
items.show();
}
var data = {};
data['url'] = apiurl;
$('.config-item').each(function(index){
var config = $(this).data('config');
data[config] = $(this).val();
});
$.post(base+'test_config', { data: data }, function(data) {
alert(data);
});
});
$('#pinlist').on('click', 'a', function(e) {
e.preventDefault();
var current = $(this);
var id = current.data('id');
var tag = current.data('tag');
$.get(base+'items/pintoggle/'+id+'/true/'+tag, function(data) {
var inner = $(data).filter('#sortable').html();
$('#sortable').html(inner);
current.toggleClass('active');
});
} else {
$("#search-container button").show();
items.show();
}
});
$("#app")
.on("click", "#config-button", (e) => {
e.preventDefault();
const app = $("#app");
const active = app.hasClass("header");
app.toggleClass("header");
if (active) {
$(".add-item").hide();
$(".item-edit").hide();
$("#app").removeClass("sidebar");
$("#sortable .tooltip").css("display", "");
$("#sortable").sortable("disable");
} else {
$("#sortable .tooltip").css("display", "none");
$("#sortable").sortable("enable");
setTimeout(() => {
$(".add-item").fadeIn();
$(".item-edit").fadeIn();
}, 350);
}
})
.on("click", "#add-item, #pin-item", (e) => {
e.preventDefault();
const app = $("#app");
// const active = app.hasClass("sidebar");
app.toggleClass("sidebar");
})
.on("click", ".close-sidenav", (e) => {
e.preventDefault();
const app = $("#app");
app.removeClass("sidebar");
})
.on("click", "#test_config", (e) => {
e.preventDefault();
let apiurl = $("#create input[name=url]").val();
const overrideUrl = $(
'#sapconfig input[name="config[override_url]"]'
).val();
if (overrideUrl.length && overrideUrl !== "") {
apiurl = overrideUrl;
}
const data = {};
data.url = apiurl;
$(".config-item").each(function () {
const config = $(this).data("config");
data[config] = $(this).val();
});
data.id = $("form[data-item-id]").data("item-id");
if (data.password && data.password === fakePassword) {
data.password = "";
}
$.post(`${base}test_config`, { data }, (responseData) => {
alert(responseData);
});
});
$("#pinlist").on("click", "a", function (e) {
e.preventDefault();
const current = $(this);
const id = current.data("id");
const tag = current.data("tag");
$.get(`${base}items/pintoggle/${id}/true/${tag}`, (data) => {
const inner = $(data).filter("#sortable").html();
$("#sortable").html(inner);
current.toggleClass("active");
});
});
$("#itemform").on("submit", () => {
const passwordField = $('input[name="config[password]"]').first();
if (passwordField.length > 0) {
if (passwordField.attr("value") === fakePassword) {
passwordField.attr("value", "");
}
}
});
});

48
resources/assets/js/itemExport.js vendored Normal file
View File

@@ -0,0 +1,48 @@
const EXPORT_FILE_NAME = "HeimdallExport.json";
const EXPORT_API_URL = "api/item";
/**
*
* @param {string} fileName
* @param {string} data
*/
function triggerFileDownload(fileName, data) {
const a = document.createElement("a");
const file = new Blob([data], {
type: "text/plain",
});
a.href = URL.createObjectURL(file);
a.download = EXPORT_FILE_NAME;
a.click();
}
/**
*
* @param {Event} event
*/
const exportItems = (event) => {
event.preventDefault();
fetch(EXPORT_API_URL)
.then((response) => {
if (response.status !== 200) {
window.alert("An error occurred while exporting...");
}
return response.json();
})
.then((data) => {
const exportedJson = JSON.stringify(data, null, 2);
triggerFileDownload(EXPORT_FILE_NAME, exportedJson);
});
};
const exportButton = document.querySelector("#item-export");
if (exportButton) {
exportButton.addEventListener("click", exportItems);
}

176
resources/assets/js/itemImport.js vendored Normal file
View File

@@ -0,0 +1,176 @@
const IMPORT_API_URL = "api/item";
const APP_LOAD_URL = "appload";
/**
*
* @param {object} item
* @param {array} errors
*/
const updateStatus = ({ item, errors }) => {
console.log(item, errors);
let statusLine;
if (errors.length === 0) {
statusLine = `<li class="success"><i class="fas fa-circle-check"></i> Imported: ${item.title} </li>`;
} else {
statusLine = `<li class="fail"><i class="fas fa-circle-xmark"></i> Failed: ${item.title} - ${errors[0]} </li>`;
}
document.querySelector(".import-status").innerHTML += statusLine;
};
/**
*
*/
function clearStatus() {
const statusContainer = document.querySelector(".import-status");
statusContainer.innerHTML = "";
}
/**
*
* @param {object} data
* @param {string} csrfToken
*/
const postToApi = (data, csrfToken) =>
fetch(IMPORT_API_URL, {
method: "POST",
cache: "no-cache",
redirect: "follow",
headers: {
"Content-Type": "application/json",
"X-CSRF-TOKEN": csrfToken,
},
body: JSON.stringify(data),
});
/**
*
* @returns {string}
*/
const getCSRFToken = () => {
const tokenSelector = 'input[name="_token"]';
return document.querySelector(tokenSelector).value;
};
/**
*
* @param {object} item
* @param {object} appDetails
* @returns {object}
*/
const mergeItemWithAppDetails = (item, appDetails) => ({
pinned: 1,
tags: [0],
appid: item.appid,
title: item.title,
colour: item.colour,
url: item.url,
appdescription: item.appdescription
? item.appdescription
: appDetails.description,
website: appDetails.website,
icon: appDetails.iconview,
config: item.description ? JSON.parse(item.description) : null,
});
/**
*
* @param {string|null} appId
* @returns {Promise<{}>|Promise<any>}
*/
const fetchAppDetails = (appId) => {
if (appId === null || appId === "null") {
return Promise.resolve({});
}
return fetch(APP_LOAD_URL, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ app: appId }),
}).then((response) => response.json());
};
/**
*
* @param {array} items
*/
const importItems = (items) => {
items.forEach((item) => {
const errors = [];
fetchAppDetails(item.appid)
.catch(() =>
errors.push(new Error(`Failed to find app id: ${item.appid}`))
)
.then((appDetails) => {
const itemWithAppDetails = mergeItemWithAppDetails(item, appDetails);
const csrfToken = getCSRFToken();
return postToApi(itemWithAppDetails, csrfToken);
})
.catch(() =>
errors.push(new Error(`Failed to create item: ${item.title}`))
)
.finally(() => {
updateStatus({
item,
errors,
});
});
});
};
/**
*
* @param {Blob} file
* @returns {Promise<unknown>}
*/
const readJSON = (file) =>
new Promise((resolve, reject) => {
try {
const reader = new FileReader();
reader.onload = (event) => {
const contents = event.target.result;
resolve(JSON.parse(contents));
};
reader.readAsText(file);
} catch (e) {
reject(new Error("Unable to read file"));
}
});
/**
*
* @param {Event} event
*/
const openFileForImport = (file) => {
clearStatus();
return readJSON(file)
.catch((error) => {
console.error(error);
})
.then(importItems);
};
const fileInput = document.querySelector("input[name='import']");
const importButton = document.querySelectorAll(".import-button");
if (fileInput && importButton) {
importButton.forEach((importButton) => {
importButton.addEventListener("click", () => {
const file = fileInput.files[0];
if (!file) {
return;
}
openFileForImport(file);
});
});
fileInput.addEventListener("change", openFileForImport, false);
}

45
resources/assets/js/keyBindings.js vendored Normal file
View File

@@ -0,0 +1,45 @@
const focusSearch = (event) => {
const searchInput = document.querySelector('input[name="q"]');
if (searchInput) {
event.preventDefault();
searchInput.focus();
}
};
const openFirstNonHiddenItem = (event) => {
if (event.target !== document.querySelector('input[name="q"]')) {
return;
}
const providerSelect = document.querySelector(
"#search-container select[name=provider]"
);
if (providerSelect.value !== "tiles") {
return;
}
const item = document.querySelector(
'#sortable section.item-container:not([style="display: none;"]) a'
);
if ("href" in item) {
event.preventDefault();
window.open(item.href);
}
};
const KEY_BINDINGS = {
"/": focusSearch,
Enter: openFirstNonHiddenItem,
};
document.addEventListener("keydown", (event) => {
try {
if (event.key in KEY_BINDINGS) {
KEY_BINDINGS[event.key](event);
}
} catch (e) {
// Nothing to do
}
});

100
resources/assets/js/liveStatRefresh.js vendored Normal file
View File

@@ -0,0 +1,100 @@
const REFRESH_INTERVAL_SMALL = 5000;
const REFRESH_INTERVAL_BIG = 30000;
const QUEUE_PROCESSING_INTERVAL = 1000;
const CONTAINER_SELECTOR = ".livestats-container";
/**
* @returns {*[]}
*/
function createQueue() {
const queue = [];
let suspended = false;
function processQueue() {
if (queue.length === 0 || suspended === true) {
return;
}
const next = queue.shift();
next();
}
document.addEventListener("visibilitychange", () => {
suspended = document.hidden;
});
setInterval(processQueue, QUEUE_PROCESSING_INTERVAL);
return queue;
}
/**
* @returns {NodeListOf<Element>}
*/
function getContainers() {
return document.querySelectorAll(CONTAINER_SELECTOR);
}
/**
*
* @param {boolean} dataOnly
* @param {boolean} active
* @returns {number}
*/
function getQueueInterval(dataOnly, active) {
if (dataOnly) {
return REFRESH_INTERVAL_BIG;
}
if (active) {
return REFRESH_INTERVAL_SMALL;
}
return REFRESH_INTERVAL_BIG;
}
/**
* @param {HTMLElement} container
* @param {array} queue
* @returns {function(): Promise<Response>}
*/
function createUpdateJob(container, queue) {
const id = container.getAttribute("data-id");
// Data only attribute seems to indicate that the item should not be updated that often
const isDataOnly = container.getAttribute("data-dataonly") === "1";
return () =>
fetch(`get_stats/${id}`)
.then((response) => {
if (response.ok) {
return response.json();
}
throw new Error(`Network response was not ok: ${response.status}`);
})
.then((data) => {
// eslint-disable-next-line no-param-reassign
container.innerHTML = data.html;
const isActive = data.status === "active";
if (queue) {
setTimeout(() => {
queue.push(createUpdateJob(container, queue));
}, getQueueInterval(isDataOnly, isActive));
}
})
.catch((error) => {
console.error(error);
});
}
const livestatContainers = getContainers();
if (livestatContainers.length > 0) {
const myQueue = createQueue();
livestatContainers.forEach((container) => {
createUpdateJob(container, myQueue)();
});
}

View File

@@ -191,15 +191,31 @@ body {
width: 50px;
height: 50px;
background: rgba(0,0,0,0.8);
text-align: center;
line-height: 50px;
color: white;
margin-top: 1px;
position: relative;
border: 1px solid transparent;
display: flex;
justify-content: center;
align-items: center;
img {
width: 26px;
height: 26px;
margin-top: 12px;
}
.tooltip {
bottom: 50%;
left: auto;
right: 55px;
padding: 10px 15px;
line-height: 1.2;
transform: translate(200px, 50%);
white-space: nowrap;
&.active {
transform: translate(0, 50%);
}
}
}
}
@@ -262,29 +278,29 @@ body {
display: none;
z-index: 1;
}
.tooltip {
padding: 25px;
border-radius: 5px;
background: #000000c8;
color: white;
position: absolute;
bottom: 120px;
left: 0;
right: 0;
font-size: 13px;
backdrop-filter: blur(8px);
z-index: 0;
opacity: 0;
transform: translateY(-20px);
transition: all 0.3s;
&.active {
transform: translateY(0);
opacity: 1;
z-index: 4;
}
}
.tooltip {
padding: 25px;
border-radius: 5px;
background: #000000c8;
color: white;
position: absolute;
bottom: 120px;
left: 0;
right: 0;
font-size: 13px;
backdrop-filter: blur(8px);
z-index: 0;
opacity: 0;
transform: translateY(-20px);
transition: all 0.3s;
&.active {
transform: translateY(0);
opacity: 1;
z-index: 4;
}
}
.tile-actions {
position: absolute;
top: 0px;
@@ -1108,3 +1124,39 @@ select:-webkit-autofill:focus {
transition: inherit;
color: $app-text!important;
}
#sortable:focus-within {
.item:focus-within {
outline: 1px solid #ffffff91;
}
.item:not(:focus-within) {
opacity: 0.4;
}
}
#config-buttons:focus-within {
a:focus {
outline: 0;
border: 1px solid #ffffff91;
}
a:not(:focus-within) {
opacity: 0.4;
}
}
.import-status {
list-style: none;
li {
display: flex;
align-items: center;
margin: 6px 0;
svg {
margin-right: 8px;
}
&.success svg {
color: $app-green;
}
&.fail svg {
color: $app-red;
}
}
}

View File

@@ -9,7 +9,7 @@
@import "normalise";
// Bootstrap
@import "app";
@import "_app";
@import "rune";
// Huebee

106
resources/lang/cs/app.php Normal file
View File

@@ -0,0 +1,106 @@
<?php
return array (
'settings.system' => 'Systém',
'settings.appearance' => 'Vzhled',
'settings.miscellaneous' => 'Různé',
'settings.advanced' => 'Rozšířené nastavení',
'settings.support' => 'Podpora',
'settings.donate' => 'Podpořte nás',
'settings.version' => 'Verze',
'settings.background_image' => 'Obrázek pozadí',
'settings.window_target' => 'Odkazy otevírat v',
'settings.window_target.current' => 'Otevřít v této záložce',
'settings.window_target.one' => 'Otevřít ve stejné záložce',
'settings.window_target.new' => 'Otevřít v nové záložce',
'settings.homepage_search' => 'Vyhledávání na domovské stránce',
'settings.search_provider' => 'Vyhledávat pomocí',
'settings.language' => 'Jazyk',
'settings.reset' => 'Obnovit výchozí nastavení',
'settings.remove' => 'Odstranit',
'settings.search' => 'hledat',
'settings.no_items' => 'Žadné položky nenalezeny',
'settings.label' => 'Název',
'settings.value' => 'Hodnota',
'settings.edit' => 'Upravit',
'settings.view' => 'Náhled',
'settings.custom_css' => 'Vlastní CSS',
'settings.custom_js' => 'Vlastní JavaScript',
'options.none' => '- nenastaveno -',
'options.google' => 'Google',
'options.ddg' => 'DuckDuckGo',
'options.bing' => 'Bing',
'options.qwant' => 'Qwant',
'options.startpage' => 'StartPage',
'options.yes' => 'Ano',
'options.no' => 'Ne',
'options.nzbhydra' => 'NZBHydra',
'options.jackett' => 'Jackett',
'buttons.save' => 'Uložit',
'buttons.cancel' => 'Zrušit',
'buttons.add' => 'Přidat',
'buttons.upload' => 'Nahrát ikonu',
'buttons.downloadapps' => 'Aktualizovat seznam aplikací',
'dash.pin_item' => 'Připnout na dashboard',
'dash.no_apps' => 'Aktuálně nemáte žádné připnuté aplikace, :link1 nebo :link2',
'dash.link1' => 'Přidejte zde aplikacei',
'dash.link2' => 'Připnout na dashboard',
'dash.pinned_items' => 'Připnuté položky',
'apps.app_list' => 'Seznam aplikací',
'apps.view_trash' => 'Zobrazit koš',
'apps.add_application' => 'Přidat aplikaci',
'apps.application_name' => 'Název aplikace',
'apps.colour' => 'Barva',
'apps.icon' => 'Ikona',
'apps.pinned' => 'Připnuto',
'apps.title' => 'Název',
'apps.hex' => 'Hex barva',
'apps.username' => 'Uživatelské jméno',
'apps.password' => 'Heslo',
'apps.config' => 'Config',
'apps.apikey' => 'API Klíč',
'apps.enable' => 'Povolit',
'apps.tag_list' => 'Seznam tagů',
'apps.add_tag' => 'Přidat tag',
'apps.tag_name' => 'Název tagu',
'apps.tags' => 'Tagy',
'apps.override' => 'Pokud je různá od hlavní url',
'apps.preview' => 'Náhled',
'apps.apptype' => 'Typ apliakce',
'apps.website' => 'Webová stránka',
'apps.description' => 'Popis',
'apps.only_admin_account' => 'Pouze pokud máte administrátorský účet!',
'apps.autologin_url' => 'URL automatického přihlášení',
'apps.show_deleted' => 'Zobrazit smazané aplikace',
'dashboard' => 'Domácí obrazovka',
'user.user_list' => 'Uživatelé',
'user.add_user' => 'Přidat uživatele',
'user.username' => 'Uživatelské jméno',
'user.avatar' => 'Avatar',
'user.email' => 'Email',
'user.password_confirm' => 'Potvrdit heslo',
'user.secure_front' => 'Povolit veřejný přístup k rozhraní - Nastavte pouze pokud je nastaveno heslo.',
'user.autologin' => 'Povolit přihlášení ze specifické URL. Kdokoliv s odkazem se může přihlásit.',
'url' => 'URL',
'title' => 'Název',
'delete' => 'Smazat',
'optional' => 'Volitelné',
'restore' => 'Obnovit',
'alert.success.item_created' => 'Položka úspěšně vytvořena',
'alert.success.item_updated' => 'Položka úspěšně aktualizována',
'alert.success.item_deleted' => 'Položka úspěšně smazána',
'alert.success.item_restored' => 'Položka úspěšně obnovena',
'alert.success.updating' => 'Aktualizuji seznam aplikací',
'alert.success.tag_created' => 'Tag úspěšně vytvořen',
'alert.success.tag_updated' => 'Tag úspěšně aktualizován',
'alert.success.tag_deleted' => 'Tag úspěšně smazán',
'alert.success.tag_restored' => 'Tag úspěšně obnoven',
'alert.success.setting_updated' => 'Úspěšně jste aktualizovali nastavení',
'alert.error.not_exist' => 'Tohle nastavení neexistuje.',
'alert.success.user_created' => 'Uživatel úspěšně vytovřen',
'alert.success.user_updated' => 'Uživatel úspěšně aktualizován',
'alert.success.user_deleted' => 'Uživatel úspěšně smazán',
'alert.success.user_restored' => 'Uživatel úspěšně obnoven',
'dashboard.reorder' => 'Změňte pořadí a připněte položky',
'dashboard.settings' => 'Nastavení',
);

View File

@@ -0,0 +1,6 @@
<?php
return array (
'failed' => 'Zadané údaje se neshodují s našimi záznamy.',
'throttle' => 'Příliš mnoho pokusů o přihlášení. Prosím opakujte za :seconds sekund.',
);

View File

@@ -0,0 +1,6 @@
<?php
return array (
'previous' => '&laquo; Předchozí',
'next' => 'Další &raquo;',
);

View File

@@ -0,0 +1,9 @@
<?php
return array (
'password' => 'Heslo musí mít alespoň šest znaků a musí se shodovat s potvrzením.',
'reset' => 'Vaše heslo bylo úspěšně resetováno!',
'sent' => 'Odeslali jsme vám emailem odkaz pro reset hesla!',
'token' => 'Token pro obnovu hesla je neplatný.',
'user' => 'Nenalezli jsme uživatele se zadaným e-mailem.',
);

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 musí být přijat.',
'active_url' => ':attribute není platná URL.',
'after' => ':attribute musí být datum po :date.',
'after_or_equal' => ':attribute musí být datum po nebo rovno :date.',
'alpha' => ':attribute může obsahovat pouze písmena.',
'alpha_dash' => ':attribute může obsahovat pouze písmena, čísla a pomlčku.',
'alpha_num' => ':attribute může obsahovat pouze písmena a čísla.',
'array' => ':attribute musí být pole.',
'before' => ':attribute musí být datum před :date.',
'before_or_equal' => ':attribute musí být datum před nebo rovno :date.',
'between' => [
'numeric' => ':attribute musí být mezi :min a :max.',
'file' => ':attribute musí být mezi :min a :max kilobyty.',
'string' => ':attribute musí mít mezi :min a :max znaky.',
'array' => ':attribute musí mít mezi :min a :max položkami.',
],
'boolean' => ':attribute může být true nebo false.',
'confirmed' => ':attribute potvrzení se neshoduje.',
'date' => ':attribute není platné datum.',
'date_format' => ':attribute neodpovídá formátu :format.',
'different' => ':attribute a :other se musí lišit.',
'digits' => ':attribute musí být :digits číslo.',
'digits_between' => ':attribute must be between :min and :max digits.',
'dimensions' => ':attribute má neplatné rozměry.',
'distinct' => ':attribute položka obsahuje duplicitní hodnoty.',
'email' => ':attribute musí být platná emailová adresa.',
'exists' => 'Vybraný :attribute je neplatný.',
'file' => ':attribute musí být soubor.',
'filled' => ':attribute položka musí mít hodnotu.',
'image' => ':attribute musí být obrázek.',
'in' => 'Vybraný :attribute je neplatný.',
'in_array' => ':attribute položka neexistuje v :other.',
'integer' => ':attribute musí být celočíselný.',
'ip' => ':attribute musí být platná IP adresa.',
'ipv4' => ':attribute musí být platná IPv4 adresa.',
'ipv6' => ':attribute musí být platná IPv6 adresa.',
'json' => ':attribute musí být validní JSON řetězec.',
'max' => [
'numeric' => ':attribute nemůže být větší než :max.',
'file' => ':attribute nemůže být větší než :max kilobytů.',
'string' => ':attribute nemůže být větší než :max znaků.',
'array' => ':attribute nemsí mít více než :max položek.',
],
'mimes' => ':attribute musí být soubor typu: :values.',
'mimetypes' => ':attribute musí být soubor typu: :values.',
'min' => [
'numeric' => ':attribute musí být nejméně :min.',
'file' => ':attribute musí mít nejméně :min kilobytů.',
'string' => ':attribute musí mít alespoň :min znaků.',
'array' => ':attribute musí mít nejméně :min položek.',
],
'not_in' => 'Vybraný :attribute je neplatný.',
'numeric' => ':attribute musí být číslo.',
'present' => ':attribute musí být přitomná.',
'regex' => ':attribute formát je neplatný.',
'required' => ':attribute je povinná.',
'required_if' => ':attribute je poviná pokud :other je :value.',
'required_unless' => ':attribute je poviná pokud :other je v :values.',
'required_with' => ':attribute je poviná pokud :values je přítomna.',
'required_with_all' => ':attribute je poviná pokud :values je přítomna.',
'required_without' => ':attribute je poviná pokud :values není přítomna.',
'required_without_all' => ':attribute je poviná pokud žádná z :values není přítomná.',
'same' => ':attribute a :other musí být stejné.',
'size' => [
'numeric' => ':attribute musí být :size.',
'file' => ':attribute musí být :size kilobytes.',
'string' => ':attribute musí být :size characters.',
'array' => ':attribute musí obsahovat :size items.',
],
'string' => ':attribute musí být řetězec.',
'timezone' => ':attribute musí být pltná časová zóna.',
'unique' => ':attribute musí být unikátní.',
'uploaded' => ':attribute se nepodařilo nahrát.',
'url' => ':attribute formát je neplatný.',
/*
|--------------------------------------------------------------------------
| 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' => [],
];

View File

@@ -1,118 +1,106 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| App Language Lines
|--------------------------------------------------------------------------
|
*/
'settings.system' => 'System',
'settings.appearance' => 'Appearance',
'settings.miscellaneous' => 'Miscellaneous',
'settings.support' => 'Support',
'settings.donate' => 'Doner',
'settings.version' => 'Version',
'settings.background_image' => 'Baggrundsbillede',
'settings.window_target' => 'Link opens in',
'settings.window_target.current' => 'Åbn i denne fane',
'settings.window_target.one' => 'Åbn i den samme fane',
'settings.window_target.new' => 'Åbn i en ny fane',
'settings.homepage_search' => 'Homepage Search',
'settings.search_provider' => 'Standardsøgemaskine',
'settings.language' => 'Sprog',
'settings.reset' => 'Nulstil tilbage til standard',
'settings.remove' => 'Fjern',
'settings.search' => 'søg',
'settings.no_items' => 'Intet fundet',
'settings.label' => 'Etiket',
'settings.value' => 'Værdi',
'settings.edit' => 'Rediger',
'settings.view' => 'Vis',
'options.none' => '- ikke indstillet -',
'options.google' => 'Google',
'options.ddg' => 'DuckDuckGo',
'options.bing' => 'Bing',
'options.qwant' => 'Qwant',
'options.startpage' => 'Startside',
'options.yes' => 'Ja',
'options.no' => 'Nej',
'options.nzbhydra' => 'NZBHydra',
'options.jackett' => 'Jackett',
'buttons.save' => 'Gem',
'buttons.cancel' => 'Afbryd',
'buttons.add' => 'Tilføj',
'buttons.upload' => 'Upload et ikon',
'buttons.downloadapps' => 'Opdater apps-listen',
'dash.pin_item' => 'Fastgør element til dashboard',
'dash.no_apps' => 'Der er i øjeblikket ingen fastgjorte applikationer, :link1 eller :link2',
'dash.link1' => 'Add an application here',
'dash.link2' => 'Pin an item to the dash',
'dash.pinned_items' => 'Fastgjorte elementer',
'apps.app_list' => 'Applikations liste',
'apps.view_trash' => 'View trash',
'apps.add_application' => 'Tilføj applikation',
'apps.application_name' => 'Applikations navn',
'apps.colour' => 'Farver',
'apps.icon' => 'Ikon',
'apps.pinned' => 'Fastgjort',
'apps.title' => 'Titel',
'apps.hex' => 'Hex farver',
'apps.username' => 'brugernavn',
'apps.password' => 'kodeord',
'apps.config' => 'Config',
'apps.apikey' => 'API nøgle',
'apps.enable' => 'Aktiver',
'apps.tag_list' => 'Tags liste',
'apps.add_tag' => 'Tilføj tag',
'apps.tag_name' => 'Tag navn',
'apps.tags' => 'Tags',
'apps.override' => 'Hvis det er anderledes end hovedwebadressen',
'apps.preview' => 'Eksempel',
'apps.apptype' => 'Applikationstype',
'dashboard' => 'Home dashboard',
'user.user_list' => 'Brugere',
'user.add_user' => 'Tilføj bruger',
'user.username' => 'Brugernavn',
'user.avatar' => 'Avatar',
'user.email' => 'E-mail',
'user.password_confirm' => 'Bekræft kodeord',
'user.secure_front' => 'Tillad offentlig adgang til forsiden - Kun håndhævet, hvis der er angivet en adgangskode.',
'user.autologin' => 'Tillad at logge ind fra en bestemt URL. Alle med linket kan logge ind.',
'url' => 'URL',
'title' => 'Title',
'delete' => 'Slet',
'optional' => 'Valgfri',
'restore' => 'Genskab',
'alert.success.item_created' => 'Item created successfully',
'alert.success.item_updated' => 'Item updated successfully',
'alert.success.item_deleted' => 'Item deleted successfully',
'alert.success.item_restored' => 'Item restored successfully',
'alert.success.updating' => 'Updating apps list',
'alert.success.tag_created' => 'Tag oprettet med succes',
'alert.success.tag_updated' => 'Tag opdateret med succes',
'alert.success.tag_deleted' => 'Tag slettet med succes',
'alert.success.tag_restored' => 'Tag genskabt med succes',
'alert.success.setting_updated' => 'You have successfully edited this setting',
'alert.error.not_exist' => 'Denne indstilling findes ikke.',
'alert.success.user_created' => 'Bruger oprettet med succes',
'alert.success.user_updated' => 'Bruger opdateret med succes',
'alert.success.user_deleted' => 'Bruger slettet med succes',
'alert.success.user_restored' => 'Bruger genskabt med succes',
];
return array (
'settings.system' => 'System',
'settings.appearance' => 'Appearance',
'settings.miscellaneous' => 'Miscellaneous',
'settings.advanced' => 'Fremskreden',
'settings.support' => 'Support',
'settings.donate' => 'Doner',
'settings.version' => 'Version',
'settings.background_image' => 'Baggrundsbillede',
'settings.window_target' => 'Link opens in',
'settings.window_target.current' => 'Åbn i denne fane',
'settings.window_target.one' => 'Åbn i den samme fane',
'settings.window_target.new' => 'Åbn i en ny fane',
'settings.homepage_search' => 'Homepage Search',
'settings.search_provider' => 'Standardsøgemaskine',
'settings.language' => 'Sprog',
'settings.reset' => 'Nulstil tilbage til standard',
'settings.remove' => 'Fjern',
'settings.search' => 'søg',
'settings.no_items' => 'Intet fundet',
'settings.label' => 'Etiket',
'settings.value' => 'Værdi',
'settings.edit' => 'Rediger',
'settings.view' => 'Vis',
'settings.custom_css' => 'Brugerdefineret CSS',
'settings.custom_js' => 'Brugerdefineret JavaScript',
'options.none' => '- ikke indstillet -',
'options.google' => 'Google',
'options.ddg' => 'DuckDuckGo',
'options.bing' => 'Bing',
'options.qwant' => 'Qwant',
'options.startpage' => 'Startside',
'options.yes' => 'Ja',
'options.no' => 'Nej',
'options.nzbhydra' => 'NZBHydra',
'options.jackett' => 'Jackett',
'buttons.save' => 'Gem',
'buttons.cancel' => 'Afbryd',
'buttons.add' => 'Tilføj',
'buttons.upload' => 'Upload et ikon',
'buttons.downloadapps' => 'Opdater apps-listen',
'dash.pin_item' => 'Fastgør element til dashboard',
'dash.no_apps' => 'Der er i øjeblikket ingen fastgjorte applikationer, :link1 eller :link2',
'dash.link1' => 'Add an application here',
'dash.link2' => 'Pin an item to the dash',
'dash.pinned_items' => 'Fastgjorte elementer',
'apps.app_list' => 'Applikations liste',
'apps.view_trash' => 'View trash',
'apps.add_application' => 'Tilføj applikation',
'apps.application_name' => 'Applikations navn',
'apps.colour' => 'Farver',
'apps.icon' => 'Ikon',
'apps.pinned' => 'Fastgjort',
'apps.title' => 'Titel',
'apps.hex' => 'Hex farver',
'apps.username' => 'brugernavn',
'apps.password' => 'kodeord',
'apps.config' => 'Config',
'apps.apikey' => 'API nøgle',
'apps.enable' => 'Aktiver',
'apps.tag_list' => 'Tags liste',
'apps.add_tag' => 'Tilføj tag',
'apps.tag_name' => 'Tag navn',
'apps.tags' => 'Tags',
'apps.override' => 'Hvis det er anderledes end hovedwebadressen',
'apps.preview' => 'Eksempel',
'apps.apptype' => 'Applikationstype',
'apps.website' => 'Internet side',
'apps.description' => 'Beskrivelse',
'apps.only_admin_account' => 'Kun hvis du har en admin-konto!',
'apps.autologin_url' => 'Auto login url',
'apps.show_deleted' => 'Viser slettede applikationer',
'dashboard' => 'Home dashboard',
'user.user_list' => 'Brugere',
'user.add_user' => 'Tilføj bruger',
'user.username' => 'Brugernavn',
'user.avatar' => 'Avatar',
'user.email' => 'E-mail',
'user.password_confirm' => 'Bekræft kodeord',
'user.secure_front' => 'Tillad offentlig adgang til forsiden - Kun håndhævet, hvis der er angivet en adgangskode.',
'user.autologin' => 'Tillad at logge ind fra en bestemt URL. Alle med linket kan logge ind.',
'url' => 'URL',
'title' => 'Title',
'delete' => 'Slet',
'optional' => 'Valgfri',
'restore' => 'Genskab',
'alert.success.item_created' => 'Item created successfully',
'alert.success.item_updated' => 'Item updated successfully',
'alert.success.item_deleted' => 'Item deleted successfully',
'alert.success.item_restored' => 'Item restored successfully',
'alert.success.updating' => 'Updating apps list',
'alert.success.tag_created' => 'Tag oprettet med succes',
'alert.success.tag_updated' => 'Tag opdateret med succes',
'alert.success.tag_deleted' => 'Tag slettet med succes',
'alert.success.tag_restored' => 'Tag genskabt med succes',
'alert.success.setting_updated' => 'You have successfully edited this setting',
'alert.error.not_exist' => 'Denne indstilling findes ikke.',
'alert.success.user_created' => 'Bruger oprettet med succes',
'alert.success.user_updated' => 'Bruger opdateret med succes',
'alert.success.user_deleted' => 'Bruger slettet med succes',
'alert.success.user_restored' => 'Bruger genskabt med succes',
'dashboard.reorder' => 'Genbestil og fastgør varer',
'dashboard.settings' => 'Indstillinger',
);

View File

@@ -0,0 +1,6 @@
<?php
return array (
'failed' => 'Disse legitimationsoplysninger stemmer ikke overens med vores optegnelser.',
'throttle' => 'For mange loginforsøg. Prøv venligst igen om :sekunder sekunder.',
);

View File

@@ -1,19 +1,6 @@
<?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; Tidligere',
'next' => 'Næste &raquo;',
];
return array (
'previous' => '&laquo; Tidligere',
'next' => 'Næste &raquo;',
);

View File

@@ -1,22 +1,9 @@
<?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' => 'Adgangskoder skal bestå af mindst seks tegn og matche bekræftelsen.',
'reset' => 'Din adgangskode er nulstillet!',
'sent' => 'Vi har sendt dig en e-mail med et link til nulstilling af adgangskode!',
'token' => 'Dit token er ikke gyldigt!',
'user' => 'Vi kan ikke finde en bruger med den e-mail-adresse.',
];
return array (
'password' => 'Adgangskoder skal bestå af mindst seks tegn og matche bekræftelsen.',
'reset' => 'Din adgangskode er nulstillet!',
'sent' => 'Vi har sendt dig en e-mail med et link til nulstilling af adgangskode!',
'token' => 'Dit token er ikke gyldigt!',
'user' => 'Vi kan ikke finde en bruger med den e-mail-adresse.',
);

View File

@@ -1,60 +1,106 @@
<?php
return [
'settings.system' => 'System',
'settings.appearance' => 'Aussehen',
'settings.miscellaneous' => 'Sonstiges',
'settings.version' => 'Version',
'settings.background_image' => 'Hintergrundbild',
'settings.homepage_search' => 'Startseite Sucheingabe',
'settings.search_provider' => 'Suchanbieter',
'settings.language' => 'Sprache',
'settings.reset' => 'Zurücksetzen auf Standard',
'settings.remove' => 'Entfernen',
'settings.search' => 'suche',
'settings.no_items' => 'Keine Elemente gefunden',
'settings.label' => 'Bezeichnung',
'settings.value' => 'Wert',
'settings.edit' => 'Bearbeiten',
'settings.view' => 'Ansicht',
'options.none' => '- nicht festgelegt -',
'options.google' => 'Google',
'options.ddg' => 'DuckDuckGo',
'options.bing' => 'Bing',
'options.qwant' => 'Qwant',
'options.yes' => 'Ja',
'options.no' => 'Nein',
'buttons.save' => 'Speichern',
'buttons.cancel' => 'Abbrechen',
'buttons.add' => 'Hinzufügen',
'buttons.upload' => 'Hochladen einer Datei',
'dash.pin_item' => 'Element auf dem Dashboard anheften',
'dash.no_apps' => 'Derzeit gibt es keine angeheftete Anwendungen. :link1 oder :link2',
'dash.link1' => 'Anwendung neu hinzufügen',
'dash.link2' => 'anheften',
'dash.pinned_items' => 'Angeheftete Elemente',
'apps.app_list' => 'Anwendungsliste',
'apps.view_trash' => 'Ansicht Papierkorb',
'apps.add_application' => 'Anwendung hinzufügen',
'apps.application_name' => 'Anwendungsname',
'apps.colour' => 'Farbe',
'apps.icon' => 'Symbol',
'apps.pinned' => 'Angeheftet',
'apps.title' => 'Titel',
'apps.hex' => 'Hex-Farbe',
'apps.username' => 'Benutzername',
'apps.password' => 'Passwort',
'apps.config' => 'Konfiguration',
'apps.only_admin_account' => 'Nur mit Admin-Konto!',
'url' => 'URL',
'title' => 'Titel',
'delete' => 'Löschen',
'optional' => 'Optional',
'restore' => 'Wiederherstellen',
'alert.success.item_created' => 'Element erfolgreich erstellt',
'alert.success.item_updated' => 'Element erfolgreich aktualisiert',
'alert.success.item_deleted' => 'Element erfolgreich gelöscht',
'alert.success.item_restored' => 'Element erfolgreich wiederhergestellt',
'alert.success.setting_updated' => 'Die Einstellungen wurden übernommen',
'alert.error.not_exist' => 'Diese Einstellung existiert nicht.',
];
return array (
'settings.system' => 'System',
'settings.appearance' => 'Aussehen',
'settings.miscellaneous' => 'Sonstiges',
'settings.advanced' => 'Erweitert',
'settings.support' => 'Unterstütze',
'settings.donate' => 'Spende',
'settings.version' => 'Version',
'settings.background_image' => 'Hintergrundbild',
'settings.window_target' => 'Link öffnen in',
'settings.window_target.current' => 'In diesem Tab öffnen',
'settings.window_target.one' => 'Im selben Tab öffnen',
'settings.window_target.new' => 'Im neuen Tab öffnen',
'settings.homepage_search' => 'Startseite Sucheingabe',
'settings.search_provider' => 'Suchanbieter',
'settings.language' => 'Sprache',
'settings.reset' => 'Zurücksetzen auf Standard',
'settings.remove' => 'Entfernen',
'settings.search' => 'suche',
'settings.no_items' => 'Keine Elemente gefunden',
'settings.label' => 'Bezeichnung',
'settings.value' => 'Wert',
'settings.edit' => 'Bearbeiten',
'settings.view' => 'Ansicht',
'settings.custom_css' => 'Angepasstes CSS',
'settings.custom_js' => 'Angepasstes JavaScript',
'options.none' => '- nicht festgelegt -',
'options.google' => 'Google',
'options.ddg' => 'DuckDuckGo',
'options.bing' => 'Bing',
'options.qwant' => 'Qwant',
'options.startpage' => 'StartSeite',
'options.yes' => 'Ja',
'options.no' => 'Nein',
'options.nzbhydra' => 'NZBHydra',
'options.jackett' => 'Jackett',
'buttons.save' => 'Speichern',
'buttons.cancel' => 'Abbrechen',
'buttons.add' => 'Hinzufügen',
'buttons.upload' => 'Hochladen einer Datei',
'buttons.downloadapps' => 'Update der Anwendungsliste',
'dash.pin_item' => 'Element auf dem Dashboard anheften',
'dash.no_apps' => 'Derzeit gibt es keine angeheftete Anwendungen. :link1 oder :link2',
'dash.link1' => 'Anwendung neu hinzufügen',
'dash.link2' => 'anheften',
'dash.pinned_items' => 'Angeheftete Elemente',
'apps.app_list' => 'Anwendungsliste',
'apps.view_trash' => 'Ansicht Papierkorb',
'apps.add_application' => 'Anwendung hinzufügen',
'apps.application_name' => 'Anwendungsname',
'apps.colour' => 'Farbe',
'apps.icon' => 'Symbol',
'apps.pinned' => 'Angeheftet',
'apps.title' => 'Titel',
'apps.hex' => 'Hex-Farbe',
'apps.username' => 'Benutzername',
'apps.password' => 'Passwort',
'apps.config' => 'Konfiguration',
'apps.apikey' => 'API Key',
'apps.enable' => 'Aktivieren',
'apps.tag_list' => 'Tags Liste',
'apps.add_tag' => 'Tag hinzufügen',
'apps.tag_name' => 'Tag Name',
'apps.tags' => 'Tags',
'apps.override' => 'Fals anders zur Haupt-URL',
'apps.preview' => 'Vorschau',
'apps.apptype' => 'Anwendungstyp',
'apps.website' => 'Webseite',
'apps.description' => 'Beschreibung',
'apps.only_admin_account' => 'Nur mit Admin-Konto!',
'apps.autologin_url' => 'Auto Login URL',
'apps.show_deleted' => 'Gelöschte Anwendung anzeigen',
'dashboard' => 'Home Dashboard',
'user.user_list' => 'Nutzer',
'user.add_user' => 'Nutzer hinzufügen',
'user.username' => 'Benutzername',
'user.avatar' => 'Avatar',
'user.email' => 'Email',
'user.password_confirm' => 'Passwort bestätigen',
'user.secure_front' => 'Öffentlichen Zugang erlauben - Tritt nur bei gesetztem Passwort in kraft.',
'user.autologin' => 'Anmelden von spezieller URL erlauben. Jeder mit diesem Link kann sich anmelden.',
'url' => 'URL',
'title' => 'Titel',
'delete' => 'Löschen',
'optional' => 'Optional',
'restore' => 'Wiederherstellen',
'alert.success.item_created' => 'Element erfolgreich erstellt',
'alert.success.item_updated' => 'Element erfolgreich aktualisiert',
'alert.success.item_deleted' => 'Element erfolgreich gelöscht',
'alert.success.item_restored' => 'Element erfolgreich wiederhergestellt',
'alert.success.updating' => 'Aktualisiere Anwendungsliste',
'alert.success.tag_created' => 'Tag erfolgreich erstellt',
'alert.success.tag_updated' => 'Tag erfolgreich aktualisiert',
'alert.success.tag_deleted' => 'Tag erfolgreich gelöscht',
'alert.success.tag_restored' => 'Tag erfolgreich wiederhergestellt',
'alert.success.setting_updated' => 'Die Einstellungen wurden übernommen',
'alert.error.not_exist' => 'Diese Einstellung existiert nicht.',
'alert.success.user_created' => 'Nutzer erfolgreich erstellt',
'alert.success.user_updated' => 'Nutzer erfolgreich aktualisiert',
'alert.success.user_deleted' => 'Nutzer erfolgreich gelöscht',
'alert.success.user_restored' => 'Nutzer erfolgreich wiederhergestellt',
'dashboard.reorder' => 'Elemente neu anordnen und anheften',
'dashboard.settings' => 'Einstellungen',
);

View File

@@ -0,0 +1,6 @@
<?php
return array (
'failed' => 'Diese Anmeldeinformationen stimmen nicht mit unseren Aufzeichnungen überein.',
'throttle' => 'Zu viele Anmeldeversuche. Bitte versuchen Sie es in :Sekunden Sekunden erneut.',
);

View File

@@ -0,0 +1,6 @@
<?php
return array (
'previous' => '&laquo; Vorherige',
'next' => 'Weiter &raquo;',
);

View File

@@ -0,0 +1,9 @@
<?php
return array (
'password' => 'Passwörter müssen mindestens sechs Zeichen lang sein und mit der Bestätigung übereinstimmen.',
'reset' => 'Dein Passwort wurde zurück gesetzt!',
'sent' => 'Wir haben Ihren Link zum Zurücksetzen des Passworts per E-Mail gesendet!',
'token' => 'Dieses Token zum Zurücksetzen des Passworts ist ungültig.',
'user' => 'Wir können keinen Benutzer mit dieser E-Mail-Adresse finden.',
);

View File

@@ -1,118 +1,106 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| App Language Lines
|--------------------------------------------------------------------------
|
*/
'settings.system' => 'Σύστημα',
'settings.appearance' => 'Εμφάνιση',
'settings.miscellaneous' => 'Λοιπά',
'settings.support' => 'Υποστήριξη',
'settings.donate' => 'Δωρεά',
'settings.version' => 'Έκδοση',
'settings.background_image' => 'Εικόνα Παρασκηνίου',
'settings.window_target' => 'Ο Σύνδεσμος ανοίγει σε',
'settings.window_target.current' => 'Άνοιγμα σε αυτή την καρτέλα',
'settings.window_target.one' => 'Άνοιγμα στην ίδια καρτέλα',
'settings.window_target.new' => 'Άνοιγμα σε νέα καρτέλα',
'settings.homepage_search' => 'Αναζήτηση στην Αρχική Σελίδα',
'settings.search_provider' => 'Προεπιλεγμένος Πάροχος Αναζήτησης',
'settings.language' => 'Γλώσσα',
'settings.reset' => 'Επαναφορά πίσω στις προεπιλογές',
'settings.remove' => 'Αφαίρεση',
'settings.search' => 'αναζήτηση',
'settings.no_items' => 'Δε βρεθηκαν αποτελέσματα',
'settings.label' => 'Ετικέτα',
'settings.value' => 'Τιμή',
'settings.edit' => 'Επεξεργασία',
'settings.view' => 'Προβολή',
'options.none' => '- μη ορισμένο -',
'options.google' => 'Google',
'options.ddg' => 'DuckDuckGo',
'options.bing' => 'Bing',
'options.qwant' => 'Qwant',
'options.startpage' => 'StartPage',
'options.yes' => 'Ναι',
'options.no' => 'Όχι',
'options.nzbhydra' => 'NZBHydra',
'options.jackett' => 'Jackett',
'buttons.save' => 'Αποθήκευση',
'buttons.cancel' => 'Ακύρωση',
'buttons.add' => 'Προσθήκη',
'buttons.upload' => 'Μεταφόρτωση ενός αρχείου',
'buttons.downloadapps' => 'Ανανέωση Λίστας Εφαρμογών',
'dash.pin_item' => 'Καρφίτσωμα του αντικειμένου στο ταμπλό',
'dash.no_apps' => 'Δεν υπάρχουν προς το παρόν καρφιτσωμένες εφαρμογές, :link1 ή :link2',
'dash.link1' => 'Προσθήκη μίας εφαρμογής εδώ',
'dash.link2' => 'Καρφίτσωμα ενός αντικειμένου στο ταμπλό',
'dash.pinned_items' => 'Καρφιτσωμένα αντικείμενα',
'apps.app_list' => 'Λίστα Εφαρμογών',
'apps.view_trash' => 'Εμφάνιση Απορριμμάτων',
'apps.add_application' => 'Προσθήκη εφαρμογής',
'apps.application_name' => 'Όνομα Εφαρμογής',
'apps.colour' => 'Χρώμα',
'apps.icon' => 'Εικονίδιο',
'apps.pinned' => 'Καρφιτσωμένο',
'apps.title' => 'Τίτλος',
'apps.hex' => 'Hex χρώμα',
'apps.username' => 'Όνομα χρήστη',
'apps.password' => 'Κωδικός πρόσβασης',
'apps.config' => 'Ρύθμιση',
'apps.apikey' => 'Κλειδί API',
'apps.enable' => 'Ενεργοποίηση',
'apps.tag_list' => 'Λίστα Ετικετών',
'apps.add_tag' => 'Προσθήκη ετικέτας',
'apps.tag_name' => 'Όνομα Ετικέτας',
'apps.tags' => 'Ετικέτες',
'apps.override' => 'Αν διαφορετικό με το κύριο url',
'apps.preview' => 'Προεπισκόπιση',
'apps.apptype' => 'Τύπος Εφαρμογής',
'dashboard' => 'Αρχικό ταμπλό',
'user.user_list' => 'Χρήστες',
'user.add_user' => 'Προσθήκη χρήστη',
'user.username' => 'Όνομα χρήστη',
'user.avatar' => 'Εικόνα χρήστη',
'user.email' => 'Email',
'user.password_confirm' => 'Επιβεβαίωση κωδικού πρόσβασης',
'user.secure_front' => 'Χορήγηση δημόσιας πρόσβασης στο εμπρόσθιο τμήμα - Τίθεται σε ενέργεια μόνο εαν έχει ορισθεί κωδικός.',
'user.autologin' => 'Χορήγηση πρόσβασης από ένα συγκεκριμένο URL. Οποιοσδήποτε με τον σύνδεσμο μπορεί να εισέρθει.',
'url' => 'URL',
'title' => 'Τίτλος',
'delete' => 'Διαγραφή',
'optional' => 'Προεραιτικό',
'restore' => 'Επαναφορά',
'alert.success.item_created' => 'Το αντικείμενο δημιουργήθηκε επιτυχώς',
'alert.success.item_updated' => 'Το αντικείμενο ενημερώθηκε επιτυχώς',
'alert.success.item_deleted' => 'Το αντικείμενο διαγράφηκε επιτυχώς',
'alert.success.item_restored' => 'Το αντικείμενο επαναφέρθηκε επιτυχώς',
'alert.success.updating' => 'Η λίστα των εφαρμογών ενημερώνεται',
'alert.success.tag_created' => 'Η ετικέτα δημιουργήθηκε επιτυχώ',
'alert.success.tag_updated' => 'Η ετικέτα ενημερώθηκε επιτυχώς',
'alert.success.tag_deleted' => 'Η ετικέτα διαγράφηκε επιτυχώς',
'alert.success.tag_restored' => 'Η ετικέτα επαναφέρθηκε επιτυχώς',
'alert.success.setting_updated' => 'Επεξεργαστήκατε επιτυχώς αυτή τη ρύθμιση',
'alert.error.not_exist' => 'Αυτή η ρύθμιση δεν υπάρχει.',
'alert.success.user_created' => 'Ο χρήστης δημιουργήθηκε επιτυχώς',
'alert.success.user_updated' => 'Ο χρήστης ενημερώθηκε επιτυχώς',
'alert.success.user_deleted' => 'Ο χρήστης διαγράφηκε επιτυχώς',
'alert.success.user_restored' => 'Ο χρήστης επαναφέρθηκε επιτυχώς',
];
return array (
'settings.system' => 'Σύστημα',
'settings.appearance' => 'Εμφάνιση',
'settings.miscellaneous' => 'Λοιπά',
'settings.advanced' => 'Προχωρημένος',
'settings.support' => 'Υποστήριξη',
'settings.donate' => 'Δωρεά',
'settings.version' => 'Έκδοση',
'settings.background_image' => 'Εικόνα Παρασκηνίου',
'settings.window_target' => 'Ο Σύνδεσμος ανοίγει σε',
'settings.window_target.current' => 'Άνοιγμα σε αυτή την καρτέλα',
'settings.window_target.one' => 'Άνοιγμα στην ίδια καρτέλα',
'settings.window_target.new' => 'Άνοιγμα σε νέα καρτέλα',
'settings.homepage_search' => 'Αναζήτηση στην Αρχική Σελίδα',
'settings.search_provider' => 'Προεπιλεγμένος Πάροχος Αναζήτησης',
'settings.language' => 'Γλώσσα',
'settings.reset' => 'Επαναφορά πίσω στις προεπιλογές',
'settings.remove' => 'Αφαίρεση',
'settings.search' => 'αναζήτηση',
'settings.no_items' => 'Δε βρεθηκαν αποτελέσματα',
'settings.label' => 'Ετικέτα',
'settings.value' => 'Τιμή',
'settings.edit' => 'Επεξεργασία',
'settings.view' => 'Προβολή',
'settings.custom_css' => 'Προσαρμοσμένο CSS',
'settings.custom_js' => 'Προσαρμοσμένη JavaScript',
'options.none' => '- μη ορισμένο -',
'options.google' => 'Google',
'options.ddg' => 'DuckDuckGo',
'options.bing' => 'Bing',
'options.qwant' => 'Qwant',
'options.startpage' => 'StartPage',
'options.yes' => 'Ναι',
'options.no' => 'Όχι',
'options.nzbhydra' => 'NZBHydra',
'options.jackett' => 'Jackett',
'buttons.save' => 'Αποθήκευση',
'buttons.cancel' => 'Ακύρωση',
'buttons.add' => 'Προσθήκη',
'buttons.upload' => 'Μεταφόρτωση ενός αρχείου',
'buttons.downloadapps' => 'Ανανέωση Λίστας Εφαρμογών',
'dash.pin_item' => 'Καρφίτσωμα του αντικειμένου στο ταμπλό',
'dash.no_apps' => 'Δεν υπάρχουν προς το παρόν καρφιτσωμένες εφαρμογές, :link1 ή :link2',
'dash.link1' => 'Προσθήκη μίας εφαρμογής εδώ',
'dash.link2' => 'Καρφίτσωμα ενός αντικειμένου στο ταμπλό',
'dash.pinned_items' => 'Καρφιτσωμένα αντικείμενα',
'apps.app_list' => 'Λίστα Εφαρμογών',
'apps.view_trash' => 'Εμφάνιση Απορριμμάτων',
'apps.add_application' => 'Προσθήκη εφαρμογής',
'apps.application_name' => 'Όνομα Εφαρμογής',
'apps.colour' => 'Χρώμα',
'apps.icon' => 'Εικονίδιο',
'apps.pinned' => 'Καρφιτσωμένο',
'apps.title' => 'Τίτλος',
'apps.hex' => 'Hex χρώμα',
'apps.username' => 'Όνομα χρήστη',
'apps.password' => 'Κωδικός πρόσβασης',
'apps.config' => 'Ρύθμιση',
'apps.apikey' => 'Κλειδί API',
'apps.enable' => 'Ενεργοποίηση',
'apps.tag_list' => 'Λίστα Ετικετών',
'apps.add_tag' => 'Προσθήκη ετικέτας',
'apps.tag_name' => 'Όνομα Ετικέτας',
'apps.tags' => 'Ετικέτες',
'apps.override' => 'Αν διαφορετικό με το κύριο url',
'apps.preview' => 'Προεπισκόπιση',
'apps.apptype' => 'Τύπος Εφαρμογής',
'apps.website' => 'Δικτυακός τόπος',
'apps.description' => 'Περιγραφή',
'apps.only_admin_account' => 'Μόνο αν έχετε λογαριασμό διαχειριστή!',
'apps.autologin_url' => 'URL αυτόματης σύνδεσης',
'apps.show_deleted' => 'Εμφάνιση διαγραμμένων εφαρμογών',
'dashboard' => 'Αρχικό ταμπλό',
'user.user_list' => 'Χρήστες',
'user.add_user' => 'Προσθήκη χρήστη',
'user.username' => 'Όνομα χρήστη',
'user.avatar' => 'Εικόνα χρήστη',
'user.email' => 'Email',
'user.password_confirm' => 'Επιβεβαίωση κωδικού πρόσβασης',
'user.secure_front' => 'Χορήγηση δημόσιας πρόσβασης στο εμπρόσθιο τμήμα - Τίθεται σε ενέργεια μόνο εαν έχει ορισθεί κωδικός.',
'user.autologin' => 'Χορήγηση πρόσβασης από ένα συγκεκριμένο URL. Οποιοσδήποτε με τον σύνδεσμο μπορεί να εισέρθει.',
'url' => 'URL',
'title' => 'Τίτλος',
'delete' => 'Διαγραφή',
'optional' => 'Προεραιτικό',
'restore' => 'Επαναφορά',
'alert.success.item_created' => 'Το αντικείμενο δημιουργήθηκε επιτυχώς',
'alert.success.item_updated' => 'Το αντικείμενο ενημερώθηκε επιτυχώς',
'alert.success.item_deleted' => 'Το αντικείμενο διαγράφηκε επιτυχώς',
'alert.success.item_restored' => 'Το αντικείμενο επαναφέρθηκε επιτυχώς',
'alert.success.updating' => 'Η λίστα των εφαρμογών ενημερώνεται',
'alert.success.tag_created' => 'Η ετικέτα δημιουργήθηκε επιτυχώ',
'alert.success.tag_updated' => 'Η ετικέτα ενημερώθηκε επιτυχώς',
'alert.success.tag_deleted' => 'Η ετικέτα διαγράφηκε επιτυχώς',
'alert.success.tag_restored' => 'Η ετικέτα επαναφέρθηκε επιτυχώς',
'alert.success.setting_updated' => 'Επεξεργαστήκατε επιτυχώς αυτή τη ρύθμιση',
'alert.error.not_exist' => 'Αυτή η ρύθμιση δεν υπάρχει.',
'alert.success.user_created' => 'Ο χρήστης δημιουργήθηκε επιτυχώς',
'alert.success.user_updated' => 'Ο χρήστης ενημερώθηκε επιτυχώς',
'alert.success.user_deleted' => 'Ο χρήστης διαγράφηκε επιτυχώς',
'alert.success.user_restored' => 'Ο χρήστης επαναφέρθηκε επιτυχώς',
'dashboard.reorder' => 'Παραγγείλετε ξανά και καρφιτσώστε αντικείμενα',
'dashboard.settings' => 'Ρυθμίσεις',
);

View File

@@ -1,19 +1,6 @@
<?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' => 'Αυτά τα διαπιστευτήρια δεν ταιριάζουν με τα μητρώα μας.',
'throttle' => 'Πολλές προσπάθειες εισόδου. Παρακαλούμε προσπαθήστε ξανά σε :seconds δευτερόλεπτα.',
];
return array (
'failed' => 'Αυτά τα διαπιστευτήρια δεν ταιριάζουν με τα μητρώα μας.',
'throttle' => 'Πολλές προσπάθειες εισόδου. Παρακαλούμε προσπαθήστε ξανά σε :seconds δευτερόλεπτα.',
);

View File

@@ -1,19 +1,6 @@
<?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; Προηγούμενη',
'next' => 'Επόμενη &raquo;',
];
return array (
'previous' => '&laquo; Προηγούμενη',
'next' => 'Επόμενη &raquo;',
);

View File

@@ -1,22 +1,9 @@
<?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' => 'Οι κωδικοί πρόσβασης πρέπει να αποτελλούνται τουλάχιστον από έξι χαρακτήρες και να ταιριάζουν με την επικύρωση.',
'reset' => 'Έχει γίνει επαναφορά του κωδικού σας!',
'sent' => 'Σας στείλαμε ένα Ε-mail με τον σύνδεσμο για την επαναφορά του κωδικού πρόσβασής σας!',
'token' => 'Αυτό το token για την επαναφορά του κωδικού πρόσβασής σας είναι άκυρο.',
'user' => 'Δεν μπορούμε να βρόυμε κάποιον χρήστη με αυτή τη διεύθυνση E-mail.',
];
return array (
'password' => 'Οι κωδικοί πρόσβασης πρέπει να αποτελλούνται τουλάχιστον από έξι χαρακτήρες και να ταιριάζουν με την επικύρωση.',
'reset' => 'Έχει γίνει επαναφορά του κωδικού σας!',
'sent' => 'Σας στείλαμε ένα Ε-mail με τον σύνδεσμο για την επαναφορά του κωδικού πρόσβασής σας!',
'token' => 'Αυτό το token για την επαναφορά του κωδικού πρόσβασής σας είναι άκυρο.',
'user' => 'Δεν μπορούμε να βρόυμε κάποιον χρήστη με αυτή τη διεύθυνση E-mail.',
);

View File

@@ -1,128 +1,109 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| App Language Lines
|--------------------------------------------------------------------------
|
*/
'settings.system' => 'System',
'settings.appearance' => 'Appearance',
'settings.miscellaneous' => 'Miscellaneous',
'settings.advanced' => 'Advanced',
'settings.support' => 'Support',
'settings.donate' => 'Donate',
'settings.version' => 'Version',
'settings.background_image' => 'Background Image',
'settings.window_target' => 'Link opens in',
'settings.window_target.current' => 'Open in this tab',
'settings.window_target.one' => 'Open in the same tab',
'settings.window_target.new' => 'Open in a new tab',
'settings.homepage_search' => 'Homepage Search',
'settings.search_provider' => 'Default Search Provider',
'settings.language' => 'Language',
'settings.reset' => 'Reset back to default',
'settings.remove' => 'Remove',
'settings.search' => 'search',
'settings.no_items' => 'No items found',
'settings.label' => 'Label',
'settings.value' => 'Value',
'settings.edit' => 'Edit',
'settings.view' => 'View',
'settings.custom_css' => 'Custom CSS',
'settings.custom_js' => 'Custom JavaScript',
'options.none' => '- not set -',
'options.google' => 'Google',
'options.ddg' => 'DuckDuckGo',
'options.bing' => 'Bing',
'options.qwant' => 'Qwant',
'options.startpage' => 'StartPage',
'options.yes' => 'Yes',
'options.no' => 'No',
'options.nzbhydra' => 'NZBHydra',
'options.jackett' => 'Jackett',
'buttons.save' => 'Save',
'buttons.cancel' => 'Cancel',
'buttons.add' => 'Add',
'buttons.upload' => 'Upload an icon',
'buttons.downloadapps' => 'Update Apps List',
'dash.pin_item' => 'Pin item to dashboard',
'dash.no_apps' => 'There are currently no pinned applications, :link1 or :link2',
'dash.link1' => 'Add an application here',
'dash.link2' => 'Pin an item to the dash',
'dash.pinned_items' => 'Pinned Items',
'apps.app_list' => 'Application list',
'apps.view_trash' => 'View trash',
'apps.add_application' => 'Add application',
'apps.application_name' => 'Application name',
'apps.colour' => 'Colour',
'apps.icon' => 'Icon',
'apps.pinned' => 'Pinned',
'apps.title' => 'Title',
'apps.hex' => 'Hex colour',
'apps.username' => 'Username',
'apps.password' => 'Password',
'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',
'apps.preview' => 'Preview',
'apps.apptype' => 'Application Type',
'apps.website' => 'Website',
'apps.description' => 'Description',
'apps.only_admin_account' => 'Only if you have admin-account!',
'apps.autologin_url' => 'Auto login url',
'apps.show_deleted' => 'Showing Deleted Applications',
'dashboard' => 'Home dashboard',
'user.user_list' => 'Users',
'user.add_user' => 'Add user',
'user.username' => 'Username',
'user.avatar' => 'Avatar',
'user.email' => 'Email',
'user.password_confirm' => 'Confirm Password',
'user.secure_front' => 'Allow public access to front - Only enforced if a password is set.',
'user.autologin' => 'Allow logging in from a specific URL. Anyone with the link can login.',
'url' => 'URL',
'title' => 'Title',
'delete' => 'Delete',
'optional' => 'Optional',
'restore' => 'Restore',
'alert.success.item_created' => 'Item created successfully',
'alert.success.item_updated' => 'Item updated successfully',
'alert.success.item_deleted' => 'Item deleted successfully',
'alert.success.item_restored' => 'Item restored successfully',
'alert.success.updating' => 'Updating apps list',
'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.',
'alert.success.user_created' => 'User created successfully',
'alert.success.user_updated' => 'User updated successfully',
'alert.success.user_deleted' => 'User deleted successfully',
'alert.success.user_restored' => 'User restored successfully',
];
return array (
'settings.system' => 'System',
'settings.appearance' => 'Appearance',
'settings.miscellaneous' => 'Miscellaneous',
'settings.advanced' => 'Advanced',
'settings.support' => 'Support',
'settings.donate' => 'Donate',
'settings.version' => 'Version',
'settings.background_image' => 'Background Image',
'settings.window_target' => 'Link opens in',
'settings.window_target.current' => 'Open in this tab',
'settings.window_target.one' => 'Open in the same tab',
'settings.window_target.new' => 'Open in a new tab',
'settings.homepage_search' => 'Homepage Search',
'settings.search_provider' => 'Default Search Provider',
'settings.language' => 'Language',
'settings.reset' => 'Reset back to default',
'settings.remove' => 'Remove',
'settings.search' => 'search',
'settings.no_items' => 'No items found',
'settings.label' => 'Label',
'settings.value' => 'Value',
'settings.edit' => 'Edit',
'settings.view' => 'View',
'settings.custom_css' => 'Custom CSS',
'settings.custom_js' => 'Custom JavaScript',
'options.none' => '- not set -',
'options.google' => 'Google',
'options.ddg' => 'DuckDuckGo',
'options.bing' => 'Bing',
'options.qwant' => 'Qwant',
'options.startpage' => 'StartPage',
'options.yes' => 'Yes',
'options.no' => 'No',
'options.nzbhydra' => 'NZBHydra',
'options.jackett' => 'Jackett',
'buttons.save' => 'Save',
'buttons.cancel' => 'Cancel',
'buttons.add' => 'Add',
'buttons.upload' => 'Upload an icon',
'buttons.downloadapps' => 'Update Apps List',
'dash.pin_item' => 'Pin item to dashboard',
'dash.no_apps' => 'There are currently no pinned applications, :link1 or :link2',
'dash.link1' => 'Add an application here',
'dash.link2' => 'Pin an item to the dash',
'dash.pinned_items' => 'Pinned Items',
'apps.app_list' => 'Application list',
'apps.view_trash' => 'View trash',
'apps.add_application' => 'Add application',
'apps.application_name' => 'Application name',
'apps.colour' => 'Colour',
'apps.icon' => 'Icon',
'apps.pinned' => 'Pinned',
'apps.title' => 'Title',
'apps.hex' => 'Hex colour',
'apps.username' => 'Username',
'apps.password' => 'Password',
'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',
'apps.preview' => 'Preview',
'apps.apptype' => 'Application Type',
'apps.website' => 'Website',
'apps.description' => 'Description',
'apps.only_admin_account' => 'Only if you have admin-account!',
'apps.autologin_url' => 'Auto login url',
'apps.show_deleted' => 'Showing Deleted Applications',
'app.import' => 'Import',
'dashboard' => 'Home dashboard',
'user.user_list' => 'Users',
'user.add_user' => 'Add user',
'user.username' => 'Username',
'user.avatar' => 'Avatar',
'user.email' => 'Email',
'user.password_confirm' => 'Confirm Password',
'user.secure_front' => 'Allow public access to front - Only enforced if a password is set.',
'user.autologin' => 'Allow logging in from a specific URL. Anyone with the link can login.',
'url' => 'URL',
'title' => 'Title',
'delete' => 'Delete',
'optional' => 'Optional',
'restore' => 'Restore',
'export' => 'Export',
'import' => 'Import',
'alert.success.item_created' => 'Item created successfully',
'alert.success.item_updated' => 'Item updated successfully',
'alert.success.item_deleted' => 'Item deleted successfully',
'alert.success.item_restored' => 'Item restored successfully',
'alert.success.updating' => 'Updating apps list',
'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.',
'alert.success.user_created' => 'User created successfully',
'alert.success.user_updated' => 'User updated successfully',
'alert.success.user_deleted' => 'User deleted successfully',
'alert.success.user_restored' => 'User restored successfully',
'dashboard.reorder' => 'Reorder and pin items',
'dashboard.settings' => 'Settings',
);

View File

@@ -1,19 +1,6 @@
<?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' => 'These credentials do not match our records.',
'throttle' => 'Too many login attempts. Please try again in :seconds seconds.',
];
return array (
'failed' => 'These credentials do not match our records.',
'throttle' => 'Too many login attempts. Please try again in :seconds seconds.',
);

View File

@@ -1,19 +1,6 @@
<?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; Previous',
'next' => 'Next &raquo;',
];
return array (
'previous' => '&laquo; Previous',
'next' => 'Next &raquo;',
);

View File

@@ -1,22 +1,9 @@
<?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' => 'Passwords must be at least six characters and match the confirmation.',
'reset' => 'Your password has been reset!',
'sent' => 'We have e-mailed your password reset link!',
'token' => 'This password reset token is invalid.',
'user' => "We can't find a user with that e-mail address.",
];
return array (
'password' => 'Passwords must be at least six characters and match the confirmation.',
'reset' => 'Your password has been reset!',
'sent' => 'We have e-mailed your password reset link!',
'token' => 'This password reset token is invalid.',
'user' => 'We can\'t find a user with that e-mail address.',
);

View File

@@ -1,60 +1,106 @@
<?php
return [
'settings.system' => 'Sistema',
'settings.appearance' => 'Apariencia',
'settings.miscellaneous' => 'Miscelánea',
'settings.version' => 'Versión',
'settings.background_image' => 'Imagen De Fondo',
'settings.homepage_search' => 'Página De Inicio De Búsqueda',
'settings.search_provider' => 'Proveedor de búsqueda',
'settings.language' => 'Idioma',
'settings.reset' => 'Restablecer a predeterminado',
'settings.remove' => 'Quitar',
'settings.search' => 'búsqueda',
'settings.no_items' => 'No se encontraron elementos',
'settings.label' => 'Etiqueta',
'settings.value' => 'Valor',
'settings.edit' => 'Editar',
'settings.view' => 'Ver',
'options.none' => '- no establecido -',
'options.google' => 'Google',
'options.ddg' => 'DuckDuckGo',
'options.bing' => 'Bing',
'options.qwant' => 'Qwant',
'options.jackett' => 'Jackett',
'options.yes' => '',
'options.no' => 'No',
'buttons.save' => 'Guardar',
'buttons.cancel' => 'Cancelar',
'buttons.add' => 'Añadir',
'buttons.upload' => 'Cargar un archivo',
'dash.pin_item' => 'Pin elemento al tablero',
'dash.no_apps' => 'Actualmente no hay aplicaciones ancladas, :link1 o :link2',
'dash.link1' => 'Agregue una aplicación aquí',
'dash.link2' => 'Pin de un elemento en el tablero',
'dash.pinned_items' => 'Elementos Anclados',
'apps.app_list' => 'Lista de aplicaciones',
'apps.view_trash' => 'Vista de la papelera de reciclaje',
'apps.add_application' => 'Agregar aplicación',
'apps.application_name' => 'Nombre de la aplicación',
'apps.colour' => 'Color',
'apps.icon' => 'Icono',
'apps.pinned' => 'Fijado',
'apps.title' => 'Título',
'apps.hex' => 'Código de color hexadecimal',
'apps.username' => 'Nombre de usuario',
'apps.password' => 'Contraseña',
'apps.config' => 'Config',
'url' => 'Url',
'title' => 'Título',
'delete' => 'Borrar',
'optional' => 'Opcional',
'restore' => 'Restaurar',
'alert.success.item_created' => 'Elemento creado con éxito',
'alert.success.item_updated' => 'Artículo actualizado con éxito',
'alert.success.item_deleted' => 'Elemento eliminado correctamente',
'alert.success.item_restored' => 'Elemento restaurado con éxito',
'alert.success.setting_updated' => 'Ha editado con éxito esta configuración',
'alert.error.not_exist' => 'Esta configuración no existe.',
];
return array (
'settings.system' => 'Sistema',
'settings.appearance' => 'Apariencia',
'settings.miscellaneous' => 'Miscelánea',
'settings.advanced' => 'Avanzada',
'settings.support' => 'Soporte',
'settings.donate' => 'Donar',
'settings.version' => 'Versión',
'settings.background_image' => 'Imagen de Fondo',
'settings.window_target' => 'Vínculo abre en',
'settings.window_target.current' => 'Abrir en ésta pestaña',
'settings.window_target.one' => 'Abrir en la misma pestaña',
'settings.window_target.new' => 'Abrir en una nueva pestaña',
'settings.homepage_search' => 'Página de Inicio de Búsqueda',
'settings.search_provider' => 'Proveedor de búsqueda',
'settings.language' => 'Idioma',
'settings.reset' => 'Restablecer a predeterminado',
'settings.remove' => 'Quitar',
'settings.search' => 'búsqueda',
'settings.no_items' => 'No se encontraron elementos',
'settings.label' => 'Etiqueta',
'settings.value' => 'Valor',
'settings.edit' => 'Editar',
'settings.view' => 'Ver',
'settings.custom_css' => 'CSS Personalizado',
'settings.custom_js' => 'JavaScript Personalizado',
'options.none' => '- no establecido -',
'options.google' => 'Google',
'options.ddg' => 'DuckDuckGo',
'options.bing' => 'Bing',
'options.qwant' => 'Qwant',
'options.startpage' => 'Página de Inicio',
'options.yes' => 'Sí',
'options.no' => 'No',
'options.nzbhydra' => 'NZBHydra',
'options.jackett' => 'Jackett',
'buttons.save' => 'Guardar',
'buttons.cancel' => 'Cancelar',
'buttons.add' => 'Añadir',
'buttons.upload' => 'Cargar un archivo',
'buttons.downloadapps' => 'Actualizar lista de Applicaciones',
'dash.pin_item' => 'Pin elemento al tablero',
'dash.no_apps' => 'Actualmente no hay aplicaciones ancladas, :link1 o :link2',
'dash.link1' => 'Agregue una aplicación aquí',
'dash.link2' => 'Pin de un elemento en el tablero',
'dash.pinned_items' => 'Elementos Anclados',
'apps.app_list' => 'Lista de aplicaciones',
'apps.view_trash' => 'Vista de la papelera de reciclaje',
'apps.add_application' => 'Agregar aplicación',
'apps.application_name' => 'Nombre de la aplicación',
'apps.colour' => 'Color',
'apps.icon' => 'Icono',
'apps.pinned' => 'Fijado',
'apps.title' => 'Título',
'apps.hex' => 'Código de color hexadecimal',
'apps.username' => 'Nombre de usuario',
'apps.password' => 'Contraseña',
'apps.config' => 'Config',
'apps.apikey' => 'Clave de API',
'apps.enable' => 'Habilitar',
'apps.tag_list' => 'Lista de Etiquetas',
'apps.add_tag' => 'Añadir Etiqueta',
'apps.tag_name' => 'Nombre de Etiqueta',
'apps.tags' => 'Etiquetas',
'apps.override' => 'Si es differente de la URL principal',
'apps.preview' => 'Previsualizar',
'apps.apptype' => 'Tipo de Aplicación',
'apps.website' => 'Sitio Web',
'apps.description' => 'Descripción',
'apps.only_admin_account' => '¡Solo si tienes cuenta de administrador!',
'apps.autologin_url' => 'URL de auto inicio de sessión',
'apps.show_deleted' => 'Mostrando Aplicaciones Eliminadas',
'dashboard' => 'Tablero Inicial',
'user.user_list' => 'Usuarios',
'user.add_user' => 'Añadir Usuario',
'user.username' => 'Nombre de Usuario',
'user.avatar' => 'Avatar',
'user.email' => 'Correo Electrónico',
'user.password_confirm' => 'Confirmar Contraseña',
'user.secure_front' => 'Permitir acceso público a la interfaz - Forzado solo si una contraseña está definida.',
'user.autologin' => 'Permitir inicio de sesión desde una URL específica. Cualquiera con el vínculo puede iniciar sesión.',
'url' => 'Url',
'title' => 'Título',
'delete' => 'Borrar',
'optional' => 'Opcional',
'restore' => 'Restaurar',
'alert.success.item_created' => 'Elemento creado con éxito',
'alert.success.item_updated' => 'Artículo actualizado con éxito',
'alert.success.item_deleted' => 'Elemento eliminado correctamente',
'alert.success.item_restored' => 'Elemento restaurado con éxito',
'alert.success.updating' => 'Actualizando lista de aplicaciones',
'alert.success.tag_created' => 'Etiqueta creada exitósamente',
'alert.success.tag_updated' => 'Etiqueta actualizada exitósamente',
'alert.success.tag_deleted' => 'Etiqueta eliminada exitósamente',
'alert.success.tag_restored' => 'Etiqueta restaurada exitósamente',
'alert.success.setting_updated' => 'Ha editado con éxito esta configuración',
'alert.error.not_exist' => 'Esta configuración no existe.',
'alert.success.user_created' => 'Usuario creado exitósamente',
'alert.success.user_updated' => 'Usuario actualizado exitósamente',
'alert.success.user_deleted' => 'Usuario eliminado exitósamente',
'alert.success.user_restored' => 'Usuario restaurado exitósamente',
'dashboard.reorder' => 'Reordenar y anclar elementos',
'dashboard.settings' => 'Ajustes',
);

View File

@@ -0,0 +1,6 @@
<?php
return array (
'failed' => 'Estas credenciales no coinciden con nuestros registros.',
'throttle' => 'Demasiados intentos de inicio de sesión. Vuelva a intentarlo en :segundos segundos.',
);

View File

@@ -0,0 +1,6 @@
<?php
return array (
'previous' => '&laquo; Anterior',
'next' => 'Siguiente &raquo;',
);

View File

@@ -0,0 +1,9 @@
<?php
return array (
'password' => 'Las contraseñas deben tener al menos seis caracteres y coincidir con la confirmación.',
'reset' => '¡Tu contraseña ha sido restablecida!',
'sent' => '¡Le hemos enviado por correo electrónico su enlace de restablecimiento de contraseña!',
'token' => 'Este token de restablecimiento de contraseña no es válido.',
'user' => 'No podemos encontrar un usuario con esa dirección de correo electrónico.',
);

View File

@@ -1,104 +1,106 @@
<?php
return [
'settings.system' => 'Järjestelmä',
'settings.appearance' => 'Ulkonäkö',
'settings.miscellaneous' => 'Sekalainen',
'settings.support' => 'Tue',
'settings.donate' => 'Lahjoita',
'settings.version' => 'Versio',
'settings.background_image' => 'Taustakuva',
'settings.window_target' => 'Linkit aukeaa',
'settings.window_target.current' => 'Avaa tässä välilehdessä',
'settings.window_target.one' => 'Avaa samassa välilehdessä',
'settings.window_target.new' => 'Avaa uudessa välilehdessä',
'settings.homepage_search' => 'Kotisivu Haku',
'settings.search_provider' => 'Hakupalvelu',
'settings.language' => 'Kieli',
'settings.reset' => 'Palauta oletusasetukset',
'settings.remove' => 'Poista',
'settings.search' => 'haku',
'settings.no_items' => 'Kohteita ei löytynyt',
'settings.label' => 'Etiketti',
'settings.value' => 'Arvo',
'settings.edit' => 'Muokkaa',
'settings.view' => 'Näkymä',
'options.none' => '- ei asetettu -',
'options.google' => 'Google',
'options.ddg' => 'DuckDuckGo',
'options.bing' => 'Bing',
'options.qwant' => 'Qwant',
'options.startpage' => 'Etusivu',
'options.yes' => 'Kyllä',
'options.no' => 'Ei',
'buttons.save' => 'Tallenna',
'buttons.cancel' => 'Peruuta',
'buttons.add' => 'Lisää',
'buttons.upload' => 'Lataa tiedosto',
'buttons.downloadapps' => 'Päivitä sovelluslistaa',
'dash.pin_item' => 'Kiinnitä kohde hallintapaneliin',
'dash.no_apps' => 'Tällä hetkellä ei ole kiinnitettyjä sovelluksia :link1 tai :link2',
'dash.link1' => 'Lisää sovellus tähän',
'dash.link2' => 'Kiinnitä kohde hallintapaneliin',
'dash.pinned_items' => 'Kiinnitetyt Kohteet',
'apps.app_list' => 'Sovellusluettelo',
'apps.view_trash' => 'Näytä roskakori',
'apps.add_application' => 'Lisää sovellus',
'apps.application_name' => 'Sovelluksen nimi',
'apps.colour' => 'Väri',
'apps.icon' => 'Kuvake',
'apps.pinned' => 'Kiinnitetty',
'apps.title' => 'Otsikko',
'apps.hex' => 'Hex väri',
'apps.username' => 'Käyttäjätunnus',
'apps.password' => 'Salasana',
'apps.config' => 'Konfiguraatio',
'apps.apikey' => 'API Avain',
'apps.enable' => 'Aktivoi',
'apps.tag_list' => 'Tagi lista',
'apps.add_tag' => 'Lisää tagi',
'apps.tag_name' => 'Tagin nimi',
'apps.tags' => 'Tagit',
'apps.override' => 'Jos eri kuin pää-osoite',
'apps.preview' => 'Esikatsele',
'user.user_list' => 'Käyttäjät',
'user.add_user' => 'Lisää käyttäjä',
'user.username' => 'Käyttäjänimi',
'user.avatar' => 'Avatar',
'user.email' => 'Sähköposti',
'user.password_confirm' => 'Vahvista salasana',
'user.secure_front' => 'Salli yleinen pääsy etusivulle - Pakotetaan ainoastaan jos salasana on asetettu.',
'user.autologin' => 'Salli sisäänkirjautuminen tietystä URLista. Linkilläk uka tahansa pystyy kirjautua.',
'url' => 'Url',
'title' => 'Otsikko',
'delete' => 'Poistaa',
'optional' => 'Valinnainen',
'restore' => 'Palauta',
'alert.success.item_created' => 'Kohde luotu onnistuneesti',
'alert.success.item_updated' => 'Kohde päivitetty onnistuneesti',
'alert.success.item_deleted' => 'Kohde poistettu onnistuneesti',
'alert.success.item_restored' => 'Kohde palautettu onnistuneesti',
'alert.success.tag_created' => 'Tagi luotu onnistuneesti',
'alert.success.tag_updated' => 'Tagi päivitetty onnistuneesti',
'alert.success.tag_deleted' => 'Tagi poistettu onnistuneesti',
'alert.success.tag_restored' => 'Tagi palautettu onnistuneesti',
'alert.success.updating' => 'Päivitetään sovelluslistaa',
'alert.success.setting_updated' => 'Asetus muokattu onnistuneesti',
'alert.error.not_exist' => 'Tätä asetusta ei ole olemassa.',
'alert.success.user_created' => 'Käyttäjä luotu onnistuneesti',
'alert.success.user_updated' => 'Käyttäjä päivitetty onnistuneesti',
'alert.success.user_deleted' => 'Käyttäjä poistettu onnistuneesti',
'alert.success.user_restored' => 'Käyttäjä palautettu onnistuneesti',
];
return array (
'settings.system' => 'Järjestelmä',
'settings.appearance' => 'Ulkonäkö',
'settings.miscellaneous' => 'Sekalainen',
'settings.advanced' => 'Pitkälle kehittynyt',
'settings.support' => 'Tue',
'settings.donate' => 'Lahjoita',
'settings.version' => 'Versio',
'settings.background_image' => 'Taustakuva',
'settings.window_target' => 'Linkit aukeaa',
'settings.window_target.current' => 'Avaa tässä välilehdessä',
'settings.window_target.one' => 'Avaa samassa välilehdessä',
'settings.window_target.new' => 'Avaa uudessa välilehdessä',
'settings.homepage_search' => 'Kotisivu Haku',
'settings.search_provider' => 'Hakupalvelu',
'settings.language' => 'Kieli',
'settings.reset' => 'Palauta oletusasetukset',
'settings.remove' => 'Poista',
'settings.search' => 'haku',
'settings.no_items' => 'Kohteita ei löytynyt',
'settings.label' => 'Etiketti',
'settings.value' => 'Arvo',
'settings.edit' => 'Muokkaa',
'settings.view' => 'Näkymä',
'settings.custom_css' => 'Mukautettu CSS',
'settings.custom_js' => 'Mukautettu JavaScript',
'options.none' => '- ei asetettu -',
'options.google' => 'Google',
'options.ddg' => 'DuckDuckGo',
'options.bing' => 'Bing',
'options.qwant' => 'Qwant',
'options.startpage' => 'Etusivu',
'options.yes' => 'Kyllä',
'options.no' => 'Ei',
'options.nzbhydra' => 'NZBHydra',
'options.jackett' => 'Jackett',
'buttons.save' => 'Tallenna',
'buttons.cancel' => 'Peruuta',
'buttons.add' => 'Lisää',
'buttons.upload' => 'Lataa tiedosto',
'buttons.downloadapps' => 'Päivitä sovelluslistaa',
'dash.pin_item' => 'Kiinnitä kohde hallintapaneliin',
'dash.no_apps' => 'Tällä hetkellä ei ole kiinnitettyjä sovelluksia :link1 tai :link2',
'dash.link1' => 'Lisää sovellus tähän',
'dash.link2' => 'Kiinnitä kohde hallintapaneliin',
'dash.pinned_items' => 'Kiinnitetyt Kohteet',
'apps.app_list' => 'Sovellusluettelo',
'apps.view_trash' => 'Näytä roskakori',
'apps.add_application' => 'Lisää sovellus',
'apps.application_name' => 'Sovelluksen nimi',
'apps.colour' => 'Väri',
'apps.icon' => 'Kuvake',
'apps.pinned' => 'Kiinnitetty',
'apps.title' => 'Otsikko',
'apps.hex' => 'Hex väri',
'apps.username' => 'Käyttäjätunnus',
'apps.password' => 'Salasana',
'apps.config' => 'Konfiguraatio',
'apps.apikey' => 'API Avain',
'apps.enable' => 'Aktivoi',
'apps.tag_list' => 'Tagi lista',
'apps.add_tag' => 'Lisää tagi',
'apps.tag_name' => 'Tagin nimi',
'apps.tags' => 'Tagit',
'apps.override' => 'Jos eri kuin pää-osoite',
'apps.preview' => 'Esikatsele',
'apps.apptype' => 'Sovellustyyppi',
'apps.website' => 'Verkkosivusto',
'apps.description' => 'Kuvaus',
'apps.only_admin_account' => 'Vain jos sinulla on admin-tili!',
'apps.autologin_url' => 'Automaattisen kirjautumisen url',
'apps.show_deleted' => 'Näytetään poistetut sovellukset',
'dashboard' => 'Etusivun kojelauta',
'user.user_list' => 'Käyttäjät',
'user.add_user' => 'Lisää käyttäjä',
'user.username' => 'Käyttäjänimi',
'user.avatar' => 'Avatar',
'user.email' => 'Sähköposti',
'user.password_confirm' => 'Vahvista salasana',
'user.secure_front' => 'Salli yleinen pääsy etusivulle - Pakotetaan ainoastaan jos salasana on asetettu.',
'user.autologin' => 'Salli sisäänkirjautuminen tietystä URLista. Linkilläk uka tahansa pystyy kirjautua.',
'url' => 'Url',
'title' => 'Otsikko',
'delete' => 'Poistaa',
'optional' => 'Valinnainen',
'restore' => 'Palauta',
'alert.success.item_created' => 'Kohde luotu onnistuneesti',
'alert.success.item_updated' => 'Kohde päivitetty onnistuneesti',
'alert.success.item_deleted' => 'Kohde poistettu onnistuneesti',
'alert.success.item_restored' => 'Kohde palautettu onnistuneesti',
'alert.success.updating' => 'Päivitetään sovelluslistaa',
'alert.success.tag_created' => 'Tagi luotu onnistuneesti',
'alert.success.tag_updated' => 'Tagi päivitetty onnistuneesti',
'alert.success.tag_deleted' => 'Tagi poistettu onnistuneesti',
'alert.success.tag_restored' => 'Tagi palautettu onnistuneesti',
'alert.success.setting_updated' => 'Asetus muokattu onnistuneesti',
'alert.error.not_exist' => 'Tätä asetusta ei ole olemassa.',
'alert.success.user_created' => 'Käyttäjä luotu onnistuneesti',
'alert.success.user_updated' => 'Käyttäjä päivitetty onnistuneesti',
'alert.success.user_deleted' => 'Käyttäjä poistettu onnistuneesti',
'alert.success.user_restored' => 'Käyttäjä palautettu onnistuneesti',
'dashboard.reorder' => 'Järjestä ja kiinnitä kohteita uudelleen',
'dashboard.settings' => 'asetukset',
);

View File

@@ -0,0 +1,6 @@
<?php
return array (
'failed' => 'Nämä valtuustiedot eivät vastaa tietueitamme.',
'throttle' => 'Liian monta kirjautumisyritystä. Yritä uudelleen :seconds sekunnin kuluttua.',
);

View File

@@ -0,0 +1,6 @@
<?php
return array (
'previous' => '&laquo; Edellinen',
'next' => 'Seuraava &raquo;',
);

View File

@@ -0,0 +1,9 @@
<?php
return array (
'password' => 'Salasanassa on oltava vähintään kuusi merkkiä ja vastattava vahvistusta.',
'reset' => 'Salasanasi on nollattu!',
'sent' => 'Olemme lähettäneet salasanan palautuslinkin sähköpostitse!',
'token' => 'Tämä salasanan palautustunnus on virheellinen.',
'user' => 'Emme löydä käyttäjää tällä sähköpostiosoitteella.',
);

View File

@@ -1,114 +1,106 @@
<?php
return [
'settings.system' => 'Système',
'settings.appearance' => 'Apparence',
'settings.miscellaneous' => 'Divers',
'settings.support' => 'Support',
'settings.donate' => 'Contribuer',
'settings.advanced' => 'Options avancées',
'settings.version' => 'Version',
'settings.background_image' => 'Image d\'arrière-plan',
'settings.window_target' => 'Ouverture des liens',
'settings.window_target.current' => 'Dans l\'onglet courant',
'settings.window_target.one' => 'Dans le même nouvel onglet',
'settings.window_target.new' => 'Dans un nouvel onglet',
'settings.homepage_search' => 'Barre de recherche',
'settings.search_provider' => 'Moteur de recherche',
'settings.language' => 'Langue',
'settings.reset' => 'Réinitialiser les valeurs par défaut',
'settings.remove' => 'Supprimer',
'settings.search' => 'Chercher',
'settings.no_items' => 'Aucun élement trouvé',
'settings.label' => 'Étiquette',
'settings.value' => 'Valeur',
'settings.edit' => 'Modifier',
'settings.view' => 'Vue',
'options.none' => '- non défini -',
'options.google' => 'Google',
'options.ddg' => 'DuckDuckGo',
'options.bing' => 'Bing',
'options.qwant' => 'Qwant',
'options.startpage' => 'Page d\'accueil',
'options.yes' => 'Oui',
'options.no' => 'Non',
'options.nzbhydra' => 'NZBHydra',
'options.jackett' => 'Jackett',
'buttons.save' => 'Enregistrer',
'buttons.cancel' => 'Annuler',
'buttons.add' => 'Ajouter',
'buttons.upload' => 'Choisir un fichier',
'buttons.downloadapps' => 'Mettre à jour la liste',
'dash.pin_item' => 'Épingler l\'application au tableau de bord',
'dash.no_apps' => 'Il n\'existe actuellement aucune application épinglée :link1 ou :link2',
'dash.link1' => 'Ajouter une application',
'dash.link2' => 'Épingler une application au tableau de bord',
'dash.pinned_items' => 'Applications épinglées',
'apps.app_list' => 'Liste des applications',
'apps.view_trash' => 'Voir la corbeille',
'apps.add_application' => 'Ajouter une application',
'apps.application_name' => 'Nom de l\'application',
'apps.colour' => 'Couleur',
'apps.icon' => 'Icône',
'apps.pinned' => 'Épinglée',
'apps.title' => 'Titre',
'apps.hex' => 'Hexadécimal de la couleur',
'apps.username' => 'Nom d\'utilisateur',
'apps.password' => 'Mot de passe',
'apps.config' => 'Config',
'apps.apikey' => 'Clé de l\'API',
'apps.enable' => 'Actif',
'apps.tag_list' => 'Liste des labels',
'apps.add_tag' => 'Ajouter un label',
'apps.tag_name' => 'Nom du label',
'apps.tags' => 'Labels',
'apps.override' => 'Si différent de l\'url actuelle',
'apps.preview' => 'Aperçu',
'apps.apptype' => 'Type d\'application ',
'apps.only_admin_account' => 'Seulement si vous avez un compte administrateur!',
'apps.autologin_url' => 'URL de connexion automatique',
'apps.show_deleted' => 'Afficher les applications supprimées',
'dashboard' => 'Tableau de bord',
'user.user_list' => 'Utilisateurs',
'user.add_user' => 'Ajouter un utilisateur',
'user.username' => 'Nom d\'utilisateur',
'user.avatar' => 'Avatar',
'user.email' => 'Email',
'user.password_confirm' => 'Confirmer le mot de passe',
'user.secure_front' => 'Autoriser l\'accès public au front - Uniquement appliqué si un mot de passe est défini.',
'user.autologin' => 'Autorisez la connexion à partir d\'une URL spécifique. Toute personne disposant du lien peut se connecter.',
'url' => 'Url',
'title' => 'Titre',
'delete' => 'Effacer',
'optional' => 'Optionnel',
'restore' => 'Restaurer',
'alert.success.item_created' => 'Application créée avec succès',
'alert.success.item_updated' => 'Application mise à jour avec succès',
'alert.success.item_deleted' => 'Application supprimée avec succès',
'alert.success.item_restored' => 'Application restaurée avec succès',
'alert.success.updating' => 'Liste des applications mise à jour avec succès',
'alert.success.tag_created' => 'Label crée avec succès',
'alert.success.tag_updated' => 'Label mis à jour avec succès',
'alert.success.tag_deleted' => 'Label supprimé avec succès',
'alert.success.tag_restored' => 'Label restauré avec succès',
'alert.success.setting_updated' => 'Paramètre mis à jour avec succès',
'alert.error.not_exist' => 'Ce paramètre n\'existe pas.',
'alert.success.user_created' => 'Utilisateur crée avec succès',
'alert.success.user_updated' => 'Utilisateur mis à jour avec succès',
'alert.success.user_deleted' => 'Utilisateur supprimé avec succès',
'alert.success.user_restored' => 'Utilisateur restoré avec succès',
];
return array (
'settings.system' => 'Système',
'settings.appearance' => 'Apparence',
'settings.miscellaneous' => 'Divers',
'settings.advanced' => 'Options avancées',
'settings.support' => 'Support',
'settings.donate' => 'Contribuer',
'settings.version' => 'Version',
'settings.background_image' => 'Image d\'arrière-plan',
'settings.window_target' => 'Ouverture des liens',
'settings.window_target.current' => 'Dans l\'onglet courant',
'settings.window_target.one' => 'Dans le même nouvel onglet',
'settings.window_target.new' => 'Dans un nouvel onglet',
'settings.homepage_search' => 'Barre de recherche',
'settings.search_provider' => 'Moteur de recherche',
'settings.language' => 'Langue',
'settings.reset' => 'Réinitialiser les valeurs par défaut',
'settings.remove' => 'Supprimer',
'settings.search' => 'Chercher',
'settings.no_items' => 'Aucun élement trouvé',
'settings.label' => 'Étiquette',
'settings.value' => 'Valeur',
'settings.edit' => 'Modifier',
'settings.view' => 'Vue',
'settings.custom_css' => 'CSS personnalisé',
'settings.custom_js' => 'JavaScript personnalisé',
'options.none' => '- non défini -',
'options.google' => 'Google',
'options.ddg' => 'DuckDuckGo',
'options.bing' => 'Bing',
'options.qwant' => 'Qwant',
'options.startpage' => 'Page d\'accueil',
'options.yes' => 'Oui',
'options.no' => 'Non',
'options.nzbhydra' => 'NZBHydra',
'options.jackett' => 'Jackett',
'buttons.save' => 'Enregistrer',
'buttons.cancel' => 'Annuler',
'buttons.add' => 'Ajouter',
'buttons.upload' => 'Choisir un fichier',
'buttons.downloadapps' => 'Mettre à jour la liste',
'dash.pin_item' => 'Épingler l\'application au tableau de bord',
'dash.no_apps' => 'Il n\'existe actuellement aucune application épinglée :link1 ou :link2',
'dash.link1' => 'Ajouter une application',
'dash.link2' => 'Épingler une application au tableau de bord',
'dash.pinned_items' => 'Applications épinglées',
'apps.app_list' => 'Liste des applications',
'apps.view_trash' => 'Voir la corbeille',
'apps.add_application' => 'Ajouter une application',
'apps.application_name' => 'Nom de l\'application',
'apps.colour' => 'Couleur',
'apps.icon' => 'Icône',
'apps.pinned' => 'Épinglée',
'apps.title' => 'Titre',
'apps.hex' => 'Hexadécimal de la couleur',
'apps.username' => 'Nom d\'utilisateur',
'apps.password' => 'Mot de passe',
'apps.config' => 'Config',
'apps.apikey' => 'Clé de l\'API',
'apps.enable' => 'Actif',
'apps.tag_list' => 'Liste des labels',
'apps.add_tag' => 'Ajouter un label',
'apps.tag_name' => 'Nom du label',
'apps.tags' => 'Labels',
'apps.override' => 'Si différent de l\'url actuelle',
'apps.preview' => 'Aperçu',
'apps.apptype' => 'Type d\'application ',
'apps.website' => 'Site Web',
'apps.description' => 'Description',
'apps.only_admin_account' => 'Seulement si vous avez un compte administrateur!',
'apps.autologin_url' => 'URL de connexion automatique',
'apps.show_deleted' => 'Afficher les applications supprimées',
'dashboard' => 'Tableau de bord',
'user.user_list' => 'Utilisateurs',
'user.add_user' => 'Ajouter un utilisateur',
'user.username' => 'Nom d\'utilisateur',
'user.avatar' => 'Avatar',
'user.email' => 'Email',
'user.password_confirm' => 'Confirmer le mot de passe',
'user.secure_front' => 'Autoriser l\'accès public au front - Uniquement appliqué si un mot de passe est défini.',
'user.autologin' => 'Autorisez la connexion à partir d\'une URL spécifique. Toute personne disposant du lien peut se connecter.',
'url' => 'Url',
'title' => 'Titre',
'delete' => 'Effacer',
'optional' => 'Optionnel',
'restore' => 'Restaurer',
'alert.success.item_created' => 'Application créée avec succès',
'alert.success.item_updated' => 'Application mise à jour avec succès',
'alert.success.item_deleted' => 'Application supprimée avec succès',
'alert.success.item_restored' => 'Application restaurée avec succès',
'alert.success.updating' => 'Liste des applications mise à jour avec succès',
'alert.success.tag_created' => 'Label crée avec succès',
'alert.success.tag_updated' => 'Label mis à jour avec succès',
'alert.success.tag_deleted' => 'Label supprimé avec succès',
'alert.success.tag_restored' => 'Label restauré avec succès',
'alert.success.setting_updated' => 'Paramètre mis à jour avec succès',
'alert.error.not_exist' => 'Ce paramètre n\'existe pas.',
'alert.success.user_created' => 'Utilisateur crée avec succès',
'alert.success.user_updated' => 'Utilisateur mis à jour avec succès',
'alert.success.user_deleted' => 'Utilisateur supprimé avec succès',
'alert.success.user_restored' => 'Utilisateur restoré avec succès',
'dashboard.reorder' => 'Réorganiser et épingler les éléments',
'dashboard.settings' => 'Réglages',
);

View File

@@ -1,19 +1,6 @@
<?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' => 'Ces informations d\'identification ne correspondent pas à nos enregistrements.',
'throttle' => 'Trop de tentatives de connexion. Veuillez réessayer dans :seconds secondes.',
];
return array (
'failed' => 'Ces informations d\'identification ne correspondent pas à nos enregistrements.',
'throttle' => 'Trop de tentatives de connexion. Veuillez réessayer dans :seconds secondes.',
);

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