Self-host front-end libraries, minimal sign-in header and CSP
- sign-in pages load only what they use (include_login_header.php, ajax_core.js) - every library, font and data file served from assets/vendor with pinned versions (VERSIONS.json); no CDN at runtime - Content-Security-Policy on app, sign-in and landing pages - remove httpbin Dropzone target and source-map references
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
@charset "UTF-8";@import"https://fonts.googleapis.com/css2?family=Poppins:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap";@import"https://cdnjs.cloudflare.com/ajax/libs/tabler-icons/3.35.0/tabler-icons.min.css";/*!
|
||||
@charset "UTF-8";@import"../vendor/fonts/poppins/poppins.css";@import"../vendor/tabler-icons/3.35.0/tabler-icons.min.css";/*!
|
||||
* Bootstrap v5.3.8 (https://getbootstrap.com/)
|
||||
* Copyright 2011-2025 The Bootstrap Authors
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
|
||||
|
||||
@@ -0,0 +1,370 @@
|
||||
/**
|
||||
* ajax_core.js — helpers every page needs, including the sign-in pages:
|
||||
* HTML escaping, form-data collection, the ajax_request() wrapper, the
|
||||
* page-wide form-submit guard and live required-field validation.
|
||||
*
|
||||
* Loaded by include_header.php (before custom.js) and by the minimal
|
||||
* login/include_login_header.php, so the sign-in pages no longer download
|
||||
* custom.js with every feature's API URLs.
|
||||
*/
|
||||
|
||||
function escape_html(value) {
|
||||
return String(value ?? '').replace(/[&<>"']/g, function(c) {
|
||||
return {'&':'&','<':'<','>':'>','"':'"',"'":'''}[c];
|
||||
});
|
||||
}
|
||||
|
||||
// Text is stored HTML-escaped (see db_statement in dbconn.php), which is right
|
||||
// for anything written into markup but wrong inside a form field: a note saved
|
||||
// as 5" pipe <spare> came back as 5" pipe <spare>. Field values
|
||||
// are never parsed as HTML, so decoding them here is safe.
|
||||
function decode_html(value) {
|
||||
if (typeof value !== 'string' || value.indexOf('&') === -1) return value;
|
||||
return value.replace(/&(quot|#0*39|#x0*27|apos|lt|gt|amp);/gi, function (m, name) {
|
||||
name = name.toLowerCase();
|
||||
if (name === 'quot') return '"';
|
||||
if (name === 'lt') return '<';
|
||||
if (name === 'gt') return '>';
|
||||
if (name === 'amp') return '&';
|
||||
return "'";
|
||||
});
|
||||
}
|
||||
|
||||
(function ($) {
|
||||
if (!$ || !$.fn || $.fn.val.__decodes_html) return;
|
||||
var original_val = $.fn.val;
|
||||
$.fn.val = function (value) {
|
||||
if (arguments.length && typeof value === 'string') {
|
||||
// Only free-text fields; a <select> value must keep matching its option.
|
||||
var text_fields = this.filter('input, textarea');
|
||||
if (text_fields.length === this.length) return original_val.call(this, decode_html(value));
|
||||
}
|
||||
return original_val.apply(this, arguments);
|
||||
};
|
||||
$.fn.val.__decodes_html = true;
|
||||
})(window.jQuery);
|
||||
|
||||
|
||||
/** =========================
|
||||
* FORMS
|
||||
* ========================= */
|
||||
|
||||
// Prevent all forms from refreshing the page
|
||||
$(function () {
|
||||
$("form").on("submit", function (e) {
|
||||
e.preventDefault();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
function prepare_form_data(check_required, raw_data) {
|
||||
|
||||
var q = {};
|
||||
|
||||
// Get session context
|
||||
const session_element = document.getElementById('session-context');
|
||||
|
||||
if (session_element) {
|
||||
q['company_id'] = session_element.dataset.companyId;
|
||||
q['otp'] = session_element.dataset.otp;
|
||||
}
|
||||
|
||||
// Include GET parameters
|
||||
const url_params = new URLSearchParams(window.location.search);
|
||||
url_params.forEach((value, key) => {
|
||||
q[key] = value;
|
||||
});
|
||||
|
||||
// Collect form inputs (exclude search inputs — UI-only filters, not API data)
|
||||
$(".form-control:not([type=search]), .form-select").each(function () {
|
||||
if (!$(this).attr("id")) return true;
|
||||
var el = $(this).get(0);
|
||||
if (!el || !el.nodeName) return true;
|
||||
q[$(this).attr("id")] = $(this).val();
|
||||
});
|
||||
|
||||
// Validate required fields
|
||||
if (check_required === 1) {
|
||||
|
||||
const required_inputs = document.querySelectorAll('[required]');
|
||||
let is_valid = true;
|
||||
|
||||
required_inputs.forEach(input => {
|
||||
if (!input.value.trim()) {
|
||||
input.classList.add('is-invalid');
|
||||
is_valid = false;
|
||||
} else {
|
||||
input.classList.remove('is-invalid');
|
||||
input.classList.add('is-valid');
|
||||
}
|
||||
});
|
||||
|
||||
if (!is_valid) {
|
||||
alert("Please fill in all mandatory fields.");
|
||||
isAjaxProcessing = false;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return (raw_data) ? q : JSON.stringify(q);
|
||||
}
|
||||
|
||||
|
||||
// server_url is set by include_topbar.php (app pages) and login/include_login_header.php.
|
||||
function app_base_url() {
|
||||
if (typeof server_url !== 'undefined' && server_url) return server_url;
|
||||
return (document.body && document.body.dataset.serverUrl) || '/';
|
||||
}
|
||||
|
||||
/** =========================
|
||||
* AJAX WRAPPER
|
||||
* ========================= */
|
||||
|
||||
// Prevent double firing
|
||||
let isAjaxProcessing = false;
|
||||
|
||||
function ajax_request(options) {
|
||||
|
||||
if (isAjaxProcessing && options.queueLock !== false) {
|
||||
// Instead of rejecting, we just return a "never-ending" promise
|
||||
// or a resolved promise that does nothing.
|
||||
console.warn("Request is busy... ignoring click.");
|
||||
return new Promise(() => { }); // This stays pending and won't trigger .then or .catch
|
||||
}
|
||||
|
||||
if (options.queueLock !== false) {
|
||||
isAjaxProcessing = true;
|
||||
}
|
||||
|
||||
// Auto prepare form data
|
||||
if (options.autoPrepare === true) {
|
||||
|
||||
let payloadJson = prepare_form_data(options.checkRequired ?? 0, true);
|
||||
if (payloadJson === false) {
|
||||
isAjaxProcessing = false;
|
||||
return Promise.reject("validation_failed");
|
||||
}
|
||||
|
||||
if (options.data) {
|
||||
Object.entries(options.data).forEach(([key, value]) => {
|
||||
payloadJson[key] = value;
|
||||
});
|
||||
}
|
||||
|
||||
if (options.action) {
|
||||
// modify action
|
||||
if (options.action === 'manage') {
|
||||
options.action = (payloadJson['id']) ? 'update' : 'create';
|
||||
}
|
||||
// add action to JSON
|
||||
payloadJson['action'] = options.action;
|
||||
} else {
|
||||
isAjaxProcessing = false;
|
||||
return Promise.reject("please_define_action");
|
||||
}
|
||||
|
||||
options.data = { json: JSON.stringify(payloadJson) };
|
||||
|
||||
if (options.debugMode) {
|
||||
isAjaxProcessing = false;
|
||||
// Show FormData contents if applicable
|
||||
if (options.formData instanceof FormData) {
|
||||
// Log original formData before merging
|
||||
for (let [key, value] of options.formData.entries()) {
|
||||
console.log("FORMDATA: " + key, value);
|
||||
}
|
||||
}
|
||||
// Show stringified JSON payload
|
||||
console.log("REQUEST DATA:", options.data);
|
||||
}
|
||||
|
||||
// IF formData exist, we pass as $_POST [not json]
|
||||
if (options.formData instanceof FormData) {
|
||||
// THE BYPASS: If formData exists, move all text data into it
|
||||
Object.entries(payloadJson).forEach(([key, value]) => {
|
||||
options.formData.append(key, value);
|
||||
});
|
||||
// Override options.data with the full FormData object
|
||||
options.data = options.formData;
|
||||
}
|
||||
|
||||
} else if (
|
||||
options.data && !(options.data instanceof FormData) &&
|
||||
typeof options.data === 'object' && !('json' in options.data)
|
||||
) {
|
||||
|
||||
// autoPrepare: false with a plain field map — e.g. the delete buttons'
|
||||
// `data: { id: id }`. db_auth.php only accepts a `json` string or a
|
||||
// FormData post carrying `otp`, so an unwrapped map was rejected outright
|
||||
// with "Request denied: No valid JSON payload or Form Data detected.", and
|
||||
// `options.action` was dropped because only the autoPrepare branch applied
|
||||
// it. Wrap it the same way here, without touching callers that already
|
||||
// pass a ready-made `{ json: ... }`.
|
||||
const session_element = document.getElementById('session-context');
|
||||
const payload = {};
|
||||
|
||||
if (session_element) {
|
||||
payload['company_id'] = session_element.dataset.companyId;
|
||||
payload['otp'] = session_element.dataset.otp;
|
||||
}
|
||||
|
||||
Object.entries(options.data).forEach(([key, value]) => {
|
||||
payload[key] = value;
|
||||
});
|
||||
|
||||
if (options.action) {
|
||||
payload['action'] = (options.action === 'manage')
|
||||
? (payload['id'] ? 'update' : 'create')
|
||||
: options.action;
|
||||
}
|
||||
|
||||
options.data = { json: JSON.stringify(payload) };
|
||||
|
||||
if (options.debugMode) {
|
||||
console.log("REQUEST DATA:", options.data);
|
||||
}
|
||||
}
|
||||
|
||||
// --- START MODIFIED $.AJAX BLOCK ---
|
||||
let isSendingFiles = (options.data instanceof FormData);
|
||||
|
||||
// Show loading overlay
|
||||
if (options.noLoading !== true) {
|
||||
$.LoadingOverlay("show", {
|
||||
imageColor: "#525252",
|
||||
imageAnimation: "2s rotate_right",
|
||||
background: "rgba(255,255,255,0.8)"
|
||||
});
|
||||
}
|
||||
|
||||
return $.ajax({
|
||||
async: true,
|
||||
type: options.type || "POST",
|
||||
url: options.url,
|
||||
data: options.data,
|
||||
dataType: "json",
|
||||
// These two settings are only triggered when sending files
|
||||
processData: isSendingFiles ? false : true,
|
||||
contentType: isSendingFiles ? false : "application/x-www-form-urlencoded; charset=UTF-8",
|
||||
// for CSRF validation
|
||||
headers: {
|
||||
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
|
||||
}
|
||||
|
||||
})
|
||||
.then(function (res) {
|
||||
|
||||
isAjaxProcessing = false;
|
||||
if (options.noLoading !== true) $.LoadingOverlay("hide");
|
||||
|
||||
if (options.debugMode) {
|
||||
console.log("RESPONSE:", res);
|
||||
return res;
|
||||
}
|
||||
|
||||
if (!res || res.success != 1) {
|
||||
if (options.noAlert !== true) bootbox.alert(res?.message || "Unexpected error");
|
||||
options.onError?.(null, res?.message || 'api_failed');
|
||||
throw new Error(res?.message || "api_failed");
|
||||
}
|
||||
|
||||
options.onSuccess?.(res);
|
||||
return res;
|
||||
|
||||
})
|
||||
.catch(function (xhr) {
|
||||
|
||||
isAjaxProcessing = false;
|
||||
$.LoadingOverlay("hide");
|
||||
|
||||
// Errors re-thrown from .then() — pass through
|
||||
if (xhr instanceof Error) {
|
||||
throw xhr;
|
||||
}
|
||||
|
||||
// Session displaced — another login took over this account
|
||||
if (xhr?.status === 401 && xhr?.responseJSON?.code === 'signed_elsewhere') {
|
||||
bootbox.alert('<strong>Signed in from another device.</strong><br>Your session has been ended because this account was signed in elsewhere.', function() {
|
||||
window.location.href = app_base_url() + 'index.php';
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// Session ended on the server (idle timeout, not signed in, password changed):
|
||||
// drop per-tab data and go back to the sign-in form.
|
||||
const endedCodes = ['session_expired', 'auth_required', 'password_changed'];
|
||||
if (xhr?.status === 401 && endedCodes.includes(xhr?.responseJSON?.code)) {
|
||||
try { sessionStorage.clear(); } catch (e) {}
|
||||
bootbox.alert(escape_html(xhr.responseJSON.message || 'Please sign in again.'), function() {
|
||||
window.location.href = app_base_url() + 'login/index.php';
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// File / payload too large (nginx 413)
|
||||
if (xhr?.status === 413) {
|
||||
bootbox.alert('The file you selected is too large. Please use an image under 2 MB and try again.');
|
||||
options.onError?.(xhr, 'payload_too_large');
|
||||
throw xhr;
|
||||
}
|
||||
|
||||
// Usage limit reached — show upgrade notice instead of generic error
|
||||
if (xhr?.status === 402) {
|
||||
const d = xhr?.responseJSON ?? {};
|
||||
const daily = d.daily_limit > 0 ? `Daily: <strong>${d.daily_count} / ${d.daily_limit}</strong>` : null;
|
||||
const weekly = d.weekly_limit > 0 ? `Weekly: <strong>${d.weekly_count} / ${d.weekly_limit}</strong>` : null;
|
||||
const detail = [daily, weekly].filter(Boolean).join(' | ');
|
||||
bootbox.alert(
|
||||
`<strong>Usage limit reached.</strong><br>${detail}<br><br>` +
|
||||
`Reports are locked until the quota resets. Upgrade your package for higher limits.`
|
||||
);
|
||||
options.onError?.(xhr, 'limit_reached');
|
||||
throw xhr;
|
||||
}
|
||||
|
||||
// Extract server's error message from JSON response
|
||||
let serverMessage = xhr?.responseJSON?.message;
|
||||
|
||||
// Fallback: parse responseText if responseJSON isn't set
|
||||
if (!serverMessage && xhr?.responseText) {
|
||||
try {
|
||||
serverMessage = JSON.parse(xhr.responseText)?.message;
|
||||
} catch (e) {
|
||||
// Response wasn't JSON — real server crash or HTML error page
|
||||
}
|
||||
}
|
||||
|
||||
if (serverMessage) {
|
||||
if (options.noAlert !== true) bootbox.alert(serverMessage);
|
||||
options.onError?.(xhr, serverMessage);
|
||||
} else {
|
||||
console.error("AJAX Error:", xhr?.status, xhr?.responseText);
|
||||
if (options.noAlert !== true) bootbox.alert("Server error occurred.");
|
||||
options.onError?.(xhr, null);
|
||||
}
|
||||
|
||||
throw xhr;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/** =========================
|
||||
* REAL-TIME REQUIRED VALIDATION
|
||||
* ========================= */
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
|
||||
const required_inputs = document.querySelectorAll('[required]');
|
||||
|
||||
required_inputs.forEach(input => {
|
||||
input.addEventListener('input', function () {
|
||||
if (this.value.trim() !== "") {
|
||||
this.classList.remove('is-invalid');
|
||||
this.classList.add('is-valid');
|
||||
} else {
|
||||
this.classList.remove('is-valid');
|
||||
this.classList.add('is-invalid');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
@@ -1,38 +1,3 @@
|
||||
function escape_html(value) {
|
||||
return String(value ?? '').replace(/[&<>"']/g, function(c) {
|
||||
return {'&':'&','<':'<','>':'>','"':'"',"'":'''}[c];
|
||||
});
|
||||
}
|
||||
|
||||
// Text is stored HTML-escaped (see db_statement in dbconn.php), which is right
|
||||
// for anything written into markup but wrong inside a form field: a note saved
|
||||
// as 5" pipe <spare> came back as 5" pipe <spare>. Field values
|
||||
// are never parsed as HTML, so decoding them here is safe.
|
||||
function decode_html(value) {
|
||||
if (typeof value !== 'string' || value.indexOf('&') === -1) return value;
|
||||
return value.replace(/&(quot|#0*39|#x0*27|apos|lt|gt|amp);/gi, function (m, name) {
|
||||
name = name.toLowerCase();
|
||||
if (name === 'quot') return '"';
|
||||
if (name === 'lt') return '<';
|
||||
if (name === 'gt') return '>';
|
||||
if (name === 'amp') return '&';
|
||||
return "'";
|
||||
});
|
||||
}
|
||||
|
||||
(function ($) {
|
||||
if (!$ || !$.fn || $.fn.val.__decodes_html) return;
|
||||
var original_val = $.fn.val;
|
||||
$.fn.val = function (value) {
|
||||
if (arguments.length && typeof value === 'string') {
|
||||
// Only free-text fields; a <select> value must keep matching its option.
|
||||
var text_fields = this.filter('input, textarea');
|
||||
if (text_fields.length === this.length) return original_val.call(this, decode_html(value));
|
||||
}
|
||||
return original_val.apply(this, arguments);
|
||||
};
|
||||
$.fn.val.__decodes_html = true;
|
||||
})(window.jQuery);
|
||||
|
||||
/** =========================
|
||||
* SIDEBAR ACTIVE STATE
|
||||
@@ -93,10 +58,6 @@ function debounce(fn, wait) {
|
||||
* ========================= */
|
||||
$(function () {
|
||||
|
||||
// Prevent all forms from refreshing the page
|
||||
$("form").on("submit", function (e) {
|
||||
e.preventDefault();
|
||||
});
|
||||
|
||||
// Initialize autocomplete for product search inputs
|
||||
init_product_search_inputs();
|
||||
@@ -678,289 +639,6 @@ function populate_dept_filter(select_id) {
|
||||
});
|
||||
}
|
||||
|
||||
function prepare_form_data(check_required, raw_data) {
|
||||
|
||||
var q = {};
|
||||
|
||||
// Get session context
|
||||
const session_element = document.getElementById('session-context');
|
||||
|
||||
if (session_element) {
|
||||
q['company_id'] = session_element.dataset.companyId;
|
||||
q['otp'] = session_element.dataset.otp;
|
||||
}
|
||||
|
||||
// Include GET parameters
|
||||
const url_params = new URLSearchParams(window.location.search);
|
||||
url_params.forEach((value, key) => {
|
||||
q[key] = value;
|
||||
});
|
||||
|
||||
// Collect form inputs (exclude search inputs — UI-only filters, not API data)
|
||||
$(".form-control:not([type=search]), .form-select").each(function () {
|
||||
if (!$(this).attr("id")) return true;
|
||||
var el = $(this).get(0);
|
||||
if (!el || !el.nodeName) return true;
|
||||
q[$(this).attr("id")] = $(this).val();
|
||||
});
|
||||
|
||||
// Validate required fields
|
||||
if (check_required === 1) {
|
||||
|
||||
const required_inputs = document.querySelectorAll('[required]');
|
||||
let is_valid = true;
|
||||
|
||||
required_inputs.forEach(input => {
|
||||
if (!input.value.trim()) {
|
||||
input.classList.add('is-invalid');
|
||||
is_valid = false;
|
||||
} else {
|
||||
input.classList.remove('is-invalid');
|
||||
input.classList.add('is-valid');
|
||||
}
|
||||
});
|
||||
|
||||
if (!is_valid) {
|
||||
alert("Please fill in all mandatory fields.");
|
||||
isAjaxProcessing = false;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return (raw_data) ? q : JSON.stringify(q);
|
||||
}
|
||||
|
||||
|
||||
/** =========================
|
||||
* AJAX WRAPPER
|
||||
* ========================= */
|
||||
|
||||
// Prevent double firing
|
||||
let isAjaxProcessing = false;
|
||||
|
||||
function ajax_request(options) {
|
||||
|
||||
if (isAjaxProcessing && options.queueLock !== false) {
|
||||
// Instead of rejecting, we just return a "never-ending" promise
|
||||
// or a resolved promise that does nothing.
|
||||
console.warn("Request is busy... ignoring click.");
|
||||
return new Promise(() => { }); // This stays pending and won't trigger .then or .catch
|
||||
}
|
||||
|
||||
if (options.queueLock !== false) {
|
||||
isAjaxProcessing = true;
|
||||
}
|
||||
|
||||
// Auto prepare form data
|
||||
if (options.autoPrepare === true) {
|
||||
|
||||
let payloadJson = prepare_form_data(options.checkRequired ?? 0, true);
|
||||
if (payloadJson === false) {
|
||||
isAjaxProcessing = false;
|
||||
return Promise.reject("validation_failed");
|
||||
}
|
||||
|
||||
if (options.data) {
|
||||
Object.entries(options.data).forEach(([key, value]) => {
|
||||
payloadJson[key] = value;
|
||||
});
|
||||
}
|
||||
|
||||
if (options.action) {
|
||||
// modify action
|
||||
if (options.action === 'manage') {
|
||||
options.action = (payloadJson['id']) ? 'update' : 'create';
|
||||
}
|
||||
// add action to JSON
|
||||
payloadJson['action'] = options.action;
|
||||
} else {
|
||||
isAjaxProcessing = false;
|
||||
return Promise.reject("please_define_action");
|
||||
}
|
||||
|
||||
options.data = { json: JSON.stringify(payloadJson) };
|
||||
|
||||
if (options.debugMode) {
|
||||
isAjaxProcessing = false;
|
||||
// Show FormData contents if applicable
|
||||
if (options.formData instanceof FormData) {
|
||||
// Log original formData before merging
|
||||
for (let [key, value] of options.formData.entries()) {
|
||||
console.log("FORMDATA: " + key, value);
|
||||
}
|
||||
}
|
||||
// Show stringified JSON payload
|
||||
console.log("REQUEST DATA:", options.data);
|
||||
}
|
||||
|
||||
// IF formData exist, we pass as $_POST [not json]
|
||||
if (options.formData instanceof FormData) {
|
||||
// THE BYPASS: If formData exists, move all text data into it
|
||||
Object.entries(payloadJson).forEach(([key, value]) => {
|
||||
options.formData.append(key, value);
|
||||
});
|
||||
// Override options.data with the full FormData object
|
||||
options.data = options.formData;
|
||||
}
|
||||
|
||||
} else if (
|
||||
options.data && !(options.data instanceof FormData) &&
|
||||
typeof options.data === 'object' && !('json' in options.data)
|
||||
) {
|
||||
|
||||
// autoPrepare: false with a plain field map — e.g. the delete buttons'
|
||||
// `data: { id: id }`. db_auth.php only accepts a `json` string or a
|
||||
// FormData post carrying `otp`, so an unwrapped map was rejected outright
|
||||
// with "Request denied: No valid JSON payload or Form Data detected.", and
|
||||
// `options.action` was dropped because only the autoPrepare branch applied
|
||||
// it. Wrap it the same way here, without touching callers that already
|
||||
// pass a ready-made `{ json: ... }`.
|
||||
const session_element = document.getElementById('session-context');
|
||||
const payload = {};
|
||||
|
||||
if (session_element) {
|
||||
payload['company_id'] = session_element.dataset.companyId;
|
||||
payload['otp'] = session_element.dataset.otp;
|
||||
}
|
||||
|
||||
Object.entries(options.data).forEach(([key, value]) => {
|
||||
payload[key] = value;
|
||||
});
|
||||
|
||||
if (options.action) {
|
||||
payload['action'] = (options.action === 'manage')
|
||||
? (payload['id'] ? 'update' : 'create')
|
||||
: options.action;
|
||||
}
|
||||
|
||||
options.data = { json: JSON.stringify(payload) };
|
||||
|
||||
if (options.debugMode) {
|
||||
console.log("REQUEST DATA:", options.data);
|
||||
}
|
||||
}
|
||||
|
||||
// --- START MODIFIED $.AJAX BLOCK ---
|
||||
let isSendingFiles = (options.data instanceof FormData);
|
||||
|
||||
// Show loading overlay
|
||||
if (options.noLoading !== true) {
|
||||
$.LoadingOverlay("show", {
|
||||
imageColor: "#525252",
|
||||
imageAnimation: "2s rotate_right",
|
||||
background: "rgba(255,255,255,0.8)"
|
||||
});
|
||||
}
|
||||
|
||||
return $.ajax({
|
||||
async: true,
|
||||
type: options.type || "POST",
|
||||
url: options.url,
|
||||
data: options.data,
|
||||
dataType: "json",
|
||||
// These two settings are only triggered when sending files
|
||||
processData: isSendingFiles ? false : true,
|
||||
contentType: isSendingFiles ? false : "application/x-www-form-urlencoded; charset=UTF-8",
|
||||
// for CSRF validation
|
||||
headers: {
|
||||
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
|
||||
}
|
||||
|
||||
})
|
||||
.then(function (res) {
|
||||
|
||||
isAjaxProcessing = false;
|
||||
if (options.noLoading !== true) $.LoadingOverlay("hide");
|
||||
|
||||
if (options.debugMode) {
|
||||
console.log("RESPONSE:", res);
|
||||
return res;
|
||||
}
|
||||
|
||||
if (!res || res.success != 1) {
|
||||
if (options.noAlert !== true) bootbox.alert(res?.message || "Unexpected error");
|
||||
options.onError?.(null, res?.message || 'api_failed');
|
||||
throw new Error(res?.message || "api_failed");
|
||||
}
|
||||
|
||||
options.onSuccess?.(res);
|
||||
return res;
|
||||
|
||||
})
|
||||
.catch(function (xhr) {
|
||||
|
||||
isAjaxProcessing = false;
|
||||
$.LoadingOverlay("hide");
|
||||
|
||||
// Errors re-thrown from .then() — pass through
|
||||
if (xhr instanceof Error) {
|
||||
throw xhr;
|
||||
}
|
||||
|
||||
// Session displaced — another login took over this account
|
||||
if (xhr?.status === 401 && xhr?.responseJSON?.code === 'signed_elsewhere') {
|
||||
bootbox.alert('<strong>Signed in from another device.</strong><br>Your session has been ended because this account was signed in elsewhere.', function() {
|
||||
window.location.href = server_url + 'index.php';
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// Session ended on the server (idle timeout, not signed in, password changed):
|
||||
// drop per-tab data and go back to the sign-in form.
|
||||
const endedCodes = ['session_expired', 'auth_required', 'password_changed'];
|
||||
if (xhr?.status === 401 && endedCodes.includes(xhr?.responseJSON?.code)) {
|
||||
try { sessionStorage.clear(); } catch (e) {}
|
||||
bootbox.alert(escape_html(xhr.responseJSON.message || 'Please sign in again.'), function() {
|
||||
window.location.href = server_url + 'login/index.php';
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// File / payload too large (nginx 413)
|
||||
if (xhr?.status === 413) {
|
||||
bootbox.alert('The file you selected is too large. Please use an image under 2 MB and try again.');
|
||||
options.onError?.(xhr, 'payload_too_large');
|
||||
throw xhr;
|
||||
}
|
||||
|
||||
// Usage limit reached — show upgrade notice instead of generic error
|
||||
if (xhr?.status === 402) {
|
||||
const d = xhr?.responseJSON ?? {};
|
||||
const daily = d.daily_limit > 0 ? `Daily: <strong>${d.daily_count} / ${d.daily_limit}</strong>` : null;
|
||||
const weekly = d.weekly_limit > 0 ? `Weekly: <strong>${d.weekly_count} / ${d.weekly_limit}</strong>` : null;
|
||||
const detail = [daily, weekly].filter(Boolean).join(' | ');
|
||||
bootbox.alert(
|
||||
`<strong>Usage limit reached.</strong><br>${detail}<br><br>` +
|
||||
`Reports are locked until the quota resets. Upgrade your package for higher limits.`
|
||||
);
|
||||
options.onError?.(xhr, 'limit_reached');
|
||||
throw xhr;
|
||||
}
|
||||
|
||||
// Extract server's error message from JSON response
|
||||
let serverMessage = xhr?.responseJSON?.message;
|
||||
|
||||
// Fallback: parse responseText if responseJSON isn't set
|
||||
if (!serverMessage && xhr?.responseText) {
|
||||
try {
|
||||
serverMessage = JSON.parse(xhr.responseText)?.message;
|
||||
} catch (e) {
|
||||
// Response wasn't JSON — real server crash or HTML error page
|
||||
}
|
||||
}
|
||||
|
||||
if (serverMessage) {
|
||||
if (options.noAlert !== true) bootbox.alert(serverMessage);
|
||||
options.onError?.(xhr, serverMessage);
|
||||
} else {
|
||||
console.error("AJAX Error:", xhr?.status, xhr?.responseText);
|
||||
if (options.noAlert !== true) bootbox.alert("Server error occurred.");
|
||||
options.onError?.(xhr, null);
|
||||
}
|
||||
|
||||
throw xhr;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/** =========================
|
||||
@@ -1057,26 +735,6 @@ flatpickr(".flatpickr", {
|
||||
});
|
||||
|
||||
|
||||
/** =========================
|
||||
* REAL-TIME REQUIRED VALIDATION
|
||||
* ========================= */
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
|
||||
const required_inputs = document.querySelectorAll('[required]');
|
||||
|
||||
required_inputs.forEach(input => {
|
||||
input.addEventListener('input', function () {
|
||||
if (this.value.trim() !== "") {
|
||||
this.classList.remove('is-invalid');
|
||||
this.classList.add('is-valid');
|
||||
} else {
|
||||
this.classList.remove('is-valid');
|
||||
this.classList.add('is-invalid');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
/**
|
||||
* page_headers.php — security headers for HTML pages (app pages, sign-in pages).
|
||||
*
|
||||
* Call send_page_security_headers() before any output. The Content-Security-Policy
|
||||
* lists what the pages actually load:
|
||||
* - scripts, styles, fonts and data files are all self-hosted under assets/vendor/
|
||||
* (versions in assets/vendor/VERSIONS.json), so no CDN host is allowed;
|
||||
* - the Node.js real-time server (NODE_PUBLIC_URL) serves socket.io.js and the
|
||||
* WebSocket connection;
|
||||
* - 'unsafe-inline' because pages use inline <script> blocks and onclick=
|
||||
* handlers; 'unsafe-eval' because alasql compiles its queries with new Function.
|
||||
*/
|
||||
|
||||
if (!function_exists('send_page_security_headers')) {
|
||||
function send_page_security_headers(): void {
|
||||
if (headers_sent()) return;
|
||||
|
||||
$script = ["'self'", "'unsafe-inline'", "'unsafe-eval'"];
|
||||
$connect = ["'self'"];
|
||||
|
||||
if (defined('NODE_PUBLIC_URL')) {
|
||||
$node = parse_url(NODE_PUBLIC_URL);
|
||||
if (!empty($node['scheme']) && !empty($node['host'])) {
|
||||
$origin = $node['host'] . (isset($node['port']) ? ':' . $node['port'] : '');
|
||||
$secure = strtolower($node['scheme']) === 'https';
|
||||
$script[] = ($secure ? 'https://' : 'http://') . $origin;
|
||||
$connect[] = ($secure ? 'https://' : 'http://') . $origin;
|
||||
$connect[] = ($secure ? 'wss://' : 'ws://') . $origin;
|
||||
}
|
||||
}
|
||||
|
||||
$csp = implode('; ', [
|
||||
"default-src 'self'",
|
||||
'script-src ' . implode(' ', $script),
|
||||
"style-src 'self' 'unsafe-inline'",
|
||||
"font-src 'self' data:",
|
||||
"img-src 'self' data: blob:",
|
||||
"media-src 'self' blob:",
|
||||
'connect-src ' . implode(' ', $connect),
|
||||
"worker-src 'self' blob:",
|
||||
"frame-src 'self' blob:",
|
||||
"object-src 'none'",
|
||||
"base-uri 'self'",
|
||||
"form-action 'self'",
|
||||
"frame-ancestors 'self'",
|
||||
]);
|
||||
|
||||
header('Content-Security-Policy: ' . $csp, true);
|
||||
header('X-Content-Type-Options: nosniff', true);
|
||||
header('X-Frame-Options: SAMEORIGIN', true);
|
||||
header('Referrer-Policy: strict-origin-when-cross-origin', true);
|
||||
}
|
||||
}
|
||||
Vendored
+35
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"resolved": {
|
||||
"apexcharts": "7.5.1",
|
||||
"flatpickr": "4.6.13",
|
||||
"dropzone": "5.9.3",
|
||||
"chart.js": "4.5.1",
|
||||
"world_countries_lists": "3.3.0"
|
||||
},
|
||||
"files": {
|
||||
"jquery/3.7.1/jquery.min.js": "https://code.jquery.com/jquery-3.7.1.min.js",
|
||||
"popper/2.11.8/popper.min.js": "https://cdn.jsdelivr.net/npm/@popperjs/core@2.11.8/dist/umd/popper.min.js",
|
||||
"bootstrap/5.3.8/bootstrap.min.js": "https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/js/bootstrap.min.js",
|
||||
"bootstrap/5.3.8/bootstrap.min.css": "https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/css/bootstrap.min.css",
|
||||
"bootbox/4.4.0/bootbox.min.js": "https://cdnjs.cloudflare.com/ajax/libs/bootbox.js/4.4.0/bootbox.min.js",
|
||||
"loadingoverlay/2.1.7/loadingoverlay.min.js": "https://cdn.jsdelivr.net/npm/gasparesganga-jquery-loading-overlay@2.1.7/dist/loadingoverlay.min.js",
|
||||
"flatpickr/4.6.13/flatpickr.min.js": "https://cdn.jsdelivr.net/npm/flatpickr@4.6.13/dist/flatpickr.min.js",
|
||||
"flatpickr/4.6.13/flatpickr.min.css": "https://cdn.jsdelivr.net/npm/flatpickr@4.6.13/dist/flatpickr.min.css",
|
||||
"flatpickr/4.6.13/plugins/monthSelect/index.js": "https://cdn.jsdelivr.net/npm/flatpickr@4.6.13/dist/plugins/monthSelect/index.js",
|
||||
"flatpickr/4.6.13/plugins/monthSelect/style.css": "https://cdn.jsdelivr.net/npm/flatpickr@4.6.13/dist/plugins/monthSelect/style.css",
|
||||
"jquery-ui/1.14.1/jquery-ui.min.js": "https://code.jquery.com/ui/1.14.1/jquery-ui.min.js",
|
||||
"jquery-ui/1.14.1/jquery-ui.css": "https://code.jquery.com/ui/1.14.1/themes/base/jquery-ui.css",
|
||||
"alasql/4.6.6/alasql.min.js": "https://cdnjs.cloudflare.com/ajax/libs/alasql/4.6.6/alasql.min.js",
|
||||
"dropzone/5.9.3/dropzone.min.js": "https://cdn.jsdelivr.net/npm/dropzone@5.9.3/dist/min/dropzone.min.js",
|
||||
"apexcharts/7.5.1/apexcharts.min.js": "https://cdn.jsdelivr.net/npm/apexcharts@7.5.1/dist/apexcharts.min.js",
|
||||
"html5-qrcode/2.3.8/html5-qrcode.min.js": "https://cdnjs.cloudflare.com/ajax/libs/html5-qrcode/2.3.8/html5-qrcode.min.js",
|
||||
"zxcvbn/4.4.2/zxcvbn.js": "https://cdn.jsdelivr.net/npm/zxcvbn@4.4.2/dist/zxcvbn.js",
|
||||
"jsbarcode/3.11.6/JsBarcode.all.min.js": "https://cdn.jsdelivr.net/npm/jsbarcode@3.11.6/dist/JsBarcode.all.min.js",
|
||||
"xlsx/0.18.5/xlsx.full.min.js": "https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.18.5/xlsx.full.min.js",
|
||||
"jspdf/2.5.1/jspdf.umd.min.js": "https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js",
|
||||
"jspdf-autotable/3.8.2/jspdf.plugin.autotable.min.js": "https://cdnjs.cloudflare.com/ajax/libs/jspdf-autotable/3.8.2/jspdf.plugin.autotable.min.js",
|
||||
"chart.js/4.5.1/chart.umd.min.js": "https://cdn.jsdelivr.net/npm/chart.js@4.5.1/dist/chart.umd.min.js",
|
||||
"tabler-icons/3.35.0/tabler-icons.min.css": "https://cdnjs.cloudflare.com/ajax/libs/tabler-icons/3.35.0/tabler-icons.min.css",
|
||||
"world_countries_lists/3.3.0/countries.json": "https://cdn.jsdelivr.net/npm/world_countries_lists@3.3.0/data/countries/en/countries.json"
|
||||
}
|
||||
}
|
||||
+264
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,301 @@
|
||||
(function (global, factory) {
|
||||
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
|
||||
typeof define === 'function' && define.amd ? define(factory) :
|
||||
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.monthSelectPlugin = factory());
|
||||
}(this, (function () { 'use strict';
|
||||
|
||||
/*! *****************************************************************************
|
||||
Copyright (c) Microsoft Corporation.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||||
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
PERFORMANCE OF THIS SOFTWARE.
|
||||
***************************************************************************** */
|
||||
|
||||
var __assign = function() {
|
||||
__assign = Object.assign || function __assign(t) {
|
||||
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
||||
s = arguments[i];
|
||||
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
|
||||
}
|
||||
return t;
|
||||
};
|
||||
return __assign.apply(this, arguments);
|
||||
};
|
||||
|
||||
var monthToStr = function (monthNumber, shorthand, locale) { return locale.months[shorthand ? "shorthand" : "longhand"][monthNumber]; };
|
||||
|
||||
function clearNode(node) {
|
||||
while (node.firstChild)
|
||||
node.removeChild(node.firstChild);
|
||||
}
|
||||
function getEventTarget(event) {
|
||||
try {
|
||||
if (typeof event.composedPath === "function") {
|
||||
var path = event.composedPath();
|
||||
return path[0];
|
||||
}
|
||||
return event.target;
|
||||
}
|
||||
catch (error) {
|
||||
return event.target;
|
||||
}
|
||||
}
|
||||
|
||||
var defaultConfig = {
|
||||
shorthand: false,
|
||||
dateFormat: "F Y",
|
||||
altFormat: "F Y",
|
||||
theme: "light",
|
||||
};
|
||||
function monthSelectPlugin(pluginConfig) {
|
||||
var config = __assign(__assign({}, defaultConfig), pluginConfig);
|
||||
return function (fp) {
|
||||
fp.config.dateFormat = config.dateFormat;
|
||||
fp.config.altFormat = config.altFormat;
|
||||
var self = { monthsContainer: null };
|
||||
function clearUnnecessaryDOMElements() {
|
||||
if (!fp.rContainer)
|
||||
return;
|
||||
clearNode(fp.rContainer);
|
||||
for (var index = 0; index < fp.monthElements.length; index++) {
|
||||
var element = fp.monthElements[index];
|
||||
if (!element.parentNode)
|
||||
continue;
|
||||
element.parentNode.removeChild(element);
|
||||
}
|
||||
}
|
||||
function build() {
|
||||
if (!fp.rContainer)
|
||||
return;
|
||||
self.monthsContainer = fp._createElement("div", "flatpickr-monthSelect-months");
|
||||
self.monthsContainer.tabIndex = -1;
|
||||
buildMonths();
|
||||
fp.rContainer.appendChild(self.monthsContainer);
|
||||
fp.calendarContainer.classList.add("flatpickr-monthSelect-theme-" + config.theme);
|
||||
}
|
||||
function buildMonths() {
|
||||
if (!self.monthsContainer)
|
||||
return;
|
||||
clearNode(self.monthsContainer);
|
||||
var frag = document.createDocumentFragment();
|
||||
for (var i = 0; i < 12; i++) {
|
||||
var month = fp.createDay("flatpickr-monthSelect-month", new Date(fp.currentYear, i), 0, i);
|
||||
if (month.dateObj.getMonth() === new Date().getMonth() &&
|
||||
month.dateObj.getFullYear() === new Date().getFullYear())
|
||||
month.classList.add("today");
|
||||
month.textContent = monthToStr(i, config.shorthand, fp.l10n);
|
||||
month.addEventListener("click", selectMonth);
|
||||
frag.appendChild(month);
|
||||
}
|
||||
self.monthsContainer.appendChild(frag);
|
||||
if (fp.config.minDate &&
|
||||
fp.currentYear === fp.config.minDate.getFullYear())
|
||||
fp.prevMonthNav.classList.add("flatpickr-disabled");
|
||||
else
|
||||
fp.prevMonthNav.classList.remove("flatpickr-disabled");
|
||||
if (fp.config.maxDate &&
|
||||
fp.currentYear === fp.config.maxDate.getFullYear())
|
||||
fp.nextMonthNav.classList.add("flatpickr-disabled");
|
||||
else
|
||||
fp.nextMonthNav.classList.remove("flatpickr-disabled");
|
||||
}
|
||||
function bindEvents() {
|
||||
fp._bind(fp.prevMonthNav, "click", function (e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
fp.changeYear(fp.currentYear - 1);
|
||||
selectYear();
|
||||
buildMonths();
|
||||
});
|
||||
fp._bind(fp.nextMonthNav, "click", function (e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
fp.changeYear(fp.currentYear + 1);
|
||||
selectYear();
|
||||
buildMonths();
|
||||
});
|
||||
fp._bind(self.monthsContainer, "mouseover", function (e) {
|
||||
if (fp.config.mode === "range")
|
||||
fp.onMouseOver(getEventTarget(e), "flatpickr-monthSelect-month");
|
||||
});
|
||||
}
|
||||
function setCurrentlySelected() {
|
||||
if (!fp.rContainer)
|
||||
return;
|
||||
if (!fp.selectedDates.length)
|
||||
return;
|
||||
var currentlySelected = fp.rContainer.querySelectorAll(".flatpickr-monthSelect-month.selected");
|
||||
for (var index = 0; index < currentlySelected.length; index++) {
|
||||
currentlySelected[index].classList.remove("selected");
|
||||
}
|
||||
var targetMonth = fp.selectedDates[0].getMonth();
|
||||
var month = fp.rContainer.querySelector(".flatpickr-monthSelect-month:nth-child(" + (targetMonth + 1) + ")");
|
||||
if (month) {
|
||||
month.classList.add("selected");
|
||||
}
|
||||
}
|
||||
function selectYear() {
|
||||
var selectedDate = fp.selectedDates[0];
|
||||
if (selectedDate) {
|
||||
selectedDate = new Date(selectedDate);
|
||||
selectedDate.setFullYear(fp.currentYear);
|
||||
if (fp.config.minDate && selectedDate < fp.config.minDate) {
|
||||
selectedDate = fp.config.minDate;
|
||||
}
|
||||
if (fp.config.maxDate && selectedDate > fp.config.maxDate) {
|
||||
selectedDate = fp.config.maxDate;
|
||||
}
|
||||
fp.currentYear = selectedDate.getFullYear();
|
||||
}
|
||||
fp.currentYearElement.value = String(fp.currentYear);
|
||||
if (fp.rContainer) {
|
||||
var months = fp.rContainer.querySelectorAll(".flatpickr-monthSelect-month");
|
||||
months.forEach(function (month) {
|
||||
month.dateObj.setFullYear(fp.currentYear);
|
||||
if ((fp.config.minDate && month.dateObj < fp.config.minDate) ||
|
||||
(fp.config.maxDate && month.dateObj > fp.config.maxDate)) {
|
||||
month.classList.add("flatpickr-disabled");
|
||||
}
|
||||
else {
|
||||
month.classList.remove("flatpickr-disabled");
|
||||
}
|
||||
});
|
||||
}
|
||||
setCurrentlySelected();
|
||||
}
|
||||
function selectMonth(e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
var eventTarget = getEventTarget(e);
|
||||
if (!(eventTarget instanceof Element))
|
||||
return;
|
||||
if (eventTarget.classList.contains("flatpickr-disabled"))
|
||||
return;
|
||||
if (eventTarget.classList.contains("notAllowed"))
|
||||
return; // necessary??
|
||||
setMonth(eventTarget.dateObj);
|
||||
if (fp.config.closeOnSelect) {
|
||||
var single = fp.config.mode === "single";
|
||||
var range = fp.config.mode === "range" && fp.selectedDates.length === 2;
|
||||
if (single || range)
|
||||
fp.close();
|
||||
}
|
||||
}
|
||||
function setMonth(date) {
|
||||
var selectedDate = new Date(fp.currentYear, date.getMonth(), date.getDate());
|
||||
var selectedDates = [];
|
||||
switch (fp.config.mode) {
|
||||
case "single":
|
||||
selectedDates = [selectedDate];
|
||||
break;
|
||||
case "multiple":
|
||||
selectedDates.push(selectedDate);
|
||||
break;
|
||||
case "range":
|
||||
if (fp.selectedDates.length === 2) {
|
||||
selectedDates = [selectedDate];
|
||||
}
|
||||
else {
|
||||
selectedDates = fp.selectedDates.concat([selectedDate]);
|
||||
selectedDates.sort(function (a, b) { return a.getTime() - b.getTime(); });
|
||||
}
|
||||
break;
|
||||
}
|
||||
fp.setDate(selectedDates, true);
|
||||
setCurrentlySelected();
|
||||
}
|
||||
var shifts = {
|
||||
37: -1,
|
||||
39: 1,
|
||||
40: 3,
|
||||
38: -3,
|
||||
};
|
||||
function onKeyDown(_, __, ___, e) {
|
||||
var shouldMove = shifts[e.keyCode] !== undefined;
|
||||
if (!shouldMove && e.keyCode !== 13) {
|
||||
return;
|
||||
}
|
||||
if (!fp.rContainer || !self.monthsContainer)
|
||||
return;
|
||||
var currentlySelected = fp.rContainer.querySelector(".flatpickr-monthSelect-month.selected");
|
||||
var index = Array.prototype.indexOf.call(self.monthsContainer.children, document.activeElement);
|
||||
if (index === -1) {
|
||||
var target = currentlySelected || self.monthsContainer.firstElementChild;
|
||||
target.focus();
|
||||
index = target.$i;
|
||||
}
|
||||
if (shouldMove) {
|
||||
self.monthsContainer.children[(12 + index + shifts[e.keyCode]) % 12].focus();
|
||||
}
|
||||
else if (e.keyCode === 13 &&
|
||||
self.monthsContainer.contains(document.activeElement)) {
|
||||
setMonth(document.activeElement.dateObj);
|
||||
}
|
||||
}
|
||||
function closeHook() {
|
||||
var _a;
|
||||
if (((_a = fp.config) === null || _a === void 0 ? void 0 : _a.mode) === "range" && fp.selectedDates.length === 1)
|
||||
fp.clear(false);
|
||||
if (!fp.selectedDates.length)
|
||||
buildMonths();
|
||||
}
|
||||
// Help the prev/next year nav honor config.minDate (see 3fa5a69)
|
||||
function stubCurrentMonth() {
|
||||
config._stubbedCurrentMonth = fp._initialDate.getMonth();
|
||||
fp._initialDate.setMonth(config._stubbedCurrentMonth);
|
||||
fp.currentMonth = config._stubbedCurrentMonth;
|
||||
}
|
||||
function unstubCurrentMonth() {
|
||||
if (!config._stubbedCurrentMonth)
|
||||
return;
|
||||
fp._initialDate.setMonth(config._stubbedCurrentMonth);
|
||||
fp.currentMonth = config._stubbedCurrentMonth;
|
||||
delete config._stubbedCurrentMonth;
|
||||
}
|
||||
function destroyPluginInstance() {
|
||||
if (self.monthsContainer !== null) {
|
||||
var months = self.monthsContainer.querySelectorAll(".flatpickr-monthSelect-month");
|
||||
for (var index = 0; index < months.length; index++) {
|
||||
months[index].removeEventListener("click", selectMonth);
|
||||
}
|
||||
}
|
||||
}
|
||||
return {
|
||||
onParseConfig: function () {
|
||||
fp.config.enableTime = false;
|
||||
},
|
||||
onValueUpdate: setCurrentlySelected,
|
||||
onKeyDown: onKeyDown,
|
||||
onReady: [
|
||||
stubCurrentMonth,
|
||||
clearUnnecessaryDOMElements,
|
||||
build,
|
||||
bindEvents,
|
||||
setCurrentlySelected,
|
||||
function () {
|
||||
fp.config.onClose.push(closeHook);
|
||||
fp.loadedPlugins.push("monthSelect");
|
||||
},
|
||||
],
|
||||
onDestroy: [
|
||||
unstubCurrentMonth,
|
||||
destroyPluginInstance,
|
||||
function () {
|
||||
fp.config.onClose = fp.config.onClose.filter(function (hook) { return hook !== closeHook; });
|
||||
},
|
||||
],
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
return monthSelectPlugin;
|
||||
|
||||
})));
|
||||
@@ -0,0 +1,117 @@
|
||||
.flatpickr-monthSelect-months {
|
||||
margin: 10px 1px 3px 1px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.flatpickr-monthSelect-month {
|
||||
background: none;
|
||||
border: 1px solid transparent;
|
||||
border-radius: 4px;
|
||||
-webkit-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
color: #393939;
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
font-weight: 400;
|
||||
margin: 0.5px;
|
||||
justify-content: center;
|
||||
padding: 10px;
|
||||
position: relative;
|
||||
-webkit-box-pack: center;
|
||||
-webkit-justify-content: center;
|
||||
-ms-flex-pack: center;
|
||||
text-align: center;
|
||||
width: 33%;
|
||||
}
|
||||
|
||||
.flatpickr-monthSelect-month.flatpickr-disabled {
|
||||
color: #eee;
|
||||
}
|
||||
|
||||
.flatpickr-monthSelect-month.flatpickr-disabled:hover,
|
||||
.flatpickr-monthSelect-month.flatpickr-disabled:focus {
|
||||
cursor: not-allowed;
|
||||
background: none !important;
|
||||
}
|
||||
|
||||
.flatpickr-monthSelect-theme-dark {
|
||||
background: #3f4458;
|
||||
}
|
||||
|
||||
.flatpickr-monthSelect-theme-dark .flatpickr-current-month input.cur-year {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.flatpickr-monthSelect-theme-dark .flatpickr-months .flatpickr-prev-month,
|
||||
.flatpickr-monthSelect-theme-dark .flatpickr-months .flatpickr-next-month {
|
||||
color: #fff;
|
||||
fill: #fff;
|
||||
}
|
||||
|
||||
.flatpickr-monthSelect-theme-dark .flatpickr-monthSelect-month {
|
||||
color: rgba(255, 255, 255, 0.95);
|
||||
}
|
||||
|
||||
.flatpickr-monthSelect-month.today {
|
||||
border-color: #959ea9;
|
||||
}
|
||||
|
||||
.flatpickr-monthSelect-month.inRange,
|
||||
.flatpickr-monthSelect-month.inRange.today,
|
||||
.flatpickr-monthSelect-month:hover,
|
||||
.flatpickr-monthSelect-month:focus {
|
||||
background: #e6e6e6;
|
||||
cursor: pointer;
|
||||
outline: 0;
|
||||
border-color: #e6e6e6;
|
||||
}
|
||||
|
||||
.flatpickr-monthSelect-theme-dark .flatpickr-monthSelect-month.inRange,
|
||||
.flatpickr-monthSelect-theme-dark .flatpickr-monthSelect-month:hover,
|
||||
.flatpickr-monthSelect-theme-dark .flatpickr-monthSelect-month:focus {
|
||||
background: #646c8c;
|
||||
border-color: #646c8c;
|
||||
}
|
||||
|
||||
.flatpickr-monthSelect-month.today:hover,
|
||||
.flatpickr-monthSelect-month.today:focus {
|
||||
background: #959ea9;
|
||||
border-color: #959ea9;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.flatpickr-monthSelect-month.selected,
|
||||
.flatpickr-monthSelect-month.startRange,
|
||||
.flatpickr-monthSelect-month.endRange {
|
||||
background-color: #569ff7;
|
||||
box-shadow: none;
|
||||
color: #fff;
|
||||
border-color: #569ff7;
|
||||
}
|
||||
|
||||
.flatpickr-monthSelect-month.startRange {
|
||||
border-radius: 50px 0 0 50px;
|
||||
}
|
||||
|
||||
.flatpickr-monthSelect-month.endRange {
|
||||
border-radius: 0 50px 50px 0;
|
||||
}
|
||||
|
||||
.flatpickr-monthSelect-month.startRange.endRange {
|
||||
border-radius: 50px;
|
||||
}
|
||||
|
||||
.flatpickr-monthSelect-month.inRange {
|
||||
border-radius: 0;
|
||||
box-shadow: -5px 0 0 #e6e6e6, 5px 0 0 #e6e6e6;
|
||||
}
|
||||
|
||||
.flatpickr-monthSelect-theme-dark .flatpickr-monthSelect-month.selected,
|
||||
.flatpickr-monthSelect-theme-dark .flatpickr-monthSelect-month.startRange,
|
||||
.flatpickr-monthSelect-theme-dark .flatpickr-monthSelect-month.endRange {
|
||||
background: #80cbc4;
|
||||
-webkit-box-shadow: none;
|
||||
box-shadow: none;
|
||||
color: #fff;
|
||||
border-color: #80cbc4;
|
||||
}
|
||||
+324
@@ -0,0 +1,324 @@
|
||||
/* latin-ext */
|
||||
@font-face {
|
||||
font-family: 'Poppins';
|
||||
font-style: italic;
|
||||
font-weight: 100;
|
||||
font-display: swap;
|
||||
src: url(pxiAyp8kv8JHgFVrJJLmE0tMMPKzSQ.woff2) format('woff2');
|
||||
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
||||
}
|
||||
/* latin */
|
||||
@font-face {
|
||||
font-family: 'Poppins';
|
||||
font-style: italic;
|
||||
font-weight: 100;
|
||||
font-display: swap;
|
||||
src: url(pxiAyp8kv8JHgFVrJJLmE0tCMPI.woff2) format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||
}
|
||||
/* latin-ext */
|
||||
@font-face {
|
||||
font-family: 'Poppins';
|
||||
font-style: italic;
|
||||
font-weight: 200;
|
||||
font-display: swap;
|
||||
src: url(pxiDyp8kv8JHgFVrJJLmv1pVGdeOcEg.woff2) format('woff2');
|
||||
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
||||
}
|
||||
/* latin */
|
||||
@font-face {
|
||||
font-family: 'Poppins';
|
||||
font-style: italic;
|
||||
font-weight: 200;
|
||||
font-display: swap;
|
||||
src: url(pxiDyp8kv8JHgFVrJJLmv1pVF9eO.woff2) format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||
}
|
||||
/* latin-ext */
|
||||
@font-face {
|
||||
font-family: 'Poppins';
|
||||
font-style: italic;
|
||||
font-weight: 300;
|
||||
font-display: swap;
|
||||
src: url(pxiDyp8kv8JHgFVrJJLm21lVGdeOcEg.woff2) format('woff2');
|
||||
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
||||
}
|
||||
/* latin */
|
||||
@font-face {
|
||||
font-family: 'Poppins';
|
||||
font-style: italic;
|
||||
font-weight: 300;
|
||||
font-display: swap;
|
||||
src: url(pxiDyp8kv8JHgFVrJJLm21lVF9eO.woff2) format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||
}
|
||||
/* latin-ext */
|
||||
@font-face {
|
||||
font-family: 'Poppins';
|
||||
font-style: italic;
|
||||
font-weight: 400;
|
||||
font-display: swap;
|
||||
src: url(pxiGyp8kv8JHgFVrJJLufntAKPY.woff2) format('woff2');
|
||||
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
||||
}
|
||||
/* latin */
|
||||
@font-face {
|
||||
font-family: 'Poppins';
|
||||
font-style: italic;
|
||||
font-weight: 400;
|
||||
font-display: swap;
|
||||
src: url(pxiGyp8kv8JHgFVrJJLucHtA.woff2) format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||
}
|
||||
/* latin-ext */
|
||||
@font-face {
|
||||
font-family: 'Poppins';
|
||||
font-style: italic;
|
||||
font-weight: 500;
|
||||
font-display: swap;
|
||||
src: url(pxiDyp8kv8JHgFVrJJLmg1hVGdeOcEg.woff2) format('woff2');
|
||||
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
||||
}
|
||||
/* latin */
|
||||
@font-face {
|
||||
font-family: 'Poppins';
|
||||
font-style: italic;
|
||||
font-weight: 500;
|
||||
font-display: swap;
|
||||
src: url(pxiDyp8kv8JHgFVrJJLmg1hVF9eO.woff2) format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||
}
|
||||
/* latin-ext */
|
||||
@font-face {
|
||||
font-family: 'Poppins';
|
||||
font-style: italic;
|
||||
font-weight: 600;
|
||||
font-display: swap;
|
||||
src: url(pxiDyp8kv8JHgFVrJJLmr19VGdeOcEg.woff2) format('woff2');
|
||||
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
||||
}
|
||||
/* latin */
|
||||
@font-face {
|
||||
font-family: 'Poppins';
|
||||
font-style: italic;
|
||||
font-weight: 600;
|
||||
font-display: swap;
|
||||
src: url(pxiDyp8kv8JHgFVrJJLmr19VF9eO.woff2) format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||
}
|
||||
/* latin-ext */
|
||||
@font-face {
|
||||
font-family: 'Poppins';
|
||||
font-style: italic;
|
||||
font-weight: 700;
|
||||
font-display: swap;
|
||||
src: url(pxiDyp8kv8JHgFVrJJLmy15VGdeOcEg.woff2) format('woff2');
|
||||
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
||||
}
|
||||
/* latin */
|
||||
@font-face {
|
||||
font-family: 'Poppins';
|
||||
font-style: italic;
|
||||
font-weight: 700;
|
||||
font-display: swap;
|
||||
src: url(pxiDyp8kv8JHgFVrJJLmy15VF9eO.woff2) format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||
}
|
||||
/* latin-ext */
|
||||
@font-face {
|
||||
font-family: 'Poppins';
|
||||
font-style: italic;
|
||||
font-weight: 800;
|
||||
font-display: swap;
|
||||
src: url(pxiDyp8kv8JHgFVrJJLm111VGdeOcEg.woff2) format('woff2');
|
||||
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
||||
}
|
||||
/* latin */
|
||||
@font-face {
|
||||
font-family: 'Poppins';
|
||||
font-style: italic;
|
||||
font-weight: 800;
|
||||
font-display: swap;
|
||||
src: url(pxiDyp8kv8JHgFVrJJLm111VF9eO.woff2) format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||
}
|
||||
/* latin-ext */
|
||||
@font-face {
|
||||
font-family: 'Poppins';
|
||||
font-style: italic;
|
||||
font-weight: 900;
|
||||
font-display: swap;
|
||||
src: url(pxiDyp8kv8JHgFVrJJLm81xVGdeOcEg.woff2) format('woff2');
|
||||
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
||||
}
|
||||
/* latin */
|
||||
@font-face {
|
||||
font-family: 'Poppins';
|
||||
font-style: italic;
|
||||
font-weight: 900;
|
||||
font-display: swap;
|
||||
src: url(pxiDyp8kv8JHgFVrJJLm81xVF9eO.woff2) format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||
}
|
||||
/* latin-ext */
|
||||
@font-face {
|
||||
font-family: 'Poppins';
|
||||
font-style: normal;
|
||||
font-weight: 100;
|
||||
font-display: swap;
|
||||
src: url(pxiGyp8kv8JHgFVrLPTufntAKPY.woff2) format('woff2');
|
||||
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
||||
}
|
||||
/* latin */
|
||||
@font-face {
|
||||
font-family: 'Poppins';
|
||||
font-style: normal;
|
||||
font-weight: 100;
|
||||
font-display: swap;
|
||||
src: url(pxiGyp8kv8JHgFVrLPTucHtA.woff2) format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||
}
|
||||
/* latin-ext */
|
||||
@font-face {
|
||||
font-family: 'Poppins';
|
||||
font-style: normal;
|
||||
font-weight: 200;
|
||||
font-display: swap;
|
||||
src: url(pxiByp8kv8JHgFVrLFj_Z1JlFc-K.woff2) format('woff2');
|
||||
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
||||
}
|
||||
/* latin */
|
||||
@font-face {
|
||||
font-family: 'Poppins';
|
||||
font-style: normal;
|
||||
font-weight: 200;
|
||||
font-display: swap;
|
||||
src: url(pxiByp8kv8JHgFVrLFj_Z1xlFQ.woff2) format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||
}
|
||||
/* latin-ext */
|
||||
@font-face {
|
||||
font-family: 'Poppins';
|
||||
font-style: normal;
|
||||
font-weight: 300;
|
||||
font-display: swap;
|
||||
src: url(pxiByp8kv8JHgFVrLDz8Z1JlFc-K.woff2) format('woff2');
|
||||
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
||||
}
|
||||
/* latin */
|
||||
@font-face {
|
||||
font-family: 'Poppins';
|
||||
font-style: normal;
|
||||
font-weight: 300;
|
||||
font-display: swap;
|
||||
src: url(pxiByp8kv8JHgFVrLDz8Z1xlFQ.woff2) format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||
}
|
||||
/* latin-ext */
|
||||
@font-face {
|
||||
font-family: 'Poppins';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-display: swap;
|
||||
src: url(pxiEyp8kv8JHgFVrJJnecmNE.woff2) format('woff2');
|
||||
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
||||
}
|
||||
/* latin */
|
||||
@font-face {
|
||||
font-family: 'Poppins';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-display: swap;
|
||||
src: url(pxiEyp8kv8JHgFVrJJfecg.woff2) format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||
}
|
||||
/* latin-ext */
|
||||
@font-face {
|
||||
font-family: 'Poppins';
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
font-display: swap;
|
||||
src: url(pxiByp8kv8JHgFVrLGT9Z1JlFc-K.woff2) format('woff2');
|
||||
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
||||
}
|
||||
/* latin */
|
||||
@font-face {
|
||||
font-family: 'Poppins';
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
font-display: swap;
|
||||
src: url(pxiByp8kv8JHgFVrLGT9Z1xlFQ.woff2) format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||
}
|
||||
/* latin-ext */
|
||||
@font-face {
|
||||
font-family: 'Poppins';
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
font-display: swap;
|
||||
src: url(pxiByp8kv8JHgFVrLEj6Z1JlFc-K.woff2) format('woff2');
|
||||
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
||||
}
|
||||
/* latin */
|
||||
@font-face {
|
||||
font-family: 'Poppins';
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
font-display: swap;
|
||||
src: url(pxiByp8kv8JHgFVrLEj6Z1xlFQ.woff2) format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||
}
|
||||
/* latin-ext */
|
||||
@font-face {
|
||||
font-family: 'Poppins';
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
font-display: swap;
|
||||
src: url(pxiByp8kv8JHgFVrLCz7Z1JlFc-K.woff2) format('woff2');
|
||||
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
||||
}
|
||||
/* latin */
|
||||
@font-face {
|
||||
font-family: 'Poppins';
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
font-display: swap;
|
||||
src: url(pxiByp8kv8JHgFVrLCz7Z1xlFQ.woff2) format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||
}
|
||||
/* latin-ext */
|
||||
@font-face {
|
||||
font-family: 'Poppins';
|
||||
font-style: normal;
|
||||
font-weight: 800;
|
||||
font-display: swap;
|
||||
src: url(pxiByp8kv8JHgFVrLDD4Z1JlFc-K.woff2) format('woff2');
|
||||
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
||||
}
|
||||
/* latin */
|
||||
@font-face {
|
||||
font-family: 'Poppins';
|
||||
font-style: normal;
|
||||
font-weight: 800;
|
||||
font-display: swap;
|
||||
src: url(pxiByp8kv8JHgFVrLDD4Z1xlFQ.woff2) format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||
}
|
||||
/* latin-ext */
|
||||
@font-face {
|
||||
font-family: 'Poppins';
|
||||
font-style: normal;
|
||||
font-weight: 900;
|
||||
font-display: swap;
|
||||
src: url(pxiByp8kv8JHgFVrLBT5Z1JlFc-K.woff2) format('woff2');
|
||||
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
||||
}
|
||||
/* latin */
|
||||
@font-face {
|
||||
font-family: 'Poppins';
|
||||
font-style: normal;
|
||||
font-weight: 900;
|
||||
font-display: swap;
|
||||
src: url(pxiByp8kv8JHgFVrLBT5Z1xlFQ.woff2) format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because one or more lines are too long
Binary file not shown.
|
After Width: | Height: | Size: 6.8 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 6.8 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 4.4 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 6.8 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 4.4 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 6.3 KiB |
+1284
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+397
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Binary file not shown.
File diff suppressed because one or more lines are too long
@@ -0,0 +1,193 @@
|
||||
[{"id":4,"alpha2":"af","alpha3":"afg","name":"Afghanistan"},
|
||||
{"id":8,"alpha2":"al","alpha3":"alb","name":"Albania"},
|
||||
{"id":12,"alpha2":"dz","alpha3":"dza","name":"Algeria"},
|
||||
{"id":20,"alpha2":"ad","alpha3":"and","name":"Andorra"},
|
||||
{"id":24,"alpha2":"ao","alpha3":"ago","name":"Angola"},
|
||||
{"id":28,"alpha2":"ag","alpha3":"atg","name":"Antigua and Barbuda"},
|
||||
{"id":32,"alpha2":"ar","alpha3":"arg","name":"Argentina"},
|
||||
{"id":51,"alpha2":"am","alpha3":"arm","name":"Armenia"},
|
||||
{"id":36,"alpha2":"au","alpha3":"aus","name":"Australia"},
|
||||
{"id":40,"alpha2":"at","alpha3":"aut","name":"Austria"},
|
||||
{"id":31,"alpha2":"az","alpha3":"aze","name":"Azerbaijan"},
|
||||
{"id":44,"alpha2":"bs","alpha3":"bhs","name":"Bahamas"},
|
||||
{"id":48,"alpha2":"bh","alpha3":"bhr","name":"Bahrain"},
|
||||
{"id":50,"alpha2":"bd","alpha3":"bgd","name":"Bangladesh"},
|
||||
{"id":52,"alpha2":"bb","alpha3":"brb","name":"Barbados"},
|
||||
{"id":112,"alpha2":"by","alpha3":"blr","name":"Belarus"},
|
||||
{"id":56,"alpha2":"be","alpha3":"bel","name":"Belgium"},
|
||||
{"id":84,"alpha2":"bz","alpha3":"blz","name":"Belize"},
|
||||
{"id":204,"alpha2":"bj","alpha3":"ben","name":"Benin"},
|
||||
{"id":64,"alpha2":"bt","alpha3":"btn","name":"Bhutan"},
|
||||
{"id":68,"alpha2":"bo","alpha3":"bol","name":"Bolivia, Plurinational State of"},
|
||||
{"id":70,"alpha2":"ba","alpha3":"bih","name":"Bosnia and Herzegovina"},
|
||||
{"id":72,"alpha2":"bw","alpha3":"bwa","name":"Botswana"},
|
||||
{"id":76,"alpha2":"br","alpha3":"bra","name":"Brazil"},
|
||||
{"id":96,"alpha2":"bn","alpha3":"brn","name":"Brunei Darussalam"},
|
||||
{"id":100,"alpha2":"bg","alpha3":"bgr","name":"Bulgaria"},
|
||||
{"id":854,"alpha2":"bf","alpha3":"bfa","name":"Burkina Faso"},
|
||||
{"id":108,"alpha2":"bi","alpha3":"bdi","name":"Burundi"},
|
||||
{"id":132,"alpha2":"cv","alpha3":"cpv","name":"Cabo Verde"},
|
||||
{"id":116,"alpha2":"kh","alpha3":"khm","name":"Cambodia"},
|
||||
{"id":120,"alpha2":"cm","alpha3":"cmr","name":"Cameroon"},
|
||||
{"id":124,"alpha2":"ca","alpha3":"can","name":"Canada"},
|
||||
{"id":140,"alpha2":"cf","alpha3":"caf","name":"Central African Republic"},
|
||||
{"id":148,"alpha2":"td","alpha3":"tcd","name":"Chad"},
|
||||
{"id":152,"alpha2":"cl","alpha3":"chl","name":"Chile"},
|
||||
{"id":156,"alpha2":"cn","alpha3":"chn","name":"China"},
|
||||
{"id":170,"alpha2":"co","alpha3":"col","name":"Colombia"},
|
||||
{"id":174,"alpha2":"km","alpha3":"com","name":"Comoros"},
|
||||
{"id":178,"alpha2":"cg","alpha3":"cog","name":"Congo"},
|
||||
{"id":180,"alpha2":"cd","alpha3":"cod","name":"Congo, Democratic Republic of the"},
|
||||
{"id":188,"alpha2":"cr","alpha3":"cri","name":"Costa Rica"},
|
||||
{"id":384,"alpha2":"ci","alpha3":"civ","name":"Côte d'Ivoire"},
|
||||
{"id":191,"alpha2":"hr","alpha3":"hrv","name":"Croatia"},
|
||||
{"id":192,"alpha2":"cu","alpha3":"cub","name":"Cuba"},
|
||||
{"id":196,"alpha2":"cy","alpha3":"cyp","name":"Cyprus"},
|
||||
{"id":203,"alpha2":"cz","alpha3":"cze","name":"Czechia"},
|
||||
{"id":208,"alpha2":"dk","alpha3":"dnk","name":"Denmark"},
|
||||
{"id":262,"alpha2":"dj","alpha3":"dji","name":"Djibouti"},
|
||||
{"id":212,"alpha2":"dm","alpha3":"dma","name":"Dominica"},
|
||||
{"id":214,"alpha2":"do","alpha3":"dom","name":"Dominican Republic"},
|
||||
{"id":218,"alpha2":"ec","alpha3":"ecu","name":"Ecuador"},
|
||||
{"id":818,"alpha2":"eg","alpha3":"egy","name":"Egypt"},
|
||||
{"id":222,"alpha2":"sv","alpha3":"slv","name":"El Salvador"},
|
||||
{"id":226,"alpha2":"gq","alpha3":"gnq","name":"Equatorial Guinea"},
|
||||
{"id":232,"alpha2":"er","alpha3":"eri","name":"Eritrea"},
|
||||
{"id":233,"alpha2":"ee","alpha3":"est","name":"Estonia"},
|
||||
{"id":748,"alpha2":"sz","alpha3":"swz","name":"Eswatini"},
|
||||
{"id":231,"alpha2":"et","alpha3":"eth","name":"Ethiopia"},
|
||||
{"id":242,"alpha2":"fj","alpha3":"fji","name":"Fiji"},
|
||||
{"id":246,"alpha2":"fi","alpha3":"fin","name":"Finland"},
|
||||
{"id":250,"alpha2":"fr","alpha3":"fra","name":"France"},
|
||||
{"id":266,"alpha2":"ga","alpha3":"gab","name":"Gabon"},
|
||||
{"id":270,"alpha2":"gm","alpha3":"gmb","name":"Gambia"},
|
||||
{"id":268,"alpha2":"ge","alpha3":"geo","name":"Georgia"},
|
||||
{"id":276,"alpha2":"de","alpha3":"deu","name":"Germany"},
|
||||
{"id":288,"alpha2":"gh","alpha3":"gha","name":"Ghana"},
|
||||
{"id":300,"alpha2":"gr","alpha3":"grc","name":"Greece"},
|
||||
{"id":308,"alpha2":"gd","alpha3":"grd","name":"Grenada"},
|
||||
{"id":320,"alpha2":"gt","alpha3":"gtm","name":"Guatemala"},
|
||||
{"id":324,"alpha2":"gn","alpha3":"gin","name":"Guinea"},
|
||||
{"id":624,"alpha2":"gw","alpha3":"gnb","name":"Guinea-Bissau"},
|
||||
{"id":328,"alpha2":"gy","alpha3":"guy","name":"Guyana"},
|
||||
{"id":332,"alpha2":"ht","alpha3":"hti","name":"Haiti"},
|
||||
{"id":340,"alpha2":"hn","alpha3":"hnd","name":"Honduras"},
|
||||
{"id":348,"alpha2":"hu","alpha3":"hun","name":"Hungary"},
|
||||
{"id":352,"alpha2":"is","alpha3":"isl","name":"Iceland"},
|
||||
{"id":356,"alpha2":"in","alpha3":"ind","name":"India"},
|
||||
{"id":360,"alpha2":"id","alpha3":"idn","name":"Indonesia"},
|
||||
{"id":364,"alpha2":"ir","alpha3":"irn","name":"Iran, Islamic Republic of"},
|
||||
{"id":368,"alpha2":"iq","alpha3":"irq","name":"Iraq"},
|
||||
{"id":372,"alpha2":"ie","alpha3":"irl","name":"Ireland"},
|
||||
{"id":376,"alpha2":"il","alpha3":"isr","name":"Israel"},
|
||||
{"id":380,"alpha2":"it","alpha3":"ita","name":"Italy"},
|
||||
{"id":388,"alpha2":"jm","alpha3":"jam","name":"Jamaica"},
|
||||
{"id":392,"alpha2":"jp","alpha3":"jpn","name":"Japan"},
|
||||
{"id":400,"alpha2":"jo","alpha3":"jor","name":"Jordan"},
|
||||
{"id":398,"alpha2":"kz","alpha3":"kaz","name":"Kazakhstan"},
|
||||
{"id":404,"alpha2":"ke","alpha3":"ken","name":"Kenya"},
|
||||
{"id":296,"alpha2":"ki","alpha3":"kir","name":"Kiribati"},
|
||||
{"id":408,"alpha2":"kp","alpha3":"prk","name":"Korea, Democratic People's Republic of"},
|
||||
{"id":410,"alpha2":"kr","alpha3":"kor","name":"Korea, Republic of"},
|
||||
{"id":414,"alpha2":"kw","alpha3":"kwt","name":"Kuwait"},
|
||||
{"id":417,"alpha2":"kg","alpha3":"kgz","name":"Kyrgyzstan"},
|
||||
{"id":418,"alpha2":"la","alpha3":"lao","name":"Lao People's Democratic Republic"},
|
||||
{"id":428,"alpha2":"lv","alpha3":"lva","name":"Latvia"},
|
||||
{"id":422,"alpha2":"lb","alpha3":"lbn","name":"Lebanon"},
|
||||
{"id":426,"alpha2":"ls","alpha3":"lso","name":"Lesotho"},
|
||||
{"id":430,"alpha2":"lr","alpha3":"lbr","name":"Liberia"},
|
||||
{"id":434,"alpha2":"ly","alpha3":"lby","name":"Libya"},
|
||||
{"id":438,"alpha2":"li","alpha3":"lie","name":"Liechtenstein"},
|
||||
{"id":440,"alpha2":"lt","alpha3":"ltu","name":"Lithuania"},
|
||||
{"id":442,"alpha2":"lu","alpha3":"lux","name":"Luxembourg"},
|
||||
{"id":450,"alpha2":"mg","alpha3":"mdg","name":"Madagascar"},
|
||||
{"id":454,"alpha2":"mw","alpha3":"mwi","name":"Malawi"},
|
||||
{"id":458,"alpha2":"my","alpha3":"mys","name":"Malaysia"},
|
||||
{"id":462,"alpha2":"mv","alpha3":"mdv","name":"Maldives"},
|
||||
{"id":466,"alpha2":"ml","alpha3":"mli","name":"Mali"},
|
||||
{"id":470,"alpha2":"mt","alpha3":"mlt","name":"Malta"},
|
||||
{"id":584,"alpha2":"mh","alpha3":"mhl","name":"Marshall Islands"},
|
||||
{"id":478,"alpha2":"mr","alpha3":"mrt","name":"Mauritania"},
|
||||
{"id":480,"alpha2":"mu","alpha3":"mus","name":"Mauritius"},
|
||||
{"id":484,"alpha2":"mx","alpha3":"mex","name":"Mexico"},
|
||||
{"id":583,"alpha2":"fm","alpha3":"fsm","name":"Micronesia, Federated States of"},
|
||||
{"id":498,"alpha2":"md","alpha3":"mda","name":"Moldova, Republic of"},
|
||||
{"id":492,"alpha2":"mc","alpha3":"mco","name":"Monaco"},
|
||||
{"id":496,"alpha2":"mn","alpha3":"mng","name":"Mongolia"},
|
||||
{"id":499,"alpha2":"me","alpha3":"mne","name":"Montenegro"},
|
||||
{"id":504,"alpha2":"ma","alpha3":"mar","name":"Morocco"},
|
||||
{"id":508,"alpha2":"mz","alpha3":"moz","name":"Mozambique"},
|
||||
{"id":104,"alpha2":"mm","alpha3":"mmr","name":"Myanmar"},
|
||||
{"id":516,"alpha2":"na","alpha3":"nam","name":"Namibia"},
|
||||
{"id":520,"alpha2":"nr","alpha3":"nru","name":"Nauru"},
|
||||
{"id":524,"alpha2":"np","alpha3":"npl","name":"Nepal"},
|
||||
{"id":528,"alpha2":"nl","alpha3":"nld","name":"Netherlands"},
|
||||
{"id":554,"alpha2":"nz","alpha3":"nzl","name":"New Zealand"},
|
||||
{"id":558,"alpha2":"ni","alpha3":"nic","name":"Nicaragua"},
|
||||
{"id":562,"alpha2":"ne","alpha3":"ner","name":"Niger"},
|
||||
{"id":566,"alpha2":"ng","alpha3":"nga","name":"Nigeria"},
|
||||
{"id":807,"alpha2":"mk","alpha3":"mkd","name":"North Macedonia"},
|
||||
{"id":578,"alpha2":"no","alpha3":"nor","name":"Norway"},
|
||||
{"id":512,"alpha2":"om","alpha3":"omn","name":"Oman"},
|
||||
{"id":586,"alpha2":"pk","alpha3":"pak","name":"Pakistan"},
|
||||
{"id":585,"alpha2":"pw","alpha3":"plw","name":"Palau"},
|
||||
{"id":591,"alpha2":"pa","alpha3":"pan","name":"Panama"},
|
||||
{"id":598,"alpha2":"pg","alpha3":"png","name":"Papua New Guinea"},
|
||||
{"id":600,"alpha2":"py","alpha3":"pry","name":"Paraguay"},
|
||||
{"id":604,"alpha2":"pe","alpha3":"per","name":"Peru"},
|
||||
{"id":608,"alpha2":"ph","alpha3":"phl","name":"Philippines"},
|
||||
{"id":616,"alpha2":"pl","alpha3":"pol","name":"Poland"},
|
||||
{"id":620,"alpha2":"pt","alpha3":"prt","name":"Portugal"},
|
||||
{"id":634,"alpha2":"qa","alpha3":"qat","name":"Qatar"},
|
||||
{"id":642,"alpha2":"ro","alpha3":"rou","name":"Romania"},
|
||||
{"id":643,"alpha2":"ru","alpha3":"rus","name":"Russian Federation"},
|
||||
{"id":646,"alpha2":"rw","alpha3":"rwa","name":"Rwanda"},
|
||||
{"id":659,"alpha2":"kn","alpha3":"kna","name":"Saint Kitts and Nevis"},
|
||||
{"id":662,"alpha2":"lc","alpha3":"lca","name":"Saint Lucia"},
|
||||
{"id":670,"alpha2":"vc","alpha3":"vct","name":"Saint Vincent and the Grenadines"},
|
||||
{"id":882,"alpha2":"ws","alpha3":"wsm","name":"Samoa"},
|
||||
{"id":674,"alpha2":"sm","alpha3":"smr","name":"San Marino"},
|
||||
{"id":678,"alpha2":"st","alpha3":"stp","name":"Sao Tome and Principe"},
|
||||
{"id":682,"alpha2":"sa","alpha3":"sau","name":"Saudi Arabia"},
|
||||
{"id":686,"alpha2":"sn","alpha3":"sen","name":"Senegal"},
|
||||
{"id":688,"alpha2":"rs","alpha3":"srb","name":"Serbia"},
|
||||
{"id":690,"alpha2":"sc","alpha3":"syc","name":"Seychelles"},
|
||||
{"id":694,"alpha2":"sl","alpha3":"sle","name":"Sierra Leone"},
|
||||
{"id":702,"alpha2":"sg","alpha3":"sgp","name":"Singapore"},
|
||||
{"id":703,"alpha2":"sk","alpha3":"svk","name":"Slovakia"},
|
||||
{"id":705,"alpha2":"si","alpha3":"svn","name":"Slovenia"},
|
||||
{"id":90,"alpha2":"sb","alpha3":"slb","name":"Solomon Islands"},
|
||||
{"id":706,"alpha2":"so","alpha3":"som","name":"Somalia"},
|
||||
{"id":710,"alpha2":"za","alpha3":"zaf","name":"South Africa"},
|
||||
{"id":728,"alpha2":"ss","alpha3":"ssd","name":"South Sudan"},
|
||||
{"id":724,"alpha2":"es","alpha3":"esp","name":"Spain"},
|
||||
{"id":144,"alpha2":"lk","alpha3":"lka","name":"Sri Lanka"},
|
||||
{"id":729,"alpha2":"sd","alpha3":"sdn","name":"Sudan"},
|
||||
{"id":740,"alpha2":"sr","alpha3":"sur","name":"Suriname"},
|
||||
{"id":752,"alpha2":"se","alpha3":"swe","name":"Sweden"},
|
||||
{"id":756,"alpha2":"ch","alpha3":"che","name":"Switzerland"},
|
||||
{"id":760,"alpha2":"sy","alpha3":"syr","name":"Syrian Arab Republic"},
|
||||
{"id":762,"alpha2":"tj","alpha3":"tjk","name":"Tajikistan"},
|
||||
{"id":834,"alpha2":"tz","alpha3":"tza","name":"Tanzania, United Republic of"},
|
||||
{"id":764,"alpha2":"th","alpha3":"tha","name":"Thailand"},
|
||||
{"id":626,"alpha2":"tl","alpha3":"tls","name":"Timor-Leste"},
|
||||
{"id":768,"alpha2":"tg","alpha3":"tgo","name":"Togo"},
|
||||
{"id":776,"alpha2":"to","alpha3":"ton","name":"Tonga"},
|
||||
{"id":780,"alpha2":"tt","alpha3":"tto","name":"Trinidad and Tobago"},
|
||||
{"id":788,"alpha2":"tn","alpha3":"tun","name":"Tunisia"},
|
||||
{"id":792,"alpha2":"tr","alpha3":"tur","name":"Türkiye"},
|
||||
{"id":795,"alpha2":"tm","alpha3":"tkm","name":"Turkmenistan"},
|
||||
{"id":798,"alpha2":"tv","alpha3":"tuv","name":"Tuvalu"},
|
||||
{"id":800,"alpha2":"ug","alpha3":"uga","name":"Uganda"},
|
||||
{"id":804,"alpha2":"ua","alpha3":"ukr","name":"Ukraine"},
|
||||
{"id":784,"alpha2":"ae","alpha3":"are","name":"United Arab Emirates"},
|
||||
{"id":826,"alpha2":"gb","alpha3":"gbr","name":"United Kingdom of Great Britain and Northern Ireland"},
|
||||
{"id":840,"alpha2":"us","alpha3":"usa","name":"United States of America"},
|
||||
{"id":858,"alpha2":"uy","alpha3":"ury","name":"Uruguay"},
|
||||
{"id":860,"alpha2":"uz","alpha3":"uzb","name":"Uzbekistan"},
|
||||
{"id":548,"alpha2":"vu","alpha3":"vut","name":"Vanuatu"},
|
||||
{"id":862,"alpha2":"ve","alpha3":"ven","name":"Venezuela, Bolivarian Republic of"},
|
||||
{"id":704,"alpha2":"vn","alpha3":"vnm","name":"Viet Nam"},
|
||||
{"id":887,"alpha2":"ye","alpha3":"yem","name":"Yemen"},
|
||||
{"id":894,"alpha2":"zm","alpha3":"zmb","name":"Zambia"},
|
||||
{"id":716,"alpha2":"zw","alpha3":"zwe","name":"Zimbabwe"}]
|
||||
+22
File diff suppressed because one or more lines are too long
+27
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user