WIP: Sicherheitsnetz vor Phase-1-R\u00fcckbau
Enth\u00e4lt gemischt: Laravel-10-Upgrade + Phase 1 (Contacts-Modul, Duplicats-Commands, Soft-Delete+Merge-Fields) + Phase 2 Code-Umstellungen (inquiry_id, $table='contacts'/'inquiries') + Offers-Modul (Migrationen, Models, offer_id in Booking, offer-Disk in filesystems.php). Phase 2 + Offers werden im folgenden Commit nach dev/backups/phase2-offers-2026-04-17/ verschoben, damit der Workspace auf Phase-1-only (= Test-System-Stand) reduziert ist und direkt auf Live deploybar wird. Tarball-Backup zus\u00e4tzlich unter: ../backups-safety/workspace-pre-phase1-rollback-2026-04-17.tar.gz Made-with: Cursor
This commit is contained in:
parent
389d5d1820
commit
e3dc1afd8e
165 changed files with 21914 additions and 3516 deletions
135
resources/views/contact/_detail_contact.blade.php
Normal file
135
resources/views/contact/_detail_contact.blade.php
Normal file
|
|
@ -0,0 +1,135 @@
|
|||
<div class="card mb-2 border-primary">
|
||||
<h6 class="card-header bg-primary text-white py-2"
|
||||
data-toggle="collapse" data-target="#collapseContactDetail"
|
||||
aria-expanded="false" aria-controls="collapseContactDetail">
|
||||
<strong style="line-height: 1.6em">Kontaktdaten</strong>
|
||||
@if($id !== 'new' && $contact->mergedContacts->isNotEmpty())
|
||||
<span class="badge badge-warning ml-2">
|
||||
{{ $contact->mergedContacts->count() }} zusammengeführt
|
||||
</span>
|
||||
@endif
|
||||
</h6>
|
||||
|
||||
<div class="collapse" id="collapseContactDetail">
|
||||
<div class="card-body">
|
||||
|
||||
@if($id !== 'new')
|
||||
<div class="form-row">
|
||||
<div class="form-group col-sm-6">
|
||||
<label class="form-label" for="contact_id">{{ __('Kontakt ID') }}</label>
|
||||
{{ Form::text('contact_id', $contact->id, ['placeholder' => __('Kontakt ID'), 'class' => 'form-control', 'id' => 'contact_id', 'readonly']) }}
|
||||
</div>
|
||||
<div class="form-group col-sm-6">
|
||||
<label class="form-label">{{ __('Angelegt am') }}</label>
|
||||
<input type="text" class="form-control" readonly
|
||||
value="{{ $contact->created_at ? $contact->created_at->format('d.m.Y') : '-' }}">
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<div class="form-row">
|
||||
<div class="form-group col-sm-3">
|
||||
<label for="salutation_id" class="form-label">{{ __('Anrede') }} *</label>
|
||||
{{ Form::select('salutation_id', \App\Models\Contact::$salutationType, $contact->salutation_id, ['class' => 'custom-select', 'required' => true]) }}
|
||||
</div>
|
||||
|
||||
<div class="form-group col-sm-4">
|
||||
<label class="form-label" for="firstname">{{ __('Vorname') }} *</label>
|
||||
{{ Form::text('firstname', $contact->firstname, ['placeholder' => __('Vorname'), 'class' => 'form-control', 'id' => 'firstname', 'required' => true]) }}
|
||||
</div>
|
||||
|
||||
<div class="form-group col-sm-5">
|
||||
<label class="form-label" for="name">{{ __('Nachname') }} *</label>
|
||||
{{ Form::text('name', $contact->name, ['placeholder' => __('Nachname'), 'class' => 'form-control', 'id' => 'name', 'required' => true]) }}
|
||||
</div>
|
||||
|
||||
<div class="form-group col-sm-6">
|
||||
<label class="form-label" for="birthdate">{{ __('Geburtsdatum') }}</label>
|
||||
{{ Form::text('birthdate', $contact->birthdate ? $contact->birthdate->format('d.m.Y') : '', ['placeholder' => 'TT.MM.JJJJ', 'class' => 'form-control', 'id' => 'birthdate']) }}
|
||||
</div>
|
||||
|
||||
<div class="form-group col-sm-6">
|
||||
<label class="form-label" for="company">{{ __('Firma') }}</label>
|
||||
{{ Form::text('company', $contact->company, ['placeholder' => __('Firma'), 'class' => 'form-control', 'id' => 'company']) }}
|
||||
</div>
|
||||
|
||||
<div class="form-group col-sm-12">
|
||||
<label class="form-label" for="street">{{ __('Straße') }}</label>
|
||||
{{ Form::text('street', $contact->street, ['placeholder' => __('Straße'), 'class' => 'form-control', 'id' => 'street']) }}
|
||||
</div>
|
||||
|
||||
<div class="form-group col-sm-3">
|
||||
<label class="form-label" for="zip">{{ __('PLZ') }}</label>
|
||||
{{ Form::text('zip', $contact->zip, ['placeholder' => __('PLZ'), 'class' => 'form-control', 'id' => 'zip']) }}
|
||||
</div>
|
||||
|
||||
<div class="form-group col-sm-4">
|
||||
<label class="form-label" for="city">{{ __('Stadt') }}</label>
|
||||
{{ Form::text('city', $contact->city, ['placeholder' => __('Stadt'), 'class' => 'form-control', 'id' => 'city']) }}
|
||||
</div>
|
||||
|
||||
<div class="form-group col-sm-5">
|
||||
<label class="form-label" for="country_id">{{ __('Land') }} *</label>
|
||||
{{ Form::select('country_id', \App\Models\Contact::getCountriesArray(), $contact->country_id, ['class' => 'custom-select', 'required' => true]) }}
|
||||
</div>
|
||||
|
||||
<div class="form-group col-sm-4">
|
||||
<label class="form-label" for="phone">{{ __('Telefon') }}</label>
|
||||
{{ Form::text('phone', $contact->phone, ['placeholder' => __('Telefon'), 'class' => 'form-control', 'id' => 'phone']) }}
|
||||
</div>
|
||||
|
||||
<div class="form-group col-sm-4">
|
||||
<label class="form-label" for="phonemobile">{{ __('Mobil') }}</label>
|
||||
{{ Form::text('phonemobile', $contact->phonemobile, ['placeholder' => __('Mobil'), 'class' => 'form-control', 'id' => 'phonemobile']) }}
|
||||
</div>
|
||||
|
||||
<div class="form-group col-sm-4">
|
||||
<label class="form-label" for="phonebusiness">{{ __('Geschäftlich') }}</label>
|
||||
{{ Form::text('phonebusiness', $contact->phonebusiness, ['placeholder' => __('Geschäftlich'), 'class' => 'form-control', 'id' => 'phonebusiness']) }}
|
||||
</div>
|
||||
|
||||
<div class="form-group col-sm-12">
|
||||
<label class="form-label" for="email">{{ __('E-Mail') }} *</label>
|
||||
{{ Form::text('email', $contact->email, ['placeholder' => __('E-Mail'), 'class' => 'form-control', 'id' => 'email', 'required' => true]) }}
|
||||
</div>
|
||||
|
||||
<div class="col-sm-12">
|
||||
<div class="text-left mt-2">
|
||||
<button type="submit" name="action" value="saveContact" class="btn btn-sm btn-secondary">
|
||||
{{ __('Änderungen speichern') }}
|
||||
</button>
|
||||
<a href="{{ route('contacts') }}" class="btn btn-sm btn-default ml-1">
|
||||
{{ __('zur Übersicht') }}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@if($id !== 'new' && $contact->mergedContacts->isNotEmpty())
|
||||
<hr class="mt-4 mb-3">
|
||||
<h6 class="text-muted">{{ __('Zusammengeführte Duplikate') }}</h6>
|
||||
<table class="table table-sm table-bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{{ __('ID') }}</th>
|
||||
<th>{{ __('Name') }}</th>
|
||||
<th>{{ __('E-Mail') }}</th>
|
||||
<th>{{ __('Zusammengeführt am') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach($contact->mergedContacts as $merged)
|
||||
<tr class="text-muted">
|
||||
<td>{{ $merged->id }}</td>
|
||||
<td>{{ $merged->fullName() }}</td>
|
||||
<td>{{ $merged->email }}</td>
|
||||
<td>{{ $merged->merged_at ? $merged->merged_at->format('d.m.Y') : '-' }}</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
@endif
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
122
resources/views/contact/_detail_history.blade.php
Normal file
122
resources/views/contact/_detail_history.blade.php
Normal file
|
|
@ -0,0 +1,122 @@
|
|||
@php $modal = $modal ?? false; @endphp
|
||||
|
||||
@if(!$modal)
|
||||
<div class="card mb-2 border-primary">
|
||||
<h6 class="card-header bg-primary text-white py-2"
|
||||
data-toggle="collapse" data-target="#collapseContactHistory"
|
||||
aria-expanded="false" aria-controls="collapseContactHistory">
|
||||
<strong style="line-height: 1.6em">
|
||||
Anfragen <span class="badge badge-secondary">{{ $contact->leads->count() }}</span>
|
||||
</strong>
|
||||
|
|
||||
<strong style="line-height: 1.6em">
|
||||
Buchungen <span class="badge badge-secondary">{{ $contact->bookings->count() }}</span>
|
||||
</strong>
|
||||
</h6>
|
||||
<div class="collapse" id="collapseContactHistory">
|
||||
<div class="card-body">
|
||||
@endif
|
||||
|
||||
{{-- Anfragen --}}
|
||||
@if($contact->leads->isNotEmpty())
|
||||
<h6 class="text-muted mb-2">{{ __('Anfragen') }}</h6>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-striped table-sm mb-4">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="max-width: 80px;">{{ __('ID') }}</th>
|
||||
<th>{{ __('Sachbearbeiter') }}</th>
|
||||
<th>{{ __('Status') }}</th>
|
||||
<th>{{ __('Anfrage-Datum') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach($contact->leads as $lead)
|
||||
<tr>
|
||||
<td>
|
||||
<a href="{{ route('lead_detail', [$lead->id]) }}" class="btn icon-btn btn-sm btn-primary" target="{{ $modal ? '_blank' : '_self' }}">
|
||||
<span class="fa fa-edit"></span>
|
||||
</a>
|
||||
{{ $lead->id }}
|
||||
</td>
|
||||
<td>
|
||||
@if($lead->sf_guard_user_id && $lead->sf_guard_user)
|
||||
{{ $lead->sf_guard_user->first_name }} {{ $lead->sf_guard_user->last_name }}
|
||||
@endif
|
||||
</td>
|
||||
<td>{!! $lead->getStatusBadge() !!}</td>
|
||||
<td>{{ _format_date($lead->request_date) }}</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
@else
|
||||
<p class="text-muted small mb-4">{{ __('Keine Anfragen vorhanden.') }}</p>
|
||||
@endif
|
||||
|
||||
<hr class="my-3">
|
||||
|
||||
{{-- Buchungen --}}
|
||||
@if($contact->bookings->isNotEmpty())
|
||||
<h6 class="text-muted mb-2">{{ __('Buchungen') }}</h6>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-striped table-sm">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="max-width: 80px;">{{ __('ID') }}</th>
|
||||
<th>{{ __('Reiseland') }}</th>
|
||||
<th>{{ __('Programm') }}</th>
|
||||
<th>{{ __('Anreise') }}</th>
|
||||
<th>{{ __('Abreise') }}</th>
|
||||
<th>{{ __('Sachbearbeiter') }}</th>
|
||||
<th>{{ __('Status') }}</th>
|
||||
<th>{{ __('Datum') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach($contact->bookings as $booking)
|
||||
<tr>
|
||||
<td>
|
||||
<a href="{{ route('booking_detail', [$booking->id]) }}" class="btn icon-btn btn-sm btn-primary" target="{{ $modal ? '_blank' : '_self' }}">
|
||||
<span class="fa fa-edit"></span>
|
||||
</a>
|
||||
{{ $booking->id }}
|
||||
</td>
|
||||
<td>
|
||||
@if($booking->travel_country_id && $booking->travel_country)
|
||||
{{ $booking->travel_country->name }}
|
||||
@endif
|
||||
</td>
|
||||
<td>
|
||||
@if($booking->travelagenda_id && $booking->travel_agenda)
|
||||
{{ $booking->travel_agenda->name }}
|
||||
@endif
|
||||
</td>
|
||||
<td>{{ _format_date($booking->start_date) }}</td>
|
||||
<td>{{ _format_date($booking->end_date) }}</td>
|
||||
<td>
|
||||
@if($booking->sf_guard_user_id && $booking->sf_guard_user)
|
||||
{{ $booking->sf_guard_user->first_name }} {{ $booking->sf_guard_user->last_name }}
|
||||
@endif
|
||||
</td>
|
||||
<td>
|
||||
@if($booking->lead)
|
||||
{!! $booking->lead->getStatusBadge($booking) !!}
|
||||
@endif
|
||||
</td>
|
||||
<td>{{ _format_date($booking->booking_date) }}</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
@else
|
||||
<p class="text-muted small">{{ __('Keine Buchungen vorhanden.') }}</p>
|
||||
@endif
|
||||
|
||||
@if(!$modal)
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
97
resources/views/contact/detail.blade.php
Normal file
97
resources/views/contact/detail.blade.php
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
@extends('layouts.layout-2')
|
||||
|
||||
@section('content')
|
||||
|
||||
<div class="float-right mt-3">
|
||||
<a href="{{ route('contacts') }}" class="btn btn-sm btn-default">{{ __('zur Übersicht') }}</a>
|
||||
</div>
|
||||
|
||||
<h4 class="font-weight-bold py-3 mb-1">
|
||||
{{ $id === 'new' ? __('Neuer Kontakt') : __('Kontakt') . ': ' . $contact->fullName() }}
|
||||
</h4>
|
||||
|
||||
@if(session('alert-save'))
|
||||
<div class="alert alert-success alert-dismissible fade show" role="alert">
|
||||
{{ __('Änderungen wurden gespeichert.') }}
|
||||
<button type="button" class="close" data-dismiss="alert">×</button>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<ul class="nav nav-sm nav-tabs nav-justified tabs-alt mb-3" id="top-nav-quick-jump">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link active" href="javascript:void(0)" data-collapse="#collapseContactDetail">
|
||||
{{ __('Kontaktdaten') }}
|
||||
</a>
|
||||
</li>
|
||||
@if($id !== 'new')
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="javascript:void(0)" data-collapse="#collapseContactHistory">
|
||||
{{ __('Verlauf') }}
|
||||
@if($contact->leads->isNotEmpty() || $contact->bookings->isNotEmpty())
|
||||
<span class="badge badge-primary ml-1">
|
||||
{{ $contact->leads->count() + $contact->bookings->count() }}
|
||||
</span>
|
||||
@endif
|
||||
</a>
|
||||
</li>
|
||||
@endif
|
||||
</ul>
|
||||
|
||||
{!! Form::open(['url' => route('contact_detail_store', [$id]), 'class' => 'form-horizontal', 'id' => 'contact-form-validation']) !!}
|
||||
<input type="hidden" name="id" value="{{ $id }}">
|
||||
|
||||
@include('contact._detail_contact')
|
||||
|
||||
@if($id !== 'new')
|
||||
@include('contact._detail_history')
|
||||
@endif
|
||||
|
||||
<div class="float-right mt-3">
|
||||
<a href="{{ route('contacts') }}" class="btn btn-sm btn-default">{{ __('zur Übersicht') }}</a>
|
||||
</div>
|
||||
|
||||
{!! Form::close() !!}
|
||||
|
||||
<script>
|
||||
$(document).ready(function () {
|
||||
|
||||
$("#contact-form-validation button[type='submit']").on("click", function () {
|
||||
$(':input[required]', "#contact-form-validation").each(function () {
|
||||
if ($(this).val() === "" || $(this).val() === null) {
|
||||
$(this).closest(".collapse").collapse('show');
|
||||
return false;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$('#top-nav-quick-jump .nav-link').on('click', function (e) {
|
||||
e.preventDefault();
|
||||
$('#top-nav-quick-jump .nav-link').removeClass('active');
|
||||
$(this).addClass('active');
|
||||
var collapseId = $(this).data('collapse');
|
||||
$(collapseId).collapse('show');
|
||||
$('html, body').animate({
|
||||
scrollTop: $(collapseId).parent('.card').offset().top
|
||||
}, 300, function () {
|
||||
window.location.hash = collapseId;
|
||||
});
|
||||
});
|
||||
|
||||
$(".collapse").on('shown.bs.collapse', function () {
|
||||
window.location.hash = "#" + $(this).attr('id');
|
||||
});
|
||||
|
||||
// Hash beim Laden auswerten
|
||||
if (window.location.hash) {
|
||||
var target = $(window.location.hash);
|
||||
if (target.length) {
|
||||
$('a[data-collapse="#' + target.attr('id') + '"]').click();
|
||||
}
|
||||
} else {
|
||||
// Standard: Kontaktdaten aufklappen
|
||||
$('#collapseContactDetail').collapse('show');
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
@endsection
|
||||
224
resources/views/contact/duplicates.blade.php
Normal file
224
resources/views/contact/duplicates.blade.php
Normal file
|
|
@ -0,0 +1,224 @@
|
|||
@extends('layouts.layout-2')
|
||||
|
||||
@section('content')
|
||||
<div class="d-flex justify-content-between align-items-center py-3 mb-3">
|
||||
<h4 class="font-weight-bold mb-0">
|
||||
Mögliche Duplikate
|
||||
<small class="text-muted font-weight-light ml-2 d-none d-md-inline">Kontakte zur manuellen Prüfung</small>
|
||||
</h4>
|
||||
<a href="{{ route('contacts') }}" class="btn btn-sm btn-outline-secondary">
|
||||
<span class="fa fa-arrow-left mr-1"></span> Zurück zur Übersicht
|
||||
</a>
|
||||
</div>
|
||||
|
||||
{{-- Konfidenz-Tabs --}}
|
||||
<ul class="nav nav-tabs mb-3" id="confidence-tabs">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link active" href="#" data-confidence="HIGH">
|
||||
<span class="badge badge-success mr-1">{{ $counts['HIGH'] }}</span>
|
||||
HIGH — gleiche E-Mail
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="#" data-confidence="MEDIUM">
|
||||
<span class="badge badge-warning mr-1">{{ $counts['MEDIUM'] }}</span>
|
||||
MEDIUM — Name + Geburtsdatum
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="#" data-confidence="LOW">
|
||||
<span class="badge badge-danger mr-1">{{ $counts['LOW'] }}</span>
|
||||
LOW — Name + PLZ
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
{{-- Lade-Spinner --}}
|
||||
<div id="loading" class="text-center py-5">
|
||||
<span class="fa fa-spinner fa-spin fa-2x text-muted"></span>
|
||||
<p class="text-muted mt-2">Duplikate werden geladen…</p>
|
||||
</div>
|
||||
|
||||
{{-- Gruppen-Container --}}
|
||||
<div id="groups-container" style="display:none;"></div>
|
||||
|
||||
{{-- Leer-Zustand --}}
|
||||
<div id="no-duplicates" class="text-center py-5" style="display:none;">
|
||||
<span class="fa fa-check-circle fa-3x text-success mb-3 d-block"></span>
|
||||
<p class="text-muted">Keine Duplikate in dieser Kategorie.</p>
|
||||
</div>
|
||||
|
||||
{{-- Erfolg-Toast --}}
|
||||
<div id="merge-success-toast" class="alert alert-success alert-dismissible fade"
|
||||
style="position:fixed; bottom:1rem; right:1rem; z-index:9999; min-width:300px; display:none;">
|
||||
<button type="button" class="close" onclick="$('#merge-success-toast').fadeOut();">×</button>
|
||||
<span class="fa fa-check mr-1"></span> Kontakte erfolgreich zusammengeführt.
|
||||
</div>
|
||||
|
||||
{{-- Fehler-Toast --}}
|
||||
<div id="merge-error-toast" class="alert alert-danger alert-dismissible fade"
|
||||
style="position:fixed; bottom:1rem; right:1rem; z-index:9999; min-width:300px; display:none;">
|
||||
<button type="button" class="close" onclick="$('#merge-error-toast').fadeOut();">×</button>
|
||||
<span id="merge-error-message"></span>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
var currentConfidence = 'HIGH';
|
||||
var csrfToken = '{{ csrf_token() }}';
|
||||
|
||||
function loadGroups(confidence) {
|
||||
currentConfidence = confidence;
|
||||
$('#groups-container').hide().empty();
|
||||
$('#no-duplicates').hide();
|
||||
$('#loading').show();
|
||||
|
||||
$.get('{{ route('data_contacts_duplicates') }}', { confidence: confidence }, function(groups) {
|
||||
$('#loading').hide();
|
||||
|
||||
if (!groups || groups.length === 0) {
|
||||
$('#no-duplicates').show();
|
||||
return;
|
||||
}
|
||||
|
||||
groups.forEach(function(group) {
|
||||
$('#groups-container').append(renderGroup(group));
|
||||
});
|
||||
|
||||
$('#groups-container').show();
|
||||
}).fail(function() {
|
||||
$('#loading').hide();
|
||||
showError('Fehler beim Laden der Duplikate.');
|
||||
});
|
||||
}
|
||||
|
||||
function renderGroup(group) {
|
||||
var master = group.master;
|
||||
var dupes = group.duplicates;
|
||||
|
||||
var html = '<div class="card mb-3 border-left-primary" style="border-left: 4px solid #5a8dee;">';
|
||||
html += '<div class="card-header py-2 d-flex justify-content-between align-items-center">';
|
||||
html += '<span class="font-weight-bold"><span class="fa fa-copy mr-1 text-muted"></span>';
|
||||
html += escHtml(master.firstname + ' ' + master.name);
|
||||
html += '</span>';
|
||||
html += '<span class="text-muted small">' + dupes.length + ' Duplikat(e)</span>';
|
||||
html += '</div>';
|
||||
html += '<div class="card-body py-2">';
|
||||
html += '<div class="row">';
|
||||
|
||||
// Master-Karte
|
||||
html += renderContactCard(master, true);
|
||||
|
||||
// Duplikat-Karten
|
||||
dupes.forEach(function(dupe) {
|
||||
html += renderContactCard(dupe, false, master.id);
|
||||
});
|
||||
|
||||
html += '</div></div></div>';
|
||||
return html;
|
||||
}
|
||||
|
||||
function renderContactCard(contact, isMaster, masterId) {
|
||||
var borderClass = isMaster ? 'border-success' : 'border-warning';
|
||||
var badgeHtml = isMaster
|
||||
? '<span class="badge badge-success">Master</span>'
|
||||
: '<span class="badge badge-warning">Duplikat</span>';
|
||||
|
||||
var html = '<div class="col-md-6 col-lg-4 mb-2">';
|
||||
html += '<div class="card h-100 ' + borderClass + '">';
|
||||
html += '<div class="card-header py-1 d-flex justify-content-between align-items-center">';
|
||||
html += '<span class="small font-weight-bold">#' + contact.id + ' ' + badgeHtml + '</span>';
|
||||
html += '<a href="/contact/detail/' + contact.id + '" target="_blank" class="btn btn-xs btn-outline-primary" title="Öffnen"><span class="fa fa-external-link-alt"></span></a>';
|
||||
html += '</div>';
|
||||
html += '<div class="card-body py-2 small">';
|
||||
html += '<table class="table table-sm table-borderless mb-0">';
|
||||
html += '<tr><td class="text-muted pr-2" style="width:90px;">Name</td><td>' + escHtml(contact.firstname + ' ' + contact.name) + '</td></tr>';
|
||||
html += '<tr><td class="text-muted">E-Mail</td><td>' + escHtml(contact.email || '—') + '</td></tr>';
|
||||
html += '<tr><td class="text-muted">PLZ / Ort</td><td>' + escHtml((contact.zip || '') + ' ' + (contact.city || '')) + '</td></tr>';
|
||||
html += '<tr><td class="text-muted">Telefon</td><td>' + escHtml(contact.phone || contact.phonemobile || '—') + '</td></tr>';
|
||||
html += '<tr><td class="text-muted">Anfragen</td><td>' + (contact.leads_count || 0) + '</td></tr>';
|
||||
html += '<tr><td class="text-muted">Buchungen</td><td>' + (contact.bookings_count || 0) + '</td></tr>';
|
||||
html += '<tr><td class="text-muted">Erstellt</td><td>' + formatDate(contact.created_at) + '</td></tr>';
|
||||
html += '</table>';
|
||||
html += '</div>';
|
||||
|
||||
if (!isMaster) {
|
||||
html += '<div class="card-footer py-1 text-right">';
|
||||
html += '<button class="btn btn-sm btn-warning btn-merge" ';
|
||||
html += 'data-master="' + masterId + '" data-dupe="' + contact.id + '" ';
|
||||
html += 'data-name="' + escAttr(contact.firstname + ' ' + contact.name) + '">';
|
||||
html += '<span class="fa fa-compress-arrows-alt mr-1"></span> In Master zusammenführen';
|
||||
html += '</button>';
|
||||
html += '</div>';
|
||||
}
|
||||
|
||||
html += '</div></div>';
|
||||
return html;
|
||||
}
|
||||
|
||||
function formatDate(dateStr) {
|
||||
if (!dateStr) { return '—'; }
|
||||
var d = new Date(dateStr);
|
||||
return d.toLocaleDateString('de-DE');
|
||||
}
|
||||
|
||||
function escHtml(str) {
|
||||
if (!str) { return ''; }
|
||||
return String(str).replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>').replace(/"/g,'"');
|
||||
}
|
||||
|
||||
function escAttr(str) {
|
||||
if (!str) { return ''; }
|
||||
return String(str).replace(/"/g, '"');
|
||||
}
|
||||
|
||||
function showError(msg) {
|
||||
$('#merge-error-message').text(msg);
|
||||
$('#merge-error-toast').show().addClass('show');
|
||||
setTimeout(function() { $('#merge-error-toast').removeClass('show').fadeOut(); }, 6000);
|
||||
}
|
||||
|
||||
// ── Tab-Wechsel ───────────────────────────────────────────────────────
|
||||
$('#confidence-tabs a').on('click', function(e) {
|
||||
e.preventDefault();
|
||||
$('#confidence-tabs a').removeClass('active');
|
||||
$(this).addClass('active');
|
||||
loadGroups($(this).data('confidence'));
|
||||
});
|
||||
|
||||
// ── Zusammenführen ────────────────────────────────────────────────────
|
||||
$(document).on('click', '.btn-merge', function() {
|
||||
var $btn = $(this);
|
||||
var masterId = $btn.data('master');
|
||||
var dupeId = $btn.data('dupe');
|
||||
var name = $btn.data('name');
|
||||
|
||||
if (!confirm('"' + name + '" als Duplikat in Master #' + masterId + ' zusammenführen?\n\nAlle Anfragen und Buchungen werden umgehängt.')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$btn.prop('disabled', true).html('<span class="fa fa-spinner fa-spin mr-1"></span> Wird zusammengeführt…');
|
||||
|
||||
$.ajax({
|
||||
url: '{{ route('contact_merge') }}',
|
||||
type: 'POST',
|
||||
data: { master_id: masterId, duplicate_id: dupeId, _token: csrfToken },
|
||||
success: function() {
|
||||
$('#merge-success-toast').show().addClass('show');
|
||||
setTimeout(function() { $('#merge-success-toast').removeClass('show').fadeOut(); }, 4000);
|
||||
// Gruppe aus DOM entfernen und neu laden
|
||||
loadGroups(currentConfidence);
|
||||
},
|
||||
error: function(xhr) {
|
||||
var msg = (xhr.responseJSON && xhr.responseJSON.message) ? xhr.responseJSON.message : 'Zusammenführen fehlgeschlagen.';
|
||||
showError(msg);
|
||||
$btn.prop('disabled', false).html('<span class="fa fa-compress-arrows-alt mr-1"></span> In Master zusammenführen');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// ── Initial laden ─────────────────────────────────────────────────────
|
||||
$(document).ready(function() {
|
||||
loadGroups('HIGH');
|
||||
});
|
||||
</script>
|
||||
@endsection
|
||||
409
resources/views/contact/index.blade.php
Normal file
409
resources/views/contact/index.blade.php
Normal file
|
|
@ -0,0 +1,409 @@
|
|||
@extends('layouts.layout-2')
|
||||
|
||||
@section('content')
|
||||
<div class="d-flex justify-content-between align-items-center py-3 mb-3">
|
||||
<h4 class="font-weight-bold mb-0">
|
||||
{{ __('Kontakte') }}
|
||||
<small class="text-muted font-weight-light ml-2 d-none d-md-inline" id="header-subtitle">Stammkunden ohne Duplikate</small>
|
||||
</h4>
|
||||
<a href="{{ route('contact_detail', ['new']) }}" class="btn btn-sm btn-primary" id="btn-new-contact">
|
||||
<span class="fa fa-plus mr-1"></span> {{ __('Neuer Kontakt') }}
|
||||
</a>
|
||||
</div>
|
||||
|
||||
{{-- Filterleiste --}}
|
||||
<div class="card mb-3">
|
||||
<div class="card-body py-2">
|
||||
<div class="form-row align-items-end">
|
||||
|
||||
<div class="form-group col-sm-4 col-md-3 mb-2">
|
||||
<label class="form-label small text-muted mb-1">{{ __('Schnellsuche') }}</label>
|
||||
<input type="text" id="filter-search" class="form-control form-control-sm"
|
||||
placeholder="Name, Vorname, E-Mail, Telefon…">
|
||||
</div>
|
||||
|
||||
<div class="form-group col-sm-3 col-md-2 mb-2">
|
||||
<label class="form-label small text-muted mb-1">{{ __('PLZ / Ort') }}</label>
|
||||
<input type="text" id="filter-location" class="form-control form-control-sm"
|
||||
placeholder="z.B. 80331 oder München">
|
||||
</div>
|
||||
|
||||
<div class="form-group col-sm-5 col-md-4 mb-2">
|
||||
<label class="form-label small text-muted mb-1">{{ __('Anzeigen') }}</label>
|
||||
<div class="btn-group btn-group-sm d-flex" id="filter-group" role="group">
|
||||
<button type="button" class="btn btn-outline-primary filter-btn active" data-filter="">
|
||||
Alle
|
||||
</button>
|
||||
<button type="button" class="btn btn-outline-primary filter-btn" data-filter="has_leads">
|
||||
Mit Anfragen
|
||||
</button>
|
||||
<button type="button" class="btn btn-outline-primary filter-btn" data-filter="has_bookings">
|
||||
Mit Buchungen
|
||||
</button>
|
||||
<button type="button" class="btn btn-outline-warning filter-btn" data-filter="deleted">
|
||||
<span class="fa fa-trash mr-1"></span> Papierkorb
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group col-auto mb-2 ml-auto">
|
||||
<button type="button" id="filter-reset" class="btn btn-sm btn-outline-danger">
|
||||
<span class="fa fa-times mr-1"></span> Zurücksetzen
|
||||
</button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- History-Modal (Anfragen + Buchungen) --}}
|
||||
<div class="modal fade" id="contactHistoryModal" tabindex="-1" role="dialog" aria-labelledby="contactHistoryModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog modal-xl modal-dialog-scrollable" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="contactHistoryModalLabel">
|
||||
<i class="fa fa-history mr-2"></i>
|
||||
<span id="history-modal-title">Anfragen & Buchungen</span>
|
||||
</h5>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Schließen">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body" id="history-modal-body">
|
||||
<div class="text-center py-4">
|
||||
<span class="fa fa-spinner fa-spin fa-2x text-muted"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">Schließen</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- Bestätigungs-Modal Löschen --}}
|
||||
<div class="modal fade" id="deleteContactModal" tabindex="-1" role="dialog" aria-labelledby="deleteContactModalLabel"
|
||||
aria-hidden="true">
|
||||
<div class="modal-dialog modal-dialog-centered" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="deleteContactModalLabel">
|
||||
<i class="fa fa-exclamation-triangle text-danger mr-2"></i>Kontakt löschen
|
||||
</h5>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Schließen">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>Soll <strong id="delete-contact-name"></strong> wirklich gelöscht werden?</p>
|
||||
<p class="text-muted small mb-0">Der Kontakt wird als gelöscht markiert und kann bei Bedarf
|
||||
wiederhergestellt werden.</p>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">Abbrechen</button>
|
||||
<button type="button" class="btn btn-danger" id="btn-confirm-delete">
|
||||
<span class="fa fa-trash mr-1"></span> Endgültig löschen
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- Fehler-Toast --}}
|
||||
<div id="delete-error-toast" class="alert alert-danger alert-dismissible fade"
|
||||
style="position:fixed; bottom:1rem; right:1rem; z-index:9999; min-width:300px; display:none;">
|
||||
<button type="button" class="close" onclick="$('#delete-error-toast').fadeOut();">×</button>
|
||||
<span id="delete-error-message"></span>
|
||||
</div>
|
||||
|
||||
{{-- Erfolg-Toast (Wiederherstellen) --}}
|
||||
<div id="restore-success-toast" class="alert alert-success alert-dismissible fade"
|
||||
style="position:fixed; bottom:1rem; right:1rem; z-index:9999; min-width:300px; display:none;">
|
||||
<button type="button" class="close" onclick="$('#restore-success-toast').fadeOut();">×</button>
|
||||
<span class="fa fa-check mr-1"></span> Kontakt wurde wiederhergestellt.
|
||||
</div>
|
||||
|
||||
{{-- Tabelle --}}
|
||||
<div class="card">
|
||||
<div class="table-responsive-track" id="datatables-contact-scroll">
|
||||
<div class="table-responsive-thumb" id="datatables-contact-thumb"></div>
|
||||
</div>
|
||||
<div class="card-datatable table-responsive">
|
||||
<table class="table table-striped table-bordered table-sm" id="datatables-contact">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 42px;"> </th>
|
||||
<th style="width: 70px;">{{ __('ID') }}</th>
|
||||
<th>{{ __('Vorname') }}</th>
|
||||
<th>{{ __('Nachname') }}</th>
|
||||
<th>{{ __('E-Mail') }}</th>
|
||||
<th>{{ __('PLZ') }}</th>
|
||||
<th>{{ __('Ort') }}</th>
|
||||
<th style="width: 80px;" class="text-center">{{ __('Anfragen') }}</th>
|
||||
<th style="width: 80px;" class="text-center">{{ __('Buchungen') }}</th>
|
||||
<th style="width: 130px;">{{ __('Gelöscht am') }}</th>
|
||||
<th style="width: 42px;"> </th>
|
||||
</tr>
|
||||
</thead>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
|
||||
var activeFilter = '';
|
||||
var locationFilter = '';
|
||||
|
||||
var table = $('#datatables-contact').dataTable({
|
||||
"processing": true,
|
||||
"serverSide": true,
|
||||
"ajax": {
|
||||
"url": '{!! route('data_table_contacts') !!}',
|
||||
"data": function(d) {
|
||||
if (activeFilter === 'has_leads') {
|
||||
d.filter_has_leads = 1;
|
||||
}
|
||||
if (activeFilter === 'has_bookings') {
|
||||
d.filter_has_bookings = 1;
|
||||
}
|
||||
if (activeFilter === 'deleted') {
|
||||
d.filter_deleted = 1;
|
||||
}
|
||||
if (locationFilter !== '') {
|
||||
d.filter_location = locationFilter;
|
||||
}
|
||||
}
|
||||
},
|
||||
"order": [
|
||||
[1, "desc"]
|
||||
],
|
||||
"columns": [{
|
||||
data: 'action_edit',
|
||||
orderable: false,
|
||||
searchable: false
|
||||
},
|
||||
{
|
||||
data: 'id',
|
||||
name: 'customer.id'
|
||||
},
|
||||
{
|
||||
data: 'firstname',
|
||||
name: 'firstname',
|
||||
searchable: true
|
||||
},
|
||||
{
|
||||
data: 'name',
|
||||
name: 'name',
|
||||
searchable: true
|
||||
},
|
||||
{
|
||||
data: 'email',
|
||||
name: 'email',
|
||||
searchable: true
|
||||
},
|
||||
|
||||
|
||||
{
|
||||
data: 'zip',
|
||||
name: 'zip',
|
||||
searchable: true
|
||||
},
|
||||
{
|
||||
data: 'city',
|
||||
name: 'city',
|
||||
searchable: true
|
||||
|
||||
},
|
||||
{
|
||||
data: 'leads_count',
|
||||
name: 'leads_count',
|
||||
orderable: false,
|
||||
searchable: false,
|
||||
className: 'text-center'
|
||||
},
|
||||
{
|
||||
data: 'bookings_count',
|
||||
name: 'bookings_count',
|
||||
orderable: false,
|
||||
searchable: false,
|
||||
className: 'text-center'
|
||||
},
|
||||
{
|
||||
data: 'deleted_at',
|
||||
name: 'deleted_at',
|
||||
searchable: false,
|
||||
visible: false
|
||||
},
|
||||
{
|
||||
data: 'action_delete',
|
||||
orderable: false,
|
||||
searchable: false
|
||||
},
|
||||
],
|
||||
"columnDefs": [{
|
||||
// Anzahl-Badges — klickbar für History-Modal
|
||||
targets: [7, 8],
|
||||
render: function(data, type, row) {
|
||||
if (data === null || parseInt(data) === 0) {
|
||||
return '<span class="text-muted">' + (data !== null ? data : '—') + '</span>';
|
||||
}
|
||||
return '<span class="badge badge-pill badge-primary badge-history-link" '
|
||||
+ 'style="cursor:pointer;" data-id="' + row.raw_id + '">'
|
||||
+ data + '</span>';
|
||||
}
|
||||
}],
|
||||
"bLengthChange": false,
|
||||
"iDisplayLength": 100,
|
||||
"language": {
|
||||
"url": "/js/German.json"
|
||||
},
|
||||
"dom": 'rt<"d-flex justify-content-between mt-2"ip>',
|
||||
drawCallback: function() {
|
||||
dataTableScrollTrack('#datatables-contact');
|
||||
}
|
||||
}).api();
|
||||
|
||||
// ── Schnellsuche (Globale Suche) ──────────────────────────────────
|
||||
var searchTimer;
|
||||
$('#filter-search').on('keyup', function() {
|
||||
clearTimeout(searchTimer);
|
||||
var val = $(this).val();
|
||||
searchTimer = setTimeout(function() {
|
||||
table.search(val).draw();
|
||||
}, 350);
|
||||
});
|
||||
|
||||
// ── PLZ / Ort Suche (OR über zip + city, serverseitig) ───────────
|
||||
var locationTimer;
|
||||
$('#filter-location').on('keyup', function() {
|
||||
clearTimeout(locationTimer);
|
||||
locationFilter = $(this).val();
|
||||
locationTimer = setTimeout(function() {
|
||||
table.draw();
|
||||
}, 350);
|
||||
});
|
||||
|
||||
// ── Schnellfilter-Buttons ─────────────────────────────────────────
|
||||
$('.filter-btn').on('click', function() {
|
||||
$('.filter-btn').removeClass('active');
|
||||
$(this).addClass('active');
|
||||
activeFilter = $(this).data('filter');
|
||||
var isTrash = (activeFilter === 'deleted');
|
||||
$('#btn-new-contact').toggle(!isTrash);
|
||||
$('#header-subtitle').text(isTrash ? 'Gelöschte Kontakte' : 'Stammkunden ohne Duplikate');
|
||||
table.column(9).visible(isTrash);
|
||||
if (isTrash) {
|
||||
table.order([9, 'desc']).draw();
|
||||
} else {
|
||||
table.order([1, 'desc']).draw();
|
||||
}
|
||||
});
|
||||
|
||||
// ── Zurücksetzen ──────────────────────────────────────────────────
|
||||
$('#filter-reset').on('click', function() {
|
||||
activeFilter = '';
|
||||
locationFilter = '';
|
||||
$('#filter-search').val('');
|
||||
$('#filter-location').val('');
|
||||
$('.filter-btn').removeClass('active');
|
||||
$('.filter-btn[data-filter=""]').addClass('active');
|
||||
$('#btn-new-contact').show();
|
||||
$('#header-subtitle').text('Stammkunden ohne Duplikate');
|
||||
table.column(9).visible(false);
|
||||
table.order([1, 'desc']).search('').columns().search('').draw();
|
||||
});
|
||||
|
||||
// ── Löschen ───────────────────────────────────────────────────────
|
||||
var deleteContactId = null;
|
||||
|
||||
// Klick auf Löschen-Button öffnet Modal
|
||||
$('#datatables-contact').on('click', '.btn-contact-delete', function() {
|
||||
deleteContactId = $(this).data('id');
|
||||
$('#delete-contact-name').text($(this).data('name'));
|
||||
$('#deleteContactModal').modal('show');
|
||||
});
|
||||
|
||||
// Bestätigung: DELETE-Request abschicken
|
||||
$('#btn-confirm-delete').on('click', function() {
|
||||
if (!deleteContactId) {
|
||||
return;
|
||||
}
|
||||
|
||||
var $btn = $(this).prop('disabled', true).html(
|
||||
'<span class="fa fa-spinner fa-spin mr-1"></span> Löschen…');
|
||||
|
||||
$.ajax({
|
||||
url: '/contact/' + deleteContactId,
|
||||
type: 'POST',
|
||||
data: {
|
||||
_method: 'DELETE',
|
||||
_token: '{{ csrf_token() }}'
|
||||
},
|
||||
success: function() {
|
||||
$('#deleteContactModal').modal('hide');
|
||||
table.draw(false); // Seite behalten, nur neu laden
|
||||
},
|
||||
error: function(xhr) {
|
||||
$('#deleteContactModal').modal('hide');
|
||||
var msg = (xhr.responseJSON && xhr.responseJSON.message) ?
|
||||
xhr.responseJSON.message :
|
||||
'Löschen fehlgeschlagen.';
|
||||
$('#delete-error-message').text(msg);
|
||||
$('#delete-error-toast').show().addClass('show');
|
||||
setTimeout(function() {
|
||||
$('#delete-error-toast').removeClass('show').fadeOut();
|
||||
}, 6000);
|
||||
},
|
||||
complete: function() {
|
||||
$btn.prop('disabled', false).html(
|
||||
'<span class="fa fa-trash mr-1"></span> Endgültig löschen');
|
||||
deleteContactId = null;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// ── Wiederherstellen ──────────────────────────────────────────────
|
||||
$('#datatables-contact').on('click', '.btn-contact-restore', function() {
|
||||
var $btn = $(this).prop('disabled', true).html('<span class="fa fa-spinner fa-spin"></span>');
|
||||
var contactId = $(this).data('id');
|
||||
|
||||
$.ajax({
|
||||
url: '/contact/' + contactId + '/restore',
|
||||
type: 'POST',
|
||||
data: {
|
||||
_method: 'PATCH',
|
||||
_token: '{{ csrf_token() }}'
|
||||
},
|
||||
success: function() {
|
||||
table.draw(false);
|
||||
$('#restore-success-toast').show().addClass('show');
|
||||
setTimeout(function() {
|
||||
$('#restore-success-toast').removeClass('show').fadeOut();
|
||||
}, 4000);
|
||||
},
|
||||
error: function() {
|
||||
$btn.prop('disabled', false).html('<span class="fa fa-undo"></span>');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// ── History-Modal (Anfragen & Buchungen) ──────────────────────────
|
||||
$('#datatables-contact').on('click', '.badge-history-link', function() {
|
||||
var contactId = $(this).data('id');
|
||||
$('#history-modal-body').html(
|
||||
'<div class="text-center py-4"><span class="fa fa-spinner fa-spin fa-2x text-muted"></span></div>'
|
||||
);
|
||||
$('#contactHistoryModal').modal('show');
|
||||
$.get('/contact/' + contactId + '/history', function(html) {
|
||||
$('#history-modal-body').html(html);
|
||||
}).fail(function() {
|
||||
$('#history-modal-body').html(
|
||||
'<p class="text-danger p-3">Fehler beim Laden der Daten.</p>'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
</script>
|
||||
@endsection
|
||||
|
|
@ -45,7 +45,7 @@
|
|||
<p><strong>Kunde: </strong>
|
||||
{{ $customer_mail->customer->salutation->name }} {{ $customer_mail->customer->title }} {{ $customer_mail->customer->firstname }} {{ $customer_mail->customer->name }}
|
||||
@if($customer_mail->booking)
|
||||
({{$customer_mail->booking->lead_id}})
|
||||
({{$customer_mail->booking->inquiry_id}})
|
||||
@endif
|
||||
</p>
|
||||
@endif
|
||||
|
|
|
|||
|
|
@ -1,11 +1,13 @@
|
|||
<!DOCTYPE html>
|
||||
|
||||
<html lang="{{ app()->getLocale() }}" class="default-style layout-collapsed">
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="x-ua-compatible" content="IE=edge,chrome=1">
|
||||
<meta name="description" content="">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
|
||||
<meta name="viewport"
|
||||
content="width=device-width, initial-scale=1.0, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
|
||||
<meta name="csrf-token" content="{{ csrf_token() }}">
|
||||
|
||||
<title>{{ config('app.name') }}</title>
|
||||
|
|
@ -32,9 +34,9 @@
|
|||
|
||||
<link rel="stylesheet" href="{{ asset('/vendor/laravel-filemanager/css/dropzone.min.css') }}">
|
||||
|
||||
@if(isset($lfm_helper))
|
||||
@if (isset($lfm_helper))
|
||||
@else
|
||||
{{-- <link rel="stylesheet" href="{{ asset('/vendor/libs/dropzone/dropzone.css') }}"> --}}
|
||||
{{-- <link rel="stylesheet" href="{{ asset('/vendor/libs/dropzone/dropzone.css') }}"> --}}
|
||||
@endif
|
||||
|
||||
<link rel="stylesheet" href="{{ mix('/vendor/libs/bootstrap-select/bootstrap-select.css') }}">
|
||||
|
|
@ -42,7 +44,8 @@
|
|||
<link rel="stylesheet" href="{{ mix('/vendor/libs/datatables/datatables.css') }}">
|
||||
|
||||
<link rel="stylesheet" href="{{ mix('/vendor/libs/bootstrap-datepicker/bootstrap-datepicker.css') }}">
|
||||
<link rel="stylesheet" href="{{ asset('/vendor/libs/bootstrap-material-datetimepicker/bootstrap-material-datetimepicker.css') }}">
|
||||
<link rel="stylesheet"
|
||||
href="{{ asset('/vendor/libs/bootstrap-material-datetimepicker/bootstrap-material-datetimepicker.css') }}">
|
||||
<!--
|
||||
<link rel="stylesheet" href="{{ mix('/vendor/libs/bootstrap-daterangepicker/bootstrap-daterangepicker.css') }}">
|
||||
-->
|
||||
|
|
@ -65,16 +68,16 @@
|
|||
<!-- `perfect-scrollbar` library required by SideNav plugin -->
|
||||
<link rel="stylesheet" href="{{ mix('/vendor/libs/perfect-scrollbar/perfect-scrollbar.css') }}">
|
||||
|
||||
@yield('styles')
|
||||
@yield('styles')
|
||||
|
||||
<!-- Application stylesheets -->
|
||||
<!-- Application stylesheets -->
|
||||
<link rel="stylesheet" href="{{ mix('/css/application.css') }}?v=9{{ get_file_last_time('js/application.css') }}">
|
||||
<script src="{{ asset('/js/jquery.min.js') }}"></script>
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="{{ asset('/css/cookieconsent.min.css') }}" />
|
||||
<script src="{{ asset('/js/cookieconsent.min.js') }}"></script>
|
||||
<script>
|
||||
window.addEventListener("load", function(){
|
||||
window.addEventListener("load", function() {
|
||||
window.cookieconsent.initialise({
|
||||
"palette": {
|
||||
"popup": {
|
||||
|
|
@ -87,109 +90,138 @@
|
|||
}
|
||||
},
|
||||
"content": {
|
||||
"message": "{{__('This website uses cookies in order to guarantee the best possible service. With your visit to this site you agree to our use of cookies.') }}",
|
||||
"dismiss": "{{__('OK')}}",
|
||||
"link": "{{__('data protection')}}",
|
||||
"message": "{{ __('This website uses cookies in order to guarantee the best possible service. With your visit to this site you agree to our use of cookies.') }}",
|
||||
"dismiss": "{{ __('OK') }}",
|
||||
"link": "{{ __('data protection') }}",
|
||||
"href": "{{ route('data_protected') }}",
|
||||
"target": "_blank",
|
||||
}
|
||||
})});
|
||||
})
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
@yield('layout-content')
|
||||
@yield('layout-content')
|
||||
|
||||
@include('iq.content.assets.modals')
|
||||
@include('iq.content.assets.modals')
|
||||
|
||||
<!-- Core scripts -->
|
||||
<script src="{{ mix('/vendor/libs/popper/popper.js') }}"></script>
|
||||
<script src="{{ mix('/vendor/js/bootstrap.js') }}"></script>
|
||||
<script src="{{ mix('/vendor/js/sidenav.js') }}"></script>
|
||||
<script src="{{ mix('/vendor/libs/growl/growl.js') }}"></script>
|
||||
<script src="{{ asset('/vendor/libs/js-cookie/src/js.cookie.js') }}"></script>
|
||||
<script src="{{ asset('/vendor/libs/moment-develop/min/moment.min.js') }}"></script>
|
||||
<script src="{{ asset('/vendor/libs/moment-develop/locale/de.js') }}"></script>
|
||||
<!-- Core scripts -->
|
||||
<script src="{{ mix('/vendor/libs/popper/popper.js') }}"></script>
|
||||
<script src="{{ mix('/vendor/js/bootstrap.js') }}"></script>
|
||||
<script src="{{ mix('/vendor/js/sidenav.js') }}"></script>
|
||||
<script src="{{ mix('/vendor/libs/growl/growl.js') }}"></script>
|
||||
<script src="{{ asset('/vendor/libs/js-cookie/src/js.cookie.js') }}"></script>
|
||||
<script src="{{ asset('/vendor/libs/moment-develop/min/moment.min.js') }}"></script>
|
||||
<script src="{{ asset('/vendor/libs/moment-develop/locale/de.js') }}"></script>
|
||||
|
||||
<script src="{{ asset('/vendor/laravel-filemanager/js/dropzone.min.js') }}"></script>
|
||||
<script src="{{ asset('/vendor/laravel-filemanager/js/dropzone.min.js') }}"></script>
|
||||
|
||||
@if(isset($lfm_helper))
|
||||
@else
|
||||
{{-- <script src="{{asset('/vendor/libs/dropzone/dropzone.js')}}"></script>--}}
|
||||
@endif
|
||||
@if (isset($lfm_helper))
|
||||
@else
|
||||
{{-- <script src="{{asset('/vendor/libs/dropzone/dropzone.js')}}"></script> --}}
|
||||
@endif
|
||||
|
||||
<script src="{{ mix('/vendor/libs/validate/validate.js') }}"></script>
|
||||
<script src="{{ mix('/vendor/libs/validate/validate.js') }}"></script>
|
||||
|
||||
<script src="{{ mix('/vendor/libs/bootstrap-select/bootstrap-select.js') }}"></script>
|
||||
<script src="{{ mix('/vendor/libs/select2/select2.js') }}"></script>
|
||||
<script src="{{ mix('/vendor/libs/datatables/datatables.js') }}"></script>
|
||||
<script src="{{ mix('/vendor/libs/bootstrap-select/bootstrap-select.js') }}"></script>
|
||||
<script src="{{ mix('/vendor/libs/select2/select2.js') }}"></script>
|
||||
<script src="{{ mix('/vendor/libs/datatables/datatables.js') }}"></script>
|
||||
|
||||
<script src="{{ mix('/vendor/libs/bootstrap-datepicker/bootstrap-datepicker.js') }}"></script>
|
||||
<!--
|
||||
<script src="{{ mix('/vendor/libs/bootstrap-datepicker/bootstrap-datepicker.js') }}"></script>
|
||||
<!--
|
||||
<script src="{{ mix('/vendor/libs/bootstrap-daterangepicker/bootstrap-daterangepicker.js') }}"></script>
|
||||
-->
|
||||
<script src="{{ asset('/vendor/libs/bootstrap-material-datetimepicker/bootstrap-material-datetimepicker.js') }}"></script>
|
||||
<script src="{{ asset('/vendor/libs/bootstrap-material-datetimepicker/bootstrap-material-datetimepicker.js') }}">
|
||||
</script>
|
||||
|
||||
|
||||
<script src="{{asset('/js/bootstrap-datepicker.de.min.js')}}"></script>
|
||||
<script src="{{ mix('/vendor/libs/dragula/dragula.js') }}"></script>
|
||||
<script src="{{asset('/vendor/libs/nestable/my-nestable.js')}}"></script>
|
||||
<script src="{{ mix('/vendor/libs/minicolors/minicolors.js') }}"></script>
|
||||
<script src="{{ asset('/vendor/libs/summernote/dist/summernote-bs4.js?v=0.8.16') }}"></script>
|
||||
<script src="{{ asset('/vendor/libs/summernote/dist/lang/summernote-de-DE.js?v=0.8.16') }}"></script>
|
||||
<script src="{{ asset('/js/summernote-cleaner.js?v=1') }}"></script>
|
||||
<script src="{{ asset('/js/bootstrap-datepicker.de.min.js') }}"></script>
|
||||
<script src="{{ mix('/vendor/libs/dragula/dragula.js') }}"></script>
|
||||
<script src="{{ asset('/vendor/libs/nestable/my-nestable.js') }}"></script>
|
||||
<script src="{{ mix('/vendor/libs/minicolors/minicolors.js') }}"></script>
|
||||
<script src="{{ asset('/vendor/libs/summernote/dist/summernote-bs4.js?v=0.8.16') }}"></script>
|
||||
<script src="{{ asset('/vendor/libs/summernote/dist/lang/summernote-de-DE.js?v=0.8.16') }}"></script>
|
||||
<script src="{{ asset('/js/summernote-cleaner.js?v=1') }}"></script>
|
||||
|
||||
<script src="{{ asset('/vendor/libs/quill/quill.min.js?v=1.3.6') }}"></script>
|
||||
<script src="{{ asset('/vendor/libs/quill-placeholder-module/dist/placeholder-module.js?v=1') }}"></script>
|
||||
<script src="{{ asset('/vendor/libs/quill/quill.min.js?v=1.3.6') }}"></script>
|
||||
<script src="{{ asset('/vendor/libs/quill-placeholder-module/dist/placeholder-module.js?v=1') }}"></script>
|
||||
|
||||
@if(isset($lfm_helper))
|
||||
<script src="{{ asset('/js/summernote-iq-content-extension.js?v=6') }}"></script>
|
||||
<script src="{{ asset('/js/summernote-image-title.js?v=2') }}"></script>
|
||||
<script src="{{ asset('/vendor/laravel-filemanager/js/cropper.min.js') }}"></script>
|
||||
<script src="{{ asset('/js/filemanager.js') }}?v=6"></script>
|
||||
<script src="{{ asset('/js/pages_file-manager.js') }}?v=6"></script>
|
||||
@if (isset($lfm_helper))
|
||||
<script src="{{ asset('/js/summernote-iq-content-extension.js?v=6') }}"></script>
|
||||
<script src="{{ asset('/js/summernote-image-title.js?v=2') }}"></script>
|
||||
<script src="{{ asset('/vendor/laravel-filemanager/js/cropper.min.js') }}"></script>
|
||||
<script src="{{ asset('/js/filemanager.js') }}?v=6"></script>
|
||||
<script src="{{ asset('/js/pages_file-manager.js') }}?v=6"></script>
|
||||
@endif
|
||||
|
||||
@endif
|
||||
<!-- Libs -->
|
||||
<!-- `perfect-scrollbar` library required by SideNav plugin -->
|
||||
<script src="{{ mix('/vendor/libs/perfect-scrollbar/perfect-scrollbar.js') }}"></script>
|
||||
|
||||
<!-- Libs -->
|
||||
<!-- `perfect-scrollbar` library required by SideNav plugin -->
|
||||
<script src="{{ mix('/vendor/libs/perfect-scrollbar/perfect-scrollbar.js') }}"></script>
|
||||
@yield('scripts')
|
||||
|
||||
@yield('scripts')
|
||||
|
||||
<!-- Application javascripts -->
|
||||
<script src="{{ mix('/js/application.js') }}"></script>
|
||||
<script src="{{ asset('/js/custom.js') }}?v=11{{ get_file_last_time('/js/custom.js') }}"></script>
|
||||
<!-- Application javascripts -->
|
||||
<script src="{{ mix('/js/application.js') }}"></script>
|
||||
<script src="{{ asset('/js/custom.js') }}?v=11{{ get_file_last_time('/js/custom.js') }}"></script>
|
||||
|
||||
|
||||
@include('asset.js')
|
||||
@include('asset.js')
|
||||
|
||||
<script>
|
||||
// Dragula
|
||||
$(function() {
|
||||
// Drag handle
|
||||
dragula([$('#dragula-drag-handles')[0]], {
|
||||
moves: function (el, container, handle) {
|
||||
return handle.classList.contains('handle');
|
||||
}
|
||||
<script>
|
||||
// Dragula
|
||||
$(function() {
|
||||
// Drag handle
|
||||
dragula([$('#dragula-drag-handles')[0]], {
|
||||
moves: function(el, container, handle) {
|
||||
return handle.classList.contains('handle');
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Dropzone.autoDiscover = false;
|
||||
Dropzone.autoDiscover = false;
|
||||
|
||||
@if(isset($lfm_helper))
|
||||
$("#uploadForm").dropzone({
|
||||
@if (isset($lfm_helper))
|
||||
$("#uploadForm").dropzone({
|
||||
paramName: "upload[]", // The name that will be used to transfer the file
|
||||
uploadMultiple: false,
|
||||
parallelUploads: 10,
|
||||
clickable: '#upload-button',
|
||||
dictDefaultMessage: '<i class="ion ion-ios-cloud-upload "></i>Hier klicken, oder Datei hier reinziehen (Drag&Drop)',
|
||||
init: function() {
|
||||
var _this = this; // For the closure
|
||||
this.on('success', function(file, response) {
|
||||
//console.log(response);
|
||||
if (response === 'OK') {
|
||||
LFileManager.loadItems();
|
||||
} else {
|
||||
_this.defaultOptions.error(file, response); //response.join('\n')
|
||||
}
|
||||
});
|
||||
},
|
||||
headers: {
|
||||
'Authorization': 'Bearer ' + LFileManager.getUrlParam('token'),
|
||||
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
|
||||
},
|
||||
// acceptedFiles: LFileManager.lfm_config['lfm_availableMimeTypes'] ,
|
||||
maxFilesize: (LFileManager.lfm_config['lfm_maxUploadSize'] / 1000),
|
||||
});
|
||||
@endif
|
||||
|
||||
/*Dropzone.options.uploadForm = {
|
||||
paramName: "upload[]", // The name that will be used to transfer the file
|
||||
uploadMultiple: false,
|
||||
parallelUploads: 10,
|
||||
clickable: '#upload-button',
|
||||
dictDefaultMessage: '<i class="ion ion-ios-cloud-upload "></i>Hier klicken, oder Datei hier reinziehen (Drag&Drop)',
|
||||
init: function () {
|
||||
//dictDefaultMessage: LFileManager.lfm_config['lfm_lang']['message-drop'],
|
||||
init: function() {
|
||||
console.log("Dinit")
|
||||
var _this = this; // For the closure
|
||||
this.on('success', function (file, response) {
|
||||
//console.log(response);
|
||||
this.on('success', function(file, response) {
|
||||
console.log(response);
|
||||
if (response === 'OK') {
|
||||
LFileManager.loadItems();
|
||||
} else {
|
||||
|
|
@ -202,170 +234,150 @@
|
|||
},
|
||||
// acceptedFiles: LFileManager.lfm_config['lfm_availableMimeTypes'] ,
|
||||
maxFilesize: (LFileManager.lfm_config['lfm_maxUploadSize'] / 1000),
|
||||
});
|
||||
@endif
|
||||
};*/
|
||||
|
||||
/*Dropzone.options.uploadForm = {
|
||||
paramName: "upload[]", // The name that will be used to transfer the file
|
||||
uploadMultiple: false,
|
||||
parallelUploads: 10,
|
||||
clickable: '#upload-button',
|
||||
//dictDefaultMessage: LFileManager.lfm_config['lfm_lang']['message-drop'],
|
||||
init: function() {
|
||||
console.log("Dinit")
|
||||
var _this = this; // For the closure
|
||||
this.on('success', function(file, response) {
|
||||
console.log(response);
|
||||
if (response === 'OK') {
|
||||
LFileManager.loadItems();
|
||||
} else {
|
||||
_this.defaultOptions.error(file, response); //response.join('\n')
|
||||
}
|
||||
});
|
||||
},
|
||||
headers: {
|
||||
'Authorization': 'Bearer ' + LFileManager.getUrlParam('token')
|
||||
},
|
||||
// acceptedFiles: LFileManager.lfm_config['lfm_availableMimeTypes'] ,
|
||||
maxFilesize: (LFileManager.lfm_config['lfm_maxUploadSize'] / 1000),
|
||||
};*/
|
||||
$(document).ready(function() {
|
||||
|
||||
$(document).ready(function() {
|
||||
|
||||
$('.summernote').summernote({
|
||||
height: 400,
|
||||
tabsize: 2,
|
||||
followingToolbar: true,
|
||||
imageTitle: {
|
||||
specificAltField: true,
|
||||
},
|
||||
lang: 'de-DE',
|
||||
toolbar: [
|
||||
['style', ['style']],
|
||||
['font', ['bold', 'italic', 'underline', 'clear']],
|
||||
['color', ['color']],
|
||||
['para', ['ul', 'ol', 'paragraph']],
|
||||
['extensions', ['gallery']],
|
||||
['insert', ['link', 'picture', 'video', 'hr']],
|
||||
['view', ['fullscreen', 'codeview']],
|
||||
['help', ['help']]
|
||||
],
|
||||
popover: {
|
||||
image: [
|
||||
['image', ['resizeFull', 'resizeHalf', 'resizeQuarter', 'resizeNone']],
|
||||
['float', ['floatLeft', 'floatRight', 'floatNone']],
|
||||
['remove', ['removeMedia']],
|
||||
['custom', ['imageTitle']],
|
||||
],
|
||||
},
|
||||
callbacks :{
|
||||
onInit: function() {
|
||||
// $(this).data('image_dialog_images_html', '<div class="row"..');
|
||||
$(this).data('image_dialog_images_url', "/iq/content/assets/modal");
|
||||
$(this).data('image_dialog_title', "Medien");
|
||||
$(this).data('image_dialog_close_btn_text', "schließen");
|
||||
$(this).data('image_dialog_ok_btn_text', "Einfügen");
|
||||
}
|
||||
},
|
||||
/*
|
||||
callbacks: {
|
||||
onPaste: function (e) {
|
||||
var bufferText = ((e.originalEvent || e).clipboardData || window.clipboardData).getData('Text');
|
||||
e.preventDefault();
|
||||
document.execCommand('insertText', false, bufferText);
|
||||
}
|
||||
}
|
||||
*/
|
||||
});
|
||||
|
||||
$('.summernote-small').summernote({
|
||||
height: 150,
|
||||
tabsize: 2,
|
||||
followingToolbar: true,
|
||||
imageTitle: {
|
||||
specificAltField: true,
|
||||
},
|
||||
toolbar: [
|
||||
['style', ['style']],
|
||||
['font', ['bold', 'italic', 'underline', 'clear']],
|
||||
['color', ['color']],
|
||||
['para', ['ul', 'ol', 'paragraph']],
|
||||
['extensions', ['gallery']],
|
||||
['insert', ['link', 'picture', 'video', 'hr']],
|
||||
['view', ['fullscreen', 'codeview']],
|
||||
['help', ['help']]
|
||||
],
|
||||
popover: {
|
||||
image: [
|
||||
['imagesize', ['imageSize100', 'imageSize50', 'imageSize25']],
|
||||
['float', ['floatLeft', 'floatRight', 'floatNone']],
|
||||
['remove', ['removeMedia']],
|
||||
['custom', ['imageTitle']],
|
||||
],
|
||||
},
|
||||
callbacks :{
|
||||
onInit: function() {
|
||||
// $(this).data('image_dialog_images_html', '<div class="row"..');
|
||||
$(this).data('image_dialog_images_url', "/iq/content/assets/modal");
|
||||
$(this).data('image_dialog_title', "Medien");
|
||||
$(this).data('image_dialog_close_btn_text', "schließen");
|
||||
$(this).data('image_dialog_ok_btn_text', "Einfügen");
|
||||
}
|
||||
},
|
||||
|
||||
});
|
||||
|
||||
$('.summernote-exsmall').summernote({
|
||||
height: 100,
|
||||
tabsize: 2,
|
||||
followingToolbar: true,
|
||||
toolbar: [
|
||||
['font', ['bold', 'italic', 'underline', 'clear']],
|
||||
['para', ['ul', 'ol']],
|
||||
['insert', ['link', 'hr']],
|
||||
['view', ['fullscreen', 'codeview']],
|
||||
],
|
||||
});
|
||||
|
||||
$('.summernote-air').summernote({
|
||||
airMode: true,
|
||||
lang: 'de-DE',
|
||||
placeholder: 'Text ...',
|
||||
tabsize: 2,
|
||||
popover: { air:[
|
||||
$('.summernote').summernote({
|
||||
height: 400,
|
||||
tabsize: 2,
|
||||
followingToolbar: true,
|
||||
imageTitle: {
|
||||
specificAltField: true,
|
||||
},
|
||||
lang: 'de-DE',
|
||||
toolbar: [
|
||||
['style', ['style']],
|
||||
['font', ['bold', 'italic', 'underline', 'clear']],
|
||||
['font', ['strikethrough']],
|
||||
['para', ['ul', 'ol', 'paragraph']],
|
||||
['insert', ['link']],
|
||||
['color', ['color']],
|
||||
['view', ['codeview']],
|
||||
] },
|
||||
cleaner:{
|
||||
action: 'paste', // both|button|paste 'button' only cleans via toolbar button, 'paste' only clean when pasting content, both does both options.
|
||||
newline: '<br>', // Summernote's default is to use '<p><br></p>'
|
||||
notStyle: 'position:absolute;top:0;left:0;right:0', // Position of Notification
|
||||
icon: '<i class="note-icon">[Your Button]</i>',
|
||||
keepHtml: false, // Remove all Html formats
|
||||
keepOnlyTags: ['<p>', '<br>', '<ul>', '<li>', '<b>', '<strong>','<i>', '<a>'], // If keepHtml is true, remove all tags except these
|
||||
keepClasses: false, // Remove Classes
|
||||
badTags: ['style', 'script', 'applet', 'embed', 'noframes', 'noscript', 'html'], // Remove full tags with contents
|
||||
badAttributes: ['style', 'start'], // Remove attributes from remaining tags
|
||||
limitChars: false, // 0/false|# 0/false disables option
|
||||
limitDisplay: false, // text|html|both
|
||||
limitStop: false // true/false
|
||||
}
|
||||
});
|
||||
//save in the codeview
|
||||
$('.note-codable').on('blur', function() {
|
||||
var codeviewHtml = $(this).val();
|
||||
var $summernoteTextarea = $(this).closest('.note-editor').siblings('textarea');
|
||||
$summernoteTextarea.val(codeviewHtml);
|
||||
});
|
||||
});
|
||||
['para', ['ul', 'ol', 'paragraph']],
|
||||
['extensions', ['gallery']],
|
||||
['insert', ['link', 'picture', 'video', 'hr']],
|
||||
['view', ['fullscreen', 'codeview']],
|
||||
['help', ['help']]
|
||||
],
|
||||
popover: {
|
||||
image: [
|
||||
['image', ['resizeFull', 'resizeHalf', 'resizeQuarter', 'resizeNone']],
|
||||
['float', ['floatLeft', 'floatRight', 'floatNone']],
|
||||
['remove', ['removeMedia']],
|
||||
['custom', ['imageTitle']],
|
||||
],
|
||||
},
|
||||
callbacks: {
|
||||
onInit: function() {
|
||||
// $(this).data('image_dialog_images_html', '<div class="row"..');
|
||||
$(this).data('image_dialog_images_url', "/iq/content/assets/modal");
|
||||
$(this).data('image_dialog_title', "Medien");
|
||||
$(this).data('image_dialog_close_btn_text', "schließen");
|
||||
$(this).data('image_dialog_ok_btn_text', "Einfügen");
|
||||
}
|
||||
},
|
||||
/*
|
||||
callbacks: {
|
||||
onPaste: function (e) {
|
||||
var bufferText = ((e.originalEvent || e).clipboardData || window.clipboardData).getData('Text');
|
||||
e.preventDefault();
|
||||
document.execCommand('insertText', false, bufferText);
|
||||
}
|
||||
}
|
||||
*/
|
||||
});
|
||||
|
||||
</script>
|
||||
$('.summernote-small').summernote({
|
||||
height: 150,
|
||||
tabsize: 2,
|
||||
followingToolbar: true,
|
||||
imageTitle: {
|
||||
specificAltField: true,
|
||||
},
|
||||
toolbar: [
|
||||
['style', ['style']],
|
||||
['font', ['bold', 'italic', 'underline', 'clear']],
|
||||
['color', ['color']],
|
||||
['para', ['ul', 'ol', 'paragraph']],
|
||||
['extensions', ['gallery']],
|
||||
['insert', ['link', 'picture', 'video', 'hr']],
|
||||
['view', ['fullscreen', 'codeview']],
|
||||
['help', ['help']]
|
||||
],
|
||||
popover: {
|
||||
image: [
|
||||
['imagesize', ['imageSize100', 'imageSize50', 'imageSize25']],
|
||||
['float', ['floatLeft', 'floatRight', 'floatNone']],
|
||||
['remove', ['removeMedia']],
|
||||
['custom', ['imageTitle']],
|
||||
],
|
||||
},
|
||||
callbacks: {
|
||||
onInit: function() {
|
||||
// $(this).data('image_dialog_images_html', '<div class="row"..');
|
||||
$(this).data('image_dialog_images_url', "/iq/content/assets/modal");
|
||||
$(this).data('image_dialog_title', "Medien");
|
||||
$(this).data('image_dialog_close_btn_text', "schließen");
|
||||
$(this).data('image_dialog_ok_btn_text', "Einfügen");
|
||||
}
|
||||
},
|
||||
|
||||
});
|
||||
|
||||
$('.summernote-exsmall').summernote({
|
||||
height: 100,
|
||||
tabsize: 2,
|
||||
followingToolbar: true,
|
||||
toolbar: [
|
||||
['font', ['bold', 'italic', 'underline', 'clear']],
|
||||
['para', ['ul', 'ol']],
|
||||
['insert', ['link', 'hr']],
|
||||
['view', ['fullscreen', 'codeview']],
|
||||
],
|
||||
});
|
||||
|
||||
$('.summernote-air').summernote({
|
||||
airMode: true,
|
||||
lang: 'de-DE',
|
||||
placeholder: 'Text ...',
|
||||
tabsize: 2,
|
||||
popover: {
|
||||
air: [
|
||||
['style', ['style']],
|
||||
['font', ['bold', 'italic', 'underline', 'clear']],
|
||||
['font', ['strikethrough']],
|
||||
['para', ['ul', 'ol', 'paragraph']],
|
||||
['insert', ['link']],
|
||||
['color', ['color']],
|
||||
['view', ['codeview']],
|
||||
]
|
||||
},
|
||||
cleaner: {
|
||||
action: 'paste', // both|button|paste 'button' only cleans via toolbar button, 'paste' only clean when pasting content, both does both options.
|
||||
newline: '<br>', // Summernote's default is to use '<p><br></p>'
|
||||
notStyle: 'position:absolute;top:0;left:0;right:0', // Position of Notification
|
||||
icon: '<i class="note-icon">[Your Button]</i>',
|
||||
keepHtml: false, // Remove all Html formats
|
||||
keepOnlyTags: ['<p>', '<br>', '<ul>', '<li>', '<b>', '<strong>', '<i>',
|
||||
'<a>'
|
||||
], // If keepHtml is true, remove all tags except these
|
||||
keepClasses: false, // Remove Classes
|
||||
badTags: ['style', 'script', 'applet', 'embed', 'noframes', 'noscript',
|
||||
'html'
|
||||
], // Remove full tags with contents
|
||||
badAttributes: ['style', 'start'], // Remove attributes from remaining tags
|
||||
limitChars: false, // 0/false|# 0/false disables option
|
||||
limitDisplay: false, // text|html|both
|
||||
limitStop: false // true/false
|
||||
}
|
||||
});
|
||||
//save in the codeview
|
||||
$('.note-codable').on('blur', function() {
|
||||
var codeviewHtml = $(this).val();
|
||||
var $summernoteTextarea = $(this).closest('.note-editor').siblings('textarea');
|
||||
$summernoteTextarea.val(codeviewHtml);
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
</html>
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@
|
|||
@endif
|
||||
@if (Auth::user()->isPermission('crm-bo'))
|
||||
<li
|
||||
class="sidenav-item{{ Request::is(['requests', 'bookings', 'booking/*', 'leads', 'lead/*', 'customers', 'customer/*', 'customer_mails', 'customer_mail/*']) ? ' open' : '' }}">
|
||||
class="sidenav-item{{ Request::is(['requests', 'bookings', 'booking/*', 'leads', 'lead/*', 'customers', 'customer/*', 'contacts', 'contact/*', 'customer_mails', 'customer_mail/*']) ? ' open' : '' }}">
|
||||
<a href="javascript:void(0)" class="sidenav-link sidenav-toggle">
|
||||
<i class="sidenav-icon ion ion-md-bed"></i>
|
||||
<div>Buchungen</div>
|
||||
|
|
@ -101,6 +101,20 @@
|
|||
<div>Kunden</div>
|
||||
</a>
|
||||
</li>
|
||||
<li
|
||||
class="sidenav-item{{ Request::is(['contacts', 'contact/*']) && !Request::is('contacts/duplicates') ? ' active' : '' }}">
|
||||
<a href="{{ route('contacts') }}" class="sidenav-link"><i
|
||||
class="sidenav-icon ion ion-ios-person-add"></i>
|
||||
<div>Kontakte</div>
|
||||
</a>
|
||||
</li>
|
||||
<li
|
||||
class="sidenav-item{{ Request::is('contacts/duplicates') ? ' active' : '' }}">
|
||||
<a href="{{ route('contacts_duplicates') }}" class="sidenav-link"><i
|
||||
class="sidenav-icon ion ion-ios-copy"></i>
|
||||
<div>Duplikate</div>
|
||||
</a>
|
||||
</li>
|
||||
@endif
|
||||
</ul>
|
||||
</li>
|
||||
|
|
|
|||
|
|
@ -1,8 +1,6 @@
|
|||
@extends('pdf.layout-template')
|
||||
|
||||
@section('content')
|
||||
|
||||
|
||||
@include('pdf.components.booking_header')
|
||||
|
||||
@include('pdf.components.booking_participant')
|
||||
|
|
@ -13,7 +11,5 @@
|
|||
|
||||
@include('pdf.components.booking_sterntours')
|
||||
|
||||
@include('pdf.components.booking_footer', ['set_contact_footer' => false])
|
||||
|
||||
|
||||
@include('pdf.components.booking_footer', ['set_contact_footer' => true])
|
||||
@endsection
|
||||
|
|
|
|||
|
|
@ -1,8 +1,6 @@
|
|||
@extends('pdf.layout-template')
|
||||
|
||||
@section('content')
|
||||
|
||||
|
||||
@include('pdf.components.booking_header')
|
||||
|
||||
@include('pdf.components.booking_participant')
|
||||
|
|
@ -15,7 +13,5 @@
|
|||
|
||||
@include('pdf.components.booking_sterntours')
|
||||
|
||||
@include('pdf.components.booking_footer', ['set_contact_footer' => false])
|
||||
|
||||
|
||||
@include('pdf.components.booking_footer', ['set_contact_footer' => true])
|
||||
@endsection
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@
|
|||
{{-- @endif --}}
|
||||
</td>
|
||||
<td align="left" style="color: #000; padding:0.5rem">
|
||||
Buchungsnummer: <strong>{{ $booking->lead_id }}</strong><br />
|
||||
Buchungsnummer: <strong>{{ $booking->inquiry_id }}</strong><br />
|
||||
Buchungsdatum: <strong>{{ _format_date($booking->booking_date) }}</strong><br /><br />
|
||||
Reisetermin: <strong>{{ _format_date($booking->start_date) }} -
|
||||
{{ _format_date($booking->end_date) }}</strong><br />
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@
|
|||
</tr>
|
||||
<tr>
|
||||
<td>Buchungsnummer:</td>
|
||||
<td><strong>{{ $booking->lead_id }}</strong></td>
|
||||
<td><strong>{{ $booking->inquiry_id }}</strong></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Buchungsdatum:</td>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue