Initial Commit

This commit is contained in:
2021-05-13 11:20:17 +02:00
commit 48b3256ebf
126 changed files with 39162 additions and 0 deletions

106
resources/css/app.scss vendored Normal file
View File

@@ -0,0 +1,106 @@
@import "libs/sweetalert2.min.css";
@import "libs/bulma-0.9.1.min.css";
@import "libs/Chart-2.9.4.min.css";
@import "libs/microtip.css";
@import "libs/animate-4.1.1.min.css";
#section-navbar {
margin-bottom: 20px;
.navbar-end {
.navbar-item {
&:last-child {
margin-right: 10px;
}
}
}
}
.delete-btn {
border: none;
background-color: transparent;
color: #fc4d4d;
&:hover {
cursor: pointer;
}
}
.edit-btn {
border: none;
background-color: transparent;
color: orange;
&:hover {
cursor: pointer;
}
}
.is-centered {
text-align: center;
}
#overviewTable {
margin-bottom: 0;
}
.btn-refresh-records {
margin-top: 1em;
}
.is-hidden {
display: none;
}
.lang-active, .lang-active:hover {
background-color: #3273dc !important;
color: #fff !important;
}
.flag {
background-repeat: no-repeat;
display: inline-block;
background-image: url(/img/languages.png);
min-width: 22px;
height: 16px;
min-height: 16px;
max-height: 16px;
&[lang=de] {
background-position: 0 -575px;
}
&[lang=en] {
background-position: 0 -607px;
}
}
.flag-xs {
min-width: 14px;
height: 11px;
min-height: 11px;
max-height: 11px;
&[lang=de] {
background-position: 0 -55px;
}
&[lang=en] {
background-position: 0 -77px;
}
}
#error-container {
.message-body {
ul {
list-style: decimal;
}
}
}
#recordEditModal {
.modal-content {
background-color: #fff;
padding: 50px;
}
}

View File

@@ -0,0 +1 @@
@keyframes chartjs-render-animation{from{opacity:.99}to{opacity:1}}.chartjs-render-monitor{animation:chartjs-render-animation 1ms}.chartjs-size-monitor,.chartjs-size-monitor-expand,.chartjs-size-monitor-shrink{position:absolute;direction:ltr;left:0;top:0;right:0;bottom:0;overflow:hidden;pointer-events:none;visibility:hidden;z-index:-1}.chartjs-size-monitor-expand>div{position:absolute;width:1000000px;height:1000000px;left:0;top:0}.chartjs-size-monitor-shrink>div{position:absolute;width:200%;height:200%;left:0;top:0}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

266
resources/css/libs/microtip.css vendored Normal file
View File

