ikinci temizlik tamamlandı

This commit is contained in:
Ümit Tunç
2026-04-28 21:15:09 +03:00
parent f80443aec0
commit 37e7296527
8313 changed files with 2400677 additions and 0 deletions
+203
View File
@@ -0,0 +1,203 @@
@extends('admin.master')
@section("title","Artisan")
@section("desc","")
@section('content')
<div class="content">
<div class="row">
{{col("col-md-6","Schema Generator")}}
<?php if(getisset("columns")) {
$columns = explode("\n", get("columns"));
$tableName = str_slug(get("table_name"),"_");
?>
<pre>
Schema::create('{{$tableName}}', function (Blueprint $table) {
$table->id();
$table->timestamps();
<?php foreach($columns AS $column) {
$column = trim($column);
$column = str_slug($column, '_');
if(strpos($column, "date") !== false) {
$type = "date";
} else {
$type = "string";
}
if($type == "string") {
?>$table->string('{{$column}}', 100)->nullable()->default(null);
<?php } else {
?>$table->date('{{$column}}')->nullable()->default(null);
<?php
} ?>
<?php
} ?>
});
</pre>
<?php
} ?>
<form action="?testa" method="get">
@csrf
Table Name:
<input type="text" name="table_name" id="" class="form-control">
Column List:
<textarea name="columns" id="" cols="30" rows="10" class="form-control"></textarea>
<button class="btn btn-primary">Generate Migration Schema</button>
</form>
{{_col()}}
{{col("col-md-6","Table Column To Array")}}
<?php if(getisset("table_name")) {
$columns = table_columns(get("table_name"));
?>
<div class="form-group">
<label>Generated Array:</label>
<textarea class="form-control" rows="7" readonly >[
<?php foreach($columns AS $column) {
$column = trim($column);
$column = str_slug($column, '_');
?>'{{$column}}',
<?php
} ?>
]</textarea>
<small class="text-muted">Click to select all</small>
</div>
<?php
} ?>
<form action="?array" method="get">
@csrf
Table Name:
<select name="table_name" id="tableSelect" class="form-control select2">
<option value="">Select a table</option>
@foreach(DB::select('SHOW TABLES') as $table)
@php
$tableName = array_values((array)$table)[0];
@endphp
<option value="{{ $tableName }}" {{ get("table_name") == $tableName ? 'selected' : '' }}>
{{ $tableName }}
</option>
@endforeach
</select>
<button class="btn btn-primary">Generate Table Column To Array</button>
</form>
{{_col()}}
{{col("col-md-6","Array")}}
<?php if(getisset("columns2")) {
$columns = explode("\n", get("columns2"));
?>
<pre>
[
<?php foreach($columns AS $column) {
$column = trim($column);
$column = str_slug($column, '_');
?>'{{$column}}',
<?php
} ?>
]
</pre>
<?php
} ?>
<form action="?array" method="get">
@csrf
Column List:
<textarea name="columns2" id="" cols="30" rows="10" class="form-control"></textarea>
<button class="btn btn-primary">Generate Array</button>
</form>
{{_col()}}
</div>
<div class="block">
<div class="block-header block-header-default">
<h3 class="block-title">{{__('Artisan Command Panel')}}</h3>
<div class="block-options">
</div>
</div>
<div class="block-content">
<?php if(getisset("command")) {
try {
dump(get("command"));
$command = str_replace("\\","/",get("command"));
Artisan::call($command);
$output = Artisan::output();
ekle2([
'title' => $command,
'html' => $output,
'type' => 'ARTISAN',
'kid' => 'ARTISAN'
],"contents");
dump($output);
} catch (\Throwable $th) {
dump($th);
}
} ?>
<form action="" method="get">
<?php $macros = [
'make:migration MigrationName',
'migrate:refresh --path=',
'make:model ModelName -a',
'cache:clear',
];
foreach($macros AS $macro) {
?>
<div class="btn btn-outline-success" onclick="$('#command').val($(this).text().trim()).focus()">{{$macro}}</div>
<?php } ?>
<div class="input-group">
<input type="text" name="command" value="{{get("command")}}" required id="command" class="form-control">
<button class="btn btn-primary"><i class="fa fa-cog"></i></button>
</div>
</form>
<div class="table-responsive">
<table class="table table-bordered">
<tr>
<th style="width:50%">Command</th>
<th>Output</th>
</tr>
<?php $query = db("contents")->where("type","ARTISAN")->orderBy("id","DESC")->simplePaginate(100);
foreach($query AS $q) {
?>
<tr>
<td><?php echo $q->title ?></td>
<td><textarea name="" id="" cols="30" rows="1" class="form-control"><?php echo $q->html ?></textarea></td>
</tr>
<?php } ?>
</table>
</div>
{{$query->links()}}
</div>
</div>
</div>
@endsection
@push('scripts')
<script>
$(document).ready(function() {
$('#tableSelect').select2({
placeholder: "Select a table",
allowClear: true
});
});
</script>
@endpush
@@ -0,0 +1,34 @@
@extends('admin.master')
@section("title",__('Ana İçerikler'))
@section("desc",__('Bu sayfada ana içerikler yer almakta'))
@section('content')
<div class="content">
<div class="block">
<div class="block-header block-header-default">
<h3 class="block-title">{{__('Ana İçerikler')}}</h3>
<div class="block-options">
<div class="block-options-item">
<div class="input-group">
<select name="" id="" class="types_select form-control">
@foreach($types AS $t)
<option value="{{$t->title}}">{{$t->title}}</option>
@endforeach
</select>
<div onclick="location.href='{{ url('admin-ajax/content-add?id=main&type=') }}'+$('.types_select').val()" class="input-group-append">
<button type="button" class="btn btn-secondary">{{__('Ekle')}}</button>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="row gutters-tiny draggable sortable">
@foreach($contents AS $a)
@include("admin.inc.block")
@endforeach
</div>
</div>
@endsection
+134
View File
@@ -0,0 +1,134 @@
<?php redirect("admin/new/types2")->send(); ?>
@extends('admin.master')
@section("title","Modules")
@section("desc","Bu sayfada içerik türlerini yönetebilirsiniz")
@section('content')
<div class="content">
<div class="block">
<div class="block-header block-header-default">
<h3 class="block-title">{{__('Modules')}}</h3>
<div class="block-options">
<div class="block-options-item">
<a href="{{ url('admin/action/add/types') }}" class="btn btn-default"><i class="fa fa-plus"></i></a>
</div>
</div>
</div>
<div class="block-content">
<div class="table-responsive">
<table class="table table-bordered table-striped table-hover">
<tr>
<th>{{e2("User No")}}</th>
<th>{{e2("Level")}}</th>
<th>{{e2("Delete")}}</th>
<th>{{e2("Write")}}</th>
<th>{{e2("Read")}}</th>
<th>{{e2("Modify")}}</th>
</tr>
<?php $levels = levels();
foreach($levels AS $level => $detail) {
?>
<tr>
<td>{{$detail[0]}}</td>
<td>{{$level}}</td>
<td>{{$detail[1]==1 ? "✅" : "❌"}}</td>
<td>{{$detail[2]==1 ? "✅" : "❌"}}</td>
<td>{{$detail[3]==1 ? "✅" : "❌"}}</td>
<td>{{$detail[4]==1 ? "✅" : "❌"}}</td>
</tr>
<?php } ?>
</table>
<script>
$(document).ready(function(){
$("#search").on("keyup", function() {
var value = $(this).val().toLowerCase();
$("#types tr").filter(function() {
$(this).toggle($(this).text().toLowerCase().indexOf(value) > -1)
});
});
});
</script>
<input type="text" name="search" id="search" placeholder="{{e2("Search Module...")}}" class="form-control">
<table class="table table-striped table-hover table-bordered table-vcenter table-sm">
<thead>
<tr>
<th>{{__("Enabled")}}</th>
<th>{{__("Icon")}}</th>
<th>{{__("Icon Name")}}</th>
<th>{{__("Title")}}</th>
<th>{{__("Parent")}}</th>
<th>{{__("ID")}}</th>
<th>{{__("Order")}}</th>
<th>{{__("Delete")}} </th>
<th>{{__("Write")}} </th>
<th>{{__("Read")}} </th>
<th>{{__("Modify")}} </th>
<th class="text-center" style="width: 100px;">{{__("İşlemler")}}</th>
</tr>
</thead>
<tbody id="types">
@foreach($types AS $a)
<tr>
<td>
<select name="enabled" table="types" data-id="{{$a->id}}" class="form-control edit">
<option value="1" @if($a->enabled) selected @endif>✅</option>
<option value="0" @if(!$a->enabled) selected @endif>🟥</option>
</select>
</td>
<td class="text-center">
<div class="d-none"><?php echo json_encode_tr($a); ?></div>
<img src="{{url("assets/icons/". $a->icon .".png")}}" width="24" alt="">
</td>
<td>
<input type="text" name="icon" value="{{$a->icon}}" table="types"data-id="{{$a->id}}" class="icon form-control edit" /></td>
<td><input type="text" name="title" value="{{$a->title}}" table="types"data-id="{{$a->id}}" class="title{{$a->id}} form-control edit" /></td>
<td><input type="text" name="kid" value="{{$a->kid}}" table="types"data-id="{{$a->id}}" class="title{{$a->id}} form-control edit" /></td>
<td>
<div class="input-group">
<div class="input-group-prepend">
<div class="btn btn-default" onclick="$.get('{{url('admin-ajax/slug?title='.$a->breadcrumb)}}'+$('.title{{$a->id}}').val(),function(d){
$('.slug{{$a->id}}').val(d).blur();
})"><i class="si si-refresh"></i></div>
</div>
<input type="text" name="slug" value="{{$a->slug}}" table="types"data-id="{{$a->id}}" class="slug{{$a->id}} form-control edit" />
</div>
</td>
<td><input type="number" name="s" value="{{$a->s}}" table="types"data-id="{{$a->id}}" class="title{{$a->id}} form-control edit" /></td>
<td>
<textarea name="full_control" table="types" data-id="{{$a->id}}" class="form-control edit" cols="30" rows="2">{{$a->full_control}}</textarea>
</td>
<td>
<textarea name="write" table="types" data-id="{{$a->id}}" class="form-control edit" cols="30" rows="2">{{$a->write}}</textarea>
</td>
<td>
<textarea name="read" table="types" data-id="{{$a->id}}" class="form-control edit" cols="30" rows="2">{{$a->read}}</textarea>
</td>
<td>
<textarea name="modify" table="types" data-id="{{$a->id}}" class="form-control edit" cols="30" rows="2">{{$a->modify}}</textarea>
</td>
<td class="text-center">
<div class="btn-group">
<a href="{{ url('admin/types/'. $a->slug) }}" type="button" class="btn btn-sm btn-secondary js-tooltip-enabled" data-toggle="tooltip" title="" data-original-title="Edit">
<i class="fa fa-link"></i>
</a>
<a href="{{ url('admin/types/'. $a->id.'/delete') }}" type="button" teyit="{{$a->title}} tipini silmek istediğinizden emin misiniz?" title="{{$a->title}} Silinecek!" class=" btn btn-sm btn-secondary js-tooltip-enabled" data-toggle="tooltip" title="" data-original-title="Delete">
<i class="fa fa-times"></i>
</a>
</div>
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
</div>
</div>
</div>
@endsection
+828
View File
@@ -0,0 +1,828 @@
@extends('admin.master')
@section("title","Modules")
@section("desc","Bu sayfada içerik türlerini yönetebilirsiniz")
@section('content')
<meta name="csrf-token" content="{{ csrf_token() }}">
<div class="content">
<div class="block">
<div class="block-header block-header-default">
<h3 class="block-title">{{__('Modules')}}</h3>
<div class="block-options">
<div class="block-options-item">
<a href="{{ url('admin/action/add/types') }}" class="btn btn-default"><i class="fa fa-plus"></i></a>
</div>
</div>
</div>
<div class="block-content">
<div class="table-responsive">
<table class="table table-bordered table-striped table-hover">
<tr>
<th>{{e2("User No")}}</th>
<th>{{e2("Level")}}</th>
<th>{{e2("Full Control")}}</th>
<th>{{e2("Write")}}</th>
<th>{{e2("Read")}}</th>
<th>{{e2("Modify")}}</th>
</tr>
<?php
// Specific Permissions List
$specificPermissionsList = [
'Right Click Menu' => [
'Copy Paste Permission' => 'copy_paste_permission',
'Copy Start Until Paste Permission' => 'copy_start_until_paste_permission',
'Row Column History Permission' => 'row_column_history_permission',
'Clear Value Permission' => 'clear_value_permission',
'Inspection Photo Upload Permission' => 'inspection_photo_upload_permission',
],
'Toolbar Actions' => [
'Add Row Permission' => 'add_row_permission',
'Apply Filter Permission' => 'apply_filter_permission',
'Column Chooser Permission' => 'column_chooser_permission',
'Revert Permission' => 'revert_permission',
'Save Permission' => 'save_permission',
'Search Panel Permission' => 'search_panel_permission',
'Export Permission' => 'export_permission',
'Group Panel Permission' => 'group_panel_permission',
'Clear Filter Permission' => 'clear_filter_permission',
'Select All Permission' => 'select_all_permission',
'Deselect All Permission' => 'deselect_all_permission',
'Refresh Permission' => 'refresh_permission',
'Delete Selected Permission' => 'delete_selected_permission',
'MTO Sync Permission' => 'mto_sync_permission',
],
];
$levels = levels();
foreach($levels AS $level => $detail) {
?>
<tr>
<td>{{$detail[0]}}</td>
<td>{{$level}}</td>
<td>{{$detail[1]==1 ? "✅" : "❌"}}</td>
<td>{{$detail[2]==1 ? "✅" : "❌"}}</td>
<td>{{$detail[3]==1 ? "✅" : "❌"}}</td>
<td>{{$detail[4]==1 ? "✅" : "❌"}}</td>
</tr>
<?php } ?>
</table>
<script>
$(document).ready(function(){
$("#search").on("keyup", function() {
var value = $(this).val().toLowerCase();
$("#types tr").filter(function() {
$(this).toggle($(this).text().toLowerCase().indexOf(value) > -1)
});
});
});
</script>
<input type="text" name="search" id="search" placeholder="{{e2("Search Module...")}}" class="form-control">
<table class="table table-striped table-hover table-bordered table-vcenter table-sm">
<thead>
<tr>
<th>{{__("Enabled")}}</th>
<th>{{__("Mobile")}}</th>
<th>{{__("Icon")}}</th>
<th>{{__("Icon Name")}}</th>
<th>{{__("Title")}}</th>
<th>{{__("Parent")}}</th>
<th>{{__("ID")}}</th>
<th>{{__("Order")}}</th>
<th>{{__("Full Control")}} </th>
<th>{{__("Write")}} </th>
<th>{{__("Read")}} </th>
<th>{{__("Modify")}} </th>
<th class="text-center" style="width: 100px;"><i class="fa fa-cog"></i></th>
</tr>
</thead>
<tbody id="types">
@foreach($types AS $a)
<tr>
<td>
<select name="enabled" table="types" data-id="{{$a->id}}" class="form-control edit">
<option value="1" @if($a->enabled) selected @endif>✅</option>
<option value="0" @if(!$a->enabled) selected @endif>🟥</option>
</select>
</td>
<td>
<select name="is_mobile" table="types" data-id="{{$a->id}}" class="form-control edit">
<option value="1" @if($a->is_mobile) selected @endif>✅</option>
<option value="0" @if(!$a->is_mobile) selected @endif>🟥</option>
</select>
</td>
<td class="text-center">
<img src="{{url("assets/icons/". $a->icon .".png")}}" width="24" alt="">
</td>
<td>
<input type="text" name="icon" value="{{$a->icon}}" table="types"data-id="{{$a->id}}" class="icon form-control edit" /></td>
<td><input type="text" name="title" value="{{$a->title}}" table="types"data-id="{{$a->id}}" class="title{{$a->id}} form-control edit" /></td>
<td><input type="text" name="kid" value="{{$a->kid}}" table="types"data-id="{{$a->id}}" class="title{{$a->id}} form-control edit" /></td>
<td>
<div class="input-group">
<div class="input-group-prepend">
<div class="btn btn-default" onclick="$.get('{{url('admin-ajax/slug?title='.$a->breadcrumb)}}'+$('.title{{$a->id}}').val(),function(d){
$('.slug{{$a->id}}').val(d).blur();
})"><i class="si si-refresh"></i></div>
</div>
<input type="text" name="slug" value="{{$a->slug}}" table="types"data-id="{{$a->id}}" class="slug{{$a->id}} form-control edit" />
</div>
</td>
<td><input type="number" name="s" value="{{$a->s}}" table="types"data-id="{{$a->id}}" class="title{{$a->id}} form-control edit" /></td>
<td>
<div class="level-input">
<div class="level-tags">
@foreach(explode(',', $a->full_control) as $level)
@if($level)
<span class="badge badge-pill badge-{{ levelColor($level) }}">{{ intval($level) }}</span>
@endif
@endforeach
</div>
<button class="btn btn-sm btn-light edit-levels"
data-target="full_control_{{ $a->id }}"
data-type="full_control">
<i class="fa fa-cog"></i>
</button>
<input type="hidden"
name="full_control"
table="types"
data-id="{{ $a->id }}"
value="{{ $a->full_control }}"
class="edit"
id="full_control_{{ $a->id }}">
</div>
</td>
<td>
<div class="level-input">
<div class="level-tags">
@foreach(explode(',', $a->write) as $level)
@if($level)
<span class="badge badge-pill badge-{{ levelColor($level) }}">{{ $level }}</span>
@endif
@endforeach
</div>
<button class="btn btn-sm btn-light edit-levels"
data-target="write_{{ $a->id }}"
data-type="write">
<i class="fa fa-cog"></i>
</button>
<input type="hidden"
name="write"
table="types"
data-id="{{ $a->id }}"
value="{{ $a->write }}"
class="edit"
id="write_{{ $a->id }}">
</div>
</td>
<td>
<div class="level-input">
<div class="level-tags">
@foreach(explode(',', $a->read) as $level)
@if($level)
<span class="badge badge-pill badge-{{ levelColor($level) }}">{{ $level }}</span>
@endif
@endforeach
</div>
<button class="btn btn-sm btn-light edit-levels"
data-target="read_{{ $a->id }}"
data-type="read">
<i class="fa fa-cog"></i>
</button>
<input type="hidden"
name="read"
table="types"
data-id="{{ $a->id }}"
value="{{ $a->read }}"
class="edit"
id="read_{{ $a->id }}">
</div>
</td>
<td>
<div class="level-input">
<div class="level-tags">
@foreach(explode(',', $a->modify) as $level)
@if($level)
<span class="badge badge-pill badge-{{ levelColor($level) }}">{{ $level }}</span>
@endif
@endforeach
</div>
<button class="btn btn-sm btn-light edit-levels"
data-target="modify_{{ $a->id }}"
data-type="modify">
<i class="fa fa-cog"></i>
</button>
<input type="hidden"
name="modify"
table="types"
data-id="{{ $a->id }}"
value="{{ $a->modify }}"
class="edit"
id="modify_{{ $a->id }}">
</div>
</td>
<td class="text-center">
<div class="btn-group">
<a href="{{ url('admin/types/'. $a->slug) }}" class="btn btn-sm btn-secondary">
<i class="fa fa-link"></i>
</a>
<a href="{{ url('admin/types/'. $a->id.'/delete') }}" class="btn btn-sm btn-secondary delete-confirm">
<i class="fa fa-times"></i>
</a>
<button type="button"
class="btn btn-sm btn-info open-specific-permissions"
data-id="{{ $a->id }}"
data-title="{{ $a->title }}"
data-slug="{{ $a->slug }}"
data-permissions='{{ setting("type_{$a->id}_specific_permissions") }}'
data-mobile-columns='{{ setting("type_{$a->id}_mobile_columns") }}'>
<i class="fa fa-cogs"></i>
</button>
</div>
</td>
<td style="display: none;" class="module-data">
<?php echo json_encode_tr([
'icon' => $a->icon,
'title' => $a->title
]); ?>
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
</div>
</div>
</div>
<div class="modal fade" id="levelModal" tabindex="-1" role="dialog">
<div class="modal-dialog modal-lg" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">
<i class="fa fa-cog"></i>
<span class="modal-module-title"></span> -
<span class="modal-permission-title"></span>
</h5>
<button type="button" class="close" data-dismiss="modal">
<span>&times;</span>
</button>
</div>
<div class="modal-body">
<div class="table-responsive">
<table class="table table-bordered table-hover">
<thead>
<tr>
<th>Level No</th>
<th>Level Name</th>
<th class="text-center">Select</th>
</tr>
</thead>
<tbody>
<?php $levels = levels(); ?>
@foreach($levels as $level => $detail)
<tr>
<td>
<span class="badge badge-pill badge-{{levelColor($detail[0])}}">
{{$detail[0]}}
</span>
</td>
<td>{{$level}}</td>
<td class="text-center">
<div class="custom-control custom-checkbox">
<input type="checkbox"
class="custom-control-input level-checkbox"
id="level_{{$detail[0]}}"
value="{{$detail[0]}}">
<label class="custom-control-label"
for="level_{{$detail[0]}}"></label>
</div>
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary" id="saveLevels">Save</button>
</div>
</div>
</div>
</div>
<script>
function levelColor(level) {
const colors = {1: 'success', 2: 'primary', 3: 'warning', 4: 'danger'};
return colors[level] || 'secondary';
}
let currentTarget = null;
let currentType = null;
let currentModuleData = null;
// Level edit button click handler
$(document).on('click', '.edit-levels', function(e) {
e.preventDefault();
currentTarget = $(this).data('target');
currentType = $(this).data('type');
try {
// If button is inside the main table (has module-data)
const $moduleData = $(this).closest('tr').find('.module-data');
if ($moduleData.length) {
currentModuleData = JSON.parse($moduleData.text().trim());
// Update modal title and icon
$('.modal-icon').attr('src', `{{url("assets/icons")}}/${currentModuleData.icon}.png`);
$('.modal-module-title').text(currentModuleData.title);
$('.modal-permission-title').text(getPermissionTitle(currentType));
} else {
// If button is inside Specific Permissions modal
$('.modal-icon').attr('src', ''); // Or default icon
$('.modal-module-title').text($('#spModalTitle').text());
$('.modal-permission-title').text(currentType); // Directly use the permission name
}
// Check current levels from the target input
const currentVal = $('#' + currentTarget).val();
const currentLevels = currentVal ? currentVal.toString().split(',').filter(l => l) : [];
$('.level-checkbox').prop('checked', false);
currentLevels.forEach(level => {
$('#level_' + parseInt(level)).prop('checked', true);
});
$('#levelModal').modal('show');
} catch (error) {
console.error('Error opening level modal:', error);
$('#levelModal').modal('show');
}
});
function getPermissionTitle(type) {
const titles = {
'full_control': 'Full Control',
'write': 'Write Permission',
'read': 'Read Permission',
'modify': 'Modify Permission'
};
return titles[type] || type;
}
// Save button click handler
$('#saveLevels').click(function() {
if (!currentTarget) return;
const selectedLevels = [];
$('.level-checkbox:checked').each(function() {
selectedLevels.push(parseInt($(this).val()));
});
const $target = $('#' + currentTarget);
const $container = $target.closest('.level-input');
const $tags = $container.find('.level-tags');
// Update hidden input
$target.val(selectedLevels.join(',')).trigger('change');
// Update badges
$tags.empty();
selectedLevels.forEach(level => {
$tags.append(
`<span class="badge badge-pill badge-${levelColor(level)}">${level}</span>`
);
});
$('#levelModal').modal('hide');
});
// AJAX setup
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
// Edit sınıfına sahip elementlerin değişikliklerini izle
$(document).on('change', '.edit', function() {
$.post('{{url("admin-ajax/input-edit")}}', {
table: $(this).attr("table"),
value: $(this).val(),
id: $(this).data("id"),
name: $(this).attr("name"),
_token: '{{ csrf_token() }}'
});
});
</script>
<style>
.level-tags {
min-height: 38px;
padding: 5px;
border: 1px solid #eee;
margin-bottom: 5px;
border-radius: 4px;
display: flex;
flex-wrap: wrap;
align-items: center;
}
.level-tags .badge {
margin: 2px;
font-size: 0.85rem;
}
.level-input {
position: relative;
width: 120px;
}
.level-input .edit-levels {
position: absolute;
right: 5px;
top: 5px;
z-index: 2;
padding: 2px 6px;
display: none;
}
.level-input:hover .edit-levels {
display: block;
}
.level-list {
max-height: 400px;
overflow-y: auto;
}
.form-check-label {
display: flex;
align-items: center;
gap: 8px;
}
.form-check-label .badge {
min-width: 24px;
text-align: center;
}
.modal-dialog {
max-width: 700px;
}
.table td {
vertical-align: middle;
}
.custom-control {
margin: 0;
}
</style>
@endsection
<!-- Specific Permissions Modal -->
<div class="modal fade" id="specificPermissionsModal" tabindex="-1" role="dialog">
<div class="modal-dialog modal-lg" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">
<i class="fa fa-cogs mr-2"></i>
<span id="spModalTitle"></span> - Specific Permissions
</h5>
<button type="button" class="close" data-dismiss="modal">
<span>&times;</span>
</button>
</div>
<div class="modal-body">
<form id="specificPermissionsForm">
<input type="hidden" id="spTypeId" name="id">
<input type="hidden" id="spTypeSlug" name="slug">
<div class="row">
<div class="col-12">
<ul class="nav nav-tabs nav-tabs-alt" role="tablist">
@foreach($specificPermissionsList as $groupName => $perms)
<li class="nav-item">
<a class="nav-link @if($loop->first) active @endif" href="#sp-tab-{{Str::slug($groupName)}}" data-toggle="tab">
{{$groupName}}
</a>
</li>
@endforeach
<li class="nav-item">
<a class="nav-link" href="#sp-tab-mobile-columns" data-toggle="tab">
Mobile Columns
</a>
</li>
</ul>
<div class="block-content tab-content">
@foreach($specificPermissionsList as $groupName => $perms)
<div class="tab-pane @if($loop->first) active @endif" id="sp-tab-{{Str::slug($groupName)}}" role="tabpanel">
<table class="table table-vcenter table-hover mb-0">
<thead>
<tr>
<th>Permission Name</th>
<th>Allowed Levels (e.g. 1,2)</th>
</tr>
</thead>
<tbody>
@foreach($perms as $label => $key)
<tr>
<td>{{$label}}</td>
<td>
<div class="level-input" style="width: 100%;">
<div class="level-tags" id="tags_{{$key}}">
<!-- Badges will be inserted here via JS -->
</div>
<button type="button" class="btn btn-sm btn-light edit-levels"
data-target="sp_{{$key}}"
data-type="{{$label}}">
<i class="fa fa-cog"></i>
</button>
<input type="hidden"
name="permissions[{{$key}}]"
id="sp_{{$key}}"
class="sp-input">
</div>
<small class="text-muted d-none">{{$key}}</small>
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
@endforeach
<div class="tab-pane" id="sp-tab-mobile-columns" role="tabpanel">
<div id="mobileColumnsLoading" class="text-center py-4">
<i class="fa fa-spinner fa-spin fa-2x"></i>
<p class="mt-2">Loading columns...</p>
</div>
<div id="mobileColumnsContainer" style="display:none;">
<div class="mb-2">
<button type="button" class="btn btn-sm btn-outline-primary" id="mcSelectAll">Select All</button>
<button type="button" class="btn btn-sm btn-outline-secondary" id="mcDeselectAll">Deselect All</button>
</div>
<div class="table-responsive">
<table class="table table-vcenter table-hover mb-0">
<thead>
<tr>
<th style="width:30px;"></th>
<th style="width:50px;">Select</th>
<th>Column Name</th>
</tr>
</thead>
<tbody id="mobileColumnsList"></tbody>
</table>
</div>
</div>
<div id="mobileColumnsEmpty" style="display:none;" class="text-center py-4 text-muted">
<i class="fa fa-exclamation-circle fa-2x"></i>
<p class="mt-2">No columns found for this module.</p>
</div>
</div>
</div>
</div>
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary" id="saveSpecificPermissions">Save</button>
</div>
</div>
</div>
</div>
<script>
window.addEventListener('load', function() {
// Open Modal
$(document).on('click', '.open-specific-permissions', function() {
var id = $(this).data('id');
var title = $(this).data('title');
var slug = $(this).data('slug');
var currentPerms = $(this).data('permissions'); // JSON object or string
var currentMobileColumns = $(this).data('mobile-columns'); // JSON string
$('#spModalTitle').text(title);
$('#spTypeId').val(id);
$('#spTypeSlug').val(slug);
// Reset form and tags
$('.sp-input').val('');
$('.level-tags').empty();
// Fill existing values
if (currentPerms) {
if (typeof currentPerms === 'string') {
try {
currentPerms = JSON.parse(currentPerms);
} catch(e) {
console.error("JSON parse error", e);
currentPerms = {};
}
}
$.each(currentPerms, function(key, value) {
// Set hidden input value
var $input = $('input[name="permissions[' + key + ']"]');
$input.val(value);
// Create badges
if(value) {
var levels = value.toString().split(',');
var $tagsContainer = $input.closest('.level-input').find('.level-tags');
levels.forEach(function(level) {
if(level.trim() !== '') {
$tagsContainer.append(
`<span class="badge badge-pill badge-${levelColor(parseInt(level))}">${level}</span>`
);
}
});
}
});
}
// Parse saved mobile columns
var savedMobileColumns = [];
if (currentMobileColumns) {
if (typeof currentMobileColumns === 'string') {
try {
savedMobileColumns = JSON.parse(currentMobileColumns);
} catch(e) {
savedMobileColumns = [];
}
} else if (Array.isArray(currentMobileColumns)) {
savedMobileColumns = currentMobileColumns;
}
}
// Reset mobile columns tab
$('#mobileColumnsLoading').show();
$('#mobileColumnsContainer').hide();
$('#mobileColumnsEmpty').hide();
$('#mobileColumnsList').empty();
// Fetch columns via AJAX
$.ajax({
url: '{{url("admin-ajax/get-module-columns")}}',
type: 'GET',
data: { slug: slug },
success: function(response) {
$('#mobileColumnsLoading').hide();
try {
var res = typeof response === 'string' ? JSON.parse(response) : response;
if (res.status === 'success' && res.columns && res.columns.length > 0) {
// All columns from database
var allDbColumns = res.columns;
// Reorder: Saved columns first (in their saved order), then others
var finalOrder = [];
// Add saved ones first
savedMobileColumns.forEach(function(col) {
if (allDbColumns.indexOf(col) !== -1) {
finalOrder.push(col);
}
});
// Add remaining ones
allDbColumns.forEach(function(col) {
if (finalOrder.indexOf(col) === -1) {
finalOrder.push(col);
}
});
var html = '';
finalOrder.forEach(function(col) {
var checked = savedMobileColumns.indexOf(col) !== -1 ? 'checked' : '';
html += '<tr class="mc-item" data-col="' + col + '">' +
'<td class="text-center mc-handle" style="cursor:move;"><i class="fa fa-arrows-alt text-muted"></i></td>' +
'<td class="text-center">' +
'<div class="custom-control custom-checkbox">' +
'<input type="checkbox" class="custom-control-input mc-checkbox" id="mc_' + col + '" value="' + col + '" ' + checked + '>' +
'<label class="custom-control-label" for="mc_' + col + '"></label>' +
'</div>' +
'</td>' +
'<td><code>' + col + '</code></td>' +
'</tr>';
});
$('#mobileColumnsList').html(html);
// Initialize Sortable
$('#mobileColumnsList').sortable({
handle: '.mc-handle',
axis: 'y',
containment: 'parent',
helper: function(e, tr) {
var $originals = tr.children();
var $helper = tr.clone();
$helper.children().each(function(index) {
$(this).width($originals.eq(index).width());
});
return $helper;
}
}).disableSelection();
$('#mobileColumnsContainer').show();
} else {
$('#mobileColumnsEmpty').show();
}
} catch(e) {
console.error('Column parse error', e);
$('#mobileColumnsEmpty').show();
}
},
error: function() {
$('#mobileColumnsLoading').hide();
$('#mobileColumnsEmpty').show();
}
});
$('#specificPermissionsModal').modal('show');
});
// Select All / Deselect All for Mobile Columns
$('#mcSelectAll').click(function() {
$('.mc-checkbox').prop('checked', true);
});
$('#mcDeselectAll').click(function() {
$('.mc-checkbox').prop('checked', false);
});
// Save
$('#saveSpecificPermissions').click(function() {
var formData = {};
// Only take filled inputs
$('.sp-input').each(function() {
var val = $(this).val();
var name = $(this).attr('name').replace('permissions[', '').replace(']', '');
if(val && val.trim() !== '') {
formData[name] = val;
}
});
// Collect selected mobile columns in UI order
var selectedColumns = [];
$('.mc-item').each(function() {
var $item = $(this);
var isChecked = $item.find('.mc-checkbox').is(':checked');
if (isChecked) {
selectedColumns.push($item.data('col'));
}
});
var typeId = $('#spTypeId').val();
$.ajax({
url: '{{url("admin-ajax/save-module-permissions")}}',
type: 'POST',
data: {
type_id: typeId,
permissions: JSON.stringify(formData),
mobile_columns: JSON.stringify(selectedColumns),
_token: '{{ csrf_token() }}'
},
success: function(response) {
try {
var res = typeof response === 'string' ? JSON.parse(response) : response;
if(res.status === 'success') {
$('#specificPermissionsModal').modal('hide');
location.reload();
} else {
alert('Error: ' + (res.message || 'Unknown error'));
}
} catch(e) {
console.error("Response parse error", e);
location.reload(); // Assume success if parse fails but request worked
}
},
error: function() {
alert('An error occurred while saving.');
}
});
});
// Delete confirmation
$(document).on('click', '.delete-confirm', function(e) {
e.preventDefault();
var url = $(this).attr('href');
Swal.fire({
title: '{{__("Are you sure?")}}',
text: '{{__("This module and all its settings will be deleted!")}}',
icon: 'warning',
showCancelButton: true,
confirmButtonColor: '#d33',
cancelButtonColor: '#3085d6',
confirmButtonText: '{{__("Yes, delete it!")}}',
cancelButtonText: '{{__("Cancel")}}'
}).then((result) => {
if (result.isConfirmed) {
window.location.href = url;
}
});
});
});
</script>