Compare commits

..

281 commits
2.1.2 ... main

Author SHA1 Message Date
corbpie
525b1d29f0
Merge pull request #119 from cp6/dev3
3.0.0
2024-12-28 21:44:55 +11:00
cp6
2cd623d49e Updated README.md 2024-12-09 23:15:03 +11:00
cp6
79cc41c729 Fixed osIntToIcon() giving wrong icon 2024-12-09 22:48:50 +11:00
cp6
a91047dacf Fixed error in call when fetching IP who is data 2024-12-09 22:37:13 +11:00
cp6
00701650e6 Updated composer.lock file 2024-12-09 20:27:03 +11:00
cp6
8ffbe79a60 Updated README.md 2024-12-09 20:26:04 +11:00
cp6
5445e9d67f Added note to API 2024-12-09 19:09:20 +11:00
cp6
6f59fb628c Removed logging 2024-12-09 18:58:26 +11:00
cp6
97585e0f5b Added IP who is data fetch and update 2024-12-09 18:58:02 +11:00
cp6
146bd64803 Updated README.md 2024-12-09 17:05:17 +11:00
cp6
3b7c587249 Removed user being seeded 2024-12-09 17:03:32 +11:00
cp6
c662710300 Added IP who is data columns to the ips table 2024-12-09 16:59:04 +11:00
cp6
d180779133 Updated back and submit buttons in reseller and shared create to use new icon button components 2024-12-09 16:53:15 +11:00
cp6
37032e0344 Added icon to back-button.blade.php and submit-button.blade.php 2024-12-09 16:52:44 +11:00
cp6
71ab8e36ca Updated domains index "due in" column to format massive floats 2024-12-09 16:47:06 +11:00
cp6
946fe9b893 Added Datatables to domain index for sorting and searching ability 2024-12-09 16:45:31 +11:00
cp6
29b0f2aed1 Added Datatables to reseller index for sorting and searching ability 2024-12-09 16:44:07 +11:00
cp6
19a0f2f646 Added Datatables to shared index for sorting and searching ability 2024-12-09 16:42:43 +11:00
cp6
a7cce1cfff Minor update to servers index page formatting 2024-12-09 16:34:21 +11:00
cp6
44766c8fdd Updated osIntToIcon() 2024-12-09 16:33:12 +11:00
cp6
1666d57a9b Added OS's to OsSeeder.php 2024-12-09 16:32:49 +11:00
cp6
5ebbcce44c Updated webpack and package.json dependencies versions. NPM run dev 2024-12-09 16:24:07 +11:00
cp6
ac580c23ed Added fa-brands 2024-12-09 16:23:18 +11:00
cp6
526f360f2c Added datatables to server/index for sorting and searching ability.
Updated days due in to no longer give 8 digit long floats
2024-12-09 15:49:41 +11:00
cp6
720dc50852 Removed prefers-color-scheme: dark for .card 2024-12-09 15:37:59 +11:00
cp6
fcfa44f94f PHP 8.3 2024-12-09 15:37:23 +11:00
cp6
9f4738c75e Updated dependencies 2024-12-09 15:32:52 +11:00
cp6
cc9f585f5b Updated README.md 2024-05-14 22:52:25 +10:00
cp6
157e3edf5e Compiled styles 2024-05-14 22:52:15 +10:00
cp6
4b07be6417 Added darker card background style to style.css 2024-05-14 22:49:03 +10:00
cp6
12b7a81479 Updated submit-button to be py-1 2024-05-14 22:45:47 +10:00
cp6
c944fb907f Updated back-button to be py-1 2024-05-14 22:45:33 +10:00
cp6
d2237b74a6 Updated readme 2024-05-14 22:41:37 +10:00
cp6
6a5c6b7a61 Updated routes in web.php to use more readable format 2024-05-14 22:35:11 +10:00
cp6
9704ebc561 Added grouped middleware for auth 2024-05-14 22:31:30 +10:00
cp6
9d2cf82c31 Removed comments from web.php 2024-05-14 22:28:05 +10:00
cp6
f9e39e74bc Updated login and register form layout slightly 2024-05-14 22:27:08 +10:00
cp6
6e55018974 Fixed for settings not existing MK2 2024-05-14 21:52:38 +10:00
cp6
1aab332ef8 Fix for settings not existing 2024-05-14 21:52:13 +10:00
cp6
cd41dcdfff Updated PHP version in Dockerfile 2024-05-14 21:42:44 +10:00
cp6
2172236463 Updated assets 2024-05-14 21:42:02 +10:00
cp6
c9aa314155 Updated assets 2024-05-14 21:39:08 +10:00
cp6
5797e8c30a Fixed issue 104 2024-05-08 22:01:06 +10:00
cp6
c10d77d46b Updated package.json 2024-05-02 23:07:37 +10:00
cp6
ddecd8125e Updated Readme for v3.0.0 2024-05-02 23:01:13 +10:00
cp6
c5422fac09 Updated PHP version to 8.2
Updated Laravel version to 11
Updated packages
2024-05-02 23:00:26 +10:00
corbpie
25ff23d98d
Update README.md 2024-03-08 23:46:29 +11:00
corbpie
6df8b27337
Merge pull request #103 from HRA42/main
Added Arm Support
2023-11-21 11:26:06 +11:00
Henry Rausch
32580be6b4
Build and push Docker image with Buildx
The commit adds steps to build and push a Docker image using Buildx in the GitHub Actions workflow. It includes checking out the repository, installing the cosign tool, setting up Docker buildx, logging into the Docker registry, extracting metadata for Docker, and finally building and pushing the Docker image with the specified tags and platforms. The commit ensures that the image is only pushed when the event name is not a pull request.
2023-11-16 23:46:25 +01:00
Henry Rausch
0c3dd6b7e2
Update docker image push configuration
Changed the repository for pushing the docker image to GHCR from `ghcr.io/cp6/my-idlers` to `ghcr.io/hra42/my-idlers-arm64` in order to align with the updated repository naming convention.
2023-11-16 23:41:33 +01:00
Henry Rausch
27a0cd494a
Update tags in GitHub Actions workflow
This commit updates the tags in the GitHub Actions workflow for building Docker images. The previous tags `ghcr.io/cp6/my-idlers` are replaced with `ghcr.io/hra42/my-idlers-arm64`. This change ensures that the correct tags are used for the Docker image.
2023-11-16 23:38:46 +01:00
Henry Rausch
53bdc596a5
Build container image with support for both Linux/amd64 and Linux/arm64 platforms. 2023-11-16 23:37:00 +01:00
corbpie
2b1cfa0787
Merge pull request #101 from Gamerboy59/main
Update resources and remove duplicated webfa files
2023-10-06 09:31:54 +11:00
Gamerboy59
72c49d8e60
fixed some namings of the webfonts 2023-10-05 16:51:42 +02:00
Gamerboy59
8ee3a1ee43
Move webfa from css to public folder 2023-10-05 16:12:20 +02:00
Gamerboy59
60df780917 Update public resources 2023-09-26 23:26:24 +00:00
Gamerboy59
2f6078ac1c
make font url relative 2023-09-27 01:23:46 +02:00
Gamerboy59
8c1878267b
remove more duplicated webfa font files 2023-09-27 01:02:20 +02:00
Gamerboy59
0b2a6c6a49 Update public resources 2023-09-26 22:47:22 +00:00
Gamerboy59
3cf049f1be
fix folder structure to not duplicate again 2023-09-27 00:40:26 +02:00
Gamerboy59
8561e9c4b8
Add missing sass loader for mix 2023-09-27 00:11:20 +02:00
Gamerboy59
642293016f
remove duplicated font-files 2023-09-27 00:07:33 +02:00
corbpie
5ce233bfb8
Updated README.md for 2.3.2
Updated README.md for 2.3.2
2023-09-26 22:48:19 +10:00
corbpie
b8f5ee223d
Merge pull request #99 from cp6/dev
Added Geekbench 6
2023-09-26 22:42:11 +10:00
cp6
918320c876 servers\index.blade.php cleanup
servers\index.blade.php cleanup
2023-09-25 23:45:07 +10:00
cp6
ebf4e5243c Added LabelsAssigned::create into try catch
Added LabelsAssigned::create into try catch
2023-09-25 23:40:13 +10:00
cp6
f4bd6e6d66 Updated tests
Updated tests
1 was failing due to redirect for when no users exist
2023-09-24 21:35:34 +10:00
cp6
4179f70a4f Update home blade
Made Session conditional for showing details in footer to be 1 step
2023-09-22 11:01:56 +10:00
cp6
c296bd6be4 Updated details footer blade 2023-09-22 10:59:51 +10:00
cp6
76c7b0395d Updated details footer blade component
Made Session check conditional 1 step
2023-09-22 10:58:58 +10:00
cp6
da14c2dde3 Added GB6 values to server show and public show
Added GB6 values to server show and public show
2023-09-21 22:24:02 +10:00
cp6
827fc57af6 Update README.md 2023-09-20 22:33:39 +10:00
cp6
cca325cf2d Added geekbench 6 to Yabs
Added geekbench 6 inserts and varaibles to Yabs model
Updated JSON values accessor to include version 5 still
2023-09-20 22:26:00 +10:00
cp6
c19d831da5 Created migration for YABS geekbench 6 values
Created migration for YABS geekbench 6 values
2023-09-20 22:21:49 +10:00
cp6
df15ea3141 Formatting 2023-09-19 22:48:30 +10:00
cp6
047260b953 Added tabs to home page for stats and avg cards 2023-09-19 22:47:24 +10:00
corbpie
d4b75b204f
Update README.md
Added TODO for Geekbench 6 scores
2023-09-15 16:24:50 +10:00
cp6
5e6c0a60ff Removed unused ExampleComponent.vue 2023-09-14 23:53:05 +10:00
cp6
cfbc1bf3ca Updated homepage tables to remove card with padding, made tables rounded 2023-09-14 23:50:07 +10:00
cp6
f44c69caed Fixed save_yabs_as_txt causing settings update to fail validation 2023-09-14 23:44:27 +10:00
cp6
b2595fc920 Fixed pricing breakdown cache not being refreshed 2023-09-14 23:38:46 +10:00
cp6
e48678130a Removed YABS GB5 table row from server show
Removed YABS GB5 table row from server show
Need to implement GB6
2023-09-12 22:22:52 +10:00
cp6
25d338bc24 Update README.md 2023-09-11 23:32:37 +10:00
cp6
aadfc481ac timestamps false for LabelsAssigned
timestamps false for LabelsAssigned
2023-09-11 23:32:07 +10:00
corbpie
266d67f986
Merge pull request #95 from Gamerboy59/main
Fix for accessing an object instead of an array
2023-09-10 02:01:12 +10:00
Gamerboy59
3f4c46edbc
Fix for accessing an object instead of an array 2023-09-09 16:13:13 +02:00
cp6
ec2947936b Fix for accessing an object instead of an array
Fix for accessing an object instead of an array
2023-09-09 23:14:07 +10:00
cp6
6bbbc232bd Removed un-needed imports in Controllers 2023-08-20 21:25:45 +10:00
cp6
f0178ac74f Removed un-needed imports 2023-08-20 21:25:22 +10:00
cp6
966ff38320 Unused cleanup 2023-08-19 23:59:51 +10:00
cp6
7fcbd53c84 Cleaned up unused file imports 2023-08-19 23:58:51 +10:00
cp6
b20e405906 Used Eloquent 2023-08-19 23:58:25 +10:00
cp6
b512caecc7 Updated to use Eloquent rather than DB::table() 2023-08-19 23:52:59 +10:00
cp6
ae9b23cba7 Added return types 2023-08-19 23:48:34 +10:00
cp6
3bef30d861 Removed un unused create() and store() from YabsController.php 2023-08-19 23:46:52 +10:00
cp6
507f128bf6 Added return types 2023-08-19 23:46:18 +10:00
cp6
455cf45c29 Cleaned up Server.php
Added Return types on relations
2023-08-18 19:35:53 +10:00
cp6
afe5c1e525 Cleaned up queries that had un-needed '=' 2023-08-18 19:33:26 +10:00
cp6
877592f614 Updated count 2023-08-18 19:31:21 +10:00
cp6
e100203331 Updated counts to use Eloquent 2023-08-18 19:28:53 +10:00
cp6
65f0474ebe Merge remote-tracking branch 'origin/main' into main 2023-08-18 19:26:14 +10:00
cp6
de66fb2852 Fixed spelling mistake in array key 2023-08-18 19:26:00 +10:00
corbpie
c448a27a04
Update README.md for 2.3.1
Update README.md for 2.3.1
2023-08-17 22:03:01 +10:00
corbpie
3b82fd6564
Update README.md for 2.3.1
Update README.md for 2.3.1
2023-08-17 22:02:41 +10:00
corbpie
171eb63b9a
Update Pricing.php
Updated allPricing() to only be for active services, changed its cache name so this will instantly populate and work
2023-08-15 19:04:56 +10:00
corbpie
0aeb38d516
Merge pull request #92 from Gamerboy59/main
Update resources and fix register/login page
2023-08-07 17:44:48 +10:00
Gamerboy59
349599288b
Fix resource links 2023-08-06 13:34:28 +02:00
Gamerboy59
02c15e9622
Fix resource links 2023-08-06 13:29:41 +02:00
Gamerboy59
fcb99b1e31 Update css/js resources 2023-08-06 11:09:08 +00:00
Gamerboy59
72f22be781
Update package.json 2023-08-06 12:36:16 +02:00
Gamerboy59
e82941ba35
Update composer.json 2023-08-06 12:29:41 +02:00
cp6
5dbc6a5be5 Updated readme for version 2.3 2023-03-31 11:57:38 +11:00
cp6
a683f0ea42 Updated Settings.php
getSettings() now uses Eloquent rather than DB
Gave getSettings() return type of Settings
2023-03-31 11:56:18 +11:00
cp6
f488e10c2f Updated array() usages to be [] 2023-03-31 11:38:21 +11:00
cp6
8a6748f1b0 Added ability to upload own favicon
Must be either .ico, .jpg or .png format and under 40KB
Upload is done in /settings
Also removed save YABS to text input in settings form
2023-03-31 11:31:19 +11:00
cp6
f619f34081 Merge remote-tracking branch 'origin/main' into main 2023-03-30 23:16:45 +11:00
cp6
4dbfe6f7bd Removed CSS and JS files as these are no longer needed with the use of webpack 2023-03-30 23:16:27 +11:00
corbpie
2708d37450
Updated readme for 2.2.1 2023-03-20 23:41:30 +11:00
cp6
c24056c511 Fix for issue 89
Locations, OS and Providers now Alpha-Sorted correctly
2023-03-20 10:37:28 +11:00
cp6
39b9033bf8 Updated readme for version 2.2 2023-02-19 13:12:59 +11:00
corbpie
6e9591719e
Merge pull request #85 from Gamerboy59/laravel-10
Laravel 10 update
2023-02-19 13:02:42 +11:00
Gamerboy59
7ed69cbbc2
Delete package-lock.json
No specific functionality of a version is used thus I see no point in having this file as maintance overhead. Everybody should install the latest subversion.
2023-02-14 18:58:24 +01:00
Gamerboy59
102f02b064
Update package.json
Maybe devDeps and deps should be re-sorted.
2023-02-14 18:54:06 +01:00
Gamerboy59
792f010f27
Update Kernel.php
Use build in cors module of Laravel/framework which should work like the version of fruitcake.
2023-02-14 18:28:58 +01:00
Gamerboy59
cd03865162
Delete composer.lock
In my view it doesn't make sense to keep exact versions locked because no specific functions of such are used.
2023-02-14 18:27:43 +01:00
Gamerboy59
ba21329a20
Update composer.json
I havn't tested the dev dependencies and just used what composer put out as generated update. Everything seems to be working even the used functions of Guzzle appear working on php8.2 which isn't officially supported for this version. Fruitcake/cors is now part of Laravel/framework.
2023-02-14 18:25:37 +01:00
corbpie
6ecf12c226
Merge pull request #84 from Gamerboy59/appname-patch
Use app name at more places in app
2023-02-14 14:42:56 +11:00
Gamerboy59
7f83b922d2
Use app name at more places in app 2023-01-17 23:11:59 +01:00
cp6
7f88a38c73 Updated gitignore for fonts to be included
Updated gitignore for fonts to be included
2022-12-02 15:02:06 +11:00
corbpie
036122cfd8
Merge pull request #82 from cp6/Development
Updated version in readme
2022-12-02 14:36:40 +11:00
cp6
6f8d8cec37 Updated version in readme
Updated version in readme
2022-12-02 14:35:42 +11:00
corbpie
159d17e77b
Merge pull request #81 from cp6/Development
Development 2.1.9
2022-12-02 14:35:14 +11:00
cp6
055443f917 Updated readme
Updated readme
2022-12-02 14:28:45 +11:00
cp6
5dd23f6a46 Updated create views to replace previous sponsor provider as default
Updated create views to replace the previous sponsor provider that was the default
2022-12-02 14:09:00 +11:00
cp6
a01110dcd0 Added public css and js to .gitattributes
Added public css and js to .gitattributes
These do not need to be tracked
2022-12-02 14:03:07 +11:00
cp6
89525fd1c1 Added compiled assets
Added compiled assets so there can be no need to run NPM
2022-12-02 13:59:47 +11:00
cp6
e77c402aba Notes table migration (create)
Notes table migration (create)
2022-12-02 13:57:55 +11:00
cp6
924415eb66 Added & implemented notes
Added & implemented notes to servers, shared, reseller, domains, DNS and IPs

/notes is a CRUD resource
2022-12-02 13:57:28 +11:00
corbpie
1572ceaec8
Update README.md 2022-12-01 15:09:43 +11:00
cp6
0f0b06ee47 Updated readme for NPM usage
Updated readme for NPM usage
2022-11-13 21:58:01 +11:00
corbpie
14f1e808eb
Merge pull request #78 from cp6/Development
Changes for the move to NPM Webpack asset loading
2022-11-13 21:44:13 +11:00
cp6
28e58475b1 Updated package.json for "build"
Updated package.json for "build"
2022-11-13 16:27:34 +11:00
cp6
d16af57799 Added Datatables Bootstrap 5 package
Added Datatables Bootstrap 5 package
2022-11-13 15:55:34 +11:00
cp6
908b8df495 Updated server create blade view
Updated server create blade view for NPM webpack usage
2022-11-13 15:54:43 +11:00
cp6
26356b3cd7 Updated server index blade view
Updated server index blade view for NPM webpack usage
2022-11-13 15:54:27 +11:00
cp6
f0903e08f4 Updated app.blade.php for NPM webpack
Updated app.blade.php for NPM webpack
2022-11-13 15:53:57 +11:00
cp6
68f1d331f9 Updated index view blade for NPM webpack usage
Updated index view blade for NPM webpack usage
2022-11-13 15:53:05 +11:00
cp6
84902191e5 Updated delete modal component
Updated delete modal component to display none initially and have the id "confirmDeleteModal" to remove this class. This prevents the modal flashing up briefly on page laod
2022-11-13 15:47:24 +11:00
cp6
a9a3bc1ca1 Updated delete modal script to load after page loaded
Updated delete modal script to load after page loaded
2022-11-13 15:46:12 +11:00
cp6
7a2ed8887f Updated style.css to have the wide max width
Updated style.css to have the wide max width
2022-11-13 15:45:18 +11:00
cp6
290b11952b Added datatables bootstrap 5 to app.css
Added datatables bootstrap 5 to app.css
2022-11-13 15:44:53 +11:00
cp6
407d2b3368 Added axios and datatables bootstrap 5 to app.js
Added axios and datatables bootstrap 5 to app.js
2022-11-13 15:44:32 +11:00
cp6
b2b6dc36c9 Changes for the move to NPM Webpack asset loading
Changes for the move to Webpack asset loading
Bootstrap light and dark get own CSS files still
2022-11-12 14:04:04 +11:00
cp6
322898e62e Added domains limit to Shared and Reseller index view table
Added domains limit to Shared and Reseller index view table
2022-11-11 15:15:06 +11:00
cp6
14eac80912 Removed flat input bottom radius
Removed flat input bottom radius
2022-11-10 14:53:36 +11:00
cp6
0eaf09fa92 Removed logo option from auth card
Removed logo option from auth card
2022-11-10 14:53:08 +11:00
cp6
e31a785844 Updated destroy() methods for delete condition
Updated destroy() methods for delete condition
If not true then return with the error alert
2022-11-09 15:18:25 +11:00
cp6
43d22f8e16 Updated IPsController create variable names & added seed box to input
Updated IPsController create variable names & added seed boxes to select input
2022-11-09 15:05:55 +11:00
cp6
b7c02fc4fa Removed unneeded axios.min.js fixed modal delete header title
Removed unneeded axios.min.js

Fixed modal delete header title to be the IP
2022-11-08 11:20:23 +11:00
cp6
aef969532f Removed unneeded axios.min.js
Removed unneeded axios.min.js
2022-11-08 11:19:52 +11:00
cp6
42e8982e3f Updated and fixed location delete modal not showing
Updated and fixed location delete modal not showing
2022-11-08 11:17:06 +11:00
cp6
3bd9d5890c Updated all destroy() methods
Updated all destroy() methods to directly delete the resource rather than fetch from database which turns out is not needed
2022-11-08 11:14:07 +11:00
cp6
74691a6ed8 Added max length validation for OS, Provider and Location
Added max length validation for OS, Provider and Location
2022-11-08 10:39:05 +11:00
cp6
f6dee0d256 Updated YABS index view blade
Updated YABS index view blade
2022-11-07 16:06:20 +11:00
cp6
f300ef030d Updated index view blade titles for domains & misc
Updated index view blade titles for domains & misc
2022-11-06 21:41:24 +11:00
cp6
8cfb0d76a0 Updated create view blade titles for consistency
Updated create view blade titles for consistency
2022-11-06 21:39:52 +11:00
cp6
997b07a0b7 Update YabsController return formatting & compare data check
Update YabsController return formatting
Update for an is null check on data calling
2022-11-05 12:48:07 +11:00
cp6
34a12e6ffd Updated YABS single to be first() views updated for this
Updated YABS single use first()
Updated show and compare blade views
2022-11-05 12:47:08 +11:00
cp6
a397333aca Updated home.blade.php
Removed unnecessary auth & route check conditionals
Implemented card components
Removed container div element which is duplicated from parent layout
2022-11-05 11:59:03 +11:00
cp6
237577074d Created home page service tally card component
Created home page service tally card component
2022-11-05 11:57:28 +11:00
cp6
c154e2033a Created home page info card component
Created home page info card component
2022-11-05 11:57:17 +11:00
corbpie
897044f7db
Merge pull request #77 from wky0211/main
style: capitalization
2022-11-02 23:11:17 +11:00
wky0211
f0a756660e fix: URLs of README.md 2022-11-02 12:09:17 +00:00
wky0211
6b12e764c2 style: capitalization 2022-11-02 11:02:12 +00:00
cp6
1c0a82d533 Updated Server controller and create & edit views
Uses the resource id now
No passing hidden input id
Uses alert component for response
2022-10-31 16:02:50 +11:00
cp6
1b2f501744 Updated seedbox index yo use alerts component 2022-10-31 16:02:18 +11:00
cp6
b3a0e6313c Removed unused hidden inputs from create/edit blades 2022-10-31 16:01:59 +11:00
cp6
a8e1235922 Updated account index blade view
uses alert component for response
2022-10-31 16:01:16 +11:00
cp6
9d33f8ad6e Updated Reseller controller and create & edit views
Uses the resource id now
No passing hidden input id
Uses alert component for response
2022-10-31 16:00:43 +11:00
cp6
d79c571505 Updated Shared controller and create & edit views
Updated Shared controller and create & edit views

Uses the resource id now
No passing hidden input id
Uses alert component for response
2022-10-31 16:00:00 +11:00
cp6
724b7536a7 Updated resellerHosting() input parameter name
Updated resellerHosting() input parameter name to be $reseller_id
2022-10-31 15:58:47 +11:00
cp6
f7cdaeb342 Removed unused getProviders() function
Removed unused getProviders() function
2022-10-31 15:19:27 +11:00
cp6
09307828a1 Deleted unused YABS create blade view
Deleted unused YABS create blade view
2022-10-31 15:18:20 +11:00
cp6
955c3ffd67 Update settings index blade view
Implemented components
Using new data without array index [0]
2022-10-31 14:49:47 +11:00
cp6
ac0cf82e8d SettingsController update
Updated validation
Updated index view return
Update response from update
2022-10-31 14:46:07 +11:00
cp6
ae5c541516 Implemented text input component
Implemented text input component
2022-10-31 14:42:02 +11:00
cp6
5fbadf8063 Updated text input component
Updated text input component to include placeholder and error message output if exists
2022-10-31 14:41:26 +11:00
cp6
5f18ccff2c Added and implemented a form-check input component 2022-10-31 12:02:56 +11:00
cp6
1c90ff116e Fixed Undefined array key 0 in public servers blade view
Fixed Undefined array key 0 in public servers blade view
2022-10-31 12:02:40 +11:00
cp6
d9699a2ed6 Code cleanup renamed click function
Code cleanup renamed click function from onClk to fetchDnsRecords
2022-10-31 11:48:39 +11:00
cp6
285786d1a5 Minor comment fixup
Minor comment fixup
2022-10-31 11:17:30 +11:00
cp6
a20ce989dc Fixed domain cache not clearing on settings update
Fixed domain cache not clearing on settings update
2022-10-31 11:15:28 +11:00
cp6
10e2d7dbba Fix orderByProcess() input being null
Fix orderByProcess() input being null by having the input be 2 if the settings values via the session havent  been set
2022-10-31 11:14:26 +11:00
corbpie
1c8ec5fc6b
Merge pull request #74 from cp6/Development
2.1.8 Development to main
2022-10-20 15:49:15 +11:00
cp6
a56424bcaf Updated server show page for new add YABS method
Updated server show page for new add YABS method
2022-10-20 15:45:26 +11:00
cp6
bd7ca6c1cf Updated readme
Updated readme
2022-10-20 15:41:33 +11:00
cp6
846a5c3af5 Updated readme for 2.1.8
Updated readme for 2.1.8
2022-10-20 15:40:07 +11:00
cp6
4de5beb2ea Implemented the details footer component
More Implementing of the details footer component
2022-10-20 15:33:50 +11:00
cp6
dd8564a23e Implemented the new index layout for the index pages
Implemented the new index layout for the index pages.
domains, misc, reseller, seedboxes and shared use this layout
2022-10-20 14:57:30 +11:00
cp6
25822351ef Added new index layout
Added new index layout for the index pages of the CRUD as it includes vue.js for the confirm delete modal
2022-10-20 14:56:43 +11:00
cp6
beaf9af041 Updated order/sort by on index pages
Updated order/sort by on index pages
As using the relationship for price related sorts does not work this method does
2022-10-20 13:57:04 +11:00
cp6
eda9d1b945 Implemented the details footer component
Implemented the details footer component
2022-10-20 11:59:03 +11:00
cp6
c7a9e5ad80 Added details footer blade component
Added details footer blade component
2022-10-20 11:56:53 +11:00
cp6
7b602d3616 Updated confirmDeleteModal action
Updated confirmDeleteModal action
Made consistency in all the index blade files to use the component
2022-10-20 11:56:35 +11:00
cp6
9c1a853d6a Updated labels_assigned insert
Updated labels_assigned insert
2022-10-20 11:27:01 +11:00
cp6
2139629077 Updated updatePricing() to not need as_usd parameter
Updated updatePricing() to not need as_usd parameter
2022-10-20 11:17:34 +11:00
cp6
736b6c9479 Minor code update
Minor code update
2022-10-20 11:12:53 +11:00
cp6
17b7733258 Removed "add a YABs" button
Removed "add a YABs" button
No longer needed with the POST YABS
2022-10-20 11:09:13 +11:00
cp6
a649f1749e Added/Updated validation on store and update
Added/Updated validation on store and update
Updated update method in shared, server, seedboxes, reseller and misc
2022-10-20 11:06:44 +11:00
cp6
c45df61f10 Merge branch 'Development' of https://github.com/cp6/my-idlers into Development 2022-10-20 10:24:57 +11:00
cp6
b6d06a1f37 JS cleanup
JS cleanup
2022-10-20 10:24:35 +11:00
corbpie
54a705fb9b
Merge pull request #73 from cp6/main
Development up to main
2022-10-20 10:20:35 +11:00
cp6
0ad542afb4 Updated readme for 2.1.7
Updated readme for 2.1.7
2022-10-13 16:09:30 +11:00
cp6
ea8c15d2d8 Removed dashboard redirect from routes
Removed dashboard redirect from routes
2022-10-13 16:04:50 +11:00
cp6
83500fa58e Updated RouteServiceProvider::HOME for '/'
Updated RouteServiceProvider::HOME for '/' instead of '/dashboard'
2022-10-13 16:04:26 +11:00
cp6
2f639a3e95 Removed welcome and dashboard views
Removed welcome and dashboard views as these are unused
2022-10-13 16:03:54 +11:00
cp6
07194a299d Updated views title @section
Updated views title @section
This method removes the whitespace
2022-10-13 16:03:31 +11:00
cp6
3b35cae875 Implemented new response alert component into views
Implemented new response alert component into views
2022-10-13 14:36:21 +11:00
cp6
c52a55dd5a Added response alert for success and error
Added response alert for success and error
2022-10-13 14:34:00 +11:00
cp6
888171c970 Removed unused alert components
Removed unused alert components
2022-10-13 14:33:45 +11:00
cp6
cde2c8d8b6 Added input parameters for compareYabs()
Added input parameters for compareYabs()
Used abort(404) instead of return response()->view('errors.404',........
2022-10-13 14:21:27 +11:00
cp6
dcb8a78ff8 Updated the server choose compare method
Updated the server choose compare method
If 2 suitable servers aren't found then throw an error alert
2022-10-13 14:20:26 +11:00
cp6
4b3e72bc93 Updated the confirm delete modal JS
Updated the confirm delete modal JS
More readability
2022-10-13 14:19:39 +11:00
cp6
20d308b7be Removed unused labels.label with
Removed unused labels.label with
2022-10-13 13:43:09 +11:00
cp6
a1d81a3244 Updated cache timeframes
Updated cache timeframes
2022-10-13 13:37:02 +11:00
corbpie
d0d2cc71ac
Merge pull request #70 from cp6/Development
Added order by for index actions
2022-10-13 13:30:32 +11:00
cp6
b44b4bb259 Code cleanup
Removed unused osIdAsString function
Added return types to some functions
2022-10-05 11:58:19 +11:00
cp6
4abbd451b9 Added order by for index actions
Added order by setting
Order by for index
Updated showing 404 methods in serverController
2022-10-04 14:35:46 +11:00
cp6
41413a224f Updated server fixed server_type & virt
Updated server fixed server_type & virt
Merged server_type & virt into just server_type
Updated serviceServerType() for paramater types and a short/long return value
2022-10-04 11:13:57 +11:00
corbpie
ab650efa3c
Merge pull request #68 from imlonghao/patch-2
controller(server): fix update server ssh port
2022-09-27 14:36:36 +10:00
corbpie
e02f4f6b11
Merge pull request #67 from imlonghao/patch-1
fix: server page due in 0 days
2022-09-27 14:35:07 +10:00
imlonghao
3f669df922
controller(server): fix update server ssh port 2022-09-27 00:05:57 +08:00
imlonghao
dadef79367
fix: server page due in 0 days 2022-09-26 22:46:53 +08:00
cp6
2ae19112e3 Update readme
Update readme for composer
2022-09-26 13:24:53 +10:00
cp6
e9750f10ec Merge branch 'main' of https://github.com/cp6/my-idlers 2022-09-26 13:23:07 +10:00
cp6
78c2703a2b Added doctrine/dbal
Added doctrine/dbal
2022-09-26 13:22:52 +10:00
corbpie
263616ae6d
Merge pull request #64 from cp6/main
Merge main to dev
2022-09-22 13:36:10 +10:00
corbpie
bba4bf9e98
Merge pull request #63 from cp6/Development
Updated readme added run migrate
2022-09-22 13:34:38 +10:00
cp6
f81d12cac3 Updated readme added run migrate
Updated readme added run migrate
2022-09-22 13:33:21 +10:00
corbpie
e0f9f27414
Merge pull request #62 from cp6/Development
Development (2.1.6)
2022-09-22 13:31:20 +10:00
cp6
38dafff877 Readme for 2.1.6
Readme for 2.1.6
2022-09-22 13:30:34 +10:00
cp6
5ef21ec63f Added custom HTTP error pages
Added custom HTTP error pages
2022-09-22 13:29:12 +10:00
cp6
df9411e1bf Updated compare view for nullable values
Updated compare view for nullable values
2022-09-22 13:20:44 +10:00
cp6
df779ba633 Updated models and controllers to use first()
Updated models and controllers to use first() rather than get() with [0]
2022-09-22 13:20:23 +10:00
cp6
8221bf45d8 Removed unused functions in controllers
Removed unused functions in controllers
2022-09-22 12:59:58 +10:00
cp6
69a972e0d9 Updated & fixed YABS JSON parser
Fixed ram conversion
Fixed disk conversion
Fixed disk speed conversion
2022-09-22 12:26:56 +10:00
cp6
6b4f4e8437 Updated error alert component 2022-09-22 12:25:56 +10:00
cp6
d4052259cd Updated YABS table for GB5 values to be nullable
Updated YABS table for GB5 values to be nullable
2022-09-22 12:25:41 +10:00
cp6
51bad4a64b Fixed OS icons not showing for correct OS INT
Fixed OS icons not showing for correct OS INT
2022-09-22 12:25:19 +10:00
cp6
bb901ca703 Removed old YABS add/store method & functions
Removed old YABS store method & functions
2022-09-22 12:24:47 +10:00
cp6
9dc73ba4fe Fixed YABS JSON parsing disk as ram
Fixed YABS JSON parsing disk as ram
Added cache forget for YASB and server
2022-09-22 11:12:29 +10:00
corbpie
91a1466f09
Merge pull request #60 from cp6/Development
Development v2.1.5
2022-09-07 16:02:48 +10:00
cp6
5bf529661a Updated readme v 2.1.5
Updated readme v 2.1.5
2022-09-07 16:01:33 +10:00
cp6
49b9f4e4ad Updated readme for version 2.1.4
Updated readme for version 2.1.4
2022-09-07 15:50:23 +10:00
cp6
9e824e0cb6 Added version v2022-08-20 to YABS parser
Added version v2022-08-20 to YABS parser
2022-09-07 15:50:01 +10:00
cp6
a8a87a2e0f Updated server show page
Updated server show page for a click reveal YABS command to automatically POST the result. e.g

curl -sL yabs.sh | bash -s -- -s "http://domain.com/api/yabs/tnSJLyhz/THEUSERAPIKEYISHERE"
2022-09-07 14:00:21 +10:00
cp6
13a37242d2 Updated yabs/ POST API request
Needs the server for the YABS and users api key in the URL
2022-09-07 13:58:38 +10:00
cp6
badb640bd9 Updated storeYabs API function
Updated storeYabs API function
Now used to insert YABS from the POST request

-s flag
2022-09-07 13:57:43 +10:00
cp6
c79f67916e Added YABS from JSON parsing
Added YABS from JSON parsing
2022-09-07 13:56:56 +10:00
cp6
f36d73c04d Merge branch 'Development' of https://github.com/cp6/my-idlers into Development 2022-08-30 23:37:21 +10:00
cp6
d1eb588b11 Updated pricing model insertPricing() func
Updated pricing model insertPricing() function
Move as_usd parameter into the function
Updated is_active check as it is an int anyway
2022-08-30 23:37:05 +10:00
cp6
8f8ae8edb5 Updated YABS processor
Removed === and replaced with str_contains for the line validators

As when posting with API the \r character post-pending each line don't exist
2022-08-10 00:37:40 +10:00
cp6
007890855b Added YABS to API
Get YABS from API
Add/create/post/store YABS
2022-08-10 00:34:03 +10:00
cp6
3b9ff1ab85 Possible fix for YABs migration dropping multiple columns error
Possible fix for YABs migration dropping multiple columns error
2022-07-25 10:38:06 +10:00
cp6
59b3138dfb Possible YABs foreign keys migrations error fix
Possible YABs foreign keys migrations error fix
2022-07-25 10:33:54 +10:00
cp6
20058cb9c9 Issue 56 & 57 fix?
Issue 56 & 57 fix?
2022-07-22 23:49:18 +10:00
corbpie
82f3b62761
Merge pull request #55 from cp6/Development
Development 2.1.3
2022-07-20 14:55:51 +10:00
cp6
01e2613d90 Updated readme
Updated readme
2022-07-20 14:48:19 +10:00
cp6
e6943b4640 Updated readme for 2.1.3
Updated readme for 2.1.3
2022-07-20 14:47:37 +10:00
cp6
3340d296f9 Updated ApiController to use new Class fetching (Relationships)
Updated ApiController to use new Class fetching (Relationships)
2022-07-20 14:37:37 +10:00
cp6
bb07f86deb Updated Labels class
Removed unused function
Added assigned() hasMany
2022-07-20 14:36:19 +10:00
cp6
c9108efd63 Updated SeedBoxes class to use relationships + cache
Updated SeedBoxes class to use relationships + cache
2022-07-20 14:35:37 +10:00
cp6
356bd368a4 Updated Misc class to use relationships + cache
Updated Misc class to use relationships + cache
2022-07-20 14:35:12 +10:00
cp6
3d87c645dc Updated style max container width
Updated style max container width from 1320px to 1420px
2022-07-20 13:12:46 +10:00
cp6
b1a135b41b Updated YABs show for new values
Updated YABs show for new values (uptime, distro, swap)
2022-07-20 13:08:52 +10:00
cp6
47bfcea4c8 Added more YABs value saving & YABs save txt setting
Added more YABs value saving (uptime, distro, kernel and swap memory)
Added setting for saving YABs output to txt yes/no
2022-07-20 12:51:45 +10:00
cp6
b9aed757ad Added YABs to Json output
Added YABs to Json output
Cleaned up old unused functions
2022-07-20 00:20:15 +10:00
cp6
e46b7b3c63 Added back & edit icon button components
Added back & edit icon button components
2022-07-20 00:19:43 +10:00
cp6
88636b88c7 Updated Domains model for relationships
Updated Domains model for relationships
Added caching
2022-07-20 00:19:05 +10:00
cp6
36194efbd8 Updated Shared for data index
Updated Shared for data index
2022-07-19 15:55:37 +10:00
cp6
eb31701076 Updated Reseller model to use relationships
Updated Reseller model to use relationships
Added caching for Reseller
2022-07-19 15:55:10 +10:00
203 changed files with 119681 additions and 54684 deletions

View file

@ -1,49 +0,0 @@
APP_NAME=MyIdlers
APP_ENV=local
APP_KEY=
APP_DEBUG=true
APP_URL=http://localhost
LOG_CHANNEL=stack
LOG_LEVEL=debug
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=my_idlers
DB_USERNAME=root
DB_PASSWORD=
BROADCAST_DRIVER=log
CACHE_DRIVER=file
QUEUE_CONNECTION=sync
SESSION_DRIVER=file
SESSION_LIFETIME=120
MEMCACHED_HOST=127.0.0.1
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379
MAIL_MAILER=smtp
MAIL_HOST=mailhog
MAIL_PORT=1025
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_ENCRYPTION=null
MAIL_FROM_ADDRESS=null
MAIL_FROM_NAME="${APP_NAME}"
AWS_ACCESS_KEY_ID=
AWS_SECRET_ACCESS_KEY=
AWS_DEFAULT_REGION=us-east-1
AWS_BUCKET=
PUSHER_APP_ID=
PUSHER_APP_KEY=
PUSHER_APP_SECRET=
PUSHER_APP_CLUSTER=mt1
MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"

3
.gitattributes vendored
View file

@ -3,3 +3,6 @@
*.scss linguist-vendored *.scss linguist-vendored
*.js linguist-vendored *.js linguist-vendored
CHANGELOG.md export-ignore CHANGELOG.md export-ignore
/public/css/* -diff
/public/js/* -diff

View file

@ -1,28 +1,79 @@
name: Docker
# This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
# documentation.
on: on:
push: push:
branches: [ "main" ]
env:
# Use docker.io for Docker Hub if empty
REGISTRY: ghcr.io
# github.repository as <account>/<repo>
IMAGE_NAME: ${{ github.repository }}
jobs: jobs:
build: build:
name: Build, push, and deploy
runs-on: ubuntu-latest runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main' permissions:
contents: read
packages: write
# This is used to complete the identity challenge
# with sigstore/fulcio when running outside of PRs.
id-token: write
steps: steps:
- name: Checkout repository
uses: actions/checkout@v3
- name: Checkout # Install the cosign tool except on PR
uses: actions/checkout@v2 # https://github.com/sigstore/cosign-installer
- name: Install cosign
if: github.event_name != 'pull_request'
uses: sigstore/cosign-installer@main
with:
cosign-release: 'v1.11.0'
- name: Build container image
run: |
docker build \
--tag ghcr.io/cp6/my-idlers:$(echo $GITHUB_SHA | head -c7) \
--tag ghcr.io/cp6/my-idlers:latest \
.
- name: Container registry login
run: |
echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u "${{ github.actor }}" --password-stdin
- name: Push image to GHCR # Workaround: https://github.com/docker/build-push-action/issues/461
if: github.ref == 'refs/heads/main' - name: Setup Docker buildx
run: | uses: docker/setup-buildx-action@79abd3f86f79a9d68a23c75a09a9a85889262adf
docker push ghcr.io/cp6/my-idlers:$(echo $GITHUB_SHA | head -c7)
docker push ghcr.io/cp6/my-idlers:latest # Login against a Docker registry except on PR
# https://github.com/docker/login-action
- name: Log into registry ${{ env.REGISTRY }}
if: github.event_name != 'pull_request'
uses: docker/login-action@28218f9b04b4f3f62068d7b6ce6ca5b26e35336c
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
# Extract metadata (tags, labels) for Docker
# https://github.com/docker/metadata-action
- name: Extract Docker metadata
id: meta
uses: docker/metadata-action@98669ae865ea3cffbcbaa878cf57c20bbf1c6c38
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
latest
# Build and push Docker image with Buildx (don't push on PR)
# https://github.com/docker/build-push-action
- name: Build and push Docker image
id: build-and-push
uses: docker/build-push-action@v2
with:
context: .
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta.outputs.tags }}
platforms: linux/amd64,linux/arm64
cache-from: type=gha
cache-to: type=gha,mode=max

1
.gitignore vendored
View file

@ -57,3 +57,4 @@ fabric.properties
# .idea/misc.xml # .idea/misc.xml
# *.ipr # *.ipr
storage/clockwork/ storage/clockwork/
!public/

View file

@ -1,4 +1,4 @@
FROM php:8.1-fpm-alpine FROM php:8.2-fpm-alpine
RUN docker-php-ext-install pdo pdo_mysql sockets RUN docker-php-ext-install pdo pdo_mysql sockets
RUN curl -sS https://getcomposer.org/installer | php -- \ RUN curl -sS https://getcomposer.org/installer | php -- \

199
README.md
View file

@ -1,39 +1,60 @@
# My idlers # My idlers
A web app for displaying, organizing and storing information about servers (VPS), shared & reseller hosting, seed boxes, domains, A self-hosted web app for displaying, organizing and storing information about your servers (VPS/Dedi), shared &
DNS and misc services. reseller hosting, seedboxes,
domains, DNS and misc services.
Despite what the name infers this self hosted web app isn't just for storing idling server information. By using Despite what the name infers this self-hosted web app isn't just for storing idling server information. By using
a [YABs](https://github.com/masonr/yet-another-bench-script) output you can get disk & network speed values along with a [YABS](https://github.com/masonr/yet-another-bench-script) output you can get disk & network speed values along with
GeekBench 5 scores to do easier comparing and sorting. GeekBench 5 & 6 scores to do easier comparing and sorting. Of course storing other services e.g. web hosting is possible
and supported too with My idlers.
[![Generic badge](https://img.shields.io/badge/version-2.1.2-blue.svg)](https://shields.io/) [![Generic badge](https://img.shields.io/badge/Laravel-9.0-red.svg)](https://shields.io/) [![Generic badge](https://img.shields.io/badge/PHP-8.1-purple.svg)](https://shields.io/) [![Generic badge](https://img.shields.io/badge/Bootstrap-5.1-pink.svg)](https://shields.io/) [![Generic badge](https://img.shields.io/badge/version-3.0.0-blue.svg)](https://shields.io/) [![Generic badge](https://img.shields.io/badge/Laravel-11.0-red.svg)](https://shields.io/) [![Generic badge](https://img.shields.io/badge/PHP-8.3-purple.svg)](https://shields.io/) [![Generic badge](https://img.shields.io/badge/Bootstrap-5.3-pink.svg)](https://shields.io/)
<img src="https://raw.githubusercontent.com/cp6/my-idlers/main/public/My%20Idlers%20logo.jpg" width="128" height="128" /> <img src="https://raw.githubusercontent.com/cp6/my-idlers/main/public/My%20Idlers%20logo.jpg" width="128" height="128" />
[Demo site](https://demo.myidlers.com/) [View demo site](https://demo.myidlers.com/)
**Note:** Create, Update and Delete are disabled on demo site. **Note:** Create, Update and Delete are disabled on the demo site.
## Project sponsor ## Project sponsor
[Cloud Five Limited](https://cloud-v.net/) for providing the hosting for demo installation. Currently seeking a project sponsor
## 2.1.2 changes (19th July 2022): ## 3.0.0 changes (9 December 2024):
* Added YABs compare page * Updated PHP version to 8.3
* Added caching for YABs * Updated Laravel version to ^11
* Added LabelsAssigned model * Updated composer package versions
* Updated Server model to use relationships * Updated routes into middleware grouping for auth
* Updated Shared model to use relationships * Updated login and register forms
* Updated Shared model to use caching * Updated servers, shared, reseller and domains pages to use Datatables
* Updated Table model to have table name defined * Added icons to back and submit button components
* Fixed server compare initial selection * Added icon button to shared and reseller create pages
* Fixed switch in getIpForDomain() * Added several updated OS versions to OsSeeder
* Added Font awesome Brands webfont
* Added IP whois data columns to the ips table
* Added IP whois data fetching and updating DB
* Added Note to API
* Fixed OS icons not loading in servers index page
* Fixed Settings being called without being created (existing)
* Fixed issue with OS: `Call to a member function toJson() on array`
* Fixed due in (days) column showing a massive float
* Removed 1 user being seeded
* Removed doctrine/dbal
#### Please run the following if updating from an existing install:
```shell
composer update
php artisan migrate
php artisan route:cache
php artisan cache:clear
```
## Requires ## Requires
* PHP 8.1 * PHP 8.3
## Features ## Features
@ -42,10 +63,10 @@ GeekBench 5 scores to do easier comparing and sorting.
* Add domains * Add domains
* [Auto get IP's from hostname](https://cdn.write.corbpie.com/wp-content/uploads/2021/01/my-idlers-self-hosted-server-domain-information-ips-from-hostname.gif) * [Auto get IP's from hostname](https://cdn.write.corbpie.com/wp-content/uploads/2021/01/my-idlers-self-hosted-server-domain-information-ips-from-hostname.gif)
* [Check up/down status](https://cdn.write.corbpie.com/wp-content/uploads/2021/01/my-idlers-self-hosted-server-domain-information-ping-up-feature.gif) * [Check up/down status](https://cdn.write.corbpie.com/wp-content/uploads/2021/01/my-idlers-self-hosted-server-domain-information-ping-up-feature.gif)
* Get YABs data from output * Get YABS data from output
* Compare 2 servers * Compare 2 servers
* Save & view YABs output * Save & view YABS output
* Update YABs disk & network results * Update YABS disk & network results
* Next due date system * Next due date system
* Multi currency compatibility * Multi currency compatibility
* Multi payment-term compatibility * Multi payment-term compatibility
@ -53,6 +74,7 @@ GeekBench 5 scores to do easier comparing and sorting.
* Assign labels * Assign labels
* Assign server type (KVM, OVZ, LXC & dedi) * Assign server type (KVM, OVZ, LXC & dedi)
* Easy to edit values * Easy to edit values
* Assign notes
## Install ## Install
@ -65,13 +87,16 @@ GeekBench 5 scores to do easier comparing and sorting.
* Run `php artisan migrate:fresh --seed` to create tables and seed data * Run `php artisan migrate:fresh --seed` to create tables and seed data
* Run `php artisan serve` * Run `php artisan serve`
## Update ## Updating
If you have at least version 2.0 installed: If you already have at least version 2.0 installed:
* Run `git clone https://github.com/cp6/my-idlers.git` * Run `git clone https://github.com/cp6/my-idlers.git`
* Run `composer install` * Run `composer install`
* Run `composer update`
* Run `php artisan migrate` * Run `php artisan migrate`
* Run `php artisan route:cache`
* Run `php artisan cache:clear`
## Run using Docker ## Run using Docker
@ -93,6 +118,21 @@ Run with a single click on [PikaPods.com](https://www.pikapods.com/)
[![PikaPods](https://www.pikapods.com/static/run-button.svg)](https://www.pikapods.com/pods?run=my-idlers) [![PikaPods](https://www.pikapods.com/static/run-button.svg)](https://www.pikapods.com/pods?run=my-idlers)
## Adding a YABS benchmark
yabs.sh now has JSON formatted response and can POST the output directly from calling the script.
With My idlers you can use your API key and the server id to directly POST the benchmark result
`https://yourdomain.com/api/yabs/SERVERID/USERAPIKEYISHERE`
Example yabs.sh call to POST the result:
`curl -sL yabs.sh | bash -s -- -s "https://yourdomain.com/api/yabs/SERVERID/USERAPIKEYISHERE"`
## Credits
IP who is data provided by [ipwhois.io](https://ipwhois.io/documentation)
## API endpoints ## API endpoints
@ -158,6 +198,8 @@ All API requests must be appended with `api/` e.g `mydomain.com/api/servers/gYk8
`shared/{id}` `shared/{id}`
`note/{id}`
**POST requests** **POST requests**
Create a server Create a server
@ -168,35 +210,35 @@ Body content template
```json ```json
{ {
"active": 1, "active": 1,
"show_public": 0, "show_public": 0,
"hostname": "test.domain.com", "hostname": "test.domain.com",
"ns1": "ns1", "ns1": "ns1",
"ns2": "ns2", "ns2": "ns2",
"server_type": 1, "server_type": 1,
"os_id": 2, "os_id": 2,
"provider_id": 10, "provider_id": 10,
"location_id": 15, "location_id": 15,
"ssh_port": 22, "ssh_port": 22,
"bandwidth": 2000, "bandwidth": 2000,
"ram": 2024, "ram": 2024,
"ram_type": "MB", "ram_type": "MB",
"ram_as_mb": 2024, "ram_as_mb": 2024,
"disk": 30, "disk": 30,
"disk_type": "GB", "disk_type": "GB",
"disk_as_gb": 30, "disk_as_gb": 30,
"cpu": 2, "cpu": 2,
"has_yabs": 0, "has_yabs": 0,
"was_promo": 1, "was_promo": 1,
"ip1": "127.0.0.1", "ip1": "127.0.0.1",
"ip2": null, "ip2": null,
"owned_since": "2022-01-01", "owned_since": "2022-01-01",
"currency": "USD", "currency": "USD",
"price": 4.00, "price": 4.00,
"payment_term": 1, "payment_term": 1,
"as_usd": 4.00, "as_usd": 4.00,
"usd_per_month": 4.00, "usd_per_month": 4.00,
"next_due_date": "2022-02-01" "next_due_date": "2022-02-01"
} }
``` ```
@ -210,27 +252,27 @@ Body content template
```json ```json
{ {
"active": 1, "active": 1,
"show_public": 0, "show_public": 0,
"hostname": "test.domain.com", "hostname": "test.domain.com",
"ns1": "ns1", "ns1": "ns1",
"ns2": "ns2", "ns2": "ns2",
"server_type": 1, "server_type": 1,
"os_id": 2, "os_id": 2,
"provider_id": 10, "provider_id": 10,
"location_id": 15, "location_id": 15,
"ssh_port": 22, "ssh_port": 22,
"bandwidth": 2000, "bandwidth": 2000,
"ram": 2024, "ram": 2024,
"ram_type": "MB", "ram_type": "MB",
"ram_as_mb": 2024, "ram_as_mb": 2024,
"disk": 30, "disk": 30,
"disk_type": "GB", "disk_type": "GB",
"disk_as_gb": 30, "disk_as_gb": 30,
"cpu": 2, "cpu": 2,
"has_yabs": 0, "has_yabs": 0,
"was_promo": 1, "was_promo": 1,
"owned_since": "2022-01-01" "owned_since": "2022-01-01"
} }
``` ```
@ -244,7 +286,7 @@ Body content template
{ {
"price": 10.50, "price": 10.50,
"currency": "USD", "currency": "USD",
"term" : 1 "term": 1
} }
``` ```
@ -254,7 +296,6 @@ Delete a server
`/servers/ID` `/servers/ID`
## Notes ## Notes
**Public viewable listings** **Public viewable listings**
@ -277,10 +318,6 @@ or
```curl -sL yabs.sh | bash -s -- -r``` ```curl -sL yabs.sh | bash -s -- -r```
**Make sure YABs output starts at the first line which is:**
```# ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## #```
Logo icons created by Freepik - Flaticon Logo icons created by Freepik - Flaticon
## Screenshots for v2 ## Screenshots for v2

View file

@ -2,14 +2,21 @@
namespace App\Http\Controllers; namespace App\Http\Controllers;
use App\Models\Domains;
use App\Models\IPs; use App\Models\IPs;
use App\Models\Labels; use App\Models\Labels;
use App\Models\Misc;
use App\Models\NetworkSpeed; use App\Models\NetworkSpeed;
use App\Models\Note;
use App\Models\OS; use App\Models\OS;
use App\Models\Pricing; use App\Models\Pricing;
use App\Models\Providers; use App\Models\Providers;
use App\Models\Reseller;
use App\Models\SeedBoxes;
use App\Models\Server; use App\Models\Server;
use App\Models\Shared; use App\Models\Shared;
use App\Models\User;
use App\Models\Yabs;
use DataTables; use DataTables;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache; use Illuminate\Support\Facades\Cache;
@ -21,53 +28,13 @@ class ApiController extends Controller
{ {
protected function getAllServers() protected function getAllServers()
{ {
$servers = DB::table('servers as s') $servers = Server::allServers()->toJson(JSON_PRETTY_PRINT);
->Join('pricings as p', 's.id', '=', 'p.service_id')
->join('providers as pr', 's.provider_id', '=', 'pr.id')
->join('locations as l', 's.location_id', '=', 'l.id')
->join('os as o', 's.os_id', '=', 'o.id')
->get(['s.*', 'p.id as price_id', 'p.currency', 'p.price', 'p.term', 'p.as_usd', 'p.usd_per_month', 'p.next_due_date', 'pr.name as provider', 'l.name as location', 'o.name as os'])->toJson(JSON_PRETTY_PRINT);
return response($servers, 200); return response($servers, 200);
} }
protected function getServer($id) protected function getServer($id)
{ {
$server = DB::table('servers as s') $server = Server::server($id)->toJson(JSON_PRETTY_PRINT);
->Join('pricings as p', 's.id', '=', 'p.service_id')
->join('providers as pr', 's.provider_id', '=', 'pr.id')
->join('locations as l', 's.location_id', '=', 'l.id')
->join('os as o', 's.os_id', '=', 'o.id')
->where('s.id', '=', $id)
->get(['s.*', 'p.id as price_id', 'p.currency', 'p.price', 'p.term', 'p.as_usd', 'p.usd_per_month', 'p.next_due_date', 'pr.name as provider', 'l.name as location', 'o.name as os']);
$yabs = DB::table('yabs')
->where('yabs.server_id', '=', $id)
->get();
$disk_speed = DB::table('disk_speed')
->where('disk_speed.server_id', '=', $id)
->get();
$network_speed = DB::table('network_speed')
->where('network_speed.server_id', '=', $id)
->get();
$labels = DB::table('labels_assigned as la')
->Join('labels as l', 'la.label_id', '=', 'l.id')
->where('la.service_id', '=', $id)
->get(['l.*']);
$ip_addresses = DB::table('ips as i')
->where('i.service_id', '=', $id)
->get(['i.*']);
$server['ip_addresses'] = $ip_addresses;
$server['yabs'] = $yabs;
$server['disk_speed'] = $disk_speed;
$server['network_speed'] = $network_speed;
$server['labels'] = $labels;
return response($server, 200); return response($server, 200);
} }
@ -79,7 +46,8 @@ class ApiController extends Controller
protected function getPricing($id) protected function getPricing($id)
{ {
$pricing = Pricing::where('id', $id)->get()->toJson(JSON_PRETTY_PRINT); $pricing = Pricing::where('id', $id)
->get()->toJson(JSON_PRETTY_PRINT);
return response($pricing, 200); return response($pricing, 200);
} }
@ -91,8 +59,7 @@ class ApiController extends Controller
protected function getNetworkSpeeds($id) protected function getNetworkSpeeds($id)
{ {
$ns = DB::table('network_speed as n') $ns = NetworkSpeed::where('server_id', $id)
->where('n.server_id', '=', $id)
->get()->toJson(JSON_PRETTY_PRINT); ->get()->toJson(JSON_PRETTY_PRINT);
return response($ns, 200); return response($ns, 200);
} }
@ -105,94 +72,68 @@ class ApiController extends Controller
protected function getLabel($id) protected function getLabel($id)
{ {
$label = DB::table('labels as l') $label = Labels::where('id', $id)
->where('l.id', '=', $id)
->get()->toJson(JSON_PRETTY_PRINT); ->get()->toJson(JSON_PRETTY_PRINT);
return response($label, 200); return response($label, 200);
} }
protected function getAllShared() protected function getAllShared()
{ {
$shared = DB::table('shared_hosting as sh') $shared = Shared::allSharedHosting()->toJson(JSON_PRETTY_PRINT);
->Join('pricings as p', 'sh.id', '=', 'p.service_id')
->get(['sh.*', 'p.id as price_id', 'p.currency', 'p.price', 'p.term', 'p.as_usd', 'p.usd_per_month', 'p.next_due_date'])->toJson(JSON_PRETTY_PRINT);
return response($shared, 200); return response($shared, 200);
} }
protected function getShared($id) protected function getShared($id)
{ {
$shared = DB::table('shared_hosting as sh') $shared = Shared::sharedHosting($id)->toJson(JSON_PRETTY_PRINT);
->Join('pricings as p', 'sh.id', '=', 'p.service_id')
->where('sh.id', '=', $id)
->get(['sh.*', 'p.id as price_id', 'p.currency', 'p.price', 'p.term', 'p.as_usd', 'p.usd_per_month', 'p.next_due_date'])->toJson(JSON_PRETTY_PRINT);
return response($shared, 200); return response($shared, 200);
} }
protected function getAllReseller() protected function getAllReseller()
{ {
$reseller = DB::table('reseller_hosting as rh') $reseller = Reseller::allResellerHosting()->toJson(JSON_PRETTY_PRINT);
->Join('pricings as p', 'rh.id', '=', 'p.service_id')
->get(['rh.*', 'p.id as price_id', 'p.currency', 'p.price', 'p.term', 'p.as_usd', 'p.usd_per_month', 'p.next_due_date'])->toJson(JSON_PRETTY_PRINT);
return response($reseller, 200); return response($reseller, 200);
} }
protected function getReseller($id) protected function getReseller($id)
{ {
$reseller = DB::table('reseller_hosting as rh') $reseller = Reseller::resellerHosting($id)->toJson(JSON_PRETTY_PRINT);
->Join('pricings as p', 'rh.id', '=', 'p.service_id')
->where('rh.id', '=', $id)
->get(['rh.*', 'p.id as price_id', 'p.currency', 'p.price', 'p.term', 'p.as_usd', 'p.usd_per_month', 'p.next_due_date'])->toJson(JSON_PRETTY_PRINT);
return response($reseller, 200); return response($reseller, 200);
} }
protected function getAllSeedbox() protected function getAllSeedbox()
{ {
$reseller = DB::table('seedboxes as sb') $reseller = SeedBoxes::allSeedboxes()->toJson(JSON_PRETTY_PRINT);
->Join('pricings as p', 'sb.id', '=', 'p.service_id')
->get(['sb.*', 'p.id as price_id', 'p.currency', 'p.price', 'p.term', 'p.as_usd', 'p.usd_per_month', 'p.next_due_date'])->toJson(JSON_PRETTY_PRINT);
return response($reseller, 200); return response($reseller, 200);
} }
protected function getSeedbox($id) protected function getSeedbox($id)
{ {
$reseller = DB::table('seedboxes as sb') $reseller = SeedBoxes::seedbox($id)->toJson(JSON_PRETTY_PRINT);
->Join('pricings as p', 'sb.id', '=', 'p.service_id')
->where('sb.id', '=', $id)
->get(['sb.*', 'p.id as price_id', 'p.currency', 'p.price', 'p.term', 'p.as_usd', 'p.usd_per_month', 'p.next_due_date'])->toJson(JSON_PRETTY_PRINT);
return response($reseller, 200); return response($reseller, 200);
} }
protected function getAllDomains() protected function getAllDomains()
{ {
$domains = DB::table('domains as d') $domains = Domains::allDomains()->toJson(JSON_PRETTY_PRINT);
->Join('pricings as p', 'd.id', '=', 'p.service_id')
->get(['d.*', 'p.id as price_id', 'p.currency', 'p.price', 'p.term', 'p.as_usd', 'p.usd_per_month', 'p.next_due_date'])->toJson(JSON_PRETTY_PRINT);
return response($domains, 200); return response($domains, 200);
} }
protected function getDomains($id) protected function getDomains($id)
{ {
$domain = DB::table('domains as d') $domain = Domains::domain($id)->toJson(JSON_PRETTY_PRINT);
->Join('pricings as p', 'd.id', '=', 'p.service_id')
->where('d.id', '=', $id)
->get(['d.*', 'p.id as price_id', 'p.currency', 'p.price', 'p.term', 'p.as_usd', 'p.usd_per_month', 'p.next_due_date'])->toJson(JSON_PRETTY_PRINT);
return response($domain, 200); return response($domain, 200);
} }
protected function getAllMisc() protected function getAllMisc()
{ {
$misc = DB::table('misc_services as m') $misc = Misc::allMisc()->toJson(JSON_PRETTY_PRINT);
->Join('pricings as p', 'm.id', '=', 'p.service_id')
->get(['m.*', 'p.id as price_id', 'p.currency', 'p.price', 'p.term', 'p.as_usd', 'p.usd_per_month', 'p.next_due_date'])->toJson(JSON_PRETTY_PRINT);
return response($misc, 200); return response($misc, 200);
} }
protected function getMisc($id) protected function getMisc($id)
{ {
$misc = DB::table('misc_services as m') $misc = Misc::misc($id)->toJson(JSON_PRETTY_PRINT);
->Join('pricings as p', 'm.id', '=', 'p.service_id')
->where('m.id', '=', $id)
->get(['m.*', 'p.id as price_id', 'p.currency', 'p.price', 'p.term', 'p.as_usd', 'p.usd_per_month', 'p.next_due_date'])->toJson(JSON_PRETTY_PRINT);
return response($misc, 200); return response($misc, 200);
} }
@ -206,7 +147,7 @@ class ApiController extends Controller
protected function getDns($id) protected function getDns($id)
{ {
$dns = DB::table('d_n_s') $dns = DB::table('d_n_s')
->where('id', '=', $id) ->where('id', $id)
->get()->toJson(JSON_PRETTY_PRINT); ->get()->toJson(JSON_PRETTY_PRINT);
return response($dns, 200); return response($dns, 200);
} }
@ -221,7 +162,7 @@ class ApiController extends Controller
protected function getLocation($id) protected function getLocation($id)
{ {
$location = DB::table('locations') $location = DB::table('locations')
->where('id', '=', $id) ->where('id', $id)
->get()->toJson(JSON_PRETTY_PRINT); ->get()->toJson(JSON_PRETTY_PRINT);
return response($location, 200); return response($location, 200);
} }
@ -236,7 +177,7 @@ class ApiController extends Controller
protected function getProvider($id) protected function getProvider($id)
{ {
$providers = DB::table('providers') $providers = DB::table('providers')
->where('id', '=', $id) ->where('id', $id)
->get()->toJson(JSON_PRETTY_PRINT); ->get()->toJson(JSON_PRETTY_PRINT);
return response($providers, 200); return response($providers, 200);
} }
@ -257,7 +198,7 @@ class ApiController extends Controller
protected function getOs($id) protected function getOs($id)
{ {
$os = DB::table('os as o') $os = DB::table('os as o')
->where('o.id', '=', $id) ->where('o.id', $id)
->get()->toJson(JSON_PRETTY_PRINT); ->get()->toJson(JSON_PRETTY_PRINT);
return response($os, 200); return response($os, 200);
} }
@ -271,7 +212,7 @@ class ApiController extends Controller
protected function getIP($id) protected function getIP($id)
{ {
$ip = DB::table('ips as i') $ip = DB::table('ips as i')
->where('i.id', '=', $id) ->where('i.id', $id)
->get()->toJson(JSON_PRETTY_PRINT); ->get()->toJson(JSON_PRETTY_PRINT);
return response($ip, 200); return response($ip, 200);
} }
@ -322,7 +263,7 @@ class ApiController extends Controller
protected function storeServer(Request $request) protected function storeServer(Request $request)
{ {
$rules = array( $rules = [
'hostname' => 'min:3', 'hostname' => 'min:3',
'server_type' => 'required|integer', 'server_type' => 'required|integer',
'os_id' => 'required|integer', 'os_id' => 'required|integer',
@ -347,9 +288,9 @@ class ApiController extends Controller
'price' => 'required|numeric', 'price' => 'required|numeric',
'payment_term' => 'required|integer', 'payment_term' => 'required|integer',
'next_due_date' => 'date', 'next_due_date' => 'date',
); ];
$messages = array( $messages = [
'required' => ':attribute is required', 'required' => ':attribute is required',
'min' => ':attribute must be longer than 3', 'min' => ':attribute must be longer than 3',
'integer' => ':attribute must be an integer', 'integer' => ':attribute must be an integer',
@ -358,7 +299,7 @@ class ApiController extends Controller
'numeric' => ':attribute must be a float', 'numeric' => ':attribute must be a float',
'ip' => ':attribute must be a valid IP address', 'ip' => ':attribute must be a valid IP address',
'date' => ':attribute must be a date Y-m-d', 'date' => ':attribute must be a date Y-m-d',
); ];
$validator = Validator::make($request->all(), $rules, $messages); $validator = Validator::make($request->all(), $rules, $messages);
@ -369,10 +310,7 @@ class ApiController extends Controller
$server_id = Str::random(8); $server_id = Str::random(8);
$pricing = new Pricing(); $pricing = new Pricing();
$pricing->insertPricing(1, $server_id, $request->currency, $request->price, $request->payment_term, $request->next_due_date);
$as_usd = $pricing->convertToUSD($request->price, $request->currency);
$pricing->insertPricing(1, $server_id, $request->currency, $request->price, $request->payment_term, $as_usd, $request->next_due_date);
if (!is_null($request->ip1)) { if (!is_null($request->ip1)) {
IPs::insertIP($server_id, $request->ip1); IPs::insertIP($server_id, $request->ip1);
@ -436,7 +374,7 @@ class ApiController extends Controller
public function updateServer(Request $request) public function updateServer(Request $request)
{ {
$rules = array( $rules = [
'hostname' => 'string|min:3', 'hostname' => 'string|min:3',
'server_type' => 'integer', 'server_type' => 'integer',
'os_id' => 'integer', 'os_id' => 'integer',
@ -459,9 +397,9 @@ class ApiController extends Controller
'price' => 'numeric', 'price' => 'numeric',
'payment_term' => 'integer', 'payment_term' => 'integer',
'next_due_date' => 'date', 'next_due_date' => 'date',
); ];
$messages = array( $messages = [
'required' => ':attribute is required', 'required' => ':attribute is required',
'min' => ':attribute must be longer than 3', 'min' => ':attribute must be longer than 3',
'integer' => ':attribute must be an integer', 'integer' => ':attribute must be an integer',
@ -469,7 +407,7 @@ class ApiController extends Controller
'size' => ':attribute must be exactly :size characters', 'size' => ':attribute must be exactly :size characters',
'numeric' => ':attribute must be a float', 'numeric' => ':attribute must be a float',
'date' => ':attribute must be a date Y-m-d', 'date' => ':attribute must be a date Y-m-d',
); ];
$validator = Validator::make($request->all(), $rules, $messages); $validator = Validator::make($request->all(), $rules, $messages);
@ -491,22 +429,22 @@ class ApiController extends Controller
public function updatePricing(Request $request) public function updatePricing(Request $request)
{ {
$rules = array( $rules = [
'price' => 'required|numeric', 'price' => 'required|numeric',
'currency' => 'required|string|size:3', 'currency' => 'required|string|size:3',
'term' => 'required|integer', 'term' => 'required|integer',
'active' => 'integer', 'active' => 'integer',
'next_due_date' => 'date', 'next_due_date' => 'date',
); ];
$messages = array( $messages = [
'required' => ':attribute is required', 'required' => ':attribute is required',
'integer' => ':attribute must be an integer', 'integer' => ':attribute must be an integer',
'string' => ':attribute must be a string', 'string' => ':attribute must be a string',
'size' => ':attribute must be exactly :size characters', 'size' => ':attribute must be exactly :size characters',
'numeric' => ':attribute must be a float', 'numeric' => ':attribute must be a float',
'date' => ':attribute must be a date Y-m-d', 'date' => ':attribute must be a date Y-m-d',
); ];
$validator = Validator::make($request->all(), $rules, $messages); $validator = Validator::make($request->all(), $rules, $messages);
@ -532,4 +470,41 @@ class ApiController extends Controller
return response()->json(array('result' => 'fail', 'request' => $request->post()), 500); return response()->json(array('result' => 'fail', 'request' => $request->post()), 500);
} }
public function storeYabs(Request $request, Server $server, string $key): \Illuminate\Http\JsonResponse
{
$r = User::where('api_token', $key)->first();
if (!isset($r->id)) {
return response()->json(['error' => 'Unauthenticated'], 401);
}
$insert = Yabs::insertFromJson($request, $server->id);
if ($insert) {
Cache::forget('all_active_servers');//all servers cache
Cache::forget('non_active_servers');//all servers cache
Cache::forget('all_yabs');//Forget the all YABS cache
return response()->json(array('message' => 'Successfully added YABS'), 200);
}
return response()->json(array('error' => 'Server error'), 500);
}
public function getAllYabs()
{
$yabs = Yabs::allYabs()->toJson(JSON_PRETTY_PRINT);
return response($yabs, 200);
}
protected function getYabs($id)
{
$yabs = Yabs::yabs($id)->toJson(JSON_PRETTY_PRINT);
return response($yabs, 200);
}
protected function getNote($id)
{
$note = Note::where('id', $id)->firstOrFail('note')->pluck('note');
return response($note, 200)->header('Content-Type', 'text/plain');
}
} }

View file

@ -8,7 +8,6 @@ use App\Models\Reseller;
use App\Models\Server; use App\Models\Server;
use App\Models\Domains; use App\Models\Domains;
use App\Models\Shared; use App\Models\Shared;
use Carbon\Carbon;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache; use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\DB;
@ -34,9 +33,13 @@ class DNSController extends Controller
public function store(Request $request) public function store(Request $request)
{ {
$request->validate([ $request->validate([
'hostname' => 'required|min:2', 'hostname' => 'required|string|min:2',
'address' => 'required|min:2', 'address' => 'required|string|min:2',
'dns_type' => 'required' 'dns_type' => 'required|string',
'label1' => 'sometimes|nullable|string',
'label2' => 'sometimes|nullable|string',
'label3' => 'sometimes|nullable|string',
'label4' => 'sometimes|nullable|string',
]); ]);
$dns_id = Str::random(8); $dns_id = Str::random(8);
@ -65,8 +68,8 @@ class DNSController extends Controller
$dns = DNS::findOrFail($dn->id); $dns = DNS::findOrFail($dn->id);
$labels = DB::table('labels_assigned as l') $labels = DB::table('labels_assigned as l')
->join('labels', 'l.label_id', '=', 'labels.id') ->join('labels', 'l.label_id', 'labels.id')
->where('l.service_id', '=', $dn->id) ->where('l.service_id', $dn->id)
->get(['labels.label']); ->get(['labels.label']);
return view('dns.show', compact(['dn', 'dns', 'labels'])); return view('dns.show', compact(['dn', 'dns', 'labels']));
@ -80,19 +83,23 @@ class DNSController extends Controller
$Resellers = Reseller::all(); $Resellers = Reseller::all();
$dn = DNS::findOrFail($dn->id); $dn = DNS::findOrFail($dn->id);
$labels = DB::table('labels_assigned as l') $labels = DB::table('labels_assigned as l')
->join('labels', 'l.label_id', '=', 'labels.id') ->join('labels', 'l.label_id', 'labels.id')
->where('l.service_id', '=', $dn->id) ->where('l.service_id', $dn->id)
->get(['labels.id', 'labels.label']); ->get(['labels.id']);
return view('dns.edit', compact(['dn', 'labels', 'Servers', 'Domains', 'Shareds', 'Resellers'])); return view('dns.edit', compact(['dn', 'labels', 'Servers', 'Domains', 'Shareds', 'Resellers']));
} }
public function update(Request $request, DNS $dn) public function update(Request $request, DNS $dn): \Illuminate\Http\RedirectResponse
{ {
$request->validate([ $request->validate([
'hostname' => 'required|min:2', 'hostname' => 'required|string|min:2',
'address' => 'required|min:2', 'address' => 'required|string|min:2',
'dns_type' => 'required' 'dns_type' => 'required|string',
'label1' => 'sometimes|nullable|string',
'label2' => 'sometimes|nullable|string',
'label3' => 'sometimes|nullable|string',
'label4' => 'sometimes|nullable|string',
]); ]);
$dn->update([ $dn->update([
@ -113,18 +120,18 @@ class DNSController extends Controller
->with('success', 'DNS updated Successfully.'); ->with('success', 'DNS updated Successfully.');
} }
public function destroy(DNS $dn) public function destroy(DNS $dn): \Illuminate\Http\RedirectResponse
{ {
$id = $dn->id; if ( $dn->delete()){
$items = DNS::find($id); Cache::forget('dns_count');
$items->delete(); Labels::deleteLabelsAssignedTo($dn->id);
Cache::forget('dns_count'); return redirect()->route('dns.index')
->with('success', 'DNS was deleted Successfully.');
Labels::deleteLabelsAssignedTo($id); }
return redirect()->route('dns.index') return redirect()->route('dns.index')
->with('success', 'DNS was deleted Successfully.'); ->with('error', 'DNS was not deleted.');
} }
} }

View file

@ -7,23 +7,5 @@ use Illuminate\Http\Request;
class DiskSpeedController extends Controller class DiskSpeedController extends Controller
{ {
public function index()
{
//
}
public function create()
{
//
}
public function store(Request $request)
{
//
}
public function destroy(DiskSpeed $diskSpeed)
{
//
}
} }

View file

@ -14,20 +14,16 @@ use Illuminate\Support\Str;
class DomainsController extends Controller class DomainsController extends Controller
{ {
public function index() public function index()
{ {
$domains = Domains::domainsDataIndexPage(); $domains = Domains::allDomains();
return view('domains.index', compact(['domains'])); return view('domains.index', compact(['domains']));
} }
public function show(Domains $domain) public function show(Domains $domain)
{ {//Need to modern
$service_extras = Domains::domainsDataShowPage($domain->id); $domain_info = Domains::domain($domain->id);
$labels = Labels::labelsForService($domain->id); return view('domains.show', compact(['domain_info']));
return view('domains.show', compact(['domain', 'service_extras', 'labels']));
} }
public function create() public function create()
@ -38,20 +34,25 @@ class DomainsController extends Controller
public function store(Request $request) public function store(Request $request)
{ {
$request->validate([ $request->validate([
'domain' => 'required|min:2', 'domain' => 'required|string|min:2',
'extension' => 'required|min:2', 'extension' => 'required|string|min:2',
'provider_id' => 'numeric', 'ns1' => 'sometimes|nullable|min:2',
'ns2' => 'sometimes|nullable|min:2',
'ns3' => 'sometimes|nullable|min:2',
'provider_id' => 'integer',
'payment_term' => 'integer',
'price' => 'numeric', 'price' => 'numeric',
'next_due_date' => 'required|date' 'next_due_date' => 'required|date',
'owned_since' => 'sometimes|nullable|date',
'label1' => 'sometimes|nullable|string',
'label2' => 'sometimes|nullable|string',
'label3' => 'sometimes|nullable|string',
'label4' => 'sometimes|nullable|string',
]); ]);
$domain_id = Str::random(8); $domain_id = Str::random(8);
$pricing = new Pricing(); $pricing = new Pricing();
$pricing->insertPricing(4, $domain_id, $request->currency, $request->price, $request->payment_term, $request->next_due_date);
$as_usd = $pricing->convertToUSD($request->price, $request->currency);
$pricing->insertPricing(4, $domain_id, $request->currency, $request->price, $request->payment_term, $as_usd, $request->next_due_date);
Domains::create([ Domains::create([
'id' => $domain_id, 'id' => $domain_id,
@ -66,6 +67,7 @@ class DomainsController extends Controller
Labels::insertLabelsAssigned([$request->label1, $request->label2, $request->label3, $request->label4], $domain_id); Labels::insertLabelsAssigned([$request->label1, $request->label2, $request->label3, $request->label4], $domain_id);
Cache::forget("all_domains");
Home::homePageCacheForget(); Home::homePageCacheForget();
return redirect()->route('domains.index') return redirect()->route('domains.index')
@ -74,27 +76,31 @@ class DomainsController extends Controller
public function edit(Domains $domain) public function edit(Domains $domain)
{ {
$domain_info = Domains::domainsDataEditPage($domain->id); $domain_info = Domains::domain($domain->id);
return view('domains.edit', compact(['domain_info']));
$labels = Labels::labelsForService($domain->id);
return view('domains.edit', compact(['domain', 'domain_info', 'labels']));
} }
public function update(Request $request, Domains $domain) public function update(Request $request, Domains $domain)
{ {
$request->validate([ $request->validate([
'domain' => 'required|min:2', 'domain' => 'required|string|min:2',
'extension' => 'required|min:2', 'extension' => 'required|string|min:2',
'provider_id' => 'numeric', 'ns1' => 'sometimes|nullable|min:2',
'price' => 'numeric' 'ns2' => 'sometimes|nullable|min:2',
'ns3' => 'sometimes|nullable|min:2',
'provider_id' => 'integer',
'payment_term' => 'integer',
'price' => 'numeric',
'next_due_date' => 'required|date',
'owned_since' => 'sometimes|nullable|date',
'label1' => 'sometimes|nullable|string',
'label2' => 'sometimes|nullable|string',
'label3' => 'sometimes|nullable|string',
'label4' => 'sometimes|nullable|string',
]); ]);
$pricing = new Pricing(); $pricing = new Pricing();
$pricing->updatePricing($domain->id, $request->currency, $request->price, $request->payment_term, $request->next_due_date);
$as_usd = $pricing->convertToUSD($request->price, $request->currency);
$pricing->updatePricing($domain->id, $request->currency, $request->price, $request->payment_term, $as_usd, $request->next_due_date);
$domain->update([ $domain->update([
'domain' => $request->domain, 'domain' => $request->domain,
@ -108,9 +114,10 @@ class DomainsController extends Controller
]); ]);
Labels::deleteLabelsAssignedTo($domain->id); Labels::deleteLabelsAssignedTo($domain->id);
Labels::insertLabelsAssigned([$request->label1, $request->label2, $request->label3, $request->label4], $domain->id); Labels::insertLabelsAssigned([$request->label1, $request->label2, $request->label3, $request->label4], $domain->id);
Cache::forget("all_domains");
Cache::forget("domain.{$domain->id}");
Cache::forget("labels_for_service.{$domain->id}"); Cache::forget("labels_for_service.{$domain->id}");
Home::homePageCacheForget(); Home::homePageCacheForget();
@ -120,19 +127,22 @@ class DomainsController extends Controller
public function destroy(Domains $domain) public function destroy(Domains $domain)
{ {
$items = Domains::find($domain->id); if ($domain->delete()){
$p = new Pricing();
$p->deletePricing($domain->id);
$items->delete(); Labels::deleteLabelsAssignedTo($domain->id);
$p = new Pricing(); Cache::forget("all_domains");
$p->deletePricing($domain->id); Cache::forget("domain.{$domain->id}");
Home::homePageCacheForget();
Labels::deleteLabelsAssignedTo($domain->id); return redirect()->route('domains.index')
->with('success', 'Domain was deleted Successfully.');
Home::homePageCacheForget(); }
return redirect()->route('domains.index') return redirect()->route('domains.index')
->with('success', 'Domain was deleted Successfully.'); ->with('error', 'Domain was not deleted.');
} }
} }

View file

@ -7,9 +7,6 @@ use App\Models\Home;
use App\Models\Labels; use App\Models\Labels;
use App\Models\Pricing; use App\Models\Pricing;
use App\Models\Settings; use App\Models\Settings;
use Carbon\Carbon;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;
use App\Process; use App\Process;
use Illuminate\Support\Facades\Session; use Illuminate\Support\Facades\Session;
@ -47,7 +44,7 @@ class HomeController extends Controller
$p->stopTimer(); $p->stopTimer();
$information = array( $information = [
'servers' => $service_count['servers'], 'servers' => $service_count['servers'],
'domains' => $service_count['domains'], 'domains' => $service_count['domains'],
'shared' => $service_count['shared'], 'shared' => $service_count['shared'],
@ -59,7 +56,7 @@ class HomeController extends Controller
'total_services' => $service_count['total'], 'total_services' => $service_count['total'],
'total_inactive' => $pricing_breakdown['inactive_count'], 'total_inactive' => $pricing_breakdown['inactive_count'],
'total_cost_weekly' => number_format($pricing_breakdown['total_cost_weekly'], 2), 'total_cost_weekly' => number_format($pricing_breakdown['total_cost_weekly'], 2),
'total_cost_monthly' => number_format($pricing_breakdown['total_cost_montly'], 2), 'total_cost_monthly' => number_format($pricing_breakdown['total_cost_monthly'], 2),
'total_cost_yearly' => number_format($pricing_breakdown['total_cost_yearly'], 2), 'total_cost_yearly' => number_format($pricing_breakdown['total_cost_yearly'], 2),
'total_cost_2_yearly' => number_format(($pricing_breakdown['total_cost_yearly'] * 2), 2), 'total_cost_2_yearly' => number_format(($pricing_breakdown['total_cost_yearly'] * 2), 2),
'due_soon' => $due_soon, 'due_soon' => $due_soon,
@ -67,7 +64,7 @@ class HomeController extends Controller
'execution_time' => number_format($p->getTimeTaken(), 2), 'execution_time' => number_format($p->getTimeTaken(), 2),
'servers_summary' => $server_summary, 'servers_summary' => $server_summary,
'currency' => Session::get('dashboard_currency') 'currency' => Session::get('dashboard_currency')
); ];
return view('home', compact('information')); return view('home', compact('information'));
} }

View file

@ -2,13 +2,13 @@
namespace App\Http\Controllers; namespace App\Http\Controllers;
use App\Models\DNS;
use App\Models\IPs; use App\Models\IPs;
use App\Models\Reseller; use App\Models\Reseller;
use App\Models\SeedBoxes;
use App\Models\Server; use App\Models\Server;
use App\Models\Shared; use App\Models\Shared;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Http;
use Illuminate\Support\Str; use Illuminate\Support\Str;
class IPsController extends Controller class IPsController extends Controller
@ -21,22 +21,24 @@ class IPsController extends Controller
public function create() public function create()
{ {
$Servers = Server::all(); $servers = Server::all();
$Shareds = Shared::all(); $shareds = Shared::all();
$Resellers = Reseller::all(); $resellers = Reseller::all();
return view('ips.create', compact(['Servers', 'Shareds', 'Resellers'])); $seed_boxes = SeedBoxes::all();
return view('ips.create', compact(['servers', 'shareds', 'resellers', 'seed_boxes']));
} }
public function store(Request $request) public function store(Request $request)
{ {
$request->validate([ $request->validate([
'address' => 'required|ip|min:2', 'address' => 'required|ip|min:2',
'ip_type' => 'required' 'ip_type' => 'required|string|size:4',
'service_id' => 'required|string'
]); ]);
$ip_id = Str::random(8); $ip_id = Str::random(8);
IPs::create([ $ip = IPs::create([
'id' => $ip_id, 'id' => $ip_id,
'address' => $request->address, 'address' => $request->address,
'is_ipv4' => ($request->ip_type === 'ipv4') ? 1 : 0, 'is_ipv4' => ($request->ip_type === 'ipv4') ? 1 : 0,
@ -44,16 +46,32 @@ class IPsController extends Controller
'active' => 1 'active' => 1
]); ]);
$fetch = IPs::getUpdateIpInfo($ip);
return redirect()->route('IPs.index') return redirect()->route('IPs.index')
->with('success', 'IP address created Successfully.'); ->with('success', 'IP address created Successfully.');
} }
public function destroy(IPs $IP) public function destroy(IPs $IP)
{ {
$items = IPs::find($IP->id); if ($IP->delete()) {
$items->delete(); return redirect()->route('IPs.index')
->with('success', 'IP address was deleted Successfully.');
}
return redirect()->route('IPs.index') return redirect()->route('IPs.index')
->with('success', 'IP address was deleted Successfully.'); ->with('error', 'IP was not deleted.');
} }
public function getUpdateWhoIs(IPs $IP): \Illuminate\Http\RedirectResponse
{
$result = IPs::getUpdateIpInfo($IP);
if ($result) {
return redirect()->route('IPs.index')
->with('success', 'IP address updated Successfully.');
}
return redirect()->route('IPs.index')
->with('error', 'IP was not updated.');
}
} }

View file

@ -25,7 +25,7 @@ class LabelsController extends Controller
public function store(Request $request) public function store(Request $request)
{ {
$request->validate([ $request->validate([
'label' => 'required|min:2' 'label' => 'required|string|min:2'
]); ]);
Labels::create([ Labels::create([
@ -43,37 +43,31 @@ class LabelsController extends Controller
public function show(Labels $label) public function show(Labels $label)
{ {
$labels = DB::table('labels_assigned as las') $labels = DB::table('labels_assigned as las')
->leftJoin('pricings as p', 'las.service_id', '=', 'p.service_id') ->leftJoin('pricings as p', 'las.service_id', 'p.service_id')
->leftJoin('servers as s', 'las.service_id', '=', 's.id') ->leftJoin('servers as s', 'las.service_id', 's.id')
->leftJoin('shared_hosting as sh', 'las.service_id', '=', 'sh.id') ->leftJoin('shared_hosting as sh', 'las.service_id', 'sh.id')
->leftJoin('reseller_hosting as r', 'las.service_id', '=', 'r.id') ->leftJoin('reseller_hosting as r', 'las.service_id', 'r.id')
->leftJoin('domains as d', 'las.service_id', '=', 'd.id') ->leftJoin('domains as d', 'las.service_id', 'd.id')
->where('las.label_id', '=', $label->id) ->where('las.label_id', $label->id)
->get(['p.service_type', 'p.service_id', 's.hostname', 'sh.main_domain as shared', 'r.main_domain as reseller', 'd.domain', 'd.extension']); ->get(['p.service_type', 'p.service_id', 's.hostname', 'sh.main_domain as shared', 'r.main_domain as reseller', 'd.domain', 'd.extension']);
return view('labels.show', compact(['label', 'labels'])); return view('labels.show', compact(['label', 'labels']));
} }
public function edit(Labels $label)
{
abort(404);
}
public function destroy(Labels $label) public function destroy(Labels $label)
{ {
$label_id = $label->id; if ($label->delete()) {
Cache::forget('labels_count');
$items = Labels::find($label_id); Labels::deleteLabelAssignedAs($label->id);
$items->delete(); Cache::forget('all_labels');
Cache::forget('labels_count'); return redirect()->route('labels.index')
->with('success', 'Label was deleted Successfully.');
Labels::deleteLabelAssignedAs($label_id); }
Cache::forget('all_labels');
return redirect()->route('labels.index') return redirect()->route('labels.index')
->with('success', 'Label was deleted Successfully.'); ->with('error', 'Label was not deleted.');
} }
} }

View file

@ -24,7 +24,7 @@ class LocationsController extends Controller
public function store(Request $request) public function store(Request $request)
{ {
$request->validate([ $request->validate([
'location_name' => 'required|min:2' 'location_name' => 'required|string|min:2|max:255'
]); ]);
Locations::create([ Locations::create([
@ -40,17 +40,17 @@ class LocationsController extends Controller
public function show(Locations $location) public function show(Locations $location)
{ {
$servers = DB::table('servers as s') $servers = DB::table('servers as s')
->where('s.location_id', '=', $location->id) ->where('s.location_id', $location->id)
->get(['s.id', 's.hostname']) ->get(['s.id', 's.hostname'])
->toArray(); ->toArray();
$shared = DB::table('shared_hosting as s') $shared = DB::table('shared_hosting as s')
->where('s.location_id', '=', $location->id) ->where('s.location_id', $location->id)
->get(['s.id', 's.main_domain as main_domain_shared']) ->get(['s.id', 's.main_domain as main_domain_shared'])
->toArray(); ->toArray();
$reseller = DB::table('reseller_hosting as r') $reseller = DB::table('reseller_hosting as r')
->where('r.location_id', '=', $location->id) ->where('r.location_id', $location->id)
->get(['r.id', 'r.main_domain as main_domain_reseller']) ->get(['r.id', 'r.main_domain as main_domain_reseller'])
->toArray(); ->toArray();
@ -61,13 +61,15 @@ class LocationsController extends Controller
public function destroy(Locations $location) public function destroy(Locations $location)
{ {
$items = Locations::find($location->id); if ($location->delete()){
Cache::forget('locations');
$items->delete(); return redirect()->route('locations.index')
->with('success', 'Location was deleted Successfully.');
Cache::forget('locations'); }
return redirect()->route('locations.index') return redirect()->route('locations.index')
->with('success', 'Location was deleted Successfully.'); ->with('error', 'Location was not deleted.');
} }
} }

View file

@ -7,17 +7,13 @@ use App\Models\Misc;
use App\Models\Pricing; use App\Models\Pricing;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache; use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str; use Illuminate\Support\Str;
class MiscController extends Controller class MiscController extends Controller
{ {
public function index() public function index()
{ {
$misc = DB::table('misc_services as d') $misc = Misc::allMisc();
->join('pricings as pr', 'd.id', '=', 'pr.service_id')
->get(['d.*', 'pr.*']);
return view('misc.index', compact(['misc'])); return view('misc.index', compact(['misc']));
} }
@ -28,37 +24,33 @@ class MiscController extends Controller
public function show(Misc $misc) public function show(Misc $misc)
{ {
$service_extras = DB::table('misc_services as m') $misc_data = Misc::misc($misc->id);
->join('pricings as p', 'm.id', '=', 'p.service_id') return view('misc.show', compact(['misc_data']));
->where('m.id', '=', $misc->id)
->get(['m.*', 'p.*']);
return view('misc.show', compact(['misc', 'service_extras']));
} }
public function store(Request $request) public function store(Request $request)
{ {
$request->validate([ $request->validate([
'name' => 'required|min:3', 'name' => 'required|string|min:3',
'price' => 'required|numeric', 'price' => 'required|numeric',
'owned_since' => 'date', 'payment_term' => 'required|integer',
'currency' => 'required|string|size:3',
'owned_since' => 'sometimes|nullable|date',
'next_due_date' => 'required|date' 'next_due_date' => 'required|date'
]); ]);
$ms_id = Str::random(8); $misc_id = Str::random(8);
$pricing = new Pricing(); $pricing = new Pricing();
$pricing->insertPricing(5, $misc_id, $request->currency, $request->price, $request->payment_term, $request->next_due_date);
$as_usd = $pricing->convertToUSD($request->price, $request->currency);
$pricing->insertPricing(5, $ms_id, $request->currency, $request->price, $request->payment_term, $as_usd, $request->next_due_date);
Misc::create([ Misc::create([
'id' => $ms_id, 'id' => $misc_id,
'name' => $request->name, 'name' => $request->name,
'owned_since' => $request->owned_since 'owned_since' => $request->owned_since
]); ]);
Cache::forget("all_misc");
Home::homePageCacheForget(); Home::homePageCacheForget();
return redirect()->route('misc.index') return redirect()->route('misc.index')
@ -67,35 +59,32 @@ class MiscController extends Controller
public function edit(Misc $misc) public function edit(Misc $misc)
{ {
$misc = DB::table('misc_services as s') $misc_data = Misc::misc($misc->id);
->join('pricings as p', 's.id', '=', 'p.service_id') return view('misc.edit', compact('misc_data'));
->where('s.id', '=', $misc->id)
->get(['s.*', 'p.*']);
return view('misc.edit', compact('misc'));
} }
public function update(Request $request, Misc $misc) public function update(Request $request, Misc $misc)
{ {
$request->validate([ $request->validate([
'name' => 'required', 'name' => 'required|string|min:3',
'owned_since' => 'date', 'price' => 'required|numeric',
'payment_term' => 'required|integer',
'currency' => 'required|string|size:3',
'owned_since' => 'sometimes|nullable|date',
'next_due_date' => 'required|date'
]); ]);
DB::table('misc_services') $misc->update([
->where('id', $misc->id) 'name' => $request->name,
->update([ 'owned_since' => $request->owned_since,
'name' => $request->name, 'active' => (isset($request->is_active)) ? 1 : 0
'owned_since' => $request->owned_since, ]);
'active' => (isset($request->is_active)) ? 1 : 0
]);
$pricing = new Pricing(); $pricing = new Pricing();
$pricing->updatePricing($misc->id, $request->currency, $request->price, $request->payment_term, $request->next_due_date);
$as_usd = $pricing->convertToUSD($request->price, $request->currency); Cache::forget("all_misc");
Cache::forget("misc.{$misc->id}");
$pricing->updatePricing($misc->id, $request->currency, $request->price, $request->payment_term, $as_usd, $request->next_due_date);
Home::homePageCacheForget(); Home::homePageCacheForget();
return redirect()->route('misc.index') return redirect()->route('misc.index')
@ -104,16 +93,19 @@ class MiscController extends Controller
public function destroy(Misc $misc) public function destroy(Misc $misc)
{ {
$items = Misc::find($misc->id); if ($misc->delete()) {
$p = new Pricing();
$p->deletePricing($misc->id);
$items->delete(); Cache::forget("all_misc");
Cache::forget("misc.{$misc->id}");
Home::homePageCacheForget();
$p = new Pricing(); return redirect()->route('misc.index')
$p->deletePricing($misc->id); ->with('success', 'Misc service was deleted Successfully.');
}
Home::homePageCacheForget();
return redirect()->route('misc.index') return redirect()->route('misc.index')
->with('success', 'Misc service was deleted Successfully.'); ->with('error', 'Misc service was not deleted.');
} }
} }

View file

@ -7,18 +7,4 @@ use Illuminate\Http\Request;
class NetworkSpeedController extends Controller class NetworkSpeedController extends Controller
{ {
public function index()
{
//
}
public function show(NetworkSpeed $networkSpeed)
{
//
}
public function destroy(NetworkSpeed $networkSpeed)
{
//
}
} }

View file

@ -0,0 +1,123 @@
<?php
namespace App\Http\Controllers;
use App\Models\DNS;
use App\Models\Domains;
use App\Models\IPs;
use App\Models\Note;
use App\Models\Reseller;
use App\Models\Server;
use App\Models\Shared;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Str;
class NoteController extends Controller
{
public function index()
{
$notes = Note::allNotes();
return view('notes.index', compact('notes'));
}
public function create()
{
$servers = Server::all();
$shareds = Shared::all();
$resellers = Reseller::all();
$domains = Domains::all();
$dns = DNS::all();
$ips = IPs::all();
return view('notes.create', compact(['servers', 'shareds', 'resellers', 'domains', 'dns', 'ips']));
}
public function store(Request $request)
{
$request->validate([
'service_id' => 'required|string|size:8',
'note' => 'required|string',
]);
try {
$note_id = Str::random(8);
$a = Note::create([
'id' => $note_id,
'service_id' => $request->service_id,
'note' => $request->note
]);
} catch (\Exception $e) {
if ($e->getCode() === "23000") {
$message = "A note already exists for this service";
} else {
$message = "Error inserting note";
}
return redirect()->route('notes.create')
->withInput($request->input())->with('error', $message);
}
Cache::forget('all_notes');
return redirect()->route('notes.index')
->with('success', 'Note created successfully.');
}
public function edit(Note $note)
{
$note = Note::note($note->service_id);
$servers = Server::all();
$shareds = Shared::all();
$resellers = Reseller::all();
$domains = Domains::all();
$dns = DNS::all();
$ips = IPs::all();
return view('notes.edit', compact(['note', 'servers', 'shareds', 'resellers', 'domains', 'dns', 'ips']));
}
public function update(Request $request, Note $note)
{
$request->validate([
'service_id' => 'required|string|size:8',
'note' => 'required|string'
]);
$note->update([
'service_id' => $request->service_id,
'note' => $request->note
]);
Cache::forget('all_notes');
Cache::forget("note.$note->service_id");
return redirect()->route('notes.index')
->with('success', 'Note was updated successfully.');
}
public function show(Note $note)
{
$note = Note::note($note->service_id);
return view('notes.show', compact(['note']));
}
public function destroy(Note $note)
{
if ($note->delete()) {
Cache::forget("all_notes");
Cache::forget("note.$note->service_id");
return redirect()->route('notes.index')
->with('success', 'Note was deleted successfully.');
}
return redirect()->route('notes.index')
->with('error', 'Note was not deleted.');
}
}

View file

@ -10,7 +10,7 @@ class OsController extends Controller
{ {
public function index() public function index()
{ {
$os = OS::allOS(); $os = OS::allOS()->toArray();
return view('os.index', compact(['os'])); return view('os.index', compact(['os']));
} }
@ -22,7 +22,7 @@ class OsController extends Controller
public function store(Request $request) public function store(Request $request)
{ {
$request->validate([ $request->validate([
'os_name' => 'required|min:2' 'os_name' => 'required|string|min:2|max:255'
]); ]);
OS::create([ OS::create([
@ -37,13 +37,15 @@ class OsController extends Controller
public function destroy(OS $o) public function destroy(OS $o)
{ {
$items = OS::find($o->id); if ($o->delete()) {
Cache::forget('operating_systems');
$items->delete(); return redirect()->route('os.index')
->with('success', 'OS was deleted Successfully.');
Cache::forget('operating_systems'); }
return redirect()->route('os.index') return redirect()->route('os.index')
->with('success', 'OS was deleted Successfully.'); ->with('error', 'OS was not deleted.');
} }
} }

View file

@ -7,13 +7,5 @@ use Illuminate\Http\Request;
class PricingController extends Controller class PricingController extends Controller
{ {
public function index()
{
//
}
public function destroy(Pricing $pricing)
{
//
}
} }

View file

@ -3,10 +3,8 @@
namespace App\Http\Controllers; namespace App\Http\Controllers;
use App\Models\Providers; use App\Models\Providers;
use DataTables;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache; use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;
class ProvidersController extends Controller class ProvidersController extends Controller
{ {
@ -24,7 +22,7 @@ class ProvidersController extends Controller
public function store(Request $request) public function store(Request $request)
{ {
$request->validate([ $request->validate([
'provider_name' => 'required|min:2' 'provider_name' => 'required|string|min:2|max:255'
]); ]);
Providers::create([ Providers::create([
@ -46,29 +44,16 @@ class ProvidersController extends Controller
public function destroy(Providers $provider) public function destroy(Providers $provider)
{ {
$items = Providers::find($provider->id); if ($provider->delete()) {
Cache::forget('providers');
$items->delete(); return redirect()->route('providers.index')
->with('success', 'Provider was deleted Successfully.');
Cache::forget('providers'); }
return redirect()->route('providers.index') return redirect()->route('providers.index')
->with('success', 'Provider was deleted Successfully.'); ->with('error', 'Provider was not deleted.');
}
public function getProviders(Request $request)
{
if ($request->ajax()) {
$data = Providers::latest()->get();
$dt = Datatables::of($data)
->addIndexColumn()
->addColumn('action', function ($row) {
$actionBtn = '<a href="javascript:void(0)" class="edit btn btn-success btn-sm">Edit</a> <a href="javascript:void(0)" class="delete btn btn-danger btn-sm">Delete</a>';
return $actionBtn;
})
->rawColumns(['action'])
->make(true);
}
} }
} }

View file

@ -5,65 +5,56 @@ namespace App\Http\Controllers;
use App\Models\Home; use App\Models\Home;
use App\Models\IPs; use App\Models\IPs;
use App\Models\Labels; use App\Models\Labels;
use App\Models\Locations;
use App\Models\Pricing; use App\Models\Pricing;
use App\Models\Providers;
use App\Models\Reseller; use App\Models\Reseller;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache; use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str; use Illuminate\Support\Str;
class ResellerController extends Controller class ResellerController extends Controller
{ {
public function index() public function index()
{ {
$resellers = Reseller::resellerDataIndexPage(); $resellers = Reseller::allResellerHosting();
return view('reseller.index', compact(['resellers'])); return view('reseller.index', compact(['resellers']));
} }
public function create() public function create()
{ {
$Providers = Providers::allProviders(); return view('reseller.create');
$Locations = Locations::allLocations();
return view('reseller.create', compact(['Providers', 'Locations']));
} }
public function store(Request $request) public function store(Request $request)
{ {
$request->validate([ $request->validate([
'domain' => 'required|min:4', 'domain' => 'required|min:4',
'reseller_type' => 'required', 'reseller_type' => 'required|string',
'dedicated_ip' => 'present', 'disk' => 'integer',
'accounts' => 'numeric', 'os_id' => 'integer',
'server_type' => 'numeric', 'provider_id' => 'integer',
'ram' => 'numeric', 'location_id' => 'integer',
'disk' => 'numeric',
'os_id' => 'numeric',
'provider_id' => 'numeric',
'location_id' => 'numeric',
'price' => 'numeric', 'price' => 'numeric',
'payment_term' => 'numeric', 'payment_term' => 'integer',
'was_promo' => 'numeric', 'was_promo' => 'integer',
'owned_since' => 'date', 'owned_since' => 'sometimes|nullable|date',
'domains' => 'numeric', 'accounts' => 'integer',
'sub_domains' => 'numeric', 'domains' => 'integer',
'bandwidth' => 'numeric', 'sub_domains' => 'integer',
'email' => 'numeric', 'bandwidth' => 'integer',
'ftp' => 'numeric', 'email' => 'integer',
'db' => 'numeric', 'ftp' => 'integer',
'next_due_date' => 'required|date' 'db' => 'integer',
'next_due_date' => 'required|date',
'label1' => 'sometimes|nullable|string',
'label2' => 'sometimes|nullable|string',
'label3' => 'sometimes|nullable|string',
'label4' => 'sometimes|nullable|string',
]); ]);
$reseller_id = Str::random(8); $reseller_id = Str::random(8);
$pricing = new Pricing(); $pricing = new Pricing();
$pricing->insertPricing(3, $reseller_id, $request->currency, $request->price, $request->payment_term, $request->next_due_date);
$as_usd = $pricing->convertToUSD($request->price, $request->currency);
$pricing->insertPricing(3, $reseller_id, $request->currency, $request->price, $request->payment_term, $as_usd, $request->next_due_date);
if (!is_null($request->dedicated_ip)) { if (!is_null($request->dedicated_ip)) {
IPs::insertIP($reseller_id, $request->dedicated_ip); IPs::insertIP($reseller_id, $request->dedicated_ip);
@ -91,95 +82,86 @@ class ResellerController extends Controller
'db_limit' => $request->db 'db_limit' => $request->db
]); ]);
Cache::forget("all_reseller");
Home::homePageCacheForget(); Home::homePageCacheForget();
return redirect()->route('reseller.index') return redirect()->route('reseller.index')
->with('success', 'Reseller hosting created Successfully.'); ->with('success', 'Reseller hosting created Successfully.');
} }
public function show(Reseller $reseller) public function show(Reseller $reseller)
{ {
$reseller_extras = Reseller::resellerDataShowPage($reseller->id); $reseller = Reseller::resellerHosting($reseller->id);
return view('reseller.show', compact(['reseller']));
$labels = Labels::labelsForService($reseller->id);
$ip_address = IPs::ipsForServer($reseller->id);
return view('reseller.show', compact(['reseller', 'reseller_extras', 'labels', 'ip_address']));
} }
public function edit(Reseller $reseller) public function edit(Reseller $reseller)
{ {
$labels = Labels::labelsForService($reseller->id); $reseller = Reseller::resellerHosting($reseller->id);
return view('reseller.edit', compact(['reseller']));
$ip_address = IPs::ipsForServer($reseller->id);
$reseller = Reseller::resellerDataEditPage($reseller->id);
return view('reseller.edit', compact(['reseller', 'ip_address', 'labels']));
} }
public function update(Request $request, Reseller $reseller) public function update(Request $request, Reseller $reseller)
{ {
$request->validate([ $request->validate([
'id' => 'required|size:8',
'domain' => 'required|min:4', 'domain' => 'required|min:4',
'reseller_type' => 'required', 'reseller_type' => 'required|string',
'dedicated_ip' => 'present', 'disk' => 'integer',
'server_type' => 'numeric', 'os_id' => 'integer',
'disk' => 'numeric', 'provider_id' => 'integer',
'os_id' => 'numeric', 'location_id' => 'integer',
'provider_id' => 'numeric',
'location_id' => 'numeric',
'price' => 'numeric', 'price' => 'numeric',
'payment_term' => 'numeric', 'payment_term' => 'integer',
'was_promo' => 'numeric', 'was_promo' => 'integer',
'owned_since' => 'date', 'owned_since' => 'sometimes|nullable|date',
'domains' => 'numeric', 'accounts' => 'integer',
'sub_domains' => 'numeric', 'domains' => 'integer',
'bandwidth' => 'numeric', 'sub_domains' => 'integer',
'email' => 'numeric', 'bandwidth' => 'integer',
'ftp' => 'numeric', 'email' => 'integer',
'db' => 'numeric' 'ftp' => 'integer',
'db' => 'integer',
'next_due_date' => 'required|date',
'label1' => 'sometimes|nullable|string',
'label2' => 'sometimes|nullable|string',
'label3' => 'sometimes|nullable|string',
'label4' => 'sometimes|nullable|string',
]); ]);
DB::table('reseller_hosting') $reseller->update([
->where('id', $request->id) 'main_domain' => $request->domain,
->update([ 'reseller_type' => $request->reseller_type,
'main_domain' => $request->domain, 'provider_id' => $request->provider_id,
'reseller_type' => $request->reseller_type, 'location_id' => $request->location_id,
'provider_id' => $request->provider_id, 'accounts' => $request->accounts,
'location_id' => $request->location_id, 'disk' => $request->disk,
'disk' => $request->disk, 'disk_type' => 'GB',
'disk_type' => 'GB', 'disk_as_gb' => $request->disk,
'disk_as_gb' => $request->disk, 'owned_since' => $request->owned_since,
'owned_since' => $request->owned_since, 'bandwidth' => $request->bandwidth,
'bandwidth' => $request->bandwidth, 'was_promo' => $request->was_promo,
'was_promo' => $request->was_promo, 'domains_limit' => $request->domains,
'domains_limit' => $request->domains, 'subdomains_limit' => $request->sub_domains,
'subdomains_limit' => $request->sub_domains, 'email_limit' => $request->email,
'email_limit' => $request->email, 'ftp_limit' => $request->ftp,
'ftp_limit' => $request->ftp, 'db_limit' => $request->db
'db_limit' => $request->db ]);
]);
$pricing = new Pricing(); $pricing = new Pricing();
$pricing->updatePricing($reseller->id, $request->currency, $request->price, $request->payment_term, $request->next_due_date);
$as_usd = $pricing->convertToUSD($request->price, $request->currency); Labels::deleteLabelsAssignedTo($reseller->id);
Labels::insertLabelsAssigned([$request->label1, $request->label2, $request->label3, $request->label4], $reseller->id);
$pricing->updatePricing($request->id, $request->currency, $request->price, $request->payment_term, $as_usd, $request->next_due_date); IPs::deleteIPsAssignedTo($reseller->id);
Labels::deleteLabelsAssignedTo($request->id); if (!is_null($request->dedicated_ip)) {
IPs::insertIP($reseller->id, $request->dedicated_ip);
Labels::insertLabelsAssigned([$request->label1, $request->label2, $request->label3, $request->label4], $request->id);
IPs::deleteIPsAssignedTo($request->id);
if (isset($request->dedicated_ip)) {
IPs::insertIP($request->id, $request->dedicated_ip);
} }
Cache::forget("labels_for_service.{$request->id}"); Cache::forget("all_reseller");
Cache::forget("reseller_hosting.{$reseller->id}");
Cache::forget("labels_for_service.{$reseller->id}");
Home::homePageCacheForget(); Home::homePageCacheForget();
@ -189,21 +171,24 @@ class ResellerController extends Controller
public function destroy(Reseller $reseller) public function destroy(Reseller $reseller)
{ {
$id = $reseller->id; if ($reseller->delete()) {
$items = Reseller::find($id); $p = new Pricing();
$p->deletePricing($reseller->id);
$items->delete(); Labels::deleteLabelsAssignedTo($reseller->id);
$p = new Pricing(); IPs::deleteIPsAssignedTo($reseller->id);
$p->deletePricing($id);
Labels::deleteLabelsAssignedTo($id); Cache::forget("all_reseller");
Cache::forget("reseller_hosting.$reseller->id");
Home::homePageCacheForget();
IPs::deleteIPsAssignedTo($id); return redirect()->route('reseller.index')
->with('success', 'Reseller hosting was deleted Successfully.');
Home::homePageCacheForget(); }
return redirect()->route('reseller.index') return redirect()->route('reseller.index')
->with('success', 'Reseller hosting was deleted Successfully.'); ->with('error', 'Reseller was not deleted.');
} }
} }

View file

@ -3,22 +3,18 @@
namespace App\Http\Controllers; namespace App\Http\Controllers;
use App\Models\Home; use App\Models\Home;
use App\Models\IPs;
use App\Models\Labels; use App\Models\Labels;
use App\Models\Pricing; use App\Models\Pricing;
use App\Models\SeedBoxes; use App\Models\SeedBoxes;
use App\Models\Shared;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache; use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str; use Illuminate\Support\Str;
class SeedBoxesController extends Controller class SeedBoxesController extends Controller
{ {
public function index() public function index()
{ {
$seedboxes = SeedBoxes::seedBoxesDataIndexPage(); $seedboxes = SeedBoxes::allSeedboxes();
return view('seedboxes.index', compact(['seedboxes'])); return view('seedboxes.index', compact(['seedboxes']));
} }
@ -30,31 +26,31 @@ class SeedBoxesController extends Controller
public function store(Request $request) public function store(Request $request)
{ {
$request->validate([ $request->validate([
'title' => 'required|string', 'title' => 'required|string|min:2',
'hostname' => 'string|nullable', 'hostname' => 'sometimes|nullable|string|min:2',
'seed_box_type' => 'required', 'seed_box_type' => 'required|string',
'provider_id' => 'numeric', 'provider_id' => 'integer',
'location_id' => 'numeric', 'location_id' => 'integer',
'price' => 'numeric', 'price' => 'numeric',
'payment_term' => 'numeric', 'payment_term' => 'integer',
'was_promo' => 'numeric', 'was_promo' => 'integer',
'owned_since' => 'date', 'owned_since' => 'sometimes|nullable|date',
'disk' => 'numeric', 'disk' => 'integer',
'bandwidth' => 'numeric', 'bandwidth' => 'integer',
'port_speed' => 'numeric', 'port_speed' => 'integer',
'next_due_date' => 'required|date' 'next_due_date' => 'required|date',
'label1' => 'sometimes|nullable|string',
'label2' => 'sometimes|nullable|string',
'label3' => 'sometimes|nullable|string',
'label4' => 'sometimes|nullable|string',
]); ]);
$seedbox_id = Str::random(8); $seedbox_id = Str::random(8);
$pricing = new Pricing(); $pricing = new Pricing();
$pricing->insertPricing(6, $seedbox_id, $request->currency, $request->price, $request->payment_term, $request->next_due_date);
$as_usd = $pricing->convertToUSD($request->price, $request->currency);
$pricing->insertPricing(6, $seedbox_id, $request->currency, $request->price, $request->payment_term, $as_usd, $request->next_due_date);
Labels::deleteLabelsAssignedTo($seedbox_id); Labels::deleteLabelsAssignedTo($seedbox_id);
Labels::insertLabelsAssigned([$request->label1, $request->label2, $request->label3, $request->label4], $seedbox_id); Labels::insertLabelsAssigned([$request->label1, $request->label2, $request->label3, $request->label4], $seedbox_id);
SeedBoxes::create([ SeedBoxes::create([
@ -73,6 +69,7 @@ class SeedBoxesController extends Controller
'was_promo' => $request->was_promo 'was_promo' => $request->was_promo
]); ]);
Cache::forget("all_seedboxes");
Home::homePageCacheForget(); Home::homePageCacheForget();
return redirect()->route('seedboxes.index') return redirect()->route('seedboxes.index')
@ -82,69 +79,62 @@ class SeedBoxesController extends Controller
public function show(SeedBoxes $seedbox) public function show(SeedBoxes $seedbox)
{ {
$seedbox_extras = SeedBoxes::seedBoxDataShowPage($seedbox->id); $seedbox_data = SeedBoxes::seedbox($seedbox->id);
return view('seedboxes.show', compact(['seedbox_data']));
$labels = Labels::labelsForService($seedbox->id);
return view('seedboxes.show', compact(['seedbox', 'seedbox_extras', 'labels']));
} }
public function edit(SeedBoxes $seedbox) public function edit(SeedBoxes $seedbox)
{ {
$seedbox = SeedBoxes::seedBoxEditDataPage($seedbox->id); $seedbox_data = SeedBoxes::seedbox($seedbox->id);
return view('seedboxes.edit', compact(['seedbox_data']));
$labels = Labels::labelsForService($seedbox[0]->id);
return view('seedboxes.edit', compact(['seedbox', 'labels']));
} }
public function update(Request $request, SeedBoxes $seedbox) public function update(Request $request, SeedBoxes $seedbox)
{ {
$request->validate([ $request->validate([
'id' => 'required|size:8', 'title' => 'required|string|min:2',
'title' => 'required|string', 'hostname' => 'sometimes|nullable|string|min:2',
'hostname' => 'string|nullable', 'seed_box_type' => 'required|string',
'seed_box_type' => 'required', 'provider_id' => 'integer',
'disk' => 'numeric', 'location_id' => 'integer',
'provider_id' => 'numeric',
'location_id' => 'numeric',
'price' => 'numeric', 'price' => 'numeric',
'payment_term' => 'numeric', 'payment_term' => 'integer',
'was_promo' => 'numeric', 'was_promo' => 'integer',
'owned_since' => 'date', 'owned_since' => 'sometimes|nullable|date',
'bandwidth' => 'numeric', 'disk' => 'integer',
'port_speed' => 'numeric' 'bandwidth' => 'integer',
'port_speed' => 'integer',
'next_due_date' => 'required|date',
'label1' => 'sometimes|nullable|string',
'label2' => 'sometimes|nullable|string',
'label3' => 'sometimes|nullable|string',
'label4' => 'sometimes|nullable|string',
]); ]);
DB::table('seedboxes') $seedbox->update([
->where('id', $seedbox->id) 'title' => $request->title,
->update([ 'hostname' => $request->hostname,
'title' => $request->title, 'seed_box_type' => $request->seed_box_type,
'hostname' => $request->hostname, 'location_id' => $request->location_id,
'seed_box_type' => $request->seed_box_type, 'provider_id' => $request->provider_id,
'location_id' => $request->location_id, 'disk' => $request->disk,
'provider_id' => $request->provider_id, 'disk_type' => 'GB',
'disk' => $request->disk, 'disk_as_gb' => $request->disk,
'disk_type' => 'GB', 'owned_since' => $request->owned_since,
'disk_as_gb' => $request->disk, 'bandwidth' => $request->bandwidth,
'owned_since' => $request->owned_since, 'port_speed' => $request->port_speed,
'bandwidth' => $request->bandwidth, 'was_promo' => $request->was_promo
'port_speed' => $request->port_speed, ]);
'was_promo' => $request->was_promo
]);
$pricing = new Pricing(); $pricing = new Pricing();
$pricing->updatePricing($seedbox->id, $request->currency, $request->price, $request->payment_term, $request->next_due_date);
$as_usd = $pricing->convertToUSD($request->price, $request->currency);
$pricing->updatePricing($seedbox->id, $request->currency, $request->price, $request->payment_term, $as_usd, $request->next_due_date);
Labels::deleteLabelsAssignedTo($seedbox->id); Labels::deleteLabelsAssignedTo($seedbox->id);
Labels::insertLabelsAssigned([$request->label1, $request->label2, $request->label3, $request->label4], $seedbox->id); Labels::insertLabelsAssigned([$request->label1, $request->label2, $request->label3, $request->label4], $seedbox->id);
Cache::forget("all_seedboxes");
Cache::forget("seedbox.{$seedbox->id}");
Cache::forget("labels_for_service.{$seedbox->id}"); Cache::forget("labels_for_service.{$seedbox->id}");
Home::homePageCacheForget(); Home::homePageCacheForget();
return redirect()->route('seedboxes.index') return redirect()->route('seedboxes.index')
@ -153,18 +143,21 @@ class SeedBoxesController extends Controller
public function destroy(SeedBoxes $seedbox) public function destroy(SeedBoxes $seedbox)
{ {
$seedbox_id = $seedbox->id; if ($seedbox->delete()) {
$items = SeedBoxes::find($seedbox_id); $p = new Pricing();
$items->delete(); $p->deletePricing($seedbox->id);
$p = new Pricing(); Labels::deleteLabelsAssignedTo($seedbox->id);
$p->deletePricing($seedbox_id);
Labels::deleteLabelsAssignedTo($seedbox_id); Cache::forget("all_seedboxes");
Cache::forget("seedbox.{$seedbox->id}");
Home::homePageCacheForget();
Home::homePageCacheForget(); return redirect()->route('seedboxes.index')
->with('success', 'Seed box was deleted Successfully.');
}
return redirect()->route('seedboxes.index') return redirect()->route('seedboxes.index')
->with('success', 'Seed box was deleted Successfully.'); ->with('error', 'Seed box was not deleted.');
} }
} }

View file

@ -7,12 +7,9 @@ use App\Models\Labels;
use App\Models\Pricing; use App\Models\Pricing;
use App\Models\Server; use App\Models\Server;
use App\Models\Settings; use App\Models\Settings;
use App\Models\Yabs;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Session; use Illuminate\Support\Facades\Session;
use Illuminate\Support\Str; use Illuminate\Support\Str;
use Illuminate\Support\Facades\DB;
class ServerController extends Controller class ServerController extends Controller
{ {
@ -20,31 +17,20 @@ class ServerController extends Controller
public function index() public function index()
{ {
$servers = Server::allActiveServers(); $servers = Server::allActiveServers();
$non_active_servers = Server::allNonActiveServers(); $non_active_servers = Server::allNonActiveServers();
return view('servers.index', compact(['servers', 'non_active_servers'])); return view('servers.index', compact(['servers', 'non_active_servers']));
} }
public function showServersPublic() public function showServersPublic()
{ {
$settings = Settings::getSettings(); $settings = Settings::getSettings();
Settings::setSettingsToSession($settings);
Session::put('timer_version_footer', $settings[0]->show_versions_footer ?? 1);
Session::put('show_servers_public', $settings[0]->show_servers_public ?? 0);
Session::put('show_server_value_ip', $settings[0]->show_server_value_ip ?? 0);
Session::put('show_server_value_hostname', $settings[0]->show_server_value_hostname ?? 0);
Session::put('show_server_value_price', $settings[0]->show_server_value_price ?? 0);
Session::put('show_server_value_yabs', $settings[0]->show_server_value_yabs ?? 0);
Session::put('show_server_value_provider', $settings[0]->show_server_value_provider ?? 0);
Session::put('show_server_value_location', $settings[0]->show_server_value_location ?? 0);
Session::save();
if ((Session::get('show_servers_public') === 1)) { if ((Session::get('show_servers_public') === 1)) {
$servers = Server::allPublicServers(); $servers = Server::allPublicServers();
return view('servers.public-index', compact('servers')); return view('servers.public-index', compact('servers'));
} }
return response()->view('errors.404', array("status" => 404, "title" => "Page not found", "message" => ""), 404); abort(404);
} }
public function create() public function create()
@ -54,31 +40,35 @@ class ServerController extends Controller
public function store(Request $request) public function store(Request $request)
{ {
$request->validate([ $request->validate([
'hostname' => 'required|min:5', 'hostname' => 'required|min:5',
'ip1' => 'nullable|ip', 'ip1' => 'sometimes|nullable|ip',
'ip2' => 'nullable|ip', 'ip2' => 'sometimes|nullable|ip',
'service_type' => 'numeric', 'ns1' => 'sometimes|nullable|string',
'server_type' => 'numeric', 'ns2' => 'sometimes|nullable|string',
'ram' => 'numeric', 'server_type' => 'integer',
'disk' => 'numeric', 'ssh_port' => 'integer',
'os_id' => 'numeric', 'bandwidth' => 'integer',
'provider_id' => 'numeric', 'ram' => 'required|numeric',
'location_id' => 'numeric', 'disk' => 'required|integer',
'price' => 'numeric', 'os_id' => 'required|integer',
'cpu' => 'numeric', 'provider_id' => 'required|integer',
'was_promo' => 'numeric', 'location_id' => 'required|integer',
'next_due_date' => 'required|date' 'price' => 'required|numeric',
'cpu' => 'required|integer',
'was_promo' => 'integer',
'next_due_date' => 'required|date',
'owned_since' => 'sometimes|nullable|date',
'label1' => 'sometimes|nullable|string',
'label2' => 'sometimes|nullable|string',
'label3' => 'sometimes|nullable|string',
'label4' => 'sometimes|nullable|string',
]); ]);
$server_id = Str::random(8); $server_id = Str::random(8);
$pricing = new Pricing(); $pricing = new Pricing();
$pricing->insertPricing(1, $server_id, $request->currency, $request->price, $request->payment_term, $request->next_due_date);
$as_usd = $pricing->convertToUSD($request->price, $request->currency);
$pricing->insertPricing(1, $server_id, $request->currency, $request->price, $request->payment_term, $as_usd, $request->next_due_date);
if (!is_null($request->ip1)) { if (!is_null($request->ip1)) {
IPs::insertIP($server_id, $request->ip1); IPs::insertIP($server_id, $request->ip1);
@ -121,14 +111,14 @@ class ServerController extends Controller
public function show(Server $server) public function show(Server $server)
{ {
$server_data = Server::server($server->id)[0]; $server_data = Server::server($server->id);
return view('servers.show', compact(['server_data'])); return view('servers.show', compact(['server_data']));
} }
public function edit(Server $server) public function edit(Server $server)
{ {
$server_data = Server::server($server->id)[0]; $server_data = Server::server($server->id);
return view('servers.edit', compact(['server_data'])); return view('servers.edit', compact(['server_data']));
} }
@ -137,65 +127,70 @@ class ServerController extends Controller
{ {
$request->validate([ $request->validate([
'hostname' => 'required|min:5', 'hostname' => 'required|min:5',
'ram' => 'numeric', 'ip1' => 'sometimes|nullable|ip',
'disk' => 'numeric', 'ip2' => 'sometimes|nullable|ip',
'os_id' => 'numeric', 'ns1' => 'sometimes|nullable|string',
'provider_id' => 'numeric', 'ns2' => 'sometimes|nullable|string',
'location_id' => 'numeric', 'server_type' => 'integer',
'price' => 'numeric', 'ssh_port' => 'integer',
'cpu' => 'numeric', 'bandwidth' => 'integer',
'was_promo' => 'numeric', 'ram' => 'required|numeric',
'next_due_date' => 'date' 'disk' => 'required|integer',
'os_id' => 'required|integer',
'provider_id' => 'required|integer',
'location_id' => 'required|integer',
'price' => 'required|numeric',
'cpu' => 'required|integer',
'was_promo' => 'integer',
'next_due_date' => 'required|date',
'owned_since' => 'sometimes|nullable|date',
'label1' => 'sometimes|nullable|string',
'label2' => 'sometimes|nullable|string',
'label3' => 'sometimes|nullable|string',
'label4' => 'sometimes|nullable|string',
]); ]);
$server_id = $request->server_id; $server->update([
'hostname' => $request->hostname,
DB::table('servers') 'server_type' => $request->server_type,
->where('id', $server_id) 'os_id' => $request->os_id,
->update([ 'ssh' => $request->ssh_port,
'hostname' => $request->hostname, 'provider_id' => $request->provider_id,
'server_type' => $request->server_type, 'location_id' => $request->location_id,
'os_id' => $request->os_id, 'ram' => $request->ram,
'ssh' => $request->ssh, 'ram_type' => $request->ram_type,
'provider_id' => $request->provider_id, 'ram_as_mb' => ($request->ram_type === 'MB') ? $request->ram : ($request->ram * 1024),
'location_id' => $request->location_id, 'disk' => $request->disk,
'ram' => $request->ram, 'disk_type' => $request->disk_type,
'ram_type' => $request->ram_type, 'disk_as_gb' => ($request->disk_type === 'GB') ? $request->disk : ($request->disk * 1024),
'ram_as_mb' => ($request->ram_type === 'MB') ? $request->ram : ($request->ram * 1024), 'owned_since' => $request->owned_since,
'disk' => $request->disk, 'ns1' => $request->ns1,
'disk_type' => $request->disk_type, 'ns2' => $request->ns2,
'disk_as_gb' => ($request->disk_type === 'GB') ? $request->disk : ($request->disk * 1024), 'bandwidth' => $request->bandwidth,
'owned_since' => $request->owned_since, 'cpu' => $request->cpu,
'ns1' => $request->ns1, 'was_promo' => $request->was_promo,
'ns2' => $request->ns2, 'active' => (isset($request->is_active)) ? 1 : 0,
'bandwidth' => $request->bandwidth, 'show_public' => (isset($request->show_public)) ? 1 : 0
'cpu' => $request->cpu, ]);
'was_promo' => $request->was_promo,
'active' => (isset($request->is_active)) ? 1 : 0,
'show_public' => (isset($request->show_public)) ? 1 : 0
]);
$pricing = new Pricing(); $pricing = new Pricing();
$pricing->updatePricing($server->id, $request->currency, $request->price, $request->payment_term, $request->next_due_date);
$as_usd = $pricing->convertToUSD($request->price, $request->currency); Labels::deleteLabelsAssignedTo($server->id);
$pricing->updatePricing($server_id, $request->currency, $request->price, $request->payment_term, $as_usd, $request->next_due_date); Labels::insertLabelsAssigned([$request->label1, $request->label2, $request->label3, $request->label4], $server->id);
Labels::deleteLabelsAssignedTo($server_id); IPs::deleteIPsAssignedTo($server->id);
Labels::insertLabelsAssigned([$request->label1, $request->label2, $request->label3, $request->label4], $server_id);
IPs::deleteIPsAssignedTo($server_id);
for ($i = 1; $i <= 8; $i++) {//Max of 8 ips for ($i = 1; $i <= 8; $i++) {//Max of 8 ips
$obj = 'ip' . $i; $obj = 'ip' . $i;
if (isset($request->$obj) && !is_null($request->$obj)) { if (isset($request->$obj) && !is_null($request->$obj)) {
IPs::insertIP($server_id, $request->$obj); IPs::insertIP($server->id, $request->$obj);
} }
} }
Server::serverRelatedCacheForget(); Server::serverRelatedCacheForget();
Server::serverSpecificCacheForget($server_id); Server::serverSpecificCacheForget($server->id);
return redirect()->route('servers.index') return redirect()->route('servers.index')
->with('success', 'Server Updated Successfully.'); ->with('success', 'Server Updated Successfully.');
@ -203,27 +198,34 @@ class ServerController extends Controller
public function destroy(Server $server) public function destroy(Server $server)
{ {
$items = Server::find($server->id); if ($server->delete()) {
$p = new Pricing();
$p->deletePricing($server->id);
$items->delete(); Labels::deleteLabelsAssignedTo($server->id);
$p = new Pricing(); IPs::deleteIPsAssignedTo($server->id);
$p->deletePricing($server->id);
Labels::deleteLabelsAssignedTo($server->id); Server::serverRelatedCacheForget();
IPs::deleteIPsAssignedTo($server->id); return redirect()->route('servers.index')
->with('success', 'Server was deleted Successfully.');
Server::serverRelatedCacheForget(); }
return redirect()->route('servers.index') return redirect()->route('servers.index')
->with('success', 'Server was deleted Successfully.'); ->with('error', 'Server was not deleted.');
} }
public function chooseCompare() public function chooseCompare()
{//NOTICE: Selecting servers is not cached yet {//NOTICE: Selecting servers is not cached yet
$all_servers = Server::where('has_yabs', 1)->get(); $all_servers = Server::where('has_yabs', 1)->get();
return view('servers.choose-compare', compact('all_servers'));
if (isset($all_servers[1])) {
return view('servers.choose-compare', compact('all_servers'));
}
return redirect()->route('servers.index')
->with('error', 'You need atleast 2 servers with a YABS to do a compare');
} }
public function compareServers($server1, $server2) public function compareServers($server1, $server2)
@ -231,13 +233,13 @@ class ServerController extends Controller
$server1_data = Server::server($server1); $server1_data = Server::server($server1);
if (!isset($server1_data[0]->yabs[0])) { if (!isset($server1_data[0]->yabs[0])) {
return response()->view('errors.404', array("status" => 404, "title" => "Page not found", "message" => "No server with YABs data was found for id '$server1'"), 404); abort(404);
} }
$server2_data = Server::server($server2); $server2_data = Server::server($server2);
if (!isset($server2_data[0]->yabs[0])) { if (!isset($server2_data[0]->yabs[0])) {
return response()->view('errors.404', array("status" => 404, "title" => "Page not found", "message" => "No server with YABs data was found for id '$server2'"), 404); abort(404);
} }
return view('servers.compare', compact('server1_data', 'server2_data')); return view('servers.compare', compact('server1_data', 'server2_data'));
} }

View file

@ -5,67 +5,94 @@ namespace App\Http\Controllers;
use App\Models\Settings; use App\Models\Settings;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache; use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\Session;
class SettingsController extends Controller class SettingsController extends Controller
{ {
public function index() public function index()
{ {
$setting = DB::table('settings') return view('settings.index', ['setting' => Settings::where('id', 1)->first()]);
->where('id', '=', 1)
->get();
return view('settings.index', compact(['setting']));
} }
public function update(Request $request, Settings $settings) public function update(Request $request)
{ {
$request->validate([ $request->validate([
'dark_mode' => 'required|boolean', 'dark_mode' => 'required|integer|min:0|max:1',
'show_versions_footer' => 'required|boolean', 'show_versions_footer' => 'required|integer|min:0|max:1',
'show_server_value_ip' => 'required|boolean', 'show_server_value_ip' => 'required|integer|min:0|max:1',
'show_server_value_hostname' => 'required|boolean', 'show_server_value_hostname' => 'required|integer|min:0|max:1',
'show_server_value_provider' => 'required|boolean', 'show_server_value_provider' => 'required|integer|min:0|max:1',
'show_server_value_location' => 'required|boolean', 'show_server_value_location' => 'required|integer|min:0|max:1',
'show_server_value_price' => 'required|boolean', 'show_server_value_price' => 'required|integer|min:0|max:1',
'show_server_value_yabs' => 'required|boolean', 'show_server_value_yabs' => 'required|integer|min:0|max:1',
'default_currency' => 'required', 'save_yabs_as_txt' => 'integer|min:0|max:1',
'default_server_os' => 'required', 'default_currency' => 'required|string|size:3',
'default_server_os' => 'required|integer',
'due_soon_amount' => 'required|integer|between:0,12', 'due_soon_amount' => 'required|integer|between:0,12',
'recently_added_amount' => 'required|integer|between:0,12', 'recently_added_amount' => 'required|integer|between:0,12',
'currency' => 'required|string|size:3' 'currency' => 'required|string|size:3',
'sort_on' => 'required|integer|between:1,10',
'favicon' => 'sometimes|nullable|mimes:ico,jpg,png|max:40',
]); ]);
DB::table('settings') $settings = Settings::where('id', 1)->first();
->where('id', 1)
->update([
'dark_mode' => $request->dark_mode,
'show_versions_footer' => $request->show_versions_footer,
'show_servers_public' => $request->show_servers_public,
'show_server_value_ip' => $request->show_server_value_ip,
'show_server_value_hostname' => $request->show_server_value_hostname,
'show_server_value_provider' => $request->show_server_value_provider,
'show_server_value_location' => $request->show_server_value_location,
'show_server_value_price' => $request->show_server_value_price,
'show_server_value_yabs' => $request->show_server_value_yabs,
'default_currency' => $request->default_currency,
'default_server_os' => $request->default_server_os,
'due_soon_amount' => $request->due_soon_amount,
'recently_added_amount' => $request->recently_added_amount,
'dashboard_currency' => $request->currency,
]);
Settings::setSettingsToSession($settings); if ($request->favicon) {//Has a favicon upload
$file = $request->favicon;
$extension = $file->getClientOriginalExtension();
$favicon_filename = "favicon.$extension";
if ($favicon_filename !== $settings->favicon && $settings->favicon !== 'favicon.ico') {
Storage::disk('public_uploads')->delete($settings->favicon);//Delete old favicon
}
$file->storeAs("", $favicon_filename, "public_uploads");//Save into /public
}
$do_update = $settings->update([
'dark_mode' => $request->dark_mode,
'show_versions_footer' => $request->show_versions_footer,
'show_servers_public' => $request->show_servers_public,
'show_server_value_ip' => $request->show_server_value_ip,
'show_server_value_hostname' => $request->show_server_value_hostname,
'show_server_value_provider' => $request->show_server_value_provider,
'show_server_value_location' => $request->show_server_value_location,
'show_server_value_price' => $request->show_server_value_price,
'show_server_value_yabs' => $request->show_server_value_yabs,
'save_yabs_as_txt' => 0,
'default_currency' => $request->default_currency,
'default_server_os' => $request->default_server_os,
'due_soon_amount' => $request->due_soon_amount,
'recently_added_amount' => $request->recently_added_amount,
'dashboard_currency' => $request->currency,
'sort_on' => $request->sort_on,
'favicon' => $favicon_filename ?? $settings->favicon
]);
Cache::forget('due_soon');//Main page due_soon cache Cache::forget('due_soon');//Main page due_soon cache
Cache::forget('recently_added');//Main page recently_added cache Cache::forget('recently_added');//Main page recently_added cache
Cache::forget('pricing_breakdown');//Main page pricing breakdown Cache::forget('pricing_breakdown');//Main page pricing breakdown
Cache::forget('settings');//Main page settings cache Cache::forget('settings');//Main page settings cache
//Clear because they are affected by settings change (sort_on)
Cache::forget('all_servers');
Cache::forget('all_active_servers');
Cache::forget('all_shared');
Cache::forget('all_seedboxes');
Cache::forget('all_reseller');
Cache::forget('all_misc');
Cache::forget('all_domains');
Settings::setSettingsToSession(Settings::getSettings());
if ($do_update) {
return redirect()->route('settings.index')
->with('success', 'Settings Updated Successfully.');
}
return redirect()->route('settings.index') return redirect()->route('settings.index')
->with('success', 'Settings Updated Successfully.'); ->with('error', 'Settings failed to update.');
} }
} }

View file

@ -9,7 +9,6 @@ use App\Models\Pricing;
use App\Models\Shared; use App\Models\Shared;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache; use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str; use Illuminate\Support\Str;
class SharedController extends Controller class SharedController extends Controller
@ -29,31 +28,32 @@ class SharedController extends Controller
{ {
$request->validate([ $request->validate([
'domain' => 'required|min:4', 'domain' => 'required|min:4',
'shared_type' => 'required', 'shared_type' => 'required|string',
'server_type' => 'numeric', 'disk' => 'integer',
'ram' => 'numeric', 'os_id' => 'integer',
'disk' => 'numeric', 'provider_id' => 'integer',
'os_id' => 'numeric', 'location_id' => 'integer',
'provider_id' => 'numeric',
'location_id' => 'numeric',
'price' => 'numeric', 'price' => 'numeric',
'payment_term' => 'numeric', 'payment_term' => 'integer',
'was_promo' => 'numeric', 'was_promo' => 'integer',
'owned_since' => 'date', 'owned_since' => 'sometimes|nullable|date',
'domains' => 'numeric', 'domains' => 'integer',
'sub_domains' => 'numeric', 'sub_domains' => 'integer',
'bandwidth' => 'numeric', 'bandwidth' => 'integer',
'email' => 'numeric', 'email' => 'integer',
'ftp' => 'numeric', 'ftp' => 'integer',
'db' => 'numeric', 'db' => 'integer',
'next_due_date' => 'required|date' 'next_due_date' => 'required|date',
'label1' => 'sometimes|nullable|string',
'label2' => 'sometimes|nullable|string',
'label3' => 'sometimes|nullable|string',
'label4' => 'sometimes|nullable|string',
]); ]);
$shared_id = Str::random(8); $shared_id = Str::random(8);
$pricing = new Pricing(); $pricing = new Pricing();
$as_usd = $pricing->convertToUSD($request->price, $request->currency); $pricing->insertPricing(2, $shared_id, $request->currency, $request->price, $request->payment_term, $request->next_due_date);
$pricing->insertPricing(2, $shared_id, $request->currency, $request->price, $request->payment_term, $as_usd, $request->next_due_date);
Labels::deleteLabelsAssignedTo($shared_id); Labels::deleteLabelsAssignedTo($shared_id);
Labels::insertLabelsAssigned([$request->label1, $request->label2, $request->label3, $request->label4], $shared_id); Labels::insertLabelsAssigned([$request->label1, $request->label2, $request->label3, $request->label4], $shared_id);
@ -91,7 +91,7 @@ class SharedController extends Controller
public function show(Shared $shared) public function show(Shared $shared)
{ {
$shared = Shared::sharedHosting($shared->id)[0]; $shared = Shared::sharedHosting($shared->id);
return view('shared.show', compact(['shared'])); return view('shared.show', compact(['shared']));
} }
@ -104,61 +104,60 @@ class SharedController extends Controller
public function update(Request $request, Shared $shared) public function update(Request $request, Shared $shared)
{ {
$request->validate([ $request->validate([
'id' => 'required|size:8',
'domain' => 'required|min:4', 'domain' => 'required|min:4',
'shared_type' => 'required', 'shared_type' => 'required|string',
'dedicated_ip' => 'present', 'disk' => 'integer',
'server_type' => 'numeric', 'os_id' => 'integer',
'disk' => 'numeric', 'provider_id' => 'integer',
'os_id' => 'numeric', 'location_id' => 'integer',
'provider_id' => 'numeric',
'location_id' => 'numeric',
'price' => 'numeric', 'price' => 'numeric',
'payment_term' => 'numeric', 'payment_term' => 'integer',
'was_promo' => 'numeric', 'was_promo' => 'integer',
'owned_since' => 'date', 'owned_since' => 'sometimes|nullable|date',
'domains' => 'numeric', 'domains' => 'integer',
'sub_domains' => 'numeric', 'sub_domains' => 'integer',
'bandwidth' => 'numeric', 'bandwidth' => 'integer',
'email' => 'numeric', 'email' => 'integer',
'ftp' => 'numeric', 'ftp' => 'integer',
'db' => 'numeric' 'db' => 'integer',
'next_due_date' => 'required|date',
'label1' => 'sometimes|nullable|string',
'label2' => 'sometimes|nullable|string',
'label3' => 'sometimes|nullable|string',
'label4' => 'sometimes|nullable|string',
]); ]);
DB::table('shared_hosting') $shared->update([
->where('id', $request->id) 'main_domain' => $request->domain,
->update([ 'shared_type' => $request->shared_type,
'main_domain' => $request->domain, 'provider_id' => $request->provider_id,
'shared_type' => $request->shared_type, 'location_id' => $request->location_id,
'provider_id' => $request->provider_id, 'disk' => $request->disk,
'location_id' => $request->location_id, 'disk_type' => 'GB',
'disk' => $request->disk, 'disk_as_gb' => $request->disk,
'disk_type' => 'GB', 'owned_since' => $request->owned_since,
'disk_as_gb' => $request->disk, 'bandwidth' => $request->bandwidth,
'owned_since' => $request->owned_since, 'was_promo' => $request->was_promo,
'bandwidth' => $request->bandwidth, 'domains_limit' => $request->domains,
'was_promo' => $request->was_promo, 'subdomains_limit' => $request->sub_domains,
'domains_limit' => $request->domains, 'email_limit' => $request->email,
'subdomains_limit' => $request->sub_domains, 'ftp_limit' => $request->ftp,
'email_limit' => $request->email, 'db_limit' => $request->db
'ftp_limit' => $request->ftp, ]);
'db_limit' => $request->db
]);
$pricing = new Pricing(); $pricing = new Pricing();
$as_usd = $pricing->convertToUSD($request->price, $request->currency); $pricing->updatePricing($shared->id, $request->currency, $request->price, $request->payment_term, $request->next_due_date);
$pricing->updatePricing($request->id, $request->currency, $request->price, $request->payment_term, $as_usd, $request->next_due_date);
Labels::deleteLabelsAssignedTo($request->id); Labels::deleteLabelsAssignedTo($shared->id);
Labels::insertLabelsAssigned([$request->label1, $request->label2, $request->label3, $request->label4], $request->id); Labels::insertLabelsAssigned([$request->label1, $request->label2, $request->label3, $request->label4], $shared->id);
Cache::forget("labels_for_service.{$request->id}"); Cache::forget("labels_for_service.{$shared->id}");
IPs::deleteIPsAssignedTo($request->id); IPs::deleteIPsAssignedTo($shared->id);
if (isset($request->dedicated_ip)) { if (isset($request->dedicated_ip)) {
IPs::insertIP($request->id, $request->dedicated_ip); IPs::insertIP($shared->id, $request->dedicated_ip);
} }
Cache::forget("shared_hosting.{$request->id}"); Cache::forget("shared_hosting.{$shared->id}");
Cache::forget('all_shared'); Cache::forget('all_shared');
Home::homePageCacheForget(); Home::homePageCacheForget();
@ -168,23 +167,24 @@ class SharedController extends Controller
public function destroy(Shared $shared) public function destroy(Shared $shared)
{ {
$shared_id = $shared->id; if ($shared->delete()) {
$items = Shared::find($shared_id); $p = new Pricing();
$items->delete(); $p->deletePricing($shared->id);
$p = new Pricing(); Labels::deleteLabelsAssignedTo($shared->id);
$p->deletePricing($shared_id);
Labels::deleteLabelsAssignedTo($shared_id); IPs::deleteIPsAssignedTo($shared->id);
IPs::deleteIPsAssignedTo($shared_id); Cache::forget("shared_hosting.$shared->id");
Cache::forget('all_shared');
Home::homePageCacheForget();
Cache::forget("shared_hosting.$shared_id"); return redirect()->route('shared.index')
Cache::forget('all_shared'); ->with('success', 'Shared hosting was deleted Successfully.');
Home::homePageCacheForget(); }
return redirect()->route('shared.index') return redirect()->route('shared.index')
->with('success', 'Shared hosting was deleted Successfully.'); ->with('error', 'Shared was not deleted.');
} }
} }

View file

@ -4,159 +4,74 @@ namespace App\Http\Controllers;
use App\Models\Server; use App\Models\Server;
use App\Models\Yabs; use App\Models\Yabs;
use App\Process;
use App\Models\DiskSpeed;
use App\Models\NetworkSpeed;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache; use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
class YabsController extends Controller class YabsController extends Controller
{ {
public function index() public function index()
{ {
$yabs = Yabs::allYabs(); return view('yabs.index', ['yabs' => Yabs::allYabs()]);
return view('yabs.index', compact(['yabs']));
}
public function create()
{
$Servers = Server::all();
return view('yabs.create', compact(['Servers']));
}
public function store(Request $request)
{
$process = new Process();
$yabs = $process->yabsOutputAsJson($request->server_id, $request->yabs);
if (isset($yabs['error_id'])) {
return back()->withErrors(["yabs" => 'Problem inserting YABs. Error id ' . $yabs['error_id']])->withInput();
}
//No errors, do insert
$yabs_id = Str::random(8);
Yabs::create([
'id' => $yabs_id,
'server_id' => $request->server_id,
'has_ipv6' => $yabs['has_ipv6'],
'aes' => $yabs['aes'],
'vm' => $yabs['vm'],
'output_date' => $yabs['output_date'],
'cpu_cores' => $yabs['cpu_cores'],
'cpu_freq' => $yabs['cpu_freq'],
'cpu_model' => $yabs['cpu'],
'ram' => $yabs['ram'],
'ram_type' => $yabs['ram_type'],
'ram_mb' => $yabs['ram_mb'],
'disk' => $yabs['disk'],
'disk_type' => $yabs['disk_type'],
'disk_gb' => $yabs['disk_gb'],
'gb5_single' => $yabs['GB5_single'],
'gb5_multi' => $yabs['GB5_mult'],
'gb5_id' => $yabs['GB5_id']
]);
DiskSpeed::create([
'id' => $yabs_id,
'server_id' => $request->server_id,
'd_4k' => $yabs['disk_speed']['4k_total'],
'd_4k_type' => $yabs['disk_speed']['4k_total_type'],
'd_4k_as_mbps' => $yabs['disk_speed']['4k_total_mbps'],
'd_64k' => $yabs['disk_speed']['64k_total'],
'd_64k_type' => $yabs['disk_speed']['64k_total_type'],
'd_64k_as_mbps' => $yabs['disk_speed']['64k_total_mbps'],
'd_512k' => $yabs['disk_speed']['512k_total'],
'd_512k_type' => $yabs['disk_speed']['512k_total_type'],
'd_512k_as_mbps' => $yabs['disk_speed']['512k_total_mbps'],
'd_1m' => $yabs['disk_speed']['1m_total'],
'd_1m_type' => $yabs['disk_speed']['1m_total_type'],
'd_1m_as_mbps' => $yabs['disk_speed']['1m_total_mbps']
]);
foreach ($yabs['network_speed'] as $y) {
NetworkSpeed::create([
'id' => $yabs_id,
'server_id' => $request->server_id,
'location' => $y['location'],
'send' => $y['send'],
'send_type' => $y['send_type'],
'send_as_mbps' => $y['send_type_mbps'],
'receive' => $y['receive'],
'receive_type' => $y['receive_type'],
'receive_as_mbps' => $y['receive_type_mbps']
]);
}
$update_server = DB::table('servers')
->where('id', $request->server_id)
->update([
'ram' => $yabs['ram'],
'ram_type' => $yabs['ram_type'],
'ram_as_mb' => ($yabs['ram_type'] === 'GB') ? ($yabs['ram'] * 1024) : $yabs['ram'],
'disk' => $yabs['disk'],
'disk_type' => $yabs['disk_type'],
'disk_as_gb' => ($yabs['disk_type'] === 'TB') ? ($yabs['disk'] * 1024) : $yabs['disk'],
'cpu' => $yabs['cpu_cores'],
'has_yabs' => 1
]);
Cache::forget('all_active_servers');//all servers cache
Cache::forget('non_active_servers');//all servers cache
Cache::forget('all_yabs');//Forget the all YABs cache
return redirect()->route('yabs.index')
->with('success', 'Success inserting YABs');
} }
public function show(Yabs $yab) public function show(Yabs $yab)
{ {
$yab = Yabs::yabs($yab->id); return view('yabs.show', ['yabs' => Yabs::yabs($yab->id)]);
return view('yabs.show', compact(['yab']));
} }
public function destroy(Yabs $yab) public function destroy(Yabs $yab)
{ {
$yabs = Yabs::find($yab->id); if ($yab->delete()) {
$yabs->delete(); if (Server::serverYabsAmount($yab->server_id) === 0) {
DB::table('servers')
->where('id', $yab->server_id)
->update(['has_yabs' => 0]);
}
if (Server::serverYabsAmount($yab->server_id) === 0) { Cache::forget('all_yabs');
DB::table('servers') Cache::forget("yabs.{$yab->id}");
->where('id', $yab->server_id)
->update(['has_yabs' => 0]); return redirect()->route('yabs.index')
->with('success', 'YABS was deleted Successfully.');
} }
Cache::forget('all_yabs');
Cache::forget("yabs.{$yab->id}");
return redirect()->route('yabs.index') return redirect()->route('yabs.index')
->with('success', 'YABs was deleted Successfully.'); ->with('error', 'YABS was not deleted.');
} }
public function chooseYabsCompare() public function chooseYabsCompare()
{ {
$all_yabs = Yabs::allYabs(); $all_yabs = Yabs::allYabs();
return view('yabs.choose-compare', compact('all_yabs'));
if (isset($all_yabs[1])) {
return view('yabs.choose-compare', compact('all_yabs'));
}
return redirect()->route('yabs.index')
->with('error', 'You need atleast 2 YABS to do a compare');
} }
public function compareYabs($yabs1, $yabs2) public function compareYabs(string $yabs1, string $yabs2)
{ {
$yabs1_data = Yabs::yabs($yabs1); $yabs1_data = Yabs::yabs($yabs1);
if (count($yabs1_data) === 0) { if (is_null($yabs1_data)) {
return response()->view('errors.404', array("status" => 404, "title" => "Page not found", "message" => "No YABs data was found for id '$yabs1'"), 404); abort(404);
} }
$yabs2_data = Yabs::yabs($yabs2); $yabs2_data = Yabs::yabs($yabs2);
if (count($yabs2_data) === 0) { if (is_null($yabs2_data)) {
return response()->view('errors.404', array("status" => 404, "title" => "Page not found", "message" => "No YABs data was found for id '$server2'"), 404); abort(404);
} }
return view('yabs.compare', compact('yabs1_data', 'yabs2_data')); return view('yabs.compare', compact('yabs1_data', 'yabs2_data'));
} }
public function yabsToJson(Yabs $yab): array
{
$all_yabs = Yabs::yabs($yab->id)[0];
return Yabs::buildYabsArray($all_yabs);
}
} }

View file

@ -17,7 +17,7 @@ class Kernel extends HttpKernel
protected $middleware = [ protected $middleware = [
// \App\Http\Middleware\TrustHosts::class, // \App\Http\Middleware\TrustHosts::class,
\App\Http\Middleware\TrustProxies::class, \App\Http\Middleware\TrustProxies::class,
\Fruitcake\Cors\HandleCors::class, \Illuminate\Http\Middleware\HandleCors::class,
\App\Http\Middleware\PreventRequestsDuringMaintenance::class, \App\Http\Middleware\PreventRequestsDuringMaintenance::class,
\Illuminate\Foundation\Http\Middleware\ValidatePostSize::class, \Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
\App\Http\Middleware\TrimStrings::class, \App\Http\Middleware\TrimStrings::class,

View file

@ -13,6 +13,8 @@ class DNS extends Model
public $incrementing = false; public $incrementing = false;
protected $keyType = 'string';
protected $fillable = ['id', 'service_id', 'hostname', 'dns_type', 'address', 'server_id', 'domain_id']; protected $fillable = ['id', 'service_id', 'hostname', 'dns_type', 'address', 'server_id', 'domain_id'];
public static $dns_types = ['A', 'AAAA', 'DNAME', 'MX', 'NS', 'SOA', 'TXT', 'URI']; public static $dns_types = ['A', 'AAAA', 'DNAME', 'MX', 'NS', 'SOA', 'TXT', 'URI'];
@ -20,7 +22,13 @@ class DNS extends Model
public static function dnsCount() public static function dnsCount()
{ {
return Cache::remember('dns_count', now()->addMonth(1), function () { return Cache::remember('dns_count', now()->addMonth(1), function () {
return DB::table('d_n_s')->count(); return DNS::count();
}); });
} }
public function note(): \Illuminate\Database\Eloquent\Relations\HasOne
{
return $this->hasOne(Note::class, 'service_id', 'id');
}
} }

View file

@ -11,11 +11,13 @@ class DiskSpeed extends Model
public $incrementing = false; public $incrementing = false;
protected $keyType = 'string';
protected $table = 'disk_speed'; protected $table = 'disk_speed';
protected $fillable = ['id', 'server_id', 'd_4k', 'd_4k_type', 'd_4k_as_mbps', 'd_64k', 'd_64k_type', 'd_64k_as_mbps', 'd_512k', 'd_512k_type', 'd_512k_as_mbps', 'd_1m', 'd_1m_type', 'd_1m_as_mbps']; protected $fillable = ['id', 'server_id', 'd_4k', 'd_4k_type', 'd_4k_as_mbps', 'd_64k', 'd_64k_type', 'd_64k_as_mbps', 'd_512k', 'd_512k_type', 'd_512k_as_mbps', 'd_1m', 'd_1m_type', 'd_1m_as_mbps'];
public function yabs() public function yabs(): \Illuminate\Database\Eloquent\Relations\BelongsTo
{ {
return $this->belongsTo(Yabs::class, 'id', 'id'); return $this->belongsTo(Yabs::class, 'id', 'id');
} }

View file

@ -4,7 +4,8 @@ namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Session;
class Domains extends Model class Domains extends Model
{ {
@ -12,30 +13,51 @@ class Domains extends Model
public $incrementing = false; public $incrementing = false;
protected $table = 'domains';
protected $keyType = 'string';
protected $fillable = ['id', 'domain', 'extension', 'ns1', 'ns2', 'ns3', 'price', 'currency', 'payment_term', 'owned_since', 'provider_id', 'next_due_date']; protected $fillable = ['id', 'domain', 'extension', 'ns1', 'ns2', 'ns3', 'price', 'currency', 'payment_term', 'owned_since', 'provider_id', 'next_due_date'];
public static function domainsDataIndexPage()
{ public static function allDomains()
return DB::table('domains as d') {//All domains and relationships (no using joins)
->join('providers as p', 'd.provider_id', '=', 'p.id') return Cache::remember("all_domains", now()->addMonth(1), function () {
->join('pricings as pr', 'd.id', '=', 'pr.service_id') $query = Domains::with(['provider', 'price', 'labels']);
->get(['d.*', 'p.name as provider_name', 'pr.*']); if (in_array(Session::get('sort_on'), [3, 4, 5, 6], true)) {
$options = Settings::orderByProcess(Session::get('sort_on'));
$query->orderBy(Pricing::select("pricings.$options[0]")->whereColumn("pricings.service_id", "domains.id"), $options[1]);
}
return $query->get();
});
} }
public static function domainsDataShowPage(string $domain_id) public static function domain(string $domain_id)
{ {//Single domains and relationships (no using joins)
return DB::table('domains as d') return Cache::remember("domain.$domain_id", now()->addMonth(1), function () use ($domain_id) {
->join('providers as p', 'd.provider_id', '=', 'p.id') return Domains::where('id', $domain_id)
->join('pricings as pr', 'd.id', '=', 'pr.service_id') ->with(['provider', 'price', 'labels'])->first();
->where('d.id', '=', $domain_id) });
->get(['d.*', 'p.name as provider_name', 'pr.*']);
} }
public static function domainsDataEditPage(string $domain_id) public function provider(): \Illuminate\Database\Eloquent\Relations\HasOne
{ {
return DB::table('domains as d') return $this->hasOne(Providers::class, 'id', 'provider_id');
->join('pricings as pr', 'd.id', '=', 'pr.service_id')
->where('d.id', '=', $domain_id)
->get(['d.*', 'pr.*']);
} }
public function price(): \Illuminate\Database\Eloquent\Relations\HasOne
{
return $this->hasOne(Pricing::class, 'service_id', 'id');
}
public function labels(): \Illuminate\Database\Eloquent\Relations\HasMany
{
return $this->hasMany(LabelsAssigned::class, 'service_id', 'id');
}
public function note(): \Illuminate\Database\Eloquent\Relations\HasOne
{
return $this->hasOne(Note::class, 'service_id', 'id');
}
} }

View file

@ -13,7 +13,7 @@ class Home extends Model
{ {
use HasFactory; use HasFactory;
public static function homePageCacheForget() public static function homePageCacheForget(): void
{ {
Cache::forget('services_count');//Main page services_count cache Cache::forget('services_count');//Main page services_count cache
Cache::forget('due_soon');//Main page due_soon cache Cache::forget('due_soon');//Main page due_soon cache
@ -25,26 +25,26 @@ class Home extends Model
public static function servicesCount() public static function servicesCount()
{ {
return Cache::remember('services_count', now()->addHour(6), function () { return Cache::remember('services_count', now()->addHours(6), function () {
return DB::table('pricings') return DB::table('pricings')
->select('service_type', DB::raw('COUNT(*) as amount')) ->select('service_type', DB::raw('COUNT(*) as amount'))
->groupBy('service_type') ->groupBy('service_type')
->where('active', '=', 1) ->where('active', 1)
->get(); ->get();
}); });
} }
public static function dueSoonData() public static function dueSoonData()
{ {
return Cache::remember('due_soon', now()->addHour(6), function () { return Cache::remember('due_soon', now()->addHours(6), function () {
return DB::table('pricings as p') return DB::table('pricings as p')
->leftJoin('servers as s', 'p.service_id', '=', 's.id') ->leftJoin('servers as s', 'p.service_id', 's.id')
->leftJoin('shared_hosting as sh', 'p.service_id', '=', 'sh.id') ->leftJoin('shared_hosting as sh', 'p.service_id', 'sh.id')
->leftJoin('reseller_hosting as r', 'p.service_id', '=', 'r.id') ->leftJoin('reseller_hosting as r', 'p.service_id', 'r.id')
->leftJoin('domains as d', 'p.service_id', '=', 'd.id') ->leftJoin('domains as d', 'p.service_id', 'd.id')
->leftJoin('misc_services as ms', 'p.service_id', '=', 'ms.id') ->leftJoin('misc_services as ms', 'p.service_id', 'ms.id')
->leftJoin('seedboxes as sb', 'p.service_id', '=', 'sb.id') ->leftJoin('seedboxes as sb', 'p.service_id', 'sb.id')
->where('p.active', '=', 1) ->where('p.active', 1)
->orderBy('next_due_date', 'ASC') ->orderBy('next_due_date', 'ASC')
->limit(Session::get('due_soon_amount')) ->limit(Session::get('due_soon_amount'))
->get(['p.*', 's.hostname', 'd.domain', 'd.extension', 'r.main_domain as reseller', 'sh.main_domain', 'ms.name', 'sb.title']); ->get(['p.*', 's.hostname', 'd.domain', 'd.extension', 'r.main_domain as reseller', 'sh.main_domain', 'ms.name', 'sb.title']);
@ -53,13 +53,13 @@ class Home extends Model
public static function serverSummary() public static function serverSummary()
{ {
return Cache::remember('servers_summary', now()->addHour(6), function () { return Cache::remember('servers_summary', now()->addHours(6), function () {
$cpu_sum = DB::table('servers')->get()->where('active', '=', 1)->sum('cpu'); $cpu_sum = DB::table('servers')->get()->where('active', 1)->sum('cpu');
$ram_mb = DB::table('servers')->get()->where('active', '=', 1)->sum('ram_as_mb'); $ram_mb = DB::table('servers')->get()->where('active', 1)->sum('ram_as_mb');
$disk_gb = DB::table('servers')->get()->where('active', '=', 1)->sum('disk_as_gb'); $disk_gb = DB::table('servers')->get()->where('active', 1)->sum('disk_as_gb');
$bandwidth = DB::table('servers')->get()->where('active', '=', 1)->sum('bandwidth'); $bandwidth = DB::table('servers')->get()->where('active', 1)->sum('bandwidth');
$locations_sum = DB::table('servers')->get()->where('active', '=', 1)->groupBy('location_id')->count(); $locations_sum = DB::table('servers')->get()->where('active', 1)->groupBy('location_id')->count();
$providers_sum = DB::table('servers')->get()->where('active', '=', 1)->groupBy('provider_id')->count(); $providers_sum = DB::table('servers')->get()->where('active', 1)->groupBy('provider_id')->count();
return array( return array(
'cpu_sum' => $cpu_sum, 'cpu_sum' => $cpu_sum,
'ram_mb_sum' => $ram_mb, 'ram_mb_sum' => $ram_mb,
@ -73,15 +73,15 @@ class Home extends Model
public static function recentlyAdded() public static function recentlyAdded()
{ {
return Cache::remember('recently_added', now()->addHour(6), function () { return Cache::remember('recently_added', now()->addHours(6), function () {
return DB::table('pricings as p') return DB::table('pricings as p')
->leftJoin('servers as s', 'p.service_id', '=', 's.id') ->leftJoin('servers as s', 'p.service_id', 's.id')
->leftJoin('shared_hosting as sh', 'p.service_id', '=', 'sh.id') ->leftJoin('shared_hosting as sh', 'p.service_id', 'sh.id')
->leftJoin('reseller_hosting as r', 'p.service_id', '=', 'r.id') ->leftJoin('reseller_hosting as r', 'p.service_id', 'r.id')
->leftJoin('domains as d', 'p.service_id', '=', 'd.id') ->leftJoin('domains as d', 'p.service_id', 'd.id')
->leftJoin('misc_services as ms', 'p.service_id', '=', 'ms.id') ->leftJoin('misc_services as ms', 'p.service_id', 'ms.id')
->leftJoin('seedboxes as sb', 'p.service_id', '=', 'sb.id') ->leftJoin('seedboxes as sb', 'p.service_id', 'sb.id')
->where('p.active', '=', 1) ->where('p.active', 1)
->orderBy('created_at', 'DESC') ->orderBy('created_at', 'DESC')
->limit(Session::get('recently_added_amount')) ->limit(Session::get('recently_added_amount'))
->get(['p.*', 's.hostname', 'd.domain', 'd.extension', 'r.main_domain as reseller', 'sh.main_domain', 'ms.name', 'sb.title']); ->get(['p.*', 's.hostname', 'd.domain', 'd.extension', 'r.main_domain as reseller', 'sh.main_domain', 'ms.name', 'sb.title']);
@ -163,7 +163,7 @@ class Home extends Model
return array( return array(
'total_cost_weekly' => $total_cost_weekly, 'total_cost_weekly' => $total_cost_weekly,
'total_cost_montly' => $total_cost_pm, 'total_cost_monthly' => $total_cost_pm,
'total_cost_yearly' => $total_cost_yearly, 'total_cost_yearly' => $total_cost_yearly,
'inactive_count' => $inactive_count, 'inactive_count' => $inactive_count,
); );

View file

@ -6,6 +6,7 @@ use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Cache; use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Str; use Illuminate\Support\Str;
class IPs extends Model class IPs extends Model
@ -14,18 +15,20 @@ class IPs extends Model
public $table = 'ips'; public $table = 'ips';
protected $fillable = ['id', 'active', 'service_id', 'address', 'is_ipv4']; protected $keyType = 'string';
protected $fillable = ['id', 'service_id', 'address', 'is_ipv4', 'active', 'continent', 'country', 'region', 'city', 'org', 'isp', 'asn', 'timezone_gmt', 'fetched_at'];
public $incrementing = false; public $incrementing = false;
public static function deleteIPsAssignedTo($service_id) public static function deleteIPsAssignedTo($service_id): void
{ {
DB::table('ips')->where('service_id', '=', $service_id)->delete(); DB::table('ips')->where('service_id', $service_id)->delete();
} }
public static function insertIP(string $service_id, string $address) public static function insertIP(string $service_id, string $address): IPs
{ {
self::create( return self::create(
[ [
'id' => Str::random(8), 'id' => Str::random(8),
'service_id' => $service_id, 'service_id' => $service_id,
@ -38,11 +41,41 @@ class IPs extends Model
public static function ipsForServer(string $server_id) public static function ipsForServer(string $server_id)
{ {
return Cache::remember("ip_addresses.$server_id", now()->addHour(1), function () use ($server_id) { return Cache::remember("ip_addresses.$server_id", now()->addHours(1), function () use ($server_id) {
return json_decode(DB::table('ips as i') return json_decode(DB::table('ips as i')
->where('i.service_id', '=', $server_id) ->where('i.service_id', $server_id)
->get(), true); ->get(), true);
}); });
} }
public function note(): \Illuminate\Database\Eloquent\Relations\HasOne
{
return $this->hasOne(Note::class, 'service_id', 'id');
}
public static function getUpdateIpInfo(IPs $IP): bool
{
$response = Http::get("https://ipwhois.app/json/{$IP->address}");
if ($response->ok()) {
$data = $response->json();
$IP->update([
'continent' => $data['continent'],
'country' => $data['country'],
'region' => $data['region'],
'city' => $data['city'],
'org' => $data['org'],
'isp' => $data['isp'],
'asn' => $data['asn'],
'timezone_gmt' => $data['timezone_gmt'],
'fetched_at' => now()
]);
}
return $response->ok();
}
} }

View file

@ -5,7 +5,7 @@ namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Cache; use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB; use Mockery\Exception;
class Labels extends Model class Labels extends Model
{ {
@ -15,42 +15,46 @@ class Labels extends Model
protected $table = 'labels'; protected $table = 'labels';
protected $keyType = 'string';
protected $fillable = ['id', 'label', 'server_id', 'server_id_2', 'domain_id', 'domain_id_2', 'shared_id', 'shared_id_2']; protected $fillable = ['id', 'label', 'server_id', 'server_id_2', 'domain_id', 'domain_id_2', 'shared_id', 'shared_id_2'];
public static function deleteLabelsAssignedTo($service_id) public static function deleteLabelsAssignedTo($service_id): void
{ {
DB::table('labels_assigned')->where('service_id', '=', $service_id)->delete(); LabelsAssigned::where('service_id', $service_id)->delete();
} }
public static function deleteLabelAssignedAs($label_id) public static function deleteLabelAssignedAs($label_id): void
{ {
DB::table('labels_assigned')->where('label_id', '=', $label_id)->delete(); LabelsAssigned::where('label_id', $label_id)->delete();
} }
public static function insertLabelsAssigned(array $labels_array, string $service_id) public static function insertLabelsAssigned(array $labels_array, string $service_id): void
{ {
for ($i = 1; $i <= 4; $i++) { for ($i = 1; $i <= 4; $i++) {
if (!is_null($labels_array[($i - 1)])) { if (!is_null($labels_array[($i - 1)])) {
DB::insert('INSERT INTO labels_assigned (label_id, service_id) values (?, ?)', [$labels_array[($i - 1)], $service_id]); try {
LabelsAssigned::create([
'label_id' => $labels_array[($i - 1)],
'service_id' => $service_id
]);
} catch (Exception $exception) {
}
} }
} }
} }
public static function labelsCount() public static function labelsCount(): int
{ {
return Cache::remember('labels_count', now()->addMonth(1), function () { return Cache::remember('labels_count', now()->addMonth(1), function () {
return DB::table('labels')->count(); return Labels::count();
}); });
} }
public static function labelsForService(string $service_id) public function assigned(): \Illuminate\Database\Eloquent\Relations\HasMany
{ {
return Cache::remember("labels_for_service.$service_id", now()->addMinute(5), function () use ($service_id) { return $this->hasMany(LabelsAssigned::class, 'label_id', 'id');
return DB::table('labels_assigned as l')
->join('labels', 'l.label_id', '=', 'labels.id')
->where('l.service_id', '=', $service_id)
->get(['labels.id', 'labels.label']);
});
} }
} }

View file

@ -11,11 +11,15 @@ class LabelsAssigned extends Model
public $incrementing = false; public $incrementing = false;
public $timestamps = false;
public $table = 'labels_assigned'; public $table = 'labels_assigned';
protected $fillable = ['label_id', 'service_id']; protected $fillable = ['label_id', 'service_id'];
public function label() protected $keyType = 'string';
public function label(): \Illuminate\Database\Eloquent\Relations\HasOne
{ {
return $this->hasOne(Labels::class, 'id', 'label_id'); return $this->hasOne(Labels::class, 'id', 'label_id');
} }

View file

@ -5,7 +5,6 @@ namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Cache; use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;
class Locations extends Model class Locations extends Model
{ {
@ -15,10 +14,12 @@ class Locations extends Model
protected $table = 'locations'; protected $table = 'locations';
protected $keyType = 'string';
public static function allLocations(): array public static function allLocations(): array
{ {
return Cache::remember("locations", now()->addMonth(1), function () { return Cache::remember("locations", now()->addMonth(1), function () {
return DB::table('locations')->get()->toArray(); return self::orderBy('name')->get()->toArray();
}); });
} }
} }

View file

@ -2,8 +2,11 @@
namespace App\Models; namespace App\Models;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Session;
class Misc extends Model class Misc extends Model
{ {
@ -13,5 +16,45 @@ class Misc extends Model
protected $table = 'misc_services'; protected $table = 'misc_services';
protected $keyType = 'string';
protected $fillable = ['id', 'name', 'owned_since']; protected $fillable = ['id', 'name', 'owned_since'];
protected static function boot()
{
parent::boot();
static::addGlobalScope('order', function (Builder $builder) {
$array = Settings::orderByProcess(Session::get('sort_on') ?? 2);//created_at desc if not set
if (!in_array(Session::get('sort_on'), [3, 4, 5, 6], true)) {
$builder->orderBy($array[0], $array[1]);
}
});
}
public static function allMisc()
{//All misc and relationships (no using joins)
return Cache::remember("all_misc", now()->addMonth(1), function () {
$query = Misc::with(['price']);
if (in_array(Session::get('sort_on'), [3, 4, 5, 6], true)) {
$options = Settings::orderByProcess(Session::get('sort_on'));
$query->orderBy(Pricing::select("pricings.$options[0]")->whereColumn("pricings.service_id", "misc_services.id"), $options[1]);
}
return $query->get();
});
}
public static function misc(string $misc_id)
{//Single misc and relationships (no using joins)
return Cache::remember("misc.$misc_id", now()->addMonth(1), function () use ($misc_id) {
return Misc::where('id', $misc_id)
->with(['price'])->first();
});
}
public function price(): \Illuminate\Database\Eloquent\Relations\HasOne
{
return $this->hasOne(Pricing::class, 'service_id', 'id');
}
} }

View file

@ -11,11 +11,13 @@ class NetworkSpeed extends Model
public $incrementing = false; public $incrementing = false;
protected $keyType = 'string';
protected $table = 'network_speed'; protected $table = 'network_speed';
protected $fillable = ['id', 'server_id', 'location', 'send', 'send_type', 'send_as_mbps', 'receive', 'receive_type', 'receive_as_mbps', 'created_at', 'updated_at']; protected $fillable = ['id', 'server_id', 'location', 'send', 'send_type', 'send_as_mbps', 'receive', 'receive_type', 'receive_as_mbps', 'created_at', 'updated_at'];
public function yabs() public function yabs(): \Illuminate\Database\Eloquent\Relations\BelongsTo
{ {
return $this->belongsTo(Yabs::class, 'id', 'id'); return $this->belongsTo(Yabs::class, 'id', 'id');
} }

65
app/Models/Note.php Normal file
View file

@ -0,0 +1,65 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Cache;
class Note extends Model
{
use HasFactory;
public $incrementing = false;
protected $table = 'notes';
protected $keyType = 'string';
protected $fillable = ['id', 'service_id', 'note'];
public static function note(string $service_id): Note
{
return Cache::remember("note.$service_id", now()->addMonth(1), function () use ($service_id) {
return self::where('service_id', $service_id)->with(['server', 'shared', 'reseller', 'domain', 'dns', 'ip'])->first();
});
}
public static function allNotes()
{
return Cache::remember("all_notes", now()->addMonth(1), function () {
return self::with(['server', 'shared', 'reseller', 'domain', 'dns', 'ip'])->orderBy('created_at', 'desc')->get();
});
}
public function server(): \Illuminate\Database\Eloquent\Relations\BelongsTo
{
return $this->belongsTo(Server::class, 'service_id', 'id');
}
public function shared(): \Illuminate\Database\Eloquent\Relations\BelongsTo
{
return $this->belongsTo(Shared::class, 'service_id', 'id');
}
public function reseller(): \Illuminate\Database\Eloquent\Relations\BelongsTo
{
return $this->belongsTo(Reseller::class, 'service_id', 'id');
}
public function domain(): \Illuminate\Database\Eloquent\Relations\BelongsTo
{
return $this->belongsTo(Domains::class, 'service_id', 'id');
}
public function dns(): \Illuminate\Database\Eloquent\Relations\BelongsTo
{
return $this->belongsTo(DNS::class, 'service_id', 'id');
}
public function ip(): \Illuminate\Database\Eloquent\Relations\BelongsTo
{
return $this->belongsTo(IPs::class, 'service_id', 'id');
}
}

View file

@ -5,7 +5,6 @@ namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Cache; use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;
class OS extends Model class OS extends Model
{ {
@ -13,12 +12,14 @@ class OS extends Model
protected $fillable = ['name']; protected $fillable = ['name'];
protected $keyType = 'string';
protected $table = 'os'; protected $table = 'os';
public static function allOS(): array public static function allOS()
{ {
return Cache::remember("operating_systems", now()->addMonth(1), function () { return Cache::remember("operating_systems", now()->addMonth(1), function () {
return DB::table('os')->get()->toArray(); return self::orderBy('name')->get();
}); });
} }
} }

View file

@ -13,6 +13,12 @@ class Pricing extends Model
{ {
use HasFactory; use HasFactory;
protected $table = 'pricings';
public $incrementing = false;
protected $keyType = 'string';
protected $fillable = ['service_id', 'service_type', 'currency', 'price', 'term', 'as_usd', 'usd_per_month', 'next_due_date']; protected $fillable = ['service_id', 'service_type', 'currency', 'price', 'term', 'as_usd', 'usd_per_month', 'next_due_date'];
private static function refreshRates(): object private static function refreshRates(): object
@ -42,7 +48,7 @@ class Pricing extends Model
private static function getRates($currency): float private static function getRates($currency): float
{ {
$rate = self::refreshRates()->$currency; $rate = self::refreshRates()->$currency;
return $rate === null ? 1.00 : $rate; return $rate ?? 1.00;
} }
public static function getCurrencyList(): array public static function getCurrencyList(): array
@ -100,11 +106,12 @@ class Pricing extends Model
public function deletePricing($id): void public function deletePricing($id): void
{ {
DB::table('pricings')->where('service_id', '=', $id)->delete(); DB::table('pricings')->where('service_id', $id)->delete();
} }
public function insertPricing(int $type, string $service_id, string $currency, float $price, int $term, float $as_usd, string $next_due_date, int $is_active = 1) public function insertPricing(int $type, string $service_id, string $currency, float $price, int $term, string $next_due_date, int $is_active = 1): Pricing
{ {
$as_usd = $this->convertToUSD($price, $currency);
return self::create([ return self::create([
'service_type' => $type, 'service_type' => $type,
'service_id' => $service_id, 'service_id' => $service_id,
@ -114,12 +121,13 @@ class Pricing extends Model
'as_usd' => $as_usd, 'as_usd' => $as_usd,
'usd_per_month' => $this->costAsPerMonth($as_usd, $term), 'usd_per_month' => $this->costAsPerMonth($as_usd, $term),
'next_due_date' => $next_due_date, 'next_due_date' => $next_due_date,
'active' => ($is_active) ? 1 : 0 'active' => $is_active
]); ]);
} }
public function updatePricing(string $service_id, string $currency, float $price, int $term, float $as_usd, string $next_due_date, int $is_active = 1) public function updatePricing(string $service_id, string $currency, float $price, int $term, string $next_due_date, int $is_active = 1): int
{ {
$as_usd = $this->convertToUSD($price, $currency);
return DB::table('pricings') return DB::table('pricings')
->where('service_id', $service_id) ->where('service_id', $service_id)
->update([ ->update([
@ -129,15 +137,14 @@ class Pricing extends Model
'as_usd' => $as_usd, 'as_usd' => $as_usd,
'usd_per_month' => $this->costAsPerMonth($as_usd, $term), 'usd_per_month' => $this->costAsPerMonth($as_usd, $term),
'next_due_date' => $next_due_date, 'next_due_date' => $next_due_date,
'active' => ($is_active) ? 1 : 0 'active' => $is_active
]); ]);
} }
public static function allPricing() public static function allPricing()
{ {
return Cache::remember('all_pricing', now()->addWeek(1), function () { return Cache::remember('all_active_pricing', now()->addWeek(1), function () {
return DB::table('pricings') return Pricing::where('active', 1)->get();
->get();
}); });
} }

View file

@ -13,29 +13,31 @@ class Providers extends Model
protected $fillable = ['name']; protected $fillable = ['name'];
protected $keyType = 'string';
protected $table = 'providers'; protected $table = 'providers';
public static function allProviders(): array public static function allProviders(): array
{ {
return Cache::remember("providers", now()->addMonth(1), function () { return Cache::remember("providers", now()->addMonth(1), function () {
return DB::table('providers')->get()->toArray(); return self::orderBy('name')->get()->toArray();
}); });
} }
public static function showServicesForProvider($provider): array public static function showServicesForProvider($provider): array
{ {
$servers = DB::table('servers as s') $servers = DB::table('servers as s')
->where('s.provider_id', '=', $provider) ->where('s.provider_id', $provider)
->get(['s.id', 's.hostname']) ->get(['s.id', 's.hostname'])
->toArray(); ->toArray();
$shared = DB::table('shared_hosting as s') $shared = DB::table('shared_hosting as s')
->where('s.provider_id', '=', $provider) ->where('s.provider_id', $provider)
->get(['s.id', 's.main_domain as main_domain_shared']) ->get(['s.id', 's.main_domain as main_domain_shared'])
->toArray(); ->toArray();
$reseller = DB::table('reseller_hosting as r') $reseller = DB::table('reseller_hosting as r')
->where('r.provider_id', '=', $provider) ->where('r.provider_id', $provider)
->get(['r.id', 'r.main_domain as main_domain_reseller']) ->get(['r.id', 'r.main_domain as main_domain_reseller'])
->toArray(); ->toArray();

View file

@ -2,10 +2,12 @@
namespace App\Models; namespace App\Models;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Cache; use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Session;
class Reseller extends Model class Reseller extends Model
{ {
@ -13,36 +15,72 @@ class Reseller extends Model
protected $table = 'reseller_hosting'; protected $table = 'reseller_hosting';
protected $keyType = 'string';
protected $fillable = ['id', 'active', 'accounts', 'main_domain', 'has_dedicated_ip', 'ip', 'reseller_type', 'provider_id', 'location_id', 'bandwidth', 'disk', 'disk_type', 'disk_as_gb', 'domains_limit', 'subdomains_limit', 'ftp_limit', 'email_limit', 'db_limit', 'was_promo', 'owned_since']; protected $fillable = ['id', 'active', 'accounts', 'main_domain', 'has_dedicated_ip', 'ip', 'reseller_type', 'provider_id', 'location_id', 'bandwidth', 'disk', 'disk_type', 'disk_as_gb', 'domains_limit', 'subdomains_limit', 'ftp_limit', 'email_limit', 'db_limit', 'was_promo', 'owned_since'];
public $incrementing = false; public $incrementing = false;
public static function resellerDataIndexPage() protected static function boot()
{ {
return DB::table('reseller_hosting as s') parent::boot();
->join('providers as p', 's.provider_id', '=', 'p.id')
->join('locations as l', 's.location_id', '=', 'l.id') static::addGlobalScope('order', function (Builder $builder) {
->join('pricings as pr', 's.id', '=', 'pr.service_id') $array = Settings::orderByProcess(Session::get('sort_on') ?? 2);//created_at desc if not set
->get(['s.*', 'p.name as provider_name', 'pr.*', 'l.name as location']); if (!in_array(Session::get('sort_on'), [3, 4, 5, 6], true)) {
$builder->orderBy($array[0], $array[1]);
}
});
} }
public static function resellerDataShowPage(string $reseller_id) public static function allResellerHosting()
{ {//All reseller hosting and relationships (no using joins)
return DB::table('reseller_hosting as s') return Cache::remember("all_reseller", now()->addMonth(1), function () {
->join('pricings as pr', 's.id', '=', 'pr.service_id') $query = Reseller::with(['location', 'provider', 'price', 'ips', 'labels']);
->join('providers as p', 's.provider_id', '=', 'p.id') if (in_array(Session::get('sort_on'), [3, 4, 5, 6], true)) {
->join('locations as l', 's.location_id', '=', 'l.id') $options = Settings::orderByProcess(Session::get('sort_on'));
->where('s.id', '=', $reseller_id) $query->orderBy(Pricing::select("pricings.$options[0]")->whereColumn("pricings.service_id", "reseller_hosting.id"), $options[1]);
->get(['s.*', 'p.name as provider_name', 'l.name as location', 'pr.*']); }
return $query->get();
});
} }
public static function resellerDataEditPage(string $reseller_id) public static function resellerHosting(string $reseller_id)
{ {//Single reseller hosting and relationships (no using joins)
return DB::table('reseller_hosting as s') return Cache::remember("reseller_hosting.$reseller_id", now()->addMonth(1), function () use ($reseller_id) {
->join('pricings as p', 's.id', '=', 'p.service_id') return Reseller::where('id', $reseller_id)
->where('s.id', '=', $reseller_id) ->with(['location', 'provider', 'price', 'ips', 'labels'])->first();
->get(['s.*', 'p.*']); });
}
public function ips(): \Illuminate\Database\Eloquent\Relations\HasMany
{
return $this->hasMany(IPs::class, 'service_id', 'id');
}
public function location(): \Illuminate\Database\Eloquent\Relations\HasOne
{
return $this->hasOne(Locations::class, 'id', 'location_id');
}
public function provider(): \Illuminate\Database\Eloquent\Relations\HasOne
{
return $this->hasOne(Providers::class, 'id', 'provider_id');
}
public function price(): \Illuminate\Database\Eloquent\Relations\HasOne
{
return $this->hasOne(Pricing::class, 'service_id', 'id');
}
public function labels(): \Illuminate\Database\Eloquent\Relations\HasMany
{
return $this->hasMany(LabelsAssigned::class, 'service_id', 'id');
}
public function note(): \Illuminate\Database\Eloquent\Relations\HasOne
{
return $this->hasOne(Note::class, 'service_id', 'id');
} }
} }

View file

@ -2,10 +2,11 @@
namespace App\Models; namespace App\Models;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Cache; use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Session;
class SeedBoxes extends Model class SeedBoxes extends Model
{ {
@ -13,38 +14,62 @@ class SeedBoxes extends Model
protected $table = 'seedboxes'; protected $table = 'seedboxes';
protected $keyType = 'string';
public $incrementing = false; public $incrementing = false;
protected $fillable = ['id', 'active', 'title', 'hostname', 'seed_box_type', 'provider_id', 'location_id', 'bandwidth', 'port_speed', 'disk', 'disk_type', 'disk_as_gb', 'was_promo', 'owned_since']; protected $fillable = ['id', 'active', 'title', 'hostname', 'seed_box_type', 'provider_id', 'location_id', 'bandwidth', 'port_speed', 'disk', 'disk_type', 'disk_as_gb', 'was_promo', 'owned_since'];
public static function seedBoxesDataIndexPage() protected static function boot()
{ {
return DB::table('seedboxes as s') parent::boot();
->join('providers as p', 's.provider_id', '=', 'p.id')
->join('locations as l', 's.location_id', '=', 'l.id') static::addGlobalScope('order', function (Builder $builder) {
->join('pricings as pr', 's.id', '=', 'pr.service_id') $array = Settings::orderByProcess(Session::get('sort_on') ?? 2);//created_at desc if not set
->get(['s.*', 'p.name as provider_name', 'pr.*', 'l.name as location']); if (!in_array(Session::get('sort_on'), [3, 4, 5, 6], true)) {
$builder->orderBy($array[0], $array[1]);
}
});
} }
public static function seedBoxDataShowPage(string $seed_box_id) public static function allSeedboxes()
{ {//All seedboxes and relationships (no using joins)
return DB::table('seedboxes as s') return Cache::remember("all_seedboxes", now()->addMonth(1), function () {
->join('pricings as pr', 's.id', '=', 'pr.service_id') $query = SeedBoxes::with(['location', 'provider', 'price']);
->join('providers as p', 's.provider_id', '=', 'p.id') if (in_array(Session::get('sort_on'), [3, 4, 5, 6], true)) {
->join('locations as l', 's.location_id', '=', 'l.id') $options = Settings::orderByProcess(Session::get('sort_on'));
->where('s.id', '=', $seed_box_id) $query->orderBy(Pricing::select("pricings.$options[0]")->whereColumn("pricings.service_id", "seedboxes.id"), $options[1]);
->get(['s.*', 'p.name as provider_name', 'l.name as location', 'pr.*']); }
return $query->get();
});
} }
public static function seedBoxEditDataPage(string $seed_box_id) public static function seedbox(string $seedbox_id)
{ {//Single seedbox and relationships (no using joins)
return DB::table('seedboxes as s') return Cache::remember("seedbox.$seedbox_id", now()->addMonth(1), function () use ($seedbox_id) {
->join('pricings as pr', 's.id', '=', 'pr.service_id') return SeedBoxes::where('id', $seedbox_id)
->join('providers as p', 's.provider_id', '=', 'p.id') ->with(['location', 'provider', 'price'])->first();
->join('locations as l', 's.location_id', '=', 'l.id') });
->where('s.id', '=', $seed_box_id)
->get(['s.*', 'p.name as provider_name', 'l.name as location', 'pr.*']);
} }
public function location(): \Illuminate\Database\Eloquent\Relations\HasOne
{
return $this->hasOne(Locations::class, 'id', 'location_id');
}
public function provider(): \Illuminate\Database\Eloquent\Relations\HasOne
{
return $this->hasOne(Providers::class, 'id', 'provider_id');
}
public function price(): \Illuminate\Database\Eloquent\Relations\HasOne
{
return $this->hasOne(Pricing::class, 'service_id', 'id');
}
public function labels(): \Illuminate\Database\Eloquent\Relations\HasMany
{
return $this->hasMany(LabelsAssigned::class, 'service_id', 'id');
}
} }

View file

@ -2,16 +2,20 @@
namespace App\Models; namespace App\Models;
use App\Process;
use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Cache; use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Session;
use Illuminate\Database\Eloquent\Builder;
class Server extends Model class Server extends Model
{ {
use HasFactory; use HasFactory;
protected $table = 'servers';
protected $keyType = 'string';
public $incrementing = false; public $incrementing = false;
protected $fillable = ['id', 'hostname', 'ipv4', 'ipv6', 'server_type', 'os_id', 'location_id', 'provider_id', protected $fillable = ['id', 'hostname', 'ipv4', 'ipv6', 'server_type', 'os_id', 'location_id', 'provider_id',
@ -22,35 +26,56 @@ class Server extends Model
*/ */
private $id; private $id;
public static function allServers() protected static function boot()
{//All servers and relationships (no using joins) {
return Cache::remember("all_servers", now()->addMonth(1), function () { parent::boot();
return Server::with(['location', 'provider', 'os', 'price', 'ips', 'yabs', 'yabs.disk_speed', 'yabs.network_speed', 'labels', 'labels.label'])->get();
static::addGlobalScope('order', function (Builder $builder) {
$array = Settings::orderByProcess(Session::get('sort_on') ?? 2);//created_at desc if not set
if (!in_array(Session::get('sort_on'), [3, 4, 5, 6], true)) {
$builder->orderBy($array[0], $array[1]);
}
}); });
} }
public static function server(string $server_id) public static function allServers()
{//All servers and relationships (no using joins)
return Cache::remember("all_servers", now()->addMonth(1), function () {
$query = Server::with(['location', 'provider', 'os', 'price', 'ips', 'yabs', 'yabs.disk_speed', 'yabs.network_speed', 'labels']);
if (in_array(Session::get('sort_on'), [3, 4, 5, 6], true)) {
$options = Settings::orderByProcess(Session::get('sort_on'));
$query->orderBy(Pricing::select("pricings.$options[0]")->whereColumn("pricings.service_id", "servers.id"), $options[1]);
}
return $query->get();
});
}
public static function server(string $server_id): Server
{//Single server and relationships (no using joins) {//Single server and relationships (no using joins)
return Cache::remember("server.$server_id", now()->addMonth(1), function () use ($server_id) { return Cache::remember("server.$server_id", now()->addMonth(1), function () use ($server_id) {
return Server::where('id', $server_id) return Server::where('id', $server_id)
->with(['location', 'provider', 'os', 'price', 'ips', 'yabs', 'yabs.disk_speed', 'yabs.network_speed', 'labels', 'labels.label'])->get(); ->with(['location', 'provider', 'os', 'price', 'ips', 'yabs', 'yabs.disk_speed', 'yabs.network_speed', 'labels'])->first();
}); });
} }
public static function allActiveServers() public static function allActiveServers()
{//All ACTIVE servers and relationships replaces activeServersDataIndexPage() {//All ACTIVE servers and relationships replaces activeServersDataIndexPage()
return Cache::remember("all_active_servers", now()->addMonth(1), function () { return Cache::remember("all_active_servers", now()->addMonth(1), function () {
return Server::where('active', '=', 1) $query = Server::where('active', 1)
->with(['location', 'provider', 'os', 'price', 'ips', 'yabs', 'yabs.disk_speed', 'yabs.network_speed', 'labels', 'labels.label']) ->with(['location', 'provider', 'os', 'ips', 'yabs', 'yabs.disk_speed', 'yabs.network_speed', 'labels', 'price']);
->get(); if (in_array(Session::get('sort_on'), [3, 4, 5, 6], true)) {
$options = Settings::orderByProcess(Session::get('sort_on'));
$query->orderBy(Pricing::select("pricings.$options[0]")->whereColumn("pricings.service_id", "servers.id"), $options[1]);
}
return $query->get();
}); });
} }
public static function allNonActiveServers() public static function allNonActiveServers()
{//All NON ACTIVE servers and relationships replaces nonActiveServersDataIndexPage() {//All NON ACTIVE servers and relationships replaces nonActiveServersDataIndexPage()
return Cache::remember("non_active_servers", now()->addMonth(1), function () { return Cache::remember("non_active_servers", now()->addMonth(1), function () {
return Server::where('active', '=', 0) return Server::where('active', 0)
->with(['location', 'provider', 'os', 'price', 'ips', 'yabs', 'yabs.disk_speed', 'yabs.network_speed', 'labels', 'labels.label']) ->with(['location', 'provider', 'os', 'price', 'ips', 'yabs', 'yabs.disk_speed', 'yabs.network_speed', 'labels'])
->get(); ->get();
}); });
} }
@ -58,116 +83,61 @@ class Server extends Model
public static function allPublicServers() public static function allPublicServers()
{//server data that will be publicly viewable (values in settings) {//server data that will be publicly viewable (values in settings)
return Cache::remember("public_server_data", now()->addMonth(1), function () { return Cache::remember("public_server_data", now()->addMonth(1), function () {
return Server::where('show_public', '=', 1) return Server::where('show_public', 1)
->with(['location', 'provider', 'os', 'price', 'ips', 'yabs', 'yabs.disk_speed', 'yabs.network_speed', 'labels', 'labels.label']) ->with(['location', 'provider', 'os', 'price', 'ips', 'yabs', 'yabs.disk_speed', 'yabs.network_speed', 'labels'])
->get(); ->get();
}); });
} }
public static function serviceServerType($type) public static function serviceServerType(int $type, bool $short = true): string
{ {
if ($type === 1) { if ($type === 1) {
return "KVM"; return "KVM";
} elseif ($type === 2) { } elseif ($type === 2) {
return "OVZ"; return "OVZ";
} elseif ($type === 3) { } elseif ($type === 3) {
if (!$short) {
return "Dedicated";
}
return "DEDI"; return "DEDI";
} elseif ($type === 4) { } elseif ($type === 4) {
return "LXC"; return "LXC";
} elseif ($type === 6) { } elseif ($type === 6) {
return "VMware"; return "VMware";
} elseif ($type === 7) {
return "NAT";
} else { } else {
if (!$short) {
return "Semi-dedicated";
}
return "SEMI-DEDI"; return "SEMI-DEDI";
} }
} }
public static function osIntToIcon(int $os, string $os_name) public static function osIntToIcon(int $os, string $os_name): string
{ {
if ($os === 1) {//None if ($os === 1) {//None
return "<i class='fas fa-expand' title='{$os_name}'></i>"; return "<i class='fas fa-expand' title='{$os_name}'></i>";
} else if ($os <= 3) {//Centos } else if ($os <= 3) {//Centos
return "<i class='fab fa-centos os-icon' title='{$os_name}'></i>"; return "<i class='fa-brands fa-centos os-icon' title='{$os_name}'></i>";
} elseif ($os > 3 && $os <= 6) {//Debain } elseif (($os > 7 && $os <= 10) || $os === 44) {//Debian
return "<i class='fab fa-linux os-icon' title='{$os_name}'></i>"; return "<i class='fa-brands fa-linux os-icon' title='{$os_name}'></i>";
} elseif ($os > 6 && $os < 10) {//Fedora } elseif (($os > 11 && $os < 15) || $os === 43) {//Fedora
return "<i class='fab fa-fedora os-icon' title='{$os_name}'></i>"; return "<i class='fa-brands fa-fedora os-icon' title='{$os_name}'></i>";
} elseif ($os > 10 && $os < 13) {//FreeBSD } elseif (($os > 14 && $os < 18) || $os === 46) {//FreeBSD
return "<i class='fab fa-linux os-icon' title='{$os_name}'></i>"; return "<i class='fa-brands fa-linux os-icon' title='{$os_name}'></i>";
} elseif ($os > 13 && $os < 16) {//OpenBSD } elseif (($os > 17 && $os < 21) || $os === 42) {//OpenBSD
return "<i class='fab fa-linux os-icon' title='{$os_name}'></i>"; return "<i class='fa-brands fa-linux os-icon' title='{$os_name}'></i>";
} elseif ($os > 15 && $os < 21) {//Ubuntu } elseif (($os > 25 && $os < 32) || $os === 41) {//Ubuntu
return "<i class='fab fa-ubuntu os-icon' title='{$os_name}'></i>"; return "<i class='fa-brands fa-ubuntu os-icon' title='{$os_name}'></i>";
} elseif ($os > 20 && $os < 26) {//Windows } elseif (($os > 32 && $os < 38) || $os === 40) {//Windows
return "<i class='fab fa-windows os-icon' title='{$os_name}'></i>"; return "<i class='fa-brands fa-windows os-icon' title='{$os_name}'></i>";
} else {//OTHER ISO CUSTOM etc } else {//OTHER ISO CUSTOM etc
return "<i class='fas fa-compact-disc os-icon' title='{$os_name}'></i>"; return "<i class='fa-solid fa-compact-disc os-icon' title='{$os_name}'></i>";
} }
} }
public static function osIdAsString($os) public static function tableRowCompare(string $val1, string $val2, string $value_type = '', bool $is_int = true): string
{
if ($os === "0") {
return "None";
} elseif ($os === "1") {
return "CentOS 7";
} elseif ($os === "2") {
return "CentOS 8";
} elseif ($os === "3") {
return "CentOS";
} elseif ($os === "4") {
return "Debian 9";
} elseif ($os === "5") {
return "Debian 10";
} elseif ($os === "6") {
return "Debian";
} elseif ($os === "7") {
return "Fedora 32";
} elseif ($os === "8") {
return "Fedora 33";
} elseif ($os === "9") {
return "Fedora";
} elseif ($os === "10") {
return "FreeBSD 11.4";
} elseif ($os === "11") {
return "FreeBSD 12.1";
} elseif ($os === "12") {
return "FreeBSD";
} elseif ($os === "13") {
return "OpenBSD 6.7";
} elseif ($os === "14") {
return "OpenBSD 6.8";
} elseif ($os === "15") {
return "OpenBSD";
} elseif ($os == "16") {
return "Ubuntu 16.04";
} elseif ($os === "17") {
return "Ubuntu 18.04";
} elseif ($os === "18") {
return "Ubuntu 20.04";
} elseif ($os === "19") {
return "Ubuntu 20.10";
} elseif ($os === "20") {
return "Ubuntu";
} elseif ($os === "21") {
return "Windows Server 2008";
} elseif ($os === "22") {
return "Windows Server 2012";
} elseif ($os === "23") {
return "Windows Server 2016";
} elseif ($os === "24") {
return "Windows Server 2019";
} elseif ($os === "25") {
return "Windows 10";
} elseif ($os === "26") {
return "Custom";
} elseif ($os === "27") {
return "Other";
} else {
return "Unknown";
}
}
public static function tableRowCompare(string $val1, string $val2, string $value_type = '', bool $is_int = true)
{ {
//<td class="td-nowrap plus-td">+303<span class="data-type">MBps</span></td> //<td class="td-nowrap plus-td">+303<span class="data-type">MBps</span></td>
$str = '<td class="td-nowrap '; $str = '<td class="td-nowrap ';
@ -212,6 +182,7 @@ class Server extends Model
Cache::forget('all_pricing');//All pricing Cache::forget('all_pricing');//All pricing
Cache::forget('services_count_all'); Cache::forget('services_count_all');
Cache::forget('pricing_breakdown'); Cache::forget('pricing_breakdown');
Cache::forget('all_active_pricing');
} }
public static function serverSpecificCacheForget(string $server_id): void public static function serverSpecificCacheForget(string $server_id): void
@ -221,45 +192,48 @@ class Server extends Model
} }
public static function serverYabsAmount(string $server_id): int public static function serverYabsAmount(string $server_id): int
{//Returns amount of YABs a server has {//Returns amount of YABS a server has
return DB::table('yabs') return Yabs::where('server_id', $server_id)->count();
->where('server_id', '=', $server_id)
->get()->count();
} }
public function yabs() public function yabs(): \Illuminate\Database\Eloquent\Relations\HasMany
{ {
return $this->hasMany(Yabs::class, 'server_id', 'id'); return $this->hasMany(Yabs::class, 'server_id', 'id');
} }
public function ips() public function ips(): \Illuminate\Database\Eloquent\Relations\HasMany
{ {
return $this->hasMany(IPs::class, 'service_id', 'id'); return $this->hasMany(IPs::class, 'service_id', 'id');
} }
public function location() public function location(): \Illuminate\Database\Eloquent\Relations\HasOne
{ {
return $this->hasOne(Locations::class, 'id', 'location_id'); return $this->hasOne(Locations::class, 'id', 'location_id');
} }
public function provider() public function provider(): \Illuminate\Database\Eloquent\Relations\HasOne
{ {
return $this->hasOne(Providers::class, 'id', 'provider_id'); return $this->hasOne(Providers::class, 'id', 'provider_id');
} }
public function os() public function os(): \Illuminate\Database\Eloquent\Relations\HasOne
{ {
return $this->hasOne(OS::class, 'id', 'os_id'); return $this->hasOne(OS::class, 'id', 'os_id');
} }
public function price() public function price(): \Illuminate\Database\Eloquent\Relations\HasOne
{ {
return $this->hasOne(Pricing::class, 'service_id', 'id'); return $this->hasOne(Pricing::class, 'service_id', 'id');
} }
public function labels() public function labels(): \Illuminate\Database\Eloquent\Relations\HasMany
{ {
return $this->hasMany(LabelsAssigned::class, 'service_id', 'id'); return $this->hasMany(LabelsAssigned::class, 'service_id', 'id');
} }
public function note(): \Illuminate\Database\Eloquent\Relations\HasOne
{
return $this->hasOne(Note::class, 'service_id', 'id');
}
} }

View file

@ -5,7 +5,6 @@ namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Cache; use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Session; use Illuminate\Support\Facades\Session;
class Settings extends Model class Settings extends Model
@ -14,35 +13,65 @@ class Settings extends Model
protected $table = 'settings'; protected $table = 'settings';
protected $fillable = ['id', 'show_versions_footer', 'show_servers_public']; protected $fillable = ['id', 'show_versions_footer', 'show_servers_public', 'show_server_value_ip', 'show_server_value_hostname', 'show_server_value_provider', 'show_server_value_location', 'show_server_value_price', 'show_server_value_yabs', 'save_yabs_as_txt', 'default_currency', 'default_server_os', 'due_soon_amount', 'recently_added_amount', 'dark_mode', 'dashboard_currency', 'sort_on', 'favicon'];
public static function getSettings() public static function getSettings(): Settings
{ {
return Cache::remember('settings', now()->addWeek(1), function () { return Cache::remember('settings', now()->addWeek(1), function () {
return DB::table('settings') $settings = self::where('id', 1)->first();
->where('id', '=', 1) if (is_null($settings)){
->get(); $settings = Settings::create();
}
return $settings;
}); });
} }
public static function setSettingsToSession($settings): void public static function setSettingsToSession($settings): void
{ {
Session::put('dark_mode', $settings[0]->dark_mode ?? 0); Session::put('dark_mode', $settings->dark_mode ?? 0);
Session::put('timer_version_footer', $settings[0]->show_versions_footer ?? 1); Session::put('timer_version_footer', $settings->show_versions_footer ?? 1);
Session::put('show_servers_public', $settings[0]->show_servers_public ?? 0); Session::put('show_servers_public', $settings->show_servers_public ?? 0);
Session::put('show_server_value_ip', $settings[0]->show_server_value_ip ?? 0); Session::put('show_server_value_ip', $settings->show_server_value_ip ?? 0);
Session::put('show_server_value_hostname', $settings[0]->show_server_value_hostname ?? 0); Session::put('show_server_value_hostname', $settings->show_server_value_hostname ?? 0);
Session::put('show_server_value_price', $settings[0]->show_server_value_price ?? 0); Session::put('show_server_value_price', $settings->show_server_value_price ?? 0);
Session::put('show_server_value_yabs', $settings[0]->show_server_value_yabs ?? 0); Session::put('show_server_value_yabs', $settings->show_server_value_yabs ?? 0);
Session::put('show_server_value_provider', $settings[0]->show_server_value_provider ?? 0); Session::put('show_server_value_provider', $settings->show_server_value_provider ?? 0);
Session::put('show_server_value_location', $settings[0]->show_server_value_location ?? 0); Session::put('show_server_value_location', $settings->show_server_value_location ?? 0);
Session::put('default_currency', $settings[0]->default_currency ?? 'USD'); Session::put('save_yabs_as_txt', $settings->save_yabs_as_txt ?? 0);
Session::put('default_server_os', $settings[0]->default_server_os ?? 1); Session::put('default_currency', $settings->default_currency ?? 'USD');
Session::put('due_soon_amount', $settings[0]->due_soon_amount ?? 6); Session::put('default_server_os', $settings->default_server_os ?? 1);
Session::put('recently_added_amount', $settings[0]->recently_added_amount ?? 6); Session::put('due_soon_amount', $settings->due_soon_amount ?? 6);
Session::put('dashboard_currency', $settings[0]->dashboard_currency ?? 'USD'); Session::put('recently_added_amount', $settings->recently_added_amount ?? 6);
Session::put('dashboard_currency', $settings->dashboard_currency ?? 'USD');
Session::put('sort_on', $settings->sort_on ?? 1);
Session::put('favicon', $settings->favicon ?? 'favicon.ico');
Session::save(); Session::save();
} }
public static function orderByProcess(int $value): array
{
if ($value === 1) {//created_at ASC
return ['created_at', 'asc'];
} elseif ($value === 2) {//created_at DESC
return ['created_at', 'desc'];
} elseif ($value === 3) {//next_due_date ASC
return ['next_due_date', 'asc'];
} elseif ($value === 4) {//next_due_date DESC
return ['next_due_date', 'desc'];
} elseif ($value === 5) {//as_usd ASC
return ['as_usd', 'asc'];
} elseif ($value === 6) {//as_usd DESC
return ['as_usd', 'desc'];
} elseif ($value === 7) {//owned_since ASC
return ['owned_since', 'asc'];
} elseif ($value === 8) {//owned_since DESC
return ['owned_since', 'desc'];
} elseif ($value === 9) {//updated_at ASC
return ['updated_at', 'asc'];
} elseif ($value === 10) {//updated_at DESC
return ['updated_at', 'desc'];
}
return ['created_at', 'desc'];
}
} }

View file

@ -2,10 +2,11 @@
namespace App\Models; namespace App\Models;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Cache; use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Session;
class Shared extends Model class Shared extends Model
{ {
@ -13,14 +14,33 @@ class Shared extends Model
public $table = 'shared_hosting'; public $table = 'shared_hosting';
protected $keyType = 'string';
protected $fillable = ['id', 'active', 'main_domain', 'has_dedicated_ip', 'ip', 'shared_type', 'provider_id', 'location_id', 'bandwidth', 'disk', 'disk_type', 'disk_as_gb', 'domains_limit', 'subdomains_limit', 'ftp_limit', 'email_limit', 'db_limit', 'was_promo', 'owned_since']; protected $fillable = ['id', 'active', 'main_domain', 'has_dedicated_ip', 'ip', 'shared_type', 'provider_id', 'location_id', 'bandwidth', 'disk', 'disk_type', 'disk_as_gb', 'domains_limit', 'subdomains_limit', 'ftp_limit', 'email_limit', 'db_limit', 'was_promo', 'owned_since'];
public $incrementing = false; public $incrementing = false;
protected static function boot()
{
parent::boot();
static::addGlobalScope('order', function (Builder $builder) {
$array = Settings::orderByProcess(Session::get('sort_on') ?? 2);//created_at desc if not set
if (!in_array(Session::get('sort_on'), [3, 4, 5, 6], true)) {
$builder->orderBy($array[0], $array[1]);
}
});
}
public static function allSharedHosting() public static function allSharedHosting()
{//All shared hosting and relationships (no using joins) {//All shared hosting and relationships (no using joins)
return Cache::remember("all_shared", now()->addMonth(1), function () { return Cache::remember("all_shared", now()->addMonth(1), function () {
return Shared::with(['location', 'provider', 'price', 'ips', 'labels', 'labels.label'])->get(); $query = Shared::with(['location', 'provider', 'price', 'ips', 'labels']);
if (in_array(Session::get('sort_on'), [3, 4, 5, 6], true)) {
$options = Settings::orderByProcess(Session::get('sort_on'));
$query->orderBy(Pricing::select("pricings.$options[0]")->whereColumn("pricings.service_id", "shared_hosting.id"), $options[1]);
}
return $query->get();
}); });
} }
@ -28,33 +48,38 @@ class Shared extends Model
{//Single shared hosting and relationships (no using joins) {//Single shared hosting and relationships (no using joins)
return Cache::remember("shared_hosting.$shared_id", now()->addMonth(1), function () use ($shared_id) { return Cache::remember("shared_hosting.$shared_id", now()->addMonth(1), function () use ($shared_id) {
return Shared::where('id', $shared_id) return Shared::where('id', $shared_id)
->with(['location', 'provider', 'price', 'ips', 'labels', 'labels.label'])->get(); ->with(['location', 'provider', 'price', 'ips', 'labels'])->first();
}); });
} }
public function ips() public function ips(): \Illuminate\Database\Eloquent\Relations\HasMany
{ {
return $this->hasMany(IPs::class, 'service_id', 'id'); return $this->hasMany(IPs::class, 'service_id', 'id');
} }
public function location() public function location(): \Illuminate\Database\Eloquent\Relations\HasOne
{ {
return $this->hasOne(Locations::class, 'id', 'location_id'); return $this->hasOne(Locations::class, 'id', 'location_id');
} }
public function provider() public function provider(): \Illuminate\Database\Eloquent\Relations\HasOne
{ {
return $this->hasOne(Providers::class, 'id', 'provider_id'); return $this->hasOne(Providers::class, 'id', 'provider_id');
} }
public function price() public function price(): \Illuminate\Database\Eloquent\Relations\HasOne
{ {
return $this->hasOne(Pricing::class, 'service_id', 'id'); return $this->hasOne(Pricing::class, 'service_id', 'id');
} }
public function labels() public function labels(): \Illuminate\Database\Eloquent\Relations\HasMany
{ {
return $this->hasMany(LabelsAssigned::class, 'service_id', 'id'); return $this->hasMany(LabelsAssigned::class, 'service_id', 'id');
} }
public function note(): \Illuminate\Database\Eloquent\Relations\HasOne
{
return $this->hasOne(Note::class, 'service_id', 'id');
}
} }

View file

@ -2,10 +2,13 @@
namespace App\Models; namespace App\Models;
use DateTime;
use Exception;
use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Cache; use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
class Yabs extends Model class Yabs extends Model
{ {
@ -13,57 +16,322 @@ class Yabs extends Model
public $incrementing = false; public $incrementing = false;
protected $keyType = 'string';
protected $table = 'yabs'; protected $table = 'yabs';
protected $fillable = ['id', 'server_id', 'has_ipv6', 'aes', 'vm', 'output_date', 'cpu_cores', 'cpu_freq', 'cpu_model', 'ram', 'ram_type', 'ram_mb', 'disk', 'disk_type', 'disk_gb', 'gb5_single', 'gb5_multi', 'gb5_id', '4k', '4k_type', '4k_as_mbps', '64k', '64k_type', '64k_as_mbps', '512k', '512k_type', '512k_as_mbps', '1m', '1m_type', '1m_as_mbps', 'location', 'send', 'send_type', 'send_as_mbps', 'receive', 'receive_type', 'receive_as_mbps']; protected $fillable = ['id', 'server_id', 'has_ipv6', 'aes', 'vm', 'output_date', 'cpu_cores', 'cpu_freq', 'cpu_model', 'ram', 'ram_type', 'ram_mb', 'disk', 'disk_type', 'disk_gb', 'gb5_single', 'gb5_multi', 'gb5_id', 'gb6_single', 'gb6_multi', 'gb6_id', '4k', '4k_type', '4k_as_mbps', '64k', '64k_type', '64k_as_mbps', '512k', '512k_type', '512k_as_mbps', '1m', '1m_type', '1m_as_mbps', 'location', 'send', 'send_type', 'send_as_mbps', 'receive', 'receive_type', 'receive_as_mbps', 'uptime', 'distro', 'kernel', 'swap', 'swap_type', 'swap_mb'];
public static function networkSpeedsForServer(string $server_id)
{
return Cache::remember("network_speeds.$server_id", now()->addMonth(1), function () use ($server_id) {
return json_decode(DB::table('network_speed')
->where('network_speed.server_id', '=', $server_id)
->get(), true);
});
}
public static function serverCompareNetwork(string $yabs_id)
{
return Cache::remember("compare_network_speeds.$yabs_id", now()->addMonth(1), function () use ($yabs_id) {
return DB::table('network_speed')
->where('id', '=', $yabs_id)
->get();
});
}
public static function yabs(string $yabs_id) public static function yabs(string $yabs_id)
{ {
return Cache::remember("yabs.$yabs_id", now()->addMonth(1), function () use ($yabs_id) { return Cache::remember("yabs.$yabs_id", now()->addMonth(1), function () use ($yabs_id) {
return self::where('id', $yabs_id)->with(['server', 'disk_speed', 'network_speed']) return self::where('id', $yabs_id)->with(['server', 'disk_speed', 'network_speed', 'server.location', 'server.provider'])
->get(); ->first();
}); });
} }
public static function allYabs() public static function allYabs()
{ {
return Cache::remember("all_yabs", now()->addMonth(1), function () { return Cache::remember("all_yabs", now()->addMonth(1), function () {
return self::with(['server', 'disk_speed', 'network_speed']) return self::with(['server', 'disk_speed', 'network_speed', 'server.location', 'server.provider'])
->get(); ->get();
}); });
} }
public function server() public function server(): \Illuminate\Database\Eloquent\Relations\HasOne
{ {
return $this->hasOne(Server::class, 'id', 'server_id'); return $this->hasOne(Server::class, 'id', 'server_id');
} }
public function disk_speed() public function disk_speed(): \Illuminate\Database\Eloquent\Relations\HasOne
{ {
return $this->hasOne(DiskSpeed::class, 'id', 'id'); return $this->hasOne(DiskSpeed::class, 'id', 'id');
} }
public function network_speed() public function network_speed(): \Illuminate\Database\Eloquent\Relations\HasMany
{ {
return $this->hasMany(NetworkSpeed::class, 'id', 'id'); return $this->hasMany(NetworkSpeed::class, 'id', 'id');
} }
public static function buildYabsArray($data): array
{
$speed_tests = [];
foreach ($data->network_speed as $ns) {
$speed_tests[] = [
'location' => $ns->location,
'send' => $ns->send . ' ' . $ns->send_type,
'receive' => $ns->receive . ' ' . $ns->receive_type,
];
}
return [
'date_time' => $data->output_date,
'location' => $data->server->location->name,
'provider' => $data->server->provider->name,
'uptime' => $data->uptime,
'distro' => $data->distro,
'kernel' => $data->kernel,
'cpu' => [
'cores' => $data->cpu_cores,
'speed_mhz' => $data->cpu_freq,
'model' => $data->cpu_model,
'aes' => $data->aes === 1,
'vm' => $data->vm === 1,
'GB5_single' => $data->gb5_single,
'GB5_multi' => $data->gb5_multi,
],
'ram' => [
'amount' => $data->ram . ' ' . $data->ram_type,
'mb' => $data->ram_mb,
'swap' => [
'amount' => $data->swap ?? null . ' ' . $data->swap_type ?? null,
'mb' => $data->swap_mb ?? null,
],
],
'disk' => [
'amount' => $data->disk . ' ' . $data->disk_type,
'gb' => $data->disk_gb,
'speed_tests' => [
'4k' => $data->disk_speed->d_4k . ' ' . $data->disk_speed->d_4k_type,
'64k' => $data->disk_speed->d_64k . ' ' . $data->disk_speed->d_64k_type,
'512k' => $data->disk_speed->d_512k . ' ' . $data->disk_speed->d_512k_type,
'1m' => $data->disk_speed->d_1m . ' ' . $data->disk_speed->d_1m_type,
],
],
'network' => [
'has_ipv6' => $data->has_ipv6 === 1,
'speed_tests' => $speed_tests
],
];
}
public static function speedAsMbps(string $string): float
{
$data = explode(" ", $string);
if ($data[0] === 'busy') {
return 0;
}
if ($data[1] === "Gbits/sec") {
return $data[0] * 1000;
} else if ($data[1] === "Mbits/sec") {
return $data[0];
} else {//Kbps
return $data[0] / 1000;
}
}
public static function speedType(string $string): string
{
$data = explode(" ", $string);
if ($data[0] === 'busy') {
return "MBps";
}
if ($data[1] === "Gbits/sec") {
return "GBps";
} else if ($data[1] === "Mbits/sec") {
return "MBps";
} else {//Kbps
return "KBps";
}
}
public static function speedAsFloat(string $string): float
{
$data = explode(" ", $string);
if ($data[0] === 'busy') {
return 0;
}
return (float)$data[0];
}
public static function formatRunTime(string $date): string
{
return DateTime::createFromFormat('Ymd-His', $date)->format('Y-m-d H:i:s');
}
public static function gb5IdFromURL(string $url): int
{
return str_replace("https://browser.geekbench.com/v5/cpu/", "", $url);
}
public static function gb6IdFromURL(string $url): int
{
return str_replace("https://browser.geekbench.com/v6/cpu/", "", $url);
}
public static function KBstoMBs(int $kbs): float
{
return $kbs / 1000;
}
public static function insertFromJson($data, string $server_id): bool
{
$data = (object)$data;
try {
$date_ran = self::formatRunTime($data->time);
$version = $data['version'];
$has_ipv4 = $data['net']['ipv4'];
$has_ipv6 = $data['net']['ipv6'];
//OS
$arch = $data['os']['arch'];
$distro = $data['os']['distro'];
$kernel = $data['os']['kernel'];
$uptime = $data['os']['uptime'];
//CPU
$model = $data['cpu']['model'];
$cores = $data['cpu']['cores'];
$freq = $data['cpu']['freq'];
$aes = $data['cpu']['aes'];
$virt = $data['cpu']['virt'];
//RAM Disk
$ram = $data['mem']['ram'];
$swap = $data['mem']['swap'];
$disk = $data['mem']['disk'];
$gb5_single = $gb5_multi = $gb5_id = $gb6_single = $gb6_multi = $gb6_id = null;
foreach ($data['geekbench'] as $gb) {
if ($gb['version'] === 5) {
$gb5_single = $gb['single'];
$gb5_multi = $gb['multi'];
$gb5_id = self::gb5IdFromURL($gb['url']);
} elseif ($gb['version'] === 6) {
$gb6_single = $gb['single'];
$gb6_multi = $gb['multi'];
$gb6_id = self::gb6IdFromURL($gb['url']);
}
}
$yabs_id = Str::random(8);
if ($ram > 999999) {
$ram_f = ($ram / 1024 / 1024);
$ram_type = 'GB';
} else {
$ram_f = ($ram / 1024);
$ram_type = 'MB';
}
if ($disk > 100000000) {
$disk_f = ($disk / 1024 / 1024 / 1024);
$disk_type = 'TB';
} else {
$disk_f = ($disk / 1024 / 1024);
$disk_type = 'GB';
}
self::create([
'id' => $yabs_id,
'server_id' => $server_id,
'has_ipv6' => $has_ipv6,
'aes' => $aes,
'vm' => $virt,
'distro' => $distro,
'kernel' => $kernel,
'uptime' => $uptime,
'cpu_model' => $model,
'cpu_cores' => $cores,
'cpu_freq' => (float)$freq,
'ram' => $ram_f,
'ram_type' => $ram_type,
'ram_mb' => ($ram / 1024),
'swap' => $swap / 1024,
'swap_mb' => ($swap / 1024),
'swap_type' => 'MB',
'disk' => $disk_f,
'disk_gb' => ($disk / 1024 / 1024),
'disk_type' => $disk_type,
'output_date' => $date_ran,
'gb5_single' => $gb5_single,
'gb5_multi' => $gb5_multi,
'gb5_id' => $gb5_id,
'gb6_single' => $gb6_single,
'gb6_multi' => $gb6_multi,
'gb6_id' => $gb6_id
]);
//fio
foreach ($data['fio'] as $ds) {
if ($ds['bs'] === '4k') {
$d4k = ($ds['speed_rw'] > 999999) ? ($ds['speed_rw'] / 1000 / 1000) : $ds['speed_rw'] / 1000;
$d4k_type = ($ds['speed_rw'] > 999999) ? 'GB/s' : 'MB/s';
$d4k_mbps = self::KBstoMBs($ds['speed_rw']);
}
if ($ds['bs'] === '64k') {
$d64k = ($ds['speed_rw'] > 999999) ? ($ds['speed_rw'] / 1000 / 1000) : $ds['speed_rw'] / 1000;
$d64k_type = ($ds['speed_rw'] > 999999) ? 'GB/s' : 'MB/s';
$d64k_mbps = self::KBstoMBs($ds['speed_rw']);
}
if ($ds['bs'] === '512k') {
$d512k = ($ds['speed_rw'] > 999999) ? ($ds['speed_rw'] / 1000 / 1000) : $ds['speed_rw'] / 1000;
$d512k_type = ($ds['speed_rw'] > 999999) ? 'GB/s' : 'MB/s';
$d512k_mbps = self::KBstoMBs($ds['speed_rw']);
}
if ($ds['bs'] === '1m') {
$d1m = ($ds['speed_rw'] > 999999) ? ($ds['speed_rw'] / 1000 / 1000) : $ds['speed_rw'] / 1000;
$d1m_type = ($ds['speed_rw'] > 999999) ? 'GB/s' : 'MB/s';
$d1m_mbps = self::KBstoMBs($ds['speed_rw']);
}
}
DiskSpeed::create([
'id' => $yabs_id,
'server_id' => $server_id,
'd_4k' => $d4k,
'd_4k_type' => $d4k_type,
'd_4k_as_mbps' => $d4k_mbps,
'd_64k' => $d64k,
'd_64k_type' => $d64k_type,
'd_64k_as_mbps' => $d64k_mbps,
'd_512k' => $d512k,
'd_512k_type' => $d512k_type,
'd_512k_as_mbps' => $d512k_mbps,
'd_1m' => $d1m,
'd_1m_type' => $d1m_type,
'd_1m_as_mbps' => $d1m_mbps
]);
//iperf
foreach ($data['iperf'] as $st) {
($has_ipv4) ? $match = 'IPv4' : $match = 'IPv6';
if ($st['mode'] === $match) {
if ($st['send'] !== "busy " || $st['recv'] !== "busy ") {
NetworkSpeed::create([
'id' => $yabs_id,
'server_id' => $server_id,
'location' => $st['loc'],
'send' => self::speedAsFloat($st['send']),
'send_type' => self::speedType($st['send']),
'send_as_mbps' => self::speedAsMbps($st['send']),
'receive' => self::speedAsFloat($st['recv']),
'receive_type' => self::speedType($st['recv']),
'receive_as_mbps' => self::speedAsMbps($st['recv'])
]);
}
}
}
//Update server
$update_server = DB::table('servers')
->where('id', $server_id)
->update([
'ram' => $ram_f,
'ram_type' => $ram_type,
'ram_as_mb' => ($ram / 1024),
'disk' => $disk_f,
'disk_as_gb' => ($disk / 1024 / 1024),
'disk_type' => $disk_type,
'cpu' => $cores,
'has_yabs' => 1
]);
Cache::forget("yabs.$yabs_id");
Cache::forget("all_yabs");
Cache::forget("server.$server_id");
Cache::forget("all_servers");
} catch (Exception $e) {//Not valid JSON
return false;
}
return true;
}
} }

View file

@ -2,9 +2,6 @@
namespace App; namespace App;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Storage;
class Process class Process
{ {
public string $start_time; public string $start_time;
@ -43,398 +40,4 @@ class Process
return "unknown"; return "unknown";
} }
} }
private function floatValue(string $string): float
{//Keeps only numbers and . AKA a float
return preg_replace('/[^0-9,.]/', '', trim($string));
}
private function intValue(string $string): int
{//Keeps only numbers AKA an int
return (int)preg_replace('/[^0-9]/', '', trim($string));
}
private function removeFloat(string $string): string
{//Removes float from a string
return ltrim(preg_replace('/[^A-Za-z\-,.]/', '', $string), '.');
}
private function trimRemoveR(string $string): string
{//Removes \r and does a trim()
return trim(str_replace("\r", '', $string));
}
private function datatype(string $string): string
{//Formats data type (ram and disk)
if (str_contains($string, 'M')) {
return 'MB';//Megabytes
} elseif (str_contains($string, 'G')) {
return 'GB';//Gigabytes
} elseif (str_contains($string, 'K')) {
return 'KB';//Kilobytes
} elseif (str_contains($string, 'T')) {
return 'TB';//TeraBytes
} elseif (str_contains($string, 'B')) {
return 'BT';//Bytes
} else {
return "GB";
}
}
private function GBtoMB(string $gb): float
{//Gigabyte to Megabyte conversion
return ($gb * 1024);
}
private function TBtoGB(string $tb): float
{//Terabyte to Gigabyte conversion
return ($tb * 1024);
}
private function GBpstoMBps(string $gbps, bool $format = false): float
{//Gigabits to Megabits
if ($format) {
return (float)number_format(((float)$gbps * 1024), 3);
}
return (float)$gbps * 1024;
}
private function diskSpeedAsMbps(string $type, string $value): float
{//If value type GB/s convert to MB/s, KB/s to MB/s
if ($type === "GB/s") {
return $this->GBpstoMBps($value);
}
if ($type === "KB/s") {
return (float)($value / 1024);
}
return $value;
}
private function networkSpeedAsMbps(string $type, string $value): float
{//If value type GBps convert to MB/s
if ($type === "GBps") {
return $this->GBpstoMBps($value);
}
return $value;
}
private function yabsSpeedValues(array $data): array
{//Formats YABs speed test for speed value and type as array
$data = explode('|', implode($data));
if ($data[2] === 'busy') {
$send = $send_type = NULL;
} else {
$send = (float)$data[2];
if ($this->removeFloat($data[2]) === 'Mbitssec') {
$send_type = "MBps";
} elseif ($this->removeFloat($data[2]) === 'Gbitssec') {
$send_type = "GBps";
} elseif ($this->removeFloat($data[2]) === 'Kbitssec') {
$send_type = "KBps";
} else {
$send_type = $this->removeFloat($data[2]);
}
}
if ($data[3] === 'busy') {
$receive = $receive_type = NULL;
} else {
$receive = (float)$data[3];
if ($this->removeFloat($data[3]) === 'Mbitssec') {
$receive_type = "MBps";
} elseif ($this->removeFloat($data[3]) === 'Gbitssec') {
$receive_type = "GBps";
} elseif ($this->removeFloat($data[3]) === 'Kbitssec') {
$receive_type = "KBps";
} else {
$receive_type = $this->removeFloat($data[3]);
}
}
return array('send' => $send, 'send_type' => $send_type, 'receive' => $receive, 'receive_type' => $receive_type);
}
private function yabsSpeedLoc(array $data): array
{//Formats YABs speed test provider and location as array
if ($data[1] === '|') {
$provider = $data[0];
} else {
$provider = $data[0] . ' ' . $data[1];
}
if ($data[2] !== '|') {
$location = $data[2] . ' ' . str_replace(',', '', $data[3]);
} else {
$location = $data[3] . ' ' . str_replace(',', '', $data[4]);
}
return array('provider' => $provider, 'location' => $location);
}
public function yabsOutputAsJson(string $server_id, string $data_from_form): array
{
$file_name = 'tempYabs.txt';
$allowed_versions = ['v2021-12-28', 'v2022-02-18', 'v2022-04-30', 'v2022-05-06', 'v2022-06-11'];
Storage::disk('local')->put($file_name, $data_from_form);
$file = Storage::disk('local')->get($file_name);
if ($file) {
$array = explode("\n", $file);
Storage::disk('local')->delete($file_name);//Delete file
} else {
return array('error_id' => 10, 'error_message' => 'Issue writing/reading txt file');
}
//dd($array);
if (count($array) < 46) {
return array('error_id' => 9, 'error_message' => 'Less than 46 lines');
}
if (str_contains($array[0], "# ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## #\r")) {
if ($array[1] !== "# Yet-Another-Bench-Script #\r") {
return array('error_id' => 8, 'error_message' => 'Didnt copy output correctly');
}
$version_array = explode(' ', preg_replace('!\s+!', ' ', $this->trimRemoveR($array[2])));
if (in_array($version_array[1], $allowed_versions, true)) {//YABs version is allowed
if ($version_array[1] === 'v2022-05-06' || $version_array[1] === 'v2022-06-11') {//These versions added in more responses
$cpu = $this->trimRemoveR(str_replace(':', '', strstr($array[11], ': ')));
$cpu_spec = explode(' ', strstr($array[12], ': '));//: 2 @ 3792.872 MHz
$ram_line = $this->trimRemoveR(str_replace(':', '', strstr($array[15], ': ')));
$ram = (float)$ram_line;
$ram_type = $this->datatype($ram_line);
$swap_line = $this->trimRemoveR(str_replace(':', '', strstr($array[16], ': ')));
$swap = (float)$swap_line;
$swap_type = $this->datatype($swap_line);
$disk_line = $this->trimRemoveR(str_replace(':', '', strstr($array[17], ': ')));
$disk = (float)$disk_line;
$disk_type = $this->datatype($disk_line);
$io_3 = explode(' ', preg_replace('!\s+!', ' ', $array[27]));
$io_6 = explode(' ', preg_replace('!\s+!', ' ', $array[33]));
(str_contains($array[13], 'Enabled')) ? $aes_ni = true : $aes_ni = false;
(str_contains($array[14], 'Enabled')) ? $vm_amd_v = true : $vm_amd_v = false;
} else {
$cpu = $this->trimRemoveR(str_replace(':', '', strstr($array[10], ': ')));
$cpu_spec = explode(' ', strstr($array[11], ': '));//: 2 @ 3792.872 MHz
$ram_line = $this->trimRemoveR(str_replace(':', '', strstr($array[14], ': ')));
$ram = (float)$ram_line;
$ram_type = $this->datatype($ram_line);
$swap_line = $this->trimRemoveR(str_replace(':', '', strstr($array[15], ': ')));
$swap = (float)$swap_line;
$swap_type = $this->datatype($swap_line);
$disk_line = $this->trimRemoveR(str_replace(':', '', strstr($array[16], ': ')));
$disk = (float)$disk_line;
$disk_type = $this->datatype($disk_line);
$io_3 = explode(' ', preg_replace('!\s+!', ' ', $array[24]));
$io_6 = explode(' ', preg_replace('!\s+!', ' ', $array[30]));
(str_contains($array[12], 'Enabled')) ? $aes_ni = true : $aes_ni = false;
(str_contains($array[13], 'Enabled')) ? $vm_amd_v = true : $vm_amd_v = false;
}
$cpu_cores = $cpu_spec[1];
$cpu_freq = $cpu_spec[3];
$d4k_as_mbps = $this->diskSpeedAsMbps($io_3[3], $this->floatValue($io_3[2]));
$d64k_as_mbps = $this->diskSpeedAsMbps($io_3[7], $this->floatValue($io_3[6]));
$d512k_as_mbps = $this->diskSpeedAsMbps($io_6[3], $this->floatValue($io_6[2]));
$d1m_as_mbps = $this->diskSpeedAsMbps($io_6[7], $this->floatValue($io_6[6]));
$disk_test_arr = array(
'4k_total' => $this->floatValue($io_3[2]),
'4k_total_type' => $io_3[3],
'4k_total_mbps' => $d4k_as_mbps,
'64k_total' => $this->floatValue($io_3[6]),
'64k_total_type' => $io_3[7],
'64k_total_mbps' => $d64k_as_mbps,
'512k_total' => $this->floatValue($io_6[2]),
'512k_total_type' => $io_6[3],
'512k_total_mbps' => $d512k_as_mbps,
'1m_total' => $this->floatValue($io_6[6]),
'1m_total_type' => $io_6[7],
'1m_total_mbps' => $d1m_as_mbps,
);
if (isset($array[40])) {
if ($version_array[1] === 'v2022-05-06' || $version_array[1] === 'v2022-06-11') {
if ($array[43] === "Geekbench 5 Benchmark Test:\r") {
//No ipv6
//Has short ipv4 network speed testing (-r)
$has_ipv6 = false;
$start_st = 39;
$end_st = 41;
$gb_s = 47;
$gb_m = 48;
$gb_url = 49;
} elseif ($array[45] === "Geekbench 4 Benchmark Test:\r") {
return array('error_id' => 6, 'error_message' => 'GeekBench 5 only allowed');
} elseif ($array[45] === "Geekbench 5 test failed. Run manually to determine cause.\r") {
return array('error_id' => 7, 'error_message' => 'GeekBench test failed');
} elseif ($array[46] === "Geekbench 5 Benchmark Test:\r") {
//No ipv6
//Has full ipv4 network speed testing
$has_ipv6 = false;
$start_st = 39;
$end_st = 44;
$gb_s = 44;
$gb_m = 45;
$gb_url = 46;
} elseif ($array[47] === "Geekbench 5 Benchmark Test:\r") {
//No ipv6
//Has full ipv4 network speed testing
$has_ipv6 = false;
$start_st = 39;
$end_st = 45;
$gb_s = 51;
$gb_m = 52;
$gb_url = 53;
} elseif ($array[43] === "iperf3 Network Speed Tests (IPv6):\r") {
//HAS ipv6
//Has short ipv4 & ipv6 network speed testing
$has_ipv6 = true;
$start_st = 39;
$end_st = 41;
$gb_s = 55;
$gb_m = 56;
$gb_url = 57;
} elseif ($array[56] === "Geekbench 5 Benchmark Test:\r") {
//HAS ipv6
//Has full ipv4 & ipv6 network speed testing
$has_ipv6 = true;
$start_st = 39;
$end_st = 44;
$gb_s = 60;
$gb_m = 61;
$gb_url = 62;
}elseif ($array[59] === "Geekbench 5 Benchmark Test:\r") {
//HAS ipv6
//Has full ipv4 & ipv6 network speed testing
$has_ipv6 = true;
$start_st = 39;
$end_st = 45;
$gb_s = 63;
$gb_m = 64;
$gb_url = 65;
} else {
return array('error_id' => 5, 'error_message' => 'Not correct YABs command output');
}
} else {
if ($array[45] === "Geekbench 5 Benchmark Test:\r") {
//No ipv6
//Has short ipv4 network speed testing (-r)
$has_ipv6 = false;
$start_st = 36;
$end_st = 43;
$gb_s = 49;
$gb_m = 50;
$gb_url = 51;
} elseif ($array[45] === "Geekbench 4 Benchmark Test:\r") {
return array('error_id' => 6, 'error_message' => 'GeekBench 5 only allowed');
} elseif ($array[45] === "Geekbench 5 test failed. Run manually to determine cause.\r") {
return array('error_id' => 7, 'error_message' => 'GeekBench test failed');
} elseif ($array[40] === "Geekbench 5 Benchmark Test:\r") {
//No ipv6
//Has full ipv4 network speed testing
$has_ipv6 = false;
$start_st = 36;
$end_st = 38;
$gb_s = 44;
$gb_m = 45;
$gb_url = 46;
} elseif ($array[40] === "iperf3 Network Speed Tests (IPv6):\r") {
//HAS ipv6
//Has short ipv4 & ipv6 network speed testing
$has_ipv6 = true;
$start_st = 36;
$end_st = 38;
$gb_s = 52;
$gb_m = 53;
$gb_url = 54;
} elseif ($array[56] === "Geekbench 5 Benchmark Test:\r") {
//HAS ipv6
//Has full ipv4 & ipv6 network speed testing
$has_ipv6 = true;
$start_st = 36;
$end_st = 43;
$gb_s = 60;
$gb_m = 61;
$gb_url = 62;
} else {
return array('error_id' => 5, 'error_message' => 'Not correct YABs command output');
}
}
} else {
return array('error_id' => 4, 'error_message' => 'Not correct formatting');
}
$geekbench_single = $this->intValue($array[$gb_s]);
$geekbench_multi = $this->intValue($array[$gb_m]);
$geek_full_url = explode(' ', preg_replace('!\s+!', ' ', $array[$gb_url]));
$gb5_id = (int)substr($geek_full_url[3], strrpos($geek_full_url[3], '/') + 1);//
$has_a_speed_test = false;
($ram_type === 'GB') ? $ram_mb = $this->GBtoMB($ram) : $ram_mb = $ram;
($swap_type === 'GB') ? $swap_mb = $this->GBtoMB($swap) : $swap_mb = $swap;
($disk_type === 'TB') ? $disk_gb = $this->TBtoGB($disk) : $disk_gb = $disk;
$date = date_create($array[6]);
$output = [
'id' => $server_id,
'has_ipv6' => $has_ipv6,
'output_date' => date_format($date, 'Y-m-d H:i:s'),
'process_date' => date('Y-m-d H:i:s'),
'cpu_cores' => (int)$cpu_cores,
'cpu_freq' => (float)$cpu_freq,
'cpu' => $cpu,
'ram' => $ram,
'ram_type' => $ram_type,
'ram_mb' => $ram_mb,
'swap' => $swap,
'swap_type' => $swap_type,
'swap_mb' => $swap_mb,
'disk' => $disk,
'disk_type' => $disk_type,
'disk_gb' => $disk_gb,
'aes' => $aes_ni,
'vm' => $vm_amd_v,
'GB5_single' => $geekbench_single,
'GB5_mult' => $geekbench_multi,
'GB5_id' => $gb5_id
];
$output['disk_speed'] = $disk_test_arr;
$speed_test_arr = array();
for ($i = $start_st; $i <= $end_st; $i++) {
if (str_contains($array[$i], 'busy')) {
//Has a "busy" result, No insert
} else {
$data = explode(' ', preg_replace('!\s+!', ' ', $array[$i]));
$send_as_mbps = $this->networkSpeedAsMbps($this->yabsSpeedValues($data)['send_type'], $this->yabsSpeedValues($data)['send']);
$recieve_as_mbps = $this->networkSpeedAsMbps($this->yabsSpeedValues($data)['receive_type'], $this->yabsSpeedValues($data)['receive']);
$speed_test_arr[] = array(
'location' => $this->yabsSpeedLoc($data)['location'],
'send' => $this->yabsSpeedValues($data)['send'],
'send_type' => $this->yabsSpeedValues($data)['send_type'],
'send_type_mbps' => $send_as_mbps,
'receive' => $this->yabsSpeedValues($data)['receive'],
'receive_type' => $this->yabsSpeedValues($data)['receive_type'],
'receive_type_mbps' => $recieve_as_mbps
);
$has_a_speed_test = true;
}
}
if ($has_a_speed_test) {
$output['network_speed'] = $speed_test_arr;
}
return $output;
} else {
return array('error_id' => 4, 'error_message' => 'Wrong YABs version');
}
} else {
return array('error_id' => 3, 'error_message' => 'Didnt start at right spot');
}
}
} }

View file

@ -17,7 +17,7 @@ class RouteServiceProvider extends ServiceProvider
* *
* @var string * @var string
*/ */
public const HOME = '/dashboard'; public const HOME = '/';
/** /**
* The controller namespace for the application. * The controller namespace for the application.

View file

@ -11,7 +11,7 @@ class OsSelect extends Component
public function render() public function render()
{ {
return view('components.os-select', [ return view('components.os-select', [
'os' => OS::allOS() 'os' => OS::allOS()->toArray()
]); ]);
} }
} }

View file

@ -10,23 +10,23 @@
], ],
"license": "MIT", "license": "MIT",
"require": { "require": {
"php": "^8.0", "php": "^8.3",
"fruitcake/laravel-cors": "^2.2", "guzzlehttp/guzzle": "^7.9.2",
"guzzlehttp/guzzle": "^7.4", "laravel/framework": "^v11.34.2",
"laravel/framework": "^9", "laravel/tinker": "^v2.10.0",
"laravel/tinker": "^2.7", "laravel/ui": "^v4.6.0",
"laravel/ui": "^3.4", "yajra/laravel-datatables-oracle": "~v11.1.5",
"yajra/laravel-datatables-oracle": "~9.20", "ext-json": "*",
"ext-json": "*" "illuminate/view": "^v11.6.0"
}, },
"require-dev": { "require-dev": {
"fakerphp/faker": "^1.19.0", "fakerphp/faker": "^v1.24.1",
"laravel/breeze": "^1.9", "laravel/breeze": "^v2.2.6",
"laravel/sail": "^1.14", "laravel/sail": "^v1.39.1",
"mockery/mockery": "^1.5", "mockery/mockery": "^1.6.12",
"nunomaduro/collision": "^6.2", "nunomaduro/collision": "^v8.5.0",
"phpunit/phpunit": "^9.5", "phpunit/phpunit": "^11.5.0",
"spatie/laravel-ignition": "^1.2" "spatie/laravel-ignition": "^2.9.0"
}, },
"config": { "config": {
"optimize-autoloader": true, "optimize-autoloader": true,

4137
composer.lock generated

File diff suppressed because it is too large Load diff

View file

@ -42,6 +42,11 @@ return [
'visibility' => 'public', 'visibility' => 'public',
], ],
'public_uploads' => [
'driver' => 'local',
'root' => public_path(),
],
's3' => [ 's3' => [
'driver' => 's3', 'driver' => 's3',
'key' => env('AWS_ACCESS_KEY_ID'), 'key' => env('AWS_ACCESS_KEY_ID'),

View file

@ -18,10 +18,10 @@ class CreatePricingTable extends Migration
$table->tinyInteger('service_type'); $table->tinyInteger('service_type');
$table->tinyInteger('active')->default(1); $table->tinyInteger('active')->default(1);
$table->char('currency', 3); $table->char('currency', 3);
$table->decimal('price',10,2); $table->decimal('price', 10, 2);
$table->tinyInteger('term'); $table->tinyInteger('term');
$table->decimal('as_usd',10,2); $table->decimal('as_usd', 10, 2);
$table->decimal('usd_per_month',10,2); $table->decimal('usd_per_month', 10, 2);
$table->date('next_due_date'); $table->date('next_due_date');
$table->timestamps(); $table->timestamps();
}); });
@ -34,6 +34,6 @@ class CreatePricingTable extends Migration
*/ */
public function down() public function down()
{ {
Schema::dropIfExists('pricings'); Schema::dropIfExists('pricings');
} }
} }

View file

@ -2,6 +2,7 @@
use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema; use Illuminate\Support\Facades\Schema;
return new class extends Migration return new class extends Migration
@ -9,13 +10,17 @@ return new class extends Migration
public function up() public function up()
{ {
Schema::table('disk_speed', function (Blueprint $table) { Schema::table('disk_speed', function (Blueprint $table) {
$table->dropForeign('ds_fk_yabs'); if (env('DB_CONNECTION') !== 'sqlite') {
$table->dropForeign('ds_fk_yabs');
}
$table->foreign('id', 'ds_fk_yabs')->references('id')->on('yabs')->onDelete('cascade'); $table->foreign('id', 'ds_fk_yabs')->references('id')->on('yabs')->onDelete('cascade');
}); });
Schema::table('network_speed', function (Blueprint $table) { Schema::table('network_speed', function (Blueprint $table) {
$table->dropForeign('ns_fk_yabs'); if (env('DB_CONNECTION') !== 'sqlite') {
$table->dropForeign('ns_fk_yabs');
}
$table->foreign('id', 'ns_fk_yabs')->references('id')->on('yabs')->onDelete('cascade'); $table->foreign('id', 'ns_fk_yabs')->references('id')->on('yabs')->onDelete('cascade');
}); });

View file

@ -4,12 +4,13 @@ use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema; use Illuminate\Support\Facades\Schema;
return new class extends Migration return new class extends Migration {
{
public function up() public function up()
{ {
Schema::table('yabs', function (Blueprint $table) { Schema::table('yabs', function (Blueprint $table) {
$table->dropForeign('yabs_fk_servers'); if (env('DB_CONNECTION') !== 'sqlite') {
$table->dropForeign('yabs_fk_servers');
}
$table->foreign('server_id', 'yabs_fk_servers')->references('id')->on('servers')->onDelete('cascade'); $table->foreign('server_id', 'yabs_fk_servers')->references('id')->on('servers')->onDelete('cascade');
}); });

View file

@ -0,0 +1,26 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration {
public function up()
{
Schema::table('yabs', function (Blueprint $table) {
$table->string('uptime')->nullable()->default(null)->after('gb5_id');
$table->string('distro')->nullable()->default(null)->after('gb5_id');
$table->string('kernel')->nullable()->default(null)->after('gb5_id');
$table->float('swap')->nullable()->default(null)->after('ram_mb');
$table->char('swap_type', 2)->nullable()->default(null)->after('ram_mb');
$table->float('swap_mb')->nullable()->default(null)->after('ram_mb');
});
}
public function down()
{
Schema::table('yabs', function (Blueprint $table) {
$table->dropColumn(['uptime', 'distro', 'kernel', 'swap', 'swap_type', 'swap_mb']);
});
}
};

View file

@ -0,0 +1,22 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up()
{
Schema::table('settings', function (Blueprint $table) {
$table->boolean('save_yabs_as_txt')->default(false)->after('show_server_value_yabs');
});
}
public function down()
{
Schema::table('settings', function (Blueprint $table) {
$table->dropColumn('save_yabs_as_txt');
});
}
};

View file

@ -0,0 +1,18 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up()
{
Schema::table('yabs', function($table)
{
$table->integer('gb5_single')->nullable()->change();
$table->integer('gb5_multi')->nullable()->change();
$table->integer('gb5_id')->nullable()->change();
});
}
};

View file

@ -0,0 +1,22 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up()
{
Schema::table('settings', function (Blueprint $table) {
$table->tinyInteger('sort_on')->default(1)->after('dashboard_currency');
});
}
public function down()
{
Schema::table('settings', function (Blueprint $table) {
$table->dropColumn('sort_on');
});
}
};

View file

@ -0,0 +1,23 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up()
{
Schema::create('notes', function (Blueprint $table) {
$table->char('id', 8)->primary();
$table->char('service_id', 8)->unique();
$table->text('note');
$table->timestamps();
});
}
public function down()
{
Schema::dropIfExists('notes');
}
};

View file

@ -0,0 +1,22 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::table('settings', function (Blueprint $table) {
$table->string('favicon')->after('sort_on')->default('favicon.ico');
});
}
public function down(): void
{
Schema::table('settings', function (Blueprint $table) {
$table->dropColumn('favicon');
});
}
};

View file

@ -0,0 +1,25 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration {
public function up(): void
{
Schema::table('yabs', function (Blueprint $table) {
$table->integer('gb6_single')->nullable()->default(null)->after('gb5_id');
$table->integer('gb6_multi')->nullable()->default(null)->after('gb5_id');
$table->integer('gb6_id')->nullable()->default(null)->after('gb5_id');
});
}
public function down(): void
{
Schema::table('yabs', function (Blueprint $table) {
$table->dropColumn('gb6_single');
$table->dropColumn('gb6_multi');
$table->dropColumn('gb6_id');
});
}
};

View file

@ -0,0 +1,29 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration {
public function up(): void
{
Schema::table('ips', function (Blueprint $table) {
$table->string('continent')->default(null)->nullable()->after('active');
$table->string('country')->default(null)->nullable()->after('active');
$table->string('region')->default(null)->nullable()->after('active');
$table->string('city')->default(null)->nullable()->after('active');
$table->string('org')->default(null)->nullable()->after('active');
$table->string('isp')->default(null)->nullable()->after('active');
$table->string('asn')->default(null)->nullable()->after('active');
$table->string('timezone_gmt')->default(null)->nullable()->after('active');
$table->dateTime('fetched_at')->default(null)->nullable()->after('active');
});
}
public function down(): void
{
Schema::table('ips', function (Blueprint $table) {
$table->dropColumn(['continent', 'country', 'region', 'city', 'org', 'isp', 'asn', 'timezone_gmt', 'fetched_at']);
});
}
};

View file

@ -14,42 +14,49 @@ class OsSeeder extends Seeder
["name" => "None", "created_at" => Carbon::now()], ["name" => "None", "created_at" => Carbon::now()],
["name" => "AlmaLinux 8", "created_at" => Carbon::now()], ["name" => "AlmaLinux 8", "created_at" => Carbon::now()],
["name" => "AlmaLinux", "created_at" => Carbon::now()], ["name" => "AlmaLinux", "created_at" => Carbon::now()],
["name" => "Centos 7", "created_at" => Carbon::now()], ["name" => "Centos 7", "created_at" => Carbon::now()],//3
["name" => "Centos 8", "created_at" => Carbon::now()], ["name" => "Centos 8", "created_at" => Carbon::now()],
["name" => "Centos 9", "created_at" => Carbon::now()], ["name" => "Centos 9", "created_at" => Carbon::now()],
["name" => "Centos", "created_at" => Carbon::now()], ["name" => "Centos", "created_at" => Carbon::now()],
["name" => "Debian 9", "created_at" => Carbon::now()], ["name" => "Debian 9", "created_at" => Carbon::now()],//7
["name" => "Debian 10", "created_at" => Carbon::now()], ["name" => "Debian 10", "created_at" => Carbon::now()],
["name" => "Debian", "created_at" => Carbon::now()], ["name" => "Debian", "created_at" => Carbon::now()],
["name" => "Fedora 32", "created_at" => Carbon::now()], ["name" => "Fedora 32", "created_at" => Carbon::now()],//10
["name" => "Fedora 33", "created_at" => Carbon::now()], ["name" => "Fedora 33", "created_at" => Carbon::now()],
["name" => "Fedora 34", "created_at" => Carbon::now()], ["name" => "Fedora 34", "created_at" => Carbon::now()],
["name" => "Fedora", "created_at" => Carbon::now()], ["name" => "Fedora", "created_at" => Carbon::now()],//13
["name" => "FreeBSD 11.4", "created_at" => Carbon::now()], ["name" => "FreeBSD 11.4", "created_at" => Carbon::now()],
["name" => "FreeBSD 12.1", "created_at" => Carbon::now()], ["name" => "FreeBSD 12.1", "created_at" => Carbon::now()],//15
["name" => "FreeBSD", "created_at" => Carbon::now()], ["name" => "FreeBSD", "created_at" => Carbon::now()],
["name" => "OpenBSD 6.7", "created_at" => Carbon::now()], ["name" => "OpenBSD 6.7", "created_at" => Carbon::now()],
["name" => "OpenBSD 6.8", "created_at" => Carbon::now()], ["name" => "OpenBSD 6.8", "created_at" => Carbon::now()],
["name" => "OpenBSD", "created_at" => Carbon::now()], ["name" => "OpenBSD", "created_at" => Carbon::now()],
["name" => "Red Hat Enterprise Linux 8", "created_at" => Carbon::now()], ["name" => "Red Hat Enterprise Linux 8", "created_at" => Carbon::now()],//20
["name" => "Red Hat Enterprise Linux 9", "created_at" => Carbon::now()], ["name" => "Red Hat Enterprise Linux 9", "created_at" => Carbon::now()],
["name" => "Red Hat Enterprise Linux", "created_at" => Carbon::now()], ["name" => "Red Hat Enterprise Linux", "created_at" => Carbon::now()],
["name" => "Rocky Linux 8", "created_at" => Carbon::now()], ["name" => "Rocky Linux 8", "created_at" => Carbon::now()],
["name" => "Rocky Linux", "created_at" => Carbon::now()], ["name" => "Rocky Linux", "created_at" => Carbon::now()],
["name" => "Ubuntu 16.04", "created_at" => Carbon::now()], ["name" => "Ubuntu 16.04", "created_at" => Carbon::now()],//25
["name" => "Ubuntu 18.04", "created_at" => Carbon::now()], ["name" => "Ubuntu 18.04", "created_at" => Carbon::now()],
["name" => "Ubuntu 20.04", "created_at" => Carbon::now()], ["name" => "Ubuntu 20.04", "created_at" => Carbon::now()],
["name" => "Ubuntu 20.10", "created_at" => Carbon::now()], ["name" => "Ubuntu 20.10", "created_at" => Carbon::now()],
["name" => "Ubuntu 22.10", "created_at" => Carbon::now()], ["name" => "Ubuntu 22.10", "created_at" => Carbon::now()],
["name" => "Ubuntu", "created_at" => Carbon::now()], ["name" => "Ubuntu", "created_at" => Carbon::now()],//30
["name" => "Windows Server 2008", "created_at" => Carbon::now()], ["name" => "Windows Server 2008", "created_at" => Carbon::now()],
["name" => "Windows Server 2012", "created_at" => Carbon::now()], ["name" => "Windows Server 2012", "created_at" => Carbon::now()],
["name" => "Windows Server 2016", "created_at" => Carbon::now()], ["name" => "Windows Server 2016", "created_at" => Carbon::now()],
["name" => "Windows Server 2019", "created_at" => Carbon::now()], ["name" => "Windows Server 2019", "created_at" => Carbon::now()],
["name" => "Windows 10", "created_at" => Carbon::now()], ["name" => "Windows 10", "created_at" => Carbon::now()],
["name" => "Windows 11", "created_at" => Carbon::now()], ["name" => "Windows 11", "created_at" => Carbon::now()],//38
["name" => "Custom", "created_at" => Carbon::now()], ["name" => "Custom", "created_at" => Carbon::now()],//39
["name" => "Other", "created_at" => Carbon::now()] ["name" => "Other", "created_at" => Carbon::now()],//40
["name" => "Windows Server 2022", "created_at" => Carbon::now()],//41
["name" => "Ubuntu 24.04", "created_at" => Carbon::now()],//42
["name" => "OpenBSD 7.5", "created_at" => Carbon::now()],//43
["name" => "Fedora 41", "created_at" => Carbon::now()],//44
["name" => "Debian 11", "created_at" => Carbon::now()],//45
["name" => "AlmaLinux 9", "created_at" => Carbon::now()],//46
["name" => "FreeBSD 14.1", "created_at" => Carbon::now()],//47
]; ];
DB::table('os')->insert($os); DB::table('os')->insert($os);

16482
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -7,26 +7,29 @@
"watch-poll": "mix watch -- --watch-options-poll=1000", "watch-poll": "mix watch -- --watch-options-poll=1000",
"hot": "mix watch --hot", "hot": "mix watch --hot",
"prod": "npm run production", "prod": "npm run production",
"production": "mix --production" "production": "mix --production",
"build": "webpack --config webpack.config.js"
}, },
"devDependencies": { "devDependencies": {
"@popperjs/core": "^2.10.2", "axios": "^1.7.9",
"@tailwindcss/forms": "^0.4.0", "bootstrap": "^5.3.3",
"alpinejs": "^3.4.2", "bootstrap-dark-5": "^1.1.3",
"autoprefixer": "^10.1.0", "bootstrap-data-table": "^1.0.0",
"axios": "^0.21.4", "datatables": "^1.10.18",
"bootstrap": "^5.1.3", "datatables.net-bs": "^2.1.8",
"laravel-mix": "^6.0.41", "font-awesome": "^4.7.0",
"lodash": "^4.17.21", "jquery": "^3.7.1",
"postcss": "^8.2.1", "laravel-mix": "^6.0.49",
"postcss-import": "^14.0.1", "resolve-url-loader": "^5.0.0",
"resolve-url-loader": "^3.1.2", "sass": "^1.82.0",
"sass": "^1.32.11", "sass-loader": "^12.6.0",
"sass-loader": "^11.0.1", "vue": "^2.7.16",
"tailwindcss": "^3.0.0", "vue-loader": "^17.4.2",
"vue": "^2.6.12",
"vue-loader": "^15.9.5",
"vue-resource": "^1.5.3", "vue-resource": "^1.5.3",
"vue-template-compiler": "^2.6.12" "vue-template-compiler": "^2.7.16"
},
"dependencies": {
"@fortawesome/fontawesome-free": "^6.7.1",
"datatables.net-bs5": "^1.13.11"
} }
} }

14203
public/css/app.css vendored

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

13116
public/css/dark.css vendored Normal file

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

11969
public/css/light.css vendored Normal file

File diff suppressed because it is too large Load diff

View file

@ -1,10 +0,0 @@
var vm = new Vue({
data: {
key: ""
},
methods: {
onChange(event) {
console.log(event.target.value)
}
}
});

96885
public/js/app.js vendored

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,39 @@
/*!
* Bootstrap v5.3.3 (https://getbootstrap.com/)
* Copyright 2011-2024 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
*/
/*!
* The buffer module from node.js, for the browser.
*
* @author Feross Aboukhadijeh <http://feross.org>
* @license MIT
*/
/*!
* Vue.js v2.7.16
* (c) 2014-2023 Evan You
* Released under the MIT License.
*/
/*!
* jQuery JavaScript Library v3.7.1
* https://jquery.com/
*
* Copyright OpenJS Foundation and other contributors
* Released under the MIT license
* https://jquery.org/license
*
* Date: 2023-08-28T13:37Z
*/
/*! DataTables 1.10.18
* ©2008-2018 SpryMedia Ltd - datatables.net/license
*/
/*! DataTables Bootstrap 5 integration
* 2020 SpryMedia Ltd - datatables.net/license
*/
/*! ieee754. BSD-3-Clause License. Feross Aboukhadijeh <https://feross.org/opensource> */

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -1,14 +0,0 @@
/*!
DataTables Bootstrap 5 integration
2020 SpryMedia Ltd - datatables.net/license
*/
var $jscomp=$jscomp||{};$jscomp.scope={};$jscomp.findInternal=function(a,b,c){a instanceof String&&(a=String(a));for(var e=a.length,d=0;d<e;d++){var f=a[d];if(b.call(c,f,d,a))return{i:d,v:f}}return{i:-1,v:void 0}};$jscomp.ASSUME_ES5=!1;$jscomp.ASSUME_NO_NATIVE_MAP=!1;$jscomp.ASSUME_NO_NATIVE_SET=!1;$jscomp.SIMPLE_FROUND_POLYFILL=!1;$jscomp.ISOLATE_POLYFILLS=!1;
$jscomp.defineProperty=$jscomp.ASSUME_ES5||"function"==typeof Object.defineProperties?Object.defineProperty:function(a,b,c){if(a==Array.prototype||a==Object.prototype)return a;a[b]=c.value;return a};$jscomp.getGlobal=function(a){a=["object"==typeof globalThis&&globalThis,a,"object"==typeof window&&window,"object"==typeof self&&self,"object"==typeof global&&global];for(var b=0;b<a.length;++b){var c=a[b];if(c&&c.Math==Math)return c}throw Error("Cannot find global object");};$jscomp.global=$jscomp.getGlobal(this);
$jscomp.IS_SYMBOL_NATIVE="function"===typeof Symbol&&"symbol"===typeof Symbol("x");$jscomp.TRUST_ES6_POLYFILLS=!$jscomp.ISOLATE_POLYFILLS||$jscomp.IS_SYMBOL_NATIVE;$jscomp.polyfills={};$jscomp.propertyToPolyfillSymbol={};$jscomp.POLYFILL_PREFIX="$jscp$";var $jscomp$lookupPolyfilledValue=function(a,b){var c=$jscomp.propertyToPolyfillSymbol[b];if(null==c)return a[b];c=a[c];return void 0!==c?c:a[b]};
$jscomp.polyfill=function(a,b,c,e){b&&($jscomp.ISOLATE_POLYFILLS?$jscomp.polyfillIsolated(a,b,c,e):$jscomp.polyfillUnisolated(a,b,c,e))};$jscomp.polyfillUnisolated=function(a,b,c,e){c=$jscomp.global;a=a.split(".");for(e=0;e<a.length-1;e++){var d=a[e];if(!(d in c))return;c=c[d]}a=a[a.length-1];e=c[a];b=b(e);b!=e&&null!=b&&$jscomp.defineProperty(c,a,{configurable:!0,writable:!0,value:b})};
$jscomp.polyfillIsolated=function(a,b,c,e){var d=a.split(".");a=1===d.length;e=d[0];e=!a&&e in $jscomp.polyfills?$jscomp.polyfills:$jscomp.global;for(var f=0;f<d.length-1;f++){var l=d[f];if(!(l in e))return;e=e[l]}d=d[d.length-1];c=$jscomp.IS_SYMBOL_NATIVE&&"es6"===c?e[d]:null;b=b(c);null!=b&&(a?$jscomp.defineProperty($jscomp.polyfills,d,{configurable:!0,writable:!0,value:b}):b!==c&&($jscomp.propertyToPolyfillSymbol[d]=$jscomp.IS_SYMBOL_NATIVE?$jscomp.global.Symbol(d):$jscomp.POLYFILL_PREFIX+d,d=
$jscomp.propertyToPolyfillSymbol[d],$jscomp.defineProperty(e,d,{configurable:!0,writable:!0,value:b})))};$jscomp.polyfill("Array.prototype.find",function(a){return a?a:function(b,c){return $jscomp.findInternal(this,b,c).v}},"es6","es3");
(function(a){"function"===typeof define&&define.amd?define(["jquery","datatables.net"],function(b){return a(b,window,document)}):"object"===typeof exports?module.exports=function(b,c){b||(b=window);c&&c.fn.dataTable||(c=require("datatables.net")(b,c).$);return a(c,b,b.document)}:a(jQuery,window,document)})(function(a,b,c,e){var d=a.fn.dataTable;a.extend(!0,d.defaults,{dom:"<'row'<'col-sm-12 col-md-6'l><'col-sm-12 col-md-6'f>><'row'<'col-sm-12'tr>><'row'<'col-sm-12 col-md-5'i><'col-sm-12 col-md-7'p>>",
renderer:"bootstrap"});a.extend(d.ext.classes,{sWrapper:"dataTables_wrapper dt-bootstrap5",sFilterInput:"form-control form-control-sm",sLengthSelect:"form-select form-select-sm",sProcessing:"dataTables_processing card",sPageButton:"paginate_button page-item"});d.ext.renderer.pageButton.bootstrap=function(f,l,A,B,m,t){var u=new d.Api(f),C=f.oClasses,n=f.oLanguage.oPaginate,D=f.oLanguage.oAria.paginate||{},h,k,v=0,y=function(q,w){var x,E=function(p){p.preventDefault();a(p.currentTarget).hasClass("disabled")||
u.page()==p.data.action||u.page(p.data.action).draw("page")};var r=0;for(x=w.length;r<x;r++){var g=w[r];if(Array.isArray(g))y(q,g);else{k=h="";switch(g){case "ellipsis":h="&#x2026;";k="disabled";break;case "first":h=n.sFirst;k=g+(0<m?"":" disabled");break;case "previous":h=n.sPrevious;k=g+(0<m?"":" disabled");break;case "next":h=n.sNext;k=g+(m<t-1?"":" disabled");break;case "last":h=n.sLast;k=g+(m<t-1?"":" disabled");break;default:h=g+1,k=m===g?"active":""}if(h){var F=a("<li>",{"class":C.sPageButton+
" "+k,id:0===A&&"string"===typeof g?f.sTableId+"_"+g:null}).append(a("<a>",{href:"#","aria-controls":f.sTableId,"aria-label":D[g],"data-dt-idx":v,tabindex:f.iTabIndex,"class":"page-link"}).html(h)).appendTo(q);f.oApi._fnBindAction(F,{action:g},E);v++}}}};try{var z=a(l).find(c.activeElement).data("dt-idx")}catch(q){}y(a(l).empty().html('<ul class="pagination"/>').children("ul"),B);z!==e&&a(l).find("[data-dt-idx="+z+"]").trigger("focus")};return d});

View file

@ -1,181 +0,0 @@
/*!
Copyright 2008-2020 SpryMedia Ltd.
This source file is free software, available under the following license:
MIT license - http://datatables.net/license
This source file is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the license files for details.
For details please refer to: http://www.datatables.net
DataTables 1.10.21
©2008-2020 SpryMedia Ltd - datatables.net/license
*/
var $jscomp=$jscomp||{};$jscomp.scope={};$jscomp.findInternal=function(f,y,w){f instanceof String&&(f=String(f));for(var n=f.length,H=0;H<n;H++){var L=f[H];if(y.call(w,L,H,f))return{i:H,v:L}}return{i:-1,v:void 0}};$jscomp.ASSUME_ES5=!1;$jscomp.ASSUME_NO_NATIVE_MAP=!1;$jscomp.ASSUME_NO_NATIVE_SET=!1;$jscomp.SIMPLE_FROUND_POLYFILL=!1;
$jscomp.defineProperty=$jscomp.ASSUME_ES5||"function"==typeof Object.defineProperties?Object.defineProperty:function(f,y,w){f!=Array.prototype&&f!=Object.prototype&&(f[y]=w.value)};$jscomp.getGlobal=function(f){f=["object"==typeof window&&window,"object"==typeof self&&self,"object"==typeof global&&global,f];for(var y=0;y<f.length;++y){var w=f[y];if(w&&w.Math==Math)return w}throw Error("Cannot find global object");};$jscomp.global=$jscomp.getGlobal(this);
$jscomp.polyfill=function(f,y,w,n){if(y){w=$jscomp.global;f=f.split(".");for(n=0;n<f.length-1;n++){var H=f[n];H in w||(w[H]={});w=w[H]}f=f[f.length-1];n=w[f];y=y(n);y!=n&&null!=y&&$jscomp.defineProperty(w,f,{configurable:!0,writable:!0,value:y})}};$jscomp.polyfill("Array.prototype.find",function(f){return f?f:function(f,w){return $jscomp.findInternal(this,f,w).v}},"es6","es3");
(function(f){"function"===typeof define&&define.amd?define(["jquery"],function(y){return f(y,window,document)}):"object"===typeof exports?module.exports=function(y,w){y||(y=window);w||(w="undefined"!==typeof window?require("jquery"):require("jquery")(y));return f(w,y,y.document)}:f(jQuery,window,document)})(function(f,y,w,n){function H(a){var b,c,d={};f.each(a,function(e,h){(b=e.match(/^([^A-Z]+?)([A-Z])/))&&-1!=="a aa ai ao as b fn i m o s ".indexOf(b[1]+" ")&&(c=e.replace(b[0],b[2].toLowerCase()),
d[c]=e,"o"===b[1]&&H(a[e]))});a._hungarianMap=d}function L(a,b,c){a._hungarianMap||H(a);var d;f.each(b,function(e,h){d=a._hungarianMap[e];d===n||!c&&b[d]!==n||("o"===d.charAt(0)?(b[d]||(b[d]={}),f.extend(!0,b[d],b[e]),L(a[d],b[d],c)):b[d]=b[e])})}function Fa(a){var b=q.defaults.oLanguage,c=b.sDecimal;c&&Ga(c);if(a){var d=a.sZeroRecords;!a.sEmptyTable&&d&&"No data available in table"===b.sEmptyTable&&M(a,a,"sZeroRecords","sEmptyTable");!a.sLoadingRecords&&d&&"Loading..."===b.sLoadingRecords&&M(a,a,
"sZeroRecords","sLoadingRecords");a.sInfoThousands&&(a.sThousands=a.sInfoThousands);(a=a.sDecimal)&&c!==a&&Ga(a)}}function ib(a){E(a,"ordering","bSort");E(a,"orderMulti","bSortMulti");E(a,"orderClasses","bSortClasses");E(a,"orderCellsTop","bSortCellsTop");E(a,"order","aaSorting");E(a,"orderFixed","aaSortingFixed");E(a,"paging","bPaginate");E(a,"pagingType","sPaginationType");E(a,"pageLength","iDisplayLength");E(a,"searching","bFilter");"boolean"===typeof a.sScrollX&&(a.sScrollX=a.sScrollX?"100%":
"");"boolean"===typeof a.scrollX&&(a.scrollX=a.scrollX?"100%":"");if(a=a.aoSearchCols)for(var b=0,c=a.length;b<c;b++)a[b]&&L(q.models.oSearch,a[b])}function jb(a){E(a,"orderable","bSortable");E(a,"orderData","aDataSort");E(a,"orderSequence","asSorting");E(a,"orderDataType","sortDataType");var b=a.aDataSort;"number"!==typeof b||f.isArray(b)||(a.aDataSort=[b])}function kb(a){if(!q.__browser){var b={};q.__browser=b;var c=f("<div/>").css({position:"fixed",top:0,left:-1*f(y).scrollLeft(),height:1,width:1,
overflow:"hidden"}).append(f("<div/>").css({position:"absolute",top:1,left:1,width:100,overflow:"scroll"}).append(f("<div/>").css({width:"100%",height:10}))).appendTo("body"),d=c.children(),e=d.children();b.barWidth=d[0].offsetWidth-d[0].clientWidth;b.bScrollOversize=100===e[0].offsetWidth&&100!==d[0].clientWidth;b.bScrollbarLeft=1!==Math.round(e.offset().left);b.bBounding=c[0].getBoundingClientRect().width?!0:!1;c.remove()}f.extend(a.oBrowser,q.__browser);a.oScroll.iBarWidth=q.__browser.barWidth}
function lb(a,b,c,d,e,h){var g=!1;if(c!==n){var k=c;g=!0}for(;d!==e;)a.hasOwnProperty(d)&&(k=g?b(k,a[d],d,a):a[d],g=!0,d+=h);return k}function Ha(a,b){var c=q.defaults.column,d=a.aoColumns.length;c=f.extend({},q.models.oColumn,c,{nTh:b?b:w.createElement("th"),sTitle:c.sTitle?c.sTitle:b?b.innerHTML:"",aDataSort:c.aDataSort?c.aDataSort:[d],mData:c.mData?c.mData:d,idx:d});a.aoColumns.push(c);c=a.aoPreSearchCols;c[d]=f.extend({},q.models.oSearch,c[d]);la(a,d,f(b).data())}function la(a,b,c){b=a.aoColumns[b];
var d=a.oClasses,e=f(b.nTh);if(!b.sWidthOrig){b.sWidthOrig=e.attr("width")||null;var h=(e.attr("style")||"").match(/width:\s*(\d+[pxem%]+)/);h&&(b.sWidthOrig=h[1])}c!==n&&null!==c&&(jb(c),L(q.defaults.column,c,!0),c.mDataProp===n||c.mData||(c.mData=c.mDataProp),c.sType&&(b._sManualType=c.sType),c.className&&!c.sClass&&(c.sClass=c.className),c.sClass&&e.addClass(c.sClass),f.extend(b,c),M(b,c,"sWidth","sWidthOrig"),c.iDataSort!==n&&(b.aDataSort=[c.iDataSort]),M(b,c,"aDataSort"));var g=b.mData,k=T(g),
l=b.mRender?T(b.mRender):null;c=function(a){return"string"===typeof a&&-1!==a.indexOf("@")};b._bAttrSrc=f.isPlainObject(g)&&(c(g.sort)||c(g.type)||c(g.filter));b._setter=null;b.fnGetData=function(a,b,c){var d=k(a,b,n,c);return l&&b?l(d,b,a,c):d};b.fnSetData=function(a,b,c){return Q(g)(a,b,c)};"number"!==typeof g&&(a._rowReadObject=!0);a.oFeatures.bSort||(b.bSortable=!1,e.addClass(d.sSortableNone));a=-1!==f.inArray("asc",b.asSorting);c=-1!==f.inArray("desc",b.asSorting);b.bSortable&&(a||c)?a&&!c?(b.sSortingClass=
d.sSortableAsc,b.sSortingClassJUI=d.sSortJUIAscAllowed):!a&&c?(b.sSortingClass=d.sSortableDesc,b.sSortingClassJUI=d.sSortJUIDescAllowed):(b.sSortingClass=d.sSortable,b.sSortingClassJUI=d.sSortJUI):(b.sSortingClass=d.sSortableNone,b.sSortingClassJUI="")}function Z(a){if(!1!==a.oFeatures.bAutoWidth){var b=a.aoColumns;Ia(a);for(var c=0,d=b.length;c<d;c++)b[c].nTh.style.width=b[c].sWidth}b=a.oScroll;""===b.sY&&""===b.sX||ma(a);A(a,null,"column-sizing",[a])}function aa(a,b){a=na(a,"bVisible");return"number"===
typeof a[b]?a[b]:null}function ba(a,b){a=na(a,"bVisible");b=f.inArray(b,a);return-1!==b?b:null}function V(a){var b=0;f.each(a.aoColumns,function(a,d){d.bVisible&&"none"!==f(d.nTh).css("display")&&b++});return b}function na(a,b){var c=[];f.map(a.aoColumns,function(a,e){a[b]&&c.push(e)});return c}function Ja(a){var b=a.aoColumns,c=a.aoData,d=q.ext.type.detect,e,h,g;var k=0;for(e=b.length;k<e;k++){var f=b[k];var m=[];if(!f.sType&&f._sManualType)f.sType=f._sManualType;else if(!f.sType){var p=0;for(h=
d.length;p<h;p++){var v=0;for(g=c.length;v<g;v++){m[v]===n&&(m[v]=F(a,v,k,"type"));var u=d[p](m[v],a);if(!u&&p!==d.length-1)break;if("html"===u)break}if(u){f.sType=u;break}}f.sType||(f.sType="string")}}}function mb(a,b,c,d){var e,h,g,k=a.aoColumns;if(b)for(e=b.length-1;0<=e;e--){var l=b[e];var m=l.targets!==n?l.targets:l.aTargets;f.isArray(m)||(m=[m]);var p=0;for(h=m.length;p<h;p++)if("number"===typeof m[p]&&0<=m[p]){for(;k.length<=m[p];)Ha(a);d(m[p],l)}else if("number"===typeof m[p]&&0>m[p])d(k.length+
m[p],l);else if("string"===typeof m[p]){var v=0;for(g=k.length;v<g;v++)("_all"==m[p]||f(k[v].nTh).hasClass(m[p]))&&d(v,l)}}if(c)for(e=0,a=c.length;e<a;e++)d(e,c[e])}function R(a,b,c,d){var e=a.aoData.length,h=f.extend(!0,{},q.models.oRow,{src:c?"dom":"data",idx:e});h._aData=b;a.aoData.push(h);for(var g=a.aoColumns,k=0,l=g.length;k<l;k++)g[k].sType=null;a.aiDisplayMaster.push(e);b=a.rowIdFn(b);b!==n&&(a.aIds[b]=h);!c&&a.oFeatures.bDeferRender||Ka(a,e,c,d);return e}function oa(a,b){var c;b instanceof
f||(b=f(b));return b.map(function(b,e){c=La(a,e);return R(a,c.data,e,c.cells)})}function F(a,b,c,d){var e=a.iDraw,h=a.aoColumns[c],g=a.aoData[b]._aData,k=h.sDefaultContent,f=h.fnGetData(g,d,{settings:a,row:b,col:c});if(f===n)return a.iDrawError!=e&&null===k&&(O(a,0,"Requested unknown parameter "+("function"==typeof h.mData?"{function}":"'"+h.mData+"'")+" for row "+b+", column "+c,4),a.iDrawError=e),k;if((f===g||null===f)&&null!==k&&d!==n)f=k;else if("function"===typeof f)return f.call(g);return null===
f&&"display"==d?"":f}function nb(a,b,c,d){a.aoColumns[c].fnSetData(a.aoData[b]._aData,d,{settings:a,row:b,col:c})}function Ma(a){return f.map(a.match(/(\\.|[^\.])+/g)||[""],function(a){return a.replace(/\\\./g,".")})}function T(a){if(f.isPlainObject(a)){var b={};f.each(a,function(a,c){c&&(b[a]=T(c))});return function(a,c,h,g){var d=b[c]||b._;return d!==n?d(a,c,h,g):a}}if(null===a)return function(a){return a};if("function"===typeof a)return function(b,c,h,g){return a(b,c,h,g)};if("string"!==typeof a||
-1===a.indexOf(".")&&-1===a.indexOf("[")&&-1===a.indexOf("("))return function(b,c){return b[a]};var c=function(a,b,h){if(""!==h){var d=Ma(h);for(var e=0,l=d.length;e<l;e++){h=d[e].match(ca);var m=d[e].match(W);if(h){d[e]=d[e].replace(ca,"");""!==d[e]&&(a=a[d[e]]);m=[];d.splice(0,e+1);d=d.join(".");if(f.isArray(a))for(e=0,l=a.length;e<l;e++)m.push(c(a[e],b,d));a=h[0].substring(1,h[0].length-1);a=""===a?m:m.join(a);break}else if(m){d[e]=d[e].replace(W,"");a=a[d[e]]();continue}if(null===a||a[d[e]]===
n)return n;a=a[d[e]]}}return a};return function(b,e){return c(b,e,a)}}function Q(a){if(f.isPlainObject(a))return Q(a._);if(null===a)return function(){};if("function"===typeof a)return function(b,d,e){a(b,"set",d,e)};if("string"!==typeof a||-1===a.indexOf(".")&&-1===a.indexOf("[")&&-1===a.indexOf("("))return function(b,d){b[a]=d};var b=function(a,d,e){e=Ma(e);var c=e[e.length-1];for(var g,k,l=0,m=e.length-1;l<m;l++){g=e[l].match(ca);k=e[l].match(W);if(g){e[l]=e[l].replace(ca,"");a[e[l]]=[];c=e.slice();
c.splice(0,l+1);g=c.join(".");if(f.isArray(d))for(k=0,m=d.length;k<m;k++)c={},b(c,d[k],g),a[e[l]].push(c);else a[e[l]]=d;return}k&&(e[l]=e[l].replace(W,""),a=a[e[l]](d));if(null===a[e[l]]||a[e[l]]===n)a[e[l]]={};a=a[e[l]]}if(c.match(W))a[c.replace(W,"")](d);else a[c.replace(ca,"")]=d};return function(c,d){return b(c,d,a)}}function Na(a){return K(a.aoData,"_aData")}function pa(a){a.aoData.length=0;a.aiDisplayMaster.length=0;a.aiDisplay.length=0;a.aIds={}}function qa(a,b,c){for(var d=-1,e=0,h=a.length;e<
h;e++)a[e]==b?d=e:a[e]>b&&a[e]--; -1!=d&&c===n&&a.splice(d,1)}function da(a,b,c,d){var e=a.aoData[b],h,g=function(c,d){for(;c.childNodes.length;)c.removeChild(c.firstChild);c.innerHTML=F(a,b,d,"display")};if("dom"!==c&&(c&&"auto"!==c||"dom"!==e.src)){var k=e.anCells;if(k)if(d!==n)g(k[d],d);else for(c=0,h=k.length;c<h;c++)g(k[c],c)}else e._aData=La(a,e,d,d===n?n:e._aData).data;e._aSortData=null;e._aFilterData=null;g=a.aoColumns;if(d!==n)g[d].sType=null;else{c=0;for(h=g.length;c<h;c++)g[c].sType=null;
Oa(a,e)}}function La(a,b,c,d){var e=[],h=b.firstChild,g,k=0,l,m=a.aoColumns,p=a._rowReadObject;d=d!==n?d:p?{}:[];var v=function(a,b){if("string"===typeof a){var c=a.indexOf("@");-1!==c&&(c=a.substring(c+1),Q(a)(d,b.getAttribute(c)))}},u=function(a){if(c===n||c===k)g=m[k],l=f.trim(a.innerHTML),g&&g._bAttrSrc?(Q(g.mData._)(d,l),v(g.mData.sort,a),v(g.mData.type,a),v(g.mData.filter,a)):p?(g._setter||(g._setter=Q(g.mData)),g._setter(d,l)):d[k]=l;k++};if(h)for(;h;){var q=h.nodeName.toUpperCase();if("TD"==
q||"TH"==q)u(h),e.push(h);h=h.nextSibling}else for(e=b.anCells,h=0,q=e.length;h<q;h++)u(e[h]);(b=b.firstChild?b:b.nTr)&&(b=b.getAttribute("id"))&&Q(a.rowId)(d,b);return{data:d,cells:e}}function Ka(a,b,c,d){var e=a.aoData[b],h=e._aData,g=[],k,l;if(null===e.nTr){var m=c||w.createElement("tr");e.nTr=m;e.anCells=g;m._DT_RowIndex=b;Oa(a,e);var p=0;for(k=a.aoColumns.length;p<k;p++){var v=a.aoColumns[p];var n=(l=c?!1:!0)?w.createElement(v.sCellType):d[p];n._DT_CellIndex={row:b,column:p};g.push(n);if(l||
!(c&&!v.mRender&&v.mData===p||f.isPlainObject(v.mData)&&v.mData._===p+".display"))n.innerHTML=F(a,b,p,"display");v.sClass&&(n.className+=" "+v.sClass);v.bVisible&&!c?m.appendChild(n):!v.bVisible&&c&&n.parentNode.removeChild(n);v.fnCreatedCell&&v.fnCreatedCell.call(a.oInstance,n,F(a,b,p),h,b,p)}A(a,"aoRowCreatedCallback",null,[m,h,b,g])}e.nTr.setAttribute("role","row")}function Oa(a,b){var c=b.nTr,d=b._aData;if(c){if(a=a.rowIdFn(d))c.id=a;d.DT_RowClass&&(a=d.DT_RowClass.split(" "),b.__rowc=b.__rowc?
sa(b.__rowc.concat(a)):a,f(c).removeClass(b.__rowc.join(" ")).addClass(d.DT_RowClass));d.DT_RowAttr&&f(c).attr(d.DT_RowAttr);d.DT_RowData&&f(c).data(d.DT_RowData)}}function ob(a){var b,c,d=a.nTHead,e=a.nTFoot,h=0===f("th, td",d).length,g=a.oClasses,k=a.aoColumns;h&&(c=f("<tr/>").appendTo(d));var l=0;for(b=k.length;l<b;l++){var m=k[l];var p=f(m.nTh).addClass(m.sClass);h&&p.appendTo(c);a.oFeatures.bSort&&(p.addClass(m.sSortingClass),!1!==m.bSortable&&(p.attr("tabindex",a.iTabIndex).attr("aria-controls",
a.sTableId),Pa(a,m.nTh,l)));m.sTitle!=p[0].innerHTML&&p.html(m.sTitle);Qa(a,"header")(a,p,m,g)}h&&ea(a.aoHeader,d);f(d).find(">tr").attr("role","row");f(d).find(">tr>th, >tr>td").addClass(g.sHeaderTH);f(e).find(">tr>th, >tr>td").addClass(g.sFooterTH);if(null!==e)for(a=a.aoFooter[0],l=0,b=a.length;l<b;l++)m=k[l],m.nTf=a[l].cell,m.sClass&&f(m.nTf).addClass(m.sClass)}function fa(a,b,c){var d,e,h=[],g=[],k=a.aoColumns.length;if(b){c===n&&(c=!1);var l=0;for(d=b.length;l<d;l++){h[l]=b[l].slice();h[l].nTr=
b[l].nTr;for(e=k-1;0<=e;e--)a.aoColumns[e].bVisible||c||h[l].splice(e,1);g.push([])}l=0;for(d=h.length;l<d;l++){if(a=h[l].nTr)for(;e=a.firstChild;)a.removeChild(e);e=0;for(b=h[l].length;e<b;e++){var m=k=1;if(g[l][e]===n){a.appendChild(h[l][e].cell);for(g[l][e]=1;h[l+k]!==n&&h[l][e].cell==h[l+k][e].cell;)g[l+k][e]=1,k++;for(;h[l][e+m]!==n&&h[l][e].cell==h[l][e+m].cell;){for(c=0;c<k;c++)g[l+c][e+m]=1;m++}f(h[l][e].cell).attr("rowspan",k).attr("colspan",m)}}}}}function S(a){var b=A(a,"aoPreDrawCallback",
"preDraw",[a]);if(-1!==f.inArray(!1,b))J(a,!1);else{b=[];var c=0,d=a.asStripeClasses,e=d.length,h=a.oLanguage,g=a.iInitDisplayStart,k="ssp"==I(a),l=a.aiDisplay;a.bDrawing=!0;g!==n&&-1!==g&&(a._iDisplayStart=k?g:g>=a.fnRecordsDisplay()?0:g,a.iInitDisplayStart=-1);g=a._iDisplayStart;var m=a.fnDisplayEnd();if(a.bDeferLoading)a.bDeferLoading=!1,a.iDraw++,J(a,!1);else if(!k)a.iDraw++;else if(!a.bDestroying&&!pb(a))return;if(0!==l.length)for(h=k?a.aoData.length:m,k=k?0:g;k<h;k++){var p=l[k],v=a.aoData[p];
null===v.nTr&&Ka(a,p);var u=v.nTr;if(0!==e){var q=d[c%e];v._sRowStripe!=q&&(f(u).removeClass(v._sRowStripe).addClass(q),v._sRowStripe=q)}A(a,"aoRowCallback",null,[u,v._aData,c,k,p]);b.push(u);c++}else c=h.sZeroRecords,1==a.iDraw&&"ajax"==I(a)?c=h.sLoadingRecords:h.sEmptyTable&&0===a.fnRecordsTotal()&&(c=h.sEmptyTable),b[0]=f("<tr/>",{"class":e?d[0]:""}).append(f("<td />",{valign:"top",colSpan:V(a),"class":a.oClasses.sRowEmpty}).html(c))[0];A(a,"aoHeaderCallback","header",[f(a.nTHead).children("tr")[0],
Na(a),g,m,l]);A(a,"aoFooterCallback","footer",[f(a.nTFoot).children("tr")[0],Na(a),g,m,l]);d=f(a.nTBody);d.children().detach();d.append(f(b));A(a,"aoDrawCallback","draw",[a]);a.bSorted=!1;a.bFiltered=!1;a.bDrawing=!1}}function U(a,b){var c=a.oFeatures,d=c.bFilter;c.bSort&&qb(a);d?ha(a,a.oPreviousSearch):a.aiDisplay=a.aiDisplayMaster.slice();!0!==b&&(a._iDisplayStart=0);a._drawHold=b;S(a);a._drawHold=!1}function rb(a){var b=a.oClasses,c=f(a.nTable);c=f("<div/>").insertBefore(c);var d=a.oFeatures,e=
f("<div/>",{id:a.sTableId+"_wrapper","class":b.sWrapper+(a.nTFoot?"":" "+b.sNoFooter)});a.nHolding=c[0];a.nTableWrapper=e[0];a.nTableReinsertBefore=a.nTable.nextSibling;for(var h=a.sDom.split(""),g,k,l,m,p,n,u=0;u<h.length;u++){g=null;k=h[u];if("<"==k){l=f("<div/>")[0];m=h[u+1];if("'"==m||'"'==m){p="";for(n=2;h[u+n]!=m;)p+=h[u+n],n++;"H"==p?p=b.sJUIHeader:"F"==p&&(p=b.sJUIFooter);-1!=p.indexOf(".")?(m=p.split("."),l.id=m[0].substr(1,m[0].length-1),l.className=m[1]):"#"==p.charAt(0)?l.id=p.substr(1,
p.length-1):l.className=p;u+=n}e.append(l);e=f(l)}else if(">"==k)e=e.parent();else if("l"==k&&d.bPaginate&&d.bLengthChange)g=sb(a);else if("f"==k&&d.bFilter)g=tb(a);else if("r"==k&&d.bProcessing)g=ub(a);else if("t"==k)g=vb(a);else if("i"==k&&d.bInfo)g=wb(a);else if("p"==k&&d.bPaginate)g=xb(a);else if(0!==q.ext.feature.length)for(l=q.ext.feature,n=0,m=l.length;n<m;n++)if(k==l[n].cFeature){g=l[n].fnInit(a);break}g&&(l=a.aanFeatures,l[k]||(l[k]=[]),l[k].push(g),e.append(g))}c.replaceWith(e);a.nHolding=
null}function ea(a,b){b=f(b).children("tr");var c,d,e;a.splice(0,a.length);var h=0;for(e=b.length;h<e;h++)a.push([]);h=0;for(e=b.length;h<e;h++){var g=b[h];for(c=g.firstChild;c;){if("TD"==c.nodeName.toUpperCase()||"TH"==c.nodeName.toUpperCase()){var k=1*c.getAttribute("colspan");var l=1*c.getAttribute("rowspan");k=k&&0!==k&&1!==k?k:1;l=l&&0!==l&&1!==l?l:1;var m=0;for(d=a[h];d[m];)m++;var p=m;var n=1===k?!0:!1;for(d=0;d<k;d++)for(m=0;m<l;m++)a[h+m][p+d]={cell:c,unique:n},a[h+m].nTr=g}c=c.nextSibling}}}
function ta(a,b,c){var d=[];c||(c=a.aoHeader,b&&(c=[],ea(c,b)));b=0;for(var e=c.length;b<e;b++)for(var h=0,g=c[b].length;h<g;h++)!c[b][h].unique||d[h]&&a.bSortCellsTop||(d[h]=c[b][h].cell);return d}function ua(a,b,c){A(a,"aoServerParams","serverParams",[b]);if(b&&f.isArray(b)){var d={},e=/(.*?)\[\]$/;f.each(b,function(a,b){(a=b.name.match(e))?(a=a[0],d[a]||(d[a]=[]),d[a].push(b.value)):d[b.name]=b.value});b=d}var h=a.ajax,g=a.oInstance,k=function(b){A(a,null,"xhr",[a,b,a.jqXHR]);c(b)};if(f.isPlainObject(h)&&
h.data){var l=h.data;var m="function"===typeof l?l(b,a):l;b="function"===typeof l&&m?m:f.extend(!0,b,m);delete h.data}m={data:b,success:function(b){var c=b.error||b.sError;c&&O(a,0,c);a.json=b;k(b)},dataType:"json",cache:!1,type:a.sServerMethod,error:function(b,c,d){d=A(a,null,"xhr",[a,null,a.jqXHR]);-1===f.inArray(!0,d)&&("parsererror"==c?O(a,0,"Invalid JSON response",1):4===b.readyState&&O(a,0,"Ajax error",7));J(a,!1)}};a.oAjaxData=b;A(a,null,"preXhr",[a,b]);a.fnServerData?a.fnServerData.call(g,
a.sAjaxSource,f.map(b,function(a,b){return{name:b,value:a}}),k,a):a.sAjaxSource||"string"===typeof h?a.jqXHR=f.ajax(f.extend(m,{url:h||a.sAjaxSource})):"function"===typeof h?a.jqXHR=h.call(g,b,k,a):(a.jqXHR=f.ajax(f.extend(m,h)),h.data=l)}function pb(a){return a.bAjaxDataGet?(a.iDraw++,J(a,!0),ua(a,yb(a),function(b){zb(a,b)}),!1):!0}function yb(a){var b=a.aoColumns,c=b.length,d=a.oFeatures,e=a.oPreviousSearch,h=a.aoPreSearchCols,g=[],k=X(a);var l=a._iDisplayStart;var m=!1!==d.bPaginate?a._iDisplayLength:
-1;var p=function(a,b){g.push({name:a,value:b})};p("sEcho",a.iDraw);p("iColumns",c);p("sColumns",K(b,"sName").join(","));p("iDisplayStart",l);p("iDisplayLength",m);var n={draw:a.iDraw,columns:[],order:[],start:l,length:m,search:{value:e.sSearch,regex:e.bRegex}};for(l=0;l<c;l++){var u=b[l];var ra=h[l];m="function"==typeof u.mData?"function":u.mData;n.columns.push({data:m,name:u.sName,searchable:u.bSearchable,orderable:u.bSortable,search:{value:ra.sSearch,regex:ra.bRegex}});p("mDataProp_"+l,m);d.bFilter&&
(p("sSearch_"+l,ra.sSearch),p("bRegex_"+l,ra.bRegex),p("bSearchable_"+l,u.bSearchable));d.bSort&&p("bSortable_"+l,u.bSortable)}d.bFilter&&(p("sSearch",e.sSearch),p("bRegex",e.bRegex));d.bSort&&(f.each(k,function(a,b){n.order.push({column:b.col,dir:b.dir});p("iSortCol_"+a,b.col);p("sSortDir_"+a,b.dir)}),p("iSortingCols",k.length));b=q.ext.legacy.ajax;return null===b?a.sAjaxSource?g:n:b?g:n}function zb(a,b){var c=function(a,c){return b[a]!==n?b[a]:b[c]},d=va(a,b),e=c("sEcho","draw"),h=c("iTotalRecords",
"recordsTotal");c=c("iTotalDisplayRecords","recordsFiltered");if(e!==n){if(1*e<a.iDraw)return;a.iDraw=1*e}pa(a);a._iRecordsTotal=parseInt(h,10);a._iRecordsDisplay=parseInt(c,10);e=0;for(h=d.length;e<h;e++)R(a,d[e]);a.aiDisplay=a.aiDisplayMaster.slice();a.bAjaxDataGet=!1;S(a);a._bInitComplete||wa(a,b);a.bAjaxDataGet=!0;J(a,!1)}function va(a,b){a=f.isPlainObject(a.ajax)&&a.ajax.dataSrc!==n?a.ajax.dataSrc:a.sAjaxDataProp;return"data"===a?b.aaData||b[a]:""!==a?T(a)(b):b}function tb(a){var b=a.oClasses,
c=a.sTableId,d=a.oLanguage,e=a.oPreviousSearch,h=a.aanFeatures,g='<input type="search" class="'+b.sFilterInput+'"/>',k=d.sSearch;k=k.match(/_INPUT_/)?k.replace("_INPUT_",g):k+g;b=f("<div/>",{id:h.f?null:c+"_filter","class":b.sFilter}).append(f("<label/>").append(k));var l=function(){var b=this.value?this.value:"";b!=e.sSearch&&(ha(a,{sSearch:b,bRegex:e.bRegex,bSmart:e.bSmart,bCaseInsensitive:e.bCaseInsensitive}),a._iDisplayStart=0,S(a))};h=null!==a.searchDelay?a.searchDelay:"ssp"===I(a)?400:0;var m=
f("input",b).val(e.sSearch).attr("placeholder",d.sSearchPlaceholder).on("keyup.DT search.DT input.DT paste.DT cut.DT",h?Ra(l,h):l).on("mouseup",function(a){setTimeout(function(){l.call(m[0])},10)}).on("keypress.DT",function(a){if(13==a.keyCode)return!1}).attr("aria-controls",c);f(a.nTable).on("search.dt.DT",function(b,c){if(a===c)try{m[0]!==w.activeElement&&m.val(e.sSearch)}catch(u){}});return b[0]}function ha(a,b,c){var d=a.oPreviousSearch,e=a.aoPreSearchCols,h=function(a){d.sSearch=a.sSearch;d.bRegex=
a.bRegex;d.bSmart=a.bSmart;d.bCaseInsensitive=a.bCaseInsensitive},g=function(a){return a.bEscapeRegex!==n?!a.bEscapeRegex:a.bRegex};Ja(a);if("ssp"!=I(a)){Ab(a,b.sSearch,c,g(b),b.bSmart,b.bCaseInsensitive);h(b);for(b=0;b<e.length;b++)Bb(a,e[b].sSearch,b,g(e[b]),e[b].bSmart,e[b].bCaseInsensitive);Cb(a)}else h(b);a.bFiltered=!0;A(a,null,"search",[a])}function Cb(a){for(var b=q.ext.search,c=a.aiDisplay,d,e,h=0,g=b.length;h<g;h++){for(var k=[],l=0,m=c.length;l<m;l++)e=c[l],d=a.aoData[e],b[h](a,d._aFilterData,
e,d._aData,l)&&k.push(e);c.length=0;f.merge(c,k)}}function Bb(a,b,c,d,e,h){if(""!==b){var g=[],k=a.aiDisplay;d=Sa(b,d,e,h);for(e=0;e<k.length;e++)b=a.aoData[k[e]]._aFilterData[c],d.test(b)&&g.push(k[e]);a.aiDisplay=g}}function Ab(a,b,c,d,e,h){e=Sa(b,d,e,h);var g=a.oPreviousSearch.sSearch,k=a.aiDisplayMaster;h=[];0!==q.ext.search.length&&(c=!0);var f=Db(a);if(0>=b.length)a.aiDisplay=k.slice();else{if(f||c||d||g.length>b.length||0!==b.indexOf(g)||a.bSorted)a.aiDisplay=k.slice();b=a.aiDisplay;for(c=
0;c<b.length;c++)e.test(a.aoData[b[c]]._sFilterRow)&&h.push(b[c]);a.aiDisplay=h}}function Sa(a,b,c,d){a=b?a:Ta(a);c&&(a="^(?=.*?"+f.map(a.match(/"[^"]+"|[^ ]+/g)||[""],function(a){if('"'===a.charAt(0)){var b=a.match(/^"(.*)"$/);a=b?b[1]:a}return a.replace('"',"")}).join(")(?=.*?")+").*$");return new RegExp(a,d?"i":"")}function Db(a){var b=a.aoColumns,c,d,e=q.ext.type.search;var h=!1;var g=0;for(c=a.aoData.length;g<c;g++){var k=a.aoData[g];if(!k._aFilterData){var f=[];var m=0;for(d=b.length;m<d;m++){h=
b[m];if(h.bSearchable){var p=F(a,g,m,"filter");e[h.sType]&&(p=e[h.sType](p));null===p&&(p="");"string"!==typeof p&&p.toString&&(p=p.toString())}else p="";p.indexOf&&-1!==p.indexOf("&")&&(xa.innerHTML=p,p=$b?xa.textContent:xa.innerText);p.replace&&(p=p.replace(/[\r\n\u2028]/g,""));f.push(p)}k._aFilterData=f;k._sFilterRow=f.join(" ");h=!0}}return h}function Eb(a){return{search:a.sSearch,smart:a.bSmart,regex:a.bRegex,caseInsensitive:a.bCaseInsensitive}}function Fb(a){return{sSearch:a.search,bSmart:a.smart,
bRegex:a.regex,bCaseInsensitive:a.caseInsensitive}}function wb(a){var b=a.sTableId,c=a.aanFeatures.i,d=f("<div/>",{"class":a.oClasses.sInfo,id:c?null:b+"_info"});c||(a.aoDrawCallback.push({fn:Gb,sName:"information"}),d.attr("role","status").attr("aria-live","polite"),f(a.nTable).attr("aria-describedby",b+"_info"));return d[0]}function Gb(a){var b=a.aanFeatures.i;if(0!==b.length){var c=a.oLanguage,d=a._iDisplayStart+1,e=a.fnDisplayEnd(),h=a.fnRecordsTotal(),g=a.fnRecordsDisplay(),k=g?c.sInfo:c.sInfoEmpty;
g!==h&&(k+=" "+c.sInfoFiltered);k+=c.sInfoPostFix;k=Hb(a,k);c=c.fnInfoCallback;null!==c&&(k=c.call(a.oInstance,a,d,e,h,g,k));f(b).html(k)}}function Hb(a,b){var c=a.fnFormatNumber,d=a._iDisplayStart+1,e=a._iDisplayLength,h=a.fnRecordsDisplay(),g=-1===e;return b.replace(/_START_/g,c.call(a,d)).replace(/_END_/g,c.call(a,a.fnDisplayEnd())).replace(/_MAX_/g,c.call(a,a.fnRecordsTotal())).replace(/_TOTAL_/g,c.call(a,h)).replace(/_PAGE_/g,c.call(a,g?1:Math.ceil(d/e))).replace(/_PAGES_/g,c.call(a,g?1:Math.ceil(h/
e)))}function ia(a){var b=a.iInitDisplayStart,c=a.aoColumns;var d=a.oFeatures;var e=a.bDeferLoading;if(a.bInitialised){rb(a);ob(a);fa(a,a.aoHeader);fa(a,a.aoFooter);J(a,!0);d.bAutoWidth&&Ia(a);var h=0;for(d=c.length;h<d;h++){var g=c[h];g.sWidth&&(g.nTh.style.width=B(g.sWidth))}A(a,null,"preInit",[a]);U(a);c=I(a);if("ssp"!=c||e)"ajax"==c?ua(a,[],function(c){var d=va(a,c);for(h=0;h<d.length;h++)R(a,d[h]);a.iInitDisplayStart=b;U(a);J(a,!1);wa(a,c)},a):(J(a,!1),wa(a))}else setTimeout(function(){ia(a)},
200)}function wa(a,b){a._bInitComplete=!0;(b||a.oInit.aaData)&&Z(a);A(a,null,"plugin-init",[a,b]);A(a,"aoInitComplete","init",[a,b])}function Ua(a,b){b=parseInt(b,10);a._iDisplayLength=b;Va(a);A(a,null,"length",[a,b])}function sb(a){var b=a.oClasses,c=a.sTableId,d=a.aLengthMenu,e=f.isArray(d[0]),h=e?d[0]:d;d=e?d[1]:d;e=f("<select/>",{name:c+"_length","aria-controls":c,"class":b.sLengthSelect});for(var g=0,k=h.length;g<k;g++)e[0][g]=new Option("number"===typeof d[g]?a.fnFormatNumber(d[g]):d[g],h[g]);
var l=f("<div><label/></div>").addClass(b.sLength);a.aanFeatures.l||(l[0].id=c+"_length");l.children().append(a.oLanguage.sLengthMenu.replace("_MENU_",e[0].outerHTML));f("select",l).val(a._iDisplayLength).on("change.DT",function(b){Ua(a,f(this).val());S(a)});f(a.nTable).on("length.dt.DT",function(b,c,d){a===c&&f("select",l).val(d)});return l[0]}function xb(a){var b=a.sPaginationType,c=q.ext.pager[b],d="function"===typeof c,e=function(a){S(a)};b=f("<div/>").addClass(a.oClasses.sPaging+b)[0];var h=
a.aanFeatures;d||c.fnInit(a,b,e);h.p||(b.id=a.sTableId+"_paginate",a.aoDrawCallback.push({fn:function(a){if(d){var b=a._iDisplayStart,g=a._iDisplayLength,f=a.fnRecordsDisplay(),p=-1===g;b=p?0:Math.ceil(b/g);g=p?1:Math.ceil(f/g);f=c(b,g);var n;p=0;for(n=h.p.length;p<n;p++)Qa(a,"pageButton")(a,h.p[p],p,f,b,g)}else c.fnUpdate(a,e)},sName:"pagination"}));return b}function Wa(a,b,c){var d=a._iDisplayStart,e=a._iDisplayLength,h=a.fnRecordsDisplay();0===h||-1===e?d=0:"number"===typeof b?(d=b*e,d>h&&(d=0)):
"first"==b?d=0:"previous"==b?(d=0<=e?d-e:0,0>d&&(d=0)):"next"==b?d+e<h&&(d+=e):"last"==b?d=Math.floor((h-1)/e)*e:O(a,0,"Unknown paging action: "+b,5);b=a._iDisplayStart!==d;a._iDisplayStart=d;b&&(A(a,null,"page",[a]),c&&S(a));return b}function ub(a){return f("<div/>",{id:a.aanFeatures.r?null:a.sTableId+"_processing","class":a.oClasses.sProcessing}).html(a.oLanguage.sProcessing).insertBefore(a.nTable)[0]}function J(a,b){a.oFeatures.bProcessing&&f(a.aanFeatures.r).css("display",b?"block":"none");A(a,
null,"processing",[a,b])}function vb(a){var b=f(a.nTable);b.attr("role","grid");var c=a.oScroll;if(""===c.sX&&""===c.sY)return a.nTable;var d=c.sX,e=c.sY,h=a.oClasses,g=b.children("caption"),k=g.length?g[0]._captionSide:null,l=f(b[0].cloneNode(!1)),m=f(b[0].cloneNode(!1)),p=b.children("tfoot");p.length||(p=null);l=f("<div/>",{"class":h.sScrollWrapper}).append(f("<div/>",{"class":h.sScrollHead}).css({overflow:"hidden",position:"relative",border:0,width:d?d?B(d):null:"100%"}).append(f("<div/>",{"class":h.sScrollHeadInner}).css({"box-sizing":"content-box",
width:c.sXInner||"100%"}).append(l.removeAttr("id").css("margin-left",0).append("top"===k?g:null).append(b.children("thead"))))).append(f("<div/>",{"class":h.sScrollBody}).css({position:"relative",overflow:"auto",width:d?B(d):null}).append(b));p&&l.append(f("<div/>",{"class":h.sScrollFoot}).css({overflow:"hidden",border:0,width:d?d?B(d):null:"100%"}).append(f("<div/>",{"class":h.sScrollFootInner}).append(m.removeAttr("id").css("margin-left",0).append("bottom"===k?g:null).append(b.children("tfoot")))));
b=l.children();var n=b[0];h=b[1];var u=p?b[2]:null;if(d)f(h).on("scroll.DT",function(a){a=this.scrollLeft;n.scrollLeft=a;p&&(u.scrollLeft=a)});f(h).css("max-height",e);c.bCollapse||f(h).css("height",e);a.nScrollHead=n;a.nScrollBody=h;a.nScrollFoot=u;a.aoDrawCallback.push({fn:ma,sName:"scrolling"});return l[0]}function ma(a){var b=a.oScroll,c=b.sX,d=b.sXInner,e=b.sY;b=b.iBarWidth;var h=f(a.nScrollHead),g=h[0].style,k=h.children("div"),l=k[0].style,m=k.children("table");k=a.nScrollBody;var p=f(k),v=
k.style,u=f(a.nScrollFoot).children("div"),q=u.children("table"),t=f(a.nTHead),r=f(a.nTable),x=r[0],ya=x.style,w=a.nTFoot?f(a.nTFoot):null,y=a.oBrowser,A=y.bScrollOversize,ac=K(a.aoColumns,"nTh"),Xa=[],z=[],C=[],G=[],H,I=function(a){a=a.style;a.paddingTop="0";a.paddingBottom="0";a.borderTopWidth="0";a.borderBottomWidth="0";a.height=0};var D=k.scrollHeight>k.clientHeight;if(a.scrollBarVis!==D&&a.scrollBarVis!==n)a.scrollBarVis=D,Z(a);else{a.scrollBarVis=D;r.children("thead, tfoot").remove();if(w){var E=
w.clone().prependTo(r);var F=w.find("tr");E=E.find("tr")}var J=t.clone().prependTo(r);t=t.find("tr");D=J.find("tr");J.find("th, td").removeAttr("tabindex");c||(v.width="100%",h[0].style.width="100%");f.each(ta(a,J),function(b,c){H=aa(a,b);c.style.width=a.aoColumns[H].sWidth});w&&N(function(a){a.style.width=""},E);h=r.outerWidth();""===c?(ya.width="100%",A&&(r.find("tbody").height()>k.offsetHeight||"scroll"==p.css("overflow-y"))&&(ya.width=B(r.outerWidth()-b)),h=r.outerWidth()):""!==d&&(ya.width=B(d),
h=r.outerWidth());N(I,D);N(function(a){C.push(a.innerHTML);Xa.push(B(f(a).css("width")))},D);N(function(a,b){-1!==f.inArray(a,ac)&&(a.style.width=Xa[b])},t);f(D).height(0);w&&(N(I,E),N(function(a){G.push(a.innerHTML);z.push(B(f(a).css("width")))},E),N(function(a,b){a.style.width=z[b]},F),f(E).height(0));N(function(a,b){a.innerHTML='<div class="dataTables_sizing">'+C[b]+"</div>";a.childNodes[0].style.height="0";a.childNodes[0].style.overflow="hidden";a.style.width=Xa[b]},D);w&&N(function(a,b){a.innerHTML=
'<div class="dataTables_sizing">'+G[b]+"</div>";a.childNodes[0].style.height="0";a.childNodes[0].style.overflow="hidden";a.style.width=z[b]},E);r.outerWidth()<h?(F=k.scrollHeight>k.offsetHeight||"scroll"==p.css("overflow-y")?h+b:h,A&&(k.scrollHeight>k.offsetHeight||"scroll"==p.css("overflow-y"))&&(ya.width=B(F-b)),""!==c&&""===d||O(a,1,"Possible column misalignment",6)):F="100%";v.width=B(F);g.width=B(F);w&&(a.nScrollFoot.style.width=B(F));!e&&A&&(v.height=B(x.offsetHeight+b));c=r.outerWidth();m[0].style.width=
B(c);l.width=B(c);d=r.height()>k.clientHeight||"scroll"==p.css("overflow-y");e="padding"+(y.bScrollbarLeft?"Left":"Right");l[e]=d?b+"px":"0px";w&&(q[0].style.width=B(c),u[0].style.width=B(c),u[0].style[e]=d?b+"px":"0px");r.children("colgroup").insertBefore(r.children("thead"));p.trigger("scroll");!a.bSorted&&!a.bFiltered||a._drawHold||(k.scrollTop=0)}}function N(a,b,c){for(var d=0,e=0,h=b.length,g,k;e<h;){g=b[e].firstChild;for(k=c?c[e].firstChild:null;g;)1===g.nodeType&&(c?a(g,k,d):a(g,d),d++),g=
g.nextSibling,k=c?k.nextSibling:null;e++}}function Ia(a){var b=a.nTable,c=a.aoColumns,d=a.oScroll,e=d.sY,h=d.sX,g=d.sXInner,k=c.length,l=na(a,"bVisible"),m=f("th",a.nTHead),p=b.getAttribute("width"),n=b.parentNode,u=!1,q,t=a.oBrowser;d=t.bScrollOversize;(q=b.style.width)&&-1!==q.indexOf("%")&&(p=q);for(q=0;q<l.length;q++){var r=c[l[q]];null!==r.sWidth&&(r.sWidth=Ib(r.sWidthOrig,n),u=!0)}if(d||!u&&!h&&!e&&k==V(a)&&k==m.length)for(q=0;q<k;q++)l=aa(a,q),null!==l&&(c[l].sWidth=B(m.eq(q).width()));else{k=
f(b).clone().css("visibility","hidden").removeAttr("id");k.find("tbody tr").remove();var w=f("<tr/>").appendTo(k.find("tbody"));k.find("thead, tfoot").remove();k.append(f(a.nTHead).clone()).append(f(a.nTFoot).clone());k.find("tfoot th, tfoot td").css("width","");m=ta(a,k.find("thead")[0]);for(q=0;q<l.length;q++)r=c[l[q]],m[q].style.width=null!==r.sWidthOrig&&""!==r.sWidthOrig?B(r.sWidthOrig):"",r.sWidthOrig&&h&&f(m[q]).append(f("<div/>").css({width:r.sWidthOrig,margin:0,padding:0,border:0,height:1}));
if(a.aoData.length)for(q=0;q<l.length;q++)u=l[q],r=c[u],f(Jb(a,u)).clone(!1).append(r.sContentPadding).appendTo(w);f("[name]",k).removeAttr("name");r=f("<div/>").css(h||e?{position:"absolute",top:0,left:0,height:1,right:0,overflow:"hidden"}:{}).append(k).appendTo(n);h&&g?k.width(g):h?(k.css("width","auto"),k.removeAttr("width"),k.width()<n.clientWidth&&p&&k.width(n.clientWidth)):e?k.width(n.clientWidth):p&&k.width(p);for(q=e=0;q<l.length;q++)n=f(m[q]),g=n.outerWidth()-n.width(),n=t.bBounding?Math.ceil(m[q].getBoundingClientRect().width):
n.outerWidth(),e+=n,c[l[q]].sWidth=B(n-g);b.style.width=B(e);r.remove()}p&&(b.style.width=B(p));!p&&!h||a._reszEvt||(b=function(){f(y).on("resize.DT-"+a.sInstance,Ra(function(){Z(a)}))},d?setTimeout(b,1E3):b(),a._reszEvt=!0)}function Ib(a,b){if(!a)return 0;a=f("<div/>").css("width",B(a)).appendTo(b||w.body);b=a[0].offsetWidth;a.remove();return b}function Jb(a,b){var c=Kb(a,b);if(0>c)return null;var d=a.aoData[c];return d.nTr?d.anCells[b]:f("<td/>").html(F(a,c,b,"display"))[0]}function Kb(a,b){for(var c,
d=-1,e=-1,h=0,g=a.aoData.length;h<g;h++)c=F(a,h,b,"display")+"",c=c.replace(bc,""),c=c.replace(/&nbsp;/g," "),c.length>d&&(d=c.length,e=h);return e}function B(a){return null===a?"0px":"number"==typeof a?0>a?"0px":a+"px":a.match(/\d$/)?a+"px":a}function X(a){var b=[],c=a.aoColumns;var d=a.aaSortingFixed;var e=f.isPlainObject(d);var h=[];var g=function(a){a.length&&!f.isArray(a[0])?h.push(a):f.merge(h,a)};f.isArray(d)&&g(d);e&&d.pre&&g(d.pre);g(a.aaSorting);e&&d.post&&g(d.post);for(a=0;a<h.length;a++){var k=
h[a][0];g=c[k].aDataSort;d=0;for(e=g.length;d<e;d++){var l=g[d];var m=c[l].sType||"string";h[a]._idx===n&&(h[a]._idx=f.inArray(h[a][1],c[l].asSorting));b.push({src:k,col:l,dir:h[a][1],index:h[a]._idx,type:m,formatter:q.ext.type.order[m+"-pre"]})}}return b}function qb(a){var b,c=[],d=q.ext.type.order,e=a.aoData,h=0,g=a.aiDisplayMaster;Ja(a);var k=X(a);var f=0;for(b=k.length;f<b;f++){var m=k[f];m.formatter&&h++;Lb(a,m.col)}if("ssp"!=I(a)&&0!==k.length){f=0;for(b=g.length;f<b;f++)c[g[f]]=f;h===k.length?
g.sort(function(a,b){var d,h=k.length,g=e[a]._aSortData,f=e[b]._aSortData;for(d=0;d<h;d++){var l=k[d];var m=g[l.col];var p=f[l.col];m=m<p?-1:m>p?1:0;if(0!==m)return"asc"===l.dir?m:-m}m=c[a];p=c[b];return m<p?-1:m>p?1:0}):g.sort(function(a,b){var h,g=k.length,f=e[a]._aSortData,l=e[b]._aSortData;for(h=0;h<g;h++){var m=k[h];var p=f[m.col];var n=l[m.col];m=d[m.type+"-"+m.dir]||d["string-"+m.dir];p=m(p,n);if(0!==p)return p}p=c[a];n=c[b];return p<n?-1:p>n?1:0})}a.bSorted=!0}function Mb(a){var b=a.aoColumns,
c=X(a);a=a.oLanguage.oAria;for(var d=0,e=b.length;d<e;d++){var h=b[d];var g=h.asSorting;var k=h.sTitle.replace(/<.*?>/g,"");var f=h.nTh;f.removeAttribute("aria-sort");h.bSortable&&(0<c.length&&c[0].col==d?(f.setAttribute("aria-sort","asc"==c[0].dir?"ascending":"descending"),h=g[c[0].index+1]||g[0]):h=g[0],k+="asc"===h?a.sSortAscending:a.sSortDescending);f.setAttribute("aria-label",k)}}function Ya(a,b,c,d){var e=a.aaSorting,h=a.aoColumns[b].asSorting,g=function(a,b){var c=a._idx;c===n&&(c=f.inArray(a[1],
h));return c+1<h.length?c+1:b?null:0};"number"===typeof e[0]&&(e=a.aaSorting=[e]);c&&a.oFeatures.bSortMulti?(c=f.inArray(b,K(e,"0")),-1!==c?(b=g(e[c],!0),null===b&&1===e.length&&(b=0),null===b?e.splice(c,1):(e[c][1]=h[b],e[c]._idx=b)):(e.push([b,h[0],0]),e[e.length-1]._idx=0)):e.length&&e[0][0]==b?(b=g(e[0]),e.length=1,e[0][1]=h[b],e[0]._idx=b):(e.length=0,e.push([b,h[0]]),e[0]._idx=0);U(a);"function"==typeof d&&d(a)}function Pa(a,b,c,d){var e=a.aoColumns[c];Za(b,{},function(b){!1!==e.bSortable&&
(a.oFeatures.bProcessing?(J(a,!0),setTimeout(function(){Ya(a,c,b.shiftKey,d);"ssp"!==I(a)&&J(a,!1)},0)):Ya(a,c,b.shiftKey,d))})}function za(a){var b=a.aLastSort,c=a.oClasses.sSortColumn,d=X(a),e=a.oFeatures,h;if(e.bSort&&e.bSortClasses){e=0;for(h=b.length;e<h;e++){var g=b[e].src;f(K(a.aoData,"anCells",g)).removeClass(c+(2>e?e+1:3))}e=0;for(h=d.length;e<h;e++)g=d[e].src,f(K(a.aoData,"anCells",g)).addClass(c+(2>e?e+1:3))}a.aLastSort=d}function Lb(a,b){var c=a.aoColumns[b],d=q.ext.order[c.sSortDataType],
e;d&&(e=d.call(a.oInstance,a,b,ba(a,b)));for(var h,g=q.ext.type.order[c.sType+"-pre"],f=0,l=a.aoData.length;f<l;f++)if(c=a.aoData[f],c._aSortData||(c._aSortData=[]),!c._aSortData[b]||d)h=d?e[f]:F(a,f,b,"sort"),c._aSortData[b]=g?g(h):h}function Aa(a){if(a.oFeatures.bStateSave&&!a.bDestroying){var b={time:+new Date,start:a._iDisplayStart,length:a._iDisplayLength,order:f.extend(!0,[],a.aaSorting),search:Eb(a.oPreviousSearch),columns:f.map(a.aoColumns,function(b,d){return{visible:b.bVisible,search:Eb(a.aoPreSearchCols[d])}})};
A(a,"aoStateSaveParams","stateSaveParams",[a,b]);a.oSavedState=b;a.fnStateSaveCallback.call(a.oInstance,a,b)}}function Nb(a,b,c){var d,e,h=a.aoColumns;b=function(b){if(b&&b.time){var g=A(a,"aoStateLoadParams","stateLoadParams",[a,b]);if(-1===f.inArray(!1,g)&&(g=a.iStateDuration,!(0<g&&b.time<+new Date-1E3*g||b.columns&&h.length!==b.columns.length))){a.oLoadedState=f.extend(!0,{},b);b.start!==n&&(a._iDisplayStart=b.start,a.iInitDisplayStart=b.start);b.length!==n&&(a._iDisplayLength=b.length);b.order!==
n&&(a.aaSorting=[],f.each(b.order,function(b,c){a.aaSorting.push(c[0]>=h.length?[0,c[1]]:c)}));b.search!==n&&f.extend(a.oPreviousSearch,Fb(b.search));if(b.columns)for(d=0,e=b.columns.length;d<e;d++)g=b.columns[d],g.visible!==n&&(h[d].bVisible=g.visible),g.search!==n&&f.extend(a.aoPreSearchCols[d],Fb(g.search));A(a,"aoStateLoaded","stateLoaded",[a,b])}}c()};if(a.oFeatures.bStateSave){var g=a.fnStateLoadCallback.call(a.oInstance,a,b);g!==n&&b(g)}else c()}function Ba(a){var b=q.settings;a=f.inArray(a,
K(b,"nTable"));return-1!==a?b[a]:null}function O(a,b,c,d){c="DataTables warning: "+(a?"table id="+a.sTableId+" - ":"")+c;d&&(c+=". For more information about this error, please see http://datatables.net/tn/"+d);if(b)y.console&&console.log&&console.log(c);else if(b=q.ext,b=b.sErrMode||b.errMode,a&&A(a,null,"error",[a,d,c]),"alert"==b)alert(c);else{if("throw"==b)throw Error(c);"function"==typeof b&&b(a,d,c)}}function M(a,b,c,d){f.isArray(c)?f.each(c,function(c,d){f.isArray(d)?M(a,b,d[0],d[1]):M(a,b,
d)}):(d===n&&(d=c),b[c]!==n&&(a[d]=b[c]))}function $a(a,b,c){var d;for(d in b)if(b.hasOwnProperty(d)){var e=b[d];f.isPlainObject(e)?(f.isPlainObject(a[d])||(a[d]={}),f.extend(!0,a[d],e)):c&&"data"!==d&&"aaData"!==d&&f.isArray(e)?a[d]=e.slice():a[d]=e}return a}function Za(a,b,c){f(a).on("click.DT",b,function(b){f(a).trigger("blur");c(b)}).on("keypress.DT",b,function(a){13===a.which&&(a.preventDefault(),c(a))}).on("selectstart.DT",function(){return!1})}function D(a,b,c,d){c&&a[b].push({fn:c,sName:d})}
function A(a,b,c,d){var e=[];b&&(e=f.map(a[b].slice().reverse(),function(b,c){return b.fn.apply(a.oInstance,d)}));null!==c&&(b=f.Event(c+".dt"),f(a.nTable).trigger(b,d),e.push(b.result));return e}function Va(a){var b=a._iDisplayStart,c=a.fnDisplayEnd(),d=a._iDisplayLength;b>=c&&(b=c-d);b-=b%d;if(-1===d||0>b)b=0;a._iDisplayStart=b}function Qa(a,b){a=a.renderer;var c=q.ext.renderer[b];return f.isPlainObject(a)&&a[b]?c[a[b]]||c._:"string"===typeof a?c[a]||c._:c._}function I(a){return a.oFeatures.bServerSide?
"ssp":a.ajax||a.sAjaxSource?"ajax":"dom"}function ja(a,b){var c=Ob.numbers_length,d=Math.floor(c/2);b<=c?a=Y(0,b):a<=d?(a=Y(0,c-2),a.push("ellipsis"),a.push(b-1)):(a>=b-1-d?a=Y(b-(c-2),b):(a=Y(a-d+2,a+d-1),a.push("ellipsis"),a.push(b-1)),a.splice(0,0,"ellipsis"),a.splice(0,0,0));a.DT_el="span";return a}function Ga(a){f.each({num:function(b){return Ca(b,a)},"num-fmt":function(b){return Ca(b,a,ab)},"html-num":function(b){return Ca(b,a,Da)},"html-num-fmt":function(b){return Ca(b,a,Da,ab)}},function(b,
c){C.type.order[b+a+"-pre"]=c;b.match(/^html\-/)&&(C.type.search[b+a]=C.type.search.html)})}function Pb(a){return function(){var b=[Ba(this[q.ext.iApiIndex])].concat(Array.prototype.slice.call(arguments));return q.ext.internal[a].apply(this,b)}}var q=function(a){this.$=function(a,b){return this.api(!0).$(a,b)};this._=function(a,b){return this.api(!0).rows(a,b).data()};this.api=function(a){return a?new x(Ba(this[C.iApiIndex])):new x(this)};this.fnAddData=function(a,b){var c=this.api(!0);a=f.isArray(a)&&
(f.isArray(a[0])||f.isPlainObject(a[0]))?c.rows.add(a):c.row.add(a);(b===n||b)&&c.draw();return a.flatten().toArray()};this.fnAdjustColumnSizing=function(a){var b=this.api(!0).columns.adjust(),c=b.settings()[0],d=c.oScroll;a===n||a?b.draw(!1):(""!==d.sX||""!==d.sY)&&ma(c)};this.fnClearTable=function(a){var b=this.api(!0).clear();(a===n||a)&&b.draw()};this.fnClose=function(a){this.api(!0).row(a).child.hide()};this.fnDeleteRow=function(a,b,c){var d=this.api(!0);a=d.rows(a);var e=a.settings()[0],h=e.aoData[a[0][0]];
a.remove();b&&b.call(this,e,h);(c===n||c)&&d.draw();return h};this.fnDestroy=function(a){this.api(!0).destroy(a)};this.fnDraw=function(a){this.api(!0).draw(a)};this.fnFilter=function(a,b,c,d,e,f){e=this.api(!0);null===b||b===n?e.search(a,c,d,f):e.column(b).search(a,c,d,f);e.draw()};this.fnGetData=function(a,b){var c=this.api(!0);if(a!==n){var d=a.nodeName?a.nodeName.toLowerCase():"";return b!==n||"td"==d||"th"==d?c.cell(a,b).data():c.row(a).data()||null}return c.data().toArray()};this.fnGetNodes=
function(a){var b=this.api(!0);return a!==n?b.row(a).node():b.rows().nodes().flatten().toArray()};this.fnGetPosition=function(a){var b=this.api(!0),c=a.nodeName.toUpperCase();return"TR"==c?b.row(a).index():"TD"==c||"TH"==c?(a=b.cell(a).index(),[a.row,a.columnVisible,a.column]):null};this.fnIsOpen=function(a){return this.api(!0).row(a).child.isShown()};this.fnOpen=function(a,b,c){return this.api(!0).row(a).child(b,c).show().child()[0]};this.fnPageChange=function(a,b){a=this.api(!0).page(a);(b===n||
b)&&a.draw(!1)};this.fnSetColumnVis=function(a,b,c){a=this.api(!0).column(a).visible(b);(c===n||c)&&a.columns.adjust().draw()};this.fnSettings=function(){return Ba(this[C.iApiIndex])};this.fnSort=function(a){this.api(!0).order(a).draw()};this.fnSortListener=function(a,b,c){this.api(!0).order.listener(a,b,c)};this.fnUpdate=function(a,b,c,d,e){var h=this.api(!0);c===n||null===c?h.row(b).data(a):h.cell(b,c).data(a);(e===n||e)&&h.columns.adjust();(d===n||d)&&h.draw();return 0};this.fnVersionCheck=C.fnVersionCheck;
var b=this,c=a===n,d=this.length;c&&(a={});this.oApi=this.internal=C.internal;for(var e in q.ext.internal)e&&(this[e]=Pb(e));this.each(function(){var e={},g=1<d?$a(e,a,!0):a,k=0,l;e=this.getAttribute("id");var m=!1,p=q.defaults,v=f(this);if("table"!=this.nodeName.toLowerCase())O(null,0,"Non-table node initialisation ("+this.nodeName+")",2);else{ib(p);jb(p.column);L(p,p,!0);L(p.column,p.column,!0);L(p,f.extend(g,v.data()),!0);var u=q.settings;k=0;for(l=u.length;k<l;k++){var t=u[k];if(t.nTable==this||
t.nTHead&&t.nTHead.parentNode==this||t.nTFoot&&t.nTFoot.parentNode==this){var w=g.bRetrieve!==n?g.bRetrieve:p.bRetrieve;if(c||w)return t.oInstance;if(g.bDestroy!==n?g.bDestroy:p.bDestroy){t.oInstance.fnDestroy();break}else{O(t,0,"Cannot reinitialise DataTable",3);return}}if(t.sTableId==this.id){u.splice(k,1);break}}if(null===e||""===e)this.id=e="DataTables_Table_"+q.ext._unique++;var r=f.extend(!0,{},q.models.oSettings,{sDestroyWidth:v[0].style.width,sInstance:e,sTableId:e});r.nTable=this;r.oApi=
b.internal;r.oInit=g;u.push(r);r.oInstance=1===b.length?b:v.dataTable();ib(g);Fa(g.oLanguage);g.aLengthMenu&&!g.iDisplayLength&&(g.iDisplayLength=f.isArray(g.aLengthMenu[0])?g.aLengthMenu[0][0]:g.aLengthMenu[0]);g=$a(f.extend(!0,{},p),g);M(r.oFeatures,g,"bPaginate bLengthChange bFilter bSort bSortMulti bInfo bProcessing bAutoWidth bSortClasses bServerSide bDeferRender".split(" "));M(r,g,["asStripeClasses","ajax","fnServerData","fnFormatNumber","sServerMethod","aaSorting","aaSortingFixed","aLengthMenu",
"sPaginationType","sAjaxSource","sAjaxDataProp","iStateDuration","sDom","bSortCellsTop","iTabIndex","fnStateLoadCallback","fnStateSaveCallback","renderer","searchDelay","rowId",["iCookieDuration","iStateDuration"],["oSearch","oPreviousSearch"],["aoSearchCols","aoPreSearchCols"],["iDisplayLength","_iDisplayLength"]]);M(r.oScroll,g,[["sScrollX","sX"],["sScrollXInner","sXInner"],["sScrollY","sY"],["bScrollCollapse","bCollapse"]]);M(r.oLanguage,g,"fnInfoCallback");D(r,"aoDrawCallback",g.fnDrawCallback,
"user");D(r,"aoServerParams",g.fnServerParams,"user");D(r,"aoStateSaveParams",g.fnStateSaveParams,"user");D(r,"aoStateLoadParams",g.fnStateLoadParams,"user");D(r,"aoStateLoaded",g.fnStateLoaded,"user");D(r,"aoRowCallback",g.fnRowCallback,"user");D(r,"aoRowCreatedCallback",g.fnCreatedRow,"user");D(r,"aoHeaderCallback",g.fnHeaderCallback,"user");D(r,"aoFooterCallback",g.fnFooterCallback,"user");D(r,"aoInitComplete",g.fnInitComplete,"user");D(r,"aoPreDrawCallback",g.fnPreDrawCallback,"user");r.rowIdFn=
T(g.rowId);kb(r);var x=r.oClasses;f.extend(x,q.ext.classes,g.oClasses);v.addClass(x.sTable);r.iInitDisplayStart===n&&(r.iInitDisplayStart=g.iDisplayStart,r._iDisplayStart=g.iDisplayStart);null!==g.iDeferLoading&&(r.bDeferLoading=!0,e=f.isArray(g.iDeferLoading),r._iRecordsDisplay=e?g.iDeferLoading[0]:g.iDeferLoading,r._iRecordsTotal=e?g.iDeferLoading[1]:g.iDeferLoading);var y=r.oLanguage;f.extend(!0,y,g.oLanguage);y.sUrl&&(f.ajax({dataType:"json",url:y.sUrl,success:function(a){Fa(a);L(p.oLanguage,
a);f.extend(!0,y,a);ia(r)},error:function(){ia(r)}}),m=!0);null===g.asStripeClasses&&(r.asStripeClasses=[x.sStripeOdd,x.sStripeEven]);e=r.asStripeClasses;var z=v.children("tbody").find("tr").eq(0);-1!==f.inArray(!0,f.map(e,function(a,b){return z.hasClass(a)}))&&(f("tbody tr",this).removeClass(e.join(" ")),r.asDestroyStripes=e.slice());e=[];u=this.getElementsByTagName("thead");0!==u.length&&(ea(r.aoHeader,u[0]),e=ta(r));if(null===g.aoColumns)for(u=[],k=0,l=e.length;k<l;k++)u.push(null);else u=g.aoColumns;
k=0;for(l=u.length;k<l;k++)Ha(r,e?e[k]:null);mb(r,g.aoColumnDefs,u,function(a,b){la(r,a,b)});if(z.length){var B=function(a,b){return null!==a.getAttribute("data-"+b)?b:null};f(z[0]).children("th, td").each(function(a,b){var c=r.aoColumns[a];if(c.mData===a){var d=B(b,"sort")||B(b,"order");b=B(b,"filter")||B(b,"search");if(null!==d||null!==b)c.mData={_:a+".display",sort:null!==d?a+".@data-"+d:n,type:null!==d?a+".@data-"+d:n,filter:null!==b?a+".@data-"+b:n},la(r,a)}})}var C=r.oFeatures;e=function(){if(g.aaSorting===
n){var a=r.aaSorting;k=0;for(l=a.length;k<l;k++)a[k][1]=r.aoColumns[k].asSorting[0]}za(r);C.bSort&&D(r,"aoDrawCallback",function(){if(r.bSorted){var a=X(r),b={};f.each(a,function(a,c){b[c.src]=c.dir});A(r,null,"order",[r,a,b]);Mb(r)}});D(r,"aoDrawCallback",function(){(r.bSorted||"ssp"===I(r)||C.bDeferRender)&&za(r)},"sc");a=v.children("caption").each(function(){this._captionSide=f(this).css("caption-side")});var b=v.children("thead");0===b.length&&(b=f("<thead/>").appendTo(v));r.nTHead=b[0];b=v.children("tbody");
0===b.length&&(b=f("<tbody/>").appendTo(v));r.nTBody=b[0];b=v.children("tfoot");0===b.length&&0<a.length&&(""!==r.oScroll.sX||""!==r.oScroll.sY)&&(b=f("<tfoot/>").appendTo(v));0===b.length||0===b.children().length?v.addClass(x.sNoFooter):0<b.length&&(r.nTFoot=b[0],ea(r.aoFooter,r.nTFoot));if(g.aaData)for(k=0;k<g.aaData.length;k++)R(r,g.aaData[k]);else(r.bDeferLoading||"dom"==I(r))&&oa(r,f(r.nTBody).children("tr"));r.aiDisplay=r.aiDisplayMaster.slice();r.bInitialised=!0;!1===m&&ia(r)};g.bStateSave?
(C.bStateSave=!0,D(r,"aoDrawCallback",Aa,"state_save"),Nb(r,g,e)):e()}});b=null;return this},C,t,z,bb={},Qb=/[\r\n\u2028]/g,Da=/<.*?>/g,cc=/^\d{2,4}[\.\/\-]\d{1,2}[\.\/\-]\d{1,2}([T ]{1}\d{1,2}[:\.]\d{2}([\.:]\d{2})?)?$/,dc=/(\/|\.|\*|\+|\?|\||\(|\)|\[|\]|\{|\}|\\|\$|\^|\-)/g,ab=/[',$£€¥%\u2009\u202F\u20BD\u20a9\u20BArfkɃΞ]/gi,P=function(a){return a&&!0!==a&&"-"!==a?!1:!0},Rb=function(a){var b=parseInt(a,10);return!isNaN(b)&&isFinite(a)?b:null},Sb=function(a,b){bb[b]||(bb[b]=new RegExp(Ta(b),"g"));
return"string"===typeof a&&"."!==b?a.replace(/\./g,"").replace(bb[b],"."):a},cb=function(a,b,c){var d="string"===typeof a;if(P(a))return!0;b&&d&&(a=Sb(a,b));c&&d&&(a=a.replace(ab,""));return!isNaN(parseFloat(a))&&isFinite(a)},Tb=function(a,b,c){return P(a)?!0:P(a)||"string"===typeof a?cb(a.replace(Da,""),b,c)?!0:null:null},K=function(a,b,c){var d=[],e=0,h=a.length;if(c!==n)for(;e<h;e++)a[e]&&a[e][b]&&d.push(a[e][b][c]);else for(;e<h;e++)a[e]&&d.push(a[e][b]);return d},ka=function(a,b,c,d){var e=[],
h=0,g=b.length;if(d!==n)for(;h<g;h++)a[b[h]][c]&&e.push(a[b[h]][c][d]);else for(;h<g;h++)e.push(a[b[h]][c]);return e},Y=function(a,b){var c=[];if(b===n){b=0;var d=a}else d=b,b=a;for(a=b;a<d;a++)c.push(a);return c},Ub=function(a){for(var b=[],c=0,d=a.length;c<d;c++)a[c]&&b.push(a[c]);return b},sa=function(a){a:{if(!(2>a.length)){var b=a.slice().sort();for(var c=b[0],d=1,e=b.length;d<e;d++){if(b[d]===c){b=!1;break a}c=b[d]}}b=!0}if(b)return a.slice();b=[];e=a.length;var h,g=0;d=0;a:for(;d<e;d++){c=
a[d];for(h=0;h<g;h++)if(b[h]===c)continue a;b.push(c);g++}return b};q.util={throttle:function(a,b){var c=b!==n?b:200,d,e;return function(){var b=this,g=+new Date,f=arguments;d&&g<d+c?(clearTimeout(e),e=setTimeout(function(){d=n;a.apply(b,f)},c)):(d=g,a.apply(b,f))}},escapeRegex:function(a){return a.replace(dc,"\\$1")}};var E=function(a,b,c){a[b]!==n&&(a[c]=a[b])},ca=/\[.*?\]$/,W=/\(\)$/,Ta=q.util.escapeRegex,xa=f("<div>")[0],$b=xa.textContent!==n,bc=/<.*?>/g,Ra=q.util.throttle,Vb=[],G=Array.prototype,
ec=function(a){var b,c=q.settings,d=f.map(c,function(a,b){return a.nTable});if(a){if(a.nTable&&a.oApi)return[a];if(a.nodeName&&"table"===a.nodeName.toLowerCase()){var e=f.inArray(a,d);return-1!==e?[c[e]]:null}if(a&&"function"===typeof a.settings)return a.settings().toArray();"string"===typeof a?b=f(a):a instanceof f&&(b=a)}else return[];if(b)return b.map(function(a){e=f.inArray(this,d);return-1!==e?c[e]:null}).toArray()};var x=function(a,b){if(!(this instanceof x))return new x(a,b);var c=[],d=function(a){(a=
ec(a))&&c.push.apply(c,a)};if(f.isArray(a))for(var e=0,h=a.length;e<h;e++)d(a[e]);else d(a);this.context=sa(c);b&&f.merge(this,b);this.selector={rows:null,cols:null,opts:null};x.extend(this,this,Vb)};q.Api=x;f.extend(x.prototype,{any:function(){return 0!==this.count()},concat:G.concat,context:[],count:function(){return this.flatten().length},each:function(a){for(var b=0,c=this.length;b<c;b++)a.call(this,this[b],b,this);return this},eq:function(a){var b=this.context;return b.length>a?new x(b[a],this[a]):
null},filter:function(a){var b=[];if(G.filter)b=G.filter.call(this,a,this);else for(var c=0,d=this.length;c<d;c++)a.call(this,this[c],c,this)&&b.push(this[c]);return new x(this.context,b)},flatten:function(){var a=[];return new x(this.context,a.concat.apply(a,this.toArray()))},join:G.join,indexOf:G.indexOf||function(a,b){b=b||0;for(var c=this.length;b<c;b++)if(this[b]===a)return b;return-1},iterator:function(a,b,c,d){var e=[],h,g,f=this.context,l,m=this.selector;"string"===typeof a&&(d=c,c=b,b=a,
a=!1);var p=0;for(h=f.length;p<h;p++){var q=new x(f[p]);if("table"===b){var u=c.call(q,f[p],p);u!==n&&e.push(u)}else if("columns"===b||"rows"===b)u=c.call(q,f[p],this[p],p),u!==n&&e.push(u);else if("column"===b||"column-rows"===b||"row"===b||"cell"===b){var t=this[p];"column-rows"===b&&(l=Ea(f[p],m.opts));var w=0;for(g=t.length;w<g;w++)u=t[w],u="cell"===b?c.call(q,f[p],u.row,u.column,p,w):c.call(q,f[p],u,p,w,l),u!==n&&e.push(u)}}return e.length||d?(a=new x(f,a?e.concat.apply([],e):e),b=a.selector,
b.rows=m.rows,b.cols=m.cols,b.opts=m.opts,a):this},lastIndexOf:G.lastIndexOf||function(a,b){return this.indexOf.apply(this.toArray.reverse(),arguments)},length:0,map:function(a){var b=[];if(G.map)b=G.map.call(this,a,this);else for(var c=0,d=this.length;c<d;c++)b.push(a.call(this,this[c],c));return new x(this.context,b)},pluck:function(a){return this.map(function(b){return b[a]})},pop:G.pop,push:G.push,reduce:G.reduce||function(a,b){return lb(this,a,b,0,this.length,1)},reduceRight:G.reduceRight||function(a,
b){return lb(this,a,b,this.length-1,-1,-1)},reverse:G.reverse,selector:null,shift:G.shift,slice:function(){return new x(this.context,this)},sort:G.sort,splice:G.splice,toArray:function(){return G.slice.call(this)},to$:function(){return f(this)},toJQuery:function(){return f(this)},unique:function(){return new x(this.context,sa(this))},unshift:G.unshift});x.extend=function(a,b,c){if(c.length&&b&&(b instanceof x||b.__dt_wrapper)){var d,e=function(a,b,c){return function(){var d=b.apply(a,arguments);x.extend(d,
d,c.methodExt);return d}};var h=0;for(d=c.length;h<d;h++){var f=c[h];b[f.name]="function"===f.type?e(a,f.val,f):"object"===f.type?{}:f.val;b[f.name].__dt_wrapper=!0;x.extend(a,b[f.name],f.propExt)}}};x.register=t=function(a,b){if(f.isArray(a))for(var c=0,d=a.length;c<d;c++)x.register(a[c],b);else{d=a.split(".");var e=Vb,h;a=0;for(c=d.length;a<c;a++){var g=(h=-1!==d[a].indexOf("()"))?d[a].replace("()",""):d[a];a:{var k=0;for(var l=e.length;k<l;k++)if(e[k].name===g){k=e[k];break a}k=null}k||(k={name:g,
val:{},methodExt:[],propExt:[],type:"object"},e.push(k));a===c-1?(k.val=b,k.type="function"===typeof b?"function":f.isPlainObject(b)?"object":"other"):e=h?k.methodExt:k.propExt}}};x.registerPlural=z=function(a,b,c){x.register(a,c);x.register(b,function(){var a=c.apply(this,arguments);return a===this?this:a instanceof x?a.length?f.isArray(a[0])?new x(a.context,a[0]):a[0]:n:a})};var Wb=function(a,b){if(f.isArray(a))return f.map(a,function(a){return Wb(a,b)});if("number"===typeof a)return[b[a]];var c=
f.map(b,function(a,b){return a.nTable});return f(c).filter(a).map(function(a){a=f.inArray(this,c);return b[a]}).toArray()};t("tables()",function(a){return a!==n&&null!==a?new x(Wb(a,this.context)):this});t("table()",function(a){a=this.tables(a);var b=a.context;return b.length?new x(b[0]):a});z("tables().nodes()","table().node()",function(){return this.iterator("table",function(a){return a.nTable},1)});z("tables().body()","table().body()",function(){return this.iterator("table",function(a){return a.nTBody},
1)});z("tables().header()","table().header()",function(){return this.iterator("table",function(a){return a.nTHead},1)});z("tables().footer()","table().footer()",function(){return this.iterator("table",function(a){return a.nTFoot},1)});z("tables().containers()","table().container()",function(){return this.iterator("table",function(a){return a.nTableWrapper},1)});t("draw()",function(a){return this.iterator("table",function(b){"page"===a?S(b):("string"===typeof a&&(a="full-hold"===a?!1:!0),U(b,!1===
a))})});t("page()",function(a){return a===n?this.page.info().page:this.iterator("table",function(b){Wa(b,a)})});t("page.info()",function(a){if(0===this.context.length)return n;a=this.context[0];var b=a._iDisplayStart,c=a.oFeatures.bPaginate?a._iDisplayLength:-1,d=a.fnRecordsDisplay(),e=-1===c;return{page:e?0:Math.floor(b/c),pages:e?1:Math.ceil(d/c),start:b,end:a.fnDisplayEnd(),length:c,recordsTotal:a.fnRecordsTotal(),recordsDisplay:d,serverSide:"ssp"===I(a)}});t("page.len()",function(a){return a===
n?0!==this.context.length?this.context[0]._iDisplayLength:n:this.iterator("table",function(b){Ua(b,a)})});var Xb=function(a,b,c){if(c){var d=new x(a);d.one("draw",function(){c(d.ajax.json())})}if("ssp"==I(a))U(a,b);else{J(a,!0);var e=a.jqXHR;e&&4!==e.readyState&&e.abort();ua(a,[],function(c){pa(a);c=va(a,c);for(var d=0,e=c.length;d<e;d++)R(a,c[d]);U(a,b);J(a,!1)})}};t("ajax.json()",function(){var a=this.context;if(0<a.length)return a[0].json});t("ajax.params()",function(){var a=this.context;if(0<
a.length)return a[0].oAjaxData});t("ajax.reload()",function(a,b){return this.iterator("table",function(c){Xb(c,!1===b,a)})});t("ajax.url()",function(a){var b=this.context;if(a===n){if(0===b.length)return n;b=b[0];return b.ajax?f.isPlainObject(b.ajax)?b.ajax.url:b.ajax:b.sAjaxSource}return this.iterator("table",function(b){f.isPlainObject(b.ajax)?b.ajax.url=a:b.ajax=a})});t("ajax.url().load()",function(a,b){return this.iterator("table",function(c){Xb(c,!1===b,a)})});var db=function(a,b,c,d,e){var h=
[],g,k,l;var m=typeof b;b&&"string"!==m&&"function"!==m&&b.length!==n||(b=[b]);m=0;for(k=b.length;m<k;m++){var p=b[m]&&b[m].split&&!b[m].match(/[\[\(:]/)?b[m].split(","):[b[m]];var q=0;for(l=p.length;q<l;q++)(g=c("string"===typeof p[q]?f.trim(p[q]):p[q]))&&g.length&&(h=h.concat(g))}a=C.selector[a];if(a.length)for(m=0,k=a.length;m<k;m++)h=a[m](d,e,h);return sa(h)},eb=function(a){a||(a={});a.filter&&a.search===n&&(a.search=a.filter);return f.extend({search:"none",order:"current",page:"all"},a)},fb=
function(a){for(var b=0,c=a.length;b<c;b++)if(0<a[b].length)return a[0]=a[b],a[0].length=1,a.length=1,a.context=[a.context[b]],a;a.length=0;return a},Ea=function(a,b){var c=[],d=a.aiDisplay;var e=a.aiDisplayMaster;var h=b.search;var g=b.order;b=b.page;if("ssp"==I(a))return"removed"===h?[]:Y(0,e.length);if("current"==b)for(g=a._iDisplayStart,a=a.fnDisplayEnd();g<a;g++)c.push(d[g]);else if("current"==g||"applied"==g)if("none"==h)c=e.slice();else if("applied"==h)c=d.slice();else{if("removed"==h){var k=
{};g=0;for(a=d.length;g<a;g++)k[d[g]]=null;c=f.map(e,function(a){return k.hasOwnProperty(a)?null:a})}}else if("index"==g||"original"==g)for(g=0,a=a.aoData.length;g<a;g++)"none"==h?c.push(g):(e=f.inArray(g,d),(-1===e&&"removed"==h||0<=e&&"applied"==h)&&c.push(g));return c},fc=function(a,b,c){var d;return db("row",b,function(b){var e=Rb(b),g=a.aoData;if(null!==e&&!c)return[e];d||(d=Ea(a,c));if(null!==e&&-1!==f.inArray(e,d))return[e];if(null===b||b===n||""===b)return d;if("function"===typeof b)return f.map(d,
function(a){var c=g[a];return b(a,c._aData,c.nTr)?a:null});if(b.nodeName){e=b._DT_RowIndex;var k=b._DT_CellIndex;if(e!==n)return g[e]&&g[e].nTr===b?[e]:[];if(k)return g[k.row]&&g[k.row].nTr===b.parentNode?[k.row]:[];e=f(b).closest("*[data-dt-row]");return e.length?[e.data("dt-row")]:[]}if("string"===typeof b&&"#"===b.charAt(0)&&(e=a.aIds[b.replace(/^#/,"")],e!==n))return[e.idx];e=Ub(ka(a.aoData,d,"nTr"));return f(e).filter(b).map(function(){return this._DT_RowIndex}).toArray()},a,c)};t("rows()",function(a,
b){a===n?a="":f.isPlainObject(a)&&(b=a,a="");b=eb(b);var c=this.iterator("table",function(c){return fc(c,a,b)},1);c.selector.rows=a;c.selector.opts=b;return c});t("rows().nodes()",function(){return this.iterator("row",function(a,b){return a.aoData[b].nTr||n},1)});t("rows().data()",function(){return this.iterator(!0,"rows",function(a,b){return ka(a.aoData,b,"_aData")},1)});z("rows().cache()","row().cache()",function(a){return this.iterator("row",function(b,c){b=b.aoData[c];return"search"===a?b._aFilterData:
b._aSortData},1)});z("rows().invalidate()","row().invalidate()",function(a){return this.iterator("row",function(b,c){da(b,c,a)})});z("rows().indexes()","row().index()",function(){return this.iterator("row",function(a,b){return b},1)});z("rows().ids()","row().id()",function(a){for(var b=[],c=this.context,d=0,e=c.length;d<e;d++)for(var f=0,g=this[d].length;f<g;f++){var k=c[d].rowIdFn(c[d].aoData[this[d][f]]._aData);b.push((!0===a?"#":"")+k)}return new x(c,b)});z("rows().remove()","row().remove()",function(){var a=
this;this.iterator("row",function(b,c,d){var e=b.aoData,f=e[c],g,k;e.splice(c,1);var l=0;for(g=e.length;l<g;l++){var m=e[l];var p=m.anCells;null!==m.nTr&&(m.nTr._DT_RowIndex=l);if(null!==p)for(m=0,k=p.length;m<k;m++)p[m]._DT_CellIndex.row=l}qa(b.aiDisplayMaster,c);qa(b.aiDisplay,c);qa(a[d],c,!1);0<b._iRecordsDisplay&&b._iRecordsDisplay--;Va(b);c=b.rowIdFn(f._aData);c!==n&&delete b.aIds[c]});this.iterator("table",function(a){for(var b=0,d=a.aoData.length;b<d;b++)a.aoData[b].idx=b});return this});t("rows.add()",
function(a){var b=this.iterator("table",function(b){var c,d=[];var f=0;for(c=a.length;f<c;f++){var k=a[f];k.nodeName&&"TR"===k.nodeName.toUpperCase()?d.push(oa(b,k)[0]):d.push(R(b,k))}return d},1),c=this.rows(-1);c.pop();f.merge(c,b);return c});t("row()",function(a,b){return fb(this.rows(a,b))});t("row().data()",function(a){var b=this.context;if(a===n)return b.length&&this.length?b[0].aoData[this[0]]._aData:n;var c=b[0].aoData[this[0]];c._aData=a;f.isArray(a)&&c.nTr&&c.nTr.id&&Q(b[0].rowId)(a,c.nTr.id);
da(b[0],this[0],"data");return this});t("row().node()",function(){var a=this.context;return a.length&&this.length?a[0].aoData[this[0]].nTr||null:null});t("row.add()",function(a){a instanceof f&&a.length&&(a=a[0]);var b=this.iterator("table",function(b){return a.nodeName&&"TR"===a.nodeName.toUpperCase()?oa(b,a)[0]:R(b,a)});return this.row(b[0])});var gc=function(a,b,c,d){var e=[],h=function(b,c){if(f.isArray(b)||b instanceof f)for(var d=0,g=b.length;d<g;d++)h(b[d],c);else b.nodeName&&"tr"===b.nodeName.toLowerCase()?
e.push(b):(d=f("<tr><td/></tr>").addClass(c),f("td",d).addClass(c).html(b)[0].colSpan=V(a),e.push(d[0]))};h(c,d);b._details&&b._details.detach();b._details=f(e);b._detailsShow&&b._details.insertAfter(b.nTr)},gb=function(a,b){var c=a.context;c.length&&(a=c[0].aoData[b!==n?b:a[0]])&&a._details&&(a._details.remove(),a._detailsShow=n,a._details=n)},Yb=function(a,b){var c=a.context;c.length&&a.length&&(a=c[0].aoData[a[0]],a._details&&((a._detailsShow=b)?a._details.insertAfter(a.nTr):a._details.detach(),
hc(c[0])))},hc=function(a){var b=new x(a),c=a.aoData;b.off("draw.dt.DT_details column-visibility.dt.DT_details destroy.dt.DT_details");0<K(c,"_details").length&&(b.on("draw.dt.DT_details",function(d,e){a===e&&b.rows({page:"current"}).eq(0).each(function(a){a=c[a];a._detailsShow&&a._details.insertAfter(a.nTr)})}),b.on("column-visibility.dt.DT_details",function(b,e,f,g){if(a===e)for(e=V(e),f=0,g=c.length;f<g;f++)b=c[f],b._details&&b._details.children("td[colspan]").attr("colspan",e)}),b.on("destroy.dt.DT_details",
function(d,e){if(a===e)for(d=0,e=c.length;d<e;d++)c[d]._details&&gb(b,d)}))};t("row().child()",function(a,b){var c=this.context;if(a===n)return c.length&&this.length?c[0].aoData[this[0]]._details:n;!0===a?this.child.show():!1===a?gb(this):c.length&&this.length&&gc(c[0],c[0].aoData[this[0]],a,b);return this});t(["row().child.show()","row().child().show()"],function(a){Yb(this,!0);return this});t(["row().child.hide()","row().child().hide()"],function(){Yb(this,!1);return this});t(["row().child.remove()",
"row().child().remove()"],function(){gb(this);return this});t("row().child.isShown()",function(){var a=this.context;return a.length&&this.length?a[0].aoData[this[0]]._detailsShow||!1:!1});var ic=/^([^:]+):(name|visIdx|visible)$/,Zb=function(a,b,c,d,e){c=[];d=0;for(var f=e.length;d<f;d++)c.push(F(a,e[d],b));return c},jc=function(a,b,c){var d=a.aoColumns,e=K(d,"sName"),h=K(d,"nTh");return db("column",b,function(b){var g=Rb(b);if(""===b)return Y(d.length);if(null!==g)return[0<=g?g:d.length+g];if("function"===
typeof b){var l=Ea(a,c);return f.map(d,function(c,d){return b(d,Zb(a,d,0,0,l),h[d])?d:null})}var m="string"===typeof b?b.match(ic):"";if(m)switch(m[2]){case "visIdx":case "visible":g=parseInt(m[1],10);if(0>g){var p=f.map(d,function(a,b){return a.bVisible?b:null});return[p[p.length+g]]}return[aa(a,g)];case "name":return f.map(e,function(a,b){return a===m[1]?b:null});default:return[]}if(b.nodeName&&b._DT_CellIndex)return[b._DT_CellIndex.column];g=f(h).filter(b).map(function(){return f.inArray(this,
h)}).toArray();if(g.length||!b.nodeName)return g;g=f(b).closest("*[data-dt-column]");return g.length?[g.data("dt-column")]:[]},a,c)};t("columns()",function(a,b){a===n?a="":f.isPlainObject(a)&&(b=a,a="");b=eb(b);var c=this.iterator("table",function(c){return jc(c,a,b)},1);c.selector.cols=a;c.selector.opts=b;return c});z("columns().header()","column().header()",function(a,b){return this.iterator("column",function(a,b){return a.aoColumns[b].nTh},1)});z("columns().footer()","column().footer()",function(a,
b){return this.iterator("column",function(a,b){return a.aoColumns[b].nTf},1)});z("columns().data()","column().data()",function(){return this.iterator("column-rows",Zb,1)});z("columns().dataSrc()","column().dataSrc()",function(){return this.iterator("column",function(a,b){return a.aoColumns[b].mData},1)});z("columns().cache()","column().cache()",function(a){return this.iterator("column-rows",function(b,c,d,e,f){return ka(b.aoData,f,"search"===a?"_aFilterData":"_aSortData",c)},1)});z("columns().nodes()",
"column().nodes()",function(){return this.iterator("column-rows",function(a,b,c,d,e){return ka(a.aoData,e,"anCells",b)},1)});z("columns().visible()","column().visible()",function(a,b){var c=this,d=this.iterator("column",function(b,c){if(a===n)return b.aoColumns[c].bVisible;var d=b.aoColumns,e=d[c],h=b.aoData,m;if(a!==n&&e.bVisible!==a){if(a){var p=f.inArray(!0,K(d,"bVisible"),c+1);d=0;for(m=h.length;d<m;d++){var q=h[d].nTr;b=h[d].anCells;q&&q.insertBefore(b[c],b[p]||null)}}else f(K(b.aoData,"anCells",
c)).detach();e.bVisible=a}});a!==n&&this.iterator("table",function(d){fa(d,d.aoHeader);fa(d,d.aoFooter);d.aiDisplay.length||f(d.nTBody).find("td[colspan]").attr("colspan",V(d));Aa(d);c.iterator("column",function(c,d){A(c,null,"column-visibility",[c,d,a,b])});(b===n||b)&&c.columns.adjust()});return d});z("columns().indexes()","column().index()",function(a){return this.iterator("column",function(b,c){return"visible"===a?ba(b,c):c},1)});t("columns.adjust()",function(){return this.iterator("table",function(a){Z(a)},
1)});t("column.index()",function(a,b){if(0!==this.context.length){var c=this.context[0];if("fromVisible"===a||"toData"===a)return aa(c,b);if("fromData"===a||"toVisible"===a)return ba(c,b)}});t("column()",function(a,b){return fb(this.columns(a,b))});var kc=function(a,b,c){var d=a.aoData,e=Ea(a,c),h=Ub(ka(d,e,"anCells")),g=f([].concat.apply([],h)),k,l=a.aoColumns.length,m,p,q,u,t,w;return db("cell",b,function(b){var c="function"===typeof b;if(null===b||b===n||c){m=[];p=0;for(q=e.length;p<q;p++)for(k=
e[p],u=0;u<l;u++)t={row:k,column:u},c?(w=d[k],b(t,F(a,k,u),w.anCells?w.anCells[u]:null)&&m.push(t)):m.push(t);return m}if(f.isPlainObject(b))return b.column!==n&&b.row!==n&&-1!==f.inArray(b.row,e)?[b]:[];c=g.filter(b).map(function(a,b){return{row:b._DT_CellIndex.row,column:b._DT_CellIndex.column}}).toArray();if(c.length||!b.nodeName)return c;w=f(b).closest("*[data-dt-row]");return w.length?[{row:w.data("dt-row"),column:w.data("dt-column")}]:[]},a,c)};t("cells()",function(a,b,c){f.isPlainObject(a)&&
(a.row===n?(c=a,a=null):(c=b,b=null));f.isPlainObject(b)&&(c=b,b=null);if(null===b||b===n)return this.iterator("table",function(b){return kc(b,a,eb(c))});var d=c?{page:c.page,order:c.order,search:c.search}:{},e=this.columns(b,d),h=this.rows(a,d),g,k,l,m;d=this.iterator("table",function(a,b){a=[];g=0;for(k=h[b].length;g<k;g++)for(l=0,m=e[b].length;l<m;l++)a.push({row:h[b][g],column:e[b][l]});return a},1);d=c&&c.selected?this.cells(d,c):d;f.extend(d.selector,{cols:b,rows:a,opts:c});return d});z("cells().nodes()",
"cell().node()",function(){return this.iterator("cell",function(a,b,c){return(a=a.aoData[b])&&a.anCells?a.anCells[c]:n},1)});t("cells().data()",function(){return this.iterator("cell",function(a,b,c){return F(a,b,c)},1)});z("cells().cache()","cell().cache()",function(a){a="search"===a?"_aFilterData":"_aSortData";return this.iterator("cell",function(b,c,d){return b.aoData[c][a][d]},1)});z("cells().render()","cell().render()",function(a){return this.iterator("cell",function(b,c,d){return F(b,c,d,a)},
1)});z("cells().indexes()","cell().index()",function(){return this.iterator("cell",function(a,b,c){return{row:b,column:c,columnVisible:ba(a,c)}},1)});z("cells().invalidate()","cell().invalidate()",function(a){return this.iterator("cell",function(b,c,d){da(b,c,a,d)})});t("cell()",function(a,b,c){return fb(this.cells(a,b,c))});t("cell().data()",function(a){var b=this.context,c=this[0];if(a===n)return b.length&&c.length?F(b[0],c[0].row,c[0].column):n;nb(b[0],c[0].row,c[0].column,a);da(b[0],c[0].row,
"data",c[0].column);return this});t("order()",function(a,b){var c=this.context;if(a===n)return 0!==c.length?c[0].aaSorting:n;"number"===typeof a?a=[[a,b]]:a.length&&!f.isArray(a[0])&&(a=Array.prototype.slice.call(arguments));return this.iterator("table",function(b){b.aaSorting=a.slice()})});t("order.listener()",function(a,b,c){return this.iterator("table",function(d){Pa(d,a,b,c)})});t("order.fixed()",function(a){if(!a){var b=this.context;b=b.length?b[0].aaSortingFixed:n;return f.isArray(b)?{pre:b}:
b}return this.iterator("table",function(b){b.aaSortingFixed=f.extend(!0,{},a)})});t(["columns().order()","column().order()"],function(a){var b=this;return this.iterator("table",function(c,d){var e=[];f.each(b[d],function(b,c){e.push([c,a])});c.aaSorting=e})});t("search()",function(a,b,c,d){var e=this.context;return a===n?0!==e.length?e[0].oPreviousSearch.sSearch:n:this.iterator("table",function(e){e.oFeatures.bFilter&&ha(e,f.extend({},e.oPreviousSearch,{sSearch:a+"",bRegex:null===b?!1:b,bSmart:null===
c?!0:c,bCaseInsensitive:null===d?!0:d}),1)})});z("columns().search()","column().search()",function(a,b,c,d){return this.iterator("column",function(e,h){var g=e.aoPreSearchCols;if(a===n)return g[h].sSearch;e.oFeatures.bFilter&&(f.extend(g[h],{sSearch:a+"",bRegex:null===b?!1:b,bSmart:null===c?!0:c,bCaseInsensitive:null===d?!0:d}),ha(e,e.oPreviousSearch,1))})});t("state()",function(){return this.context.length?this.context[0].oSavedState:null});t("state.clear()",function(){return this.iterator("table",
function(a){a.fnStateSaveCallback.call(a.oInstance,a,{})})});t("state.loaded()",function(){return this.context.length?this.context[0].oLoadedState:null});t("state.save()",function(){return this.iterator("table",function(a){Aa(a)})});q.versionCheck=q.fnVersionCheck=function(a){var b=q.version.split(".");a=a.split(".");for(var c,d,e=0,f=a.length;e<f;e++)if(c=parseInt(b[e],10)||0,d=parseInt(a[e],10)||0,c!==d)return c>d;return!0};q.isDataTable=q.fnIsDataTable=function(a){var b=f(a).get(0),c=!1;if(a instanceof
q.Api)return!0;f.each(q.settings,function(a,e){a=e.nScrollHead?f("table",e.nScrollHead)[0]:null;var d=e.nScrollFoot?f("table",e.nScrollFoot)[0]:null;if(e.nTable===b||a===b||d===b)c=!0});return c};q.tables=q.fnTables=function(a){var b=!1;f.isPlainObject(a)&&(b=a.api,a=a.visible);var c=f.map(q.settings,function(b){if(!a||a&&f(b.nTable).is(":visible"))return b.nTable});return b?new x(c):c};q.camelToHungarian=L;t("$()",function(a,b){b=this.rows(b).nodes();b=f(b);return f([].concat(b.filter(a).toArray(),
b.find(a).toArray()))});f.each(["on","one","off"],function(a,b){t(b+"()",function(){var a=Array.prototype.slice.call(arguments);a[0]=f.map(a[0].split(/\s/),function(a){return a.match(/\.dt\b/)?a:a+".dt"}).join(" ");var d=f(this.tables().nodes());d[b].apply(d,a);return this})});t("clear()",function(){return this.iterator("table",function(a){pa(a)})});t("settings()",function(){return new x(this.context,this.context)});t("init()",function(){var a=this.context;return a.length?a[0].oInit:null});t("data()",
function(){return this.iterator("table",function(a){return K(a.aoData,"_aData")}).flatten()});t("destroy()",function(a){a=a||!1;return this.iterator("table",function(b){var c=b.nTableWrapper.parentNode,d=b.oClasses,e=b.nTable,h=b.nTBody,g=b.nTHead,k=b.nTFoot,l=f(e);h=f(h);var m=f(b.nTableWrapper),p=f.map(b.aoData,function(a){return a.nTr}),n;b.bDestroying=!0;A(b,"aoDestroyCallback","destroy",[b]);a||(new x(b)).columns().visible(!0);m.off(".DT").find(":not(tbody *)").off(".DT");f(y).off(".DT-"+b.sInstance);
e!=g.parentNode&&(l.children("thead").detach(),l.append(g));k&&e!=k.parentNode&&(l.children("tfoot").detach(),l.append(k));b.aaSorting=[];b.aaSortingFixed=[];za(b);f(p).removeClass(b.asStripeClasses.join(" "));f("th, td",g).removeClass(d.sSortable+" "+d.sSortableAsc+" "+d.sSortableDesc+" "+d.sSortableNone);h.children().detach();h.append(p);g=a?"remove":"detach";l[g]();m[g]();!a&&c&&(c.insertBefore(e,b.nTableReinsertBefore),l.css("width",b.sDestroyWidth).removeClass(d.sTable),(n=b.asDestroyStripes.length)&&
h.children().each(function(a){f(this).addClass(b.asDestroyStripes[a%n])}));c=f.inArray(b,q.settings);-1!==c&&q.settings.splice(c,1)})});f.each(["column","row","cell"],function(a,b){t(b+"s().every()",function(a){var c=this.selector.opts,e=this;return this.iterator(b,function(d,f,k,l,m){a.call(e[b](f,"cell"===b?k:c,"cell"===b?c:n),f,k,l,m)})})});t("i18n()",function(a,b,c){var d=this.context[0];a=T(a)(d.oLanguage);a===n&&(a=b);c!==n&&f.isPlainObject(a)&&(a=a[c]!==n?a[c]:a._);return a.replace("%d",c)});
q.version="1.10.21";q.settings=[];q.models={};q.models.oSearch={bCaseInsensitive:!0,sSearch:"",bRegex:!1,bSmart:!0};q.models.oRow={nTr:null,anCells:null,_aData:[],_aSortData:null,_aFilterData:null,_sFilterRow:null,_sRowStripe:"",src:null,idx:-1};q.models.oColumn={idx:null,aDataSort:null,asSorting:null,bSearchable:null,bSortable:null,bVisible:null,_sManualType:null,_bAttrSrc:!1,fnCreatedCell:null,fnGetData:null,fnSetData:null,mData:null,mRender:null,nTh:null,nTf:null,sClass:null,sContentPadding:null,
sDefaultContent:null,sName:null,sSortDataType:"std",sSortingClass:null,sSortingClassJUI:null,sTitle:null,sType:null,sWidth:null,sWidthOrig:null};q.defaults={aaData:null,aaSorting:[[0,"asc"]],aaSortingFixed:[],ajax:null,aLengthMenu:[10,25,50,100],aoColumns:null,aoColumnDefs:null,aoSearchCols:[],asStripeClasses:null,bAutoWidth:!0,bDeferRender:!1,bDestroy:!1,bFilter:!0,bInfo:!0,bLengthChange:!0,bPaginate:!0,bProcessing:!1,bRetrieve:!1,bScrollCollapse:!1,bServerSide:!1,bSort:!0,bSortMulti:!0,bSortCellsTop:!1,
bSortClasses:!0,bStateSave:!1,fnCreatedRow:null,fnDrawCallback:null,fnFooterCallback:null,fnFormatNumber:function(a){return a.toString().replace(/\B(?=(\d{3})+(?!\d))/g,this.oLanguage.sThousands)},fnHeaderCallback:null,fnInfoCallback:null,fnInitComplete:null,fnPreDrawCallback:null,fnRowCallback:null,fnServerData:null,fnServerParams:null,fnStateLoadCallback:function(a){try{return JSON.parse((-1===a.iStateDuration?sessionStorage:localStorage).getItem("DataTables_"+a.sInstance+"_"+location.pathname))}catch(b){return{}}},
fnStateLoadParams:null,fnStateLoaded:null,fnStateSaveCallback:function(a,b){try{(-1===a.iStateDuration?sessionStorage:localStorage).setItem("DataTables_"+a.sInstance+"_"+location.pathname,JSON.stringify(b))}catch(c){}},fnStateSaveParams:null,iStateDuration:7200,iDeferLoading:null,iDisplayLength:10,iDisplayStart:0,iTabIndex:0,oClasses:{},oLanguage:{oAria:{sSortAscending:": activate to sort column ascending",sSortDescending:": activate to sort column descending"},oPaginate:{sFirst:"First",sLast:"Last",
sNext:"Next",sPrevious:"Previous"},sEmptyTable:"No data available in table",sInfo:"Showing _START_ to _END_ of _TOTAL_ entries",sInfoEmpty:"Showing 0 to 0 of 0 entries",sInfoFiltered:"(filtered from _MAX_ total entries)",sInfoPostFix:"",sDecimal:"",sThousands:",",sLengthMenu:"Show _MENU_ entries",sLoadingRecords:"Loading...",sProcessing:"Processing...",sSearch:"Search:",sSearchPlaceholder:"",sUrl:"",sZeroRecords:"No matching records found"},oSearch:f.extend({},q.models.oSearch),sAjaxDataProp:"data",
sAjaxSource:null,sDom:"lfrtip",searchDelay:null,sPaginationType:"simple_numbers",sScrollX:"",sScrollXInner:"",sScrollY:"",sServerMethod:"GET",renderer:null,rowId:"DT_RowId"};H(q.defaults);q.defaults.column={aDataSort:null,iDataSort:-1,asSorting:["asc","desc"],bSearchable:!0,bSortable:!0,bVisible:!0,fnCreatedCell:null,mData:null,mRender:null,sCellType:"td",sClass:"",sContentPadding:"",sDefaultContent:null,sName:"",sSortDataType:"std",sTitle:null,sType:null,sWidth:null};H(q.defaults.column);q.models.oSettings=
{oFeatures:{bAutoWidth:null,bDeferRender:null,bFilter:null,bInfo:null,bLengthChange:null,bPaginate:null,bProcessing:null,bServerSide:null,bSort:null,bSortMulti:null,bSortClasses:null,bStateSave:null},oScroll:{bCollapse:null,iBarWidth:0,sX:null,sXInner:null,sY:null},oLanguage:{fnInfoCallback:null},oBrowser:{bScrollOversize:!1,bScrollbarLeft:!1,bBounding:!1,barWidth:0},ajax:null,aanFeatures:[],aoData:[],aiDisplay:[],aiDisplayMaster:[],aIds:{},aoColumns:[],aoHeader:[],aoFooter:[],oPreviousSearch:{},
aoPreSearchCols:[],aaSorting:null,aaSortingFixed:[],asStripeClasses:null,asDestroyStripes:[],sDestroyWidth:0,aoRowCallback:[],aoHeaderCallback:[],aoFooterCallback:[],aoDrawCallback:[],aoRowCreatedCallback:[],aoPreDrawCallback:[],aoInitComplete:[],aoStateSaveParams:[],aoStateLoadParams:[],aoStateLoaded:[],sTableId:"",nTable:null,nTHead:null,nTFoot:null,nTBody:null,nTableWrapper:null,bDeferLoading:!1,bInitialised:!1,aoOpenRows:[],sDom:null,searchDelay:null,sPaginationType:"two_button",iStateDuration:0,
aoStateSave:[],aoStateLoad:[],oSavedState:null,oLoadedState:null,sAjaxSource:null,sAjaxDataProp:null,bAjaxDataGet:!0,jqXHR:null,json:n,oAjaxData:n,fnServerData:null,aoServerParams:[],sServerMethod:null,fnFormatNumber:null,aLengthMenu:null,iDraw:0,bDrawing:!1,iDrawError:-1,_iDisplayLength:10,_iDisplayStart:0,_iRecordsTotal:0,_iRecordsDisplay:0,oClasses:{},bFiltered:!1,bSorted:!1,bSortCellsTop:null,oInit:null,aoDestroyCallback:[],fnRecordsTotal:function(){return"ssp"==I(this)?1*this._iRecordsTotal:
this.aiDisplayMaster.length},fnRecordsDisplay:function(){return"ssp"==I(this)?1*this._iRecordsDisplay:this.aiDisplay.length},fnDisplayEnd:function(){var a=this._iDisplayLength,b=this._iDisplayStart,c=b+a,d=this.aiDisplay.length,e=this.oFeatures,f=e.bPaginate;return e.bServerSide?!1===f||-1===a?b+d:Math.min(b+a,this._iRecordsDisplay):!f||c>d||-1===a?d:c},oInstance:null,sInstance:null,iTabIndex:0,nScrollHead:null,nScrollFoot:null,aLastSort:[],oPlugins:{},rowIdFn:null,rowId:null};q.ext=C={buttons:{},
classes:{},builder:"-source-",errMode:"alert",feature:[],search:[],selector:{cell:[],column:[],row:[]},internal:{},legacy:{ajax:null},pager:{},renderer:{pageButton:{},header:{}},order:{},type:{detect:[],search:{},order:{}},_unique:0,fnVersionCheck:q.fnVersionCheck,iApiIndex:0,oJUIClasses:{},sVersion:q.version};f.extend(C,{afnFiltering:C.search,aTypes:C.type.detect,ofnSearch:C.type.search,oSort:C.type.order,afnSortData:C.order,aoFeatures:C.feature,oApi:C.internal,oStdClasses:C.classes,oPagination:C.pager});
f.extend(q.ext.classes,{sTable:"dataTable",sNoFooter:"no-footer",sPageButton:"paginate_button",sPageButtonActive:"current",sPageButtonDisabled:"disabled",sStripeOdd:"odd",sStripeEven:"even",sRowEmpty:"dataTables_empty",sWrapper:"dataTables_wrapper",sFilter:"dataTables_filter",sInfo:"dataTables_info",sPaging:"dataTables_paginate paging_",sLength:"dataTables_length",sProcessing:"dataTables_processing",sSortAsc:"sorting_asc",sSortDesc:"sorting_desc",sSortable:"sorting",sSortableAsc:"sorting_asc_disabled",
sSortableDesc:"sorting_desc_disabled",sSortableNone:"sorting_disabled",sSortColumn:"sorting_",sFilterInput:"",sLengthSelect:"",sScrollWrapper:"dataTables_scroll",sScrollHead:"dataTables_scrollHead",sScrollHeadInner:"dataTables_scrollHeadInner",sScrollBody:"dataTables_scrollBody",sScrollFoot:"dataTables_scrollFoot",sScrollFootInner:"dataTables_scrollFootInner",sHeaderTH:"",sFooterTH:"",sSortJUIAsc:"",sSortJUIDesc:"",sSortJUI:"",sSortJUIAscAllowed:"",sSortJUIDescAllowed:"",sSortJUIWrapper:"",sSortIcon:"",
sJUIHeader:"",sJUIFooter:""});var Ob=q.ext.pager;f.extend(Ob,{simple:function(a,b){return["previous","next"]},full:function(a,b){return["first","previous","next","last"]},numbers:function(a,b){return[ja(a,b)]},simple_numbers:function(a,b){return["previous",ja(a,b),"next"]},full_numbers:function(a,b){return["first","previous",ja(a,b),"next","last"]},first_last_numbers:function(a,b){return["first",ja(a,b),"last"]},_numbers:ja,numbers_length:7});f.extend(!0,q.ext.renderer,{pageButton:{_:function(a,b,
c,d,e,h){var g=a.oClasses,k=a.oLanguage.oPaginate,l=a.oLanguage.oAria.paginate||{},m,p,q=0,t=function(b,d){var n,r=g.sPageButtonDisabled,u=function(b){Wa(a,b.data.action,!0)};var w=0;for(n=d.length;w<n;w++){var v=d[w];if(f.isArray(v)){var x=f("<"+(v.DT_el||"div")+"/>").appendTo(b);t(x,v)}else{m=null;p=v;x=a.iTabIndex;switch(v){case "ellipsis":b.append('<span class="ellipsis">&#x2026;</span>');break;case "first":m=k.sFirst;0===e&&(x=-1,p+=" "+r);break;case "previous":m=k.sPrevious;0===e&&(x=-1,p+=
" "+r);break;case "next":m=k.sNext;if(0===h||e===h-1)x=-1,p+=" "+r;break;case "last":m=k.sLast;e===h-1&&(x=-1,p+=" "+r);break;default:m=v+1,p=e===v?g.sPageButtonActive:""}null!==m&&(x=f("<a>",{"class":g.sPageButton+" "+p,"aria-controls":a.sTableId,"aria-label":l[v],"data-dt-idx":q,tabindex:x,id:0===c&&"string"===typeof v?a.sTableId+"_"+v:null}).html(m).appendTo(b),Za(x,{action:v},u),q++)}}};try{var x=f(b).find(w.activeElement).data("dt-idx")}catch(lc){}t(f(b).empty(),d);x!==n&&f(b).find("[data-dt-idx="+
x+"]").trigger("focus")}}});f.extend(q.ext.type.detect,[function(a,b){b=b.oLanguage.sDecimal;return cb(a,b)?"num"+b:null},function(a,b){if(a&&!(a instanceof Date)&&!cc.test(a))return null;b=Date.parse(a);return null!==b&&!isNaN(b)||P(a)?"date":null},function(a,b){b=b.oLanguage.sDecimal;return cb(a,b,!0)?"num-fmt"+b:null},function(a,b){b=b.oLanguage.sDecimal;return Tb(a,b)?"html-num"+b:null},function(a,b){b=b.oLanguage.sDecimal;return Tb(a,b,!0)?"html-num-fmt"+b:null},function(a,b){return P(a)||"string"===
typeof a&&-1!==a.indexOf("<")?"html":null}]);f.extend(q.ext.type.search,{html:function(a){return P(a)?a:"string"===typeof a?a.replace(Qb," ").replace(Da,""):""},string:function(a){return P(a)?a:"string"===typeof a?a.replace(Qb," "):a}});var Ca=function(a,b,c,d){if(0!==a&&(!a||"-"===a))return-Infinity;b&&(a=Sb(a,b));a.replace&&(c&&(a=a.replace(c,"")),d&&(a=a.replace(d,"")));return 1*a};f.extend(C.type.order,{"date-pre":function(a){a=Date.parse(a);return isNaN(a)?-Infinity:a},"html-pre":function(a){return P(a)?
"":a.replace?a.replace(/<.*?>/g,"").toLowerCase():a+""},"string-pre":function(a){return P(a)?"":"string"===typeof a?a.toLowerCase():a.toString?a.toString():""},"string-asc":function(a,b){return a<b?-1:a>b?1:0},"string-desc":function(a,b){return a<b?1:a>b?-1:0}});Ga("");f.extend(!0,q.ext.renderer,{header:{_:function(a,b,c,d){f(a.nTable).on("order.dt.DT",function(e,f,g,k){a===f&&(e=c.idx,b.removeClass(c.sSortingClass+" "+d.sSortAsc+" "+d.sSortDesc).addClass("asc"==k[e]?d.sSortAsc:"desc"==k[e]?d.sSortDesc:
c.sSortingClass))})},jqueryui:function(a,b,c,d){f("<div/>").addClass(d.sSortJUIWrapper).append(b.contents()).append(f("<span/>").addClass(d.sSortIcon+" "+c.sSortingClassJUI)).appendTo(b);f(a.nTable).on("order.dt.DT",function(e,f,g,k){a===f&&(e=c.idx,b.removeClass(d.sSortAsc+" "+d.sSortDesc).addClass("asc"==k[e]?d.sSortAsc:"desc"==k[e]?d.sSortDesc:c.sSortingClass),b.find("span."+d.sSortIcon).removeClass(d.sSortJUIAsc+" "+d.sSortJUIDesc+" "+d.sSortJUI+" "+d.sSortJUIAscAllowed+" "+d.sSortJUIDescAllowed).addClass("asc"==
k[e]?d.sSortJUIAsc:"desc"==k[e]?d.sSortJUIDesc:c.sSortingClassJUI))})}}});var hb=function(a){return"string"===typeof a?a.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;"):a};q.render={number:function(a,b,c,d,e){return{display:function(f){if("number"!==typeof f&&"string"!==typeof f)return f;var g=0>f?"-":"",h=parseFloat(f);if(isNaN(h))return hb(f);h=h.toFixed(c);f=Math.abs(h);h=parseInt(f,10);f=c?b+(f-h).toFixed(c).substring(2):"";return g+(d||"")+h.toString().replace(/\B(?=(\d{3})+(?!\d))/g,
a)+f+(e||"")}}},text:function(){return{display:hb,filter:hb}}};f.extend(q.ext.internal,{_fnExternApiFunc:Pb,_fnBuildAjax:ua,_fnAjaxUpdate:pb,_fnAjaxParameters:yb,_fnAjaxUpdateDraw:zb,_fnAjaxDataSrc:va,_fnAddColumn:Ha,_fnColumnOptions:la,_fnAdjustColumnSizing:Z,_fnVisibleToColumnIndex:aa,_fnColumnIndexToVisible:ba,_fnVisbleColumns:V,_fnGetColumns:na,_fnColumnTypes:Ja,_fnApplyColumnDefs:mb,_fnHungarianMap:H,_fnCamelToHungarian:L,_fnLanguageCompat:Fa,_fnBrowserDetect:kb,_fnAddData:R,_fnAddTr:oa,_fnNodeToDataIndex:function(a,
b){return b._DT_RowIndex!==n?b._DT_RowIndex:null},_fnNodeToColumnIndex:function(a,b,c){return f.inArray(c,a.aoData[b].anCells)},_fnGetCellData:F,_fnSetCellData:nb,_fnSplitObjNotation:Ma,_fnGetObjectDataFn:T,_fnSetObjectDataFn:Q,_fnGetDataMaster:Na,_fnClearTable:pa,_fnDeleteIndex:qa,_fnInvalidate:da,_fnGetRowElements:La,_fnCreateTr:Ka,_fnBuildHead:ob,_fnDrawHead:fa,_fnDraw:S,_fnReDraw:U,_fnAddOptionsHtml:rb,_fnDetectHeader:ea,_fnGetUniqueThs:ta,_fnFeatureHtmlFilter:tb,_fnFilterComplete:ha,_fnFilterCustom:Cb,
_fnFilterColumn:Bb,_fnFilter:Ab,_fnFilterCreateSearch:Sa,_fnEscapeRegex:Ta,_fnFilterData:Db,_fnFeatureHtmlInfo:wb,_fnUpdateInfo:Gb,_fnInfoMacros:Hb,_fnInitialise:ia,_fnInitComplete:wa,_fnLengthChange:Ua,_fnFeatureHtmlLength:sb,_fnFeatureHtmlPaginate:xb,_fnPageChange:Wa,_fnFeatureHtmlProcessing:ub,_fnProcessingDisplay:J,_fnFeatureHtmlTable:vb,_fnScrollDraw:ma,_fnApplyToChildren:N,_fnCalculateColumnWidths:Ia,_fnThrottle:Ra,_fnConvertToWidth:Ib,_fnGetWidestNode:Jb,_fnGetMaxLenString:Kb,_fnStringToCss:B,
_fnSortFlatten:X,_fnSort:qb,_fnSortAria:Mb,_fnSortListener:Ya,_fnSortAttachListener:Pa,_fnSortingClasses:za,_fnSortData:Lb,_fnSaveState:Aa,_fnLoadState:Nb,_fnSettingsFromNode:Ba,_fnLog:O,_fnMap:M,_fnBindAction:Za,_fnCallbackReg:D,_fnCallbackFire:A,_fnLengthOverflow:Va,_fnRenderer:Qa,_fnDataSource:I,_fnRowAttributes:Oa,_fnExtend:$a,_fnCalculateEnd:function(){}});f.fn.dataTable=q;q.$=f;f.fn.dataTableSettings=q.settings;f.fn.dataTableExt=q.ext;f.fn.DataTable=function(a){return f(this).dataTable(a).api()};
f.each(q,function(a,b){f.fn.DataTable[a]=b});return f.fn.dataTable});

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -1,4 +1,11 @@
{ {
"/js/app.js": "/js/app.js", "/js/app.js": "/js/app.js",
"/css/app.css": "/css/app.css" "/css/app.css": "/css/app.css",
"/css/dark.css": "/css/dark.css",
"/css/light.css": "/css/light.css",
"/webfonts/fa-regular-400.ttf": "/webfonts/fa-regular-400.ttf",
"/webfonts/fa-regular-400.woff2": "/webfonts/fa-regular-400.woff2",
"/webfonts/fa-solid-900.ttf": "/webfonts/fa-solid-900.ttf",
"/webfonts/fa-solid-900.woff2": "/webfonts/fa-solid-900.woff2",
"/webfonts/fa-brands-400.ttf": "/webfonts/fa-brands-400.ttf"
} }

Binary file not shown.

File diff suppressed because it is too large Load diff

Before

Width:  |  Height:  |  Size: 730 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load diff

Before

Width:  |  Height:  |  Size: 896 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -1,63 +0,0 @@
# ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## #
# Yet-Another-Bench-Script #
# v2021-12-28 #
# https://github.com/masonr/yet-another-bench-script #
# ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## #
Sat 05 Feb 2022 02:54:48 AM CET
Basic System Information:
---------------------------------
Processor : AMD Ryzen 9 3900X 12-Core Processor
CPU cores : 2 @ 3792.874 MHz
AES-NI : ✔ Enabled
VM-x/AMD-V : ✔ Enabled
RAM : 3.8 GiB
Swap : 0.0 KiB
Disk : 39.3 GiB
fio Disk Speed Tests (Mixed R/W 50/50):
---------------------------------
Block Size | 4k (IOPS) | 64k (IOPS)
------ | --- ---- | ---- ----
Read | 174.73 MB/s (43.6k) | 979.69 MB/s (15.3k)
Write | 175.19 MB/s (43.7k) | 984.85 MB/s (15.3k)
Total | 349.93 MB/s (87.4k) | 1.96 GB/s (30.6k)
| |
Block Size | 512k (IOPS) | 1m (IOPS)
------ | --- ---- | ---- ----
Read | 571.27 MB/s (1.1k) | 590.50 MB/s (576)
Write | 601.62 MB/s (1.1k) | 629.83 MB/s (615)
Total | 1.17 GB/s (2.2k) | 1.22 GB/s (1.1k)
iperf3 Network Speed Tests (IPv4):
---------------------------------
Provider | Location (Link) | Send Speed | Recv Speed
| | |
Clouvider | London, UK (10G) | 709 Mbits/sec | 882 Mbits/sec
Online.net | Paris, FR (10G) | 570 Mbits/sec | 786 Mbits/sec
WorldStream | The Netherlands (10G) | 886 Mbits/sec | 933 Mbits/sec
WebHorizon | Singapore (400M) | 278 Mbits/sec | 478 Mbits/sec
Clouvider | NYC, NY, US (10G) | 260 Mbits/sec | 243 Mbits/sec
Velocity Online | Tallahassee, FL, US (10G) | 227 Mbits/sec | 317 Mbits/sec
Clouvider | Los Angeles, CA, US (10G) | 255 Mbits/sec | 288 Mbits/sec
Iveloz Telecom | Sao Paulo, BR (2G) | 110 Mbits/sec | 281 Mbits/sec
iperf3 Network Speed Tests (IPv6):
---------------------------------
Provider | Location (Link) | Send Speed | Recv Speed
| | |
Clouvider | London, UK (10G) | 706 Mbits/sec | 854 Mbits/sec
Online.net | Paris, FR (10G) | 591 Mbits/sec | 760 Mbits/sec
WorldStream | The Netherlands (10G) | 867 Mbits/sec | 904 Mbits/sec
WebHorizon | Singapore (400M) | 207 Mbits/sec | 502 Mbits/sec
Clouvider | NYC, NY, US (10G) | 302 Mbits/sec | 201 Mbits/sec
Clouvider | Los Angeles, CA, US (10G) | 169 Mbits/sec | 450 Mbits/sec
Geekbench 5 Benchmark Test:
---------------------------------
Test | Value
|
Single Core | 1276
Multi Core | 2394
Full Test | https://browser.geekbench.com/v5/cpu/12590829

View file

@ -1,3 +1,2 @@
@import 'tailwindcss/base'; @import "datatables.net-bs5";
@import 'tailwindcss/components'; @import "style.css";
@import 'tailwindcss/utilities';

1
resources/css/dark.css vendored Normal file
View file

@ -0,0 +1 @@
@import 'bootstrap-dark-5';

1
resources/css/light.css vendored Normal file
View file

@ -0,0 +1 @@
@import 'bootstrap';

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