@@ -0,0 +1,266 @@
/* -------------------------------------------------------------------
Microtip
Modern, lightweight css-only tooltips
Just 1kb minified and gzipped
@author Ghosh
@package Microtip
----------------------------------------------------------------------
1. Base Styles
2. Direction Modifiers
3. Position Modifiers
--------------------------------------------------------------------*/
/* ------------------------------------------------
[1] Base Styles
-------------------------------------------------*/
[aria-label][role~="tooltip"] {
position: relative;
}
[aria-label][role~="tooltip"]::before,
[aria-label][role~="tooltip"]::after {
transform: translate3d(0, 0, 0);
-webkit-backface-visibility: hidden;
backface-visibility: hidden;
will-change: transform;
opacity: 0;
pointer-events: none;
transition: all var(--microtip-transition-duration, .18s) var(--microtip-transition-easing, ease-in-out) var(--microtip-transition-delay, 0s);
position: absolute;
box-sizing: border-box;
z-index: 10;
transform-origin: top;
}
[aria-label][role~="tooltip"]::before {
background-size: 100% auto !important;
content: "";
}
[aria-label][role~="tooltip"]::after {
background: rgba(17, 17, 17, .9);
border-radius: 4px;
color: #ffffff;
content: attr(aria-label);
font-size: var(--microtip-font-size, 13px);
font-weight: var(--microtip-font-weight, normal);
text-transform: var(--microtip-text-transform, none);
padding: .5em 1em;
white-space: nowrap;
box-sizing: content-box;
}
[aria-label][role~="tooltip"]:hover::before,
[aria-label][role~="tooltip"]:hover::after,
[aria-label][role~="tooltip"]:focus::before,
[aria-label][role~="tooltip"]:focus::after {
opacity: 1;
pointer-events: auto;
}
/* ------------------------------------------------
[2] Position Modifiers
-------------------------------------------------*/
[role~="tooltip"][data-microtip-position|="top"]::before {
background: url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2236px%22%20height%3D%2212px%22%3E%3Cpath%20fill%3D%22rgba%2817,%2017,%2017,%200.9%29%22%20transform%3D%22rotate%280%29%22%20d%3D%22M2.658,0.000%20C-13.615,0.000%2050.938,0.000%2034.662,0.000%20C28.662,0.000%2023.035,12.002%2018.660,12.002%20C14.285,12.002%208.594,0.000%202.658,0.000%20Z%22/%3E%3C/svg%3E") no-repeat;
height: 6px;
width: 18px;
margin-bottom: 5px;
}
[role~="tooltip"][data-microtip-position|="top"]::after {
margin-bottom: 11px;
}
[role~="tooltip"][data-microtip-position|="top"]::before {
transform: translate3d(-50%, 0, 0);
bottom: 100%;
left: 50%;
}
[role~="tooltip"][data-microtip-position|="top"]:hover::before {
transform: translate3d(-50%, -5px, 0);
}
[role~="tooltip"][data-microtip-position|="top"]::after {
transform: translate3d(-50%, 0, 0);
bottom: 100%;
left: 50%;
}
[role~="tooltip"][data-microtip-position="top"]:hover::after {
transform: translate3d(-50%, -5px, 0);
}
/* ------------------------------------------------
[2.1] Top Left
-------------------------------------------------*/
[role~="tooltip"][data-microtip-position="top-left"]::after {
transform: translate3d(calc(-100% + 16px), 0, 0);
bottom: 100%;
}
[role~="tooltip"][data-microtip-position="top-left"]:hover::after {
transform: translate3d(calc(-100% + 16px), -5px, 0);
}
/* ------------------------------------------------
[2.2] Top Right
-------------------------------------------------*/
[role~="tooltip"][data-microtip-position="top-right"]::after {
transform: translate3d(calc(0% + -16px), 0, 0);
bottom: 100%;
}
[role~="tooltip"][data-microtip-position="top-right"]:hover::after {
transform: translate3d(calc(0% + -16px), -5px, 0);
}
/* ------------------------------------------------
[2.3] Bottom
-------------------------------------------------*/
[role~="tooltip"][data-microtip-position|="bottom"]::before {
background: url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2236px%22%20height%3D%2212px%22%3E%3Cpath%20fill%3D%22rgba%2817,%2017,%2017,%200.9%29%22%20transform%3D%22rotate%28180%2018%206%29%22%20d%3D%22M2.658,0.000%20C-13.615,0.000%2050.938,0.000%2034.662,0.000%20C28.662,0.000%2023.035,12.002%2018.660,12.002%20C14.285,12.002%208.594,0.000%202.658,0.000%20Z%22/%3E%3C/svg%3E") no-repeat;
height: 6px;
width: 18px;
margin-top: 5px;
margin-bottom: 0;
}
[role~="tooltip"][data-microtip-position|="bottom"]::after {
margin-top: 11px;
}
[role~="tooltip"][data-microtip-position|="bottom"]::before {
transform: translate3d(-50%, -10px, 0);
bottom: auto;
left: 50%;
top: 100%;
}
[role~="tooltip"][data-microtip-position|="bottom"]:hover::before {
transform: translate3d(-50%, 0, 0);
}
[role~="tooltip"][data-microtip-position|="bottom"]::after {
transform: translate3d(-50%, -10px, 0);
top: 100%;
left: 50%;
}
[role~="tooltip"][data-microtip-position="bottom"]:hover::after {
transform: translate3d(-50%, 0, 0);
}
/* ------------------------------------------------
[2.4] Bottom Left
-------------------------------------------------*/
[role~="tooltip"][data-microtip-position="bottom-left"]::after {
transform: translate3d(calc(-100% + 16px), -10px, 0);
top: 100%;
}
[role~="tooltip"][data-microtip-position="bottom-left"]:hover::after {
transform: translate3d(calc(-100% + 16px), 0, 0);
}
/* ------------------------------------------------
[2.5] Bottom Right
-------------------------------------------------*/
[role~="tooltip"][data-microtip-position="bottom-right"]::after {
transform: translate3d(calc(0% + -16px), -10px, 0);
top: 100%;
}
[role~="tooltip"][data-microtip-position="bottom-right"]:hover::after {
transform: translate3d(calc(0% + -16px), 0, 0);
}
/* ------------------------------------------------
[2.6] Left
-------------------------------------------------*/
[role~="tooltip"][data-microtip-position="left"]::before,
[role~="tooltip"][data-microtip-position="left"]::after {
bottom: auto;
left: auto;
right: 100%;
top: 50%;
transform: translate3d(10px, -50%, 0);
}
[role~="tooltip"][data-microtip-position="left"]::before {
background: url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2212px%22%20height%3D%2236px%22%3E%3Cpath%20fill%3D%22rgba%2817,%2017,%2017,%200.9%29%22%20transform%3D%22rotate%28-90%2018%2018%29%22%20d%3D%22M2.658,0.000%20C-13.615,0.000%2050.938,0.000%2034.662,0.000%20C28.662,0.000%2023.035,12.002%2018.660,12.002%20C14.285,12.002%208.594,0.000%202.658,0.000%20Z%22/%3E%3C/svg%3E") no-repeat;
height: 18px;
width: 6px;
margin-right: 5px;
margin-bottom: 0;
}
[role~="tooltip"][data-microtip-position="left"]::after {
margin-right: 11px;
}
[role~="tooltip"][data-microtip-position="left"]:hover::before,
[role~="tooltip"][data-microtip-position="left"]:hover::after {
transform: translate3d(0, -50%, 0);
}
/* ------------------------------------------------
[2.7] Right
-------------------------------------------------*/
[role~="tooltip"][data-microtip-position="right"]::before,
[role~="tooltip"][data-microtip-position="right"]::after {
bottom: auto;
left: 100%;
top: 50%;
transform: translate3d(-10px, -50%, 0);
}
[role~="tooltip"][data-microtip-position="right"]::before {
background: url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2212px%22%20height%3D%2236px%22%3E%3Cpath%20fill%3D%22rgba%2817,%2017,%2017,%200.9%29%22%20transform%3D%22rotate%2890%206%206%29%22%20d%3D%22M2.658,0.000%20C-13.615,0.000%2050.938,0.000%2034.662,0.000%20C28.662,0.000%2023.035,12.002%2018.660,12.002%20C14.285,12.002%208.594,0.000%202.658,0.000%20Z%22/%3E%3C/svg%3E") no-repeat;
height: 18px;
width: 6px;
margin-bottom: 0;
margin-left: 5px;
}
[role~="tooltip"][data-microtip-position="right"]::after {
margin-left: 11px;
}
[role~="tooltip"][data-microtip-position="right"]:hover::before,
[role~="tooltip"][data-microtip-position="right"]:hover::after {
transform: translate3d(0, -50%, 0);
}
/* ------------------------------------------------
[3] Size
-------------------------------------------------*/
[role~="tooltip"][data-microtip-size="small"]::after {
white-space: initial;
width: 80px;
}
[role~="tooltip"][data-microtip-size="medium"]::after {
white-space: initial;
width: 150px;
}
[role~="tooltip"][data-microtip-size="large"]::after {
white-space: initial;
width: 260px;
}

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,30 @@
<?php
return [
"err_lang_code_not_found" => "Der Ländercode :code ist nicht gültig!",
"suc_lang_set" => "Die Sprache wurde erfolgreich geändert!",
"error_saving_domain" => "Die Domain konnte nicht gespeichert werden: :error",
"suc_saving_domain" => "Die Domain wurde erfolgreich gespeichert!",
"error_saving_record" => "Der Record konnte nicht gespeichert werden: :error",
"suc_saving_record" => "Der Record wurde erfolgreich gespeichert!",
"error_deleting_record" => "Der Record konnte nicht gelöscht werden: :error",
"error_editing_record" => "Fehler beim Bearbeiten des Records: :error",
"suc_editing_record" => "Der Record wurde erfolgreich gespeichert!",
"suc_deleting_record" => "Der Record :record wurde erfolgreich gelöscht!",
"error_fetching_records" => "Fehler beim Abrufen neuer Records: :error",
"suc_fetching_records" => "Einträge für die Domain :domain erfolgreich aktualisiert!",
"error_deleting_domain" => "Fehler beim löschen der Domain: :error",
"suc_deleting_domain" => "Die Domain :domain wurde erfolgreich gelöscht!",
"err_user_existing" => "Ein Benutzer mit diesem Benutzernamen existiert bereits!",
"error_creating_user" => "Beim Erstellen des Benutzers ist ein Fehler aufgetreten: :error",
"suc_creating_user" => "Der Benutzer :username wurde erfolgreich erstellt!",
"error_no_user" => "Es existiert kein Benutzer mit dem Benutzernamen :username!",
"error_deleting_user" => "Beim Löschen des Benutzers :username ist ein Fehler aufgetreten: :error",
"suc_deleting_user" => "Der Benutzer :username wurde erfolgreich gelöscht!",
"suc_logout" => "Du hast dich erfolgreich ausgeloggt!",
"suc_login" => "Erfolgreich eingeloggt!",
"err_login" => "Fehler beim einloggen! Bitte prüfe deine Daten!",
"old_password_incorrect" => "Das aktuelle Passwort ist inkorrekt!",
"error_changing_password" => "Fehler beim ändern des Passworts: :error",
"suc_changing_password" => "Das Passwort wurde erfolgreich geändert!",
];

