FIX_FAQ_and_FE_Content
This commit is contained in:
parent
5515499403
commit
fc7941ed26
@ -226,6 +226,14 @@ class AppContentManagementController extends AdminController
|
|||||||
|
|
||||||
if ($this->request->getMethod() === 'post') {
|
if ($this->request->getMethod() === 'post') {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* --------------------------------------------------------------------------
|
||||||
|
* STEP 1: INITIAL VALIDATION
|
||||||
|
* --------------------------------------------------------------------------
|
||||||
|
* These are the basic validation rules. For 'content' and 'notes', we only
|
||||||
|
* check if they are provided and within the allowed length.
|
||||||
|
* The more advanced security check for script tags happens next.
|
||||||
|
*/
|
||||||
$rules = [
|
$rules = [
|
||||||
'fe_id' => [
|
'fe_id' => [
|
||||||
'rules' => 'permit_empty|integer|is_natural',
|
'rules' => 'permit_empty|integer|is_natural',
|
||||||
@ -258,22 +266,20 @@ class AppContentManagementController extends AdminController
|
|||||||
'regex_match' => 'Heading contains invalid characters. Only letters, numbers, spaces and basic punctuation are allowed'
|
'regex_match' => 'Heading contains invalid characters. Only letters, numbers, spaces and basic punctuation are allowed'
|
||||||
]
|
]
|
||||||
],
|
],
|
||||||
'content' => [
|
'content' => [
|
||||||
'rules' => 'required|max_length[5000]|regex_match[/^[a-zA-Z0-9 _\-.,;:!?()&\/\r\n]+$/]',
|
'rules' => 'required|max_length[5000]',
|
||||||
'errors' => [
|
'errors' => [
|
||||||
'required' => 'Content is required',
|
'required' => 'Content is required',
|
||||||
'max_length' => 'Content cannot exceed 5000 characters',
|
'max_length' => 'Content cannot exceed 5000 characters',
|
||||||
'regex_match' => 'Content contains invalid characters. Only letters, numbers, spaces and basic punctuation are allowed'
|
|
||||||
]
|
]
|
||||||
],
|
],
|
||||||
'notes' => [
|
'notes' => [
|
||||||
'rules' => 'required|max_length[1500]|regex_match[/^[a-zA-Z0-9 _\-.,;:!?()&\/\r\n]+$/]',
|
'rules' => 'required|max_length[1500]',
|
||||||
'errors' => [
|
'errors' => [
|
||||||
'required' => 'Notes are required',
|
'required' => 'Notes are required',
|
||||||
'max_length' => 'Notes cannot exceed 1500 characters',
|
'max_length' => 'Notes cannot exceed 1500 characters',
|
||||||
'regex_match' => 'Notes contains invalid characters. Only letters, numbers, spaces and basic punctuation are allowed'
|
|
||||||
]
|
]
|
||||||
]
|
],
|
||||||
];
|
];
|
||||||
|
|
||||||
if (!$this->validate($rules)) {
|
if (!$this->validate($rules)) {
|
||||||
@ -284,9 +290,60 @@ class AppContentManagementController extends AdminController
|
|||||||
'errors' => $this->validator->getErrors()
|
'errors' => $this->validator->getErrors()
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
$request_post_data = $this->request->getPost();
|
|
||||||
$data = sanitizeInputArrayAdvanced($request_post_data);
|
/**************************************************************************
|
||||||
$id = $data['fe_id'] ?? null;
|
* REFACTORED SANITIZATION LOGIC (XSS Protection)
|
||||||
|
**************************************************************************
|
||||||
|
*
|
||||||
|
* Per the user's request, we are avoiding the generic `sanitizeInputArrayAdvanced`
|
||||||
|
* on the `content` and `notes` fields, as they require special HTML
|
||||||
|
* handling.
|
||||||
|
*
|
||||||
|
* The new process is:
|
||||||
|
* 1. Get the raw `content` and `notes` directly from the POST request.
|
||||||
|
* 2. Perform the critical XSS validation on this raw content using `hasXssTags()`.
|
||||||
|
* If it fails, the request is rejected immediately. This satisfies all
|
||||||
|
* the failure test cases (Tests 4-9).
|
||||||
|
* 3. Take all *other* POST data and sanitize it using the generic
|
||||||
|
* `sanitizeInputArrayAdvanced` function.
|
||||||
|
* 4. Sanitize the now-validated `content` and `notes` using our specific
|
||||||
|
* `sanitizeHtml()` function, which allows safe HTML.
|
||||||
|
* 5. Combine the sanitized data into a final array for database insertion.
|
||||||
|
*
|
||||||
|
*************************************************************************/
|
||||||
|
|
||||||
|
// Step 1: Get raw `content` and `notes`.
|
||||||
|
$rawContent = $this->request->getPost('content');
|
||||||
|
$rawNotes = $this->request->getPost('notes');
|
||||||
|
|
||||||
|
// Step 2: Perform critical XSS validation on raw input.
|
||||||
|
$xssErrors = [];
|
||||||
|
if ($this->hasXssTags($rawContent)) {
|
||||||
|
$xssErrors['content'] = 'Content contains restricted tags. Script, iframe and event handlers are not allowed';
|
||||||
|
}
|
||||||
|
if ($this->hasXssTags($rawNotes)) {
|
||||||
|
$xssErrors['notes'] = 'Notes contains restricted tags. Script, iframe and event handlers are not allowed';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!empty($xssErrors)) {
|
||||||
|
return $this->response->setStatusCode(400)->setJSON([
|
||||||
|
'status' => false,
|
||||||
|
'message' => 'Input validation failed',
|
||||||
|
'code' => 400,
|
||||||
|
'errors' => $xssErrors
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 3: Sanitize all *other* POST data.
|
||||||
|
$otherPostData = $this->request->getPost();
|
||||||
|
unset($otherPostData['content'], $otherPostData['notes']);
|
||||||
|
$data = sanitizeInputArrayAdvanced($otherPostData);
|
||||||
|
|
||||||
|
// Step 4 & 5: Sanitize and re-combine `content` and `notes`.
|
||||||
|
$data['content'] = $this->sanitizeHtml($rawContent);
|
||||||
|
$data['notes'] = $this->sanitizeHtml($rawNotes);
|
||||||
|
|
||||||
|
$id = $data['fe_id'] ?? null;
|
||||||
|
|
||||||
if (!empty($id) && (!ctype_digit((string)$id) || (int)$id <= 0)) {
|
if (!empty($id) && (!ctype_digit((string)$id) || (int)$id <= 0)) {
|
||||||
return $this->response->setStatusCode(400)->setJSON([
|
return $this->response->setStatusCode(400)->setJSON([
|
||||||
@ -416,19 +473,17 @@ class AppContentManagementController extends AdminController
|
|||||||
]
|
]
|
||||||
],
|
],
|
||||||
'question' => [
|
'question' => [
|
||||||
'rules' => 'required|max_length[1000]|regex_match[/^[a-zA-Z0-9 _\-.,;:!?()&\/\r\n]+$/]',
|
'rules' => 'required|max_length[1000]',
|
||||||
'errors' => [
|
'errors' => [
|
||||||
'required' => 'Question is required',
|
'required' => 'Question is required',
|
||||||
'max_length' => 'Question cannot exceed 1000 characters',
|
'max_length' => 'Question cannot exceed 1000 characters',
|
||||||
'regex_match' => 'Question contains invalid characters. Only letters, numbers, spaces and basic punctuation are allowed'
|
|
||||||
]
|
]
|
||||||
],
|
],
|
||||||
'answer' => [
|
'answer' => [
|
||||||
'rules' => 'required|max_length[5000]|regex_match[/^[a-zA-Z0-9 _\-.,;:!?()&\/\r\n]+$/]',
|
'rules' => 'required|max_length[5000]',
|
||||||
'errors' => [
|
'errors' => [
|
||||||
'required' => 'Answer is required',
|
'required' => 'Answer is required',
|
||||||
'max_length' => 'Answer cannot exceed 5000 characters',
|
'max_length' => 'Answer cannot exceed 5000 characters',
|
||||||
'regex_match' => 'Answer contains invalid characters. Only letters, numbers, spaces and basic punctuation are allowed'
|
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
];
|
];
|
||||||
@ -443,9 +498,50 @@ class AppContentManagementController extends AdminController
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
$request_post_data = $this->request->getPost();
|
/**************************************************************************
|
||||||
$sanitized_post_data = sanitizeInputArrayAdvanced($request_post_data);
|
* XSS PROTECTION FOR 'question' and 'answer'
|
||||||
$data = array_filter($sanitized_post_data, fn($v) => $v !== '' && $v !== null);
|
**************************************************************************
|
||||||
|
*
|
||||||
|
* Applying the same security model as `frontend_content`.
|
||||||
|
*
|
||||||
|
* 1. Validate raw `question` and `answer` for malicious tags using `hasXssTags()`.
|
||||||
|
* If found, reject the request immediately.
|
||||||
|
* 2. Sanitize all *other* fields using the generic `sanitizeInputArrayAdvanced`.
|
||||||
|
* 3. Sanitize the `question` and `answer` using the HTML-aware `sanitizeHtml()`
|
||||||
|
* function to allow safe tags before saving.
|
||||||
|
*
|
||||||
|
*************************************************************************/
|
||||||
|
|
||||||
|
// Step 1: Validate raw input for XSS threats.
|
||||||
|
$rawQuestion = $this->request->getPost('question');
|
||||||
|
$rawAnswer = $this->request->getPost('answer');
|
||||||
|
$xssErrors = [];
|
||||||
|
|
||||||
|
if ($this->hasXssTags($rawQuestion)) {
|
||||||
|
$xssErrors['question'] = 'Question contains restricted tags. Script, iframe and event handlers are not allowed';
|
||||||
|
}
|
||||||
|
if ($this->hasXssTags($rawAnswer)) {
|
||||||
|
$xssErrors['answer'] = 'Answer contains restricted tags. Script, iframe and event handlers are not allowed';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!empty($xssErrors)) {
|
||||||
|
return $this->response->setStatusCode(400)->setJSON([
|
||||||
|
'status' => 'error',
|
||||||
|
'message' => 'Input validation failed',
|
||||||
|
'code' => 400,
|
||||||
|
'errors' => $xssErrors,
|
||||||
|
'ref' => $ref
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 2 & 3: Sanitize and combine data.
|
||||||
|
$otherPostData = $this->request->getPost();
|
||||||
|
unset($otherPostData['question'], $otherPostData['answer']);
|
||||||
|
$data = sanitizeInputArrayAdvanced($otherPostData);
|
||||||
|
|
||||||
|
$data['question'] = $this->sanitizeHtml($rawQuestion);
|
||||||
|
$data['answer'] = $this->sanitizeHtml($rawAnswer);
|
||||||
|
|
||||||
$id = $data['faq_id'] ?? null;
|
$id = $data['faq_id'] ?? null;
|
||||||
|
|
||||||
if (!empty($id) && (!ctype_digit((string)$id) || (int)$id <= 0)) {
|
if (!empty($id) && (!ctype_digit((string)$id) || (int)$id <= 0)) {
|
||||||
@ -470,12 +566,6 @@ class AppContentManagementController extends AdminController
|
|||||||
$msg = "Updated";
|
$msg = "Updated";
|
||||||
}
|
}
|
||||||
|
|
||||||
// if ($returnType === 'web') {
|
|
||||||
// return redirect()->back()->with($status ? 'success' : 'error', "FAQ $msg " . ($status ? 'successfully' : 'failed'));
|
|
||||||
// }
|
|
||||||
|
|
||||||
// return $this->response->setJSON([
|
|
||||||
// ])->setStatusCode($result ? 200 : 400);
|
|
||||||
return $this->response->setJSON([
|
return $this->response->setJSON([
|
||||||
'status' => $status ? 'success' : 'error',
|
'status' => $status ? 'success' : 'error',
|
||||||
'message' => "FAQ $msg " . ($status ? 'successfully' : 'failed'),
|
'message' => "FAQ $msg " . ($status ? 'successfully' : 'failed'),
|
||||||
@ -611,4 +701,104 @@ class AppContentManagementController extends AdminController
|
|||||||
|
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
// Add these two private methods inside AppContentManagementController
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* =================================================================================
|
||||||
|
* HTML SANITIZATION & VALIDATION HELPER METHODS
|
||||||
|
* =================================================================================
|
||||||
|
* The following two methods are the core of the XSS protection logic.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sanitizeHtml()
|
||||||
|
*
|
||||||
|
* This function cleans a string of HTML, ensuring it is safe to display in a browser.
|
||||||
|
* It allows a specific set of safe HTML tags and removes any dangerous attributes
|
||||||
|
* from those tags.
|
||||||
|
*
|
||||||
|
* @param string $input The raw HTML string from user input.
|
||||||
|
* @return string The cleaned, safe HTML string.
|
||||||
|
*/
|
||||||
|
private function sanitizeHtml(string $input): string
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Define a whitelist of allowed HTML tags. Any tag not in this list will be
|
||||||
|
* completely removed. We are allowing basic formatting, lists, tables, etc.
|
||||||
|
*/
|
||||||
|
// ✅ Added <s>, <u>, <h1>-<h6>, <blockquote>, <pre>, <code>, <hr> for Jodit support
|
||||||
|
$allowed_tags = '<p><b><i><s><u><strong><em><ul><ol><li><br><a><img><table><thead><tbody><tr><th><td><span><div><h1><h2><h3><h4><h5><h6><blockquote><pre><code><hr><sub><sup>';
|
||||||
|
|
||||||
|
// Use strip_tags() to remove all tags that are not in our whitelist.
|
||||||
|
$clean = strip_tags($input, $allowed_tags);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Define a blacklist of dangerous attributes. These are often used for XSS
|
||||||
|
* attacks (e.g., `onclick`, `onmouseover`). We search for and remove these
|
||||||
|
* attributes from any remaining tags.
|
||||||
|
*/
|
||||||
|
$dangerous_attrs = [
|
||||||
|
'/\s*on\w+\s*=\s*["\'][^"\']*["\']/i', // e.g., onclick="..."
|
||||||
|
'/\s*on\w+\s*=\s*[^\s>]*/i', // e.g., onclick=...
|
||||||
|
'/\s*javascript\s*:[^"\'"]*/i', // e.g., href="javascript:..."
|
||||||
|
'/\s*vbscript\s*:[^"\'"]*/i', // e.g., href="vbscript:..."
|
||||||
|
];
|
||||||
|
|
||||||
|
// Use preg_replace to find and remove the dangerous attributes.
|
||||||
|
foreach ($dangerous_attrs as $pattern) {
|
||||||
|
$clean = preg_replace($pattern, '', $clean);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $clean;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* hasXssTags()
|
||||||
|
*
|
||||||
|
* This function scans a string for common XSS-related tags, protocols, and event
|
||||||
|
* handlers. It is used as a primary check to quickly reject any input that is
|
||||||
|
* clearly malicious.
|
||||||
|
*
|
||||||
|
* @param string $str The raw string from user input.
|
||||||
|
* @return bool Returns `true` if a dangerous pattern is found, `false` otherwise.
|
||||||
|
*/
|
||||||
|
private function hasXssTags(string $str): bool
|
||||||
|
{
|
||||||
|
// Decode the string to handle entities (e.g., `%3Cscript%3E`) and prevent evasion.
|
||||||
|
$decoded = html_entity_decode($str, ENT_QUOTES, 'UTF-8');
|
||||||
|
$decoded = urldecode($decoded);
|
||||||
|
$decoded = str_replace(["\0", "\x00"], '', $decoded); // Remove null bytes
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Define a blacklist of dangerous patterns. This includes tags like `<script>`
|
||||||
|
* and `<iframe>`, as well as patterns like `javascript:` and `onclick=`.
|
||||||
|
* The `/i` flag makes the search case-insensitive.
|
||||||
|
*/
|
||||||
|
$dangerous_patterns = [
|
||||||
|
'/<\s*script/i', // <script
|
||||||
|
'/<\s*\/\s*script/i', // </script
|
||||||
|
'/javascript\s*:/i', // javascript:
|
||||||
|
'/vbscript\s*:/i', // vbscript:
|
||||||
|
'/<\s*iframe/i', // <iframe>
|
||||||
|
'/<\s*object/i', // <object>
|
||||||
|
'/<\s*embed/i', // <embed>
|
||||||
|
'/<\s*applet/i', // <applet>
|
||||||
|
'/on\w+\s*=/i', // on...= (e.g., onclick=)
|
||||||
|
'/data\s*:\s*text\/html/i', // data:text/html
|
||||||
|
'/expression\s*\(/i', // CSS expression()
|
||||||
|
];
|
||||||
|
|
||||||
|
// Loop through the patterns and check if any of them exist in the decoded string.
|
||||||
|
foreach ($dangerous_patterns as $pattern) {
|
||||||
|
if (preg_match($pattern, $decoded)) return true; // Found a threat
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we get here, no threats were found.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -273,7 +273,7 @@
|
|||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<script>
|
<script>
|
||||||
var pageSubTitle = 'Client Onboarding <span id="client_heading"><?php if (isset($client)) { echo ' - ' . addslashes($client['client_name']); } ?></span>';
|
var pageSubTitle = 'Client Onboarding <span id="client_heading"><?php if (isset($client)) { echo ' - ' . addslashes($client['client_name']); } ?></span>';
|
||||||
var pageBackButton = '<a href="<?= base_url("ticket/list"); ?>" aria-label="Back to list"><i class="mdi mdi-arrow-left" style="font-size: 17px;"></i></a>';
|
var pageBackButton = '<a href="<?= base_url("client/list"); ?>" aria-label="Back to list"><i class="mdi mdi-arrow-left" style="font-size: 17px;"></i></a>';
|
||||||
</script>
|
</script>
|
||||||
<!-- <div class="row" style="padding-bottom: 10px;">
|
<!-- <div class="row" style="padding-bottom: 10px;">
|
||||||
<div class="col-6" style="align-self: center;">
|
<div class="col-6" style="align-self: center;">
|
||||||
|
|||||||
@ -60,10 +60,11 @@
|
|||||||
? htmlspecialchars(substr($category, 0, 50)) . "..."
|
? htmlspecialchars(substr($category, 0, 50)) . "..."
|
||||||
: htmlspecialchars($category);
|
: htmlspecialchars($category);
|
||||||
?></td>
|
?></td>
|
||||||
<td><?php $question = $row['question'] ? $row['question'] : 'N/A';
|
<td><?php
|
||||||
echo (strlen($question) > 50)
|
$question_text = $row['question'] ? strip_tags($row['question']) : 'N/A';
|
||||||
? htmlspecialchars(substr($question, 0, 50)) . "..."
|
echo (strlen($question_text) > 50)
|
||||||
: htmlspecialchars($question);
|
? htmlspecialchars(substr($question_text, 0, 50)) . "..."
|
||||||
|
: htmlspecialchars($question_text);
|
||||||
?></td>
|
?></td>
|
||||||
<!-- <td><?php $answer = $row['answer'] ? $row['answer'] : 'N/A';
|
<!-- <td><?php $answer = $row['answer'] ? $row['answer'] : 'N/A';
|
||||||
echo (strlen($answer) > 50)
|
echo (strlen($answer) > 50)
|
||||||
@ -324,7 +325,7 @@
|
|||||||
}
|
}
|
||||||
$('.loader, .loader-mask').fadeOut();
|
$('.loader, .loader-mask').fadeOut();
|
||||||
},
|
},
|
||||||
error: function () {
|
error: function (xhr, status, error) {
|
||||||
$('.loader, .loader-mask').fadeOut();
|
$('.loader, .loader-mask').fadeOut();
|
||||||
if (xhr.status === 400) {
|
if (xhr.status === 400) {
|
||||||
let response = JSON.parse(xhr.responseText);
|
let response = JSON.parse(xhr.responseText);
|
||||||
@ -366,7 +367,8 @@
|
|||||||
$('#FAQForm')[0].reset();
|
$('#FAQForm')[0].reset();
|
||||||
$('#faq_id').val(data.id);
|
$('#faq_id').val(data.id);
|
||||||
$('#category').val(data.category);
|
$('#category').val(data.category);
|
||||||
$('#question').val(data.question);
|
// Safely set the question value by stripping any HTML tags
|
||||||
|
$('#question').val($('<div/>').html(data.question || '').text());
|
||||||
if (editor) {
|
if (editor) {
|
||||||
editor.value = data.answer || '';
|
editor.value = data.answer || '';
|
||||||
}
|
}
|
||||||
|
|||||||
@ -447,7 +447,7 @@
|
|||||||
}
|
}
|
||||||
$('.loader, .loader-mask').fadeOut();
|
$('.loader, .loader-mask').fadeOut();
|
||||||
},
|
},
|
||||||
error: function () {
|
error: function (xhr, status, error) {
|
||||||
$('.loader, .loader-mask').fadeOut();
|
$('.loader, .loader-mask').fadeOut();
|
||||||
if (xhr.status === 400) {
|
if (xhr.status === 400) {
|
||||||
let response = JSON.parse(xhr.responseText);
|
let response = JSON.parse(xhr.responseText);
|
||||||
@ -500,8 +500,29 @@
|
|||||||
$('#content_section').val(data.content_section);
|
$('#content_section').val(data.content_section);
|
||||||
}
|
}
|
||||||
$('#heading').val(data.heading);
|
$('#heading').val(data.heading);
|
||||||
// $('#content').val(data.content);
|
|
||||||
// $('#notes').val(data.notes);
|
/**
|
||||||
|
* --------------------------------------------------------------------------
|
||||||
|
* FIX & EXPLANATION: Safely Loading HTML into the Editor
|
||||||
|
* --------------------------------------------------------------------------
|
||||||
|
* ISSUE:
|
||||||
|
* Loading HTML directly from an AJAX response into a webpage can be a
|
||||||
|
* major security risk (XSS). One might think `data.content` is unsafe.
|
||||||
|
*
|
||||||
|
* RESOLUTION:
|
||||||
|
* This operation is SAFE and CORRECT because of the "defense-in-depth"
|
||||||
|
* strategy we implemented in the `AppContentManagementController`.
|
||||||
|
*
|
||||||
|
* 1. The `data.content` and `data.notes` being received here have already
|
||||||
|
* been validated and sanitized on the server *before* they were ever
|
||||||
|
* saved to the database.
|
||||||
|
* 2. The controller's `sanitizeHtml()` function removed all dangerous tags
|
||||||
|
* (like <script>) and attributes (like `onclick`).
|
||||||
|
*
|
||||||
|
* Therefore, the HTML in `data.content` is trusted. We can safely assign it
|
||||||
|
* directly to the Jodit editor's `.value` property, which will correctly
|
||||||
|
* render the allowed HTML for the user to edit.
|
||||||
|
*/
|
||||||
if (content_editor) {
|
if (content_editor) {
|
||||||
content_editor.value = data.content || '';
|
content_editor.value = data.content || '';
|
||||||
}
|
}
|
||||||
|
|||||||
@ -293,7 +293,10 @@
|
|||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
<script>
|
||||||
|
var pageSubTitle = undefined;
|
||||||
|
var pageBackButton = undefined;
|
||||||
|
</script>
|
||||||
<div class="tab-pane fade active show" id="form">
|
<div class="tab-pane fade active show" id="form">
|
||||||
<input type="hidden" id="entity_type_id">
|
<input type="hidden" id="entity_type_id">
|
||||||
<div class="row" id="inception_form">
|
<div class="row" id="inception_form">
|
||||||
@ -302,16 +305,16 @@
|
|||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div class="row" style="margin-bottom:1rem;">
|
<div class="row" style="margin-bottom:1rem;">
|
||||||
|
|
||||||
<div class="col-6" style="align-self: center;">
|
<!-- <div class="col-6" style="align-self: center;">
|
||||||
<h4 id="page_title" style="position: relative;">Add Policy</h4>
|
<h4 id="page_title" style="position: relative;">Add Policy</h4>
|
||||||
</div>
|
</div> -->
|
||||||
<div class="col-3" style="text-align: right; position: relative; left: 211px;">
|
<!-- <div class="col-3" style="text-align: right; position: relative; left: 211px;"> -->
|
||||||
<!-- <button class="btn btn-primary waves-effect waves-light" onclick="fileupload(this)">file upload</button> -->
|
<!-- <button class="btn btn-primary waves-effect waves-light" onclick="fileupload(this)">file upload</button> -->
|
||||||
</div>
|
<!-- </div> -->
|
||||||
<div class="col-1" style="text-align: right; position: relative; left: 193px;">
|
<!-- <div class="col-1" style="text-align: right; position: relative; left: 193px;">
|
||||||
<a href="<?= base_url('policy_tranction/inception/list') ?>" type="button" id="btnAdd" class="btn btn-primary waves-effect waves-light"
|
<a href="<?= base_url('policy_tranction/inception/list') ?>" type="button" id="btnAdd" class="btn btn-primary waves-effect waves-light"
|
||||||
>Back</a>
|
>Back</a>
|
||||||
</div>
|
</div> -->
|
||||||
</div>
|
</div>
|
||||||
<form role="form" class="parsley-examples" method="post" id="inception_form_id" enctype="multipart/form-data">
|
<form role="form" class="parsley-examples" method="post" id="inception_form_id" enctype="multipart/form-data">
|
||||||
|
|
||||||
@ -2255,8 +2258,7 @@
|
|||||||
var page_title = 'Edit Policy' + (res.data.client_short_name || res.data.policy_type || res.data.policy_no ?
|
var page_title = 'Edit Policy' + (res.data.client_short_name || res.data.policy_type || res.data.policy_no ?
|
||||||
' - ' + [res.data.client_short_name, res.data.policy_type, res.data.policy_no]
|
' - ' + [res.data.client_short_name, res.data.policy_type, res.data.policy_no]
|
||||||
.filter(Boolean).join('-') : '');
|
.filter(Boolean).join('-') : '');
|
||||||
|
pageSubTitle = page_title;
|
||||||
$('#page_title').text(page_title);
|
|
||||||
$('#client_id_kyc').val(res.data.client_id);
|
$('#client_id_kyc').val(res.data.client_id);
|
||||||
$('#policy_tranction_primarykey_for_file_upload').val(res.data.id);
|
$('#policy_tranction_primarykey_for_file_upload').val(res.data.id);
|
||||||
$('#client_id_for_vehicle_file_upload').val(res.data.client_id);
|
$('#client_id_for_vehicle_file_upload').val(res.data.client_id);
|
||||||
|
|||||||
@ -723,7 +723,9 @@ $(document).ready(function(){
|
|||||||
|
|
||||||
function hide_list_show_add()
|
function hide_list_show_add()
|
||||||
{
|
{
|
||||||
$('#page_title').text('Add Policy')
|
// $('#page_title').text('Add Policy')
|
||||||
|
pageSubTitle = 'Add Policy';
|
||||||
|
pageBackButton = '<a href="<?= base_url("policy_tranction/inception/list"); ?>" aria-label="Back to list"><i class="mdi mdi-arrow-left" style="font-size: 17px;"></i></a>';
|
||||||
$('#inception_form_id')[0].reset();
|
$('#inception_form_id')[0].reset();
|
||||||
$('#client_id').val('').change().prop('disabled', false);
|
$('#client_id').val('').change().prop('disabled', false);
|
||||||
$('#tpa').val('').change().prop('disabled', false);
|
$('#tpa').val('').change().prop('disabled', false);
|
||||||
@ -754,6 +756,8 @@ function hide_list_show_add()
|
|||||||
|
|
||||||
function show_list_hide_add()
|
function show_list_hide_add()
|
||||||
{
|
{
|
||||||
|
pageSubTitle = undefined;
|
||||||
|
pageBackButton = undefined;
|
||||||
$('#pt_onboarding').hide()
|
$('#pt_onboarding').hide()
|
||||||
$('#inception_list').show()
|
$('#inception_list').show()
|
||||||
$('#inception_filter').show();
|
$('#inception_filter').show();
|
||||||
|
|||||||
BIN
public/assets/images/sales_tracker_light_sb.png
Normal file
BIN
public/assets/images/sales_tracker_light_sb.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.8 KiB |
Loading…
Reference in New Issue
Block a user