Compare commits
5 commits
958598b07c
...
05a6c19264
Author | SHA1 | Date | |
---|---|---|---|
|
05a6c19264 | ||
|
28e6e167ee | ||
|
84716b4527 | ||
|
c7796ac341 | ||
|
81b902ea5d |
6
.codespell-exclusions
Normal file
|
@ -0,0 +1,6 @@
|
|||
.git
|
||||
./static/lib
|
||||
./vendor
|
||||
./locales/*/LC_MESSAGES/*.po
|
||||
./locales/*.js
|
||||
./locales/*.pot
|
16
.gitignore
vendored
Normal file
|
@ -0,0 +1,16 @@
|
|||
/config.local.yml
|
||||
# Ignore vim temporary/backup files
|
||||
*~
|
||||
.*.swp
|
||||
# Exclude composer installed libs
|
||||
/vendor
|
||||
/composer.lock
|
||||
# Common UNIX user home directory files
|
||||
/.bash*
|
||||
/.vim*
|
||||
/.composer
|
||||
/.gitconfig
|
||||
/.vim*
|
||||
/.less*
|
||||
/.ssh
|
||||
/.phplint-cache
|
7
.phplint.yml
Normal file
|
@ -0,0 +1,7 @@
|
|||
path: ./
|
||||
jobs: 10
|
||||
extensions:
|
||||
- php
|
||||
exclude:
|
||||
- vendor
|
||||
warning: true
|
33
.pre-commit-config.yaml
Normal file
|
@ -0,0 +1,33 @@
|
|||
# Pre-commit hooks to run tests and ensure code is cleaned.
|
||||
# See https://pre-commit.com for more information
|
||||
---
|
||||
repos:
|
||||
- repo: https://github.com/codespell-project/codespell
|
||||
rev: v2.2.2
|
||||
hooks:
|
||||
- id: codespell
|
||||
exclude: static/lib/|locales/.*\.js$|\.pot$
|
||||
#args: ["--write-changes"]
|
||||
exclude_types: [csv, json, pofile]
|
||||
- repo: https://github.com/adrienverge/yamllint
|
||||
rev: v1.32.0
|
||||
hooks:
|
||||
- id: yamllint
|
||||
ignore: .github/
|
||||
- repo: https://github.com/pre-commit/mirrors-prettier
|
||||
rev: v2.7.1
|
||||
hooks:
|
||||
- id: prettier
|
||||
- repo: https://github.com/digitalpulp/pre-commit-php.git
|
||||
rev: 1.4.0
|
||||
hooks:
|
||||
- id: php-stan
|
||||
files: ^(?!example/).*\.(php)$
|
||||
args: ["--configuration=phpstan.neon"]
|
||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||
rev: v4.4.0
|
||||
hooks:
|
||||
- id: check-executables-have-shebangs
|
||||
stages: [manual]
|
||||
- id: check-json
|
||||
exclude: (.vscode|.devcontainer)
|
2
.prettierignore
Normal file
|
@ -0,0 +1,2 @@
|
|||
/static/lib/*
|
||||
/locales/*
|
9
.yamllint.yaml
Normal file
|
@ -0,0 +1,9 @@
|
|||
extends: default
|
||||
|
||||
ignore: |
|
||||
static/lib/*
|
||||
|
||||
rules:
|
||||
line-length:
|
||||
max: 100
|
||||
level: warning
|
7
bin/manage
Executable file
|
@ -0,0 +1,7 @@
|
|||
#!/usr/bin/php
|
||||
<?php
|
||||
|
||||
use EesyPHP\Cli;
|
||||
|
||||
require realpath(dirname(__FILE__).'/..')."/includes/core.php";
|
||||
Cli :: handle_args();
|
29
composer.json
Normal file
|
@ -0,0 +1,29 @@
|
|||
{
|
||||
"name": "brenard/mysc",
|
||||
"description": "My Sweetcase",
|
||||
"type": "project",
|
||||
"require": {
|
||||
"brenard/eesyphp": "dev-master"
|
||||
},
|
||||
"license": "GPL3",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"MySC\\": "src/"
|
||||
}
|
||||
},
|
||||
"authors": [
|
||||
{
|
||||
"name": "Benjamin Renard",
|
||||
"email": "brenard@zionetrix.net"
|
||||
}
|
||||
],
|
||||
"minimum-stability": "dev",
|
||||
"config": {
|
||||
"allow-plugins": {
|
||||
"php-http/discovery": true
|
||||
}
|
||||
},
|
||||
"require-dev": {
|
||||
"phpstan/phpstan": "2.0.x-dev"
|
||||
}
|
||||
}
|
350
config.yml
Normal file
|
@ -0,0 +1,350 @@
|
|||
# Public root URL
|
||||
public_root_url: "/"
|
||||
|
||||
# Application root data directory
|
||||
data_directory: "${root_directory_path}/data"
|
||||
|
||||
# Temporary files root directory
|
||||
tmp_root_directory: "${data_directory}/tmp"
|
||||
|
||||
# Temporary uploading files directory (optional, default: PHP ini default)
|
||||
upload_tmp_directory: ${tmp_root_directory}/uploading"
|
||||
|
||||
# Uploading file size limit (in bytes, example: 104857600 == 100Mb)
|
||||
# (optional, default: PHP ini default)
|
||||
upload_max_filesize: 104857600
|
||||
|
||||
# Main pagetitle
|
||||
main_pagetitle: "Eesyphp"
|
||||
|
||||
# Debug Ajax request/response
|
||||
debug_ajax: false
|
||||
|
||||
#
|
||||
# Log configuration
|
||||
#
|
||||
log:
|
||||
# Logs directory path
|
||||
directory_path: "${data_directory}/logs"
|
||||
|
||||
# CLI log file path
|
||||
cli_file_path: "${log.directory_path}/cli.log"
|
||||
|
||||
# Log file path
|
||||
file_path: "${log.directory_path}/app.log"
|
||||
|
||||
# Log level (TRACE / DEBUG / INFO / WARNING / ERROR / FATAL)
|
||||
level: "INFO"
|
||||
|
||||
# Log PHP errors levels (as specified to set_error_handler())
|
||||
# Note: expected a list of PHP error level constants that will be resolved and combine
|
||||
# with a bitwise operator. After the first value, the bitwise operator "|" (OR) or "^" (XOR)
|
||||
# could be specified as contanst name prefix, otherwise the "&" (AND) operator will be used.
|
||||
# The constant name could also be prefix with "~" or "!" (NOT) bitwise operator.
|
||||
#
|
||||
# Default:
|
||||
# - In TRACE or DEBUG: E_ALL & ~E_STRICT
|
||||
# - Otherwise: E_ALL & ~E_NOTICE & ~E_STRICT & ~E_DEPRECATED
|
||||
#log_php_errors_levels:
|
||||
# - E_ALL
|
||||
# - ~E_NOTICE
|
||||
# - ~E_STRICT
|
||||
# - ~E_DEPRECATED
|
||||
|
||||
#
|
||||
# Sentry configuration
|
||||
#
|
||||
sentry:
|
||||
# Sentry DSN
|
||||
#dsn: null
|
||||
|
||||
# Log PHP errors in Sentry: list of errors types to logs
|
||||
# See: https://www.php.net/manual/fr/errorfunc.constants.php
|
||||
php_error_types:
|
||||
- "E_ERROR"
|
||||
- "E_PARSE"
|
||||
- "E_CORE_ERROR"
|
||||
- "E_COMPILE_ERROR"
|
||||
- "E_USER_ERROR"
|
||||
- "E_RECOVERABLE_ERROR"
|
||||
- "E_DEPRECATED"
|
||||
|
||||
# Traces sample rate (between 0 and 1)
|
||||
# Note: this parameter permit to determine how many transactions (=~ access) are traced and
|
||||
# sent to Sentry, for instance, 0.2 meen that 20% of the transactions will be traced. In dev
|
||||
# mode, set to 1 if you want all transactions are sent to Sentry.
|
||||
# Default: 0.2
|
||||
traces_sample_rate: 0.2
|
||||
|
||||
#
|
||||
# Smarty templates configuration
|
||||
#
|
||||
templates:
|
||||
# Smarty directories
|
||||
directory: "${root_directory_path}/templates"
|
||||
cache_directory: "${tmp_root_directory}/templates_c"
|
||||
# Theme CSS file
|
||||
included_css_files:
|
||||
#- css/custom.css
|
||||
included_js_files:
|
||||
#- js/custom.js
|
||||
|
||||
#
|
||||
# Translations
|
||||
#
|
||||
i18n:
|
||||
# Default locale (see locales directory for available languages list)
|
||||
default_locale: "en_US.UTF8"
|
||||
|
||||
#
|
||||
# Session
|
||||
#
|
||||
session:
|
||||
# Session timeout due to inactivity (in seconds)
|
||||
timeout: 1800
|
||||
# Session max duration (in seconds, default : 12h)
|
||||
max_duration: 43200
|
||||
# Directory path where to store PHP sessions data (optional, default: use system default)
|
||||
directory_path: "${data_directory}/sessions"
|
||||
|
||||
#
|
||||
# Database configuration
|
||||
#
|
||||
db:
|
||||
# Sqlite
|
||||
dsn: "sqlite:${data_directory}/db.sqlite3"
|
||||
options: null
|
||||
|
||||
# Date/Datetime format in database (strptime format)
|
||||
date_format: "%s"
|
||||
datetime_format: "%s"
|
||||
|
||||
# Postgresql
|
||||
#dsn: "pgsql:host=localhost;port=5432;dbname=items"
|
||||
#user: "items"
|
||||
#pwd: "items"
|
||||
#options: null
|
||||
|
||||
# Date/Datetime format in database (strptime format)
|
||||
#date_format: '%Y-%m-%d' # Example : 2018-10-12
|
||||
#datetime_format: '%Y-%m-%d %H:%M:%S' # Example : 2018-10-12 18:06:59
|
||||
|
||||
# MariaDB / MySQL
|
||||
#dsn: "mysql:host=localhost;dbname=items"
|
||||
#user: "items"
|
||||
#pwd: "items"
|
||||
#options: null
|
||||
|
||||
# Date/Datetime format in database (strptime format)
|
||||
#date_format: '%Y-%m-%d' # Example : 2018-10-12
|
||||
#datetime_format: '%Y-%m-%d %H:%M:%S' # Example : 2018-10-12 18:06:59
|
||||
|
||||
#
|
||||
# Authentication
|
||||
#
|
||||
auth:
|
||||
# Enabled authentication
|
||||
enabled: true
|
||||
|
||||
#
|
||||
# Login form
|
||||
#
|
||||
login_form:
|
||||
# Include application navbar (default: true)
|
||||
include_navbar: true
|
||||
|
||||
# Display link for other authentication methods
|
||||
# Note: method as key and label as value
|
||||
display_other_methods:
|
||||
http: "HTTP"
|
||||
cas: "SSO"
|
||||
|
||||
# Remember username
|
||||
# Enable the feature (default: true)
|
||||
# remember_username: true
|
||||
# Cookie name (default: remember_username)
|
||||
# remember_username_cookie_name: "remember_username"
|
||||
|
||||
#
|
||||
# HTTP Authentication Configuration
|
||||
#
|
||||
http:
|
||||
# HTTP Auth methods :
|
||||
# * AUTHORIZATION : use HTTP_AUTHORIZATION environment. This mode could be use with PHP FPM.
|
||||
# Specific configuration is need in Apache to use this mode :
|
||||
# RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
|
||||
# * REMOTE_USER : use REMOTE_USER environment variable to retrieve authenticated user's login
|
||||
# This method could be only used with $http_auth_trust_without_password_challenge
|
||||
# enabled.
|
||||
# * PHP_AUTH : use PHP_AUTH_USER and PHP_AUTH_PW environment variables (only available
|
||||
# using mod_php with Apache. (default)
|
||||
method: "PHP_AUTH"
|
||||
|
||||
# Trust HTTP server authentication
|
||||
# If enabled, the application will no check user credentials and only retrieve user's login
|
||||
# from HTTP server.
|
||||
#trust_without_password_challenge: true
|
||||
|
||||
# Realm (use when force HTTP login, optional)
|
||||
#realm: "Authentication required"
|
||||
|
||||
#
|
||||
# CAS Configuration
|
||||
#
|
||||
cas:
|
||||
# CAS host (just the domain name)
|
||||
host: "idp.example.com"
|
||||
|
||||
# CAS context (the root path, default: '/idp/cas')
|
||||
# Example: for 'http://idp.example.com/idp/cas', put '/idp/cas'
|
||||
context: "/idp/cas"
|
||||
|
||||
# CAS HTTP port (default: 443)
|
||||
#port: 443
|
||||
|
||||
# CAS procotol version
|
||||
# Possible values: "1.0", "2.0" (default), "3.0" or "S1" (SAML1)
|
||||
#version: '2.0'
|
||||
|
||||
# CAS server SSL certificate validation (set to false to disable)
|
||||
ca_cert_certificate_path: "/etc/ssl/certs/ca-certificates.crt"
|
||||
|
||||
# CAS Debug log file
|
||||
#debug_log_file: "${root_directory_path}/data/logs/cas.log"
|
||||
|
||||
# CAS Logout
|
||||
#logout: true # Enable CAS logout on app logout
|
||||
#logout_url: "https://my.example.fr/logout/" # Specify custom CAS logout URL
|
||||
|
||||
# CAS Fake authenticated user
|
||||
#fake_authenticated_user: 'myusername'
|
||||
|
||||
# CAS user attributes to retrieve with their properties:
|
||||
# [attr name]:
|
||||
# # CAS attribute name (optional, default: [attr name])
|
||||
# cas_name: [CAS attr name]
|
||||
# # Alternative CAS attribute name to retrieve if the first one is not defined (optional)
|
||||
# alt_cas_name: [alternative CAS attr name]
|
||||
# # Type of value (optional, default: 'string', possible values: string, bool, int, float)
|
||||
# type: [type of value]
|
||||
# # Default attribute value (optional, default: null)
|
||||
# default: null
|
||||
# Note: only used by casuser auth backend.
|
||||
user_attributes:
|
||||
login:
|
||||
cas_name: "uid"
|
||||
default: null
|
||||
name:
|
||||
cas_name: "displayName"
|
||||
cas_ldap_name: "cn"
|
||||
default: null
|
||||
mail:
|
||||
type: "string"
|
||||
|
||||
#
|
||||
# Database user backend
|
||||
#
|
||||
db:
|
||||
# Users table name (optional, default: users)
|
||||
#users_table: "users"
|
||||
# Username field name (optional, default: username)
|
||||
#username_field: "username"
|
||||
# Password field name (optional, default: password)
|
||||
#password_field: "password"
|
||||
# Exposed users table fields in resulting EesyPHP\Auth\User object
|
||||
# (optional, default: name, mail)
|
||||
#exposed_fields:
|
||||
# - "name"
|
||||
# - "mail"
|
||||
|
||||
#
|
||||
# LDAP user backend
|
||||
#
|
||||
ldap:
|
||||
# LDAP host (required, multiple hosts could be specified with comma separator)
|
||||
host: "ldap://localhost"
|
||||
|
||||
# LDAP port (optional)
|
||||
#port: 389
|
||||
|
||||
# Enable STARTTLS (optional, default: false)
|
||||
#starttls: false
|
||||
|
||||
# LDAP directory base DN (required)
|
||||
basedn: "o=example"
|
||||
|
||||
# LDAP bind DN (optional)
|
||||
#bind_dn: 'uid=eesyphp,ou=sysaccounts,${auth.ldap.basedn}'
|
||||
|
||||
# LDAP bind password (optional)
|
||||
#bind_password: 'secret'
|
||||
|
||||
# User search filter by username. The keyword "[username]" will be replace before search by
|
||||
# the looked username (default: "uid=[username]")
|
||||
#user_filter_by_uid: 'uid=[username]'
|
||||
|
||||
# User base DN
|
||||
user_basedn: "ou=people,${auth.ldap.basedn}"
|
||||
|
||||
# Bind with username instead of user DN (optional, default: false)
|
||||
#bind_with_username: true
|
||||
|
||||
# LDAP user attributes to retrieve with their properties:
|
||||
# [attr name]:
|
||||
# # LDAP attribute name (optional, default: [attr name])
|
||||
# ldap_name: [LDAP attr name]
|
||||
# # Alternative LDAP attribute name to retrieve if the first one is not defined (optional)
|
||||
# alt_ldap_name: [alternative LDAP attr name]
|
||||
# # Type of value (optional, default: 'string', possible values: string, bool, int, float)
|
||||
# type: [type of value]
|
||||
# # Multivalued attribute (optional, default: false)
|
||||
# multivalued: true
|
||||
# # Default attribute value (optional, default: null)
|
||||
# default: null
|
||||
user_attributes:
|
||||
login:
|
||||
ldap_name: "uid"
|
||||
multivalued: false
|
||||
default: null
|
||||
name:
|
||||
ldap_name: "displayName"
|
||||
alt_ldap_name: "cn"
|
||||
multivalued: false
|
||||
default: null
|
||||
mail:
|
||||
type: "string"
|
||||
|
||||
# PEAR Net_LDAP2 library path (optional, default: Net/LDAP2.php)
|
||||
#netldap2_path: 'Net/LDAP2.php'
|
||||
|
||||
#
|
||||
# Email configuration
|
||||
#
|
||||
email:
|
||||
# PHP PEAR Mail and Mail_Mine paths
|
||||
php_mail_path: "Mail.php"
|
||||
php_mail_mime_path: "Mail/mime.php"
|
||||
|
||||
# Sending method :
|
||||
# - mail : use PHP mail function
|
||||
# - sendmail : use sendmail system command
|
||||
# - smtp : use an SMTP server (PHP PEAR Net_SMTP required)
|
||||
send_method: "smtp"
|
||||
|
||||
# Sending parameters
|
||||
# See : http:#pear.php.net/manual/en/package.mail.mail.factory.php
|
||||
send_params: NULL
|
||||
|
||||
# Headers add to all e-mails sent
|
||||
headers:
|
||||
#- "CC: support@example.com"
|
||||
|
||||
# Email sender address (for all emails sent by the application)
|
||||
sender: "noreply@example.org"
|
||||
|
||||
# Catch all e-mails sent to a configured e-mail address
|
||||
catch_all: false
|
||||
# Web Stats JS code
|
||||
#webstats_js_code: ''
|
||||
|
||||
# vim: tabstop=2 shiftwidth=2 softtabstop=2 expandtab
|
1
data/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
db.sqlite3
|
2
data/logs/.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
*.log
|
||||
*.log.*
|
1
data/sessions/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
sess_*
|
46
data/sqlite.init-db.sql
Normal file
|
@ -0,0 +1,46 @@
|
|||
CREATE TABLE users (
|
||||
username text NOT NULL PRIMARY KEY,
|
||||
name text COLLATE NOCASE NOT NULL,
|
||||
mail text COLLATE NOCASE,
|
||||
password text NOT NULL
|
||||
);
|
||||
|
||||
INSERT INTO users (username, name, mail, password) VALUES (
|
||||
"admin", "Administrator", "admin@example.com",
|
||||
"$argon2id$v=19$m=65536,t=4,p=1$WTQ0di44NW11MUJ1b3RMQw$+LRAQRaIXE2jhfavNFNuxnEtEUT6tEBz/98pTtD0EnM"
|
||||
);
|
||||
|
||||
CREATE TABLE auth_tokens (
|
||||
token text NOT NULL PRIMARY KEY,
|
||||
username text NOT NULL REFERENCES users(username) ON UPDATE CASCADE ON DELETE CASCADE,
|
||||
creation_date REAL,
|
||||
expiration_date REAL
|
||||
);
|
||||
|
||||
CREATE TABLE scases (
|
||||
uuid text NOT NULL PRIMARY KEY,
|
||||
username text NOT NULL REFERENCES users(username) ON UPDATE CASCADE ON DELETE CASCADE,
|
||||
name text NOT NULL,
|
||||
last_change REAL NOT NULL,
|
||||
removed INTEGER NOT NULL
|
||||
FOREIGN KEY(username) REFERENCES artist(artistid)
|
||||
);
|
||||
|
||||
CREATE TABLE categories (
|
||||
uuid text NOT NULL PRIMARY KEY,
|
||||
scase_uuid text NOT NULL REFERENCES scases(uuid) ON UPDATE CASCADE ON DELETE CASCADE,
|
||||
name text NOT NULL,
|
||||
color text NOT NULL,
|
||||
last_change REAL NOT NULL,
|
||||
removed INTEGER NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE things (
|
||||
uuid text NOT NULL PRIMARY KEY,
|
||||
category_uuid text NOT NULL REFERENCES categories(uuid) ON UPDATE CASCADE ON DELETE CASCADE,
|
||||
label text NOT NULL,
|
||||
nb INTEGER NOT NULL,
|
||||
checked INTEGER NOT NULL,
|
||||
last_change REAL NOT NULL,
|
||||
removed INTEGER NOT NULL
|
||||
);
|
1
data/tmp/templates_c/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
*.tpl.php
|
77
includes/core.php
Normal file
|
@ -0,0 +1,77 @@
|
|||
<?php
|
||||
|
||||
use EesyPHP\App;
|
||||
use EesyPHP\Db;
|
||||
use EesyPHP\I18n;
|
||||
use EesyPHP\SentrySpan;
|
||||
|
||||
use MySC\Auth\API;
|
||||
|
||||
error_reporting(E_ALL & ~E_NOTICE & ~E_STRICT & ~E_DEPRECATED);
|
||||
|
||||
// Root directory path
|
||||
$script = null;
|
||||
if (defined('__FILE__') && constant('__FILE__')) { // @phpstan-ignore-line
|
||||
$script = __FILE__;
|
||||
}
|
||||
else {
|
||||
// Fallback method : detect path from core.php path
|
||||
foreach(get_included_files() as $script)
|
||||
if (basename($script) == 'core.php')
|
||||
break;
|
||||
}
|
||||
if (!$script) die('Failed to detect root directory path');
|
||||
$root_dir_path = realpath(dirname($script).'/../');
|
||||
|
||||
// Include App's includes and vendor directories to PHP include paths
|
||||
set_include_path($root_dir_path.'/includes' . PATH_SEPARATOR . get_include_path());
|
||||
|
||||
// Load composer autoload.php
|
||||
require("$root_dir_path/vendor/autoload.php");
|
||||
|
||||
// Initialize EesyPHP application
|
||||
App::init(
|
||||
"$root_dir_path/config.yml",
|
||||
array(
|
||||
'overwrite_config_files' => array(
|
||||
"$root_dir_path/config.local.yml",
|
||||
),
|
||||
'templates' => array(
|
||||
'static_directories' => array(
|
||||
"$root_dir_path/static"
|
||||
),
|
||||
),
|
||||
'auth' => array(
|
||||
'enabled' => true,
|
||||
'methods' => array(
|
||||
'\\MySC\\Auth\\API',
|
||||
),
|
||||
'backends' => array(
|
||||
'db',
|
||||
),
|
||||
),
|
||||
'default' => array(
|
||||
'auth' => array(
|
||||
'enabled' => true,
|
||||
'methods' => array(
|
||||
'\\MySC\\Auth\\API',
|
||||
),
|
||||
'auth_token' => array(
|
||||
'expiration_delay' => 31536000,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
$root_dir_path
|
||||
);
|
||||
|
||||
$sentry_span = new SentrySpan('core.init', 'Core initialization');
|
||||
|
||||
// Put here your own initialization stuff
|
||||
Db :: init();
|
||||
API :: init();
|
||||
require 'views/index.php';
|
||||
|
||||
$sentry_span->finish();
|
||||
|
||||
# vim: tabstop=2 shiftwidth=2 softtabstop=2 expandtab
|
161
includes/views/index.php
Normal file
|
@ -0,0 +1,161 @@
|
|||
<?php
|
||||
|
||||
use EesyPHP\Auth;
|
||||
use EesyPHP\Db;
|
||||
use EesyPHP\Log;
|
||||
use EesyPHP\Tpl;
|
||||
use EesyPHP\Url;
|
||||
|
||||
use MySC\Db\Category;
|
||||
use MySC\Db\SCase;
|
||||
use MySC\Db\Thing;
|
||||
|
||||
use function EesyPHP\vardump;
|
||||
use function EesyPHP\generate_uuid;
|
||||
|
||||
if (php_sapi_name() == "cli")
|
||||
return true;
|
||||
|
||||
/**
|
||||
* Redirect to homepage
|
||||
* @param EesyPHP\UrlRequest $request
|
||||
* @return void
|
||||
*/
|
||||
function handle_redirect_homepage($request) {
|
||||
Url::redirect("home");
|
||||
}
|
||||
Url :: add_url_handler(null, 'handle_redirect_homepage', null, false);
|
||||
|
||||
/**
|
||||
* Homepage
|
||||
* @param EesyPHP\UrlRequest $request
|
||||
* @return void
|
||||
*/
|
||||
function handle_homepage($request) {
|
||||
Tpl :: display("index.tpl");
|
||||
}
|
||||
Url :: add_url_handler("#^home$#", 'handle_homepage', null, false);
|
||||
|
||||
function _list_static_directory_files($root_dir, $dir, &$result, &$last_updated) {
|
||||
foreach (array_diff(scandir($dir), array('.','..')) as $file) {
|
||||
$path = "$dir/$file";
|
||||
if (is_dir($path)) {
|
||||
_list_static_directory_files($root_dir, $path, $result, $last_updated);
|
||||
}
|
||||
else {
|
||||
$result[] = Tpl::static_url(substr($path, strlen($root_dir)+1));
|
||||
$file_last_updated = filemtime($path);
|
||||
if ($file_last_updated > $last_updated)
|
||||
$last_updated = $file_last_updated;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Cache manifest file
|
||||
* @param EesyPHP\UrlRequest $request
|
||||
* @return void
|
||||
*/
|
||||
function handle_cache_manifest($request) {
|
||||
$cache = ["home"];
|
||||
$last_updated = filemtime(Tpl::resolve_templates_path("index.tpl"));
|
||||
foreach (Tpl::static_directories() as $static_directory)
|
||||
_list_static_directory_files($static_directory, $static_directory, $cache, $last_updated);
|
||||
Tpl::assign("cache", $cache);
|
||||
Tpl::assign("last_updated", date("Y/m/d H:i:s", $last_updated));
|
||||
header("Content-type: text/plain");
|
||||
$content = Tpl::fetch("cache_manifest.tpl");
|
||||
$etag = md5($content);
|
||||
header("Cache-Control: max-age=3000, must-revalidate");
|
||||
header("Last-Modified: ".gmdate("D, d M Y H:i:s", $last_updated)." GMT");
|
||||
header("Etag: $etag");
|
||||
print($content);
|
||||
exit();
|
||||
}
|
||||
Url :: add_url_handler("#^cache\.manifest$#", 'handle_cache_manifest');
|
||||
|
||||
/**
|
||||
* Sync data
|
||||
* @param EesyPHP\UrlRequest $request
|
||||
* @return void
|
||||
*/
|
||||
function handle_sync($request) {
|
||||
$data = json_decode($_POST["data"], true);
|
||||
Log::debug("Sync scases data: %s", vardump($data["scases"]));
|
||||
$user = Auth::user();
|
||||
$updated = false;
|
||||
$db_scases = SCase :: list(['username' => $user -> username]);
|
||||
foreach($data["scases"] as $scase_uuid => $scase_data) {
|
||||
Log::debug("sync(): scase %s", $scase_uuid);
|
||||
$scase = Scase :: from_json($scase_data, $user);
|
||||
if (array_key_exists($scase_uuid, $db_scases)) {
|
||||
Log::debug("sync(): scase %s exist in DB", $scase_uuid);
|
||||
$db_scases[$scase_uuid] -> sync($scase, $updated);
|
||||
// @phpstan-ignore-next-line
|
||||
$db_categories = $db_scases[$scase_uuid] -> categories();
|
||||
}
|
||||
else {
|
||||
Log::debug("sync(): scase %s does not exist in DB, create it", $scase_uuid);
|
||||
$scase -> save();
|
||||
$updated = true;
|
||||
$db_categories = [];
|
||||
}
|
||||
|
||||
foreach($scase_data['cats'] as $category_uuid => $category_data) {
|
||||
Log::debug("sync(): scase %s / category %s", $scase_uuid, $category_uuid);
|
||||
$category = Category :: from_json($category_data, $scase);
|
||||
if (array_key_exists($category_uuid, $db_categories)) {
|
||||
Log::debug("sync(): scase %s / category %s exists in DB, sync it", $scase_uuid, $category_uuid);
|
||||
$db_categories[$category_uuid] -> sync($category, $updated);
|
||||
$db_things = $db_categories[$category_uuid] ->things();
|
||||
}
|
||||
else {
|
||||
Log::debug("sync(): scase %s / category %s does not exists in DB, create it", $scase_uuid, $category_uuid);
|
||||
$category -> save();
|
||||
$updated = true;
|
||||
$db_things = [];
|
||||
}
|
||||
|
||||
foreach($category_data['things'] as $thing_uuid => $thing_data) {
|
||||
$thing = Thing :: from_json($thing_data, $category);
|
||||
if (array_key_exists($thing_uuid, $db_things)) {
|
||||
$db_things[$thing_uuid] -> sync($thing, $updated);
|
||||
}
|
||||
else {
|
||||
$thing -> save();
|
||||
$updated = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$data = [
|
||||
"scases" => [],
|
||||
"updated" => $updated,
|
||||
];
|
||||
foreach (SCase :: list(['username' => $user -> username]) as $uuid => $scase) {
|
||||
$data["scases"][$uuid] = $scase -> to_json();
|
||||
}
|
||||
Tpl::display_ajax_return($data);
|
||||
}
|
||||
Url :: add_url_handler("#^sync$#", 'handle_sync', null, true, true, true);
|
||||
|
||||
/**
|
||||
* Support info page
|
||||
* @param EesyPHP\UrlRequest $request
|
||||
* @return void
|
||||
*/
|
||||
function handle_support_info($request) {
|
||||
if (isset($_REQUEST['download'])) {
|
||||
header('Content-Type: text/plain');
|
||||
header('Content-disposition: attachment; filename="'.date('Ymd-His-').Auth::user()->username.'-aide-support.txt"');
|
||||
}
|
||||
Tpl :: display(
|
||||
isset($_REQUEST['download'])?
|
||||
'support_info_content.tpl':"support_info.tpl",
|
||||
"Page d'aide à l'assistance utilisateurs"
|
||||
);
|
||||
}
|
||||
Url :: add_url_handler('|^support/?$|', 'handle_support_info');
|
||||
|
||||
# vim: tabstop=2 shiftwidth=2 softtabstop=2 expandtab
|
4
locales/.gitignore
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
headers.pot
|
||||
js-*-messages.pot
|
||||
php-messages.pot
|
||||
templates-*-messages.pot
|
1
locales/fr_FR.UTF8.js
Normal file
BIN
locales/fr_FR.UTF8/LC_MESSAGES/DEFAULT.mo
Normal file
657
locales/fr_FR.UTF8/LC_MESSAGES/DEFAULT.po
Normal file
|
@ -0,0 +1,657 @@
|
|||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"POT-Creation-Date: 2024-09-22 16:25+0000\n"
|
||||
"PO-Revision-Date: 2024-09-22 18:26+0200\n"
|
||||
"Last-Translator: Benjamin Renard <brenard@easter-eggs.com>\n"
|
||||
"Language-Team: \n"
|
||||
"Language: fr\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
|
||||
"X-Generator: Poedit 3.2.2\n"
|
||||
|
||||
#: src/Auth/API.php:49
|
||||
msgid "Invalid username or password."
|
||||
msgstr "Nom d'utilisateur ou mot de passe invalide."
|
||||
|
||||
#: src/Auth/API.php:56
|
||||
msgid "Invalid authentication token."
|
||||
msgstr "Jeton d'authentification invalide."
|
||||
|
||||
#: src/Auth/API.php:58
|
||||
msgid "Authentication token expired."
|
||||
msgstr "Jeton d'authentification expiré."
|
||||
|
||||
#: src/Auth/API.php:65
|
||||
msgid "Your account appears to have been deleted."
|
||||
msgstr "Votre compte semble avoir été supprimé."
|
||||
|
||||
#: static/main.js:27
|
||||
msgid "Confirmation"
|
||||
msgstr "Confirmation"
|
||||
|
||||
#: static/main.js:29
|
||||
msgid "OK"
|
||||
msgstr "OK"
|
||||
|
||||
#: static/main.js:31
|
||||
msgid "Cancel"
|
||||
msgstr "Annuler"
|
||||
|
||||
#: static/main.js:86
|
||||
msgid "You have to enter the name of the suitcase!"
|
||||
msgstr "Vous devez saisir le nom de la valise !"
|
||||
|
||||
#: static/main.js:96 static/main.js:143 static/main.js:200
|
||||
msgid "A suitcase exist with this name exist in the trash."
|
||||
msgstr "Une valise portant ce nom existe déjà dans la corbeille."
|
||||
|
||||
#: static/main.js:101
|
||||
msgid "This suitcase already exist!"
|
||||
msgstr "Cette valise existe déjà !"
|
||||
|
||||
#: static/main.js:135
|
||||
msgid "You have to enter the new name of the suitcase!"
|
||||
msgstr "Vous devez saisir le nouveau nom de la valise !"
|
||||
|
||||
#: static/main.js:149 static/main.js:206
|
||||
msgid "A suitcase with this name already exist!"
|
||||
msgstr "Une valise portant ce nom existe déjà !"
|
||||
|
||||
#: static/main.js:164
|
||||
msgid "An error occurred renaming this suitcase."
|
||||
msgstr "Une erreur est survenue en renommant cette valise."
|
||||
|
||||
#: static/main.js:193
|
||||
msgid "You have to enter the new suitcase name."
|
||||
msgstr "Vous devez saisir le nom de la nouvelle valise."
|
||||
|
||||
#: static/main.js:219
|
||||
msgid "An error occurred copying the suitcase."
|
||||
msgstr "Une erreur est survenue en copiant cette valise."
|
||||
|
||||
#: static/main.js:240
|
||||
#, javascript-format
|
||||
msgid "Reset the %s suitcase"
|
||||
msgstr "Réinitialiser la valise %s"
|
||||
|
||||
#: static/main.js:241
|
||||
#, javascript-format
|
||||
msgid "Are-you sure you want to reset the suitcase %s?"
|
||||
msgstr "Êtes-vous sûre de vouloir réinitialiser la valise %s ?"
|
||||
|
||||
#: static/main.js:260
|
||||
#, javascript-format
|
||||
msgid "Delete the %s suitcase"
|
||||
msgstr "Supprimer la valise %s"
|
||||
|
||||
#: static/main.js:261
|
||||
#, javascript-format
|
||||
msgid "Are-you sure you want to delete the suitcase %s?"
|
||||
msgstr "Êtes-vous sûre de vouloir supprimer la valise %s ?"
|
||||
|
||||
#: static/main.js:278
|
||||
#, javascript-format
|
||||
msgid "Restaure the %s suitcase"
|
||||
msgstr "Restaurer la valise %s"
|
||||
|
||||
#: static/main.js:279
|
||||
#, javascript-format
|
||||
msgid "Are-you sure you want to restaure the suitcase %s?"
|
||||
msgstr "Êtes-vous sûre de vouloir restaurer la valise %s ?"
|
||||
|
||||
#: static/main.js:311
|
||||
msgid "You have to enter the category name!"
|
||||
msgstr "Vous devez saisir le nom de la catégorie !"
|
||||
|
||||
#: static/main.js:320 static/main.js:378
|
||||
msgid "A category with this name already exist in the trash!"
|
||||
msgstr "Une catégorie portant ce nom existe déjà dans la corbeille !"
|
||||
|
||||
#: static/main.js:326
|
||||
msgid "A category with this name already exist!"
|
||||
msgstr "Une catégorie portant ce nom existe déjà !"
|
||||
|
||||
#: static/main.js:366
|
||||
msgid "You have to enter the new name of the category!"
|
||||
msgstr "Vous devez saisir le nouveau nom de la catégorie !"
|
||||
|
||||
#: static/main.js:383
|
||||
msgid "A category with this name already!"
|
||||
msgstr "Une catégorie portant ce nom existe déjà !"
|
||||
|
||||
#: static/main.js:414
|
||||
#, javascript-format
|
||||
msgid "Delete the category %s"
|
||||
msgstr "Supprimer la catégorie %s"
|
||||
|
||||
#: static/main.js:415
|
||||
#, javascript-format
|
||||
msgid "Are-you sure you want to delete the category %s?"
|
||||
msgstr "Êtes-vous sûre de vouloir supprimer la catégorie %s ?"
|
||||
|
||||
#: static/main.js:433
|
||||
#, javascript-format
|
||||
msgid "Restore the category %s"
|
||||
msgstr "Restaurer la catégorie %s"
|
||||
|
||||
#: static/main.js:434
|
||||
#, javascript-format
|
||||
msgid "Are-you sure you want to restore the category %s?"
|
||||
msgstr "Êtes-vous sûre de vouloir restaurer la catégorie %s ?"
|
||||
|
||||
#: static/main.js:497
|
||||
msgid "Tow elements can't have the same name!"
|
||||
msgstr "Deux éléments ne peuvent pas porter le même nom !"
|
||||
|
||||
#: static/main.js:505
|
||||
#, javascript-format
|
||||
msgid "The element '%s' already exist!"
|
||||
msgstr "Un élément portant le nom '%s' existe déjà !"
|
||||
|
||||
#: static/main.js:528
|
||||
msgid "You have to enter at least one element name!"
|
||||
msgstr "Vous devez saisir au moins un nom d'élément !"
|
||||
|
||||
#: static/main.js:561
|
||||
msgid "Another?"
|
||||
msgstr "Un autre ?"
|
||||
|
||||
#: static/main.js:566
|
||||
msgid "Nb"
|
||||
msgstr "Nb"
|
||||
|
||||
#: static/main.js:593
|
||||
msgid "You have to enter the new element name!"
|
||||
msgstr "Vous devez saisir le nom du nouvel élément !"
|
||||
|
||||
#: static/main.js:609
|
||||
msgid "An element with this name already exist in the trash!"
|
||||
msgstr "Un élément portant ce nom existe déjà dans la corbeille !"
|
||||
|
||||
#: static/main.js:615
|
||||
msgid "An element with this name already exist!"
|
||||
msgstr "Un élément portant ce nom existe déjà !"
|
||||
|
||||
#: static/main.js:659
|
||||
#, javascript-format
|
||||
msgid "Delete the element %s"
|
||||
msgstr "Supprimer l'élément %s"
|
||||
|
||||
#: static/main.js:660
|
||||
#, javascript-format
|
||||
msgid "Are-you sure you want to delete the element %s?"
|
||||
msgstr "Êtes-vous sûre de vouloir supprimer l'élément %s ?"
|
||||
|
||||
#: static/main.js:681
|
||||
#, javascript-format
|
||||
msgid "Restore the element %s"
|
||||
msgstr "Restaurer l'élément %s"
|
||||
|
||||
#: static/main.js:682
|
||||
#, javascript-format
|
||||
msgid "Are-you sure you want to restore the element %s?"
|
||||
msgstr "Êtes-vous sûre de vouloir restaurer l'élément %s ?"
|
||||
|
||||
#: static/main.js:785
|
||||
msgid "Add an element"
|
||||
msgstr "Ajouter un élément"
|
||||
|
||||
#: static/main.js:823 static/main.js:963
|
||||
msgid "Trash"
|
||||
msgstr "Corbeille"
|
||||
|
||||
#: static/main.js:836
|
||||
msgid "The trash is empty."
|
||||
msgstr "La corbeille est vide."
|
||||
|
||||
#: static/main.js:924
|
||||
msgid "Your suitcases"
|
||||
msgstr "Vos valises"
|
||||
|
||||
#: static/main.js:995
|
||||
msgid "No suitcase in the trash."
|
||||
msgstr "Aucune valise dans la corbeille."
|
||||
|
||||
#: static/main.js:1050
|
||||
msgid "Delete all local data"
|
||||
msgstr "Purger les données locales"
|
||||
|
||||
#: static/main.js:1051
|
||||
msgid "Are-you sure you want to delete all local data (irreversible action)?"
|
||||
msgstr ""
|
||||
"Êtes-vous sûre de vouloir supprimer toutes les données locales (action "
|
||||
"irréversible) ?"
|
||||
|
||||
#: static/main.js:1068
|
||||
msgid "Loading example data"
|
||||
msgstr "Charger les données d'exemple"
|
||||
|
||||
#: static/main.js:1070
|
||||
msgid ""
|
||||
"Are-you sure you want to load example data in place of your own local data "
|
||||
"(irreversible action)?"
|
||||
msgstr ""
|
||||
"Êtes-vous sûre de vouloir charger les données d'exemple à la place de vos "
|
||||
"données locales (action irréversible) ?"
|
||||
|
||||
#: static/main.js:1120
|
||||
msgid "Failed to decode JSON file."
|
||||
msgstr "Impossible de décoder le fichier JSON."
|
||||
|
||||
#: static/main.js:1125
|
||||
msgid "Import from file"
|
||||
msgstr "Import depuis un fichier"
|
||||
|
||||
#: static/main.js:1127
|
||||
msgid ""
|
||||
"Are-you sure you want to overwrite your local data with the data from this "
|
||||
"file (irreversible action)?"
|
||||
msgstr ""
|
||||
"Êtes-vous sûre de vouloir écraser vos données locales par celles issues de "
|
||||
"ce fichier (action irréversible) ?"
|
||||
|
||||
#: static/main.js:1134
|
||||
msgid "The file has been imported successfully."
|
||||
msgstr "Le fichier as bien été importé."
|
||||
|
||||
#: static/main.js:1141
|
||||
msgid "An error occurred loading this file. Restoring previous data..."
|
||||
msgstr ""
|
||||
"Une erreur est survenue en chargeant ce fichier. Restauration des données "
|
||||
"précédentes..."
|
||||
|
||||
#: static/main.js:1148 static/main.js:1315
|
||||
msgid "Previous data has been restored successfully."
|
||||
msgstr "Les données précédentes ont bien été restaurées."
|
||||
|
||||
#: static/main.js:1154 static/main.js:1321
|
||||
msgid "An error occurred restoring previous data."
|
||||
msgstr "Une erreur est survenue en restaurant les données précédentes."
|
||||
|
||||
#: static/main.js:1200
|
||||
msgid "You have to enter your username and password!"
|
||||
msgstr "Vous devez saisir votre nom d'utilisateur et votre mot de passe !"
|
||||
|
||||
#: static/main.js:1218
|
||||
msgid "Connected."
|
||||
msgstr "Connecté."
|
||||
|
||||
#: static/main.js:1226
|
||||
msgid "An error occurred logging in. Please try again later."
|
||||
msgstr ""
|
||||
"Une erreur est survenue durant la connexion. Merci de réessayer "
|
||||
"ultérieurement."
|
||||
|
||||
#: static/main.js:1247
|
||||
msgid "Logout"
|
||||
msgstr "Déconnexion"
|
||||
|
||||
#: static/main.js:1248
|
||||
msgid "Do you really want to log out?"
|
||||
msgstr "Voulez-vous vraiment vous déconnecter ?"
|
||||
|
||||
#: static/main.js:1259
|
||||
msgid "Logged out"
|
||||
msgstr "Déconnecté"
|
||||
|
||||
#: static/main.js:1262 static/main.js:1270
|
||||
msgid "An error occurred logging you out. Please try again later."
|
||||
msgstr ""
|
||||
"Une erreur est survenue durant la déconnexion. Merci de réessayer "
|
||||
"ultérieurement."
|
||||
|
||||
#: static/main.js:1303
|
||||
msgid "Data synchronized."
|
||||
msgstr "Données synchronisées."
|
||||
|
||||
#: static/main.js:1308
|
||||
msgid ""
|
||||
"An error occurred loading data from the server. Restoring previous data..."
|
||||
msgstr ""
|
||||
"Une erreur est survenue en chargeant les données depuis le serveur. "
|
||||
"Restauration des données précédentes..."
|
||||
|
||||
#: static/main.js:1331 static/main.js:1353
|
||||
msgid "An error occurred synchronizing your data. Please try again later."
|
||||
msgstr ""
|
||||
"Une erreur est survenue durant la synchronisation de vos données. Merci de "
|
||||
"réessayer ultérieurement."
|
||||
|
||||
#: static/main.js:1345
|
||||
msgid "Your session appears to have expired, please re-authenticate."
|
||||
msgstr "Votre session semble avoir expirée, merci de vous réidentifier."
|
||||
|
||||
#: static/main.js:1372
|
||||
msgid "You must sign in before you can sync your data."
|
||||
msgstr "Vous devez vous connecter avant de synchroniser vos données."
|
||||
|
||||
#: static/main.js:1386
|
||||
msgid "Synchronize your suitcases from server"
|
||||
msgstr "Synchronisation de vos valises avec les serveurs"
|
||||
|
||||
#: static/main.js:1387
|
||||
msgid "Are-you sure you want to synchronize your suitcases from server?"
|
||||
msgstr "Êtes-vous sûre de vouloir synchroniser vos valises avec le serveur ?"
|
||||
|
||||
#: static/main.js:1450
|
||||
msgid "An example of a suitcase?"
|
||||
msgstr "Un exemple de valise ?"
|
||||
|
||||
#: static/main.js:1451
|
||||
msgid "Would you like to load a sample suitcase to get started?"
|
||||
msgstr "Voulez-vous chargeant un exemple de valise pour commencer ?"
|
||||
|
||||
#: static/main.js:1468
|
||||
msgid ""
|
||||
"Your internet browser does not support local data storage. Therefore, "
|
||||
"unfortunately you cannot use this application."
|
||||
msgstr ""
|
||||
"Votre navigateur internet ne semble pas supporter le stockage de données "
|
||||
"locales. Malheureusement, vous ne pouvez donc pas utiliser cette application."
|
||||
|
||||
#: static/main.js:1557
|
||||
msgid "Error loading local data"
|
||||
msgstr "Une erreur est survenue en chargeant les données locales"
|
||||
|
||||
#: static/main.js:1558
|
||||
msgid "An error occurred while loading local data. Should we purge it?"
|
||||
msgstr ""
|
||||
"Une erreur est survenue en chargeant vos données locales. Devons-nous les "
|
||||
"purger ?"
|
||||
|
||||
#: static/mysc_objects.js:10
|
||||
msgid "White paper"
|
||||
msgstr "Papier blanc"
|
||||
|
||||
#: static/mysc_objects.js:11
|
||||
msgid "Pen"
|
||||
msgstr "Stylo"
|
||||
|
||||
#: static/mysc_objects.js:12
|
||||
msgid "ID card/passport"
|
||||
msgstr "Carte d'identité / passeport"
|
||||
|
||||
#: static/mysc_objects.js:18
|
||||
msgid "Watch"
|
||||
msgstr "Montre"
|
||||
|
||||
#: static/mysc_objects.js:19
|
||||
msgid "Watch charger"
|
||||
msgstr "Chargeur montre"
|
||||
|
||||
#: static/mysc_objects.js:20
|
||||
msgid "Laptop"
|
||||
msgstr "PC portable"
|
||||
|
||||
#: static/mysc_objects.js:21
|
||||
msgid "Laptop charger"
|
||||
msgstr "Chargeur PC portable"
|
||||
|
||||
#: static/mysc_objects.js:294
|
||||
#, javascript-format
|
||||
msgid "An error occurred while loading the %s suitcase from the cache."
|
||||
msgstr "Une erreur est survenue en chargeant la valise %s depuis le cache."
|
||||
|
||||
#: static/mysc_objects.js:417
|
||||
msgid "An error occurred while loading the category list from the cache."
|
||||
msgstr ""
|
||||
"Une erreur est survenue en chargeant la liste de catégories depuis le cache."
|
||||
|
||||
#: static/mysc_objects.js:565
|
||||
#, javascript-format
|
||||
msgid "An error occurred while loading the %s category from the cache."
|
||||
msgstr "Une erreur est survenue en chargeant la catégorie %s depuis le cache."
|
||||
|
||||
#: static/mysc_objects.js:636
|
||||
msgid "Error loading your login information. Please log in again."
|
||||
msgstr ""
|
||||
"Erreur en chargeant vos données d'authentification. Merci de vous "
|
||||
"réidentifier."
|
||||
|
||||
#: templates/support_info.tpl:4
|
||||
msgid "Helpdesk page"
|
||||
msgstr "Page d'assistance aux utilisateurs"
|
||||
|
||||
#: templates/support_info.tpl:5
|
||||
msgid ""
|
||||
"Upon request, please download and forward the following information to the "
|
||||
"support service:"
|
||||
msgstr ""
|
||||
"À leur demande, merci de télécharger et transmettre les informations ci-"
|
||||
"dessous au service support :"
|
||||
|
||||
#: templates/support_info.tpl:9
|
||||
msgid "Download"
|
||||
msgstr "Télécharger"
|
||||
|
||||
#: templates/support_info_content.tpl:1
|
||||
msgid "Application URL:"
|
||||
msgstr "URL de l'application :"
|
||||
|
||||
#: templates/support_info_content.tpl:2
|
||||
msgid "Current page URL:"
|
||||
msgstr "URL de la page courante :"
|
||||
|
||||
#: templates/support_info_content.tpl:4
|
||||
msgid "Connected user:"
|
||||
msgstr "Utilisateur connecté :"
|
||||
|
||||
#: templates/support_info_content.tpl:6
|
||||
msgid "Extra user information:"
|
||||
msgstr "Informations supplémentaires de l'utilisateur :"
|
||||
|
||||
#: templates/index.tpl:39 templates/index.tpl:91
|
||||
msgid "Add a suitcase"
|
||||
msgstr "Ajouter une valise"
|
||||
|
||||
#: templates/index.tpl:40
|
||||
msgid "Show trash"
|
||||
msgstr "Voir la corbeille"
|
||||
|
||||
#: templates/index.tpl:41
|
||||
msgid "Suitcases list"
|
||||
msgstr "Liste des valises"
|
||||
|
||||
#: templates/index.tpl:43
|
||||
msgid "Manage the suitcase"
|
||||
msgstr "Gérer les valises"
|
||||
|
||||
#: templates/index.tpl:45 templates/index.tpl:157
|
||||
msgid "Add a category"
|
||||
msgstr "Ajouter une catégorie"
|
||||
|
||||
#: templates/index.tpl:47 templates/index.tpl:135
|
||||
msgid "Rename the suitcase"
|
||||
msgstr "Renommer la valise"
|
||||
|
||||
#: templates/index.tpl:48 templates/index.tpl:113
|
||||
msgid "Copy the suitcase"
|
||||
msgstr "Copier la valise"
|
||||
|
||||
#: templates/index.tpl:49
|
||||
msgid "Reset the suitcase"
|
||||
msgstr "Réinitialiser la valise"
|
||||
|
||||
#: templates/index.tpl:50
|
||||
msgid "Delete the suitcase"
|
||||
msgstr "Supprimer la valise"
|
||||
|
||||
#: templates/index.tpl:52
|
||||
msgid "Show suitcase's trash"
|
||||
msgstr "Voir la corbeille de la valise"
|
||||
|
||||
#: templates/index.tpl:56
|
||||
msgid "Manage data"
|
||||
msgstr "Gérer les données"
|
||||
|
||||
#: templates/index.tpl:58
|
||||
msgid "Backup your data"
|
||||
msgstr "Sauvegarder vos données"
|
||||
|
||||
#: templates/index.tpl:59
|
||||
msgid "Restaure your data"
|
||||
msgstr "Restaurer vos données"
|
||||
|
||||
#: templates/index.tpl:61
|
||||
msgid "Synchronize local data"
|
||||
msgstr "Synchroniser les données locales"
|
||||
|
||||
#: templates/index.tpl:63
|
||||
msgid "Purge local data"
|
||||
msgstr "Purger les données locales"
|
||||
|
||||
#: templates/index.tpl:64
|
||||
msgid "Load example data"
|
||||
msgstr "Charger les données d'exemple"
|
||||
|
||||
#: templates/index.tpl:74
|
||||
msgid "Login"
|
||||
msgstr "Connexion"
|
||||
|
||||
#: templates/index.tpl:96
|
||||
msgid "Suitcase name"
|
||||
msgstr "Nom de la valise"
|
||||
|
||||
#: templates/index.tpl:102 templates/index.tpl:168 templates/index.tpl:218
|
||||
msgid "Add"
|
||||
msgstr "Ajouter"
|
||||
|
||||
#: templates/index.tpl:118
|
||||
msgid "Name of the new suitcase"
|
||||
msgstr "Nom de la nouvelle valise"
|
||||
|
||||
#: templates/index.tpl:124
|
||||
msgid "Copy"
|
||||
msgstr "Copier"
|
||||
|
||||
#: templates/index.tpl:140
|
||||
msgid "New suitcase name"
|
||||
msgstr "Nouveau nom de la valise"
|
||||
|
||||
#: templates/index.tpl:146 templates/index.tpl:190
|
||||
msgid "Rename"
|
||||
msgstr "Renommer"
|
||||
|
||||
#: templates/index.tpl:162
|
||||
msgid "Category name"
|
||||
msgstr "Nom de la catégorie"
|
||||
|
||||
#: templates/index.tpl:179
|
||||
msgid "Rename the category"
|
||||
msgstr "Renommer la catégorie"
|
||||
|
||||
#: templates/index.tpl:184
|
||||
msgid "New category's name"
|
||||
msgstr "Nouveau nom de la catégorie"
|
||||
|
||||
#: templates/index.tpl:207 templates/index.tpl:234
|
||||
msgid "Element name"
|
||||
msgstr "Nom de l'élément"
|
||||
|
||||
#: templates/index.tpl:229
|
||||
msgid "Edit the element"
|
||||
msgstr "Modifier l'élément"
|
||||
|
||||
#: templates/index.tpl:241
|
||||
msgid "Modify"
|
||||
msgstr "Modifier"
|
||||
|
||||
#: templates/index.tpl:252 templates/index.tpl:257
|
||||
msgid "Loading..."
|
||||
msgstr "Chargement..."
|
||||
|
||||
#: templates/index.tpl:271
|
||||
msgid "Connection"
|
||||
msgstr "Connexion"
|
||||
|
||||
#: templates/index.tpl:276
|
||||
msgid "Username"
|
||||
msgstr "Nom d'utilisateur"
|
||||
|
||||
#: templates/index.tpl:277
|
||||
msgid "Password"
|
||||
msgstr "Mot de passe"
|
||||
|
||||
#: templates/index.tpl:283 templates/index.tpl:326
|
||||
msgid "Connect"
|
||||
msgstr "Connexion"
|
||||
|
||||
#: templates/index.tpl:295
|
||||
msgid "Welcome"
|
||||
msgstr "Bienvenu"
|
||||
|
||||
#: templates/index.tpl:298
|
||||
msgid ""
|
||||
"<p>\n"
|
||||
" This application allows you to manage lists of things not to "
|
||||
"forget to pack in your\n"
|
||||
" suitcase before your departure:\n"
|
||||
" <ul>\n"
|
||||
" <li>\n"
|
||||
" To get started, create a suitcase, add the categories of "
|
||||
"things you will need to\n"
|
||||
" pack, and add all these things to it;\n"
|
||||
" </li>\n"
|
||||
" <li>\n"
|
||||
" Before your departure, you can then gradually check off all "
|
||||
"the things you have\n"
|
||||
" already gathered and ensure you don't forget anything!\n"
|
||||
" </li>\n"
|
||||
" </ul>\n"
|
||||
" </p>\n"
|
||||
" <p>\n"
|
||||
" <strong>Note:</strong> This application has been designed to work "
|
||||
"completely locally.\n"
|
||||
" The data manipulated (your suitcases, etc.) is stored only in your "
|
||||
"internet browser.\n"
|
||||
" It is also possible to export/import this information in JSON "
|
||||
"format.<br/>\n"
|
||||
" However, to facilitate the management of your suitcases from "
|
||||
"multiple devices, it's\n"
|
||||
" possible to synchronize this information on the server. For this, "
|
||||
"you need an account,\n"
|
||||
" and at this time, registrations are not open.\n"
|
||||
" </p>\n"
|
||||
" <p>\n"
|
||||
" If you have an account, you can log in by clicking the <em>Login</"
|
||||
"em> button below.\n"
|
||||
" If not, click the <em>Anonymous usage</em> button to start using "
|
||||
"the application.\n"
|
||||
" </p>"
|
||||
msgstr ""
|
||||
"<p>\n"
|
||||
" Cette application vous permet de gérer des listes de choses à ne pas "
|
||||
"oublier de glisser dans votre valise avant votre départ :\n"
|
||||
" <ul>\n"
|
||||
" <li>Pour commencer, créer une valise, ajouter les catégories de choses "
|
||||
"que vous aurez à y glisser et ajouter y toutes ces choses.</li>\n"
|
||||
" <li>Avant votre départ, vous pourrez alors cocher petit à petit toutes "
|
||||
"les choses que vous aurez déjà réunies et vous asurez de ne rien oublier !</"
|
||||
"li>\n"
|
||||
" </ul>\n"
|
||||
"</p>\n"
|
||||
"<p>\n"
|
||||
" <strong>Note :</strong> Cette application a été conçue pour pouvoir "
|
||||
"fonctionner complètement localement. Les données manipulées (vos "
|
||||
"valises, ...) sont stockés\n"
|
||||
" uniquement dans votre navigateur internet. Il est par ailleurs possible "
|
||||
"d'exporter/importer ces informations au format JSON.<br/>\n"
|
||||
" Cependant, pour faciliter la gestion de vos valises depuis plusieurs "
|
||||
"appareils, il est possible de synchroniser ces informations sur le serveur. "
|
||||
"Pour cela,\n"
|
||||
" il vous faut un compte et à ce jour, les inscriptions ne sont pas "
|
||||
"ouvertes.\n"
|
||||
"</p>\n"
|
||||
"<p>\n"
|
||||
" Si vous disposez d'un compte, vous pouvez vous connecter en cliquant sur "
|
||||
"le bouton <em>Connexion</em> ci-dessous.\n"
|
||||
" À défaut, cliquer sur le bouton <em>Utilisation annonyme</em> pour "
|
||||
"commencer à utiliser l'application.\n"
|
||||
"</p>"
|
||||
|
||||
#: templates/index.tpl:327
|
||||
msgid "Anonymous usage"
|
||||
msgstr "Utilisation annonyme"
|
597
locales/messages.pot
Normal file
|
@ -0,0 +1,597 @@
|
|||
msgid ""
|
||||
msgstr ""
|
||||
"POT-Creation-Date: 2024-09-22 16:25+0000\n"
|
||||
"PO-Revision-Date: 2024-09-22 16:25+0000\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
#: src/Auth/API.php:49
|
||||
msgid "Invalid username or password."
|
||||
msgstr ""
|
||||
|
||||
#: src/Auth/API.php:56
|
||||
msgid "Invalid authentication token."
|
||||
msgstr ""
|
||||
|
||||
#: src/Auth/API.php:58
|
||||
msgid "Authentication token expired."
|
||||
msgstr ""
|
||||
|
||||
#: src/Auth/API.php:65
|
||||
msgid "Your account appears to have been deleted."
|
||||
msgstr ""
|
||||
|
||||
#: static/main.js:27
|
||||
msgid "Confirmation"
|
||||
msgstr ""
|
||||
|
||||
#: static/main.js:29
|
||||
msgid "OK"
|
||||
msgstr ""
|
||||
|
||||
#: static/main.js:31
|
||||
msgid "Cancel"
|
||||
msgstr ""
|
||||
|
||||
#: static/main.js:86
|
||||
msgid "You have to enter the name of the suitcase!"
|
||||
msgstr ""
|
||||
|
||||
#: static/main.js:96 static/main.js:143 static/main.js:200
|
||||
msgid "A suitcase exist with this name exist in the trash."
|
||||
msgstr ""
|
||||
|
||||
#: static/main.js:101
|
||||
msgid "This suitcase already exist!"
|
||||
msgstr ""
|
||||
|
||||
#: static/main.js:135
|
||||
msgid "You have to enter the new name of the suitcase!"
|
||||
msgstr ""
|
||||
|
||||
#: static/main.js:149 static/main.js:206
|
||||
msgid "A suitcase with this name already exist!"
|
||||
msgstr ""
|
||||
|
||||
#: static/main.js:164
|
||||
msgid "An error occurred renaming this suitcase."
|
||||
msgstr ""
|
||||
|
||||
#: static/main.js:193
|
||||
msgid "You have to enter the new suitcase name."
|
||||
msgstr ""
|
||||
|
||||
#: static/main.js:219
|
||||
msgid "An error occurred copying the suitcase."
|
||||
msgstr ""
|
||||
|
||||
#: static/main.js:240
|
||||
#, javascript-format
|
||||
msgid "Reset the %s suitcase"
|
||||
msgstr ""
|
||||
|
||||
#: static/main.js:241
|
||||
#, javascript-format
|
||||
msgid "Are-you sure you want to reset the suitcase %s?"
|
||||
msgstr ""
|
||||
|
||||
#: static/main.js:260
|
||||
#, javascript-format
|
||||
msgid "Delete the %s suitcase"
|
||||
msgstr ""
|
||||
|
||||
#: static/main.js:261
|
||||
#, javascript-format
|
||||
msgid "Are-you sure you want to delete the suitcase %s?"
|
||||
msgstr ""
|
||||
|
||||
#: static/main.js:278
|
||||
#, javascript-format
|
||||
msgid "Restaure the %s suitcase"
|
||||
msgstr ""
|
||||
|
||||
#: static/main.js:279
|
||||
#, javascript-format
|
||||
msgid "Are-you sure you want to restaure the suitcase %s?"
|
||||
msgstr ""
|
||||
|
||||
#: static/main.js:311
|
||||
msgid "You have to enter the category name!"
|
||||
msgstr ""
|
||||
|
||||
#: static/main.js:320 static/main.js:378
|
||||
msgid "A category with this name already exist in the trash!"
|
||||
msgstr ""
|
||||
|
||||
#: static/main.js:326
|
||||
msgid "A category with this name already exist!"
|
||||
msgstr ""
|
||||
|
||||
#: static/main.js:366
|
||||
msgid "You have to enter the new name of the category!"
|
||||
msgstr ""
|
||||
|
||||
#: static/main.js:383
|
||||
msgid "A category with this name already!"
|
||||
msgstr ""
|
||||
|
||||
#: static/main.js:414
|
||||
#, javascript-format
|
||||
msgid "Delete the category %s"
|
||||
msgstr ""
|
||||
|
||||
#: static/main.js:415
|
||||
#, javascript-format
|
||||
msgid "Are-you sure you want to delete the category %s?"
|
||||
msgstr ""
|
||||
|
||||
#: static/main.js:433
|
||||
#, javascript-format
|
||||
msgid "Restore the category %s"
|
||||
msgstr ""
|
||||
|
||||
#: static/main.js:434
|
||||
#, javascript-format
|
||||
msgid "Are-you sure you want to restore the category %s?"
|
||||
msgstr ""
|
||||
|
||||
#: static/main.js:497
|
||||
msgid "Tow elements can't have the same name!"
|
||||
msgstr ""
|
||||
|
||||
#: static/main.js:505
|
||||
#, javascript-format
|
||||
msgid "The element '%s' already exist!"
|
||||
msgstr ""
|
||||
|
||||
#: static/main.js:528
|
||||
msgid "You have to enter at least one element name!"
|
||||
msgstr ""
|
||||
|
||||
#: static/main.js:561
|
||||
msgid "Another?"
|
||||
msgstr ""
|
||||
|
||||
#: static/main.js:566
|
||||
msgid "Nb"
|
||||
msgstr ""
|
||||
|
||||
#: static/main.js:593
|
||||
msgid "You have to enter the new element name!"
|
||||
msgstr ""
|
||||
|
||||
#: static/main.js:609
|
||||
msgid "An element with this name already exist in the trash!"
|
||||
msgstr ""
|
||||
|
||||
#: static/main.js:615
|
||||
msgid "An element with this name already exist!"
|
||||
msgstr ""
|
||||
|
||||
#: static/main.js:659
|
||||
#, javascript-format
|
||||
msgid "Delete the element %s"
|
||||
msgstr ""
|
||||
|
||||
#: static/main.js:660
|
||||
#, javascript-format
|
||||
msgid "Are-you sure you want to delete the element %s?"
|
||||
msgstr ""
|
||||
|
||||
#: static/main.js:681
|
||||
#, javascript-format
|
||||
msgid "Restore the element %s"
|
||||
msgstr ""
|
||||
|
||||
#: static/main.js:682
|
||||
#, javascript-format
|
||||
msgid "Are-you sure you want to restore the element %s?"
|
||||
msgstr ""
|
||||
|
||||
#: static/main.js:785
|
||||
msgid "Add an element"
|
||||
msgstr ""
|
||||
|
||||
#: static/main.js:823 static/main.js:963
|
||||
msgid "Trash"
|
||||
msgstr ""
|
||||
|
||||
#: static/main.js:836
|
||||
msgid "The trash is empty."
|
||||
msgstr ""
|
||||
|
||||
#: static/main.js:924
|
||||
msgid "Your suitcases"
|
||||
msgstr ""
|
||||
|
||||
#: static/main.js:995
|
||||
msgid "No suitcase in the trash."
|
||||
msgstr ""
|
||||
|
||||
#: static/main.js:1050
|
||||
msgid "Delete all local data"
|
||||
msgstr ""
|
||||
|
||||
#: static/main.js:1051
|
||||
msgid "Are-you sure you want to delete all local data (irreversible action)?"
|
||||
msgstr ""
|
||||
|
||||
#: static/main.js:1068
|
||||
msgid "Loading example data"
|
||||
msgstr ""
|
||||
|
||||
#: static/main.js:1070
|
||||
msgid ""
|
||||
"Are-you sure you want to load example data in place of your own local data "
|
||||
"(irreversible action)?"
|
||||
msgstr ""
|
||||
|
||||
#: static/main.js:1120
|
||||
msgid "Failed to decode JSON file."
|
||||
msgstr ""
|
||||
|
||||
#: static/main.js:1125
|
||||
msgid "Import from file"
|
||||
msgstr ""
|
||||
|
||||
#: static/main.js:1127
|
||||
msgid ""
|
||||
"Are-you sure you want to overwrite your local data with the data from this "
|
||||
"file (irreversible action)?"
|
||||
msgstr ""
|
||||
|
||||
#: static/main.js:1134
|
||||
msgid "The file has been imported successfully."
|
||||
msgstr ""
|
||||
|
||||
#: static/main.js:1141
|
||||
msgid "An error occurred loading this file. Restoring previous data..."
|
||||
msgstr ""
|
||||
|
||||
#: static/main.js:1148 static/main.js:1315
|
||||
msgid "Previous data has been restored successfully."
|
||||
msgstr ""
|
||||
|
||||
#: static/main.js:1154 static/main.js:1321
|
||||
msgid "An error occurred restoring previous data."
|
||||
msgstr ""
|
||||
|
||||
#: static/main.js:1200
|
||||
msgid "You have to enter your username and password!"
|
||||
msgstr ""
|
||||
|
||||
#: static/main.js:1218
|
||||
msgid "Connected."
|
||||
msgstr ""
|
||||
|
||||
#: static/main.js:1226
|
||||
msgid "An error occurred logging in. Please try again later."
|
||||
msgstr ""
|
||||
|
||||
#: static/main.js:1247
|
||||
msgid "Logout"
|
||||
msgstr ""
|
||||
|
||||
#: static/main.js:1248
|
||||
msgid "Do you really want to log out?"
|
||||
msgstr ""
|
||||
|
||||
#: static/main.js:1259
|
||||
msgid "Logged out"
|
||||
msgstr ""
|
||||
|
||||
#: static/main.js:1262 static/main.js:1270
|
||||
msgid "An error occurred logging you out. Please try again later."
|
||||
msgstr ""
|
||||
|
||||
#: static/main.js:1303
|
||||
msgid "Data synchronized."
|
||||
msgstr ""
|
||||
|
||||
#: static/main.js:1308
|
||||
msgid ""
|
||||
"An error occurred loading data from the server. Restoring previous data..."
|
||||
msgstr ""
|
||||
|
||||
#: static/main.js:1331 static/main.js:1353
|
||||
msgid "An error occurred synchronizing your data. Please try again later."
|
||||
msgstr ""
|
||||
|
||||
#: static/main.js:1345
|
||||
msgid "Your session appears to have expired, please re-authenticate."
|
||||
msgstr ""
|
||||
|
||||
#: static/main.js:1372
|
||||
msgid "You must sign in before you can sync your data."
|
||||
msgstr ""
|
||||
|
||||
#: static/main.js:1386
|
||||
msgid "Synchronize your suitcases from server"
|
||||
msgstr ""
|
||||
|
||||
#: static/main.js:1387
|
||||
msgid "Are-you sure you want to synchronize your suitcases from server?"
|
||||
msgstr ""
|
||||
|
||||
#: static/main.js:1450
|
||||
msgid "An example of a suitcase?"
|
||||
msgstr ""
|
||||
|
||||
#: static/main.js:1451
|
||||
msgid "Would you like to load a sample suitcase to get started?"
|
||||
msgstr ""
|
||||
|
||||
#: static/main.js:1468
|
||||
msgid ""
|
||||
"Your internet browser does not support local data storage. Therefore, "
|
||||
"unfortunately you cannot use this application."
|
||||
msgstr ""
|
||||
|
||||
#: static/main.js:1557
|
||||
msgid "Error loading local data"
|
||||
msgstr ""
|
||||
|
||||
#: static/main.js:1558
|
||||
msgid "An error occurred while loading local data. Should we purge it?"
|
||||
msgstr ""
|
||||
|
||||
#: static/mysc_objects.js:10
|
||||
msgid "White paper"
|
||||
msgstr ""
|
||||
|
||||
#: static/mysc_objects.js:11
|
||||
msgid "Pen"
|
||||
msgstr ""
|
||||
|
||||
#: static/mysc_objects.js:12
|
||||
msgid "ID card/passport"
|
||||
msgstr ""
|
||||
|
||||
#: static/mysc_objects.js:18
|
||||
msgid "Watch"
|
||||
msgstr ""
|
||||
|
||||
#: static/mysc_objects.js:19
|
||||
msgid "Watch charger"
|
||||
msgstr ""
|
||||
|
||||
#: static/mysc_objects.js:20
|
||||
msgid "Laptop"
|
||||
msgstr ""
|
||||
|
||||
#: static/mysc_objects.js:21
|
||||
msgid "Laptop charger"
|
||||
msgstr ""
|
||||
|
||||
#: static/mysc_objects.js:294
|
||||
#, javascript-format
|
||||
msgid "An error occurred while loading the %s suitcase from the cache."
|
||||
msgstr ""
|
||||
|
||||
#: static/mysc_objects.js:417
|
||||
msgid "An error occurred while loading the category list from the cache."
|
||||
msgstr ""
|
||||
|
||||
#: static/mysc_objects.js:565
|
||||
#, javascript-format
|
||||
msgid "An error occurred while loading the %s category from the cache."
|
||||
msgstr ""
|
||||
|
||||
#: static/mysc_objects.js:636
|
||||
msgid "Error loading your login information. Please log in again."
|
||||
msgstr ""
|
||||
|
||||
#: templates/support_info.tpl:4
|
||||
msgid "Helpdesk page"
|
||||
msgstr ""
|
||||
|
||||
#: templates/support_info.tpl:5
|
||||
msgid ""
|
||||
"Upon request, please download and forward the following information to the "
|
||||
"support service:"
|
||||
msgstr ""
|
||||
|
||||
#: templates/support_info.tpl:9
|
||||
msgid "Download"
|
||||
msgstr ""
|
||||
|
||||
#: templates/support_info_content.tpl:1
|
||||
msgid "Application URL:"
|
||||
msgstr ""
|
||||
|
||||
#: templates/support_info_content.tpl:2
|
||||
msgid "Current page URL:"
|
||||
msgstr ""
|
||||
|
||||
#: templates/support_info_content.tpl:4
|
||||
msgid "Connected user:"
|
||||
msgstr ""
|
||||
|
||||
#: templates/support_info_content.tpl:6
|
||||
msgid "Extra user information:"
|
||||
msgstr ""
|
||||
|
||||
#: templates/index.tpl:39 templates/index.tpl:91
|
||||
msgid "Add a suitcase"
|
||||
msgstr ""
|
||||
|
||||
#: templates/index.tpl:40
|
||||
msgid "Show trash"
|
||||
msgstr ""
|
||||
|
||||
#: templates/index.tpl:41
|
||||
msgid "Suitcases list"
|
||||
msgstr ""
|
||||
|
||||
#: templates/index.tpl:43
|
||||
msgid "Manage the suitcase"
|
||||
msgstr ""
|
||||
|
||||
#: templates/index.tpl:45 templates/index.tpl:157
|
||||
msgid "Add a category"
|
||||
msgstr ""
|
||||
|
||||
#: templates/index.tpl:47 templates/index.tpl:135
|
||||
msgid "Rename the suitcase"
|
||||
msgstr ""
|
||||
|
||||
#: templates/index.tpl:48 templates/index.tpl:113
|
||||
msgid "Copy the suitcase"
|
||||
msgstr ""
|
||||
|
||||
#: templates/index.tpl:49
|
||||
msgid "Reset the suitcase"
|
||||
msgstr ""
|
||||
|
||||
#: templates/index.tpl:50
|
||||
msgid "Delete the suitcase"
|
||||
msgstr ""
|
||||
|
||||
#: templates/index.tpl:52
|
||||
msgid "Show suitcase's trash"
|
||||
msgstr ""
|
||||
|
||||
#: templates/index.tpl:56
|
||||
msgid "Manage data"
|
||||
msgstr ""
|
||||
|
||||
#: templates/index.tpl:58
|
||||
msgid "Backup your data"
|
||||
msgstr ""
|
||||
|
||||
#: templates/index.tpl:59
|
||||
msgid "Restaure your data"
|
||||
msgstr ""
|
||||
|
||||
#: templates/index.tpl:61
|
||||
msgid "Synchronize local data"
|
||||
msgstr ""
|
||||
|
||||
#: templates/index.tpl:63
|
||||
msgid "Purge local data"
|
||||
msgstr ""
|
||||
|
||||
#: templates/index.tpl:64
|
||||
msgid "Load example data"
|
||||
msgstr ""
|
||||
|
||||
#: templates/index.tpl:74
|
||||
msgid "Login"
|
||||
msgstr ""
|
||||
|
||||
#: templates/index.tpl:96
|
||||
msgid "Suitcase name"
|
||||
msgstr ""
|
||||
|
||||
#: templates/index.tpl:102 templates/index.tpl:168 templates/index.tpl:218
|
||||
msgid "Add"
|
||||
msgstr ""
|
||||
|
||||
#: templates/index.tpl:118
|
||||
msgid "Name of the new suitcase"
|
||||
msgstr ""
|
||||
|
||||
#: templates/index.tpl:124
|
||||
msgid "Copy"
|
||||
msgstr ""
|
||||
|
||||
#: templates/index.tpl:140
|
||||
msgid "New suitcase name"
|
||||
msgstr ""
|
||||
|
||||
#: templates/index.tpl:146 templates/index.tpl:190
|
||||
msgid "Rename"
|
||||
msgstr ""
|
||||
|
||||
#: templates/index.tpl:162
|
||||
msgid "Category name"
|
||||
msgstr ""
|
||||
|
||||
#: templates/index.tpl:179
|
||||
msgid "Rename the category"
|
||||
msgstr ""
|
||||
|
||||
#: templates/index.tpl:184
|
||||
msgid "New category's name"
|
||||
msgstr ""
|
||||
|
||||
#: templates/index.tpl:207 templates/index.tpl:234
|
||||
msgid "Element name"
|
||||
msgstr ""
|
||||
|
||||
#: templates/index.tpl:229
|
||||
msgid "Edit the element"
|
||||
msgstr ""
|
||||
|
||||
#: templates/index.tpl:241
|
||||
msgid "Modify"
|
||||
msgstr ""
|
||||
|
||||
#: templates/index.tpl:252 templates/index.tpl:257
|
||||
msgid "Loading..."
|
||||
msgstr ""
|
||||
|
||||
#: templates/index.tpl:271
|
||||
msgid "Connection"
|
||||
msgstr ""
|
||||
|
||||
#: templates/index.tpl:276
|
||||
msgid "Username"
|
||||
msgstr ""
|
||||
|
||||
#: templates/index.tpl:277
|
||||
msgid "Password"
|
||||
msgstr ""
|
||||
|
||||
#: templates/index.tpl:283 templates/index.tpl:326
|
||||
msgid "Connect"
|
||||
msgstr ""
|
||||
|
||||
#: templates/index.tpl:295
|
||||
msgid "Welcome"
|
||||
msgstr ""
|
||||
|
||||
#: templates/index.tpl:298
|
||||
msgid ""
|
||||
"<p>\n"
|
||||
" This application allows you to manage lists of things not to "
|
||||
"forget to pack in your\n"
|
||||
" suitcase before your departure:\n"
|
||||
" <ul>\n"
|
||||
" <li>\n"
|
||||
" To get started, create a suitcase, add the categories of "
|
||||
"things you will need to\n"
|
||||
" pack, and add all these things to it;\n"
|
||||
" </li>\n"
|
||||
" <li>\n"
|
||||
" Before your departure, you can then gradually check off all "
|
||||
"the things you have\n"
|
||||
" already gathered and ensure you don't forget anything!\n"
|
||||
" </li>\n"
|
||||
" </ul>\n"
|
||||
" </p>\n"
|
||||
" <p>\n"
|
||||
" <strong>Note:</strong> This application has been designed to work "
|
||||
"completely locally.\n"
|
||||
" The data manipulated (your suitcases, etc.) is stored only in your "
|
||||
"internet browser.\n"
|
||||
" It is also possible to export/import this information in JSON "
|
||||
"format.<br/>\n"
|
||||
" However, to facilitate the management of your suitcases from "
|
||||
"multiple devices, it's\n"
|
||||
" possible to synchronize this information on the server. For this, "
|
||||
"you need an account,\n"
|
||||
" and at this time, registrations are not open.\n"
|
||||
" </p>\n"
|
||||
" <p>\n"
|
||||
" If you have an account, you can log in by clicking the <em>Login</"
|
||||
"em> button below.\n"
|
||||
" If not, click the <em>Anonymous usage</em> button to start using "
|
||||
"the application.\n"
|
||||
" </p>"
|
||||
msgstr ""
|
||||
|
||||
#: templates/index.tpl:327
|
||||
msgid "Anonymous usage"
|
||||
msgstr ""
|
14
phpstan.neon
Normal file
|
@ -0,0 +1,14 @@
|
|||
parameters:
|
||||
level: 5
|
||||
paths:
|
||||
- bin
|
||||
- includes
|
||||
- src
|
||||
- public_html
|
||||
universalObjectCratesClasses:
|
||||
- EesyPHP\HookEvent
|
||||
- EesyPHP\UrlRequest
|
||||
- EesyPHP\Auth\User
|
||||
- EesyPHP\Db\DbObject
|
||||
bootstrapFiles:
|
||||
- includes/core.php
|
8
public_html/.htaccess
Normal file
|
@ -0,0 +1,8 @@
|
|||
RewriteEngine On
|
||||
#RewriteBase /app
|
||||
|
||||
# If the request is not for a valid file
|
||||
RewriteCond %{REQUEST_FILENAME} !-f
|
||||
# If the request is not for a valid link
|
||||
RewriteCond %{REQUEST_FILENAME} !-l
|
||||
RewriteRule ^ index.php [L]
|
|
@ -1,39 +0,0 @@
|
|||
CACHE MANIFEST
|
||||
# Date : 2018/06/18 - Version : 1
|
||||
|
||||
CACHE:
|
||||
index.html
|
||||
favicon.png
|
||||
icon-196x196.png
|
||||
icon-128x128.png
|
||||
|
||||
inc/main.css
|
||||
|
||||
inc/main.js
|
||||
inc/mysc_objects.js
|
||||
|
||||
inc/mydialog.js
|
||||
|
||||
# Bootstrap
|
||||
inc/lib/bootstrap/css/bootstrap.min.css
|
||||
inc/lib/bootstrap/css/bootstrap-theme.min.css
|
||||
inc/lib/bootstrap/css/bootstrap.css
|
||||
inc/lib/bootstrap/css/bootstrap-theme.css
|
||||
inc/lib/bootstrap/css/bootstrap.css.map
|
||||
inc/lib/bootstrap/css/bootstrap-theme.min.css.map
|
||||
inc/lib/bootstrap/css/bootstrap-theme.css.map
|
||||
inc/lib/bootstrap/css/bootstrap.min.css.map
|
||||
inc/lib/bootstrap/js/bootstrap.js
|
||||
inc/lib/bootstrap/js/npm.js
|
||||
inc/lib/bootstrap/js/bootstrap.min.js
|
||||
inc/lib/bootstrap/fonts/glyphicons-halflings-regular.eot
|
||||
inc/lib/bootstrap/fonts/glyphicons-halflings-regular.woff2
|
||||
inc/lib/bootstrap/fonts/glyphicons-halflings-regular.woff
|
||||
inc/lib/bootstrap/fonts/glyphicons-halflings-regular.svg
|
||||
inc/lib/bootstrap/fonts/glyphicons-halflings-regular.ttf
|
||||
|
||||
# jQuery
|
||||
inc/lib/jquery.min.js
|
||||
|
||||
NETWORK:
|
||||
*
|
|
@ -1,962 +0,0 @@
|
|||
$('#cats').collapse({
|
||||
toggle: false
|
||||
});
|
||||
|
||||
on_title_click=function(event) {
|
||||
if (event.target.tagName=='BUTTON') {
|
||||
return;
|
||||
}
|
||||
var title=$(this);
|
||||
var panel=title.parent().parent();
|
||||
var panel_collapse=panel.find('.panel-collapse');
|
||||
var show=!panel_collapse.hasClass('in');
|
||||
$('.panel-collapse').each(function(idx,div) {
|
||||
$(div).collapse('hide');
|
||||
});
|
||||
if (show) {
|
||||
panel_collapse.collapse('show');
|
||||
}
|
||||
}
|
||||
|
||||
/***********************
|
||||
* Add scase
|
||||
**********************/
|
||||
on_add_scase_btn_click=function(event) {
|
||||
navbar_collapse_hide();
|
||||
$('#add_scase_modal').modal('show');
|
||||
}
|
||||
|
||||
on_valid_add_scase_modal=function (e) {
|
||||
e.preventDefault();
|
||||
var name=$('#add_scase_name')[0].value;
|
||||
if (name=='') {
|
||||
alert("Vous devez saisir le nom de la valise !");
|
||||
return;
|
||||
}
|
||||
var nameshake=scases.byName(name);
|
||||
if (nameshake) {
|
||||
if (nameshake.removed) {
|
||||
alert("Une valise de ce nom existe dans la corbeille !");
|
||||
}
|
||||
else {
|
||||
alert("Cette valise existe déjà !");
|
||||
}
|
||||
return;
|
||||
}
|
||||
var scase=scases.newSCase(name);
|
||||
if (scase) {
|
||||
scases.save();
|
||||
show_scase(scase);
|
||||
}
|
||||
$('#add_scase_modal').modal('hide');
|
||||
}
|
||||
|
||||
on_show_add_scase_modal=function () {
|
||||
$('#add_scase_name').focus();
|
||||
}
|
||||
|
||||
on_close_add_scase_modal=function () {
|
||||
$('#add_scase_modal form')[0].reset();
|
||||
}
|
||||
|
||||
/***********************
|
||||
* Rename scase
|
||||
**********************/
|
||||
on_rename_scase_btn_click=function(event) {
|
||||
navbar_collapse_hide();
|
||||
$('#rename_scase_name')[0].value=$('#cats').data('scase');
|
||||
$('#rename_scase_modal').modal('show');
|
||||
}
|
||||
|
||||
on_valid_rename_scase_modal=function (e) {
|
||||
e.preventDefault();
|
||||
var name=$('#rename_scase_name')[0].value;
|
||||
if (name=='') {
|
||||
alert("Vous devez saisir le nouveau nom de la valise !");
|
||||
return;
|
||||
}
|
||||
if ($('#cats').data('scase')!=name) {
|
||||
var nameshake=scases.byName(name);
|
||||
if (nameshake) {
|
||||
if (nameshake.removed) {
|
||||
alert("Une valise portant ce nom existe dans la corbeille !");
|
||||
}
|
||||
else {
|
||||
alert("Une valise portant ce nom existe déjà !");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
var scase=scases.renameSCase($('#cats').data('scase'),name);
|
||||
if (scase) {
|
||||
scases.save();
|
||||
show_scase(scase);
|
||||
}
|
||||
else {
|
||||
alert('Une erreur est survenue en renomant la valise...');
|
||||
}
|
||||
}
|
||||
$('#rename_scase_modal').modal('hide');
|
||||
}
|
||||
|
||||
on_show_rename_scase_modal=function () {
|
||||
$('#rename_scase_name').focus();
|
||||
}
|
||||
|
||||
on_close_rename_scase_modal=function () {
|
||||
$('#rename_scase_modal form')[0].reset();
|
||||
}
|
||||
|
||||
/***********************
|
||||
* Copy scase
|
||||
**********************/
|
||||
on_copy_scase_btn_click=function(event) {
|
||||
navbar_collapse_hide();
|
||||
$('#copy_scase_modal').modal('show');
|
||||
}
|
||||
|
||||
on_valid_copy_scase_modal=function (e) {
|
||||
e.preventDefault();
|
||||
var name=$('#copy_scase_name')[0].value;
|
||||
if (name=='') {
|
||||
alert("Vous devez saisir le nom de la nouvelle valise !");
|
||||
return;
|
||||
}
|
||||
var nameshake=scases.byName(name);
|
||||
if (nameshake) {
|
||||
if (nameshake.removed) {
|
||||
alert("Une valise portant ce nom existe dans la corbeille !");
|
||||
}
|
||||
else {
|
||||
alert("Une valise portant ce nom existe déjà !");
|
||||
}
|
||||
return;
|
||||
}
|
||||
var scase=scases.copySCase($('#cats').data('scase'),name);
|
||||
if (scase) {
|
||||
scases.save();
|
||||
show_scase(scase);
|
||||
}
|
||||
else {
|
||||
alert('Une erreur est survenue en copiant la valise...');
|
||||
}
|
||||
$('#copy_scase_modal').modal('hide');
|
||||
}
|
||||
|
||||
on_show_copy_scase_modal=function () {
|
||||
$('#copy_scase_name').focus();
|
||||
}
|
||||
|
||||
on_close_copy_scase_modal=function () {
|
||||
$('#copy_scase_modal form')[0].reset();
|
||||
}
|
||||
|
||||
/***********************
|
||||
* Reset scase
|
||||
**********************/
|
||||
on_reset_scase_btn_click=function(event) {
|
||||
navbar_collapse_hide();
|
||||
var scase=scases.byName($('#cats').data('scase'));
|
||||
if (scase) {
|
||||
myconfirm('Voulez-vous vraiment réinitialiser la valise '+$('#cats').data('scase')+' ?',
|
||||
function(data) {
|
||||
scases.resetSCase(scase.name);
|
||||
scases.save();
|
||||
show_scase(scase);
|
||||
});
|
||||
}
|
||||
}
|
||||
/***********************
|
||||
* Delete scase
|
||||
**********************/
|
||||
on_delete_scase_btn_click=function(event) {
|
||||
navbar_collapse_hide();
|
||||
var scase=scases.byName($('#cats').data('scase'));
|
||||
if (scase) {
|
||||
myconfirm('Voulez-vous vraiment supprimer la valise '+$('#cats').data('scase')+' ?',
|
||||
function(data) {
|
||||
scases.removeSCase(scase.name);
|
||||
scases.save();
|
||||
show_scases();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
on_restore_scase_btn_click=function(event) {
|
||||
navbar_collapse_hide();
|
||||
var scase=event.data.scase;
|
||||
if (scase) {
|
||||
myconfirm('Voulez-vous vraiment restaurer la valise '+scase.name+' ?',
|
||||
function(data) {
|
||||
scase.restore();
|
||||
scases.save();
|
||||
show_scases();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
on_scase_trash_btn_click=function(event) {
|
||||
event.preventDefault();
|
||||
navbar_collapse_hide();
|
||||
var scase=scases.byName($('#cats').data('scase'));
|
||||
if (scase) {
|
||||
show_scase_trash(scase);
|
||||
}
|
||||
}
|
||||
|
||||
/***********************
|
||||
* Add cat
|
||||
**********************/
|
||||
on_add_cat_btn_click=function(event) {
|
||||
navbar_collapse_hide();
|
||||
$('#add_cat_modal').modal('show');
|
||||
}
|
||||
|
||||
on_valid_add_cat_modal=function (e) {
|
||||
e.preventDefault();
|
||||
var name=$('#add_cat_name')[0].value;
|
||||
if (name=='') {
|
||||
alert("Vous devez saisir le nom de la catégorie !");
|
||||
return;
|
||||
}
|
||||
var scase=scases.byName($('#cats').data('scase'));
|
||||
if (scase) {
|
||||
var nameshake=scase.cats.byName(name);
|
||||
if (nameshake) {
|
||||
if (nameshake.removed) {
|
||||
alert("Une catégorie portant ce nom existe dans la corbeille !");
|
||||
}
|
||||
else {
|
||||
alert("Une catégorie portant ce nom existe déjà !");
|
||||
}
|
||||
return;
|
||||
}
|
||||
var cat=scase.cats.newCat(name);
|
||||
if (cat) {
|
||||
scases.save();
|
||||
show_scase(scase,cat.name);
|
||||
}
|
||||
}
|
||||
$('#add_cat_modal').modal('hide');
|
||||
}
|
||||
|
||||
on_show_add_cat_modal=function () {
|
||||
$('#add_cat_name').focus();
|
||||
}
|
||||
|
||||
on_close_add_cat_modal=function () {
|
||||
$('#add_cat_modal form')[0].reset();
|
||||
}
|
||||
|
||||
/***********************
|
||||
* Rename cat
|
||||
**********************/
|
||||
on_rename_cat_btn_click=function(event) {
|
||||
navbar_collapse_hide();
|
||||
$('#rename_cat_modal').data('cat',event.data.cat.name);
|
||||
$('#rename_cat_name')[0].value=event.data.cat.name;
|
||||
$('#rename_cat_modal').modal('show');
|
||||
}
|
||||
|
||||
on_valid_rename_cat_modal=function (e) {
|
||||
e.preventDefault();
|
||||
var name=$('#rename_cat_name')[0].value;
|
||||
if (name=='') {
|
||||
alert("Vous devez saisir le nouveau nom de la catégorie !");
|
||||
return;
|
||||
}
|
||||
var scase=scases.byName($('#cats').data('scase'));
|
||||
if (scase) {
|
||||
if (scase.cats.byName(name)) {
|
||||
var namesake=scase.cats.byName(name);
|
||||
if (namesake.removed) {
|
||||
alert("Une catégorie de se nom existe dans la corbeille !");
|
||||
}
|
||||
else {
|
||||
alert("Cette catégorie existe déjà !");
|
||||
}
|
||||
return;
|
||||
}
|
||||
var cat=scase.cats.renameCat($('#rename_cat_modal').data('cat'),name);
|
||||
if (cat) {
|
||||
scases.save();
|
||||
show_scase(scase,cat.name);
|
||||
}
|
||||
}
|
||||
$('#rename_cat_modal').modal('hide');
|
||||
}
|
||||
|
||||
on_show_rename_cat_modal=function () {
|
||||
$('#rename_cat_name').focus();
|
||||
}
|
||||
|
||||
on_close_rename_cat_modal=function () {
|
||||
$('#rename_cat_modal form')[0].reset();
|
||||
}
|
||||
|
||||
/***********************
|
||||
* Delete cat
|
||||
**********************/
|
||||
on_delete_cat_btn_click=function(event) {
|
||||
navbar_collapse_hide();
|
||||
var scase=scases.byName($('#cats').data('scase'));
|
||||
if (scase) {
|
||||
var cat=event.data.cat.name;
|
||||
myconfirm('Voulez-vous vraiment supprimer la catégorie '+cat+' ?',
|
||||
function(data) {
|
||||
scase.cats.removeCat(cat);
|
||||
scases.save();
|
||||
show_scase(scase);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
on_restore_cat_btn_click=function(event) {
|
||||
navbar_collapse_hide();
|
||||
var scase=scases.byName($('#cats').data('scase'));
|
||||
if (scase) {
|
||||
var cat=event.data.cat.name;
|
||||
myconfirm('Voulez-vous vraiment restaure la catégorie '+cat+' ?',
|
||||
function(data) {
|
||||
scase.cats.restoreCat(cat);
|
||||
scases.save();
|
||||
show_scase(scase);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/************************
|
||||
* Check/Uncheck thing
|
||||
***********************/
|
||||
on_li_click=function(event) {
|
||||
if (event.target.tagName!='LI') {
|
||||
return;
|
||||
}
|
||||
var li=$(this);
|
||||
if (li.hasClass('checked')) {
|
||||
li.removeClass('checked');
|
||||
}
|
||||
else {
|
||||
li.addClass('checked');
|
||||
}
|
||||
var ul=li.parent();
|
||||
var scase=scases.byName($('#cats').data('scase'));
|
||||
if (scase) {
|
||||
var cat=scase.cats.byName(ul.data('cat'));
|
||||
if (cat) {
|
||||
var thing=cat.byLabel(li.data('label'));
|
||||
if (thing) {
|
||||
thing.setChecked(li.hasClass('checked'));
|
||||
scases.save();
|
||||
}
|
||||
show_scase(scase,cat.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/***********************
|
||||
* Add thing
|
||||
**********************/
|
||||
on_li_add_click=function(event) {
|
||||
var li=$(this);
|
||||
var cat=li.parent().data('cat');
|
||||
var modal=$('#add_thing_modal');
|
||||
modal.data('cat',cat);
|
||||
modal.modal('show');
|
||||
}
|
||||
|
||||
on_valid_add_thing_modal=function (e) {
|
||||
e.preventDefault();
|
||||
|
||||
var modal=$('#add_thing_modal');
|
||||
var scase=scases.byName($('#cats').data('scase'));
|
||||
if (scase) {
|
||||
var cat=scase.cats.byName(modal.data('cat'));
|
||||
if (cat) {
|
||||
var things=[];
|
||||
var labels=[];
|
||||
var error=false;
|
||||
var add_thing_nbs=$('input.add_thing_nb');
|
||||
$('input.add_thing_label').each(function(idx,input) {
|
||||
var label=$(input).val();
|
||||
if (label && label!='') {
|
||||
if (labels.indexOf(label)>-1) {
|
||||
alert("Deux élements ne peuvent porter le même nom !");
|
||||
error=true;
|
||||
return;
|
||||
}
|
||||
if (cat.byLabel(label)) {
|
||||
alert("L'élément '"+label+"' existe déjà !");
|
||||
error=true;
|
||||
return;
|
||||
}
|
||||
var nb=1;
|
||||
if (add_thing_nbs[idx]) {
|
||||
nb=parseInt($(add_thing_nbs[idx]).val());
|
||||
if (!nb || nb==0) {
|
||||
nb=1;
|
||||
}
|
||||
}
|
||||
things.push({
|
||||
'label': label,
|
||||
'nb': nb
|
||||
});
|
||||
labels.push(label);
|
||||
}
|
||||
});
|
||||
if (error) {
|
||||
return;
|
||||
}
|
||||
if (things.length==0) {
|
||||
alert("Vous devez saisir au moins un nom d'élément !");
|
||||
return;
|
||||
}
|
||||
for (idx in things) {
|
||||
cat.newThing(things[idx]['label'], things[idx]['nb']);
|
||||
}
|
||||
scases.save();
|
||||
show_scase(scase,cat.name);
|
||||
}
|
||||
}
|
||||
modal.modal('hide');
|
||||
}
|
||||
|
||||
on_show_add_thing_modal=function () {
|
||||
$('.add_thing_other').remove();
|
||||
$('input.add_thing_label').val('');
|
||||
$('input.add_thing_nb').val('');
|
||||
$('input.add_thing_label').first().focus();
|
||||
}
|
||||
|
||||
on_close_add_thing_modal=function () {
|
||||
$('#add_thing_modal form')[0].reset();
|
||||
}
|
||||
|
||||
on_add_thing_label_focus=function(event) {
|
||||
if ($('input.add_thing_label').last()[0] == event.target) {
|
||||
var new_input_group=$('<div class="form-group add_thing_other"></div>');
|
||||
var new_input_label=$('<input type="text" class="form-control add_thing_label" placeholder="Encore un ?"/>');
|
||||
var new_input_nb=$('<input type="number" class="form-control add_thing_nb" placeholder="Nb"/>');
|
||||
new_input_group.append(new_input_label);
|
||||
new_input_group.append(' ');
|
||||
new_input_group.append(new_input_nb);
|
||||
new_input_label.bind('focus', on_add_thing_label_focus);
|
||||
$(event.target).parent().after(new_input_group);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/***********************
|
||||
* Edit thing
|
||||
**********************/
|
||||
on_edit_thing_btn_click=function(event) {
|
||||
navbar_collapse_hide();
|
||||
$('#edit_thing_modal').data('cat',event.data.cat.name);
|
||||
$('#edit_thing_modal').data('thing',event.data.thing.label);
|
||||
$('#edit_thing_label').val(event.data.thing.label);
|
||||
$('#edit_thing_nb').val(event.data.thing.nb);
|
||||
$('#edit_thing_modal').modal('show');
|
||||
}
|
||||
|
||||
on_valid_edit_thing_modal=function (e) {
|
||||
e.preventDefault();
|
||||
var label=$('#edit_thing_label').val();
|
||||
if (label=='') {
|
||||
alert("Vous devez saisir le nouveau nom de l'élément !");
|
||||
return;
|
||||
}
|
||||
var nb=parseInt($('#edit_thing_nb').val());
|
||||
if (!nb || nb==0) {
|
||||
nb=1;
|
||||
}
|
||||
var scase=scases.byName($('#cats').data('scase'));
|
||||
if (scase) {
|
||||
var cat=scase.cats.byName($('#edit_thing_modal').data('cat'));
|
||||
if (cat) {
|
||||
if (label!=$('#edit_thing_modal').data('thing')) {
|
||||
var namesake=cat.byLabel(label);
|
||||
if (namesake) {
|
||||
if (namesake.removed) {
|
||||
alert("Un élément de ce nom existe dans la corbeille !");
|
||||
}
|
||||
else {
|
||||
alert("Un élément de ce nom existe déjà !");
|
||||
}
|
||||
return;
|
||||
}
|
||||
var thing=cat.renameThing($('#edit_thing_modal').data('thing'),label);
|
||||
}
|
||||
else {
|
||||
var thing=cat.byLabel(label);
|
||||
}
|
||||
if (thing) {
|
||||
thing.setNb(nb);
|
||||
scases.save();
|
||||
show_scase(scase,cat.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
$('#edit_thing_modal').modal('hide');
|
||||
}
|
||||
|
||||
on_show_edit_thing_modal=function () {
|
||||
$('#edit_thing_label').focus();
|
||||
}
|
||||
|
||||
on_close_edit_thing_modal=function () {
|
||||
$('#edit_thing_modal form')[0].reset();
|
||||
}
|
||||
|
||||
/***********************
|
||||
* Delete thing
|
||||
**********************/
|
||||
on_delete_thing_btn_click=function(event) {
|
||||
navbar_collapse_hide();
|
||||
var scase=scases.byName($('#cats').data('scase'));
|
||||
if (scase) {
|
||||
var cat=scase.cats.byName(event.data.cat.name);
|
||||
if (cat) {
|
||||
var thing=event.data.thing.label;
|
||||
myconfirm("Voulez-vous vraiment supprimer l'élément "+thing+" ?",
|
||||
function(data) {
|
||||
cat.removeThing(thing);
|
||||
scases.save();
|
||||
show_scase(scase,cat.name);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
on_restore_thing_btn_click=function(event) {
|
||||
navbar_collapse_hide();
|
||||
var scase=scases.byName($('#cats').data('scase'));
|
||||
if (scase) {
|
||||
var cat=scase.cats.byName(event.data.cat.name);
|
||||
if (cat) {
|
||||
var thing=event.data.thing.label;
|
||||
myconfirm("Voulez-vous vraiment restaurer l'élément "+thing+" ?",
|
||||
function(data) {
|
||||
cat.restoreThing(thing);
|
||||
scases.save();
|
||||
show_scase(scase,cat.name);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/********************
|
||||
* Show one scase
|
||||
*******************/
|
||||
show_cat=function(cat,displayed) {
|
||||
var panel=$('<div class="panel panel-default"></div>');
|
||||
var panel_heading=$('<div class="panel-heading" role="tab"></div>');
|
||||
var panel_title=$('<h4 class="panel-title">'+cat.name+' </h4>');
|
||||
panel_title.bind('click',on_title_click);
|
||||
|
||||
var stats=cat.stats();
|
||||
var tag=$('<span class="count-tag pull-right"></span>');
|
||||
if (stats.things==stats.done) {
|
||||
tag.append($('<span class="label label-success"><span class="glyphicon glyphicon-ok" aria-hidden="true"></span></span>'));
|
||||
}
|
||||
else {
|
||||
tag.append($('<span class="badge">'+stats.done+' / '+stats.things+'</span>'));
|
||||
}
|
||||
|
||||
var delete_btn=$('<button class="btn btn-default btn-xs pull-right"><span class="glyphicon glyphicon-trash"></button>');
|
||||
delete_btn.bind('click',{'cat': cat},on_delete_cat_btn_click);
|
||||
tag.append(delete_btn);
|
||||
|
||||
var rename_btn=$('<button class="btn btn-default btn-xs pull-right"><span class="glyphicon glyphicon-edit"></button>');
|
||||
rename_btn.bind('click',{'cat': cat},on_rename_cat_btn_click);
|
||||
tag.append(rename_btn);
|
||||
|
||||
panel_title.append(tag);
|
||||
|
||||
|
||||
panel_heading.append(panel_title);
|
||||
panel.append(panel_heading);
|
||||
var panel_collapse=$('<div class="panel-collapse collapse" role="tabpanel"></div>');
|
||||
if (displayed) {
|
||||
panel_collapse.addClass('in');
|
||||
}
|
||||
var ul=$('<ul class="list-group" data-cat="'+cat.name+'"></ul>');
|
||||
for (idx in cat.things) {
|
||||
if (cat.things[idx].removed) {
|
||||
continue;
|
||||
}
|
||||
var li=$('<li class="list-group-item checkable" data-label="'+cat.things[idx].label+'">'+cat.things[idx].label+'</li>');
|
||||
if (cat.things[idx].nb>1) {
|
||||
li.append(' <em>('+cat.things[idx].nb+')</em>');
|
||||
}
|
||||
if (cat.things[idx].checked) {
|
||||
li.addClass('checked');
|
||||
}
|
||||
li.bind('click',on_li_click);
|
||||
|
||||
var li_actions=$('<span class="actions pull-right"></span>');
|
||||
|
||||
var delete_el_btn=$('<button class="btn btn-default btn-xs pull-right"><span class="glyphicon glyphicon-trash"></button>');
|
||||
delete_el_btn.bind('click',{'cat': cat,'thing': cat.things[idx]},on_delete_thing_btn_click);
|
||||
li_actions.append(delete_el_btn);
|
||||
|
||||
var edit_el_btn=$('<button class="btn btn-default btn-xs pull-right"><span class="glyphicon glyphicon-edit"></button>');
|
||||
edit_el_btn.bind('click',{'cat': cat,'thing': cat.things[idx]},on_edit_thing_btn_click);
|
||||
li_actions.append(edit_el_btn);
|
||||
|
||||
li.append(li_actions);
|
||||
|
||||
ul.append(li);
|
||||
}
|
||||
var li=$('<li class="list-group-item"><span class="glyphicon glyphicon-plus-sign"></span> Ajouter un élément</li>');
|
||||
li.bind('click',on_li_add_click);
|
||||
ul.append(li);
|
||||
panel_collapse.append(ul);
|
||||
panel.append(panel_collapse);
|
||||
$('#cats').append(panel);
|
||||
}
|
||||
|
||||
show_scase=function(scase,display_cat) {
|
||||
clear_page('<h3><span class="glyphicon glyphicon-briefcase" aria-hidden="true"></span> '+scase.name+'</h3><div class="panel-group" id="cats" role="tablist" aria-multiselectable="true" data-scase="'+scase.name+'"></div>');
|
||||
scase.cats.each(function(idx,cat) {
|
||||
if (cat.removed) {
|
||||
return;
|
||||
}
|
||||
show_cat(cat,(cat.name==display_cat));
|
||||
});
|
||||
show_menu('scase');
|
||||
}
|
||||
|
||||
on_back_to_scases_btn_click=function(e) {
|
||||
e.preventDefault();
|
||||
navbar_collapse_hide();
|
||||
show_scases();
|
||||
}
|
||||
|
||||
/********************
|
||||
* Show scase trash
|
||||
*******************/
|
||||
show_scase_trash=function(scase,display_cat) {
|
||||
clear_page('<h3><span class="glyphicon glyphicon-trash" aria-hidden="true"></span>'+scase.name+' : Corbeille <button class="btn btn-default btn-xs" id="back_btn"><span class="glyphicon glyphicon-arrow-left"></button></h3><div class="panel-group" id="cats" role="tablist" aria-multiselectable="true" data-scase="'+scase.name+'"></div>');
|
||||
|
||||
$('#content h3 #back_btn').bind('click', {'scase': scase}, function(event) {
|
||||
show_scase(event.data.scase);
|
||||
});
|
||||
|
||||
scase.cats.each(function(idx,cat) {
|
||||
show_cat_trash(cat,(cat.name==display_cat));
|
||||
});
|
||||
if ($('#cats .panel').length==0) {
|
||||
$('#content').append('<p class="center">La corbeille est vide.</p>');
|
||||
}
|
||||
show_menu('scase');
|
||||
}
|
||||
|
||||
show_cat_trash=function(cat,displayed) {
|
||||
var panel=$('<div class="panel panel-default"></div>');
|
||||
var panel_heading=$('<div class="panel-heading" role="tab"></div>');
|
||||
var panel_title=$('<h4 class="panel-title">'+cat.name+' </h4>');
|
||||
|
||||
var tag=$('<span class="count-tag pull-right"></span>');
|
||||
|
||||
panel_title.append(tag);
|
||||
|
||||
|
||||
panel_heading.append(panel_title);
|
||||
panel.append(panel_heading);
|
||||
|
||||
|
||||
if (cat.removed) {
|
||||
var stats=cat.stats();
|
||||
tag.append($('<span class="badge">'+stats.things+'</span>'));
|
||||
|
||||
var restore_btn=$('<button class="btn btn-default btn-xs pull-right"><span class="glyphicon glyphicon-ok"></button>');
|
||||
restore_btn.bind('click',{'cat': cat},on_restore_cat_btn_click);
|
||||
tag.append(restore_btn);
|
||||
}
|
||||
else {
|
||||
var deleted_things=[];
|
||||
for (idx in cat.things) {
|
||||
if (cat.things[idx].removed) {
|
||||
deleted_things.push(cat.things[idx]);
|
||||
}
|
||||
}
|
||||
if (deleted_things.length==0) {
|
||||
return true;
|
||||
}
|
||||
panel_title.bind('click',on_title_click);
|
||||
tag.append($('<span class="badge">'+deleted_things.length+'</span>'));
|
||||
|
||||
var panel_collapse=$('<div class="panel-collapse collapse" role="tabpanel"></div>');
|
||||
if (displayed) {
|
||||
panel_collapse.addClass('in');
|
||||
}
|
||||
var ul=$('<ul class="list-group" data-cat="'+cat.name+'"></ul>');
|
||||
for (idx in deleted_things) {
|
||||
var li=$('<li class="list-group-item" data-label="'+deleted_things[idx].label+'">'+deleted_things[idx].label+'</li>');
|
||||
var li_actions=$('<span class="actions pull-right"></span>');
|
||||
|
||||
var restore_el_btn=$('<button class="btn btn-default btn-xs pull-right"><span class="glyphicon glyphicon-ok"></button>');
|
||||
restore_el_btn.bind('click',{'cat': cat,'thing': deleted_things[idx]},on_restore_thing_btn_click);
|
||||
li_actions.append(restore_el_btn);
|
||||
|
||||
li.append(li_actions);
|
||||
|
||||
ul.append(li);
|
||||
}
|
||||
panel_collapse.append(ul);
|
||||
panel.append(panel_collapse);
|
||||
}
|
||||
|
||||
$('#cats').append(panel);
|
||||
}
|
||||
|
||||
on_back_to_scase_btn_click=function(e) {
|
||||
e.preventDefault();
|
||||
navbar_collapse_hide();
|
||||
show_scase(e.data.scase);
|
||||
}
|
||||
|
||||
/********************
|
||||
* Show scases
|
||||
*******************/
|
||||
show_scases=function() {
|
||||
clear_page('<h3>Vos valises</h3><ul class="list-group" id="scases"></ul>');
|
||||
scases.each(function(idx,scase) {
|
||||
if (scase.removed) {
|
||||
return;
|
||||
}
|
||||
var stats=scase.stats();
|
||||
var tag='<span class="count-tag pull-right">';
|
||||
if (stats.things==stats.done) {
|
||||
tag+='<span class="label label-success"><span class="glyphicon glyphicon-ok" aria-hidden="true"></span></span>';
|
||||
}
|
||||
else {
|
||||
tag+='<span class="badge">'+stats.done+' / '+stats.things+'</span>';
|
||||
}
|
||||
tag+='</span>';
|
||||
|
||||
var li=$('<li class="list-group-item" data-name="'+scase.name+'"><span class="scase-name"><span class="glyphicon glyphicon-briefcase" aria-hidden="true"></span> '+scase.name+'</span>'+tag+'</li>');
|
||||
li.bind('click',on_scase_click);
|
||||
$('#scases').append(li);
|
||||
});
|
||||
show_menu('scases');
|
||||
}
|
||||
|
||||
on_scase_click=function(event) {
|
||||
var li=$(this);
|
||||
var scase=scases.byName(li.data('name'));
|
||||
show_scase(scase);
|
||||
}
|
||||
|
||||
/********************
|
||||
* Show scases trash
|
||||
*******************/
|
||||
show_scases_trash=function() {
|
||||
clear_page('<h3>Corbeille <button class="btn btn-default btn-xs" id="back_btn"><span class="glyphicon glyphicon-arrow-left"></button></h3><ul class="list-group" id="scases"></ul>');
|
||||
$('#content h3 #back_btn').bind('click', function(event) {
|
||||
show_scases();
|
||||
});
|
||||
|
||||
scases.each(function(idx,scase) {
|
||||
if (!scase.removed) {
|
||||
return;
|
||||
}
|
||||
var stats=scase.stats();
|
||||
var tags=$('<span class="count-tag pull-right"></span>');
|
||||
tags.append('<span class="badge">'+stats.things+'</span>');
|
||||
|
||||
var restore_btn=$('<button class="btn btn-default btn-xs pull-right"><span class="glyphicon glyphicon-ok"></button>');
|
||||
restore_btn.bind('click',{'scase': scase},on_restore_scase_btn_click);
|
||||
tags.append(restore_btn);
|
||||
|
||||
var li=$('<li class="list-group-item" data-name="'+scase.name+'"><span class="scase-name"><span class="glyphicon glyphicon-briefcase" aria-hidden="true"></span> '+scase.name+'</span></li>');
|
||||
li.append(tags);
|
||||
$('#scases').append(li);
|
||||
});
|
||||
if ($('#scases li').length==0) {
|
||||
$('#content').append('<p class="center">Aucune valise dans la corbeille.</p>');
|
||||
}
|
||||
show_menu('scases');
|
||||
}
|
||||
|
||||
on_scases_trash_btn=function(e) {
|
||||
e.preventDefault();
|
||||
navbar_collapse_hide();
|
||||
show_scases_trash();
|
||||
}
|
||||
|
||||
clear_page=function(new_content) {
|
||||
if (new_content) {
|
||||
$('#content').html(new_content);
|
||||
}
|
||||
else {
|
||||
$('#content').html('');
|
||||
}
|
||||
}
|
||||
|
||||
/************************
|
||||
* Show menu
|
||||
***********************/
|
||||
show_menu=function(menu) {
|
||||
$('.menu').css('display','none');
|
||||
$('.menu-'+menu).css('display','block');
|
||||
}
|
||||
|
||||
/*******************
|
||||
* pleaseWaitDialog
|
||||
*******************/
|
||||
|
||||
pleaseWaitShow=function() {
|
||||
$('#please_wait_modal').modal('show');
|
||||
}
|
||||
|
||||
pleaseWaitHide=function() {
|
||||
$('#please_wait_modal').modal('hide');
|
||||
}
|
||||
|
||||
/****************
|
||||
* Nav bars
|
||||
****************/
|
||||
navbar_collapse_hide=function() {
|
||||
if ($('#navbar-top-collapse').hasClass('in')) {
|
||||
$('#navbar-top-collapse').collapse('hide');
|
||||
}
|
||||
}
|
||||
|
||||
/********************
|
||||
* Clear local data
|
||||
********************/
|
||||
clear_local_data=function() {
|
||||
navbar_collapse_hide();
|
||||
myconfirm('Etes-vous sûre de vouloir supprimer les données locales ?',on_confirm_clear_local_data);
|
||||
}
|
||||
|
||||
on_confirm_clear_local_data=function(data) {
|
||||
delete localStorage.scases;
|
||||
location.reload();
|
||||
}
|
||||
|
||||
/*******************************
|
||||
* Import/Export local data
|
||||
*******************************/
|
||||
export_local_data=function() {
|
||||
navbar_collapse_hide();
|
||||
$('#export_local_data').attr('href','data:application/json;base64,' + btoa(JSON.stringify(scases.export())));
|
||||
}
|
||||
|
||||
import_local_data=function() {
|
||||
navbar_collapse_hide();
|
||||
var input=$('<input type="file" accept="application/json">');
|
||||
input.css('display', 'none');
|
||||
input.bind('change',{'input': input},function(e) {
|
||||
pleaseWaitShow();
|
||||
var input=e.data.input;
|
||||
var file=input.prop('files')[0];
|
||||
if (file) {
|
||||
var reader = new FileReader();
|
||||
$(reader).bind('load',function(e) {
|
||||
if ($.type(e.target.result)=='string') {
|
||||
if (e.target.result.startsWith('data:application/json;base64,')) {
|
||||
try {
|
||||
json_data=atob(e.target.result.replace('data:application/json;base64,',''));
|
||||
data=JSON.parse(json_data);
|
||||
pleaseWaitHide();
|
||||
myconfirm('Etes-vous sûre de vouloir écraser vos données locales par celle issues de ce fichier ?',function() {
|
||||
scases.save();
|
||||
var backData=localStorage.scases;
|
||||
localStorage.scases=json_data;
|
||||
scases=new SCaseList();
|
||||
scases.loadFromLocalStorage(backData);
|
||||
show_scases();
|
||||
});
|
||||
}
|
||||
catch (e) {
|
||||
alert('Impossible de décodé le fichier.');
|
||||
pleaseWaitHide();
|
||||
}
|
||||
}
|
||||
else {
|
||||
alert('Fichier invalide.');
|
||||
pleaseWaitHide();
|
||||
}
|
||||
}
|
||||
});
|
||||
reader.readAsDataURL(file);
|
||||
}
|
||||
});
|
||||
$('body').append(input);
|
||||
input[0].click();
|
||||
}
|
||||
|
||||
/*********************
|
||||
* Activate
|
||||
*********************/
|
||||
$( document ).ready( function() {
|
||||
pleaseWaitShow();
|
||||
if(typeof(localStorage)!=="undefined"){
|
||||
scases=new SCaseList();
|
||||
scases.loadFromLocalStorage();
|
||||
show_scases();
|
||||
}
|
||||
else {
|
||||
alert('Local storage not supported !');
|
||||
pleaseWaitHide();
|
||||
return;
|
||||
}
|
||||
|
||||
$('#clear_local_data').bind('click',clear_local_data);
|
||||
$('#import_local_data').bind('click',import_local_data);
|
||||
$('#export_local_data').bind('click',export_local_data);
|
||||
|
||||
$('#add_scase_btn').bind('click',on_add_scase_btn_click);
|
||||
$('#add_scase_submit').bind('click',on_valid_add_scase_modal);
|
||||
$("#add_scase_modal").on('shown.bs.modal',on_show_add_scase_modal);
|
||||
$("#add_scase_modal").on('hidden.bs.modal',on_close_add_scase_modal);
|
||||
$("#add_scase_modal form").bind('submit',on_valid_add_scase_modal);
|
||||
|
||||
$('#scases_trash_btn').bind('click',on_scases_trash_btn);
|
||||
|
||||
$('#rename_scase_btn').bind('click',on_rename_scase_btn_click);
|
||||
$('#rename_scase_submit').bind('click',on_valid_rename_scase_modal);
|
||||
$("#rename_scase_modal").on('shown.bs.modal',on_show_rename_scase_modal);
|
||||
$("#rename_scase_modal").on('hidden.bs.modal',on_close_rename_scase_modal);
|
||||
$("#rename_scase_modal form").bind('submit',on_valid_rename_scase_modal);
|
||||
|
||||
$('#copy_scase_btn').bind('click',on_copy_scase_btn_click);
|
||||
$('#copy_scase_submit').bind('click',on_valid_copy_scase_modal);
|
||||
$("#copy_scase_modal").on('shown.bs.modal',on_show_copy_scase_modal);
|
||||
$("#copy_scase_modal").on('hidden.bs.modal',on_close_copy_scase_modal);
|
||||
$("#copy_scase_modal form").bind('submit',on_valid_copy_scase_modal);
|
||||
|
||||
$('#reset_scase_btn').bind('click',on_reset_scase_btn_click);
|
||||
$('#delete_scase_btn').bind('click',on_delete_scase_btn_click);
|
||||
$('#scase_trash_btn').bind('click',on_scase_trash_btn_click);
|
||||
|
||||
$('#add_cat_btn').bind('click',on_add_cat_btn_click);
|
||||
$('#add_cat_submit').bind('click',on_valid_add_cat_modal);
|
||||
$("#add_cat_modal").on('shown.bs.modal',on_show_add_cat_modal);
|
||||
$("#add_cat_modal").on('hidden.bs.modal',on_close_add_cat_modal);
|
||||
$("#add_cat_modal form").bind('submit',on_valid_add_cat_modal);
|
||||
|
||||
$('#rename_cat_submit').bind('click',on_valid_rename_cat_modal);
|
||||
$("#rename_cat_modal").on('shown.bs.modal',on_show_rename_cat_modal);
|
||||
$("#rename_cat_modal").on('hidden.bs.modal',on_close_rename_cat_modal);
|
||||
$("#rename_cat_modal form").bind('submit',on_valid_rename_cat_modal);
|
||||
|
||||
$('#back_to_scases').bind('click',on_back_to_scases_btn_click);
|
||||
|
||||
$('input.add_thing_label').bind('focus',on_add_thing_label_focus);
|
||||
$('#add_thing_submit').bind('click',on_valid_add_thing_modal);
|
||||
$("#add_thing_modal").on('shown.bs.modal',on_show_add_thing_modal);
|
||||
$("#add_thing_modal").on('hidden.bs.modal',on_close_add_thing_modal);
|
||||
$("#add_thing_modal form").bind('submit',on_valid_add_thing_modal);
|
||||
|
||||
$('#edit_thing_submit').bind('click',on_valid_edit_thing_modal);
|
||||
$("#edit_thing_modal").on('shown.bs.modal',on_show_edit_thing_modal);
|
||||
$("#edit_thing_modal").on('hidden.bs.modal',on_close_edit_thing_modal);
|
||||
$("#edit_thing_modal form").bind('submit',on_valid_edit_thing_modal);
|
||||
|
||||
$('#app-name').bind('click', show_scases);
|
||||
|
||||
pleaseWaitHide();
|
||||
});
|
|
@ -1,35 +0,0 @@
|
|||
var _myconfirm={
|
||||
'onconfirm': null,
|
||||
'oncancel': null,
|
||||
'data': null
|
||||
};
|
||||
|
||||
myconfirm=function(question,onconfirm,oncancel,data) {
|
||||
$('#confirm_modal #question').html(question);
|
||||
_myconfirm={
|
||||
'onconfirm': onconfirm,
|
||||
'oncancel': oncancel,
|
||||
'data': data
|
||||
};
|
||||
$('#confirm_modal').modal('show');
|
||||
}
|
||||
|
||||
_myconfirm_on_valid_click=function(e) {
|
||||
$('#confirm_modal').modal('hide');
|
||||
console.log(jQuery.type(_myconfirm.onconfirm));
|
||||
if (jQuery.type(_myconfirm.onconfirm) == 'function') {
|
||||
_myconfirm.onconfirm(_myconfirm.data);
|
||||
}
|
||||
}
|
||||
|
||||
_myconfirm_on_cancel_click=function(e) {
|
||||
$('#confirm_modal').modal('hide');
|
||||
if (jQuery.type(_myconfirm.oncancel) == 'function') {
|
||||
_myconfirm.oncancel(_myconfirm.data);
|
||||
}
|
||||
}
|
||||
|
||||
$( document ).ready( function() {
|
||||
$('#confirm_modal_submit').bind('click',_myconfirm_on_valid_click);
|
||||
$('#confirm_modal .cancel').bind('click',_myconfirm_on_cancel_click);
|
||||
});
|
|
@ -1,616 +0,0 @@
|
|||
|
||||
|
||||
function SCaseList() {
|
||||
lastChange=0;
|
||||
|
||||
this.importExampleData=function() {
|
||||
var exampleData={
|
||||
'Vacances': {
|
||||
'Papier': {
|
||||
'color': '#f00',
|
||||
'things': [
|
||||
{'label': 'Papier blanc', 'nb': 1 },
|
||||
{'label': 'Stylo', 'nb': 3 },
|
||||
{'label': "Carte d'identité", 'nb': 1 },
|
||||
]
|
||||
},
|
||||
'Multimédia' : {
|
||||
'color': '#0f0',
|
||||
'things': [
|
||||
{'label': 'Montre', 'nb': 1 },
|
||||
{'label': 'Chargeur montre', 'nb': 1 },
|
||||
{'label': 'PC portable', 'nb': 1 },
|
||||
]
|
||||
}
|
||||
}
|
||||
};
|
||||
for (scaseName in exampleData) {
|
||||
var scase=this.newSCase(scaseName);
|
||||
for (catName in exampleData[scaseName]) {
|
||||
var cat=scase.cats.newCat(catName);
|
||||
for (idx in exampleData[scaseName][catName].things) {
|
||||
cat.newThing(exampleData[scaseName][catName].things[idx]['label'],exampleData[scaseName][catName].things[idx]['nb']);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.loadFromLocalStorage=function(backData) {
|
||||
if (jQuery.type(localStorage.scases)!='undefined') {
|
||||
try {
|
||||
var data=JSON.parse(localStorage.scases);
|
||||
this.lastChange=data.lastChange;
|
||||
for (el in data.scases) {
|
||||
this[el]=new SCase(false,false,data.scases[el]);
|
||||
}
|
||||
}
|
||||
catch(e) {
|
||||
for (el in this) {
|
||||
if (this.isSCase(this[el])) {
|
||||
delete this[el];
|
||||
}
|
||||
}
|
||||
if (jQuery.type(backData)!='undefined') {
|
||||
alert('Erreur en chargeant les données. Restauration des données précédentes');
|
||||
localStorage.scases=backData;
|
||||
return this.loadFromLocalStorage();
|
||||
}
|
||||
else {
|
||||
myconfirm('Erreur en chargeant les données locales. On les purges ?',
|
||||
function(data) {
|
||||
delete localStorage.scases;
|
||||
location.reload();
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
myconfirm("<h2>Bienvenu !</h2><p>Souhaitez-vous charger les données d'exemple ?</p>",
|
||||
function(scases) {
|
||||
scases.importExampleData();
|
||||
scases.save();
|
||||
show_scases();
|
||||
},
|
||||
false,
|
||||
this
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
this.export=function() {
|
||||
return {
|
||||
'lastChange': this.lastChange,
|
||||
'scases': this.each(function(idx,scase) {
|
||||
return scase.export();
|
||||
})
|
||||
};
|
||||
}
|
||||
|
||||
this.import=function(data) {
|
||||
ret={};
|
||||
for (el in this) {
|
||||
if (this.isSCase(this[el])) {
|
||||
delete ret[el];
|
||||
}
|
||||
}
|
||||
this.lastChange=data.lastChange;
|
||||
for (el in data.scases) {
|
||||
this[el]=new SCase(false,false,data.scases[el]);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
this.save=function() {
|
||||
localStorage.scases=JSON.stringify(this.export());
|
||||
}
|
||||
|
||||
this.each=function(fct) {
|
||||
var idx=0;
|
||||
var ret={};
|
||||
for (el in this) {
|
||||
if(this.isSCase(this[el])) {
|
||||
ret[el]=fct(idx++,this[el]);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
this.count=function() {
|
||||
len=0;
|
||||
this.each(function(idx,scase) {
|
||||
len=len+1;
|
||||
});
|
||||
return len;
|
||||
}
|
||||
|
||||
this.isSCase=function(el) {
|
||||
return (jQuery.type(el)=='object' && jQuery.type(el.isSCase)=='function' && el.isSCase());
|
||||
}
|
||||
|
||||
this.byName=function(name) {
|
||||
for (el in this) {
|
||||
if(this.isSCase(this[el])) {
|
||||
if (this[el].name==name) {
|
||||
return this[el];
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
this.removeSCase=function(name) {
|
||||
for (el in this) {
|
||||
if (this.isSCase(this[el]) && this[el].name==name) {
|
||||
this[el].remove();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
this.newSCase=function(name) {
|
||||
if (this.byName(this[name])) {
|
||||
var scase=this.byName(name);
|
||||
if (scase.removed) {
|
||||
scase.restore();
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
var uuid=uuid||generate_uuid();
|
||||
this[uuid]=new SCase(uuid,name);
|
||||
return this[uuid];
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
this.renameSCase=function(name,newname) {
|
||||
var scase=this.byName(name);
|
||||
if (scase && !this.byName(newname)) {
|
||||
scase.name=newname;
|
||||
scase.lastChange=new Date().getTime();
|
||||
return scase;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
this.copySCase=function(name,newname) {
|
||||
var orig_scase=this.byName(name);
|
||||
if (this.isSCase(orig_scase) && !this.byName(newname)) {
|
||||
var uuid=uuid||generate_uuid();
|
||||
this[uuid]=new SCase(false,false,orig_scase.export());
|
||||
this[uuid].uuid=uuid;
|
||||
this[uuid].lastChange=new Date().getTime();
|
||||
this[uuid].name=newname;
|
||||
return this[uuid];
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
this.resetSCase=function(name) {
|
||||
for (el in this) {
|
||||
if (this.isSCase(this[el]) && this[el].name==name) {
|
||||
return this[el].reset();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function SCase(uuid,name,data) {
|
||||
this.uuid=uuid||generate_uuid();
|
||||
this.name=name;
|
||||
this.cats=new CatList();
|
||||
this.lastChange=new Date().getTime();
|
||||
this.removed=false;
|
||||
|
||||
this.isSCase=function() {
|
||||
return true;
|
||||
}
|
||||
|
||||
this.import=function(data) {
|
||||
this.uuid=data.uuid || generate_uuid();
|
||||
this.lastChange=data.lastChange || new Date().getTime();
|
||||
this.name=decodeURIComponent(data.name);
|
||||
this.removed=data.removed||false;
|
||||
if (jQuery.type(data.cats) == 'object') {
|
||||
this.cats=new CatList(data.cats);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
this.export=function() {
|
||||
return {
|
||||
'uuid': this.uuid,
|
||||
'lastChange': this.lastChange,
|
||||
'name': encodeURIComponent(this.name),
|
||||
'removed': this.removed,
|
||||
'cats': this.cats.export()
|
||||
};
|
||||
}
|
||||
|
||||
this.byName=function(name) {
|
||||
for (idx in this.cats) {
|
||||
if (name==this.cats[idx].name) {
|
||||
return this.cats[idx];
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
this.stats=function() {
|
||||
var cats=0;
|
||||
var things=0;
|
||||
var things_done=0;
|
||||
this.cats.each(function(cidx,cat) {
|
||||
if (cat.removed) {
|
||||
return true;
|
||||
}
|
||||
cats++;
|
||||
for (idx in cat.things) {
|
||||
if (cat.things[idx].removed) {
|
||||
continue;
|
||||
}
|
||||
things++;
|
||||
if (cat.things[idx].checked) {
|
||||
things_done++;
|
||||
}
|
||||
}
|
||||
});
|
||||
return {
|
||||
'cats': cats,
|
||||
'things': things,
|
||||
'done': things_done
|
||||
}
|
||||
}
|
||||
|
||||
this.reset=function() {
|
||||
this.cats.each(function(idx,cat) {
|
||||
for (idx in cat.things) {
|
||||
if (cat.things[idx].checked) {
|
||||
cat.things[idx].checked=false;
|
||||
}
|
||||
}
|
||||
});
|
||||
this.lastChange=new Date().getTime();
|
||||
return true;
|
||||
}
|
||||
|
||||
this.remove=function() {
|
||||
this.removed=true;
|
||||
this.lastChange=new Date().getTime();
|
||||
}
|
||||
|
||||
this.restore=function() {
|
||||
this.removed=false;
|
||||
this.lastChange=new Date().getTime();
|
||||
}
|
||||
|
||||
/*
|
||||
* Contructor
|
||||
*/
|
||||
if (jQuery.type(data)=='object') {
|
||||
try {
|
||||
this.import(data);
|
||||
}
|
||||
catch (e) {
|
||||
console.log(e);
|
||||
alert('Une erreur est survenue en chargeant la valise '+this.name+' depuis le cache');
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
function CatList(data) {
|
||||
this.export=function() {
|
||||
return this.each(function(idx,cat) {
|
||||
return cat.export();
|
||||
});
|
||||
}
|
||||
|
||||
this.import=function(data) {
|
||||
for (el in this) {
|
||||
if (this.isCat(this[el])) {
|
||||
delete this[el];
|
||||
}
|
||||
}
|
||||
for (el in data) {
|
||||
this[el]=new Cat(el,false,false,data[el]);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
this.each=function(fct) {
|
||||
var idx=0;
|
||||
var ret={};
|
||||
for (el in this) {
|
||||
if(this.isCat(this[el])) {
|
||||
ret[el]=fct(idx++,this[el]);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
this.count=function() {
|
||||
len=0;
|
||||
this.each(function(idx,cat) {
|
||||
len=len+1;
|
||||
});
|
||||
return len;
|
||||
}
|
||||
|
||||
this.isCat=function(el) {
|
||||
return (jQuery.type(el)=='object' && jQuery.type(el.isCat)=='function' && el.isCat());
|
||||
}
|
||||
|
||||
this.byName=function(name) {
|
||||
for (el in this) {
|
||||
if(this.isCat(this[el])) {
|
||||
if (this[el].name==name) {
|
||||
return this[el];
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
this.newCat=function(name) {
|
||||
if (this.byName(name)) {
|
||||
var cat=this.byName(name);
|
||||
if (cat.removed) {
|
||||
cat.restore();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
var uuid=uuid||generate_uuid();
|
||||
this[uuid]=new Cat(uuid,name);
|
||||
return this[uuid];
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
this.renameCat=function(name,newname) {
|
||||
var cat=this.byName(name);
|
||||
if (cat && !this.byName(newname)) {
|
||||
cat.name=newname;
|
||||
cat.lastChange=new Date().getTime();
|
||||
return cat;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
this.removeCat=function(name) {
|
||||
for (el in this) {
|
||||
if (this.isCat(this[el]) && this[el].name==name) {
|
||||
this[el].remove();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
this.restoreCat=function(name) {
|
||||
for (el in this) {
|
||||
if (this.isCat(this[el]) && this[el].name==name && this[el].removed) {
|
||||
this[el].restore();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Contructor
|
||||
*/
|
||||
if (jQuery.type(data)=='object') {
|
||||
try {
|
||||
this.import(data);
|
||||
}
|
||||
catch (e) {
|
||||
console.log(e);
|
||||
alert('Une erreur est survenue en chargeant la liste de catégorie depuis le cache');
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function Cat(uuid,name,color,data) {
|
||||
this.uuid=generate_uuid();
|
||||
this.lastChange=new Date().getTime();
|
||||
this.name=name;
|
||||
this.color=color || '#'+(0x1000000+(Math.random())*0xffffff).toString(16).substr(1,6);
|
||||
this.things={};
|
||||
this.removed=false;
|
||||
|
||||
this.isCat=function() {
|
||||
return true;
|
||||
}
|
||||
|
||||
this.import=function(data) {
|
||||
this.uuid=data.uuid || generate_uuid();
|
||||
this.lastChange=data.lastChange||new Date().getTime();
|
||||
this.name=decodeURIComponent(data.name);
|
||||
this.color=data.color;
|
||||
this.removed=data.removed||false;
|
||||
if (jQuery.type(data.things) == 'object') {
|
||||
for (tuuid in data.things) {
|
||||
this.things[tuuid]=new Thing(tuuid);
|
||||
this.things[tuuid].import(data.things[tuuid]);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
this.export=function() {
|
||||
var things={};
|
||||
for (tuuid in this.things) {
|
||||
things[tuuid]=this.things[tuuid].export();
|
||||
}
|
||||
return {
|
||||
'uuid': this.uuid,
|
||||
'lastChange': this.lastChange,
|
||||
'name': encodeURIComponent(this.name),
|
||||
'color': this.color,
|
||||
'removed': this.removed,
|
||||
'things': things
|
||||
};
|
||||
}
|
||||
|
||||
this.byLabel=function(label) {
|
||||
for (idx in this.things) {
|
||||
if (label==this.things[idx].label) {
|
||||
return this.things[idx];
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
this.count=function() {
|
||||
return keys(this.things).length;
|
||||
}
|
||||
|
||||
this.stats=function() {
|
||||
var count=0;
|
||||
var done=0;
|
||||
for (idx in this.things) {
|
||||
if (this.things[idx].removed) {
|
||||
continue;
|
||||
}
|
||||
if (this.things[idx].checked) {
|
||||
done+=1;
|
||||
}
|
||||
count+=1;
|
||||
}
|
||||
return {
|
||||
'things': count,
|
||||
'done': done
|
||||
};
|
||||
}
|
||||
|
||||
this.newThing=function(label,nb) {
|
||||
if (this.byLabel(label)) {
|
||||
var thing=this.byLabel(label);
|
||||
if (thing.removed) {
|
||||
thing.restore();
|
||||
thing.setChecked(false);
|
||||
thing.setNb(nb);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
var uuid=generate_uuid();
|
||||
this.things[uuid]=new Thing(uuid,label,nb);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
this.renameThing=function(label,newlabel) {
|
||||
var thing=this.byLabel(label);
|
||||
if (thing && !this.byLabel(newlabel)) {
|
||||
thing.label=newlabel;
|
||||
thing.lastChange=new Date().getTime();
|
||||
return thing;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
this.removeThing=function(label) {
|
||||
for (idx in this.things) {
|
||||
if (this.things[idx].label==label) {
|
||||
this.things[idx].remove();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
this.restoreThing=function(label) {
|
||||
for (idx in this.things) {
|
||||
if (this.things[idx].label==label && this.things[idx].removed) {
|
||||
this.things[idx].restore();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
this.remove=function() {
|
||||
this.removed=true;
|
||||
this.lastChange=new Date().getTime();
|
||||
}
|
||||
|
||||
this.restore=function() {
|
||||
this.removed=false;
|
||||
this.lastChange=new Date().getTime();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Contructor
|
||||
*/
|
||||
if (jQuery.type(data)=='object') {
|
||||
try {
|
||||
this.import(data);
|
||||
}
|
||||
catch (e) {
|
||||
console.log(e);
|
||||
alert('Une erreur est survenue en chargeant la catégorie catégorie '+this.name+' depuis le cache');
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function Thing(uuid,label,nb,checked) {
|
||||
this.uuid=uuid||generate_uuid();
|
||||
this.lastChange=new Date().getTime();
|
||||
this.label=label;
|
||||
this.nb=nb || 1;
|
||||
this.checked=checked;
|
||||
this.removed=false;
|
||||
|
||||
this.import=function(data) {
|
||||
this.uuid=data.uuid||generate_uuid();
|
||||
this.lastChange=data.lastChange||new Date().getTime();
|
||||
this.label=decodeURIComponent(data.label),
|
||||
this.nb=data.nb||1;
|
||||
this.checked=data.checked;
|
||||
this.removed=data.removed||false;
|
||||
}
|
||||
|
||||
this.export=function() {
|
||||
return {
|
||||
'uuid': this.uuid,
|
||||
'lastChange': this.lastChange,
|
||||
'label': encodeURIComponent(this.label),
|
||||
'nb': this.nb,
|
||||
'checked': this.checked,
|
||||
'removed': this.removed,
|
||||
};
|
||||
}
|
||||
|
||||
this.setNb=function(nb) {
|
||||
this.nb=nb;
|
||||
this.lastChange=new Date().getTime();
|
||||
}
|
||||
|
||||
this.setChecked=function(value) {
|
||||
this.checked=value;
|
||||
this.lastChange=new Date().getTime();
|
||||
}
|
||||
|
||||
this.remove=function() {
|
||||
this.removed=true;
|
||||
this.lastChange=new Date().getTime();
|
||||
}
|
||||
|
||||
this.restore=function() {
|
||||
this.removed=false;
|
||||
this.lastChange=new Date().getTime();
|
||||
}
|
||||
}
|
9
public_html/index.php
Normal file
|
@ -0,0 +1,9 @@
|
|||
<?php
|
||||
|
||||
include '../includes/core.php';
|
||||
|
||||
use EesyPHP\Url;
|
||||
|
||||
Url :: handle_request('');
|
||||
|
||||
# vim: tabstop=2 shiftwidth=2 softtabstop=2 expandtab
|
4
setup.cfg
Normal file
|
@ -0,0 +1,4 @@
|
|||
[codespell]
|
||||
ignore-words-list=fro,hass
|
||||
exclude-file=.codespell-exclusions
|
||||
quiet-level=2
|
128
src/Auth/API.php
Normal file
|
@ -0,0 +1,128 @@
|
|||
<?php
|
||||
|
||||
namespace MySC\Auth;
|
||||
|
||||
use EesyPHP\Auth;
|
||||
use EesyPHP\Auth\Method;
|
||||
use EesyPHP\Log;
|
||||
use EesyPHP\Url;
|
||||
use EesyPHP\Tpl;
|
||||
|
||||
use MySC\Db\AuthToken;
|
||||
|
||||
use function EesyPHP\vardump;
|
||||
|
||||
class API extends Method {
|
||||
|
||||
protected static $initialized = false;
|
||||
|
||||
/**
|
||||
* Initialize
|
||||
* @return boolean
|
||||
*/
|
||||
public static function init() {
|
||||
if (php_sapi_name() != "cli" && !self :: $initialized) {
|
||||
Url :: add_url_handler(
|
||||
'#^login$#',
|
||||
['MySC\\Auth\\API', 'handle_login'],
|
||||
null,
|
||||
false,
|
||||
true,
|
||||
true
|
||||
);
|
||||
self :: $initialized = true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Log user
|
||||
* @param bool $force Force user authentication
|
||||
* @return \EesyPHP\Auth\User|null
|
||||
*/
|
||||
public static function login($force=false) {
|
||||
$user = null;
|
||||
if (isset($_REQUEST['username']) && isset($_REQUEST['password'])) {
|
||||
Log::debug("API::login(): Try to authenticate user by username & password");
|
||||
$user = Auth :: authenticate($_REQUEST['username'], $_REQUEST['password']);
|
||||
if (!$user)
|
||||
Tpl :: add_error(_('Invalid username or password.'));
|
||||
}
|
||||
elseif (isset($_REQUEST['username']) && isset($_REQUEST['token'])) {
|
||||
Log::debug("API::login(): Try to authenticate user by token");
|
||||
$auth_token = AuthToken :: get($_REQUEST['token']);
|
||||
Log::debug("API::login(): auth token = %s", vardump($auth_token));
|
||||
if (!$auth_token || $auth_token->username != $_REQUEST['username'])
|
||||
Tpl :: add_error(_('Invalid authentication token.'));
|
||||
elseif ($auth_token->expired()) {
|
||||
Tpl :: add_error(_('Authentication token expired.'));
|
||||
$auth_token->delete();
|
||||
}
|
||||
else {
|
||||
Log::debug("API::login(): auth token valid, retrieve corresponding user");
|
||||
$user = Auth::get_user($auth_token->username);
|
||||
if (!$user) {
|
||||
Tpl :: add_error(_('Your account appears to have been deleted.'));
|
||||
$auth_token->delete();
|
||||
}
|
||||
Log::debug("login(): authenticated as %s via token", $user);
|
||||
}
|
||||
}
|
||||
return $user;
|
||||
}
|
||||
|
||||
/**
|
||||
* The login form view
|
||||
* @param \EesyPHP\UrlRequest $request
|
||||
* @return void
|
||||
*/
|
||||
public static function handle_login($request) {
|
||||
$user = Auth :: login(false, '\\mysc\\auth\\api');
|
||||
if ($user)
|
||||
Tpl :: display_ajax_return([
|
||||
"success" => true,
|
||||
"token" => AuthToken :: create($user) -> token,
|
||||
"username" => $user -> username,
|
||||
"name" => $user->name,
|
||||
"mail" => $user->mail,
|
||||
]);
|
||||
|
||||
Tpl :: display_ajax_return([
|
||||
"success" => false,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* The logout method
|
||||
* @return void
|
||||
*/
|
||||
public static function logout() {
|
||||
Log::debug("API::logout()");
|
||||
if (isset($_REQUEST['token'])) {
|
||||
$auth_token = AuthToken :: get($_REQUEST['token']);
|
||||
Log::debug("API::logout(): auth token = %s", vardump($auth_token));
|
||||
if (!$auth_token) {
|
||||
Log::debug("API::logout(): unknown auth token");
|
||||
}
|
||||
else if (isset($_REQUEST['username']) && $auth_token->username != $_REQUEST['username']) {
|
||||
Log::warning(
|
||||
"API::logout(): bad auth token owner ('%s' vs '%s')",
|
||||
$auth_token->username,
|
||||
$_REQUEST['username']
|
||||
);
|
||||
}
|
||||
else if ($auth_token->delete()) {
|
||||
Log::debug("API::logout(): auth token deleted");
|
||||
}
|
||||
else {
|
||||
Log::error("API::logout(): error deleting the auth token %s", $_REQUEST['token']);
|
||||
}
|
||||
}
|
||||
else {
|
||||
Log::warning("API::logout(): no token provided by the request");
|
||||
}
|
||||
Tpl :: display_ajax_return([
|
||||
"success" => true,
|
||||
]);
|
||||
}
|
||||
}
|
55
src/Db/AuthToken.php
Normal file
|
@ -0,0 +1,55 @@
|
|||
<?php
|
||||
|
||||
namespace MySC\Db;
|
||||
|
||||
use EesyPHP\App;
|
||||
use EesyPHP\Auth;
|
||||
use EesyPHP\Db\AttrStr;
|
||||
use EesyPHP\Db\AttrTimestamp;
|
||||
use EesyPHP\Db\DbObject;
|
||||
|
||||
/**
|
||||
* MySC database object
|
||||
* @property string|null $token
|
||||
* @property string|null $username
|
||||
* @property \DateTime|null $creation_date
|
||||
* @property \DateTime|null $expiration_date
|
||||
* @property boolean $removed
|
||||
*/
|
||||
class AuthToken extends DbObject {
|
||||
protected const TABLE = 'auth_tokens';
|
||||
protected const PRIMARY_KEYS = ['token'];
|
||||
protected const DEFAULT_ORDER = 'creation_date';
|
||||
protected const DEFAULT_ORDER_DIRECTION = 'DESC';
|
||||
|
||||
protected static function get_schema() {
|
||||
return [
|
||||
'token' => new AttrStr(['required' => true, 'default' => '\\EesyPHP\\generate_uuid']),
|
||||
'username' => new AttrStr(['required' => true]),
|
||||
'creation_date' => new AttrTimestamp(['default' => 'time']),
|
||||
'expiration_date' => new AttrTimestamp(
|
||||
['default' => ['\\MySC\\Db\\AuthToken', 'generate_expiration_date']]
|
||||
),
|
||||
];
|
||||
}
|
||||
|
||||
public static function generate_expiration_date() {
|
||||
return time() + App::get('auth.auth_token.expiration_delay', null, 'int');
|
||||
}
|
||||
|
||||
public static function create($user=null) {
|
||||
$user = $user ? $user : Auth::user();
|
||||
$token = new AuthToken();
|
||||
$token -> username = $user->username;
|
||||
$token->save();
|
||||
return $token;
|
||||
}
|
||||
|
||||
public function user() {
|
||||
return User::get($this -> username);
|
||||
}
|
||||
|
||||
public function expired() {
|
||||
return $this -> expiration_date -> getTimestamp() <= time();
|
||||
}
|
||||
}
|
56
src/Db/Category.php
Normal file
|
@ -0,0 +1,56 @@
|
|||
<?php
|
||||
|
||||
namespace MySC\Db;
|
||||
|
||||
use EesyPHP\Db\AttrStr;
|
||||
|
||||
/**
|
||||
* SCase category database object
|
||||
* @property string $uuid
|
||||
* @property string $scase_uuid
|
||||
* @property string $name
|
||||
* @property string $color
|
||||
* @property \DateTime|null $last_change
|
||||
* @property boolean $removed
|
||||
*/
|
||||
class Category extends DbObject {
|
||||
protected const TABLE = "categories";
|
||||
protected const DEFAULT_ORDER = "name";
|
||||
protected const DEFAULT_ORDER_DIRECTION = "ASC";
|
||||
protected const POSSIBLE_ORDERS = ["name", "last_change"];
|
||||
protected const UPDATABLE_FIELDS = ["name", "color"];
|
||||
|
||||
protected static function get_schema() {
|
||||
return array_merge(
|
||||
parent :: get_schema(),
|
||||
[
|
||||
"scase_uuid" => new AttrStr(["required" => true]),
|
||||
"name" => new AttrStr(["required" => true]),
|
||||
"color" => new AttrStr(["required" => true]),
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
public function to_json() {
|
||||
$data = parent :: to_json();
|
||||
$data["things"] = [];
|
||||
foreach($this -> things() as $uuid => $thing)
|
||||
$data["things"][$uuid] = $thing -> to_json();
|
||||
return $data;
|
||||
}
|
||||
|
||||
public static function from_json($data, $scase) {
|
||||
$obj = parent :: _from_json($data);
|
||||
$obj -> scase_uuid = $scase -> uuid;
|
||||
return $obj;
|
||||
}
|
||||
|
||||
public function things() {
|
||||
return Thing :: list(["category_uuid" => $this -> uuid]);
|
||||
}
|
||||
|
||||
public function delete_all_things() {
|
||||
return Thing :: deleteAll(["category_uuid" => $this -> uuid]);
|
||||
}
|
||||
|
||||
}
|
107
src/Db/DbObject.php
Normal file
|
@ -0,0 +1,107 @@
|
|||
<?php
|
||||
|
||||
namespace MySC\Db;
|
||||
|
||||
use EesyPHP\Date;
|
||||
use EesyPHP\Log;
|
||||
use EesyPHP\Db\AttrBool;
|
||||
use EesyPHP\Db\AttrStr;
|
||||
use EesyPHP\Db\AttrTimestamp;
|
||||
|
||||
use function EesyPHP\vardump;
|
||||
|
||||
/**
|
||||
* MySC database object
|
||||
* @property string $uuid
|
||||
* @property boolean $removed
|
||||
* @property \DateTime|null $last_change
|
||||
*/
|
||||
class DbObject extends \EesyPHP\Db\DbObject {
|
||||
protected const PRIMARY_KEYS = ['uuid'];
|
||||
|
||||
protected const UPDATABLE_FIELDS = [];
|
||||
|
||||
protected static function get_schema() {
|
||||
return [
|
||||
'uuid' => new AttrStr(['required' => true]),
|
||||
'last_change' => new AttrTimestamp(['default' => 'time']),
|
||||
'removed' => new AttrBool(['default' => false]),
|
||||
];
|
||||
}
|
||||
|
||||
public function to_json() {
|
||||
$data = [
|
||||
'uuid' => $this -> uuid,
|
||||
'lastChange' => intval($this -> last_change -> format('Uv')),
|
||||
'removed' => boolval($this -> removed),
|
||||
];
|
||||
foreach(static :: UPDATABLE_FIELDS as $field)
|
||||
$data[$field] = $this -> $field;
|
||||
return $data;
|
||||
}
|
||||
|
||||
public static function _from_json($data) {
|
||||
Log::debug(
|
||||
"from_json(): input=%s",
|
||||
vardump($data),
|
||||
);
|
||||
$class = get_called_class();
|
||||
$obj = new $class();
|
||||
$obj -> apply([
|
||||
'uuid' => $data['uuid'],
|
||||
'last_change' => Date :: from_timestamp($data['lastChange'] / 1000),
|
||||
'removed' => $data['removed'] == "true",
|
||||
]);
|
||||
foreach(static :: UPDATABLE_FIELDS as $field)
|
||||
$obj -> $field = $data[$field];
|
||||
Log::debug(
|
||||
"%s::from_json(): result=%s",
|
||||
$obj,
|
||||
vardump($obj->to_json()),
|
||||
);
|
||||
return $obj;
|
||||
}
|
||||
|
||||
public function sync(&$other, &$updated) {
|
||||
if ($this -> last_change >= $other -> last_change) {
|
||||
Log::debug(
|
||||
"%s::sync(): keep current (%s >= %s)",
|
||||
$this,
|
||||
Date::format($this->last_change),
|
||||
Date::format($other->last_change),
|
||||
);
|
||||
return true;
|
||||
}
|
||||
Log::debug(
|
||||
"%s::sync(): update from other (%s < %s) : %s",
|
||||
$this,
|
||||
Date::format($this->last_change),
|
||||
Date::format($other->last_change),
|
||||
vardump($other->to_json()),
|
||||
);
|
||||
$this -> apply([
|
||||
'last_change' => $other -> last_change,
|
||||
'removed' => $other -> removed,
|
||||
]);
|
||||
foreach(static :: UPDATABLE_FIELDS as $field)
|
||||
$this -> $field = $other -> $field;
|
||||
$updated = true;
|
||||
return $this -> save();
|
||||
}
|
||||
|
||||
/**
|
||||
* List objects
|
||||
* @param array<string,mixed> $where Where clauses as associative array of field name and value
|
||||
* @return array<string,DbObject>|false
|
||||
*/
|
||||
public static function list($where=null) {
|
||||
$objs = [];
|
||||
foreach(parent :: list($where) as $obj)
|
||||
$objs[$obj -> uuid] = $obj;
|
||||
return $objs;
|
||||
}
|
||||
|
||||
public function __toString() {
|
||||
return get_called_class()."<".$this -> uuid.">";
|
||||
}
|
||||
}
|
81
src/Db/SCase.php
Normal file
|
@ -0,0 +1,81 @@
|
|||
<?php
|
||||
|
||||
namespace MySC\Db;
|
||||
|
||||
use EesyPHP\Db\AttrStr;
|
||||
use EesyPHP\Log;
|
||||
|
||||
/**
|
||||
* SCase database object
|
||||
* @property string $uuid
|
||||
* @property string $name
|
||||
* @property \DateTime|null $last_change
|
||||
* @property boolean $removed
|
||||
*/
|
||||
class SCase extends DbObject {
|
||||
protected const TABLE = 'scases';
|
||||
protected const DEFAULT_ORDER = 'name';
|
||||
protected const DEFAULT_ORDER_DIRECTION = 'ASC';
|
||||
protected const POSSIBLE_ORDERS = ['name', 'last_change'];
|
||||
protected const UPDATABLE_FIELDS = ['name'];
|
||||
|
||||
protected static function get_schema() {
|
||||
return array_merge(
|
||||
parent :: get_schema(),
|
||||
[
|
||||
'username' => new AttrStr(['required' => true]),
|
||||
'name' => new AttrStr(['required' => true]),
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
public function to_json() {
|
||||
$data = parent :: to_json();
|
||||
$data["cats"] = [];
|
||||
foreach($this -> categories() as $uuid => $cat)
|
||||
$data["cats"][$uuid] = $cat -> to_json();
|
||||
return $data;
|
||||
}
|
||||
|
||||
public static function from_json($data, $user) {
|
||||
$obj = parent :: _from_json($data);
|
||||
$obj -> username = $user -> username;
|
||||
return $obj;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get scase's categories
|
||||
* @return array<Category>|false
|
||||
*/
|
||||
public function categories() {
|
||||
return Category :: list(['scase_uuid' => $this -> uuid]);
|
||||
}
|
||||
|
||||
public function delete() {
|
||||
foreach($this -> categories() as $category) {
|
||||
if (!$category->delete_all_things()) {
|
||||
Log::error(
|
||||
"Db: error occurred deleting things of category '%s' (%s)",
|
||||
$category->name, $category->uuid
|
||||
);
|
||||
return false;
|
||||
}
|
||||
if (!$category->delete()) {
|
||||
Log::error(
|
||||
"Db: error occurred deleting category '%s' (%s)",
|
||||
$category->name, $category->uuid
|
||||
);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (!parent::delete()) {
|
||||
Log::error(
|
||||
"Db: error occurred deleting scases '%s' (%s)",
|
||||
$this->name, $this->uuid
|
||||
);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
44
src/Db/Thing.php
Normal file
|
@ -0,0 +1,44 @@
|
|||
<?php
|
||||
|
||||
namespace MySC\Db;
|
||||
|
||||
use EesyPHP\Db\AttrBool;
|
||||
use EesyPHP\Db\AttrInt;
|
||||
use EesyPHP\Db\AttrStr;
|
||||
|
||||
/**
|
||||
* Thing database object
|
||||
* @property string $uuid
|
||||
* @property string $category_uuid
|
||||
* @property string $label
|
||||
* @property int $nb
|
||||
* @property boolean $checked
|
||||
* @property \DateTime|null $last_change
|
||||
* @property boolean $removed
|
||||
*/
|
||||
class Thing extends DbObject {
|
||||
protected const TABLE = 'things';
|
||||
protected const DEFAULT_ORDER = 'label';
|
||||
protected const DEFAULT_ORDER_DIRECTION = 'ASC';
|
||||
protected const POSSIBLE_ORDERS = ['label', 'last_change'];
|
||||
protected const UPDATABLE_FIELDS = ['label', 'nb', 'checked'];
|
||||
|
||||
protected static function get_schema() {
|
||||
return array_merge(
|
||||
parent :: get_schema(),
|
||||
[
|
||||
'category_uuid' => new AttrStr(['required' => true]),
|
||||
'label' => new AttrStr(['required' => true]),
|
||||
'nb' => new AttrInt(['required' => true, 'default' => 1]),
|
||||
'checked' => new AttrBool(['required' => false, 'default' => false]),
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
public static function from_json($data, $category) {
|
||||
$obj = parent :: _from_json($data);
|
||||
$obj -> category_uuid = $category -> uuid;
|
||||
return $obj;
|
||||
}
|
||||
|
||||
}
|
39
src/Db/User.php
Normal file
|
@ -0,0 +1,39 @@
|
|||
<?php
|
||||
|
||||
namespace MySC\Db;
|
||||
|
||||
use EesyPHP\Db\AttrStr;
|
||||
use EesyPHP\Db\DbObject;
|
||||
|
||||
/**
|
||||
* MySC database object
|
||||
* @property string|null $username
|
||||
* @property string|null $name
|
||||
* @property string|null $password
|
||||
* @property string|null $mail
|
||||
* @property boolean $removed
|
||||
*/
|
||||
class User extends DbObject {
|
||||
protected const TABLE = 'users';
|
||||
protected const PRIMARY_KEYS = ['username'];
|
||||
protected const DEFAULT_ORDER = 'name';
|
||||
protected const DEFAULT_ORDER_DIRECTION = 'ASC';
|
||||
|
||||
protected static function get_schema() {
|
||||
return [
|
||||
'username' => new AttrStr(['required' => true]),
|
||||
'name' => new AttrStr(['required' => true]),
|
||||
'password' => new AttrStr(['required' => true]),
|
||||
'mail' => new AttrStr(),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get user's scases
|
||||
* @return bool|SCase[]
|
||||
*/
|
||||
public function scases() {
|
||||
return SCase :: list(['username' => $this -> username]);
|
||||
}
|
||||
|
||||
}
|
0
static/.gitignore
vendored
Normal file
Before Width: | Height: | Size: 763 B After Width: | Height: | Size: 763 B |
Before Width: | Height: | Size: 2 KiB After Width: | Height: | Size: 2 KiB |
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 2.6 KiB |
3660
static/lib/alertify/alertify.js
Normal file
3
static/lib/alertify/alertify.min.js
vendored
Normal file
968
static/lib/alertify/css/alertify.css
Normal file
|
@ -0,0 +1,968 @@
|
|||
/**
|
||||
* alertifyjs 1.13.1 http://alertifyjs.com
|
||||
* AlertifyJS is a javascript framework for developing pretty browser dialogs and notifications.
|
||||
* Copyright 2019 Mohammad Younes <Mohammad@alertifyjs.com> (http://alertifyjs.com)
|
||||
* Licensed under GPL 3 <https://opensource.org/licenses/gpl-3.0>*/
|
||||
.alertify .ajs-dimmer {
|
||||
position: fixed;
|
||||
z-index: 1981;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
background-color: #252525;
|
||||
opacity: .5;
|
||||
}
|
||||
.alertify .ajs-modal {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
right: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
padding: 0;
|
||||
overflow-y: auto;
|
||||
z-index: 1981;
|
||||
}
|
||||
.alertify .ajs-dialog {
|
||||
position: relative;
|
||||
margin: 5% auto;
|
||||
min-height: 110px;
|
||||
max-width: 500px;
|
||||
padding: 24px 24px 0 24px;
|
||||
outline: 0;
|
||||
background-color: #fff;
|
||||
}
|
||||
.alertify .ajs-dialog.ajs-capture:before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
display: block;
|
||||
z-index: 1;
|
||||
}
|
||||
.alertify .ajs-reset {
|
||||
position: absolute !important;
|
||||
display: inline !important;
|
||||
width: 0 !important;
|
||||
height: 0 !important;
|
||||
opacity: 0 !important;
|
||||
}
|
||||
.alertify .ajs-commands {
|
||||
position: absolute;
|
||||
right: 4px;
|
||||
margin: -14px 24px 0 0;
|
||||
z-index: 2;
|
||||
}
|
||||
.alertify .ajs-commands button {
|
||||
display: none;
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
margin-left: 10px;
|
||||
padding: 10px;
|
||||
border: 0;
|
||||
background-color: transparent;
|
||||
background-repeat: no-repeat;
|
||||
background-position: center;
|
||||
cursor: pointer;
|
||||
}
|
||||
.alertify .ajs-commands button.ajs-close {
|
||||
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAABZ0RVh0Q3JlYXRpb24gVGltZQAwNy8xMy8xNOrZqugAAAAcdEVYdFNvZnR3YXJlAEFkb2JlIEZpcmV3b3JrcyBDUzbovLKMAAAAh0lEQVQYlY2QsQ0EIQwEB9cBAR1CJUaI/gigDnwR6NBL/7/xWLNrZ2b8EwGotVpr7eOitWa1VjugiNB7R1UPrKrWe0dEAHBbXUqxMQbeewDmnHjvyTm7C3zDwAUd9c63YQdUVdu6EAJzzquz7HXvTiklt+H9DQFYaxFjvDqllFyMkbXWvfpXHjJrWFgdBq/hAAAAAElFTkSuQmCC);
|
||||
}
|
||||
.alertify .ajs-commands button.ajs-maximize {
|
||||
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAABZ0RVh0Q3JlYXRpb24gVGltZQAwNy8xMy8xNOrZqugAAAAcdEVYdFNvZnR3YXJlAEFkb2JlIEZpcmV3b3JrcyBDUzbovLKMAAAAOUlEQVQYlWP8//8/AzGAhYGBgaG4uBiv6t7eXkYmooxjYGAgWiELsvHYFMCcRX2rSXcjoSBiJDbAAeD+EGu+8BZcAAAAAElFTkSuQmCC);
|
||||
}
|
||||
.alertify .ajs-header {
|
||||
margin: -24px;
|
||||
margin-bottom: 0;
|
||||
padding: 16px 24px;
|
||||
background-color: #fff;
|
||||
}
|
||||
.alertify .ajs-body {
|
||||
min-height: 56px;
|
||||
}
|
||||
.alertify .ajs-body .ajs-content {
|
||||
padding: 16px 24px 16px 16px;
|
||||
}
|
||||
.alertify .ajs-footer {
|
||||
padding: 4px;
|
||||
margin-left: -24px;
|
||||
margin-right: -24px;
|
||||
min-height: 43px;
|
||||
background-color: #fff;
|
||||
}
|
||||
.alertify .ajs-footer .ajs-buttons.ajs-primary {
|
||||
text-align: right;
|
||||
}
|
||||
.alertify .ajs-footer .ajs-buttons.ajs-primary .ajs-button {
|
||||
margin: 4px;
|
||||
}
|
||||
.alertify .ajs-footer .ajs-buttons.ajs-auxiliary {
|
||||
float: left;
|
||||
clear: none;
|
||||
text-align: left;
|
||||
}
|
||||
.alertify .ajs-footer .ajs-buttons.ajs-auxiliary .ajs-button {
|
||||
margin: 4px;
|
||||
}
|
||||
.alertify .ajs-footer .ajs-buttons .ajs-button {
|
||||
min-width: 88px;
|
||||
min-height: 35px;
|
||||
}
|
||||
.alertify .ajs-handle {
|
||||
position: absolute;
|
||||
display: none;
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
z-index: 1;
|
||||
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAABZ0RVh0Q3JlYXRpb24gVGltZQAwNy8xMS8xNEDQYmMAAAAcdEVYdFNvZnR3YXJlAEFkb2JlIEZpcmV3b3JrcyBDUzbovLKMAAAAQ0lEQVQYlaXNMQoAIAxD0dT7H657l0KX3iJuUlBUNOsPPCGJm7VDp6ryeMxMuDsAQH7owW3pyn3RS26iKxERMLN3ugOaAkaL3sWVigAAAABJRU5ErkJggg==);
|
||||
-webkit-transform: scaleX(1) /*rtl:scaleX(-1)*/;
|
||||
transform: scaleX(1) /*rtl:scaleX(-1)*/;
|
||||
cursor: se-resize;
|
||||
}
|
||||
.alertify.ajs-no-overflow .ajs-body .ajs-content {
|
||||
overflow: hidden !important;
|
||||
}
|
||||
.alertify.ajs-no-padding.ajs-maximized .ajs-body .ajs-content {
|
||||
left: 0;
|
||||
right: 0;
|
||||
padding: 0;
|
||||
}
|
||||
.alertify.ajs-no-padding:not(.ajs-maximized) .ajs-body {
|
||||
margin-left: -24px;
|
||||
margin-right: -24px;
|
||||
}
|
||||
.alertify.ajs-no-padding:not(.ajs-maximized) .ajs-body .ajs-content {
|
||||
padding: 0;
|
||||
}
|
||||
.alertify.ajs-no-padding.ajs-resizable .ajs-body .ajs-content {
|
||||
left: 0;
|
||||
right: 0;
|
||||
}
|
||||
.alertify.ajs-maximizable .ajs-commands button.ajs-maximize,
|
||||
.alertify.ajs-maximizable .ajs-commands button.ajs-restore {
|
||||
display: inline-block;
|
||||
}
|
||||
.alertify.ajs-closable .ajs-commands button.ajs-close {
|
||||
display: inline-block;
|
||||
}
|
||||
.alertify.ajs-maximized .ajs-dialog {
|
||||
width: 100% !important;
|
||||
height: 100% !important;
|
||||
max-width: none !important;
|
||||
margin: 0 auto !important;
|
||||
top: 0 !important;
|
||||
left: 0 !important;
|
||||
}
|
||||
.alertify.ajs-maximized.ajs-modeless .ajs-modal {
|
||||
position: fixed !important;
|
||||
min-height: 100% !important;
|
||||
max-height: none !important;
|
||||
margin: 0 !important;
|
||||
}
|
||||
.alertify.ajs-maximized .ajs-commands button.ajs-maximize {
|
||||
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAABZ0RVh0Q3JlYXRpb24gVGltZQAwNy8xMy8xNOrZqugAAAAcdEVYdFNvZnR3YXJlAEFkb2JlIEZpcmV3b3JrcyBDUzbovLKMAAAASklEQVQYlZWQ0QkAMQhDtXRincOZX78KVtrDCwgqJNEoIB3MPLj7lRUROlpyVXGzby6zWuY+kz6tj5sBMTMAyVV3/595RbOh3cAXsww1raeiOcoAAAAASUVORK5CYII=);
|
||||
}
|
||||
.alertify.ajs-resizable .ajs-dialog,
|
||||
.alertify.ajs-maximized .ajs-dialog {
|
||||
padding: 0;
|
||||
}
|
||||
.alertify.ajs-resizable .ajs-commands,
|
||||
.alertify.ajs-maximized .ajs-commands {
|
||||
margin: 14px 24px 0 0;
|
||||
}
|
||||
.alertify.ajs-resizable .ajs-header,
|
||||
.alertify.ajs-maximized .ajs-header {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
margin: 0;
|
||||
padding: 16px 24px;
|
||||
}
|
||||
.alertify.ajs-resizable .ajs-body,
|
||||
.alertify.ajs-maximized .ajs-body {
|
||||
min-height: 224px;
|
||||
display: inline-block;
|
||||
}
|
||||
.alertify.ajs-resizable .ajs-body .ajs-content,
|
||||
.alertify.ajs-maximized .ajs-body .ajs-content {
|
||||
position: absolute;
|
||||
top: 50px;
|
||||
right: 24px;
|
||||
bottom: 50px;
|
||||
left: 24px;
|
||||
overflow: auto;
|
||||
}
|
||||
.alertify.ajs-resizable .ajs-footer,
|
||||
.alertify.ajs-maximized .ajs-footer {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
margin: 0;
|
||||
}
|
||||
.alertify.ajs-resizable:not(.ajs-maximized) .ajs-dialog {
|
||||
min-width: 548px;
|
||||
}
|
||||
.alertify.ajs-resizable:not(.ajs-maximized) .ajs-handle {
|
||||
display: block;
|
||||
}
|
||||
.alertify.ajs-movable:not(.ajs-maximized) .ajs-header {
|
||||
cursor: move;
|
||||
}
|
||||
.alertify.ajs-modeless .ajs-dimmer,
|
||||
.alertify.ajs-modeless .ajs-reset {
|
||||
display: none;
|
||||
}
|
||||
.alertify.ajs-modeless .ajs-modal {
|
||||
overflow: visible;
|
||||
max-width: none;
|
||||
max-height: 0;
|
||||
}
|
||||
.alertify.ajs-modeless.ajs-pinnable .ajs-commands button.ajs-pin {
|
||||
display: inline-block;
|
||||
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAABZ0RVh0Q3JlYXRpb24gVGltZQAwNy8xMy8xNOrZqugAAAAcdEVYdFNvZnR3YXJlAEFkb2JlIEZpcmV3b3JrcyBDUzbovLKMAAAAQklEQVQYlcWPMQ4AIAwCqU9u38GbcbHRWN1MvKQDhQFMEpKImGJA0gCgnYw0V0rwxseg5erT4oSkQVI5d9f+e9+xA0NbLpWfitPXAAAAAElFTkSuQmCC);
|
||||
}
|
||||
.alertify.ajs-modeless.ajs-unpinned .ajs-modal {
|
||||
position: absolute;
|
||||
}
|
||||
.alertify.ajs-modeless.ajs-unpinned .ajs-commands button.ajs-pin {
|
||||
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAABZ0RVh0Q3JlYXRpb24gVGltZQAwNy8xMy8xNOrZqugAAAAcdEVYdFNvZnR3YXJlAEFkb2JlIEZpcmV3b3JrcyBDUzbovLKMAAAAO0lEQVQYlWP8//8/AzGAiShV6AqLi4txGs+CLoBLMYbC3t5eRmyaWfBZhwwYkX2NTxPRvibKjRhW4wMAhxkYGbLu3pEAAAAASUVORK5CYII=);
|
||||
}
|
||||
.alertify.ajs-modeless:not(.ajs-unpinned) .ajs-body {
|
||||
max-height: 500px;
|
||||
overflow: auto;
|
||||
}
|
||||
.alertify.ajs-basic .ajs-header {
|
||||
opacity: 0;
|
||||
}
|
||||
.alertify.ajs-basic .ajs-footer {
|
||||
visibility: hidden;
|
||||
}
|
||||
.alertify.ajs-frameless .ajs-header {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
min-height: 60px;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
opacity: 0;
|
||||
z-index: 1;
|
||||
}
|
||||
.alertify.ajs-frameless .ajs-footer {
|
||||
display: none;
|
||||
}
|
||||
.alertify.ajs-frameless .ajs-body .ajs-content {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
}
|
||||
.alertify.ajs-frameless:not(.ajs-resizable) .ajs-dialog {
|
||||
padding-top: 0;
|
||||
}
|
||||
.alertify.ajs-frameless:not(.ajs-resizable) .ajs-dialog .ajs-commands {
|
||||
margin-top: 0;
|
||||
}
|
||||
.ajs-no-overflow {
|
||||
overflow: hidden !important;
|
||||
outline: none;
|
||||
}
|
||||
.ajs-no-overflow.ajs-fixed {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
overflow-y: scroll!important;
|
||||
}
|
||||
.ajs-no-selection,
|
||||
.ajs-no-selection * {
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
@media screen and (max-width: 568px) {
|
||||
.alertify .ajs-dialog {
|
||||
min-width: 150px;
|
||||
}
|
||||
.alertify:not(.ajs-maximized) .ajs-modal {
|
||||
padding: 0 5%;
|
||||
}
|
||||
.alertify:not(.ajs-maximized).ajs-resizable .ajs-dialog {
|
||||
min-width: initial;
|
||||
min-width: auto /*IE fallback*/;
|
||||
}
|
||||
}
|
||||
@-moz-document url-prefix() {
|
||||
.alertify button:focus {
|
||||
outline: 1px dotted #3593D2;
|
||||
}
|
||||
}
|
||||
.alertify .ajs-dimmer,
|
||||
.alertify .ajs-modal {
|
||||
-webkit-transform: translate3d(0, 0, 0);
|
||||
transform: translate3d(0, 0, 0);
|
||||
-webkit-transition-property: opacity, visibility;
|
||||
transition-property: opacity, visibility;
|
||||
-webkit-transition-timing-function: linear;
|
||||
transition-timing-function: linear;
|
||||
-webkit-transition-duration: 250ms;
|
||||
transition-duration: 250ms;
|
||||
}
|
||||
.alertify.ajs-hidden .ajs-dimmer,
|
||||
.alertify.ajs-hidden .ajs-modal {
|
||||
visibility: hidden;
|
||||
opacity: 0;
|
||||
}
|
||||
.alertify.ajs-in:not(.ajs-hidden) .ajs-dialog {
|
||||
-webkit-animation-duration: 500ms;
|
||||
animation-duration: 500ms;
|
||||
}
|
||||
.alertify.ajs-out.ajs-hidden .ajs-dialog {
|
||||
-webkit-animation-duration: 250ms;
|
||||
animation-duration: 250ms;
|
||||
}
|
||||
.alertify .ajs-dialog.ajs-shake {
|
||||
-webkit-animation-name: ajs-shake;
|
||||
animation-name: ajs-shake;
|
||||
-webkit-animation-duration: .1s;
|
||||
animation-duration: .1s;
|
||||
-webkit-animation-fill-mode: both;
|
||||
animation-fill-mode: both;
|
||||
}
|
||||
@-webkit-keyframes ajs-shake {
|
||||
0%,
|
||||
100% {
|
||||
-webkit-transform: translate3d(0, 0, 0);
|
||||
transform: translate3d(0, 0, 0);
|
||||
}
|
||||
10%,
|
||||
30%,
|
||||
50%,
|
||||
70%,
|
||||
90% {
|
||||
-webkit-transform: translate3d(-10px, 0, 0);
|
||||
transform: translate3d(-10px, 0, 0);
|
||||
}
|
||||
20%,
|
||||
40%,
|
||||
60%,
|
||||
80% {
|
||||
-webkit-transform: translate3d(10px, 0, 0);
|
||||
transform: translate3d(10px, 0, 0);
|
||||
}
|
||||
}
|
||||
@keyframes ajs-shake {
|
||||
0%,
|
||||
100% {
|
||||
-webkit-transform: translate3d(0, 0, 0);
|
||||
transform: translate3d(0, 0, 0);
|
||||
}
|
||||
10%,
|
||||
30%,
|
||||
50%,
|
||||
70%,
|
||||
90% {
|
||||
-webkit-transform: translate3d(-10px, 0, 0);
|
||||
transform: translate3d(-10px, 0, 0);
|
||||
}
|
||||
20%,
|
||||
40%,
|
||||
60%,
|
||||
80% {
|
||||
-webkit-transform: translate3d(10px, 0, 0);
|
||||
transform: translate3d(10px, 0, 0);
|
||||
}
|
||||
}
|
||||
.alertify.ajs-slide.ajs-in:not(.ajs-hidden) .ajs-dialog {
|
||||
-webkit-animation-name: ajs-slideIn;
|
||||
animation-name: ajs-slideIn;
|
||||
-webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1.275);
|
||||
animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1.275);
|
||||
}
|
||||
.alertify.ajs-slide.ajs-out.ajs-hidden .ajs-dialog {
|
||||
-webkit-animation-name: ajs-slideOut;
|
||||
animation-name: ajs-slideOut;
|
||||
-webkit-animation-timing-function: cubic-bezier(0.6, -0.28, 0.735, 0.045);
|
||||
animation-timing-function: cubic-bezier(0.6, -0.28, 0.735, 0.045);
|
||||
}
|
||||
.alertify.ajs-zoom.ajs-in:not(.ajs-hidden) .ajs-dialog {
|
||||
-webkit-animation-name: ajs-zoomIn;
|
||||
animation-name: ajs-zoomIn;
|
||||
}
|
||||
.alertify.ajs-zoom.ajs-out.ajs-hidden .ajs-dialog {
|
||||
-webkit-animation-name: ajs-zoomOut;
|
||||
animation-name: ajs-zoomOut;
|
||||
}
|
||||
.alertify.ajs-fade.ajs-in:not(.ajs-hidden) .ajs-dialog {
|
||||
-webkit-animation-name: ajs-fadeIn;
|
||||
animation-name: ajs-fadeIn;
|
||||
}
|
||||
.alertify.ajs-fade.ajs-out.ajs-hidden .ajs-dialog {
|
||||
-webkit-animation-name: ajs-fadeOut;
|
||||
animation-name: ajs-fadeOut;
|
||||
}
|
||||
.alertify.ajs-pulse.ajs-in:not(.ajs-hidden) .ajs-dialog {
|
||||
-webkit-animation-name: ajs-pulseIn;
|
||||
animation-name: ajs-pulseIn;
|
||||
}
|
||||
.alertify.ajs-pulse.ajs-out.ajs-hidden .ajs-dialog {
|
||||
-webkit-animation-name: ajs-pulseOut;
|
||||
animation-name: ajs-pulseOut;
|
||||
}
|
||||
.alertify.ajs-flipx.ajs-in:not(.ajs-hidden) .ajs-dialog {
|
||||
-webkit-animation-name: ajs-flipInX;
|
||||
animation-name: ajs-flipInX;
|
||||
}
|
||||
.alertify.ajs-flipx.ajs-out.ajs-hidden .ajs-dialog {
|
||||
-webkit-animation-name: ajs-flipOutX;
|
||||
animation-name: ajs-flipOutX;
|
||||
}
|
||||
.alertify.ajs-flipy.ajs-in:not(.ajs-hidden) .ajs-dialog {
|
||||
-webkit-animation-name: ajs-flipInY;
|
||||
animation-name: ajs-flipInY;
|
||||
}
|
||||
.alertify.ajs-flipy.ajs-out.ajs-hidden .ajs-dialog {
|
||||
-webkit-animation-name: ajs-flipOutY;
|
||||
animation-name: ajs-flipOutY;
|
||||
}
|
||||
@-webkit-keyframes ajs-pulseIn {
|
||||
0%,
|
||||
20%,
|
||||
40%,
|
||||
60%,
|
||||
80%,
|
||||
100% {
|
||||
-webkit-transition-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
|
||||
transition-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
|
||||
}
|
||||
0% {
|
||||
opacity: 0;
|
||||
-webkit-transform: scale3d(0.3, 0.3, 0.3);
|
||||
transform: scale3d(0.3, 0.3, 0.3);
|
||||
}
|
||||
20% {
|
||||
-webkit-transform: scale3d(1.1, 1.1, 1.1);
|
||||
transform: scale3d(1.1, 1.1, 1.1);
|
||||
}
|
||||
40% {
|
||||
-webkit-transform: scale3d(0.9, 0.9, 0.9);
|
||||
transform: scale3d(0.9, 0.9, 0.9);
|
||||
}
|
||||
60% {
|
||||
opacity: 1;
|
||||
-webkit-transform: scale3d(1.03, 1.03, 1.03);
|
||||
transform: scale3d(1.03, 1.03, 1.03);
|
||||
}
|
||||
80% {
|
||||
-webkit-transform: scale3d(0.97, 0.97, 0.97);
|
||||
transform: scale3d(0.97, 0.97, 0.97);
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
-webkit-transform: scale3d(1, 1, 1);
|
||||
transform: scale3d(1, 1, 1);
|
||||
}
|
||||
}
|
||||
@keyframes ajs-pulseIn {
|
||||
0%,
|
||||
20%,
|
||||
40%,
|
||||
60%,
|
||||
80%,
|
||||
100% {
|
||||
-webkit-transition-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
|
||||
transition-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
|
||||
}
|
||||
0% {
|
||||
opacity: 0;
|
||||
-webkit-transform: scale3d(0.3, 0.3, 0.3);
|
||||
transform: scale3d(0.3, 0.3, 0.3);
|
||||
}
|
||||
20% {
|
||||
-webkit-transform: scale3d(1.1, 1.1, 1.1);
|
||||
transform: scale3d(1.1, 1.1, 1.1);
|
||||
}
|
||||
40% {
|
||||
-webkit-transform: scale3d(0.9, 0.9, 0.9);
|
||||
transform: scale3d(0.9, 0.9, 0.9);
|
||||
}
|
||||
60% {
|
||||
opacity: 1;
|
||||
-webkit-transform: scale3d(1.03, 1.03, 1.03);
|
||||
transform: scale3d(1.03, 1.03, 1.03);
|
||||
}
|
||||
80% {
|
||||
-webkit-transform: scale3d(0.97, 0.97, 0.97);
|
||||
transform: scale3d(0.97, 0.97, 0.97);
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
-webkit-transform: scale3d(1, 1, 1);
|
||||
transform: scale3d(1, 1, 1);
|
||||
}
|
||||
}
|
||||
@-webkit-keyframes ajs-pulseOut {
|
||||
20% {
|
||||
-webkit-transform: scale3d(0.9, 0.9, 0.9);
|
||||
transform: scale3d(0.9, 0.9, 0.9);
|
||||
}
|
||||
50%,
|
||||
55% {
|
||||
opacity: 1;
|
||||
-webkit-transform: scale3d(1.1, 1.1, 1.1);
|
||||
transform: scale3d(1.1, 1.1, 1.1);
|
||||
}
|
||||
100% {
|
||||
opacity: 0;
|
||||
-webkit-transform: scale3d(0.3, 0.3, 0.3);
|
||||
transform: scale3d(0.3, 0.3, 0.3);
|
||||
}
|
||||
}
|
||||
@keyframes ajs-pulseOut {
|
||||
20% {
|
||||
-webkit-transform: scale3d(0.9, 0.9, 0.9);
|
||||
transform: scale3d(0.9, 0.9, 0.9);
|
||||
}
|
||||
50%,
|
||||
55% {
|
||||
opacity: 1;
|
||||
-webkit-transform: scale3d(1.1, 1.1, 1.1);
|
||||
transform: scale3d(1.1, 1.1, 1.1);
|
||||
}
|
||||
100% {
|
||||
opacity: 0;
|
||||
-webkit-transform: scale3d(0.3, 0.3, 0.3);
|
||||
transform: scale3d(0.3, 0.3, 0.3);
|
||||
}
|
||||
}
|
||||
@-webkit-keyframes ajs-zoomIn {
|
||||
0% {
|
||||
opacity: 0;
|
||||
-webkit-transform: scale3d(0.25, 0.25, 0.25);
|
||||
transform: scale3d(0.25, 0.25, 0.25);
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
-webkit-transform: scale3d(1, 1, 1);
|
||||
transform: scale3d(1, 1, 1);
|
||||
}
|
||||
}
|
||||
@keyframes ajs-zoomIn {
|
||||
0% {
|
||||
opacity: 0;
|
||||
-webkit-transform: scale3d(0.25, 0.25, 0.25);
|
||||
transform: scale3d(0.25, 0.25, 0.25);
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
-webkit-transform: scale3d(1, 1, 1);
|
||||
transform: scale3d(1, 1, 1);
|
||||
}
|
||||
}
|
||||
@-webkit-keyframes ajs-zoomOut {
|
||||
0% {
|
||||
opacity: 1;
|
||||
-webkit-transform: scale3d(1, 1, 1);
|
||||
transform: scale3d(1, 1, 1);
|
||||
}
|
||||
100% {
|
||||
opacity: 0;
|
||||
-webkit-transform: scale3d(0.25, 0.25, 0.25);
|
||||
transform: scale3d(0.25, 0.25, 0.25);
|
||||
}
|
||||
}
|
||||
@keyframes ajs-zoomOut {
|
||||
0% {
|
||||
opacity: 1;
|
||||
-webkit-transform: scale3d(1, 1, 1);
|
||||
transform: scale3d(1, 1, 1);
|
||||
}
|
||||
100% {
|
||||
opacity: 0;
|
||||
-webkit-transform: scale3d(0.25, 0.25, 0.25);
|
||||
transform: scale3d(0.25, 0.25, 0.25);
|
||||
}
|
||||
}
|
||||
@-webkit-keyframes ajs-fadeIn {
|
||||
0% {
|
||||
opacity: 0;
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
@keyframes ajs-fadeIn {
|
||||
0% {
|
||||
opacity: 0;
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
@-webkit-keyframes ajs-fadeOut {
|
||||
0% {
|
||||
opacity: 1;
|
||||
}
|
||||
100% {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
@keyframes ajs-fadeOut {
|
||||
0% {
|
||||
opacity: 1;
|
||||
}
|
||||
100% {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
@-webkit-keyframes ajs-flipInX {
|
||||
0% {
|
||||
-webkit-transform: perspective(400px) rotate3d(1, 0, 0, 90deg);
|
||||
transform: perspective(400px) rotate3d(1, 0, 0, 90deg);
|
||||
-webkit-transition-timing-function: ease-in;
|
||||
transition-timing-function: ease-in;
|
||||
opacity: 0;
|
||||
}
|
||||
40% {
|
||||
-webkit-transform: perspective(400px) rotate3d(1, 0, 0, -20deg);
|
||||
transform: perspective(400px) rotate3d(1, 0, 0, -20deg);
|
||||
-webkit-transition-timing-function: ease-in;
|
||||
transition-timing-function: ease-in;
|
||||
}
|
||||
60% {
|
||||
-webkit-transform: perspective(400px) rotate3d(1, 0, 0, 10deg);
|
||||
transform: perspective(400px) rotate3d(1, 0, 0, 10deg);
|
||||
opacity: 1;
|
||||
}
|
||||
80% {
|
||||
-webkit-transform: perspective(400px) rotate3d(1, 0, 0, -5deg);
|
||||
transform: perspective(400px) rotate3d(1, 0, 0, -5deg);
|
||||
}
|
||||
100% {
|
||||
-webkit-transform: perspective(400px);
|
||||
transform: perspective(400px);
|
||||
}
|
||||
}
|
||||
@keyframes ajs-flipInX {
|
||||
0% {
|
||||
-webkit-transform: perspective(400px) rotate3d(1, 0, 0, 90deg);
|
||||
transform: perspective(400px) rotate3d(1, 0, 0, 90deg);
|
||||
-webkit-transition-timing-function: ease-in;
|
||||
transition-timing-function: ease-in;
|
||||
opacity: 0;
|
||||
}
|
||||
40% {
|
||||
-webkit-transform: perspective(400px) rotate3d(1, 0, 0, -20deg);
|
||||
transform: perspective(400px) rotate3d(1, 0, 0, -20deg);
|
||||
-webkit-transition-timing-function: ease-in;
|
||||
transition-timing-function: ease-in;
|
||||
}
|
||||
60% {
|
||||
-webkit-transform: perspective(400px) rotate3d(1, 0, 0, 10deg);
|
||||
transform: perspective(400px) rotate3d(1, 0, 0, 10deg);
|
||||
opacity: 1;
|
||||
}
|
||||
80% {
|
||||
-webkit-transform: perspective(400px) rotate3d(1, 0, 0, -5deg);
|
||||
transform: perspective(400px) rotate3d(1, 0, 0, -5deg);
|
||||
}
|
||||
100% {
|
||||
-webkit-transform: perspective(400px);
|
||||
transform: perspective(400px);
|
||||
}
|
||||
}
|
||||
@-webkit-keyframes ajs-flipOutX {
|
||||
0% {
|
||||
-webkit-transform: perspective(400px);
|
||||
transform: perspective(400px);
|
||||
}
|
||||
30% {
|
||||
-webkit-transform: perspective(400px) rotate3d(1, 0, 0, -20deg);
|
||||
transform: perspective(400px) rotate3d(1, 0, 0, -20deg);
|
||||
opacity: 1;
|
||||
}
|
||||
100% {
|
||||
-webkit-transform: perspective(400px) rotate3d(1, 0, 0, 90deg);
|
||||
transform: perspective(400px) rotate3d(1, 0, 0, 90deg);
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
@keyframes ajs-flipOutX {
|
||||
0% {
|
||||
-webkit-transform: perspective(400px);
|
||||
transform: perspective(400px);
|
||||
}
|
||||
30% {
|
||||
-webkit-transform: perspective(400px) rotate3d(1, 0, 0, -20deg);
|
||||
transform: perspective(400px) rotate3d(1, 0, 0, -20deg);
|
||||
opacity: 1;
|
||||
}
|
||||
100% {
|
||||
-webkit-transform: perspective(400px) rotate3d(1, 0, 0, 90deg);
|
||||
transform: perspective(400px) rotate3d(1, 0, 0, 90deg);
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
@-webkit-keyframes ajs-flipInY {
|
||||
0% {
|
||||
-webkit-transform: perspective(400px) rotate3d(0, 1, 0, 90deg);
|
||||
transform: perspective(400px) rotate3d(0, 1, 0, 90deg);
|
||||
-webkit-transition-timing-function: ease-in;
|
||||
transition-timing-function: ease-in;
|
||||
opacity: 0;
|
||||
}
|
||||
40% {
|
||||
-webkit-transform: perspective(400px) rotate3d(0, 1, 0, -20deg);
|
||||
transform: perspective(400px) rotate3d(0, 1, 0, -20deg);
|
||||
-webkit-transition-timing-function: ease-in;
|
||||
transition-timing-function: ease-in;
|
||||
}
|
||||
60% {
|
||||
-webkit-transform: perspective(400px) rotate3d(0, 1, 0, 10deg);
|
||||
transform: perspective(400px) rotate3d(0, 1, 0, 10deg);
|
||||
opacity: 1;
|
||||
}
|
||||
80% {
|
||||
-webkit-transform: perspective(400px) rotate3d(0, 1, 0, -5deg);
|
||||
transform: perspective(400px) rotate3d(0, 1, 0, -5deg);
|
||||
}
|
||||
100% {
|
||||
-webkit-transform: perspective(400px);
|
||||
transform: perspective(400px);
|
||||
}
|
||||
}
|
||||
@keyframes ajs-flipInY {
|
||||
0% {
|
||||
-webkit-transform: perspective(400px) rotate3d(0, 1, 0, 90deg);
|
||||
transform: perspective(400px) rotate3d(0, 1, 0, 90deg);
|
||||
-webkit-transition-timing-function: ease-in;
|
||||
transition-timing-function: ease-in;
|
||||
opacity: 0;
|
||||
}
|
||||
40% {
|
||||
-webkit-transform: perspective(400px) rotate3d(0, 1, 0, -20deg);
|
||||
transform: perspective(400px) rotate3d(0, 1, 0, -20deg);
|
||||
-webkit-transition-timing-function: ease-in;
|
||||
transition-timing-function: ease-in;
|
||||
}
|
||||
60% {
|
||||
-webkit-transform: perspective(400px) rotate3d(0, 1, 0, 10deg);
|
||||
transform: perspective(400px) rotate3d(0, 1, 0, 10deg);
|
||||
opacity: 1;
|
||||
}
|
||||
80% {
|
||||
-webkit-transform: perspective(400px) rotate3d(0, 1, 0, -5deg);
|
||||
transform: perspective(400px) rotate3d(0, 1, 0, -5deg);
|
||||
}
|
||||
100% {
|
||||
-webkit-transform: perspective(400px);
|
||||
transform: perspective(400px);
|
||||
}
|
||||
}
|
||||
@-webkit-keyframes ajs-flipOutY {
|
||||
0% {
|
||||
-webkit-transform: perspective(400px);
|
||||
transform: perspective(400px);
|
||||
}
|
||||
30% {
|
||||
-webkit-transform: perspective(400px) rotate3d(0, 1, 0, -15deg);
|
||||
transform: perspective(400px) rotate3d(0, 1, 0, -15deg);
|
||||
opacity: 1;
|
||||
}
|
||||
100% {
|
||||
-webkit-transform: perspective(400px) rotate3d(0, 1, 0, 90deg);
|
||||
transform: perspective(400px) rotate3d(0, 1, 0, 90deg);
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
@keyframes ajs-flipOutY {
|
||||
0% {
|
||||
-webkit-transform: perspective(400px);
|
||||
transform: perspective(400px);
|
||||
}
|
||||
30% {
|
||||
-webkit-transform: perspective(400px) rotate3d(0, 1, 0, -15deg);
|
||||
transform: perspective(400px) rotate3d(0, 1, 0, -15deg);
|
||||
opacity: 1;
|
||||
}
|
||||
100% {
|
||||
-webkit-transform: perspective(400px) rotate3d(0, 1, 0, 90deg);
|
||||
transform: perspective(400px) rotate3d(0, 1, 0, 90deg);
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
@-webkit-keyframes ajs-slideIn {
|
||||
0% {
|
||||
margin-top: -100%;
|
||||
}
|
||||
100% {
|
||||
margin-top: 5%;
|
||||
}
|
||||
}
|
||||
@keyframes ajs-slideIn {
|
||||
0% {
|
||||
margin-top: -100%;
|
||||
}
|
||||
100% {
|
||||
margin-top: 5%;
|
||||
}
|
||||
}
|
||||
@-webkit-keyframes ajs-slideOut {
|
||||
0% {
|
||||
margin-top: 5%;
|
||||
}
|
||||
100% {
|
||||
margin-top: -100%;
|
||||
}
|
||||
}
|
||||
@keyframes ajs-slideOut {
|
||||
0% {
|
||||
margin-top: 5%;
|
||||
}
|
||||
100% {
|
||||
margin-top: -100%;
|
||||
}
|
||||
}
|
||||
.alertify-notifier {
|
||||
position: fixed;
|
||||
width: 0;
|
||||
overflow: visible;
|
||||
z-index: 1982;
|
||||
-webkit-transform: translate3d(0, 0, 0);
|
||||
transform: translate3d(0, 0, 0);
|
||||
}
|
||||
.alertify-notifier .ajs-message {
|
||||
position: relative;
|
||||
width: 260px;
|
||||
max-height: 0;
|
||||
padding: 0;
|
||||
opacity: 0;
|
||||
margin: 0;
|
||||
-webkit-transform: translate3d(0, 0, 0);
|
||||
transform: translate3d(0, 0, 0);
|
||||
-webkit-transition-duration: 250ms;
|
||||
transition-duration: 250ms;
|
||||
-webkit-transition-timing-function: linear;
|
||||
transition-timing-function: linear;
|
||||
}
|
||||
.alertify-notifier .ajs-message.ajs-visible {
|
||||
-webkit-transition-duration: 500ms;
|
||||
transition-duration: 500ms;
|
||||
-webkit-transition-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1.275);
|
||||
transition-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1.275);
|
||||
opacity: 1;
|
||||
max-height: 100%;
|
||||
padding: 15px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
.alertify-notifier .ajs-message.ajs-success {
|
||||
background: rgba(91, 189, 114, 0.95);
|
||||
}
|
||||
.alertify-notifier .ajs-message.ajs-error {
|
||||
background: rgba(217, 92, 92, 0.95);
|
||||
}
|
||||
.alertify-notifier .ajs-message.ajs-warning {
|
||||
background: rgba(252, 248, 215, 0.95);
|
||||
}
|
||||
.alertify-notifier .ajs-message .ajs-close {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
cursor: pointer;
|
||||
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAYAAADED76LAAAABGdBTUEAALGPC/xhBQAAAFBJREFUGBl1j0EKADEIA+ve/P9f9bh1hEihNBfjVCO1v7RKVqJK4h8gM5cAPR42AkQEpSXPwMTyoi13n5N9YqJehm3Fnr7nL1D0ZEbD5OubGyC7a9gx+9eNAAAAAElFTkSuQmCC);
|
||||
background-repeat: no-repeat;
|
||||
background-position: center center;
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
border-top-right-radius: 2px;
|
||||
}
|
||||
.alertify-notifier.ajs-top {
|
||||
top: 10px;
|
||||
}
|
||||
.alertify-notifier.ajs-bottom {
|
||||
bottom: 10px;
|
||||
}
|
||||
.alertify-notifier.ajs-right {
|
||||
right: 10px;
|
||||
}
|
||||
.alertify-notifier.ajs-right .ajs-message {
|
||||
right: -320px;
|
||||
}
|
||||
.alertify-notifier.ajs-right .ajs-message.ajs-visible {
|
||||
right: 290px;
|
||||
}
|
||||
.alertify-notifier.ajs-left {
|
||||
left: 10px;
|
||||
}
|
||||
.alertify-notifier.ajs-left .ajs-message {
|
||||
left: -300px;
|
||||
}
|
||||
.alertify-notifier.ajs-left .ajs-message.ajs-visible {
|
||||
left: 0;
|
||||
}
|
||||
.alertify-notifier.ajs-center {
|
||||
left: 50%;
|
||||
}
|
||||
.alertify-notifier.ajs-center .ajs-message {
|
||||
-webkit-transform: translateX(-50%);
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
.alertify-notifier.ajs-center .ajs-message.ajs-visible {
|
||||
left: 50%;
|
||||
-webkit-transition-timing-function: cubic-bezier(0.57, 0.43, 0.1, 0.65);
|
||||
transition-timing-function: cubic-bezier(0.57, 0.43, 0.1, 0.65);
|
||||
}
|
||||
.alertify-notifier.ajs-center.ajs-top .ajs-message {
|
||||
top: -300px;
|
||||
}
|
||||
.alertify-notifier.ajs-center.ajs-top .ajs-message.ajs-visible {
|
||||
top: 0;
|
||||
}
|
||||
.alertify-notifier.ajs-center.ajs-bottom .ajs-message {
|
||||
bottom: -300px;
|
||||
}
|
||||
.alertify-notifier.ajs-center.ajs-bottom .ajs-message.ajs-visible {
|
||||
bottom: 0;
|
||||
}
|
||||
.ajs-no-transition.alertify .ajs-dimmer,
|
||||
.ajs-no-transition.alertify .ajs-modal,
|
||||
.ajs-no-transition.alertify .ajs-dialog {
|
||||
-webkit-transition: none!important;
|
||||
transition: none!important;
|
||||
-webkit-animation: none!important;
|
||||
animation: none!important;
|
||||
}
|
||||
.ajs-no-transition.alertify-notifier .ajs-message {
|
||||
-webkit-transition: none!important;
|
||||
transition: none!important;
|
||||
-webkit-animation: none!important;
|
||||
animation: none!important;
|
||||
}
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.alertify .ajs-dimmer,
|
||||
.alertify .ajs-modal,
|
||||
.alertify .ajs-dialog {
|
||||
-webkit-transition: none!important;
|
||||
transition: none!important;
|
||||
-webkit-animation: none!important;
|
||||
animation: none!important;
|
||||
}
|
||||
.alertify-notifier .ajs-message {
|
||||
-webkit-transition: none!important;
|
||||
transition: none!important;
|
||||
-webkit-animation: none!important;
|
||||
animation: none!important;
|
||||
}
|
||||
}
|
6
static/lib/alertify/css/alertify.min.css
vendored
Normal file
968
static/lib/alertify/css/alertify.rtl.css
Normal file
|
@ -0,0 +1,968 @@
|
|||
/**
|
||||
* alertifyjs 1.13.1 http://alertifyjs.com
|
||||
* AlertifyJS is a javascript framework for developing pretty browser dialogs and notifications.
|
||||
* Copyright 2019 Mohammad Younes <Mohammad@alertifyjs.com> (http://alertifyjs.com)
|
||||
* Licensed under GPL 3 <https://opensource.org/licenses/gpl-3.0>*/
|
||||
.alertify .ajs-dimmer {
|
||||
position: fixed;
|
||||
z-index: 1981;
|
||||
top: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
background-color: #252525;
|
||||
opacity: .5;
|
||||
}
|
||||
.alertify .ajs-modal {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
padding: 0;
|
||||
overflow-y: auto;
|
||||
z-index: 1981;
|
||||
}
|
||||
.alertify .ajs-dialog {
|
||||
position: relative;
|
||||
margin: 5% auto;
|
||||
min-height: 110px;
|
||||
max-width: 500px;
|
||||
padding: 24px 24px 0 24px;
|
||||
outline: 0;
|
||||
background-color: #fff;
|
||||
}
|
||||
.alertify .ajs-dialog.ajs-capture:before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
display: block;
|
||||
z-index: 1;
|
||||
}
|
||||
.alertify .ajs-reset {
|
||||
position: absolute !important;
|
||||
display: inline !important;
|
||||
width: 0 !important;
|
||||
height: 0 !important;
|
||||
opacity: 0 !important;
|
||||
}
|
||||
.alertify .ajs-commands {
|
||||
position: absolute;
|
||||
left: 4px;
|
||||
margin: -14px 0 0 24px;
|
||||
z-index: 2;
|
||||
}
|
||||
.alertify .ajs-commands button {
|
||||
display: none;
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
margin-right: 10px;
|
||||
padding: 10px;
|
||||
border: 0;
|
||||
background-color: transparent;
|
||||
background-repeat: no-repeat;
|
||||
background-position: center;
|
||||
cursor: pointer;
|
||||
}
|
||||
.alertify .ajs-commands button.ajs-close {
|
||||
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAABZ0RVh0Q3JlYXRpb24gVGltZQAwNy8xMy8xNOrZqugAAAAcdEVYdFNvZnR3YXJlAEFkb2JlIEZpcmV3b3JrcyBDUzbovLKMAAAAh0lEQVQYlY2QsQ0EIQwEB9cBAR1CJUaI/gigDnwR6NBL/7/xWLNrZ2b8EwGotVpr7eOitWa1VjugiNB7R1UPrKrWe0dEAHBbXUqxMQbeewDmnHjvyTm7C3zDwAUd9c63YQdUVdu6EAJzzquz7HXvTiklt+H9DQFYaxFjvDqllFyMkbXWvfpXHjJrWFgdBq/hAAAAAElFTkSuQmCC);
|
||||
}
|
||||
.alertify .ajs-commands button.ajs-maximize {
|
||||
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAABZ0RVh0Q3JlYXRpb24gVGltZQAwNy8xMy8xNOrZqugAAAAcdEVYdFNvZnR3YXJlAEFkb2JlIEZpcmV3b3JrcyBDUzbovLKMAAAAOUlEQVQYlWP8//8/AzGAhYGBgaG4uBiv6t7eXkYmooxjYGAgWiELsvHYFMCcRX2rSXcjoSBiJDbAAeD+EGu+8BZcAAAAAElFTkSuQmCC);
|
||||
}
|
||||
.alertify .ajs-header {
|
||||
margin: -24px;
|
||||
margin-bottom: 0;
|
||||
padding: 16px 24px;
|
||||
background-color: #fff;
|
||||
}
|
||||
.alertify .ajs-body {
|
||||
min-height: 56px;
|
||||
}
|
||||
.alertify .ajs-body .ajs-content {
|
||||
padding: 16px 16px 16px 24px;
|
||||
}
|
||||
.alertify .ajs-footer {
|
||||
padding: 4px;
|
||||
margin-right: -24px;
|
||||
margin-left: -24px;
|
||||
min-height: 43px;
|
||||
background-color: #fff;
|
||||
}
|
||||
.alertify .ajs-footer .ajs-buttons.ajs-primary {
|
||||
text-align: left;
|
||||
}
|
||||
.alertify .ajs-footer .ajs-buttons.ajs-primary .ajs-button {
|
||||
margin: 4px;
|
||||
}
|
||||
.alertify .ajs-footer .ajs-buttons.ajs-auxiliary {
|
||||
float: right;
|
||||
clear: none;
|
||||
text-align: right;
|
||||
}
|
||||
.alertify .ajs-footer .ajs-buttons.ajs-auxiliary .ajs-button {
|
||||
margin: 4px;
|
||||
}
|
||||
.alertify .ajs-footer .ajs-buttons .ajs-button {
|
||||
min-width: 88px;
|
||||
min-height: 35px;
|
||||
}
|
||||
.alertify .ajs-handle {
|
||||
position: absolute;
|
||||
display: none;
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
z-index: 1;
|
||||
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAABZ0RVh0Q3JlYXRpb24gVGltZQAwNy8xMS8xNEDQYmMAAAAcdEVYdFNvZnR3YXJlAEFkb2JlIEZpcmV3b3JrcyBDUzbovLKMAAAAQ0lEQVQYlaXNMQoAIAxD0dT7H657l0KX3iJuUlBUNOsPPCGJm7VDp6ryeMxMuDsAQH7owW3pyn3RS26iKxERMLN3ugOaAkaL3sWVigAAAABJRU5ErkJggg==);
|
||||
-webkit-transform: scaleX(-1);
|
||||
transform: scaleX(-1);
|
||||
cursor: sw-resize;
|
||||
}
|
||||
.alertify.ajs-no-overflow .ajs-body .ajs-content {
|
||||
overflow: hidden !important;
|
||||
}
|
||||
.alertify.ajs-no-padding.ajs-maximized .ajs-body .ajs-content {
|
||||
right: 0;
|
||||
left: 0;
|
||||
padding: 0;
|
||||
}
|
||||
.alertify.ajs-no-padding:not(.ajs-maximized) .ajs-body {
|
||||
margin-right: -24px;
|
||||
margin-left: -24px;
|
||||
}
|
||||
.alertify.ajs-no-padding:not(.ajs-maximized) .ajs-body .ajs-content {
|
||||
padding: 0;
|
||||
}
|
||||
.alertify.ajs-no-padding.ajs-resizable .ajs-body .ajs-content {
|
||||
right: 0;
|
||||
left: 0;
|
||||
}
|
||||
.alertify.ajs-maximizable .ajs-commands button.ajs-maximize,
|
||||
.alertify.ajs-maximizable .ajs-commands button.ajs-restore {
|
||||
display: inline-block;
|
||||
}
|
||||
.alertify.ajs-closable .ajs-commands button.ajs-close {
|
||||
display: inline-block;
|
||||
}
|
||||
.alertify.ajs-maximized .ajs-dialog {
|
||||
width: 100% !important;
|
||||
height: 100% !important;
|
||||
max-width: none !important;
|
||||
margin: 0 auto !important;
|
||||
top: 0 !important;
|
||||
right: 0 !important;
|
||||
}
|
||||
.alertify.ajs-maximized.ajs-modeless .ajs-modal {
|
||||
position: fixed !important;
|
||||
min-height: 100% !important;
|
||||
max-height: none !important;
|
||||
margin: 0 !important;
|
||||
}
|
||||
.alertify.ajs-maximized .ajs-commands button.ajs-maximize {
|
||||
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAABZ0RVh0Q3JlYXRpb24gVGltZQAwNy8xMy8xNOrZqugAAAAcdEVYdFNvZnR3YXJlAEFkb2JlIEZpcmV3b3JrcyBDUzbovLKMAAAASklEQVQYlZWQ0QkAMQhDtXRincOZX78KVtrDCwgqJNEoIB3MPLj7lRUROlpyVXGzby6zWuY+kz6tj5sBMTMAyVV3/595RbOh3cAXsww1raeiOcoAAAAASUVORK5CYII=);
|
||||
}
|
||||
.alertify.ajs-resizable .ajs-dialog,
|
||||
.alertify.ajs-maximized .ajs-dialog {
|
||||
padding: 0;
|
||||
}
|
||||
.alertify.ajs-resizable .ajs-commands,
|
||||
.alertify.ajs-maximized .ajs-commands {
|
||||
margin: 14px 0 0 24px;
|
||||
}
|
||||
.alertify.ajs-resizable .ajs-header,
|
||||
.alertify.ajs-maximized .ajs-header {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
left: 0;
|
||||
margin: 0;
|
||||
padding: 16px 24px;
|
||||
}
|
||||
.alertify.ajs-resizable .ajs-body,
|
||||
.alertify.ajs-maximized .ajs-body {
|
||||
min-height: 224px;
|
||||
display: inline-block;
|
||||
}
|
||||
.alertify.ajs-resizable .ajs-body .ajs-content,
|
||||
.alertify.ajs-maximized .ajs-body .ajs-content {
|
||||
position: absolute;
|
||||
top: 50px;
|
||||
left: 24px;
|
||||
bottom: 50px;
|
||||
right: 24px;
|
||||
overflow: auto;
|
||||
}
|
||||
.alertify.ajs-resizable .ajs-footer,
|
||||
.alertify.ajs-maximized .ajs-footer {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
margin: 0;
|
||||
}
|
||||
.alertify.ajs-resizable:not(.ajs-maximized) .ajs-dialog {
|
||||
min-width: 548px;
|
||||
}
|
||||
.alertify.ajs-resizable:not(.ajs-maximized) .ajs-handle {
|
||||
display: block;
|
||||
}
|
||||
.alertify.ajs-movable:not(.ajs-maximized) .ajs-header {
|
||||
cursor: move;
|
||||
}
|
||||
.alertify.ajs-modeless .ajs-dimmer,
|
||||
.alertify.ajs-modeless .ajs-reset {
|
||||
display: none;
|
||||
}
|
||||
.alertify.ajs-modeless .ajs-modal {
|
||||
overflow: visible;
|
||||
max-width: none;
|
||||
max-height: 0;
|
||||
}
|
||||
.alertify.ajs-modeless.ajs-pinnable .ajs-commands button.ajs-pin {
|
||||
display: inline-block;
|
||||
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAABZ0RVh0Q3JlYXRpb24gVGltZQAwNy8xMy8xNOrZqugAAAAcdEVYdFNvZnR3YXJlAEFkb2JlIEZpcmV3b3JrcyBDUzbovLKMAAAAQklEQVQYlcWPMQ4AIAwCqU9u38GbcbHRWN1MvKQDhQFMEpKImGJA0gCgnYw0V0rwxseg5erT4oSkQVI5d9f+e9+xA0NbLpWfitPXAAAAAElFTkSuQmCC);
|
||||
}
|
||||
.alertify.ajs-modeless.ajs-unpinned .ajs-modal {
|
||||
position: absolute;
|
||||
}
|
||||
.alertify.ajs-modeless.ajs-unpinned .ajs-commands button.ajs-pin {
|
||||
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAABZ0RVh0Q3JlYXRpb24gVGltZQAwNy8xMy8xNOrZqugAAAAcdEVYdFNvZnR3YXJlAEFkb2JlIEZpcmV3b3JrcyBDUzbovLKMAAAAO0lEQVQYlWP8//8/AzGAiShV6AqLi4txGs+CLoBLMYbC3t5eRmyaWfBZhwwYkX2NTxPRvibKjRhW4wMAhxkYGbLu3pEAAAAASUVORK5CYII=);
|
||||
}
|
||||
.alertify.ajs-modeless:not(.ajs-unpinned) .ajs-body {
|
||||
max-height: 500px;
|
||||
overflow: auto;
|
||||
}
|
||||
.alertify.ajs-basic .ajs-header {
|
||||
opacity: 0;
|
||||
}
|
||||
.alertify.ajs-basic .ajs-footer {
|
||||
visibility: hidden;
|
||||
}
|
||||
.alertify.ajs-frameless .ajs-header {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
left: 0;
|
||||
min-height: 60px;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
opacity: 0;
|
||||
z-index: 1;
|
||||
}
|
||||
.alertify.ajs-frameless .ajs-footer {
|
||||
display: none;
|
||||
}
|
||||
.alertify.ajs-frameless .ajs-body .ajs-content {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
}
|
||||
.alertify.ajs-frameless:not(.ajs-resizable) .ajs-dialog {
|
||||
padding-top: 0;
|
||||
}
|
||||
.alertify.ajs-frameless:not(.ajs-resizable) .ajs-dialog .ajs-commands {
|
||||
margin-top: 0;
|
||||
}
|
||||
.ajs-no-overflow {
|
||||
overflow: hidden !important;
|
||||
outline: none;
|
||||
}
|
||||
.ajs-no-overflow.ajs-fixed {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
overflow-y: scroll!important;
|
||||
}
|
||||
.ajs-no-selection,
|
||||
.ajs-no-selection * {
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
@media screen and (max-width: 568px) {
|
||||
.alertify .ajs-dialog {
|
||||
min-width: 150px;
|
||||
}
|
||||
.alertify:not(.ajs-maximized) .ajs-modal {
|
||||
padding: 0 5%;
|
||||
}
|
||||
.alertify:not(.ajs-maximized).ajs-resizable .ajs-dialog {
|
||||
min-width: initial;
|
||||
min-width: auto /*IE fallback*/;
|
||||
}
|
||||
}
|
||||
@-moz-document url-prefix() {
|
||||
.alertify button:focus {
|
||||
outline: 1px dotted #3593D2;
|
||||
}
|
||||
}
|
||||
.alertify .ajs-dimmer,
|
||||
.alertify .ajs-modal {
|
||||
-webkit-transform: translate3d(0, 0, 0);
|
||||
transform: translate3d(0, 0, 0);
|
||||
-webkit-transition-property: opacity, visibility;
|
||||
transition-property: opacity, visibility;
|
||||
-webkit-transition-timing-function: linear;
|
||||
transition-timing-function: linear;
|
||||
-webkit-transition-duration: 250ms;
|
||||
transition-duration: 250ms;
|
||||
}
|
||||
.alertify.ajs-hidden .ajs-dimmer,
|
||||
.alertify.ajs-hidden .ajs-modal {
|
||||
visibility: hidden;
|
||||
opacity: 0;
|
||||
}
|
||||
.alertify.ajs-in:not(.ajs-hidden) .ajs-dialog {
|
||||
-webkit-animation-duration: 500ms;
|
||||
animation-duration: 500ms;
|
||||
}
|
||||
.alertify.ajs-out.ajs-hidden .ajs-dialog {
|
||||
-webkit-animation-duration: 250ms;
|
||||
animation-duration: 250ms;
|
||||
}
|
||||
.alertify .ajs-dialog.ajs-shake {
|
||||
-webkit-animation-name: ajs-shake;
|
||||
animation-name: ajs-shake;
|
||||
-webkit-animation-duration: .1s;
|
||||
animation-duration: .1s;
|
||||
-webkit-animation-fill-mode: both;
|
||||
animation-fill-mode: both;
|
||||
}
|
||||
@-webkit-keyframes ajs-shake {
|
||||
0%,
|
||||
100% {
|
||||
-webkit-transform: translate3d(0, 0, 0);
|
||||
transform: translate3d(0, 0, 0);
|
||||
}
|
||||
10%,
|
||||
30%,
|
||||
50%,
|
||||
70%,
|
||||
90% {
|
||||
-webkit-transform: translate3d(10px, 0, 0);
|
||||
transform: translate3d(10px, 0, 0);
|
||||
}
|
||||
20%,
|
||||
40%,
|
||||
60%,
|
||||
80% {
|
||||
-webkit-transform: translate3d(-10px, 0, 0);
|
||||
transform: translate3d(-10px, 0, 0);
|
||||
}
|
||||
}
|
||||
@keyframes ajs-shake {
|
||||
0%,
|
||||
100% {
|
||||
-webkit-transform: translate3d(0, 0, 0);
|
||||
transform: translate3d(0, 0, 0);
|
||||
}
|
||||
10%,
|
||||
30%,
|
||||
50%,
|
||||
70%,
|
||||
90% {
|
||||
-webkit-transform: translate3d(10px, 0, 0);
|
||||
transform: translate3d(10px, 0, 0);
|
||||
}
|
||||
20%,
|
||||
40%,
|
||||
60%,
|
||||
80% {
|
||||
-webkit-transform: translate3d(-10px, 0, 0);
|
||||
transform: translate3d(-10px, 0, 0);
|
||||
}
|
||||
}
|
||||
.alertify.ajs-slide.ajs-in:not(.ajs-hidden) .ajs-dialog {
|
||||
-webkit-animation-name: ajs-slideIn;
|
||||
animation-name: ajs-slideIn;
|
||||
-webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1.275);
|
||||
animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1.275);
|
||||
}
|
||||
.alertify.ajs-slide.ajs-out.ajs-hidden .ajs-dialog {
|
||||
-webkit-animation-name: ajs-slideOut;
|
||||
animation-name: ajs-slideOut;
|
||||
-webkit-animation-timing-function: cubic-bezier(0.6, -0.28, 0.735, 0.045);
|
||||
animation-timing-function: cubic-bezier(0.6, -0.28, 0.735, 0.045);
|
||||
}
|
||||
.alertify.ajs-zoom.ajs-in:not(.ajs-hidden) .ajs-dialog {
|
||||
-webkit-animation-name: ajs-zoomIn;
|
||||
animation-name: ajs-zoomIn;
|
||||
}
|
||||
.alertify.ajs-zoom.ajs-out.ajs-hidden .ajs-dialog {
|
||||
-webkit-animation-name: ajs-zoomOut;
|
||||
animation-name: ajs-zoomOut;
|
||||
}
|
||||
.alertify.ajs-fade.ajs-in:not(.ajs-hidden) .ajs-dialog {
|
||||
-webkit-animation-name: ajs-fadeIn;
|
||||
animation-name: ajs-fadeIn;
|
||||
}
|
||||
.alertify.ajs-fade.ajs-out.ajs-hidden .ajs-dialog {
|
||||
-webkit-animation-name: ajs-fadeOut;
|
||||
animation-name: ajs-fadeOut;
|
||||
}
|
||||
.alertify.ajs-pulse.ajs-in:not(.ajs-hidden) .ajs-dialog {
|
||||
-webkit-animation-name: ajs-pulseIn;
|
||||
animation-name: ajs-pulseIn;
|
||||
}
|
||||
.alertify.ajs-pulse.ajs-out.ajs-hidden .ajs-dialog {
|
||||
-webkit-animation-name: ajs-pulseOut;
|
||||
animation-name: ajs-pulseOut;
|
||||
}
|
||||
.alertify.ajs-flipx.ajs-in:not(.ajs-hidden) .ajs-dialog {
|
||||
-webkit-animation-name: ajs-flipInX;
|
||||
animation-name: ajs-flipInX;
|
||||
}
|
||||
.alertify.ajs-flipx.ajs-out.ajs-hidden .ajs-dialog {
|
||||
-webkit-animation-name: ajs-flipOutX;
|
||||
animation-name: ajs-flipOutX;
|
||||
}
|
||||
.alertify.ajs-flipy.ajs-in:not(.ajs-hidden) .ajs-dialog {
|
||||
-webkit-animation-name: ajs-flipInY;
|
||||
animation-name: ajs-flipInY;
|
||||
}
|
||||
.alertify.ajs-flipy.ajs-out.ajs-hidden .ajs-dialog {
|
||||
-webkit-animation-name: ajs-flipOutY;
|
||||
animation-name: ajs-flipOutY;
|
||||
}
|
||||
@-webkit-keyframes ajs-pulseIn {
|
||||
0%,
|
||||
20%,
|
||||
40%,
|
||||
60%,
|
||||
80%,
|
||||
100% {
|
||||
-webkit-transition-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
|
||||
transition-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
|
||||
}
|
||||
0% {
|
||||
opacity: 0;
|
||||
-webkit-transform: scale3d(0.3, 0.3, 0.3);
|
||||
transform: scale3d(0.3, 0.3, 0.3);
|
||||
}
|
||||
20% {
|
||||
-webkit-transform: scale3d(1.1, 1.1, 1.1);
|
||||
transform: scale3d(1.1, 1.1, 1.1);
|
||||
}
|
||||
40% {
|
||||
-webkit-transform: scale3d(0.9, 0.9, 0.9);
|
||||
transform: scale3d(0.9, 0.9, 0.9);
|
||||
}
|
||||
60% {
|
||||
opacity: 1;
|
||||
-webkit-transform: scale3d(1.03, 1.03, 1.03);
|
||||
transform: scale3d(1.03, 1.03, 1.03);
|
||||
}
|
||||
80% {
|
||||
-webkit-transform: scale3d(0.97, 0.97, 0.97);
|
||||
transform: scale3d(0.97, 0.97, 0.97);
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
-webkit-transform: scale3d(1, 1, 1);
|
||||
transform: scale3d(1, 1, 1);
|
||||
}
|
||||
}
|
||||
@keyframes ajs-pulseIn {
|
||||
0%,
|
||||
20%,
|
||||
40%,
|
||||
60%,
|
||||
80%,
|
||||
100% {
|
||||
-webkit-transition-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
|
||||
transition-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
|
||||
}
|
||||
0% {
|
||||
opacity: 0;
|
||||
-webkit-transform: scale3d(0.3, 0.3, 0.3);
|
||||
transform: scale3d(0.3, 0.3, 0.3);
|
||||
}
|
||||
20% {
|
||||
-webkit-transform: scale3d(1.1, 1.1, 1.1);
|
||||
transform: scale3d(1.1, 1.1, 1.1);
|
||||
}
|
||||
40% {
|
||||
-webkit-transform: scale3d(0.9, 0.9, 0.9);
|
||||
transform: scale3d(0.9, 0.9, 0.9);
|
||||
}
|
||||
60% {
|
||||
opacity: 1;
|
||||
-webkit-transform: scale3d(1.03, 1.03, 1.03);
|
||||
transform: scale3d(1.03, 1.03, 1.03);
|
||||
}
|
||||
80% {
|
||||
-webkit-transform: scale3d(0.97, 0.97, 0.97);
|
||||
transform: scale3d(0.97, 0.97, 0.97);
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
-webkit-transform: scale3d(1, 1, 1);
|
||||
transform: scale3d(1, 1, 1);
|
||||
}
|
||||
}
|
||||
@-webkit-keyframes ajs-pulseOut {
|
||||
20% {
|
||||
-webkit-transform: scale3d(0.9, 0.9, 0.9);
|
||||
transform: scale3d(0.9, 0.9, 0.9);
|
||||
}
|
||||
50%,
|
||||
55% {
|
||||
opacity: 1;
|
||||
-webkit-transform: scale3d(1.1, 1.1, 1.1);
|
||||
transform: scale3d(1.1, 1.1, 1.1);
|
||||
}
|
||||
100% {
|
||||
opacity: 0;
|
||||
-webkit-transform: scale3d(0.3, 0.3, 0.3);
|
||||
transform: scale3d(0.3, 0.3, 0.3);
|
||||
}
|
||||
}
|
||||
@keyframes ajs-pulseOut {
|
||||
20% {
|
||||
-webkit-transform: scale3d(0.9, 0.9, 0.9);
|
||||
transform: scale3d(0.9, 0.9, 0.9);
|
||||
}
|
||||
50%,
|
||||
55% {
|
||||
opacity: 1;
|
||||
-webkit-transform: scale3d(1.1, 1.1, 1.1);
|
||||
transform: scale3d(1.1, 1.1, 1.1);
|
||||
}
|
||||
100% {
|
||||
opacity: 0;
|
||||
-webkit-transform: scale3d(0.3, 0.3, 0.3);
|
||||
transform: scale3d(0.3, 0.3, 0.3);
|
||||
}
|
||||
}
|
||||
@-webkit-keyframes ajs-zoomIn {
|
||||
0% {
|
||||
opacity: 0;
|
||||
-webkit-transform: scale3d(0.25, 0.25, 0.25);
|
||||
transform: scale3d(0.25, 0.25, 0.25);
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
-webkit-transform: scale3d(1, 1, 1);
|
||||
transform: scale3d(1, 1, 1);
|
||||
}
|
||||
}
|
||||
@keyframes ajs-zoomIn {
|
||||
0% {
|
||||
opacity: 0;
|
||||
-webkit-transform: scale3d(0.25, 0.25, 0.25);
|
||||
transform: scale3d(0.25, 0.25, 0.25);
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
-webkit-transform: scale3d(1, 1, 1);
|
||||
transform: scale3d(1, 1, 1);
|
||||
}
|
||||
}
|
||||
@-webkit-keyframes ajs-zoomOut {
|
||||
0% {
|
||||
opacity: 1;
|
||||
-webkit-transform: scale3d(1, 1, 1);
|
||||
transform: scale3d(1, 1, 1);
|
||||
}
|
||||
100% {
|
||||
opacity: 0;
|
||||
-webkit-transform: scale3d(0.25, 0.25, 0.25);
|
||||
transform: scale3d(0.25, 0.25, 0.25);
|
||||
}
|
||||
}
|
||||
@keyframes ajs-zoomOut {
|
||||
0% {
|
||||
opacity: 1;
|
||||
-webkit-transform: scale3d(1, 1, 1);
|
||||
transform: scale3d(1, 1, 1);
|
||||
}
|
||||
100% {
|
||||
opacity: 0;
|
||||
-webkit-transform: scale3d(0.25, 0.25, 0.25);
|
||||
transform: scale3d(0.25, 0.25, 0.25);
|
||||
}
|
||||
}
|
||||
@-webkit-keyframes ajs-fadeIn {
|
||||
0% {
|
||||
opacity: 0;
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
@keyframes ajs-fadeIn {
|
||||
0% {
|
||||
opacity: 0;
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
@-webkit-keyframes ajs-fadeOut {
|
||||
0% {
|
||||
opacity: 1;
|
||||
}
|
||||
100% {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
@keyframes ajs-fadeOut {
|
||||
0% {
|
||||
opacity: 1;
|
||||
}
|
||||
100% {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
@-webkit-keyframes ajs-flipInX {
|
||||
0% {
|
||||
-webkit-transform: perspective(400px) rotate3d(1, 0, 0, -90deg);
|
||||
transform: perspective(400px) rotate3d(1, 0, 0, -90deg);
|
||||
-webkit-transition-timing-function: ease-in;
|
||||
transition-timing-function: ease-in;
|
||||
opacity: 0;
|
||||
}
|
||||
40% {
|
||||
-webkit-transform: perspective(400px) rotate3d(1, 0, 0, 20deg);
|
||||
transform: perspective(400px) rotate3d(1, 0, 0, 20deg);
|
||||
-webkit-transition-timing-function: ease-in;
|
||||
transition-timing-function: ease-in;
|
||||
}
|
||||
60% {
|
||||
-webkit-transform: perspective(400px) rotate3d(1, 0, 0, -10deg);
|
||||
transform: perspective(400px) rotate3d(1, 0, 0, -10deg);
|
||||
opacity: 1;
|
||||
}
|
||||
80% {
|
||||
-webkit-transform: perspective(400px) rotate3d(1, 0, 0, 5deg);
|
||||
transform: perspective(400px) rotate3d(1, 0, 0, 5deg);
|
||||
}
|
||||
100% {
|
||||
-webkit-transform: perspective(400px);
|
||||
transform: perspective(400px);
|
||||
}
|
||||
}
|
||||
@keyframes ajs-flipInX {
|
||||
0% {
|
||||
-webkit-transform: perspective(400px) rotate3d(1, 0, 0, -90deg);
|
||||
transform: perspective(400px) rotate3d(1, 0, 0, -90deg);
|
||||
-webkit-transition-timing-function: ease-in;
|
||||
transition-timing-function: ease-in;
|
||||
opacity: 0;
|
||||
}
|
||||
40% {
|
||||
-webkit-transform: perspective(400px) rotate3d(1, 0, 0, 20deg);
|
||||
transform: perspective(400px) rotate3d(1, 0, 0, 20deg);
|
||||
-webkit-transition-timing-function: ease-in;
|
||||
transition-timing-function: ease-in;
|
||||
}
|
||||
60% {
|
||||
-webkit-transform: perspective(400px) rotate3d(1, 0, 0, -10deg);
|
||||
transform: perspective(400px) rotate3d(1, 0, 0, -10deg);
|
||||
opacity: 1;
|
||||
}
|
||||
80% {
|
||||
-webkit-transform: perspective(400px) rotate3d(1, 0, 0, 5deg);
|
||||
transform: perspective(400px) rotate3d(1, 0, 0, 5deg);
|
||||
}
|
||||
100% {
|
||||
-webkit-transform: perspective(400px);
|
||||
transform: perspective(400px);
|
||||
}
|
||||
}
|
||||
@-webkit-keyframes ajs-flipOutX {
|
||||
0% {
|
||||
-webkit-transform: perspective(400px);
|
||||
transform: perspective(400px);
|
||||
}
|
||||
30% {
|
||||
-webkit-transform: perspective(400px) rotate3d(1, 0, 0, 20deg);
|
||||
transform: perspective(400px) rotate3d(1, 0, 0, 20deg);
|
||||
opacity: 1;
|
||||
}
|
||||
100% {
|
||||
-webkit-transform: perspective(400px) rotate3d(1, 0, 0, -90deg);
|
||||
transform: perspective(400px) rotate3d(1, 0, 0, -90deg);
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
@keyframes ajs-flipOutX {
|
||||
0% {
|
||||
-webkit-transform: perspective(400px);
|
||||
transform: perspective(400px);
|
||||
}
|
||||
30% {
|
||||
-webkit-transform: perspective(400px) rotate3d(1, 0, 0, 20deg);
|
||||
transform: perspective(400px) rotate3d(1, 0, 0, 20deg);
|
||||
opacity: 1;
|
||||
}
|
||||
100% {
|
||||
-webkit-transform: perspective(400px) rotate3d(1, 0, 0, -90deg);
|
||||
transform: perspective(400px) rotate3d(1, 0, 0, -90deg);
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
@-webkit-keyframes ajs-flipInY {
|
||||
0% {
|
||||
-webkit-transform: perspective(400px) rotate3d(0, -1, 0, -90deg);
|
||||
transform: perspective(400px) rotate3d(0, -1, 0, -90deg);
|
||||
-webkit-transition-timing-function: ease-in;
|
||||
transition-timing-function: ease-in;
|
||||
opacity: 0;
|
||||
}
|
||||
40% {
|
||||
-webkit-transform: perspective(400px) rotate3d(0, -1, 0, 20deg);
|
||||
transform: perspective(400px) rotate3d(0, -1, 0, 20deg);
|
||||
-webkit-transition-timing-function: ease-in;
|
||||
transition-timing-function: ease-in;
|
||||
}
|
||||
60% {
|
||||
-webkit-transform: perspective(400px) rotate3d(0, -1, 0, -10deg);
|
||||
transform: perspective(400px) rotate3d(0, -1, 0, -10deg);
|
||||
opacity: 1;
|
||||
}
|
||||
80% {
|
||||
-webkit-transform: perspective(400px) rotate3d(0, -1, 0, 5deg);
|
||||
transform: perspective(400px) rotate3d(0, -1, 0, 5deg);
|
||||
}
|
||||
100% {
|
||||
-webkit-transform: perspective(400px);
|
||||
transform: perspective(400px);
|
||||
}
|
||||
}
|
||||
@keyframes ajs-flipInY {
|
||||
0% {
|
||||
-webkit-transform: perspective(400px) rotate3d(0, -1, 0, -90deg);
|
||||
transform: perspective(400px) rotate3d(0, -1, 0, -90deg);
|
||||
-webkit-transition-timing-function: ease-in;
|
||||
transition-timing-function: ease-in;
|
||||
opacity: 0;
|
||||
}
|
||||
40% {
|
||||
-webkit-transform: perspective(400px) rotate3d(0, -1, 0, 20deg);
|
||||
transform: perspective(400px) rotate3d(0, -1, 0, 20deg);
|
||||
-webkit-transition-timing-function: ease-in;
|
||||
transition-timing-function: ease-in;
|
||||
}
|
||||
60% {
|
||||
-webkit-transform: perspective(400px) rotate3d(0, -1, 0, -10deg);
|
||||
transform: perspective(400px) rotate3d(0, -1, 0, -10deg);
|
||||
opacity: 1;
|
||||
}
|
||||
80% {
|
||||
-webkit-transform: perspective(400px) rotate3d(0, -1, 0, 5deg);
|
||||
transform: perspective(400px) rotate3d(0, -1, 0, 5deg);
|
||||
}
|
||||
100% {
|
||||
-webkit-transform: perspective(400px);
|
||||
transform: perspective(400px);
|
||||
}
|
||||
}
|
||||
@-webkit-keyframes ajs-flipOutY {
|
||||
0% {
|
||||
-webkit-transform: perspective(400px);
|
||||
transform: perspective(400px);
|
||||
}
|
||||
30% {
|
||||
-webkit-transform: perspective(400px) rotate3d(0, -1, 0, 15deg);
|
||||
transform: perspective(400px) rotate3d(0, -1, 0, 15deg);
|
||||
opacity: 1;
|
||||
}
|
||||
100% {
|
||||
-webkit-transform: perspective(400px) rotate3d(0, -1, 0, -90deg);
|
||||
transform: perspective(400px) rotate3d(0, -1, 0, -90deg);
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
@keyframes ajs-flipOutY {
|
||||
0% {
|
||||
-webkit-transform: perspective(400px);
|
||||
transform: perspective(400px);
|
||||
}
|
||||
30% {
|
||||
-webkit-transform: perspective(400px) rotate3d(0, -1, 0, 15deg);
|
||||
transform: perspective(400px) rotate3d(0, -1, 0, 15deg);
|
||||
opacity: 1;
|
||||
}
|
||||
100% {
|
||||
-webkit-transform: perspective(400px) rotate3d(0, -1, 0, -90deg);
|
||||
transform: perspective(400px) rotate3d(0, -1, 0, -90deg);
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
@-webkit-keyframes ajs-slideIn {
|
||||
0% {
|
||||
margin-top: -100%;
|
||||
}
|
||||
100% {
|
||||
margin-top: 5%;
|
||||
}
|
||||
}
|
||||
@keyframes ajs-slideIn {
|
||||
0% {
|
||||
margin-top: -100%;
|
||||
}
|
||||
100% {
|
||||
margin-top: 5%;
|
||||
}
|
||||
}
|
||||
@-webkit-keyframes ajs-slideOut {
|
||||
0% {
|
||||
margin-top: 5%;
|
||||
}
|
||||
100% {
|
||||
margin-top: -100%;
|
||||
}
|
||||
}
|
||||
@keyframes ajs-slideOut {
|
||||
0% {
|
||||
margin-top: 5%;
|
||||
}
|
||||
100% {
|
||||
margin-top: -100%;
|
||||
}
|
||||
}
|
||||
.alertify-notifier {
|
||||
position: fixed;
|
||||
width: 0;
|
||||
overflow: visible;
|
||||
z-index: 1982;
|
||||
-webkit-transform: translate3d(0, 0, 0);
|
||||
transform: translate3d(0, 0, 0);
|
||||
}
|
||||
.alertify-notifier .ajs-message {
|
||||
position: relative;
|
||||
width: 260px;
|
||||
max-height: 0;
|
||||
padding: 0;
|
||||
opacity: 0;
|
||||
margin: 0;
|
||||
-webkit-transform: translate3d(0, 0, 0);
|
||||
transform: translate3d(0, 0, 0);
|
||||
-webkit-transition-duration: 250ms;
|
||||
transition-duration: 250ms;
|
||||
-webkit-transition-timing-function: linear;
|
||||
transition-timing-function: linear;
|
||||
}
|
||||
.alertify-notifier .ajs-message.ajs-visible {
|
||||
-webkit-transition-duration: 500ms;
|
||||
transition-duration: 500ms;
|
||||
-webkit-transition-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1.275);
|
||||
transition-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1.275);
|
||||
opacity: 1;
|
||||
max-height: 100%;
|
||||
padding: 15px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
.alertify-notifier .ajs-message.ajs-success {
|
||||
background: rgba(91, 189, 114, 0.95);
|
||||
}
|
||||
.alertify-notifier .ajs-message.ajs-error {
|
||||
background: rgba(217, 92, 92, 0.95);
|
||||
}
|
||||
.alertify-notifier .ajs-message.ajs-warning {
|
||||
background: rgba(252, 248, 215, 0.95);
|
||||
}
|
||||
.alertify-notifier .ajs-message .ajs-close {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
cursor: pointer;
|
||||
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAYAAADED76LAAAABGdBTUEAALGPC/xhBQAAAFBJREFUGBl1j0EKADEIA+ve/P9f9bh1hEihNBfjVCO1v7RKVqJK4h8gM5cAPR42AkQEpSXPwMTyoi13n5N9YqJehm3Fnr7nL1D0ZEbD5OubGyC7a9gx+9eNAAAAAElFTkSuQmCC);
|
||||
background-repeat: no-repeat;
|
||||
background-position: center center;
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
border-top-left-radius: 2px;
|
||||
}
|
||||
.alertify-notifier.ajs-top {
|
||||
top: 10px;
|
||||
}
|
||||
.alertify-notifier.ajs-bottom {
|
||||
bottom: 10px;
|
||||
}
|
||||
.alertify-notifier.ajs-right {
|
||||
left: 10px;
|
||||
}
|
||||
.alertify-notifier.ajs-right .ajs-message {
|
||||
left: -320px;
|
||||
}
|
||||
.alertify-notifier.ajs-right .ajs-message.ajs-visible {
|
||||
left: 290px;
|
||||
}
|
||||
.alertify-notifier.ajs-left {
|
||||
right: 10px;
|
||||
}
|
||||
.alertify-notifier.ajs-left .ajs-message {
|
||||
right: -300px;
|
||||
}
|
||||
.alertify-notifier.ajs-left .ajs-message.ajs-visible {
|
||||
right: 0;
|
||||
}
|
||||
.alertify-notifier.ajs-center {
|
||||
right: 50%;
|
||||
}
|
||||
.alertify-notifier.ajs-center .ajs-message {
|
||||
-webkit-transform: translateX(50%);
|
||||
transform: translateX(50%);
|
||||
}
|
||||
.alertify-notifier.ajs-center .ajs-message.ajs-visible {
|
||||
right: 50%;
|
||||
-webkit-transition-timing-function: cubic-bezier(0.57, 0.43, 0.1, 0.65);
|
||||
transition-timing-function: cubic-bezier(0.57, 0.43, 0.1, 0.65);
|
||||
}
|
||||
.alertify-notifier.ajs-center.ajs-top .ajs-message {
|
||||
top: -300px;
|
||||
}
|
||||
.alertify-notifier.ajs-center.ajs-top .ajs-message.ajs-visible {
|
||||
top: 0;
|
||||
}
|
||||
.alertify-notifier.ajs-center.ajs-bottom .ajs-message {
|
||||
bottom: -300px;
|
||||
}
|
||||
.alertify-notifier.ajs-center.ajs-bottom .ajs-message.ajs-visible {
|
||||
bottom: 0;
|
||||
}
|
||||
.ajs-no-transition.alertify .ajs-dimmer,
|
||||
.ajs-no-transition.alertify .ajs-modal,
|
||||
.ajs-no-transition.alertify .ajs-dialog {
|
||||
-webkit-transition: none!important;
|
||||
transition: none!important;
|
||||
-webkit-animation: none!important;
|
||||
animation: none!important;
|
||||
}
|
||||
.ajs-no-transition.alertify-notifier .ajs-message {
|
||||
-webkit-transition: none!important;
|
||||
transition: none!important;
|
||||
-webkit-animation: none!important;
|
||||
animation: none!important;
|
||||
}
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.alertify .ajs-dimmer,
|
||||
.alertify .ajs-modal,
|
||||
.alertify .ajs-dialog {
|
||||
-webkit-transition: none!important;
|
||||
transition: none!important;
|
||||
-webkit-animation: none!important;
|
||||
animation: none!important;
|
||||
}
|
||||
.alertify-notifier .ajs-message {
|
||||
-webkit-transition: none!important;
|
||||
transition: none!important;
|
||||
-webkit-animation: none!important;
|
||||
animation: none!important;
|
||||
}
|
||||
}
|
6
static/lib/alertify/css/alertify.rtl.min.css
vendored
Normal file
61
static/lib/alertify/css/themes/bootstrap.css
vendored
Normal file
|
@ -0,0 +1,61 @@
|
|||
/**
|
||||
* alertifyjs 1.13.1 http://alertifyjs.com
|
||||
* AlertifyJS is a javascript framework for developing pretty browser dialogs and notifications.
|
||||
* Copyright 2019 Mohammad Younes <Mohammad@alertifyjs.com> (http://alertifyjs.com)
|
||||
* Licensed under GPL 3 <https://opensource.org/licenses/gpl-3.0>*/
|
||||
.alertify .ajs-dimmer {
|
||||
background-color: #000;
|
||||
opacity: .5;
|
||||
}
|
||||
.alertify .ajs-dialog {
|
||||
max-width: 600px;
|
||||
min-height: 122px;
|
||||
background-color: #fff;
|
||||
border: 1px solid rgba(0, 0, 0, 0.2);
|
||||
-webkit-box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5);
|
||||
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5);
|
||||
border-radius: 6px;
|
||||
}
|
||||
.alertify .ajs-header {
|
||||
color: #333;
|
||||
border-bottom: 1px solid #e5e5e5;
|
||||
border-radius: 6px 6px 0 0;
|
||||
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||
font-size: 18px;
|
||||
}
|
||||
.alertify .ajs-body {
|
||||
font-family: 'Roboto', sans-serif;
|
||||
color: black;
|
||||
}
|
||||
.alertify.ajs-resizable .ajs-content,
|
||||
.alertify.ajs-maximized:not(.ajs-resizable) .ajs-content {
|
||||
top: 58px;
|
||||
bottom: 68px;
|
||||
}
|
||||
.alertify .ajs-footer {
|
||||
background-color: #fff;
|
||||
padding: 15px;
|
||||
border-top: 1px solid #e5e5e5;
|
||||
border-radius: 0 0 6px 6px;
|
||||
}
|
||||
.alertify-notifier .ajs-message {
|
||||
background: rgba(255, 255, 255, 0.95);
|
||||
color: #000;
|
||||
text-align: center;
|
||||
border: solid 1px #ddd;
|
||||
border-radius: 2px;
|
||||
}
|
||||
.alertify-notifier .ajs-message.ajs-success {
|
||||
color: #fff;
|
||||
background: rgba(91, 189, 114, 0.95);
|
||||
text-shadow: -1px -1px 0 rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
.alertify-notifier .ajs-message.ajs-error {
|
||||
color: #fff;
|
||||
background: rgba(217, 92, 92, 0.95);
|
||||
text-shadow: -1px -1px 0 rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
.alertify-notifier .ajs-message.ajs-warning {
|
||||
background: rgba(252, 248, 215, 0.95);
|
||||
border-color: #999;
|
||||
}
|
6
static/lib/alertify/css/themes/bootstrap.min.css
vendored
Normal file
|
@ -0,0 +1,6 @@
|
|||
/**
|
||||
* alertifyjs 1.13.1 http://alertifyjs.com
|
||||
* AlertifyJS is a javascript framework for developing pretty browser dialogs and notifications.
|
||||
* Copyright 2019 Mohammad Younes <Mohammad@alertifyjs.com> (http://alertifyjs.com)
|
||||
* Licensed under GPL 3 <https://opensource.org/licenses/gpl-3.0>*/
|
||||
.alertify .ajs-dimmer{background-color:#000;opacity:.5}.alertify .ajs-dialog{max-width:600px;min-height:122px;background-color:#fff;border:1px solid rgba(0,0,0,.2);-webkit-box-shadow:0 5px 15px rgba(0,0,0,.5);box-shadow:0 5px 15px rgba(0,0,0,.5);border-radius:6px}.alertify .ajs-header{color:#333;border-bottom:1px solid #e5e5e5;border-radius:6px 6px 0 0;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:18px}.alertify .ajs-body{font-family:Roboto,sans-serif;color:#000}.alertify.ajs-maximized:not(.ajs-resizable) .ajs-content,.alertify.ajs-resizable .ajs-content{top:58px;bottom:68px}.alertify .ajs-footer{background-color:#fff;padding:15px;border-top:1px solid #e5e5e5;border-radius:0 0 6px 6px}.alertify-notifier .ajs-message{background:rgba(255,255,255,.95);color:#000;text-align:center;border:solid 1px #ddd;border-radius:2px}.alertify-notifier .ajs-message.ajs-success{color:#fff;background:rgba(91,189,114,.95);text-shadow:-1px -1px 0 rgba(0,0,0,.5)}.alertify-notifier .ajs-message.ajs-error{color:#fff;background:rgba(217,92,92,.95);text-shadow:-1px -1px 0 rgba(0,0,0,.5)}.alertify-notifier .ajs-message.ajs-warning{background:rgba(252,248,215,.95);border-color:#999}
|
61
static/lib/alertify/css/themes/bootstrap.rtl.css
vendored
Normal file
|
@ -0,0 +1,61 @@
|
|||
/**
|
||||
* alertifyjs 1.13.1 http://alertifyjs.com
|
||||
* AlertifyJS is a javascript framework for developing pretty browser dialogs and notifications.
|
||||
* Copyright 2019 Mohammad Younes <Mohammad@alertifyjs.com> (http://alertifyjs.com)
|
||||
* Licensed under GPL 3 <https://opensource.org/licenses/gpl-3.0>*/
|
||||
.alertify .ajs-dimmer {
|
||||
background-color: #000;
|
||||
opacity: .5;
|
||||
}
|
||||
.alertify .ajs-dialog {
|
||||
max-width: 600px;
|
||||
min-height: 122px;
|
||||
background-color: #fff;
|
||||
border: 1px solid rgba(0, 0, 0, 0.2);
|
||||
-webkit-box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5);
|
||||
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5);
|
||||
border-radius: 6px;
|
||||
}
|
||||
.alertify .ajs-header {
|
||||
color: #333;
|
||||
border-bottom: 1px solid #e5e5e5;
|
||||
border-radius: 6px 6px 0 0;
|
||||
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||
font-size: 18px;
|
||||
}
|
||||
.alertify .ajs-body {
|
||||
font-family: 'Roboto', sans-serif;
|
||||
color: black;
|
||||
}
|
||||
.alertify.ajs-resizable .ajs-content,
|
||||
.alertify.ajs-maximized:not(.ajs-resizable) .ajs-content {
|
||||
top: 58px;
|
||||
bottom: 68px;
|
||||
}
|
||||
.alertify .ajs-footer {
|
||||
background-color: #fff;
|
||||
padding: 15px;
|
||||
border-top: 1px solid #e5e5e5;
|
||||
border-radius: 0 0 6px 6px;
|
||||
}
|
||||
.alertify-notifier .ajs-message {
|
||||
background: rgba(255, 255, 255, 0.95);
|
||||
color: #000;
|
||||
text-align: center;
|
||||
border: solid 1px #ddd;
|
||||
border-radius: 2px;
|
||||
}
|
||||
.alertify-notifier .ajs-message.ajs-success {
|
||||
color: #fff;
|
||||
background: rgba(91, 189, 114, 0.95);
|
||||
text-shadow: 1px -1px 0 rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
.alertify-notifier .ajs-message.ajs-error {
|
||||
color: #fff;
|
||||
background: rgba(217, 92, 92, 0.95);
|
||||
text-shadow: 1px -1px 0 rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
.alertify-notifier .ajs-message.ajs-warning {
|
||||
background: rgba(252, 248, 215, 0.95);
|
||||
border-color: #999;
|
||||
}
|
6
static/lib/alertify/css/themes/bootstrap.rtl.min.css
vendored
Normal file
|
@ -0,0 +1,6 @@
|
|||
/**
|
||||
* alertifyjs 1.13.1 http://alertifyjs.com
|
||||
* AlertifyJS is a javascript framework for developing pretty browser dialogs and notifications.
|
||||
* Copyright 2019 Mohammad Younes <Mohammad@alertifyjs.com> (http://alertifyjs.com)
|
||||
* Licensed under GPL 3 <https://opensource.org/licenses/gpl-3.0>*/
|
||||
.alertify .ajs-dimmer{background-color:#000;opacity:.5}.alertify .ajs-dialog{max-width:600px;min-height:122px;background-color:#fff;border:1px solid rgba(0,0,0,.2);-webkit-box-shadow:0 5px 15px rgba(0,0,0,.5);box-shadow:0 5px 15px rgba(0,0,0,.5);border-radius:6px}.alertify .ajs-header{color:#333;border-bottom:1px solid #e5e5e5;border-radius:6px 6px 0 0;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:18px}.alertify .ajs-body{font-family:Roboto,sans-serif;color:#000}.alertify.ajs-maximized:not(.ajs-resizable) .ajs-content,.alertify.ajs-resizable .ajs-content{top:58px;bottom:68px}.alertify .ajs-footer{background-color:#fff;padding:15px;border-top:1px solid #e5e5e5;border-radius:0 0 6px 6px}.alertify-notifier .ajs-message{background:rgba(255,255,255,.95);color:#000;text-align:center;border:solid 1px #ddd;border-radius:2px}.alertify-notifier .ajs-message.ajs-success{color:#fff;background:rgba(91,189,114,.95);text-shadow:1px -1px 0 rgba(0,0,0,.5)}.alertify-notifier .ajs-message.ajs-error{color:#fff;background:rgba(217,92,92,.95);text-shadow:1px -1px 0 rgba(0,0,0,.5)}.alertify-notifier .ajs-message.ajs-warning{background:rgba(252,248,215,.95);border-color:#999}
|
69
static/lib/alertify/css/themes/default.css
Normal file
|
@ -0,0 +1,69 @@
|
|||
/**
|
||||
* alertifyjs 1.13.1 http://alertifyjs.com
|
||||
* AlertifyJS is a javascript framework for developing pretty browser dialogs and notifications.
|
||||
* Copyright 2019 Mohammad Younes <Mohammad@alertifyjs.com> (http://alertifyjs.com)
|
||||
* Licensed under GPL 3 <https://opensource.org/licenses/gpl-3.0>*/
|
||||
.alertify .ajs-dialog {
|
||||
background-color: white;
|
||||
-webkit-box-shadow: 0px 15px 20px 0px rgba(0, 0, 0, 0.25);
|
||||
box-shadow: 0px 15px 20px 0px rgba(0, 0, 0, 0.25);
|
||||
border-radius: 2px;
|
||||
}
|
||||
.alertify .ajs-header {
|
||||
color: black;
|
||||
font-weight: bold;
|
||||
background: #fafafa;
|
||||
border-bottom: #eee 1px solid;
|
||||
border-radius: 2px 2px 0 0;
|
||||
}
|
||||
.alertify .ajs-body {
|
||||
color: black;
|
||||
}
|
||||
.alertify .ajs-body .ajs-content .ajs-input {
|
||||
display: block;
|
||||
width: 100%;
|
||||
padding: 8px;
|
||||
margin: 4px;
|
||||
border-radius: 2px;
|
||||
border: 1px solid #CCC;
|
||||
}
|
||||
.alertify .ajs-body .ajs-content p {
|
||||
margin: 0;
|
||||
}
|
||||
.alertify .ajs-footer {
|
||||
background: #fbfbfb;
|
||||
border-top: #eee 1px solid;
|
||||
border-radius: 0 0 2px 2px;
|
||||
}
|
||||
.alertify .ajs-footer .ajs-buttons .ajs-button {
|
||||
background-color: transparent;
|
||||
color: #000;
|
||||
border: 0;
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
.alertify .ajs-footer .ajs-buttons .ajs-button.ajs-ok {
|
||||
color: #3593D2;
|
||||
}
|
||||
.alertify-notifier .ajs-message {
|
||||
background: rgba(255, 255, 255, 0.95);
|
||||
color: #000;
|
||||
text-align: center;
|
||||
border: solid 1px #ddd;
|
||||
border-radius: 2px;
|
||||
}
|
||||
.alertify-notifier .ajs-message.ajs-success {
|
||||
color: #fff;
|
||||
background: rgba(91, 189, 114, 0.95);
|
||||
text-shadow: -1px -1px 0 rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
.alertify-notifier .ajs-message.ajs-error {
|
||||
color: #fff;
|
||||
background: rgba(217, 92, 92, 0.95);
|
||||
text-shadow: -1px -1px 0 rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
.alertify-notifier .ajs-message.ajs-warning {
|
||||
background: rgba(252, 248, 215, 0.95);
|
||||
border-color: #999;
|
||||
}
|
6
static/lib/alertify/css/themes/default.min.css
vendored
Normal file
|
@ -0,0 +1,6 @@
|
|||
/**
|
||||
* alertifyjs 1.13.1 http://alertifyjs.com
|
||||
* AlertifyJS is a javascript framework for developing pretty browser dialogs and notifications.
|
||||
* Copyright 2019 Mohammad Younes <Mohammad@alertifyjs.com> (http://alertifyjs.com)
|
||||
* Licensed under GPL 3 <https://opensource.org/licenses/gpl-3.0>*/
|
||||
.alertify .ajs-dialog{background-color:#fff;-webkit-box-shadow:0 15px 20px 0 rgba(0,0,0,.25);box-shadow:0 15px 20px 0 rgba(0,0,0,.25);border-radius:2px}.alertify .ajs-header{color:#000;font-weight:700;background:#fafafa;border-bottom:#eee 1px solid;border-radius:2px 2px 0 0}.alertify .ajs-body{color:#000}.alertify .ajs-body .ajs-content .ajs-input{display:block;width:100%;padding:8px;margin:4px;border-radius:2px;border:1px solid #ccc}.alertify .ajs-body .ajs-content p{margin:0}.alertify .ajs-footer{background:#fbfbfb;border-top:#eee 1px solid;border-radius:0 0 2px 2px}.alertify .ajs-footer .ajs-buttons .ajs-button{background-color:transparent;color:#000;border:0;font-size:14px;font-weight:700;text-transform:uppercase}.alertify .ajs-footer .ajs-buttons .ajs-button.ajs-ok{color:#3593d2}.alertify-notifier .ajs-message{background:rgba(255,255,255,.95);color:#000;text-align:center;border:solid 1px #ddd;border-radius:2px}.alertify-notifier .ajs-message.ajs-success{color:#fff;background:rgba(91,189,114,.95);text-shadow:-1px -1px 0 rgba(0,0,0,.5)}.alertify-notifier .ajs-message.ajs-error{color:#fff;background:rgba(217,92,92,.95);text-shadow:-1px -1px 0 rgba(0,0,0,.5)}.alertify-notifier .ajs-message.ajs-warning{background:rgba(252,248,215,.95);border-color:#999}
|
69
static/lib/alertify/css/themes/default.rtl.css
Normal file
|
@ -0,0 +1,69 @@
|
|||
/**
|
||||
* alertifyjs 1.13.1 http://alertifyjs.com
|
||||
* AlertifyJS is a javascript framework for developing pretty browser dialogs and notifications.
|
||||
* Copyright 2019 Mohammad Younes <Mohammad@alertifyjs.com> (http://alertifyjs.com)
|
||||
* Licensed under GPL 3 <https://opensource.org/licenses/gpl-3.0>*/
|
||||
.alertify .ajs-dialog {
|
||||
background-color: white;
|
||||
-webkit-box-shadow: 0px 15px 20px 0px rgba(0, 0, 0, 0.25);
|
||||
box-shadow: 0px 15px 20px 0px rgba(0, 0, 0, 0.25);
|
||||
border-radius: 2px;
|
||||
}
|
||||
.alertify .ajs-header {
|
||||
color: black;
|
||||
font-weight: bold;
|
||||
background: #fafafa;
|
||||
border-bottom: #eee 1px solid;
|
||||
border-radius: 2px 2px 0 0;
|
||||
}
|
||||
.alertify .ajs-body {
|
||||
color: black;
|
||||
}
|
||||
.alertify .ajs-body .ajs-content .ajs-input {
|
||||
display: block;
|
||||
width: 100%;
|
||||
padding: 8px;
|
||||
margin: 4px;
|
||||
border-radius: 2px;
|
||||
border: 1px solid #CCC;
|
||||
}
|
||||
.alertify .ajs-body .ajs-content p {
|
||||
margin: 0;
|
||||
}
|
||||
.alertify .ajs-footer {
|
||||
background: #fbfbfb;
|
||||
border-top: #eee 1px solid;
|
||||
border-radius: 0 0 2px 2px;
|
||||
}
|
||||
.alertify .ajs-footer .ajs-buttons .ajs-button {
|
||||
background-color: transparent;
|
||||
color: #000;
|
||||
border: 0;
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
.alertify .ajs-footer .ajs-buttons .ajs-button.ajs-ok {
|
||||
color: #3593D2;
|
||||
}
|
||||
.alertify-notifier .ajs-message {
|
||||
background: rgba(255, 255, 255, 0.95);
|
||||
color: #000;
|
||||
text-align: center;
|
||||
border: solid 1px #ddd;
|
||||
border-radius: 2px;
|
||||
}
|
||||
.alertify-notifier .ajs-message.ajs-success {
|
||||
color: #fff;
|
||||
background: rgba(91, 189, 114, 0.95);
|
||||
text-shadow: 1px -1px 0 rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
.alertify-notifier .ajs-message.ajs-error {
|
||||
color: #fff;
|
||||
background: rgba(217, 92, 92, 0.95);
|
||||
text-shadow: 1px -1px 0 rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
.alertify-notifier .ajs-message.ajs-warning {
|
||||
background: rgba(252, 248, 215, 0.95);
|
||||
border-color: #999;
|
||||
}
|
6
static/lib/alertify/css/themes/default.rtl.min.css
vendored
Normal file
|
@ -0,0 +1,6 @@
|
|||
/**
|
||||
* alertifyjs 1.13.1 http://alertifyjs.com
|
||||
* AlertifyJS is a javascript framework for developing pretty browser dialogs and notifications.
|
||||
* Copyright 2019 Mohammad Younes <Mohammad@alertifyjs.com> (http://alertifyjs.com)
|
||||
* Licensed under GPL 3 <https://opensource.org/licenses/gpl-3.0>*/
|
||||
.alertify .ajs-dialog{background-color:#fff;-webkit-box-shadow:0 15px 20px 0 rgba(0,0,0,.25);box-shadow:0 15px 20px 0 rgba(0,0,0,.25);border-radius:2px}.alertify .ajs-header{color:#000;font-weight:700;background:#fafafa;border-bottom:#eee 1px solid;border-radius:2px 2px 0 0}.alertify .ajs-body{color:#000}.alertify .ajs-body .ajs-content .ajs-input{display:block;width:100%;padding:8px;margin:4px;border-radius:2px;border:1px solid #ccc}.alertify .ajs-body .ajs-content p{margin:0}.alertify .ajs-footer{background:#fbfbfb;border-top:#eee 1px solid;border-radius:0 0 2px 2px}.alertify .ajs-footer .ajs-buttons .ajs-button{background-color:transparent;color:#000;border:0;font-size:14px;font-weight:700;text-transform:uppercase}.alertify .ajs-footer .ajs-buttons .ajs-button.ajs-ok{color:#3593d2}.alertify-notifier .ajs-message{background:rgba(255,255,255,.95);color:#000;text-align:center;border:solid 1px #ddd;border-radius:2px}.alertify-notifier .ajs-message.ajs-success{color:#fff;background:rgba(91,189,114,.95);text-shadow:1px -1px 0 rgba(0,0,0,.5)}.alertify-notifier .ajs-message.ajs-error{color:#fff;background:rgba(217,92,92,.95);text-shadow:1px -1px 0 rgba(0,0,0,.5)}.alertify-notifier .ajs-message.ajs-warning{background:rgba(252,248,215,.95);border-color:#999}
|
89
static/lib/alertify/css/themes/semantic.css
Normal file
|
@ -0,0 +1,89 @@
|
|||
/**
|
||||
* alertifyjs 1.13.1 http://alertifyjs.com
|
||||
* AlertifyJS is a javascript framework for developing pretty browser dialogs and notifications.
|
||||
* Copyright 2019 Mohammad Younes <Mohammad@alertifyjs.com> (http://alertifyjs.com)
|
||||
* Licensed under GPL 3 <https://opensource.org/licenses/gpl-3.0>*/
|
||||
.alertify .ajs-dimmer {
|
||||
background-color: rgba(0, 0, 0, 0.85);
|
||||
opacity: 1;
|
||||
}
|
||||
.alertify .ajs-dialog {
|
||||
max-width: 50%;
|
||||
min-height: 137px;
|
||||
background-color: #F4F4F4;
|
||||
border: 1px solid #DDD;
|
||||
-webkit-box-shadow: none;
|
||||
box-shadow: none;
|
||||
border-radius: 5px;
|
||||
}
|
||||
.alertify .ajs-header {
|
||||
padding: 1.5rem 2rem;
|
||||
border-bottom: none;
|
||||
border-radius: 5px 5px 0 0;
|
||||
color: #555;
|
||||
background-color: #fff;
|
||||
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||
font-size: 1.6em;
|
||||
font-weight: 700;
|
||||
}
|
||||
.alertify .ajs-body {
|
||||
font-family: 'Roboto', sans-serif;
|
||||
color: #555;
|
||||
}
|
||||
.alertify .ajs-body .ajs-content .ajs-input {
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
padding: .65em 1em;
|
||||
font-size: 1em;
|
||||
background-color: #FFF;
|
||||
border: 1px solid rgba(0, 0, 0, 0.15);
|
||||
outline: 0;
|
||||
color: rgba(0, 0, 0, 0.7);
|
||||
border-radius: .3125em;
|
||||
-webkit-transition: background-color 0.3s ease-out, border-color 0.2s ease, -webkit-box-shadow 0.2s ease;
|
||||
transition: background-color 0.3s ease-out, border-color 0.2s ease, -webkit-box-shadow 0.2s ease;
|
||||
transition: background-color 0.3s ease-out, box-shadow 0.2s ease, border-color 0.2s ease;
|
||||
transition: background-color 0.3s ease-out, box-shadow 0.2s ease, border-color 0.2s ease, -webkit-box-shadow 0.2s ease;
|
||||
-webkit-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.alertify .ajs-body .ajs-content .ajs-input:active {
|
||||
border-color: rgba(0, 0, 0, 0.3);
|
||||
background-color: #FAFAFA;
|
||||
}
|
||||
.alertify .ajs-body .ajs-content .ajs-input:focus {
|
||||
border-color: rgba(0, 0, 0, 0.2);
|
||||
color: rgba(0, 0, 0, 0.85);
|
||||
}
|
||||
.alertify.ajs-resizable .ajs-content,
|
||||
.alertify.ajs-maximized:not(.ajs-resizable) .ajs-content {
|
||||
top: 64px;
|
||||
bottom: 74px;
|
||||
}
|
||||
.alertify .ajs-footer {
|
||||
background-color: #fff;
|
||||
padding: 1rem 2rem;
|
||||
border-top: none;
|
||||
border-radius: 0 0 5px 5px;
|
||||
}
|
||||
.alertify-notifier .ajs-message {
|
||||
background: rgba(255, 255, 255, 0.95);
|
||||
color: #000;
|
||||
text-align: center;
|
||||
border: solid 1px #ddd;
|
||||
border-radius: 2px;
|
||||
}
|
||||
.alertify-notifier .ajs-message.ajs-success {
|
||||
color: #fff;
|
||||
background: rgba(91, 189, 114, 0.95);
|
||||
text-shadow: -1px -1px 0 rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
.alertify-notifier .ajs-message.ajs-error {
|
||||
color: #fff;
|
||||
background: rgba(217, 92, 92, 0.95);
|
||||
text-shadow: -1px -1px 0 rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
.alertify-notifier .ajs-message.ajs-warning {
|
||||
background: rgba(252, 248, 215, 0.95);
|
||||
border-color: #999;
|
||||
}
|
6
static/lib/alertify/css/themes/semantic.min.css
vendored
Normal file
|
@ -0,0 +1,6 @@
|
|||
/**
|
||||
* alertifyjs 1.13.1 http://alertifyjs.com
|
||||
* AlertifyJS is a javascript framework for developing pretty browser dialogs and notifications.
|
||||
* Copyright 2019 Mohammad Younes <Mohammad@alertifyjs.com> (http://alertifyjs.com)
|
||||
* Licensed under GPL 3 <https://opensource.org/licenses/gpl-3.0>*/
|
||||
.alertify .ajs-dimmer{background-color:rgba(0,0,0,.85);opacity:1}.alertify .ajs-dialog{max-width:50%;min-height:137px;background-color:#f4f4f4;border:1px solid #ddd;-webkit-box-shadow:none;box-shadow:none;border-radius:5px}.alertify .ajs-header{padding:1.5rem 2rem;border-bottom:none;border-radius:5px 5px 0 0;color:#555;background-color:#fff;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:1.6em;font-weight:700}.alertify .ajs-body{font-family:Roboto,sans-serif;color:#555}.alertify .ajs-body .ajs-content .ajs-input{width:100%;margin:0;padding:.65em 1em;font-size:1em;background-color:#fff;border:1px solid rgba(0,0,0,.15);outline:0;color:rgba(0,0,0,.7);border-radius:.3125em;-webkit-transition:background-color .3s ease-out,border-color .2s ease,-webkit-box-shadow .2s ease;transition:background-color .3s ease-out,border-color .2s ease,-webkit-box-shadow .2s ease;transition:background-color .3s ease-out,box-shadow .2s ease,border-color .2s ease;transition:background-color .3s ease-out,box-shadow .2s ease,border-color .2s ease,-webkit-box-shadow .2s ease;-webkit-box-sizing:border-box;box-sizing:border-box}.alertify .ajs-body .ajs-content .ajs-input:active{border-color:rgba(0,0,0,.3);background-color:#fafafa}.alertify .ajs-body .ajs-content .ajs-input:focus{border-color:rgba(0,0,0,.2);color:rgba(0,0,0,.85)}.alertify.ajs-maximized:not(.ajs-resizable) .ajs-content,.alertify.ajs-resizable .ajs-content{top:64px;bottom:74px}.alertify .ajs-footer{background-color:#fff;padding:1rem 2rem;border-top:none;border-radius:0 0 5px 5px}.alertify-notifier .ajs-message{background:rgba(255,255,255,.95);color:#000;text-align:center;border:solid 1px #ddd;border-radius:2px}.alertify-notifier .ajs-message.ajs-success{color:#fff;background:rgba(91,189,114,.95);text-shadow:-1px -1px 0 rgba(0,0,0,.5)}.alertify-notifier .ajs-message.ajs-error{color:#fff;background:rgba(217,92,92,.95);text-shadow:-1px -1px 0 rgba(0,0,0,.5)}.alertify-notifier .ajs-message.ajs-warning{background:rgba(252,248,215,.95);border-color:#999}
|
89
static/lib/alertify/css/themes/semantic.rtl.css
Normal file
|
@ -0,0 +1,89 @@
|
|||
/**
|
||||
* alertifyjs 1.13.1 http://alertifyjs.com
|
||||
* AlertifyJS is a javascript framework for developing pretty browser dialogs and notifications.
|
||||
* Copyright 2019 Mohammad Younes <Mohammad@alertifyjs.com> (http://alertifyjs.com)
|
||||
* Licensed under GPL 3 <https://opensource.org/licenses/gpl-3.0>*/
|
||||
.alertify .ajs-dimmer {
|
||||
background-color: rgba(0, 0, 0, 0.85);
|
||||
opacity: 1;
|
||||
}
|
||||
.alertify .ajs-dialog {
|
||||
max-width: 50%;
|
||||
min-height: 137px;
|
||||
background-color: #F4F4F4;
|
||||
border: 1px solid #DDD;
|
||||
-webkit-box-shadow: none;
|
||||
box-shadow: none;
|
||||
border-radius: 5px;
|
||||
}
|
||||
.alertify .ajs-header {
|
||||
padding: 1.5rem 2rem;
|
||||
border-bottom: none;
|
||||
border-radius: 5px 5px 0 0;
|
||||
color: #555;
|
||||
background-color: #fff;
|
||||
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||
font-size: 1.6em;
|
||||
font-weight: 700;
|
||||
}
|
||||
.alertify .ajs-body {
|
||||
font-family: 'Roboto', sans-serif;
|
||||
color: #555;
|
||||
}
|
||||
.alertify .ajs-body .ajs-content .ajs-input {
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
padding: .65em 1em;
|
||||
font-size: 1em;
|
||||
background-color: #FFF;
|
||||
border: 1px solid rgba(0, 0, 0, 0.15);
|
||||
outline: 0;
|
||||
color: rgba(0, 0, 0, 0.7);
|
||||
border-radius: .3125em;
|
||||
-webkit-transition: background-color 0.3s ease-out, border-color 0.2s ease, -webkit-box-shadow 0.2s ease;
|
||||
transition: background-color 0.3s ease-out, border-color 0.2s ease, -webkit-box-shadow 0.2s ease;
|
||||
transition: background-color 0.3s ease-out, box-shadow 0.2s ease, border-color 0.2s ease;
|
||||
transition: background-color 0.3s ease-out, box-shadow 0.2s ease, border-color 0.2s ease, -webkit-box-shadow 0.2s ease;
|
||||
-webkit-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.alertify .ajs-body .ajs-content .ajs-input:active {
|
||||
border-color: rgba(0, 0, 0, 0.3);
|
||||
background-color: #FAFAFA;
|
||||
}
|
||||
.alertify .ajs-body .ajs-content .ajs-input:focus {
|
||||
border-color: rgba(0, 0, 0, 0.2);
|
||||
color: rgba(0, 0, 0, 0.85);
|
||||
}
|
||||
.alertify.ajs-resizable .ajs-content,
|
||||
.alertify.ajs-maximized:not(.ajs-resizable) .ajs-content {
|
||||
top: 64px;
|
||||
bottom: 74px;
|
||||
}
|
||||
.alertify .ajs-footer {
|
||||
background-color: #fff;
|
||||
padding: 1rem 2rem;
|
||||
border-top: none;
|
||||
border-radius: 0 0 5px 5px;
|
||||
}
|
||||
.alertify-notifier .ajs-message {
|
||||
background: rgba(255, 255, 255, 0.95);
|
||||
color: #000;
|
||||
text-align: center;
|
||||
border: solid 1px #ddd;
|
||||
border-radius: 2px;
|
||||
}
|
||||
.alertify-notifier .ajs-message.ajs-success {
|
||||
color: #fff;
|
||||
background: rgba(91, 189, 114, 0.95);
|
||||
text-shadow: 1px -1px 0 rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
.alertify-notifier .ajs-message.ajs-error {
|
||||
color: #fff;
|
||||
background: rgba(217, 92, 92, 0.95);
|
||||
text-shadow: 1px -1px 0 rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
.alertify-notifier .ajs-message.ajs-warning {
|
||||
background: rgba(252, 248, 215, 0.95);
|
||||
border-color: #999;
|
||||
}
|
6
static/lib/alertify/css/themes/semantic.rtl.min.css
vendored
Normal file
|
@ -0,0 +1,6 @@
|
|||
/**
|
||||
* alertifyjs 1.13.1 http://alertifyjs.com
|
||||
* AlertifyJS is a javascript framework for developing pretty browser dialogs and notifications.
|
||||
* Copyright 2019 Mohammad Younes <Mohammad@alertifyjs.com> (http://alertifyjs.com)
|
||||
* Licensed under GPL 3 <https://opensource.org/licenses/gpl-3.0>*/
|
||||
.alertify .ajs-dimmer{background-color:rgba(0,0,0,.85);opacity:1}.alertify .ajs-dialog{max-width:50%;min-height:137px;background-color:#f4f4f4;border:1px solid #ddd;-webkit-box-shadow:none;box-shadow:none;border-radius:5px}.alertify .ajs-header{padding:1.5rem 2rem;border-bottom:none;border-radius:5px 5px 0 0;color:#555;background-color:#fff;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:1.6em;font-weight:700}.alertify .ajs-body{font-family:Roboto,sans-serif;color:#555}.alertify .ajs-body .ajs-content .ajs-input{width:100%;margin:0;padding:.65em 1em;font-size:1em;background-color:#fff;border:1px solid rgba(0,0,0,.15);outline:0;color:rgba(0,0,0,.7);border-radius:.3125em;-webkit-transition:background-color .3s ease-out,border-color .2s ease,-webkit-box-shadow .2s ease;transition:background-color .3s ease-out,border-color .2s ease,-webkit-box-shadow .2s ease;transition:background-color .3s ease-out,box-shadow .2s ease,border-color .2s ease;transition:background-color .3s ease-out,box-shadow .2s ease,border-color .2s ease,-webkit-box-shadow .2s ease;-webkit-box-sizing:border-box;box-sizing:border-box}.alertify .ajs-body .ajs-content .ajs-input:active{border-color:rgba(0,0,0,.3);background-color:#fafafa}.alertify .ajs-body .ajs-content .ajs-input:focus{border-color:rgba(0,0,0,.2);color:rgba(0,0,0,.85)}.alertify.ajs-maximized:not(.ajs-resizable) .ajs-content,.alertify.ajs-resizable .ajs-content{top:64px;bottom:74px}.alertify .ajs-footer{background-color:#fff;padding:1rem 2rem;border-top:none;border-radius:0 0 5px 5px}.alertify-notifier .ajs-message{background:rgba(255,255,255,.95);color:#000;text-align:center;border:solid 1px #ddd;border-radius:2px}.alertify-notifier .ajs-message.ajs-success{color:#fff;background:rgba(91,189,114,.95);text-shadow:1px -1px 0 rgba(0,0,0,.5)}.alertify-notifier .ajs-message.ajs-error{color:#fff;background:rgba(217,92,92,.95);text-shadow:1px -1px 0 rgba(0,0,0,.5)}.alertify-notifier .ajs-message.ajs-warning{background:rgba(252,248,215,.95);border-color:#999}
|
Before Width: | Height: | Size: 106 KiB After Width: | Height: | Size: 106 KiB |
|
@ -1,8 +1,10 @@
|
|||
body{
|
||||
body {
|
||||
margin-top: 4em;
|
||||
}
|
||||
|
||||
div.panel-heading, li.list-group-item, a {
|
||||
div.panel-heading,
|
||||
li.list-group-item,
|
||||
a {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
|
@ -19,7 +21,7 @@ div.panel-heading, li.list-group-item, a {
|
|||
}
|
||||
|
||||
.checkable:before {
|
||||
content: '\2713';
|
||||
content: "\2713";
|
||||
margin-right: 0.2em;
|
||||
font-style: italic;
|
||||
color: #999;
|
||||
|
@ -43,12 +45,28 @@ div.panel-heading, li.list-group-item, a {
|
|||
font-size: 1.5em;
|
||||
}
|
||||
|
||||
.add_thing_label, #edit_thing_label {
|
||||
.add_thing_label,
|
||||
#edit_thing_label {
|
||||
width: 80%;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.add_thing_nb, #edit_thing_nb {
|
||||
.add_thing_nb,
|
||||
#edit_thing_nb {
|
||||
width: 18%;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
/** Alertify **/
|
||||
.alertify-notifier .ajs-message.ajs-info {
|
||||
background: rgba(66, 215, 252, 0.95);
|
||||
}
|
||||
|
||||
.alertify .ajs-header,
|
||||
.alertify .ajs-footer {
|
||||
background-color: #4e5d6c;
|
||||
}
|
||||
|
||||
.alertify .ajs-dialog {
|
||||
background-color: #485563;
|
||||
}
|
1579
static/main.js
Normal file
657
static/mysc_objects.js
Normal file
|
@ -0,0 +1,657 @@
|
|||
function SCaseList() {
|
||||
lastChange = 0;
|
||||
|
||||
this.importExampleData = function () {
|
||||
var exampleData = {
|
||||
Vacances: {
|
||||
Papier: {
|
||||
color: "#f00",
|
||||
things: [
|
||||
{ label: _("White paper"), nb: 1 },
|
||||
{ label: _("Pen"), nb: 3 },
|
||||
{ label: _("ID card/passport"), nb: 1 },
|
||||
],
|
||||
},
|
||||
Multimédia: {
|
||||
color: "#0f0",
|
||||
things: [
|
||||
{ label: _("Watch"), nb: 1 },
|
||||
{ label: _("Watch charger"), nb: 1 },
|
||||
{ label: _("Laptop"), nb: 1 },
|
||||
{ label: _("Laptop charger"), nb: 1 },
|
||||
],
|
||||
},
|
||||
},
|
||||
};
|
||||
for (scaseName in exampleData) {
|
||||
var scase = this.newSCase(scaseName);
|
||||
for (catName in exampleData[scaseName]) {
|
||||
var cat = scase.cats.newCat(catName);
|
||||
for (idx in exampleData[scaseName][catName].things) {
|
||||
cat.newThing(
|
||||
exampleData[scaseName][catName].things[idx]["label"],
|
||||
exampleData[scaseName][catName].things[idx]["nb"]
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
this.loadFromLocalStorage = function (data) {
|
||||
if (jQuery.type(localStorage.scases) != "undefined") {
|
||||
try {
|
||||
return this.loadFromJsonData(JSON.parse(localStorage.scases));
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
this.loadFromJsonData = function (data) {
|
||||
try {
|
||||
this.lastChange = data.lastChange;
|
||||
for (el in data.scases) {
|
||||
this[el] = new SCase(false, false, data.scases[el]);
|
||||
}
|
||||
return true;
|
||||
} catch (e) {
|
||||
for (el in this) {
|
||||
if (this.isSCase(this[el])) {
|
||||
delete this[el];
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
this.export = function () {
|
||||
return {
|
||||
lastChange: this.lastChange,
|
||||
scases: this.each(function (idx, scase) {
|
||||
return scase.export();
|
||||
}),
|
||||
};
|
||||
};
|
||||
|
||||
this.import = function (data) {
|
||||
ret = {};
|
||||
for (el in this) {
|
||||
if (this.isSCase(this[el])) {
|
||||
delete ret[el];
|
||||
}
|
||||
}
|
||||
this.lastChange = data.lastChange;
|
||||
for (el in data.scases) {
|
||||
this[el] = new SCase(false, false, data.scases[el]);
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
this.save = function () {
|
||||
localStorage.scases = JSON.stringify(this.export());
|
||||
};
|
||||
|
||||
this.each = function (fct) {
|
||||
var idx = 0;
|
||||
var ret = {};
|
||||
for (el in this) {
|
||||
if (this.isSCase(this[el])) {
|
||||
ret[el] = fct(idx++, this[el]);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
};
|
||||
|
||||
this.count = function () {
|
||||
len = 0;
|
||||
this.each(function (idx, scase) {
|
||||
len = len + 1;
|
||||
});
|
||||
return len;
|
||||
};
|
||||
|
||||
this.isSCase = function (el) {
|
||||
return (
|
||||
jQuery.type(el) == "object" &&
|
||||
jQuery.type(el.isSCase) == "function" &&
|
||||
el.isSCase()
|
||||
);
|
||||
};
|
||||
|
||||
this.byName = function (name) {
|
||||
for (el in this) {
|
||||
if (this.isSCase(this[el])) {
|
||||
if (this[el].name == name) {
|
||||
return this[el];
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
this.byUUID = function (uuid) {
|
||||
return this.isCase(this[uuid]) ? this[uuid] : null;
|
||||
};
|
||||
|
||||
this.removeSCase = function (name) {
|
||||
for (el in this) {
|
||||
if (this.isSCase(this[el]) && this[el].name == name) {
|
||||
this[el].remove();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
this.newSCase = function (name) {
|
||||
if (this.byName(this[name])) {
|
||||
var scase = this.byName(name);
|
||||
if (scase.removed) {
|
||||
scase.restore();
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
var uuid = uuid || generate_uuid();
|
||||
this[uuid] = new SCase(uuid, name);
|
||||
return this[uuid];
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
this.renameSCase = function (name, newname) {
|
||||
var scase = this.byName(name);
|
||||
if (scase && !this.byName(newname)) {
|
||||
scase.name = newname;
|
||||
scase.lastChange = new Date().getTime();
|
||||
return scase;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
this.copySCase = function (name, newname) {
|
||||
var orig_scase = this.byName(name);
|
||||
if (this.isSCase(orig_scase) && !this.byName(newname)) {
|
||||
var uuid = uuid || generate_uuid();
|
||||
this[uuid] = new SCase(false, false, orig_scase.export());
|
||||
this[uuid].uuid = uuid;
|
||||
this[uuid].lastChange = new Date().getTime();
|
||||
this[uuid].name = newname;
|
||||
return this[uuid];
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
this.resetSCase = function (name) {
|
||||
for (el in this) {
|
||||
if (this.isSCase(this[el]) && this[el].name == name) {
|
||||
return this[el].reset();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
}
|
||||
|
||||
function SCase(uuid, name, data) {
|
||||
this.uuid = uuid || generate_uuid();
|
||||
this.name = name;
|
||||
this.cats = new CatList();
|
||||
this.lastChange = new Date().getTime();
|
||||
this.removed = false;
|
||||
|
||||
this.isSCase = function () {
|
||||
return true;
|
||||
};
|
||||
|
||||
this.import = function (data) {
|
||||
this.uuid = data.uuid || generate_uuid();
|
||||
this.lastChange = data.lastChange || new Date().getTime();
|
||||
this.name = decodeURIComponent(data.name);
|
||||
this.removed = data.removed || false;
|
||||
if (jQuery.type(data.cats) == "object") {
|
||||
this.cats = new CatList(data.cats);
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
this.export = function () {
|
||||
return {
|
||||
uuid: this.uuid,
|
||||
lastChange: this.lastChange,
|
||||
name: encodeURIComponent(this.name),
|
||||
removed: this.removed,
|
||||
cats: this.cats.export(),
|
||||
};
|
||||
};
|
||||
|
||||
this.byName = function (name) {
|
||||
for (idx in this.cats) {
|
||||
if (name == this.cats[idx].name) {
|
||||
return this.cats[idx];
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
this.stats = function () {
|
||||
var cats = 0;
|
||||
var things = 0;
|
||||
var things_done = 0;
|
||||
this.cats.each(function (cidx, cat) {
|
||||
if (cat.removed) {
|
||||
return true;
|
||||
}
|
||||
cats++;
|
||||
for (idx in cat.things) {
|
||||
if (cat.things[idx].removed) {
|
||||
continue;
|
||||
}
|
||||
things++;
|
||||
if (cat.things[idx].checked) {
|
||||
things_done++;
|
||||
}
|
||||
}
|
||||
});
|
||||
return {
|
||||
cats: cats,
|
||||
things: things,
|
||||
done: things_done,
|
||||
};
|
||||
};
|
||||
|
||||
this.reset = function () {
|
||||
this.cats.each(function (idx, cat) {
|
||||
for (idx in cat.things) {
|
||||
if (cat.things[idx].checked) {
|
||||
cat.things[idx].checked = false;
|
||||
}
|
||||
}
|
||||
});
|
||||
this.lastChange = new Date().getTime();
|
||||
return true;
|
||||
};
|
||||
|
||||
this.remove = function () {
|
||||
this.removed = true;
|
||||
this.lastChange = new Date().getTime();
|
||||
};
|
||||
|
||||
this.restore = function () {
|
||||
this.removed = false;
|
||||
this.lastChange = new Date().getTime();
|
||||
};
|
||||
|
||||
/*
|
||||
* Constructor
|
||||
*/
|
||||
if (jQuery.type(data) == "object") {
|
||||
try {
|
||||
this.import(data);
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
alert(
|
||||
_(
|
||||
"An error occurred while loading the %s suitcase from the cache.",
|
||||
this.name
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function CatList(data) {
|
||||
this.export = function () {
|
||||
return this.each(function (idx, cat) {
|
||||
return cat.export();
|
||||
});
|
||||
};
|
||||
|
||||
this.import = function (data) {
|
||||
for (el in this) {
|
||||
if (this.isCat(this[el])) {
|
||||
delete this[el];
|
||||
}
|
||||
}
|
||||
for (el in data) {
|
||||
this[el] = new Cat(el, false, false, data[el]);
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
this.each = function (fct) {
|
||||
var idx = 0;
|
||||
var ret = {};
|
||||
for (el in this) {
|
||||
if (this.isCat(this[el])) {
|
||||
ret[el] = fct(idx++, this[el]);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
};
|
||||
|
||||
this.count = function () {
|
||||
len = 0;
|
||||
this.each(function (idx, cat) {
|
||||
len = len + 1;
|
||||
});
|
||||
return len;
|
||||
};
|
||||
|
||||
this.isCat = function (el) {
|
||||
return (
|
||||
jQuery.type(el) == "object" &&
|
||||
jQuery.type(el.isCat) == "function" &&
|
||||
el.isCat()
|
||||
);
|
||||
};
|
||||
|
||||
this.byName = function (name) {
|
||||
for (el in this) {
|
||||
if (this.isCat(this[el])) {
|
||||
if (this[el].name == name) {
|
||||
return this[el];
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
this.byUUID = function (uuid) {
|
||||
return this.isCas(this[uuid]) ? this[uuid] : null;
|
||||
};
|
||||
|
||||
this.newCat = function (name) {
|
||||
if (this.byName(name)) {
|
||||
var cat = this.byName(name);
|
||||
if (cat.removed) {
|
||||
cat.restore();
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
var uuid = uuid || generate_uuid();
|
||||
this[uuid] = new Cat(uuid, name);
|
||||
return this[uuid];
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
this.renameCat = function (name, newname) {
|
||||
var cat = this.byName(name);
|
||||
if (cat && !this.byName(newname)) {
|
||||
cat.name = newname;
|
||||
cat.lastChange = new Date().getTime();
|
||||
return cat;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
this.removeCat = function (name) {
|
||||
for (el in this) {
|
||||
if (this.isCat(this[el]) && this[el].name == name) {
|
||||
this[el].remove();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
this.restoreCat = function (name) {
|
||||
for (el in this) {
|
||||
if (this.isCat(this[el]) && this[el].name == name && this[el].removed) {
|
||||
this[el].restore();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
/*
|
||||
* Constructor
|
||||
*/
|
||||
if (jQuery.type(data) == "object") {
|
||||
try {
|
||||
this.import(data);
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
alert(
|
||||
_("An error occurred while loading the category list from the cache.")
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function Cat(uuid, name, color, data) {
|
||||
this.uuid = generate_uuid();
|
||||
this.lastChange = new Date().getTime();
|
||||
this.name = name;
|
||||
this.color =
|
||||
color ||
|
||||
"#" + (0x1000000 + Math.random() * 0xffffff).toString(16).substr(1, 6);
|
||||
this.things = {};
|
||||
this.removed = false;
|
||||
|
||||
this.isCat = function () {
|
||||
return true;
|
||||
};
|
||||
|
||||
this.import = function (data) {
|
||||
this.uuid = data.uuid || generate_uuid();
|
||||
this.lastChange = data.lastChange || new Date().getTime();
|
||||
this.name = decodeURIComponent(data.name);
|
||||
this.color = data.color;
|
||||
this.removed = data.removed || false;
|
||||
if (jQuery.type(data.things) == "object") {
|
||||
for (tuuid in data.things) {
|
||||
this.things[tuuid] = new Thing(tuuid);
|
||||
this.things[tuuid].import(data.things[tuuid]);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
this.export = function () {
|
||||
var things = {};
|
||||
for (tuuid in this.things) {
|
||||
things[tuuid] = this.things[tuuid].export();
|
||||
}
|
||||
return {
|
||||
uuid: this.uuid,
|
||||
lastChange: this.lastChange,
|
||||
name: encodeURIComponent(this.name),
|
||||
color: this.color,
|
||||
removed: this.removed,
|
||||
things: things,
|
||||
};
|
||||
};
|
||||
|
||||
this.byLabel = function (label) {
|
||||
for (idx in this.things) {
|
||||
if (label == this.things[idx].label) {
|
||||
return this.things[idx];
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
this.count = function () {
|
||||
return keys(this.things).length;
|
||||
};
|
||||
|
||||
this.stats = function () {
|
||||
var count = 0;
|
||||
var done = 0;
|
||||
for (idx in this.things) {
|
||||
if (this.things[idx].removed) {
|
||||
continue;
|
||||
}
|
||||
if (this.things[idx].checked) {
|
||||
done += 1;
|
||||
}
|
||||
count += 1;
|
||||
}
|
||||
return {
|
||||
things: count,
|
||||
done: done,
|
||||
};
|
||||
};
|
||||
|
||||
this.newThing = function (label, nb) {
|
||||
if (this.byLabel(label)) {
|
||||
var thing = this.byLabel(label);
|
||||
if (thing.removed) {
|
||||
thing.restore();
|
||||
thing.setChecked(false);
|
||||
thing.setNb(nb);
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
var uuid = generate_uuid();
|
||||
this.things[uuid] = new Thing(uuid, label, nb);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
this.renameThing = function (label, newlabel) {
|
||||
var thing = this.byLabel(label);
|
||||
if (thing && !this.byLabel(newlabel)) {
|
||||
thing.label = newlabel;
|
||||
thing.lastChange = new Date().getTime();
|
||||
return thing;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
this.removeThing = function (label) {
|
||||
for (idx in this.things) {
|
||||
if (this.things[idx].label == label) {
|
||||
this.things[idx].remove();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
this.restoreThing = function (label) {
|
||||
for (idx in this.things) {
|
||||
if (this.things[idx].label == label && this.things[idx].removed) {
|
||||
this.things[idx].restore();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
this.remove = function () {
|
||||
this.removed = true;
|
||||
this.lastChange = new Date().getTime();
|
||||
};
|
||||
|
||||
this.restore = function () {
|
||||
this.removed = false;
|
||||
this.lastChange = new Date().getTime();
|
||||
};
|
||||
|
||||
/*
|
||||
* Constructor
|
||||
*/
|
||||
if (jQuery.type(data) == "object") {
|
||||
try {
|
||||
this.import(data);
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
alert(
|
||||
_(
|
||||
"An error occurred while loading the %s category from the cache.",
|
||||
this.name
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function Thing(uuid, label, nb, checked) {
|
||||
this.uuid = uuid || generate_uuid();
|
||||
this.lastChange = new Date().getTime();
|
||||
this.label = label;
|
||||
this.nb = nb || 1;
|
||||
this.checked = checked;
|
||||
this.removed = false;
|
||||
|
||||
this.import = function (data) {
|
||||
this.uuid = data.uuid || generate_uuid();
|
||||
this.lastChange = data.lastChange || new Date().getTime();
|
||||
(this.label = decodeURIComponent(data.label)), (this.nb = data.nb || 1);
|
||||
this.checked = data.checked;
|
||||
this.removed = data.removed || false;
|
||||
};
|
||||
|
||||
this.export = function () {
|
||||
return {
|
||||
uuid: this.uuid,
|
||||
lastChange: this.lastChange,
|
||||
label: encodeURIComponent(this.label),
|
||||
nb: this.nb,
|
||||
checked: this.checked,
|
||||
removed: this.removed,
|
||||
};
|
||||
};
|
||||
|
||||
this.setNb = function (nb) {
|
||||
this.nb = nb;
|
||||
this.lastChange = new Date().getTime();
|
||||
};
|
||||
|
||||
this.setChecked = function (value) {
|
||||
this.checked = value;
|
||||
this.lastChange = new Date().getTime();
|
||||
console.log(
|
||||
`Thing<${this.uuid}>.setChecked(${this.checked}): ${this.lastChange}`
|
||||
);
|
||||
};
|
||||
|
||||
this.remove = function () {
|
||||
this.removed = true;
|
||||
this.lastChange = new Date().getTime();
|
||||
};
|
||||
|
||||
this.restore = function () {
|
||||
this.removed = false;
|
||||
this.lastChange = new Date().getTime();
|
||||
};
|
||||
}
|
||||
|
||||
function User() {
|
||||
this.username = null;
|
||||
this.name = null;
|
||||
this.token = null;
|
||||
this.loadFromLocalStorage = function () {
|
||||
if (jQuery.type(localStorage.user) == "undefined") return;
|
||||
try {
|
||||
var data = JSON.parse(localStorage.user);
|
||||
this.username = data.username;
|
||||
this.name = data.name;
|
||||
this.token = data.token;
|
||||
} catch (e) {
|
||||
alert(_("Error loading your login information. Please log in again."));
|
||||
}
|
||||
};
|
||||
|
||||
this.connected = function () {
|
||||
return this.username && this.token;
|
||||
};
|
||||
|
||||
this.reset = function () {
|
||||
this.username = null;
|
||||
this.name = null;
|
||||
this.token = null;
|
||||
};
|
||||
|
||||
this.save = function () {
|
||||
localStorage.user = JSON.stringify({
|
||||
username: this.username,
|
||||
name: this.name,
|
||||
token: this.token,
|
||||
});
|
||||
};
|
||||
}
|
0
templates/.gitignore
vendored
Normal file
8
templates/cache_manifest.tpl
Normal file
|
@ -0,0 +1,8 @@
|
|||
CACHE MANIFEST
|
||||
# Last updated: {$last_updated} GMT
|
||||
|
||||
CACHE:
|
||||
{"\n"|implode:$cache}
|
||||
|
||||
NETWORK:
|
||||
*
|
|
@ -5,20 +5,21 @@
|
|||
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=utf-8" />
|
||||
<meta name="mobile-web-app-capable" content="yes">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1, user-scalable=0">
|
||||
<link rel="shortcut icon" href="favicon.png">
|
||||
<link rel="shortcut icon" sizes="196x196" href="icon-196x196.png">
|
||||
<link rel="shortcut icon" sizes="128x128" href="icon-128x128.png">
|
||||
<link rel="apple-touch-icon" sizes="128x128" href="icon-128x128.png">
|
||||
<link rel="apple-touch-icon-precomposed" sizes="128x128" href="icon-128x128.png">
|
||||
<link rel="shortcut icon" href="{static_url path="favicon.png"}">
|
||||
<link rel="shortcut icon" sizes="196x196" href="{static_url path="icon-196x196.png"}">
|
||||
<link rel="shortcut icon" sizes="128x128" href="{static_url path="icon-128x128.png"}">
|
||||
<link rel="apple-touch-icon" sizes="128x128" href="{static_url path="icon-128x128.png"}">
|
||||
<link rel="apple-touch-icon-precomposed" sizes="128x128" href="{static_url path="icon-128x128.png"}">
|
||||
<!-- Bootstrap -->
|
||||
|
||||
<!-- Latest compiled and minified CSS -->
|
||||
<link rel="stylesheet" href="inc/lib/bootstrap/css/bootstrap.min.css">
|
||||
<link rel="stylesheet" href="{static_url path="lib/alertify/css/alertify.min.css"}">
|
||||
<link rel="stylesheet" href="{static_url path="lib/bootstrap/css/bootstrap.min.css"}">
|
||||
|
||||
<!-- Optional theme -->
|
||||
<link rel="stylesheet" href="inc/lib/bootstrap/css/bootstrap.superhero.min.css">
|
||||
<link rel="stylesheet" href="{static_url path="lib/bootstrap/css/bootstrap.superhero.min.css"}">
|
||||
|
||||
<link rel="stylesheet" href="inc/main.css">
|
||||
<link rel="stylesheet" href="{static_url path="main.css"}">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
@ -33,31 +34,45 @@
|
|||
</button>
|
||||
<a class="navbar-brand" id='app-name'>MySC</a>
|
||||
</div>
|
||||
<div class="collapse navbar-collapse" id="navbar-top-collapse">
|
||||
<div class="collapse navbar-collapse" id="navbar-top-collapse">
|
||||
<ul class="nav navbar-nav navbar-right">
|
||||
<li class="menu menu-scases"><a href="#add_scase" id="add_scase_btn"><span class="glyphicon glyphicon-plus-sign"></span> Ajouter une valise</a></li>
|
||||
<li class="menu menu-scases"><a href="#scases_trash" id="scases_trash_btn"><span class="glyphicon glyphicon-trash"></span> Voir la corbeille</a></li>
|
||||
<li class="menu menu-scase"><a href="#scases" id="back_to_scases"><span class="glyphicon glyphicon-briefcase"></span> Liste des valises</a></li>
|
||||
<li class="menu menu-scases"><a href="#add_scase" id="add_scase_btn"><span class="glyphicon glyphicon-plus-sign"></span> {t}Add a suitcase{/t}</a></li>
|
||||
<li class="menu menu-scases"><a href="#scases_trash" id="scases_trash_btn"><span class="glyphicon glyphicon-trash"></span> {t}Show trash{/t}</a></li>
|
||||
<li class="menu menu-scase"><a href="#scases" id="back_to_scases"><span class="glyphicon glyphicon-briefcase"></span> {t}Suitcases list{/t}</a></li>
|
||||
<li class="menu menu-scase dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown"><span class='glyphicon glyphicon-tag'></span> Gérer la valise <b class="caret"></b></a>
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown"><span class='glyphicon glyphicon-tag'></span> {t}Manage the suitcase{/t} <b class="caret"></b></a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a href="#add_cat" id="add_cat_btn"><span class="glyphicon glyphicon-plus-sign"></span> Ajouter une catégorie</a></li>
|
||||
<li><a href="#add_cat" id="add_cat_btn"><span class="glyphicon glyphicon-plus-sign"></span> {t}Add a category{/t}</a></li>
|
||||
<li class="divider"></li>
|
||||
<li><a href="#rename_scase" id="rename_scase_btn"><span class="glyphicon glyphicon-edit"></span> Renommer la valise</a></li>
|
||||
<li><a href="#copy_scase" id="copy_scase_btn"><span class="glyphicon glyphicon-duplicate"></span> Copier la valise</a></li>
|
||||
<li><a href="#reset_scase" id="reset_scase_btn"><span class="glyphicon glyphicon-cog"></span> Réinitialiser la valise</a></li>
|
||||
<li><a href="#delete_scase" id="delete_scase_btn"><span class="glyphicon glyphicon-trash"></span> Supprimer la valise</a></li>
|
||||
<li><a href="#rename_scase" id="rename_scase_btn"><span class="glyphicon glyphicon-edit"></span> {t}Rename the suitcase{/t}</a></li>
|
||||
<li><a href="#copy_scase" id="copy_scase_btn"><span class="glyphicon glyphicon-duplicate"></span> {t}Copy the suitcase{/t}</a></li>
|
||||
<li><a href="#reset_scase" id="reset_scase_btn"><span class="glyphicon glyphicon-cog"></span> {t}Reset the suitcase{/t}</a></li>
|
||||
<li><a href="#delete_scase" id="delete_scase_btn"><span class="glyphicon glyphicon-trash"></span> {t}Delete the suitcase{/t}</a></li>
|
||||
<li class="divider"></li>
|
||||
<li><a href="#scase_trash" id="scase_trash_btn"><span class="glyphicon glyphicon-trash"></span> Voir la corbeille de la valise</a></li>
|
||||
<li><a href="#scase_trash" id="scase_trash_btn"><span class="glyphicon glyphicon-trash"></span> {t}Show suitcase's trash{/t}</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown"><span class='glyphicon glyphicon-hdd'></span> Gérer vos données <b class="caret"></b></a>
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown"><span class='glyphicon glyphicon-hdd'></span> {t}Manage data{/t} <b class="caret"></b></a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a id='export_local_data' href='#' download='mysc_export.json'><span class='glyphicon glyphicon-save'></span> Sauvegarder vos données</a></li>
|
||||
<li><a id='import_local_data' href='#' download='mysc_export.json'><span class='glyphicon glyphicon-open'></span> Restaurer vos données</a></li>
|
||||
<li><a id='export_local_data' href='#' download='mysc_export.json'><span class='glyphicon glyphicon-save'></span> {t}Backup your data{/t}</a></li>
|
||||
<li><a id='import_local_data' href='#' download='mysc_export.json'><span class='glyphicon glyphicon-open'></span> {t}Restaure your data{/t}</a></li>
|
||||
<li class="divider"></li>
|
||||
<li><a id='clear_local_data'><span class='glyphicon glyphicon-trash'></span> Purger les données locales</a></li>
|
||||
<li><a id='sync_local_data'><span class='glyphicon glyphicon-refresh'></span> {t}Synchronize local data{/t}</a></li>
|
||||
<li class="divider"></li>
|
||||
<li><a id='clear_local_data'><span class='glyphicon glyphicon-trash'></span> {t}Purge local data{/t}</a></li>
|
||||
<li><a id='load_example_data'><span class='glyphicon glyphicon-trash'></span> {t}Load example data{/t}</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">
|
||||
<span class='glyphicon glyphicon-user'></span>
|
||||
<span id="username"></span>
|
||||
<b class="caret"></b>
|
||||
</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a id='login' href='#'><span class='glyphicon glyphicon-loging'></span> {t}Login{/t}</a></li>
|
||||
<li><a id='logout' href='#'><span class='glyphicon glyphicon-logout'></span> {t}Logout{/t}</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
@ -73,18 +88,18 @@
|
|||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
||||
<h4 class="modal-title">Ajouter une valise</h4>
|
||||
<h4 class="modal-title">{t}Add a suitcase{/t}</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form class="form-horizontal" role="form">
|
||||
<div class="form-group">
|
||||
<input type='text' id='add_scase_name' class="form-control" placeholder="Nom de la valise"/>
|
||||
<input type='text' id='add_scase_name' class="form-control" placeholder="{t}Suitcase name{/t}"/>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">Annuler</button>
|
||||
<button type="button" class="btn btn-primary" id='add_scase_submit'>Ajouter</button>
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">{t}Cancel{/t}</button>
|
||||
<button type="button" class="btn btn-primary" id='add_scase_submit'>{t}Add{/t}</button>
|
||||
</div>
|
||||
</div><!-- /.modal-content -->
|
||||
</div><!-- /.modal-dialog -->
|
||||
|
@ -95,18 +110,18 @@
|
|||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
||||
<h4 class="modal-title">Copier une valise</h4>
|
||||
<h4 class="modal-title">{t}Copy the suitcase{/t}</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form class="form-horizontal" role="form">
|
||||
<div class="form-group">
|
||||
<input type='text' id='copy_scase_name' class="form-control" placeholder="Nom de la nouvelle valise"/>
|
||||
<input type='text' id='copy_scase_name' class="form-control" placeholder="{t}Name of the new suitcase{/t}"/>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">Annuler</button>
|
||||
<button type="button" class="btn btn-primary" id='copy_scase_submit'>Copier</button>
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">{t}Cancel{/t}</button>
|
||||
<button type="button" class="btn btn-primary" id='copy_scase_submit'>{t}Copy{/t}</button>
|
||||
</div>
|
||||
</div><!-- /.modal-content -->
|
||||
</div><!-- /.modal-dialog -->
|
||||
|
@ -117,18 +132,18 @@
|
|||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
||||
<h4 class="modal-title">Renomer la valise</h4>
|
||||
<h4 class="modal-title">{t}Rename the suitcase{/t}</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form class="form-horizontal" role="form">
|
||||
<div class="form-group">
|
||||
<input type='text' id='rename_scase_name' class="form-control" placeholder="Nom de la nouvelle valise"/>
|
||||
<input type='text' id='rename_scase_name' class="form-control" placeholder="{t}New suitcase name{/t}"/>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">Annuler</button>
|
||||
<button type="button" class="btn btn-primary" id='rename_scase_submit'>Renomer</button>
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">{t}Cancel{/t}</button>
|
||||
<button type="button" class="btn btn-primary" id='rename_scase_submit'>{t}Rename{/t}</button>
|
||||
</div>
|
||||
</div><!-- /.modal-content -->
|
||||
</div><!-- /.modal-dialog -->
|
||||
|
@ -139,18 +154,18 @@
|
|||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
||||
<h4 class="modal-title">Ajouter une catégorie</h4>
|
||||
<h4 class="modal-title">{t}Add a category{/t}</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form class="form-horizontal" role="form">
|
||||
<div class="form-group">
|
||||
<input type='text' id='add_cat_name' class="form-control" placeholder="Nom de la catégorie"/>
|
||||
<input type='text' id='add_cat_name' class="form-control" placeholder="{t}Category name{/t}"/>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">Annuler</button>
|
||||
<button type="button" class="btn btn-primary" id='add_cat_submit'>Ajouter</button>
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">{t}Cancel{/t}</button>
|
||||
<button type="button" class="btn btn-primary" id='add_cat_submit'>{t}Add{/t}</button>
|
||||
</div>
|
||||
</div><!-- /.modal-content -->
|
||||
</div><!-- /.modal-dialog -->
|
||||
|
@ -161,18 +176,18 @@
|
|||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
||||
<h4 class="modal-title">Renommer une catégorie</h4>
|
||||
<h4 class="modal-title">{t}Rename the category{/t}</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form class="form-horizontal" role="form">
|
||||
<div class="form-group">
|
||||
<input type='text' id='rename_cat_name' class="form-control" placeholder="Nouveau nom de la catégorie"/>
|
||||
<input type='text' id='rename_cat_name' class="form-control" placeholder="{t}New category's name{/t}"/>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">Annuler</button>
|
||||
<button type="button" class="btn btn-primary" id='rename_cat_submit'>Renommer</button>
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">{t}Cancel{/t}</button>
|
||||
<button type="button" class="btn btn-primary" id='rename_cat_submit'>{t}Rename{/t}</button>
|
||||
</div>
|
||||
</div><!-- /.modal-content -->
|
||||
</div><!-- /.modal-dialog -->
|
||||
|
@ -184,23 +199,23 @@
|
|||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
||||
<h4 class="modal-title">Ajouter un élément</h4>
|
||||
<h4 class="modal-title">{t}Add an element{/t}</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form role="form">
|
||||
<div class="form-group">
|
||||
<input type='text' class='form-control add_thing_label' placeholder="Nom de l'élément"/>
|
||||
<input type='number' class='form-control add_thing_nb' placeholder="Nb"/>
|
||||
<input type='text' class='form-control add_thing_label' placeholder="{t}Element name{/t}"/>
|
||||
<input type='number' class='form-control add_thing_nb' placeholder="{t}Nb{/t}"/>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<input type='text' class='form-control add_thing_label' placeholder="Un autre ?"/>
|
||||
<input type='number' class='form-control add_thing_nb' placeholder="Nb"/>
|
||||
<input type='text' class='form-control add_thing_label' placeholder="{t}Another?{/t}"/>
|
||||
<input type='number' class='form-control add_thing_nb' placeholder="{t}Nb{/t}"/>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">Annuler</button>
|
||||
<button type="button" class="btn btn-primary" id='add_thing_submit'>Ajouter</button>
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">{t}Cancel{/t}</button>
|
||||
<button type="button" class="btn btn-primary" id='add_thing_submit'>{t}Add{/t}</button>
|
||||
</div>
|
||||
</div><!-- /.modal-content -->
|
||||
</div><!-- /.modal-dialog -->
|
||||
|
@ -211,19 +226,19 @@
|
|||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
||||
<h4 class="modal-title">Modifier un élément</h4>
|
||||
<h4 class="modal-title">{t}Edit the element{/t}</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form class="form-horizontal" role="form">
|
||||
<div class="form-group">
|
||||
<input type='text' id='edit_thing_label' class="form-control" placeholder="Nouveau nom de l'élément"/>
|
||||
<input type='number' id='edit_thing_nb' class="form-control" placeholder="Nb"/>
|
||||
<input type='text' id='edit_thing_label' class="form-control" placeholder="{t}Element name{/t}"/>
|
||||
<input type='number' id='edit_thing_nb' class="form-control" placeholder="{t}Nb{/t}"/>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">Annuler</button>
|
||||
<button type="button" class="btn btn-primary" id='edit_thing_submit'>Modifier</button>
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">{t}Cancel{/t}</button>
|
||||
<button type="button" class="btn btn-primary" id='edit_thing_submit'>{t}Modify{/t}</button>
|
||||
</div>
|
||||
</div><!-- /.modal-content -->
|
||||
</div><!-- /.modal-dialog -->
|
||||
|
@ -234,12 +249,12 @@
|
|||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h2 class="modal-title">Chargement...</h2>
|
||||
<h2 class="modal-title">{t}Loading...{/t}</h2>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="progress progress-striped active">
|
||||
<div class="progress-bar" role="progressbar" aria-valuenow="100" aria-valuemin="0" aria-valuemax="100" style="width: 100%">
|
||||
<span class="sr-only">Chargement...</span>
|
||||
<span class="sr-only">{t}Loading...{/t}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -247,37 +262,88 @@
|
|||
</div><!-- /.modal-dialog -->
|
||||
</div>
|
||||
|
||||
<div class="modal" id="confirm_modal" tabindex="-1" role="dialog" aria-labelledby="confirmModal" aria-hidden="true">
|
||||
|
||||
<div class="modal" id="login_modal" tabindex="-1" role="dialog" aria-labelledby="loginModal" aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close cancel" aria-hidden="true">×</button>
|
||||
<h4 class="modal-title">Confirmation</h4>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
||||
<h4 class="modal-title">{t}Connection{/t}</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p id='question'></p>
|
||||
<form class="form-horizontal" role="form" action="login">
|
||||
<div class="form-group">
|
||||
<input type='text' id='login_username' class="form-control" placeholder="{t}Username{/t}" required/>
|
||||
<input type='password' id='login_password' class="form-control" placeholder="{t}Password{/t}" required/>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-default cancel">Annuler</button>
|
||||
<button type="button" class="btn btn-primary" id='confirm_modal_submit'>Valider</button>
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">{t}Cancel{/t}</button>
|
||||
<button type="button" class="btn btn-primary" id='login_submit'>{t}Connect{/t}</button>
|
||||
</div>
|
||||
</div><!-- /.modal-content -->
|
||||
</div><!-- /.modal-dialog -->
|
||||
</div>
|
||||
|
||||
|
||||
<div class="modal" id="welcome_modal" tabindex="-1" role="dialog" aria-labelledby="welcomeModal" aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
||||
<h4 class="modal-title">{t}Welcome{/t}</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
{t escape=false}<p>
|
||||
This application allows you to manage lists of things not to forget to pack in your
|
||||
suitcase before your departure:
|
||||
<ul>
|
||||
<li>
|
||||
To get started, create a suitcase, add the categories of things you will need to
|
||||
pack, and add all these things to it;
|
||||
</li>
|
||||
<li>
|
||||
Before your departure, you can then gradually check off all the things you have
|
||||
already gathered and ensure you don't forget anything!
|
||||
</li>
|
||||
</ul>
|
||||
</p>
|
||||
<p>
|
||||
<strong>Note:</strong> This application has been designed to work completely locally.
|
||||
The data manipulated (your suitcases, etc.) is stored only in your internet browser.
|
||||
It is also possible to export/import this information in JSON format.<br/>
|
||||
However, to facilitate the management of your suitcases from multiple devices, it's
|
||||
possible to synchronize this information on the server. For this, you need an account,
|
||||
and at this time, registrations are not open.
|
||||
</p>
|
||||
<p>
|
||||
If you have an account, you can log in by clicking the <em>Login</em> button below.
|
||||
If not, click the <em>Anonymous usage</em> button to start using the application.
|
||||
</p>{/t}
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-primary" id='welcome_connect'>{t}Connect{/t}</button>
|
||||
<button type="button" class="btn btn-default" id='welcome_annonymous'>{t}Anonymous usage{/t}</button>
|
||||
</div>
|
||||
</div><!-- /.modal-content -->
|
||||
</div><!-- /.modal-dialog -->
|
||||
</div>
|
||||
|
||||
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
|
||||
<script src="inc/lib/jquery.min.js"></script>
|
||||
<script src="{static_url path="lib/jquery.min.js"}"></script>
|
||||
<!-- Latest compiled and minified JavaScript -->
|
||||
<script src="inc/lib/bootstrap/js/bootstrap.js"></script>
|
||||
<script src="{static_url path="lib/alertify/alertify.min.js"}"></script>
|
||||
<script src="{static_url path="lib/bootstrap/js/bootstrap.js"}"></script>
|
||||
|
||||
<script>
|
||||
<!-- Other libs & JavaScript scripts -->
|
||||
{foreach $js as $path}
|
||||
<script language="javascript" src="{$path|escape:"quotes"}"></script>
|
||||
{/foreach}
|
||||
|
||||
</script>
|
||||
|
||||
<script src="inc/lib/uuid.js"></script>
|
||||
<script src="inc/mydialog.js"></script>
|
||||
<script src="inc/mysc_objects.js"></script>
|
||||
<script src="inc/main.js"></script>
|
||||
<script src="{static_url path="lib/uuid.js"}"></script>
|
||||
<script src="{static_url path="mysc_objects.js"}"></script>
|
||||
<script src="{static_url path="main.js"}"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
13
templates/support_info.tpl
Normal file
|
@ -0,0 +1,13 @@
|
|||
{extends file='Tpl:empty.tpl'}
|
||||
{block name="pagetitle"}{/block}
|
||||
{block name="content"}
|
||||
<h1>{t}Helpdesk page{/t}</h1>
|
||||
<p>{t}Upon request, please download and forward the following information to the support service:{/t}</p>
|
||||
<div class="text-center mb-2">
|
||||
<a href="{$request->current_url}?download" class="btn btn-primary">
|
||||
<i class="fa fa-download" aria-hidden="true"></i>
|
||||
{t}Download{/t}
|
||||
</a>
|
||||
</div>
|
||||
<pre class="text-bg-light p-3 copyable">{include file="Tpl:support_info_content.tpl"}</pre>
|
||||
{/block}
|
8
templates/support_info_content.tpl
Normal file
|
@ -0,0 +1,8 @@
|
|||
{t}Application URL:{/t} {$public_root_url}
|
||||
{t}Current page URL:{/t} {$public_root_url}/{$request->current_url}
|
||||
|
||||
{t}Connected user:{/t} {$auth_user->username}
|
||||
|
||||
{t}Extra user information:{/t}
|
||||
================================================
|
||||
{var_dump data=$auth_user->info}
|