View File

@@ -0,0 +1,152 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Validation Language Lines
|--------------------------------------------------------------------------
|
| The following language lines contain the default error messages used by
| the validator class. Some of these rules have multiple versions such
| as the size rules. Feel free to tweak each of these messages here.
|
*/
'accepted' => ':attribute muss akzeptiert werden.',
'active_url' => ':attribute ist keine gültige URL.',
'after' => 'The ":attribute" must be a date after :date.',
'after_or_equal' => 'The ":attribute" must be a date after or equal to :date.',
'alpha' => 'The ":attribute" must only contain letters.',
'alpha_dash' => 'The ":attribute" must only contain letters, numbers, dashes and underscores.',
'alpha_num' => 'The ":attribute" must only contain letters and numbers.',
'array' => 'The ":attribute" must be an array.',
'before' => 'The ":attribute" must be a date before :date.',
'before_or_equal' => 'The ":attribute" must be a date before or equal to :date.',
'between' => [
'numeric' => 'The ":attribute" must be between :min and :max.',
'file' => 'The ":attribute" must be between :min and :max kilobytes.',
'string' => 'The ":attribute" must be between :min and :max characters.',
'array' => 'The ":attribute" must have between :min and :max items.',
],
'boolean' => 'The ":attribute" field must be true or false.',
'confirmed' => 'The ":attribute" confirmation does not match.',
'date' => 'The ":attribute" is not a valid date.',
'date_equals' => 'The ":attribute" must be a date equal to :date.',
'date_format' => 'The ":attribute" does not match the format :format.',
'different' => 'The ":attribute" and :other must be different.',
'digits' => 'The ":attribute" must be :digits digits.',
'digits_between' => 'The ":attribute" must be between :min and :max digits.',
'dimensions' => 'The ":attribute" has invalid image dimensions.',
'distinct' => 'The ":attribute" field has a duplicate value.',
'email' => 'The ":attribute" must be a valid email address.',
'ends_with' => 'The ":attribute" must end with one of the following: :values.',
'exists' => 'Das Feld ":attribute" ist ungültig.',
'file' => 'The ":attribute" must be a file.',
'filled' => 'The ":attribute" field must have a value.',
'gt' => [
'numeric' => 'The ":attribute" must be greater than :value.',
'file' => 'The ":attribute" must be greater than :value kilobytes.',
'string' => 'The ":attribute" must be greater than :value characters.',
'array' => 'The ":attribute" must have more than :value items.',
],
'gte' => [
'numeric' => 'The ":attribute" must be greater than or equal :value.',
'file' => 'The ":attribute" must be greater than or equal :value kilobytes.',
'string' => 'The ":attribute" must be greater than or equal :value characters.',
'array' => 'The ":attribute" must have :value items or more.',
],
'image' => 'The ":attribute" must be an image.',
'in' => 'Das Feld ":attribute" ist ungültig.',
'in_array' => 'The ":attribute" field does not exist in :other.',
'integer' => 'The ":attribute" must be an integer.',
'ip' => 'The ":attribute" must be a valid IP address.',
'ipv4' => 'The ":attribute" must be a valid IPv4 address.',
'ipv6' => 'The ":attribute" must be a valid IPv6 address.',
'json' => 'The ":attribute" must be a valid JSON string.',
'lt' => [
'numeric' => 'The ":attribute" must be less than :value.',
'file' => 'The ":attribute" must be less than :value kilobytes.',
'string' => 'The ":attribute" must be less than :value characters.',
'array' => 'The ":attribute" must have less than :value items.',
],
'lte' => [
'numeric' => 'The ":attribute" must be less than or equal :value.',
'file' => 'The ":attribute" must be less than or equal :value kilobytes.',
'string' => 'The ":attribute" must be less than or equal :value characters.',
'array' => 'The ":attribute" must not have more than :value items.',
],
'max' => [
'numeric' => 'The ":attribute" must not be greater than :max.',
'file' => 'The ":attribute" must not be greater than :max kilobytes.',
'string' => 'The ":attribute" must not be greater than :max characters.',
'array' => 'The ":attribute" must not have more than :max items.',
],
'mimes' => 'The ":attribute" must be a file of type: :values.',
'mimetypes' => 'The ":attribute" must be a file of type: :values.',
'min' => [
'numeric' => 'The ":attribute" must be at least :min.',
'file' => 'The ":attribute" must be at least :min kilobytes.',
'string' => 'The ":attribute" must be at least :min characters.',
'array' => 'The ":attribute" must have at least :min items.',
],
'multiple_of' => 'The ":attribute" must be a multiple of :value.',
'not_in' => 'The selected ":attribute" is invalid.',
'not_regex' => 'The ":attribute" format is invalid.',
'numeric' => 'The ":attribute" must be a number.',
'password' => 'The password is incorrect.',
'present' => 'The ":attribute" field must be present.',
'regex' => 'The ":attribute" format is invalid.',
'required' => 'Das Feld ":attribute" ist ein Pflichtfeld.',
'required_if' => 'The ":attribute" field is required when :other is :value.',
'required_unless' => 'The ":attribute" field is required unless :other is in :values.',
'required_with' => 'The ":attribute" field is required when :values is present.',
'required_with_all' => 'The ":attribute" field is required when :values are present.',
'required_without' => 'The ":attribute" field is required when :values is not present.',
'required_without_all' => 'The ":attribute" field is required when none of :values are present.',
'same' => 'The ":attribute" and :other must match.',
'size' => [
'numeric' => 'The ":attribute" must be :size.',
'file' => 'The ":attribute" must be :size kilobytes.',
'string' => 'The ":attribute" must be :size characters.',
'array' => 'The ":attribute" must contain :size items.',
],
'starts_with' => 'The ":attribute" must start with one of the following: :values.',
'string' => 'The ":attribute" must be a string.',
'timezone' => 'The ":attribute" must be a valid zone.',
'unique' => 'The ":attribute" has already been taken.',
'uploaded' => 'The ":attribute" failed to upload.',
'url' => 'The ":attribute" format is invalid.',
'uuid' => 'The ":attribute" must be a valid UUID.',
/*
|--------------------------------------------------------------------------
| Custom Validation Language Lines
|--------------------------------------------------------------------------
|
| Here you may specify custom validation messages for attributes using the
| convention "attribute.rule" to name the lines. This makes it quick to
| specify a specific custom language line for a given attribute rule.
|
*/
'custom' => [
'attribute-name' => [
'rule-name' => 'custom-message',
],
],
/*
|--------------------------------------------------------------------------
| Custom Validation Attributes
|--------------------------------------------------------------------------
|
| The following language lines are used to swap our attribute placeholder
| with something more reader friendly such as "E-Mail Address" instead
| of "email". This simply helps us make our message more expressive.
|
*/
'attributes' => [],
];

View File

@@ -0,0 +1,52 @@
<?php
return [
"domain" => "Domain",
"domains" => "Domains",
"name" => "Name",
"type" => "Typ",
"content" => "Inhalt",
"ttl" => "TTL",
"delete" => "Löschen",
"delete_record" => "Record löschen",
"delete_domain" => "Domain löschen",
"add_record" => "Record hinzufügen",
"edit_record" => "Record bearbeiten",
"last_update" => "Letztes Update",
"last_update_text_hours" => "Letztes Update: :date (vor :hours Stunde)|Letztes Update: :date (vor :hours Stunden)",
"last_update_text_minutes" => "Letztes Update: :date (vor :minutes Minute)|Letztes Update: :date (vor :minutes Minuten)",
"update_records" => "Records aktualisieren",
"never" => "noch nie",
"update_disabled_text" => "Update nur alle :minutes Minuten möglich",
"no_data_available_header" => "Keine Daten vorhanden",
"no_data_available_body" => "Es sind keine Daten vorhanden",
"no_records_available_header" => "Keine Records vorhanden",
"no_records_available_body" => "Für diese Domain sind keine Records vorhanden",
"save" => "Speichern",
"add_domain" => "Domain hinzufügen",
"no_domains_text_header" => "Keine Domains eingetragen",
"no_domains_text_body" => "Es sind keine Domains eingetragen",
"swal_delete_record_sure_1" => "Bist du sicher, dass der Record ",
"swal_delete_record_sure_2" => " gelöscht werden soll",
"swal_delete_record_yes" => "Ja, Record löschen",
"swal_delete_domain_sure_1" => "Bist du sicher, dass die Domain ",
"swal_delete_domain_sure_2" => " gelöscht werden soll",
"swal_delete_domain_yes" => "Ja, Domain löschen",
"cancel" => "Abbrechen",
"success" => "Erfolgreich",
"error" => "Fehler",
"close" => "Schließen",
"language" => "Sprache",
"german" => "Deutsch",
"english" => "Englisch",
"record_type_not_supported" => "Hinweis: Die ServerCow API unterstützt das hinzufügen von :type Records (noch) nicht",
"edit" => "Bearbeiten",
"username" => "Benutzername",
"password" => "Passwort",
"login" => "Login",
"logout" => "Logout",
"remember_me" => "Angemeldet bleiben",
"change_password" => "Passwort ändern",
"old_password" => "Aktuelles Passwort",
"new_password" => "Neues Passwort",
];

View File

@@ -0,0 +1,20 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Authentication Language Lines
|--------------------------------------------------------------------------
|
| The following language lines are used during authentication for various
| messages that we need to display to the user. You are free to modify
| these language lines according to your application's requirements.
|
*/
'failed' => 'These credentials do not match our records.',
'password' => 'The provided password is incorrect.',
'throttle' => 'Too many login attempts. Please try again in :seconds seconds.',
];

View File

@@ -0,0 +1,30 @@
<?php
return [
"err_lang_code_not_found" => "The country code :code is not valid!",
"suc_lang_set" => "The language has been changed successfully!",
"error_saving_domain" => "Error while saving the domain: :error",
"suc_saving_domain" => "The Domain has been saved successfully!",
"error_saving_record" => "Error while saving the record: :error",
"suc_saving_record" => "The Record has been saved successfully!",
"error_deleting_record" => "Error while deleting the record: :error",
"suc_deleting_record" => "The record :record has been deleted successfully!",
"error_editing_record" => "Error while editing the record: :error",
"suc_editing_record" => "The record has been saved successfully!",
"error_fetching_records" => "Error while fetching new records: :error",
"suc_fetching_records" => "Records for the domain :domain updated successfully!",
"error_deleting_domain" => "Error while deleting the domain: :error",
"suc_deleting_domain" => "The domain :domain has been deleted successfully!",
"err_user_existing" => "A user with this user name already exists!",
"error_creating_user" => "Error while creating user: :error",
"suc_creating_user" => "The user :username has been created successfully!",
"error_no_user" => "There is no user with the user name :username!",
"error_deleting_user" => "Error while deleting user: :error",
"suc_deleting_user" => "The user :username has been deleted successfully!",
"suc_logout" => "You have successfully logged out!",
"suc_login" => "Successfully logged in!",
"err_login" => "Error logging in! Please check your data!",
"old_password_incorrect" => "The current password is incorrect!",
"error_changing_password" => "Error while changing password: :error",
"suc_changing_password" => "The password has been changed successfully!",
];

View File

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

View File

@@ -0,0 +1,22 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Password Reset Language Lines
|--------------------------------------------------------------------------
|
| The following language lines are the default lines which match reasons
| that are given by the password broker for a password update attempt
| has failed, such as for an invalid token or invalid new password.
|
*/
'reset' => 'Your password has been reset!',
'sent' => 'We have emailed your password reset link!',
'throttled' => 'Please wait before retrying.',
'token' => 'This password reset token is invalid.',
'user' => "We can't find a user with that email address.",
];

View File

@@ -0,0 +1,152 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Validation Language Lines
|--------------------------------------------------------------------------
|
| The following language lines contain the default error messages used by
| the validator class. Some of these rules have multiple versions such
| as the size rules. Feel free to tweak each of these messages here.
|
*/
'accepted' => 'The :attribute must be accepted.',
'active_url' => 'The :attribute is not a valid URL.',
'after' => 'The :attribute must be a date after :date.',
'after_or_equal' => 'The :attribute must be a date after or equal to :date.',
'alpha' => 'The :attribute must only contain letters.',
'alpha_dash' => 'The :attribute must only contain letters, numbers, dashes and underscores.',
'alpha_num' => 'The :attribute must only contain letters and numbers.',
'array' => 'The :attribute must be an array.',
'before' => 'The :attribute must be a date before :date.',
'before_or_equal' => 'The :attribute must be a date before or equal to :date.',
'between' => [
'numeric' => 'The :attribute must be between :min and :max.',
'file' => 'The :attribute must be between :min and :max kilobytes.',
'string' => 'The :attribute must be between :min and :max characters.',
'array' => 'The :attribute must have between :min and :max items.',
],
'boolean' => 'The :attribute field must be true or false.',
'confirmed' => 'The :attribute confirmation does not match.',
'date' => 'The :attribute is not a valid date.',
'date_equals' => 'The :attribute must be a date equal to :date.',
'date_format' => 'The :attribute does not match the format :format.',
'different' => 'The :attribute and :other must be different.',
'digits' => 'The :attribute must be :digits digits.',
'digits_between' => 'The :attribute must be between :min and :max digits.',
'dimensions' => 'The :attribute has invalid image dimensions.',
'distinct' => 'The :attribute field has a duplicate value.',
'email' => 'The :attribute must be a valid email address.',
'ends_with' => 'The :attribute must end with one of the following: :values.',
'exists' => 'The selected :attribute is invalid.',
'file' => 'The :attribute must be a file.',
'filled' => 'The :attribute field must have a value.',
'gt' => [
'numeric' => 'The :attribute must be greater than :value.',
'file' => 'The :attribute must be greater than :value kilobytes.',
'string' => 'The :attribute must be greater than :value characters.',
'array' => 'The :attribute must have more than :value items.',
],
'gte' => [
'numeric' => 'The :attribute must be greater than or equal :value.',
'file' => 'The :attribute must be greater than or equal :value kilobytes.',
'string' => 'The :attribute must be greater than or equal :value characters.',
'array' => 'The :attribute must have :value items or more.',
],
'image' => 'The :attribute must be an image.',
'in' => 'The selected :attribute is invalid.',
'in_array' => 'The :attribute field does not exist in :other.',
'integer' => 'The :attribute must be an integer.',
'ip' => 'The :attribute must be a valid IP address.',
'ipv4' => 'The :attribute must be a valid IPv4 address.',
'ipv6' => 'The :attribute must be a valid IPv6 address.',
'json' => 'The :attribute must be a valid JSON string.',
'lt' => [
'numeric' => 'The :attribute must be less than :value.',
'file' => 'The :attribute must be less than :value kilobytes.',
'string' => 'The :attribute must be less than :value characters.',
'array' => 'The :attribute must have less than :value items.',
],
'lte' => [
'numeric' => 'The :attribute must be less than or equal :value.',
'file' => 'The :attribute must be less than or equal :value kilobytes.',
'string' => 'The :attribute must be less than or equal :value characters.',
'array' => 'The :attribute must not have more than :value items.',
],
'max' => [
'numeric' => 'The :attribute must not be greater than :max.',
'file' => 'The :attribute must not be greater than :max kilobytes.',
'string' => 'The :attribute must not be greater than :max characters.',
'array' => 'The :attribute must not have more than :max items.',
],
'mimes' => 'The :attribute must be a file of type: :values.',
'mimetypes' => 'The :attribute must be a file of type: :values.',
'min' => [
'numeric' => 'The :attribute must be at least :min.',
'file' => 'The :attribute must be at least :min kilobytes.',
'string' => 'The :attribute must be at least :min characters.',
'array' => 'The :attribute must have at least :min items.',
],
'multiple_of' => 'The :attribute must be a multiple of :value.',
'not_in' => 'The selected :attribute is invalid.',
'not_regex' => 'The :attribute format is invalid.',
'numeric' => 'The :attribute must be a number.',
'password' => 'The password is incorrect.',
'present' => 'The :attribute field must be present.',
'regex' => 'The :attribute format is invalid.',
'required' => 'The :attribute field is required.',
'required_if' => 'The :attribute field is required when :other is :value.',
'required_unless' => 'The :attribute field is required unless :other is in :values.',
'required_with' => 'The :attribute field is required when :values is present.',
'required_with_all' => 'The :attribute field is required when :values are present.',
'required_without' => 'The :attribute field is required when :values is not present.',
'required_without_all' => 'The :attribute field is required when none of :values are present.',
'same' => 'The :attribute and :other must match.',
'size' => [
'numeric' => 'The :attribute must be :size.',
'file' => 'The :attribute must be :size kilobytes.',
'string' => 'The :attribute must be :size characters.',
'array' => 'The :attribute must contain :size items.',
],
'starts_with' => 'The :attribute must start with one of the following: :values.',
'string' => 'The :attribute must be a string.',
'timezone' => 'The :attribute must be a valid zone.',
'unique' => 'The :attribute has already been taken.',
'uploaded' => 'The :attribute failed to upload.',
'url' => 'The :attribute format is invalid.',
'uuid' => 'The :attribute must be a valid UUID.',
/*
|--------------------------------------------------------------------------
| Custom Validation Language Lines
|--------------------------------------------------------------------------
|
| Here you may specify custom validation messages for attributes using the
| convention "attribute.rule" to name the lines. This makes it quick to
| specify a specific custom language line for a given attribute rule.
|
*/
'custom' => [
'attribute-name' => [
'rule-name' => 'custom-message',
],
],
/*
|--------------------------------------------------------------------------
| Custom Validation Attributes
|--------------------------------------------------------------------------
|
| The following language lines are used to swap our attribute placeholder
| with something more reader friendly such as "E-Mail Address" instead
| of "email". This simply helps us make our message more expressive.
|
*/
'attributes' => [],
];

