diff --git a/flexiapi/app/Http/Controllers/Admin/AccountController.php b/flexiapi/app/Http/Controllers/Admin/AccountController.php
index f9d0a9a..0ef7cec 100644
--- a/flexiapi/app/Http/Controllers/Admin/AccountController.php
+++ b/flexiapi/app/Http/Controllers/Admin/AccountController.php
@@ -34,8 +34,13 @@ class AccountController extends Controller
{
public function index(Request $request)
{
- $accounts = Account::orderBy('updated_at', $request->get('updated_at_order', 'desc'))
- ->with('externalAccount');
+ $request->validate([
+ 'order_by' => 'in:username,updated_at',
+ 'order_sort' => 'in:asc,desc',
+ ]);
+
+ $accounts = Account::with('externalAccount', 'contactsLists')
+ ->orderBy($request->get('order_by', 'updated_at'), $request->get('order_sort', 'desc'));
if ($request->has('search')) {
$accounts = $accounts->where('username', 'like', '%' . $request->get('search') . '%');
@@ -45,17 +50,26 @@ class AccountController extends Controller
$accounts->whereDate('updated_at', $request->get('updated_date'));
}
+ if ($request->has('contacts_list')) {
+ $accounts->whereHas('contactsLists', function ($query) use ($request) {
+ $query->where('id', $request->get('contacts_list'));
+ });
+ }
+
+ if ($request->has('domain')) {
+ $accounts->where('domain', $request->get('domain'));
+ }
+
return view('admin.account.index', [
- 'search' => $request->get('search'),
- 'updated_date' => $request->get('updated_date'),
+ 'domains' => Account::groupBy('domain')->pluck('domain'),
+ 'contacts_lists' => ContactsList::all()->pluck('title', 'id'),
'accounts' => $accounts->paginate(20)->appends($request->query()),
- 'updated_at_order' => $request->get('updated_at_order') == 'desc' ? 'asc' : 'desc'
]);
}
public function search(Request $request)
{
- return redirect()->route('admin.account.index', $request->except('_token'));
+ return redirect()->route('admin.account.index', $request->except('_token', 'query'));
}
public function create(Request $request)
diff --git a/flexiapi/app/Http/Controllers/Admin/ContactsListController.php b/flexiapi/app/Http/Controllers/Admin/ContactsListController.php
index d995e6a..c1bb0fe 100644
--- a/flexiapi/app/Http/Controllers/Admin/ContactsListController.php
+++ b/flexiapi/app/Http/Controllers/Admin/ContactsListController.php
@@ -28,11 +28,17 @@ class ContactsListController extends Controller
{
public function index(Request $request)
{
+ $request->validate([
+ 'order_by' => 'in:title,updated_at,contacts_count',
+ 'order_sort' => 'in:asc,desc',
+ ]);
+
+ $contactsLists = ContactsList::orderBy($request->get('order_by', 'updated_at'), $request->get('order_sort', 'desc'));
+
return view('admin.contacts_list.index', [
- 'contacts_lists' => ContactsList::orderBy('updated_at', $request->get('updated_at_order', 'desc'))
+ 'contacts_lists' => $contactsLists
->paginate(20)
->appends($request->query()),
- 'updated_at_order' => $request->get('updated_at_order') == 'desc' ? 'asc' : 'desc'
]);
}
diff --git a/flexiapi/app/Services/AccountService.php b/flexiapi/app/Services/AccountService.php
index 1dd833c..3a9fc32 100644
--- a/flexiapi/app/Services/AccountService.php
+++ b/flexiapi/app/Services/AccountService.php
@@ -122,14 +122,23 @@ class AccountService
public function updatePhone(Request $request): ?Account
{
- $request->validate([
+ $request->validate($this->api ? [
'code' => 'required|digits:4'
+ ] : [
+ 'number_1' => 'required|digits:1',
+ 'number_2' => 'required|digits:1',
+ 'number_3' => 'required|digits:1',
+ 'number_4' => 'required|digits:1'
]);
+ $code = $this->api ? $request->get('code')
+ : $request->get('number_1') . $request->get('number_2') . $request->get('number_3') . $request->get('number_4');
+
$account = $request->user();
$phoneChangeCode = $account->phoneChangeCode()->firstOrFail();
- if ($phoneChangeCode->code == $request->get('code')) {
+
+ if ($phoneChangeCode->code == $code) {
$account->alias()->delete();
$alias = new Alias;
@@ -189,14 +198,22 @@ class AccountService
public function updateEmail(Request $request): ?Account
{
- $request->validate([
+ $request->validate($this->api ? [
'code' => 'required|digits:4'
+ ] : [
+ 'number_1' => 'required|digits:1',
+ 'number_2' => 'required|digits:1',
+ 'number_3' => 'required|digits:1',
+ 'number_4' => 'required|digits:1'
]);
+ $code = $this->api ? $request->get('code')
+ : $request->get('number_1') . $request->get('number_2') . $request->get('number_3') . $request->get('number_4');
+
$account = $request->user();
$emailChangeCode = $account->emailChangeCode()->firstOrFail();
- if ($emailChangeCode->validate($request->get('code'))) {
+ if ($emailChangeCode->validate($code)) {
$account->email = $emailChangeCode->email;
$account->save();
diff --git a/flexiapi/public/css/far.css b/flexiapi/public/css/far.css
index 3de339d..23840f4 100644
--- a/flexiapi/public/css/far.css
+++ b/flexiapi/public/css/far.css
@@ -333,11 +333,28 @@ content section {
box-sizing: border-box;
}
+content section.grid {
+ display: grid;
+ grid-template-columns: repeat(2, 1fr);
+ gap: 1rem;
+}
+
+@media screen and (max-width: 800px) {
+ content section.grid {
+ display: block;
+ }
+}
+
+content section.grid header,
+content section.grid .large {
+ grid-column: span 2;
+}
+
content section header {
display: flex;
gap: 1rem;
align-items: center;
- margin-bottom: 1rem;
+ margin-bottom: 3rem;
}
content section header p {
@@ -354,6 +371,7 @@ content section header > *.oppose {
content nav + section {
min-width: calc(80% - 20rem);
+ margin-bottom: 4rem;
}
/** Sidenav **/
@@ -490,6 +508,13 @@ h3 {
font-size: 1.75rem;
color: var(--second-6);
padding: 0.5rem 0;
+ font-weight: bold;
+}
+
+h3 i {
+ line-height: 2rem;
+ margin-right: 1rem;
+ vertical-align: middle;
}
h4 {
@@ -499,14 +524,20 @@ h4 {
}
p + h1, p + h2, p + h3, p + h4,
-ul + h1, ul + h2, ul + h3, ul + h4 {
+ul + h1, ul + h2, ul + h3, ul + h4, h3 + p {
margin-top: 1rem;
}
+.line {
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+}
+
/** Badge **/
.badge {
- background-color: var(--main-5);
+ background-color: var(--grey-4);
color: white;
border-radius: 0.5rem;
font-weight: 700;
@@ -540,17 +571,18 @@ table tr td a {
table tr td,
table tr th {
- line-height: 4rem;
- padding: 0 1rem;
+ padding: 1rem;
font-size: 1.5rem;
}
+table tr th {
+ padding: 0 1rem;
+ line-height: 4rem;
+}
+
table tr td.line,
table tr th.line {
- overflow: hidden;
- text-overflow: ellipsis;
- white-space: nowrap;
- max-width: 0;
+ max-width: 100%;
}
table tr th,
@@ -562,7 +594,7 @@ table tr th a {
}
table tr th a i {
- font-size: 3rem;
+ font-size: 2.5rem;
vertical-align: middle;
}
@@ -697,7 +729,7 @@ select.list_toggle {
}
.card {
- background-color: var(--grey-2);
+ background-color: var(--grey-1);
border-radius: 1rem;
padding: 1rem;
margin-bottom: 1rem;
@@ -711,4 +743,32 @@ select.list_toggle {
#chart {
min-height: 80vh;
+}
+
+/** Breadcrumb **/
+
+.breadcrumb {
+ margin-bottom: 2rem;
+}
+
+.breadcrumb li {
+ display: inline-block;
+ font-size: 1.5rem;
+ line-height: 2rem;
+}
+
+.breadcrumb li a {
+ color: var(--main-5);
+}
+
+.breadcrumb li.active {
+ color: var(--grey-5);
+}
+
+.breadcrumb li + li:before {
+ content: ">";
+ margin: 0 1rem;
+ font-size: 1rem;
+ line-height: 2rem;
+ display: inline-block;
}
\ No newline at end of file
diff --git a/flexiapi/public/css/form.css b/flexiapi/public/css/form.css
index fc35ab9..8310cfd 100644
--- a/flexiapi/public/css/form.css
+++ b/flexiapi/public/css/form.css
@@ -13,6 +13,10 @@
white-space: nowrap;
}
+p .btn {
+ margin: 0 1rem;
+}
+
.btn i {
margin-right: 0.5rem;
margin-left: -0.5rem;
@@ -79,7 +83,9 @@ form {
}
form.inline {
- display: block;
+ grid-template-columns: repeat(4, 1fr);
+ gap: 1rem;
+ margin-bottom: 2rem;
}
form div {
@@ -87,11 +93,34 @@ form div {
min-height: 4rem;
}
-form.inline div {
+form div .btn,
+form div a.chip {
+ margin-top: 2.5rem;
+}
+
+form div.oppose {
+ justify-content: right;
+}
+
+form div .btn,
+form div .chip {
display: inline-block;
- position: relative;
- margin-right: 1rem;
- margin-bottom: 1rem;
+ align-self: flex-end;
+}
+
+form div .chip {
+ line-height: 4.5rem;
+}
+
+form.inline div.large {
+ grid-column: span 2;
+ align-items: end;
+}
+
+@media screen and (max-width: 800px) {
+ form.inline div.large {
+ grid-column: span 4;
+ }
}
form .large,
@@ -105,7 +134,7 @@ form .disabled {
filter: blur(0.25rem);
}
-@media screen and (max-width: 1024px) {
+@media screen and (max-width: 800px) {
form div {
grid-column: 1/-1;
}
@@ -119,9 +148,18 @@ form small {
margin-top: 0.25rem;
}
+form small.error {
+ color: var(--danger-6);
+}
+
form label {
color: var(--second-6);
font-size: 1.5rem;
+
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ max-width: 100%;
}
form input[type="radio"]~label:after,
@@ -129,20 +167,15 @@ form input[required]+label:after {
content: '*';
}
-form input:not([type=checkbox]) ~ label,
-form textarea ~ label,
-form select ~ label {
+form input:not([type=checkbox])~label,
+form textarea~label,
+form select~label {
position: absolute;
top: 0;
left: 0;
font-weight: 700;
}
-form:not(.inline) div .btn {
- position: absolute;
- bottom: 0;
-}
-
form div .btn.oppose {
right: 0;
}
@@ -160,6 +193,7 @@ form div select {
form div select {
appearance: none;
+ padding-right: 4rem;
-moz-appearance: none;
-webkit-appearance: none;
}
@@ -168,11 +202,12 @@ form div.checkbox {
min-height: 2rem;
}
+form div.search:after,
form div.select:after {
font-family: 'Material Icons';
content: "\e5cf";
display: block;
- font-size: 3rem;
+ font-size: 2.5rem;
color: var(--second-6);
position: absolute;
right: 1rem;
@@ -181,6 +216,14 @@ form div.select:after {
line-height: 4rem;
}
+form div.search input {
+ padding-right: 4rem;
+}
+
+form div.search:after {
+ content: "\e8b6";
+}
+
form div input[disabled],
form div textarea[disabled] {
border-color: var(--grey-4);
@@ -195,6 +238,19 @@ form div textarea[readonly] {
background-color: var(--grey-2);
}
+input[type=number].digit {
+ font-size: 3rem;
+ width: 4rem;
+ height: 5rem;
+ -moz-appearance: textfield;
+ -webkit-appearance: textfield;
+ border-radius: 1.5rem;
+ background-color: white;
+ padding: 0.5rem;
+ text-align: center;
+ margin-right: 1rem;
+}
+
input[type=checkbox] {
accent-color: var(--main-5);
}
@@ -203,12 +259,13 @@ form div input[type=checkbox] {
margin-right: 1rem;
}
-form div input:not([type=checkbox]):not([type=radio]):not(.btn),
+form div input:not([type=checkbox]):not([type=radio]):not([type="number"].digit):not(.btn),
form div textarea,
form div select {
margin-top: 2.5rem;
box-sizing: border-box;
width: 100%;
+ height: max-content;
}
form div input[type=radio] {
@@ -218,7 +275,7 @@ form div input[type=radio] {
accent-color: var(--main-5);
}
-form div input[type=radio] + p {
+form div input[type=radio]+p {
display: inline-block;
}
diff --git a/flexiapi/public/scripts/utils.js b/flexiapi/public/scripts/utils.js
index 8210295..1cd117f 100644
--- a/flexiapi/public/scripts/utils.js
+++ b/flexiapi/public/scripts/utils.js
@@ -108,4 +108,10 @@ var ListToggle = {
document.addEventListener("DOMContentLoaded", function(event) {
ListToggle.init();
-});
\ No newline at end of file
+});
+
+function digitFilled(element) {
+ if (element.value.length == 1) {
+ element.nextElementSibling.focus();
+ }
+}
\ No newline at end of file
diff --git a/flexiapi/resources/views/account/dashboard.blade.php b/flexiapi/resources/views/account/dashboard.blade.php
index b5339ac..d1adea7 100644
--- a/flexiapi/resources/views/account/dashboard.blade.php
+++ b/flexiapi/resources/views/account/dashboard.blade.php
@@ -1,93 +1,101 @@
-@extends('layouts.main')
+@extends('layouts.main', ['grid' => true])
@section('content')
dashboard Dashboard
- email - @if (!empty($account->email)) - {{ $account->email }} - @else - No email yet - @endif - Change my current account email -
- -- call - @if (!empty($account->phone)) - {{ $account->phone }} - @else - No phone yet - @endif - Change my current account phone -
- @if (config('app.devices_management') == true) +- laptop - Manage my devices -
- @endif - -+ Change my current account email +
-- delete - Delete my account -
++ call + @if (!empty($account->phone)) + {{ $account->phone }} + @else + No phone yet + @endif + Change my current account phone +
+ @if (config('app.devices_management') == true) ++ laptop + Manage my devices +
+ @endif ++ lock + + @if ($account->passwords()->count() > 0) + Change my password + @else + Set my password + @endif + +
-alternate_email SIP address: sip:{{ $account->identifier }}
-person Username: {{ $account->username }}
-dns Domain: {{ $account->domain }}
- - @if (!empty(config('app.proxy_registrar_address'))) -lan Proxy/registrar address: sip:{{ config('app.proxy_registrar_address') }}
- @endif - @if (!empty(config('app.transport_protocol_text'))) -settings_ethernet Transport: {{ config('app.transport_protocol_text') }}
- @endif - - - -You can generate an API key and use it to request the different API endpoints, check - the related API documentation to know how to use that key.
- - {!! Form::open(['route' => 'account.api_key.generate']) !!} -+ delete + Delete my account +
alternate_email SIP address: sip:{{ $account->identifier }}
+person Username: {{ $account->username }}
+dns Domain: {{ $account->domain }}
+ + @if (!empty(config('app.proxy_registrar_address'))) +lan Proxy/registrar address: sip:{{ config('app.proxy_registrar_address') }} +
+ @endif + @if (!empty(config('app.transport_protocol_text'))) +settings_ethernet Transport: {{ config('app.transport_protocol_text') }}
+ @endif + + + +You can generate an API key and use it to request the different API endpoints, check + the related API documentation to know how to use that key.
+ + {!! Form::open(['route' => 'account.api_key.generate']) !!} +Please enter the verification code below:
Please enter the verification code below:
+
You already have an account? Login
- -+ You already have an account? + Login +
+ @include('parts.tabs.register') -- You already have an account? - Login -
+