initial commit
This commit is contained in:
BIN
think-backend.greaterchiangmai.com/resources/views/.DS_Store
vendored
Normal file
BIN
think-backend.greaterchiangmai.com/resources/views/.DS_Store
vendored
Normal file
Binary file not shown.
@@ -0,0 +1,604 @@
|
||||
@extends('layouts.backendTemplate')
|
||||
|
||||
@section('content')
|
||||
|
||||
<style>
|
||||
.block-wrapper {
|
||||
margin-top: 10px;
|
||||
border: 1px solid #ddd;
|
||||
padding: 10px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.invalid {
|
||||
border-color: red;
|
||||
}
|
||||
|
||||
/* Responsive Video Container */
|
||||
.video-wrapper {
|
||||
position: relative;
|
||||
padding-bottom: 56.25%;
|
||||
/* 16:9 aspect ratio */
|
||||
height: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.video-wrapper iframe {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border: 0;
|
||||
}
|
||||
</style>
|
||||
|
||||
<!--begin::Main-->
|
||||
<div class="app-main flex-column flex-row-fluid" id="kt_app_main">
|
||||
|
||||
<div class="d-flex flex-column flex-column-fluid">
|
||||
|
||||
|
||||
@include('uc.admin.breadcrumb', [
|
||||
'title' => 'WHERE ELSE : Add Article',
|
||||
'pageName' => 'Add',
|
||||
'pageParent' => 'Article Management',
|
||||
'pageParentLink' => url('where-else/article'),
|
||||
])
|
||||
|
||||
<div id="kt_app_content" class="app-content flex-column-fluid">
|
||||
<div id="kt_app_content_container" class="app-container container-xxl">
|
||||
|
||||
|
||||
|
||||
<form id="frmAdd" class="form d-flex flex-column flex-lg-row"
|
||||
action="{{ url('where-else/insert-article') }}" method="post" enctype="multipart/form-data">
|
||||
|
||||
<input type="hidden" name="_method" value="POST">
|
||||
<input type="hidden" name="_token" value="{{ csrf_token() }}">
|
||||
|
||||
|
||||
<div class="d-flex flex-column gap-7 gap-lg-10 w-100 w-lg-300px mb-7 me-lg-10">
|
||||
|
||||
<div class="card card-flush py-4">
|
||||
|
||||
|
||||
<div class="card-body text-center pt-0">
|
||||
|
||||
<style>
|
||||
.image-input-placeholder {
|
||||
background-image: url('{{ url('assets/media/svg/files/blank-image.svg') }}');
|
||||
}
|
||||
|
||||
[data-bs-theme="dark"] .image-input-placeholder {
|
||||
background-image: url('../media/svg/files/blank-image-dark.svg');
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="image-input image-input-empty image-input-outline image-input-placeholder mb-3"
|
||||
data-kt-image-input="true">
|
||||
|
||||
<div class="image-input-wrapper w-150px h-150px"></div>
|
||||
|
||||
<label
|
||||
class="btn btn-icon btn-circle btn-active-color-primary w-25px h-25px bg-body shadow"
|
||||
data-kt-image-input-action="change" data-bs-toggle="tooltip"
|
||||
title="Change avatar">
|
||||
|
||||
<i class="bi bi-pencil-fill fs-7"></i>
|
||||
|
||||
<input type="file" name="avatar" id="avatar"
|
||||
accept=".png, .jpg, .jpeg" />
|
||||
<input type="hidden" name="avatar_remove" />
|
||||
|
||||
</label>
|
||||
|
||||
<span
|
||||
class="btn btn-icon btn-circle btn-active-color-primary w-25px h-25px bg-body shadow"
|
||||
data-kt-image-input-action="cancel" data-bs-toggle="tooltip"
|
||||
title="Cancel avatar">
|
||||
<i class="bi bi-x fs-2"></i>
|
||||
</span>
|
||||
|
||||
<span
|
||||
class="btn btn-icon btn-circle btn-active-color-primary w-25px h-25px bg-body shadow"
|
||||
data-kt-image-input-action="remove" data-bs-toggle="tooltip"
|
||||
title="Remove avatar">
|
||||
<i class="bi bi-x fs-2"></i>
|
||||
</span>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="text-muted fs-7">Set the profile picture. Only *.png, *.jpg and *.jpeg
|
||||
image
|
||||
files are accepted</div>
|
||||
|
||||
</div>
|
||||
|
||||
{{-- Active --}}
|
||||
<div class="card-header" style="border: unset;">
|
||||
<div class="required card-title">
|
||||
<h2>Active</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body pt-0">
|
||||
|
||||
<label class="form-check form-switch form-check-custom form-check-solid">
|
||||
<input class="form-check-input" disabled readonly name="active" type="checkbox"
|
||||
value="1" checked />
|
||||
</label>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="d-flex flex-column flex-row-fluid gap-7 gap-lg-10">
|
||||
|
||||
<div class="card card-flush py-4">
|
||||
|
||||
|
||||
@if (Session::has('messageSuccess'))
|
||||
<div class="card-body">
|
||||
@include('uc/messageSuccess')
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@if (Session::has('messageFail'))
|
||||
<div class="card-body">
|
||||
@include('uc/messageFail')
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<div class="card-header">
|
||||
<div class="card-title">
|
||||
<h2>Overview</h2>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card-body pt-0">
|
||||
|
||||
<div class="mb-10 fv-row">
|
||||
<label class="required form-label">Sub Categories</label>
|
||||
<div class="d-flex align-items-center mt-3">
|
||||
@foreach ($subCategoriesView as $item)
|
||||
<label
|
||||
class="form-check form-check-custom form-check-inline form-check-solid me-5 {{ $errors->has('sub_categories') ? 'is-invalid' : '' }}">
|
||||
<input class="form-check-input" name="sub_categories[]"
|
||||
id="sub_categories" type="checkbox" value="{{ $item->id }}"
|
||||
{{ in_array($item->id, old('sub_categories', [])) ? 'checked' : '' }}>
|
||||
<span class="fw-semibold ps-2 fs-6">
|
||||
{{ $item->name . '(' . $item->name_en . ')' }}
|
||||
</span>
|
||||
</label>
|
||||
@endforeach
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="mb-10 fv-row">
|
||||
<label class="required form-label">Date</label>
|
||||
<div class="position-relative d-flex align-items-center">
|
||||
<span class="svg-icon svg-icon-2 position-absolute mx-4">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<path opacity="0.3"
|
||||
d="M21 22H3C2.4 22 2 21.6 2 21V5C2 4.4 2.4 4 3 4H21C21.6 4 22 4.4 22 5V21C22 21.6 21.6 22 21 22Z"
|
||||
fill="currentColor" />
|
||||
<path
|
||||
d="M6 6C5.4 6 5 5.6 5 5V3C5 2.4 5.4 2 6 2C6.6 2 7 2.4 7 3V5C7 5.6 6.6 6 6 6ZM11 5V3C11 2.4 10.6 2 10 2C9.4 2 9 2.4 9 3V5C9 5.6 9.4 6 10 6C10.6 6 11 5.6 11 5ZM15 5V3C15 2.4 14.6 2 14 2C13.4 2 13 2.4 13 3V5C13 5.6 13.4 6 14 6C14.6 6 15 5.6 15 5ZM19 5V3C19 2.4 18.6 2 18 2C17.4 2 17 2.4 17 3V5C17 5.6 17.4 6 18 6C18.6 6 19 5.6 19 5Z"
|
||||
fill="currentColor" />
|
||||
<path
|
||||
d="M8.8 13.1C9.2 13.1 9.5 13 9.7 12.8C9.9 12.6 10.1 12.3 10.1 11.9C10.1 11.6 10 11.3 9.8 11.1C9.6 10.9 9.3 10.8 9 10.8C8.8 10.8 8.59999 10.8 8.39999 10.9C8.19999 11 8.1 11.1 8 11.2C7.9 11.3 7.8 11.4 7.7 11.6C7.6 11.8 7.5 11.9 7.5 12.1C7.5 12.2 7.4 12.2 7.3 12.3C7.2 12.4 7.09999 12.4 6.89999 12.4C6.69999 12.4 6.6 12.3 6.5 12.2C6.4 12.1 6.3 11.9 6.3 11.7C6.3 11.5 6.4 11.3 6.5 11.1C6.6 10.9 6.8 10.7 7 10.5C7.2 10.3 7.49999 10.1 7.89999 10C8.29999 9.90003 8.60001 9.80003 9.10001 9.80003C9.50001 9.80003 9.80001 9.90003 10.1 10C10.4 10.1 10.7 10.3 10.9 10.4C11.1 10.5 11.3 10.8 11.4 11.1C11.5 11.4 11.6 11.6 11.6 11.9C11.6 12.3 11.5 12.6 11.3 12.9C11.1 13.2 10.9 13.5 10.6 13.7C10.9 13.9 11.2 14.1 11.4 14.3C11.6 14.5 11.8 14.7 11.9 15C12 15.3 12.1 15.5 12.1 15.8C12.1 16.2 12 16.5 11.9 16.8C11.8 17.1 11.5 17.4 11.3 17.7C11.1 18 10.7 18.2 10.3 18.3C9.9 18.4 9.5 18.5 9 18.5C8.5 18.5 8.1 18.4 7.7 18.2C7.3 18 7 17.8 6.8 17.6C6.6 17.4 6.4 17.1 6.3 16.8C6.2 16.5 6.10001 16.3 6.10001 16.1C6.10001 15.9 6.2 15.7 6.3 15.6C6.4 15.5 6.6 15.4 6.8 15.4C6.9 15.4 7.00001 15.4 7.10001 15.5C7.20001 15.6 7.3 15.6 7.3 15.7C7.5 16.2 7.7 16.6 8 16.9C8.3 17.2 8.6 17.3 9 17.3C9.2 17.3 9.5 17.2 9.7 17.1C9.9 17 10.1 16.8 10.3 16.6C10.5 16.4 10.5 16.1 10.5 15.8C10.5 15.3 10.4 15 10.1 14.7C9.80001 14.4 9.50001 14.3 9.10001 14.3C9.00001 14.3 8.9 14.3 8.7 14.3C8.5 14.3 8.39999 14.3 8.39999 14.3C8.19999 14.3 7.99999 14.2 7.89999 14.1C7.79999 14 7.7 13.8 7.7 13.7C7.7 13.5 7.79999 13.4 7.89999 13.2C7.99999 13 8.2 13 8.5 13H8.8V13.1ZM15.3 17.5V12.2C14.3 13 13.6 13.3 13.3 13.3C13.1 13.3 13 13.2 12.9 13.1C12.8 13 12.7 12.8 12.7 12.6C12.7 12.4 12.8 12.3 12.9 12.2C13 12.1 13.2 12 13.6 11.8C14.1 11.6 14.5 11.3 14.7 11.1C14.9 10.9 15.2 10.6 15.5 10.3C15.8 10 15.9 9.80003 15.9 9.70003C15.9 9.60003 16.1 9.60004 16.3 9.60004C16.5 9.60004 16.7 9.70003 16.8 9.80003C16.9 9.90003 17 10.2 17 10.5V17.2C17 18 16.7 18.4 16.2 18.4C16 18.4 15.8 18.3 15.6 18.2C15.4 18.1 15.3 17.8 15.3 17.5Z"
|
||||
fill="currentColor" />
|
||||
</svg>
|
||||
</span>
|
||||
<input class="form-control form-control-solid ps-12" placeholder="Date"
|
||||
name="due_date" id="due_date" value="{{ old('due_date') }}" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-10 fv-row">
|
||||
<label class="required form-label">Subject</label>
|
||||
<input type="text" name="name" id="subject" class="form-control mb-2 col-6"
|
||||
value="{{ old('name') }}" />
|
||||
</div>
|
||||
|
||||
|
||||
<div class="mb-10 fv-row">
|
||||
<label class="required form-label">Subject (EN)</label>
|
||||
<input type="text" name="name_en" id="subject_en"
|
||||
class="form-control mb-2 col-6" value="{{ old('name_en') }}" />
|
||||
</div>
|
||||
|
||||
<div class="mb-10 fv-row">
|
||||
<label class="required form-label">Description</label>
|
||||
<div class="form-control" id="description" name="description"></div>
|
||||
<input type="hidden" id="description_input" name="description" />
|
||||
</div>
|
||||
|
||||
|
||||
<div class="mb-10 fv-row">
|
||||
<label class="required form-label">Description (EN)</label>
|
||||
<div class="form-control" id="description_en" name="description_en"></div>
|
||||
<input type="hidden" id="description_input_en" name="description_en" />
|
||||
|
||||
</div>
|
||||
|
||||
<div hidden class="mb-10">
|
||||
<label class="form-label required">File Video</label>
|
||||
<input class="files-video" type="file" name="file_video[]" multiple
|
||||
accept=".MP4, .MOV">
|
||||
<div class="text-muted fs-7">Allowed Types .MP4, .MOV</div>
|
||||
</div>
|
||||
|
||||
<div hidden class="mb-10">
|
||||
<label class="form-label required">File Image</label>
|
||||
<input class="files-image" type="file" name="file_image[]" multiple
|
||||
accept=".jpg, .bmp, .jpeg, .png">
|
||||
<div class="text-muted fs-7">Allowed Types .jpg, .bmp, .jpeg, .png</div>
|
||||
</div>
|
||||
|
||||
<div hidden class="mb-10">
|
||||
<label class="form-label required">File Sound</label>
|
||||
<input class="files-sound" type="file" name="file_sound[]" multiple
|
||||
accept=".m4a, .mp4, .mp3, .wav">
|
||||
<div class="text-muted fs-7">Allowed Types .m4a, .mp4, .mp3, .wav</div>
|
||||
</div>
|
||||
|
||||
<div hidden class="mb-10">
|
||||
<label class="form-label required">File Documents</label>
|
||||
<input class="files-document" type="file" name="file_document[]" multiple
|
||||
accept=".pdf, .xls, .doc, .docx, .pptx, .csv, .txt">
|
||||
<div class="text-muted fs-7">Allowed Types .pdf, .xls, .doc, .docx, .pptx, .csv,
|
||||
.txt</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="d-flex justify-content-end">
|
||||
|
||||
<a href="{{ url('where-else/article') }}" id="kt_ecommerce_add_product_cancel"
|
||||
class="btn btn-light me-5">Cancel</a>
|
||||
|
||||
<button id="btn_submit" class="btn btn-primary">
|
||||
<span class="indicator-label">Save Changes</span>
|
||||
</button>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</form>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
@stop
|
||||
|
||||
|
||||
@section('script')
|
||||
|
||||
<!-- Include Editor.js core -->
|
||||
<script src="https://cdn.jsdelivr.net/npm/@editorjs/editorjs@latest"></script>
|
||||
|
||||
<!-- Include the plugins -->
|
||||
<script src="https://cdn.jsdelivr.net/npm/@editorjs/header"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/@editorjs/list"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/@editorjs/image"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/editorjs-inline-image"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/@editorjs/embed"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/editorjs-break-line"></script>
|
||||
|
||||
<script>
|
||||
// Custom video tool for embedding videos
|
||||
class VideoTool {
|
||||
constructor({
|
||||
data
|
||||
}) {
|
||||
this.data = data || {};
|
||||
}
|
||||
|
||||
// Render input for video URL
|
||||
render() {
|
||||
const wrapper = document.createElement("div");
|
||||
|
||||
const input = document.createElement("input");
|
||||
input.type = "text";
|
||||
input.placeholder = "Enter video URL";
|
||||
input.value = this.data.url || "";
|
||||
input.style.width = "100%";
|
||||
|
||||
const video = document.createElement("video");
|
||||
video.controls = true;
|
||||
video.style.width = "100%";
|
||||
video.style.marginTop = "10px";
|
||||
video.src = this.data.url || "";
|
||||
|
||||
input.addEventListener("input", (event) => {
|
||||
const value = event.target.value;
|
||||
this.data.url = value;
|
||||
video.src = value;
|
||||
});
|
||||
|
||||
wrapper.appendChild(input);
|
||||
wrapper.appendChild(video);
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
// Save the video URL
|
||||
save(blockContent) {
|
||||
const input = blockContent.querySelector("input");
|
||||
return {
|
||||
url: input.value,
|
||||
};
|
||||
}
|
||||
|
||||
// Editor.js toolbox definition
|
||||
static get toolbox() {
|
||||
return {
|
||||
title: "Video",
|
||||
icon: '<svg width="20" height="20" viewBox="0 0 24 24"><path d="M10 8.64L15.27 12 10 15.36V8.64M10 3.14L21 12 10 20.86V3.14M3 4h4v16H3V4z"></path></svg>',
|
||||
};
|
||||
}
|
||||
}
|
||||
class YoutubeEmbed {
|
||||
/**
|
||||
* Define the toolbox settings for the Editor.js toolbar.
|
||||
*/
|
||||
static get toolbox() {
|
||||
return {
|
||||
title: "YouTube",
|
||||
icon: '<svg width="18" height="18" viewBox="0 0 24 24"><path d="M19.615 3.184c-.403-1.516-1.589-2.693-3.09-3.091-2.719-.727-13.525-.727-16.244 0-1.514.398-2.687 1.57-3.09 3.091-.727 2.719-.727 13.525 0 16.244.403 1.514 1.576 2.693 3.09 3.09 2.719.727 13.525.727 16.244 0 1.516-.397 2.692-1.576 3.09-3.09.727-2.719.727-13.525 0-16.244zm-11.615 13.316v-8l8 4-8 4z"/></svg>',
|
||||
};
|
||||
}
|
||||
|
||||
constructor({
|
||||
data,
|
||||
config,
|
||||
api,
|
||||
readOnly
|
||||
}) {
|
||||
this.data = data || {};
|
||||
this.readOnly = readOnly;
|
||||
this.wrapper = null;
|
||||
this.url = this.data.url || '';
|
||||
this.isEdited = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the input field and YouTube preview.
|
||||
*/
|
||||
render() {
|
||||
this.wrapper = document.createElement('div');
|
||||
this.wrapper.classList.add('block-wrapper');
|
||||
|
||||
const input = document.createElement('input');
|
||||
input.value = this.url;
|
||||
input.placeholder = "Paste YouTube URL here...";
|
||||
input.style.width = '100%';
|
||||
|
||||
this.wrapper.appendChild(input);
|
||||
this._createIframe(this.url);
|
||||
|
||||
input.addEventListener('change', (event) => {
|
||||
this.isEdited = true;
|
||||
this.url = event.target.value;
|
||||
this._createIframe(this.url);
|
||||
});
|
||||
|
||||
return this.wrapper;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the iframe for the YouTube video.
|
||||
*/
|
||||
_createIframe(url) {
|
||||
const videoId = this._extractVideoID(url);
|
||||
if (!videoId) {
|
||||
if (this.isEdited) {
|
||||
this.wrapper.querySelector('input').classList.add('invalid');
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
this.wrapper.innerHTML = ''; // Clear the wrapper
|
||||
|
||||
const plyrContainer = document.createElement('div');
|
||||
plyrContainer.classList.add('video-wrapper');
|
||||
|
||||
const iframe = document.createElement('iframe');
|
||||
iframe.src = `https://www.youtube.com/embed/${videoId}`;
|
||||
iframe.allowFullscreen = true;
|
||||
|
||||
plyrContainer.appendChild(iframe);
|
||||
this.wrapper.appendChild(plyrContainer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract the YouTube video ID from the URL.
|
||||
*/
|
||||
_extractVideoID(url) {
|
||||
const regex = /(?:https?:\/\/)?(?:www\.)?(?:youtube\.com\/watch\?v=|youtu\.be\/)([^&?/]+)/;
|
||||
const match = url.match(regex);
|
||||
return match ? match[1] : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the saved data for this block.
|
||||
*/
|
||||
save(blockContent) {
|
||||
return {
|
||||
url: this.url,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify the core that this tool supports read-only mode.
|
||||
*/
|
||||
static get isReadOnlySupported() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
const csrfToken = document.querySelector('meta[name="csrf-token"]').getAttribute('content');
|
||||
const baseUrlUpload = "{{ url('where-else/article-upload-image') }}";
|
||||
const tools = {
|
||||
header: {
|
||||
class: Header,
|
||||
inlineToolbar: ['link', 'bold', 'italic'],
|
||||
config: {
|
||||
placeholder: 'Enter a header',
|
||||
levels: [2, 3, 4], // Set header levels
|
||||
defaultLevel: 3,
|
||||
},
|
||||
},
|
||||
breakLine: {
|
||||
class: BreakLine,
|
||||
inlineToolbar: true,
|
||||
shortcut: 'CMD+SHIFT+ENTER',
|
||||
},
|
||||
youtube: YoutubeEmbed,
|
||||
embed: {
|
||||
class: Embed,
|
||||
inlineToolbar: true,
|
||||
config: {
|
||||
services: {
|
||||
youtube: true,
|
||||
vimeo: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
video: {
|
||||
class: VideoTool,
|
||||
inlineToolbar: true,
|
||||
},
|
||||
image: {
|
||||
class: ImageTool,
|
||||
config: {
|
||||
endpoints: {
|
||||
byFile: baseUrlUpload,
|
||||
byUrl: baseUrlUpload,
|
||||
},
|
||||
field: 'image',
|
||||
types: 'image/*',
|
||||
inlineToolbar: true,
|
||||
additionalRequestHeaders: {
|
||||
'X-CSRF-TOKEN': csrfToken, // Include CSRF token here
|
||||
},
|
||||
},
|
||||
},
|
||||
inlineImage: {
|
||||
class: InlineImage,
|
||||
inlineToolbar: true,
|
||||
config: {
|
||||
embed: {
|
||||
display: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
const editorDescription = new EditorJS({
|
||||
holder: 'description',
|
||||
tools: tools
|
||||
});
|
||||
const editorDescriptionEn = new EditorJS({
|
||||
holder: 'description_en',
|
||||
tools: tools,
|
||||
});
|
||||
</script>
|
||||
|
||||
<script type="text/javascript">
|
||||
$(function() {
|
||||
$('#due_date').flatpickr({
|
||||
enableTime: false,
|
||||
dateFormat: 'd-m-Y',
|
||||
defaultDate: null, // Do not preselect any date
|
||||
onReady: function(selectedDates, dateStr, instance) {
|
||||
// Highlight today's date with a custom CSS class
|
||||
const today = instance.todayDateElem;
|
||||
today.classList.add('flatpickr-today-highlight'); // Add a custom class to today
|
||||
}
|
||||
});
|
||||
|
||||
$(document).on('click', '#btn_submit', function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
// avatar
|
||||
const avatar = $('#avatar').val();
|
||||
if (avatar == '') {
|
||||
alertFail('Notice', "Avatar is required");
|
||||
return;
|
||||
}
|
||||
|
||||
// categories
|
||||
const subCate = $('#sub_categories');
|
||||
const anySelected = Array.from(subCate).some(checkbox => checkbox.checked);
|
||||
if (!anySelected) {
|
||||
alertFail('Notice', "Sub Categories is required");
|
||||
return;
|
||||
}
|
||||
|
||||
// date
|
||||
const dueDate = $('#due_date').val();
|
||||
if (dueDate == '') {
|
||||
alertFail('Notice', "Date is required");
|
||||
return;
|
||||
}
|
||||
|
||||
// Subject
|
||||
const subject = $('#subject').val();
|
||||
if (subject == '') {
|
||||
alertFail('Notice', "Subject is required");
|
||||
return;
|
||||
}
|
||||
// Subject En
|
||||
const subjectEn = $('#subject_en').val();
|
||||
if (subjectEn == '') {
|
||||
alertFail('Notice', "Subject en is required");
|
||||
return;
|
||||
}
|
||||
|
||||
Promise.all([editorDescription.save(), editorDescriptionEn.save()])
|
||||
.then(([descriptionData, descriptionEnData]) => {
|
||||
|
||||
if (descriptionData?.blocks?.length <= 0) {
|
||||
alertFail('Notice', "Description is required");
|
||||
return;
|
||||
}
|
||||
if (descriptionEnData?.blocks?.length <= 0) {
|
||||
alertFail('Notice', "Description en is required");
|
||||
return;
|
||||
}
|
||||
|
||||
alertLoading("Loading...");
|
||||
|
||||
// Store the JSON output in the hidden input fields
|
||||
$('#description_input').val(JSON.stringify(descriptionData));
|
||||
$('#description_input_en').val(JSON.stringify(descriptionEnData));
|
||||
|
||||
// Submit the form after saving the data
|
||||
$('#frmAdd').submit();
|
||||
})
|
||||
.catch((error) => {
|
||||
hideLoading();
|
||||
console.error('Error saving editor content:', error);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
@endsection
|
||||
@@ -0,0 +1,594 @@
|
||||
@extends('layouts.backendTemplate')
|
||||
|
||||
@section('content')
|
||||
|
||||
<style>
|
||||
.video-responsive {
|
||||
position: relative;
|
||||
padding-bottom: 56.25%;
|
||||
/* Aspect ratio 16:9 */
|
||||
height: 0;
|
||||
overflow: hidden;
|
||||
max-width: 100%;
|
||||
background: #000;
|
||||
}
|
||||
|
||||
.video-responsive video {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.block-wrapper {
|
||||
margin-top: 10px;
|
||||
border: 1px solid #ddd;
|
||||
padding: 10px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.invalid {
|
||||
border-color: red;
|
||||
}
|
||||
|
||||
/* Responsive Video Container */
|
||||
.video-wrapper {
|
||||
position: relative;
|
||||
padding-bottom: 56.25%;
|
||||
/* 16:9 aspect ratio */
|
||||
height: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.video-wrapper iframe {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border: 0;
|
||||
}
|
||||
</style>
|
||||
|
||||
<!--begin::Main-->
|
||||
<div class="app-main flex-column flex-row-fluid" id="kt_app_main">
|
||||
|
||||
<div class="d-flex flex-column flex-column-fluid">
|
||||
|
||||
|
||||
@include('uc.admin.breadcrumb', [
|
||||
'title' => 'WHERE ELSE : Edit Article',
|
||||
'pageName' => 'Edit',
|
||||
'pageParent' => 'Article Management',
|
||||
'pageParentLink' => url('where-else/article'),
|
||||
])
|
||||
<div id="kt_app_content" class="app-content flex-column-fluid">
|
||||
<div id="kt_app_content_container" class="app-container container-xxl">
|
||||
|
||||
|
||||
<form id="frmUpdate" class="form d-flex flex-column flex-lg-row"
|
||||
action="{{ url('where-else/update-article') }}" method="post" enctype="multipart/form-data">
|
||||
|
||||
<input type="hidden" name="id" value="{{ $itemView->id }}">
|
||||
<input type="hidden" name="_method" value="POST">
|
||||
<input type="hidden" name="_token" value="{{ csrf_token() }}">
|
||||
|
||||
|
||||
{{-- Left --}}
|
||||
<div class="d-flex flex-column gap-7 gap-lg-10 w-100 w-lg-300px mb-7 me-lg-10">
|
||||
|
||||
<div class="card card-flush py-4">
|
||||
|
||||
<div class="card-body text-center pt-0">
|
||||
|
||||
<style>
|
||||
.image-input-placeholder {
|
||||
background-image: url('{{ url('assets/media/svg/files/blank-image.svg') }}');
|
||||
}
|
||||
|
||||
[data-bs-theme="dark"] .image-input-placeholder {
|
||||
background-image: url('../media/svg/files/blank-image-dark.svg');
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="image-input image-input-empty image-input-outline image-input-placeholder mb-3"
|
||||
data-kt-image-input="true">
|
||||
|
||||
|
||||
@if ($itemView->image_url && $itemView->image_name)
|
||||
<div class="image-input-wrapper w-150px h-150px"
|
||||
style="background-image: url('{{ $itemView->image_url . '/thumbnail/' . $itemView->image_name }}')">
|
||||
</div>
|
||||
@else
|
||||
<div class="image-input-wrapper w-150px h-150px"></div>
|
||||
@endif
|
||||
|
||||
<label
|
||||
class="btn btn-icon btn-circle btn-active-color-primary w-25px h-25px bg-body shadow"
|
||||
data-kt-image-input-action="change" data-bs-toggle="tooltip"
|
||||
title="Change avatar">
|
||||
|
||||
<i class="bi bi-pencil-fill fs-7"></i>
|
||||
|
||||
<input type="file" name="avatar" accept=".png, .jpg, .jpeg" />
|
||||
<input type="hidden" name="avatar_remove" />
|
||||
|
||||
</label>
|
||||
|
||||
<span
|
||||
class="btn btn-icon btn-circle btn-active-color-primary w-25px h-25px bg-body shadow"
|
||||
data-kt-image-input-action="cancel" data-bs-toggle="tooltip"
|
||||
title="Cancel avatar">
|
||||
<i class="bi bi-x fs-2"></i>
|
||||
</span>
|
||||
|
||||
<span
|
||||
class="btn btn-icon btn-circle btn-active-color-primary w-25px h-25px bg-body shadow"
|
||||
data-kt-image-input-action="remove" data-bs-toggle="tooltip"
|
||||
title="Remove avatar">
|
||||
<i class="bi bi-x fs-2"></i>
|
||||
</span>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="text-muted fs-7">Set the profile picture. Only *.png, *.jpg and *.jpeg
|
||||
image
|
||||
files are accepted</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="card-header" style="border: unset;">
|
||||
<!--begin::Card title-->
|
||||
<div class="required card-title">
|
||||
<h2>Active</h2>
|
||||
</div>
|
||||
<!--end::Card title-->
|
||||
</div>
|
||||
<div class="card-body pt-0">
|
||||
|
||||
<label class="form-check form-switch form-check-custom form-check-solid">
|
||||
<input class="form-check-input" name="active" type="checkbox" value="1"
|
||||
{{ $itemView->active == 1 ? 'checked' : '' }} />
|
||||
</label>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
{{-- Right --}}
|
||||
<div class="d-flex flex-column flex-row-fluid gap-7 gap-lg-10">
|
||||
|
||||
<div class="card card-flush py-4">
|
||||
|
||||
@if (Session::has('messageSuccess'))
|
||||
<div class="card-body">
|
||||
@include('uc/messageSuccess')
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@if (Session::has('messageFail'))
|
||||
<div class="card-body">
|
||||
@include('uc/messageFail')
|
||||
</div>
|
||||
@endif
|
||||
|
||||
|
||||
<div class="card-header">
|
||||
<div class="card-title">
|
||||
<h2>Overview</h2>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card-body pt-0">
|
||||
|
||||
<div class="mb-10 fv-row">
|
||||
<label class="required form-label">Sub Categories</label>
|
||||
<div class="d-flex align-items-center mt-3">
|
||||
@foreach ($subCategoriesView as $item)
|
||||
<label
|
||||
class="form-check form-check-custom form-check-inline form-check-solid me-5 is-invalid">
|
||||
<input class="form-check-input" name="sub_categories[]" type="checkbox"
|
||||
value="{{ $item->id }}"
|
||||
@if (in_array($item->id, explode(',', $itemView->sub_category_ids))) checked @endif>
|
||||
<span class="fw-semibold ps-2 fs-6">
|
||||
{{ $item->name . '(' . $item->name_en . ')' }}
|
||||
</span>
|
||||
</label>
|
||||
@endforeach
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="mb-10 fv-row">
|
||||
<div class="position-relative d-flex align-items-center">
|
||||
<span class="svg-icon svg-icon-2 position-absolute mx-4">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<path opacity="0.3"
|
||||
d="M21 22H3C2.4 22 2 21.6 2 21V5C2 4.4 2.4 4 3 4H21C21.6 4 22 4.4 22 5V21C22 21.6 21.6 22 21 22Z"
|
||||
fill="currentColor" />
|
||||
<path
|
||||
d="M6 6C5.4 6 5 5.6 5 5V3C5 2.4 5.4 2 6 2C6.6 2 7 2.4 7 3V5C7 5.6 6.6 6 6 6ZM11 5V3C11 2.4 10.6 2 10 2C9.4 2 9 2.4 9 3V5C9 5.6 9.4 6 10 6C10.6 6 11 5.6 11 5ZM15 5V3C15 2.4 14.6 2 14 2C13.4 2 13 2.4 13 3V5C13 5.6 13.4 6 14 6C14.6 6 15 5.6 15 5ZM19 5V3C19 2.4 18.6 2 18 2C17.4 2 17 2.4 17 3V5C17 5.6 17.4 6 18 6C18.6 6 19 5.6 19 5Z"
|
||||
fill="currentColor" />
|
||||
<path
|
||||
d="M8.8 13.1C9.2 13.1 9.5 13 9.7 12.8C9.9 12.6 10.1 12.3 10.1 11.9C10.1 11.6 10 11.3 9.8 11.1C9.6 10.9 9.3 10.8 9 10.8C8.8 10.8 8.59999 10.8 8.39999 10.9C8.19999 11 8.1 11.1 8 11.2C7.9 11.3 7.8 11.4 7.7 11.6C7.6 11.8 7.5 11.9 7.5 12.1C7.5 12.2 7.4 12.2 7.3 12.3C7.2 12.4 7.09999 12.4 6.89999 12.4C6.69999 12.4 6.6 12.3 6.5 12.2C6.4 12.1 6.3 11.9 6.3 11.7C6.3 11.5 6.4 11.3 6.5 11.1C6.6 10.9 6.8 10.7 7 10.5C7.2 10.3 7.49999 10.1 7.89999 10C8.29999 9.90003 8.60001 9.80003 9.10001 9.80003C9.50001 9.80003 9.80001 9.90003 10.1 10C10.4 10.1 10.7 10.3 10.9 10.4C11.1 10.5 11.3 10.8 11.4 11.1C11.5 11.4 11.6 11.6 11.6 11.9C11.6 12.3 11.5 12.6 11.3 12.9C11.1 13.2 10.9 13.5 10.6 13.7C10.9 13.9 11.2 14.1 11.4 14.3C11.6 14.5 11.8 14.7 11.9 15C12 15.3 12.1 15.5 12.1 15.8C12.1 16.2 12 16.5 11.9 16.8C11.8 17.1 11.5 17.4 11.3 17.7C11.1 18 10.7 18.2 10.3 18.3C9.9 18.4 9.5 18.5 9 18.5C8.5 18.5 8.1 18.4 7.7 18.2C7.3 18 7 17.8 6.8 17.6C6.6 17.4 6.4 17.1 6.3 16.8C6.2 16.5 6.10001 16.3 6.10001 16.1C6.10001 15.9 6.2 15.7 6.3 15.6C6.4 15.5 6.6 15.4 6.8 15.4C6.9 15.4 7.00001 15.4 7.10001 15.5C7.20001 15.6 7.3 15.6 7.3 15.7C7.5 16.2 7.7 16.6 8 16.9C8.3 17.2 8.6 17.3 9 17.3C9.2 17.3 9.5 17.2 9.7 17.1C9.9 17 10.1 16.8 10.3 16.6C10.5 16.4 10.5 16.1 10.5 15.8C10.5 15.3 10.4 15 10.1 14.7C9.80001 14.4 9.50001 14.3 9.10001 14.3C9.00001 14.3 8.9 14.3 8.7 14.3C8.5 14.3 8.39999 14.3 8.39999 14.3C8.19999 14.3 7.99999 14.2 7.89999 14.1C7.79999 14 7.7 13.8 7.7 13.7C7.7 13.5 7.79999 13.4 7.89999 13.2C7.99999 13 8.2 13 8.5 13H8.8V13.1ZM15.3 17.5V12.2C14.3 13 13.6 13.3 13.3 13.3C13.1 13.3 13 13.2 12.9 13.1C12.8 13 12.7 12.8 12.7 12.6C12.7 12.4 12.8 12.3 12.9 12.2C13 12.1 13.2 12 13.6 11.8C14.1 11.6 14.5 11.3 14.7 11.1C14.9 10.9 15.2 10.6 15.5 10.3C15.8 10 15.9 9.80003 15.9 9.70003C15.9 9.60003 16.1 9.60004 16.3 9.60004C16.5 9.60004 16.7 9.70003 16.8 9.80003C16.9 9.90003 17 10.2 17 10.5V17.2C17 18 16.7 18.4 16.2 18.4C16 18.4 15.8 18.3 15.6 18.2C15.4 18.1 15.3 17.8 15.3 17.5Z"
|
||||
fill="currentColor" />
|
||||
</svg>
|
||||
</span>
|
||||
<input class="form-control form-control-solid ps-12" type="text"
|
||||
id="due_date" name="due_date"
|
||||
value="{{ $itemView->due_date ? date('d-m-Y', strtotime($itemView->due_date)) : '' }}">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-10 fv-row">
|
||||
<label class="required form-label">Subject</label>
|
||||
<input type="text" name="name" class="form-control mb-2 col-6"
|
||||
value="{{ $itemView->name }}" />
|
||||
</div>
|
||||
|
||||
|
||||
<div class="mb-10 fv-row">
|
||||
<label class="required form-label">Subject (EN)</label>
|
||||
<input type="text" name="name_en" class="form-control mb-2 col-6"
|
||||
value="{{ $itemView->name_en }}" />
|
||||
</div>
|
||||
|
||||
<div class="mb-10 fv-row">
|
||||
<label class="required form-label">Description</label>
|
||||
<div class="form-control" id="description" name="description"></div>
|
||||
<input type="hidden" id="description_input" name="description" />
|
||||
</div>
|
||||
|
||||
|
||||
<div class="mb-10 fv-row">
|
||||
<label class="required form-label">Description (EN)</label>
|
||||
<div class="form-control" id="description_en" name="description_en"></div>
|
||||
<input type="hidden" id="description_input_en" name="description_en" />
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="d-flex justify-content-end">
|
||||
|
||||
<a href="{{ url('where-else/article') }}" id="kt_ecommerce_add_product_cancel"
|
||||
class="btn btn-light me-5">Cancel</a>
|
||||
|
||||
<button type="button" id="btn_submit" class="btn btn-primary">
|
||||
<span class="indicator-label">Save</span>
|
||||
</button>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</form>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
@stop
|
||||
|
||||
|
||||
|
||||
|
||||
@section('script')
|
||||
|
||||
<script type="text/javascript">
|
||||
$(function() {
|
||||
$('#due_date').flatpickr({
|
||||
enableTime: false,
|
||||
dateFormat: 'd-m-Y',
|
||||
defaultDate: null, // Do not preselect any date
|
||||
onReady: function(selectedDates, dateStr, instance) {
|
||||
// Highlight today's date with a custom CSS class
|
||||
const today = instance.todayDateElem;
|
||||
today.classList.add('flatpickr-today-highlight'); // Add a custom class to today
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
$(document).on("click", "#btn_submit", function(e) {
|
||||
e.preventDefault();
|
||||
alertLoading("Loading")
|
||||
const form = $('#frmUpdate');
|
||||
form.submit();
|
||||
})
|
||||
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
<!-- Include Editor.js core -->
|
||||
<script src="https://cdn.jsdelivr.net/npm/@editorjs/editorjs@latest"></script>
|
||||
|
||||
<!-- Include the plugins -->
|
||||
<script src="https://cdn.jsdelivr.net/npm/@editorjs/header"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/@editorjs/list"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/@editorjs/image"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/editorjs-inline-image"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/@editorjs/embed"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/editorjs-break-line"></script>
|
||||
|
||||
<script>
|
||||
// Custom video tool for embedding videos
|
||||
class VideoTool {
|
||||
constructor({
|
||||
data
|
||||
}) {
|
||||
this.data = data || {};
|
||||
}
|
||||
|
||||
// Render input for video URL
|
||||
render() {
|
||||
const wrapper = document.createElement("div");
|
||||
|
||||
const input = document.createElement("input");
|
||||
input.type = "text";
|
||||
input.placeholder = "Enter video URL";
|
||||
input.value = this.data.url || "";
|
||||
input.style.width = "100%";
|
||||
|
||||
const video = document.createElement("video");
|
||||
video.controls = true;
|
||||
video.style.width = "100%";
|
||||
video.style.marginTop = "10px";
|
||||
video.src = this.data.url || "";
|
||||
|
||||
input.addEventListener("input", (event) => {
|
||||
const value = event.target.value;
|
||||
this.data.url = value;
|
||||
video.src = value;
|
||||
});
|
||||
|
||||
wrapper.appendChild(input);
|
||||
wrapper.appendChild(video);
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
// Save the video URL
|
||||
save(blockContent) {
|
||||
const input = blockContent.querySelector("input");
|
||||
return {
|
||||
url: input.value,
|
||||
};
|
||||
}
|
||||
|
||||
// Editor.js toolbox definition
|
||||
static get toolbox() {
|
||||
return {
|
||||
title: "Video",
|
||||
icon: '<svg width="20" height="20" viewBox="0 0 24 24"><path d="M10 8.64L15.27 12 10 15.36V8.64M10 3.14L21 12 10 20.86V3.14M3 4h4v16H3V4z"></path></svg>',
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
class YoutubeEmbed {
|
||||
/**
|
||||
* Define the toolbox settings for the Editor.js toolbar.
|
||||
*/
|
||||
static get toolbox() {
|
||||
return {
|
||||
title: "YouTube",
|
||||
icon: '<svg width="18" height="18" viewBox="0 0 24 24"><path d="M19.615 3.184c-.403-1.516-1.589-2.693-3.09-3.091-2.719-.727-13.525-.727-16.244 0-1.514.398-2.687 1.57-3.09 3.091-.727 2.719-.727 13.525 0 16.244.403 1.514 1.576 2.693 3.09 3.09 2.719.727 13.525.727 16.244 0 1.516-.397 2.692-1.576 3.09-3.09.727-2.719.727-13.525 0-16.244zm-11.615 13.316v-8l8 4-8 4z"/></svg>',
|
||||
};
|
||||
}
|
||||
|
||||
constructor({
|
||||
data,
|
||||
config,
|
||||
api,
|
||||
readOnly
|
||||
}) {
|
||||
this.data = data || {};
|
||||
this.readOnly = readOnly;
|
||||
this.wrapper = null;
|
||||
this.url = this.data.url || '';
|
||||
this.isEdited = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the input field and YouTube preview.
|
||||
*/
|
||||
render() {
|
||||
this.wrapper = document.createElement('div');
|
||||
this.wrapper.classList.add('block-wrapper');
|
||||
|
||||
const input = document.createElement('input');
|
||||
input.value = this.url;
|
||||
input.placeholder = "Paste YouTube URL here...";
|
||||
input.style.width = '100%';
|
||||
|
||||
this.wrapper.appendChild(input);
|
||||
this._createIframe(this.url);
|
||||
|
||||
input.addEventListener('change', (event) => {
|
||||
this.isEdited = true;
|
||||
this.url = event.target.value;
|
||||
this._createIframe(this.url);
|
||||
});
|
||||
|
||||
return this.wrapper;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the iframe for the YouTube video.
|
||||
*/
|
||||
_createIframe(url) {
|
||||
const videoId = this._extractVideoID(url);
|
||||
if (!videoId) {
|
||||
if (this.isEdited) {
|
||||
this.wrapper.querySelector('input').classList.add('invalid');
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
this.wrapper.innerHTML = ''; // Clear the wrapper
|
||||
|
||||
const plyrContainer = document.createElement('div');
|
||||
plyrContainer.classList.add('video-wrapper');
|
||||
|
||||
const iframe = document.createElement('iframe');
|
||||
iframe.src = `https://www.youtube.com/embed/${videoId}`;
|
||||
iframe.allowFullscreen = true;
|
||||
|
||||
plyrContainer.appendChild(iframe);
|
||||
this.wrapper.appendChild(plyrContainer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract the YouTube video ID from the URL.
|
||||
*/
|
||||
_extractVideoID(url) {
|
||||
const regex = /(?:https?:\/\/)?(?:www\.)?(?:youtube\.com\/watch\?v=|youtu\.be\/)([^&?/]+)/;
|
||||
const match = url.match(regex);
|
||||
return match ? match[1] : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the saved data for this block.
|
||||
*/
|
||||
save(blockContent) {
|
||||
return {
|
||||
url: this.url,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify the core that this tool supports read-only mode.
|
||||
*/
|
||||
static get isReadOnlySupported() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
const csrfToken = document.querySelector('meta[name="csrf-token"]').getAttribute('content');
|
||||
const baseUrlUpload = "{{ url('where-else/article-upload-image') }}";
|
||||
const tools = {
|
||||
header: {
|
||||
class: Header,
|
||||
inlineToolbar: ['link', 'bold', 'italic'],
|
||||
config: {
|
||||
placeholder: 'Enter a header',
|
||||
levels: [2, 3, 4], // Set header levels
|
||||
defaultLevel: 3,
|
||||
},
|
||||
},
|
||||
breakLine: {
|
||||
class: BreakLine,
|
||||
inlineToolbar: true,
|
||||
shortcut: 'CMD+SHIFT+ENTER',
|
||||
},
|
||||
youtube: YoutubeEmbed,
|
||||
embed: {
|
||||
class: Embed,
|
||||
inlineToolbar: true,
|
||||
config: {
|
||||
services: {
|
||||
youtube: true,
|
||||
vimeo: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
video: {
|
||||
class: VideoTool,
|
||||
inlineToolbar: true,
|
||||
},
|
||||
image: {
|
||||
class: ImageTool,
|
||||
config: {
|
||||
endpoints: {
|
||||
byFile: baseUrlUpload,
|
||||
byUrl: baseUrlUpload,
|
||||
},
|
||||
field: 'image',
|
||||
types: 'image/*',
|
||||
inlineToolbar: true,
|
||||
additionalRequestHeaders: {
|
||||
'X-CSRF-TOKEN': csrfToken, // Include CSRF token here
|
||||
},
|
||||
},
|
||||
},
|
||||
inlineImage: {
|
||||
class: InlineImage,
|
||||
inlineToolbar: true,
|
||||
config: {
|
||||
embed: {
|
||||
display: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
const descriptionData = {!! json_encode($itemView->description) !!};
|
||||
const editorDescription = new EditorJS({
|
||||
holder: 'description',
|
||||
tools: tools,
|
||||
data: descriptionData != "" ? JSON.parse(descriptionData) : {},
|
||||
onChange: () => {
|
||||
saveData(editorDescription, 'description_input')
|
||||
}
|
||||
});
|
||||
|
||||
const descriptionDataEn = {!! json_encode($itemView->description_en) !!};
|
||||
const editorDescriptionEn = new EditorJS({
|
||||
holder: 'description_en',
|
||||
tools: tools,
|
||||
data: descriptionDataEn !== "" ? JSON.parse(descriptionDataEn) : {},
|
||||
onChange: () => {
|
||||
saveData(editorDescriptionEn, 'description_input_en');
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
|
||||
// Function to save data to hidden inputs
|
||||
function saveData(editor, inputId) {
|
||||
editor.save().then((outputData) => {
|
||||
document.getElementById(inputId).value = JSON.stringify(outputData);
|
||||
}).catch((error) => {
|
||||
console.error('Saving failed: ', error);
|
||||
});
|
||||
}
|
||||
|
||||
$(document).on('click', '#btn_submit', function(e) {
|
||||
e.preventDefault(); // Prevent default form submission
|
||||
|
||||
alertLoading("Loading..."); // Show loading alert (your custom function)
|
||||
|
||||
// Save both editor contents
|
||||
Promise.all([editorDescription.save(), editorDescriptionEn.save()])
|
||||
.then(([descriptionData, descriptionEnData]) => {
|
||||
// Store the JSON output in the hidden input fields
|
||||
$('#description_input').val(JSON.stringify(descriptionData));
|
||||
$('#description_input_en').val(JSON.stringify(descriptionEnData));
|
||||
|
||||
// Submit the form after saving the data
|
||||
$('#frmUpdate').submit();
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('Error saving editor content:', error);
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
|
||||
@endsection
|
||||
@@ -0,0 +1,411 @@
|
||||
@extends('layouts.backendTemplate')
|
||||
|
||||
@section('content')
|
||||
|
||||
<!--begin::Main-->
|
||||
<div class="app-main flex-column flex-row-fluid" id="kt_app_main">
|
||||
|
||||
<div class="d-flex flex-column flex-column-fluid">
|
||||
|
||||
|
||||
@include('uc.breadcrumbList', [
|
||||
'title' => 'WHERE ELSE : Article Management',
|
||||
'pageName' => 'Article Management',
|
||||
])
|
||||
|
||||
|
||||
<div id="kt_app_content" class="app-content flex-column-fluid">
|
||||
<!--begin::Content container-->
|
||||
<div id="kt_app_content_container" class="app-container container-xxl">
|
||||
<!--begin::Card-->
|
||||
<div class="card">
|
||||
|
||||
@if (Session::has('messageSuccess'))
|
||||
<div class="card-body">
|
||||
@include('uc/messageSuccess')
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@if (Session::has('messageFail'))
|
||||
<div class="card-body">
|
||||
@include('uc/messageFail')
|
||||
</div>
|
||||
@endif
|
||||
|
||||
|
||||
<!--begin::Card header-->
|
||||
<div class="card-header border-0 pt-6">
|
||||
<!--begin::Card title-->
|
||||
<div class="d-flex align-items-center position-relative my-1">
|
||||
</div>
|
||||
|
||||
|
||||
@if (Auth::user()->role != 2)
|
||||
<div class="card-toolbar">
|
||||
<div class="d-flex justify-content-end" data-kt-customer-table-toolbar="base">
|
||||
<a href="{{ url('where-else/add-article') }}" class="btn btn-primary">Add
|
||||
</a>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@endif
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<div class="card-header border-0 pt-5">
|
||||
|
||||
<div class="card-title">
|
||||
<div class="d-flex align-items-center position-relative my-1">
|
||||
<span class="svg-icon svg-icon-1 position-absolute ms-4">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<rect opacity="0.5" x="17.0365" y="15.1223" width="8.15546" height="2"
|
||||
rx="1" transform="rotate(45 17.0365 15.1223)" fill="currentColor">
|
||||
</rect>
|
||||
<path
|
||||
d="M11 19C6.55556 19 3 15.4444 3 11C3 6.55556 6.55556 3 11 3C15.4444 3 19 6.55556 19 11C19 15.4444 15.4444 19 11 19ZM11 5C7.53333 5 5 7.53333 5 11C5 14.4667 7.53333 17 11 17C14.4667 17 17 14.4667 17 11C17 7.53333 14.4667 5 11 5Z"
|
||||
fill="currentColor"></path>
|
||||
</svg>
|
||||
</span>
|
||||
|
||||
<input type="text" table-filter="search"
|
||||
class="form-control form-control-solid w-250px ps-15" placeholder="Search" />
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card-toolbar flex-row-fluid justify-content-end gap-5">
|
||||
|
||||
<div class="w-100 mw-150px">
|
||||
<div class="position-relative d-flex align-items-center">
|
||||
<span class="svg-icon svg-icon-2 position-absolute mx-4">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<path opacity="0.3"
|
||||
d="M21 22H3C2.4 22 2 21.6 2 21V5C2 4.4 2.4 4 3 4H21C21.6 4 22 4.4 22 5V21C22 21.6 21.6 22 21 22Z"
|
||||
fill="currentColor" />
|
||||
<path
|
||||
d="M6 6C5.4 6 5 5.6 5 5V3C5 2.4 5.4 2 6 2C6.6 2 7 2.4 7 3V5C7 5.6 6.6 6 6 6ZM11 5V3C11 2.4 10.6 2 10 2C9.4 2 9 2.4 9 3V5C9 5.6 9.4 6 10 6C10.6 6 11 5.6 11 5ZM15 5V3C15 2.4 14.6 2 14 2C13.4 2 13 2.4 13 3V5C13 5.6 13.4 6 14 6C14.6 6 15 5.6 15 5ZM19 5V3C19 2.4 18.6 2 18 2C17.4 2 17 2.4 17 3V5C17 5.6 17.4 6 18 6C18.6 6 19 5.6 19 5Z"
|
||||
fill="currentColor" />
|
||||
<path
|
||||
d="M8.8 13.1C9.2 13.1 9.5 13 9.7 12.8C9.9 12.6 10.1 12.3 10.1 11.9C10.1 11.6 10 11.3 9.8 11.1C9.6 10.9 9.3 10.8 9 10.8C8.8 10.8 8.59999 10.8 8.39999 10.9C8.19999 11 8.1 11.1 8 11.2C7.9 11.3 7.8 11.4 7.7 11.6C7.6 11.8 7.5 11.9 7.5 12.1C7.5 12.2 7.4 12.2 7.3 12.3C7.2 12.4 7.09999 12.4 6.89999 12.4C6.69999 12.4 6.6 12.3 6.5 12.2C6.4 12.1 6.3 11.9 6.3 11.7C6.3 11.5 6.4 11.3 6.5 11.1C6.6 10.9 6.8 10.7 7 10.5C7.2 10.3 7.49999 10.1 7.89999 10C8.29999 9.90003 8.60001 9.80003 9.10001 9.80003C9.50001 9.80003 9.80001 9.90003 10.1 10C10.4 10.1 10.7 10.3 10.9 10.4C11.1 10.5 11.3 10.8 11.4 11.1C11.5 11.4 11.6 11.6 11.6 11.9C11.6 12.3 11.5 12.6 11.3 12.9C11.1 13.2 10.9 13.5 10.6 13.7C10.9 13.9 11.2 14.1 11.4 14.3C11.6 14.5 11.8 14.7 11.9 15C12 15.3 12.1 15.5 12.1 15.8C12.1 16.2 12 16.5 11.9 16.8C11.8 17.1 11.5 17.4 11.3 17.7C11.1 18 10.7 18.2 10.3 18.3C9.9 18.4 9.5 18.5 9 18.5C8.5 18.5 8.1 18.4 7.7 18.2C7.3 18 7 17.8 6.8 17.6C6.6 17.4 6.4 17.1 6.3 16.8C6.2 16.5 6.10001 16.3 6.10001 16.1C6.10001 15.9 6.2 15.7 6.3 15.6C6.4 15.5 6.6 15.4 6.8 15.4C6.9 15.4 7.00001 15.4 7.10001 15.5C7.20001 15.6 7.3 15.6 7.3 15.7C7.5 16.2 7.7 16.6 8 16.9C8.3 17.2 8.6 17.3 9 17.3C9.2 17.3 9.5 17.2 9.7 17.1C9.9 17 10.1 16.8 10.3 16.6C10.5 16.4 10.5 16.1 10.5 15.8C10.5 15.3 10.4 15 10.1 14.7C9.80001 14.4 9.50001 14.3 9.10001 14.3C9.00001 14.3 8.9 14.3 8.7 14.3C8.5 14.3 8.39999 14.3 8.39999 14.3C8.19999 14.3 7.99999 14.2 7.89999 14.1C7.79999 14 7.7 13.8 7.7 13.7C7.7 13.5 7.79999 13.4 7.89999 13.2C7.99999 13 8.2 13 8.5 13H8.8V13.1ZM15.3 17.5V12.2C14.3 13 13.6 13.3 13.3 13.3C13.1 13.3 13 13.2 12.9 13.1C12.8 13 12.7 12.8 12.7 12.6C12.7 12.4 12.8 12.3 12.9 12.2C13 12.1 13.2 12 13.6 11.8C14.1 11.6 14.5 11.3 14.7 11.1C14.9 10.9 15.2 10.6 15.5 10.3C15.8 10 15.9 9.80003 15.9 9.70003C15.9 9.60003 16.1 9.60004 16.3 9.60004C16.5 9.60004 16.7 9.70003 16.8 9.80003C16.9 9.90003 17 10.2 17 10.5V17.2C17 18 16.7 18.4 16.2 18.4C16 18.4 15.8 18.3 15.6 18.2C15.4 18.1 15.3 17.8 15.3 17.5Z"
|
||||
fill="currentColor" />
|
||||
</svg>
|
||||
</span>
|
||||
<input class="form-control form-control-solid ps-12" placeholder="From"
|
||||
id="due_date_from" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="w-100 mw-150px">
|
||||
<div class="position-relative d-flex align-items-center">
|
||||
<span class="svg-icon svg-icon-2 position-absolute mx-4">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<path opacity="0.3"
|
||||
d="M21 22H3C2.4 22 2 21.6 2 21V5C2 4.4 2.4 4 3 4H21C21.6 4 22 4.4 22 5V21C22 21.6 21.6 22 21 22Z"
|
||||
fill="currentColor" />
|
||||
<path
|
||||
d="M6 6C5.4 6 5 5.6 5 5V3C5 2.4 5.4 2 6 2C6.6 2 7 2.4 7 3V5C7 5.6 6.6 6 6 6ZM11 5V3C11 2.4 10.6 2 10 2C9.4 2 9 2.4 9 3V5C9 5.6 9.4 6 10 6C10.6 6 11 5.6 11 5ZM15 5V3C15 2.4 14.6 2 14 2C13.4 2 13 2.4 13 3V5C13 5.6 13.4 6 14 6C14.6 6 15 5.6 15 5ZM19 5V3C19 2.4 18.6 2 18 2C17.4 2 17 2.4 17 3V5C17 5.6 17.4 6 18 6C18.6 6 19 5.6 19 5Z"
|
||||
fill="currentColor" />
|
||||
<path
|
||||
d="M8.8 13.1C9.2 13.1 9.5 13 9.7 12.8C9.9 12.6 10.1 12.3 10.1 11.9C10.1 11.6 10 11.3 9.8 11.1C9.6 10.9 9.3 10.8 9 10.8C8.8 10.8 8.59999 10.8 8.39999 10.9C8.19999 11 8.1 11.1 8 11.2C7.9 11.3 7.8 11.4 7.7 11.6C7.6 11.8 7.5 11.9 7.5 12.1C7.5 12.2 7.4 12.2 7.3 12.3C7.2 12.4 7.09999 12.4 6.89999 12.4C6.69999 12.4 6.6 12.3 6.5 12.2C6.4 12.1 6.3 11.9 6.3 11.7C6.3 11.5 6.4 11.3 6.5 11.1C6.6 10.9 6.8 10.7 7 10.5C7.2 10.3 7.49999 10.1 7.89999 10C8.29999 9.90003 8.60001 9.80003 9.10001 9.80003C9.50001 9.80003 9.80001 9.90003 10.1 10C10.4 10.1 10.7 10.3 10.9 10.4C11.1 10.5 11.3 10.8 11.4 11.1C11.5 11.4 11.6 11.6 11.6 11.9C11.6 12.3 11.5 12.6 11.3 12.9C11.1 13.2 10.9 13.5 10.6 13.7C10.9 13.9 11.2 14.1 11.4 14.3C11.6 14.5 11.8 14.7 11.9 15C12 15.3 12.1 15.5 12.1 15.8C12.1 16.2 12 16.5 11.9 16.8C11.8 17.1 11.5 17.4 11.3 17.7C11.1 18 10.7 18.2 10.3 18.3C9.9 18.4 9.5 18.5 9 18.5C8.5 18.5 8.1 18.4 7.7 18.2C7.3 18 7 17.8 6.8 17.6C6.6 17.4 6.4 17.1 6.3 16.8C6.2 16.5 6.10001 16.3 6.10001 16.1C6.10001 15.9 6.2 15.7 6.3 15.6C6.4 15.5 6.6 15.4 6.8 15.4C6.9 15.4 7.00001 15.4 7.10001 15.5C7.20001 15.6 7.3 15.6 7.3 15.7C7.5 16.2 7.7 16.6 8 16.9C8.3 17.2 8.6 17.3 9 17.3C9.2 17.3 9.5 17.2 9.7 17.1C9.9 17 10.1 16.8 10.3 16.6C10.5 16.4 10.5 16.1 10.5 15.8C10.5 15.3 10.4 15 10.1 14.7C9.80001 14.4 9.50001 14.3 9.10001 14.3C9.00001 14.3 8.9 14.3 8.7 14.3C8.5 14.3 8.39999 14.3 8.39999 14.3C8.19999 14.3 7.99999 14.2 7.89999 14.1C7.79999 14 7.7 13.8 7.7 13.7C7.7 13.5 7.79999 13.4 7.89999 13.2C7.99999 13 8.2 13 8.5 13H8.8V13.1ZM15.3 17.5V12.2C14.3 13 13.6 13.3 13.3 13.3C13.1 13.3 13 13.2 12.9 13.1C12.8 13 12.7 12.8 12.7 12.6C12.7 12.4 12.8 12.3 12.9 12.2C13 12.1 13.2 12 13.6 11.8C14.1 11.6 14.5 11.3 14.7 11.1C14.9 10.9 15.2 10.6 15.5 10.3C15.8 10 15.9 9.80003 15.9 9.70003C15.9 9.60003 16.1 9.60004 16.3 9.60004C16.5 9.60004 16.7 9.70003 16.8 9.80003C16.9 9.90003 17 10.2 17 10.5V17.2C17 18 16.7 18.4 16.2 18.4C16 18.4 15.8 18.3 15.6 18.2C15.4 18.1 15.3 17.8 15.3 17.5Z"
|
||||
fill="currentColor" />
|
||||
</svg>
|
||||
</span>
|
||||
<input class="form-control form-control-solid ps-12" placeholder="To"
|
||||
id="due_date_to" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button type="button" id="btn-submit" class="btn btn-primary">
|
||||
Search
|
||||
</button>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card-body py-4">
|
||||
<!--begin::Table-->
|
||||
<table class="table align-middle table-row-dashed fs-6 gy-5" id="data-table-category">
|
||||
<!--begin::Table head-->
|
||||
<thead>
|
||||
<!--begin::Table row-->
|
||||
<tr class="text-start text-muted fw-bold fs-7 text-uppercase gs-0">
|
||||
<th class="min-w-125px">Pic</th>
|
||||
<th class="min-w-125px">Date</th>
|
||||
<th class="min-w-125px">Subject</th>
|
||||
<th class="min-w-125px">Subject (EN)</th>
|
||||
<th class="min-w-125px">Created</th>
|
||||
<th class="min-w-125px">Active</th>
|
||||
<th class="text-end min-w-100px">Manage</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody class="text-gray-600 fw-semibold">
|
||||
|
||||
@foreach ($itemView as $obj)
|
||||
<tr>
|
||||
<td class="d-flex align-items-center">
|
||||
<div class="symbol symbol-100px symbol-2by3 me-4">
|
||||
@if ($obj->image_url && $obj->image_name)
|
||||
<a class="show-image-preview d-block overlay"
|
||||
href="{{ url($obj->image_url . '/original/' . $obj->image_name) }}">
|
||||
<div class="symbol-label"
|
||||
style="background-image: url('{{ url($obj->image_url . '/thumbnail/' . $obj->image_name) }}')">
|
||||
</div>
|
||||
</a>
|
||||
@else
|
||||
<div class="symbol-label"
|
||||
style="background-image: url('{{ url('assets/media/avatars/blank.png') }}')">
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
{{ Carbon\Carbon::parse($obj->due_date)->format('d, M Y') }}
|
||||
</td>
|
||||
|
||||
<td>
|
||||
<a href="#" class="text-gray-800 text-hover-primary mb-1">
|
||||
{{ $obj->name }}
|
||||
</a>
|
||||
</td>
|
||||
|
||||
<td>
|
||||
<a href="#" class="text-gray-800 text-hover-primary mb-1">
|
||||
{{ $obj->name_en }}
|
||||
</a>
|
||||
</td>
|
||||
|
||||
<td>
|
||||
{{ Carbon\Carbon::parse($obj->created_at)->format('d, M Y') }}
|
||||
</td>
|
||||
|
||||
|
||||
<td>
|
||||
@if ($obj->active == 1)
|
||||
<span class="badge py-3 px-4 fs-7 badge-light-success">Active</span>
|
||||
@else
|
||||
<span class="badge py-3 px-4 fs-7 badge-light-danger">Inactive</span>
|
||||
@endif
|
||||
</td>
|
||||
|
||||
|
||||
<td class="min-w-100px text-end">
|
||||
|
||||
{{-- View --}}
|
||||
{{-- <a href="{{ url('view-sub-category/' . $obj->id) }}"
|
||||
class="btn btn-icon btn-bg-light btn-active-color-primary btn-sm me-1">
|
||||
<span class="svg-icon svg-icon-2">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24"
|
||||
fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M17.5 11H6.5C4 11 2 9 2 6.5C2 4 4 2 6.5 2H17.5C20 2 22 4 22 6.5C22 9 20 11 17.5 11ZM15 6.5C15 7.9 16.1 9 17.5 9C18.9 9 20 7.9 20 6.5C20 5.1 18.9 4 17.5 4C16.1 4 15 5.1 15 6.5Z"
|
||||
fill="currentColor"></path>
|
||||
<path opacity="0.3"
|
||||
d="M17.5 22H6.5C4 22 2 20 2 17.5C2 15 4 13 6.5 13H17.5C20 13 22 15 22 17.5C22 20 20 22 17.5 22ZM4 17.5C4 18.9 5.1 20 6.5 20C7.9 20 9 18.9 9 17.5C9 16.1 7.9 15 6.5 15C5.1 15 4 16.1 4 17.5Z"
|
||||
fill="currentColor"></path>
|
||||
</svg>
|
||||
</span>
|
||||
</a> --}}
|
||||
|
||||
{{-- Edit --}}
|
||||
<a href="{{ url('where-else/edit-article/' . $obj->id) }}"
|
||||
class="btn btn-icon btn-bg-light btn-active-color-primary btn-sm me-1">
|
||||
<span class="svg-icon svg-icon-3">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24"
|
||||
fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path opacity="0.3"
|
||||
d="M21.4 8.35303L19.241 10.511L13.485 4.755L15.643 2.59595C16.0248 2.21423 16.5426 1.99988 17.0825 1.99988C17.6224 1.99988 18.1402 2.21423 18.522 2.59595L21.4 5.474C21.7817 5.85581 21.9962 6.37355 21.9962 6.91345C21.9962 7.45335 21.7817 7.97122 21.4 8.35303ZM3.68699 21.932L9.88699 19.865L4.13099 14.109L2.06399 20.309C1.98815 20.5354 1.97703 20.7787 2.03189 21.0111C2.08674 21.2436 2.2054 21.4561 2.37449 21.6248C2.54359 21.7934 2.75641 21.9115 2.989 21.9658C3.22158 22.0201 3.4647 22.0084 3.69099 21.932H3.68699Z"
|
||||
fill="currentColor" />
|
||||
<path
|
||||
d="M5.574 21.3L3.692 21.928C3.46591 22.0032 3.22334 22.0141 2.99144 21.9594C2.75954 21.9046 2.54744 21.7864 2.3789 21.6179C2.21036 21.4495 2.09202 21.2375 2.03711 21.0056C1.9822 20.7737 1.99289 20.5312 2.06799 20.3051L2.696 18.422L5.574 21.3ZM4.13499 14.105L9.891 19.861L19.245 10.507L13.489 4.75098L4.13499 14.105Z"
|
||||
fill="currentColor" />
|
||||
</svg>
|
||||
</span>
|
||||
</a>
|
||||
|
||||
{{-- Delete --}}
|
||||
@if ($obj->active == 1 && Auth::user()->role != 2)
|
||||
<a href="#" data-id="{{ $obj->id }}"
|
||||
class="btn btn-icon btn-bg-light btn-active-color-primary btn-sm delete-item">
|
||||
<span class="svg-icon svg-icon-3">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24"
|
||||
fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M5 9C5 8.44772 5.44772 8 6 8H18C18.5523 8 19 8.44772 19 9V18C19 19.6569 17.6569 21 16 21H8C6.34315 21 5 19.6569 5 18V9Z"
|
||||
fill="currentColor" />
|
||||
<path opacity="0.5"
|
||||
d="M5 5C5 4.44772 5.44772 4 6 4H18C18.5523 4 19 4.44772 19 5V5C19 5.55228 18.5523 6 18 6H6C5.44772 6 5 5.55228 5 5V5Z"
|
||||
fill="currentColor" />
|
||||
<path opacity="0.5"
|
||||
d="M9 4C9 3.44772 9.44772 3 10 3H14C14.5523 3 15 3.44772 15 4V4H9V4Z"
|
||||
fill="currentColor" />
|
||||
</svg>
|
||||
</span>
|
||||
</a>
|
||||
@endif
|
||||
</td>
|
||||
|
||||
|
||||
</tr>
|
||||
@endforeach
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@stop
|
||||
|
||||
|
||||
@section('script')
|
||||
|
||||
<script type="text/javascript">
|
||||
const baseUrl = "{{ url('where-else/article') }}";
|
||||
var datatable;
|
||||
datatable = $("#data-table-category").DataTable({
|
||||
"info": false,
|
||||
"order": [],
|
||||
"pageLength": 25,
|
||||
lengthMenu: [
|
||||
[10, 25, 50, 100, 500, 1000],
|
||||
[10, 25, 50, 100, 500, 1000]
|
||||
]
|
||||
});
|
||||
|
||||
// Filter by search
|
||||
const filterSearch = document.querySelector('[table-filter="search"]');
|
||||
filterSearch.addEventListener('keyup', function(e) {
|
||||
datatable.search(e.target.value).draw();
|
||||
});
|
||||
|
||||
// filter by status
|
||||
const filterStatus = document.querySelector('[table-filter="status"]');
|
||||
$(filterStatus).on('change', e => {
|
||||
let value = e.target.value;
|
||||
if (value === 'all') {
|
||||
value = '';
|
||||
}
|
||||
datatable.column(4).search(value).draw();
|
||||
});
|
||||
|
||||
|
||||
// Remove
|
||||
$(document).on('click', '.delete-item', function() {
|
||||
swal.fire({
|
||||
allowOutsideClick: false,
|
||||
text: "Are you sure you would like to Delete?",
|
||||
icon: "warning",
|
||||
buttonsStyling: false,
|
||||
showDenyButton: true,
|
||||
confirmButtonText: "Yes",
|
||||
denyButtonText: 'No',
|
||||
customClass: {
|
||||
confirmButton: "btn btn-primary",
|
||||
denyButton: "btn btn-light-danger"
|
||||
}
|
||||
}).then((result) => {
|
||||
if (result.isConfirmed) {
|
||||
|
||||
alertLoading("Loading")
|
||||
|
||||
// set up ajax
|
||||
initAjaxSetupToken();
|
||||
|
||||
const ajaxProp = {
|
||||
url: "{{ url('where-else/delete-article') }}",
|
||||
type: 'POST',
|
||||
data: {
|
||||
item_id: $(this).data('id')
|
||||
},
|
||||
};
|
||||
|
||||
$.ajax(ajaxProp).done(function(res) {
|
||||
if (res.status) {
|
||||
const url = "{{ url('where-else/article') }}";
|
||||
alertSuccessWithUrl('Notice', "Delete success", url);
|
||||
hideLoading();
|
||||
} else {
|
||||
alertFail('Notice', res.message ?? "Unsuccessfully");
|
||||
hideLoading();
|
||||
}
|
||||
}).fail(function(xhr, status, error) {
|
||||
logAjaxError(xhr, status, error);
|
||||
alertFail('Notice', error.message ?? "Unsuccessfully");
|
||||
hideLoading();
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
var today = new Date();
|
||||
var dateFormat = "d-m-Y";
|
||||
|
||||
var dueDateFrom = $("#due_date_from");
|
||||
var dueDateTo = $("#due_date_to");
|
||||
|
||||
const dateFrom = "{{ $fromDateView }}";
|
||||
const dateTo = "{{ $toDateView }}";
|
||||
|
||||
dueDateFrom.flatpickr({
|
||||
showClearButton: true,
|
||||
enableTime: false,
|
||||
dateFormat: dateFormat,
|
||||
maxDate: today,
|
||||
defaultDate: dateFrom,
|
||||
|
||||
});
|
||||
|
||||
dueDateTo.flatpickr({
|
||||
showClearButton: true,
|
||||
enableTime: false,
|
||||
dateFormat: dateFormat,
|
||||
maxDate: today,
|
||||
defaultDate: dateTo,
|
||||
|
||||
});
|
||||
|
||||
const clearDatePicker = () => {
|
||||
dueDateFrom.flatpickr().clear();
|
||||
dueDateTo.flatpickr().clear();
|
||||
|
||||
// Set the date format again after clearing
|
||||
dueDateFrom.flatpickr({
|
||||
dateFormat: dateFormat
|
||||
});
|
||||
dueDateTo.flatpickr({
|
||||
dateFormat: dateFormat
|
||||
});
|
||||
}
|
||||
|
||||
$('#btn-submit').on('click', (e) => {
|
||||
e.preventDefault(); // Prevent the default behavior of the anchor element
|
||||
|
||||
// from
|
||||
const fromDateSelected = $("#due_date_from").val();
|
||||
|
||||
// to
|
||||
const toDateSelected = $("#due_date_to").val();
|
||||
|
||||
if (fromDateSelected && toDateSelected) {
|
||||
var newUrl =
|
||||
`${baseUrl}/${fromDateSelected}/${toDateSelected}`;
|
||||
window.location.href = newUrl;
|
||||
} else {
|
||||
var newUrl = `${baseUrl}/all/all/`;
|
||||
window.location.href = newUrl;
|
||||
}
|
||||
|
||||
})
|
||||
</script>
|
||||
|
||||
@endsection
|
||||
@@ -0,0 +1,620 @@
|
||||
@extends('layouts.backendTemplate')
|
||||
|
||||
@section('content')
|
||||
|
||||
<style>
|
||||
.youtube-preview {
|
||||
margin-top: 10px;
|
||||
width: 100%;
|
||||
max-width: 560px;
|
||||
height: 315px;
|
||||
}
|
||||
|
||||
.block-wrapper {
|
||||
margin-top: 10px;
|
||||
border: 1px solid #ddd;
|
||||
padding: 10px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.invalid {
|
||||
border-color: red;
|
||||
}
|
||||
|
||||
/* Responsive Video Container */
|
||||
.video-wrapper {
|
||||
position: relative;
|
||||
padding-bottom: 56.25%;
|
||||
/* 16:9 aspect ratio */
|
||||
height: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.video-wrapper iframe {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border: 0;
|
||||
}
|
||||
</style>
|
||||
|
||||
<!--begin::Main-->
|
||||
<div class="app-main flex-column flex-row-fluid" id="kt_app_main">
|
||||
|
||||
<div class="d-flex flex-column flex-column-fluid">
|
||||
|
||||
|
||||
@include('uc.admin.breadcrumb', [
|
||||
'title' => 'CHIANG MAI AND NOWHERE ELSE : Add Article',
|
||||
'pageName' => 'Add',
|
||||
'pageParent' => 'Article Management',
|
||||
'pageParentLink' => url('no-where-else/article'),
|
||||
])
|
||||
|
||||
<div id="kt_app_content" class="app-content flex-column-fluid">
|
||||
<div id="kt_app_content_container" class="app-container container-xxl">
|
||||
|
||||
|
||||
|
||||
<form id="frmAdd" class="form d-flex flex-column flex-lg-row"
|
||||
action="{{ url('no-where-else/insert-article') }}" method="post" enctype="multipart/form-data">
|
||||
|
||||
<input type="hidden" name="_method" value="POST">
|
||||
<input type="hidden" name="_token" value="{{ csrf_token() }}">
|
||||
|
||||
|
||||
<div class="d-flex flex-column gap-7 gap-lg-10 w-100 w-lg-300px mb-7 me-lg-10">
|
||||
|
||||
<div class="card card-flush py-4">
|
||||
|
||||
|
||||
<div class="card-body text-center pt-0">
|
||||
|
||||
<style>
|
||||
.image-input-placeholder {
|
||||
background-image: url('{{ url('assets/media/svg/files/blank-image.svg') }}');
|
||||
}
|
||||
|
||||
[data-bs-theme="dark"] .image-input-placeholder {
|
||||
background-image: url('../media/svg/files/blank-image-dark.svg');
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="image-input image-input-empty image-input-outline image-input-placeholder mb-3"
|
||||
data-kt-image-input="true">
|
||||
|
||||
<div class="image-input-wrapper w-150px h-150px"></div>
|
||||
|
||||
<label
|
||||
class="btn btn-icon btn-circle btn-active-color-primary w-25px h-25px bg-body shadow"
|
||||
data-kt-image-input-action="change" data-bs-toggle="tooltip"
|
||||
title="Change avatar">
|
||||
|
||||
<i class="bi bi-pencil-fill fs-7"></i>
|
||||
|
||||
<input type="file" name="avatar" id="avatar"
|
||||
accept=".png, .jpg, .jpeg" />
|
||||
<input type="hidden" name="avatar_remove" />
|
||||
|
||||
</label>
|
||||
|
||||
<span
|
||||
class="btn btn-icon btn-circle btn-active-color-primary w-25px h-25px bg-body shadow"
|
||||
data-kt-image-input-action="cancel" data-bs-toggle="tooltip"
|
||||
title="Cancel avatar">
|
||||
<i class="bi bi-x fs-2"></i>
|
||||
</span>
|
||||
|
||||
<span
|
||||
class="btn btn-icon btn-circle btn-active-color-primary w-25px h-25px bg-body shadow"
|
||||
data-kt-image-input-action="remove" data-bs-toggle="tooltip"
|
||||
title="Remove avatar">
|
||||
<i class="bi bi-x fs-2"></i>
|
||||
</span>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="text-muted fs-7">Set the profile picture. Only *.png, *.jpg and *.jpeg
|
||||
image
|
||||
files are accepted</div>
|
||||
|
||||
</div>
|
||||
|
||||
{{-- Active --}}
|
||||
<div class="card-header" style="border: unset;">
|
||||
<div class="required card-title">
|
||||
<h2>Active</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body pt-0">
|
||||
|
||||
<label class="form-check form-switch form-check-custom form-check-solid">
|
||||
<input class="form-check-input" disabled readonly name="active" type="checkbox"
|
||||
value="1" checked />
|
||||
</label>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="d-flex flex-column flex-row-fluid gap-7 gap-lg-10">
|
||||
|
||||
<div class="card card-flush py-4">
|
||||
|
||||
|
||||
@if (Session::has('messageSuccess'))
|
||||
<div class="card-body">
|
||||
@include('uc/messageSuccess')
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@if (Session::has('messageFail'))
|
||||
<div class="card-body">
|
||||
@include('uc/messageFail')
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<div class="card-header">
|
||||
<div class="card-title">
|
||||
<h2>Overview</h2>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card-body pt-0">
|
||||
|
||||
<div class="mb-10 fv-row">
|
||||
<label class="required form-label">Sub Categories</label>
|
||||
<div class="d-flex align-items-center mt-3">
|
||||
@foreach ($subCategoriesView as $item)
|
||||
<label
|
||||
class="form-check form-check-custom form-check-inline form-check-solid me-5 {{ $errors->has('sub_categories') ? 'is-invalid' : '' }}">
|
||||
<input class="form-check-input" name="sub_categories[]"
|
||||
id="sub_categories" type="checkbox" value="{{ $item->id }}"
|
||||
{{ in_array($item->id, old('sub_categories', [])) ? 'checked' : '' }}>
|
||||
<span class="fw-semibold ps-2 fs-6">
|
||||
{{ $item->name . '(' . $item->name_en . ')' }}
|
||||
</span>
|
||||
</label>
|
||||
@endforeach
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="mb-10 fv-row">
|
||||
<label class="required form-label">Date</label>
|
||||
<div class="position-relative d-flex align-items-center">
|
||||
<span class="svg-icon svg-icon-2 position-absolute mx-4">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<path opacity="0.3"
|
||||
d="M21 22H3C2.4 22 2 21.6 2 21V5C2 4.4 2.4 4 3 4H21C21.6 4 22 4.4 22 5V21C22 21.6 21.6 22 21 22Z"
|
||||
fill="currentColor" />
|
||||
<path
|
||||
d="M6 6C5.4 6 5 5.6 5 5V3C5 2.4 5.4 2 6 2C6.6 2 7 2.4 7 3V5C7 5.6 6.6 6 6 6ZM11 5V3C11 2.4 10.6 2 10 2C9.4 2 9 2.4 9 3V5C9 5.6 9.4 6 10 6C10.6 6 11 5.6 11 5ZM15 5V3C15 2.4 14.6 2 14 2C13.4 2 13 2.4 13 3V5C13 5.6 13.4 6 14 6C14.6 6 15 5.6 15 5ZM19 5V3C19 2.4 18.6 2 18 2C17.4 2 17 2.4 17 3V5C17 5.6 17.4 6 18 6C18.6 6 19 5.6 19 5Z"
|
||||
fill="currentColor" />
|
||||
<path
|
||||
d="M8.8 13.1C9.2 13.1 9.5 13 9.7 12.8C9.9 12.6 10.1 12.3 10.1 11.9C10.1 11.6 10 11.3 9.8 11.1C9.6 10.9 9.3 10.8 9 10.8C8.8 10.8 8.59999 10.8 8.39999 10.9C8.19999 11 8.1 11.1 8 11.2C7.9 11.3 7.8 11.4 7.7 11.6C7.6 11.8 7.5 11.9 7.5 12.1C7.5 12.2 7.4 12.2 7.3 12.3C7.2 12.4 7.09999 12.4 6.89999 12.4C6.69999 12.4 6.6 12.3 6.5 12.2C6.4 12.1 6.3 11.9 6.3 11.7C6.3 11.5 6.4 11.3 6.5 11.1C6.6 10.9 6.8 10.7 7 10.5C7.2 10.3 7.49999 10.1 7.89999 10C8.29999 9.90003 8.60001 9.80003 9.10001 9.80003C9.50001 9.80003 9.80001 9.90003 10.1 10C10.4 10.1 10.7 10.3 10.9 10.4C11.1 10.5 11.3 10.8 11.4 11.1C11.5 11.4 11.6 11.6 11.6 11.9C11.6 12.3 11.5 12.6 11.3 12.9C11.1 13.2 10.9 13.5 10.6 13.7C10.9 13.9 11.2 14.1 11.4 14.3C11.6 14.5 11.8 14.7 11.9 15C12 15.3 12.1 15.5 12.1 15.8C12.1 16.2 12 16.5 11.9 16.8C11.8 17.1 11.5 17.4 11.3 17.7C11.1 18 10.7 18.2 10.3 18.3C9.9 18.4 9.5 18.5 9 18.5C8.5 18.5 8.1 18.4 7.7 18.2C7.3 18 7 17.8 6.8 17.6C6.6 17.4 6.4 17.1 6.3 16.8C6.2 16.5 6.10001 16.3 6.10001 16.1C6.10001 15.9 6.2 15.7 6.3 15.6C6.4 15.5 6.6 15.4 6.8 15.4C6.9 15.4 7.00001 15.4 7.10001 15.5C7.20001 15.6 7.3 15.6 7.3 15.7C7.5 16.2 7.7 16.6 8 16.9C8.3 17.2 8.6 17.3 9 17.3C9.2 17.3 9.5 17.2 9.7 17.1C9.9 17 10.1 16.8 10.3 16.6C10.5 16.4 10.5 16.1 10.5 15.8C10.5 15.3 10.4 15 10.1 14.7C9.80001 14.4 9.50001 14.3 9.10001 14.3C9.00001 14.3 8.9 14.3 8.7 14.3C8.5 14.3 8.39999 14.3 8.39999 14.3C8.19999 14.3 7.99999 14.2 7.89999 14.1C7.79999 14 7.7 13.8 7.7 13.7C7.7 13.5 7.79999 13.4 7.89999 13.2C7.99999 13 8.2 13 8.5 13H8.8V13.1ZM15.3 17.5V12.2C14.3 13 13.6 13.3 13.3 13.3C13.1 13.3 13 13.2 12.9 13.1C12.8 13 12.7 12.8 12.7 12.6C12.7 12.4 12.8 12.3 12.9 12.2C13 12.1 13.2 12 13.6 11.8C14.1 11.6 14.5 11.3 14.7 11.1C14.9 10.9 15.2 10.6 15.5 10.3C15.8 10 15.9 9.80003 15.9 9.70003C15.9 9.60003 16.1 9.60004 16.3 9.60004C16.5 9.60004 16.7 9.70003 16.8 9.80003C16.9 9.90003 17 10.2 17 10.5V17.2C17 18 16.7 18.4 16.2 18.4C16 18.4 15.8 18.3 15.6 18.2C15.4 18.1 15.3 17.8 15.3 17.5Z"
|
||||
fill="currentColor" />
|
||||
</svg>
|
||||
</span>
|
||||
<input class="form-control form-control-solid ps-12" placeholder="Date"
|
||||
name="due_date" id="due_date" value="{{ old('due_date') }}" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-10 fv-row">
|
||||
<label class="required form-label">Subject</label>
|
||||
<input type="text" name="name" id="subject" class="form-control mb-2 col-6"
|
||||
value="{{ old('name') }}" />
|
||||
</div>
|
||||
|
||||
|
||||
<div class="mb-10 fv-row">
|
||||
<label class="required form-label">Subject (EN)</label>
|
||||
<input type="text" id="subject_en" name="name_en"
|
||||
class="form-control mb-2 col-6" value="{{ old('name_en') }}" />
|
||||
</div>
|
||||
|
||||
<div class="mb-10 fv-row">
|
||||
<label class="required form-label">Description</label>
|
||||
<div class="form-control" id="description" name="description"></div>
|
||||
<input type="hidden" id="description_input" name="description" />
|
||||
</div>
|
||||
|
||||
|
||||
<div class="mb-10 fv-row">
|
||||
<label class="required form-label">Description (EN)</label>
|
||||
<div class="form-control" id="description_en" name="description_en"></div>
|
||||
<input type="hidden" id="description_input_en" name="description_en" />
|
||||
|
||||
</div>
|
||||
|
||||
<div hidden class="mb-10">
|
||||
<label class="form-label required">File Video</label>
|
||||
<input class="files-video" type="file" name="file_video[]" multiple
|
||||
accept=".MP4, .MOV">
|
||||
<div class="text-muted fs-7">Allowed Types .MP4, .MOV</div>
|
||||
</div>
|
||||
|
||||
<div hidden class="mb-10">
|
||||
<label class="form-label required">File Image</label>
|
||||
<input class="files-image" type="file" name="file_image[]" multiple
|
||||
accept=".jpg, .bmp, .jpeg, .png">
|
||||
<div class="text-muted fs-7">Allowed Types .jpg, .bmp, .jpeg, .png</div>
|
||||
</div>
|
||||
|
||||
<div hidden class="mb-10">
|
||||
<label class="form-label required">File Sound</label>
|
||||
<input class="files-sound" type="file" name="file_sound[]" multiple
|
||||
accept=".m4a, .mp4, .mp3, .wav">
|
||||
<div class="text-muted fs-7">Allowed Types .m4a, .mp4, .mp3, .wav</div>
|
||||
</div>
|
||||
|
||||
<div hidden class="mb-10">
|
||||
<label class="form-label required">File Documents</label>
|
||||
<input class="files-document" type="file" name="file_document[]" multiple
|
||||
accept=".pdf, .xls, .doc, .docx, .pptx, .csv, .txt">
|
||||
<div class="text-muted fs-7">Allowed Types .pdf, .xls, .doc, .docx, .pptx, .csv,
|
||||
.txt</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="d-flex justify-content-end">
|
||||
|
||||
<a href="{{ url('no-where-else/article') }}" id="kt_ecommerce_add_product_cancel"
|
||||
class="btn btn-light me-5">Cancel</a>
|
||||
|
||||
<button id="btn_submit" class="btn btn-primary">
|
||||
<span class="indicator-label">Save Changes</span>
|
||||
</button>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</form>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
@stop
|
||||
|
||||
|
||||
@section('script')
|
||||
|
||||
<!-- Include Editor.js core -->
|
||||
<script src="https://cdn.jsdelivr.net/npm/@editorjs/editorjs@latest"></script>
|
||||
|
||||
<!-- Include the plugins -->
|
||||
<script src="https://cdn.jsdelivr.net/npm/@editorjs/header"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/@editorjs/list"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/@editorjs/image"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/editorjs-inline-image"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/@editorjs/embed"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/editorjs-break-line"></script>
|
||||
|
||||
|
||||
|
||||
<script>
|
||||
// Custom video tool for embedding videos
|
||||
class VideoTool {
|
||||
constructor({
|
||||
data
|
||||
}) {
|
||||
this.data = data || {};
|
||||
}
|
||||
|
||||
// Render input for video URL
|
||||
render() {
|
||||
const wrapper = document.createElement("div");
|
||||
|
||||
const input = document.createElement("input");
|
||||
input.type = "text";
|
||||
input.placeholder = "Enter video URL";
|
||||
input.value = this.data.url || "";
|
||||
input.style.width = "100%";
|
||||
|
||||
const video = document.createElement("video");
|
||||
video.controls = true;
|
||||
video.style.width = "100%";
|
||||
video.style.marginTop = "10px";
|
||||
video.src = this.data.url || "";
|
||||
|
||||
input.addEventListener("input", (event) => {
|
||||
const value = event.target.value;
|
||||
this.data.url = value;
|
||||
video.src = value;
|
||||
});
|
||||
|
||||
wrapper.appendChild(input);
|
||||
wrapper.appendChild(video);
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
// Save the video URL
|
||||
save(blockContent) {
|
||||
const input = blockContent.querySelector("input");
|
||||
return {
|
||||
url: input.value,
|
||||
};
|
||||
}
|
||||
|
||||
// Editor.js toolbox definition
|
||||
static get toolbox() {
|
||||
return {
|
||||
title: "Video",
|
||||
icon: '<svg width="20" height="20" viewBox="0 0 24 24"><path d="M10 8.64L15.27 12 10 15.36V8.64M10 3.14L21 12 10 20.86V3.14M3 4h4v16H3V4z"></path></svg>',
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class YoutubeEmbed {
|
||||
/**
|
||||
* Define the toolbox settings for the Editor.js toolbar.
|
||||
*/
|
||||
static get toolbox() {
|
||||
return {
|
||||
title: "YouTube",
|
||||
icon: '<svg width="18" height="18" viewBox="0 0 24 24"><path d="M19.615 3.184c-.403-1.516-1.589-2.693-3.09-3.091-2.719-.727-13.525-.727-16.244 0-1.514.398-2.687 1.57-3.09 3.091-.727 2.719-.727 13.525 0 16.244.403 1.514 1.576 2.693 3.09 3.09 2.719.727 13.525.727 16.244 0 1.516-.397 2.692-1.576 3.09-3.09.727-2.719.727-13.525 0-16.244zm-11.615 13.316v-8l8 4-8 4z"/></svg>',
|
||||
};
|
||||
}
|
||||
|
||||
constructor({
|
||||
data,
|
||||
config,
|
||||
api,
|
||||
readOnly
|
||||
}) {
|
||||
this.data = data || {};
|
||||
this.readOnly = readOnly;
|
||||
this.wrapper = null;
|
||||
this.url = this.data.url || '';
|
||||
this.isEdited = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the input field and YouTube preview.
|
||||
*/
|
||||
render() {
|
||||
this.wrapper = document.createElement('div');
|
||||
this.wrapper.classList.add('block-wrapper');
|
||||
|
||||
const input = document.createElement('input');
|
||||
input.value = this.url;
|
||||
input.placeholder = "Paste YouTube URL here...";
|
||||
input.style.width = '100%';
|
||||
|
||||
this.wrapper.appendChild(input);
|
||||
this._createIframe(this.url);
|
||||
|
||||
input.addEventListener('change', (event) => {
|
||||
this.isEdited = true;
|
||||
this.url = event.target.value;
|
||||
this._createIframe(this.url);
|
||||
});
|
||||
|
||||
return this.wrapper;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the iframe for the YouTube video.
|
||||
*/
|
||||
_createIframe(url) {
|
||||
const videoId = this._extractVideoID(url);
|
||||
if (!videoId) {
|
||||
if (this.isEdited) {
|
||||
this.wrapper.querySelector('input').classList.add('invalid');
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
this.wrapper.innerHTML = ''; // Clear the wrapper
|
||||
|
||||
const plyrContainer = document.createElement('div');
|
||||
plyrContainer.classList.add('video-wrapper');
|
||||
|
||||
const iframe = document.createElement('iframe');
|
||||
iframe.src = `https://www.youtube.com/embed/${videoId}`;
|
||||
iframe.allowFullscreen = true;
|
||||
|
||||
plyrContainer.appendChild(iframe);
|
||||
this.wrapper.appendChild(plyrContainer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract the YouTube video ID from the URL.
|
||||
*/
|
||||
_extractVideoID(url) {
|
||||
const regex = /(?:https?:\/\/)?(?:www\.)?(?:youtube\.com\/watch\?v=|youtu\.be\/)([^&?/]+)/;
|
||||
const match = url.match(regex);
|
||||
return match ? match[1] : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the saved data for this block.
|
||||
*/
|
||||
save(blockContent) {
|
||||
return {
|
||||
url: this.url,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify the core that this tool supports read-only mode.
|
||||
*/
|
||||
static get isReadOnlySupported() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
const csrfToken = document.querySelector('meta[name="csrf-token"]').getAttribute('content');
|
||||
const baseUrlUpload = "{{ url('no-where-else/article-upload-image') }}";
|
||||
|
||||
const tools = {
|
||||
header: {
|
||||
class: Header,
|
||||
inlineToolbar: ['link', 'bold', 'italic'],
|
||||
config: {
|
||||
placeholder: 'Enter a header',
|
||||
levels: [2, 3, 4], // Set header levels
|
||||
defaultLevel: 3,
|
||||
},
|
||||
},
|
||||
breakLine: {
|
||||
class: BreakLine,
|
||||
inlineToolbar: true,
|
||||
shortcut: 'CMD+SHIFT+ENTER',
|
||||
},
|
||||
youtube: YoutubeEmbed,
|
||||
embed: {
|
||||
class: Embed,
|
||||
inlineToolbar: true,
|
||||
config: {
|
||||
services: {
|
||||
youtube: true,
|
||||
vimeo: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
video: {
|
||||
class: VideoTool,
|
||||
inlineToolbar: true,
|
||||
},
|
||||
image: {
|
||||
class: ImageTool,
|
||||
config: {
|
||||
endpoints: {
|
||||
byFile: baseUrlUpload,
|
||||
byUrl: baseUrlUpload,
|
||||
},
|
||||
field: 'image',
|
||||
types: 'image/*',
|
||||
inlineToolbar: true,
|
||||
additionalRequestHeaders: {
|
||||
'X-CSRF-TOKEN': csrfToken, // Include CSRF token here
|
||||
},
|
||||
},
|
||||
},
|
||||
inlineImage: {
|
||||
class: InlineImage,
|
||||
inlineToolbar: true,
|
||||
config: {
|
||||
embed: {
|
||||
display: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
const editorDescription = new EditorJS({
|
||||
holder: 'description',
|
||||
tools: tools
|
||||
});
|
||||
const editorDescriptionEn = new EditorJS({
|
||||
holder: 'description_en',
|
||||
tools: tools,
|
||||
});
|
||||
</script>
|
||||
|
||||
<script type="text/javascript">
|
||||
$(function() {
|
||||
$('#due_date').flatpickr({
|
||||
enableTime: false,
|
||||
dateFormat: 'd-m-Y',
|
||||
defaultDate: null, // Do not preselect any date
|
||||
onReady: function(selectedDates, dateStr, instance) {
|
||||
// Highlight today's date with a custom CSS class
|
||||
const today = instance.todayDateElem;
|
||||
today.classList.add('flatpickr-today-highlight'); // Add a custom class to today
|
||||
}
|
||||
});
|
||||
|
||||
$(document).on('click', '#btn_submit', function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
// avatar
|
||||
const avatar = $('#avatar').val();
|
||||
if (avatar == '') {
|
||||
alertFail('Notice', "Avatar is required");
|
||||
return;
|
||||
}
|
||||
|
||||
// categories
|
||||
const subCate = $('#sub_categories');
|
||||
const anySelected = Array.from(subCate).some(checkbox => checkbox.checked);
|
||||
if (!anySelected) {
|
||||
alertFail('Notice', "Sub Categories is required");
|
||||
return;
|
||||
}
|
||||
|
||||
// date
|
||||
const dueDate = $('#due_date').val();
|
||||
if (dueDate == '') {
|
||||
alertFail('Notice', "Date is required");
|
||||
return;
|
||||
}
|
||||
|
||||
// Subject
|
||||
const subject = $('#subject').val();
|
||||
if (subject == '') {
|
||||
alertFail('Notice', "Subject is required");
|
||||
return;
|
||||
}
|
||||
// Subject En
|
||||
const subjectEn = $('#subject_en').val();
|
||||
if (subjectEn == '') {
|
||||
alertFail('Notice', "Subject en is required");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Save both editor contents
|
||||
Promise.all([editorDescription.save(), editorDescriptionEn.save()])
|
||||
.then(([descriptionData, descriptionEnData]) => {
|
||||
|
||||
if (descriptionData?.blocks?.length <= 0) {
|
||||
alertFail('Notice', "Description is required");
|
||||
return;
|
||||
}
|
||||
if (descriptionEnData?.blocks?.length <= 0) {
|
||||
alertFail('Notice', "Description en is required");
|
||||
return;
|
||||
}
|
||||
|
||||
alertLoading("Loading...");
|
||||
|
||||
// Store the JSON output in the hidden input fields
|
||||
$('#description_input').val(JSON.stringify(descriptionData));
|
||||
$('#description_input_en').val(JSON.stringify(descriptionEnData));
|
||||
|
||||
// Submit the form after saving the data
|
||||
$('#frmAdd').submit();
|
||||
})
|
||||
.catch((error) => {
|
||||
hideLoading();
|
||||
console.error('Error saving editor content:', error);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
@endsection
|
||||
@@ -0,0 +1,604 @@
|
||||
@extends('layouts.backendTemplate')
|
||||
|
||||
@section('content')
|
||||
|
||||
<style>
|
||||
.video-responsive {
|
||||
position: relative;
|
||||
padding-bottom: 56.25%;
|
||||
/* Aspect ratio 16:9 */
|
||||
height: 0;
|
||||
overflow: hidden;
|
||||
max-width: 100%;
|
||||
background: #000;
|
||||
}
|
||||
|
||||
.video-responsive video {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.block-wrapper {
|
||||
margin-top: 10px;
|
||||
border: 1px solid #ddd;
|
||||
padding: 10px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.invalid {
|
||||
border-color: red;
|
||||
}
|
||||
|
||||
/* Responsive Video Container */
|
||||
.video-wrapper {
|
||||
position: relative;
|
||||
padding-bottom: 56.25%;
|
||||
/* 16:9 aspect ratio */
|
||||
height: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* Responsive Video Container */
|
||||
.video-wrapper {
|
||||
position: relative;
|
||||
padding-bottom: 56.25%;
|
||||
/* 16:9 aspect ratio */
|
||||
height: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.video-wrapper iframe {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border: 0;
|
||||
}
|
||||
</style>
|
||||
|
||||
<!--begin::Main-->
|
||||
<div class="app-main flex-column flex-row-fluid" id="kt_app_main">
|
||||
|
||||
<div class="d-flex flex-column flex-column-fluid">
|
||||
|
||||
|
||||
@include('uc.admin.breadcrumb', [
|
||||
'title' => 'CHIANG MAI AND NOWHERE ELSE : Edit Article',
|
||||
'pageName' => 'Edit',
|
||||
'pageParent' => 'Article Management',
|
||||
'pageParentLink' => url('no-where-else/article'),
|
||||
])
|
||||
<div id="kt_app_content" class="app-content flex-column-fluid">
|
||||
<div id="kt_app_content_container" class="app-container container-xxl">
|
||||
|
||||
|
||||
<form id="frmUpdate" class="form d-flex flex-column flex-lg-row"
|
||||
action="{{ url('no-where-else/update-article') }}" method="post" enctype="multipart/form-data">
|
||||
|
||||
<input type="hidden" name="id" value="{{ $itemView->id }}">
|
||||
<input type="hidden" name="_method" value="POST">
|
||||
<input type="hidden" name="_token" value="{{ csrf_token() }}">
|
||||
|
||||
|
||||
{{-- Left --}}
|
||||
<div class="d-flex flex-column gap-7 gap-lg-10 w-100 w-lg-300px mb-7 me-lg-10">
|
||||
|
||||
<div class="card card-flush py-4">
|
||||
|
||||
<div class="card-body text-center pt-0">
|
||||
|
||||
<style>
|
||||
.image-input-placeholder {
|
||||
background-image: url('{{ url('assets/media/svg/files/blank-image.svg') }}');
|
||||
}
|
||||
|
||||
[data-bs-theme="dark"] .image-input-placeholder {
|
||||
background-image: url('../media/svg/files/blank-image-dark.svg');
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="image-input image-input-empty image-input-outline image-input-placeholder mb-3"
|
||||
data-kt-image-input="true">
|
||||
|
||||
|
||||
@if ($itemView->image_url && $itemView->image_name)
|
||||
<div class="image-input-wrapper w-150px h-150px"
|
||||
style="background-image: url('{{ $itemView->image_url . '/thumbnail/' . $itemView->image_name }}')">
|
||||
</div>
|
||||
@else
|
||||
<div class="image-input-wrapper w-150px h-150px"></div>
|
||||
@endif
|
||||
|
||||
<label
|
||||
class="btn btn-icon btn-circle btn-active-color-primary w-25px h-25px bg-body shadow"
|
||||
data-kt-image-input-action="change" data-bs-toggle="tooltip"
|
||||
title="Change avatar">
|
||||
|
||||
<i class="bi bi-pencil-fill fs-7"></i>
|
||||
|
||||
<input type="file" name="avatar" accept=".png, .jpg, .jpeg" />
|
||||
<input type="hidden" name="avatar_remove" />
|
||||
|
||||
</label>
|
||||
|
||||
<span
|
||||
class="btn btn-icon btn-circle btn-active-color-primary w-25px h-25px bg-body shadow"
|
||||
data-kt-image-input-action="cancel" data-bs-toggle="tooltip"
|
||||
title="Cancel avatar">
|
||||
<i class="bi bi-x fs-2"></i>
|
||||
</span>
|
||||
|
||||
<span
|
||||
class="btn btn-icon btn-circle btn-active-color-primary w-25px h-25px bg-body shadow"
|
||||
data-kt-image-input-action="remove" data-bs-toggle="tooltip"
|
||||
title="Remove avatar">
|
||||
<i class="bi bi-x fs-2"></i>
|
||||
</span>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="text-muted fs-7">Set the profile picture. Only *.png, *.jpg and *.jpeg
|
||||
image
|
||||
files are accepted</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="card-header" style="border: unset;">
|
||||
<!--begin::Card title-->
|
||||
<div class="required card-title">
|
||||
<h2>Active</h2>
|
||||
</div>
|
||||
<!--end::Card title-->
|
||||
</div>
|
||||
<div class="card-body pt-0">
|
||||
|
||||
<label class="form-check form-switch form-check-custom form-check-solid">
|
||||
<input class="form-check-input" name="active" type="checkbox" value="1"
|
||||
{{ $itemView->active == 1 ? 'checked' : '' }} />
|
||||
</label>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
{{-- Right --}}
|
||||
<div class="d-flex flex-column flex-row-fluid gap-7 gap-lg-10">
|
||||
|
||||
<div class="card card-flush py-4">
|
||||
|
||||
@if (Session::has('messageSuccess'))
|
||||
<div class="card-body">
|
||||
@include('uc/messageSuccess')
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@if (Session::has('messageFail'))
|
||||
<div class="card-body">
|
||||
@include('uc/messageFail')
|
||||
</div>
|
||||
@endif
|
||||
|
||||
|
||||
<div class="card-header">
|
||||
<div class="card-title">
|
||||
<h2>Overview</h2>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card-body pt-0">
|
||||
|
||||
<div class="mb-10 fv-row">
|
||||
<label class="required form-label">Sub Categories</label>
|
||||
<div class="d-flex align-items-center mt-3">
|
||||
@foreach ($subCategoriesView as $item)
|
||||
<label
|
||||
class="form-check form-check-custom form-check-inline form-check-solid me-5 is-invalid">
|
||||
<input class="form-check-input" name="sub_categories[]" type="checkbox"
|
||||
value="{{ $item->id }}"
|
||||
@if (in_array($item->id, explode(',', $itemView->sub_category_ids))) checked @endif>
|
||||
<span class="fw-semibold ps-2 fs-6">
|
||||
{{ $item->name . '(' . $item->name_en . ')' }}
|
||||
</span>
|
||||
</label>
|
||||
@endforeach
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="mb-10 fv-row">
|
||||
<div class="position-relative d-flex align-items-center">
|
||||
<span class="svg-icon svg-icon-2 position-absolute mx-4">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<path opacity="0.3"
|
||||
d="M21 22H3C2.4 22 2 21.6 2 21V5C2 4.4 2.4 4 3 4H21C21.6 4 22 4.4 22 5V21C22 21.6 21.6 22 21 22Z"
|
||||
fill="currentColor" />
|
||||
<path
|
||||
d="M6 6C5.4 6 5 5.6 5 5V3C5 2.4 5.4 2 6 2C6.6 2 7 2.4 7 3V5C7 5.6 6.6 6 6 6ZM11 5V3C11 2.4 10.6 2 10 2C9.4 2 9 2.4 9 3V5C9 5.6 9.4 6 10 6C10.6 6 11 5.6 11 5ZM15 5V3C15 2.4 14.6 2 14 2C13.4 2 13 2.4 13 3V5C13 5.6 13.4 6 14 6C14.6 6 15 5.6 15 5ZM19 5V3C19 2.4 18.6 2 18 2C17.4 2 17 2.4 17 3V5C17 5.6 17.4 6 18 6C18.6 6 19 5.6 19 5Z"
|
||||
fill="currentColor" />
|
||||
<path
|
||||
d="M8.8 13.1C9.2 13.1 9.5 13 9.7 12.8C9.9 12.6 10.1 12.3 10.1 11.9C10.1 11.6 10 11.3 9.8 11.1C9.6 10.9 9.3 10.8 9 10.8C8.8 10.8 8.59999 10.8 8.39999 10.9C8.19999 11 8.1 11.1 8 11.2C7.9 11.3 7.8 11.4 7.7 11.6C7.6 11.8 7.5 11.9 7.5 12.1C7.5 12.2 7.4 12.2 7.3 12.3C7.2 12.4 7.09999 12.4 6.89999 12.4C6.69999 12.4 6.6 12.3 6.5 12.2C6.4 12.1 6.3 11.9 6.3 11.7C6.3 11.5 6.4 11.3 6.5 11.1C6.6 10.9 6.8 10.7 7 10.5C7.2 10.3 7.49999 10.1 7.89999 10C8.29999 9.90003 8.60001 9.80003 9.10001 9.80003C9.50001 9.80003 9.80001 9.90003 10.1 10C10.4 10.1 10.7 10.3 10.9 10.4C11.1 10.5 11.3 10.8 11.4 11.1C11.5 11.4 11.6 11.6 11.6 11.9C11.6 12.3 11.5 12.6 11.3 12.9C11.1 13.2 10.9 13.5 10.6 13.7C10.9 13.9 11.2 14.1 11.4 14.3C11.6 14.5 11.8 14.7 11.9 15C12 15.3 12.1 15.5 12.1 15.8C12.1 16.2 12 16.5 11.9 16.8C11.8 17.1 11.5 17.4 11.3 17.7C11.1 18 10.7 18.2 10.3 18.3C9.9 18.4 9.5 18.5 9 18.5C8.5 18.5 8.1 18.4 7.7 18.2C7.3 18 7 17.8 6.8 17.6C6.6 17.4 6.4 17.1 6.3 16.8C6.2 16.5 6.10001 16.3 6.10001 16.1C6.10001 15.9 6.2 15.7 6.3 15.6C6.4 15.5 6.6 15.4 6.8 15.4C6.9 15.4 7.00001 15.4 7.10001 15.5C7.20001 15.6 7.3 15.6 7.3 15.7C7.5 16.2 7.7 16.6 8 16.9C8.3 17.2 8.6 17.3 9 17.3C9.2 17.3 9.5 17.2 9.7 17.1C9.9 17 10.1 16.8 10.3 16.6C10.5 16.4 10.5 16.1 10.5 15.8C10.5 15.3 10.4 15 10.1 14.7C9.80001 14.4 9.50001 14.3 9.10001 14.3C9.00001 14.3 8.9 14.3 8.7 14.3C8.5 14.3 8.39999 14.3 8.39999 14.3C8.19999 14.3 7.99999 14.2 7.89999 14.1C7.79999 14 7.7 13.8 7.7 13.7C7.7 13.5 7.79999 13.4 7.89999 13.2C7.99999 13 8.2 13 8.5 13H8.8V13.1ZM15.3 17.5V12.2C14.3 13 13.6 13.3 13.3 13.3C13.1 13.3 13 13.2 12.9 13.1C12.8 13 12.7 12.8 12.7 12.6C12.7 12.4 12.8 12.3 12.9 12.2C13 12.1 13.2 12 13.6 11.8C14.1 11.6 14.5 11.3 14.7 11.1C14.9 10.9 15.2 10.6 15.5 10.3C15.8 10 15.9 9.80003 15.9 9.70003C15.9 9.60003 16.1 9.60004 16.3 9.60004C16.5 9.60004 16.7 9.70003 16.8 9.80003C16.9 9.90003 17 10.2 17 10.5V17.2C17 18 16.7 18.4 16.2 18.4C16 18.4 15.8 18.3 15.6 18.2C15.4 18.1 15.3 17.8 15.3 17.5Z"
|
||||
fill="currentColor" />
|
||||
</svg>
|
||||
</span>
|
||||
<input class="form-control form-control-solid ps-12" type="text"
|
||||
id="due_date" name="due_date"
|
||||
value="{{ $itemView->due_date ? date('d-m-Y', strtotime($itemView->due_date)) : '' }}">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-10 fv-row">
|
||||
<label class="required form-label">Subject</label>
|
||||
<input type="text" name="name" class="form-control mb-2 col-6"
|
||||
value="{{ $itemView->name }}" />
|
||||
</div>
|
||||
|
||||
|
||||
<div class="mb-10 fv-row">
|
||||
<label class="required form-label">Subject (EN)</label>
|
||||
<input type="text" name="name_en" class="form-control mb-2 col-6"
|
||||
value="{{ $itemView->name_en }}" />
|
||||
</div>
|
||||
|
||||
<div class="mb-10 fv-row">
|
||||
<label class="required form-label">Description</label>
|
||||
<div class="form-control" id="description" name="description"></div>
|
||||
<input type="hidden" id="description_input" name="description" />
|
||||
</div>
|
||||
|
||||
|
||||
<div class="mb-10 fv-row">
|
||||
<label class="required form-label">Description (EN)</label>
|
||||
<div class="form-control" id="description_en" name="description_en"></div>
|
||||
<input type="hidden" id="description_input_en" name="description_en" />
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="d-flex justify-content-end">
|
||||
|
||||
<a href="{{ url('no-where-else/article') }}" id="kt_ecommerce_add_product_cancel"
|
||||
class="btn btn-light me-5">Cancel</a>
|
||||
|
||||
<button type="button" id="btn_submit" class="btn btn-primary">
|
||||
<span class="indicator-label">Save</span>
|
||||
</button>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</form>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
@stop
|
||||
|
||||
|
||||
|
||||
|
||||
@section('script')
|
||||
|
||||
<script type="text/javascript">
|
||||
$(function() {
|
||||
$('#due_date').flatpickr({
|
||||
enableTime: false,
|
||||
dateFormat: 'd-m-Y',
|
||||
defaultDate: null, // Do not preselect any date
|
||||
onReady: function(selectedDates, dateStr, instance) {
|
||||
// Highlight today's date with a custom CSS class
|
||||
const today = instance.todayDateElem;
|
||||
today.classList.add('flatpickr-today-highlight'); // Add a custom class to today
|
||||
}
|
||||
});
|
||||
|
||||
$(document).on("click", "#btn_submit", function(e) {
|
||||
e.preventDefault();
|
||||
alertLoading("Loading")
|
||||
const form = $('#frmUpdate');
|
||||
form.submit();
|
||||
})
|
||||
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
<!-- Include Editor.js core -->
|
||||
<script src="https://cdn.jsdelivr.net/npm/@editorjs/editorjs@latest"></script>
|
||||
|
||||
<!-- Include the plugins -->
|
||||
<script src="https://cdn.jsdelivr.net/npm/@editorjs/header"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/@editorjs/list"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/@editorjs/image"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/editorjs-inline-image"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/@editorjs/embed"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/editorjs-break-line"></script>
|
||||
|
||||
<script>
|
||||
// Custom video tool for embedding videos
|
||||
class VideoTool {
|
||||
constructor({
|
||||
data
|
||||
}) {
|
||||
this.data = data || {};
|
||||
}
|
||||
|
||||
// Render input for video URL
|
||||
render() {
|
||||
const wrapper = document.createElement("div");
|
||||
|
||||
const input = document.createElement("input");
|
||||
input.type = "text";
|
||||
input.placeholder = "Enter video URL";
|
||||
input.value = this.data.url || "";
|
||||
input.style.width = "100%";
|
||||
|
||||
const video = document.createElement("video");
|
||||
video.controls = true;
|
||||
video.style.width = "100%";
|
||||
video.style.marginTop = "10px";
|
||||
video.src = this.data.url || "";
|
||||
|
||||
input.addEventListener("input", (event) => {
|
||||
const value = event.target.value;
|
||||
this.data.url = value;
|
||||
video.src = value;
|
||||
});
|
||||
|
||||
wrapper.appendChild(input);
|
||||
wrapper.appendChild(video);
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
// Save the video URL
|
||||
save(blockContent) {
|
||||
const input = blockContent.querySelector("input");
|
||||
return {
|
||||
url: input.value,
|
||||
};
|
||||
}
|
||||
|
||||
// Editor.js toolbox definition
|
||||
static get toolbox() {
|
||||
return {
|
||||
title: "Video",
|
||||
icon: '<svg width="20" height="20" viewBox="0 0 24 24"><path d="M10 8.64L15.27 12 10 15.36V8.64M10 3.14L21 12 10 20.86V3.14M3 4h4v16H3V4z"></path></svg>',
|
||||
};
|
||||
}
|
||||
}
|
||||
class YoutubeEmbed {
|
||||
/**
|
||||
* Define the toolbox settings for the Editor.js toolbar.
|
||||
*/
|
||||
static get toolbox() {
|
||||
return {
|
||||
title: "YouTube",
|
||||
icon: '<svg width="18" height="18" viewBox="0 0 24 24"><path d="M19.615 3.184c-.403-1.516-1.589-2.693-3.09-3.091-2.719-.727-13.525-.727-16.244 0-1.514.398-2.687 1.57-3.09 3.091-.727 2.719-.727 13.525 0 16.244.403 1.514 1.576 2.693 3.09 3.09 2.719.727 13.525.727 16.244 0 1.516-.397 2.692-1.576 3.09-3.09.727-2.719.727-13.525 0-16.244zm-11.615 13.316v-8l8 4-8 4z"/></svg>',
|
||||
};
|
||||
}
|
||||
|
||||
constructor({
|
||||
data,
|
||||
config,
|
||||
api,
|
||||
readOnly
|
||||
}) {
|
||||
this.data = data || {};
|
||||
this.readOnly = readOnly;
|
||||
this.wrapper = null;
|
||||
this.url = this.data.url || '';
|
||||
this.isEdited = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the input field and YouTube preview.
|
||||
*/
|
||||
render() {
|
||||
this.wrapper = document.createElement('div');
|
||||
this.wrapper.classList.add('block-wrapper');
|
||||
|
||||
const input = document.createElement('input');
|
||||
input.value = this.url;
|
||||
input.placeholder = "Paste YouTube URL here...";
|
||||
input.style.width = '100%';
|
||||
|
||||
this.wrapper.appendChild(input);
|
||||
this._createIframe(this.url);
|
||||
|
||||
input.addEventListener('change', (event) => {
|
||||
this.isEdited = true;
|
||||
this.url = event.target.value;
|
||||
this._createIframe(this.url);
|
||||
});
|
||||
|
||||
return this.wrapper;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the iframe for the YouTube video.
|
||||
*/
|
||||
_createIframe(url) {
|
||||
const videoId = this._extractVideoID(url);
|
||||
if (!videoId) {
|
||||
if (this.isEdited) {
|
||||
this.wrapper.querySelector('input').classList.add('invalid');
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
this.wrapper.innerHTML = ''; // Clear the wrapper
|
||||
|
||||
const plyrContainer = document.createElement('div');
|
||||
plyrContainer.classList.add('video-wrapper');
|
||||
|
||||
const iframe = document.createElement('iframe');
|
||||
iframe.src = `https://www.youtube.com/embed/${videoId}`;
|
||||
iframe.allowFullscreen = true;
|
||||
|
||||
plyrContainer.appendChild(iframe);
|
||||
this.wrapper.appendChild(plyrContainer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract the YouTube video ID from the URL.
|
||||
*/
|
||||
_extractVideoID(url) {
|
||||
const regex = /(?:https?:\/\/)?(?:www\.)?(?:youtube\.com\/watch\?v=|youtu\.be\/)([^&?/]+)/;
|
||||
const match = url.match(regex);
|
||||
return match ? match[1] : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the saved data for this block.
|
||||
*/
|
||||
save(blockContent) {
|
||||
return {
|
||||
url: this.url,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify the core that this tool supports read-only mode.
|
||||
*/
|
||||
static get isReadOnlySupported() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
const csrfToken = document.querySelector('meta[name="csrf-token"]').getAttribute('content');
|
||||
const baseUrlUpload = "{{ url('no-where-else/article-upload-image') }}";
|
||||
const tools = {
|
||||
header: {
|
||||
class: Header,
|
||||
inlineToolbar: ['link', 'bold', 'italic'],
|
||||
config: {
|
||||
placeholder: 'Enter a header',
|
||||
levels: [2, 3, 4], // Set header levels
|
||||
defaultLevel: 3,
|
||||
},
|
||||
},
|
||||
breakLine: {
|
||||
class: BreakLine,
|
||||
inlineToolbar: true,
|
||||
shortcut: 'CMD+SHIFT+ENTER',
|
||||
},
|
||||
youtube: YoutubeEmbed,
|
||||
embed: {
|
||||
class: Embed,
|
||||
inlineToolbar: true,
|
||||
config: {
|
||||
services: {
|
||||
youtube: true,
|
||||
vimeo: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
video: {
|
||||
class: VideoTool,
|
||||
inlineToolbar: true,
|
||||
},
|
||||
image: {
|
||||
class: ImageTool,
|
||||
config: {
|
||||
endpoints: {
|
||||
byFile: baseUrlUpload,
|
||||
byUrl: baseUrlUpload,
|
||||
},
|
||||
field: 'image',
|
||||
types: 'image/*',
|
||||
inlineToolbar: true,
|
||||
additionalRequestHeaders: {
|
||||
'X-CSRF-TOKEN': csrfToken, // Include CSRF token here
|
||||
},
|
||||
enableResizing: true, // This is hypothetical; check if your tool supports this
|
||||
|
||||
},
|
||||
},
|
||||
inlineImage: {
|
||||
class: InlineImage,
|
||||
inlineToolbar: true,
|
||||
config: {
|
||||
embed: {
|
||||
display: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
const descriptionData = {!! json_encode($itemView->description) !!};
|
||||
const editorDescription = new EditorJS({
|
||||
holder: 'description',
|
||||
tools: tools,
|
||||
data: descriptionData != "" ? JSON.parse(descriptionData) : {},
|
||||
onChange: () => {
|
||||
saveData(editorDescription, 'description_input')
|
||||
}
|
||||
});
|
||||
|
||||
const descriptionDataEn = {!! json_encode($itemView->description_en) !!};
|
||||
const editorDescriptionEn = new EditorJS({
|
||||
holder: 'description_en',
|
||||
tools: tools,
|
||||
data: descriptionDataEn !== "" ? JSON.parse(descriptionDataEn) : {},
|
||||
onChange: () => {
|
||||
saveData(editorDescriptionEn, 'description_input_en');
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
|
||||
// Function to save data to hidden inputs
|
||||
function saveData(editor, inputId) {
|
||||
editor.save().then((outputData) => {
|
||||
document.getElementById(inputId).value = JSON.stringify(outputData);
|
||||
}).catch((error) => {
|
||||
console.error('Saving failed: ', error);
|
||||
});
|
||||
}
|
||||
|
||||
$(document).on('click', '#btn_submit', function(e) {
|
||||
e.preventDefault(); // Prevent default form submission
|
||||
|
||||
alertLoading("Loading..."); // Show loading alert (your custom function)
|
||||
|
||||
// Save both editor contents
|
||||
Promise.all([editorDescription.save(), editorDescriptionEn.save()])
|
||||
.then(([descriptionData, descriptionEnData]) => {
|
||||
// Store the JSON output in the hidden input fields
|
||||
$('#description_input').val(JSON.stringify(descriptionData));
|
||||
$('#description_input_en').val(JSON.stringify(descriptionEnData));
|
||||
|
||||
// Submit the form after saving the data
|
||||
$('#frmUpdate').submit();
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('Error saving editor content:', error);
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
|
||||
@endsection
|
||||
@@ -0,0 +1,411 @@
|
||||
@extends('layouts.backendTemplate')
|
||||
|
||||
@section('content')
|
||||
|
||||
<!--begin::Main-->
|
||||
<div class="app-main flex-column flex-row-fluid" id="kt_app_main">
|
||||
|
||||
<div class="d-flex flex-column flex-column-fluid">
|
||||
|
||||
|
||||
@include('uc.breadcrumbList', [
|
||||
'title' => 'CHIANG MAI AND NOWHERE ELSE : Article Management',
|
||||
'pageName' => 'Article Management',
|
||||
])
|
||||
|
||||
|
||||
<div id="kt_app_content" class="app-content flex-column-fluid">
|
||||
<!--begin::Content container-->
|
||||
<div id="kt_app_content_container" class="app-container container-xxl">
|
||||
<!--begin::Card-->
|
||||
<div class="card">
|
||||
|
||||
@if (Session::has('messageSuccess'))
|
||||
<div class="card-body">
|
||||
@include('uc/messageSuccess')
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@if (Session::has('messageFail'))
|
||||
<div class="card-body">
|
||||
@include('uc/messageFail')
|
||||
</div>
|
||||
@endif
|
||||
|
||||
|
||||
<!--begin::Card header-->
|
||||
<div class="card-header border-0 pt-6">
|
||||
<!--begin::Card title-->
|
||||
<div class="d-flex align-items-center position-relative my-1">
|
||||
</div>
|
||||
|
||||
|
||||
@if (Auth::user()->role != 2)
|
||||
<div class="card-toolbar">
|
||||
<div class="d-flex justify-content-end" data-kt-customer-table-toolbar="base">
|
||||
<a href="{{ url('no-where-else/add-article') }}" class="btn btn-primary">Add
|
||||
</a>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@endif
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<div class="card-header border-0 pt-5">
|
||||
|
||||
<div class="card-title">
|
||||
<div class="d-flex align-items-center position-relative my-1">
|
||||
<span class="svg-icon svg-icon-1 position-absolute ms-4">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<rect opacity="0.5" x="17.0365" y="15.1223" width="8.15546" height="2"
|
||||
rx="1" transform="rotate(45 17.0365 15.1223)" fill="currentColor">
|
||||
</rect>
|
||||
<path
|
||||
d="M11 19C6.55556 19 3 15.4444 3 11C3 6.55556 6.55556 3 11 3C15.4444 3 19 6.55556 19 11C19 15.4444 15.4444 19 11 19ZM11 5C7.53333 5 5 7.53333 5 11C5 14.4667 7.53333 17 11 17C14.4667 17 17 14.4667 17 11C17 7.53333 14.4667 5 11 5Z"
|
||||
fill="currentColor"></path>
|
||||
</svg>
|
||||
</span>
|
||||
|
||||
<input type="text" table-filter="search"
|
||||
class="form-control form-control-solid w-250px ps-15" placeholder="Search" />
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card-toolbar flex-row-fluid justify-content-end gap-5">
|
||||
|
||||
<div class="w-100 mw-150px">
|
||||
<div class="position-relative d-flex align-items-center">
|
||||
<span class="svg-icon svg-icon-2 position-absolute mx-4">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<path opacity="0.3"
|
||||
d="M21 22H3C2.4 22 2 21.6 2 21V5C2 4.4 2.4 4 3 4H21C21.6 4 22 4.4 22 5V21C22 21.6 21.6 22 21 22Z"
|
||||
fill="currentColor" />
|
||||
<path
|
||||
d="M6 6C5.4 6 5 5.6 5 5V3C5 2.4 5.4 2 6 2C6.6 2 7 2.4 7 3V5C7 5.6 6.6 6 6 6ZM11 5V3C11 2.4 10.6 2 10 2C9.4 2 9 2.4 9 3V5C9 5.6 9.4 6 10 6C10.6 6 11 5.6 11 5ZM15 5V3C15 2.4 14.6 2 14 2C13.4 2 13 2.4 13 3V5C13 5.6 13.4 6 14 6C14.6 6 15 5.6 15 5ZM19 5V3C19 2.4 18.6 2 18 2C17.4 2 17 2.4 17 3V5C17 5.6 17.4 6 18 6C18.6 6 19 5.6 19 5Z"
|
||||
fill="currentColor" />
|
||||
<path
|
||||
d="M8.8 13.1C9.2 13.1 9.5 13 9.7 12.8C9.9 12.6 10.1 12.3 10.1 11.9C10.1 11.6 10 11.3 9.8 11.1C9.6 10.9 9.3 10.8 9 10.8C8.8 10.8 8.59999 10.8 8.39999 10.9C8.19999 11 8.1 11.1 8 11.2C7.9 11.3 7.8 11.4 7.7 11.6C7.6 11.8 7.5 11.9 7.5 12.1C7.5 12.2 7.4 12.2 7.3 12.3C7.2 12.4 7.09999 12.4 6.89999 12.4C6.69999 12.4 6.6 12.3 6.5 12.2C6.4 12.1 6.3 11.9 6.3 11.7C6.3 11.5 6.4 11.3 6.5 11.1C6.6 10.9 6.8 10.7 7 10.5C7.2 10.3 7.49999 10.1 7.89999 10C8.29999 9.90003 8.60001 9.80003 9.10001 9.80003C9.50001 9.80003 9.80001 9.90003 10.1 10C10.4 10.1 10.7 10.3 10.9 10.4C11.1 10.5 11.3 10.8 11.4 11.1C11.5 11.4 11.6 11.6 11.6 11.9C11.6 12.3 11.5 12.6 11.3 12.9C11.1 13.2 10.9 13.5 10.6 13.7C10.9 13.9 11.2 14.1 11.4 14.3C11.6 14.5 11.8 14.7 11.9 15C12 15.3 12.1 15.5 12.1 15.8C12.1 16.2 12 16.5 11.9 16.8C11.8 17.1 11.5 17.4 11.3 17.7C11.1 18 10.7 18.2 10.3 18.3C9.9 18.4 9.5 18.5 9 18.5C8.5 18.5 8.1 18.4 7.7 18.2C7.3 18 7 17.8 6.8 17.6C6.6 17.4 6.4 17.1 6.3 16.8C6.2 16.5 6.10001 16.3 6.10001 16.1C6.10001 15.9 6.2 15.7 6.3 15.6C6.4 15.5 6.6 15.4 6.8 15.4C6.9 15.4 7.00001 15.4 7.10001 15.5C7.20001 15.6 7.3 15.6 7.3 15.7C7.5 16.2 7.7 16.6 8 16.9C8.3 17.2 8.6 17.3 9 17.3C9.2 17.3 9.5 17.2 9.7 17.1C9.9 17 10.1 16.8 10.3 16.6C10.5 16.4 10.5 16.1 10.5 15.8C10.5 15.3 10.4 15 10.1 14.7C9.80001 14.4 9.50001 14.3 9.10001 14.3C9.00001 14.3 8.9 14.3 8.7 14.3C8.5 14.3 8.39999 14.3 8.39999 14.3C8.19999 14.3 7.99999 14.2 7.89999 14.1C7.79999 14 7.7 13.8 7.7 13.7C7.7 13.5 7.79999 13.4 7.89999 13.2C7.99999 13 8.2 13 8.5 13H8.8V13.1ZM15.3 17.5V12.2C14.3 13 13.6 13.3 13.3 13.3C13.1 13.3 13 13.2 12.9 13.1C12.8 13 12.7 12.8 12.7 12.6C12.7 12.4 12.8 12.3 12.9 12.2C13 12.1 13.2 12 13.6 11.8C14.1 11.6 14.5 11.3 14.7 11.1C14.9 10.9 15.2 10.6 15.5 10.3C15.8 10 15.9 9.80003 15.9 9.70003C15.9 9.60003 16.1 9.60004 16.3 9.60004C16.5 9.60004 16.7 9.70003 16.8 9.80003C16.9 9.90003 17 10.2 17 10.5V17.2C17 18 16.7 18.4 16.2 18.4C16 18.4 15.8 18.3 15.6 18.2C15.4 18.1 15.3 17.8 15.3 17.5Z"
|
||||
fill="currentColor" />
|
||||
</svg>
|
||||
</span>
|
||||
<input class="form-control form-control-solid ps-12" placeholder="From"
|
||||
id="due_date_from" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="w-100 mw-150px">
|
||||
<div class="position-relative d-flex align-items-center">
|
||||
<span class="svg-icon svg-icon-2 position-absolute mx-4">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<path opacity="0.3"
|
||||
d="M21 22H3C2.4 22 2 21.6 2 21V5C2 4.4 2.4 4 3 4H21C21.6 4 22 4.4 22 5V21C22 21.6 21.6 22 21 22Z"
|
||||
fill="currentColor" />
|
||||
<path
|
||||
d="M6 6C5.4 6 5 5.6 5 5V3C5 2.4 5.4 2 6 2C6.6 2 7 2.4 7 3V5C7 5.6 6.6 6 6 6ZM11 5V3C11 2.4 10.6 2 10 2C9.4 2 9 2.4 9 3V5C9 5.6 9.4 6 10 6C10.6 6 11 5.6 11 5ZM15 5V3C15 2.4 14.6 2 14 2C13.4 2 13 2.4 13 3V5C13 5.6 13.4 6 14 6C14.6 6 15 5.6 15 5ZM19 5V3C19 2.4 18.6 2 18 2C17.4 2 17 2.4 17 3V5C17 5.6 17.4 6 18 6C18.6 6 19 5.6 19 5Z"
|
||||
fill="currentColor" />
|
||||
<path
|
||||
d="M8.8 13.1C9.2 13.1 9.5 13 9.7 12.8C9.9 12.6 10.1 12.3 10.1 11.9C10.1 11.6 10 11.3 9.8 11.1C9.6 10.9 9.3 10.8 9 10.8C8.8 10.8 8.59999 10.8 8.39999 10.9C8.19999 11 8.1 11.1 8 11.2C7.9 11.3 7.8 11.4 7.7 11.6C7.6 11.8 7.5 11.9 7.5 12.1C7.5 12.2 7.4 12.2 7.3 12.3C7.2 12.4 7.09999 12.4 6.89999 12.4C6.69999 12.4 6.6 12.3 6.5 12.2C6.4 12.1 6.3 11.9 6.3 11.7C6.3 11.5 6.4 11.3 6.5 11.1C6.6 10.9 6.8 10.7 7 10.5C7.2 10.3 7.49999 10.1 7.89999 10C8.29999 9.90003 8.60001 9.80003 9.10001 9.80003C9.50001 9.80003 9.80001 9.90003 10.1 10C10.4 10.1 10.7 10.3 10.9 10.4C11.1 10.5 11.3 10.8 11.4 11.1C11.5 11.4 11.6 11.6 11.6 11.9C11.6 12.3 11.5 12.6 11.3 12.9C11.1 13.2 10.9 13.5 10.6 13.7C10.9 13.9 11.2 14.1 11.4 14.3C11.6 14.5 11.8 14.7 11.9 15C12 15.3 12.1 15.5 12.1 15.8C12.1 16.2 12 16.5 11.9 16.8C11.8 17.1 11.5 17.4 11.3 17.7C11.1 18 10.7 18.2 10.3 18.3C9.9 18.4 9.5 18.5 9 18.5C8.5 18.5 8.1 18.4 7.7 18.2C7.3 18 7 17.8 6.8 17.6C6.6 17.4 6.4 17.1 6.3 16.8C6.2 16.5 6.10001 16.3 6.10001 16.1C6.10001 15.9 6.2 15.7 6.3 15.6C6.4 15.5 6.6 15.4 6.8 15.4C6.9 15.4 7.00001 15.4 7.10001 15.5C7.20001 15.6 7.3 15.6 7.3 15.7C7.5 16.2 7.7 16.6 8 16.9C8.3 17.2 8.6 17.3 9 17.3C9.2 17.3 9.5 17.2 9.7 17.1C9.9 17 10.1 16.8 10.3 16.6C10.5 16.4 10.5 16.1 10.5 15.8C10.5 15.3 10.4 15 10.1 14.7C9.80001 14.4 9.50001 14.3 9.10001 14.3C9.00001 14.3 8.9 14.3 8.7 14.3C8.5 14.3 8.39999 14.3 8.39999 14.3C8.19999 14.3 7.99999 14.2 7.89999 14.1C7.79999 14 7.7 13.8 7.7 13.7C7.7 13.5 7.79999 13.4 7.89999 13.2C7.99999 13 8.2 13 8.5 13H8.8V13.1ZM15.3 17.5V12.2C14.3 13 13.6 13.3 13.3 13.3C13.1 13.3 13 13.2 12.9 13.1C12.8 13 12.7 12.8 12.7 12.6C12.7 12.4 12.8 12.3 12.9 12.2C13 12.1 13.2 12 13.6 11.8C14.1 11.6 14.5 11.3 14.7 11.1C14.9 10.9 15.2 10.6 15.5 10.3C15.8 10 15.9 9.80003 15.9 9.70003C15.9 9.60003 16.1 9.60004 16.3 9.60004C16.5 9.60004 16.7 9.70003 16.8 9.80003C16.9 9.90003 17 10.2 17 10.5V17.2C17 18 16.7 18.4 16.2 18.4C16 18.4 15.8 18.3 15.6 18.2C15.4 18.1 15.3 17.8 15.3 17.5Z"
|
||||
fill="currentColor" />
|
||||
</svg>
|
||||
</span>
|
||||
<input class="form-control form-control-solid ps-12" placeholder="To"
|
||||
id="due_date_to" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button type="button" id="btn-submit" class="btn btn-primary">
|
||||
Search
|
||||
</button>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card-body py-4">
|
||||
<!--begin::Table-->
|
||||
<table class="table align-middle table-row-dashed fs-6 gy-5" id="data-table-category">
|
||||
<!--begin::Table head-->
|
||||
<thead>
|
||||
<!--begin::Table row-->
|
||||
<tr class="text-start text-muted fw-bold fs-7 text-uppercase gs-0">
|
||||
<th class="min-w-125px">Pic</th>
|
||||
<th class="min-w-125px">Date</th>
|
||||
<th class="min-w-125px">Subject</th>
|
||||
<th class="min-w-125px">Subject (EN)</th>
|
||||
<th class="min-w-125px">Created</th>
|
||||
<th class="min-w-125px">Active</th>
|
||||
<th class="text-end min-w-100px">Manage</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody class="text-gray-600 fw-semibold">
|
||||
|
||||
@foreach ($itemView as $obj)
|
||||
<tr>
|
||||
<td class="d-flex align-items-center">
|
||||
<div class="symbol symbol-100px symbol-2by3 me-4">
|
||||
@if ($obj->image_url && $obj->image_name)
|
||||
<a class="show-image-preview d-block overlay"
|
||||
href="{{ url($obj->image_url . '/original/' . $obj->image_name) }}">
|
||||
<div class="symbol-label"
|
||||
style="background-image: url('{{ url($obj->image_url . '/thumbnail/' . $obj->image_name) }}')">
|
||||
</div>
|
||||
</a>
|
||||
@else
|
||||
<div class="symbol-label"
|
||||
style="background-image: url('{{ url('assets/media/avatars/blank.png') }}')">
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
{{ Carbon\Carbon::parse($obj->due_date)->format('d, M Y') }}
|
||||
</td>
|
||||
|
||||
<td>
|
||||
<a href="#" class="text-gray-800 text-hover-primary mb-1">
|
||||
{{ $obj->name }}
|
||||
</a>
|
||||
</td>
|
||||
|
||||
<td>
|
||||
<a href="#" class="text-gray-800 text-hover-primary mb-1">
|
||||
{{ $obj->name_en }}
|
||||
</a>
|
||||
</td>
|
||||
|
||||
<td>
|
||||
{{ Carbon\Carbon::parse($obj->created_at)->format('d, M Y') }}
|
||||
</td>
|
||||
|
||||
|
||||
<td>
|
||||
@if ($obj->active == 1)
|
||||
<span class="badge py-3 px-4 fs-7 badge-light-success">Active</span>
|
||||
@else
|
||||
<span class="badge py-3 px-4 fs-7 badge-light-danger">Inactive</span>
|
||||
@endif
|
||||
</td>
|
||||
|
||||
|
||||
<td class="min-w-100px text-end">
|
||||
|
||||
{{-- View --}}
|
||||
{{-- <a href="{{ url('view-sub-category/' . $obj->id) }}"
|
||||
class="btn btn-icon btn-bg-light btn-active-color-primary btn-sm me-1">
|
||||
<span class="svg-icon svg-icon-2">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24"
|
||||
fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M17.5 11H6.5C4 11 2 9 2 6.5C2 4 4 2 6.5 2H17.5C20 2 22 4 22 6.5C22 9 20 11 17.5 11ZM15 6.5C15 7.9 16.1 9 17.5 9C18.9 9 20 7.9 20 6.5C20 5.1 18.9 4 17.5 4C16.1 4 15 5.1 15 6.5Z"
|
||||
fill="currentColor"></path>
|
||||
<path opacity="0.3"
|
||||
d="M17.5 22H6.5C4 22 2 20 2 17.5C2 15 4 13 6.5 13H17.5C20 13 22 15 22 17.5C22 20 20 22 17.5 22ZM4 17.5C4 18.9 5.1 20 6.5 20C7.9 20 9 18.9 9 17.5C9 16.1 7.9 15 6.5 15C5.1 15 4 16.1 4 17.5Z"
|
||||
fill="currentColor"></path>
|
||||
</svg>
|
||||
</span>
|
||||
</a> --}}
|
||||
|
||||
{{-- Edit --}}
|
||||
<a href="{{ url('no-where-else/edit-article/' . $obj->id) }}"
|
||||
class="btn btn-icon btn-bg-light btn-active-color-primary btn-sm me-1">
|
||||
<span class="svg-icon svg-icon-3">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24"
|
||||
fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path opacity="0.3"
|
||||
d="M21.4 8.35303L19.241 10.511L13.485 4.755L15.643 2.59595C16.0248 2.21423 16.5426 1.99988 17.0825 1.99988C17.6224 1.99988 18.1402 2.21423 18.522 2.59595L21.4 5.474C21.7817 5.85581 21.9962 6.37355 21.9962 6.91345C21.9962 7.45335 21.7817 7.97122 21.4 8.35303ZM3.68699 21.932L9.88699 19.865L4.13099 14.109L2.06399 20.309C1.98815 20.5354 1.97703 20.7787 2.03189 21.0111C2.08674 21.2436 2.2054 21.4561 2.37449 21.6248C2.54359 21.7934 2.75641 21.9115 2.989 21.9658C3.22158 22.0201 3.4647 22.0084 3.69099 21.932H3.68699Z"
|
||||
fill="currentColor" />
|
||||
<path
|
||||
d="M5.574 21.3L3.692 21.928C3.46591 22.0032 3.22334 22.0141 2.99144 21.9594C2.75954 21.9046 2.54744 21.7864 2.3789 21.6179C2.21036 21.4495 2.09202 21.2375 2.03711 21.0056C1.9822 20.7737 1.99289 20.5312 2.06799 20.3051L2.696 18.422L5.574 21.3ZM4.13499 14.105L9.891 19.861L19.245 10.507L13.489 4.75098L4.13499 14.105Z"
|
||||
fill="currentColor" />
|
||||
</svg>
|
||||
</span>
|
||||
</a>
|
||||
|
||||
{{-- Delete --}}
|
||||
@if ($obj->active == 1 && Auth::user()->role != 2)
|
||||
<a href="#" data-id="{{ $obj->id }}"
|
||||
class="btn btn-icon btn-bg-light btn-active-color-primary btn-sm delete-item">
|
||||
<span class="svg-icon svg-icon-3">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24"
|
||||
fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M5 9C5 8.44772 5.44772 8 6 8H18C18.5523 8 19 8.44772 19 9V18C19 19.6569 17.6569 21 16 21H8C6.34315 21 5 19.6569 5 18V9Z"
|
||||
fill="currentColor" />
|
||||
<path opacity="0.5"
|
||||
d="M5 5C5 4.44772 5.44772 4 6 4H18C18.5523 4 19 4.44772 19 5V5C19 5.55228 18.5523 6 18 6H6C5.44772 6 5 5.55228 5 5V5Z"
|
||||
fill="currentColor" />
|
||||
<path opacity="0.5"
|
||||
d="M9 4C9 3.44772 9.44772 3 10 3H14C14.5523 3 15 3.44772 15 4V4H9V4Z"
|
||||
fill="currentColor" />
|
||||
</svg>
|
||||
</span>
|
||||
</a>
|
||||
@endif
|
||||
</td>
|
||||
|
||||
|
||||
</tr>
|
||||
@endforeach
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@stop
|
||||
|
||||
|
||||
@section('script')
|
||||
|
||||
<script type="text/javascript">
|
||||
const baseUrl = "{{ url('no-where-else/article') }}";
|
||||
var datatable;
|
||||
datatable = $("#data-table-category").DataTable({
|
||||
"info": false,
|
||||
"order": [],
|
||||
"pageLength": 25,
|
||||
lengthMenu: [
|
||||
[10, 25, 50, 100, 500, 1000],
|
||||
[10, 25, 50, 100, 500, 1000]
|
||||
]
|
||||
});
|
||||
|
||||
// Filter by search
|
||||
const filterSearch = document.querySelector('[table-filter="search"]');
|
||||
filterSearch.addEventListener('keyup', function(e) {
|
||||
datatable.search(e.target.value).draw();
|
||||
});
|
||||
|
||||
// filter by status
|
||||
const filterStatus = document.querySelector('[table-filter="status"]');
|
||||
$(filterStatus).on('change', e => {
|
||||
let value = e.target.value;
|
||||
if (value === 'all') {
|
||||
value = '';
|
||||
}
|
||||
datatable.column(4).search(value).draw();
|
||||
});
|
||||
|
||||
|
||||
// Remove
|
||||
$(document).on('click', '.delete-item', function() {
|
||||
swal.fire({
|
||||
allowOutsideClick: false,
|
||||
text: "Are you sure you would like to Delete?",
|
||||
icon: "warning",
|
||||
buttonsStyling: false,
|
||||
showDenyButton: true,
|
||||
confirmButtonText: "Yes",
|
||||
denyButtonText: 'No',
|
||||
customClass: {
|
||||
confirmButton: "btn btn-primary",
|
||||
denyButton: "btn btn-light-danger"
|
||||
}
|
||||
}).then((result) => {
|
||||
if (result.isConfirmed) {
|
||||
|
||||
alertLoading("Loading")
|
||||
|
||||
// set up ajax
|
||||
initAjaxSetupToken();
|
||||
|
||||
const ajaxProp = {
|
||||
url: "{{ url('no-where-else/delete-article') }}",
|
||||
type: 'POST',
|
||||
data: {
|
||||
item_id: $(this).data('id')
|
||||
},
|
||||
};
|
||||
|
||||
$.ajax(ajaxProp).done(function(res) {
|
||||
if (res.status) {
|
||||
const url = "{{ url('no-where-else/article') }}";
|
||||
alertSuccessWithUrl('Notice', "Delete success", url);
|
||||
hideLoading();
|
||||
} else {
|
||||
alertFail('Notice', res.message ?? "Unsuccessfully");
|
||||
hideLoading();
|
||||
}
|
||||
}).fail(function(xhr, status, error) {
|
||||
logAjaxError(xhr, status, error);
|
||||
alertFail('Notice', error.message ?? "Unsuccessfully");
|
||||
hideLoading();
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
var today = new Date();
|
||||
var dateFormat = "d-m-Y";
|
||||
|
||||
var dueDateFrom = $("#due_date_from");
|
||||
var dueDateTo = $("#due_date_to");
|
||||
|
||||
const dateFrom = "{{ $fromDateView }}";
|
||||
const dateTo = "{{ $toDateView }}";
|
||||
|
||||
dueDateFrom.flatpickr({
|
||||
showClearButton: true,
|
||||
enableTime: false,
|
||||
dateFormat: dateFormat,
|
||||
maxDate: today,
|
||||
defaultDate: dateFrom,
|
||||
|
||||
});
|
||||
|
||||
dueDateTo.flatpickr({
|
||||
showClearButton: true,
|
||||
enableTime: false,
|
||||
dateFormat: dateFormat,
|
||||
maxDate: today,
|
||||
defaultDate: dateTo,
|
||||
|
||||
});
|
||||
|
||||
const clearDatePicker = () => {
|
||||
dueDateFrom.flatpickr().clear();
|
||||
dueDateTo.flatpickr().clear();
|
||||
|
||||
// Set the date format again after clearing
|
||||
dueDateFrom.flatpickr({
|
||||
dateFormat: dateFormat
|
||||
});
|
||||
dueDateTo.flatpickr({
|
||||
dateFormat: dateFormat
|
||||
});
|
||||
}
|
||||
|
||||
$('#btn-submit').on('click', (e) => {
|
||||
e.preventDefault(); // Prevent the default behavior of the anchor element
|
||||
|
||||
// from
|
||||
const fromDateSelected = $("#due_date_from").val();
|
||||
|
||||
// to
|
||||
const toDateSelected = $("#due_date_to").val();
|
||||
|
||||
if (fromDateSelected && toDateSelected) {
|
||||
var newUrl =
|
||||
`${baseUrl}/${fromDateSelected}/${toDateSelected}`;
|
||||
window.location.href = newUrl;
|
||||
} else {
|
||||
var newUrl = `${baseUrl}/all/all/`;
|
||||
window.location.href = newUrl;
|
||||
}
|
||||
|
||||
})
|
||||
</script>
|
||||
|
||||
@endsection
|
||||
@@ -0,0 +1,178 @@
|
||||
@extends('layouts.backendTemplate')
|
||||
|
||||
@section('content')
|
||||
|
||||
<!--begin::Main-->
|
||||
<div class="app-main flex-column flex-row-fluid" id="kt_app_main">
|
||||
|
||||
<div class="d-flex flex-column flex-column-fluid">
|
||||
|
||||
|
||||
@include('uc.admin.breadcrumb', [
|
||||
'title' => 'Category Add',
|
||||
'pageName' => 'Add',
|
||||
'pageParent' => 'Category Management',
|
||||
'pageParentLink' => url('category'),
|
||||
])
|
||||
|
||||
<div id="kt_app_content" class="app-content flex-column-fluid">
|
||||
<div id="kt_app_content_container" class="app-container container-xxl">
|
||||
|
||||
|
||||
<form class="form d-flex flex-column flex-lg-row" action="{{ url('category/insert') }}" method="post"
|
||||
enctype="multipart/form-data">
|
||||
|
||||
<input type="hidden" name="_method" value="POST">
|
||||
<input type="hidden" name="_token" value="{{ csrf_token() }}">
|
||||
|
||||
|
||||
<div class="d-flex flex-column gap-7 gap-lg-10 w-100 w-lg-300px mb-7 me-lg-10">
|
||||
|
||||
<div class="card card-flush py-4">
|
||||
|
||||
<div class="card-body text-center pt-0">
|
||||
|
||||
<style>
|
||||
.image-input-placeholder {
|
||||
background-image: url('{{ url('assets/media/svg/files/blank-image.svg') }}');
|
||||
}
|
||||
|
||||
[data-bs-theme="dark"] .image-input-placeholder {
|
||||
background-image: url('../media/svg/files/blank-image-dark.svg');
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="image-input image-input-empty image-input-outline image-input-placeholder mb-3"
|
||||
data-kt-image-input="true">
|
||||
|
||||
<div class="image-input-wrapper w-150px h-150px"></div>
|
||||
|
||||
<label
|
||||
class="btn btn-icon btn-circle btn-active-color-primary w-25px h-25px bg-body shadow"
|
||||
data-kt-image-input-action="change" data-bs-toggle="tooltip"
|
||||
title="Change avatar">
|
||||
|
||||
<i class="bi bi-pencil-fill fs-7"></i>
|
||||
|
||||
<input type="file" name="avatar" accept=".png, .jpg, .jpeg" />
|
||||
<input type="hidden" name="avatar_remove" />
|
||||
|
||||
</label>
|
||||
|
||||
<span
|
||||
class="btn btn-icon btn-circle btn-active-color-primary w-25px h-25px bg-body shadow"
|
||||
data-kt-image-input-action="cancel" data-bs-toggle="tooltip"
|
||||
title="Cancel avatar">
|
||||
<i class="bi bi-x fs-2"></i>
|
||||
</span>
|
||||
|
||||
<span
|
||||
class="btn btn-icon btn-circle btn-active-color-primary w-25px h-25px bg-body shadow"
|
||||
data-kt-image-input-action="remove" data-bs-toggle="tooltip"
|
||||
title="Remove avatar">
|
||||
<i class="bi bi-x fs-2"></i>
|
||||
</span>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="text-muted fs-7">Set the profile picture. Only *.png, *.jpg and *.jpeg
|
||||
image
|
||||
files are accepted</div>
|
||||
|
||||
</div>
|
||||
|
||||
{{-- Active --}}
|
||||
<div class="card-header" style="border: unset;">
|
||||
<div class="required card-title">
|
||||
<h2>Active</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body pt-0">
|
||||
|
||||
<label class="form-check form-switch form-check-custom form-check-solid">
|
||||
<input class="form-check-input" disabled readonly name="active" type="checkbox"
|
||||
value="1" checked />
|
||||
</label>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="d-flex flex-column flex-row-fluid gap-7 gap-lg-10">
|
||||
|
||||
<div class="card card-flush py-4">
|
||||
|
||||
|
||||
@if (Session::has('messageSuccess'))
|
||||
<div class="card-body">
|
||||
@include('uc/messageSuccess')
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@if (Session::has('messageFail'))
|
||||
<div class="card-body">
|
||||
@include('uc/messageFail')
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<div class="card-header">
|
||||
<div class="card-title">
|
||||
<h2>Overview</h2>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card-body pt-0">
|
||||
|
||||
<div class="mb-10 fv-row">
|
||||
<label class="required form-label">Name</label>
|
||||
<input type="text" name="name" class="form-control mb-2 col-6"
|
||||
value="{{ old('name') }}" />
|
||||
</div>
|
||||
|
||||
|
||||
<div class="mb-10 fv-row">
|
||||
<label class="required form-label">Name (EN)</label>
|
||||
<input type="text" name="name_en" class="form-control mb-2 col-6"
|
||||
value="{{ old('name_en') }}" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="d-flex justify-content-end">
|
||||
|
||||
<a href="{{ url('category') }}" id="kt_ecommerce_add_product_cancel"
|
||||
class="btn btn-light me-5">Cancel</a>
|
||||
|
||||
<button type="submit" class="btn btn-primary">
|
||||
<span class="indicator-label">Save Changes</span>
|
||||
</button>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</form>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
@stop
|
||||
|
||||
|
||||
@section('script')
|
||||
|
||||
<script type="text/javascript">
|
||||
$(function() {});
|
||||
</script>
|
||||
|
||||
@endsection
|
||||
@@ -0,0 +1,186 @@
|
||||
@extends('layouts.backendTemplate')
|
||||
|
||||
@section('content')
|
||||
|
||||
<!--begin::Main-->
|
||||
<div class="app-main flex-column flex-row-fluid" id="kt_app_main">
|
||||
|
||||
<div class="d-flex flex-column flex-column-fluid">
|
||||
|
||||
|
||||
@include('uc.admin.breadcrumb', [
|
||||
'title' => 'Category Edit',
|
||||
'pageName' => 'Edit',
|
||||
'pageParent' => 'Category Management',
|
||||
'pageParentLink' => url('category'),
|
||||
])
|
||||
<div id="kt_app_content" class="app-content flex-column-fluid">
|
||||
<div id="kt_app_content_container" class="app-container container-xxl">
|
||||
|
||||
|
||||
<form class="form d-flex flex-column flex-lg-row" action="{{ url('category/update') }}" method="post"
|
||||
enctype="multipart/form-data">
|
||||
|
||||
<input type="hidden" name="id" value="{{ $itemView->id }}">
|
||||
<input type="hidden" name="_method" value="POST">
|
||||
<input type="hidden" name="_token" value="{{ csrf_token() }}">
|
||||
|
||||
|
||||
{{-- Left --}}
|
||||
<div class="d-flex flex-column gap-7 gap-lg-10 w-100 w-lg-300px mb-7 me-lg-10">
|
||||
|
||||
<div class="card card-flush py-4">
|
||||
|
||||
<div class="card-body text-center pt-0">
|
||||
|
||||
<style>
|
||||
.image-input-placeholder {
|
||||
background-image: url('{{ url('assets/media/svg/files/blank-image.svg') }}');
|
||||
}
|
||||
|
||||
[data-bs-theme="dark"] .image-input-placeholder {
|
||||
background-image: url('../media/svg/files/blank-image-dark.svg');
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="image-input image-input-empty image-input-outline image-input-placeholder mb-3"
|
||||
data-kt-image-input="true">
|
||||
|
||||
|
||||
@if ($itemView->image_url && $itemView->image_name)
|
||||
<div class="image-input-wrapper w-150px h-150px"
|
||||
style="background-image: url('{{ $itemView->image_url . '/thumbnail/' . $itemView->image_name }}')">
|
||||
</div>
|
||||
@else
|
||||
<div class="image-input-wrapper w-150px h-150px"></div>
|
||||
@endif
|
||||
|
||||
<label
|
||||
class="btn btn-icon btn-circle btn-active-color-primary w-25px h-25px bg-body shadow"
|
||||
data-kt-image-input-action="change" data-bs-toggle="tooltip"
|
||||
title="Change avatar">
|
||||
|
||||
<i class="bi bi-pencil-fill fs-7"></i>
|
||||
|
||||
<input type="file" name="avatar" accept=".png, .jpg, .jpeg" />
|
||||
<input type="hidden" name="avatar_remove" />
|
||||
|
||||
</label>
|
||||
|
||||
<span
|
||||
class="btn btn-icon btn-circle btn-active-color-primary w-25px h-25px bg-body shadow"
|
||||
data-kt-image-input-action="cancel" data-bs-toggle="tooltip"
|
||||
title="Cancel avatar">
|
||||
<i class="bi bi-x fs-2"></i>
|
||||
</span>
|
||||
|
||||
<span
|
||||
class="btn btn-icon btn-circle btn-active-color-primary w-25px h-25px bg-body shadow"
|
||||
data-kt-image-input-action="remove" data-bs-toggle="tooltip"
|
||||
title="Remove avatar">
|
||||
<i class="bi bi-x fs-2"></i>
|
||||
</span>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="text-muted fs-7">Set the profile picture. Only *.png, *.jpg and *.jpeg
|
||||
image
|
||||
files are accepted</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="card-header" style="border: unset;">
|
||||
<div class="required card-title">
|
||||
<h2>Active</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body pt-0">
|
||||
<label class="form-check form-switch form-check-custom form-check-solid">
|
||||
<input class="form-check-input" name="active" type="checkbox" value="1"
|
||||
{{ $itemView->active == 1 ? 'checked' : '' }} />
|
||||
</label>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
{{-- Right --}}
|
||||
<div class="d-flex flex-column flex-row-fluid gap-7 gap-lg-10">
|
||||
|
||||
<div class="card card-flush py-4">
|
||||
|
||||
@if (Session::has('messageSuccess'))
|
||||
<div class="card-body">
|
||||
@include('uc/messageSuccess')
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@if (Session::has('messageFail'))
|
||||
<div class="card-body">
|
||||
@include('uc/messageFail')
|
||||
</div>
|
||||
@endif
|
||||
|
||||
|
||||
<div class="card-header">
|
||||
<div class="card-title">
|
||||
<h2>Overview</h2>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card-body pt-0">
|
||||
|
||||
|
||||
<div class="mb-10 fv-row">
|
||||
<label class="required form-label">Name</label>
|
||||
<input type="text" name="name" class="form-control mb-2 col-6"
|
||||
value="{{ $itemView->name }}" />
|
||||
</div>
|
||||
|
||||
|
||||
<div class="mb-10 fv-row">
|
||||
<label class="required form-label">Name (EN)</label>
|
||||
<input type="text" name="name_en" class="form-control mb-2 col-6"
|
||||
value="{{ $itemView->name_en }}" />
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="d-flex justify-content-end">
|
||||
|
||||
<a href="{{ url('category') }}" id="kt_ecommerce_add_product_cancel"
|
||||
class="btn btn-light me-5">Cancel</a>
|
||||
|
||||
<button type="submit" class="btn btn-primary">
|
||||
<span class="indicator-label">Save Changes</span>
|
||||
</button>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</form>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
@stop
|
||||
|
||||
|
||||
@section('script')
|
||||
|
||||
<script type="text/javascript">
|
||||
$(function() {});
|
||||
</script>
|
||||
|
||||
@endsection
|
||||
@@ -0,0 +1,270 @@
|
||||
@extends('layouts.backendTemplate')
|
||||
|
||||
@section('content')
|
||||
|
||||
<!--begin::Main-->
|
||||
<div class="app-main flex-column flex-row-fluid" id="kt_app_main">
|
||||
|
||||
<div class="d-flex flex-column flex-column-fluid">
|
||||
|
||||
|
||||
@include('uc.breadcrumbList', [
|
||||
'title' => 'Category Management',
|
||||
'pageName' => 'Category Management',
|
||||
])
|
||||
|
||||
|
||||
<div id="kt_app_content" class="app-content flex-column-fluid">
|
||||
<!--begin::Content container-->
|
||||
<div id="kt_app_content_container" class="app-container container-xxl">
|
||||
<!--begin::Card-->
|
||||
<div class="card">
|
||||
|
||||
@if (Session::has('messageSuccess'))
|
||||
<div class="card-body">
|
||||
@include('uc/messageSuccess')
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@if (Session::has('messageFail'))
|
||||
<div class="card-body">
|
||||
@include('uc/messageFail')
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<!--begin::Card header-->
|
||||
<div class="card-header border-0 pt-6">
|
||||
<!--begin::Card title-->
|
||||
<div class="d-flex align-items-center position-relative my-1">
|
||||
<span class="svg-icon svg-icon-1 position-absolute ms-6">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<rect opacity="0.5" x="17.0365" y="15.1223" width="8.15546" height="2"
|
||||
rx="1" transform="rotate(45 17.0365 15.1223)" fill="currentColor" />
|
||||
<path
|
||||
d="M11 19C6.55556 19 3 15.4444 3 11C3 6.55556 6.55556 3 11 3C15.4444 3 19 6.55556 19 11C19 15.4444 15.4444 19 11 19ZM11 5C7.53333 5 5 7.53333 5 11C5 14.4667 7.53333 17 11 17C14.4667 17 17 14.4667 17 11C17 7.53333 14.4667 5 11 5Z"
|
||||
fill="currentColor" />
|
||||
</svg>
|
||||
</span>
|
||||
<input type="text" table-filter="search"
|
||||
class="form-control form-control-solid w-250px ps-15" placeholder="Search" />
|
||||
</div>
|
||||
|
||||
<div class="card-toolbar">
|
||||
<div class="w-150px me-3">
|
||||
<select class="form-select form-select-solid" data-control="select2"
|
||||
data-hide-search="true" data-placeholder="Status" table-filter="status">
|
||||
<option></option>
|
||||
<option value="all">All</option>
|
||||
<option value="active">Active</option>
|
||||
<option value="inactive">Inactive</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="d-flex justify-content-end" data-kt-customer-table-toolbar="base">
|
||||
<a href="{{ url('category/add') }}" class="btn btn-primary">Add </a>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<div class="card-body py-4">
|
||||
<!--begin::Table-->
|
||||
<table class="table align-middle table-row-dashed fs-6 gy-5" id="data-table-category">
|
||||
<!--begin::Table head-->
|
||||
<thead>
|
||||
<!--begin::Table row-->
|
||||
<tr class="text-start text-muted fw-bold fs-7 text-uppercase gs-0">
|
||||
<th class="min-w-125px">Pic</th>
|
||||
<th class="min-w-125px">Name</th>
|
||||
<th class="min-w-125px">Name (EN)</th>
|
||||
<th class="min-w-125px">Created</th>
|
||||
<th class="min-w-125px">Active</th>
|
||||
<th class="text-end min-w-100px">Actions</th>
|
||||
</tr>
|
||||
<!--end::Table row-->
|
||||
</thead>
|
||||
<!--end::Table head-->
|
||||
<!--begin::Table body-->
|
||||
<tbody class="text-gray-600 fw-semibold">
|
||||
|
||||
@foreach ($itemView as $obj)
|
||||
<!--begin::Table row-->
|
||||
<tr>
|
||||
<td class="d-flex align-items-center">
|
||||
<div class="symbol symbol-100px symbol-2by3 me-4">
|
||||
@if ($obj->image_url && $obj->image_name)
|
||||
<a class="show-image-preview d-block overlay"
|
||||
href="{{ url($obj->image_url . '/original/' . $obj->image_name) }}">
|
||||
<div class="symbol-label"
|
||||
style="background-image: url('{{ url($obj->image_url . '/thumbnail/' . $obj->image_name) }}')">
|
||||
</div>
|
||||
</a>
|
||||
@else
|
||||
<div class="symbol-label"
|
||||
style="background-image: url('{{ url('assets/media/avatars/blank.png') }}')">
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
</td>
|
||||
|
||||
<td>
|
||||
{{ $obj->name }}
|
||||
</td>
|
||||
|
||||
<td>
|
||||
{{ $obj->name_en }}
|
||||
</td>
|
||||
|
||||
<td class="">{{ date('d M, Y', strtotime($obj->created_at)) }}</td>
|
||||
|
||||
|
||||
<td class="">
|
||||
@if ($obj->active == 1)
|
||||
<span class="badge py-3 px-4 fs-7 badge-light-success">Active</span>
|
||||
@else
|
||||
<span class="badge py-3 px-4 fs-7 badge-light-danger">Inactive</span>
|
||||
@endif
|
||||
</td>
|
||||
|
||||
|
||||
<td class="min-w-100px text-end">
|
||||
|
||||
{{-- Edit --}}
|
||||
<a href="{{ url('category/edit/' . $obj->id) }}"
|
||||
class="btn btn-icon btn-bg-light btn-active-color-primary btn-sm me-1">
|
||||
<span class="svg-icon svg-icon-3">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24"
|
||||
fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path opacity="0.3"
|
||||
d="M21.4 8.35303L19.241 10.511L13.485 4.755L15.643 2.59595C16.0248 2.21423 16.5426 1.99988 17.0825 1.99988C17.6224 1.99988 18.1402 2.21423 18.522 2.59595L21.4 5.474C21.7817 5.85581 21.9962 6.37355 21.9962 6.91345C21.9962 7.45335 21.7817 7.97122 21.4 8.35303ZM3.68699 21.932L9.88699 19.865L4.13099 14.109L2.06399 20.309C1.98815 20.5354 1.97703 20.7787 2.03189 21.0111C2.08674 21.2436 2.2054 21.4561 2.37449 21.6248C2.54359 21.7934 2.75641 21.9115 2.989 21.9658C3.22158 22.0201 3.4647 22.0084 3.69099 21.932H3.68699Z"
|
||||
fill="currentColor" />
|
||||
<path
|
||||
d="M5.574 21.3L3.692 21.928C3.46591 22.0032 3.22334 22.0141 2.99144 21.9594C2.75954 21.9046 2.54744 21.7864 2.3789 21.6179C2.21036 21.4495 2.09202 21.2375 2.03711 21.0056C1.9822 20.7737 1.99289 20.5312 2.06799 20.3051L2.696 18.422L5.574 21.3ZM4.13499 14.105L9.891 19.861L19.245 10.507L13.489 4.75098L4.13499 14.105Z"
|
||||
fill="currentColor" />
|
||||
</svg>
|
||||
</span>
|
||||
</a>
|
||||
|
||||
{{-- Delete --}}
|
||||
@if ($obj->active == 1)
|
||||
<a href="#" data-id="{{ $obj->id }}"
|
||||
class="btn btn-icon btn-bg-light btn-active-color-primary btn-sm delete-item">
|
||||
<span class="svg-icon svg-icon-3">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24"
|
||||
fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M5 9C5 8.44772 5.44772 8 6 8H18C18.5523 8 19 8.44772 19 9V18C19 19.6569 17.6569 21 16 21H8C6.34315 21 5 19.6569 5 18V9Z"
|
||||
fill="currentColor" />
|
||||
<path opacity="0.5"
|
||||
d="M5 5C5 4.44772 5.44772 4 6 4H18C18.5523 4 19 4.44772 19 5V5C19 5.55228 18.5523 6 18 6H6C5.44772 6 5 5.55228 5 5V5Z"
|
||||
fill="currentColor" />
|
||||
<path opacity="0.5"
|
||||
d="M9 4C9 3.44772 9.44772 3 10 3H14C14.5523 3 15 3.44772 15 4V4H9V4Z"
|
||||
fill="currentColor" />
|
||||
</svg>
|
||||
</span>
|
||||
</a>
|
||||
@endif
|
||||
</td>
|
||||
|
||||
|
||||
</tr>
|
||||
@endforeach
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@stop
|
||||
|
||||
|
||||
@section('script')
|
||||
|
||||
<script type="text/javascript">
|
||||
var datatable;
|
||||
datatable = $("#data-table-category").DataTable({
|
||||
"info": false,
|
||||
"order": [],
|
||||
"pageLength": 25,
|
||||
lengthMenu: [
|
||||
[10, 25, 50, 100, 500, 1000],
|
||||
[10, 25, 50, 100, 500, 1000]
|
||||
]
|
||||
});
|
||||
|
||||
// Filter by search
|
||||
const filterSearch = document.querySelector('[table-filter="search"]');
|
||||
filterSearch.addEventListener('keyup', function(e) {
|
||||
datatable.search(e.target.value).draw();
|
||||
});
|
||||
|
||||
// filter by status
|
||||
const filterStatus = document.querySelector('[table-filter="status"]');
|
||||
$(filterStatus).on('change', e => {
|
||||
let value = e.target.value;
|
||||
if (value === 'all') {
|
||||
value = '';
|
||||
}
|
||||
datatable.column(4).search(value).draw();
|
||||
});
|
||||
|
||||
|
||||
// Remove
|
||||
$(document).on('click', '.delete-item', function() {
|
||||
swal.fire({
|
||||
allowOutsideClick: false,
|
||||
text: "Are you sure you would like to Delete?",
|
||||
icon: "warning",
|
||||
buttonsStyling: false,
|
||||
showDenyButton: true,
|
||||
confirmButtonText: "Yes",
|
||||
denyButtonText: 'No',
|
||||
customClass: {
|
||||
confirmButton: "btn btn-primary",
|
||||
denyButton: "btn btn-light-danger"
|
||||
}
|
||||
}).then((result) => {
|
||||
if (result.isConfirmed) {
|
||||
|
||||
alertLoading("Loading")
|
||||
|
||||
// set up ajax
|
||||
initAjaxSetupToken();
|
||||
|
||||
const ajaxProp = {
|
||||
url: "{{ url('category/delete') }}",
|
||||
type: 'POST',
|
||||
data: {
|
||||
item_id: $(this).data('id')
|
||||
},
|
||||
};
|
||||
|
||||
$.ajax(ajaxProp).done(function(res) {
|
||||
if (res.status) {
|
||||
const url = "{{ url('category') }}";
|
||||
alertSuccessWithUrl('Notice', "Delete success", url);
|
||||
hideLoading();
|
||||
} else {
|
||||
alertFail('Notice', res.message ?? "Unsuccessfully");
|
||||
hideLoading();
|
||||
}
|
||||
}).fail(function(xhr, status, error) {
|
||||
logAjaxError(xhr, status, error);
|
||||
alertFail('Notice', error.message ?? "Unsuccessfully");
|
||||
hideLoading();
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
@endsection
|
||||
@@ -0,0 +1,316 @@
|
||||
@extends('layouts/backendTemplate')
|
||||
|
||||
@section('content')
|
||||
<div class="app-main flex-column flex-row-fluid" id="kt_app_main">
|
||||
|
||||
<div class="d-flex flex-column flex-column-fluid">
|
||||
|
||||
<div id="kt_app_toolbar" class="app-toolbar py-3 py-lg-6">
|
||||
|
||||
<div id="kt_app_toolbar_container" class="app-container container-xxl d-flex flex-stack">
|
||||
|
||||
<div class="page-title d-flex flex-column justify-content-center flex-wrap me-3">
|
||||
|
||||
<h1 class="page-heading d-flex text-dark fw-bold fs-3 flex-column justify-content-center my-3">
|
||||
Dashboard
|
||||
</h1>
|
||||
|
||||
<ul class="breadcrumb breadcrumb-separatorless fw-semibold fs-7 my-0 pt-1">
|
||||
|
||||
<li class="breadcrumb-item text-muted">
|
||||
<a href="{{ url('') }}" class="text-muted text-hover-primary">
|
||||
Dashboard
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<div id="kt_app_content" class="app-content flex-column-fluid">
|
||||
<!--begin::Content container-->
|
||||
<div id="kt_app_content_container" class="app-container container-xxl">
|
||||
<!--begin::Row-->
|
||||
|
||||
@if ($itemView['sub_category_no_where_else'])
|
||||
<h1>CHIANG MAI AND NOWHERE ELSE</h1>
|
||||
<div class="row gy-5 g-xl-10">
|
||||
@foreach ($itemView['sub_category_no_where_else'] as $item)
|
||||
<div class="col-sm-6 col-xl-2 mb-xl-10">
|
||||
<div class="card h-lg-100">
|
||||
<div class="card-body d-flex justify-content-between align-items-start flex-column">
|
||||
|
||||
<div class="m-0">
|
||||
<span class="svg-icon svg-icon-2hx svg-icon-gray-600">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<path opacity="0.3"
|
||||
d="M14 3V21H10V3C10 2.4 10.4 2 11 2H13C13.6 2 14 2.4 14 3ZM7 14H5C4.4 14 4 14.4 4 15V21H8V15C8 14.4 7.6 14 7 14Z"
|
||||
fill="currentColor"></path>
|
||||
<path
|
||||
d="M21 20H20V8C20 7.4 19.6 7 19 7H17C16.4 7 16 7.4 16 8V20H3C2.4 20 2 20.4 2 21C2 21.6 2.4 22 3 22H21C21.6 22 22 21.6 22 21C22 20.4 21.6 20 21 20Z"
|
||||
fill="currentColor"></path>
|
||||
</svg>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="d-flex flex-column my-7">
|
||||
|
||||
<span class="fw-semibold fs-3x text-gray-800 lh-1 ls-n2">
|
||||
{{ number_format($item['article_count'], 0) }}
|
||||
</span>
|
||||
|
||||
<div class="m-0">
|
||||
<span class="fw-semibold fs-6 text-gray-400">
|
||||
{{ $item['name'] ?? '-' }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
@endif
|
||||
|
||||
|
||||
@if ($itemView['sub_category_where_else'])
|
||||
<h1>WHERE ELSE</h1>
|
||||
<div class="row gy-5 g-xl-10">
|
||||
@foreach ($itemView['sub_category_where_else'] as $item)
|
||||
<div class="col-sm-6 col-xl-2 mb-xl-10">
|
||||
<div class="card h-lg-100">
|
||||
<div class="card-body d-flex justify-content-between align-items-start flex-column">
|
||||
|
||||
<div class="m-0">
|
||||
<span class="svg-icon svg-icon-2hx svg-icon-gray-600">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<path opacity="0.3"
|
||||
d="M14 3V21H10V3C10 2.4 10.4 2 11 2H13C13.6 2 14 2.4 14 3ZM7 14H5C4.4 14 4 14.4 4 15V21H8V15C8 14.4 7.6 14 7 14Z"
|
||||
fill="currentColor"></path>
|
||||
<path
|
||||
d="M21 20H20V8C20 7.4 19.6 7 19 7H17C16.4 7 16 7.4 16 8V20H3C2.4 20 2 20.4 2 21C2 21.6 2.4 22 3 22H21C21.6 22 22 21.6 22 21C22 20.4 21.6 20 21 20Z"
|
||||
fill="currentColor"></path>
|
||||
</svg>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="d-flex flex-column my-7">
|
||||
|
||||
<span class="fw-semibold fs-3x text-gray-800 lh-1 ls-n2">
|
||||
{{ number_format($item['article_count'], 0) }}
|
||||
</span>
|
||||
|
||||
<div class="m-0">
|
||||
<span class="fw-semibold fs-6 text-gray-400">
|
||||
{{ $item['name'] ?? '-' }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
@endif
|
||||
|
||||
|
||||
<h1>FILES</h1>
|
||||
<div class="row gy-5 g-xl-10">
|
||||
|
||||
<div class="col-sm-6 col-xl-2 mb-xl-10">
|
||||
<!--begin::Card widget 2-->
|
||||
<div class="card h-lg-100">
|
||||
<!--begin::Body-->
|
||||
<div class="card-body d-flex justify-content-between align-items-start flex-column">
|
||||
<!--begin::Icon-->
|
||||
<div class="m-0">
|
||||
<!--begin::Svg Icon | path: icons/duotune/graphs/gra001.svg-->
|
||||
<span class="svg-icon svg-icon-2hx svg-icon-gray-600">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<path opacity="0.3"
|
||||
d="M14 3V21H10V3C10 2.4 10.4 2 11 2H13C13.6 2 14 2.4 14 3ZM7 14H5C4.4 14 4 14.4 4 15V21H8V15C8 14.4 7.6 14 7 14Z"
|
||||
fill="currentColor"></path>
|
||||
<path
|
||||
d="M21 20H20V8C20 7.4 19.6 7 19 7H17C16.4 7 16 7.4 16 8V20H3C2.4 20 2 20.4 2 21C2 21.6 2.4 22 3 22H21C21.6 22 22 21.6 22 21C22 20.4 21.6 20 21 20Z"
|
||||
fill="currentColor"></path>
|
||||
</svg>
|
||||
</span>
|
||||
<!--end::Svg Icon-->
|
||||
</div>
|
||||
<!--end::Icon-->
|
||||
<!--begin::Section-->
|
||||
<div class="d-flex flex-column my-7">
|
||||
<!--begin::Number-->
|
||||
<span class="fw-semibold fs-3x text-gray-800 lh-1 ls-n2">
|
||||
{{ number_format($countVideoView, 0) }}
|
||||
</span>
|
||||
<!--end::Number-->
|
||||
<!--begin::Follower-->
|
||||
<div class="m-0">
|
||||
<span class="fw-semibold fs-6 text-gray-400">Video</span>
|
||||
</div>
|
||||
<!--end::Follower-->
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<!--end::Body-->
|
||||
</div>
|
||||
<!--end::Card widget 2-->
|
||||
</div>
|
||||
|
||||
<div class="col-sm-6 col-xl-2 mb-xl-10">
|
||||
<!--begin::Card widget 2-->
|
||||
<div class="card h-lg-100">
|
||||
<!--begin::Body-->
|
||||
<div class="card-body d-flex justify-content-between align-items-start flex-column">
|
||||
<!--begin::Icon-->
|
||||
<div class="m-0">
|
||||
<!--begin::Svg Icon | path: icons/duotune/graphs/gra001.svg-->
|
||||
<span class="svg-icon svg-icon-2hx svg-icon-gray-600">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<path opacity="0.3"
|
||||
d="M14 3V21H10V3C10 2.4 10.4 2 11 2H13C13.6 2 14 2.4 14 3ZM7 14H5C4.4 14 4 14.4 4 15V21H8V15C8 14.4 7.6 14 7 14Z"
|
||||
fill="currentColor"></path>
|
||||
<path
|
||||
d="M21 20H20V8C20 7.4 19.6 7 19 7H17C16.4 7 16 7.4 16 8V20H3C2.4 20 2 20.4 2 21C2 21.6 2.4 22 3 22H21C21.6 22 22 21.6 22 21C22 20.4 21.6 20 21 20Z"
|
||||
fill="currentColor"></path>
|
||||
</svg>
|
||||
</span>
|
||||
<!--end::Svg Icon-->
|
||||
</div>
|
||||
<!--end::Icon-->
|
||||
<!--begin::Section-->
|
||||
<div class="d-flex flex-column my-7">
|
||||
<!--begin::Number-->
|
||||
<span class="fw-semibold fs-3x text-gray-800 lh-1 ls-n2">
|
||||
{{ number_format($countSoundView, 0) }}
|
||||
</span>
|
||||
<!--end::Number-->
|
||||
<!--begin::Follower-->
|
||||
<div class="m-0">
|
||||
<span class="fw-semibold fs-6 text-gray-400">Sound</span>
|
||||
</div>
|
||||
<!--end::Follower-->
|
||||
</div>
|
||||
<!--end::Section-->
|
||||
|
||||
</div>
|
||||
<!--end::Body-->
|
||||
</div>
|
||||
<!--end::Card widget 2-->
|
||||
</div>
|
||||
|
||||
<div class="col-sm-6 col-xl-2 mb-xl-10">
|
||||
<!--begin::Card widget 2-->
|
||||
<div class="card h-lg-100">
|
||||
<!--begin::Body-->
|
||||
<div class="card-body d-flex justify-content-between align-items-start flex-column">
|
||||
<!--begin::Icon-->
|
||||
<div class="m-0">
|
||||
<!--begin::Svg Icon | path: icons/duotune/graphs/gra001.svg-->
|
||||
<span class="svg-icon svg-icon-2hx svg-icon-gray-600">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<path opacity="0.3"
|
||||
d="M14 3V21H10V3C10 2.4 10.4 2 11 2H13C13.6 2 14 2.4 14 3ZM7 14H5C4.4 14 4 14.4 4 15V21H8V15C8 14.4 7.6 14 7 14Z"
|
||||
fill="currentColor"></path>
|
||||
<path
|
||||
d="M21 20H20V8C20 7.4 19.6 7 19 7H17C16.4 7 16 7.4 16 8V20H3C2.4 20 2 20.4 2 21C2 21.6 2.4 22 3 22H21C21.6 22 22 21.6 22 21C22 20.4 21.6 20 21 20Z"
|
||||
fill="currentColor"></path>
|
||||
</svg>
|
||||
</span>
|
||||
<!--end::Svg Icon-->
|
||||
</div>
|
||||
<!--end::Icon-->
|
||||
<!--begin::Section-->
|
||||
<div class="d-flex flex-column my-7">
|
||||
<!--begin::Number-->
|
||||
<span class="fw-semibold fs-3x text-gray-800 lh-1 ls-n2">
|
||||
{{ number_format($countImageView, 0) }}
|
||||
</span>
|
||||
<!--end::Number-->
|
||||
<!--begin::Follower-->
|
||||
<div class="m-0">
|
||||
<span class="fw-semibold fs-6 text-gray-400">Images</span>
|
||||
</div>
|
||||
<!--end::Follower-->
|
||||
</div>
|
||||
<!--end::Section-->
|
||||
|
||||
</div>
|
||||
<!--end::Body-->
|
||||
</div>
|
||||
<!--end::Card widget 2-->
|
||||
</div>
|
||||
|
||||
|
||||
<div class="col-sm-6 col-xl-2 mb-xl-10">
|
||||
<!--begin::Card widget 2-->
|
||||
<div class="card h-lg-100">
|
||||
<!--begin::Body-->
|
||||
<div class="card-body d-flex justify-content-between align-items-start flex-column">
|
||||
<!--begin::Icon-->
|
||||
<div class="m-0">
|
||||
<!--begin::Svg Icon | path: icons/duotune/graphs/gra001.svg-->
|
||||
<span class="svg-icon svg-icon-2hx svg-icon-gray-600">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<path opacity="0.3"
|
||||
d="M14 3V21H10V3C10 2.4 10.4 2 11 2H13C13.6 2 14 2.4 14 3ZM7 14H5C4.4 14 4 14.4 4 15V21H8V15C8 14.4 7.6 14 7 14Z"
|
||||
fill="currentColor"></path>
|
||||
<path
|
||||
d="M21 20H20V8C20 7.4 19.6 7 19 7H17C16.4 7 16 7.4 16 8V20H3C2.4 20 2 20.4 2 21C2 21.6 2.4 22 3 22H21C21.6 22 22 21.6 22 21C22 20.4 21.6 20 21 20Z"
|
||||
fill="currentColor"></path>
|
||||
</svg>
|
||||
</span>
|
||||
<!--end::Svg Icon-->
|
||||
</div>
|
||||
<!--end::Icon-->
|
||||
<!--begin::Section-->
|
||||
<div class="d-flex flex-column my-7">
|
||||
<!--begin::Number-->
|
||||
<span class="fw-semibold fs-3x text-gray-800 lh-1 ls-n2">
|
||||
{{ number_format($countDocumentView, 0) }}
|
||||
</span>
|
||||
<!--end::Number-->
|
||||
<!--begin::Follower-->
|
||||
<div class="m-0">
|
||||
<span class="fw-semibold fs-6 text-gray-400">Documents</span>
|
||||
</div>
|
||||
<!--end::Follower-->
|
||||
</div>
|
||||
<!--end::Section-->
|
||||
|
||||
</div>
|
||||
<!--end::Body-->
|
||||
</div>
|
||||
<!--end::Card widget 2-->
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<!--end::Content container-->
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
|
||||
|
||||
@section('script')
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function() {});
|
||||
</script>
|
||||
@endsection
|
||||
@@ -0,0 +1,366 @@
|
||||
@extends('layouts.backendTemplate')
|
||||
|
||||
@section('content')
|
||||
|
||||
<style>
|
||||
#progressBar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.progress-bar {
|
||||
width: 100%;
|
||||
height: 10px;
|
||||
border-radius: 5px;
|
||||
margin-top: 10px;
|
||||
appearance: none;
|
||||
}
|
||||
|
||||
.progress-bar::-webkit-progress-value {
|
||||
background-color: #4CAF50;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.progress-text {
|
||||
margin-top: 10px;
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
}
|
||||
</style>
|
||||
|
||||
<!--begin::Main-->
|
||||
<div class="app-main flex-column flex-row-fluid" id="kt_app_main">
|
||||
|
||||
<div class="d-flex flex-column flex-column-fluid">
|
||||
|
||||
|
||||
@include('uc.admin.breadcrumb', [
|
||||
'title' => 'Document Add',
|
||||
'pageName' => 'Add',
|
||||
'pageParent' => 'Document Management',
|
||||
'pageParentLink' => url('document'),
|
||||
])
|
||||
|
||||
<div id="kt_app_content" class="app-content flex-column-fluid">
|
||||
<div id="kt_app_content_container" class="app-container container-xxl">
|
||||
|
||||
|
||||
|
||||
<form id="frmAdd" class="form d-flex flex-column flex-lg-row" method="post"
|
||||
enctype="multipart/form-data">
|
||||
|
||||
<input type="hidden" name="_method" value="POST">
|
||||
<input type="hidden" name="_token" value="{{ csrf_token() }}">
|
||||
|
||||
|
||||
<div class="d-flex flex-column flex-row-fluid gap-7 gap-lg-10">
|
||||
|
||||
<div class="card card-flush py-4">
|
||||
|
||||
|
||||
@if (Session::has('messageSuccess'))
|
||||
<div class="card-body">
|
||||
@include('uc/messageSuccess')
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@if (Session::has('messageFail'))
|
||||
<div class="card-body">
|
||||
@include('uc/messageFail')
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<div class="card-header">
|
||||
<div class="card-title">
|
||||
<h2>Overview</h2>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card-body pt-0">
|
||||
|
||||
<div class="mb-10">
|
||||
<label class="form-label required">File Document</label>
|
||||
|
||||
<input class="fileInput file-input" type="file" id="fileInput" name="fileInput"
|
||||
accept=".pdf, .xls, .doc, .docx, .pptx, .csv, .txt" multiple>
|
||||
|
||||
<progress id="progressBar" class="progress-bar" value="0"
|
||||
max="100"></progress>
|
||||
<div id="progressText" class="progress-text">0%</div>
|
||||
|
||||
<div class="text-muted fs-7">Allowed Types .pdf, .xls, .doc, .docx, .pptx, .csv,
|
||||
.txt</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="d-flex justify-content-end">
|
||||
|
||||
<a href="{{ url('document') }}" id="kt_ecommerce_add_product_cancel"
|
||||
class="btn btn-light me-5">Cancel</a>
|
||||
|
||||
<button type="button" id="btn_submit" class="btn btn-primary">
|
||||
<span class="indicator-label">Save</span>
|
||||
</button>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</form>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
@stop
|
||||
|
||||
|
||||
@section('script')
|
||||
|
||||
<script>
|
||||
const baseApiUrl = "{{ env('API_URL') }}";
|
||||
|
||||
|
||||
$(document).on("click", "#btn_submit", async function(e) {
|
||||
|
||||
e.preventDefault();
|
||||
|
||||
alertLoading("Loading")
|
||||
|
||||
await uploadFile();
|
||||
|
||||
});
|
||||
|
||||
|
||||
// Step 1
|
||||
async function uploadFile() {
|
||||
const fileInput = document.getElementById("fileInput");
|
||||
const progressBar = document.getElementById("progressBar");
|
||||
const progressText = document.getElementById("progressText");
|
||||
|
||||
if (!fileInput || fileInput.files.length === 0) {
|
||||
alertFail("Notice", "Please select one or more files.");
|
||||
hideLoading();
|
||||
return;
|
||||
}
|
||||
|
||||
const files = Array.from(fileInput.files); // Get all selected files
|
||||
$("#progressBar").show();
|
||||
|
||||
let totalSize = files.reduce((sum, file) => sum + file.size, 0);
|
||||
let totalUploadedSize = 0;
|
||||
|
||||
// Upload all files sequentially
|
||||
for (const file of files) {
|
||||
await uploadSingleFile(file, progressBar, progressText, totalSize, (fileUploadedSize) => {
|
||||
totalUploadedSize += fileUploadedSize;
|
||||
const overallPercent = Math.floor((totalUploadedSize / totalSize) * 100);
|
||||
animateProgress(progressBar, progressText, overallPercent);
|
||||
});
|
||||
}
|
||||
const folderId = "{{ $folderIdView }}";
|
||||
let redirectUrl = "{{ url('document') }}"
|
||||
if (folderId) {
|
||||
redirectUrl = `${redirectUrl}/folder/${folderId}`;
|
||||
}
|
||||
alertSuccessWithUrl("Notice", "All files uploaded successfully", redirectUrl);
|
||||
}
|
||||
|
||||
async function uploadSingleFile(file, progressBar, progressText, totalSize, updateOverallProgress) {
|
||||
const uploadId = await initiateMultipartUpload(file.name);
|
||||
const partSize = 500 * 1024 * 1024; // 500 MB per part
|
||||
const parts = [];
|
||||
let uploadedSize = 0;
|
||||
|
||||
const uploadPromises = Array.from({
|
||||
length: Math.ceil(file.size / partSize)
|
||||
},
|
||||
(_, index) => {
|
||||
const partNumber = index + 1;
|
||||
const chunk = file.slice(index * partSize, (index + 1) * partSize);
|
||||
|
||||
return (async () => {
|
||||
const presignedUrl = await getPresignedUrl(uploadId, partNumber, file.name);
|
||||
const etag = await uploadPartToS3(presignedUrl, chunk);
|
||||
|
||||
parts.push({
|
||||
PartNumber: partNumber,
|
||||
ETag: etag
|
||||
});
|
||||
|
||||
uploadedSize += chunk.size;
|
||||
updateOverallProgress(chunk.size); // Update the overall progress
|
||||
})();
|
||||
}
|
||||
);
|
||||
|
||||
await Promise.all(uploadPromises);
|
||||
await completeMultipartUpload(uploadId, parts, file.name);
|
||||
await saveFileNameToDB(file.name);
|
||||
}
|
||||
|
||||
// Step 2
|
||||
async function initiateMultipartUpload(fileName) {
|
||||
const urlUploadImage = `${baseApiUrl}/initiate-multipart-upload`;
|
||||
const response = await fetch(
|
||||
urlUploadImage, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
fileName
|
||||
}),
|
||||
}
|
||||
);
|
||||
|
||||
const {
|
||||
uploadId
|
||||
} = await response.json();
|
||||
|
||||
return uploadId;
|
||||
}
|
||||
|
||||
// Step 3
|
||||
async function getPresignedUrl(uploadId, partNumber, fileName) {
|
||||
|
||||
const urlPresigned = `${baseApiUrl}/get-presigned-url`
|
||||
const response = await fetch(
|
||||
urlPresigned, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
uploadId,
|
||||
partNumber,
|
||||
fileName
|
||||
}),
|
||||
}
|
||||
);
|
||||
const {
|
||||
url
|
||||
} = await response.json();
|
||||
return url;
|
||||
}
|
||||
|
||||
// Step 4
|
||||
async function uploadPartToS3(url, chunk) {
|
||||
const response = await fetch(url, {
|
||||
method: "PUT",
|
||||
headers: {
|
||||
"Content-Type": "application/octet-stream",
|
||||
},
|
||||
body: chunk,
|
||||
});
|
||||
if (!response.ok) {
|
||||
alertFail("Notice", "Failed to upload part")
|
||||
hideLoading();
|
||||
//throw new Error("Failed to upload part");
|
||||
}
|
||||
|
||||
const etag = `${response.headers.get("ETag")}`.replace(/"/g, "");
|
||||
|
||||
if (!etag) {
|
||||
throw new Error("Failed to retrieve ETag from the response.");
|
||||
}
|
||||
|
||||
return etag;
|
||||
}
|
||||
|
||||
// Step 5
|
||||
async function completeMultipartUpload(uploadId, parts, fileName) {
|
||||
const urlUploadComplete = `${baseApiUrl}/complete-multipart-upload`;
|
||||
const response = await fetch(urlUploadComplete, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
uploadId,
|
||||
parts,
|
||||
fileName
|
||||
}),
|
||||
});
|
||||
if (response.ok) {
|
||||
//window.location.href = "{{ url('image') }}";
|
||||
} else {
|
||||
alertFail("Notice", "Failed to upload part");
|
||||
hideLoading();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Smoothly animates the progress bar and percentage text.
|
||||
*/
|
||||
async function animateProgress(progressBar, progressText, targetPercent) {
|
||||
const currentPercent = parseInt(progressBar.value) || 0;
|
||||
// Increment the percentage smoothly
|
||||
for (let percent = currentPercent + 1; percent <= targetPercent; percent++) {
|
||||
progressBar.value = percent;
|
||||
progressText.textContent = `${percent}%`;
|
||||
|
||||
// Add a small delay to make the increment visible (10ms delay)
|
||||
await new Promise((resolve) => setTimeout(resolve, 10));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends the uploaded file name to the server using AJAX.
|
||||
*/
|
||||
function saveFileNameToDB(fileName) {
|
||||
initAjaxSetupToken();
|
||||
|
||||
const folderId = "{{ $folderIdView }}";
|
||||
const url = "{{ url('') }}";
|
||||
|
||||
return $.ajax({
|
||||
url: `${url}/document/insert`,
|
||||
type: 'POST',
|
||||
contentType: 'application/json',
|
||||
data: JSON.stringify({
|
||||
fileName,
|
||||
folderId
|
||||
}),
|
||||
success: (response) => {
|
||||
console.log('File name saved:', response);
|
||||
},
|
||||
error: (err) => {
|
||||
console.error('Error saving file name:', err);
|
||||
alertFail("Notice", "There was an error saving the file name.");
|
||||
hideLoading();
|
||||
return;
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<script>
|
||||
$('.file-input').fileuploader({
|
||||
extensions: ['pdf', 'xls', 'doc', 'docx', 'pptx', 'csv', 'txt'],
|
||||
limit: null,
|
||||
fileMaxSize: null,
|
||||
changeInput: '<div class="fileuploader-input">' +
|
||||
'<div class="fileuploader-input-inner">' +
|
||||
'<p><i class="fileuploader-icon-main"></i></p>' +
|
||||
'<h6>Drag and drop files here</h6>' +
|
||||
'<p>or</p>' +
|
||||
'<br>' +
|
||||
'<button type="button" class="fileuploader-input-button"><span>${captions.button}</span></button>' +
|
||||
'</div>' +
|
||||
'</div>',
|
||||
theme: 'dragdrop',
|
||||
});
|
||||
</script>
|
||||
|
||||
@endsection
|
||||
@@ -0,0 +1,95 @@
|
||||
@extends('layouts.backendTemplate')
|
||||
|
||||
@section('content')
|
||||
|
||||
<!--begin::Main-->
|
||||
<div class="app-main flex-column flex-row-fluid" id="kt_app_main">
|
||||
|
||||
<div class="d-flex flex-column flex-column-fluid">
|
||||
|
||||
|
||||
@include('uc.admin.breadcrumb', [
|
||||
'title' => 'Document Create Folder',
|
||||
'pageName' => 'Create folder',
|
||||
'pageParent' => 'Document Management',
|
||||
'pageParentLink' => url('document'),
|
||||
])
|
||||
|
||||
<div id="kt_app_content" class="app-content flex-column-fluid">
|
||||
<div id="kt_app_content_container" class="app-container container-xxl">
|
||||
|
||||
<form id="frmAdd" action="{{ url('document/insert-folder') }}"
|
||||
class="form d-flex flex-column flex-lg-row" method="post" enctype="multipart/form-data">
|
||||
|
||||
<input type="hidden" name="_method" value="POST">
|
||||
<input type="hidden" name="_token" value="{{ csrf_token() }}">
|
||||
|
||||
|
||||
<div class="d-flex flex-column flex-row-fluid gap-7 gap-lg-10">
|
||||
|
||||
<div class="card card-flush py-4">
|
||||
|
||||
|
||||
@if (Session::has('messageSuccess'))
|
||||
<div class="card-body">
|
||||
@include('uc/messageSuccess')
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@if (Session::has('messageFail'))
|
||||
<div class="card-body">
|
||||
@include('uc/messageFail')
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<div class="card-header">
|
||||
<div class="card-title">
|
||||
<h2>Overview</h2>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card-body pt-0">
|
||||
|
||||
<div class="mb-10 fv-row">
|
||||
<label class="required form-label">Name</label>
|
||||
<input type="text" name="name" class="form-control mb-2 col-6"
|
||||
value="{{ old('name') }}" />
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="d-flex justify-content-end">
|
||||
|
||||
<a href="{{ url('document') }}" id="kt_ecommerce_add_product_cancel"
|
||||
class="btn btn-light me-5">Cancel</a>
|
||||
|
||||
<button type="submit" class="btn btn-primary">
|
||||
<span class="indicator-label">Save</span>
|
||||
</button>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</form>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
@stop
|
||||
|
||||
|
||||
@section('script')
|
||||
|
||||
<script></script>
|
||||
|
||||
@endsection
|
||||
@@ -0,0 +1,96 @@
|
||||
@extends('layouts.backendTemplate')
|
||||
|
||||
@section('content')
|
||||
|
||||
<!--begin::Main-->
|
||||
<div class="app-main flex-column flex-row-fluid" id="kt_app_main">
|
||||
|
||||
<div class="d-flex flex-column flex-column-fluid">
|
||||
|
||||
|
||||
@include('uc.admin.breadcrumb', [
|
||||
'title' => 'Document Edit Folder',
|
||||
'pageName' => 'Edit folder',
|
||||
'pageParent' => 'Document Management',
|
||||
'pageParentLink' => url('document'),
|
||||
])
|
||||
|
||||
<div id="kt_app_content" class="app-content flex-column-fluid">
|
||||
<div id="kt_app_content_container" class="app-container container-xxl">
|
||||
|
||||
<form id="frmAdd" action="{{ url('document/update-folder') }}"
|
||||
class="form d-flex flex-column flex-lg-row" method="post" enctype="multipart/form-data">
|
||||
|
||||
<input type="hidden" name="id" value="{{ $idView }}">
|
||||
<input type="hidden" name="_method" value="POST">
|
||||
<input type="hidden" name="_token" value="{{ csrf_token() }}">
|
||||
|
||||
|
||||
<div class="d-flex flex-column flex-row-fluid gap-7 gap-lg-10">
|
||||
|
||||
<div class="card card-flush py-4">
|
||||
|
||||
|
||||
@if (Session::has('messageSuccess'))
|
||||
<div class="card-body">
|
||||
@include('uc/messageSuccess')
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@if (Session::has('messageFail'))
|
||||
<div class="card-body">
|
||||
@include('uc/messageFail')
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<div class="card-header">
|
||||
<div class="card-title">
|
||||
<h2>Overview</h2>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card-body pt-0">
|
||||
|
||||
<div class="mb-10 fv-row">
|
||||
<label class="required form-label">Name</label>
|
||||
<input type="text" name="name" class="form-control mb-2 col-6"
|
||||
value="{{ $itemView->name }}" />
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="d-flex justify-content-end">
|
||||
|
||||
<a href="{{ url('document') }}" id="kt_ecommerce_add_product_cancel"
|
||||
class="btn btn-light me-5">Cancel</a>
|
||||
|
||||
<button type="submit" class="btn btn-primary">
|
||||
<span class="indicator-label">Save</span>
|
||||
</button>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</form>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
@stop
|
||||
|
||||
|
||||
@section('script')
|
||||
|
||||
<script></script>
|
||||
|
||||
@endsection
|
||||
@@ -0,0 +1,324 @@
|
||||
@extends('layouts.backendTemplate')
|
||||
|
||||
@section('content')
|
||||
|
||||
<style>
|
||||
.link-container {
|
||||
display: flex;
|
||||
/* Use flexbox for alignment */
|
||||
align-items: center;
|
||||
/* Center items vertically */
|
||||
justify-content: space-between;
|
||||
/* Space between the URL and button */
|
||||
}
|
||||
|
||||
.file-url {
|
||||
flex: 1;
|
||||
/* Allow the URL to take up available space */
|
||||
color: #007bff;
|
||||
/* Link color */
|
||||
text-decoration: none;
|
||||
/* Remove underline */
|
||||
overflow: hidden;
|
||||
/* Hide overflow */
|
||||
white-space: nowrap;
|
||||
/* Prevent text wrapping */
|
||||
text-overflow: ellipsis;
|
||||
/* Add ellipsis for overflow */
|
||||
margin-right: 10px;
|
||||
/* Space between text and button */
|
||||
}
|
||||
</style>
|
||||
|
||||
<!--begin::Main-->
|
||||
<div class="app-main flex-column flex-row-fluid" id="kt_app_main">
|
||||
|
||||
<div class="d-flex flex-column flex-column-fluid">
|
||||
|
||||
|
||||
@include('uc.breadcrumbList', [
|
||||
'title' => 'Document Management Folder ' . $folderView->name,
|
||||
'pageName' => 'Document Management',
|
||||
])
|
||||
|
||||
|
||||
<div id="kt_app_content" class="app-content flex-column-fluid">
|
||||
|
||||
<div id="kt_app_content_container" class="app-container container-xxl">
|
||||
|
||||
<div class="card">
|
||||
|
||||
@if (Session::has('messageSuccess'))
|
||||
<div class="card-body">
|
||||
@include('uc/messageSuccess')
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@if (Session::has('messageFail'))
|
||||
<div class="card-body">
|
||||
@include('uc/messageFail')
|
||||
</div>
|
||||
@endif
|
||||
|
||||
|
||||
<div class="card-header border-0 pt-6">
|
||||
<div class="d-flex align-items-center position-relative my-1">
|
||||
</div>
|
||||
|
||||
@if (Auth::user()->role != 2)
|
||||
<div class="card-toolbar">
|
||||
<div class="d-flex justify-content-end" data-kt-customer-table-toolbar="base">
|
||||
<a href="{{ url('document/add/' . $folderView->id) }}" class="btn btn-primary">Add
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<div class="card-header border-0 pt-5">
|
||||
|
||||
<div class="card-title">
|
||||
<div class="d-flex align-items-center position-relative my-1">
|
||||
<span class="svg-icon svg-icon-1 position-absolute ms-4">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<rect opacity="0.5" x="17.0365" y="15.1223" width="8.15546" height="2"
|
||||
rx="1" transform="rotate(45 17.0365 15.1223)" fill="currentColor">
|
||||
</rect>
|
||||
<path
|
||||
d="M11 19C6.55556 19 3 15.4444 3 11C3 6.55556 6.55556 3 11 3C15.4444 3 19 6.55556 19 11C19 15.4444 15.4444 19 11 19ZM11 5C7.53333 5 5 7.53333 5 11C5 14.4667 7.53333 17 11 17C14.4667 17 17 14.4667 17 11C17 7.53333 14.4667 5 11 5Z"
|
||||
fill="currentColor"></path>
|
||||
</svg>
|
||||
</span>
|
||||
|
||||
<input type="text" table-filter="search"
|
||||
class="form-control form-control-solid w-250px ps-15" placeholder="Search" />
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="card-body py-4">
|
||||
<!--begin::Table-->
|
||||
<table class="table align-middle table-row-dashed fs-6 gy-5" id="data-table">
|
||||
<!--begin::Table head-->
|
||||
<thead>
|
||||
<!--begin::Table row-->
|
||||
<tr class="text-start text-muted fw-bold fs-7 text-uppercase gs-0">
|
||||
<th class="min-w-125px">Name</th>
|
||||
<th class="min-w-125px">Created</th>
|
||||
<th class="text-end min-w-100px">Manage</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody class="text-gray-600 fw-semibold">
|
||||
|
||||
@foreach ($itemView as $obj)
|
||||
<tr>
|
||||
<td>
|
||||
<div class="d-flex align-items-center">
|
||||
<a href="#" class="text-gray-800 text-hover-primary">
|
||||
@if (isset($obj['name']) && Str::endsWith($obj['name'], ['.pdf']))
|
||||
<img alt="PDF Icon" class="w-30px me-3"
|
||||
src="{{ url('assets/media/svg/files/pdf.svg') }}">
|
||||
@elseif (isset($obj['name']) && Str::endsWith($obj['name'], ['.doc', '.docx']))
|
||||
<img alt="DOC Icon" class="w-30px me-3"
|
||||
src="{{ url('assets/media/svg/files/doc.svg') }}">
|
||||
@else
|
||||
<span class="svg-icon svg-icon-2x svg-icon-primary me-4">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24"
|
||||
fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path opacity="0.3"
|
||||
d="M19 22H5C4.4 22 4 21.6 4 21V3C4 2.4 4.4 2 5 2H14L20 8V21C20 21.6 19.6 22 19 22Z"
|
||||
fill="currentColor"></path>
|
||||
<path d="M15 8H20L14 2V7C14 7.6 14.4 8 15 8Z"
|
||||
fill="currentColor"></path>
|
||||
</svg>
|
||||
</span>
|
||||
@endif
|
||||
{{ $obj['name'] }}
|
||||
</a>
|
||||
|
||||
</div>
|
||||
</td>
|
||||
|
||||
|
||||
<td>
|
||||
{{ Carbon\Carbon::parse($obj['created_at'])->format('d, M Y') }}
|
||||
</td>
|
||||
|
||||
<td class="min-w-100px text-end">
|
||||
|
||||
{{-- Download --}}
|
||||
<a href="{{ env('R2_SCHEMA_URL') . $obj['name'] }}" target="_blank"
|
||||
class="btn btn-sm btn-icon btn-light btn-active-light-primary"
|
||||
type="button" data-bs-toggle="tooltip" aria-label="Coming soon"
|
||||
data-bs-original-title="Coming soon" data-kt-initialized="1">
|
||||
<i class="bi bi-download fs-3"></i>
|
||||
</a>
|
||||
|
||||
{{-- Copy --}}
|
||||
<button type="button" data-action="copy"
|
||||
data-url="{{ env('R2_SCHEMA_URL') . $obj['name'] }}"
|
||||
class="btn btn-sm btn-icon btn-light btn-active-light-primary copy-button">
|
||||
<span class="svg-icon svg-icon-2">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24"
|
||||
fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path opacity="0.5"
|
||||
d="M18 2H9C7.34315 2 6 3.34315 6 5H8C8 4.44772 8.44772 4 9 4H18C18.5523 4 19 4.44772 19 5V16C19 16.5523 18.5523 17 18 17V19C19.6569 19 21 17.6569 21 16V5C21 3.34315 19.6569 2 18 2Z"
|
||||
fill="currentColor"></path>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd"
|
||||
d="M14.7857 7.125H6.21429C5.62255 7.125 5.14286 7.6007 5.14286 8.1875V18.8125C5.14286 19.3993 5.62255 19.875 6.21429 19.875H14.7857C15.3774 19.875 15.8571 19.3993 15.8571 18.8125V8.1875C15.8571 7.6007 15.3774 7.125 14.7857 7.125ZM6.21429 5C4.43908 5 3 6.42709 3 8.1875V18.8125C3 20.5729 4.43909 22 6.21429 22H14.7857C16.5609 22 18 20.5729 18 18.8125V8.1875C18 6.42709 16.5609 5 14.7857 5H6.21429Z"
|
||||
fill="currentColor"></path>
|
||||
</svg>
|
||||
</span>
|
||||
<!--end::Svg Icon-->
|
||||
</button>
|
||||
|
||||
|
||||
{{-- Delete --}}
|
||||
@if (Auth::user()->role != 2)
|
||||
<a href="#" data-id="{{ $obj['id'] }}"
|
||||
class="btn btn-icon btn-bg-light btn-active-color-primary btn-sm delete-item">
|
||||
<span class="svg-icon svg-icon-3">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24"
|
||||
fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M5 9C5 8.44772 5.44772 8 6 8H18C18.5523 8 19 8.44772 19 9V18C19 19.6569 17.6569 21 16 21H8C6.34315 21 5 19.6569 5 18V9Z"
|
||||
fill="currentColor" />
|
||||
<path opacity="0.5"
|
||||
d="M5 5C5 4.44772 5.44772 4 6 4H18C18.5523 4 19 4.44772 19 5V5C19 5.55228 18.5523 6 18 6H6C5.44772 6 5 5.55228 5 5V5Z"
|
||||
fill="currentColor" />
|
||||
<path opacity="0.5"
|
||||
d="M9 4C9 3.44772 9.44772 3 10 3H14C14.5523 3 15 3.44772 15 4V4H9V4Z"
|
||||
fill="currentColor" />
|
||||
</svg>
|
||||
</span>
|
||||
</a>
|
||||
@endif
|
||||
</td>
|
||||
|
||||
|
||||
</tr>
|
||||
@endforeach
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@stop
|
||||
|
||||
|
||||
@section('script')
|
||||
|
||||
<script type="text/javascript">
|
||||
const baseUrl = "{{ url('document') }}";
|
||||
var datatable;
|
||||
datatable = $("#data-table").DataTable({
|
||||
"info": false,
|
||||
"order": [],
|
||||
"pageLength": 25,
|
||||
lengthMenu: [
|
||||
[10, 25, 50, 100, 500, 1000],
|
||||
[10, 25, 50, 100, 500, 1000]
|
||||
]
|
||||
});
|
||||
|
||||
// Filter by search
|
||||
const filterSearch = document.querySelector('[table-filter="search"]');
|
||||
filterSearch.addEventListener('keyup', function(e) {
|
||||
datatable.search(e.target.value).draw();
|
||||
});
|
||||
|
||||
// filter by status
|
||||
const filterStatus = document.querySelector('[table-filter="status"]');
|
||||
$(filterStatus).on('change', e => {
|
||||
let value = e.target.value;
|
||||
if (value === 'all') {
|
||||
value = '';
|
||||
}
|
||||
datatable.column(4).search(value).draw();
|
||||
});
|
||||
|
||||
|
||||
// Remove
|
||||
$(document).on('click', '.delete-item', function() {
|
||||
swal.fire({
|
||||
allowOutsideClick: false,
|
||||
text: "Are you sure you would like to Delete?",
|
||||
icon: "warning",
|
||||
buttonsStyling: false,
|
||||
showDenyButton: true,
|
||||
confirmButtonText: "Yes",
|
||||
denyButtonText: 'No',
|
||||
customClass: {
|
||||
confirmButton: "btn btn-primary",
|
||||
denyButton: "btn btn-light-danger"
|
||||
}
|
||||
}).then((result) => {
|
||||
if (result.isConfirmed) {
|
||||
|
||||
alertLoading("Loading")
|
||||
|
||||
// set up ajax
|
||||
initAjaxSetupToken();
|
||||
|
||||
const ajaxProp = {
|
||||
url: "{{ url('document/delete') }}",
|
||||
type: 'POST',
|
||||
data: {
|
||||
item_id: $(this).data('id')
|
||||
},
|
||||
};
|
||||
|
||||
// const id = $(this).data('id');
|
||||
const id = "{{ $folderView->id }}";
|
||||
|
||||
$.ajax(ajaxProp).done(function(res) {
|
||||
if (res.status) {
|
||||
const url = "{{ url('document/folder') }}/" + id;
|
||||
alertSuccessWithUrl('Notice', "Delete success", url);
|
||||
hideLoading();
|
||||
} else {
|
||||
alertFail('Notice', res.message ?? "Unsuccessfully");
|
||||
hideLoading();
|
||||
}
|
||||
}).fail(function(xhr, status, error) {
|
||||
logAjaxError(xhr, status, error);
|
||||
alertFail('Notice', error.message ?? "Unsuccessfully");
|
||||
hideLoading();
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const copyButtons = document.querySelectorAll('.copy-button');
|
||||
|
||||
copyButtons.forEach(button => {
|
||||
button.addEventListener('click', function() {
|
||||
const urlToCopy = button.getAttribute('data-url');
|
||||
|
||||
// Copy the URL to the clipboard
|
||||
navigator.clipboard.writeText(urlToCopy).then(() => {
|
||||
alert(
|
||||
'Link copied to clipboard!'
|
||||
); // You can change this to a toast notification
|
||||
}).catch(err => {
|
||||
console.error('Could not copy text: ', err);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
@endsection
|
||||
@@ -0,0 +1,451 @@
|
||||
@extends('layouts.backendTemplate')
|
||||
|
||||
@section('content')
|
||||
|
||||
<style>
|
||||
.link-container {
|
||||
display: flex;
|
||||
/* Use flexbox for alignment */
|
||||
align-items: center;
|
||||
/* Center items vertically */
|
||||
justify-content: space-between;
|
||||
/* Space between the URL and button */
|
||||
}
|
||||
|
||||
.file-url {
|
||||
flex: 1;
|
||||
/* Allow the URL to take up available space */
|
||||
color: #007bff;
|
||||
/* Link color */
|
||||
text-decoration: none;
|
||||
/* Remove underline */
|
||||
overflow: hidden;
|
||||
/* Hide overflow */
|
||||
white-space: nowrap;
|
||||
/* Prevent text wrapping */
|
||||
text-overflow: ellipsis;
|
||||
/* Add ellipsis for overflow */
|
||||
margin-right: 10px;
|
||||
/* Space between text and button */
|
||||
}
|
||||
</style>
|
||||
|
||||
<!--begin::Main-->
|
||||
<div class="app-main flex-column flex-row-fluid" id="kt_app_main">
|
||||
|
||||
<div class="d-flex flex-column flex-column-fluid">
|
||||
|
||||
|
||||
@include('uc.breadcrumbList', [
|
||||
'title' => 'Document Management',
|
||||
'pageName' => 'Document Management',
|
||||
])
|
||||
|
||||
|
||||
<div id="kt_app_content" class="app-content flex-column-fluid">
|
||||
|
||||
<div id="kt_app_content_container" class="app-container container-xxl">
|
||||
|
||||
<div class="card">
|
||||
|
||||
@if (Session::has('messageSuccess'))
|
||||
<div class="card-body">
|
||||
@include('uc/messageSuccess')
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@if (Session::has('messageFail'))
|
||||
<div class="card-body">
|
||||
@include('uc/messageFail')
|
||||
</div>
|
||||
@endif
|
||||
|
||||
|
||||
<div class="card-header border-0 pt-6">
|
||||
<div class="d-flex align-items-center position-relative my-1">
|
||||
</div>
|
||||
|
||||
@if (Auth::user()->role != 2)
|
||||
<div class="card-toolbar">
|
||||
<div class="d-flex justify-content-end" style="margin-right: 5px;"
|
||||
data-kt-customer-table-toolbar="base">
|
||||
<a href="{{ url('document/add-folder') }}" class="btn btn-light-primary me-3"
|
||||
id="kt_file_manager_new_folder">New
|
||||
Folder</a>
|
||||
</div>
|
||||
<div class="d-flex justify-content-end" data-kt-customer-table-toolbar="base">
|
||||
<a href="{{ url('document/add') }}" class="btn btn-primary">Add </a>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<div class="card-header border-0 pt-5">
|
||||
|
||||
<div class="card-title">
|
||||
<div class="d-flex align-items-center position-relative my-1">
|
||||
<span class="svg-icon svg-icon-1 position-absolute ms-4">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<rect opacity="0.5" x="17.0365" y="15.1223" width="8.15546" height="2"
|
||||
rx="1" transform="rotate(45 17.0365 15.1223)" fill="currentColor">
|
||||
</rect>
|
||||
<path
|
||||
d="M11 19C6.55556 19 3 15.4444 3 11C3 6.55556 6.55556 3 11 3C15.4444 3 19 6.55556 19 11C19 15.4444 15.4444 19 11 19ZM11 5C7.53333 5 5 7.53333 5 11C5 14.4667 7.53333 17 11 17C14.4667 17 17 14.4667 17 11C17 7.53333 14.4667 5 11 5Z"
|
||||
fill="currentColor"></path>
|
||||
</svg>
|
||||
</span>
|
||||
|
||||
<input type="text" table-filter="search"
|
||||
class="form-control form-control-solid w-250px ps-15" placeholder="Search" />
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="card-body py-4">
|
||||
<!--begin::Table-->
|
||||
<table class="table align-middle table-row-dashed fs-6 gy-5" id="data-table">
|
||||
<!--begin::Table head-->
|
||||
<thead>
|
||||
<!--begin::Table row-->
|
||||
<tr class="text-start text-muted fw-bold fs-7 text-uppercase gs-0">
|
||||
<th class="min-w-125px">Name</th>
|
||||
<th class="min-w-125px">Created</th>
|
||||
<th class="text-end min-w-100px">Manage</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody class="text-gray-600 fw-semibold">
|
||||
|
||||
|
||||
@foreach ($folderView as $obj)
|
||||
<tr>
|
||||
<td>
|
||||
<div class="d-flex align-items-center">
|
||||
<span class="svg-icon svg-icon-2x svg-icon-primary me-4">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24"
|
||||
fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path opacity="0.3" d="M10 4H21C21.6 4 22 4.4 22 5V7H10V4Z"
|
||||
fill="currentColor"></path>
|
||||
<path
|
||||
d="M9.2 3H3C2.4 3 2 3.4 2 4V19C2 19.6 2.4 20 3 20H21C21.6 20 22 19.6 22 19V7C22 6.4 21.6 6 21 6H12L10.4 3.60001C10.2 3.20001 9.7 3 9.2 3Z"
|
||||
fill="currentColor"></path>
|
||||
</svg>
|
||||
</span>
|
||||
<a href="{{ url('document/folder/' . $obj->id) }}"
|
||||
class="text-gray-800 text-hover-primary">
|
||||
{{ $obj->name }}</a>
|
||||
</div>
|
||||
</td>
|
||||
|
||||
<td>
|
||||
{{ Carbon\Carbon::parse($obj['created_at'])->format('d, M Y') }}
|
||||
</td>
|
||||
|
||||
<td class="min-w-100px text-end">
|
||||
|
||||
{{-- Download --}}
|
||||
<a href="{{ url('document/download-folder') . '/' . $obj->id }}"
|
||||
class="btn-download-folder btn btn-sm btn-icon btn-light btn-active-light-primary"
|
||||
type="button" data-bs-toggle="tooltip" aria-label="Coming soon"
|
||||
data-bs-original-title="Coming soon" data-kt-initialized="1">
|
||||
<i class="bi bi-download fs-3"></i>
|
||||
</a>
|
||||
|
||||
{{-- Edit --}}
|
||||
<a href="{{ url('document/edit-folder/' . $obj['id']) }}"
|
||||
class="btn btn-icon btn-bg-light btn-active-color-primary btn-sm me-1">
|
||||
<span class="svg-icon svg-icon-3">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24"
|
||||
fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path opacity="0.3"
|
||||
d="M21.4 8.35303L19.241 10.511L13.485 4.755L15.643 2.59595C16.0248 2.21423 16.5426 1.99988 17.0825 1.99988C17.6224 1.99988 18.1402 2.21423 18.522 2.59595L21.4 5.474C21.7817 5.85581 21.9962 6.37355 21.9962 6.91345C21.9962 7.45335 21.7817 7.97122 21.4 8.35303ZM3.68699 21.932L9.88699 19.865L4.13099 14.109L2.06399 20.309C1.98815 20.5354 1.97703 20.7787 2.03189 21.0111C2.08674 21.2436 2.2054 21.4561 2.37449 21.6248C2.54359 21.7934 2.75641 21.9115 2.989 21.9658C3.22158 22.0201 3.4647 22.0084 3.69099 21.932H3.68699Z"
|
||||
fill="currentColor" />
|
||||
<path
|
||||
d="M5.574 21.3L3.692 21.928C3.46591 22.0032 3.22334 22.0141 2.99144 21.9594C2.75954 21.9046 2.54744 21.7864 2.3789 21.6179C2.21036 21.4495 2.09202 21.2375 2.03711 21.0056C1.9822 20.7737 1.99289 20.5312 2.06799 20.3051L2.696 18.422L5.574 21.3ZM4.13499 14.105L9.891 19.861L19.245 10.507L13.489 4.75098L4.13499 14.105Z"
|
||||
fill="currentColor" />
|
||||
</svg>
|
||||
</span>
|
||||
</a>
|
||||
|
||||
{{-- Delete --}}
|
||||
<a href="#" data-id="{{ $obj['id'] }}"
|
||||
class="btn btn-icon btn-bg-light btn-active-color-primary btn-sm delete-folder-item">
|
||||
<span class="svg-icon svg-icon-3">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24"
|
||||
fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M5 9C5 8.44772 5.44772 8 6 8H18C18.5523 8 19 8.44772 19 9V18C19 19.6569 17.6569 21 16 21H8C6.34315 21 5 19.6569 5 18V9Z"
|
||||
fill="currentColor" />
|
||||
<path opacity="0.5"
|
||||
d="M5 5C5 4.44772 5.44772 4 6 4H18C18.5523 4 19 4.44772 19 5V5C19 5.55228 18.5523 6 18 6H6C5.44772 6 5 5.55228 5 5V5Z"
|
||||
fill="currentColor" />
|
||||
<path opacity="0.5"
|
||||
d="M9 4C9 3.44772 9.44772 3 10 3H14C14.5523 3 15 3.44772 15 4V4H9V4Z"
|
||||
fill="currentColor" />
|
||||
</svg>
|
||||
</span>
|
||||
</a>
|
||||
</td>
|
||||
|
||||
|
||||
</tr>
|
||||
@endforeach
|
||||
|
||||
@foreach ($itemView as $obj)
|
||||
<tr>
|
||||
<td>
|
||||
<div class="d-flex align-items-center">
|
||||
<a href="#" class="text-gray-800 text-hover-primary">
|
||||
@if (isset($obj['name']) && Str::endsWith($obj['name'], ['.pdf']))
|
||||
<img alt="PDF Icon" class="w-30px me-3"
|
||||
src="{{ url('assets/media/svg/files/pdf.svg') }}">
|
||||
@elseif (isset($obj['name']) && Str::endsWith($obj['name'], ['.doc', '.docx']))
|
||||
<img alt="DOC Icon" class="w-30px me-3"
|
||||
src="{{ url('assets/media/svg/files/doc.svg') }}">
|
||||
@else
|
||||
<span class="svg-icon svg-icon-2x svg-icon-primary me-4">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24"
|
||||
fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path opacity="0.3"
|
||||
d="M19 22H5C4.4 22 4 21.6 4 21V3C4 2.4 4.4 2 5 2H14L20 8V21C20 21.6 19.6 22 19 22Z"
|
||||
fill="currentColor"></path>
|
||||
<path d="M15 8H20L14 2V7C14 7.6 14.4 8 15 8Z"
|
||||
fill="currentColor"></path>
|
||||
</svg>
|
||||
</span>
|
||||
@endif
|
||||
{{ $obj['name'] }}
|
||||
</a>
|
||||
|
||||
</div>
|
||||
</td>
|
||||
|
||||
|
||||
<td>
|
||||
{{ Carbon\Carbon::parse($obj['created_at'])->format('d, M Y') }}
|
||||
</td>
|
||||
|
||||
<td class="min-w-100px text-end">
|
||||
|
||||
{{-- Download --}}
|
||||
<a href="{{ env('R2_SCHEMA_URL') . $obj['name'] }}" target="_blank"
|
||||
class="btn btn-sm btn-icon btn-light btn-active-light-primary"
|
||||
type="button" data-bs-toggle="tooltip" aria-label="Coming soon"
|
||||
data-bs-original-title="Coming soon" data-kt-initialized="1">
|
||||
<i class="bi bi-download fs-3"></i>
|
||||
</a>
|
||||
|
||||
{{-- Copy --}}
|
||||
<button type="button" data-action="copy"
|
||||
data-url="{{ env('R2_SCHEMA_URL') . $obj['name'] }}"
|
||||
class="btn btn-sm btn-icon btn-light btn-active-light-primary copy-button">
|
||||
<span class="svg-icon svg-icon-2">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24"
|
||||
fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path opacity="0.5"
|
||||
d="M18 2H9C7.34315 2 6 3.34315 6 5H8C8 4.44772 8.44772 4 9 4H18C18.5523 4 19 4.44772 19 5V16C19 16.5523 18.5523 17 18 17V19C19.6569 19 21 17.6569 21 16V5C21 3.34315 19.6569 2 18 2Z"
|
||||
fill="currentColor"></path>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd"
|
||||
d="M14.7857 7.125H6.21429C5.62255 7.125 5.14286 7.6007 5.14286 8.1875V18.8125C5.14286 19.3993 5.62255 19.875 6.21429 19.875H14.7857C15.3774 19.875 15.8571 19.3993 15.8571 18.8125V8.1875C15.8571 7.6007 15.3774 7.125 14.7857 7.125ZM6.21429 5C4.43908 5 3 6.42709 3 8.1875V18.8125C3 20.5729 4.43909 22 6.21429 22H14.7857C16.5609 22 18 20.5729 18 18.8125V8.1875C18 6.42709 16.5609 5 14.7857 5H6.21429Z"
|
||||
fill="currentColor"></path>
|
||||
</svg>
|
||||
</span>
|
||||
<!--end::Svg Icon-->
|
||||
</button>
|
||||
|
||||
|
||||
{{-- Delete --}}
|
||||
@if (Auth::user()->role != 2)
|
||||
<a href="#" data-id="{{ $obj['id'] }}"
|
||||
class="btn btn-icon btn-bg-light btn-active-color-primary btn-sm delete-item">
|
||||
<span class="svg-icon svg-icon-3">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24"
|
||||
fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M5 9C5 8.44772 5.44772 8 6 8H18C18.5523 8 19 8.44772 19 9V18C19 19.6569 17.6569 21 16 21H8C6.34315 21 5 19.6569 5 18V9Z"
|
||||
fill="currentColor" />
|
||||
<path opacity="0.5"
|
||||
d="M5 5C5 4.44772 5.44772 4 6 4H18C18.5523 4 19 4.44772 19 5V5C19 5.55228 18.5523 6 18 6H6C5.44772 6 5 5.55228 5 5V5Z"
|
||||
fill="currentColor" />
|
||||
<path opacity="0.5"
|
||||
d="M9 4C9 3.44772 9.44772 3 10 3H14C14.5523 3 15 3.44772 15 4V4H9V4Z"
|
||||
fill="currentColor" />
|
||||
</svg>
|
||||
</span>
|
||||
</a>
|
||||
@endif
|
||||
</td>
|
||||
|
||||
|
||||
</tr>
|
||||
@endforeach
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@stop
|
||||
|
||||
|
||||
@section('script')
|
||||
|
||||
<script type="text/javascript">
|
||||
const baseUrl = "{{ url('document') }}";
|
||||
var datatable;
|
||||
datatable = $("#data-table").DataTable({
|
||||
"info": false,
|
||||
"order": [],
|
||||
"pageLength": 25,
|
||||
lengthMenu: [
|
||||
[10, 25, 50, 100, 500, 1000],
|
||||
[10, 25, 50, 100, 500, 1000]
|
||||
]
|
||||
});
|
||||
|
||||
// Filter by search
|
||||
const filterSearch = document.querySelector('[table-filter="search"]');
|
||||
filterSearch.addEventListener('keyup', function(e) {
|
||||
datatable.search(e.target.value).draw();
|
||||
});
|
||||
|
||||
// filter by status
|
||||
const filterStatus = document.querySelector('[table-filter="status"]');
|
||||
$(filterStatus).on('change', e => {
|
||||
let value = e.target.value;
|
||||
if (value === 'all') {
|
||||
value = '';
|
||||
}
|
||||
datatable.column(4).search(value).draw();
|
||||
});
|
||||
|
||||
|
||||
// Remove
|
||||
$(document).on('click', '.delete-item', function() {
|
||||
swal.fire({
|
||||
allowOutsideClick: false,
|
||||
text: "Are you sure you would like to Delete?",
|
||||
icon: "warning",
|
||||
buttonsStyling: false,
|
||||
showDenyButton: true,
|
||||
confirmButtonText: "Yes",
|
||||
denyButtonText: 'No',
|
||||
customClass: {
|
||||
confirmButton: "btn btn-primary",
|
||||
denyButton: "btn btn-light-danger"
|
||||
}
|
||||
}).then((result) => {
|
||||
if (result.isConfirmed) {
|
||||
|
||||
alertLoading("Loading")
|
||||
|
||||
// set up ajax
|
||||
initAjaxSetupToken();
|
||||
|
||||
const ajaxProp = {
|
||||
url: "{{ url('document/delete') }}",
|
||||
type: 'POST',
|
||||
data: {
|
||||
item_id: $(this).data('id')
|
||||
},
|
||||
};
|
||||
|
||||
$.ajax(ajaxProp).done(function(res) {
|
||||
if (res.status) {
|
||||
const url = "{{ url('document') }}";
|
||||
alertSuccessWithUrl('Notice', "Delete success", url);
|
||||
hideLoading();
|
||||
} else {
|
||||
alertFail('Notice', res.message ?? "Unsuccessfully");
|
||||
hideLoading();
|
||||
}
|
||||
}).fail(function(xhr, status, error) {
|
||||
logAjaxError(xhr, status, error);
|
||||
alertFail('Notice', error.message ?? "Unsuccessfully");
|
||||
hideLoading();
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const copyButtons = document.querySelectorAll('.copy-button');
|
||||
|
||||
copyButtons.forEach(button => {
|
||||
button.addEventListener('click', function() {
|
||||
const urlToCopy = button.getAttribute('data-url');
|
||||
|
||||
// Copy the URL to the clipboard
|
||||
navigator.clipboard.writeText(urlToCopy).then(() => {
|
||||
alert(
|
||||
'Link copied to clipboard!'
|
||||
); // You can change this to a toast notification
|
||||
}).catch(err => {
|
||||
console.error('Could not copy text: ', err);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
|
||||
// Delete folder
|
||||
$(document).on('click', '.delete-folder-item', function() {
|
||||
swal.fire({
|
||||
allowOutsideClick: false,
|
||||
text: "Are you sure you would like to Delete?",
|
||||
icon: "warning",
|
||||
buttonsStyling: false,
|
||||
showDenyButton: true,
|
||||
confirmButtonText: "Yes",
|
||||
denyButtonText: 'No',
|
||||
customClass: {
|
||||
confirmButton: "btn btn-primary",
|
||||
denyButton: "btn btn-light-danger"
|
||||
}
|
||||
}).then((result) => {
|
||||
if (result.isConfirmed) {
|
||||
|
||||
alertLoading("Loading")
|
||||
|
||||
// set up ajax
|
||||
initAjaxSetupToken();
|
||||
|
||||
const ajaxProp = {
|
||||
url: "{{ url('document/delete-folder') }}",
|
||||
type: 'POST',
|
||||
data: {
|
||||
item_id: $(this).data('id')
|
||||
},
|
||||
};
|
||||
|
||||
$.ajax(ajaxProp).done(function(res) {
|
||||
if (res.status) {
|
||||
const url = "{{ url('document') }}";
|
||||
alertSuccessWithUrl('Notice', "Delete success", url);
|
||||
hideLoading();
|
||||
} else {
|
||||
alertFail('Notice', res.message ?? "Unsuccessfully");
|
||||
hideLoading();
|
||||
}
|
||||
}).fail(function(xhr, status, error) {
|
||||
logAjaxError(xhr, status, error);
|
||||
alertFail('Notice', error.message ?? "Unsuccessfully");
|
||||
hideLoading();
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
@endsection
|
||||
@@ -0,0 +1,121 @@
|
||||
@extends('layouts.loginTemplate')
|
||||
|
||||
@section('content')
|
||||
|
||||
<form class="form w-100" novalidate="novalidate" id="frm-forgot-password" method="post"
|
||||
action="{{ url('post-forgot-password') }}">
|
||||
|
||||
<input type="hidden" name="_method" value="POST">
|
||||
<input type="hidden" name="_token" value="{{ csrf_token() }}">
|
||||
|
||||
<!--begin::Heading-->
|
||||
<div class="text-center mb-11">
|
||||
<!--begin::Title-->
|
||||
<h1 class="text-dark fw-bolder mb-3">Forgot Password</h1>
|
||||
<!--end::Title-->
|
||||
</div>
|
||||
<!--begin::Heading-->
|
||||
|
||||
|
||||
<!--begin::Input group=-->
|
||||
<div class="fv-row mb-8">
|
||||
<!--begin::Email-->
|
||||
<input type="email" placeholder="Email" name="email" autocomplete="off"
|
||||
class="form-control bg-transparent" />
|
||||
<!--end::Email-->
|
||||
</div>
|
||||
|
||||
<!--end::Input group=-->
|
||||
<!--begin::Wrapper-->
|
||||
<div class="d-flex flex-stack flex-wrap gap-3 fs-base fw-semibold mb-8">
|
||||
<div></div>
|
||||
<!--begin::Link-->
|
||||
<a href="{{ url('login') }}" class="link-primary">Login ?</a>
|
||||
<!--end::Link-->
|
||||
</div>
|
||||
<!--end::Wrapper-->
|
||||
|
||||
<!--begin::Submit button-->
|
||||
<div class="d-grid mb-10">
|
||||
<button type="button" id="btn-submit" class="btn btn-primary">
|
||||
<!--begin::Indicator label-->
|
||||
<span class="indicator-label">Submit</span>
|
||||
<!--end::Indicator label-->
|
||||
<!--begin::Indicator progress-->
|
||||
<span class="indicator-progress">Please wait...
|
||||
<span class="spinner-border spinner-border-sm align-middle ms-2"></span></span>
|
||||
<!--end::Indicator progress-->
|
||||
</button>
|
||||
</div>
|
||||
<!--end::Submit button-->
|
||||
|
||||
</form>
|
||||
|
||||
@stop
|
||||
|
||||
@section('script')
|
||||
|
||||
<script type="text/javascript">
|
||||
$(function() {
|
||||
|
||||
$(document).on("click", "#btn-submit", function(e) {
|
||||
|
||||
// handle bomb click
|
||||
e.preventDefault();
|
||||
|
||||
alertLoading("Loading")
|
||||
|
||||
formSubmit()
|
||||
})
|
||||
|
||||
var inputPassword = document.getElementById("input-password");
|
||||
|
||||
// Execute a function when the user presses a key on the keyboard
|
||||
inputPassword.addEventListener("keypress", function(event) {
|
||||
// If the user presses the "Enter" key on the keyboard
|
||||
if (event.key === "Enter") {
|
||||
// Cancel the default action, if needed
|
||||
event.preventDefault();
|
||||
alertLoading("Loading")
|
||||
// Trigger the button element with a click
|
||||
document.getElementById("btn-submit").click();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
|
||||
function formSubmit() {
|
||||
// form data
|
||||
const form = $('#frm-forgot-password')[0];
|
||||
const formData = new FormData(form);
|
||||
|
||||
// set up ajax
|
||||
initAjaxSetupToken();
|
||||
|
||||
const ajaxProp = {
|
||||
url: "{{ url('post-forgot-password') }}",
|
||||
dataType: 'json',
|
||||
method: 'post',
|
||||
data: formData,
|
||||
processData: false,
|
||||
contentType: false,
|
||||
};
|
||||
|
||||
$.ajax(ajaxProp).done(function(res) {
|
||||
if (isAjaxStatusSuccess(res.status)) {
|
||||
alertSuccess('Notice', 'Please check your email address')
|
||||
window.location.href = '{{ url('') }}';
|
||||
hideLoading();
|
||||
} else {
|
||||
alertFail('Notice', res.message ?? "Forgot password unsuccessfully");
|
||||
}
|
||||
}).fail(function(xhr, status, error) {
|
||||
logAjaxError(xhr, status, error);
|
||||
alertFail('Notice', error.message ?? "Forgot password unsuccessfully");
|
||||
hideLoading();
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
@endsection
|
||||
@@ -0,0 +1,367 @@
|
||||
@extends('layouts.backendTemplate')
|
||||
|
||||
@section('content')
|
||||
|
||||
<style>
|
||||
#progressBar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.progress-bar {
|
||||
width: 100%;
|
||||
height: 10px;
|
||||
border-radius: 5px;
|
||||
margin-top: 10px;
|
||||
appearance: none;
|
||||
}
|
||||
|
||||
.progress-bar::-webkit-progress-value {
|
||||
background-color: #4CAF50;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.progress-text {
|
||||
margin-top: 10px;
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
}
|
||||
</style>
|
||||
|
||||
<!--begin::Main-->
|
||||
<div class="app-main flex-column flex-row-fluid" id="kt_app_main">
|
||||
|
||||
<div class="d-flex flex-column flex-column-fluid">
|
||||
|
||||
|
||||
@include('uc.admin.breadcrumb', [
|
||||
'title' => 'Image Add',
|
||||
'pageName' => 'Add',
|
||||
'pageParent' => 'Image Management',
|
||||
'pageParentLink' => url('image'),
|
||||
])
|
||||
|
||||
<div id="kt_app_content" class="app-content flex-column-fluid">
|
||||
<div id="kt_app_content_container" class="app-container container-xxl">
|
||||
|
||||
|
||||
|
||||
<form id="frmAdd" class="form d-flex flex-column flex-lg-row" method="post"
|
||||
enctype="multipart/form-data">
|
||||
|
||||
<input type="hidden" name="_method" value="POST">
|
||||
<input type="hidden" name="_token" value="{{ csrf_token() }}">
|
||||
|
||||
|
||||
<div class="d-flex flex-column flex-row-fluid gap-7 gap-lg-10">
|
||||
|
||||
<div class="card card-flush py-4">
|
||||
|
||||
|
||||
@if (Session::has('messageSuccess'))
|
||||
<div class="card-body">
|
||||
@include('uc/messageSuccess')
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@if (Session::has('messageFail'))
|
||||
<div class="card-body">
|
||||
@include('uc/messageFail')
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<div class="card-header">
|
||||
<div class="card-title">
|
||||
<h2>Overview</h2>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card-body pt-0">
|
||||
|
||||
<div class="mb-10">
|
||||
<label class="form-label required">File Image</label>
|
||||
|
||||
<input class="fileInput file-input" type="file" id="fileInput" name="fileInput"
|
||||
accept=".jpg, .bmp, .jpeg, .png" multiple>
|
||||
|
||||
<progress id="progressBar" class="progress-bar" value="0"
|
||||
max="100"></progress>
|
||||
<div id="progressText" class="progress-text">0%</div>
|
||||
|
||||
<div class="text-muted fs-7">Allowed Types .jpg, .bmp, .jpeg, .png</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="d-flex justify-content-end">
|
||||
|
||||
<a href="{{ url('image') }}" id="kt_ecommerce_add_product_cancel"
|
||||
class="btn btn-light me-5">Cancel</a>
|
||||
|
||||
<button type="button" id="btn_submit" class="btn btn-primary">
|
||||
<span class="indicator-label">Save</span>
|
||||
</button>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</form>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
@stop
|
||||
|
||||
|
||||
@section('script')
|
||||
|
||||
<script>
|
||||
const baseApiUrl = "{{ env('API_URL') }}";
|
||||
|
||||
|
||||
$(document).on("click", "#btn_submit", async function(e) {
|
||||
|
||||
e.preventDefault();
|
||||
|
||||
alertLoading("Loading")
|
||||
|
||||
await uploadFile();
|
||||
|
||||
});
|
||||
|
||||
|
||||
// Step 1
|
||||
async function uploadFile() {
|
||||
const fileInput = document.getElementById("fileInput");
|
||||
const progressBar = document.getElementById("progressBar");
|
||||
const progressText = document.getElementById("progressText");
|
||||
|
||||
if (!fileInput || fileInput.files.length === 0) {
|
||||
alertFail("Notice", "Please select one or more files.");
|
||||
hideLoading();
|
||||
return;
|
||||
}
|
||||
|
||||
const files = Array.from(fileInput.files); // Get all selected files
|
||||
$("#progressBar").show();
|
||||
|
||||
let totalSize = files.reduce((sum, file) => sum + file.size, 0);
|
||||
let totalUploadedSize = 0;
|
||||
|
||||
// Upload all files sequentially
|
||||
for (const file of files) {
|
||||
await uploadSingleFile(file, progressBar, progressText, totalSize, (fileUploadedSize) => {
|
||||
totalUploadedSize += fileUploadedSize;
|
||||
const overallPercent = Math.floor((totalUploadedSize / totalSize) * 100);
|
||||
animateProgress(progressBar, progressText, overallPercent);
|
||||
});
|
||||
}
|
||||
|
||||
const folderId = "{{ $folderIdView }}";
|
||||
console.log('folderId', folderId);
|
||||
let redirectUrl = "{{ url('image') }}"
|
||||
if (folderId) {
|
||||
redirectUrl = `${redirectUrl}/folder/${folderId}`;
|
||||
}
|
||||
alertSuccessWithUrl("Notice", "All files uploaded successfully", redirectUrl);
|
||||
}
|
||||
|
||||
async function uploadSingleFile(file, progressBar, progressText, totalSize, updateOverallProgress) {
|
||||
const uploadId = await initiateMultipartUpload(file.name);
|
||||
const partSize = 500 * 1024 * 1024; // 500 MB per part
|
||||
const parts = [];
|
||||
let uploadedSize = 0;
|
||||
|
||||
const uploadPromises = Array.from({
|
||||
length: Math.ceil(file.size / partSize)
|
||||
},
|
||||
(_, index) => {
|
||||
const partNumber = index + 1;
|
||||
const chunk = file.slice(index * partSize, (index + 1) * partSize);
|
||||
|
||||
return (async () => {
|
||||
const presignedUrl = await getPresignedUrl(uploadId, partNumber, file.name);
|
||||
const etag = await uploadPartToS3(presignedUrl, chunk);
|
||||
|
||||
parts.push({
|
||||
PartNumber: partNumber,
|
||||
ETag: etag
|
||||
});
|
||||
|
||||
uploadedSize += chunk.size;
|
||||
updateOverallProgress(chunk.size); // Update the overall progress
|
||||
})();
|
||||
}
|
||||
);
|
||||
|
||||
await Promise.all(uploadPromises);
|
||||
await completeMultipartUpload(uploadId, parts, file.name);
|
||||
await saveFileNameToDB(file.name);
|
||||
}
|
||||
|
||||
// Step 2
|
||||
async function initiateMultipartUpload(fileName) {
|
||||
const urlUploadImage = `${baseApiUrl}/initiate-multipart-upload`;
|
||||
const response = await fetch(
|
||||
urlUploadImage, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
fileName
|
||||
}),
|
||||
}
|
||||
);
|
||||
|
||||
const {
|
||||
uploadId
|
||||
} = await response.json();
|
||||
|
||||
return uploadId;
|
||||
}
|
||||
|
||||
// Step 3
|
||||
async function getPresignedUrl(uploadId, partNumber, fileName) {
|
||||
|
||||
const urlPresigned = `${baseApiUrl}/get-presigned-url`
|
||||
const response = await fetch(
|
||||
urlPresigned, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
uploadId,
|
||||
partNumber,
|
||||
fileName
|
||||
}),
|
||||
}
|
||||
);
|
||||
const {
|
||||
url
|
||||
} = await response.json();
|
||||
return url;
|
||||
}
|
||||
|
||||
// Step 4
|
||||
async function uploadPartToS3(url, chunk) {
|
||||
const response = await fetch(url, {
|
||||
method: "PUT",
|
||||
headers: {
|
||||
"Content-Type": "application/octet-stream",
|
||||
},
|
||||
body: chunk,
|
||||
});
|
||||
if (!response.ok) {
|
||||
alertFail("Notice", "Failed to upload part")
|
||||
hideLoading();
|
||||
//throw new Error("Failed to upload part");
|
||||
}
|
||||
|
||||
const etag = `${response.headers.get("ETag")}`.replace(/"/g, "");
|
||||
|
||||
if (!etag) {
|
||||
throw new Error("Failed to retrieve ETag from the response.");
|
||||
}
|
||||
|
||||
return etag;
|
||||
}
|
||||
|
||||
// Step 5
|
||||
async function completeMultipartUpload(uploadId, parts, fileName) {
|
||||
const urlUploadComplete = `${baseApiUrl}/complete-multipart-upload`;
|
||||
const response = await fetch(urlUploadComplete, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
uploadId,
|
||||
parts,
|
||||
fileName
|
||||
}),
|
||||
});
|
||||
if (response.ok) {
|
||||
//window.location.href = "{{ url('image') }}";
|
||||
} else {
|
||||
alertFail("Notice", "Failed to upload part");
|
||||
hideLoading();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Smoothly animates the progress bar and percentage text.
|
||||
*/
|
||||
async function animateProgress(progressBar, progressText, targetPercent) {
|
||||
const currentPercent = parseInt(progressBar.value) || 0;
|
||||
// Increment the percentage smoothly
|
||||
for (let percent = currentPercent + 1; percent <= targetPercent; percent++) {
|
||||
progressBar.value = percent;
|
||||
progressText.textContent = `${percent}%`;
|
||||
|
||||
// Add a small delay to make the increment visible (10ms delay)
|
||||
await new Promise((resolve) => setTimeout(resolve, 10));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends the uploaded file name to the server using AJAX.
|
||||
*/
|
||||
function saveFileNameToDB(fileName) {
|
||||
initAjaxSetupToken();
|
||||
|
||||
const folderId = "{{ $folderIdView }}";
|
||||
const url = "{{ url('') }}";
|
||||
|
||||
return $.ajax({
|
||||
url: `${url}/image/insert`,
|
||||
type: 'POST',
|
||||
contentType: 'application/json',
|
||||
data: JSON.stringify({
|
||||
fileName,
|
||||
folderId
|
||||
}),
|
||||
success: (response) => {
|
||||
console.log('File name saved:', response);
|
||||
},
|
||||
error: (err) => {
|
||||
console.error('Error saving file name:', err);
|
||||
alertFail("Notice", "There was an error saving the file name.");
|
||||
hideLoading();
|
||||
return;
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<script>
|
||||
$('.file-input').fileuploader({
|
||||
extensions: ['jpg', 'bmp', 'jpeg', 'png'],
|
||||
limit: null,
|
||||
fileMaxSize: null,
|
||||
changeInput: '<div class="fileuploader-input">' +
|
||||
'<div class="fileuploader-input-inner">' +
|
||||
'<p><i class="fileuploader-icon-main"></i></p>' +
|
||||
'<h6>Drag and drop files here</h6>' +
|
||||
'<p>or</p>' +
|
||||
'<br>' +
|
||||
'<button type="button" class="fileuploader-input-button"><span>${captions.button}</span></button>' +
|
||||
'</div>' +
|
||||
'</div>',
|
||||
theme: 'dragdrop',
|
||||
});
|
||||
</script>
|
||||
|
||||
@endsection
|
||||
@@ -0,0 +1,95 @@
|
||||
@extends('layouts.backendTemplate')
|
||||
|
||||
@section('content')
|
||||
|
||||
<!--begin::Main-->
|
||||
<div class="app-main flex-column flex-row-fluid" id="kt_app_main">
|
||||
|
||||
<div class="d-flex flex-column flex-column-fluid">
|
||||
|
||||
|
||||
@include('uc.admin.breadcrumb', [
|
||||
'title' => 'Image Create Folder',
|
||||
'pageName' => 'Create folder',
|
||||
'pageParent' => 'Image Management',
|
||||
'pageParentLink' => url('image'),
|
||||
])
|
||||
|
||||
<div id="kt_app_content" class="app-content flex-column-fluid">
|
||||
<div id="kt_app_content_container" class="app-container container-xxl">
|
||||
|
||||
<form id="frmAdd" action="{{ url('image/insert-folder') }}" class="form d-flex flex-column flex-lg-row"
|
||||
method="post" enctype="multipart/form-data">
|
||||
|
||||
<input type="hidden" name="_method" value="POST">
|
||||
<input type="hidden" name="_token" value="{{ csrf_token() }}">
|
||||
|
||||
|
||||
<div class="d-flex flex-column flex-row-fluid gap-7 gap-lg-10">
|
||||
|
||||
<div class="card card-flush py-4">
|
||||
|
||||
|
||||
@if (Session::has('messageSuccess'))
|
||||
<div class="card-body">
|
||||
@include('uc/messageSuccess')
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@if (Session::has('messageFail'))
|
||||
<div class="card-body">
|
||||
@include('uc/messageFail')
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<div class="card-header">
|
||||
<div class="card-title">
|
||||
<h2>Overview</h2>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card-body pt-0">
|
||||
|
||||
<div class="mb-10 fv-row">
|
||||
<label class="required form-label">Name</label>
|
||||
<input type="text" name="name" class="form-control mb-2 col-6"
|
||||
value="{{ old('name') }}" />
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="d-flex justify-content-end">
|
||||
|
||||
<a href="{{ url('image') }}" id="kt_ecommerce_add_product_cancel"
|
||||
class="btn btn-light me-5">Cancel</a>
|
||||
|
||||
<button type="submit" class="btn btn-primary">
|
||||
<span class="indicator-label">Save</span>
|
||||
</button>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</form>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
@stop
|
||||
|
||||
|
||||
@section('script')
|
||||
|
||||
<script></script>
|
||||
|
||||
@endsection
|
||||
@@ -0,0 +1,96 @@
|
||||
@extends('layouts.backendTemplate')
|
||||
|
||||
@section('content')
|
||||
|
||||
<!--begin::Main-->
|
||||
<div class="app-main flex-column flex-row-fluid" id="kt_app_main">
|
||||
|
||||
<div class="d-flex flex-column flex-column-fluid">
|
||||
|
||||
|
||||
@include('uc.admin.breadcrumb', [
|
||||
'title' => 'Image Edit Folder',
|
||||
'pageName' => 'Edit folder',
|
||||
'pageParent' => 'Image Management',
|
||||
'pageParentLink' => url('image'),
|
||||
])
|
||||
|
||||
<div id="kt_app_content" class="app-content flex-column-fluid">
|
||||
<div id="kt_app_content_container" class="app-container container-xxl">
|
||||
|
||||
<form id="frmAdd" action="{{ url('image/update-folder') }}" class="form d-flex flex-column flex-lg-row"
|
||||
method="post" enctype="multipart/form-data">
|
||||
|
||||
<input type="hidden" name="id" value="{{ $idView }}">
|
||||
<input type="hidden" name="_method" value="POST">
|
||||
<input type="hidden" name="_token" value="{{ csrf_token() }}">
|
||||
|
||||
|
||||
<div class="d-flex flex-column flex-row-fluid gap-7 gap-lg-10">
|
||||
|
||||
<div class="card card-flush py-4">
|
||||
|
||||
|
||||
@if (Session::has('messageSuccess'))
|
||||
<div class="card-body">
|
||||
@include('uc/messageSuccess')
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@if (Session::has('messageFail'))
|
||||
<div class="card-body">
|
||||
@include('uc/messageFail')
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<div class="card-header">
|
||||
<div class="card-title">
|
||||
<h2>Overview</h2>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card-body pt-0">
|
||||
|
||||
<div class="mb-10 fv-row">
|
||||
<label class="required form-label">Name</label>
|
||||
<input type="text" name="name" class="form-control mb-2 col-6"
|
||||
value="{{ $itemView->name }}" />
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="d-flex justify-content-end">
|
||||
|
||||
<a href="{{ url('image') }}" id="kt_ecommerce_add_product_cancel"
|
||||
class="btn btn-light me-5">Cancel</a>
|
||||
|
||||
<button type="submit" class="btn btn-primary">
|
||||
<span class="indicator-label">Save</span>
|
||||
</button>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</form>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
@stop
|
||||
|
||||
|
||||
@section('script')
|
||||
|
||||
<script></script>
|
||||
|
||||
@endsection
|
||||
@@ -0,0 +1,316 @@
|
||||
@extends('layouts.backendTemplate')
|
||||
|
||||
@section('content')
|
||||
|
||||
<style>
|
||||
.link-container {
|
||||
display: flex;
|
||||
/* Use flexbox for alignment */
|
||||
align-items: center;
|
||||
/* Center items vertically */
|
||||
justify-content: space-between;
|
||||
/* Space between the URL and button */
|
||||
}
|
||||
|
||||
.file-url {
|
||||
flex: 1;
|
||||
/* Allow the URL to take up available space */
|
||||
color: #007bff;
|
||||
/* Link color */
|
||||
text-decoration: none;
|
||||
/* Remove underline */
|
||||
overflow: hidden;
|
||||
/* Hide overflow */
|
||||
white-space: nowrap;
|
||||
/* Prevent text wrapping */
|
||||
text-overflow: ellipsis;
|
||||
/* Add ellipsis for overflow */
|
||||
margin-right: 10px;
|
||||
/* Space between text and button */
|
||||
}
|
||||
</style>
|
||||
|
||||
<!--begin::Main-->
|
||||
<div class="app-main flex-column flex-row-fluid" id="kt_app_main">
|
||||
|
||||
<div class="d-flex flex-column flex-column-fluid">
|
||||
|
||||
|
||||
@include('uc.breadcrumbList', [
|
||||
'title' => 'Image Management Folder ' . $folderView->name,
|
||||
'pageName' => 'Image Management',
|
||||
])
|
||||
|
||||
|
||||
<div id="kt_app_content" class="app-content flex-column-fluid">
|
||||
|
||||
<div id="kt_app_content_container" class="app-container container-xxl">
|
||||
|
||||
<div class="card">
|
||||
|
||||
@if (Session::has('messageSuccess'))
|
||||
<div class="card-body">
|
||||
@include('uc/messageSuccess')
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@if (Session::has('messageFail'))
|
||||
<div class="card-body">
|
||||
@include('uc/messageFail')
|
||||
</div>
|
||||
@endif
|
||||
|
||||
|
||||
<div class="card-header border-0 pt-6">
|
||||
<div class="d-flex align-items-center position-relative my-1">
|
||||
</div>
|
||||
|
||||
@if (Auth::user()->role != 2)
|
||||
<div class="card-toolbar">
|
||||
<div class="d-flex justify-content-end" data-kt-customer-table-toolbar="base">
|
||||
<a href="{{ url('image/add/' . $folderView->id) }}" class="btn btn-primary">Add
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<div class="card-header border-0 pt-5">
|
||||
|
||||
<div class="card-title">
|
||||
<div class="d-flex align-items-center position-relative my-1">
|
||||
<span class="svg-icon svg-icon-1 position-absolute ms-4">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<rect opacity="0.5" x="17.0365" y="15.1223" width="8.15546" height="2"
|
||||
rx="1" transform="rotate(45 17.0365 15.1223)" fill="currentColor">
|
||||
</rect>
|
||||
<path
|
||||
d="M11 19C6.55556 19 3 15.4444 3 11C3 6.55556 6.55556 3 11 3C15.4444 3 19 6.55556 19 11C19 15.4444 15.4444 19 11 19ZM11 5C7.53333 5 5 7.53333 5 11C5 14.4667 7.53333 17 11 17C14.4667 17 17 14.4667 17 11C17 7.53333 14.4667 5 11 5Z"
|
||||
fill="currentColor"></path>
|
||||
</svg>
|
||||
</span>
|
||||
|
||||
<input type="text" table-filter="search"
|
||||
class="form-control form-control-solid w-250px ps-15" placeholder="Search" />
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="card-body py-4">
|
||||
<!--begin::Table-->
|
||||
<table class="table align-middle table-row-dashed fs-6 gy-5" id="data-table">
|
||||
<!--begin::Table head-->
|
||||
<thead>
|
||||
<!--begin::Table row-->
|
||||
<tr class="text-start text-muted fw-bold fs-7 text-uppercase gs-0">
|
||||
<th class="min-w-125px">Name</th>
|
||||
<th class="min-w-125px">Created</th>
|
||||
<th class="text-end min-w-100px">Manage</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody class="text-gray-600 fw-semibold">
|
||||
|
||||
@foreach ($itemView as $obj)
|
||||
<tr>
|
||||
<td class="d-flex align-items-center">
|
||||
<!--begin:: Avatar -->
|
||||
<div class="symbol symbol-100px overflow-hidden me-3">
|
||||
<a class="show-image-preview"
|
||||
href="{{ env('R2_SCHEMA_URL') . $obj['name'] }}">
|
||||
<div class="symbol-label">
|
||||
<img src="{{ env('R2_SCHEMA_URL') . $obj['name'] }}"
|
||||
alt="Emma Smith" class="w-100">
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
<div class="d-flex flex-column">
|
||||
<a href="#"
|
||||
class="text-gray-800 text-hover-primary mb-1">{{ $obj['name'] }}</a>
|
||||
|
||||
</div>
|
||||
<!--begin::User details-->
|
||||
</td>
|
||||
|
||||
|
||||
<td>
|
||||
{{ Carbon\Carbon::parse($obj['created_at'])->format('d, M Y') }}
|
||||
</td>
|
||||
|
||||
<td class="min-w-100px text-end">
|
||||
|
||||
{{-- Download --}}
|
||||
<a href="{{ env('R2_SCHEMA_URL') . $obj['name'] }}" target="_blank"
|
||||
class="btn btn-sm btn-icon btn-light btn-active-light-primary"
|
||||
type="button" data-bs-toggle="tooltip" aria-label="Coming soon"
|
||||
data-bs-original-title="Coming soon" data-kt-initialized="1">
|
||||
<i class="bi bi-download fs-3"></i>
|
||||
</a>
|
||||
|
||||
{{-- Copy --}}
|
||||
<button type="button" data-action="copy"
|
||||
data-url="{{ env('R2_SCHEMA_URL') . $obj['name'] }}"
|
||||
class="btn btn-sm btn-icon btn-light btn-active-light-primary copy-button">
|
||||
<span class="svg-icon svg-icon-2">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24"
|
||||
fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path opacity="0.5"
|
||||
d="M18 2H9C7.34315 2 6 3.34315 6 5H8C8 4.44772 8.44772 4 9 4H18C18.5523 4 19 4.44772 19 5V16C19 16.5523 18.5523 17 18 17V19C19.6569 19 21 17.6569 21 16V5C21 3.34315 19.6569 2 18 2Z"
|
||||
fill="currentColor"></path>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd"
|
||||
d="M14.7857 7.125H6.21429C5.62255 7.125 5.14286 7.6007 5.14286 8.1875V18.8125C5.14286 19.3993 5.62255 19.875 6.21429 19.875H14.7857C15.3774 19.875 15.8571 19.3993 15.8571 18.8125V8.1875C15.8571 7.6007 15.3774 7.125 14.7857 7.125ZM6.21429 5C4.43908 5 3 6.42709 3 8.1875V18.8125C3 20.5729 4.43909 22 6.21429 22H14.7857C16.5609 22 18 20.5729 18 18.8125V8.1875C18 6.42709 16.5609 5 14.7857 5H6.21429Z"
|
||||
fill="currentColor"></path>
|
||||
</svg>
|
||||
</span>
|
||||
<!--end::Svg Icon-->
|
||||
</button>
|
||||
|
||||
|
||||
{{-- Delete --}}
|
||||
@if (Auth::user()->role != 2)
|
||||
<a href="#" data-id="{{ $obj['id'] }}"
|
||||
class="btn btn-icon btn-bg-light btn-active-color-primary btn-sm delete-item">
|
||||
<span class="svg-icon svg-icon-3">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24"
|
||||
fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M5 9C5 8.44772 5.44772 8 6 8H18C18.5523 8 19 8.44772 19 9V18C19 19.6569 17.6569 21 16 21H8C6.34315 21 5 19.6569 5 18V9Z"
|
||||
fill="currentColor" />
|
||||
<path opacity="0.5"
|
||||
d="M5 5C5 4.44772 5.44772 4 6 4H18C18.5523 4 19 4.44772 19 5V5C19 5.55228 18.5523 6 18 6H6C5.44772 6 5 5.55228 5 5V5Z"
|
||||
fill="currentColor" />
|
||||
<path opacity="0.5"
|
||||
d="M9 4C9 3.44772 9.44772 3 10 3H14C14.5523 3 15 3.44772 15 4V4H9V4Z"
|
||||
fill="currentColor" />
|
||||
</svg>
|
||||
</span>
|
||||
</a>
|
||||
@endif
|
||||
</td>
|
||||
|
||||
|
||||
</tr>
|
||||
@endforeach
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@stop
|
||||
|
||||
|
||||
@section('script')
|
||||
|
||||
<script type="text/javascript">
|
||||
const baseUrl = "{{ url('image') }}";
|
||||
var datatable;
|
||||
datatable = $("#data-table").DataTable({
|
||||
"info": false,
|
||||
"order": [],
|
||||
"pageLength": 25,
|
||||
lengthMenu: [
|
||||
[10, 25, 50, 100, 500, 1000],
|
||||
[10, 25, 50, 100, 500, 1000]
|
||||
]
|
||||
});
|
||||
|
||||
// Filter by search
|
||||
const filterSearch = document.querySelector('[table-filter="search"]');
|
||||
filterSearch.addEventListener('keyup', function(e) {
|
||||
datatable.search(e.target.value).draw();
|
||||
});
|
||||
|
||||
// filter by status
|
||||
const filterStatus = document.querySelector('[table-filter="status"]');
|
||||
$(filterStatus).on('change', e => {
|
||||
let value = e.target.value;
|
||||
if (value === 'all') {
|
||||
value = '';
|
||||
}
|
||||
datatable.column(4).search(value).draw();
|
||||
});
|
||||
|
||||
|
||||
// Remove
|
||||
$(document).on('click', '.delete-item', function() {
|
||||
swal.fire({
|
||||
allowOutsideClick: false,
|
||||
text: "Are you sure you would like to Delete?",
|
||||
icon: "warning",
|
||||
buttonsStyling: false,
|
||||
showDenyButton: true,
|
||||
confirmButtonText: "Yes",
|
||||
denyButtonText: 'No',
|
||||
customClass: {
|
||||
confirmButton: "btn btn-primary",
|
||||
denyButton: "btn btn-light-danger"
|
||||
}
|
||||
}).then((result) => {
|
||||
if (result.isConfirmed) {
|
||||
|
||||
alertLoading("Loading")
|
||||
|
||||
// set up ajax
|
||||
initAjaxSetupToken();
|
||||
|
||||
const ajaxProp = {
|
||||
url: "{{ url('image/delete') }}",
|
||||
type: 'POST',
|
||||
data: {
|
||||
item_id: $(this).data('id')
|
||||
},
|
||||
};
|
||||
|
||||
//const id = $(this).data('id');
|
||||
const id = "{{ $folderView->id }}";
|
||||
|
||||
$.ajax(ajaxProp).done(function(res) {
|
||||
if (res.status) {
|
||||
const url = "{{ url('image/folder') }}/" + id;
|
||||
alertSuccessWithUrl('Notice', "Delete success", url);
|
||||
hideLoading();
|
||||
} else {
|
||||
alertFail('Notice', res.message ?? "Unsuccessfully");
|
||||
hideLoading();
|
||||
}
|
||||
}).fail(function(xhr, status, error) {
|
||||
logAjaxError(xhr, status, error);
|
||||
alertFail('Notice', error.message ?? "Unsuccessfully");
|
||||
hideLoading();
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const copyButtons = document.querySelectorAll('.copy-button');
|
||||
|
||||
copyButtons.forEach(button => {
|
||||
button.addEventListener('click', function() {
|
||||
const urlToCopy = button.getAttribute('data-url');
|
||||
|
||||
// Copy the URL to the clipboard
|
||||
navigator.clipboard.writeText(urlToCopy).then(() => {
|
||||
alert(
|
||||
'Link copied to clipboard!'
|
||||
); // You can change this to a toast notification
|
||||
}).catch(err => {
|
||||
console.error('Could not copy text: ', err);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
@endsection
|
||||
@@ -0,0 +1,449 @@
|
||||
@extends('layouts.backendTemplate')
|
||||
|
||||
@section('content')
|
||||
|
||||
<style>
|
||||
.link-container {
|
||||
display: flex;
|
||||
/* Use flexbox for alignment */
|
||||
align-items: center;
|
||||
/* Center items vertically */
|
||||
justify-content: space-between;
|
||||
/* Space between the URL and button */
|
||||
}
|
||||
|
||||
.file-url {
|
||||
flex: 1;
|
||||
/* Allow the URL to take up available space */
|
||||
color: #007bff;
|
||||
/* Link color */
|
||||
text-decoration: none;
|
||||
/* Remove underline */
|
||||
overflow: hidden;
|
||||
/* Hide overflow */
|
||||
white-space: nowrap;
|
||||
/* Prevent text wrapping */
|
||||
text-overflow: ellipsis;
|
||||
/* Add ellipsis for overflow */
|
||||
margin-right: 10px;
|
||||
/* Space between text and button */
|
||||
}
|
||||
</style>
|
||||
|
||||
<!--begin::Main-->
|
||||
<div class="app-main flex-column flex-row-fluid" id="kt_app_main">
|
||||
|
||||
<div class="d-flex flex-column flex-column-fluid">
|
||||
|
||||
|
||||
@include('uc.breadcrumbList', [
|
||||
'title' => 'Image Management',
|
||||
'pageName' => 'Image Management',
|
||||
])
|
||||
|
||||
|
||||
<div id="kt_app_content" class="app-content flex-column-fluid">
|
||||
|
||||
<div id="kt_app_content_container" class="app-container container-xxl">
|
||||
|
||||
<div class="card">
|
||||
|
||||
@if (Session::has('messageSuccess'))
|
||||
<div class="card-body">
|
||||
@include('uc/messageSuccess')
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@if (Session::has('messageFail'))
|
||||
<div class="card-body">
|
||||
@include('uc/messageFail')
|
||||
</div>
|
||||
@endif
|
||||
|
||||
|
||||
<div class="card-header border-0 pt-6">
|
||||
<div class="d-flex align-items-center position-relative my-1">
|
||||
</div>
|
||||
|
||||
@if (Auth::user()->role != 2)
|
||||
<div class="card-toolbar">
|
||||
|
||||
<div class="d-flex justify-content-end" style="margin-right: 5px;"
|
||||
data-kt-customer-table-toolbar="base">
|
||||
<a href="{{ url('image/add-folder') }}" class="btn btn-light-primary me-3"
|
||||
id="kt_file_manager_new_folder">New
|
||||
Folder</a>
|
||||
</div>
|
||||
|
||||
<div class="d-flex justify-content-end" data-kt-customer-table-toolbar="base">
|
||||
<a href="{{ url('image/add') }}" class="btn btn-primary">Add </a>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@endif
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<div class="card-header border-0 pt-5">
|
||||
|
||||
<div class="card-title">
|
||||
<div class="d-flex align-items-center position-relative my-1">
|
||||
<span class="svg-icon svg-icon-1 position-absolute ms-4">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<rect opacity="0.5" x="17.0365" y="15.1223" width="8.15546" height="2"
|
||||
rx="1" transform="rotate(45 17.0365 15.1223)" fill="currentColor">
|
||||
</rect>
|
||||
<path
|
||||
d="M11 19C6.55556 19 3 15.4444 3 11C3 6.55556 6.55556 3 11 3C15.4444 3 19 6.55556 19 11C19 15.4444 15.4444 19 11 19ZM11 5C7.53333 5 5 7.53333 5 11C5 14.4667 7.53333 17 11 17C14.4667 17 17 14.4667 17 11C17 7.53333 14.4667 5 11 5Z"
|
||||
fill="currentColor"></path>
|
||||
</svg>
|
||||
</span>
|
||||
|
||||
<input type="text" table-filter="search"
|
||||
class="form-control form-control-solid w-250px ps-15" placeholder="Search" />
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="card-body py-4">
|
||||
<!--begin::Table-->
|
||||
<table class="table align-middle table-row-dashed fs-6 gy-5" id="data-table">
|
||||
<!--begin::Table head-->
|
||||
<thead>
|
||||
<!--begin::Table row-->
|
||||
<tr class="text-start text-muted fw-bold fs-7 text-uppercase gs-0">
|
||||
<th class="min-w-125px">Name</th>
|
||||
<th class="min-w-125px">Created</th>
|
||||
<th class="text-end min-w-100px">Action</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody class="text-gray-600 fw-semibold">
|
||||
|
||||
@foreach ($folderView as $obj)
|
||||
<tr>
|
||||
<td>
|
||||
<div class="d-flex align-items-center">
|
||||
<span class="svg-icon svg-icon-2x svg-icon-primary me-4">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24"
|
||||
fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path opacity="0.3" d="M10 4H21C21.6 4 22 4.4 22 5V7H10V4Z"
|
||||
fill="currentColor"></path>
|
||||
<path
|
||||
d="M9.2 3H3C2.4 3 2 3.4 2 4V19C2 19.6 2.4 20 3 20H21C21.6 20 22 19.6 22 19V7C22 6.4 21.6 6 21 6H12L10.4 3.60001C10.2 3.20001 9.7 3 9.2 3Z"
|
||||
fill="currentColor"></path>
|
||||
</svg>
|
||||
</span>
|
||||
<a href="{{ url('image/folder/' . $obj->id) }}"
|
||||
class="text-gray-800 text-hover-primary">
|
||||
{{ $obj->name }}</a>
|
||||
</div>
|
||||
</td>
|
||||
|
||||
<td>
|
||||
{{ Carbon\Carbon::parse($obj['created_at'])->format('d, M Y') }}
|
||||
</td>
|
||||
|
||||
<td class="min-w-100px text-end">
|
||||
|
||||
{{-- Download --}}
|
||||
<a href="{{ url('image/download-folder') . '/' . $obj->id }}"
|
||||
class="btn-download-folder btn btn-sm btn-icon btn-light btn-active-light-primary"
|
||||
type="button" data-bs-toggle="tooltip" aria-label="Coming soon"
|
||||
data-bs-original-title="Coming soon" data-kt-initialized="1">
|
||||
<i class="bi bi-download fs-3"></i>
|
||||
</a>
|
||||
|
||||
{{-- Edit --}}
|
||||
<a href="{{ url('image/edit-folder/' . $obj['id']) }}"
|
||||
class="btn btn-icon btn-bg-light btn-active-color-primary btn-sm me-1">
|
||||
<span class="svg-icon svg-icon-3">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24"
|
||||
fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path opacity="0.3"
|
||||
d="M21.4 8.35303L19.241 10.511L13.485 4.755L15.643 2.59595C16.0248 2.21423 16.5426 1.99988 17.0825 1.99988C17.6224 1.99988 18.1402 2.21423 18.522 2.59595L21.4 5.474C21.7817 5.85581 21.9962 6.37355 21.9962 6.91345C21.9962 7.45335 21.7817 7.97122 21.4 8.35303ZM3.68699 21.932L9.88699 19.865L4.13099 14.109L2.06399 20.309C1.98815 20.5354 1.97703 20.7787 2.03189 21.0111C2.08674 21.2436 2.2054 21.4561 2.37449 21.6248C2.54359 21.7934 2.75641 21.9115 2.989 21.9658C3.22158 22.0201 3.4647 22.0084 3.69099 21.932H3.68699Z"
|
||||
fill="currentColor" />
|
||||
<path
|
||||
d="M5.574 21.3L3.692 21.928C3.46591 22.0032 3.22334 22.0141 2.99144 21.9594C2.75954 21.9046 2.54744 21.7864 2.3789 21.6179C2.21036 21.4495 2.09202 21.2375 2.03711 21.0056C1.9822 20.7737 1.99289 20.5312 2.06799 20.3051L2.696 18.422L5.574 21.3ZM4.13499 14.105L9.891 19.861L19.245 10.507L13.489 4.75098L4.13499 14.105Z"
|
||||
fill="currentColor" />
|
||||
</svg>
|
||||
</span>
|
||||
</a>
|
||||
|
||||
{{-- Delete --}}
|
||||
<a href="#" data-id="{{ $obj['id'] }}"
|
||||
class="btn btn-icon btn-bg-light btn-active-color-primary btn-sm delete-folder-item">
|
||||
<span class="svg-icon svg-icon-3">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24"
|
||||
fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M5 9C5 8.44772 5.44772 8 6 8H18C18.5523 8 19 8.44772 19 9V18C19 19.6569 17.6569 21 16 21H8C6.34315 21 5 19.6569 5 18V9Z"
|
||||
fill="currentColor" />
|
||||
<path opacity="0.5"
|
||||
d="M5 5C5 4.44772 5.44772 4 6 4H18C18.5523 4 19 4.44772 19 5V5C19 5.55228 18.5523 6 18 6H6C5.44772 6 5 5.55228 5 5V5Z"
|
||||
fill="currentColor" />
|
||||
<path opacity="0.5"
|
||||
d="M9 4C9 3.44772 9.44772 3 10 3H14C14.5523 3 15 3.44772 15 4V4H9V4Z"
|
||||
fill="currentColor" />
|
||||
</svg>
|
||||
</span>
|
||||
</a>
|
||||
</td>
|
||||
|
||||
|
||||
</tr>
|
||||
@endforeach
|
||||
|
||||
|
||||
@foreach ($itemView as $obj)
|
||||
<tr>
|
||||
|
||||
<td class="d-flex align-items-center">
|
||||
<!--begin:: Avatar -->
|
||||
<div class="symbol symbol-100px overflow-hidden me-3">
|
||||
<a class="show-image-preview"
|
||||
href="{{ env('R2_SCHEMA_URL') . $obj['name'] }}">
|
||||
<div class="symbol-label">
|
||||
<img src="{{ env('R2_SCHEMA_URL') . $obj['name'] }}"
|
||||
alt="Emma Smith" class="w-100">
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
<div class="d-flex flex-column">
|
||||
<a href="#"
|
||||
class="text-gray-800 text-hover-primary mb-1">{{ $obj['name'] }}</a>
|
||||
|
||||
</div>
|
||||
<!--begin::User details-->
|
||||
</td>
|
||||
|
||||
|
||||
<td>
|
||||
{{ Carbon\Carbon::parse($obj['created_at'])->format('d, M Y') }}
|
||||
</td>
|
||||
|
||||
|
||||
<td class="min-w-100px text-end">
|
||||
|
||||
{{-- Download --}}
|
||||
<a download="{{ env('R2_SCHEMA_URL') . $obj['name'] }}"
|
||||
href="{{ env('R2_SCHEMA_URL') . $obj['name'] }}" target="_blank"
|
||||
class="btn btn-sm btn-icon btn-light btn-active-light-primary"
|
||||
type="button" data-bs-toggle="tooltip" aria-label="Coming soon"
|
||||
data-bs-original-title="Coming soon" data-kt-initialized="1">
|
||||
<i class="bi bi-download fs-3"></i>
|
||||
</a>
|
||||
|
||||
{{-- Copy --}}
|
||||
<button type="button" data-action="copy"
|
||||
data-url="{{ env('R2_SCHEMA_URL') . $obj['name'] }}"
|
||||
class="btn btn-sm btn-icon btn-light btn-active-light-primary copy-button">
|
||||
<span class="svg-icon svg-icon-2">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24"
|
||||
fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path opacity="0.5"
|
||||
d="M18 2H9C7.34315 2 6 3.34315 6 5H8C8 4.44772 8.44772 4 9 4H18C18.5523 4 19 4.44772 19 5V16C19 16.5523 18.5523 17 18 17V19C19.6569 19 21 17.6569 21 16V5C21 3.34315 19.6569 2 18 2Z"
|
||||
fill="currentColor"></path>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd"
|
||||
d="M14.7857 7.125H6.21429C5.62255 7.125 5.14286 7.6007 5.14286 8.1875V18.8125C5.14286 19.3993 5.62255 19.875 6.21429 19.875H14.7857C15.3774 19.875 15.8571 19.3993 15.8571 18.8125V8.1875C15.8571 7.6007 15.3774 7.125 14.7857 7.125ZM6.21429 5C4.43908 5 3 6.42709 3 8.1875V18.8125C3 20.5729 4.43909 22 6.21429 22H14.7857C16.5609 22 18 20.5729 18 18.8125V8.1875C18 6.42709 16.5609 5 14.7857 5H6.21429Z"
|
||||
fill="currentColor"></path>
|
||||
</svg>
|
||||
</span>
|
||||
<!--end::Svg Icon-->
|
||||
</button>
|
||||
|
||||
|
||||
{{-- Delete --}}
|
||||
@if (Auth::user()->role != 2)
|
||||
<a href="#" data-id="{{ $obj['id'] }}"
|
||||
class="btn btn-icon btn-bg-light btn-active-color-primary btn-sm delete-item">
|
||||
<span class="svg-icon svg-icon-3">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24"
|
||||
fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M5 9C5 8.44772 5.44772 8 6 8H18C18.5523 8 19 8.44772 19 9V18C19 19.6569 17.6569 21 16 21H8C6.34315 21 5 19.6569 5 18V9Z"
|
||||
fill="currentColor" />
|
||||
<path opacity="0.5"
|
||||
d="M5 5C5 4.44772 5.44772 4 6 4H18C18.5523 4 19 4.44772 19 5V5C19 5.55228 18.5523 6 18 6H6C5.44772 6 5 5.55228 5 5V5Z"
|
||||
fill="currentColor" />
|
||||
<path opacity="0.5"
|
||||
d="M9 4C9 3.44772 9.44772 3 10 3H14C14.5523 3 15 3.44772 15 4V4H9V4Z"
|
||||
fill="currentColor" />
|
||||
</svg>
|
||||
</span>
|
||||
</a>
|
||||
@endif
|
||||
</td>
|
||||
|
||||
|
||||
</tr>
|
||||
@endforeach
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@stop
|
||||
|
||||
|
||||
@section('script')
|
||||
|
||||
<script type="text/javascript">
|
||||
const baseUrl = "{{ url('image') }}";
|
||||
var datatable;
|
||||
datatable = $("#data-table").DataTable({
|
||||
"info": false,
|
||||
"order": [],
|
||||
"pageLength": 25,
|
||||
lengthMenu: [
|
||||
[10, 25, 50, 100, 500, 1000],
|
||||
[10, 25, 50, 100, 500, 1000]
|
||||
]
|
||||
});
|
||||
|
||||
// Filter by search
|
||||
const filterSearch = document.querySelector('[table-filter="search"]');
|
||||
filterSearch.addEventListener('keyup', function(e) {
|
||||
datatable.search(e.target.value).draw();
|
||||
});
|
||||
|
||||
// filter by status
|
||||
const filterStatus = document.querySelector('[table-filter="status"]');
|
||||
$(filterStatus).on('change', e => {
|
||||
let value = e.target.value;
|
||||
if (value === 'all') {
|
||||
value = '';
|
||||
}
|
||||
datatable.column(4).search(value).draw();
|
||||
});
|
||||
|
||||
|
||||
// Remove
|
||||
$(document).on('click', '.delete-item', function() {
|
||||
swal.fire({
|
||||
allowOutsideClick: false,
|
||||
text: "Are you sure you would like to Delete?",
|
||||
icon: "warning",
|
||||
buttonsStyling: false,
|
||||
showDenyButton: true,
|
||||
confirmButtonText: "Yes",
|
||||
denyButtonText: 'No',
|
||||
customClass: {
|
||||
confirmButton: "btn btn-primary",
|
||||
denyButton: "btn btn-light-danger"
|
||||
}
|
||||
}).then((result) => {
|
||||
if (result.isConfirmed) {
|
||||
|
||||
alertLoading("Loading")
|
||||
|
||||
// set up ajax
|
||||
initAjaxSetupToken();
|
||||
|
||||
const ajaxProp = {
|
||||
url: "{{ url('image/delete') }}",
|
||||
type: 'POST',
|
||||
data: {
|
||||
item_id: $(this).data('id')
|
||||
},
|
||||
};
|
||||
|
||||
$.ajax(ajaxProp).done(function(res) {
|
||||
if (res.status) {
|
||||
const url = "{{ url('image') }}";
|
||||
alertSuccessWithUrl('Notice', "Delete success", url);
|
||||
hideLoading();
|
||||
} else {
|
||||
alertFail('Notice', res.message ?? "Unsuccessfully");
|
||||
hideLoading();
|
||||
}
|
||||
}).fail(function(xhr, status, error) {
|
||||
logAjaxError(xhr, status, error);
|
||||
alertFail('Notice', error.message ?? "Unsuccessfully");
|
||||
hideLoading();
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const copyButtons = document.querySelectorAll('.copy-button');
|
||||
|
||||
copyButtons.forEach(button => {
|
||||
button.addEventListener('click', function() {
|
||||
const urlToCopy = button.getAttribute('data-url');
|
||||
|
||||
// Copy the URL to the clipboard
|
||||
navigator.clipboard.writeText(urlToCopy).then(() => {
|
||||
alert(
|
||||
'Link copied to clipboard!'
|
||||
); // You can change this to a toast notification
|
||||
}).catch(err => {
|
||||
console.error('Could not copy text: ', err);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
|
||||
// Delete folder
|
||||
$(document).on('click', '.delete-folder-item', function() {
|
||||
swal.fire({
|
||||
allowOutsideClick: false,
|
||||
text: "Are you sure you would like to Delete?",
|
||||
icon: "warning",
|
||||
buttonsStyling: false,
|
||||
showDenyButton: true,
|
||||
confirmButtonText: "Yes",
|
||||
denyButtonText: 'No',
|
||||
customClass: {
|
||||
confirmButton: "btn btn-primary",
|
||||
denyButton: "btn btn-light-danger"
|
||||
}
|
||||
}).then((result) => {
|
||||
if (result.isConfirmed) {
|
||||
|
||||
alertLoading("Loading")
|
||||
|
||||
// set up ajax
|
||||
initAjaxSetupToken();
|
||||
|
||||
const ajaxProp = {
|
||||
url: "{{ url('image/delete-folder') }}",
|
||||
type: 'POST',
|
||||
data: {
|
||||
item_id: $(this).data('id')
|
||||
},
|
||||
};
|
||||
|
||||
$.ajax(ajaxProp).done(function(res) {
|
||||
if (res.status) {
|
||||
const url = "{{ url('image') }}";
|
||||
alertSuccessWithUrl('Notice', "Delete success", url);
|
||||
hideLoading();
|
||||
} else {
|
||||
alertFail('Notice', res.message ?? "Unsuccessfully");
|
||||
hideLoading();
|
||||
}
|
||||
}).fail(function(xhr, status, error) {
|
||||
logAjaxError(xhr, status, error);
|
||||
alertFail('Notice', error.message ?? "Unsuccessfully");
|
||||
hideLoading();
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
@endsection
|
||||
@@ -0,0 +1,131 @@
|
||||
@extends('layouts.loginTemplate')
|
||||
|
||||
@section('content')
|
||||
|
||||
<form class="form w-100" novalidate="novalidate" id="frm-login" method="post" action="{{ url('authenticate') }}">
|
||||
|
||||
<input type="hidden" name="_method" value="POST">
|
||||
<input type="hidden" name="_token" value="{{ csrf_token() }}">
|
||||
|
||||
<!--begin::Heading-->
|
||||
<div class="text-center mb-11">
|
||||
<!--begin::Title-->
|
||||
<h1 class="text-dark fw-bolder mb-3">
|
||||
<img src="{{ url('assets/media/logos/footer-logo.png') }}" alt="" />
|
||||
</h1>
|
||||
<!--end::Title-->
|
||||
</div>
|
||||
<!--begin::Heading-->
|
||||
|
||||
|
||||
<!--begin::Input group=-->
|
||||
<div class="fv-row mb-8">
|
||||
<!--begin::Email-->
|
||||
<input type="email" placeholder="Email" name="email" autocomplete="off"
|
||||
class="form-control bg-transparent" />
|
||||
<!--end::Email-->
|
||||
</div>
|
||||
|
||||
<!--end::Input group=-->
|
||||
<div class="fv-row mb-3">
|
||||
<!--begin::Password-->
|
||||
<input id="input-password" type="password" placeholder="Password" name="password" autocomplete="off"
|
||||
class="form-control bg-transparent" />
|
||||
<!--end::Password-->
|
||||
</div>
|
||||
|
||||
<!--end::Input group=-->
|
||||
<!--begin::Wrapper-->
|
||||
<div class="d-flex flex-stack flex-wrap gap-3 fs-base fw-semibold mb-8">
|
||||
<div></div>
|
||||
<!--begin::Link-->
|
||||
{{-- <a href="{{ url('forgot-password') }}" class="link-primary">Forgot
|
||||
Password ?</a> --}}
|
||||
<!--end::Link-->
|
||||
</div>
|
||||
<!--end::Wrapper-->
|
||||
|
||||
<!--begin::Submit button-->
|
||||
<div class="d-grid mb-10">
|
||||
<button type="button" id="btn-login" class="btn btn-primary">
|
||||
<!--begin::Indicator label-->
|
||||
<span class="indicator-label">Sign In</span>
|
||||
<!--end::Indicator label-->
|
||||
<!--begin::Indicator progress-->
|
||||
<span class="indicator-progress">Please wait...
|
||||
<span class="spinner-border spinner-border-sm align-middle ms-2"></span></span>
|
||||
<!--end::Indicator progress-->
|
||||
</button>
|
||||
</div>
|
||||
<!--end::Submit button-->
|
||||
|
||||
</form>
|
||||
|
||||
@stop
|
||||
|
||||
@section('script')
|
||||
|
||||
<script type="text/javascript">
|
||||
$(function() {
|
||||
|
||||
$(document).on("click", "#btn-login", function(e) {
|
||||
|
||||
// handle bomb click
|
||||
e.preventDefault();
|
||||
|
||||
alertLoading("Loading")
|
||||
|
||||
formSubmit()
|
||||
})
|
||||
|
||||
var inputPassword = document.getElementById("input-password");
|
||||
|
||||
// Execute a function when the user presses a key on the keyboard
|
||||
inputPassword.addEventListener("keypress", function(event) {
|
||||
// If the user presses the "Enter" key on the keyboard
|
||||
if (event.key === "Enter") {
|
||||
// Cancel the default action, if needed
|
||||
event.preventDefault();
|
||||
alertLoading("Loading")
|
||||
// Trigger the button element with a click
|
||||
document.getElementById("btn-login").click();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
|
||||
function formSubmit() {
|
||||
// form data
|
||||
const form = $('#frm-login')[0];
|
||||
const formData = new FormData(form);
|
||||
|
||||
// set up ajax
|
||||
initAjaxSetupToken();
|
||||
|
||||
const ajaxProp = {
|
||||
url: "{{ url('authenticate') }}",
|
||||
dataType: 'json',
|
||||
method: 'post',
|
||||
data: formData,
|
||||
processData: false,
|
||||
contentType: false,
|
||||
};
|
||||
|
||||
$.ajax(ajaxProp).done(function(res) {
|
||||
if (isAjaxStatusSuccess(res.status)) {
|
||||
window.location.href = '{{ url('dashboard') }}';
|
||||
hideLoading();
|
||||
} else {
|
||||
alertFail('Notice', res.message ?? "Login unsuccessfully");
|
||||
hideLoading();
|
||||
}
|
||||
}).fail(function(xhr, status, error) {
|
||||
logAjaxError(xhr, status, error);
|
||||
alertFail('Notice', error.message ?? "Login unsuccessfully");
|
||||
hideLoading();
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
@endsection
|
||||
@@ -0,0 +1,110 @@
|
||||
@extends('layouts/backendTemplate')
|
||||
|
||||
@section('content')
|
||||
|
||||
<div class="row">
|
||||
<div class="col-xs-12">
|
||||
<div class="page-title-box">
|
||||
<h4 class="page-title m-b-20">Profile</h4>
|
||||
<ol class="breadcrumb p-0 m-0">
|
||||
<li>@include('uc.backHome')</li>
|
||||
<li>
|
||||
<a href="{{ url('profile') }}">User</a>
|
||||
</li>
|
||||
<li class="active">
|
||||
Profile
|
||||
</li>
|
||||
</ol>
|
||||
<div class="clearfix"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
|
||||
<div class="col-md-12">
|
||||
|
||||
<!-- Message -->
|
||||
<div class="form-group">
|
||||
<div class="form-group">
|
||||
@if (Session::has('messageSuccess'))
|
||||
@include('uc/messageSuccess')
|
||||
@endif
|
||||
|
||||
@if (Session::has('messageFail'))
|
||||
@include('uc/messageFail')
|
||||
@endif
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="panel">
|
||||
<div class="panel-heading">
|
||||
<h3 class="panel-title">Profile</h3>
|
||||
</div>
|
||||
|
||||
<div class="panel-body">
|
||||
|
||||
<form class="form-horizontal" action="{{ url('update-profile') }}" method="post"
|
||||
enctype="multipart/form-data">
|
||||
|
||||
<input type="hidden" name="_method" value="POST">
|
||||
<input type="hidden" name="_token" value="{{ csrf_token() }}">
|
||||
|
||||
<!-- First Name -->
|
||||
<div class="form-group">
|
||||
<label class="col-md-2 control-label">First Name</label>
|
||||
<div class="col-md-10">
|
||||
<input type="text" id="first_name" class="form-control" name="first_name"
|
||||
value="{{ $profileView->first_name }}">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Last Name -->
|
||||
<div class="form-group">
|
||||
<label class="col-md-2 control-label">Last Name</label>
|
||||
<div class="col-md-10">
|
||||
<input type="text" id="last_name" class="form-control" name="last_name"
|
||||
value="{{ $profileView->last_name }}">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Password -->
|
||||
<div class="form-group">
|
||||
<label class="col-md-2 control-label">Password</label>
|
||||
<div class="col-md-10">
|
||||
<input type="password" id="password" class="form-control" name="password" value="">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Email -->
|
||||
<div class="form-group">
|
||||
<label class="col-md-2 control-label">Email</label>
|
||||
<div class="col-md-10">
|
||||
<input readonly type="text" id="email" class="form-control" name="email"
|
||||
value="{{ $profileView->email }}">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Button -->
|
||||
<div class="text-center">
|
||||
<button type="submit" class="btn btn-success waves-effect waves-light">Save</button>
|
||||
<button type="reset" class="btn btn-danger waves-effect waves-light">Cancel</button>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
@stop
|
||||
|
||||
@section('script')
|
||||
|
||||
@endsection
|
||||
@@ -0,0 +1,122 @@
|
||||
@extends('layouts.loginTemplate')
|
||||
|
||||
@section('content')
|
||||
|
||||
<form class="form w-100" novalidate="novalidate" id="frm-reset-password" method="post"
|
||||
action="{{ url('post-reset-password') }}">
|
||||
|
||||
<input type="hidden" name="userId" value="{{ $userIdView }}">
|
||||
<input type="hidden" name="_method" value="POST">
|
||||
<input type="hidden" name="_token" value="{{ csrf_token() }}">
|
||||
|
||||
<!--begin::Heading-->
|
||||
<div class="text-center mb-11">
|
||||
<!--begin::Title-->
|
||||
<h1 class="text-dark fw-bolder mb-3">Reset Password</h1>
|
||||
<!--end::Title-->
|
||||
</div>
|
||||
<!--begin::Heading-->
|
||||
|
||||
|
||||
<!--begin::Input group=-->
|
||||
<div class="fv-row mb-8">
|
||||
<!--begin::Email-->
|
||||
<input type="password" placeholder="Password" name="password" autocomplete="off"
|
||||
class="form-control bg-transparent" />
|
||||
<!--end::Email-->
|
||||
</div>
|
||||
|
||||
<!--end::Input group=-->
|
||||
<!--begin::Wrapper-->
|
||||
<div class="d-flex flex-stack flex-wrap gap-3 fs-base fw-semibold mb-8">
|
||||
<div></div>
|
||||
<!--begin::Link-->
|
||||
<a href="{{ url('login') }}" class="link-primary">Login ?</a>
|
||||
<!--end::Link-->
|
||||
</div>
|
||||
<!--end::Wrapper-->
|
||||
|
||||
<!--begin::Submit button-->
|
||||
<div class="d-grid mb-10">
|
||||
<button type="button" id="btn-submit" class="btn btn-primary">
|
||||
<!--begin::Indicator label-->
|
||||
<span class="indicator-label">Submit</span>
|
||||
<!--end::Indicator label-->
|
||||
<!--begin::Indicator progress-->
|
||||
<span class="indicator-progress">Please wait...
|
||||
<span class="spinner-border spinner-border-sm align-middle ms-2"></span></span>
|
||||
<!--end::Indicator progress-->
|
||||
</button>
|
||||
</div>
|
||||
<!--end::Submit button-->
|
||||
|
||||
</form>
|
||||
|
||||
@stop
|
||||
|
||||
@section('script')
|
||||
|
||||
<script type="text/javascript">
|
||||
$(function() {
|
||||
|
||||
$(document).on("click", "#btn-submit", function(e) {
|
||||
|
||||
// handle bomb click
|
||||
e.preventDefault();
|
||||
|
||||
alertLoading("Loading")
|
||||
|
||||
formSubmit()
|
||||
})
|
||||
|
||||
var inputPassword = document.getElementById("input-password");
|
||||
|
||||
// Execute a function when the user presses a key on the keyboard
|
||||
inputPassword.addEventListener("keypress", function(event) {
|
||||
// If the user presses the "Enter" key on the keyboard
|
||||
if (event.key === "Enter") {
|
||||
// Cancel the default action, if needed
|
||||
event.preventDefault();
|
||||
alertLoading("Loading")
|
||||
// Trigger the button element with a click
|
||||
document.getElementById("btn-submit").click();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
|
||||
function formSubmit() {
|
||||
// form data
|
||||
const form = $('#frm-reset-password')[0];
|
||||
const formData = new FormData(form);
|
||||
|
||||
// set up ajax
|
||||
initAjaxSetupToken();
|
||||
|
||||
const ajaxProp = {
|
||||
url: "{{ url('post-reset-password') }}",
|
||||
dataType: 'json',
|
||||
method: 'post',
|
||||
data: formData,
|
||||
processData: false,
|
||||
contentType: false,
|
||||
};
|
||||
|
||||
$.ajax(ajaxProp).done(function(res) {
|
||||
if (isAjaxStatusSuccess(res.status)) {
|
||||
alertSuccess('Notice', 'Please check your email address')
|
||||
window.location.href = '{{ url('') }}';
|
||||
hideLoading();
|
||||
} else {
|
||||
alertFail('Notice', res.message ?? "Reset password unsuccessfully");
|
||||
}
|
||||
}).fail(function(xhr, status, error) {
|
||||
logAjaxError(xhr, status, error);
|
||||
alertFail('Notice', error.message ?? "Reset password unsuccessfully");
|
||||
hideLoading();
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
@endsection
|
||||
@@ -0,0 +1,365 @@
|
||||
@extends('layouts.backendTemplate')
|
||||
|
||||
@section('content')
|
||||
|
||||
<style>
|
||||
#progressBar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.progress-bar {
|
||||
width: 100%;
|
||||
height: 10px;
|
||||
border-radius: 5px;
|
||||
margin-top: 10px;
|
||||
appearance: none;
|
||||
}
|
||||
|
||||
.progress-bar::-webkit-progress-value {
|
||||
background-color: #4CAF50;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.progress-text {
|
||||
margin-top: 10px;
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
}
|
||||
</style>
|
||||
|
||||
<!--begin::Main-->
|
||||
<div class="app-main flex-column flex-row-fluid" id="kt_app_main">
|
||||
|
||||
<div class="d-flex flex-column flex-column-fluid">
|
||||
|
||||
|
||||
@include('uc.admin.breadcrumb', [
|
||||
'title' => 'Sound Add',
|
||||
'pageName' => 'Add',
|
||||
'pageParent' => 'Sound Management',
|
||||
'pageParentLink' => url('sound'),
|
||||
])
|
||||
|
||||
<div id="kt_app_content" class="app-content flex-column-fluid">
|
||||
<div id="kt_app_content_container" class="app-container container-xxl">
|
||||
|
||||
|
||||
|
||||
<form id="frmAdd" class="form d-flex flex-column flex-lg-row" method="post"
|
||||
enctype="multipart/form-data">
|
||||
|
||||
<input type="hidden" name="_method" value="POST">
|
||||
<input type="hidden" name="_token" value="{{ csrf_token() }}">
|
||||
|
||||
|
||||
<div class="d-flex flex-column flex-row-fluid gap-7 gap-lg-10">
|
||||
|
||||
<div class="card card-flush py-4">
|
||||
|
||||
|
||||
@if (Session::has('messageSuccess'))
|
||||
<div class="card-body">
|
||||
@include('uc/messageSuccess')
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@if (Session::has('messageFail'))
|
||||
<div class="card-body">
|
||||
@include('uc/messageFail')
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<div class="card-header">
|
||||
<div class="card-title">
|
||||
<h2>Overview</h2>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card-body pt-0">
|
||||
|
||||
<div class="mb-10">
|
||||
<label class="form-label required">File Sound</label>
|
||||
|
||||
<input class="fileInput file-input" type="file" id="fileInput" name="fileInput"
|
||||
multiple accept=".m4a, .mp4, .mp3, .wav">
|
||||
|
||||
<progress id="progressBar" class="progress-bar" value="0"
|
||||
max="100"></progress>
|
||||
<div id="progressText" class="progress-text">0%</div>
|
||||
|
||||
<div class="text-muted fs-7">Allowed Types .m4a, .mp4, .mp3, .wav</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="d-flex justify-content-end">
|
||||
|
||||
<a href="{{ url('sound') }}" id="kt_ecommerce_add_product_cancel"
|
||||
class="btn btn-light me-5">Cancel</a>
|
||||
|
||||
<button type="button" id="btn_submit" class="btn btn-primary">
|
||||
<span class="indicator-label">Save</span>
|
||||
</button>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</form>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
@stop
|
||||
|
||||
|
||||
@section('script')
|
||||
|
||||
<script>
|
||||
const baseApiUrl = "{{ env('API_URL') }}";
|
||||
|
||||
$(document).on("click", "#btn_submit", async function(e) {
|
||||
|
||||
e.preventDefault();
|
||||
|
||||
alertLoading("Loading")
|
||||
|
||||
await uploadFile();
|
||||
|
||||
});
|
||||
|
||||
|
||||
// Step 1
|
||||
async function uploadFile() {
|
||||
const fileInput = document.getElementById("fileInput");
|
||||
const progressBar = document.getElementById("progressBar");
|
||||
const progressText = document.getElementById("progressText");
|
||||
|
||||
if (!fileInput || fileInput.files.length === 0) {
|
||||
alertFail("Notice", "Please select one or more files.");
|
||||
hideLoading();
|
||||
return;
|
||||
}
|
||||
|
||||
const files = Array.from(fileInput.files); // Get all selected files
|
||||
$("#progressBar").show();
|
||||
|
||||
let totalSize = files.reduce((sum, file) => sum + file.size, 0);
|
||||
let totalUploadedSize = 0;
|
||||
|
||||
// Upload all files sequentially
|
||||
for (const file of files) {
|
||||
await uploadSingleFile(file, progressBar, progressText, totalSize, (fileUploadedSize) => {
|
||||
totalUploadedSize += fileUploadedSize;
|
||||
const overallPercent = Math.floor((totalUploadedSize / totalSize) * 100);
|
||||
animateProgress(progressBar, progressText, overallPercent);
|
||||
});
|
||||
}
|
||||
|
||||
const folderId = "{{ $folderIdView }}";
|
||||
let redirectUrl = "{{ url('sound') }}"
|
||||
if (folderId) {
|
||||
redirectUrl = `${redirectUrl}/folder/${folderId}`;
|
||||
}
|
||||
alertSuccessWithUrl("Notice", "All files uploaded successfully", redirectUrl);
|
||||
}
|
||||
|
||||
async function uploadSingleFile(file, progressBar, progressText, totalSize, updateOverallProgress) {
|
||||
const uploadId = await initiateMultipartUpload(file.name);
|
||||
const partSize = 500 * 1024 * 1024; // 500 MB per part
|
||||
const parts = [];
|
||||
let uploadedSize = 0;
|
||||
|
||||
const uploadPromises = Array.from({
|
||||
length: Math.ceil(file.size / partSize)
|
||||
},
|
||||
(_, index) => {
|
||||
const partNumber = index + 1;
|
||||
const chunk = file.slice(index * partSize, (index + 1) * partSize);
|
||||
|
||||
return (async () => {
|
||||
const presignedUrl = await getPresignedUrl(uploadId, partNumber, file.name);
|
||||
const etag = await uploadPartToS3(presignedUrl, chunk);
|
||||
|
||||
parts.push({
|
||||
PartNumber: partNumber,
|
||||
ETag: etag
|
||||
});
|
||||
|
||||
uploadedSize += chunk.size;
|
||||
updateOverallProgress(chunk.size); // Update the overall progress
|
||||
})();
|
||||
}
|
||||
);
|
||||
|
||||
await Promise.all(uploadPromises);
|
||||
await completeMultipartUpload(uploadId, parts, file.name);
|
||||
await saveFileNameToDB(file.name);
|
||||
}
|
||||
|
||||
// Step 2
|
||||
async function initiateMultipartUpload(fileName) {
|
||||
const urlUploadImage = `${baseApiUrl}/initiate-multipart-upload`;
|
||||
const response = await fetch(
|
||||
urlUploadImage, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
fileName
|
||||
}),
|
||||
}
|
||||
);
|
||||
|
||||
const {
|
||||
uploadId
|
||||
} = await response.json();
|
||||
|
||||
return uploadId;
|
||||
}
|
||||
|
||||
// Step 3
|
||||
async function getPresignedUrl(uploadId, partNumber, fileName) {
|
||||
|
||||
const urlPresigned = `${baseApiUrl}/get-presigned-url`
|
||||
const response = await fetch(
|
||||
urlPresigned, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
uploadId,
|
||||
partNumber,
|
||||
fileName
|
||||
}),
|
||||
}
|
||||
);
|
||||
const {
|
||||
url
|
||||
} = await response.json();
|
||||
return url;
|
||||
}
|
||||
|
||||
// Step 4
|
||||
async function uploadPartToS3(url, chunk) {
|
||||
const response = await fetch(url, {
|
||||
method: "PUT",
|
||||
headers: {
|
||||
"Content-Type": "application/octet-stream",
|
||||
},
|
||||
body: chunk,
|
||||
});
|
||||
if (!response.ok) {
|
||||
alertFail("Notice", "Failed to upload part")
|
||||
hideLoading();
|
||||
//throw new Error("Failed to upload part");
|
||||
}
|
||||
|
||||
const etag = `${response.headers.get("ETag")}`.replace(/"/g, "");
|
||||
|
||||
if (!etag) {
|
||||
throw new Error("Failed to retrieve ETag from the response.");
|
||||
}
|
||||
|
||||
return etag;
|
||||
}
|
||||
|
||||
// Step 5
|
||||
async function completeMultipartUpload(uploadId, parts, fileName) {
|
||||
const urlUploadComplete = `${baseApiUrl}/complete-multipart-upload`;
|
||||
const response = await fetch(urlUploadComplete, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
uploadId,
|
||||
parts,
|
||||
fileName
|
||||
}),
|
||||
});
|
||||
if (response.ok) {
|
||||
//window.location.href = "{{ url('image') }}";
|
||||
} else {
|
||||
alertFail("Notice", "Failed to upload part");
|
||||
hideLoading();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Smoothly animates the progress bar and percentage text.
|
||||
*/
|
||||
async function animateProgress(progressBar, progressText, targetPercent) {
|
||||
const currentPercent = parseInt(progressBar.value) || 0;
|
||||
// Increment the percentage smoothly
|
||||
for (let percent = currentPercent + 1; percent <= targetPercent; percent++) {
|
||||
progressBar.value = percent;
|
||||
progressText.textContent = `${percent}%`;
|
||||
|
||||
// Add a small delay to make the increment visible (10ms delay)
|
||||
await new Promise((resolve) => setTimeout(resolve, 10));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends the uploaded file name to the server using AJAX.
|
||||
*/
|
||||
function saveFileNameToDB(fileName) {
|
||||
initAjaxSetupToken();
|
||||
|
||||
const folderId = "{{ $folderIdView }}";
|
||||
const url = "{{ url('') }}";
|
||||
|
||||
return $.ajax({
|
||||
url: `${url}/sound/insert`,
|
||||
type: 'POST',
|
||||
contentType: 'application/json',
|
||||
data: JSON.stringify({
|
||||
fileName,
|
||||
folderId
|
||||
}),
|
||||
success: (response) => {
|
||||
console.log('File name saved:', response);
|
||||
},
|
||||
error: (err) => {
|
||||
console.error('Error saving file name:', err);
|
||||
alertFail("Notice", "There was an error saving the file name.");
|
||||
hideLoading();
|
||||
return;
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<script>
|
||||
$('.file-input').fileuploader({
|
||||
extensions: ['m4a', 'mp4', 'mp3', 'wav'],
|
||||
limit: null,
|
||||
fileMaxSize: null,
|
||||
changeInput: '<div class="fileuploader-input">' +
|
||||
'<div class="fileuploader-input-inner">' +
|
||||
'<p><i class="fileuploader-icon-main"></i></p>' +
|
||||
'<h6>Drag and drop files here</h6>' +
|
||||
'<p>or</p>' +
|
||||
'<br>' +
|
||||
'<button type="button" class="fileuploader-input-button"><span>${captions.button}</span></button>' +
|
||||
'</div>' +
|
||||
'</div>',
|
||||
theme: 'dragdrop',
|
||||
});
|
||||
</script>
|
||||
|
||||
@endsection
|
||||
@@ -0,0 +1,95 @@
|
||||
@extends('layouts.backendTemplate')
|
||||
|
||||
@section('content')
|
||||
|
||||
<!--begin::Main-->
|
||||
<div class="app-main flex-column flex-row-fluid" id="kt_app_main">
|
||||
|
||||
<div class="d-flex flex-column flex-column-fluid">
|
||||
|
||||
|
||||
@include('uc.admin.breadcrumb', [
|
||||
'title' => 'Sound Create Folder',
|
||||
'pageName' => 'Create folder',
|
||||
'pageParent' => 'Sound Management',
|
||||
'pageParentLink' => url('sound'),
|
||||
])
|
||||
|
||||
<div id="kt_app_content" class="app-content flex-column-fluid">
|
||||
<div id="kt_app_content_container" class="app-container container-xxl">
|
||||
|
||||
<form id="frmAdd" action="{{ url('sound/insert-folder') }}" class="form d-flex flex-column flex-lg-row"
|
||||
method="post" enctype="multipart/form-data">
|
||||
|
||||
<input type="hidden" name="_method" value="POST">
|
||||
<input type="hidden" name="_token" value="{{ csrf_token() }}">
|
||||
|
||||
|
||||
<div class="d-flex flex-column flex-row-fluid gap-7 gap-lg-10">
|
||||
|
||||
<div class="card card-flush py-4">
|
||||
|
||||
|
||||
@if (Session::has('messageSuccess'))
|
||||
<div class="card-body">
|
||||
@include('uc/messageSuccess')
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@if (Session::has('messageFail'))
|
||||
<div class="card-body">
|
||||
@include('uc/messageFail')
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<div class="card-header">
|
||||
<div class="card-title">
|
||||
<h2>Overview</h2>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card-body pt-0">
|
||||
|
||||
<div class="mb-10 fv-row">
|
||||
<label class="required form-label">Name</label>
|
||||
<input type="text" name="name" class="form-control mb-2 col-6"
|
||||
value="{{ old('name') }}" />
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="d-flex justify-content-end">
|
||||
|
||||
<a href="{{ url('sound') }}" id="kt_ecommerce_add_product_cancel"
|
||||
class="btn btn-light me-5">Cancel</a>
|
||||
|
||||
<button type="submit" class="btn btn-primary">
|
||||
<span class="indicator-label">Save</span>
|
||||
</button>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</form>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
@stop
|
||||
|
||||
|
||||
@section('script')
|
||||
|
||||
<script></script>
|
||||
|
||||
@endsection
|
||||
@@ -0,0 +1,96 @@
|
||||
@extends('layouts.backendTemplate')
|
||||
|
||||
@section('content')
|
||||
|
||||
<!--begin::Main-->
|
||||
<div class="app-main flex-column flex-row-fluid" id="kt_app_main">
|
||||
|
||||
<div class="d-flex flex-column flex-column-fluid">
|
||||
|
||||
|
||||
@include('uc.admin.breadcrumb', [
|
||||
'title' => 'Sound Edit Folder',
|
||||
'pageName' => 'Edit folder',
|
||||
'pageParent' => 'Sound Management',
|
||||
'pageParentLink' => url('sound'),
|
||||
])
|
||||
|
||||
<div id="kt_app_content" class="app-content flex-column-fluid">
|
||||
<div id="kt_app_content_container" class="app-container container-xxl">
|
||||
|
||||
<form id="frmAdd" action="{{ url('sound/update-folder') }}" class="form d-flex flex-column flex-lg-row"
|
||||
method="post" enctype="multipart/form-data">
|
||||
|
||||
<input type="hidden" name="id" value="{{ $idView }}">
|
||||
<input type="hidden" name="_method" value="POST">
|
||||
<input type="hidden" name="_token" value="{{ csrf_token() }}">
|
||||
|
||||
|
||||
<div class="d-flex flex-column flex-row-fluid gap-7 gap-lg-10">
|
||||
|
||||
<div class="card card-flush py-4">
|
||||
|
||||
|
||||
@if (Session::has('messageSuccess'))
|
||||
<div class="card-body">
|
||||
@include('uc/messageSuccess')
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@if (Session::has('messageFail'))
|
||||
<div class="card-body">
|
||||
@include('uc/messageFail')
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<div class="card-header">
|
||||
<div class="card-title">
|
||||
<h2>Overview</h2>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card-body pt-0">
|
||||
|
||||
<div class="mb-10 fv-row">
|
||||
<label class="required form-label">Name</label>
|
||||
<input type="text" name="name" class="form-control mb-2 col-6"
|
||||
value="{{ $itemView->name }}" />
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="d-flex justify-content-end">
|
||||
|
||||
<a href="{{ url('sound') }}" id="kt_ecommerce_add_product_cancel"
|
||||
class="btn btn-light me-5">Cancel</a>
|
||||
|
||||
<button type="submit" class="btn btn-primary">
|
||||
<span class="indicator-label">Save</span>
|
||||
</button>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</form>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
@stop
|
||||
|
||||
|
||||
@section('script')
|
||||
|
||||
<script></script>
|
||||
|
||||
@endsection
|
||||
@@ -0,0 +1,311 @@
|
||||
@extends('layouts.backendTemplate')
|
||||
|
||||
@section('content')
|
||||
|
||||
<style>
|
||||
.link-container {
|
||||
display: flex;
|
||||
/* Use flexbox for alignment */
|
||||
align-items: center;
|
||||
/* Center items vertically */
|
||||
justify-content: space-between;
|
||||
/* Space between the URL and button */
|
||||
}
|
||||
|
||||
.file-url {
|
||||
flex: 1;
|
||||
/* Allow the URL to take up available space */
|
||||
color: #007bff;
|
||||
/* Link color */
|
||||
text-decoration: none;
|
||||
/* Remove underline */
|
||||
overflow: hidden;
|
||||
/* Hide overflow */
|
||||
white-space: nowrap;
|
||||
/* Prevent text wrapping */
|
||||
text-overflow: ellipsis;
|
||||
/* Add ellipsis for overflow */
|
||||
margin-right: 10px;
|
||||
/* Space between text and button */
|
||||
}
|
||||
</style>
|
||||
|
||||
<!--begin::Main-->
|
||||
<div class="app-main flex-column flex-row-fluid" id="kt_app_main">
|
||||
|
||||
<div class="d-flex flex-column flex-column-fluid">
|
||||
|
||||
|
||||
@include('uc.breadcrumbList', [
|
||||
'title' => 'Sound Management Folder ' . $folderView->name,
|
||||
'pageName' => 'Sound Management',
|
||||
])
|
||||
|
||||
|
||||
<div id="kt_app_content" class="app-content flex-column-fluid">
|
||||
|
||||
<div id="kt_app_content_container" class="app-container container-xxl">
|
||||
|
||||
<div class="card">
|
||||
|
||||
@if (Session::has('messageSuccess'))
|
||||
<div class="card-body">
|
||||
@include('uc/messageSuccess')
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@if (Session::has('messageFail'))
|
||||
<div class="card-body">
|
||||
@include('uc/messageFail')
|
||||
</div>
|
||||
@endif
|
||||
|
||||
|
||||
<div class="card-header border-0 pt-6">
|
||||
<div class="d-flex align-items-center position-relative my-1">
|
||||
</div>
|
||||
|
||||
@if (Auth::user()->role != 2)
|
||||
<div class="card-toolbar">
|
||||
<div class="d-flex justify-content-end" data-kt-customer-table-toolbar="base">
|
||||
<a href="{{ url('sound/add/' . $folderView->id) }}" class="btn btn-primary">Add
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<div class="card-header border-0 pt-5">
|
||||
|
||||
<div class="card-title">
|
||||
<div class="d-flex align-items-center position-relative my-1">
|
||||
<span class="svg-icon svg-icon-1 position-absolute ms-4">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<rect opacity="0.5" x="17.0365" y="15.1223" width="8.15546" height="2"
|
||||
rx="1" transform="rotate(45 17.0365 15.1223)" fill="currentColor">
|
||||
</rect>
|
||||
<path
|
||||
d="M11 19C6.55556 19 3 15.4444 3 11C3 6.55556 6.55556 3 11 3C15.4444 3 19 6.55556 19 11C19 15.4444 15.4444 19 11 19ZM11 5C7.53333 5 5 7.53333 5 11C5 14.4667 7.53333 17 11 17C14.4667 17 17 14.4667 17 11C17 7.53333 14.4667 5 11 5Z"
|
||||
fill="currentColor"></path>
|
||||
</svg>
|
||||
</span>
|
||||
|
||||
<input type="text" table-filter="search"
|
||||
class="form-control form-control-solid w-250px ps-15" placeholder="Search" />
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="card-body py-4">
|
||||
<!--begin::Table-->
|
||||
<table class="table align-middle table-row-dashed fs-6 gy-5" id="data-table">
|
||||
<!--begin::Table head-->
|
||||
<thead>
|
||||
<!--begin::Table row-->
|
||||
<tr class="text-start text-muted fw-bold fs-7 text-uppercase gs-0">
|
||||
<th class="min-w-125px">Name</th>
|
||||
<th class="min-w-125px">Created</th>
|
||||
<th class="text-end min-w-100px">Manage</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody class="text-gray-600 fw-semibold">
|
||||
|
||||
@foreach ($itemView as $obj)
|
||||
<tr>
|
||||
<td>
|
||||
<div class="d-flex flex-column">
|
||||
<a href="#" class="text-gray-800 text-hover-primary mb-1">
|
||||
|
||||
<audio controls class="me-3">
|
||||
<source src="{{ env('R2_SCHEMA_URL') . $obj['name'] }}"
|
||||
type="audio/mp4">
|
||||
Your browser does not support the audio element.
|
||||
</audio>
|
||||
</a>
|
||||
<span>{{ $obj['name'] }}</span>
|
||||
</div>
|
||||
</td>
|
||||
|
||||
|
||||
<td>
|
||||
{{ Carbon\Carbon::parse($obj['created_at'])->format('d, M Y') }}
|
||||
</td>
|
||||
|
||||
<td class="min-w-100px text-end">
|
||||
|
||||
{{-- Download --}}
|
||||
<a href="{{ env('R2_SCHEMA_URL') . $obj['name'] }}" target="_blank"
|
||||
class="btn btn-sm btn-icon btn-light btn-active-light-primary"
|
||||
type="button" data-bs-toggle="tooltip" aria-label="Coming soon"
|
||||
data-bs-original-title="Coming soon" data-kt-initialized="1">
|
||||
<i class="bi bi-download fs-3"></i>
|
||||
</a>
|
||||
|
||||
{{-- Copy --}}
|
||||
<button type="button" data-action="copy"
|
||||
data-url="{{ env('R2_SCHEMA_URL') . $obj['name'] }}"
|
||||
class="btn btn-sm btn-icon btn-light btn-active-light-primary copy-button">
|
||||
<span class="svg-icon svg-icon-2">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24"
|
||||
fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path opacity="0.5"
|
||||
d="M18 2H9C7.34315 2 6 3.34315 6 5H8C8 4.44772 8.44772 4 9 4H18C18.5523 4 19 4.44772 19 5V16C19 16.5523 18.5523 17 18 17V19C19.6569 19 21 17.6569 21 16V5C21 3.34315 19.6569 2 18 2Z"
|
||||
fill="currentColor"></path>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd"
|
||||
d="M14.7857 7.125H6.21429C5.62255 7.125 5.14286 7.6007 5.14286 8.1875V18.8125C5.14286 19.3993 5.62255 19.875 6.21429 19.875H14.7857C15.3774 19.875 15.8571 19.3993 15.8571 18.8125V8.1875C15.8571 7.6007 15.3774 7.125 14.7857 7.125ZM6.21429 5C4.43908 5 3 6.42709 3 8.1875V18.8125C3 20.5729 4.43909 22 6.21429 22H14.7857C16.5609 22 18 20.5729 18 18.8125V8.1875C18 6.42709 16.5609 5 14.7857 5H6.21429Z"
|
||||
fill="currentColor"></path>
|
||||
</svg>
|
||||
</span>
|
||||
<!--end::Svg Icon-->
|
||||
</button>
|
||||
|
||||
|
||||
{{-- Delete --}}
|
||||
@if (Auth::user()->role != 2)
|
||||
<a href="#" data-id="{{ $obj['id'] }}"
|
||||
class="btn btn-icon btn-bg-light btn-active-color-primary btn-sm delete-item">
|
||||
<span class="svg-icon svg-icon-3">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24"
|
||||
fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M5 9C5 8.44772 5.44772 8 6 8H18C18.5523 8 19 8.44772 19 9V18C19 19.6569 17.6569 21 16 21H8C6.34315 21 5 19.6569 5 18V9Z"
|
||||
fill="currentColor" />
|
||||
<path opacity="0.5"
|
||||
d="M5 5C5 4.44772 5.44772 4 6 4H18C18.5523 4 19 4.44772 19 5V5C19 5.55228 18.5523 6 18 6H6C5.44772 6 5 5.55228 5 5V5Z"
|
||||
fill="currentColor" />
|
||||
<path opacity="0.5"
|
||||
d="M9 4C9 3.44772 9.44772 3 10 3H14C14.5523 3 15 3.44772 15 4V4H9V4Z"
|
||||
fill="currentColor" />
|
||||
</svg>
|
||||
</span>
|
||||
</a>
|
||||
@endif
|
||||
</td>
|
||||
|
||||
|
||||
</tr>
|
||||
@endforeach
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@stop
|
||||
|
||||
|
||||
@section('script')
|
||||
|
||||
<script type="text/javascript">
|
||||
const baseUrl = "{{ url('sound') }}";
|
||||
var datatable;
|
||||
datatable = $("#data-table").DataTable({
|
||||
"info": false,
|
||||
"order": [],
|
||||
"pageLength": 25,
|
||||
lengthMenu: [
|
||||
[10, 25, 50, 100, 500, 1000],
|
||||
[10, 25, 50, 100, 500, 1000]
|
||||
]
|
||||
});
|
||||
|
||||
// Filter by search
|
||||
const filterSearch = document.querySelector('[table-filter="search"]');
|
||||
filterSearch.addEventListener('keyup', function(e) {
|
||||
datatable.search(e.target.value).draw();
|
||||
});
|
||||
|
||||
// filter by status
|
||||
const filterStatus = document.querySelector('[table-filter="status"]');
|
||||
$(filterStatus).on('change', e => {
|
||||
let value = e.target.value;
|
||||
if (value === 'all') {
|
||||
value = '';
|
||||
}
|
||||
datatable.column(4).search(value).draw();
|
||||
});
|
||||
|
||||
|
||||
// Remove
|
||||
$(document).on('click', '.delete-item', function() {
|
||||
swal.fire({
|
||||
allowOutsideClick: false,
|
||||
text: "Are you sure you would like to Delete?",
|
||||
icon: "warning",
|
||||
buttonsStyling: false,
|
||||
showDenyButton: true,
|
||||
confirmButtonText: "Yes",
|
||||
denyButtonText: 'No',
|
||||
customClass: {
|
||||
confirmButton: "btn btn-primary",
|
||||
denyButton: "btn btn-light-danger"
|
||||
}
|
||||
}).then((result) => {
|
||||
if (result.isConfirmed) {
|
||||
|
||||
alertLoading("Loading")
|
||||
|
||||
// set up ajax
|
||||
initAjaxSetupToken();
|
||||
|
||||
const ajaxProp = {
|
||||
url: "{{ url('sound/delete') }}",
|
||||
type: 'POST',
|
||||
data: {
|
||||
item_id: $(this).data('id')
|
||||
},
|
||||
};
|
||||
|
||||
// const id = $(this).data('id');
|
||||
const id = "{{ $folderView->id }}";
|
||||
|
||||
$.ajax(ajaxProp).done(function(res) {
|
||||
if (res.status) {
|
||||
const url = "{{ url('sound/folder') }}/" + id;
|
||||
alertSuccessWithUrl('Notice', "Delete success", url);
|
||||
hideLoading();
|
||||
} else {
|
||||
alertFail('Notice', res.message ?? "Unsuccessfully");
|
||||
hideLoading();
|
||||
}
|
||||
}).fail(function(xhr, status, error) {
|
||||
logAjaxError(xhr, status, error);
|
||||
alertFail('Notice', error.message ?? "Unsuccessfully");
|
||||
hideLoading();
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const copyButtons = document.querySelectorAll('.copy-button');
|
||||
|
||||
copyButtons.forEach(button => {
|
||||
button.addEventListener('click', function() {
|
||||
const urlToCopy = button.getAttribute('data-url');
|
||||
|
||||
// Copy the URL to the clipboard
|
||||
navigator.clipboard.writeText(urlToCopy).then(() => {
|
||||
alert(
|
||||
'Link copied to clipboard!'
|
||||
); // You can change this to a toast notification
|
||||
}).catch(err => {
|
||||
console.error('Could not copy text: ', err);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
@endsection
|
||||
@@ -0,0 +1,440 @@
|
||||
@extends('layouts.backendTemplate')
|
||||
|
||||
@section('content')
|
||||
|
||||
<style>
|
||||
.link-container {
|
||||
display: flex;
|
||||
/* Use flexbox for alignment */
|
||||
align-items: center;
|
||||
/* Center items vertically */
|
||||
justify-content: space-between;
|
||||
/* Space between the URL and button */
|
||||
}
|
||||
|
||||
.file-url {
|
||||
flex: 1;
|
||||
/* Allow the URL to take up available space */
|
||||
color: #007bff;
|
||||
/* Link color */
|
||||
text-decoration: none;
|
||||
/* Remove underline */
|
||||
overflow: hidden;
|
||||
/* Hide overflow */
|
||||
white-space: nowrap;
|
||||
/* Prevent text wrapping */
|
||||
text-overflow: ellipsis;
|
||||
/* Add ellipsis for overflow */
|
||||
margin-right: 10px;
|
||||
/* Space between text and button */
|
||||
}
|
||||
</style>
|
||||
|
||||
<!--begin::Main-->
|
||||
<div class="app-main flex-column flex-row-fluid" id="kt_app_main">
|
||||
|
||||
<div class="d-flex flex-column flex-column-fluid">
|
||||
|
||||
|
||||
@include('uc.breadcrumbList', [
|
||||
'title' => 'Sound Management',
|
||||
'pageName' => 'Sound Management',
|
||||
])
|
||||
|
||||
|
||||
<div id="kt_app_content" class="app-content flex-column-fluid">
|
||||
|
||||
<div id="kt_app_content_container" class="app-container container-xxl">
|
||||
|
||||
<div class="card">
|
||||
|
||||
@if (Session::has('messageSuccess'))
|
||||
<div class="card-body">
|
||||
@include('uc/messageSuccess')
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@if (Session::has('messageFail'))
|
||||
<div class="card-body">
|
||||
@include('uc/messageFail')
|
||||
</div>
|
||||
@endif
|
||||
|
||||
|
||||
<div class="card-header border-0 pt-6">
|
||||
<div class="d-flex align-items-center position-relative my-1">
|
||||
</div>
|
||||
|
||||
@if (Auth::user()->role != 2)
|
||||
<div class="card-toolbar">
|
||||
|
||||
<div class="d-flex justify-content-end" style="margin-right: 5px;"
|
||||
data-kt-customer-table-toolbar="base">
|
||||
<a href="{{ url('sound/add-folder') }}" class="btn btn-light-primary me-3"
|
||||
id="kt_file_manager_new_folder">New
|
||||
Folder</a>
|
||||
</div>
|
||||
|
||||
<div class="d-flex justify-content-end" data-kt-customer-table-toolbar="base">
|
||||
<a href="{{ url('sound/add') }}" class="btn btn-primary">Add </a>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@endif
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<div class="card-header border-0 pt-5">
|
||||
|
||||
<div class="card-title">
|
||||
<div class="d-flex align-items-center position-relative my-1">
|
||||
<span class="svg-icon svg-icon-1 position-absolute ms-4">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<rect opacity="0.5" x="17.0365" y="15.1223" width="8.15546" height="2"
|
||||
rx="1" transform="rotate(45 17.0365 15.1223)" fill="currentColor">
|
||||
</rect>
|
||||
<path
|
||||
d="M11 19C6.55556 19 3 15.4444 3 11C3 6.55556 6.55556 3 11 3C15.4444 3 19 6.55556 19 11C19 15.4444 15.4444 19 11 19ZM11 5C7.53333 5 5 7.53333 5 11C5 14.4667 7.53333 17 11 17C14.4667 17 17 14.4667 17 11C17 7.53333 14.4667 5 11 5Z"
|
||||
fill="currentColor"></path>
|
||||
</svg>
|
||||
</span>
|
||||
|
||||
<input type="text" table-filter="search"
|
||||
class="form-control form-control-solid w-250px ps-15" placeholder="Search" />
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="card-body py-4">
|
||||
<!--begin::Table-->
|
||||
<table class="table align-middle table-row-dashed fs-6 gy-5" id="data-table">
|
||||
<!--begin::Table head-->
|
||||
<thead>
|
||||
<!--begin::Table row-->
|
||||
<tr class="text-start text-muted fw-bold fs-7 text-uppercase gs-0">
|
||||
<th class="min-w-125px">Name</th>
|
||||
<th class="min-w-125px">Created</th>
|
||||
<th class="text-end min-w-100px">Action</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody class="text-gray-600 fw-semibold">
|
||||
@foreach ($folderView as $obj)
|
||||
<tr>
|
||||
<td>
|
||||
<div class="d-flex align-items-center">
|
||||
<span class="svg-icon svg-icon-2x svg-icon-primary me-4">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24"
|
||||
fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path opacity="0.3" d="M10 4H21C21.6 4 22 4.4 22 5V7H10V4Z"
|
||||
fill="currentColor"></path>
|
||||
<path
|
||||
d="M9.2 3H3C2.4 3 2 3.4 2 4V19C2 19.6 2.4 20 3 20H21C21.6 20 22 19.6 22 19V7C22 6.4 21.6 6 21 6H12L10.4 3.60001C10.2 3.20001 9.7 3 9.2 3Z"
|
||||
fill="currentColor"></path>
|
||||
</svg>
|
||||
</span>
|
||||
<a href="{{ url('sound/folder/' . $obj->id) }}"
|
||||
class="text-gray-800 text-hover-primary">
|
||||
{{ $obj->name }}</a>
|
||||
</div>
|
||||
</td>
|
||||
|
||||
<td>
|
||||
{{ Carbon\Carbon::parse($obj['created_at'])->format('d, M Y') }}
|
||||
</td>
|
||||
|
||||
<td class="min-w-100px text-end">
|
||||
|
||||
{{-- Download --}}
|
||||
<a href="{{ url('sound/download-folder') . '/' . $obj->id }}"
|
||||
class="btn-download-folder btn btn-sm btn-icon btn-light btn-active-light-primary"
|
||||
type="button" data-bs-toggle="tooltip" aria-label="Coming soon"
|
||||
data-bs-original-title="Coming soon" data-kt-initialized="1">
|
||||
<i class="bi bi-download fs-3"></i>
|
||||
</a>
|
||||
|
||||
{{-- Edit --}}
|
||||
<a href="{{ url('sound/edit-folder/' . $obj['id']) }}"
|
||||
class="btn btn-icon btn-bg-light btn-active-color-primary btn-sm me-1">
|
||||
<span class="svg-icon svg-icon-3">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24"
|
||||
fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path opacity="0.3"
|
||||
d="M21.4 8.35303L19.241 10.511L13.485 4.755L15.643 2.59595C16.0248 2.21423 16.5426 1.99988 17.0825 1.99988C17.6224 1.99988 18.1402 2.21423 18.522 2.59595L21.4 5.474C21.7817 5.85581 21.9962 6.37355 21.9962 6.91345C21.9962 7.45335 21.7817 7.97122 21.4 8.35303ZM3.68699 21.932L9.88699 19.865L4.13099 14.109L2.06399 20.309C1.98815 20.5354 1.97703 20.7787 2.03189 21.0111C2.08674 21.2436 2.2054 21.4561 2.37449 21.6248C2.54359 21.7934 2.75641 21.9115 2.989 21.9658C3.22158 22.0201 3.4647 22.0084 3.69099 21.932H3.68699Z"
|
||||
fill="currentColor" />
|
||||
<path
|
||||
d="M5.574 21.3L3.692 21.928C3.46591 22.0032 3.22334 22.0141 2.99144 21.9594C2.75954 21.9046 2.54744 21.7864 2.3789 21.6179C2.21036 21.4495 2.09202 21.2375 2.03711 21.0056C1.9822 20.7737 1.99289 20.5312 2.06799 20.3051L2.696 18.422L5.574 21.3ZM4.13499 14.105L9.891 19.861L19.245 10.507L13.489 4.75098L4.13499 14.105Z"
|
||||
fill="currentColor" />
|
||||
</svg>
|
||||
</span>
|
||||
</a>
|
||||
|
||||
{{-- Delete --}}
|
||||
<a href="#" data-id="{{ $obj['id'] }}"
|
||||
class="btn btn-icon btn-bg-light btn-active-color-primary btn-sm delete-folder-item">
|
||||
<span class="svg-icon svg-icon-3">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24"
|
||||
fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M5 9C5 8.44772 5.44772 8 6 8H18C18.5523 8 19 8.44772 19 9V18C19 19.6569 17.6569 21 16 21H8C6.34315 21 5 19.6569 5 18V9Z"
|
||||
fill="currentColor" />
|
||||
<path opacity="0.5"
|
||||
d="M5 5C5 4.44772 5.44772 4 6 4H18C18.5523 4 19 4.44772 19 5V5C19 5.55228 18.5523 6 18 6H6C5.44772 6 5 5.55228 5 5V5Z"
|
||||
fill="currentColor" />
|
||||
<path opacity="0.5"
|
||||
d="M9 4C9 3.44772 9.44772 3 10 3H14C14.5523 3 15 3.44772 15 4V4H9V4Z"
|
||||
fill="currentColor" />
|
||||
</svg>
|
||||
</span>
|
||||
</a>
|
||||
</td>
|
||||
|
||||
|
||||
</tr>
|
||||
@endforeach
|
||||
|
||||
@foreach ($itemView as $obj)
|
||||
<tr>
|
||||
<td class="d-flex align-items-center">
|
||||
<div class="d-flex flex-column">
|
||||
<a href="#" class="text-gray-800 text-hover-primary mb-1">
|
||||
|
||||
<audio controls class="me-3">
|
||||
<source src="{{ env('R2_SCHEMA_URL') . $obj['name'] }}"
|
||||
type="audio/mp4">
|
||||
Your browser does not support the audio element.
|
||||
</audio>
|
||||
</a>
|
||||
<span>{{ $obj['name'] }}</span>
|
||||
</div>
|
||||
</td>
|
||||
|
||||
|
||||
<td>
|
||||
{{ Carbon\Carbon::parse($obj['created_at'])->format('d, M Y') }}
|
||||
</td>
|
||||
|
||||
|
||||
<td class="min-w-100px text-end">
|
||||
|
||||
{{-- Download --}}
|
||||
<a href="{{ env('R2_SCHEMA_URL') . $obj['name'] }}" target="_blank"
|
||||
class="btn btn-sm btn-icon btn-light btn-active-light-primary"
|
||||
type="button" data-bs-toggle="tooltip" aria-label="Coming soon"
|
||||
data-bs-original-title="Coming soon" data-kt-initialized="1">
|
||||
<i class="bi bi-download fs-3"></i>
|
||||
</a>
|
||||
|
||||
{{-- Copy --}}
|
||||
<button type="button" data-action="copy"
|
||||
data-url="{{ env('R2_SCHEMA_URL') . $obj['name'] }}"
|
||||
class="btn btn-sm btn-icon btn-light btn-active-light-primary copy-button">
|
||||
<span class="svg-icon svg-icon-2">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24"
|
||||
fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path opacity="0.5"
|
||||
d="M18 2H9C7.34315 2 6 3.34315 6 5H8C8 4.44772 8.44772 4 9 4H18C18.5523 4 19 4.44772 19 5V16C19 16.5523 18.5523 17 18 17V19C19.6569 19 21 17.6569 21 16V5C21 3.34315 19.6569 2 18 2Z"
|
||||
fill="currentColor"></path>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd"
|
||||
d="M14.7857 7.125H6.21429C5.62255 7.125 5.14286 7.6007 5.14286 8.1875V18.8125C5.14286 19.3993 5.62255 19.875 6.21429 19.875H14.7857C15.3774 19.875 15.8571 19.3993 15.8571 18.8125V8.1875C15.8571 7.6007 15.3774 7.125 14.7857 7.125ZM6.21429 5C4.43908 5 3 6.42709 3 8.1875V18.8125C3 20.5729 4.43909 22 6.21429 22H14.7857C16.5609 22 18 20.5729 18 18.8125V8.1875C18 6.42709 16.5609 5 14.7857 5H6.21429Z"
|
||||
fill="currentColor"></path>
|
||||
</svg>
|
||||
</span>
|
||||
<!--end::Svg Icon-->
|
||||
</button>
|
||||
|
||||
|
||||
{{-- Delete --}}
|
||||
@if (Auth::user()->role != 2)
|
||||
<a href="#" data-id="{{ $obj['id'] }}"
|
||||
class="btn btn-icon btn-bg-light btn-active-color-primary btn-sm delete-item">
|
||||
<span class="svg-icon svg-icon-3">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24"
|
||||
fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M5 9C5 8.44772 5.44772 8 6 8H18C18.5523 8 19 8.44772 19 9V18C19 19.6569 17.6569 21 16 21H8C6.34315 21 5 19.6569 5 18V9Z"
|
||||
fill="currentColor" />
|
||||
<path opacity="0.5"
|
||||
d="M5 5C5 4.44772 5.44772 4 6 4H18C18.5523 4 19 4.44772 19 5V5C19 5.55228 18.5523 6 18 6H6C5.44772 6 5 5.55228 5 5V5Z"
|
||||
fill="currentColor" />
|
||||
<path opacity="0.5"
|
||||
d="M9 4C9 3.44772 9.44772 3 10 3H14C14.5523 3 15 3.44772 15 4V4H9V4Z"
|
||||
fill="currentColor" />
|
||||
</svg>
|
||||
</span>
|
||||
</a>
|
||||
@endif
|
||||
</td>
|
||||
|
||||
|
||||
</tr>
|
||||
@endforeach
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@stop
|
||||
|
||||
|
||||
@section('script')
|
||||
|
||||
<script type="text/javascript">
|
||||
const baseUrl = "{{ url('sound') }}";
|
||||
var datatable;
|
||||
datatable = $("#data-table").DataTable({
|
||||
"info": false,
|
||||
"order": [],
|
||||
"pageLength": 25,
|
||||
lengthMenu: [
|
||||
[10, 25, 50, 100, 500, 1000],
|
||||
[10, 25, 50, 100, 500, 1000]
|
||||
]
|
||||
});
|
||||
|
||||
// Filter by search
|
||||
const filterSearch = document.querySelector('[table-filter="search"]');
|
||||
filterSearch.addEventListener('keyup', function(e) {
|
||||
datatable.search(e.target.value).draw();
|
||||
});
|
||||
|
||||
// filter by status
|
||||
const filterStatus = document.querySelector('[table-filter="status"]');
|
||||
$(filterStatus).on('change', e => {
|
||||
let value = e.target.value;
|
||||
if (value === 'all') {
|
||||
value = '';
|
||||
}
|
||||
datatable.column(4).search(value).draw();
|
||||
});
|
||||
|
||||
|
||||
// Remove
|
||||
$(document).on('click', '.delete-item', function() {
|
||||
swal.fire({
|
||||
allowOutsideClick: false,
|
||||
text: "Are you sure you would like to Delete?",
|
||||
icon: "warning",
|
||||
buttonsStyling: false,
|
||||
showDenyButton: true,
|
||||
confirmButtonText: "Yes",
|
||||
denyButtonText: 'No',
|
||||
customClass: {
|
||||
confirmButton: "btn btn-primary",
|
||||
denyButton: "btn btn-light-danger"
|
||||
}
|
||||
}).then((result) => {
|
||||
if (result.isConfirmed) {
|
||||
|
||||
alertLoading("Loading")
|
||||
|
||||
// set up ajax
|
||||
initAjaxSetupToken();
|
||||
|
||||
const ajaxProp = {
|
||||
url: "{{ url('sound/delete') }}",
|
||||
type: 'POST',
|
||||
data: {
|
||||
item_id: $(this).data('id')
|
||||
},
|
||||
};
|
||||
|
||||
$.ajax(ajaxProp).done(function(res) {
|
||||
if (res.status) {
|
||||
const url = "{{ url('sound') }}";
|
||||
alertSuccessWithUrl('Notice', "Delete success", url);
|
||||
hideLoading();
|
||||
} else {
|
||||
alertFail('Notice', res.message ?? "Unsuccessfully");
|
||||
hideLoading();
|
||||
}
|
||||
}).fail(function(xhr, status, error) {
|
||||
logAjaxError(xhr, status, error);
|
||||
alertFail('Notice', error.message ?? "Unsuccessfully");
|
||||
hideLoading();
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const copyButtons = document.querySelectorAll('.copy-button');
|
||||
|
||||
copyButtons.forEach(button => {
|
||||
button.addEventListener('click', function() {
|
||||
const urlToCopy = button.getAttribute('data-url');
|
||||
|
||||
// Copy the URL to the clipboard
|
||||
navigator.clipboard.writeText(urlToCopy).then(() => {
|
||||
alert(
|
||||
'Link copied to clipboard!'
|
||||
); // You can change this to a toast notification
|
||||
}).catch(err => {
|
||||
console.error('Could not copy text: ', err);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
|
||||
// Delete folder
|
||||
$(document).on('click', '.delete-folder-item', function() {
|
||||
swal.fire({
|
||||
allowOutsideClick: false,
|
||||
text: "Are you sure you would like to Delete?",
|
||||
icon: "warning",
|
||||
buttonsStyling: false,
|
||||
showDenyButton: true,
|
||||
confirmButtonText: "Yes",
|
||||
denyButtonText: 'No',
|
||||
customClass: {
|
||||
confirmButton: "btn btn-primary",
|
||||
denyButton: "btn btn-light-danger"
|
||||
}
|
||||
}).then((result) => {
|
||||
if (result.isConfirmed) {
|
||||
|
||||
alertLoading("Loading")
|
||||
|
||||
// set up ajax
|
||||
initAjaxSetupToken();
|
||||
|
||||
const ajaxProp = {
|
||||
url: "{{ url('sound/delete-folder') }}",
|
||||
type: 'POST',
|
||||
data: {
|
||||
item_id: $(this).data('id')
|
||||
},
|
||||
};
|
||||
|
||||
$.ajax(ajaxProp).done(function(res) {
|
||||
if (res.status) {
|
||||
const url = "{{ url('sound') }}";
|
||||
alertSuccessWithUrl('Notice', "Delete success", url);
|
||||
hideLoading();
|
||||
} else {
|
||||
alertFail('Notice', res.message ?? "Unsuccessfully");
|
||||
hideLoading();
|
||||
}
|
||||
}).fail(function(xhr, status, error) {
|
||||
logAjaxError(xhr, status, error);
|
||||
alertFail('Notice', error.message ?? "Unsuccessfully");
|
||||
hideLoading();
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
@endsection
|
||||
@@ -0,0 +1,472 @@
|
||||
@extends('layouts.backendTemplate')
|
||||
|
||||
@section('content')
|
||||
|
||||
<!--begin::Main-->
|
||||
<div class="app-main flex-column flex-row-fluid" id="kt_app_main">
|
||||
|
||||
<div class="d-flex flex-column flex-column-fluid">
|
||||
|
||||
|
||||
@include('uc.admin.breadcrumb', [
|
||||
'title' => 'WHERE ELSE : Add Sub Category',
|
||||
'pageName' => 'Add',
|
||||
'pageParent' => 'Sub Category Management',
|
||||
'pageParentLink' => url('where-else/sub-category'),
|
||||
])
|
||||
|
||||
<div id="kt_app_content" class="app-content flex-column-fluid">
|
||||
<div id="kt_app_content_container" class="app-container container-xxl">
|
||||
|
||||
|
||||
|
||||
<form id="frmAdd" class="form d-flex flex-column flex-lg-row"
|
||||
action="{{ url('where-else/insert-sub-category') }}" method="post" enctype="multipart/form-data">
|
||||
|
||||
<input type="hidden" name="_method" value="POST">
|
||||
<input type="hidden" name="_token" value="{{ csrf_token() }}">
|
||||
|
||||
|
||||
<div class="d-flex flex-column gap-7 gap-lg-10 w-100 w-lg-300px mb-7 me-lg-10">
|
||||
|
||||
<div class="card card-flush py-4">
|
||||
|
||||
|
||||
<div class="card-body text-center pt-0">
|
||||
|
||||
<style>
|
||||
.image-input-placeholder {
|
||||
background-image: url('{{ url('assets/media/svg/files/blank-image.svg') }}');
|
||||
}
|
||||
|
||||
[data-bs-theme="dark"] .image-input-placeholder {
|
||||
background-image: url('../media/svg/files/blank-image-dark.svg');
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="image-input image-input-empty image-input-outline image-input-placeholder mb-3"
|
||||
data-kt-image-input="true">
|
||||
|
||||
<div class="image-input-wrapper w-150px h-150px"></div>
|
||||
|
||||
<label
|
||||
class="btn btn-icon btn-circle btn-active-color-primary w-25px h-25px bg-body shadow"
|
||||
data-kt-image-input-action="change" data-bs-toggle="tooltip"
|
||||
title="Change avatar">
|
||||
|
||||
<i class="bi bi-pencil-fill fs-7"></i>
|
||||
|
||||
<input type="file" name="avatar" accept=".png, .jpg, .jpeg" />
|
||||
<input type="hidden" name="avatar_remove" />
|
||||
|
||||
</label>
|
||||
|
||||
<span
|
||||
class="btn btn-icon btn-circle btn-active-color-primary w-25px h-25px bg-body shadow"
|
||||
data-kt-image-input-action="cancel" data-bs-toggle="tooltip"
|
||||
title="Cancel avatar">
|
||||
<i class="bi bi-x fs-2"></i>
|
||||
</span>
|
||||
|
||||
<span
|
||||
class="btn btn-icon btn-circle btn-active-color-primary w-25px h-25px bg-body shadow"
|
||||
data-kt-image-input-action="remove" data-bs-toggle="tooltip"
|
||||
title="Remove avatar">
|
||||
<i class="bi bi-x fs-2"></i>
|
||||
</span>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="text-muted fs-7">Set the profile picture. Only *.png, *.jpg and *.jpeg
|
||||
image
|
||||
files are accepted</div>
|
||||
|
||||
</div>
|
||||
|
||||
{{-- Active --}}
|
||||
<div class="card-header" style="border: unset;">
|
||||
<div class="required card-title">
|
||||
<h2>Active</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body pt-0">
|
||||
|
||||
<label class="form-check form-switch form-check-custom form-check-solid">
|
||||
<input class="form-check-input" disabled readonly name="active" type="checkbox"
|
||||
value="1" checked />
|
||||
</label>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="d-flex flex-column flex-row-fluid gap-7 gap-lg-10">
|
||||
|
||||
<div class="card card-flush py-4">
|
||||
|
||||
|
||||
@if (Session::has('messageSuccess'))
|
||||
<div class="card-body">
|
||||
@include('uc/messageSuccess')
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@if (Session::has('messageFail'))
|
||||
<div class="card-body">
|
||||
@include('uc/messageFail')
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<div class="card-header">
|
||||
<div class="card-title">
|
||||
<h2>Overview</h2>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card-body pt-0">
|
||||
|
||||
|
||||
{{-- <div class="mb-10 fv-row">
|
||||
<label class="required form-label">Date</label>
|
||||
<div class="position-relative d-flex align-items-center">
|
||||
<span class="svg-icon svg-icon-2 position-absolute mx-4">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<path opacity="0.3"
|
||||
d="M21 22H3C2.4 22 2 21.6 2 21V5C2 4.4 2.4 4 3 4H21C21.6 4 22 4.4 22 5V21C22 21.6 21.6 22 21 22Z"
|
||||
fill="currentColor" />
|
||||
<path
|
||||
d="M6 6C5.4 6 5 5.6 5 5V3C5 2.4 5.4 2 6 2C6.6 2 7 2.4 7 3V5C7 5.6 6.6 6 6 6ZM11 5V3C11 2.4 10.6 2 10 2C9.4 2 9 2.4 9 3V5C9 5.6 9.4 6 10 6C10.6 6 11 5.6 11 5ZM15 5V3C15 2.4 14.6 2 14 2C13.4 2 13 2.4 13 3V5C13 5.6 13.4 6 14 6C14.6 6 15 5.6 15 5ZM19 5V3C19 2.4 18.6 2 18 2C17.4 2 17 2.4 17 3V5C17 5.6 17.4 6 18 6C18.6 6 19 5.6 19 5Z"
|
||||
fill="currentColor" />
|
||||
<path
|
||||
d="M8.8 13.1C9.2 13.1 9.5 13 9.7 12.8C9.9 12.6 10.1 12.3 10.1 11.9C10.1 11.6 10 11.3 9.8 11.1C9.6 10.9 9.3 10.8 9 10.8C8.8 10.8 8.59999 10.8 8.39999 10.9C8.19999 11 8.1 11.1 8 11.2C7.9 11.3 7.8 11.4 7.7 11.6C7.6 11.8 7.5 11.9 7.5 12.1C7.5 12.2 7.4 12.2 7.3 12.3C7.2 12.4 7.09999 12.4 6.89999 12.4C6.69999 12.4 6.6 12.3 6.5 12.2C6.4 12.1 6.3 11.9 6.3 11.7C6.3 11.5 6.4 11.3 6.5 11.1C6.6 10.9 6.8 10.7 7 10.5C7.2 10.3 7.49999 10.1 7.89999 10C8.29999 9.90003 8.60001 9.80003 9.10001 9.80003C9.50001 9.80003 9.80001 9.90003 10.1 10C10.4 10.1 10.7 10.3 10.9 10.4C11.1 10.5 11.3 10.8 11.4 11.1C11.5 11.4 11.6 11.6 11.6 11.9C11.6 12.3 11.5 12.6 11.3 12.9C11.1 13.2 10.9 13.5 10.6 13.7C10.9 13.9 11.2 14.1 11.4 14.3C11.6 14.5 11.8 14.7 11.9 15C12 15.3 12.1 15.5 12.1 15.8C12.1 16.2 12 16.5 11.9 16.8C11.8 17.1 11.5 17.4 11.3 17.7C11.1 18 10.7 18.2 10.3 18.3C9.9 18.4 9.5 18.5 9 18.5C8.5 18.5 8.1 18.4 7.7 18.2C7.3 18 7 17.8 6.8 17.6C6.6 17.4 6.4 17.1 6.3 16.8C6.2 16.5 6.10001 16.3 6.10001 16.1C6.10001 15.9 6.2 15.7 6.3 15.6C6.4 15.5 6.6 15.4 6.8 15.4C6.9 15.4 7.00001 15.4 7.10001 15.5C7.20001 15.6 7.3 15.6 7.3 15.7C7.5 16.2 7.7 16.6 8 16.9C8.3 17.2 8.6 17.3 9 17.3C9.2 17.3 9.5 17.2 9.7 17.1C9.9 17 10.1 16.8 10.3 16.6C10.5 16.4 10.5 16.1 10.5 15.8C10.5 15.3 10.4 15 10.1 14.7C9.80001 14.4 9.50001 14.3 9.10001 14.3C9.00001 14.3 8.9 14.3 8.7 14.3C8.5 14.3 8.39999 14.3 8.39999 14.3C8.19999 14.3 7.99999 14.2 7.89999 14.1C7.79999 14 7.7 13.8 7.7 13.7C7.7 13.5 7.79999 13.4 7.89999 13.2C7.99999 13 8.2 13 8.5 13H8.8V13.1ZM15.3 17.5V12.2C14.3 13 13.6 13.3 13.3 13.3C13.1 13.3 13 13.2 12.9 13.1C12.8 13 12.7 12.8 12.7 12.6C12.7 12.4 12.8 12.3 12.9 12.2C13 12.1 13.2 12 13.6 11.8C14.1 11.6 14.5 11.3 14.7 11.1C14.9 10.9 15.2 10.6 15.5 10.3C15.8 10 15.9 9.80003 15.9 9.70003C15.9 9.60003 16.1 9.60004 16.3 9.60004C16.5 9.60004 16.7 9.70003 16.8 9.80003C16.9 9.90003 17 10.2 17 10.5V17.2C17 18 16.7 18.4 16.2 18.4C16 18.4 15.8 18.3 15.6 18.2C15.4 18.1 15.3 17.8 15.3 17.5Z"
|
||||
fill="currentColor" />
|
||||
</svg>
|
||||
</span>
|
||||
<input class="form-control form-control-solid ps-12" placeholder="Date"
|
||||
name="due_date" id="due_date" />
|
||||
</div>
|
||||
</div> --}}
|
||||
|
||||
<div class="mb-10 fv-row">
|
||||
<label class="required form-label">Subject</label>
|
||||
<input type="text" name="name" class="form-control mb-2 col-6"
|
||||
value="{{ old('name') }}" />
|
||||
</div>
|
||||
|
||||
|
||||
<div class="mb-10 fv-row">
|
||||
<label class="required form-label">Subject (EN)</label>
|
||||
<input type="text" name="name_en" class="form-control mb-2 col-6"
|
||||
value="{{ old('name_en') }}" />
|
||||
</div>
|
||||
|
||||
{{-- <div class="mb-10 fv-row">
|
||||
<label class="required form-label">Description</label>
|
||||
<div class="form-control" id="description" name="description"></div>
|
||||
<input type="hidden" id="description_input" name="description" />
|
||||
</div>
|
||||
|
||||
|
||||
<div class="mb-10 fv-row">
|
||||
<label class="required form-label">Description (EN)</label>
|
||||
<div class="form-control" id="description_en" name="description_en"></div>
|
||||
<input type="hidden" id="description_input_en" name="description_en" />
|
||||
|
||||
</div> --}}
|
||||
|
||||
{{-- <div hidden class="mb-10">
|
||||
<label class="form-label required">File Video</label>
|
||||
<input class="files-video" type="file" name="file_video[]" multiple
|
||||
accept=".MP4, .MOV">
|
||||
<div class="text-muted fs-7">Allowed Types .MP4, .MOV</div>
|
||||
</div>
|
||||
|
||||
<div hidden class="mb-10">
|
||||
<label class="form-label required">File Image</label>
|
||||
<input class="files-image" type="file" name="file_image[]" multiple
|
||||
accept=".jpg, .bmp, .jpeg, .png">
|
||||
<div class="text-muted fs-7">Allowed Types .jpg, .bmp, .jpeg, .png</div>
|
||||
</div>
|
||||
|
||||
<div hidden class="mb-10">
|
||||
<label class="form-label required">File Sound</label>
|
||||
<input class="files-sound" type="file" name="file_sound[]" multiple
|
||||
accept=".m4a, .mp4, .mp3, .wav">
|
||||
<div class="text-muted fs-7">Allowed Types .m4a, .mp4, .mp3, .wav</div>
|
||||
</div>
|
||||
|
||||
<div hidden class="mb-10">
|
||||
<label class="form-label required">File Documents</label>
|
||||
<input class="files-document" type="file" name="file_document[]" multiple
|
||||
accept=".pdf, .xls, .doc, .docx, .pptx, .csv, .txt">
|
||||
<div class="text-muted fs-7">Allowed Types .pdf, .xls, .doc, .docx, .pptx, .csv,
|
||||
.txt</div>
|
||||
</div> --}}
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="d-flex justify-content-end">
|
||||
|
||||
<a href="{{ url('where-else/sub-category') }}" id="kt_ecommerce_add_product_cancel"
|
||||
class="btn btn-light me-5">Cancel</a>
|
||||
|
||||
<button id="btn_submit" class="btn btn-primary">
|
||||
<span class="indicator-label">Save Changes</span>
|
||||
</button>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</form>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
@stop
|
||||
|
||||
|
||||
@section('script')
|
||||
|
||||
<!-- Include Editor.js core -->
|
||||
<script src="https://cdn.jsdelivr.net/npm/@editorjs/editorjs@latest"></script>
|
||||
|
||||
<!-- Include the plugins -->
|
||||
<script src="https://cdn.jsdelivr.net/npm/@editorjs/header"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/@editorjs/list"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/@editorjs/paragraph"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/@editorjs/quote"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/@editorjs/image"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/editorjs-inline-image"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/@editorjs/embed"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/@editorjs/code"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/@editorjs/table"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/@editorjs/marker"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/@editorjs/checklist"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/@editorjs/delimiter"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/@editorjs/warning"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/@editorjs/link"></script>
|
||||
|
||||
<script>
|
||||
/*
|
||||
class VideoTool {
|
||||
constructor({
|
||||
data
|
||||
}) {
|
||||
this.data = data || {};
|
||||
}
|
||||
|
||||
// Render input for video URL
|
||||
render() {
|
||||
const wrapper = document.createElement("div");
|
||||
|
||||
const input = document.createElement("input");
|
||||
input.type = "text";
|
||||
input.placeholder = "Enter video URL";
|
||||
input.value = this.data.url || "";
|
||||
input.style.width = "100%";
|
||||
|
||||
const video = document.createElement("video");
|
||||
video.controls = true;
|
||||
video.style.width = "100%";
|
||||
video.style.marginTop = "10px";
|
||||
video.src = this.data.url || "";
|
||||
|
||||
input.addEventListener("input", (event) => {
|
||||
const value = event.target.value;
|
||||
this.data.url = value;
|
||||
video.src = value;
|
||||
});
|
||||
|
||||
wrapper.appendChild(input);
|
||||
wrapper.appendChild(video);
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
// Save the video URL
|
||||
save(blockContent) {
|
||||
const input = blockContent.querySelector("input");
|
||||
return {
|
||||
url: input.value,
|
||||
};
|
||||
}
|
||||
|
||||
// Editor.js toolbox definition
|
||||
static get toolbox() {
|
||||
return {
|
||||
title: "Video",
|
||||
icon: '<svg width="20" height="20" viewBox="0 0 24 24"><path d="M10 8.64L15.27 12 10 15.36V8.64M10 3.14L21 12 10 20.86V3.14M3 4h4v16H3V4z"></path></svg>',
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
const tools = {
|
||||
header: {
|
||||
class: Header,
|
||||
inlineToolbar: ['link', 'bold', 'italic'],
|
||||
config: {
|
||||
placeholder: 'Enter a header',
|
||||
levels: [2, 3, 4], // Set header levels
|
||||
defaultLevel: 3,
|
||||
},
|
||||
},
|
||||
embed: {
|
||||
class: Embed,
|
||||
inlineToolbar: true,
|
||||
config: {
|
||||
services: {
|
||||
youtube: true,
|
||||
vimeo: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
video: {
|
||||
class: VideoTool,
|
||||
inlineToolbar: true,
|
||||
},
|
||||
image: {
|
||||
class: InlineImage,
|
||||
inlineToolbar: true,
|
||||
config: {
|
||||
embed: {
|
||||
display: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
const editorDescription = new EditorJS({
|
||||
holder: 'description',
|
||||
tools: tools
|
||||
});
|
||||
const editorDescriptionEn = new EditorJS({
|
||||
holder: 'description_en',
|
||||
tools: tools,
|
||||
});
|
||||
*/
|
||||
</script>
|
||||
|
||||
<script type="text/javascript">
|
||||
$(function() {
|
||||
/*
|
||||
$('#due_date').flatpickr({
|
||||
enableTime: false,
|
||||
dateFormat: 'd-m-Y',
|
||||
defaultDate: null, // Do not preselect any date
|
||||
onReady: function(selectedDates, dateStr, instance) {
|
||||
// Highlight today's date with a custom CSS class
|
||||
const today = instance.todayDateElem;
|
||||
today.classList.add('flatpickr-today-highlight'); // Add a custom class to today
|
||||
}
|
||||
});
|
||||
|
||||
// file video
|
||||
$('.files-video').fileuploader({
|
||||
extensions: ['MP4', 'mp4', 'MOV', 'mov'],
|
||||
limit: null,
|
||||
fileMaxSize: null,
|
||||
changeInput: '<div class="fileuploader-input">' +
|
||||
'<div class="fileuploader-input-inner">' +
|
||||
'<p><i class="fileuploader-icon-main"></i></p>' +
|
||||
'<h6>Drag and drop files here</h6>' +
|
||||
'<p>or</p>' +
|
||||
'<br>' +
|
||||
'<button type="button" class="fileuploader-input-button"><span>${captions.button}</span></button>' +
|
||||
'</div>' +
|
||||
'</div>',
|
||||
theme: 'dragdrop',
|
||||
});
|
||||
|
||||
// file image
|
||||
$('.files-image').fileuploader({
|
||||
extensions: ['jpg', 'bmp', 'jpeg', 'png'],
|
||||
limit: null,
|
||||
fileMaxSize: null,
|
||||
changeInput: '<div class="fileuploader-input">' +
|
||||
'<div class="fileuploader-input-inner">' +
|
||||
'<p><i class="fileuploader-icon-main"></i></p>' +
|
||||
'<h6>Drag and drop files here</h6>' +
|
||||
'<p>or</p>' +
|
||||
'<br>' +
|
||||
'<button type="button" class="fileuploader-input-button"><span>${captions.button}</span></button>' +
|
||||
'</div>' +
|
||||
'</div>',
|
||||
theme: 'dragdrop',
|
||||
});
|
||||
|
||||
// file sound
|
||||
$('.files-sound').fileuploader({
|
||||
extensions: ['m4a', 'mp4', 'mp3', 'wav'],
|
||||
limit: null,
|
||||
fileMaxSize: null,
|
||||
changeInput: '<div class="fileuploader-input">' +
|
||||
'<div class="fileuploader-input-inner">' +
|
||||
'<p><i class="fileuploader-icon-main"></i></p>' +
|
||||
'<h6>Drag and drop files here</h6>' +
|
||||
'<p>or</p>' +
|
||||
'<br>' +
|
||||
'<button type="button" class="fileuploader-input-button"><span>${captions.button}</span></button>' +
|
||||
'</div>' +
|
||||
'</div>',
|
||||
theme: 'dragdrop',
|
||||
});
|
||||
|
||||
// file document
|
||||
$('.files-document').fileuploader({
|
||||
extensions: ['pdf', 'xls', 'doc', 'docx', 'pptx', 'csv', 'txt'],
|
||||
limit: null,
|
||||
fileMaxSize: null,
|
||||
changeInput: '<div class="fileuploader-input">' +
|
||||
'<div class="fileuploader-input-inner">' +
|
||||
'<p><i class="fileuploader-icon-main"></i></p>' +
|
||||
'<h6>Drag and drop files here</h6>' +
|
||||
'<p>or</p>' +
|
||||
'<br>' +
|
||||
'<button type="button" class="fileuploader-input-button"><span>${captions.button}</span></button>' +
|
||||
'</div>' +
|
||||
'</div>',
|
||||
theme: 'dragdrop',
|
||||
});
|
||||
*/
|
||||
|
||||
$(document).on('click', '#btn_submit', function(e) {
|
||||
e.preventDefault(); // Prevent default form submission
|
||||
|
||||
alertLoading("Loading..."); // Show loading alert (your custom function)
|
||||
$('#frmAdd').submit();
|
||||
|
||||
/*
|
||||
// Save both editor contents
|
||||
Promise.all([editorDescription.save(), editorDescriptionEn.save()])
|
||||
.then(([descriptionData, descriptionEnData]) => {
|
||||
|
||||
// Store the JSON output in the hidden input fields
|
||||
$('#description_input').val(JSON.stringify(descriptionData));
|
||||
$('#description_input_en').val(JSON.stringify(descriptionEnData));
|
||||
|
||||
// Submit the form after saving the data
|
||||
$('#frmAdd').submit();
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('Error saving editor content:', error);
|
||||
});
|
||||
*/
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
@endsection
|
||||
@@ -0,0 +1,505 @@
|
||||
@extends('layouts.backendTemplate')
|
||||
|
||||
@section('content')
|
||||
|
||||
<style>
|
||||
.video-responsive {
|
||||
position: relative;
|
||||
padding-bottom: 56.25%;
|
||||
/* Aspect ratio 16:9 */
|
||||
height: 0;
|
||||
overflow: hidden;
|
||||
max-width: 100%;
|
||||
background: #000;
|
||||
}
|
||||
|
||||
.video-responsive video {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
</style>
|
||||
|
||||
<!--begin::Main-->
|
||||
<div class="app-main flex-column flex-row-fluid" id="kt_app_main">
|
||||
|
||||
<div class="d-flex flex-column flex-column-fluid">
|
||||
|
||||
|
||||
@include('uc.admin.breadcrumb', [
|
||||
'title' => 'WHERE ELSE : Edit Sub Category',
|
||||
'pageName' => 'Edit',
|
||||
'pageParent' => 'Sub Category Management',
|
||||
'pageParentLink' => url('where-else/sub-category'),
|
||||
])
|
||||
<div id="kt_app_content" class="app-content flex-column-fluid">
|
||||
<div id="kt_app_content_container" class="app-container container-xxl">
|
||||
|
||||
|
||||
<form id="frmUpdate" class="form d-flex flex-column flex-lg-row"
|
||||
action="{{ url('where-else/update-sub-category') }}" method="post" enctype="multipart/form-data">
|
||||
|
||||
<input type="hidden" name="id" value="{{ $itemView->id }}">
|
||||
<input type="hidden" name="_method" value="POST">
|
||||
<input type="hidden" name="_token" value="{{ csrf_token() }}">
|
||||
|
||||
|
||||
{{-- Left --}}
|
||||
<div class="d-flex flex-column gap-7 gap-lg-10 w-100 w-lg-300px mb-7 me-lg-10">
|
||||
|
||||
<div class="card card-flush py-4">
|
||||
|
||||
<div class="card-body text-center pt-0">
|
||||
|
||||
<style>
|
||||
.image-input-placeholder {
|
||||
background-image: url('{{ url('assets/media/svg/files/blank-image.svg') }}');
|
||||
}
|
||||
|
||||
[data-bs-theme="dark"] .image-input-placeholder {
|
||||
background-image: url('../media/svg/files/blank-image-dark.svg');
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="image-input image-input-empty image-input-outline image-input-placeholder mb-3"
|
||||
data-kt-image-input="true">
|
||||
|
||||
|
||||
@if ($itemView->image_url && $itemView->image_name)
|
||||
<div class="image-input-wrapper w-150px h-150px"
|
||||
style="background-image: url('{{ $itemView->image_url . '/thumbnail/' . $itemView->image_name }}')">
|
||||
</div>
|
||||
@else
|
||||
<div class="image-input-wrapper w-150px h-150px"></div>
|
||||
@endif
|
||||
|
||||
<label
|
||||
class="btn btn-icon btn-circle btn-active-color-primary w-25px h-25px bg-body shadow"
|
||||
data-kt-image-input-action="change" data-bs-toggle="tooltip"
|
||||
title="Change avatar">
|
||||
|
||||
<i class="bi bi-pencil-fill fs-7"></i>
|
||||
|
||||
<input type="file" name="avatar" accept=".png, .jpg, .jpeg" />
|
||||
<input type="hidden" name="avatar_remove" />
|
||||
|
||||
</label>
|
||||
|
||||
<span
|
||||
class="btn btn-icon btn-circle btn-active-color-primary w-25px h-25px bg-body shadow"
|
||||
data-kt-image-input-action="cancel" data-bs-toggle="tooltip"
|
||||
title="Cancel avatar">
|
||||
<i class="bi bi-x fs-2"></i>
|
||||
</span>
|
||||
|
||||
<span
|
||||
class="btn btn-icon btn-circle btn-active-color-primary w-25px h-25px bg-body shadow"
|
||||
data-kt-image-input-action="remove" data-bs-toggle="tooltip"
|
||||
title="Remove avatar">
|
||||
<i class="bi bi-x fs-2"></i>
|
||||
</span>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="text-muted fs-7">Set the profile picture. Only *.png, *.jpg and *.jpeg
|
||||
image
|
||||
files are accepted</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="card-header" style="border: unset;">
|
||||
<!--begin::Card title-->
|
||||
<div class="required card-title">
|
||||
<h2>Active</h2>
|
||||
</div>
|
||||
<!--end::Card title-->
|
||||
</div>
|
||||
<div class="card-body pt-0">
|
||||
|
||||
<label class="form-check form-switch form-check-custom form-check-solid">
|
||||
<input class="form-check-input" name="active" type="checkbox" value="1"
|
||||
{{ $itemView->active == 1 ? 'checked' : '' }} />
|
||||
</label>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
{{-- Right --}}
|
||||
<div class="d-flex flex-column flex-row-fluid gap-7 gap-lg-10">
|
||||
|
||||
<div class="card card-flush py-4">
|
||||
|
||||
@if (Session::has('messageSuccess'))
|
||||
<div class="card-body">
|
||||
@include('uc/messageSuccess')
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@if (Session::has('messageFail'))
|
||||
<div class="card-body">
|
||||
@include('uc/messageFail')
|
||||
</div>
|
||||
@endif
|
||||
|
||||
|
||||
<div class="card-header">
|
||||
<div class="card-title">
|
||||
<h2>Overview</h2>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card-body pt-0">
|
||||
|
||||
{{-- <div class="mb-10 fv-row">
|
||||
<div class="position-relative d-flex align-items-center">
|
||||
<span class="svg-icon svg-icon-2 position-absolute mx-4">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<path opacity="0.3"
|
||||
d="M21 22H3C2.4 22 2 21.6 2 21V5C2 4.4 2.4 4 3 4H21C21.6 4 22 4.4 22 5V21C22 21.6 21.6 22 21 22Z"
|
||||
fill="currentColor" />
|
||||
<path
|
||||
d="M6 6C5.4 6 5 5.6 5 5V3C5 2.4 5.4 2 6 2C6.6 2 7 2.4 7 3V5C7 5.6 6.6 6 6 6ZM11 5V3C11 2.4 10.6 2 10 2C9.4 2 9 2.4 9 3V5C9 5.6 9.4 6 10 6C10.6 6 11 5.6 11 5ZM15 5V3C15 2.4 14.6 2 14 2C13.4 2 13 2.4 13 3V5C13 5.6 13.4 6 14 6C14.6 6 15 5.6 15 5ZM19 5V3C19 2.4 18.6 2 18 2C17.4 2 17 2.4 17 3V5C17 5.6 17.4 6 18 6C18.6 6 19 5.6 19 5Z"
|
||||
fill="currentColor" />
|
||||
<path
|
||||
d="M8.8 13.1C9.2 13.1 9.5 13 9.7 12.8C9.9 12.6 10.1 12.3 10.1 11.9C10.1 11.6 10 11.3 9.8 11.1C9.6 10.9 9.3 10.8 9 10.8C8.8 10.8 8.59999 10.8 8.39999 10.9C8.19999 11 8.1 11.1 8 11.2C7.9 11.3 7.8 11.4 7.7 11.6C7.6 11.8 7.5 11.9 7.5 12.1C7.5 12.2 7.4 12.2 7.3 12.3C7.2 12.4 7.09999 12.4 6.89999 12.4C6.69999 12.4 6.6 12.3 6.5 12.2C6.4 12.1 6.3 11.9 6.3 11.7C6.3 11.5 6.4 11.3 6.5 11.1C6.6 10.9 6.8 10.7 7 10.5C7.2 10.3 7.49999 10.1 7.89999 10C8.29999 9.90003 8.60001 9.80003 9.10001 9.80003C9.50001 9.80003 9.80001 9.90003 10.1 10C10.4 10.1 10.7 10.3 10.9 10.4C11.1 10.5 11.3 10.8 11.4 11.1C11.5 11.4 11.6 11.6 11.6 11.9C11.6 12.3 11.5 12.6 11.3 12.9C11.1 13.2 10.9 13.5 10.6 13.7C10.9 13.9 11.2 14.1 11.4 14.3C11.6 14.5 11.8 14.7 11.9 15C12 15.3 12.1 15.5 12.1 15.8C12.1 16.2 12 16.5 11.9 16.8C11.8 17.1 11.5 17.4 11.3 17.7C11.1 18 10.7 18.2 10.3 18.3C9.9 18.4 9.5 18.5 9 18.5C8.5 18.5 8.1 18.4 7.7 18.2C7.3 18 7 17.8 6.8 17.6C6.6 17.4 6.4 17.1 6.3 16.8C6.2 16.5 6.10001 16.3 6.10001 16.1C6.10001 15.9 6.2 15.7 6.3 15.6C6.4 15.5 6.6 15.4 6.8 15.4C6.9 15.4 7.00001 15.4 7.10001 15.5C7.20001 15.6 7.3 15.6 7.3 15.7C7.5 16.2 7.7 16.6 8 16.9C8.3 17.2 8.6 17.3 9 17.3C9.2 17.3 9.5 17.2 9.7 17.1C9.9 17 10.1 16.8 10.3 16.6C10.5 16.4 10.5 16.1 10.5 15.8C10.5 15.3 10.4 15 10.1 14.7C9.80001 14.4 9.50001 14.3 9.10001 14.3C9.00001 14.3 8.9 14.3 8.7 14.3C8.5 14.3 8.39999 14.3 8.39999 14.3C8.19999 14.3 7.99999 14.2 7.89999 14.1C7.79999 14 7.7 13.8 7.7 13.7C7.7 13.5 7.79999 13.4 7.89999 13.2C7.99999 13 8.2 13 8.5 13H8.8V13.1ZM15.3 17.5V12.2C14.3 13 13.6 13.3 13.3 13.3C13.1 13.3 13 13.2 12.9 13.1C12.8 13 12.7 12.8 12.7 12.6C12.7 12.4 12.8 12.3 12.9 12.2C13 12.1 13.2 12 13.6 11.8C14.1 11.6 14.5 11.3 14.7 11.1C14.9 10.9 15.2 10.6 15.5 10.3C15.8 10 15.9 9.80003 15.9 9.70003C15.9 9.60003 16.1 9.60004 16.3 9.60004C16.5 9.60004 16.7 9.70003 16.8 9.80003C16.9 9.90003 17 10.2 17 10.5V17.2C17 18 16.7 18.4 16.2 18.4C16 18.4 15.8 18.3 15.6 18.2C15.4 18.1 15.3 17.8 15.3 17.5Z"
|
||||
fill="currentColor" />
|
||||
</svg>
|
||||
</span>
|
||||
<input class="form-control form-control-solid ps-12" type="text"
|
||||
id="due_date" name="due_date"
|
||||
value="{{ $itemView->due_date ? date('d-m-Y', strtotime($itemView->due_date)) : '' }}">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</div> --}}
|
||||
|
||||
<div class="mb-10 fv-row">
|
||||
<label class="required form-label">Subject</label>
|
||||
<input type="text" name="name" class="form-control mb-2 col-6"
|
||||
value="{{ $itemView->name }}" />
|
||||
</div>
|
||||
|
||||
|
||||
<div class="mb-10 fv-row">
|
||||
<label class="required form-label">Subject (EN)</label>
|
||||
<input type="text" name="name_en" class="form-control mb-2 col-6"
|
||||
value="{{ $itemView->name_en }}" />
|
||||
</div>
|
||||
|
||||
{{-- <div class="mb-10 fv-row">
|
||||
<label class="required form-label">Description</label>
|
||||
<div class="form-control" id="description" name="description"></div>
|
||||
<input type="hidden" id="description_input" name="description" />
|
||||
</div>
|
||||
|
||||
|
||||
<div class="mb-10 fv-row">
|
||||
<label class="required form-label">Description (EN)</label>
|
||||
<div class="form-control" id="description_en" name="description_en"></div>
|
||||
<input type="hidden" id="description_input_en" name="description_en" />
|
||||
|
||||
</div> --}}
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="d-flex justify-content-end">
|
||||
|
||||
<a href="{{ url('where-else/sub-category') }}" id="kt_ecommerce_add_product_cancel"
|
||||
class="btn btn-light me-5">Cancel</a>
|
||||
|
||||
<button type="button" id="btn_submit" class="btn btn-primary">
|
||||
<span class="indicator-label">Save</span>
|
||||
</button>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</form>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
@stop
|
||||
|
||||
|
||||
|
||||
|
||||
@section('script')
|
||||
|
||||
<script type="text/javascript">
|
||||
$(function() {
|
||||
/*
|
||||
$('#due_date').flatpickr({
|
||||
enableTime: false,
|
||||
dateFormat: 'd-m-Y',
|
||||
defaultDate: null, // Do not preselect any date
|
||||
onReady: function(selectedDates, dateStr, instance) {
|
||||
// Highlight today's date with a custom CSS class
|
||||
const today = instance.todayDateElem;
|
||||
today.classList.add('flatpickr-today-highlight'); // Add a custom class to today
|
||||
}
|
||||
});
|
||||
|
||||
// file video
|
||||
$('.files-video').fileuploader({
|
||||
extensions: ['MP4', 'mp4', 'MOV', 'mov'],
|
||||
limit: null,
|
||||
fileMaxSize: null,
|
||||
changeInput: '<div class="fileuploader-input">' +
|
||||
'<div class="fileuploader-input-inner">' +
|
||||
'<p><i class="fileuploader-icon-main"></i></p>' +
|
||||
'<h6>Drag and drop files here</h6>' +
|
||||
'<p>or</p>' +
|
||||
'<br>' +
|
||||
'<button type="button" class="fileuploader-input-button"><span>${captions.button}</span></button>' +
|
||||
'</div>' +
|
||||
'</div>',
|
||||
theme: 'dragdrop',
|
||||
});
|
||||
|
||||
// file image
|
||||
$('.files-image').fileuploader({
|
||||
extensions: ['jpg', 'bmp', 'jpeg', 'png'],
|
||||
limit: null,
|
||||
fileMaxSize: null,
|
||||
changeInput: '<div class="fileuploader-input">' +
|
||||
'<div class="fileuploader-input-inner">' +
|
||||
'<p><i class="fileuploader-icon-main"></i></p>' +
|
||||
'<h6>Drag and drop files here</h6>' +
|
||||
'<p>or</p>' +
|
||||
'<br>' +
|
||||
'<button type="button" class="fileuploader-input-button"><span>${captions.button}</span></button>' +
|
||||
'</div>' +
|
||||
'</div>',
|
||||
theme: 'dragdrop',
|
||||
});
|
||||
|
||||
// file sound
|
||||
$('.files-sound').fileuploader({
|
||||
extensions: ['m4a', 'mp4', 'mp3', 'wav'],
|
||||
limit: null,
|
||||
fileMaxSize: null,
|
||||
changeInput: '<div class="fileuploader-input">' +
|
||||
'<div class="fileuploader-input-inner">' +
|
||||
'<p><i class="fileuploader-icon-main"></i></p>' +
|
||||
'<h6>Drag and drop files here</h6>' +
|
||||
'<p>or</p>' +
|
||||
'<br>' +
|
||||
'<button type="button" class="fileuploader-input-button"><span>${captions.button}</span></button>' +
|
||||
'</div>' +
|
||||
'</div>',
|
||||
theme: 'dragdrop',
|
||||
});
|
||||
|
||||
// file document
|
||||
$('.files-document').fileuploader({
|
||||
extensions: ['pdf', 'xls', 'doc', 'docx', 'pptx', 'csv', 'txt'],
|
||||
limit: null,
|
||||
fileMaxSize: null,
|
||||
changeInput: '<div class="fileuploader-input">' +
|
||||
'<div class="fileuploader-input-inner">' +
|
||||
'<p><i class="fileuploader-icon-main"></i></p>' +
|
||||
'<h6>Drag and drop files here</h6>' +
|
||||
'<p>or</p>' +
|
||||
'<br>' +
|
||||
'<button type="button" class="fileuploader-input-button"><span>${captions.button}</span></button>' +
|
||||
'</div>' +
|
||||
'</div>',
|
||||
theme: 'dragdrop',
|
||||
});
|
||||
*/
|
||||
|
||||
$(document).on("click", "#btn_submit", function(e) {
|
||||
e.preventDefault();
|
||||
alertLoading("Loading")
|
||||
const form = $('#frmUpdate');
|
||||
form.submit();
|
||||
})
|
||||
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
{{-- <!-- Include Editor.js core -->
|
||||
<script src="https://cdn.jsdelivr.net/npm/@editorjs/editorjs@latest"></script>
|
||||
|
||||
<!-- Include the plugins -->
|
||||
<script src="https://cdn.jsdelivr.net/npm/@editorjs/header"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/@editorjs/list"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/@editorjs/paragraph"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/@editorjs/quote"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/@editorjs/image"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/editorjs-inline-image"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/@editorjs/embed"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/@editorjs/code"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/@editorjs/table"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/@editorjs/marker"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/@editorjs/checklist"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/@editorjs/delimiter"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/@editorjs/warning"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/@editorjs/link"></script> --}}
|
||||
|
||||
<script>
|
||||
/*
|
||||
// Custom video tool for embedding videos
|
||||
class VideoTool {
|
||||
constructor({
|
||||
data
|
||||
}) {
|
||||
this.data = data || {};
|
||||
}
|
||||
|
||||
// Render input for video URL
|
||||
render() {
|
||||
const wrapper = document.createElement("div");
|
||||
|
||||
const input = document.createElement("input");
|
||||
input.type = "text";
|
||||
input.placeholder = "Enter video URL";
|
||||
input.value = this.data.url || "";
|
||||
input.style.width = "100%";
|
||||
|
||||
const video = document.createElement("video");
|
||||
video.controls = true;
|
||||
video.style.width = "100%";
|
||||
video.style.marginTop = "10px";
|
||||
video.src = this.data.url || "";
|
||||
|
||||
input.addEventListener("input", (event) => {
|
||||
const value = event.target.value;
|
||||
this.data.url = value;
|
||||
video.src = value;
|
||||
});
|
||||
|
||||
wrapper.appendChild(input);
|
||||
wrapper.appendChild(video);
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
// Save the video URL
|
||||
save(blockContent) {
|
||||
const input = blockContent.querySelector("input");
|
||||
return {
|
||||
url: input.value,
|
||||
};
|
||||
}
|
||||
|
||||
// Editor.js toolbox definition
|
||||
static get toolbox() {
|
||||
return {
|
||||
title: "Video",
|
||||
icon: '<svg width="20" height="20" viewBox="0 0 24 24"><path d="M10 8.64L15.27 12 10 15.36V8.64M10 3.14L21 12 10 20.86V3.14M3 4h4v16H3V4z"></path></svg>',
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
const tools = {
|
||||
header: {
|
||||
class: Header,
|
||||
inlineToolbar: ['link', 'bold', 'italic'],
|
||||
config: {
|
||||
placeholder: 'Enter a header',
|
||||
levels: [2, 3, 4], // Set header levels
|
||||
defaultLevel: 3,
|
||||
},
|
||||
},
|
||||
embed: {
|
||||
class: Embed,
|
||||
inlineToolbar: true,
|
||||
config: {
|
||||
services: {
|
||||
youtube: true,
|
||||
vimeo: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
video: {
|
||||
class: VideoTool,
|
||||
inlineToolbar: true,
|
||||
},
|
||||
image: {
|
||||
class: InlineImage,
|
||||
inlineToolbar: true,
|
||||
config: {
|
||||
embed: {
|
||||
display: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
const descriptionData = {!! json_encode($itemView->description) !!};
|
||||
const editorDescription = new EditorJS({
|
||||
holder: 'description',
|
||||
tools: tools,
|
||||
data: descriptionData != "" ? JSON.parse(descriptionData) : {},
|
||||
onChange: () => {
|
||||
saveData(editorDescription, 'description_input')
|
||||
}
|
||||
});
|
||||
|
||||
const descriptionDataEn = {!! json_encode($itemView->description_en) !!};
|
||||
const editorDescriptionEn = new EditorJS({
|
||||
holder: 'description_en',
|
||||
tools: tools,
|
||||
data: descriptionDataEn !== "" ? JSON.parse(descriptionDataEn) : {},
|
||||
onChange: () => {
|
||||
saveData(editorDescriptionEn, 'description_input_en');
|
||||
}
|
||||
});
|
||||
*/
|
||||
|
||||
|
||||
// Function to save data to hidden inputs
|
||||
function saveData(editor, inputId) {
|
||||
editor.save().then((outputData) => {
|
||||
document.getElementById(inputId).value = JSON.stringify(outputData);
|
||||
}).catch((error) => {
|
||||
console.error('Saving failed: ', error);
|
||||
});
|
||||
}
|
||||
|
||||
$(document).on('click', '#btn_submit', function(e) {
|
||||
e.preventDefault(); // Prevent default form submission
|
||||
|
||||
alertLoading("Loading..."); // Show loading alert (your custom function)
|
||||
$('#frmUpdate').submit();
|
||||
|
||||
/*
|
||||
// Save both editor contents
|
||||
Promise.all([editorDescription.save(), editorDescriptionEn.save()])
|
||||
.then(([descriptionData, descriptionEnData]) => {
|
||||
// Store the JSON output in the hidden input fields
|
||||
$('#description_input').val(JSON.stringify(descriptionData));
|
||||
$('#description_input_en').val(JSON.stringify(descriptionEnData));
|
||||
|
||||
// Submit the form after saving the data
|
||||
$('#frmUpdate').submit();
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('Error saving editor content:', error);
|
||||
});
|
||||
*/
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
|
||||
@endsection
|
||||
@@ -0,0 +1,408 @@
|
||||
@extends('layouts.backendTemplate')
|
||||
|
||||
@section('content')
|
||||
|
||||
<!--begin::Main-->
|
||||
<div class="app-main flex-column flex-row-fluid" id="kt_app_main">
|
||||
|
||||
<div class="d-flex flex-column flex-column-fluid">
|
||||
|
||||
|
||||
@include('uc.breadcrumbList', [
|
||||
'title' => 'WHERE ELSE : Sub Category Management',
|
||||
'pageName' => 'Sub Category Management',
|
||||
])
|
||||
|
||||
|
||||
<div id="kt_app_content" class="app-content flex-column-fluid">
|
||||
<!--begin::Content container-->
|
||||
<div id="kt_app_content_container" class="app-container container-xxl">
|
||||
<!--begin::Card-->
|
||||
<div class="card">
|
||||
|
||||
@if (Session::has('messageSuccess'))
|
||||
<div class="card-body">
|
||||
@include('uc/messageSuccess')
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@if (Session::has('messageFail'))
|
||||
<div class="card-body">
|
||||
@include('uc/messageFail')
|
||||
</div>
|
||||
@endif
|
||||
|
||||
|
||||
<!--begin::Card header-->
|
||||
<div class="card-header border-0 pt-6">
|
||||
<!--begin::Card title-->
|
||||
<div class="d-flex align-items-center position-relative my-1">
|
||||
</div>
|
||||
|
||||
|
||||
@if (Auth::user()->role != 2)
|
||||
<div class="card-toolbar">
|
||||
<div class="d-flex justify-content-end" data-kt-customer-table-toolbar="base">
|
||||
<a href="{{ url('where-else/add-sub-category') }}" class="btn btn-primary">Add
|
||||
</a>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@endif
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<div class="card-header border-0 pt-5">
|
||||
|
||||
<div class="card-title">
|
||||
<div class="d-flex align-items-center position-relative my-1">
|
||||
<span class="svg-icon svg-icon-1 position-absolute ms-4">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<rect opacity="0.5" x="17.0365" y="15.1223" width="8.15546" height="2"
|
||||
rx="1" transform="rotate(45 17.0365 15.1223)" fill="currentColor">
|
||||
</rect>
|
||||
<path
|
||||
d="M11 19C6.55556 19 3 15.4444 3 11C3 6.55556 6.55556 3 11 3C15.4444 3 19 6.55556 19 11C19 15.4444 15.4444 19 11 19ZM11 5C7.53333 5 5 7.53333 5 11C5 14.4667 7.53333 17 11 17C14.4667 17 17 14.4667 17 11C17 7.53333 14.4667 5 11 5Z"
|
||||
fill="currentColor"></path>
|
||||
</svg>
|
||||
</span>
|
||||
|
||||
<input type="text" table-filter="search"
|
||||
class="form-control form-control-solid w-250px ps-15" placeholder="Search" />
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- <div class="card-toolbar flex-row-fluid justify-content-end gap-5">
|
||||
|
||||
<div class="w-100 mw-150px">
|
||||
<div class="position-relative d-flex align-items-center">
|
||||
<span class="svg-icon svg-icon-2 position-absolute mx-4">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<path opacity="0.3"
|
||||
d="M21 22H3C2.4 22 2 21.6 2 21V5C2 4.4 2.4 4 3 4H21C21.6 4 22 4.4 22 5V21C22 21.6 21.6 22 21 22Z"
|
||||
fill="currentColor" />
|
||||
<path
|
||||
d="M6 6C5.4 6 5 5.6 5 5V3C5 2.4 5.4 2 6 2C6.6 2 7 2.4 7 3V5C7 5.6 6.6 6 6 6ZM11 5V3C11 2.4 10.6 2 10 2C9.4 2 9 2.4 9 3V5C9 5.6 9.4 6 10 6C10.6 6 11 5.6 11 5ZM15 5V3C15 2.4 14.6 2 14 2C13.4 2 13 2.4 13 3V5C13 5.6 13.4 6 14 6C14.6 6 15 5.6 15 5ZM19 5V3C19 2.4 18.6 2 18 2C17.4 2 17 2.4 17 3V5C17 5.6 17.4 6 18 6C18.6 6 19 5.6 19 5Z"
|
||||
fill="currentColor" />
|
||||
<path
|
||||
d="M8.8 13.1C9.2 13.1 9.5 13 9.7 12.8C9.9 12.6 10.1 12.3 10.1 11.9C10.1 11.6 10 11.3 9.8 11.1C9.6 10.9 9.3 10.8 9 10.8C8.8 10.8 8.59999 10.8 8.39999 10.9C8.19999 11 8.1 11.1 8 11.2C7.9 11.3 7.8 11.4 7.7 11.6C7.6 11.8 7.5 11.9 7.5 12.1C7.5 12.2 7.4 12.2 7.3 12.3C7.2 12.4 7.09999 12.4 6.89999 12.4C6.69999 12.4 6.6 12.3 6.5 12.2C6.4 12.1 6.3 11.9 6.3 11.7C6.3 11.5 6.4 11.3 6.5 11.1C6.6 10.9 6.8 10.7 7 10.5C7.2 10.3 7.49999 10.1 7.89999 10C8.29999 9.90003 8.60001 9.80003 9.10001 9.80003C9.50001 9.80003 9.80001 9.90003 10.1 10C10.4 10.1 10.7 10.3 10.9 10.4C11.1 10.5 11.3 10.8 11.4 11.1C11.5 11.4 11.6 11.6 11.6 11.9C11.6 12.3 11.5 12.6 11.3 12.9C11.1 13.2 10.9 13.5 10.6 13.7C10.9 13.9 11.2 14.1 11.4 14.3C11.6 14.5 11.8 14.7 11.9 15C12 15.3 12.1 15.5 12.1 15.8C12.1 16.2 12 16.5 11.9 16.8C11.8 17.1 11.5 17.4 11.3 17.7C11.1 18 10.7 18.2 10.3 18.3C9.9 18.4 9.5 18.5 9 18.5C8.5 18.5 8.1 18.4 7.7 18.2C7.3 18 7 17.8 6.8 17.6C6.6 17.4 6.4 17.1 6.3 16.8C6.2 16.5 6.10001 16.3 6.10001 16.1C6.10001 15.9 6.2 15.7 6.3 15.6C6.4 15.5 6.6 15.4 6.8 15.4C6.9 15.4 7.00001 15.4 7.10001 15.5C7.20001 15.6 7.3 15.6 7.3 15.7C7.5 16.2 7.7 16.6 8 16.9C8.3 17.2 8.6 17.3 9 17.3C9.2 17.3 9.5 17.2 9.7 17.1C9.9 17 10.1 16.8 10.3 16.6C10.5 16.4 10.5 16.1 10.5 15.8C10.5 15.3 10.4 15 10.1 14.7C9.80001 14.4 9.50001 14.3 9.10001 14.3C9.00001 14.3 8.9 14.3 8.7 14.3C8.5 14.3 8.39999 14.3 8.39999 14.3C8.19999 14.3 7.99999 14.2 7.89999 14.1C7.79999 14 7.7 13.8 7.7 13.7C7.7 13.5 7.79999 13.4 7.89999 13.2C7.99999 13 8.2 13 8.5 13H8.8V13.1ZM15.3 17.5V12.2C14.3 13 13.6 13.3 13.3 13.3C13.1 13.3 13 13.2 12.9 13.1C12.8 13 12.7 12.8 12.7 12.6C12.7 12.4 12.8 12.3 12.9 12.2C13 12.1 13.2 12 13.6 11.8C14.1 11.6 14.5 11.3 14.7 11.1C14.9 10.9 15.2 10.6 15.5 10.3C15.8 10 15.9 9.80003 15.9 9.70003C15.9 9.60003 16.1 9.60004 16.3 9.60004C16.5 9.60004 16.7 9.70003 16.8 9.80003C16.9 9.90003 17 10.2 17 10.5V17.2C17 18 16.7 18.4 16.2 18.4C16 18.4 15.8 18.3 15.6 18.2C15.4 18.1 15.3 17.8 15.3 17.5Z"
|
||||
fill="currentColor" />
|
||||
</svg>
|
||||
</span>
|
||||
<input class="form-control form-control-solid ps-12" placeholder="From"
|
||||
id="due_date_from" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="w-100 mw-150px">
|
||||
<div class="position-relative d-flex align-items-center">
|
||||
<span class="svg-icon svg-icon-2 position-absolute mx-4">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<path opacity="0.3"
|
||||
d="M21 22H3C2.4 22 2 21.6 2 21V5C2 4.4 2.4 4 3 4H21C21.6 4 22 4.4 22 5V21C22 21.6 21.6 22 21 22Z"
|
||||
fill="currentColor" />
|
||||
<path
|
||||
d="M6 6C5.4 6 5 5.6 5 5V3C5 2.4 5.4 2 6 2C6.6 2 7 2.4 7 3V5C7 5.6 6.6 6 6 6ZM11 5V3C11 2.4 10.6 2 10 2C9.4 2 9 2.4 9 3V5C9 5.6 9.4 6 10 6C10.6 6 11 5.6 11 5ZM15 5V3C15 2.4 14.6 2 14 2C13.4 2 13 2.4 13 3V5C13 5.6 13.4 6 14 6C14.6 6 15 5.6 15 5ZM19 5V3C19 2.4 18.6 2 18 2C17.4 2 17 2.4 17 3V5C17 5.6 17.4 6 18 6C18.6 6 19 5.6 19 5Z"
|
||||
fill="currentColor" />
|
||||
<path
|
||||
d="M8.8 13.1C9.2 13.1 9.5 13 9.7 12.8C9.9 12.6 10.1 12.3 10.1 11.9C10.1 11.6 10 11.3 9.8 11.1C9.6 10.9 9.3 10.8 9 10.8C8.8 10.8 8.59999 10.8 8.39999 10.9C8.19999 11 8.1 11.1 8 11.2C7.9 11.3 7.8 11.4 7.7 11.6C7.6 11.8 7.5 11.9 7.5 12.1C7.5 12.2 7.4 12.2 7.3 12.3C7.2 12.4 7.09999 12.4 6.89999 12.4C6.69999 12.4 6.6 12.3 6.5 12.2C6.4 12.1 6.3 11.9 6.3 11.7C6.3 11.5 6.4 11.3 6.5 11.1C6.6 10.9 6.8 10.7 7 10.5C7.2 10.3 7.49999 10.1 7.89999 10C8.29999 9.90003 8.60001 9.80003 9.10001 9.80003C9.50001 9.80003 9.80001 9.90003 10.1 10C10.4 10.1 10.7 10.3 10.9 10.4C11.1 10.5 11.3 10.8 11.4 11.1C11.5 11.4 11.6 11.6 11.6 11.9C11.6 12.3 11.5 12.6 11.3 12.9C11.1 13.2 10.9 13.5 10.6 13.7C10.9 13.9 11.2 14.1 11.4 14.3C11.6 14.5 11.8 14.7 11.9 15C12 15.3 12.1 15.5 12.1 15.8C12.1 16.2 12 16.5 11.9 16.8C11.8 17.1 11.5 17.4 11.3 17.7C11.1 18 10.7 18.2 10.3 18.3C9.9 18.4 9.5 18.5 9 18.5C8.5 18.5 8.1 18.4 7.7 18.2C7.3 18 7 17.8 6.8 17.6C6.6 17.4 6.4 17.1 6.3 16.8C6.2 16.5 6.10001 16.3 6.10001 16.1C6.10001 15.9 6.2 15.7 6.3 15.6C6.4 15.5 6.6 15.4 6.8 15.4C6.9 15.4 7.00001 15.4 7.10001 15.5C7.20001 15.6 7.3 15.6 7.3 15.7C7.5 16.2 7.7 16.6 8 16.9C8.3 17.2 8.6 17.3 9 17.3C9.2 17.3 9.5 17.2 9.7 17.1C9.9 17 10.1 16.8 10.3 16.6C10.5 16.4 10.5 16.1 10.5 15.8C10.5 15.3 10.4 15 10.1 14.7C9.80001 14.4 9.50001 14.3 9.10001 14.3C9.00001 14.3 8.9 14.3 8.7 14.3C8.5 14.3 8.39999 14.3 8.39999 14.3C8.19999 14.3 7.99999 14.2 7.89999 14.1C7.79999 14 7.7 13.8 7.7 13.7C7.7 13.5 7.79999 13.4 7.89999 13.2C7.99999 13 8.2 13 8.5 13H8.8V13.1ZM15.3 17.5V12.2C14.3 13 13.6 13.3 13.3 13.3C13.1 13.3 13 13.2 12.9 13.1C12.8 13 12.7 12.8 12.7 12.6C12.7 12.4 12.8 12.3 12.9 12.2C13 12.1 13.2 12 13.6 11.8C14.1 11.6 14.5 11.3 14.7 11.1C14.9 10.9 15.2 10.6 15.5 10.3C15.8 10 15.9 9.80003 15.9 9.70003C15.9 9.60003 16.1 9.60004 16.3 9.60004C16.5 9.60004 16.7 9.70003 16.8 9.80003C16.9 9.90003 17 10.2 17 10.5V17.2C17 18 16.7 18.4 16.2 18.4C16 18.4 15.8 18.3 15.6 18.2C15.4 18.1 15.3 17.8 15.3 17.5Z"
|
||||
fill="currentColor" />
|
||||
</svg>
|
||||
</span>
|
||||
<input class="form-control form-control-solid ps-12" placeholder="To"
|
||||
id="due_date_to" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button type="button" id="btn-submit" class="btn btn-primary">
|
||||
Search
|
||||
</button>
|
||||
|
||||
</div> --}}
|
||||
</div>
|
||||
|
||||
<div class="card-body py-4">
|
||||
<!--begin::Table-->
|
||||
<table class="table align-middle table-row-dashed fs-6 gy-5" id="data-table-category">
|
||||
<!--begin::Table head-->
|
||||
<thead>
|
||||
<!--begin::Table row-->
|
||||
<tr class="text-start text-muted fw-bold fs-7 text-uppercase gs-0">
|
||||
<th class="min-w-125px">Pic</th>
|
||||
{{-- <th class="min-w-125px">Date</th> --}}
|
||||
<th class="min-w-125px">Subject</th>
|
||||
<th class="min-w-125px">Subject (EN)</th>
|
||||
<th class="min-w-125px">Created</th>
|
||||
<th class="min-w-125px">Active</th>
|
||||
<th class="text-end min-w-100px">Manage</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody class="text-gray-600 fw-semibold">
|
||||
|
||||
@foreach ($itemView as $obj)
|
||||
<tr>
|
||||
<td class="d-flex align-items-center">
|
||||
<div class="symbol symbol-100px symbol-2by3 me-4">
|
||||
@if ($obj->image_url && $obj->image_name)
|
||||
<a class="show-image-preview d-block overlay"
|
||||
href="{{ url($obj->image_url . '/original/' . $obj->image_name) }}">
|
||||
<div class="symbol-label"
|
||||
style="background-image: url('{{ url($obj->image_url . '/thumbnail/' . $obj->image_name) }}')">
|
||||
</div>
|
||||
</a>
|
||||
@else
|
||||
<div class="symbol-label"
|
||||
style="background-image: url('{{ url('assets/media/avatars/blank.png') }}')">
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
</td>
|
||||
|
||||
<td>
|
||||
<a href="#" class="text-gray-800 text-hover-primary mb-1">
|
||||
{{ $obj->name }}
|
||||
</a>
|
||||
</td>
|
||||
|
||||
<td>
|
||||
<a href="#" class="text-gray-800 text-hover-primary mb-1">
|
||||
{{ $obj->name_en }}
|
||||
</a>
|
||||
</td>
|
||||
|
||||
<td>
|
||||
{{ Carbon\Carbon::parse($obj->created_at)->format('d, M Y') }}
|
||||
</td>
|
||||
|
||||
|
||||
<td>
|
||||
@if ($obj->active == 1)
|
||||
<span class="badge py-3 px-4 fs-7 badge-light-success">Active</span>
|
||||
@else
|
||||
<span class="badge py-3 px-4 fs-7 badge-light-danger">Inactive</span>
|
||||
@endif
|
||||
</td>
|
||||
|
||||
|
||||
<td class="min-w-100px text-end">
|
||||
|
||||
{{-- View --}}
|
||||
<a href="{{ url('where-else/article/' . $obj->id) }}"
|
||||
class="btn btn-icon btn-bg-light btn-active-color-primary btn-sm me-1">
|
||||
<span class="svg-icon svg-icon-3">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24"
|
||||
fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M17.5 11H6.5C4 11 2 9 2 6.5C2 4 4 2 6.5 2H17.5C20 2 22 4 22 6.5C22 9 20 11 17.5 11ZM15 6.5C15 7.9 16.1 9 17.5 9C18.9 9 20 7.9 20 6.5C20 5.1 18.9 4 17.5 4C16.1 4 15 5.1 15 6.5Z"
|
||||
fill="currentColor"></path>
|
||||
<path opacity="0.3"
|
||||
d="M17.5 22H6.5C4 22 2 20 2 17.5C2 15 4 13 6.5 13H17.5C20 13 22 15 22 17.5C22 20 20 22 17.5 22ZM4 17.5C4 18.9 5.1 20 6.5 20C7.9 20 9 18.9 9 17.5C9 16.1 7.9 15 6.5 15C5.1 15 4 16.1 4 17.5Z"
|
||||
fill="currentColor"></path>
|
||||
</svg>
|
||||
</span>
|
||||
</a>
|
||||
|
||||
{{-- Edit --}}
|
||||
<a href="{{ url('where-else/edit-sub-category/' . $obj->id) }}"
|
||||
class="btn btn-icon btn-bg-light btn-active-color-primary btn-sm me-1">
|
||||
<span class="svg-icon svg-icon-3">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24"
|
||||
fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path opacity="0.3"
|
||||
d="M21.4 8.35303L19.241 10.511L13.485 4.755L15.643 2.59595C16.0248 2.21423 16.5426 1.99988 17.0825 1.99988C17.6224 1.99988 18.1402 2.21423 18.522 2.59595L21.4 5.474C21.7817 5.85581 21.9962 6.37355 21.9962 6.91345C21.9962 7.45335 21.7817 7.97122 21.4 8.35303ZM3.68699 21.932L9.88699 19.865L4.13099 14.109L2.06399 20.309C1.98815 20.5354 1.97703 20.7787 2.03189 21.0111C2.08674 21.2436 2.2054 21.4561 2.37449 21.6248C2.54359 21.7934 2.75641 21.9115 2.989 21.9658C3.22158 22.0201 3.4647 22.0084 3.69099 21.932H3.68699Z"
|
||||
fill="currentColor" />
|
||||
<path
|
||||
d="M5.574 21.3L3.692 21.928C3.46591 22.0032 3.22334 22.0141 2.99144 21.9594C2.75954 21.9046 2.54744 21.7864 2.3789 21.6179C2.21036 21.4495 2.09202 21.2375 2.03711 21.0056C1.9822 20.7737 1.99289 20.5312 2.06799 20.3051L2.696 18.422L5.574 21.3ZM4.13499 14.105L9.891 19.861L19.245 10.507L13.489 4.75098L4.13499 14.105Z"
|
||||
fill="currentColor" />
|
||||
</svg>
|
||||
</span>
|
||||
</a>
|
||||
|
||||
{{-- Delete --}}
|
||||
@if ($obj->active == 1 && Auth::user()->role != 2)
|
||||
<a href="#" data-id="{{ $obj->id }}"
|
||||
class="btn btn-icon btn-bg-light btn-active-color-primary btn-sm delete-item">
|
||||
<span class="svg-icon svg-icon-3">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24"
|
||||
fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M5 9C5 8.44772 5.44772 8 6 8H18C18.5523 8 19 8.44772 19 9V18C19 19.6569 17.6569 21 16 21H8C6.34315 21 5 19.6569 5 18V9Z"
|
||||
fill="currentColor" />
|
||||
<path opacity="0.5"
|
||||
d="M5 5C5 4.44772 5.44772 4 6 4H18C18.5523 4 19 4.44772 19 5V5C19 5.55228 18.5523 6 18 6H6C5.44772 6 5 5.55228 5 5V5Z"
|
||||
fill="currentColor" />
|
||||
<path opacity="0.5"
|
||||
d="M9 4C9 3.44772 9.44772 3 10 3H14C14.5523 3 15 3.44772 15 4V4H9V4Z"
|
||||
fill="currentColor" />
|
||||
</svg>
|
||||
</span>
|
||||
</a>
|
||||
@endif
|
||||
</td>
|
||||
|
||||
|
||||
</tr>
|
||||
@endforeach
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@stop
|
||||
|
||||
|
||||
@section('script')
|
||||
|
||||
<script type="text/javascript">
|
||||
const baseUrl = "{{ url('where-else/sub-category') }}";
|
||||
var datatable;
|
||||
datatable = $("#data-table-category").DataTable({
|
||||
"info": false,
|
||||
"order": [],
|
||||
"pageLength": 25,
|
||||
lengthMenu: [
|
||||
[10, 25, 50, 100, 500, 1000],
|
||||
[10, 25, 50, 100, 500, 1000]
|
||||
]
|
||||
});
|
||||
|
||||
// Filter by search
|
||||
const filterSearch = document.querySelector('[table-filter="search"]');
|
||||
filterSearch.addEventListener('keyup', function(e) {
|
||||
datatable.search(e.target.value).draw();
|
||||
});
|
||||
|
||||
// filter by status
|
||||
const filterStatus = document.querySelector('[table-filter="status"]');
|
||||
$(filterStatus).on('change', e => {
|
||||
let value = e.target.value;
|
||||
if (value === 'all') {
|
||||
value = '';
|
||||
}
|
||||
datatable.column(4).search(value).draw();
|
||||
});
|
||||
|
||||
|
||||
// Remove
|
||||
$(document).on('click', '.delete-item', function() {
|
||||
swal.fire({
|
||||
allowOutsideClick: false,
|
||||
text: "Are you sure you would like to Delete?",
|
||||
icon: "warning",
|
||||
buttonsStyling: false,
|
||||
showDenyButton: true,
|
||||
confirmButtonText: "Yes",
|
||||
denyButtonText: 'No',
|
||||
customClass: {
|
||||
confirmButton: "btn btn-primary",
|
||||
denyButton: "btn btn-light-danger"
|
||||
}
|
||||
}).then((result) => {
|
||||
if (result.isConfirmed) {
|
||||
|
||||
alertLoading("Loading")
|
||||
|
||||
// set up ajax
|
||||
initAjaxSetupToken();
|
||||
|
||||
const ajaxProp = {
|
||||
url: "{{ url('where-else/delete-sub-category') }}",
|
||||
type: 'POST',
|
||||
data: {
|
||||
item_id: $(this).data('id')
|
||||
},
|
||||
};
|
||||
|
||||
$.ajax(ajaxProp).done(function(res) {
|
||||
if (res.status) {
|
||||
const url = "{{ url('where-else/sub-category') }}";
|
||||
alertSuccessWithUrl('Notice', "Delete success", url);
|
||||
hideLoading();
|
||||
} else {
|
||||
alertFail('Notice', res.message ?? "Unsuccessfully");
|
||||
hideLoading();
|
||||
}
|
||||
}).fail(function(xhr, status, error) {
|
||||
logAjaxError(xhr, status, error);
|
||||
alertFail('Notice', error.message ?? "Unsuccessfully");
|
||||
hideLoading();
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
var today = new Date();
|
||||
var dateFormat = "d-m-Y";
|
||||
|
||||
var dueDateFrom = $("#due_date_from");
|
||||
var dueDateTo = $("#due_date_to");
|
||||
|
||||
const dateFrom = "{{ $fromDateView }}";
|
||||
const dateTo = "{{ $toDateView }}";
|
||||
|
||||
dueDateFrom.flatpickr({
|
||||
showClearButton: true,
|
||||
enableTime: false,
|
||||
dateFormat: dateFormat,
|
||||
maxDate: today,
|
||||
defaultDate: dateFrom,
|
||||
|
||||
});
|
||||
|
||||
dueDateTo.flatpickr({
|
||||
showClearButton: true,
|
||||
enableTime: false,
|
||||
dateFormat: dateFormat,
|
||||
maxDate: today,
|
||||
defaultDate: dateTo,
|
||||
|
||||
});
|
||||
|
||||
const clearDatePicker = () => {
|
||||
dueDateFrom.flatpickr().clear();
|
||||
dueDateTo.flatpickr().clear();
|
||||
|
||||
// Set the date format again after clearing
|
||||
dueDateFrom.flatpickr({
|
||||
dateFormat: dateFormat
|
||||
});
|
||||
dueDateTo.flatpickr({
|
||||
dateFormat: dateFormat
|
||||
});
|
||||
}
|
||||
|
||||
$('#btn-submit').on('click', (e) => {
|
||||
e.preventDefault(); // Prevent the default behavior of the anchor element
|
||||
|
||||
// from
|
||||
const fromDateSelected = $("#due_date_from").val();
|
||||
|
||||
// to
|
||||
const toDateSelected = $("#due_date_to").val();
|
||||
|
||||
if (fromDateSelected && toDateSelected) {
|
||||
var newUrl =
|
||||
`${baseUrl}/${fromDateSelected}/${toDateSelected}`;
|
||||
window.location.href = newUrl;
|
||||
} else {
|
||||
var newUrl = `${baseUrl}/all/all/`;
|
||||
window.location.href = newUrl;
|
||||
}
|
||||
|
||||
})
|
||||
</script>
|
||||
|
||||
@endsection
|
||||
@@ -0,0 +1,474 @@
|
||||
@extends('layouts.backendTemplate')
|
||||
|
||||
@section('content')
|
||||
|
||||
<!--begin::Main-->
|
||||
<div class="app-main flex-column flex-row-fluid" id="kt_app_main">
|
||||
|
||||
<div class="d-flex flex-column flex-column-fluid">
|
||||
|
||||
|
||||
@include('uc.admin.breadcrumb', [
|
||||
'title' => 'CHIANG MAI AND NOWHERE ELSE : Add Category Management',
|
||||
'pageName' => 'Add',
|
||||
'pageParent' => 'Sub Category Management',
|
||||
'pageParentLink' => url('no-where-else/sub-category'),
|
||||
])
|
||||
|
||||
<div id="kt_app_content" class="app-content flex-column-fluid">
|
||||
<div id="kt_app_content_container" class="app-container container-xxl">
|
||||
|
||||
|
||||
|
||||
<form id="frmAdd" class="form d-flex flex-column flex-lg-row"
|
||||
action="{{ url('no-where-else/insert-sub-category') }}" method="post"
|
||||
enctype="multipart/form-data">
|
||||
|
||||
<input type="hidden" name="_method" value="POST">
|
||||
<input type="hidden" name="_token" value="{{ csrf_token() }}">
|
||||
|
||||
|
||||
<div class="d-flex flex-column gap-7 gap-lg-10 w-100 w-lg-300px mb-7 me-lg-10">
|
||||
|
||||
<div class="card card-flush py-4">
|
||||
|
||||
|
||||
<div class="card-body text-center pt-0">
|
||||
|
||||
<style>
|
||||
.image-input-placeholder {
|
||||
background-image: url('{{ url('assets/media/svg/files/blank-image.svg') }}');
|
||||
}
|
||||
|
||||
[data-bs-theme="dark"] .image-input-placeholder {
|
||||
background-image: url('../media/svg/files/blank-image-dark.svg');
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="image-input image-input-empty image-input-outline image-input-placeholder mb-3"
|
||||
data-kt-image-input="true">
|
||||
|
||||
<div class="image-input-wrapper w-150px h-150px"></div>
|
||||
|
||||
<label
|
||||
class="btn btn-icon btn-circle btn-active-color-primary w-25px h-25px bg-body shadow"
|
||||
data-kt-image-input-action="change" data-bs-toggle="tooltip"
|
||||
title="Change avatar">
|
||||
|
||||
<i class="bi bi-pencil-fill fs-7"></i>
|
||||
|
||||
<input type="file" name="avatar" accept=".png, .jpg, .jpeg" />
|
||||
<input type="hidden" name="avatar_remove" />
|
||||
|
||||
</label>
|
||||
|
||||
<span
|
||||
class="btn btn-icon btn-circle btn-active-color-primary w-25px h-25px bg-body shadow"
|
||||
data-kt-image-input-action="cancel" data-bs-toggle="tooltip"
|
||||
title="Cancel avatar">
|
||||
<i class="bi bi-x fs-2"></i>
|
||||
</span>
|
||||
|
||||
<span
|
||||
class="btn btn-icon btn-circle btn-active-color-primary w-25px h-25px bg-body shadow"
|
||||
data-kt-image-input-action="remove" data-bs-toggle="tooltip"
|
||||
title="Remove avatar">
|
||||
<i class="bi bi-x fs-2"></i>
|
||||
</span>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="text-muted fs-7">Set the profile picture. Only *.png, *.jpg and *.jpeg
|
||||
image
|
||||
files are accepted</div>
|
||||
|
||||
</div>
|
||||
|
||||
{{-- Active --}}
|
||||
<div class="card-header" style="border: unset;">
|
||||
<div class="required card-title">
|
||||
<h2>Active</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body pt-0">
|
||||
|
||||
<label class="form-check form-switch form-check-custom form-check-solid">
|
||||
<input class="form-check-input" disabled readonly name="active" type="checkbox"
|
||||
value="1" checked />
|
||||
</label>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="d-flex flex-column flex-row-fluid gap-7 gap-lg-10">
|
||||
|
||||
<div class="card card-flush py-4">
|
||||
|
||||
|
||||
@if (Session::has('messageSuccess'))
|
||||
<div class="card-body">
|
||||
@include('uc/messageSuccess')
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@if (Session::has('messageFail'))
|
||||
<div class="card-body">
|
||||
@include('uc/messageFail')
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<div class="card-header">
|
||||
<div class="card-title">
|
||||
<h2>Overview</h2>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card-body pt-0">
|
||||
|
||||
|
||||
{{-- <div class="mb-10 fv-row">
|
||||
<label class="required form-label">Date</label>
|
||||
<div class="position-relative d-flex align-items-center">
|
||||
<span class="svg-icon svg-icon-2 position-absolute mx-4">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<path opacity="0.3"
|
||||
d="M21 22H3C2.4 22 2 21.6 2 21V5C2 4.4 2.4 4 3 4H21C21.6 4 22 4.4 22 5V21C22 21.6 21.6 22 21 22Z"
|
||||
fill="currentColor" />
|
||||
<path
|
||||
d="M6 6C5.4 6 5 5.6 5 5V3C5 2.4 5.4 2 6 2C6.6 2 7 2.4 7 3V5C7 5.6 6.6 6 6 6ZM11 5V3C11 2.4 10.6 2 10 2C9.4 2 9 2.4 9 3V5C9 5.6 9.4 6 10 6C10.6 6 11 5.6 11 5ZM15 5V3C15 2.4 14.6 2 14 2C13.4 2 13 2.4 13 3V5C13 5.6 13.4 6 14 6C14.6 6 15 5.6 15 5ZM19 5V3C19 2.4 18.6 2 18 2C17.4 2 17 2.4 17 3V5C17 5.6 17.4 6 18 6C18.6 6 19 5.6 19 5Z"
|
||||
fill="currentColor" />
|
||||
<path
|
||||
d="M8.8 13.1C9.2 13.1 9.5 13 9.7 12.8C9.9 12.6 10.1 12.3 10.1 11.9C10.1 11.6 10 11.3 9.8 11.1C9.6 10.9 9.3 10.8 9 10.8C8.8 10.8 8.59999 10.8 8.39999 10.9C8.19999 11 8.1 11.1 8 11.2C7.9 11.3 7.8 11.4 7.7 11.6C7.6 11.8 7.5 11.9 7.5 12.1C7.5 12.2 7.4 12.2 7.3 12.3C7.2 12.4 7.09999 12.4 6.89999 12.4C6.69999 12.4 6.6 12.3 6.5 12.2C6.4 12.1 6.3 11.9 6.3 11.7C6.3 11.5 6.4 11.3 6.5 11.1C6.6 10.9 6.8 10.7 7 10.5C7.2 10.3 7.49999 10.1 7.89999 10C8.29999 9.90003 8.60001 9.80003 9.10001 9.80003C9.50001 9.80003 9.80001 9.90003 10.1 10C10.4 10.1 10.7 10.3 10.9 10.4C11.1 10.5 11.3 10.8 11.4 11.1C11.5 11.4 11.6 11.6 11.6 11.9C11.6 12.3 11.5 12.6 11.3 12.9C11.1 13.2 10.9 13.5 10.6 13.7C10.9 13.9 11.2 14.1 11.4 14.3C11.6 14.5 11.8 14.7 11.9 15C12 15.3 12.1 15.5 12.1 15.8C12.1 16.2 12 16.5 11.9 16.8C11.8 17.1 11.5 17.4 11.3 17.7C11.1 18 10.7 18.2 10.3 18.3C9.9 18.4 9.5 18.5 9 18.5C8.5 18.5 8.1 18.4 7.7 18.2C7.3 18 7 17.8 6.8 17.6C6.6 17.4 6.4 17.1 6.3 16.8C6.2 16.5 6.10001 16.3 6.10001 16.1C6.10001 15.9 6.2 15.7 6.3 15.6C6.4 15.5 6.6 15.4 6.8 15.4C6.9 15.4 7.00001 15.4 7.10001 15.5C7.20001 15.6 7.3 15.6 7.3 15.7C7.5 16.2 7.7 16.6 8 16.9C8.3 17.2 8.6 17.3 9 17.3C9.2 17.3 9.5 17.2 9.7 17.1C9.9 17 10.1 16.8 10.3 16.6C10.5 16.4 10.5 16.1 10.5 15.8C10.5 15.3 10.4 15 10.1 14.7C9.80001 14.4 9.50001 14.3 9.10001 14.3C9.00001 14.3 8.9 14.3 8.7 14.3C8.5 14.3 8.39999 14.3 8.39999 14.3C8.19999 14.3 7.99999 14.2 7.89999 14.1C7.79999 14 7.7 13.8 7.7 13.7C7.7 13.5 7.79999 13.4 7.89999 13.2C7.99999 13 8.2 13 8.5 13H8.8V13.1ZM15.3 17.5V12.2C14.3 13 13.6 13.3 13.3 13.3C13.1 13.3 13 13.2 12.9 13.1C12.8 13 12.7 12.8 12.7 12.6C12.7 12.4 12.8 12.3 12.9 12.2C13 12.1 13.2 12 13.6 11.8C14.1 11.6 14.5 11.3 14.7 11.1C14.9 10.9 15.2 10.6 15.5 10.3C15.8 10 15.9 9.80003 15.9 9.70003C15.9 9.60003 16.1 9.60004 16.3 9.60004C16.5 9.60004 16.7 9.70003 16.8 9.80003C16.9 9.90003 17 10.2 17 10.5V17.2C17 18 16.7 18.4 16.2 18.4C16 18.4 15.8 18.3 15.6 18.2C15.4 18.1 15.3 17.8 15.3 17.5Z"
|
||||
fill="currentColor" />
|
||||
</svg>
|
||||
</span>
|
||||
<input class="form-control form-control-solid ps-12" placeholder="Date"
|
||||
name="due_date" id="due_date" />
|
||||
</div>
|
||||
</div> --}}
|
||||
|
||||
<div class="mb-10 fv-row">
|
||||
<label class="required form-label">Subject</label>
|
||||
<input type="text" name="name" class="form-control mb-2 col-6"
|
||||
value="{{ old('name') }}" />
|
||||
</div>
|
||||
|
||||
|
||||
<div class="mb-10 fv-row">
|
||||
<label class="required form-label">Subject (EN)</label>
|
||||
<input type="text" name="name_en" class="form-control mb-2 col-6"
|
||||
value="{{ old('name_en') }}" />
|
||||
</div>
|
||||
|
||||
{{-- <div class="mb-10 fv-row">
|
||||
<label class="required form-label">Description</label>
|
||||
<div class="form-control" id="description" name="description"></div>
|
||||
<input type="hidden" id="description_input" name="description" />
|
||||
</div>
|
||||
|
||||
|
||||
<div class="mb-10 fv-row">
|
||||
<label class="required form-label">Description (EN)</label>
|
||||
<div class="form-control" id="description_en" name="description_en"></div>
|
||||
<input type="hidden" id="description_input_en" name="description_en" />
|
||||
|
||||
</div> --}}
|
||||
|
||||
{{-- <div hidden class="mb-10">
|
||||
<label class="form-label required">File Video</label>
|
||||
<input class="files-video" type="file" name="file_video[]" multiple
|
||||
accept=".MP4, .MOV">
|
||||
<div class="text-muted fs-7">Allowed Types .MP4, .MOV</div>
|
||||
</div>
|
||||
|
||||
<div hidden class="mb-10">
|
||||
<label class="form-label required">File Image</label>
|
||||
<input class="files-image" type="file" name="file_image[]" multiple
|
||||
accept=".jpg, .bmp, .jpeg, .png">
|
||||
<div class="text-muted fs-7">Allowed Types .jpg, .bmp, .jpeg, .png</div>
|
||||
</div>
|
||||
|
||||
<div hidden class="mb-10">
|
||||
<label class="form-label required">File Sound</label>
|
||||
<input class="files-sound" type="file" name="file_sound[]" multiple
|
||||
accept=".m4a, .mp4, .mp3, .wav">
|
||||
<div class="text-muted fs-7">Allowed Types .m4a, .mp4, .mp3, .wav</div>
|
||||
</div>
|
||||
|
||||
<div hidden class="mb-10">
|
||||
<label class="form-label required">File Documents</label>
|
||||
<input class="files-document" type="file" name="file_document[]" multiple
|
||||
accept=".pdf, .xls, .doc, .docx, .pptx, .csv, .txt">
|
||||
<div class="text-muted fs-7">Allowed Types .pdf, .xls, .doc, .docx, .pptx, .csv,
|
||||
.txt</div>
|
||||
</div> --}}
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="d-flex justify-content-end">
|
||||
|
||||
<a href="{{ url('no-where-else/sub-category') }}" id="kt_ecommerce_add_product_cancel"
|
||||
class="btn btn-light me-5">Cancel</a>
|
||||
|
||||
<button id="btn_submit" class="btn btn-primary">
|
||||
<span class="indicator-label">Save Changes</span>
|
||||
</button>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</form>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
@stop
|
||||
|
||||
|
||||
@section('script')
|
||||
|
||||
<!-- Include Editor.js core -->
|
||||
<script src="https://cdn.jsdelivr.net/npm/@editorjs/editorjs@latest"></script>
|
||||
|
||||
<!-- Include the plugins -->
|
||||
<script src="https://cdn.jsdelivr.net/npm/@editorjs/header"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/@editorjs/list"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/@editorjs/paragraph"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/@editorjs/quote"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/@editorjs/image"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/editorjs-inline-image"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/@editorjs/embed"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/@editorjs/code"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/@editorjs/table"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/@editorjs/marker"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/@editorjs/checklist"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/@editorjs/delimiter"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/@editorjs/warning"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/@editorjs/link"></script>
|
||||
|
||||
|
||||
<script>
|
||||
/*
|
||||
class VideoTool {
|
||||
constructor({
|
||||
data
|
||||
}) {
|
||||
this.data = data || {};
|
||||
}
|
||||
|
||||
// Render input for video URL
|
||||
render() {
|
||||
const wrapper = document.createElement("div");
|
||||
|
||||
const input = document.createElement("input");
|
||||
input.type = "text";
|
||||
input.placeholder = "Enter video URL";
|
||||
input.value = this.data.url || "";
|
||||
input.style.width = "100%";
|
||||
|
||||
const video = document.createElement("video");
|
||||
video.controls = true;
|
||||
video.style.width = "100%";
|
||||
video.style.marginTop = "10px";
|
||||
video.src = this.data.url || "";
|
||||
|
||||
input.addEventListener("input", (event) => {
|
||||
const value = event.target.value;
|
||||
this.data.url = value;
|
||||
video.src = value;
|
||||
});
|
||||
|
||||
wrapper.appendChild(input);
|
||||
wrapper.appendChild(video);
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
// Save the video URL
|
||||
save(blockContent) {
|
||||
const input = blockContent.querySelector("input");
|
||||
return {
|
||||
url: input.value,
|
||||
};
|
||||
}
|
||||
|
||||
// Editor.js toolbox definition
|
||||
static get toolbox() {
|
||||
return {
|
||||
title: "Video",
|
||||
icon: '<svg width="20" height="20" viewBox="0 0 24 24"><path d="M10 8.64L15.27 12 10 15.36V8.64M10 3.14L21 12 10 20.86V3.14M3 4h4v16H3V4z"></path></svg>',
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
const tools = {
|
||||
header: {
|
||||
class: Header,
|
||||
inlineToolbar: ['link', 'bold', 'italic'],
|
||||
config: {
|
||||
placeholder: 'Enter a header',
|
||||
levels: [2, 3, 4], // Set header levels
|
||||
defaultLevel: 3,
|
||||
},
|
||||
},
|
||||
embed: {
|
||||
class: Embed,
|
||||
inlineToolbar: true,
|
||||
config: {
|
||||
services: {
|
||||
youtube: true,
|
||||
vimeo: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
video: {
|
||||
class: VideoTool,
|
||||
inlineToolbar: true,
|
||||
},
|
||||
image: {
|
||||
class: InlineImage,
|
||||
inlineToolbar: true,
|
||||
config: {
|
||||
embed: {
|
||||
display: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
const editorDescription = new EditorJS({
|
||||
holder: 'description',
|
||||
tools: tools
|
||||
});
|
||||
const editorDescriptionEn = new EditorJS({
|
||||
holder: 'description_en',
|
||||
tools: tools,
|
||||
});
|
||||
*/
|
||||
</script>
|
||||
|
||||
<script type="text/javascript">
|
||||
$(function() {
|
||||
/*
|
||||
$('#due_date').flatpickr({
|
||||
enableTime: false,
|
||||
dateFormat: 'd-m-Y',
|
||||
defaultDate: null, // Do not preselect any date
|
||||
onReady: function(selectedDates, dateStr, instance) {
|
||||
// Highlight today's date with a custom CSS class
|
||||
const today = instance.todayDateElem;
|
||||
today.classList.add('flatpickr-today-highlight'); // Add a custom class to today
|
||||
}
|
||||
});
|
||||
|
||||
// file video
|
||||
$('.files-video').fileuploader({
|
||||
extensions: ['MP4', 'mp4', 'MOV', 'mov'],
|
||||
limit: null,
|
||||
fileMaxSize: null,
|
||||
changeInput: '<div class="fileuploader-input">' +
|
||||
'<div class="fileuploader-input-inner">' +
|
||||
'<p><i class="fileuploader-icon-main"></i></p>' +
|
||||
'<h6>Drag and drop files here</h6>' +
|
||||
'<p>or</p>' +
|
||||
'<br>' +
|
||||
'<button type="button" class="fileuploader-input-button"><span>${captions.button}</span></button>' +
|
||||
'</div>' +
|
||||
'</div>',
|
||||
theme: 'dragdrop',
|
||||
});
|
||||
|
||||
// file image
|
||||
$('.files-image').fileuploader({
|
||||
extensions: ['jpg', 'bmp', 'jpeg', 'png'],
|
||||
limit: null,
|
||||
fileMaxSize: null,
|
||||
changeInput: '<div class="fileuploader-input">' +
|
||||
'<div class="fileuploader-input-inner">' +
|
||||
'<p><i class="fileuploader-icon-main"></i></p>' +
|
||||
'<h6>Drag and drop files here</h6>' +
|
||||
'<p>or</p>' +
|
||||
'<br>' +
|
||||
'<button type="button" class="fileuploader-input-button"><span>${captions.button}</span></button>' +
|
||||
'</div>' +
|
||||
'</div>',
|
||||
theme: 'dragdrop',
|
||||
});
|
||||
|
||||
// file sound
|
||||
$('.files-sound').fileuploader({
|
||||
extensions: ['m4a', 'mp4', 'mp3', 'wav'],
|
||||
limit: null,
|
||||
fileMaxSize: null,
|
||||
changeInput: '<div class="fileuploader-input">' +
|
||||
'<div class="fileuploader-input-inner">' +
|
||||
'<p><i class="fileuploader-icon-main"></i></p>' +
|
||||
'<h6>Drag and drop files here</h6>' +
|
||||
'<p>or</p>' +
|
||||
'<br>' +
|
||||
'<button type="button" class="fileuploader-input-button"><span>${captions.button}</span></button>' +
|
||||
'</div>' +
|
||||
'</div>',
|
||||
theme: 'dragdrop',
|
||||
});
|
||||
|
||||
// file document
|
||||
$('.files-document').fileuploader({
|
||||
extensions: ['pdf', 'xls', 'doc', 'docx', 'pptx', 'csv', 'txt'],
|
||||
limit: null,
|
||||
fileMaxSize: null,
|
||||
changeInput: '<div class="fileuploader-input">' +
|
||||
'<div class="fileuploader-input-inner">' +
|
||||
'<p><i class="fileuploader-icon-main"></i></p>' +
|
||||
'<h6>Drag and drop files here</h6>' +
|
||||
'<p>or</p>' +
|
||||
'<br>' +
|
||||
'<button type="button" class="fileuploader-input-button"><span>${captions.button}</span></button>' +
|
||||
'</div>' +
|
||||
'</div>',
|
||||
theme: 'dragdrop',
|
||||
});
|
||||
*/
|
||||
|
||||
$(document).on('click', '#btn_submit', function(e) {
|
||||
e.preventDefault(); // Prevent default form submission
|
||||
|
||||
alertLoading("Loading..."); // Show loading alert (your custom function)
|
||||
|
||||
$('#frmAdd').submit();
|
||||
|
||||
/*
|
||||
// Save both editor contents
|
||||
Promise.all([editorDescription.save(), editorDescriptionEn.save()])
|
||||
.then(([descriptionData, descriptionEnData]) => {
|
||||
|
||||
// Store the JSON output in the hidden input fields
|
||||
$('#description_input').val(JSON.stringify(descriptionData));
|
||||
$('#description_input_en').val(JSON.stringify(descriptionEnData));
|
||||
|
||||
// Submit the form after saving the data
|
||||
$('#frmAdd').submit();
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('Error saving editor content:', error);
|
||||
});
|
||||
*/
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
@endsection
|
||||
@@ -0,0 +1,505 @@
|
||||
@extends('layouts.backendTemplate')
|
||||
|
||||
@section('content')
|
||||
|
||||
<style>
|
||||
.video-responsive {
|
||||
position: relative;
|
||||
padding-bottom: 56.25%;
|
||||
/* Aspect ratio 16:9 */
|
||||
height: 0;
|
||||
overflow: hidden;
|
||||
max-width: 100%;
|
||||
background: #000;
|
||||
}
|
||||
|
||||
.video-responsive video {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
</style>
|
||||
|
||||
<!--begin::Main-->
|
||||
<div class="app-main flex-column flex-row-fluid" id="kt_app_main">
|
||||
|
||||
<div class="d-flex flex-column flex-column-fluid">
|
||||
|
||||
|
||||
@include('uc.admin.breadcrumb', [
|
||||
'title' => 'CHIANG MAI AND NOWHERE ELSE : Edit Sub Category Management',
|
||||
'pageName' => 'Edit',
|
||||
'pageParent' => 'Sub Category Management',
|
||||
'pageParentLink' => url('no-where-else/sub-category'),
|
||||
])
|
||||
<div id="kt_app_content" class="app-content flex-column-fluid">
|
||||
<div id="kt_app_content_container" class="app-container container-xxl">
|
||||
|
||||
|
||||
<form id="frmUpdate" class="form d-flex flex-column flex-lg-row"
|
||||
action="{{ url('no-where-else/update-sub-category') }}" method="post" enctype="multipart/form-data">
|
||||
|
||||
<input type="hidden" name="id" value="{{ $itemView->id }}">
|
||||
<input type="hidden" name="_method" value="POST">
|
||||
<input type="hidden" name="_token" value="{{ csrf_token() }}">
|
||||
|
||||
|
||||
{{-- Left --}}
|
||||
<div class="d-flex flex-column gap-7 gap-lg-10 w-100 w-lg-300px mb-7 me-lg-10">
|
||||
|
||||
<div class="card card-flush py-4">
|
||||
|
||||
<div class="card-body text-center pt-0">
|
||||
|
||||
<style>
|
||||
.image-input-placeholder {
|
||||
background-image: url('{{ url('assets/media/svg/files/blank-image.svg') }}');
|
||||
}
|
||||
|
||||
[data-bs-theme="dark"] .image-input-placeholder {
|
||||
background-image: url('../media/svg/files/blank-image-dark.svg');
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="image-input image-input-empty image-input-outline image-input-placeholder mb-3"
|
||||
data-kt-image-input="true">
|
||||
|
||||
|
||||
@if ($itemView->image_url && $itemView->image_name)
|
||||
<div class="image-input-wrapper w-150px h-150px"
|
||||
style="background-image: url('{{ $itemView->image_url . '/thumbnail/' . $itemView->image_name }}')">
|
||||
</div>
|
||||
@else
|
||||
<div class="image-input-wrapper w-150px h-150px"></div>
|
||||
@endif
|
||||
|
||||
<label
|
||||
class="btn btn-icon btn-circle btn-active-color-primary w-25px h-25px bg-body shadow"
|
||||
data-kt-image-input-action="change" data-bs-toggle="tooltip"
|
||||
title="Change avatar">
|
||||
|
||||
<i class="bi bi-pencil-fill fs-7"></i>
|
||||
|
||||
<input type="file" name="avatar" accept=".png, .jpg, .jpeg" />
|
||||
<input type="hidden" name="avatar_remove" />
|
||||
|
||||
</label>
|
||||
|
||||
<span
|
||||
class="btn btn-icon btn-circle btn-active-color-primary w-25px h-25px bg-body shadow"
|
||||
data-kt-image-input-action="cancel" data-bs-toggle="tooltip"
|
||||
title="Cancel avatar">
|
||||
<i class="bi bi-x fs-2"></i>
|
||||
</span>
|
||||
|
||||
<span
|
||||
class="btn btn-icon btn-circle btn-active-color-primary w-25px h-25px bg-body shadow"
|
||||
data-kt-image-input-action="remove" data-bs-toggle="tooltip"
|
||||
title="Remove avatar">
|
||||
<i class="bi bi-x fs-2"></i>
|
||||
</span>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="text-muted fs-7">Set the profile picture. Only *.png, *.jpg and *.jpeg
|
||||
image
|
||||
files are accepted</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="card-header" style="border: unset;">
|
||||
<!--begin::Card title-->
|
||||
<div class="required card-title">
|
||||
<h2>Active</h2>
|
||||
</div>
|
||||
<!--end::Card title-->
|
||||
</div>
|
||||
<div class="card-body pt-0">
|
||||
|
||||
<label class="form-check form-switch form-check-custom form-check-solid">
|
||||
<input class="form-check-input" name="active" type="checkbox" value="1"
|
||||
{{ $itemView->active == 1 ? 'checked' : '' }} />
|
||||
</label>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
{{-- Right --}}
|
||||
<div class="d-flex flex-column flex-row-fluid gap-7 gap-lg-10">
|
||||
|
||||
<div class="card card-flush py-4">
|
||||
|
||||
@if (Session::has('messageSuccess'))
|
||||
<div class="card-body">
|
||||
@include('uc/messageSuccess')
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@if (Session::has('messageFail'))
|
||||
<div class="card-body">
|
||||
@include('uc/messageFail')
|
||||
</div>
|
||||
@endif
|
||||
|
||||
|
||||
<div class="card-header">
|
||||
<div class="card-title">
|
||||
<h2>Overview</h2>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card-body pt-0">
|
||||
|
||||
{{-- <div class="mb-10 fv-row">
|
||||
<div class="position-relative d-flex align-items-center">
|
||||
<span class="svg-icon svg-icon-2 position-absolute mx-4">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<path opacity="0.3"
|
||||
d="M21 22H3C2.4 22 2 21.6 2 21V5C2 4.4 2.4 4 3 4H21C21.6 4 22 4.4 22 5V21C22 21.6 21.6 22 21 22Z"
|
||||
fill="currentColor" />
|
||||
<path
|
||||
d="M6 6C5.4 6 5 5.6 5 5V3C5 2.4 5.4 2 6 2C6.6 2 7 2.4 7 3V5C7 5.6 6.6 6 6 6ZM11 5V3C11 2.4 10.6 2 10 2C9.4 2 9 2.4 9 3V5C9 5.6 9.4 6 10 6C10.6 6 11 5.6 11 5ZM15 5V3C15 2.4 14.6 2 14 2C13.4 2 13 2.4 13 3V5C13 5.6 13.4 6 14 6C14.6 6 15 5.6 15 5ZM19 5V3C19 2.4 18.6 2 18 2C17.4 2 17 2.4 17 3V5C17 5.6 17.4 6 18 6C18.6 6 19 5.6 19 5Z"
|
||||
fill="currentColor" />
|
||||
<path
|
||||
d="M8.8 13.1C9.2 13.1 9.5 13 9.7 12.8C9.9 12.6 10.1 12.3 10.1 11.9C10.1 11.6 10 11.3 9.8 11.1C9.6 10.9 9.3 10.8 9 10.8C8.8 10.8 8.59999 10.8 8.39999 10.9C8.19999 11 8.1 11.1 8 11.2C7.9 11.3 7.8 11.4 7.7 11.6C7.6 11.8 7.5 11.9 7.5 12.1C7.5 12.2 7.4 12.2 7.3 12.3C7.2 12.4 7.09999 12.4 6.89999 12.4C6.69999 12.4 6.6 12.3 6.5 12.2C6.4 12.1 6.3 11.9 6.3 11.7C6.3 11.5 6.4 11.3 6.5 11.1C6.6 10.9 6.8 10.7 7 10.5C7.2 10.3 7.49999 10.1 7.89999 10C8.29999 9.90003 8.60001 9.80003 9.10001 9.80003C9.50001 9.80003 9.80001 9.90003 10.1 10C10.4 10.1 10.7 10.3 10.9 10.4C11.1 10.5 11.3 10.8 11.4 11.1C11.5 11.4 11.6 11.6 11.6 11.9C11.6 12.3 11.5 12.6 11.3 12.9C11.1 13.2 10.9 13.5 10.6 13.7C10.9 13.9 11.2 14.1 11.4 14.3C11.6 14.5 11.8 14.7 11.9 15C12 15.3 12.1 15.5 12.1 15.8C12.1 16.2 12 16.5 11.9 16.8C11.8 17.1 11.5 17.4 11.3 17.7C11.1 18 10.7 18.2 10.3 18.3C9.9 18.4 9.5 18.5 9 18.5C8.5 18.5 8.1 18.4 7.7 18.2C7.3 18 7 17.8 6.8 17.6C6.6 17.4 6.4 17.1 6.3 16.8C6.2 16.5 6.10001 16.3 6.10001 16.1C6.10001 15.9 6.2 15.7 6.3 15.6C6.4 15.5 6.6 15.4 6.8 15.4C6.9 15.4 7.00001 15.4 7.10001 15.5C7.20001 15.6 7.3 15.6 7.3 15.7C7.5 16.2 7.7 16.6 8 16.9C8.3 17.2 8.6 17.3 9 17.3C9.2 17.3 9.5 17.2 9.7 17.1C9.9 17 10.1 16.8 10.3 16.6C10.5 16.4 10.5 16.1 10.5 15.8C10.5 15.3 10.4 15 10.1 14.7C9.80001 14.4 9.50001 14.3 9.10001 14.3C9.00001 14.3 8.9 14.3 8.7 14.3C8.5 14.3 8.39999 14.3 8.39999 14.3C8.19999 14.3 7.99999 14.2 7.89999 14.1C7.79999 14 7.7 13.8 7.7 13.7C7.7 13.5 7.79999 13.4 7.89999 13.2C7.99999 13 8.2 13 8.5 13H8.8V13.1ZM15.3 17.5V12.2C14.3 13 13.6 13.3 13.3 13.3C13.1 13.3 13 13.2 12.9 13.1C12.8 13 12.7 12.8 12.7 12.6C12.7 12.4 12.8 12.3 12.9 12.2C13 12.1 13.2 12 13.6 11.8C14.1 11.6 14.5 11.3 14.7 11.1C14.9 10.9 15.2 10.6 15.5 10.3C15.8 10 15.9 9.80003 15.9 9.70003C15.9 9.60003 16.1 9.60004 16.3 9.60004C16.5 9.60004 16.7 9.70003 16.8 9.80003C16.9 9.90003 17 10.2 17 10.5V17.2C17 18 16.7 18.4 16.2 18.4C16 18.4 15.8 18.3 15.6 18.2C15.4 18.1 15.3 17.8 15.3 17.5Z"
|
||||
fill="currentColor" />
|
||||
</svg>
|
||||
</span>
|
||||
<input class="form-control form-control-solid ps-12" type="text"
|
||||
id="due_date" name="due_date"
|
||||
value="{{ $itemView->due_date ? date('d-m-Y', strtotime($itemView->due_date)) : '' }}">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</div> --}}
|
||||
|
||||
<div class="mb-10 fv-row">
|
||||
<label class="required form-label">Subject</label>
|
||||
<input type="text" name="name" class="form-control mb-2 col-6"
|
||||
value="{{ $itemView->name }}" />
|
||||
</div>
|
||||
|
||||
|
||||
<div class="mb-10 fv-row">
|
||||
<label class="required form-label">Subject (EN)</label>
|
||||
<input type="text" name="name_en" class="form-control mb-2 col-6"
|
||||
value="{{ $itemView->name_en }}" />
|
||||
</div>
|
||||
|
||||
{{-- <div class="mb-10 fv-row">
|
||||
<label class="required form-label">Description</label>
|
||||
<div class="form-control" id="description" name="description"></div>
|
||||
<input type="hidden" id="description_input" name="description" />
|
||||
</div>
|
||||
|
||||
|
||||
<div class="mb-10 fv-row">
|
||||
<label class="required form-label">Description (EN)</label>
|
||||
<div class="form-control" id="description_en" name="description_en"></div>
|
||||
<input type="hidden" id="description_input_en" name="description_en" />
|
||||
|
||||
</div> --}}
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="d-flex justify-content-end">
|
||||
|
||||
<a href="{{ url('no-where-else/sub-category') }}" id="kt_ecommerce_add_product_cancel"
|
||||
class="btn btn-light me-5">Cancel</a>
|
||||
|
||||
<button type="button" id="btn_submit" class="btn btn-primary">
|
||||
<span class="indicator-label">Save</span>
|
||||
</button>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</form>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
@stop
|
||||
|
||||
|
||||
|
||||
|
||||
@section('script')
|
||||
|
||||
<script type="text/javascript">
|
||||
$(function() {
|
||||
/*
|
||||
$('#due_date').flatpickr({
|
||||
enableTime: false,
|
||||
dateFormat: 'd-m-Y',
|
||||
defaultDate: null
|
||||
onReady: function(selectedDates, dateStr, instance) {
|
||||
const today = instance.todayDateElem;
|
||||
today.classList.add('flatpickr-today-highlight');
|
||||
}
|
||||
});
|
||||
*/
|
||||
|
||||
/*
|
||||
// file video
|
||||
$('.files-video').fileuploader({
|
||||
extensions: ['MP4', 'mp4', 'MOV', 'mov'],
|
||||
limit: null,
|
||||
fileMaxSize: null,
|
||||
changeInput: '<div class="fileuploader-input">' +
|
||||
'<div class="fileuploader-input-inner">' +
|
||||
'<p><i class="fileuploader-icon-main"></i></p>' +
|
||||
'<h6>Drag and drop files here</h6>' +
|
||||
'<p>or</p>' +
|
||||
'<br>' +
|
||||
'<button type="button" class="fileuploader-input-button"><span>${captions.button}</span></button>' +
|
||||
'</div>' +
|
||||
'</div>',
|
||||
theme: 'dragdrop',
|
||||
});
|
||||
|
||||
// file image
|
||||
$('.files-image').fileuploader({
|
||||
extensions: ['jpg', 'bmp', 'jpeg', 'png'],
|
||||
limit: null,
|
||||
fileMaxSize: null,
|
||||
changeInput: '<div class="fileuploader-input">' +
|
||||
'<div class="fileuploader-input-inner">' +
|
||||
'<p><i class="fileuploader-icon-main"></i></p>' +
|
||||
'<h6>Drag and drop files here</h6>' +
|
||||
'<p>or</p>' +
|
||||
'<br>' +
|
||||
'<button type="button" class="fileuploader-input-button"><span>${captions.button}</span></button>' +
|
||||
'</div>' +
|
||||
'</div>',
|
||||
theme: 'dragdrop',
|
||||
});
|
||||
|
||||
// file sound
|
||||
$('.files-sound').fileuploader({
|
||||
extensions: ['m4a', 'mp4', 'mp3', 'wav'],
|
||||
limit: null,
|
||||
fileMaxSize: null,
|
||||
changeInput: '<div class="fileuploader-input">' +
|
||||
'<div class="fileuploader-input-inner">' +
|
||||
'<p><i class="fileuploader-icon-main"></i></p>' +
|
||||
'<h6>Drag and drop files here</h6>' +
|
||||
'<p>or</p>' +
|
||||
'<br>' +
|
||||
'<button type="button" class="fileuploader-input-button"><span>${captions.button}</span></button>' +
|
||||
'</div>' +
|
||||
'</div>',
|
||||
theme: 'dragdrop',
|
||||
});
|
||||
|
||||
// file document
|
||||
$('.files-document').fileuploader({
|
||||
extensions: ['pdf', 'xls', 'doc', 'docx', 'pptx', 'csv', 'txt'],
|
||||
limit: null,
|
||||
fileMaxSize: null,
|
||||
changeInput: '<div class="fileuploader-input">' +
|
||||
'<div class="fileuploader-input-inner">' +
|
||||
'<p><i class="fileuploader-icon-main"></i></p>' +
|
||||
'<h6>Drag and drop files here</h6>' +
|
||||
'<p>or</p>' +
|
||||
'<br>' +
|
||||
'<button type="button" class="fileuploader-input-button"><span>${captions.button}</span></button>' +
|
||||
'</div>' +
|
||||
'</div>',
|
||||
theme: 'dragdrop',
|
||||
});
|
||||
*/
|
||||
|
||||
$(document).on("click", "#btn_submit", function(e) {
|
||||
e.preventDefault();
|
||||
alertLoading("Loading")
|
||||
const form = $('#frmUpdate');
|
||||
form.submit();
|
||||
})
|
||||
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
<!-- Include Editor.js core -->
|
||||
<script src="https://cdn.jsdelivr.net/npm/@editorjs/editorjs@latest"></script>
|
||||
|
||||
<!-- Include the plugins -->
|
||||
<script src="https://cdn.jsdelivr.net/npm/@editorjs/header"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/@editorjs/list"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/@editorjs/paragraph"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/@editorjs/quote"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/@editorjs/image"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/editorjs-inline-image"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/@editorjs/embed"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/@editorjs/code"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/@editorjs/table"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/@editorjs/marker"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/@editorjs/checklist"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/@editorjs/delimiter"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/@editorjs/warning"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/@editorjs/link"></script>
|
||||
|
||||
<script>
|
||||
// Custom video tool for embedding videos
|
||||
/*
|
||||
class VideoTool {
|
||||
constructor({
|
||||
data
|
||||
}) {
|
||||
this.data = data || {};
|
||||
}
|
||||
|
||||
// Render input for video URL
|
||||
render() {
|
||||
const wrapper = document.createElement("div");
|
||||
|
||||
const input = document.createElement("input");
|
||||
input.type = "text";
|
||||
input.placeholder = "Enter video URL";
|
||||
input.value = this.data.url || "";
|
||||
input.style.width = "100%";
|
||||
|
||||
const video = document.createElement("video");
|
||||
video.controls = true;
|
||||
video.style.width = "100%";
|
||||
video.style.marginTop = "10px";
|
||||
video.src = this.data.url || "";
|
||||
|
||||
input.addEventListener("input", (event) => {
|
||||
const value = event.target.value;
|
||||
this.data.url = value;
|
||||
video.src = value;
|
||||
});
|
||||
|
||||
wrapper.appendChild(input);
|
||||
wrapper.appendChild(video);
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
// Save the video URL
|
||||
save(blockContent) {
|
||||
const input = blockContent.querySelector("input");
|
||||
return {
|
||||
url: input.value,
|
||||
};
|
||||
}
|
||||
|
||||
// Editor.js toolbox definition
|
||||
static get toolbox() {
|
||||
return {
|
||||
title: "Video",
|
||||
icon: '<svg width="20" height="20" viewBox="0 0 24 24"><path d="M10 8.64L15.27 12 10 15.36V8.64M10 3.14L21 12 10 20.86V3.14M3 4h4v16H3V4z"></path></svg>',
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
const tools = {
|
||||
header: {
|
||||
class: Header,
|
||||
inlineToolbar: ['link', 'bold', 'italic'],
|
||||
config: {
|
||||
placeholder: 'Enter a header',
|
||||
levels: [2, 3, 4], // Set header levels
|
||||
defaultLevel: 3,
|
||||
},
|
||||
},
|
||||
embed: {
|
||||
class: Embed,
|
||||
inlineToolbar: true,
|
||||
config: {
|
||||
services: {
|
||||
youtube: true,
|
||||
vimeo: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
video: {
|
||||
class: VideoTool,
|
||||
inlineToolbar: true,
|
||||
},
|
||||
image: {
|
||||
class: InlineImage,
|
||||
inlineToolbar: true,
|
||||
config: {
|
||||
embed: {
|
||||
display: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
const descriptionData = {!! json_encode($itemView->description) !!};
|
||||
const editorDescription = new EditorJS({
|
||||
holder: 'description',
|
||||
tools: tools,
|
||||
data: descriptionData != "" ? JSON.parse(descriptionData) : {},
|
||||
onChange: () => {
|
||||
saveData(editorDescription, 'description_input')
|
||||
}
|
||||
});
|
||||
|
||||
const descriptionDataEn = {!! json_encode($itemView->description_en) !!};
|
||||
const editorDescriptionEn = new EditorJS({
|
||||
holder: 'description_en',
|
||||
tools: tools,
|
||||
data: descriptionDataEn !== "" ? JSON.parse(descriptionDataEn) : {},
|
||||
onChange: () => {
|
||||
saveData(editorDescriptionEn, 'description_input_en');
|
||||
}
|
||||
});
|
||||
*/
|
||||
|
||||
|
||||
|
||||
// Function to save data to hidden inputs
|
||||
function saveData(editor, inputId) {
|
||||
editor.save().then((outputData) => {
|
||||
document.getElementById(inputId).value = JSON.stringify(outputData);
|
||||
}).catch((error) => {
|
||||
console.error('Saving failed: ', error);
|
||||
});
|
||||
}
|
||||
|
||||
$(document).on('click', '#btn_submit', function(e) {
|
||||
e.preventDefault(); // Prevent default form submission
|
||||
|
||||
alertLoading("Loading..."); // Show loading alert (your custom function)
|
||||
$('#frmUpdate').submit();
|
||||
/*
|
||||
// Save both editor contents
|
||||
Promise.all([editorDescription.save(), editorDescriptionEn.save()])
|
||||
.then(([descriptionData, descriptionEnData]) => {
|
||||
// Store the JSON output in the hidden input fields
|
||||
$('#description_input').val(JSON.stringify(descriptionData));
|
||||
$('#description_input_en').val(JSON.stringify(descriptionEnData));
|
||||
|
||||
// Submit the form after saving the data
|
||||
$('#frmUpdate').submit();
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('Error saving editor content:', error);
|
||||
});
|
||||
*/
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
|
||||
@endsection
|
||||
@@ -0,0 +1,407 @@
|
||||
@extends('layouts.backendTemplate')
|
||||
|
||||
@section('content')
|
||||
|
||||
<!--begin::Main-->
|
||||
<div class="app-main flex-column flex-row-fluid" id="kt_app_main">
|
||||
|
||||
<div class="d-flex flex-column flex-column-fluid">
|
||||
|
||||
|
||||
@include('uc.breadcrumbList', [
|
||||
'title' => 'CHIANG MAI AND NOWHERE ELSE : Sub Category Management',
|
||||
'pageName' => 'Sub Category Management',
|
||||
])
|
||||
|
||||
|
||||
<div id="kt_app_content" class="app-content flex-column-fluid">
|
||||
<!--begin::Content container-->
|
||||
<div id="kt_app_content_container" class="app-container container-xxl">
|
||||
<!--begin::Card-->
|
||||
<div class="card">
|
||||
|
||||
@if (Session::has('messageSuccess'))
|
||||
<div class="card-body">
|
||||
@include('uc/messageSuccess')
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@if (Session::has('messageFail'))
|
||||
<div class="card-body">
|
||||
@include('uc/messageFail')
|
||||
</div>
|
||||
@endif
|
||||
|
||||
|
||||
<!--begin::Card header-->
|
||||
<div class="card-header border-0 pt-6">
|
||||
<!--begin::Card title-->
|
||||
<div class="d-flex align-items-center position-relative my-1">
|
||||
</div>
|
||||
|
||||
|
||||
@if (Auth::user()->role != 2)
|
||||
<div class="card-toolbar">
|
||||
<div class="d-flex justify-content-end" data-kt-customer-table-toolbar="base">
|
||||
<a href="{{ url('no-where-else/add-sub-category') }}" class="btn btn-primary">Add
|
||||
</a>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@endif
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<div class="card-header border-0 pt-5">
|
||||
|
||||
<div class="card-title">
|
||||
<div class="d-flex align-items-center position-relative my-1">
|
||||
<span class="svg-icon svg-icon-1 position-absolute ms-4">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<rect opacity="0.5" x="17.0365" y="15.1223" width="8.15546" height="2"
|
||||
rx="1" transform="rotate(45 17.0365 15.1223)" fill="currentColor">
|
||||
</rect>
|
||||
<path
|
||||
d="M11 19C6.55556 19 3 15.4444 3 11C3 6.55556 6.55556 3 11 3C15.4444 3 19 6.55556 19 11C19 15.4444 15.4444 19 11 19ZM11 5C7.53333 5 5 7.53333 5 11C5 14.4667 7.53333 17 11 17C14.4667 17 17 14.4667 17 11C17 7.53333 14.4667 5 11 5Z"
|
||||
fill="currentColor"></path>
|
||||
</svg>
|
||||
</span>
|
||||
|
||||
<input type="text" table-filter="search"
|
||||
class="form-control form-control-solid w-250px ps-15" placeholder="Search" />
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- <div class="card-toolbar flex-row-fluid justify-content-end gap-5">
|
||||
|
||||
<div class="w-100 mw-150px">
|
||||
<div class="position-relative d-flex align-items-center">
|
||||
<span class="svg-icon svg-icon-2 position-absolute mx-4">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<path opacity="0.3"
|
||||
d="M21 22H3C2.4 22 2 21.6 2 21V5C2 4.4 2.4 4 3 4H21C21.6 4 22 4.4 22 5V21C22 21.6 21.6 22 21 22Z"
|
||||
fill="currentColor" />
|
||||
<path
|
||||
d="M6 6C5.4 6 5 5.6 5 5V3C5 2.4 5.4 2 6 2C6.6 2 7 2.4 7 3V5C7 5.6 6.6 6 6 6ZM11 5V3C11 2.4 10.6 2 10 2C9.4 2 9 2.4 9 3V5C9 5.6 9.4 6 10 6C10.6 6 11 5.6 11 5ZM15 5V3C15 2.4 14.6 2 14 2C13.4 2 13 2.4 13 3V5C13 5.6 13.4 6 14 6C14.6 6 15 5.6 15 5ZM19 5V3C19 2.4 18.6 2 18 2C17.4 2 17 2.4 17 3V5C17 5.6 17.4 6 18 6C18.6 6 19 5.6 19 5Z"
|
||||
fill="currentColor" />
|
||||
<path
|
||||
d="M8.8 13.1C9.2 13.1 9.5 13 9.7 12.8C9.9 12.6 10.1 12.3 10.1 11.9C10.1 11.6 10 11.3 9.8 11.1C9.6 10.9 9.3 10.8 9 10.8C8.8 10.8 8.59999 10.8 8.39999 10.9C8.19999 11 8.1 11.1 8 11.2C7.9 11.3 7.8 11.4 7.7 11.6C7.6 11.8 7.5 11.9 7.5 12.1C7.5 12.2 7.4 12.2 7.3 12.3C7.2 12.4 7.09999 12.4 6.89999 12.4C6.69999 12.4 6.6 12.3 6.5 12.2C6.4 12.1 6.3 11.9 6.3 11.7C6.3 11.5 6.4 11.3 6.5 11.1C6.6 10.9 6.8 10.7 7 10.5C7.2 10.3 7.49999 10.1 7.89999 10C8.29999 9.90003 8.60001 9.80003 9.10001 9.80003C9.50001 9.80003 9.80001 9.90003 10.1 10C10.4 10.1 10.7 10.3 10.9 10.4C11.1 10.5 11.3 10.8 11.4 11.1C11.5 11.4 11.6 11.6 11.6 11.9C11.6 12.3 11.5 12.6 11.3 12.9C11.1 13.2 10.9 13.5 10.6 13.7C10.9 13.9 11.2 14.1 11.4 14.3C11.6 14.5 11.8 14.7 11.9 15C12 15.3 12.1 15.5 12.1 15.8C12.1 16.2 12 16.5 11.9 16.8C11.8 17.1 11.5 17.4 11.3 17.7C11.1 18 10.7 18.2 10.3 18.3C9.9 18.4 9.5 18.5 9 18.5C8.5 18.5 8.1 18.4 7.7 18.2C7.3 18 7 17.8 6.8 17.6C6.6 17.4 6.4 17.1 6.3 16.8C6.2 16.5 6.10001 16.3 6.10001 16.1C6.10001 15.9 6.2 15.7 6.3 15.6C6.4 15.5 6.6 15.4 6.8 15.4C6.9 15.4 7.00001 15.4 7.10001 15.5C7.20001 15.6 7.3 15.6 7.3 15.7C7.5 16.2 7.7 16.6 8 16.9C8.3 17.2 8.6 17.3 9 17.3C9.2 17.3 9.5 17.2 9.7 17.1C9.9 17 10.1 16.8 10.3 16.6C10.5 16.4 10.5 16.1 10.5 15.8C10.5 15.3 10.4 15 10.1 14.7C9.80001 14.4 9.50001 14.3 9.10001 14.3C9.00001 14.3 8.9 14.3 8.7 14.3C8.5 14.3 8.39999 14.3 8.39999 14.3C8.19999 14.3 7.99999 14.2 7.89999 14.1C7.79999 14 7.7 13.8 7.7 13.7C7.7 13.5 7.79999 13.4 7.89999 13.2C7.99999 13 8.2 13 8.5 13H8.8V13.1ZM15.3 17.5V12.2C14.3 13 13.6 13.3 13.3 13.3C13.1 13.3 13 13.2 12.9 13.1C12.8 13 12.7 12.8 12.7 12.6C12.7 12.4 12.8 12.3 12.9 12.2C13 12.1 13.2 12 13.6 11.8C14.1 11.6 14.5 11.3 14.7 11.1C14.9 10.9 15.2 10.6 15.5 10.3C15.8 10 15.9 9.80003 15.9 9.70003C15.9 9.60003 16.1 9.60004 16.3 9.60004C16.5 9.60004 16.7 9.70003 16.8 9.80003C16.9 9.90003 17 10.2 17 10.5V17.2C17 18 16.7 18.4 16.2 18.4C16 18.4 15.8 18.3 15.6 18.2C15.4 18.1 15.3 17.8 15.3 17.5Z"
|
||||
fill="currentColor" />
|
||||
</svg>
|
||||
</span>
|
||||
<input class="form-control form-control-solid ps-12" placeholder="From"
|
||||
id="due_date_from" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="w-100 mw-150px">
|
||||
<div class="position-relative d-flex align-items-center">
|
||||
<span class="svg-icon svg-icon-2 position-absolute mx-4">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<path opacity="0.3"
|
||||
d="M21 22H3C2.4 22 2 21.6 2 21V5C2 4.4 2.4 4 3 4H21C21.6 4 22 4.4 22 5V21C22 21.6 21.6 22 21 22Z"
|
||||
fill="currentColor" />
|
||||
<path
|
||||
d="M6 6C5.4 6 5 5.6 5 5V3C5 2.4 5.4 2 6 2C6.6 2 7 2.4 7 3V5C7 5.6 6.6 6 6 6ZM11 5V3C11 2.4 10.6 2 10 2C9.4 2 9 2.4 9 3V5C9 5.6 9.4 6 10 6C10.6 6 11 5.6 11 5ZM15 5V3C15 2.4 14.6 2 14 2C13.4 2 13 2.4 13 3V5C13 5.6 13.4 6 14 6C14.6 6 15 5.6 15 5ZM19 5V3C19 2.4 18.6 2 18 2C17.4 2 17 2.4 17 3V5C17 5.6 17.4 6 18 6C18.6 6 19 5.6 19 5Z"
|
||||
fill="currentColor" />
|
||||
<path
|
||||
d="M8.8 13.1C9.2 13.1 9.5 13 9.7 12.8C9.9 12.6 10.1 12.3 10.1 11.9C10.1 11.6 10 11.3 9.8 11.1C9.6 10.9 9.3 10.8 9 10.8C8.8 10.8 8.59999 10.8 8.39999 10.9C8.19999 11 8.1 11.1 8 11.2C7.9 11.3 7.8 11.4 7.7 11.6C7.6 11.8 7.5 11.9 7.5 12.1C7.5 12.2 7.4 12.2 7.3 12.3C7.2 12.4 7.09999 12.4 6.89999 12.4C6.69999 12.4 6.6 12.3 6.5 12.2C6.4 12.1 6.3 11.9 6.3 11.7C6.3 11.5 6.4 11.3 6.5 11.1C6.6 10.9 6.8 10.7 7 10.5C7.2 10.3 7.49999 10.1 7.89999 10C8.29999 9.90003 8.60001 9.80003 9.10001 9.80003C9.50001 9.80003 9.80001 9.90003 10.1 10C10.4 10.1 10.7 10.3 10.9 10.4C11.1 10.5 11.3 10.8 11.4 11.1C11.5 11.4 11.6 11.6 11.6 11.9C11.6 12.3 11.5 12.6 11.3 12.9C11.1 13.2 10.9 13.5 10.6 13.7C10.9 13.9 11.2 14.1 11.4 14.3C11.6 14.5 11.8 14.7 11.9 15C12 15.3 12.1 15.5 12.1 15.8C12.1 16.2 12 16.5 11.9 16.8C11.8 17.1 11.5 17.4 11.3 17.7C11.1 18 10.7 18.2 10.3 18.3C9.9 18.4 9.5 18.5 9 18.5C8.5 18.5 8.1 18.4 7.7 18.2C7.3 18 7 17.8 6.8 17.6C6.6 17.4 6.4 17.1 6.3 16.8C6.2 16.5 6.10001 16.3 6.10001 16.1C6.10001 15.9 6.2 15.7 6.3 15.6C6.4 15.5 6.6 15.4 6.8 15.4C6.9 15.4 7.00001 15.4 7.10001 15.5C7.20001 15.6 7.3 15.6 7.3 15.7C7.5 16.2 7.7 16.6 8 16.9C8.3 17.2 8.6 17.3 9 17.3C9.2 17.3 9.5 17.2 9.7 17.1C9.9 17 10.1 16.8 10.3 16.6C10.5 16.4 10.5 16.1 10.5 15.8C10.5 15.3 10.4 15 10.1 14.7C9.80001 14.4 9.50001 14.3 9.10001 14.3C9.00001 14.3 8.9 14.3 8.7 14.3C8.5 14.3 8.39999 14.3 8.39999 14.3C8.19999 14.3 7.99999 14.2 7.89999 14.1C7.79999 14 7.7 13.8 7.7 13.7C7.7 13.5 7.79999 13.4 7.89999 13.2C7.99999 13 8.2 13 8.5 13H8.8V13.1ZM15.3 17.5V12.2C14.3 13 13.6 13.3 13.3 13.3C13.1 13.3 13 13.2 12.9 13.1C12.8 13 12.7 12.8 12.7 12.6C12.7 12.4 12.8 12.3 12.9 12.2C13 12.1 13.2 12 13.6 11.8C14.1 11.6 14.5 11.3 14.7 11.1C14.9 10.9 15.2 10.6 15.5 10.3C15.8 10 15.9 9.80003 15.9 9.70003C15.9 9.60003 16.1 9.60004 16.3 9.60004C16.5 9.60004 16.7 9.70003 16.8 9.80003C16.9 9.90003 17 10.2 17 10.5V17.2C17 18 16.7 18.4 16.2 18.4C16 18.4 15.8 18.3 15.6 18.2C15.4 18.1 15.3 17.8 15.3 17.5Z"
|
||||
fill="currentColor" />
|
||||
</svg>
|
||||
</span>
|
||||
<input class="form-control form-control-solid ps-12" placeholder="To"
|
||||
id="due_date_to" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button type="button" id="btn-submit" class="btn btn-primary">
|
||||
Search
|
||||
</button>
|
||||
|
||||
</div> --}}
|
||||
|
||||
</div>
|
||||
|
||||
<div class="card-body py-4">
|
||||
<!--begin::Table-->
|
||||
<table class="table align-middle table-row-dashed fs-6 gy-5" id="data-table-category">
|
||||
<!--begin::Table head-->
|
||||
<thead>
|
||||
<!--begin::Table row-->
|
||||
<tr class="text-start text-muted fw-bold fs-7 text-uppercase gs-0">
|
||||
<th class="min-w-125px">Pic</th>
|
||||
<th class="min-w-125px">Subject</th>
|
||||
<th class="min-w-125px">Subject (EN)</th>
|
||||
<th class="min-w-125px">Created</th>
|
||||
<th class="min-w-125px">Active</th>
|
||||
<th class="text-end min-w-100px">Manage</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody class="text-gray-600 fw-semibold">
|
||||
|
||||
@foreach ($itemView as $obj)
|
||||
<tr>
|
||||
<td class="d-flex align-items-center">
|
||||
<div class="symbol symbol-100px symbol-2by3 me-4">
|
||||
@if ($obj->image_url && $obj->image_name)
|
||||
<a class="show-image-preview d-block overlay"
|
||||
href="{{ url($obj->image_url . '/original/' . $obj->image_name) }}">
|
||||
<div class="symbol-label"
|
||||
style="background-image: url('{{ url($obj->image_url . '/thumbnail/' . $obj->image_name) }}')">
|
||||
</div>
|
||||
</a>
|
||||
@else
|
||||
<div class="symbol-label"
|
||||
style="background-image: url('{{ url('assets/media/avatars/blank.png') }}')">
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<a href="#" class="text-gray-800 text-hover-primary mb-1">
|
||||
{{ $obj->name }}
|
||||
</a>
|
||||
</td>
|
||||
|
||||
<td>
|
||||
<a href="#" class="text-gray-800 text-hover-primary mb-1">
|
||||
{{ $obj->name_en }}
|
||||
</a>
|
||||
</td>
|
||||
|
||||
<td>
|
||||
{{ Carbon\Carbon::parse($obj->created_at)->format('d, M Y') }}
|
||||
</td>
|
||||
|
||||
|
||||
<td>
|
||||
@if ($obj->active == 1)
|
||||
<span class="badge py-3 px-4 fs-7 badge-light-success">Active</span>
|
||||
@else
|
||||
<span class="badge py-3 px-4 fs-7 badge-light-danger">Inactive</span>
|
||||
@endif
|
||||
</td>
|
||||
|
||||
|
||||
<td class="min-w-100px text-end">
|
||||
|
||||
{{-- View --}}
|
||||
<a href="{{ url('no-where-else/article/' . $obj->id) }}"
|
||||
class="btn btn-icon btn-bg-light btn-active-color-primary btn-sm me-1">
|
||||
<span class="svg-icon svg-icon-3">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24"
|
||||
fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M17.5 11H6.5C4 11 2 9 2 6.5C2 4 4 2 6.5 2H17.5C20 2 22 4 22 6.5C22 9 20 11 17.5 11ZM15 6.5C15 7.9 16.1 9 17.5 9C18.9 9 20 7.9 20 6.5C20 5.1 18.9 4 17.5 4C16.1 4 15 5.1 15 6.5Z"
|
||||
fill="currentColor"></path>
|
||||
<path opacity="0.3"
|
||||
d="M17.5 22H6.5C4 22 2 20 2 17.5C2 15 4 13 6.5 13H17.5C20 13 22 15 22 17.5C22 20 20 22 17.5 22ZM4 17.5C4 18.9 5.1 20 6.5 20C7.9 20 9 18.9 9 17.5C9 16.1 7.9 15 6.5 15C5.1 15 4 16.1 4 17.5Z"
|
||||
fill="currentColor"></path>
|
||||
</svg>
|
||||
</span>
|
||||
</a>
|
||||
|
||||
{{-- Edit --}}
|
||||
<a href="{{ url('no-where-else/edit-sub-category/' . $obj->id) }}"
|
||||
class="btn btn-icon btn-bg-light btn-active-color-primary btn-sm me-1">
|
||||
<span class="svg-icon svg-icon-3">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24"
|
||||
fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path opacity="0.3"
|
||||
d="M21.4 8.35303L19.241 10.511L13.485 4.755L15.643 2.59595C16.0248 2.21423 16.5426 1.99988 17.0825 1.99988C17.6224 1.99988 18.1402 2.21423 18.522 2.59595L21.4 5.474C21.7817 5.85581 21.9962 6.37355 21.9962 6.91345C21.9962 7.45335 21.7817 7.97122 21.4 8.35303ZM3.68699 21.932L9.88699 19.865L4.13099 14.109L2.06399 20.309C1.98815 20.5354 1.97703 20.7787 2.03189 21.0111C2.08674 21.2436 2.2054 21.4561 2.37449 21.6248C2.54359 21.7934 2.75641 21.9115 2.989 21.9658C3.22158 22.0201 3.4647 22.0084 3.69099 21.932H3.68699Z"
|
||||
fill="currentColor" />
|
||||
<path
|
||||
d="M5.574 21.3L3.692 21.928C3.46591 22.0032 3.22334 22.0141 2.99144 21.9594C2.75954 21.9046 2.54744 21.7864 2.3789 21.6179C2.21036 21.4495 2.09202 21.2375 2.03711 21.0056C1.9822 20.7737 1.99289 20.5312 2.06799 20.3051L2.696 18.422L5.574 21.3ZM4.13499 14.105L9.891 19.861L19.245 10.507L13.489 4.75098L4.13499 14.105Z"
|
||||
fill="currentColor" />
|
||||
</svg>
|
||||
</span>
|
||||
</a>
|
||||
|
||||
{{-- Delete --}}
|
||||
@if ($obj->active == 1 && Auth::user()->role != 2)
|
||||
<a href="#" data-id="{{ $obj->id }}"
|
||||
class="btn btn-icon btn-bg-light btn-active-color-primary btn-sm delete-item">
|
||||
<span class="svg-icon svg-icon-3">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24"
|
||||
fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M5 9C5 8.44772 5.44772 8 6 8H18C18.5523 8 19 8.44772 19 9V18C19 19.6569 17.6569 21 16 21H8C6.34315 21 5 19.6569 5 18V9Z"
|
||||
fill="currentColor" />
|
||||
<path opacity="0.5"
|
||||
d="M5 5C5 4.44772 5.44772 4 6 4H18C18.5523 4 19 4.44772 19 5V5C19 5.55228 18.5523 6 18 6H6C5.44772 6 5 5.55228 5 5V5Z"
|
||||
fill="currentColor" />
|
||||
<path opacity="0.5"
|
||||
d="M9 4C9 3.44772 9.44772 3 10 3H14C14.5523 3 15 3.44772 15 4V4H9V4Z"
|
||||
fill="currentColor" />
|
||||
</svg>
|
||||
</span>
|
||||
</a>
|
||||
@endif
|
||||
</td>
|
||||
|
||||
|
||||
</tr>
|
||||
@endforeach
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@stop
|
||||
|
||||
|
||||
@section('script')
|
||||
|
||||
<script type="text/javascript">
|
||||
const baseUrl = "{{ url('no-where-else/sub-category') }}";
|
||||
var datatable;
|
||||
datatable = $("#data-table-category").DataTable({
|
||||
"info": false,
|
||||
"order": [],
|
||||
"pageLength": 25,
|
||||
lengthMenu: [
|
||||
[10, 25, 50, 100, 500, 1000],
|
||||
[10, 25, 50, 100, 500, 1000]
|
||||
]
|
||||
});
|
||||
|
||||
// Filter by search
|
||||
const filterSearch = document.querySelector('[table-filter="search"]');
|
||||
filterSearch.addEventListener('keyup', function(e) {
|
||||
datatable.search(e.target.value).draw();
|
||||
});
|
||||
|
||||
// filter by status
|
||||
const filterStatus = document.querySelector('[table-filter="status"]');
|
||||
$(filterStatus).on('change', e => {
|
||||
let value = e.target.value;
|
||||
if (value === 'all') {
|
||||
value = '';
|
||||
}
|
||||
datatable.column(4).search(value).draw();
|
||||
});
|
||||
|
||||
|
||||
// Remove
|
||||
$(document).on('click', '.delete-item', function() {
|
||||
swal.fire({
|
||||
allowOutsideClick: false,
|
||||
text: "Are you sure you would like to Delete?",
|
||||
icon: "warning",
|
||||
buttonsStyling: false,
|
||||
showDenyButton: true,
|
||||
confirmButtonText: "Yes",
|
||||
denyButtonText: 'No',
|
||||
customClass: {
|
||||
confirmButton: "btn btn-primary",
|
||||
denyButton: "btn btn-light-danger"
|
||||
}
|
||||
}).then((result) => {
|
||||
if (result.isConfirmed) {
|
||||
|
||||
alertLoading("Loading")
|
||||
|
||||
// set up ajax
|
||||
initAjaxSetupToken();
|
||||
|
||||
const ajaxProp = {
|
||||
url: "{{ url('no-where-else/delete-sub-category') }}",
|
||||
type: 'POST',
|
||||
data: {
|
||||
item_id: $(this).data('id')
|
||||
},
|
||||
};
|
||||
|
||||
$.ajax(ajaxProp).done(function(res) {
|
||||
if (res.status) {
|
||||
const url = "{{ url('no-where-else/sub-category') }}";
|
||||
alertSuccessWithUrl('Notice', "Delete success", url);
|
||||
hideLoading();
|
||||
} else {
|
||||
alertFail('Notice', res.message ?? "Unsuccessfully");
|
||||
hideLoading();
|
||||
}
|
||||
}).fail(function(xhr, status, error) {
|
||||
logAjaxError(xhr, status, error);
|
||||
alertFail('Notice', error.message ?? "Unsuccessfully");
|
||||
hideLoading();
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
var today = new Date();
|
||||
var dateFormat = "d-m-Y";
|
||||
|
||||
var dueDateFrom = $("#due_date_from");
|
||||
var dueDateTo = $("#due_date_to");
|
||||
|
||||
const dateFrom = "{{ $fromDateView }}";
|
||||
const dateTo = "{{ $toDateView }}";
|
||||
|
||||
dueDateFrom.flatpickr({
|
||||
showClearButton: true,
|
||||
enableTime: false,
|
||||
dateFormat: dateFormat,
|
||||
maxDate: today,
|
||||
defaultDate: dateFrom,
|
||||
|
||||
});
|
||||
|
||||
dueDateTo.flatpickr({
|
||||
showClearButton: true,
|
||||
enableTime: false,
|
||||
dateFormat: dateFormat,
|
||||
maxDate: today,
|
||||
defaultDate: dateTo,
|
||||
|
||||
});
|
||||
|
||||
const clearDatePicker = () => {
|
||||
dueDateFrom.flatpickr().clear();
|
||||
dueDateTo.flatpickr().clear();
|
||||
|
||||
// Set the date format again after clearing
|
||||
dueDateFrom.flatpickr({
|
||||
dateFormat: dateFormat
|
||||
});
|
||||
dueDateTo.flatpickr({
|
||||
dateFormat: dateFormat
|
||||
});
|
||||
}
|
||||
|
||||
$('#btn-submit').on('click', (e) => {
|
||||
e.preventDefault(); // Prevent the default behavior of the anchor element
|
||||
|
||||
// from
|
||||
const fromDateSelected = $("#due_date_from").val();
|
||||
|
||||
// to
|
||||
const toDateSelected = $("#due_date_to").val();
|
||||
|
||||
if (fromDateSelected && toDateSelected) {
|
||||
var newUrl =
|
||||
`${baseUrl}/${fromDateSelected}/${toDateSelected}`;
|
||||
window.location.href = newUrl;
|
||||
} else {
|
||||
var newUrl = `${baseUrl}/all/all/`;
|
||||
window.location.href = newUrl;
|
||||
}
|
||||
|
||||
})
|
||||
</script>
|
||||
|
||||
@endsection
|
||||
@@ -0,0 +1,212 @@
|
||||
@extends('layouts.backendTemplate')
|
||||
|
||||
@section('content')
|
||||
|
||||
<!--begin::Main-->
|
||||
<div class="app-main flex-column flex-row-fluid" id="kt_app_main">
|
||||
|
||||
<div class="d-flex flex-column flex-column-fluid">
|
||||
|
||||
@include('uc.admin.breadcrumb', [
|
||||
'title' => 'User Add',
|
||||
'pageName' => 'Add',
|
||||
'pageParent' => 'Users Management',
|
||||
'pageParentLink' => url('user'),
|
||||
])
|
||||
|
||||
<div id="kt_app_content" class="app-content flex-column-fluid">
|
||||
<div id="kt_app_content_container" class="app-container container-xxl">
|
||||
|
||||
|
||||
<form class="form d-flex flex-column flex-lg-row" action="{{ url('user/insert') }}" method="post"
|
||||
enctype="multipart/form-data">
|
||||
|
||||
<input type="hidden" name="_method" value="POST">
|
||||
<input type="hidden" name="_token" value="{{ csrf_token() }}">
|
||||
|
||||
|
||||
<div class="d-flex flex-column gap-7 gap-lg-10 w-100 w-lg-300px mb-7 me-lg-10">
|
||||
|
||||
<div class="card card-flush py-4">
|
||||
|
||||
|
||||
|
||||
<div class="card-header">
|
||||
|
||||
<div class="required card-title">
|
||||
<h2>Profile Picture</h2>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="card-body text-center pt-0">
|
||||
|
||||
<style>
|
||||
.image-input-placeholder {
|
||||
background-image: url('{{ url('assets/media/svg/files/blank-image.svg') }}');
|
||||
}
|
||||
|
||||
[data-bs-theme="dark"] .image-input-placeholder {
|
||||
background-image: url('{{ url('assets/media/svg/files/blank-image-dark.svg') }}');
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="image-input image-input-empty image-input-outline image-input-placeholder mb-3"
|
||||
data-kt-image-input="true">
|
||||
|
||||
<div class="image-input-wrapper w-150px h-150px"></div>
|
||||
|
||||
<label
|
||||
class="btn btn-icon btn-circle btn-active-color-primary w-25px h-25px bg-body shadow"
|
||||
data-kt-image-input-action="change" data-bs-toggle="tooltip"
|
||||
title="Change avatar">
|
||||
|
||||
<i class="bi bi-pencil-fill fs-7"></i>
|
||||
|
||||
<input type="file" name="avatar" accept=".png, .jpg, .jpeg" />
|
||||
<input type="hidden" name="avatar_remove" />
|
||||
|
||||
</label>
|
||||
|
||||
<span
|
||||
class="btn btn-icon btn-circle btn-active-color-primary w-25px h-25px bg-body shadow"
|
||||
data-kt-image-input-action="cancel" data-bs-toggle="tooltip"
|
||||
title="Cancel avatar">
|
||||
<i class="bi bi-x fs-2"></i>
|
||||
</span>
|
||||
|
||||
<span
|
||||
class="btn btn-icon btn-circle btn-active-color-primary w-25px h-25px bg-body shadow"
|
||||
data-kt-image-input-action="remove" data-bs-toggle="tooltip"
|
||||
title="Remove avatar">
|
||||
<i class="bi bi-x fs-2"></i>
|
||||
</span>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="text-muted fs-7">Set the profile picture. Only *.png, *.jpg and *.jpeg image
|
||||
files are accepted</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="d-flex flex-column flex-row-fluid gap-7 gap-lg-10">
|
||||
|
||||
<div class="card card-flush py-4">
|
||||
|
||||
@if (Session::has('messageSuccess'))
|
||||
<div class="card-body">
|
||||
@include('uc/messageSuccess')
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@if (Session::has('messageFail'))
|
||||
<div class="card-body">
|
||||
@include('uc/messageFail')
|
||||
</div>
|
||||
@endif
|
||||
|
||||
|
||||
<div class="card-header">
|
||||
<div class="card-title">
|
||||
<h2>Overview</h2>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card-body pt-0">
|
||||
|
||||
<div class="mb-10 fv-row">
|
||||
<label class="required form-label">Role</label>
|
||||
<div class="d-flex fv-row me-1 mb-5">
|
||||
<div class="form-check form-check-custom form-check-solid">
|
||||
<input class="form-check-input me-3" name="role" type="radio"
|
||||
value="0" checked="checked" data-gtm-form-interact-field-id="1">
|
||||
<label class="form-check-label" for="kt_modal_update_role_option_0">
|
||||
<div class="fw-bold text-gray-800">Administrator</div>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="d-flex fv-row me-1 mb-5">
|
||||
<div class="form-check form-check-custom form-check-solid">
|
||||
<input class="form-check-input me-3" name="role" type="radio"
|
||||
value="1" data-gtm-form-interact-field-id="1">
|
||||
<label class="form-check-label" for="kt_modal_update_role_option_0">
|
||||
<div class="fw-bold text-gray-800">Editor</div>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="d-flex fv-row me-1 mb-5">
|
||||
<div class="form-check form-check-custom form-check-solid">
|
||||
<input class="form-check-input me-3" name="role" type="radio"
|
||||
value="2" data-gtm-form-interact-field-id="1">
|
||||
<label class="form-check-label" for="kt_modal_update_role_option_0">
|
||||
<div class="fw-bold text-gray-800">Contributor</div>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-10 fv-row">
|
||||
<label class="required form-label">Firstname</label>
|
||||
<input type="text" name="first_name" class="form-control mb-2 col-6"
|
||||
value="{{ old('first_name') }}" />
|
||||
</div>
|
||||
|
||||
<div class="mb-10 fv-row">
|
||||
<label class="required form-label">Lastname</label>
|
||||
<input type="text" name="last_name" class="form-control mb-2 col-6"
|
||||
value="{{ old('last_name') }}" />
|
||||
</div>
|
||||
|
||||
|
||||
<div class="mb-10 fv-row">
|
||||
<label class="required form-label">E-mail</label>
|
||||
<input type="email" name="email" class="form-control mb-2"
|
||||
value="{{ old('email') }}" />
|
||||
</div>
|
||||
|
||||
<div class="mb-10 fv-row">
|
||||
<label class="required form-label">Password</label>
|
||||
<input type="password" name="password" class="form-control mb-2" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="d-flex justify-content-end">
|
||||
|
||||
<a href="{{ url('user') }}" id="kt_ecommerce_add_product_cancel"
|
||||
class="btn btn-light me-5">Cancel</a>
|
||||
|
||||
<button type="submit" class="btn btn-primary">
|
||||
<span class="indicator-label">Save</span>
|
||||
</button>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</form>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
@stop
|
||||
|
||||
@section('script')
|
||||
|
||||
<script type="text/javascript">
|
||||
$(function() {});
|
||||
</script>
|
||||
|
||||
@endsection
|
||||
@@ -0,0 +1,244 @@
|
||||
@extends('layouts.backendTemplate')
|
||||
|
||||
@section('content')
|
||||
|
||||
<!--begin::Main-->
|
||||
<div class="app-main flex-column flex-row-fluid" id="kt_app_main">
|
||||
|
||||
<div class="d-flex flex-column flex-column-fluid">
|
||||
|
||||
@include('uc.admin.breadcrumb', [
|
||||
'title' => 'User Edit',
|
||||
'pageName' => 'Edit',
|
||||
'pageParent' => 'Users Management',
|
||||
'pageParentLink' => url('user'),
|
||||
])
|
||||
|
||||
<div id="kt_app_content" class="app-content flex-column-fluid">
|
||||
<div id="kt_app_content_container" class="app-container container-xxl">
|
||||
|
||||
|
||||
<form class="form d-flex flex-column flex-lg-row" action="{{ url('user/update') }}" method="post"
|
||||
enctype="multipart/form-data">
|
||||
|
||||
<input type="hidden" name="userId" value="{{ $userView->id }}">
|
||||
<input type="hidden" name="_method" value="POST">
|
||||
<input type="hidden" name="_token" value="{{ csrf_token() }}">
|
||||
|
||||
|
||||
<div class="d-flex flex-column gap-7 gap-lg-10 w-100 w-lg-300px mb-7 me-lg-10">
|
||||
|
||||
<div class="card card-flush py-4">
|
||||
|
||||
<div class="card-header">
|
||||
|
||||
<div class="required card-title">
|
||||
<h2>Profile Picture</h2>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="card-body text-center pt-0">
|
||||
|
||||
<style>
|
||||
.image-input-placeholder {
|
||||
background-image: url('{{ url('assets/media/svg/files/blank-image.svg') }}');
|
||||
}
|
||||
|
||||
[data-bs-theme="dark"] .image-input-placeholder {
|
||||
background-image: url('{{ url('assets/media/svg/files/blank-image-dark.svg') }}');
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="image-input image-input-empty image-input-outline image-input-placeholder mb-3"
|
||||
data-kt-image-input="true">
|
||||
|
||||
@if ($userView->image_url && $userView->image_name)
|
||||
<div class="image-input-wrapper w-150px h-150px"
|
||||
style="background-image: url('{{ $userView->image_url . '/thumbnail/' . $userView->image_name }}')">
|
||||
</div>
|
||||
@else
|
||||
<div class="image-input-wrapper w-150px h-150px"></div>
|
||||
@endif
|
||||
|
||||
<label
|
||||
class="btn btn-icon btn-circle btn-active-color-primary w-25px h-25px bg-body shadow"
|
||||
data-kt-image-input-action="change" data-bs-toggle="tooltip"
|
||||
title="Change avatar">
|
||||
|
||||
<i class="bi bi-pencil-fill fs-7"></i>
|
||||
|
||||
<input type="file" name="avatar" accept=".png, .jpg, .jpeg" />
|
||||
<input type="hidden" name="avatar_remove" />
|
||||
|
||||
</label>
|
||||
|
||||
<span
|
||||
class="btn btn-icon btn-circle btn-active-color-primary w-25px h-25px bg-body shadow"
|
||||
data-kt-image-input-action="cancel" data-bs-toggle="tooltip"
|
||||
title="Cancel avatar">
|
||||
<i class="bi bi-x fs-2"></i>
|
||||
</span>
|
||||
|
||||
<span
|
||||
class="btn btn-icon btn-circle btn-active-color-primary w-25px h-25px bg-body shadow"
|
||||
data-kt-image-input-action="remove" data-bs-toggle="tooltip"
|
||||
title="Remove avatar">
|
||||
<i class="bi bi-x fs-2"></i>
|
||||
</span>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="text-muted fs-7">Set the profile picture. Only *.png, *.jpg and *.jpeg image
|
||||
files are accepted</div>
|
||||
|
||||
|
||||
{{-- Active --}}
|
||||
<div class="card-header" style="border: unset;">
|
||||
<!--begin::Card title-->
|
||||
<div class="required card-title">
|
||||
<h2>Active</h2>
|
||||
</div>
|
||||
<!--end::Card title-->
|
||||
</div>
|
||||
<div class="card-body pt-0">
|
||||
<label class="form-check form-switch form-check-custom form-check-solid">
|
||||
<input class="form-check-input" name="active" type="checkbox" value="1"
|
||||
{{ $userView->active == 1 ? 'checked' : '' }} />
|
||||
</label>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="d-flex flex-column flex-row-fluid gap-7 gap-lg-10">
|
||||
|
||||
|
||||
<div class="card card-flush py-4">
|
||||
|
||||
|
||||
@if (Session::has('messageSuccess'))
|
||||
<div class="card-body">
|
||||
@include('uc/messageSuccess')
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@if (Session::has('messageFail'))
|
||||
<div class="card-body">
|
||||
@include('uc/messageFail')
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<div class="card-header">
|
||||
<div class="card-title">
|
||||
<h2>Overview</h2>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card-body pt-0">
|
||||
|
||||
|
||||
|
||||
<div class="mb-10 fv-row">
|
||||
<label class="required form-label">Role</label>
|
||||
<div class="d-flex fv-row me-1 mb-5">
|
||||
<div class="form-check form-check-custom form-check-solid">
|
||||
<input class="form-check-input me-3" name="role" type="radio"
|
||||
value="0" @if ($userView->role == 0) checked @endif
|
||||
data-gtm-form-interact-field-id="1">
|
||||
<label class="form-check-label" for="kt_modal_update_role_option_0">
|
||||
<div class="fw-bold text-gray-800">Administrator</div>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="d-flex fv-row me-1 mb-5">
|
||||
<div class="form-check form-check-custom form-check-solid">
|
||||
<input class="form-check-input me-3" name="role" type="radio"
|
||||
value="1" @if ($userView->role == 1) checked @endif
|
||||
data-gtm-form-interact-field-id="1">
|
||||
<label class="form-check-label" for="kt_modal_update_role_option_0">
|
||||
<div class="fw-bold text-gray-800">Editor</div>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="d-flex fv-row me-1 mb-5">
|
||||
<div class="form-check form-check-custom form-check-solid">
|
||||
<input class="form-check-input me-3" name="role" type="radio"
|
||||
value="2" @if ($userView->role == 2) checked @endif
|
||||
data-gtm-form-interact-field-id="1">
|
||||
<label class="form-check-label" for="kt_modal_update_role_option_0">
|
||||
<div class="fw-bold text-gray-800">Contributor</div>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="mb-10 fv-row">
|
||||
<label class="required form-label">Firstname</label>
|
||||
<input type="text" name="first_name" class="form-control mb-2 col-6"
|
||||
value="{{ $userView->first_name }}" />
|
||||
</div>
|
||||
|
||||
<div class="mb-10 fv-row">
|
||||
<label class="required form-label">Lastname</label>
|
||||
<input type="text" name="last_name" class="form-control mb-2 col-6"
|
||||
value="{{ $userView->last_name }}" />
|
||||
</div>
|
||||
|
||||
|
||||
<div class="mb-10 fv-row">
|
||||
|
||||
<label class="required form-label">E-mail</label>
|
||||
|
||||
|
||||
<input type="email" name="email" class="form-control mb-2"
|
||||
value="{{ $userView->email }}" />
|
||||
|
||||
</div>
|
||||
|
||||
<div class="mb-10 fv-row">
|
||||
<label class="form-label">Password</label>
|
||||
<input type="password" name="password" class="form-control mb-2" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="d-flex justify-content-end">
|
||||
|
||||
<a href="{{ url('user') }}" id="kt_ecommerce_add_product_cancel"
|
||||
class="btn btn-light me-5">Cancel</a>
|
||||
|
||||
<button type="submit" class="btn btn-primary">
|
||||
<span class="indicator-label">Save</span>
|
||||
</button>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</form>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
@stop
|
||||
|
||||
@section('script')
|
||||
|
||||
<script type="text/javascript">
|
||||
$(function() {});
|
||||
</script>
|
||||
|
||||
@endsection
|
||||
@@ -0,0 +1,357 @@
|
||||
@extends('layouts.backendTemplate')
|
||||
|
||||
@section('content')
|
||||
|
||||
<!--begin::Main-->
|
||||
<div class="app-main flex-column flex-row-fluid" id="kt_app_main">
|
||||
|
||||
<div class="d-flex flex-column flex-column-fluid">
|
||||
|
||||
|
||||
@include('uc.admin.breadcrumbList', [
|
||||
'title' => 'Users Management',
|
||||
'pageName' => 'User Management',
|
||||
])
|
||||
|
||||
|
||||
<div id="kt_app_content" class="app-content flex-column-fluid">
|
||||
<!--begin::Content container-->
|
||||
<div id="kt_app_content_container" class="app-container container-xxl">
|
||||
<!--begin::Card-->
|
||||
<div class="card">
|
||||
|
||||
@if (Session::has('messageSuccess'))
|
||||
<div class="card-body">
|
||||
@include('uc/messageSuccess')
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@if (Session::has('messageFail'))
|
||||
<div class="card-body">
|
||||
@include('uc/messageFail')
|
||||
</div>
|
||||
@endif
|
||||
|
||||
|
||||
<!--begin::Card header-->
|
||||
<div class="card-header border-0 pt-6">
|
||||
<!--begin::Card title-->
|
||||
<div class="card-title">
|
||||
<div class="d-flex align-items-center position-relative my-1">
|
||||
<span class="svg-icon svg-icon-1 position-absolute ms-6">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<rect opacity="0.5" x="17.0365" y="15.1223" width="8.15546" height="2"
|
||||
rx="1" transform="rotate(45 17.0365 15.1223)" fill="currentColor" />
|
||||
<path
|
||||
d="M11 19C6.55556 19 3 15.4444 3 11C3 6.55556 6.55556 3 11 3C15.4444 3 19 6.55556 19 11C19 15.4444 15.4444 19 11 19ZM11 5C7.53333 5 5 7.53333 5 11C5 14.4667 7.53333 17 11 17C14.4667 17 17 14.4667 17 11C17 7.53333 14.4667 5 11 5Z"
|
||||
fill="currentColor" />
|
||||
</svg>
|
||||
</span>
|
||||
<input type="text" table-filter="search"
|
||||
class="form-control form-control-solid w-250px ps-15" placeholder="Search" />
|
||||
</div>
|
||||
</div>
|
||||
<!--begin::Card title-->
|
||||
<!--begin::Card toolbar-->
|
||||
<div class="card-toolbar">
|
||||
|
||||
<div class="w-150px me-3">
|
||||
<select class="form-select form-select-solid" data-control="select2"
|
||||
data-hide-search="true" data-placeholder="Status" table-filter="status">
|
||||
<option></option>
|
||||
<option value="all">All</option>
|
||||
<option value="active">Active</option>
|
||||
<option value="inactive">Inactive</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<!--begin::Toolbar-->
|
||||
<div class="d-flex justify-content-end" data-kt-customer-table-toolbar="base">
|
||||
<a href="{{ url('user/add') }}" class="btn btn-primary">Add </a>
|
||||
</div>
|
||||
<!--end::Toolbar-->
|
||||
</div>
|
||||
<!--end::Card toolbar-->
|
||||
</div>
|
||||
<!--end::Card header-->
|
||||
|
||||
|
||||
<div class="card-body py-4">
|
||||
<!--begin::Table-->
|
||||
<table class="table align-middle table-row-dashed fs-6 gy-5" id="data-table-user">
|
||||
<!--begin::Table head-->
|
||||
<thead>
|
||||
<!--begin::Table row-->
|
||||
<tr class="text-start text-muted fw-bold fs-7 text-uppercase gs-0">
|
||||
<th class="min-w-150px">Pic</th>
|
||||
<th class="min-w-150px">Role</th>
|
||||
<th class="min-w-150px">First Name</th>
|
||||
<th class="min-w-150px">Last Name</th>
|
||||
<th class="min-w-150px">Email</th>
|
||||
<th class="min-w-150px">Status</th>
|
||||
<th class="min-w-150px">Created At</th>
|
||||
<th class="min-w-100px text-end">Actions</th>
|
||||
</tr>
|
||||
<!--end::Table row-->
|
||||
</thead>
|
||||
|
||||
<tbody class="fw-bold text-gray-600">
|
||||
@foreach ($userView as $key => $obj)
|
||||
<tr>
|
||||
|
||||
|
||||
<td class="d-flex align-items-center">
|
||||
<div class="symbol symbol-100px symbol-2by3 me-4">
|
||||
@if ($obj->image_url && $obj->image_name)
|
||||
<a class="show-image-preview d-block overlay"
|
||||
href="{{ url($obj->image_url . '/original/' . $obj->image_name) }}">
|
||||
<div class="symbol-label"
|
||||
style="background-image: url('{{ url($obj->image_url . '/thumbnail/' . $obj->image_name) }}')">
|
||||
</div>
|
||||
</a>
|
||||
@else
|
||||
<div class="symbol-label"
|
||||
style="background-image: url('{{ url('assets/media/avatars/blank.png') }}')">
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
</td>
|
||||
|
||||
<td>
|
||||
@if ($obj->role == 1)
|
||||
<span class="badge py-3 px-4 fs-7 badge-light-warning"> EDITOR </span>
|
||||
@elseif($obj->role == 2)
|
||||
<span class="badge py-3 px-4 fs-7 badge-light-info"> CONTRIBUTOR </span>
|
||||
@else
|
||||
<span class="badge py-3 px-4 fs-7 badge-light-success"> ADMIN </span>
|
||||
@endif
|
||||
</td>
|
||||
|
||||
<td class="">{{ $obj->first_name }}</td>
|
||||
<td class="">{{ $obj->last_name }}</td>
|
||||
<td class="">{{ $obj->email }}</td>
|
||||
<td class="">
|
||||
@if ($obj->active == 1)
|
||||
<span class="badge py-3 px-4 fs-7 badge-light-success">Active</span>
|
||||
@else
|
||||
<span class="badge py-3 px-4 fs-7 badge-light-danger">Locked</span>
|
||||
@endif
|
||||
</td>
|
||||
<td class="">{{ date('d M, Y', strtotime($obj->created_at)) }}</td>
|
||||
<td class="min-w-100px text-end">
|
||||
|
||||
{{-- Edit --}}
|
||||
<a href="{{ url('user/edit/' . $obj->id) }}"
|
||||
class="btn btn-icon btn-bg-light btn-active-color-primary btn-sm me-1">
|
||||
<span class="svg-icon svg-icon-3">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24"
|
||||
fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path opacity="0.3"
|
||||
d="M21.4 8.35303L19.241 10.511L13.485 4.755L15.643 2.59595C16.0248 2.21423 16.5426 1.99988 17.0825 1.99988C17.6224 1.99988 18.1402 2.21423 18.522 2.59595L21.4 5.474C21.7817 5.85581 21.9962 6.37355 21.9962 6.91345C21.9962 7.45335 21.7817 7.97122 21.4 8.35303ZM3.68699 21.932L9.88699 19.865L4.13099 14.109L2.06399 20.309C1.98815 20.5354 1.97703 20.7787 2.03189 21.0111C2.08674 21.2436 2.2054 21.4561 2.37449 21.6248C2.54359 21.7934 2.75641 21.9115 2.989 21.9658C3.22158 22.0201 3.4647 22.0084 3.69099 21.932H3.68699Z"
|
||||
fill="currentColor" />
|
||||
<path
|
||||
d="M5.574 21.3L3.692 21.928C3.46591 22.0032 3.22334 22.0141 2.99144 21.9594C2.75954 21.9046 2.54744 21.7864 2.3789 21.6179C2.21036 21.4495 2.09202 21.2375 2.03711 21.0056C1.9822 20.7737 1.99289 20.5312 2.06799 20.3051L2.696 18.422L5.574 21.3ZM4.13499 14.105L9.891 19.861L19.245 10.507L13.489 4.75098L4.13499 14.105Z"
|
||||
fill="currentColor" />
|
||||
</svg>
|
||||
</span>
|
||||
</a>
|
||||
|
||||
{{-- Delete --}}
|
||||
@if ($obj->active == 1)
|
||||
<a href="#" data-id="{{ $obj->id }}"
|
||||
class="btn btn-icon btn-bg-light btn-active-color-primary btn-sm delete-item">
|
||||
<span class="svg-icon svg-icon-3">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24"
|
||||
fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M5 9C5 8.44772 5.44772 8 6 8H18C18.5523 8 19 8.44772 19 9V18C19 19.6569 17.6569 21 16 21H8C6.34315 21 5 19.6569 5 18V9Z"
|
||||
fill="currentColor" />
|
||||
<path opacity="0.5"
|
||||
d="M5 5C5 4.44772 5.44772 4 6 4H18C18.5523 4 19 4.44772 19 5V5C19 5.55228 18.5523 6 18 6H6C5.44772 6 5 5.55228 5 5V5Z"
|
||||
fill="currentColor" />
|
||||
<path opacity="0.5"
|
||||
d="M9 4C9 3.44772 9.44772 3 10 3H14C14.5523 3 15 3.44772 15 4V4H9V4Z"
|
||||
fill="currentColor" />
|
||||
</svg>
|
||||
</span>
|
||||
</a>
|
||||
@endif
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
|
||||
</tbody>
|
||||
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
{{-- <div class="modal fade" id="deleteModal" tabindex="-1" aria-hidden="true">
|
||||
<div class="modal-dialog modal-dialog-centered mw-650px">
|
||||
|
||||
<form class="form-horizontal" action="{{ url('user/delete') }}" method="POST">
|
||||
|
||||
<input type="hidden" id="item_id" name="item_id" value="">
|
||||
<input type="hidden" name="_method" value="POST">
|
||||
<input type="hidden" name="_token" value="{{ csrf_token() }}">
|
||||
|
||||
|
||||
<div class="modal-content">
|
||||
|
||||
<!--begin::Modal body-->
|
||||
<div class="modal-body scroll-y mx-5 mx-xl-15 my-7">
|
||||
<!--begin::Notice-->
|
||||
<!--begin::Notice-->
|
||||
<div class="notice d-flex bg-light-warning rounded border-warning border border-dashed mb-9 p-6">
|
||||
<!--begin::Icon-->
|
||||
<!--begin::Svg Icon | path: icons/duotune/general/gen044.svg-->
|
||||
<span class="svg-icon svg-icon-2tx svg-icon-warning me-4">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<rect opacity="0.3" x="2" y="2" width="20" height="20"
|
||||
rx="10" fill="currentColor" />
|
||||
<rect x="11" y="14" width="7" height="2" rx="1"
|
||||
transform="rotate(-90 11 14)" fill="currentColor" />
|
||||
<rect x="11" y="17" width="2" height="2" rx="1"
|
||||
transform="rotate(-90 11 17)" fill="currentColor" />
|
||||
</svg>
|
||||
</span>
|
||||
|
||||
<div class="d-flex flex-stack flex-grow-1">
|
||||
<!--begin::Content-->
|
||||
<div class="fw-semibold">
|
||||
<div class="fs-6 text-gray-700">
|
||||
<strong class="me-1">Confirm Delete</strong>
|
||||
Please ensure you're absolutely certain
|
||||
before proceeding.
|
||||
</div>
|
||||
</div>
|
||||
<!--end::Content-->
|
||||
</div>
|
||||
<!--end::Wrapper-->
|
||||
</div>
|
||||
<!--end::Notice-->
|
||||
|
||||
|
||||
|
||||
<!--begin::Actions-->
|
||||
<div class="text-center pt-15">
|
||||
|
||||
<div class="swal2-actions" style="display: flex;">
|
||||
<div class="swal2-loader"></div>
|
||||
<button type="submit" class="btn fw-bold btn-danger" aria-label=""
|
||||
style="display: inline-block;">Yes
|
||||
</button>
|
||||
<button type="reset" class="btn btn-light fw-bold btn-active-light-primary hide-item"
|
||||
aria-label="" style="display: inline-block; margin-left:10px;">No
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<!--end::Actions-->
|
||||
|
||||
</div>
|
||||
<!--end::Modal body-->
|
||||
</div>
|
||||
|
||||
</form>
|
||||
|
||||
</div>
|
||||
</div> --}}
|
||||
|
||||
@stop
|
||||
|
||||
@section('script')
|
||||
|
||||
<script type="text/javascript">
|
||||
var datatable;
|
||||
datatable = $("#data-table-user").DataTable({
|
||||
"info": false,
|
||||
"order": [],
|
||||
"pageLength": 25,
|
||||
lengthMenu: [
|
||||
[10, 25, 50, 100, 500, 1000],
|
||||
[10, 25, 50, 100, 500, 1000]
|
||||
]
|
||||
});
|
||||
|
||||
// Filter by search
|
||||
const filterSearch = document.querySelector('[table-filter="search"]');
|
||||
filterSearch.addEventListener('keyup', function(e) {
|
||||
datatable.search(e.target.value).draw();
|
||||
});
|
||||
|
||||
// filter by status
|
||||
const filterStatus = document.querySelector('[table-filter="status"]');
|
||||
$(filterStatus).on('change', e => {
|
||||
let value = e.target.value;
|
||||
if (value === 'all') {
|
||||
value = '';
|
||||
}
|
||||
datatable.column(5).search(value).draw();
|
||||
});
|
||||
|
||||
// Remove
|
||||
$(document).on('click', '.delete-item', function() {
|
||||
// $('#deleteModal #item_id').val($(this).data('id'));
|
||||
// showModal('#deleteModal');
|
||||
|
||||
swal.fire({
|
||||
allowOutsideClick: false,
|
||||
text: "Are you sure you would like to Delete?",
|
||||
icon: "warning",
|
||||
buttonsStyling: false,
|
||||
showDenyButton: true,
|
||||
confirmButtonText: "Yes",
|
||||
denyButtonText: 'No',
|
||||
customClass: {
|
||||
confirmButton: "btn btn-primary",
|
||||
denyButton: "btn btn-light-danger"
|
||||
}
|
||||
}).then((result) => {
|
||||
if (result.isConfirmed) {
|
||||
|
||||
alertLoading("Loading")
|
||||
|
||||
// set up ajax
|
||||
initAjaxSetupToken();
|
||||
|
||||
const ajaxProp = {
|
||||
url: "{{ url('user/delete') }}",
|
||||
type: 'POST',
|
||||
data: {
|
||||
item_id: $(this).data('id')
|
||||
},
|
||||
};
|
||||
|
||||
$.ajax(ajaxProp).done(function(res) {
|
||||
if (isAjaxStatusSuccess(res.status)) {
|
||||
const url = "{{ url('user') }}";
|
||||
alertSuccessWithUrl('Notice', "Delete success", url);
|
||||
hideLoading();
|
||||
} else {
|
||||
alertFail('Notice', res.message ?? "Unsuccessfully");
|
||||
hideLoading();
|
||||
}
|
||||
}).fail(function(xhr, status, error) {
|
||||
logAjaxError(xhr, status, error);
|
||||
alertFail('Notice', error.message ?? "Unsuccessfully");
|
||||
hideLoading();
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
// $(document).on('click', '.hide-item', function() {
|
||||
// hideModal('#deleteModal');
|
||||
// });
|
||||
</script>
|
||||
|
||||
@endsection
|
||||
@@ -0,0 +1,367 @@
|
||||
@extends('layouts.backendTemplate')
|
||||
|
||||
@section('content')
|
||||
|
||||
<style>
|
||||
#progressBar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.progress-bar {
|
||||
width: 100%;
|
||||
height: 10px;
|
||||
border-radius: 5px;
|
||||
margin-top: 10px;
|
||||
appearance: none;
|
||||
}
|
||||
|
||||
.progress-bar::-webkit-progress-value {
|
||||
background-color: #4CAF50;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.progress-text {
|
||||
margin-top: 10px;
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
}
|
||||
</style>
|
||||
|
||||
<!--begin::Main-->
|
||||
<div class="app-main flex-column flex-row-fluid" id="kt_app_main">
|
||||
|
||||
<div class="d-flex flex-column flex-column-fluid">
|
||||
|
||||
|
||||
@include('uc.admin.breadcrumb', [
|
||||
'title' => 'Video Add',
|
||||
'pageName' => 'Add',
|
||||
'pageParent' => 'Video Management',
|
||||
'pageParentLink' => url('video'),
|
||||
])
|
||||
|
||||
<div id="kt_app_content" class="app-content flex-column-fluid">
|
||||
<div id="kt_app_content_container" class="app-container container-xxl">
|
||||
|
||||
|
||||
|
||||
<form id="frmAdd" class="form d-flex flex-column flex-lg-row" method="post"
|
||||
enctype="multipart/form-data">
|
||||
|
||||
<input type="hidden" name="_method" value="POST">
|
||||
<input type="hidden" name="_token" value="{{ csrf_token() }}">
|
||||
|
||||
|
||||
<div class="d-flex flex-column flex-row-fluid gap-7 gap-lg-10">
|
||||
|
||||
<div class="card card-flush py-4">
|
||||
|
||||
|
||||
@if (Session::has('messageSuccess'))
|
||||
<div class="card-body">
|
||||
@include('uc/messageSuccess')
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@if (Session::has('messageFail'))
|
||||
<div class="card-body">
|
||||
@include('uc/messageFail')
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<div class="card-header">
|
||||
<div class="card-title">
|
||||
<h2>Overview</h2>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card-body pt-0">
|
||||
|
||||
<div class="mb-10">
|
||||
<label class="form-label required">File Video</label>
|
||||
|
||||
<input class="fileInput file-input" type="file" id="fileInput" name="fileInput"
|
||||
multiple accept=".MP4, .MOV">
|
||||
|
||||
<progress id="progressBar" class="progress-bar" value="0"
|
||||
max="100"></progress>
|
||||
<div id="progressText" class="progress-text">0%</div>
|
||||
|
||||
<div class="text-muted fs-7">Allowed Types .MP4, .MOV</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="d-flex justify-content-end">
|
||||
|
||||
<a href="{{ url('video') }}" id="kt_ecommerce_add_product_cancel"
|
||||
class="btn btn-light me-5">Cancel</a>
|
||||
|
||||
<button type="button" id="btn_submit" class="btn btn-primary">
|
||||
<span class="indicator-label">Save</span>
|
||||
</button>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</form>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
@stop
|
||||
|
||||
|
||||
@section('script')
|
||||
|
||||
<script>
|
||||
const baseApiUrl = "{{ env('API_URL') }}";
|
||||
|
||||
|
||||
$(document).on("click", "#btn_submit", async function(e) {
|
||||
|
||||
e.preventDefault();
|
||||
|
||||
alertLoading("Loading")
|
||||
|
||||
await uploadFile();
|
||||
|
||||
});
|
||||
|
||||
|
||||
// Step 1
|
||||
async function uploadFile() {
|
||||
const fileInput = document.getElementById("fileInput");
|
||||
const progressBar = document.getElementById("progressBar");
|
||||
const progressText = document.getElementById("progressText");
|
||||
|
||||
if (!fileInput || fileInput.files.length === 0) {
|
||||
alertFail("Notice", "Please select one or more files.");
|
||||
hideLoading();
|
||||
return;
|
||||
}
|
||||
|
||||
const files = Array.from(fileInput.files); // Get all selected files
|
||||
$("#progressBar").show();
|
||||
|
||||
let totalSize = files.reduce((sum, file) => sum + file.size, 0);
|
||||
let totalUploadedSize = 0;
|
||||
|
||||
// Upload all files sequentially
|
||||
for (const file of files) {
|
||||
await uploadSingleFile(file, progressBar, progressText, totalSize, (fileUploadedSize) => {
|
||||
totalUploadedSize += fileUploadedSize;
|
||||
const overallPercent = Math.floor((totalUploadedSize / totalSize) * 100);
|
||||
animateProgress(progressBar, progressText, overallPercent);
|
||||
});
|
||||
}
|
||||
|
||||
const folderId = "{{ $folderIdView }}";
|
||||
let redirectUrl = "{{ url('video') }}"
|
||||
if (folderId) {
|
||||
redirectUrl = `${redirectUrl}/folder/${folderId}`;
|
||||
}
|
||||
|
||||
alertSuccessWithUrl("Notice", "All files uploaded successfully", redirectUrl);
|
||||
}
|
||||
|
||||
async function uploadSingleFile(file, progressBar, progressText, totalSize, updateOverallProgress) {
|
||||
const uploadId = await initiateMultipartUpload(file.name);
|
||||
const partSize = 500 * 1024 * 1024; // 500 MB per part
|
||||
const parts = [];
|
||||
let uploadedSize = 0;
|
||||
|
||||
const uploadPromises = Array.from({
|
||||
length: Math.ceil(file.size / partSize)
|
||||
},
|
||||
(_, index) => {
|
||||
const partNumber = index + 1;
|
||||
const chunk = file.slice(index * partSize, (index + 1) * partSize);
|
||||
|
||||
return (async () => {
|
||||
const presignedUrl = await getPresignedUrl(uploadId, partNumber, file.name);
|
||||
const etag = await uploadPartToS3(presignedUrl, chunk);
|
||||
|
||||
parts.push({
|
||||
PartNumber: partNumber,
|
||||
ETag: etag
|
||||
});
|
||||
|
||||
uploadedSize += chunk.size;
|
||||
updateOverallProgress(chunk.size); // Update the overall progress
|
||||
})();
|
||||
}
|
||||
);
|
||||
|
||||
await Promise.all(uploadPromises);
|
||||
await completeMultipartUpload(uploadId, parts, file.name);
|
||||
await saveFileNameToDB(file.name);
|
||||
}
|
||||
|
||||
// Step 2
|
||||
async function initiateMultipartUpload(fileName) {
|
||||
const urlUploadImage = `${baseApiUrl}/initiate-multipart-upload`;
|
||||
const response = await fetch(
|
||||
urlUploadImage, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
fileName
|
||||
}),
|
||||
}
|
||||
);
|
||||
|
||||
const {
|
||||
uploadId
|
||||
} = await response.json();
|
||||
|
||||
return uploadId;
|
||||
}
|
||||
|
||||
// Step 3
|
||||
async function getPresignedUrl(uploadId, partNumber, fileName) {
|
||||
|
||||
const urlPresigned = `${baseApiUrl}/get-presigned-url`
|
||||
const response = await fetch(
|
||||
urlPresigned, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
uploadId,
|
||||
partNumber,
|
||||
fileName
|
||||
}),
|
||||
}
|
||||
);
|
||||
const {
|
||||
url
|
||||
} = await response.json();
|
||||
return url;
|
||||
}
|
||||
|
||||
// Step 4
|
||||
async function uploadPartToS3(url, chunk) {
|
||||
const response = await fetch(url, {
|
||||
method: "PUT",
|
||||
headers: {
|
||||
"Content-Type": "application/octet-stream",
|
||||
},
|
||||
body: chunk,
|
||||
});
|
||||
if (!response.ok) {
|
||||
alertFail("Notice", "Failed to upload part")
|
||||
hideLoading();
|
||||
//throw new Error("Failed to upload part");
|
||||
}
|
||||
|
||||
const etag = `${response.headers.get("ETag")}`.replace(/"/g, "");
|
||||
|
||||
if (!etag) {
|
||||
throw new Error("Failed to retrieve ETag from the response.");
|
||||
}
|
||||
|
||||
return etag;
|
||||
}
|
||||
|
||||
// Step 5
|
||||
async function completeMultipartUpload(uploadId, parts, fileName) {
|
||||
const urlUploadComplete = `${baseApiUrl}/complete-multipart-upload`;
|
||||
const response = await fetch(urlUploadComplete, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
uploadId,
|
||||
parts,
|
||||
fileName
|
||||
}),
|
||||
});
|
||||
if (response.ok) {
|
||||
//window.location.href = "{{ url('image') }}";
|
||||
} else {
|
||||
alertFail("Notice", "Failed to upload part");
|
||||
hideLoading();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Smoothly animates the progress bar and percentage text.
|
||||
*/
|
||||
async function animateProgress(progressBar, progressText, targetPercent) {
|
||||
const currentPercent = parseInt(progressBar.value) || 0;
|
||||
// Increment the percentage smoothly
|
||||
for (let percent = currentPercent + 1; percent <= targetPercent; percent++) {
|
||||
progressBar.value = percent;
|
||||
progressText.textContent = `${percent}%`;
|
||||
|
||||
// Add a small delay to make the increment visible (10ms delay)
|
||||
await new Promise((resolve) => setTimeout(resolve, 10));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends the uploaded file name to the server using AJAX.
|
||||
*/
|
||||
function saveFileNameToDB(fileName) {
|
||||
initAjaxSetupToken();
|
||||
|
||||
const folderId = "{{ $folderIdView }}";
|
||||
const url = "{{ url('') }}";
|
||||
|
||||
return $.ajax({
|
||||
url: `${url}/video/insert`,
|
||||
type: 'POST',
|
||||
contentType: 'application/json',
|
||||
data: JSON.stringify({
|
||||
fileName,
|
||||
folderId
|
||||
}),
|
||||
success: (response) => {
|
||||
console.log('File name saved:', response);
|
||||
},
|
||||
error: (err) => {
|
||||
console.error('Error saving file name:', err);
|
||||
alertFail("Notice", "There was an error saving the file name.");
|
||||
hideLoading();
|
||||
return;
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<script>
|
||||
$('.file-input').fileuploader({
|
||||
extensions: ['MP4', 'mp4', 'MOV', 'mov'],
|
||||
limit: null,
|
||||
fileMaxSize: null,
|
||||
changeInput: '<div class="fileuploader-input">' +
|
||||
'<div class="fileuploader-input-inner">' +
|
||||
'<p><i class="fileuploader-icon-main"></i></p>' +
|
||||
'<h6>Drag and drop files here</h6>' +
|
||||
'<p>or</p>' +
|
||||
'<br>' +
|
||||
'<button type="button" class="fileuploader-input-button"><span>${captions.button}</span></button>' +
|
||||
'</div>' +
|
||||
'</div>',
|
||||
theme: 'dragdrop',
|
||||
});
|
||||
</script>
|
||||
|
||||
@endsection
|
||||
@@ -0,0 +1,95 @@
|
||||
@extends('layouts.backendTemplate')
|
||||
|
||||
@section('content')
|
||||
|
||||
<!--begin::Main-->
|
||||
<div class="app-main flex-column flex-row-fluid" id="kt_app_main">
|
||||
|
||||
<div class="d-flex flex-column flex-column-fluid">
|
||||
|
||||
|
||||
@include('uc.admin.breadcrumb', [
|
||||
'title' => 'Video Create Folder',
|
||||
'pageName' => 'Create folder',
|
||||
'pageParent' => 'Video Management',
|
||||
'pageParentLink' => url('video'),
|
||||
])
|
||||
|
||||
<div id="kt_app_content" class="app-content flex-column-fluid">
|
||||
<div id="kt_app_content_container" class="app-container container-xxl">
|
||||
|
||||
<form id="frmAdd" action="{{ url('video/insert-folder') }}" class="form d-flex flex-column flex-lg-row"
|
||||
method="post" enctype="multipart/form-data">
|
||||
|
||||
<input type="hidden" name="_method" value="POST">
|
||||
<input type="hidden" name="_token" value="{{ csrf_token() }}">
|
||||
|
||||
|
||||
<div class="d-flex flex-column flex-row-fluid gap-7 gap-lg-10">
|
||||
|
||||
<div class="card card-flush py-4">
|
||||
|
||||
|
||||
@if (Session::has('messageSuccess'))
|
||||
<div class="card-body">
|
||||
@include('uc/messageSuccess')
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@if (Session::has('messageFail'))
|
||||
<div class="card-body">
|
||||
@include('uc/messageFail')
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<div class="card-header">
|
||||
<div class="card-title">
|
||||
<h2>Overview</h2>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card-body pt-0">
|
||||
|
||||
<div class="mb-10 fv-row">
|
||||
<label class="required form-label">Name</label>
|
||||
<input type="text" name="name" class="form-control mb-2 col-6"
|
||||
value="{{ old('name') }}" />
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="d-flex justify-content-end">
|
||||
|
||||
<a href="{{ url('video') }}" id="kt_ecommerce_add_product_cancel"
|
||||
class="btn btn-light me-5">Cancel</a>
|
||||
|
||||
<button type="submit" class="btn btn-primary">
|
||||
<span class="indicator-label">Save</span>
|
||||
</button>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</form>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
@stop
|
||||
|
||||
|
||||
@section('script')
|
||||
|
||||
<script></script>
|
||||
|
||||
@endsection
|
||||
@@ -0,0 +1,96 @@
|
||||
@extends('layouts.backendTemplate')
|
||||
|
||||
@section('content')
|
||||
|
||||
<!--begin::Main-->
|
||||
<div class="app-main flex-column flex-row-fluid" id="kt_app_main">
|
||||
|
||||
<div class="d-flex flex-column flex-column-fluid">
|
||||
|
||||
|
||||
@include('uc.admin.breadcrumb', [
|
||||
'title' => 'Video Edit Folder',
|
||||
'pageName' => 'Edit folder',
|
||||
'pageParent' => 'Video Management',
|
||||
'pageParentLink' => url('Video'),
|
||||
])
|
||||
|
||||
<div id="kt_app_content" class="app-content flex-column-fluid">
|
||||
<div id="kt_app_content_container" class="app-container container-xxl">
|
||||
|
||||
<form id="frmAdd" action="{{ url('video/update-folder') }}" class="form d-flex flex-column flex-lg-row"
|
||||
method="post" enctype="multipart/form-data">
|
||||
|
||||
<input type="hidden" name="id" value="{{ $idView }}">
|
||||
<input type="hidden" name="_method" value="POST">
|
||||
<input type="hidden" name="_token" value="{{ csrf_token() }}">
|
||||
|
||||
|
||||
<div class="d-flex flex-column flex-row-fluid gap-7 gap-lg-10">
|
||||
|
||||
<div class="card card-flush py-4">
|
||||
|
||||
|
||||
@if (Session::has('messageSuccess'))
|
||||
<div class="card-body">
|
||||
@include('uc/messageSuccess')
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@if (Session::has('messageFail'))
|
||||
<div class="card-body">
|
||||
@include('uc/messageFail')
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<div class="card-header">
|
||||
<div class="card-title">
|
||||
<h2>Overview</h2>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card-body pt-0">
|
||||
|
||||
<div class="mb-10 fv-row">
|
||||
<label class="required form-label">Name</label>
|
||||
<input type="text" name="name" class="form-control mb-2 col-6"
|
||||
value="{{ $itemView->name }}" />
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="d-flex justify-content-end">
|
||||
|
||||
<a href="{{ url('video') }}" id="kt_ecommerce_add_product_cancel"
|
||||
class="btn btn-light me-5">Cancel</a>
|
||||
|
||||
<button type="submit" class="btn btn-primary">
|
||||
<span class="indicator-label">Save</span>
|
||||
</button>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</form>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
@stop
|
||||
|
||||
|
||||
@section('script')
|
||||
|
||||
<script></script>
|
||||
|
||||
@endsection
|
||||
@@ -0,0 +1,310 @@
|
||||
@extends('layouts.backendTemplate')
|
||||
|
||||
@section('content')
|
||||
|
||||
<style>
|
||||
.link-container {
|
||||
display: flex;
|
||||
/* Use flexbox for alignment */
|
||||
align-items: center;
|
||||
/* Center items vertically */
|
||||
justify-content: space-between;
|
||||
/* Space between the URL and button */
|
||||
}
|
||||
|
||||
.file-url {
|
||||
flex: 1;
|
||||
/* Allow the URL to take up available space */
|
||||
color: #007bff;
|
||||
/* Link color */
|
||||
text-decoration: none;
|
||||
/* Remove underline */
|
||||
overflow: hidden;
|
||||
/* Hide overflow */
|
||||
white-space: nowrap;
|
||||
/* Prevent text wrapping */
|
||||
text-overflow: ellipsis;
|
||||
/* Add ellipsis for overflow */
|
||||
margin-right: 10px;
|
||||
/* Space between text and button */
|
||||
}
|
||||
</style>
|
||||
|
||||
<!--begin::Main-->
|
||||
<div class="app-main flex-column flex-row-fluid" id="kt_app_main">
|
||||
|
||||
<div class="d-flex flex-column flex-column-fluid">
|
||||
|
||||
|
||||
@include('uc.breadcrumbList', [
|
||||
'title' => 'Video Management Folder ' . $folderView->name,
|
||||
'pageName' => 'Video Management',
|
||||
])
|
||||
|
||||
|
||||
<div id="kt_app_content" class="app-content flex-column-fluid">
|
||||
|
||||
<div id="kt_app_content_container" class="app-container container-xxl">
|
||||
|
||||
<div class="card">
|
||||
|
||||
@if (Session::has('messageSuccess'))
|
||||
<div class="card-body">
|
||||
@include('uc/messageSuccess')
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@if (Session::has('messageFail'))
|
||||
<div class="card-body">
|
||||
@include('uc/messageFail')
|
||||
</div>
|
||||
@endif
|
||||
|
||||
|
||||
<div class="card-header border-0 pt-6">
|
||||
<div class="d-flex align-items-center position-relative my-1">
|
||||
</div>
|
||||
|
||||
@if (Auth::user()->role != 2)
|
||||
<div class="card-toolbar">
|
||||
<div class="d-flex justify-content-end" data-kt-customer-table-toolbar="base">
|
||||
<a href="{{ url('video/add/' . $folderView->id) }}" class="btn btn-primary">Add
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<div class="card-header border-0 pt-5">
|
||||
|
||||
<div class="card-title">
|
||||
<div class="d-flex align-items-center position-relative my-1">
|
||||
<span class="svg-icon svg-icon-1 position-absolute ms-4">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<rect opacity="0.5" x="17.0365" y="15.1223" width="8.15546" height="2"
|
||||
rx="1" transform="rotate(45 17.0365 15.1223)" fill="currentColor">
|
||||
</rect>
|
||||
<path
|
||||
d="M11 19C6.55556 19 3 15.4444 3 11C3 6.55556 6.55556 3 11 3C15.4444 3 19 6.55556 19 11C19 15.4444 15.4444 19 11 19ZM11 5C7.53333 5 5 7.53333 5 11C5 14.4667 7.53333 17 11 17C14.4667 17 17 14.4667 17 11C17 7.53333 14.4667 5 11 5Z"
|
||||
fill="currentColor"></path>
|
||||
</svg>
|
||||
</span>
|
||||
|
||||
<input type="text" table-filter="search"
|
||||
class="form-control form-control-solid w-250px ps-15" placeholder="Search" />
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="card-body py-4">
|
||||
<!--begin::Table-->
|
||||
<table class="table align-middle table-row-dashed fs-6 gy-5" id="data-table">
|
||||
<!--begin::Table head-->
|
||||
<thead>
|
||||
<!--begin::Table row-->
|
||||
<tr class="text-start text-muted fw-bold fs-7 text-uppercase gs-0">
|
||||
<th class="min-w-125px">Name</th>
|
||||
<th class="min-w-125px">Created</th>
|
||||
<th class="text-end min-w-100px">Manage</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody class="text-gray-600 fw-semibold">
|
||||
|
||||
@foreach ($itemView as $obj)
|
||||
<tr>
|
||||
<td>
|
||||
<div class="d-flex flex-column">
|
||||
<a href="#" class="text-gray-800 text-hover-primary mb-1">
|
||||
<video controls class="h-100px" style="height: 150px!important;">
|
||||
<source src="{{ env('R2_SCHEMA_URL') . $obj['name'] }}"
|
||||
type="video/mp4">
|
||||
Your browser does not support the video element.
|
||||
</video>
|
||||
</a>
|
||||
<span>{{ $obj['name'] }}</span>
|
||||
</div>
|
||||
</td>
|
||||
|
||||
|
||||
<td>
|
||||
{{ Carbon\Carbon::parse($obj['created_at'])->format('d, M Y') }}
|
||||
</td>
|
||||
|
||||
<td class="min-w-100px text-end">
|
||||
|
||||
{{-- Download --}}
|
||||
<a href="{{ env('R2_SCHEMA_URL') . $obj['name'] }}" target="_blank"
|
||||
class="btn btn-sm btn-icon btn-light btn-active-light-primary"
|
||||
type="button" data-bs-toggle="tooltip" aria-label="Coming soon"
|
||||
data-bs-original-title="Coming soon" data-kt-initialized="1">
|
||||
<i class="bi bi-download fs-3"></i>
|
||||
</a>
|
||||
|
||||
{{-- Copy --}}
|
||||
<button type="button" data-action="copy"
|
||||
data-url="{{ env('R2_SCHEMA_URL') . $obj['name'] }}"
|
||||
class="btn btn-sm btn-icon btn-light btn-active-light-primary copy-button">
|
||||
<span class="svg-icon svg-icon-2">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24"
|
||||
fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path opacity="0.5"
|
||||
d="M18 2H9C7.34315 2 6 3.34315 6 5H8C8 4.44772 8.44772 4 9 4H18C18.5523 4 19 4.44772 19 5V16C19 16.5523 18.5523 17 18 17V19C19.6569 19 21 17.6569 21 16V5C21 3.34315 19.6569 2 18 2Z"
|
||||
fill="currentColor"></path>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd"
|
||||
d="M14.7857 7.125H6.21429C5.62255 7.125 5.14286 7.6007 5.14286 8.1875V18.8125C5.14286 19.3993 5.62255 19.875 6.21429 19.875H14.7857C15.3774 19.875 15.8571 19.3993 15.8571 18.8125V8.1875C15.8571 7.6007 15.3774 7.125 14.7857 7.125ZM6.21429 5C4.43908 5 3 6.42709 3 8.1875V18.8125C3 20.5729 4.43909 22 6.21429 22H14.7857C16.5609 22 18 20.5729 18 18.8125V8.1875C18 6.42709 16.5609 5 14.7857 5H6.21429Z"
|
||||
fill="currentColor"></path>
|
||||
</svg>
|
||||
</span>
|
||||
<!--end::Svg Icon-->
|
||||
</button>
|
||||
|
||||
|
||||
{{-- Delete --}}
|
||||
@if (Auth::user()->role != 2)
|
||||
<a href="#" data-id="{{ $obj['id'] }}"
|
||||
class="btn btn-icon btn-bg-light btn-active-color-primary btn-sm delete-item">
|
||||
<span class="svg-icon svg-icon-3">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24"
|
||||
fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M5 9C5 8.44772 5.44772 8 6 8H18C18.5523 8 19 8.44772 19 9V18C19 19.6569 17.6569 21 16 21H8C6.34315 21 5 19.6569 5 18V9Z"
|
||||
fill="currentColor" />
|
||||
<path opacity="0.5"
|
||||
d="M5 5C5 4.44772 5.44772 4 6 4H18C18.5523 4 19 4.44772 19 5V5C19 5.55228 18.5523 6 18 6H6C5.44772 6 5 5.55228 5 5V5Z"
|
||||
fill="currentColor" />
|
||||
<path opacity="0.5"
|
||||
d="M9 4C9 3.44772 9.44772 3 10 3H14C14.5523 3 15 3.44772 15 4V4H9V4Z"
|
||||
fill="currentColor" />
|
||||
</svg>
|
||||
</span>
|
||||
</a>
|
||||
@endif
|
||||
</td>
|
||||
|
||||
|
||||
</tr>
|
||||
@endforeach
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@stop
|
||||
|
||||
|
||||
@section('script')
|
||||
|
||||
<script type="text/javascript">
|
||||
const baseUrl = "{{ url('video') }}";
|
||||
var datatable;
|
||||
datatable = $("#data-table").DataTable({
|
||||
"info": false,
|
||||
"order": [],
|
||||
"pageLength": 25,
|
||||
lengthMenu: [
|
||||
[10, 25, 50, 100, 500, 1000],
|
||||
[10, 25, 50, 100, 500, 1000]
|
||||
]
|
||||
});
|
||||
|
||||
// Filter by search
|
||||
const filterSearch = document.querySelector('[table-filter="search"]');
|
||||
filterSearch.addEventListener('keyup', function(e) {
|
||||
datatable.search(e.target.value).draw();
|
||||
});
|
||||
|
||||
// filter by status
|
||||
const filterStatus = document.querySelector('[table-filter="status"]');
|
||||
$(filterStatus).on('change', e => {
|
||||
let value = e.target.value;
|
||||
if (value === 'all') {
|
||||
value = '';
|
||||
}
|
||||
datatable.column(4).search(value).draw();
|
||||
});
|
||||
|
||||
|
||||
// Remove
|
||||
$(document).on('click', '.delete-item', function() {
|
||||
swal.fire({
|
||||
allowOutsideClick: false,
|
||||
text: "Are you sure you would like to Delete?",
|
||||
icon: "warning",
|
||||
buttonsStyling: false,
|
||||
showDenyButton: true,
|
||||
confirmButtonText: "Yes",
|
||||
denyButtonText: 'No',
|
||||
customClass: {
|
||||
confirmButton: "btn btn-primary",
|
||||
denyButton: "btn btn-light-danger"
|
||||
}
|
||||
}).then((result) => {
|
||||
if (result.isConfirmed) {
|
||||
|
||||
alertLoading("Loading")
|
||||
|
||||
// set up ajax
|
||||
initAjaxSetupToken();
|
||||
|
||||
const ajaxProp = {
|
||||
url: "{{ url('video/delete') }}",
|
||||
type: 'POST',
|
||||
data: {
|
||||
item_id: $(this).data('id')
|
||||
},
|
||||
};
|
||||
|
||||
//const id = $(this).data('id');
|
||||
const id = "{{ $folderView->id }}";
|
||||
|
||||
$.ajax(ajaxProp).done(function(res) {
|
||||
if (res.status) {
|
||||
const url = "{{ url('video/folder') }}/" + id;
|
||||
alertSuccessWithUrl('Notice', "Delete success", url);
|
||||
hideLoading();
|
||||
} else {
|
||||
alertFail('Notice', res.message ?? "Unsuccessfully");
|
||||
hideLoading();
|
||||
}
|
||||
}).fail(function(xhr, status, error) {
|
||||
logAjaxError(xhr, status, error);
|
||||
alertFail('Notice', error.message ?? "Unsuccessfully");
|
||||
hideLoading();
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const copyButtons = document.querySelectorAll('.copy-button');
|
||||
|
||||
copyButtons.forEach(button => {
|
||||
button.addEventListener('click', function() {
|
||||
const urlToCopy = button.getAttribute('data-url');
|
||||
|
||||
// Copy the URL to the clipboard
|
||||
navigator.clipboard.writeText(urlToCopy).then(() => {
|
||||
alert(
|
||||
'Link copied to clipboard!'
|
||||
); // You can change this to a toast notification
|
||||
}).catch(err => {
|
||||
console.error('Could not copy text: ', err);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
@endsection
|
||||
@@ -0,0 +1,440 @@
|
||||
@extends('layouts.backendTemplate')
|
||||
|
||||
@section('content')
|
||||
|
||||
<style>
|
||||
.link-container {
|
||||
display: flex;
|
||||
/* Use flexbox for alignment */
|
||||
align-items: center;
|
||||
/* Center items vertically */
|
||||
justify-content: space-between;
|
||||
/* Space between the URL and button */
|
||||
}
|
||||
|
||||
.file-url {
|
||||
flex: 1;
|
||||
/* Allow the URL to take up available space */
|
||||
color: #007bff;
|
||||
/* Link color */
|
||||
text-decoration: none;
|
||||
/* Remove underline */
|
||||
overflow: hidden;
|
||||
/* Hide overflow */
|
||||
white-space: nowrap;
|
||||
/* Prevent text wrapping */
|
||||
text-overflow: ellipsis;
|
||||
/* Add ellipsis for overflow */
|
||||
margin-right: 10px;
|
||||
/* Space between text and button */
|
||||
}
|
||||
</style>
|
||||
|
||||
<!--begin::Main-->
|
||||
<div class="app-main flex-column flex-row-fluid" id="kt_app_main">
|
||||
|
||||
<div class="d-flex flex-column flex-column-fluid">
|
||||
|
||||
|
||||
@include('uc.breadcrumbList', [
|
||||
'title' => 'Video Management',
|
||||
'pageName' => 'Video Management',
|
||||
])
|
||||
|
||||
|
||||
<div id="kt_app_content" class="app-content flex-column-fluid">
|
||||
|
||||
<div id="kt_app_content_container" class="app-container container-xxl">
|
||||
|
||||
<div class="card">
|
||||
|
||||
@if (Session::has('messageSuccess'))
|
||||
<div class="card-body">
|
||||
@include('uc/messageSuccess')
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@if (Session::has('messageFail'))
|
||||
<div class="card-body">
|
||||
@include('uc/messageFail')
|
||||
</div>
|
||||
@endif
|
||||
|
||||
|
||||
<div class="card-header border-0 pt-6">
|
||||
<div class="d-flex align-items-center position-relative my-1">
|
||||
</div>
|
||||
|
||||
@if (Auth::user()->role != 2)
|
||||
<div class="card-toolbar">
|
||||
|
||||
<div class="d-flex justify-content-end" style="margin-right: 5px;"
|
||||
data-kt-customer-table-toolbar="base">
|
||||
<a href="{{ url('video/add-folder') }}" class="btn btn-light-primary me-3"
|
||||
id="kt_file_manager_new_folder">New
|
||||
Folder</a>
|
||||
</div>
|
||||
|
||||
<div class="d-flex justify-content-end" data-kt-customer-table-toolbar="base">
|
||||
<a href="{{ url('video/add') }}" class="btn btn-primary">Add </a>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@endif
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<div class="card-header border-0 pt-5">
|
||||
|
||||
<div class="card-title">
|
||||
<div class="d-flex align-items-center position-relative my-1">
|
||||
<span class="svg-icon svg-icon-1 position-absolute ms-4">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<rect opacity="0.5" x="17.0365" y="15.1223" width="8.15546" height="2"
|
||||
rx="1" transform="rotate(45 17.0365 15.1223)" fill="currentColor">
|
||||
</rect>
|
||||
<path
|
||||
d="M11 19C6.55556 19 3 15.4444 3 11C3 6.55556 6.55556 3 11 3C15.4444 3 19 6.55556 19 11C19 15.4444 15.4444 19 11 19ZM11 5C7.53333 5 5 7.53333 5 11C5 14.4667 7.53333 17 11 17C14.4667 17 17 14.4667 17 11C17 7.53333 14.4667 5 11 5Z"
|
||||
fill="currentColor"></path>
|
||||
</svg>
|
||||
</span>
|
||||
|
||||
<input type="text" table-filter="search"
|
||||
class="form-control form-control-solid w-250px ps-15" placeholder="Search" />
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="card-body py-4">
|
||||
<!--begin::Table-->
|
||||
<table class="table align-middle table-row-dashed fs-6 gy-5" id="data-table">
|
||||
<!--begin::Table head-->
|
||||
<thead>
|
||||
<!--begin::Table row-->
|
||||
<tr class="text-start text-muted fw-bold fs-7 text-uppercase gs-0">
|
||||
<th class="min-w-125px">Name</th>
|
||||
<th class="min-w-125px">Created</th>
|
||||
<th class="text-end min-w-100px">Action</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody class="text-gray-600 fw-semibold">
|
||||
|
||||
@foreach ($folderView as $obj)
|
||||
<tr>
|
||||
<td>
|
||||
<div class="d-flex align-items-center">
|
||||
<span class="svg-icon svg-icon-2x svg-icon-primary me-4">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24"
|
||||
fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path opacity="0.3" d="M10 4H21C21.6 4 22 4.4 22 5V7H10V4Z"
|
||||
fill="currentColor"></path>
|
||||
<path
|
||||
d="M9.2 3H3C2.4 3 2 3.4 2 4V19C2 19.6 2.4 20 3 20H21C21.6 20 22 19.6 22 19V7C22 6.4 21.6 6 21 6H12L10.4 3.60001C10.2 3.20001 9.7 3 9.2 3Z"
|
||||
fill="currentColor"></path>
|
||||
</svg>
|
||||
</span>
|
||||
<a href="{{ url('video/folder/' . $obj->id) }}"
|
||||
class="text-gray-800 text-hover-primary">
|
||||
{{ $obj->name }}</a>
|
||||
</div>
|
||||
</td>
|
||||
|
||||
<td>
|
||||
{{ Carbon\Carbon::parse($obj['created_at'])->format('d, M Y') }}
|
||||
</td>
|
||||
|
||||
<td class="min-w-100px text-end">
|
||||
|
||||
{{-- Download --}}
|
||||
<a href="{{ url('video/download-folder') . '/' . $obj->id }}"
|
||||
class="btn-download-folder btn btn-sm btn-icon btn-light btn-active-light-primary"
|
||||
type="button" data-bs-toggle="tooltip" aria-label="Coming soon"
|
||||
data-bs-original-title="Coming soon" data-kt-initialized="1">
|
||||
<i class="bi bi-download fs-3"></i>
|
||||
</a>
|
||||
|
||||
|
||||
{{-- Edit --}}
|
||||
<a href="{{ url('video/edit-folder/' . $obj['id']) }}"
|
||||
class="btn btn-icon btn-bg-light btn-active-color-primary btn-sm me-1">
|
||||
<span class="svg-icon svg-icon-3">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24"
|
||||
fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path opacity="0.3"
|
||||
d="M21.4 8.35303L19.241 10.511L13.485 4.755L15.643 2.59595C16.0248 2.21423 16.5426 1.99988 17.0825 1.99988C17.6224 1.99988 18.1402 2.21423 18.522 2.59595L21.4 5.474C21.7817 5.85581 21.9962 6.37355 21.9962 6.91345C21.9962 7.45335 21.7817 7.97122 21.4 8.35303ZM3.68699 21.932L9.88699 19.865L4.13099 14.109L2.06399 20.309C1.98815 20.5354 1.97703 20.7787 2.03189 21.0111C2.08674 21.2436 2.2054 21.4561 2.37449 21.6248C2.54359 21.7934 2.75641 21.9115 2.989 21.9658C3.22158 22.0201 3.4647 22.0084 3.69099 21.932H3.68699Z"
|
||||
fill="currentColor" />
|
||||
<path
|
||||
d="M5.574 21.3L3.692 21.928C3.46591 22.0032 3.22334 22.0141 2.99144 21.9594C2.75954 21.9046 2.54744 21.7864 2.3789 21.6179C2.21036 21.4495 2.09202 21.2375 2.03711 21.0056C1.9822 20.7737 1.99289 20.5312 2.06799 20.3051L2.696 18.422L5.574 21.3ZM4.13499 14.105L9.891 19.861L19.245 10.507L13.489 4.75098L4.13499 14.105Z"
|
||||
fill="currentColor" />
|
||||
</svg>
|
||||
</span>
|
||||
</a>
|
||||
|
||||
{{-- Delete --}}
|
||||
<a href="#" data-id="{{ $obj['id'] }}"
|
||||
class="btn btn-icon btn-bg-light btn-active-color-primary btn-sm delete-folder-item">
|
||||
<span class="svg-icon svg-icon-3">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24"
|
||||
fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M5 9C5 8.44772 5.44772 8 6 8H18C18.5523 8 19 8.44772 19 9V18C19 19.6569 17.6569 21 16 21H8C6.34315 21 5 19.6569 5 18V9Z"
|
||||
fill="currentColor" />
|
||||
<path opacity="0.5"
|
||||
d="M5 5C5 4.44772 5.44772 4 6 4H18C18.5523 4 19 4.44772 19 5V5C19 5.55228 18.5523 6 18 6H6C5.44772 6 5 5.55228 5 5V5Z"
|
||||
fill="currentColor" />
|
||||
<path opacity="0.5"
|
||||
d="M9 4C9 3.44772 9.44772 3 10 3H14C14.5523 3 15 3.44772 15 4V4H9V4Z"
|
||||
fill="currentColor" />
|
||||
</svg>
|
||||
</span>
|
||||
</a>
|
||||
</td>
|
||||
|
||||
|
||||
</tr>
|
||||
@endforeach
|
||||
|
||||
|
||||
@foreach ($itemView as $obj)
|
||||
<tr>
|
||||
|
||||
<td class="d-flex align-items-center">
|
||||
<div class="d-flex flex-column">
|
||||
<a href="#" class="text-gray-800 text-hover-primary mb-1">
|
||||
<video controls class="h-100px" style="height: 150px!important;">
|
||||
<source src="{{ env('R2_SCHEMA_URL') . $obj['name'] }}"
|
||||
type="video/mp4">
|
||||
Your browser does not support the video element.
|
||||
</video>
|
||||
</a>
|
||||
<span>{{ $obj['name'] }}</span>
|
||||
</div>
|
||||
</td>
|
||||
|
||||
<td>
|
||||
{{ Carbon\Carbon::parse($obj['created_at'])->format('d, M Y') }}
|
||||
</td>
|
||||
|
||||
<td class="min-w-100px text-end">
|
||||
|
||||
{{-- Download --}}
|
||||
<a href="{{ env('R2_SCHEMA_URL') . $obj['name'] }}" target="_blank"
|
||||
class="btn btn-sm btn-icon btn-light btn-active-light-primary"
|
||||
type="button" data-bs-toggle="tooltip" aria-label="Coming soon"
|
||||
data-bs-original-title="Coming soon" data-kt-initialized="1">
|
||||
<i class="bi bi-download fs-3"></i>
|
||||
</a>
|
||||
|
||||
{{-- Copy --}}
|
||||
<button type="button" data-action="copy"
|
||||
data-url="{{ env('R2_SCHEMA_URL') . $obj['name'] }}"
|
||||
class="btn btn-sm btn-icon btn-light btn-active-light-primary copy-button">
|
||||
<span class="svg-icon svg-icon-2">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24"
|
||||
fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path opacity="0.5"
|
||||
d="M18 2H9C7.34315 2 6 3.34315 6 5H8C8 4.44772 8.44772 4 9 4H18C18.5523 4 19 4.44772 19 5V16C19 16.5523 18.5523 17 18 17V19C19.6569 19 21 17.6569 21 16V5C21 3.34315 19.6569 2 18 2Z"
|
||||
fill="currentColor"></path>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd"
|
||||
d="M14.7857 7.125H6.21429C5.62255 7.125 5.14286 7.6007 5.14286 8.1875V18.8125C5.14286 19.3993 5.62255 19.875 6.21429 19.875H14.7857C15.3774 19.875 15.8571 19.3993 15.8571 18.8125V8.1875C15.8571 7.6007 15.3774 7.125 14.7857 7.125ZM6.21429 5C4.43908 5 3 6.42709 3 8.1875V18.8125C3 20.5729 4.43909 22 6.21429 22H14.7857C16.5609 22 18 20.5729 18 18.8125V8.1875C18 6.42709 16.5609 5 14.7857 5H6.21429Z"
|
||||
fill="currentColor"></path>
|
||||
</svg>
|
||||
</span>
|
||||
<!--end::Svg Icon-->
|
||||
</button>
|
||||
|
||||
{{-- Delete --}}
|
||||
@if (Auth::user()->role != 2)
|
||||
<a href="#" data-id="{{ $obj['id'] }}"
|
||||
class="btn btn-sm btn-icon btn-light btn-active-light-primary delete-item">
|
||||
<span class="svg-icon svg-icon-3">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24"
|
||||
fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M5 9C5 8.44772 5.44772 8 6 8H18C18.5523 8 19 8.44772 19 9V18C19 19.6569 17.6569 21 16 21H8C6.34315 21 5 19.6569 5 18V9Z"
|
||||
fill="currentColor" />
|
||||
<path opacity="0.5"
|
||||
d="M5 5C5 4.44772 5.44772 4 6 4H18C18.5523 4 19 4.44772 19 5V5C19 5.55228 18.5523 6 18 6H6C5.44772 6 5 5.55228 5 5V5Z"
|
||||
fill="currentColor" />
|
||||
<path opacity="0.5"
|
||||
d="M9 4C9 3.44772 9.44772 3 10 3H14C14.5523 3 15 3.44772 15 4V4H9V4Z"
|
||||
fill="currentColor" />
|
||||
</svg>
|
||||
</span>
|
||||
</a>
|
||||
@endif
|
||||
</td>
|
||||
|
||||
|
||||
</tr>
|
||||
@endforeach
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@stop
|
||||
|
||||
|
||||
@section('script')
|
||||
|
||||
<script type="text/javascript">
|
||||
const baseUrl = "{{ url('video') }}";
|
||||
var datatable;
|
||||
datatable = $("#data-table").DataTable({
|
||||
"info": false,
|
||||
"order": [],
|
||||
"pageLength": 25,
|
||||
lengthMenu: [
|
||||
[10, 25, 50, 100, 500, 1000],
|
||||
[10, 25, 50, 100, 500, 1000]
|
||||
]
|
||||
});
|
||||
|
||||
// Filter by search
|
||||
const filterSearch = document.querySelector('[table-filter="search"]');
|
||||
filterSearch.addEventListener('keyup', function(e) {
|
||||
datatable.search(e.target.value).draw();
|
||||
});
|
||||
|
||||
// filter by status
|
||||
const filterStatus = document.querySelector('[table-filter="status"]');
|
||||
$(filterStatus).on('change', e => {
|
||||
let value = e.target.value;
|
||||
if (value === 'all') {
|
||||
value = '';
|
||||
}
|
||||
datatable.column(4).search(value).draw();
|
||||
});
|
||||
|
||||
|
||||
// Remove
|
||||
$(document).on('click', '.delete-item', function() {
|
||||
swal.fire({
|
||||
allowOutsideClick: false,
|
||||
text: "Are you sure you would like to Delete?",
|
||||
icon: "warning",
|
||||
buttonsStyling: false,
|
||||
showDenyButton: true,
|
||||
confirmButtonText: "Yes",
|
||||
denyButtonText: 'No',
|
||||
customClass: {
|
||||
confirmButton: "btn btn-primary",
|
||||
denyButton: "btn btn-light-danger"
|
||||
}
|
||||
}).then((result) => {
|
||||
if (result.isConfirmed) {
|
||||
|
||||
alertLoading("Loading")
|
||||
|
||||
// set up ajax
|
||||
initAjaxSetupToken();
|
||||
|
||||
const ajaxProp = {
|
||||
url: "{{ url('video/delete') }}",
|
||||
type: 'POST',
|
||||
data: {
|
||||
item_id: $(this).data('id')
|
||||
},
|
||||
};
|
||||
|
||||
$.ajax(ajaxProp).done(function(res) {
|
||||
if (res.status) {
|
||||
const url = "{{ url('video') }}";
|
||||
alertSuccessWithUrl('Notice', "Delete success", url);
|
||||
hideLoading();
|
||||
} else {
|
||||
alertFail('Notice', res.message ?? "Unsuccessfully");
|
||||
hideLoading();
|
||||
}
|
||||
}).fail(function(xhr, status, error) {
|
||||
logAjaxError(xhr, status, error);
|
||||
alertFail('Notice', error.message ?? "Unsuccessfully");
|
||||
hideLoading();
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const copyButtons = document.querySelectorAll('.copy-button');
|
||||
|
||||
copyButtons.forEach(button => {
|
||||
button.addEventListener('click', function() {
|
||||
const urlToCopy = button.getAttribute('data-url');
|
||||
|
||||
// Copy the URL to the clipboard
|
||||
navigator.clipboard.writeText(urlToCopy).then(() => {
|
||||
alert(
|
||||
'Link copied to clipboard!'
|
||||
); // You can change this to a toast notification
|
||||
}).catch(err => {
|
||||
console.error('Could not copy text: ', err);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
|
||||
// Delete folder
|
||||
$(document).on('click', '.delete-folder-item', function() {
|
||||
swal.fire({
|
||||
allowOutsideClick: false,
|
||||
text: "Are you sure you would like to Delete?",
|
||||
icon: "warning",
|
||||
buttonsStyling: false,
|
||||
showDenyButton: true,
|
||||
confirmButtonText: "Yes",
|
||||
denyButtonText: 'No',
|
||||
customClass: {
|
||||
confirmButton: "btn btn-primary",
|
||||
denyButton: "btn btn-light-danger"
|
||||
}
|
||||
}).then((result) => {
|
||||
if (result.isConfirmed) {
|
||||
|
||||
alertLoading("Loading")
|
||||
|
||||
// set up ajax
|
||||
initAjaxSetupToken();
|
||||
|
||||
const ajaxProp = {
|
||||
url: "{{ url('video/delete-folder') }}",
|
||||
type: 'POST',
|
||||
data: {
|
||||
item_id: $(this).data('id')
|
||||
},
|
||||
};
|
||||
|
||||
$.ajax(ajaxProp).done(function(res) {
|
||||
if (res.status) {
|
||||
const url = "{{ url('video') }}";
|
||||
alertSuccessWithUrl('Notice', "Delete success", url);
|
||||
hideLoading();
|
||||
} else {
|
||||
alertFail('Notice', res.message ?? "Unsuccessfully");
|
||||
hideLoading();
|
||||
}
|
||||
}).fail(function(xhr, status, error) {
|
||||
logAjaxError(xhr, status, error);
|
||||
alertFail('Notice', error.message ?? "Unsuccessfully");
|
||||
hideLoading();
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
@endsection
|
||||
BIN
think-backend.greaterchiangmai.com/resources/views/emails/.DS_Store
vendored
Normal file
BIN
think-backend.greaterchiangmai.com/resources/views/emails/.DS_Store
vendored
Normal file
Binary file not shown.
@@ -0,0 +1,85 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" style="background-color: #d5d9e2;">
|
||||
<!--begin::Body-->
|
||||
|
||||
<body id="kt_body" class="app-blank">
|
||||
|
||||
<div class="d-flex flex-column flex-root" id="kt_app_root">
|
||||
<!--begin::Wrapper-->
|
||||
<div class="d-flex flex-column flex-column-fluid">
|
||||
|
||||
|
||||
<!--begin::Body-->
|
||||
<div class="scroll-y flex-column-fluid px-10 py-10" data-kt-scroll="true" data-kt-scroll-activate="true"
|
||||
data-kt-scroll-height="auto" data-kt-scroll-dependencies="#kt_app_header_nav"
|
||||
data-kt-scroll-offset="5px" data-kt-scroll-save-state="true"
|
||||
style="background-color:#D5D9E2; --kt-scrollbar-color: #d9d0cc; --kt-scrollbar-hover-color: #d9d0cc">
|
||||
<!--begin::Email template-->
|
||||
<style>
|
||||
html,
|
||||
body {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
font-family: Inter, Helvetica, "sans-serif";
|
||||
}
|
||||
|
||||
a:hover {
|
||||
color: #009ef7;
|
||||
}
|
||||
</style>
|
||||
<div id="#kt_app_body_content"
|
||||
style="background-color:#D5D9E2; font-family:Arial,Helvetica,sans-serif; line-height: 1.5; min-height: 100%; font-weight: normal; font-size: 15px; color: #2F3044; margin:0; padding:0; width:100%;">
|
||||
<div
|
||||
style="background-color:#ffffff; padding: 45px 0 34px 0; border-radius: 24px; margin:40px auto; max-width: 600px;">
|
||||
<table align="center" border="0" cellpadding="0" cellspacing="0" width="100%"
|
||||
height="auto" style="border-collapse:collapse">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td align="center" valign="center" style="text-align:center; padding-bottom: 10px">
|
||||
<!--begin:Email content-->
|
||||
<div style="text-align:center; margin:0 60px 34px 60px">
|
||||
|
||||
<!--begin:Media-->
|
||||
<div style="margin-bottom:15px">
|
||||
<p
|
||||
style="margin-bottom:9px; color:#181C32; font-size: 28px; font-weight:600">
|
||||
The Greater Chiangmai</p>
|
||||
</div>
|
||||
<!--end:Media-->
|
||||
|
||||
<div
|
||||
style="font-size: 14px; font-weight: 500; margin-bottom: 40px; font-family:Arial,Helvetica,sans-serif;">
|
||||
<p
|
||||
style="margin-bottom:9px; color:#181C32; font-size: 22px; font-weight:700">
|
||||
ลืมรหัสผ่าน
|
||||
</p>
|
||||
<p style="margin-bottom:2px; color:#7E8299">
|
||||
เราได้รับคำขอให้รีเซ็ตรหัสผ่านสำหรับบัญชีของคุณ
|
||||
</p>
|
||||
</div>
|
||||
<!--end:Text-->
|
||||
<!--begin:Text-->
|
||||
<div
|
||||
style="text-align:start; font-size: 13px; font-weight: 500; margin-bottom: 27px; font-family:Arial,Helvetica,sans-serif;">
|
||||
|
||||
{{-- Link --}}
|
||||
<p style="margin-bottom:2px; color:#5E6278">
|
||||
<a target="_blank" href="{{ $link }}"
|
||||
style="color:#50cd89; font-weight: 600"> ยืนยัน</a>
|
||||
</p>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -0,0 +1,81 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" style="background-color: #d5d9e2;">
|
||||
<!--begin::Body-->
|
||||
|
||||
<body id="kt_body" class="app-blank">
|
||||
|
||||
<div class="d-flex flex-column flex-root" id="kt_app_root">
|
||||
<!--begin::Wrapper-->
|
||||
<div class="d-flex flex-column flex-column-fluid">
|
||||
|
||||
|
||||
<!--begin::Body-->
|
||||
<div class="scroll-y flex-column-fluid px-10 py-10" data-kt-scroll="true" data-kt-scroll-activate="true"
|
||||
data-kt-scroll-height="auto" data-kt-scroll-dependencies="#kt_app_header_nav"
|
||||
data-kt-scroll-offset="5px" data-kt-scroll-save-state="true"
|
||||
style="background-color:#D5D9E2; --kt-scrollbar-color: #d9d0cc; --kt-scrollbar-hover-color: #d9d0cc">
|
||||
<!--begin::Email template-->
|
||||
<style>
|
||||
html,
|
||||
body {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
font-family: Inter, Helvetica, "sans-serif";
|
||||
}
|
||||
|
||||
a:hover {
|
||||
color: #009ef7;
|
||||
}
|
||||
</style>
|
||||
<div id="#kt_app_body_content"
|
||||
style="background-color:#D5D9E2; font-family:Arial,Helvetica,sans-serif; line-height: 1.5; min-height: 100%; font-weight: normal; font-size: 15px; color: #2F3044; margin:0; padding:0; width:100%;">
|
||||
<div
|
||||
style="background-color:#ffffff; padding: 45px 0 34px 0; border-radius: 24px; margin:40px auto; max-width: 600px;">
|
||||
<table align="center" border="0" cellpadding="0" cellspacing="0" width="100%"
|
||||
height="auto" style="border-collapse:collapse">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td align="center" valign="center" style="text-align:center; padding-bottom: 10px">
|
||||
<!--begin:Email content-->
|
||||
<div style="text-align:center; margin:0 60px 34px 60px">
|
||||
|
||||
<!--begin:Media-->
|
||||
<div style="margin-bottom:15px">
|
||||
<p
|
||||
style="margin-bottom:9px; color:#181C32; font-size: 28px; font-weight:600">
|
||||
The Greater Chiangmai</p>
|
||||
</div>
|
||||
<!--end:Media-->
|
||||
<!--begin:Text-->
|
||||
<div
|
||||
style="font-size: 14px; font-weight: 500; margin-bottom: 40px; font-family:Arial,Helvetica,sans-serif;">
|
||||
<p
|
||||
style="margin-bottom:9px; color:#181C32; font-size: 22px; font-weight:700">
|
||||
รีเซทรหัสผ่าน
|
||||
</p>
|
||||
<p style="margin-bottom:2px; color:#7E8299"> รหัสผ่านใหม่ด้านล่าง</p>
|
||||
</div>
|
||||
<!--end:Text-->
|
||||
<!--begin:Text-->
|
||||
<div
|
||||
style="text-align:start; font-size: 13px; font-weight: 500; margin-bottom: 27px; font-family:Arial,Helvetica,sans-serif;">
|
||||
<p
|
||||
style="margin-bottom:9px; color:#181C32; font-size: 18px; font-weight:600">
|
||||
{{ $password }} </p>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -0,0 +1,31 @@
|
||||
@extends('layouts.errorTemplate')
|
||||
|
||||
@section('main')
|
||||
<div class="d-flex flex-column flex-center text-center p-10">
|
||||
<!--begin::Wrapper-->
|
||||
<div class="card card-flush w-lg-650px py-5">
|
||||
<div class="card-body py-15 py-lg-20">
|
||||
<!--begin::Title-->
|
||||
<h1 class="fw-bolder fs-2qx text-gray-900 mb-4">Not Found</h1>
|
||||
<!--end::Title-->
|
||||
<!--begin::Text-->
|
||||
<div class="fw-semibold fs-6 text-gray-500 mb-7">We can't find that page.</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<img src="{{ url('assets/media/auth/404-error.png') }}" class="mw-100 mh-300px theme-light-show"
|
||||
alt="" />
|
||||
<img src="{{ url('assets/media/auth/404-error-dark.png') }}" class="mw-100 mh-300px theme-dark-show"
|
||||
alt="" />
|
||||
</div>
|
||||
|
||||
<!--end::Illustration-->
|
||||
<!--begin::Link-->
|
||||
<div class="mb-0">
|
||||
<a href="{{ url('') }}" class="btn btn-sm btn-primary">Return Home</a>
|
||||
</div>
|
||||
<!--end::Link-->
|
||||
</div>
|
||||
</div>
|
||||
<!--end::Wrapper-->
|
||||
</div>
|
||||
@endsection
|
||||
@@ -0,0 +1,32 @@
|
||||
@extends('layouts.errorTemplate')
|
||||
|
||||
@section('main')
|
||||
<div class="d-flex flex-column flex-center text-center p-10">
|
||||
<!--begin::Wrapper-->
|
||||
<div class="card card-flush w-lg-650px py-5">
|
||||
<div class="card-body py-15 py-lg-20">
|
||||
<!--begin::Title-->
|
||||
<h1 class="fw-bolder fs-2qx text-gray-900 mb-4">Internal Server Error</h1>
|
||||
<!--end::Title-->
|
||||
<!--begin::Text-->
|
||||
<div class="fw-semibold fs-6 text-gray-500 mb-7">Something went wrong! Please try again later or contact the
|
||||
administrator.</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<img src="{{ url('assets/media/auth/500-error.png') }}" class="mw-100 mh-300px theme-light-show"
|
||||
alt="" />
|
||||
<img src="{{ url('assets/media/auth/500-error-dark.png') }}" class="mw-100 mh-300px theme-dark-show"
|
||||
alt="" />
|
||||
</div>
|
||||
|
||||
<!--end::Illustration-->
|
||||
<!--begin::Link-->
|
||||
<div class="mb-0">
|
||||
<a href="{{ url('') }}" class="btn btn-sm btn-primary">Return Home</a>
|
||||
</div>
|
||||
<!--end::Link-->
|
||||
</div>
|
||||
</div>
|
||||
<!--end::Wrapper-->
|
||||
</div>
|
||||
@endsection
|
||||
@@ -0,0 +1,32 @@
|
||||
@extends('layouts.errorTemplate')
|
||||
|
||||
@section('main')
|
||||
<div class="d-flex flex-column flex-center text-center p-10">
|
||||
<!--begin::Wrapper-->
|
||||
<div class="card card-flush w-lg-650px py-5">
|
||||
<div class="card-body py-15 py-lg-20">
|
||||
<!--begin::Title-->
|
||||
<h1 class="fw-bolder fs-2qx text-gray-900 mb-4">503 Service Unavailable Error</h1>
|
||||
<!--end::Title-->
|
||||
<!--begin::Text-->
|
||||
<div class="fw-semibold fs-6 text-gray-500 mb-7">Something went wrong! Please try again later or contact the
|
||||
administrator.</div>
|
||||
<!--end::Text-->
|
||||
<!--begin::Illustration-->
|
||||
{{-- <div class="mb-11">
|
||||
<img src="{{ url('assets/media/auth/500-error.png') }}" class="mw-100 mh-300px theme-light-show"
|
||||
alt="" />
|
||||
<img src="{{ url('assets/media/auth/500-error-dark.png') }}" class="mw-100 mh-300px theme-dark-show"
|
||||
alt="" />
|
||||
</div> --}}
|
||||
<!--end::Illustration-->
|
||||
<!--begin::Link-->
|
||||
<div class="mb-0">
|
||||
<a href="{{ url('') }}" class="btn btn-sm btn-primary">Return Home</a>
|
||||
</div>
|
||||
<!--end::Link-->
|
||||
</div>
|
||||
</div>
|
||||
<!--end::Wrapper-->
|
||||
</div>
|
||||
@endsection
|
||||
@@ -0,0 +1,25 @@
|
||||
@extends('layouts.errorTemplate')
|
||||
|
||||
@section('main')
|
||||
<div class="d-flex flex-column flex-center text-center p-10">
|
||||
<!--begin::Wrapper-->
|
||||
<div class="card card-flush w-lg-650px py-5">
|
||||
<div class="card-body py-15 py-lg-20">
|
||||
<!--begin::Title-->
|
||||
<h1 class="fw-bolder fs-2qx text-gray-900 mb-4">No Access</h1>
|
||||
<!--end::Title-->
|
||||
<!--begin::Text-->
|
||||
<div class="fw-semibold fs-6 text-gray-500 mb-7">
|
||||
Sorry, you are not allowed to see this.
|
||||
</div>
|
||||
<!--end::Text-->
|
||||
<!--begin::Link-->
|
||||
<div class="mb-0">
|
||||
<a href="{{ url('') }}" class="btn btn-sm btn-primary">Return Home</a>
|
||||
</div>
|
||||
<!--end::Link-->
|
||||
</div>
|
||||
</div>
|
||||
<!--end::Wrapper-->
|
||||
</div>
|
||||
@endsection
|
||||
@@ -0,0 +1,25 @@
|
||||
@extends('layouts.errorTemplate')
|
||||
|
||||
@section('main')
|
||||
<div class="d-flex flex-column flex-center text-center p-10">
|
||||
<!--begin::Wrapper-->
|
||||
<div class="card card-flush w-lg-650px py-5">
|
||||
<div class="card-body py-15 py-lg-20">
|
||||
<!--begin::Title-->
|
||||
<h1 class="fw-bolder fs-2qx text-gray-900 mb-4">No Permission</h1>
|
||||
<!--end::Title-->
|
||||
<!--begin::Text-->
|
||||
<div class="fw-semibold fs-6 text-gray-500 mb-7">
|
||||
Sorry, you do not have permission to access this view.
|
||||
</div>
|
||||
<!--end::Text-->
|
||||
<!--begin::Link-->
|
||||
<div class="mb-0">
|
||||
<a href="{{ url('') }}" class="btn btn-sm btn-primary">Return Home</a>
|
||||
</div>
|
||||
<!--end::Link-->
|
||||
</div>
|
||||
</div>
|
||||
<!--end::Wrapper-->
|
||||
</div>
|
||||
@endsection
|
||||
@@ -0,0 +1,563 @@
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html lang="en">
|
||||
<!--begin::Head-->
|
||||
|
||||
<head>
|
||||
<title>The Greater Chiangmai : Backend</title>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="description" content="The Greater Chiangmai : Backend" />
|
||||
<meta name="keywords" content="The Greater Chiangmai : Backend" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<meta property="og:locale" content="en_US" />
|
||||
<meta property="og:type" content="article" />
|
||||
<meta property="og:title" content="The Greater Chiangmai : Backend" />
|
||||
<meta property="og:url" content="" />
|
||||
<meta property="og:site_name" content="Keenthemes | Metronic" />
|
||||
<link rel="canonical" href="" />
|
||||
<link rel="shortcut icon" href="{{ url('assets/media/logos/favicon.ico') }}" />
|
||||
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Inter:300,400,500,600,700" />
|
||||
|
||||
<link href="{{ url('assets/plugins/custom/fullcalendar/fullcalendar.bundle.css') }}" rel="stylesheet"
|
||||
type="text/css" />
|
||||
<link href="{{ url('assets/plugins/custom/datatables/datatables.bundle.css') }}" rel="stylesheet" type="text/css" />
|
||||
|
||||
<link href="{{ url('assets/plugins/global/plugins.bundle.css') }}" rel="stylesheet" type="text/css" />
|
||||
|
||||
<link href="{{ url('assets/css/style.bundle.css') }}" rel="stylesheet" type="text/css" />
|
||||
|
||||
|
||||
<link href="{{ url('assets/plugins/custom/magnific/magnific-popup.css') }}" rel="stylesheet" type="text/css" />
|
||||
|
||||
<meta name="csrf-token" content="{{ csrf_token() }}">
|
||||
|
||||
|
||||
{{-- fileuploader --}}
|
||||
<link href="{{ url('assets/plugins/fileuploader-2.2/dist/jquery.fileuploader.min.css') }}" media="all"
|
||||
rel="stylesheet">
|
||||
|
||||
<link href="{{ url('assets/plugins/fileuploader-2.2/dist/font/font-fileuploader.css') }}" rel="stylesheet">
|
||||
<link href="{{ url('assets/plugins/fileuploader-2.2/dist/jquery.fileuploader-theme-dragdrop.css') }}" media="all"
|
||||
rel="stylesheet">
|
||||
<link href="{{ url('assets/plugins/fileuploader-2.2/dist/jquery.fileuploader-theme-thumbnails.css') }}"
|
||||
media="all" rel="stylesheet">
|
||||
|
||||
<style>
|
||||
.image-input-placeholder {
|
||||
background-image: url('{{ url('assets/media/svg/files/blank-image.svg') }}');
|
||||
}
|
||||
|
||||
[data-bs-theme="dark"] .image-input-placeholder {
|
||||
background-image: url('{{ url('assets/media/svg/files/blank-image-dark.svg') }}');
|
||||
}
|
||||
|
||||
.form-check-label {
|
||||
color: #2e2e2e;
|
||||
font-size: 1.2rem;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.fv-row {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.invalid {
|
||||
color: red;
|
||||
font-size: 0.9rem;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
.ck-editor__editable_inline {
|
||||
min-height: 300px;
|
||||
}
|
||||
|
||||
.app-sidebar-logo-default {
|
||||
height: 50px;
|
||||
}
|
||||
|
||||
@media (min-width: 992px) {
|
||||
.app-sidebar-logo-minimize {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
</head>
|
||||
<!--end::Head-->
|
||||
|
||||
|
||||
<!--begin::Body-->
|
||||
|
||||
<body id="kt_app_body" data-kt-app-layout="dark-sidebar" data-kt-app-header-fixed="true"
|
||||
data-kt-app-sidebar-enabled="true" data-kt-app-sidebar-fixed="true" data-kt-app-sidebar-hoverable="true"
|
||||
data-kt-app-sidebar-push-header="true" data-kt-app-sidebar-push-toolbar="true"
|
||||
data-kt-app-sidebar-push-footer="true" data-kt-app-toolbar-enabled="true" class="app-default">
|
||||
|
||||
|
||||
<div class="page-loader flex-column">
|
||||
<span class="spinner-border text-primary" role="status"></span>
|
||||
<span class="text-muted fs-6 fw-semibold mt-5">Loading...</span>
|
||||
</div>
|
||||
|
||||
<!--begin body -->
|
||||
<div class="d-flex flex-column flex-root app-root" id="kt_app_root">
|
||||
<!--begin::Page-->
|
||||
<div class="app-page flex-column flex-column-fluid" id="kt_app_page">
|
||||
|
||||
@include('uc.header')
|
||||
|
||||
|
||||
<!--begin:: Main Wrapper -->
|
||||
<div class="app-wrapper flex-column flex-row-fluid" id="kt_app_wrapper">
|
||||
|
||||
<!--begin:: Sidebar-->
|
||||
<div id="kt_app_sidebar" class="app-sidebar flex-column" data-kt-drawer="true"
|
||||
data-kt-drawer-name="app-sidebar" data-kt-drawer-activate="{default: true, lg: false}"
|
||||
data-kt-drawer-overlay="true" data-kt-drawer-width="225px" data-kt-drawer-direction="start"
|
||||
data-kt-drawer-toggle="#kt_app_sidebar_mobile_toggle">
|
||||
|
||||
<!--begin::Logo-->
|
||||
<div class="app-sidebar-logo px-6" id="kt_app_sidebar_logo">
|
||||
<!--begin::Logo image-->
|
||||
<a href="{{ url('') }}">
|
||||
<img alt="The Greater Chiangmai" src="{{ url('assets/media/logos/footer-logo.png') }}"
|
||||
class=" app-sidebar-logo-default" />
|
||||
<img alt="The Greater Chiangmai" src="{{ url('assets/media/logos/footer-logo.png') }}"
|
||||
class="app-sidebar-logo-minimize" />
|
||||
</a>
|
||||
<!--end::Logo image-->
|
||||
<!--begin::Sidebar toggle-->
|
||||
<div id="kt_app_sidebar_toggle"
|
||||
class="app-sidebar-toggle btn btn-icon btn-shadow btn-sm btn-color-muted btn-active-color-primary body-bg h-30px w-30px position-absolute top-50 start-100 translate-middle rotate"
|
||||
data-kt-toggle="true" data-kt-toggle-state="active" data-kt-toggle-target="body"
|
||||
data-kt-toggle-name="app-sidebar-minimize">
|
||||
<!--begin::Svg Icon | path: icons/duotune/arrows/arr079.svg-->
|
||||
<span class="svg-icon svg-icon-2 rotate-180">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<path opacity="0.5"
|
||||
d="M14.2657 11.4343L18.45 7.25C18.8642 6.83579 18.8642 6.16421 18.45 5.75C18.0358 5.33579 17.3642 5.33579 16.95 5.75L11.4071 11.2929C11.0166 11.6834 11.0166 12.3166 11.4071 12.7071L16.95 18.25C17.3642 18.6642 18.0358 18.6642 18.45 18.25C18.8642 17.8358 18.8642 17.1642 18.45 16.75L14.2657 12.5657C13.9533 12.2533 13.9533 11.7467 14.2657 11.4343Z"
|
||||
fill="currentColor" />
|
||||
<path
|
||||
d="M8.2657 11.4343L12.45 7.25C12.8642 6.83579 12.8642 6.16421 12.45 5.75C12.0358 5.33579 11.3642 5.33579 10.95 5.75L5.40712 11.2929C5.01659 11.6834 5.01659 12.3166 5.40712 12.7071L10.95 18.25C11.3642 18.6642 12.0358 18.6642 12.45 18.25C12.8642 17.8358 12.8642 17.1642 12.45 16.75L8.2657 12.5657C7.95328 12.2533 7.95328 11.7467 8.2657 11.4343Z"
|
||||
fill="currentColor" />
|
||||
</svg>
|
||||
</span>
|
||||
|
||||
</div>
|
||||
<!--end::Sidebar toggle-->
|
||||
</div>
|
||||
<!--end::Logo-->
|
||||
|
||||
<!--begin:: SIDEBAR menu-->
|
||||
<div class="app-sidebar-menu overflow-hidden flex-column-fluid">
|
||||
<!--begin::Menu wrapper-->
|
||||
<div id="kt_app_sidebar_menu_wrapper" class="app-sidebar-wrapper hover-scroll-overlay-y my-5"
|
||||
data-kt-scroll="true" data-kt-scroll-activate="true" data-kt-scroll-height="auto"
|
||||
data-kt-scroll-dependencies="#kt_app_sidebar_logo, #kt_app_sidebar_footer"
|
||||
data-kt-scroll-wrappers="#kt_app_sidebar_menu" data-kt-scroll-offset="5px"
|
||||
data-kt-scroll-save-state="true">
|
||||
|
||||
<div class="menu menu-column menu-rounded menu-sub-indention px-3"
|
||||
id="#kt_app_sidebar_menu" data-kt-menu="true" data-kt-menu-expand="false">
|
||||
|
||||
<div class="menu-item here show menu-accordion">
|
||||
|
||||
<a class="menu-link {{ Request::is('dashboard*') ? 'active' : '' }}"
|
||||
href="{{ url('') }}">
|
||||
<span class="menu-icon">
|
||||
<!--begin::Svg Icon | path: icons/duotune/general/gen025.svg-->
|
||||
<span class="svg-icon svg-icon-2">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24"
|
||||
fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect x="2" y="2" width="9" height="9" rx="2"
|
||||
fill="currentColor" />
|
||||
<rect opacity="0.3" x="13" y="2" width="9" height="9"
|
||||
rx="2" fill="currentColor" />
|
||||
<rect opacity="0.3" x="13" y="13" width="9" height="9"
|
||||
rx="2" fill="currentColor" />
|
||||
<rect opacity="0.3" x="2" y="13" width="9" height="9"
|
||||
rx="2" fill="currentColor" />
|
||||
</svg>
|
||||
</span>
|
||||
|
||||
</span>
|
||||
<span class="menu-title">Dashboards</span>
|
||||
</a>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
@if (Auth::user()->role != 2)
|
||||
{{-- Category: CHIANG MAI AND NOWHERE ELSE --}}
|
||||
<div class="menu-item pt-5">
|
||||
<div class="menu-content"><span
|
||||
class="menu-heading fw-bold text-uppercase fs-7">
|
||||
CHIANG MAI AND NOWHERE ELSE
|
||||
</span></div>
|
||||
</div>
|
||||
|
||||
|
||||
{{-- Sub category --}}
|
||||
<div class="menu-item menu-accordion">
|
||||
|
||||
<a class="menu-link {{ Request::is('no-where-else/sub-category*') || Request::is('no-where-else/add-sub-category*') || Request::is('no-where-else/edit-sub-category*') ? 'active' : '' }}"
|
||||
href="{{ url('no-where-else/sub-category') }}">
|
||||
<span class="menu-icon">
|
||||
<!--begin::Svg Icon | path: icons/duotune/abstract/abs042.svg-->
|
||||
<span class="svg-icon svg-icon-2">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24"
|
||||
fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M18 21.6C16.6 20.4 9.1 20.3 6.3 21.2C5.7 21.4 5.1 21.2 4.7 20.8L2 18C4.2 15.8 10.8 15.1 15.8 15.8C16.2 18.3 17 20.5 18 21.6ZM18.8 2.8C18.4 2.4 17.8 2.20001 17.2 2.40001C14.4 3.30001 6.9 3.2 5.5 2C6.8 3.3 7.4 5.5 7.7 7.7C9 7.9 10.3 8 11.7 8C15.8 8 19.8 7.2 21.5 5.5L18.8 2.8Z"
|
||||
fill="currentColor"></path>
|
||||
<path opacity="0.3"
|
||||
d="M21.2 17.3C21.4 17.9 21.2 18.5 20.8 18.9L18 21.6C15.8 19.4 15.1 12.8 15.8 7.8C18.3 7.4 20.4 6.70001 21.5 5.60001C20.4 7.00001 20.2 14.5 21.2 17.3ZM8 11.7C8 9 7.7 4.2 5.5 2L2.8 4.8C2.4 5.2 2.2 5.80001 2.4 6.40001C2.7 7.40001 3.00001 9.2 3.10001 11.7C3.10001 15.5 2.40001 17.6 2.10001 18C3.20001 16.9 5.3 16.2 7.8 15.8C8 14.2 8 12.7 8 11.7Z"
|
||||
fill="currentColor"></path>
|
||||
</svg>
|
||||
</span>
|
||||
<!--end::Svg Icon-->
|
||||
</span>
|
||||
<span class="menu-title">Sub Category</span>
|
||||
</a>
|
||||
|
||||
</div>
|
||||
|
||||
{{-- Sub article --}}
|
||||
<div class="menu-item menu-accordion">
|
||||
<a class="menu-link {{ Request::is('no-where-else/article*') || Request::is('no-where-else/add-article*') ? 'active' : '' }}"
|
||||
href="{{ url('no-where-else/article') }}">
|
||||
<span class="menu-icon">
|
||||
<!--begin::Svg Icon | path: icons/duotune/layouts/lay008.svg-->
|
||||
<span class="svg-icon svg-icon-2">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24"
|
||||
fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M20 7H3C2.4 7 2 6.6 2 6V3C2 2.4 2.4 2 3 2H20C20.6 2 21 2.4 21 3V6C21 6.6 20.6 7 20 7ZM7 9H3C2.4 9 2 9.4 2 10V20C2 20.6 2.4 21 3 21H7C7.6 21 8 20.6 8 20V10C8 9.4 7.6 9 7 9Z"
|
||||
fill="currentColor"></path>
|
||||
<path opacity="0.3"
|
||||
d="M20 21H11C10.4 21 10 20.6 10 20V10C10 9.4 10.4 9 11 9H20C20.6 9 21 9.4 21 10V20C21 20.6 20.6 21 20 21Z"
|
||||
fill="currentColor"></path>
|
||||
</svg>
|
||||
</span>
|
||||
<!--end::Svg Icon-->
|
||||
</span>
|
||||
<span class="menu-title">Article</span>
|
||||
</a>
|
||||
|
||||
</div>
|
||||
@endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@if (Auth::user()->role != 2)
|
||||
{{-- Category: CHIANG MAI AND NOWHERE ELSE --}}
|
||||
<div class="menu-item pt-5">
|
||||
<div class="menu-content"><span
|
||||
class="menu-heading fw-bold text-uppercase fs-7">
|
||||
WHERE ELSE
|
||||
</span></div>
|
||||
</div>
|
||||
|
||||
{{-- Sub category --}}
|
||||
<div class="menu-item menu-accordion">
|
||||
<a class="menu-link {{ Request::is('where-else/sub-category*') || Request::is('where-else/add-sub-category*') || Request::is('where-else/edit-sub-category*') ? 'active' : '' }}"
|
||||
href="{{ url('where-else/sub-category') }}">
|
||||
<span class="menu-icon">
|
||||
<!--begin::Svg Icon | path: icons/duotune/abstract/abs042.svg-->
|
||||
<span class="svg-icon svg-icon-2">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24"
|
||||
fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M18 21.6C16.6 20.4 9.1 20.3 6.3 21.2C5.7 21.4 5.1 21.2 4.7 20.8L2 18C4.2 15.8 10.8 15.1 15.8 15.8C16.2 18.3 17 20.5 18 21.6ZM18.8 2.8C18.4 2.4 17.8 2.20001 17.2 2.40001C14.4 3.30001 6.9 3.2 5.5 2C6.8 3.3 7.4 5.5 7.7 7.7C9 7.9 10.3 8 11.7 8C15.8 8 19.8 7.2 21.5 5.5L18.8 2.8Z"
|
||||
fill="currentColor"></path>
|
||||
<path opacity="0.3"
|
||||
d="M21.2 17.3C21.4 17.9 21.2 18.5 20.8 18.9L18 21.6C15.8 19.4 15.1 12.8 15.8 7.8C18.3 7.4 20.4 6.70001 21.5 5.60001C20.4 7.00001 20.2 14.5 21.2 17.3ZM8 11.7C8 9 7.7 4.2 5.5 2L2.8 4.8C2.4 5.2 2.2 5.80001 2.4 6.40001C2.7 7.40001 3.00001 9.2 3.10001 11.7C3.10001 15.5 2.40001 17.6 2.10001 18C3.20001 16.9 5.3 16.2 7.8 15.8C8 14.2 8 12.7 8 11.7Z"
|
||||
fill="currentColor"></path>
|
||||
</svg>
|
||||
</span>
|
||||
<!--end::Svg Icon-->
|
||||
</span>
|
||||
<span class="menu-title">Sub Category</span>
|
||||
</a>
|
||||
|
||||
</div>
|
||||
|
||||
{{-- Sub article --}}
|
||||
<div class="menu-item menu-accordion">
|
||||
<a class="menu-link {{ Request::is('where-else/article*') || Request::is('where-else/add-article*') ? 'active' : '' }}"
|
||||
href="{{ url('where-else/article') }}">
|
||||
<span class="menu-icon">
|
||||
<!--begin::Svg Icon | path: icons/duotune/layouts/lay008.svg-->
|
||||
<span class="svg-icon svg-icon-2">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24"
|
||||
fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M20 7H3C2.4 7 2 6.6 2 6V3C2 2.4 2.4 2 3 2H20C20.6 2 21 2.4 21 3V6C21 6.6 20.6 7 20 7ZM7 9H3C2.4 9 2 9.4 2 10V20C2 20.6 2.4 21 3 21H7C7.6 21 8 20.6 8 20V10C8 9.4 7.6 9 7 9Z"
|
||||
fill="currentColor"></path>
|
||||
<path opacity="0.3"
|
||||
d="M20 21H11C10.4 21 10 20.6 10 20V10C10 9.4 10.4 9 11 9H20C20.6 9 21 9.4 21 10V20C21 20.6 20.6 21 20 21Z"
|
||||
fill="currentColor"></path>
|
||||
</svg>
|
||||
</span>
|
||||
<!--end::Svg Icon-->
|
||||
</span>
|
||||
<span class="menu-title">Article</span>
|
||||
</a>
|
||||
|
||||
</div>
|
||||
@endif
|
||||
|
||||
{{-- Manage: File --}}
|
||||
<div class="menu-item pt-5">
|
||||
<div class="menu-content"><span class="menu-heading fw-bold text-uppercase fs-7">
|
||||
MANAGE FILE
|
||||
</span></div>
|
||||
</div>
|
||||
|
||||
{{-- Video --}}
|
||||
<div class="menu-item menu-accordion">
|
||||
<a class="menu-link {{ Request::is('video*') ? 'active' : '' }}"
|
||||
href="{{ url('video') }}">
|
||||
<span class="menu-icon">
|
||||
<!--begin::Svg Icon | path: icons/duotune/abstract/abs042.svg-->
|
||||
<span class="svg-icon svg-icon-2">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24"
|
||||
fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M18 21.6C16.6 20.4 9.1 20.3 6.3 21.2C5.7 21.4 5.1 21.2 4.7 20.8L2 18C4.2 15.8 10.8 15.1 15.8 15.8C16.2 18.3 17 20.5 18 21.6ZM18.8 2.8C18.4 2.4 17.8 2.20001 17.2 2.40001C14.4 3.30001 6.9 3.2 5.5 2C6.8 3.3 7.4 5.5 7.7 7.7C9 7.9 10.3 8 11.7 8C15.8 8 19.8 7.2 21.5 5.5L18.8 2.8Z"
|
||||
fill="currentColor"></path>
|
||||
<path opacity="0.3"
|
||||
d="M21.2 17.3C21.4 17.9 21.2 18.5 20.8 18.9L18 21.6C15.8 19.4 15.1 12.8 15.8 7.8C18.3 7.4 20.4 6.70001 21.5 5.60001C20.4 7.00001 20.2 14.5 21.2 17.3ZM8 11.7C8 9 7.7 4.2 5.5 2L2.8 4.8C2.4 5.2 2.2 5.80001 2.4 6.40001C2.7 7.40001 3.00001 9.2 3.10001 11.7C3.10001 15.5 2.40001 17.6 2.10001 18C3.20001 16.9 5.3 16.2 7.8 15.8C8 14.2 8 12.7 8 11.7Z"
|
||||
fill="currentColor"></path>
|
||||
</svg>
|
||||
</span>
|
||||
<!--end::Svg Icon-->
|
||||
</span>
|
||||
<span class="menu-title">Videos</span>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
{{-- Sound --}}
|
||||
<div class="menu-item menu-accordion">
|
||||
<a class="menu-link {{ Request::is('sound*') ? 'active' : '' }}"
|
||||
href="{{ url('sound') }}">
|
||||
<span class="menu-icon">
|
||||
<!--begin::Svg Icon | path: icons/duotune/maps/map002.svg-->
|
||||
<span class="svg-icon svg-icon-2">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24"
|
||||
fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M8.7 4.19995L4 6.30005V18.8999L8.7 16.8V19L3.1 21.5C2.6 21.7 2 21.4 2 20.8V6C2 5.4 2.3 4.89995 2.9 4.69995L8.7 2.09998V4.19995Z"
|
||||
fill="currentColor"></path>
|
||||
<path
|
||||
d="M15.3 19.8L20 17.6999V5.09992L15.3 7.19989V4.99994L20.9 2.49994C21.4 2.29994 22 2.59989 22 3.19989V17.9999C22 18.5999 21.7 19.1 21.1 19.3L15.3 21.8998V19.8Z"
|
||||
fill="currentColor"></path>
|
||||
<path opacity="0.3"
|
||||
d="M15.3 7.19995L20 5.09998V17.7L15.3 19.8V7.19995Z"
|
||||
fill="currentColor"></path>
|
||||
<path opacity="0.3"
|
||||
d="M8.70001 4.19995V2L15.4 5V7.19995L8.70001 4.19995ZM8.70001 16.8V19L15.4 22V19.8L8.70001 16.8Z"
|
||||
fill="currentColor"></path>
|
||||
<path opacity="0.3"
|
||||
d="M8.7 16.8L4 18.8999V6.30005L8.7 4.19995V16.8Z"
|
||||
fill="currentColor"></path>
|
||||
</svg>
|
||||
</span>
|
||||
<!--end::Svg Icon-->
|
||||
</span>
|
||||
<span class="menu-title">Sounds</span>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
{{-- Images --}}
|
||||
<div class="menu-item menu-accordion">
|
||||
<a class="menu-link {{ Request::is('image*') ? 'active' : '' }}"
|
||||
href="{{ url('image') }}">
|
||||
<span class="menu-icon">
|
||||
<!--begin::Svg Icon | path: icons/duotune/abstract/abs014.svg-->
|
||||
<span class="svg-icon svg-icon-2">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24"
|
||||
fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path opacity="0.3"
|
||||
d="M11.8 5.2L17.7 8.6V15.4L11.8 18.8L5.90001 15.4V8.6L11.8 5.2ZM11.8 2C11.5 2 11.2 2.1 11 2.2L3.8 6.4C3.3 6.7 3 7.3 3 7.9V16.2C3 16.8 3.3 17.4 3.8 17.7L11 21.9C11.3 22 11.5 22.1 11.8 22.1C12.1 22.1 12.4 22 12.6 21.9L19.8 17.7C20.3 17.4 20.6 16.8 20.6 16.2V7.9C20.6 7.3 20.3 6.7 19.8 6.4L12.6 2.2C12.4 2.1 12.1 2 11.8 2Z"
|
||||
fill="currentColor"></path>
|
||||
<path
|
||||
d="M11.8 8.69995L8.90001 10.3V13.7L11.8 15.3L14.7 13.7V10.3L11.8 8.69995Z"
|
||||
fill="currentColor"></path>
|
||||
</svg>
|
||||
</span>
|
||||
<!--end::Svg Icon-->
|
||||
</span>
|
||||
<span class="menu-title">Images</span>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
{{-- Documents --}}
|
||||
<div class="menu-item menu-accordion">
|
||||
<a class="menu-link {{ Request::is('document*') ? 'active' : '' }}"
|
||||
href="{{ url('document') }}">
|
||||
<span class="menu-icon">
|
||||
<!--begin::Svg Icon | path: icons/duotune/abstract/abs026.svg-->
|
||||
<span class="svg-icon svg-icon-2">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24"
|
||||
fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path opacity="0.3"
|
||||
d="M7 20.5L2 17.6V11.8L7 8.90002L12 11.8V17.6L7 20.5ZM21 20.8V18.5L19 17.3L17 18.5V20.8L19 22L21 20.8Z"
|
||||
fill="currentColor"></path>
|
||||
<path d="M22 14.1V6L15 2L8 6V14.1L15 18.2L22 14.1Z"
|
||||
fill="currentColor"></path>
|
||||
</svg>
|
||||
</span>
|
||||
<!--end::Svg Icon-->
|
||||
</span>
|
||||
<span class="menu-title">Documents</span>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
@if (Auth::user()->role == 0)
|
||||
{{-- Manage: User --}}
|
||||
<div class="menu-item pt-5">
|
||||
<div class="menu-content"><span
|
||||
class="menu-heading fw-bold text-uppercase fs-7">
|
||||
MANAGE USER
|
||||
</span></div>
|
||||
</div>
|
||||
|
||||
{{-- User --}}
|
||||
<div class="menu-item menu-accordion">
|
||||
|
||||
<a class="menu-link {{ Request::is('user*') ? 'active' : '' }}"
|
||||
href="{{ url('user') }}">
|
||||
<span class="menu-icon">
|
||||
<!--begin::Svg Icon | path: icons/duotune/communication/com005.svg-->
|
||||
<span class="svg-icon svg-icon-2">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24"
|
||||
fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M20 14H18V10H20C20.6 10 21 10.4 21 11V13C21 13.6 20.6 14 20 14ZM21 19V17C21 16.4 20.6 16 20 16H18V20H20C20.6 20 21 19.6 21 19ZM21 7V5C21 4.4 20.6 4 20 4H18V8H20C20.6 8 21 7.6 21 7Z"
|
||||
fill="currentColor"></path>
|
||||
<path opacity="0.3"
|
||||
d="M17 22H3C2.4 22 2 21.6 2 21V3C2 2.4 2.4 2 3 2H17C17.6 2 18 2.4 18 3V21C18 21.6 17.6 22 17 22ZM10 7C8.9 7 8 7.9 8 9C8 10.1 8.9 11 10 11C11.1 11 12 10.1 12 9C12 7.9 11.1 7 10 7ZM13.3 16C14 16 14.5 15.3 14.3 14.7C13.7 13.2 12 12 10.1 12C8.10001 12 6.49999 13.1 5.89999 14.7C5.59999 15.3 6.19999 16 7.39999 16H13.3Z"
|
||||
fill="currentColor"></path>
|
||||
</svg>
|
||||
</span>
|
||||
|
||||
</span>
|
||||
<span class="menu-title">User</span>
|
||||
</a>
|
||||
|
||||
</div>
|
||||
@endif
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<!--end:: Sidebar-->
|
||||
|
||||
@yield('content')
|
||||
|
||||
</div>
|
||||
<!--end:: Main Wrapper-->
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div id="kt_scrolltop" class="scrolltop" data-kt-scrolltop="true">
|
||||
<!--begin::Svg Icon | path: icons/duotune/arrows/arr066.svg-->
|
||||
<span class="svg-icon">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<rect opacity="0.5" x="13" y="6" width="13" height="2" rx="1"
|
||||
transform="rotate(90 13 6)" fill="currentColor" />
|
||||
<path
|
||||
d="M12.5657 8.56569L16.75 12.75C17.1642 13.1642 17.8358 13.1642 18.25 12.75C18.6642 12.3358 18.6642 11.6642 18.25 11.25L12.7071 5.70711C12.3166 5.31658 11.6834 5.31658 11.2929 5.70711L5.75 11.25C5.33579 11.6642 5.33579 12.3358 5.75 12.75C6.16421 13.1642 6.83579 13.1642 7.25 12.75L11.4343 8.56569C11.7467 8.25327 12.2533 8.25327 12.5657 8.56569Z"
|
||||
fill="currentColor" />
|
||||
</svg>
|
||||
</span>
|
||||
|
||||
</div>
|
||||
|
||||
<script>
|
||||
var hostUrl = "";
|
||||
let baseSite = "{{ url('') }}";
|
||||
</script>
|
||||
|
||||
<!--begin::Global Javascript Bundle(mandatory for all pages)-->
|
||||
<script src="{{ url('assets/plugins/global/plugins.bundle.js') }}"></script>
|
||||
<script src="{{ url('assets/plugins/custom/fslightbox/fslightbox.bundle.js') }}"></script>
|
||||
<script src="{{ url('assets/js/scripts.bundle.js') }}"></script>
|
||||
<!--end::Global Javascript Bundle-->
|
||||
|
||||
<!--begin::Vendors Javascript(used for this page only)-->
|
||||
<script src="{{ url('assets/plugins/custom/fullcalendar/fullcalendar.bundle.js') }}"></script>
|
||||
<script src="https://cdn.amcharts.com/lib/5/index.js"></script>
|
||||
<script src="https://cdn.amcharts.com/lib/5/xy.js"></script>
|
||||
<script src="https://cdn.amcharts.com/lib/5/percent.js"></script>
|
||||
<script src="https://cdn.amcharts.com/lib/5/radar.js"></script>
|
||||
<script src="https://cdn.amcharts.com/lib/5/themes/Animated.js"></script>
|
||||
<script src="https://cdn.amcharts.com/lib/5/map.js"></script>
|
||||
<script src="https://cdn.amcharts.com/lib/5/geodata/worldLow.js"></script>
|
||||
<script src="https://cdn.amcharts.com/lib/5/geodata/continentsLow.js"></script>
|
||||
<script src="https://cdn.amcharts.com/lib/5/geodata/usaLow.js"></script>
|
||||
<script src="https://cdn.amcharts.com/lib/5/geodata/worldTimeZonesLow.js"></script>
|
||||
<script src="https://cdn.amcharts.com/lib/5/geodata/worldTimeZoneAreasLow.js"></script>
|
||||
<script src="{{ url('assets/plugins/custom/datatables/datatables.bundle.js') }}"></script>
|
||||
<script src="{{ url('assets/plugins/custom/formrepeater/formrepeater.bundle.js') }}"></script>
|
||||
<!--end::Vendors Javascript-->
|
||||
<!--begin::Custom Javascript(used for this page only)-->
|
||||
<script src="{{ url('assets/js/widgets.bundle.js') }}"></script>
|
||||
<script src="{{ url('assets/js/custom/widgets.js') }}"></script>
|
||||
<script src="{{ url('assets/js/custom/apps/chat/chat.js') }}"></script>
|
||||
<script src="{{ url('assets/js/custom/utilities/modals/upgrade-plan.js') }}"></script>
|
||||
<script src="{{ url('assets/js/custom/utilities/modals/create-app.js') }}"></script>
|
||||
<script src="{{ url('assets/js/custom/utilities/modals/new-target.js') }}"></script>
|
||||
<script src="{{ url('assets/js/custom/utilities/modals/users-search.js') }}"></script>
|
||||
<script src="{{ url('assets/js/custom/apps/ecommerce/catalog/save-category.js') }}"></script>
|
||||
<script src="{{ url('assets/js/custom/utilities/modals/upgrade-plan.js') }}"></script>
|
||||
<script src="{{ url('assets/js/custom/utilities/modals/create-app.js') }}"></script>
|
||||
<script src="{{ url('assets/js/custom/utilities/modals/users-search.js') }}"></script>
|
||||
<!--end::Custom Javascript-->
|
||||
|
||||
<script src="{{ url('assets/js/utils.js') }}"></script>
|
||||
<!--end::Javascript-->
|
||||
|
||||
|
||||
{{-- Custom --}}
|
||||
{{-- <script type="text/javascript" src="{{ url('assets/plugins/ckeditor4162/ckeditor.js') }}"></script>
|
||||
<script type="text/javascript" src="{{ url('assets/plugins/ckeditor4162/styles.js') }}"></script>
|
||||
--}}
|
||||
|
||||
<script src="https://cdn.ckeditor.com/ckeditor5/39.0.2/super-build/ckeditor.js"></script>
|
||||
|
||||
<script src="{{ url('assets/plugins/custom/magnific/magnific-popup.js') }}"></script>
|
||||
|
||||
{{-- fileuploader --}}
|
||||
<script src="{{ url('assets/plugins/fileuploader-2.2/dist/jquery.fileuploader.min.js') }}" type="text/javascript">
|
||||
</script>
|
||||
|
||||
<script>
|
||||
$('.show-image-preview').magnificPopup({
|
||||
type: 'image'
|
||||
// other options
|
||||
});
|
||||
</script>
|
||||
|
||||
@yield('script')
|
||||
|
||||
</body>
|
||||
<!--end::Body-->
|
||||
|
||||
</html>
|
||||
@@ -0,0 +1,101 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<!--begin::Head-->
|
||||
|
||||
<head>
|
||||
<base href="{{ url('') }}" />
|
||||
<title>The Greater Chiangmai</title>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="description" content="" />
|
||||
<meta name="keywords" content="" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
|
||||
<meta property="og:locale" content="en_US" />
|
||||
<meta property="og:type" content="article" />
|
||||
<meta property="og:title" content="" />
|
||||
<meta property="og:url" content="" />
|
||||
<meta property="og:site_name" content="" />
|
||||
|
||||
<link rel="canonical" href="" />
|
||||
<link rel="shortcut icon" href="{{ url('assets/media/logos/favicon.ico') }}" />
|
||||
|
||||
<!--begin::Fonts(mandatory for all pages)-->
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Inter:300,400,500,600,700" />
|
||||
|
||||
<!--end::Fonts-->
|
||||
<!--begin::Global Stylesheets Bundle(mandatory for all pages)-->
|
||||
|
||||
<link href="{{ url('assets/plugins/global/plugins.bundle.css') }}" rel="stylesheet" type="text/css" />
|
||||
<link href="{{ url('assets/css/style.bundle.css') }}" rel="stylesheet" type="text/css" />
|
||||
|
||||
<!--end::Global Stylesheets Bundle-->
|
||||
</head>
|
||||
<!--end::Head-->
|
||||
<!--begin::Body-->
|
||||
|
||||
<body id="kt_body" class="app-blank bgi-size-cover bgi-position-center bgi-no-repeat">
|
||||
<!--begin::Theme mode setup on page load-->
|
||||
<script>
|
||||
var defaultThemeMode = "light";
|
||||
var themeMode;
|
||||
if (document.documentElement) {
|
||||
if (document.documentElement.hasAttribute("data-bs-theme-mode")) {
|
||||
themeMode = document.documentElement.getAttribute("data-bs-theme-mode");
|
||||
} else {
|
||||
if (localStorage.getItem("data-bs-theme") !== null) {
|
||||
themeMode = localStorage.getItem("data-bs-theme");
|
||||
} else {
|
||||
themeMode = defaultThemeMode;
|
||||
}
|
||||
}
|
||||
if (themeMode === "system") {
|
||||
themeMode = window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
|
||||
}
|
||||
document.documentElement.setAttribute("data-bs-theme", themeMode);
|
||||
}
|
||||
</script>
|
||||
<!--end::Theme mode setup on page load-->
|
||||
<!--begin::Root-->
|
||||
<div class="d-flex flex-column flex-root" id="kt_app_root">
|
||||
<!--begin::Page bg image-->
|
||||
<style>
|
||||
body {
|
||||
background-image: url('{{ url('assets/media/auth/bg7.jpg') }}');
|
||||
}
|
||||
|
||||
[data-bs-theme="dark"] body {
|
||||
background-image: url('{{ url('assets/media/auth/bg7-dark.jpg') }}');
|
||||
}
|
||||
</style>
|
||||
<!--end::Page bg image-->
|
||||
<!--begin::Authentication - Signup Welcome Message -->
|
||||
<div class="d-flex flex-column flex-center flex-column-fluid">
|
||||
<!--begin::Content-->
|
||||
@yield('main')
|
||||
<!--end::Content-->
|
||||
</div>
|
||||
<!--end::Authentication - Signup Welcome Message-->
|
||||
</div>
|
||||
<!--end::Root-->
|
||||
<!--begin::Javascript-->
|
||||
<script>
|
||||
var hostUrl = "{{ url('assets') }}";
|
||||
var baseUrl = "{{ url('') }}"
|
||||
</script>
|
||||
<!--begin::Global Javascript Bundle(mandatory for all pages)-->
|
||||
<script src="{{ url('assets/plugins/global/plugins.bundle.js') }}"></script>
|
||||
<script src="{{ url('assets/js/scripts.bundle.js') }}"></script>
|
||||
<!--end::Global Javascript Bundle-->
|
||||
<!--begin::Custom Javascript(used for this page only)-->
|
||||
<script src="{{ url('assets/js/custom/authentication/sign-in/general.js') }}"></script>
|
||||
<script src="{{ url('assets/js/custom/authentication/sign-in/i18n.js') }}"></script>
|
||||
<!--end::Custom Javascript-->
|
||||
<!--end::Javascript-->
|
||||
|
||||
|
||||
@yield('script')
|
||||
|
||||
</body>
|
||||
<!--end::Body-->
|
||||
|
||||
</html>
|
||||
@@ -0,0 +1,129 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<!--begin::Head-->
|
||||
|
||||
<head>
|
||||
|
||||
<title>The Greater Chiangmai</title>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="description" content="The Greater Chiangmai" />
|
||||
<meta name="keywords" content="The Greater Chiangmai" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<meta property="og:locale" content="en_US" />
|
||||
<meta property="og:type" content="article" />
|
||||
<meta property="og:title" content="The Greater Chiangmai" />
|
||||
<meta property="og:url" content="{{ url('') }}" />
|
||||
<meta property="og:site_name" content="" />
|
||||
<link rel="canonical" href="{{ url('') }}" />
|
||||
<link rel="shortcut icon" href="{{ url('assets/media/logos/favicon.ico') }}" />
|
||||
|
||||
<meta name="csrf-token" content="{{ csrf_token() }}">
|
||||
|
||||
<!--begin::Fonts(mandatory for all pages)-->
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Inter:300,400,500,600,700" />
|
||||
<!--end::Fonts-->
|
||||
|
||||
<!--begin::Global Stylesheets Bundle(mandatory for all pages)-->
|
||||
<link href="{{ url('assets/plugins/global/plugins.bundle.css') }}" rel="stylesheet" type="text/css" />
|
||||
<link href="{{ url('assets/css/style.bundle.css') }}" rel="stylesheet" type="text/css" />
|
||||
|
||||
<!--end::Global Stylesheets Bundle-->
|
||||
|
||||
</head>
|
||||
<!--end::Head-->
|
||||
<!--begin::Body-->
|
||||
|
||||
<body id="kt_body" class="app-blank">
|
||||
<!--begin::Theme mode setup on page load-->
|
||||
<script>
|
||||
var defaultThemeMode = "light";
|
||||
var themeMode;
|
||||
if (document.documentElement) {
|
||||
if (document.documentElement.hasAttribute("data-bs-theme-mode")) {
|
||||
themeMode = document.documentElement.getAttribute("data-bs-theme-mode");
|
||||
} else {
|
||||
if (localStorage.getItem("data-bs-theme") !== null) {
|
||||
themeMode = localStorage.getItem("data-bs-theme");
|
||||
} else {
|
||||
themeMode = defaultThemeMode;
|
||||
}
|
||||
}
|
||||
if (themeMode === "system") {
|
||||
themeMode = window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
|
||||
}
|
||||
document.documentElement.setAttribute("data-bs-theme", themeMode);
|
||||
}
|
||||
</script>
|
||||
<!--end::Theme mode setup on page load-->
|
||||
<!--begin::Root-->
|
||||
<div class="d-flex flex-column flex-root" id="kt_app_root" style="background-color: #1c1c1c;">
|
||||
<!--begin::Page bg image-->
|
||||
<style>
|
||||
</style>
|
||||
<!--end::Page bg image-->
|
||||
<!--begin::Authentication - Sign-in -->
|
||||
<div class="d-flex flex-column flex-lg-row flex-column-fluid">
|
||||
<!--begin::Logo-->
|
||||
|
||||
|
||||
<!--begin::Body-->
|
||||
<div class="d-none d-lg-flex flex-lg-row-fluid w-50 bgi-size-cover bgi-position-x-start bgi-no-repeat"
|
||||
style="background-image: url({{ url('assets/media/bg.jpg') }});"></div>
|
||||
<!--begin::Body-->
|
||||
|
||||
|
||||
<!--end::Logo-->
|
||||
<!--begin::Aside-->
|
||||
<div class="d-flex flex-column flex-column-fluid flex-center w-lg-50 p-10">
|
||||
<!--begin::Wrapper-->
|
||||
<div class="d-flex justify-content-between flex-column-fluid flex-column w-100 mw-450px">
|
||||
<!--begin::Header-->
|
||||
<div class="d-flex flex-stack py-2">
|
||||
<!--begin::Back link-->
|
||||
<div class="me-2"></div>
|
||||
<!--end::Back link-->
|
||||
|
||||
</div>
|
||||
<!--end::Header-->
|
||||
<!--begin::Body-->
|
||||
|
||||
@yield('content')
|
||||
<!--end::Body-->
|
||||
<!--begin::Footer-->
|
||||
<div class="m-0">
|
||||
|
||||
</div>
|
||||
<!--end::Footer-->
|
||||
</div>
|
||||
<!--end::Wrapper-->
|
||||
</div>
|
||||
<!--end::Aside-->
|
||||
|
||||
</div>
|
||||
<!--end::Authentication - Sign-in-->
|
||||
</div>
|
||||
<!--end::Root-->
|
||||
|
||||
<script>
|
||||
var baseUrl = "{{ url('') }}";
|
||||
</script>
|
||||
|
||||
<script src="{{ url('assets/plugins/global/plugins.bundle.js') }}"></script>
|
||||
<script src="{{ url('assets/js/scripts.bundle.js') }}"></script>
|
||||
<!--end::Global Javascript Bundle-->
|
||||
<!--begin::Custom Javascript(used for this page only)-->
|
||||
<script src="{{ url('assets/js/custom/authentication/sign-in/general.js') }}"></script>
|
||||
<script src="{{ url('assets/js/custom/authentication/sign-in/i18n.js') }}"></script>
|
||||
<!--end::Custom Javascript-->
|
||||
<!--end::Javascript-->
|
||||
|
||||
|
||||
{{-- custom --}}
|
||||
<script src="{{ url('assets/js/utils.js') }}"></script>
|
||||
|
||||
@yield('script')
|
||||
|
||||
</body>
|
||||
<!--end::Body-->
|
||||
|
||||
</html>
|
||||
@@ -0,0 +1,43 @@
|
||||
<div id="kt_app_toolbar" class="app-toolbar py-3 py-lg-6">
|
||||
|
||||
<div id="kt_app_toolbar_container" class="app-container container-xxl d-flex flex-stack">
|
||||
|
||||
<div class="page-title d-flex flex-column justify-content-center flex-wrap me-3">
|
||||
|
||||
<h1 class="page-heading d-flex text-dark fw-bold fs-3 flex-column justify-content-center my-3">
|
||||
{{ $title }}
|
||||
</h1>
|
||||
|
||||
<ul class="breadcrumb breadcrumb-separatorless fw-semibold fs-7 my-0 pt-1">
|
||||
|
||||
<li class="breadcrumb-item text-muted">
|
||||
<a href="{{ url('') }}" class="text-muted text-hover-primary">
|
||||
Dashboard
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="breadcrumb-item">
|
||||
<span class="bullet bg-gray-400 w-5px h-2px"></span>
|
||||
</li>
|
||||
|
||||
<li class="breadcrumb-item text-muted">
|
||||
<a href="{{ $pageParentLink ?? url('') }}" class="text-muted text-hover-primary">
|
||||
{{ $pageParent }}
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="breadcrumb-item">
|
||||
<span class="bullet bg-gray-400 w-5px h-2px"></span>
|
||||
</li>
|
||||
|
||||
<li class="breadcrumb-item text-muted">
|
||||
{{ $pageName }}
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@@ -0,0 +1,30 @@
|
||||
|
||||
<div id="kt_app_toolbar" class="app-toolbar py-3 py-lg-6">
|
||||
|
||||
<div id="kt_app_toolbar_container" class="app-container container-xxl d-flex flex-stack">
|
||||
|
||||
<div class="page-title d-flex flex-column justify-content-center flex-wrap me-3">
|
||||
|
||||
<h1 class="page-heading d-flex text-dark fw-bold fs-3 flex-column justify-content-center my-3">
|
||||
{{ $title }}
|
||||
</h1>
|
||||
|
||||
<ul class="breadcrumb breadcrumb-separatorless fw-semibold fs-7 my-0 pt-1">
|
||||
|
||||
<li class="breadcrumb-item text-muted">
|
||||
<a href="{{ url('') }}" class="text-muted text-hover-primary">Dashboard</a>
|
||||
</li>
|
||||
|
||||
<li class="breadcrumb-item">
|
||||
<span class="bullet bg-gray-400 w-5px h-2px"></span>
|
||||
</li>
|
||||
|
||||
<li class="breadcrumb-item text-muted">{{ $pageName }}</li>
|
||||
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@@ -0,0 +1,32 @@
|
||||
<!--dynamic table-->
|
||||
<script type="text/javascript">
|
||||
const btnDTable = [];
|
||||
|
||||
const langDTable = {
|
||||
"lengthMenu": "แสดง _MENU_ หน้า"
|
||||
, "zeroRecords": "ไม่มีข้อมูล"
|
||||
, "info": "หน้า _PAGE_ จาก _PAGES_"
|
||||
, "infoEmpty": "ไม่มีข้อมูล"
|
||||
, "infoFiltered": "(filtered from _MAX_ total records)"
|
||||
};
|
||||
|
||||
$("#dynamic-table-1").dataTable({
|
||||
language: langDTable
|
||||
, order: [
|
||||
[0, "desc"]
|
||||
]
|
||||
, aoColumnDefs: [{
|
||||
'bSortable': true
|
||||
, 'aTargets': [0] /* 1st one, start by the right */
|
||||
}]
|
||||
, pageLength: 100
|
||||
, dom: 'Blfrtip'
|
||||
, lengthMenu: [
|
||||
[10, 25, 50, 100, 500]
|
||||
, [10, 25, 50, 100, 500]
|
||||
]
|
||||
, buttons: btnDTable
|
||||
, responsive: !0
|
||||
});
|
||||
|
||||
</script>
|
||||
@@ -0,0 +1,40 @@
|
||||
<!--dynamic table-->
|
||||
<link href="{{ url('assets-backend/js/advanced-datatable/css/demo_page.css') }}" rel="stylesheet" />
|
||||
<link href="{{ url('assets-backend/js/advanced-datatable/css/demo_table.css') }}" rel="stylesheet" />
|
||||
<link href="{{ url('assets-backend/js/data-tables/DT_bootstrap.css') }}" rel="stylesheet" />
|
||||
|
||||
|
||||
<style>
|
||||
div.dataTables_wrapper div.dataTables_filter label {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.buttons-excel {
|
||||
background-color: #1fb5ad;
|
||||
border-color: #1fb5ad;
|
||||
color: #FFFFFF;
|
||||
margin-right: 10px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.buttons-pdf {
|
||||
background-color: #fa8564;
|
||||
border-color: #fa8564;
|
||||
color: #FFFFFF;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.adv-table .dataTables_filter label input {
|
||||
border: solid 1px #e3e3e4;
|
||||
}
|
||||
|
||||
tr.odd td.sorting_1 {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.dataTables_wrapper .dataTables_paginate .paginate_button {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
<div class="alert alert-block alert-danger fade in">
|
||||
<button data-dismiss="alert" class="close close-sm" type="button">
|
||||
<i class="fa fa-times"></i>
|
||||
</button>
|
||||
<strong>Oh snap!</strong> {{ Session::get('messageDetail') }}
|
||||
</div>
|
||||
@@ -0,0 +1,6 @@
|
||||
<div class="alert alert-success fade in">
|
||||
<button data-dismiss="alert" class="close close-sm" type="button">
|
||||
<i class="fa fa-times"></i>
|
||||
</button>
|
||||
<strong>Well done!</strong> {{ Session::get('messageDetail') }}
|
||||
</div>
|
||||
@@ -0,0 +1 @@
|
||||
<a href="{{ url('backend/dashboard') }}">Dashboard</a>
|
||||
@@ -0,0 +1,71 @@
|
||||
<section class="wow fadeIn p-0 main-slider mobile-height top-space">
|
||||
<div class="swiper-full-screen swiper-container-fluid w-100 white-move homepage-slider">
|
||||
<div class="swiper-wrapper">
|
||||
|
||||
<!-- start slider item -->
|
||||
@foreach($bannerView['banner'] as $item)
|
||||
|
||||
@if(!empty($bannerView['banner_images'][$item->banner_id]->file_name))
|
||||
<div class="swiper-slide cover-background"
|
||||
style="background-image:url('{{ url($bannerView['banner_images'][$item->banner_id]->file_path."/".$bannerView['banner_images'][$item->banner_id]->file_name.".".$bannerView['banner_images'][$item->banner_id]->extension) }}');"
|
||||
>
|
||||
<div class="container-fluid position-relative one-fourth-screen sm-height-200px">
|
||||
<div class="slider-typography text-center">
|
||||
<div class="slider-text-middle-main">
|
||||
<div class="slider-text-middle">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@else
|
||||
<div class="swiper-slide cover-background"
|
||||
style="background-image:url('{{ url('tvo-images/19562755765ffbceae6cd991610337966.jpg') }}');"
|
||||
>
|
||||
<div class="container-fluid position-relative one-fourth-screen sm-height-200px">
|
||||
<div class="slider-typography text-center">
|
||||
<div class="slider-text-middle-main">
|
||||
<div class="slider-text-middle">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@endforeach
|
||||
<!-- end slider item -->
|
||||
|
||||
</div>
|
||||
|
||||
<!-- Add Pagination -->
|
||||
<div class="swiper-pagination swiper-pagination-white swiper-full-screen-pagination"></div>
|
||||
<div class="swiper-button-next swiper-button-black-highlight d-none"></div>
|
||||
<div class="swiper-button-prev swiper-button-black-highlight d-none"></div>
|
||||
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{{--<div class="tp-banner-container">--}}
|
||||
{{-- <div class="tp-banner">--}}
|
||||
{{-- <ul>--}}
|
||||
{{-- @foreach($bannerView['banner'] as $item)--}}
|
||||
{{-- <!-- SLIDE i -->--}}
|
||||
{{-- <li data-transition="zoomout" data-slotamount="7" data-masterspeed="1500" >--}}
|
||||
{{-- @if(!empty($bannerView['banner_images'][$item->banner_id]->file_name))--}}
|
||||
{{-- <img src="{{ url($bannerView['banner_images'][$item->banner_id]->file_path."/".$bannerView['banner_images'][$item->banner_id]->file_name.".".$bannerView['banner_images'][$item->banner_id]->extension) }}"--}}
|
||||
{{-- alt=""--}}
|
||||
{{-- data-bgposition="center center"--}}
|
||||
{{-- data-kenburns="on"--}}
|
||||
{{-- data-duration="25000"--}}
|
||||
{{-- data-ease="Linear.easeNone" data-bgfit="100" data-bgfitend="120" data-bgpositionend="center top">--}}
|
||||
{{-- @else--}}
|
||||
{{-- <img src="{{ url('img/no_image.jpg') }}" class="img-thumbnail img-responsive" alt="">--}}
|
||||
{{-- @endif--}}
|
||||
{{-- </li>--}}
|
||||
{{-- <!-- END SLIDE -->--}}
|
||||
{{-- @endforeach--}}
|
||||
{{-- </ul>--}}
|
||||
{{-- <div class="tp-bannertimer"></div>--}}
|
||||
{{-- </div>--}}
|
||||
{{--</div>--}}
|
||||
@@ -0,0 +1,42 @@
|
||||
|
||||
<div id="kt_app_toolbar" class="app-toolbar py-3 py-lg-6">
|
||||
|
||||
<div id="kt_app_toolbar_container" class="app-container container-xxl d-flex flex-stack">
|
||||
|
||||
<div class="page-title d-flex flex-column justify-content-center flex-wrap me-3">
|
||||
|
||||
<h1 class="page-heading d-flex text-dark fw-bold fs-3 flex-column justify-content-center my-3">
|
||||
{{ $title }}
|
||||
</h1>
|
||||
|
||||
<ul class="breadcrumb breadcrumb-separatorless fw-semibold fs-7 my-0 pt-1">
|
||||
|
||||
<li class="breadcrumb-item text-muted">
|
||||
<a href="{{ url('') }}" class="text-muted text-hover-primary">
|
||||
Dashboard
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="breadcrumb-item">
|
||||
<span class="bullet bg-gray-400 w-5px h-2px"></span>
|
||||
</li>
|
||||
|
||||
<li class="breadcrumb-item text-muted">
|
||||
{{ $pageParent }}
|
||||
</li>
|
||||
|
||||
<li class="breadcrumb-item">
|
||||
<span class="bullet bg-gray-400 w-5px h-2px"></span>
|
||||
</li>
|
||||
|
||||
<li class="breadcrumb-item text-muted">
|
||||
{{ $pageName }}
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@@ -0,0 +1,20 @@
|
||||
<section
|
||||
class="wow fadeIn bg-light-gray padding-35px-tb page-title-small {{ Request::is('login') || Request::is('register') || Request::is('private-message') ? 'top-space' : '' }}">
|
||||
<div class="container">
|
||||
<div class="row align-items-center">
|
||||
<div class="col-lg-8 col-md-6 breadcrumb text-center text-md-left">
|
||||
<ul>
|
||||
<li><a href="{{ url('') }}" class="text-dark-gray">{{ trans('global.menu_home') }}</a></li>
|
||||
<li class="text-dark-gray">
|
||||
{{ $title }}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="col-lg-4 col-md-6 justify-content-center justify-content-md-end sm-margin-10px-top">
|
||||
<h1 class="text-extra-dark-gray font-weight-600 mb-0 text-uppercase text-md-right">
|
||||
{{ $title }}
|
||||
</h1>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
@@ -0,0 +1,30 @@
|
||||
|
||||
<div id="kt_app_toolbar" class="app-toolbar py-3 py-lg-6">
|
||||
|
||||
<div id="kt_app_toolbar_container" class="app-container container-xxl d-flex flex-stack">
|
||||
|
||||
<div class="page-title d-flex flex-column justify-content-center flex-wrap me-3">
|
||||
|
||||
<h1 class="page-heading d-flex text-dark fw-bold fs-3 flex-column justify-content-center my-3">
|
||||
{{ $title }}
|
||||
</h1>
|
||||
|
||||
<ul class="breadcrumb breadcrumb-separatorless fw-semibold fs-7 my-0 pt-1">
|
||||
|
||||
<li class="breadcrumb-item text-muted">
|
||||
<a href="{{ url('') }}" class="text-muted text-hover-primary">Home</a>
|
||||
</li>
|
||||
|
||||
<li class="breadcrumb-item">
|
||||
<span class="bullet bg-gray-400 w-5px h-2px"></span>
|
||||
</li>
|
||||
|
||||
<li class="breadcrumb-item text-muted">{{ $pageName }}</li>
|
||||
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@@ -0,0 +1,27 @@
|
||||
<section class="title-section">
|
||||
<div class="container">
|
||||
|
||||
<div class="row crumbs">
|
||||
<div class="col-md-12">
|
||||
<a href="{{ url('') }}">{{ trans('global.menu_home') }}</a> / {{ $title }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row title">
|
||||
<!-- Title -->
|
||||
<div class="col-md-12">
|
||||
<h1>
|
||||
{{ $title }}
|
||||
<span class="subtitle-section">
|
||||
{{ $desc }}
|
||||
<span class="left"></span>
|
||||
<span class="right"></span>
|
||||
</span>
|
||||
<span class="line-title"></span>
|
||||
</h1>
|
||||
</div>
|
||||
<!-- End Title-->
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</section>
|
||||
@@ -0,0 +1,10 @@
|
||||
@if ($errors->any())
|
||||
<div class="alert alert-danger">
|
||||
<p>Notice</p>
|
||||
<ul>
|
||||
@foreach ($errors->all() as $error)
|
||||
<li>{{ $error }}</li>
|
||||
@endforeach
|
||||
</ul>
|
||||
</div>
|
||||
@endif
|
||||
@@ -0,0 +1,134 @@
|
||||
<!--begin::Header-->
|
||||
<div id="kt_app_header" class="app-header">
|
||||
<!--begin::Header container-->
|
||||
<div class="app-container container-fluid d-flex align-items-stretch justify-content-between"
|
||||
id="kt_app_header_container">
|
||||
|
||||
<!--begin::Sidebar mobile toggle-->
|
||||
<div class="d-flex align-items-center d-lg-none ms-n3 me-1 me-md-2" title="Show sidebar menu">
|
||||
<div class="btn btn-icon btn-active-color-primary w-35px h-35px" id="kt_app_sidebar_mobile_toggle">
|
||||
<!--begin::Svg Icon | path: icons/duotune/abstract/abs015.svg-->
|
||||
<span class="svg-icon svg-icon-2 svg-icon-md-1">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M21 7H3C2.4 7 2 6.6 2 6V4C2 3.4 2.4 3 3 3H21C21.6 3 22 3.4 22 4V6C22 6.6 21.6 7 21 7Z"
|
||||
fill="currentColor" />
|
||||
<path opacity="0.3"
|
||||
d="M21 14H3C2.4 14 2 13.6 2 13V11C2 10.4 2.4 10 3 10H21C21.6 10 22 10.4 22 11V13C22 13.6 21.6 14 21 14ZM22 20V18C22 17.4 21.6 17 21 17H3C2.4 17 2 17.4 2 18V20C2 20.6 2.4 21 3 21H21C21.6 21 22 20.6 22 20Z"
|
||||
fill="currentColor" />
|
||||
</svg>
|
||||
</span>
|
||||
<!--end::Svg Icon-->
|
||||
</div>
|
||||
</div>
|
||||
<!--end::Sidebar mobile toggle-->
|
||||
|
||||
<!--begin::Mobile logo-->
|
||||
<div class="d-flex align-items-center flex-grow-1 flex-lg-grow-0">
|
||||
<a href="{{ url('') }}" class="d-lg-none">
|
||||
The Greater Chiangmai
|
||||
{{-- <img alt="The Greater Chiangmai" src="{{ url('assets/media/logo.png') }}" class="h-30px" /> --}}
|
||||
</a>
|
||||
</div>
|
||||
<!--end::Mobile logo-->
|
||||
|
||||
<!--begin::Header wrapper-->
|
||||
<div class="d-flex align-items-stretch justify-content-between flex-lg-grow-1" id="kt_app_header_wrapper">
|
||||
<!--begin::Menu wrapper-->
|
||||
<div class="app-header-menu app-header-mobile-drawer align-items-stretch" data-kt-drawer="true"
|
||||
data-kt-drawer-name="app-header-menu" data-kt-drawer-activate="{default: true, lg: false}"
|
||||
data-kt-drawer-overlay="true" data-kt-drawer-width="250px" data-kt-drawer-direction="end"
|
||||
data-kt-drawer-toggle="#kt_app_header_menu_toggle" data-kt-swapper="true"
|
||||
data-kt-swapper-mode="{default: 'append', lg: 'prepend'}"
|
||||
data-kt-swapper-parent="{default: '#kt_app_body', lg: '#kt_app_header_wrapper'}">
|
||||
<!--begin::Menu-->
|
||||
<div class="menu menu-rounded menu-column menu-lg-row my-5 my-lg-0 align-items-stretch fw-semibold px-2 px-lg-0"
|
||||
id="kt_app_header_menu" data-kt-menu="true">
|
||||
</div>
|
||||
<!--end::Menu-->
|
||||
</div>
|
||||
<!--end::Menu wrapper-->
|
||||
|
||||
<!--begin::Navbar-->
|
||||
<div class="app-navbar flex-shrink-0">
|
||||
|
||||
|
||||
<!--begin::User menu-->
|
||||
<div class="app-navbar-item ms-1 ms-md-3" id="kt_header_user_menu_toggle">
|
||||
<!--begin::Menu wrapper-->
|
||||
<div class="cursor-pointer symbol symbol-30px symbol-md-40px"
|
||||
data-kt-menu-trigger="{default: 'click', lg: 'hover'}" data-kt-menu-attach="parent"
|
||||
data-kt-menu-placement="bottom-end">
|
||||
|
||||
@if (Auth::user()->image_url && Auth::user()->image_name)
|
||||
<img src="{{ Auth::user()->image_url . '/thumbnail/' . Auth::user()->image_name }}"
|
||||
alt="The Greater Chiangmai" />
|
||||
@else
|
||||
<img src="{{ url('assets/media/avatars/blank.png') }}" alt="The Greater Chiangmai" />
|
||||
@endif
|
||||
|
||||
|
||||
</div>
|
||||
<!--begin::User account menu-->
|
||||
<div class="menu menu-sub menu-sub-dropdown menu-column menu-rounded menu-gray-800 menu-state-bg menu-state-color fw-semibold py-4 fs-6 w-275px"
|
||||
data-kt-menu="true">
|
||||
<!--begin::Menu item-->
|
||||
<div class="menu-item px-3">
|
||||
<div class="menu-content d-flex align-items-center px-3">
|
||||
<!--begin::Avatar-->
|
||||
<div class="symbol symbol-50px me-5">
|
||||
@if (Auth::user()->image_url && Auth::user()->image_name)
|
||||
<img src="{{ Auth::user()->image_url . '/thumbnail/' . Auth::user()->image_name }}"
|
||||
alt="The Greater Chiangmai" />
|
||||
@else
|
||||
<img src="{{ url('assets/media/avatars/blank.png') }}"
|
||||
alt="The Greater Chiangmai" />
|
||||
@endif
|
||||
</div>
|
||||
<!--end::Avatar-->
|
||||
<!--begin::Username-->
|
||||
<div class="d-flex flex-column">
|
||||
<div class="fw-bold d-flex align-items-center fs-5">
|
||||
{{ Auth::user()->first_name }}
|
||||
</div>
|
||||
<a href="#" class="fw-semibold text-muted text-hover-primary fs-7">
|
||||
{{ Auth::user()->email }}
|
||||
</a>
|
||||
|
||||
</div>
|
||||
<!--end::Username-->
|
||||
</div>
|
||||
</div>
|
||||
<!--end::Menu item-->
|
||||
<!--begin::Menu separator-->
|
||||
<div class="separator my-2"></div>
|
||||
<!--end::Menu separator-->
|
||||
<!--begin::Menu item-->
|
||||
<div class="menu-item px-5">
|
||||
<a href="{{ url('user/edit/' . Auth::user()->id) }}" class="menu-link px-5">My
|
||||
Profile</a>
|
||||
</div>
|
||||
<!--end::Menu item-->
|
||||
|
||||
<!--begin::Menu item-->
|
||||
<div class="menu-item px-5">
|
||||
<a href="{{ url('logout') }}" class="menu-link px-5">Sign Out</a>
|
||||
</div>
|
||||
<!--end::Menu item-->
|
||||
</div>
|
||||
<!--end::User account menu-->
|
||||
<!--end::Menu wrapper-->
|
||||
</div>
|
||||
<!--end::User menu-->
|
||||
|
||||
</div>
|
||||
<!--end::Navbar-->
|
||||
|
||||
</div>
|
||||
<!--end::Header wrapper-->
|
||||
|
||||
</div>
|
||||
<!--end::Header container-->
|
||||
</div>
|
||||
<!--end::Header-->
|
||||
@@ -0,0 +1,23 @@
|
||||
<br />
|
||||
|
||||
<div class="notice d-flex bg-light-danger rounded border-danger border border-dashed mb-9 p-6">
|
||||
<span class="svg-icon svg-icon-2tx svg-icon-danger me-4">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect opacity="0.3" x="2" y="2" width="20" height="20" rx="10"
|
||||
fill="currentColor" />
|
||||
<rect x="11" y="14" width="7" height="2" rx="1"
|
||||
transform="rotate(-90 11 14)" fill="currentColor" />
|
||||
<rect x="11" y="17" width="2" height="2" rx="1"
|
||||
transform="rotate(-90 11 17)" fill="currentColor" />
|
||||
</svg>
|
||||
</span>
|
||||
<div class="d-flex flex-stack flex-grow-1">
|
||||
<div class="fw-semibold">
|
||||
<h4 class="text-gray-900 fw-bold">Warning</h4>
|
||||
<div class="fs-6 text-gray-700">
|
||||
{{ Session::get('messageDetail') }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<br />
|
||||
@@ -0,0 +1,24 @@
|
||||
<br />
|
||||
|
||||
<div class="notice d-flex bg-light-success rounded border-success border border-dashed min-w-lg-600px flex-shrink-0 p-6">
|
||||
<span class="svg-icon svg-icon-2tx svg-icon-success me-4">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path opacity="0.3"
|
||||
d="M19.0687 17.9688H11.0687C10.4687 17.9688 10.0687 18.3687 10.0687 18.9688V19.9688C10.0687 20.5687 10.4687 20.9688 11.0687 20.9688H19.0687C19.6687 20.9688 20.0687 20.5687 20.0687 19.9688V18.9688C20.0687 18.3687 19.6687 17.9688 19.0687 17.9688Z"
|
||||
fill="currentColor" />
|
||||
<path
|
||||
d="M4.06875 17.9688C3.86875 17.9688 3.66874 17.8688 3.46874 17.7688C2.96874 17.4688 2.86875 16.8688 3.16875 16.3688L6.76874 10.9688L3.16875 5.56876C2.86875 5.06876 2.96874 4.46873 3.46874 4.16873C3.96874 3.86873 4.56875 3.96878 4.86875 4.46878L8.86875 10.4688C9.06875 10.7688 9.06875 11.2688 8.86875 11.5688L4.86875 17.5688C4.66875 17.7688 4.36875 17.9688 4.06875 17.9688Z"
|
||||
fill="currentColor" />
|
||||
</svg>
|
||||
</span>
|
||||
<div class="d-flex flex-stack flex-grow-1">
|
||||
<div class="fw-semibold">
|
||||
<h4 class="text-gray-900 fw-bold">Success</h4>
|
||||
<div class="fs-6 text-gray-700">
|
||||
{{ Session::get('messageDetail') }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<br />
|
||||
@@ -0,0 +1,39 @@
|
||||
<style type="text/css">
|
||||
.pagination li {
|
||||
float: left;
|
||||
margin: 0 1px;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 3px;
|
||||
-webkit-border-radius: 3px;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
.pagination li.disabled a {
|
||||
color: #c7c7c7;
|
||||
}
|
||||
|
||||
.pagination li a {
|
||||
color: #797979;
|
||||
padding: 5px 10px;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.pagination li:hover a, .pagination li.active a {
|
||||
color: #797979;
|
||||
background: #eee;
|
||||
border-radius: 3px;
|
||||
-webkit-border-radius: 3px;
|
||||
}
|
||||
|
||||
.dataTable tr:last-child {
|
||||
border-bottom: 1px solid #ddd;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
|
||||
<div class="shop_toolbar t_bottom">
|
||||
<div class="pagination">
|
||||
{!! str_replace('/?', '?', $data->render()) !!}
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,33 @@
|
||||
<style type="text/css">
|
||||
|
||||
.pagination > .active > a, .pagination > .active > span, .pagination > .active > a:hover, .pagination > .active > span:hover, .pagination > .active > a:focus, .pagination > .active > span:focus {
|
||||
background-color: #093979 !important;
|
||||
color: #ffffff !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-12 col-lg-3">
|
||||
</div>
|
||||
<div class="col-12 col-lg-6">
|
||||
|
||||
{!! str_replace('/?', '?', $data->render()) !!}
|
||||
{{-- --}}
|
||||
{{-- <div class="text-center margin-50px-top wow fadeInUp">--}}
|
||||
{{-- <div class="pagination text-small text-uppercase text-extra-dark-gray">--}}
|
||||
{{-- <ul class="mx-auto">--}}
|
||||
{{-- <li><a href="#"><i class="fas fa-long-arrow-alt-left margin-5px-right d-none d-md-inline-block"></i> Prev</a></li>--}}
|
||||
{{-- <li class="active"><a href="#">1</a></li>--}}
|
||||
{{-- <li><a href="#">2</a></li>--}}
|
||||
{{-- <li><a href="#">3</a></li>--}}
|
||||
{{-- <li><a href="#">Next <i class="fas fa-long-arrow-alt-right margin-5px-left d-none d-md-inline-block"></i></a></li>--}}
|
||||
{{-- </ul>--}}
|
||||
{{-- </div>--}}
|
||||
{{-- </div>--}}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@@ -0,0 +1,41 @@
|
||||
<section class="title-section">
|
||||
|
||||
<div class="container">
|
||||
|
||||
<!-- crumbs -->
|
||||
<div class="row crumbs">
|
||||
<div class="col-md-12">
|
||||
<a href="{{ url('') }}">หน้าแรก</a> @if($detail) / <a href="{{ $link }}"> {{ $title }} </a>
|
||||
/ {{ $detail }} @else / {{ $title }} @endif
|
||||
</div>
|
||||
</div>
|
||||
<!-- End crumbs -->
|
||||
|
||||
<!-- Title -->
|
||||
<div class="row crumbs">
|
||||
<div class="col-md-12">
|
||||
<h1> {{ $title }} </h1>
|
||||
</div>
|
||||
</div>
|
||||
<!-- End Title -->
|
||||
|
||||
<!-- Back Button -->
|
||||
<div class="row crumbs">
|
||||
<div class="col-md-12">
|
||||
<div class="back-button">
|
||||
<h4>
|
||||
<a href="{{ url('') }}">
|
||||
<i class="fa fa-angle-left"></i>
|
||||
กลับ
|
||||
</a>
|
||||
</h4>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- End Back Button -->
|
||||
|
||||
</div>
|
||||
|
||||
</section>
|
||||
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
<section class="title-section">
|
||||
|
||||
<div class="container">
|
||||
|
||||
<!-- crumbs -->
|
||||
<div class="row crumbs">
|
||||
<div class="col-md-12">
|
||||
<a href="{{ url('') }}">หน้าแรก</a> @if($detail) / <a href="{{ $link }}"> {{ $title }} </a>
|
||||
/ {{ $detail }} @else / {{ $title }} @endif
|
||||
</div>
|
||||
</div>
|
||||
<!-- End crumbs -->
|
||||
|
||||
<!-- Title -->
|
||||
<div class="row crumbs">
|
||||
<div class="col-md-12">
|
||||
<h1> {{ $title }} </h1>
|
||||
</div>
|
||||
</div>
|
||||
<!-- End Title -->
|
||||
|
||||
<!-- Back Button -->
|
||||
<div class="row crumbs">
|
||||
<div class="col-md-12">
|
||||
<div class="back-button">
|
||||
<h4>
|
||||
<a href="{{ $link }}">
|
||||
<i class="fa fa-angle-left"></i>
|
||||
กลับ
|
||||
</a>
|
||||
</h4>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- End Back Button -->
|
||||
|
||||
</div>
|
||||
|
||||
</section>
|
||||
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
<section class="title-section">
|
||||
|
||||
<div class="container">
|
||||
|
||||
<!-- crumbs -->
|
||||
<div class="row crumbs">
|
||||
<div class="col-md-12">
|
||||
<a href="{{ url('') }}">หน้าแรก</a> @if($detail) / <a href="{{ url('find-job') }}"> {{ $title }} </a>
|
||||
/ {{ $detail }} @else / {{ $title }} @endif
|
||||
</div>
|
||||
</div>
|
||||
<!-- End crumbs -->
|
||||
|
||||
<!-- Title -->
|
||||
<div class="row crumbs">
|
||||
<div class="col-md-12">
|
||||
<h1> {{ $title }} </h1>
|
||||
</div>
|
||||
</div>
|
||||
<!-- End Title -->
|
||||
|
||||
<!-- Back Button -->
|
||||
<div class="row crumbs">
|
||||
<div class="col-md-12">
|
||||
<div class="back-button">
|
||||
<h4>
|
||||
<a href="{{ $link }}">
|
||||
<i class="fa fa-angle-left"></i>
|
||||
กลับ
|
||||
</a>
|
||||
</h4>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- End Back Button -->
|
||||
|
||||
</div>
|
||||
|
||||
</section>
|
||||
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
<section class="title-section">
|
||||
|
||||
<div class="container">
|
||||
|
||||
<!-- crumbs -->
|
||||
<div class="row crumbs">
|
||||
<div class="col-md-12">
|
||||
<a href="{{ url('') }}">หน้าแรก</a> @if($detail) / <a
|
||||
href="{{ url('find-volunteer') }}"> {{ $title }} </a> / {{ $detail }} @else / {{ $title }} @endif
|
||||
</div>
|
||||
</div>
|
||||
<!-- End crumbs -->
|
||||
|
||||
<!-- Title -->
|
||||
<div class="row crumbs">
|
||||
<div class="col-md-12">
|
||||
<h1> {{ $title }} </h1>
|
||||
</div>
|
||||
</div>
|
||||
<!-- End Title -->
|
||||
|
||||
<!-- Back Button -->
|
||||
<div class="row crumbs">
|
||||
<div class="col-md-12">
|
||||
<div class="back-button">
|
||||
<h4>
|
||||
<a href="{{ $link }}">
|
||||
<i class="fa fa-angle-left"></i>
|
||||
กลับ
|
||||
</a>
|
||||
</h4>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- End Back Button -->
|
||||
|
||||
</div>
|
||||
|
||||
</section>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user