View File

@@ -0,0 +1,52 @@
<?php
return [
"domain" => "Domain",
"domains" => "Domains",
"name" => "Name",
"type" => "Type",
"content" => "Content",
"ttl" => "TTL",
"delete" => "Delete",
"delete_record" => "Delete Record",
"delete_domain" => "Delete Domain",
"add_record" => "Add Record",
"edit_record" => "Edit Record",
"last_update" => "Last Update",
"last_update_text_hours" => "Last update: :date (:hours Hour ago)|Last update: :date (:hours Hours ago)",
"last_update_text_minutes" => "Last update: :date (:minutes Minute ago)|Last update: :date (:minutes Minutes ago)",
"update_records" => "Update Records",
"never" => "never",
"update_disabled_text" => "Update available every :minutes Minutes",
"no_data_available_header" => "No data available",
"no_data_available_body" => "There is no data available",
"no_records_available_header" => "No records available",
"no_records_available_body" => "There are no records for this domain",
"save" => "Save",
"add_domain" => "Add Domain",
"no_domains_text_header" => "No domains saved",
"no_domains_text_body" => "There are no domains saved",
"swal_delete_record_sure_1" => "Are you sure that you want to delete the record ",
"swal_delete_record_sure_2" => "",
"swal_delete_record_yes" => "Yes, delete record",
"swal_delete_domain_sure_1" => "Are you sure that you want to delete the domain ",
"swal_delete_domain_sure_2" => "",
"swal_delete_domain_yes" => "Yes, delete domain",
"cancel" => "Cancel",
"success" => "Success",
"error" => "Error",
"close" => "Close",
"language" => "Language",
"german" => "German",
"english" => "English",
"record_type_not_supported" => "Note: The ServerCow API does not support adding :type Records (yet)",
"edit" => "Edit",
"username" => "Username",
"password" => "Password",
"login" => "Login",
"logout" => "Logout",
"remember_me" => "Remember me",
"change_password" => "Change password",
"old_password" => "Current password",
"new_password" => "New password",
];

View File

@@ -0,0 +1,29 @@
@extends('layout.main')
@section('title', $title)
@section('content')
<form action="{{ Route("auth-password-change.post") }}" method="post">
<div class="field">
<label for="old_password" class="label">{{ __("views.old_password") }}</label>
<div class="control">
<input type="password" name="old_password" id="old_password" class="input" placeholder="{{ __("views.old_password") }}" required>
</div>
</div>
<div class="field">
<label for="new_password" class="label">{{ __("views.new_password") }}</label>
<div class="control">
<input type="password" name="new_password" id="new_password" class="input" placeholder="{{ __("views.new_password") }}" required>
</div>
</div>
{{ csrf_field() }}
<div class="field">
<div class="control">
<button class="button is-link">{{ __("views.change_password") }}</button>
</div>
</div>
</form>
@endsection

View File

@@ -0,0 +1,35 @@
@extends('layout.main')
@section('title', $title)
@section('content')
<form action="{{ Route("auth-login.post") }}" method="post">
<div class="field">
<label for="username" class="label">{{ __("views.username") }}</label>
<div class="control">
<input type="text" name="username" id="username" class="input" placeholder="{{ __("views.username") }}" value="{{ Request::old('username') }}" required>
</div>
</div>
<div class="field">
<label for="password" class="label">{{ __("views.password") }}</label>
<div class="control">
<input type="password" name="password" id="password" class="input" placeholder="{{ __("views.password") }}" required>
</div>
</div>
<div class="field">
<label class="checkbox">
<input type="checkbox" name="remember"> {{ __("views.remember_me") }}
</label>
</div>
{{ csrf_field() }}
<div class="field">
<div class="control">
<button class="button is-link">{{ __("views.login") }}</button>
</div>
</div>
</form>
@endsection

View File

@@ -0,0 +1,68 @@
@extends('layout.main')
@section('title', $title)
@section('content')
<div class="card">
<div class="card-header">
<p class="card-header-title">{{ __("views.add_domain") }}</p>
</div>
<div class="card-content">
<form action="{{ Route("domains.add") }}" method="post">
<div class="field">
<label for="name" class="label">{{ __("views.name") }}</label>
<div class="control">
<input type="text" name="name" id="name" class="input" placeholder="{{ __('views.name') }}" autofocus required>
</div>
</div>
{{ csrf_field() }}
<div class="field">
<div class="control">
<button class="button is-link">{{ __("views.save") }}</button>
</div>
</div>
</form>
</div>
</div>
<hr>
@if($domains->isEmpty())
<article class="message is-warning">
<div class="message-header">
<p>{{ __("views.no_domains_text_header") }}!</p>
</div>
<div class="message-body">
{{ __("views.no_domains_text_body") }}!
</div>
</article>
@else
Domains: {{ $domains->count() }}
<table class="table is-bordered is-striped is-hoverable is-fullwidth">
<thead>
<tr>
<th>{{ __("views.domain") }}</th>
<th>{{ __("views.delete") }}</th>
</tr>
</thead>
<tbody>
@foreach($domains as $domain)
<tr>
<td>{{ $domain->name }}</td>
<td>
<form action="{{ Route("domains.delete") }}" method="post">
<input type="hidden" name="domain_name" value="{{ $domain->name }}">
<input type="hidden" name="domain_id" value="{{ $domain->id }}">
{{ csrf_field() }}
<span class="delete-btn" aria-label="{{ __("views.delete_domain") }}" data-microtip-position="top" data-name="{{ $domain->name }}" data-delete="domain" role="tooltip"><i class="fas fa-trash-alt"></i></span>
</form>
</td>
</tr>
@endforeach
</tbody>
</table>
@endif
@endsection

View File

@@ -0,0 +1,119 @@
@extends('layout.main')
@section('title', $title)
@section('content')
@if($domains->isEmpty())
@else
@include('modals.record-edit')
<div class="select" id="domain-select">
<div class="field is-horizontal">
<div class="field-label">
<label class="label" for="select_domain">{{ __("views.domain") }}</label>
</div>
<div class="field-body">
<select id="select_domain">
@foreach($domains as $domain)
<option value="{{ $domain->id }}">{{ $domain->name }}</option>
@endforeach
</select>
</div>
</div>
</div>
<hr>
@foreach($domains as $domain)
<nav class="panel domain-panel domain-panel-{{ $domain->id }} {{ $loop->first ? 'is-active' : 'is-hidden' }}">
<p class="panel-heading">{{ __("views.domain") }}: {{ $domain->name }}</p>
<!-- TODO: Check for Domain specific records -->
@if($records->isEmpty())
<div class="panel-block">
<article class="message is-warning">
<div class="message-header">
<p>{{ __("views.no_data_available_header") }}!</p>
</div>
<div class="message-body">
{{ __("views.no_data_available_body") }}!
</div>
</article>
</div>
@elseif(empty($recordCount[$domain->id]))
<div class="panel-block">
<article class="message is-warning">
<div class="message-header">
<p>{{ __("views.no_records_available_header") }}!</p>
</div>
<div class="message-body">
{{ __("views.no_records_available_body") }}!<br />
<a href="{{ Route('records.add') }}?domain={{ $domain->id }}">{{ __("views.add_record") }}</a>
</div>
</article>
</div>
@else
<div class="panel-block">
<table id="overviewTable-{{ $domain->id }}" class="table is-bordered is-striped is-hoverable is-fullwidth record-table">
<thead>
<tr>
<th>{{ __("views.name") }}</th>
<th>{{ __("views.type") }}</th>
<th>{{ __("views.content") }}</th>
<th>{{ __("views.ttl") }}</th>
<th>{{ __("views.edit") }}</th>
<th>{{ __("views.delete") }}</th>
</tr>
</thead>
<tbody>
@foreach($records as $record)
@if($record->domains_id == $domain->id)
<tr>
<td>{{ $record->name }}
<td>{{ $record->type }}</td>
<td>
{{ \Illuminate\Support\Str::of($record->content)->limit(70) }}
@if($record->type == "SRV")
TTL: {{ explode(" ", $record->content)[0] }}
Priority: {{ explode(" ", $record->content)[1] }}
Port: {{ explode(" ", $record->content)[2] }}
Ziel: {{ explode(" ", $record->content)[3] }}
@endif
</td>
<td>{{ $record->ttl }}</td>
<td align="center"><span class="edit-btn" data-edit="record" data-url="{{ Route("records.data.json", ["id" => $record->id]) }}"><i class="far fa-edit"></i></span></td>
<td align="center">
<form action="{{ Route('records.delete') }}" method="post">
<input type="hidden" name="type" value="{{ $record->type }}">
<input type="hidden" name="name" value="{{ $record->name }}">
<input type="hidden" name="domain_name" value="{{ $domain->name }}">
<input type="hidden" name="domain_id" value="{{ $domain->id }}">
{{ csrf_field() }}
<span class="delete-btn" aria-label="{{ __("views.delete_record") }}" data-microtip-position="top" data-name="{{ $record->name }}" data-delete="record" role="tooltip"><i class="fas fa-trash-alt"></i></span>
</form>
</td>
</tr>
@endif
@endforeach
</tbody>
</table>
</div>
@endif
@if(!empty($update[$domain->id]))
<div class="panel-block">
<p>{{ $update[$domain->id]["text"] }}</p>
</div>
<div class="panel-block">
<a class="button btn-refresh-records is-link" @if($update[$domain->id]["diff"]->i < env('RECORD_FETCH_LIMIT_MINUTES') and $update[$domain->id]["diff"]->h == 0) disabled aria-label="{{ __("views.update_disabled_text", ["minutes" => env('RECORD_FETCH_LIMIT_MINUTES')]) }}!" data-microtip-position="right" role="tooltip" @else href="{{ Route("fetch-records.get", ['domain' => $domain->name, 'id' => $domain->id]) }}" @endif><i class="fas fa-sync"></i>&nbsp;{{ __("views.update_records") }}</a>
</div>
@else
<div class="panel-block">
<p>{{ __("views.last_update") }}: {{ __("views.never") }}</p>
</div>
<div class="panel-block">
<a class="button btn-refresh-records is-link" href="{{ Route("fetch-records.get", ['domain' => $domain->name, 'id' => $domain->id]) }}"><i class="fas fa-sync"></i>&nbsp;{{ __("views.update_records") }}</a>
</div>
@endif
</nav>
@endforeach
@endif
@endsection

View File

@@ -0,0 +1,36 @@
@if(Session::has('Success_Message'))
<script>
var message = "{{ Session::get('Success_Message') }}";
swal({
title: "{{ __('views.success') }}",
html: message,
type: 'success',
confirmButtonText: "{{ __('views.close') }}"
})
</script>
@elseif(Session::has('Error_Message'))
<script>
var message = "{{ Session::get('Error_Message') }}";
swal({
title: "{{ __('views.error') }}",
html: message,
type: 'error',
confirmButtonText: "{{ __("views.close") }}"
})
</script>
@endif
@if(count($errors) > 0)
<article class="message is-danger" id="error-container">
<div class="message-header">
<p>{{ __("views.error") }}</p>
<button class="delete" aria-label="delete"></button>
</div>
<div class="message-body">
<ul>
@foreach($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
</article>
@endif

View File

@@ -0,0 +1,45 @@
<!doctype html>
<html lang="{{ \App\Http\Controllers\LanguageController::getActiveLanguage() }}">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>{{ env('APP_NAME') }} | @yield('title')</title>
<script src="https://cdn.jsdelivr.net/sweetalert2/1.3.2/sweetalert2.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/chart.js@2.9.4/dist/Chart.min.js"></script>
<link rel="stylesheet" href="/css/app.css">
</head>
<body class="page-{{ strtolower(str_replace(" ", "_", $title)) }}">
<section id="section-navbar">
<div class="container">@include('layout.nav')</div>
</section>
<section class="section">
<div class="container">
@include('layout.alerts')
<h1 class="title">@yield('title')</h1>
@yield('content')
</div>
</section>
<script defer src="{{ URL::asset("js/libs/fontawesome-5.14.0.js") }}"></script>
<script src="{{ URL::asset("js/libs/moment.min.js") }}"></script>
<script src="{{ URL::asset("js/libs/jquery-3.5.1.min.js") }}"></script>
<script src="{{ URL::asset("js/libs/jquery.dataTables-1.10.23.min.js") }}"></script>
<script src="{{ URL::asset("js/libs/dataTables.bulma-1.10.23.min.js") }}"></script>
<script>
let swalDeleteRecordTitle = "{{ __("views.delete_record") }}";
let swalDeleteDomainTitle = "{{ __("views.delete_domain") }}"
let swalDeleteRecordText1 = "{{ __("views.swal_delete_record_sure_1") }}";
let swalDeleteRecordText2 = "{{ __("views.swal_delete_record_sure_2") }}";
let swalDeleteRecordYes = "{{ __("views.swal_delete_record_yes") }}";
let swalDeleteDomainText1 = "{{ __("views.swal_delete_domain_sure_1") }}";
let swalDeleteDomainText2 = "{{ __("views.swal_delete_domain_sure_2") }}";
let swalDeleteDomainYes = "{{ __("views.swal_delete_domain_yes") }}";
let cancel = "{{ __("views.cancel") }}";
</script>
<script src="{{ URL::asset("js/main.js") }}"></script>
</body>
</html>

View File

@@ -0,0 +1,46 @@
<nav class="navbar is-link is-fixed-top" role="navigation" aria-label="main navigation">
<a role="button" id="mainBurger" class="navbar-burger" aria-label="menu" aria-expanded="false" data-target="mainNavbar">
<span aria-hidden="true"></span>
<span aria-hidden="true"></span>
<span aria-hidden="true"></span>
</a>
<div id="mainNavbar" class="navbar-menu">
@if(Auth::check())
<div class="navbar-start">
<a href="/" class="navbar-item">Home</a>
<a href="{{ Route('records.add') }}" class="navbar-item"><i class="far fa-plus-square"></i>&nbsp;{{ __("views.add_record") }}</a>
<a href="{{ Route('domains.get') }}" class="navbar-item"><i class="fas fa-globe"></i>&nbsp;{{ __("views.domains") }}</a>
</div>
@endif
<div class="navbar-end">
<div class="navbar-item has-dropdown is-hoverable">
<a class="navbar-link">
{{ __("views.language") }}
</a>
<div class="navbar-dropdown">
<a href="{{ Route("language.set", ["code" => "de"]) }}" class="navbar-item {{ \App\Http\Controllers\LanguageController::getActiveLanguage() == 'de' ? 'lang-active' : '' }}"><span class="flag flag-xs" lang="de"></span>&nbsp;{{ __("views.german") }}</a>
<a href="{{ Route("language.set", ["code" => "en"]) }}" class="navbar-item {{ \App\Http\Controllers\LanguageController::getActiveLanguage() == 'en' ? 'lang-active' : '' }}"><span class="flag flag-xs" lang="en"></span>&nbsp;{{ __("views.english")}}</a>
</div>
</div>
@if(Auth::check())
<div class="navbar-item has-dropdown is-hoverable">
<a class="navbar-link">
<i class="fas fa-user"></i>&nbsp;{{ Auth::user()->username }}
</a>
<div class="navbar-dropdown is-right">
<a href="{{ Route("auth-password-change.get") }}" class="navbar-item"><i class="fas fa-key"></i>&nbsp;{{ __("views.change_password") }}</a>
<hr class="navbar-divider">
<a href="{{ Route("auth-logout.get") }}" class="navbar-item"><i class="fas fa-sign-out-alt"></i>&nbsp;{{ __("views.logout") }}</a>
</div>
</div>
@else
<a href="{{ Route('auth-login.get') }}" class="navbar-item">Login</a>
@endif
</div>
</div>
</nav>

View File

@@ -0,0 +1,50 @@
<div class="modal" id="recordEditModal">
<div class="modal-background"></div>
<div class="modal-card">
<header class="modal-card-head">
<p class="modal-card-title">{{ __("views.edit_record") }}</p>
<button class="delete modal-closer" aria-label="close"></button>
</header>
<section class="modal-card-body">
<form action="{{ Route("records.edit") }}" method="post">
<input type="hidden" name="record_id" id="edit_record_id">
<div class="field">
<label for="edit_name">{{ __("views.name") }}</label>
<div class="control">
<input type="text" name="name" id="edit_name" class="input" disabled>
</div>
</div>
<div class="field">
<label for="edit_type">{{ __("views.type") }}</label>
<div class="control">
<input type="text" name="type" id="edit_type" class="input" disabled>
</div>
</div>
<div class="field">
<label for="edit_content">{{ __("views.content") }}</label>
<div class="control">
<input type="text" name="content" id="edit_content" class="input">
</div>
</div>
<div class="field">
<label for="edit_ttl">{{ __("views.ttl") }}</label>
<div class="control">
<input type="number" name="ttl" id="edit_ttl" class="input">
</div>
</div>
{{ csrf_field() }}
<div class="field">
<div class="control">
<button class="button is-link">{{ __("views.save") }}</button>
</div>
</div>
</form>
</section>
</div>
</div>

View File

@@ -0,0 +1,66 @@
@extends('layout.main')
@section('title', $title)
@section('content')
<form action="{{ Route("records.add") }}" method="post">
<div class="field">
<label for="domain" class="label">{{ __("views.domain") }}</label>
<div class="control">
<div class="select">
<select name="domain" id="domain">
@foreach($domains as $domain)
<option value="{{ $domain->id }}">{{ $domain->name }}</option>
@endforeach
</select>
</div>
</div>
</div>
<div class="field">
<label for="type" class="label">{{ __("views.type") }}</label>
<div class="control">
<div class="select">
<select name="type" id="type">
<option value="a">A</option>
<option value="aaaa">AAAA</option>
<option value="cname">CNAME</option>
<option value="mx">MX</option>
<option value="txt">TXT</option>
<option value="tlsa">TLSA</option>
<option value="caa">CAA</option>
</select>
</div>
</div>
</div>
<div class="field">
<label for="name" class="label">{{ __("views.name") }}</label>
<div class="control">
<input type="text" name="name" id="name" class="input" placeholder="{{ __('views.name') }}">
</div>
</div>
<div class="field">
<label for="content" class="label">{{ __("views.content") }}</label>
<div class="control">
<input type="text" name="content" id="content" class="input" placeholder="{{ __('views.content') }}" required>
</div>
</div>
<div class="field">
<label for="ttl" class="label">{{ __("views.ttl") }}</label>
<div class="control">
<input type="number" value="20" name="ttl" id="ttl" class="input" placeholder="{{ __('views.ttl') }}" required>
</div>
</div>
{{ csrf_field() }}
<div class="field">
<div class="control">
<button class="button is-link">{{ __("views.save") }}</button>
</div>
</div>
</form>
@endsection