commit 6fd3a23aa7fbbd1d195cf83a3f6c1e3276a20de1 Author: Teddy Middleton-Smith Date: Sat Jun 21 17:51:07 2025 +0100 Initial commit. diff --git a/.babelrc b/.babelrc new file mode 100644 index 0000000..827c750 --- /dev/null +++ b/.babelrc @@ -0,0 +1,4 @@ +{ + "presets": ["@babel/preset-env"], + "plugins": ["@babel/plugin-syntax-dynamic-import"] +} \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3967646 --- /dev/null +++ b/.gitignore @@ -0,0 +1,77 @@ + +# Ignore Git files +git-filter-repo/ + +# Ignore compiled files +*.class +*.o +*.pyc +.VSCodeCounter/ +__pycache__/ + +# Ignore logs and databases +*.log +*.log.* + +# Ignore logs and databases +# *.sql +# *.sqlite + +# Ignore OS generated files +.DS_Store +.DS_Store? +._* +.Spotlight-V100 +.Trashes +ehthumbs.db +Thumbs.db + +# Ignore IDE and editor files +.vscode/ +.idea/ +*.swp +*.swo +*.sublime-workspace + +# Ignore package management directories +node_modules/ +jspm_packages/ +bower_components/ + +# Ignore build directories +build/ +dist/ +out/ + +# Ignore environment and config files +.env +config.js +secrets.yaml + +# Ignore dependency lock files (uncomment if you want to ignore) +# package-lock.json +# yarn.lock + +# Ignore personal TODO lists +TODO.md + +# Ignore all files in a directory +tmp/ + +# Ignore all .txt files in the doc/ directory +doc/*.txt + +# But don't ignore doc/important.txt, even though we're ignoring .txt files above +!doc/important.txt + +# Ignore all .pdf files in the doc/ directory and any of its subdirectories +doc/**/*.pdf + +# Ignore deprecated files +DEPRECATED/ + +# Ignore virtual environments +bot_env/ +bot_web/ +env_test/ +env_web/ \ No newline at end of file diff --git a/.htaccess b/.htaccess new file mode 100644 index 0000000..1e17a18 --- /dev/null +++ b/.htaccess @@ -0,0 +1,7 @@ +PassengerEnabled On +PassengerAppRoot parts_website +PassengerAppType wsgi +PassengerStartupFile passenger_wsgi.py + +# Optional: Set the Python interpreter if required +PassengerPython /home/partsltd/virtualenv/public_html/parts_website/3.11/bin/python diff --git a/README.md b/README.md new file mode 100644 index 0000000..4be183b --- /dev/null +++ b/README.md @@ -0,0 +1,41 @@ +Precision and Research Technology Systems Limited +Website with online store + +Powered by flask + +enter virtual environment: +python -m venv VIRTUAL_ENVIRONMENT_NAME + +run module bundler: +npm run build + +host for machine: +python -m flask run + +host for local network: +python -m flask run --host=0.0.0.0 + + +files dedicated to each page: +CSS + page +HTML + page + row +JavaScript + page + api + router + base - navigation buttons +MySQL + get + save + table + staging table + audit table +Python + business object + controller + datastore + form + model \ No newline at end of file diff --git a/__init__.py b/__init__.py new file mode 100644 index 0000000..03dc31c --- /dev/null +++ b/__init__.py @@ -0,0 +1,20 @@ +""" +Project: PARTS Website +Author: Edward Middleton-Smith + Precision And Research Technology Systems Limited + +Technology: Backend +Feature: Initialisation + +Description: +Initializes the Flask application. +Initializes any extensions used in the project. +""" + +from flask import Flask + +app = Flask(__name__) +app.config.from_object('config') + +# from app import routes +# import business_objects, lib, models diff --git a/app.py b/app.py new file mode 100644 index 0000000..7c6869d --- /dev/null +++ b/app.py @@ -0,0 +1,129 @@ +""" +Project: PARTS Website +Author: Edward Middleton-Smith + Precision And Research Technology Systems Limited + +Technology: App General +Feature: App + +Description: +Initializes the Flask application, sets the configuration based on the environment, and defines two routes (/ and /about) that render templates with the specified titles. +""" + +# IMPORTS +# VARIABLE INSTANTIATION +# METHODS + +# IMPORTS +# internal +from config import app_config, Config +from controllers.core.contact import routes_core_contact +from controllers.core.home import routes_core_home +from controllers.legal.legal import routes_legal +from extensions import db, csrf, mail, oauth +from helpers.helper_app import Helper_App +# external +from flask import Flask, render_template, jsonify, request, render_template_string, send_from_directory, redirect, url_for, session +# from flask_appconfig import AppConfig +from flask_cors import CORS +from flask_sqlalchemy import SQLAlchemy +from flask_mail import Mail, Message +from flask_wtf.csrf import CSRFProtect +from werkzeug.exceptions import HTTPException +from authlib.integrations.flask_client import OAuth +import os +import sys +from logging.handlers import RotatingFileHandler +import traceback +import logging + +sys.path.insert(0, os.path.dirname(__file__)) # Todo: why? + + +app = Flask(__name__) +app.secret_key = os.getenv('KEY_SECRET_FLASK') + +# AppConfig(app) +app.config.from_object(app_config) # for db init with required keys +app.app_config = app_config +# app.config["config"] = app_config() + +# logging +handler = RotatingFileHandler('app.log', maxBytes=10000, backupCount=3) +handler.setLevel(logging.DEBUG) +app.logger.addHandler(handler) + +@app.errorhandler(Exception) +def internal_server_error(error): + if isinstance(error, HTTPException) and error.code == 404: + return "Not Found", 404 + + app.logger.error('Server Error: %s', (error)) + app.logger.error('Request: %s %s %s %s %s', + request.remote_addr, + request.method, + request.scheme, + request.full_path, + request.headers) + app.logger.error('Request data: %s', request.get_data()) + app.logger.error('Traceback: %s', traceback.format_exc()) + return "Internal Server Error", 500 + +@app.before_request +def make_session_permanent(): + session.permanent = True + +csrf = CSRFProtect() +cors = CORS(app, resources={ + r"/static/*": { + "origins": [app.config["URL_HOST"]], + "methods": ["GET"], + "max_age": 3600 + } +}) + +csrf.init_app(app) +cors.init_app(app) +db.init_app(app) +mail.init_app(app) +oauth.init_app(app) + +with app.app_context(): + # config = app.config["config"] + db.create_all() + db.engine.url = app.config['SQLALCHEMY_DATABASE_URI'] + + oauth.register( + "auth0", + client_id = app.config['ID_AUTH0_CLIENT'], + client_secret = app.config['ID_AUTH0_CLIENT_SECRET'], + client_kwargs={ + "scope": "openid profile email", + }, + server_metadata_url=f'https://{app.config["DOMAIN_AUTH0"]}/.well-known/openid-configuration', + api_base_url = f'https://{app.config["DOMAIN_AUTH0"]}', + authorize_url = f'https://{app.config["DOMAIN_AUTH0"]}/authorize', + access_token_url = f'https://{app.config["DOMAIN_AUTH0"]}/oauth/token', + ) + + +app.register_blueprint(routes_core_home) +app.register_blueprint(routes_core_contact) +app.register_blueprint(routes_legal) + + + +@app.template_filter('console_log') +def console_log(value): + Helper_App.console_log(value) + return value + +@app.after_request +def add_cache_headers(response): + if request.path.startswith('/static/'): + # Cache static assets + response.headers['Cache-Control'] = 'public, max-age=31536000' + else: + # No caching for dynamic content + response.headers['Cache-Control'] = 'no-store, no-cache, must-revalidate, max-age=0' + return response \ No newline at end of file diff --git a/business_objects/__init__.py b/business_objects/__init__.py new file mode 100644 index 0000000..0ed1a26 --- /dev/null +++ b/business_objects/__init__.py @@ -0,0 +1,11 @@ +""" +Project: PARTS Website +Author: Edward Middleton-Smith + Precision And Research Technology Systems Limited + +Technology: Module Initialisation +Feature: Business Objects + +Description: +Initialises business objects module. +""" diff --git a/business_objects/api.py b/business_objects/api.py new file mode 100644 index 0000000..4f004b8 --- /dev/null +++ b/business_objects/api.py @@ -0,0 +1,32 @@ +""" +Project: PARTS Website +Author: Edward Middleton-Smith + Precision And Research Technology Systems Limited + +Technology: Business Objects +Feature: Base Business Object + +Description: +Abstract business object +""" + +# internal +from extensions import db +import lib.argument_validation as av +# external +from typing import ClassVar +from flask import jsonify + + +class API(): + + @staticmethod + def get_standard_response(success: bool, status_code: int, message: str, data: any, errors: list, meta: dict): + return jsonify({ + "success": success, + "status_code": status_code, + "message": message, + "data": data, + "errors": errors, + "meta": meta + }) diff --git a/business_objects/base.py b/business_objects/base.py new file mode 100644 index 0000000..dcf4464 --- /dev/null +++ b/business_objects/base.py @@ -0,0 +1,90 @@ +""" +Project: PARTS Website +Author: Edward Middleton-Smith + Precision And Research Technology Systems Limited + +Technology: Business Objects +Feature: Base Business Object + +Description: +Abstract base class for all business objects in app +""" + +# internal +from extensions import db +import lib.argument_validation as av +# external +from typing import ClassVar + + +class Base(): + ATTR_ID_ACCESS_LEVEL: ClassVar[str] = 'id_access_level' + ATTR_ID_ADDRESS: ClassVar[str] = 'id_address' + ATTR_ID_CURRENCY: ClassVar[str] = 'id_currency' + ATTR_ID_MSG_ERROR_TYPE: ClassVar[str] = 'id_type' + ATTR_ID_REGION: ClassVar[str] = 'id_region' + ATTR_ID_USER: ClassVar[str] = 'id_user' + ATTR_ID_USER_MANAGER: ClassVar[str] = 'id_user_manager' + FLAG_ACCESS_LEVEL_REQUIRED: ClassVar[str] = 'access_level_required' + FLAG_ACTIVE: ClassVar[str] = 'active' + FLAG_ADDRESS: ClassVar[str] = 'address' + FLAG_ADDRESS_LINE_1: ClassVar[str] = 'address_line_1' + FLAG_ADDRESS_LINE_2: ClassVar[str] = 'address_line_2' + FLAG_CAN_ADMIN: ClassVar[str] = 'can_admin' + FLAG_CAN_EDIT: ClassVar[str] = 'can_edit' + FLAG_CAN_VIEW: ClassVar[str] = 'can_view' + FLAG_CITY: ClassVar[str] = 'city' + FLAG_CODE: ClassVar[str] = 'code' + FLAG_COUNTY: ClassVar[str] = 'county' + FLAG_CREATED_BY: ClassVar[str] = 'created_by' + FLAG_CREATED_ON: ClassVar[str] = 'created_on' + FLAG_CURRENCY: ClassVar[str] = 'currency' + FLAG_CURRENCY_COST: ClassVar[str] = 'currency_cost' + FLAG_DATE_FROM: ClassVar[str] = 'date_from' + FLAG_DATE_TO: ClassVar[str] = 'date_to' + FLAG_DESCRIPTION: ClassVar[str] = 'description' + FLAG_DISPLAY_ORDER: ClassVar[str] = 'display_order' + FLAG_EDIT: ClassVar[str] = 'edit' + FLAG_EMAIL: ClassVar[str] = 'email' + FLAG_FAX: ClassVar[str] = 'fax' + FLAG_GUID: ClassVar[str] = 'guid' + FLAG_IS_NOT_EMPTY: ClassVar[str] = 'is_not_empty' + # FLAG_KEY_PRIMARY: ClassVar[str] = 'key_primary' + FLAG_MESSAGE: ClassVar[str] = 'message' + FLAG_NAME: ClassVar[str] = 'name' + FLAG_NAME_ATTR_OPTION_TEXT: ClassVar[str] = 'NAME_ATTR_OPTION_TEXT' + FLAG_NAME_ATTR_OPTION_VALUE: ClassVar[str] = 'NAME_ATTR_OPTION_VALUE' + FLAG_NAME_SINGULAR: ClassVar[str] = 'name_singular' + FLAG_NAME_PLURAL: ClassVar[str] = 'name_plural' + FLAG_PHONE_NUMBER: ClassVar[str] = 'phone_number' + FLAG_POSTCODE: ClassVar[str] = 'postcode' + FLAG_PRIORITY: ClassVar[str] = 'priority' + FLAG_REGION: ClassVar[str] = 'region' + FLAG_ROWS: ClassVar[str] = 'rows' + FLAG_SYMBOL: ClassVar[str] = 'symbol' + FLAG_URL: ClassVar[str] = 'url' + FLAG_USER: ClassVar[str] = 'authorisedUser' # 'user' already used + FLAG_VALUE_LOCAL_VAT_EXCL: ClassVar[str] = 'value_local_vat_excl' + FLAG_VALUE_LOCAL_VAT_INCL: ClassVar[str] = 'value_local_vat_incl' + FLAG_WEBSITE: ClassVar[str] = 'website' + ID_USER_GUEST: ClassVar[int] = 3 + """ + NAME_ATTR_OPTION_TEXT: ClassVar[str] = 'name-attribute-option-text' + NAME_ATTR_OPTION_VALUE: ClassVar[str] = 'name-attribute-option-value' + """ + def __repr__(self): + attrs = '\n'.join(f'{k}={v!r}' for k, v in self.__dict__.items()) + return f'<{self.__class__.__name__}(\n{attrs}\n)>' + + @classmethod + def output_bool(cls, value): + return av.input_bool(value, f'{cls.__name__} bool attribute', f'{cls.__name__}.output_bool') + @staticmethod + def convert_list_objects_to_list_options(objects): + return [object.to_json_option() for object in objects] + @classmethod + def get_shared_json_attributes(cls, object): + return { + cls.FLAG_NAME_ATTR_OPTION_TEXT: object.NAME_ATTR_OPTION_TEXT, + cls.FLAG_NAME_ATTR_OPTION_VALUE: object.NAME_ATTR_OPTION_VALUE + } \ No newline at end of file diff --git a/business_objects/db_base.py b/business_objects/db_base.py new file mode 100644 index 0000000..f82a737 --- /dev/null +++ b/business_objects/db_base.py @@ -0,0 +1,48 @@ +""" +Project: PARTS Website +Author: Edward Middleton-Smith + Precision And Research Technology Systems Limited + +Technology: Business Objects +Feature: Database Base Business Objects + +Description: +Abstract base class for database objects +""" + +# internal +# from helpers.DEPRECATED.helper_abc import Interface_ABC +from extensions import db +import lib.argument_validation as av +# external +from typing import ClassVar +from abc import abstractmethod, ABCMeta +from pydantic import BaseModel +from sqlalchemy.ext.declarative import DeclarativeMeta +# from flask_sqlalchemy import SQLAlchemy + + + +class SQLAlchemy_ABCMeta(db.Model.__class__, ABCMeta): + pass + +class SQLAlchemy_ABC(db.Model, metaclass=SQLAlchemy_ABCMeta): + __abstract__ = True + # id = db.Column(db.Integer, primary_key=True) + def __init__(self): + pass + def __repr__(self): + pass + def to_json(self): + pass + @classmethod + def from_json(cls, json): + pass + def to_temporary_record(self): + pass + def to_object_with_missing_attributes(self, excluded_attributes): + return { + column.name: getattr(self, column.name) + for column in self.__table__.columns + if column.name not in excluded_attributes + } \ No newline at end of file diff --git a/business_objects/dog/DEPRECATED - access_level.py b/business_objects/dog/DEPRECATED - access_level.py new file mode 100644 index 0000000..d28a20a --- /dev/null +++ b/business_objects/dog/DEPRECATED - access_level.py @@ -0,0 +1,82 @@ +""" +Project: PARTS Website +Author: Edward Middleton-Smith + Precision And Research Technology Systems Limited + +Technology: Business Objects +Feature: Product Category Business Object + +Description: +Business object for product +""" + +# internal +import lib.argument_validation as av +from business_objects.base import Base +from extensions import db +from helpers.helper_app import Helper_App +# external +from pydantic import BaseModel +from typing import ClassVar + + +class Access_Level(db.Model, Base): + NAME_ATTR_OPTION_VALUE: ClassVar[str] = Base.ATTR_ID_ACCESS_LEVEL + NAME_ATTR_OPTION_TEXT: ClassVar[str] = Base.FLAG_NAME + __tablename__ = 'PH_Access_Level_Temp' + id_access_level = db.Column(db.Integer, primary_key=True) + code = db.Column(db.String(50)) + name = db.Column(db.String(250)) + priority = db.Column(db.Integer) + display_order = db.Column(db.Integer) + active = db.Column(db.Boolean) + def __init__(self): + super().__init__() + Base.__init__(self) + @classmethod + def from_DB_access_level(cls, query_row): + access_level = cls() + access_level.id_access_level = query_row[0] + access_level.code = query_row[1] + access_level.name = query_row[2] + access_level.priority = query_row[3] + access_level.display_order = query_row[4] + access_level.active = query_row[5] + return access_level + def __repr__(self): + return f''' + id: {self.id_access_level[0] if isinstance(self.id_access_level, tuple) else self.id_access_level} + code: {self.code[0] if isinstance(self.code, tuple) else self.code} + name: {self.name[0] if isinstance(self.name, tuple) else self.name} + description: {self.description[0] if isinstance(self.description, tuple) else self.description} + priority: {self.priority[0] if isinstance(self.priority, tuple) else self.priority} + display_order: {self.display_order} + active: {self.active} + ''' + def to_json(self): + return { + **self.get_shared_json_attributes(self), + self.ATTR_ID_ACCESS_LEVEL: self.id_access_level[0] if isinstance(self.id_access_level, tuple) else self.id_access_level, + self.FLAG_CODE: self.code[0] if isinstance(self.code, tuple) else self.code, + self.FLAG_NAME: self.name[0] if isinstance(self.name, tuple) else self.name, + self.FLAG_DESCRIPTION: self.description[0] if isinstance(self.description, tuple) else self.description, + self.FLAG_PRIORITY: self.priority[0] if isinstance(self.priority, tuple) else self.priority, + self.FLAG_DISPLAY_ORDER: self.display_order, + self.FLAG_ACTIVE: av.input_bool(self.active, self.FLAG_ACTIVE, f'{self.__class__.__name__}.to_json') + } + def to_json_option(self): + return { + 'value': self.id_access_level, + 'text': self.name + } + @classmethod + def from_json(cls, json): + access_level = cls() + access_level.id_access_level = json[cls.ATTR_ID_ACCESS_LEVEL], + access_level.code = json[cls.FLAG_CODE], + access_level.name = json[cls.FLAG_NAME], + access_level.priority = json[cls.FLAG_PRIORITY], + access_level.description = json[cls.FLAG_DESCRIPTION], + access_level.display_order = json[cls.FLAG_DISPLAY_ORDER] + access_level.active = json[cls.FLAG_ACTIVE] + return access_level \ No newline at end of file diff --git a/business_objects/dog/__init__.py b/business_objects/dog/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/business_objects/dog/command.py b/business_objects/dog/command.py new file mode 100644 index 0000000..085faeb --- /dev/null +++ b/business_objects/dog/command.py @@ -0,0 +1,136 @@ +""" +Project: PARTS Website +Author: Edward Middleton-Smith + Precision And Research Technology Systems Limited + +Technology: Business Objects +Feature: Command Business Object +""" + +# internal +from business_objects.base import Base +from business_objects.db_base import SQLAlchemy_ABC +import lib.argument_validation as av +from extensions import db +from helpers.helper_app import Helper_App +# external +from dataclasses import dataclass +from typing import ClassVar + + +class Command(SQLAlchemy_ABC, Base): + FLAG_ALTCHA: ClassVar[str] = 'altcha' + FLAG_COMMAND: ClassVar[str] = 'command' + FLAG_NAME_COMPANY: ClassVar[str] = 'name-company' + FLAG_NAME_CONTACT: ClassVar[str] = 'name-contact' + FLAG_MESSAGE: ClassVar[str] = 'message' + FLAG_RECEIVE_MARKETING_COMMUNICATIONS: ClassVar[str] = 'receive-marketing-communications' + NAME_ATTR_OPTION_VALUE: ClassVar[str] = FLAG_COMMAND + NAME_ATTR_OPTION_TEXT: ClassVar[str] = Base.FLAG_EMAIL + + __tablename__ = 'PH_Command' + __table_args__ = { 'extend_existing': True } + + id_command = db.Column(db.Integer, primary_key=True) + email = db.Column(db.String(250)) + name_contact = db.Column(db.String(250)) + name_company = db.Column(db.String(250)) + message = db.Column(db.Text) + receive_marketing_communications = db.Column(db.Boolean) + active = db.Column(db.Boolean) + created_on = db.Column(db.DateTime) + + def __init__(self): + self.id_command = 0 + self.is_new = False + super().__init__() + + def from_DB_Command(query_row): + _m = 'Command.from_DB_Command' + command = Command() + command.id_command = query_row[0] + command.email = query_row[1] + command.name_contact = query_row[2] + command.name_company = query_row[3] + command.message = query_row[4] + command.receive_marketing_communications = av.input_bool(query_row[5], 'receive_marketing_communications', _m) + command.active = av.input_bool(query_row[6], 'active', _m) + command.created_on = query_row[7] + return command + + @classmethod + def from_json(cls, json): + _m = 'Command.from_json' + command = cls() + if json is None: return Command + Helper_App.console_log(f'{_m}\njson: {json}') + command.id_command = -1 + command.email = json[cls.FLAG_EMAIL] + command.name_contact = json[cls.FLAG_NAME_CONTACT] + command.name_company = json[cls.FLAG_NAME_COMPANY] + command.message = json[cls.FLAG_MESSAGE] + command.receive_marketing_communications = json[cls.FLAG_RECEIVE_MARKETING_COMMUNICATIONS] + command.active = json[cls.FLAG_ACTIVE] + command.created_on = json.get(cls.FLAG_CREATED_ON, None) + Helper_App.console_log(f'Command: {command}') + return command + + + def to_json(self): + as_json = { + self.FLAG_COMMAND: self.id_command + , self.FLAG_EMAIL: self.email + , self.FLAG_NAME_CONTACT: self.name_contact + , self.FLAG_NAME_COMPANY: self.name_company + , self.FLAG_MESSAGE: self.message + , self.FLAG_RECEIVE_MARKETING_COMMUNICATIONS: self.receive_marketing_communications + , self.FLAG_ACTIVE: self.active + , self.FLAG_CREATED_ON: self.created_on + } + Helper_App.console_log(f'as_json: {as_json}') + return as_json + + def __repr__(self): + return f''' +{self.__class__.__name__}( + {self.FLAG_COMMAND}: {self.id_command} + {self.FLAG_EMAIL}: {self.email} + {self.FLAG_NAME_CONTACT}: {self.name_contact} + {self.FLAG_NAME_COMPANY}: {self.name_company} + {self.FLAG_MESSAGE}: {self.message} + {self.FLAG_RECEIVE_MARKETING_COMMUNICATIONS}: {self.receive_marketing_communications} + {self.FLAG_ACTIVE}: {self.active} + {self.FLAG_CREATED_ON}: {self.created_on} +) + ''' + +class Command_Temp(db.Model, Base): + __tablename__ = 'PH_Command_Temp' + __table_args__ = { 'extend_existing': True } + id_temp = db.Column(db.Integer, primary_key=True) + id_command = db.Column(db.Integer) + email = db.Column(db.String(250)) + name_contact = db.Column(db.String(250)) + name_company = db.Column(db.String(250)) + message = db.Column(db.Text) + receive_marketing_communications = db.Column(db.Boolean) + active = db.Column(db.Boolean) + created_on = db.Column(db.DateTime) + guid: str = db.Column(db.String(36)) + + def __init__(self): + super().__init__() + + @classmethod + def from_command(cls, command): + _m = 'Command_Temp.from_Command' + temp = cls() + temp.id_command = command.id_command + temp.email = command.email + temp.name_contact = command.name_contact + temp.name_company = command.name_company + temp.message = command.message + temp.receive_marketing_communications = command.receive_marketing_communications + temp.active = command.active + temp.created_on = command.created_on + return temp \ No newline at end of file diff --git a/business_objects/dog/dog.py b/business_objects/dog/dog.py new file mode 100644 index 0000000..1245601 --- /dev/null +++ b/business_objects/dog/dog.py @@ -0,0 +1,126 @@ +""" +Project: PARTS Website +Author: Edward Middleton-Smith + Precision And Research Technology Systems Limited + +Technology: Business Objects +Feature: Dog Business Object +""" + +# internal +from business_objects.base import Base +from business_objects.db_base import SQLAlchemy_ABC +import lib.argument_validation as av +from extensions import db +from helpers.helper_app import Helper_App +# external +from dataclasses import dataclass +from typing import ClassVar + + +class Dog(SQLAlchemy_ABC, Base): + FLAG_DOG: ClassVar[str] = 'dog' + FLAG_APPEARANCE: ClassVar[str] = 'appearance' + FLAG_MASS_KG: ClassVar[str] = 'mass-kg' + FLAG_NOTES: ClassVar[str] = 'notes' + NAME_ATTR_OPTION_VALUE: ClassVar[str] = FLAG_DOG + NAME_ATTR_OPTION_TEXT: ClassVar[str] = Base.FLAG_EMAIL + + __tablename__ = 'PH_Dog' + __table_args__ = { 'extend_existing': True } + + id_dog = db.Column(db.Integer, primary_key=True) + name = db.Column(db.String(250)) + appearance = db.Column(db.String(1000)) + mass_kg = db.Column(db.Numeric(precision=7, scale=3)) + notes = db.Column(db.Text) + active = db.Column(db.Boolean) + + def __init__(self): + self.id_dog = 0 + self.is_new = False + super().__init__() + + def from_DB_Dog(query_row): + _m = 'Dog.from_DB_Dog' + dog = Dog() + dog.id_dog = query_row[0] + dog.name = query_row[1] + dog.appearance = query_row[2] + dog.mass_kg = query_row[3] + dog.notes = query_row[4] + dog.active = av.input_bool(query_row[5], 'active', _m) + return dog + + @classmethod + def from_json(cls, json): + _m = 'Dog.from_json' + dog = cls() + if json is None: return Dog + Helper_App.console_log(f'{_m}\njson: {json}') + dog.id_dog = -1 + dog.name = json[cls.FLAG_NAME] + dog.appearance = json[cls.FLAG_APPEARANCE] + dog.mass_kg = json[cls.FLAG_MASS_KG] + dog.notes = json[cls.FLAG_NOTES] + dog.active = json[cls.FLAG_ACTIVE] + Helper_App.console_log(f'Dog: {dog}') + return dog + + + def to_json(self): + as_json = { + self.FLAG_DOG: self.id_dog + , self.FLAG_NAME: self.name + , self.FLAG_APPEARANCE: self.appearance + , self.FLAG_MASS_KG: self.mass_kg + , self.FLAG_NOTES: self.notes + , self.FLAG_ACTIVE: self.active + } + Helper_App.console_log(f'as_json: {as_json}') + return as_json + + def __repr__(self): + return f''' +{self.__class__.__name__}( + {self.FLAG_DOG}: {self.id_dog} + {self.FLAG_NAME}: {self.name} + {self.FLAG_APPEARANCE}: {self.appearance} + {self.FLAG_MASS_KG}: {self.mass_kg} + {self.FLAG_NOTES}: {self.notes} + {self.FLAG_ACTIVE}: {self.active} +) + ''' + +""" +class Dog_Temp(db.Model, Base): + __tablename__ = 'PH_Dog_Temp' + __table_args__ = { 'extend_existing': True } + id_temp = db.Column(db.Integer, primary_key=True) + id_dog = db.Column(db.Integer) + email = db.Column(db.String(250)) + name_contact = db.Column(db.String(250)) + name_company = db.Column(db.String(250)) + message = db.Column(db.Text) + receive_marketing_communications = db.Column(db.Boolean) + active = db.Column(db.Boolean) + created_on = db.Column(db.DateTime) + guid: str = db.Column(db.String(36)) + + def __init__(self): + super().__init__() + + @classmethod + def from_dog(cls, dog): + _m = 'Dog_Temp.from_Dog' + temp = cls() + temp.id_dog = dog.id_dog + temp.email = dog.email + temp.name_contact = dog.name_contact + temp.name_company = dog.name_company + temp.message = dog.message + temp.receive_marketing_communications = dog.receive_marketing_communications + temp.active = dog.active + temp.created_on = dog.created_on + return temp +""" \ No newline at end of file diff --git a/business_objects/dog/user.py b/business_objects/dog/user.py new file mode 100644 index 0000000..3f93c02 --- /dev/null +++ b/business_objects/dog/user.py @@ -0,0 +1,133 @@ +""" +Project: PARTS Website +Author: Edward Middleton-Smith + Precision And Research Technology Systems Limited + +Technology: Business Objects +Feature: User Business Object +""" + +# internal +from business_objects.base import Base +from business_objects.db_base import SQLAlchemy_ABC +import lib.argument_validation as av +from forms.forms import Form_Contact +from extensions import db +from helpers.helper_app import Helper_App +# external +from dataclasses import dataclass +from typing import ClassVar + + +class User(SQLAlchemy_ABC, Base): + NAME_ATTR_OPTION_VALUE: ClassVar[str] = Base.ATTR_ID_USER + NAME_ATTR_OPTION_TEXT: ClassVar[str] = 'email' + + __tablename__ = 'PH_User' + __table_args__ = { 'extend_existing': True } + + id_user = db.Column(db.Integer, primary_key=True) + id_user_auth0 = db.Column(db.String(250)) + firstname = db.Column(db.String(250)) + surname = db.Column(db.String(250)) + email = db.Column(db.String(250)) + is_email_verified = db.Column(db.Boolean) + is_super_user = db.Column(db.Boolean) + is_new = db.Column(db.Boolean) + + def __init__(self): + self.id_user = 0 + self.is_new = False + super().__init__() + + def from_DB_user(query_row): + _m = 'User.from_DB_user' + user = User() + user.id_user = query_row[0] + user.id_user_auth0 = query_row[1] + user.firstname = query_row[2] + user.surname = query_row[3] + user.email = query_row[4] + user.is_email_verified = av.input_bool(query_row[5], 'is_email_verified', _m) + user.is_super_user = av.input_bool(query_row[9], 'is_super_user', _m) + user.is_new = av.input_bool(query_row[12], 'is_new', _m) + return user + + @staticmethod + def from_json(json): + _m = 'User.from_json' + user = User() + if json is None: return user + Helper_App.console_log(f'{_m}\njson: {json}') + user.id_user = json['id_user'] + user.id_user_auth0 = json['id_user_auth0'] + user.firstname = json['firstname'] + user.surname = json['surname'] + user.email = json['email'] + user.is_email_verified = av.input_bool(json['is_email_verified'], 'is_email_verified', _m) + user.is_super_user = av.input_bool(json['is_super_user'], 'is_super_user', _m) + Helper_App.console_log(f'user: {user}') + return user + + @staticmethod + def from_json_auth0(json): + _m = 'User.from_json_auth0' + user = User() + if json is None: return user + Helper_App.console_log(f'{_m}\njson: {json}') + user_info = json['userinfo'] + user.id_user = None + user.id_user_auth0 = user_info['sub'] + user.firstname = None + user.surname = None + user.email = user_info['email'] + user.is_email_verified = av.input_bool(user_info['email_verified'], 'is_email_verified', _m) + user.is_super_user = None + Helper_App.console_log(f'user: {user}') + return user + + def to_json(self): + as_json = { + 'id_user': self.id_user, + 'id_user_auth0': self.id_user_auth0, + 'firstname': self.firstname, + 'surname': self.surname, + 'email': self.email, + 'is_email_verified': self.is_email_verified, + 'is_super_user': self.is_super_user + } + Helper_App.console_log(f'as_json: {as_json}') + return as_json + + def __repr__(self): + return f''' + id_user: {self.id_user} + id_user_auth0: {self.id_user_auth0} + firstname: {self.firstname} + surname: {self.surname} + email: {self.email} + is_email_verified: {self.is_email_verified} + is_super_user: {self.is_super_user} + ''' + + def get_is_logged_in(self): + return (self.id_user > 0 and self.id_user != Base.ID_USER_GUEST) + +class User_Temp(db.Model, Base): + __tablename__ = 'Shop_User_Temp' + __table_args__ = { 'extend_existing': True } + id_user = db.Column(db.Integer, primary_key=True) + id_user_auth0 = db.Column(db.String(250)) + firstname = db.Column(db.String(250)) + surname = db.Column(db.String(250)) + email = db.Column(db.String(250)) + is_email_verified = db.Column(db.Boolean) + is_super_user = db.Column(db.Boolean) + id_currency_default = db.Column(db.Integer) + id_region_default = db.Column(db.Integer) + is_included_VAT_default = db.Column(db.Boolean) + # is_logged_in: bool + + def __init__(self): + self.id_user = 0 + super().__init__() \ No newline at end of file diff --git a/business_objects/sql_error.py b/business_objects/sql_error.py new file mode 100644 index 0000000..1b562b2 --- /dev/null +++ b/business_objects/sql_error.py @@ -0,0 +1,69 @@ +""" +Project: PARTS Website +Author: Edward Middleton-Smith + Precision And Research Technology Systems Limited + +Technology: Business Objects +Feature: SQL Error Business Object + +Description: +Business object for SQL errors returned by Get Many Stored Procedures +""" + +# internal +from business_objects.base import Base +import lib.argument_validation as av +from lib import data_types +from forms.forms import Form_Basket_Add, Form_Basket_Edit # Form_Product +# external +from enum import Enum +from datetime import datetime, timedelta +import locale +from flask_sqlalchemy import SQLAlchemy + + +db = SQLAlchemy() + + +class SQL_Error(db.Model): + display_order = db.Column(db.Integer, primary_key=True) + id_type = db.Column(db.Integer) + code = db.Column(db.String(50)) + msg = db.Column(db.String(4000)) + name = db.Column(db.String(500)) + description = db.Column(db.String(4000)) + + """ + def __new__(cls, display_order, code, msg): + _m = 'SQL_Error.__new__' + v_arg_type = 'class attribute' + av.val_int(display_order, 'display_order', _m) + av.val_str(code, 'code', _m, max_len=50, v_arg_type=v_arg_type) + av.val_str(msg, 'msg', _m, max_len=4000, v_arg_type=v_arg_type) + return super(SQL_Error, cls).__new__(cls) + + def __init__(self, display_order, code, msg): + self.display_order = display_order + self.code = code + self.msg = msg + super().__init__() + """ + + def from_DB_record(record): + error = SQL_Error() + error.display_order = record[0] + error.id_type = record[1] + error.code = record[2] + error.msg = record[3] + error.name = record[4] + error.description = record[5] + return error + def to_json(self): + return { + Base.FLAG_DISPLAY_ORDER: self.display_order, + Base.ATTR_ID_MSG_ERROR_TYPE: self.id_type, + Base.FLAG_CODE: self.code, + Base.FLAG_MESSAGE: self.msg, + Base.FLAG_NAME: self.name, + Base.FLAG_DESCRIPTION: self.description, + } \ No newline at end of file diff --git a/config.py b/config.py new file mode 100644 index 0000000..bfea46c --- /dev/null +++ b/config.py @@ -0,0 +1,131 @@ +""" +Project: PARTS Website +Author: Edward Middleton-Smith + Precision And Research Technology Systems Limited + +Technology: Backend +Feature: Configuration + +Description: +Configuration variables +""" + +# IMPORTS +import os +from dotenv import load_dotenv, find_dotenv +from flask import current_app + +load_dotenv(find_dotenv()) + +# CLASSES +class Config: + is_development = False + is_production = False + # Miscellaneous + DEBUG = False # av.input_bool(os.getenv('DEBUG'), 'DEBUG', 'Config') + TESTING = False + URL_HOST = os.getenv('URL_HOST') + SECRET_KEY = os.getenv('KEY_SECRET_FLASK') # gen cmd: openssl rand -hex 32 + # Add other configuration variables as needed + # MySQL + SQLALCHEMY_DATABASE_URI = os.getenv('SQLALCHEMY_DATABASE_URI') + SQLALCHEMY_TRACK_MODIFICATIONS = False + SQLALCHEMY_ENGINE_OPTIONS = { + 'pool_size': 10, + 'pool_recycle': 280, + 'pool_pre_ping': True, + 'pool_timeout': 30, + } + # Auth0 + SESSION_COOKIE_SECURE = True + SESSION_COOKIE_HTTPONLY = True + SESSION_COOKIE_SAMESITE = 'Strict' + REMEMBER_COOKIE_SECURE = True + WTF_CSRF_ENABLED = True + # WTF_CSRF_CHECK_DEFAULT = False # We'll check it manually for API routes + # WTF_CSRF_HEADERS = ['X-CSRFToken'] # Accept CSRF token from this header + WTF_CSRF_TIME_LIMIT = None + WTF_CSRF_SSL_STRICT = False # Allows testing without HTTPS + ID_AUTH0_CLIENT = os.getenv('ID_AUTH0_CLIENT') + ID_AUTH0_CLIENT_SECRET = os.getenv('ID_AUTH0_CLIENT_SECRET') + DOMAIN_AUTH0 = os.getenv('DOMAIN_AUTH0') + ID_TOKEN_USER = 'user' + # PostgreSQL + DB_NAME = os.getenv('parts') + DB_USER = os.getenv('DB_USER') + DB_PASSWORD = os.getenv('DB_PASSWORD') + DB_HOST = os.getenv('DB_HOST') + # DB_PORT = os.getenv('DB_PORT') + # Store + # is_included_VAT = True + """ + KEY_IS_INCLUDED_VAT = 'is_included_VAT' + code_currency = 1 + KEY_CODE_CURRENCY = 'id_currency' + code_region_delivery = 1 + KEY_CODE_REGION_DELIVERY = 'id_region_delivery' + KEY_ID_CURRENCY = 'id_currency' + KEY_ID_REGION_DELIVERY = 'id_region_delivery' + """ + # id_currency = 1 + # id_region_delivery = 1 + # Mail + MAIL_DEBUG = False # av.input_bool(os.getenv('DEBUG'), 'DEBUG', 'Config') + MAIL_SERVER = 'mail.partsltd.co.uk' # 'smtp.gmail.com' + MAIL_PORT = 465 # 587 + MAIL_USE_TLS = False + MAIL_USE_SSL = True + MAIL_USERNAME = os.getenv('MAIL_DEFAULT_SENDER') + MAIL_PASSWORD = os.getenv('MAIL_PASSWORD') + MAIL_DEFAULT_SENDER = os.getenv('MAIL_DEFAULT_SENDER') + MAIL_CONTACT_PUBLIC = os.getenv('MAIL_CONTACT_PUBLIC') + """ + # Recaptcha + RECAPTCHA_PUBLIC_KEY = os.getenv('RECAPTCHA_PUBLIC_KEY') + RECAPTCHA_PRIVATE_KEY = os.getenv('RECAPTCHA_PRIVATE_KEY') + """ + # ALTCHA + ALTCHA_API_KEY = os.getenv('ALTCHA_API_KEY') + ALTCHA_SECRET_KEY = os.getenv('ALTCHA_SECRET_KEY') + ALTCHA_REGION = 'eu' + +class DevelopmentConfig(Config): + is_development = True + # Add development-specific configuration variables + DEBUG = True + MAIL_DEBUG = True + SESSION_COOKIE_SECURE = False + +class ProductionConfig(Config): + is_production = True + # Add production-specific configuration variables + pass + +# Set the configuration class based on the environment +# You can change 'development' to 'production' when deploying +config_env = os.getenv('FLASK_ENV', "development") +with open('app.log', 'a') as f: + print(f'config_env: {config_env}') + f.write(f'config_env: {config_env}\n') + # current_app.logger.error(f'config_env: {config_env}') # logger not yet initialised +if config_env == 'development': + app_config = DevelopmentConfig +elif config_env == 'production': + app_config = ProductionConfig +else: + raise ValueError("Invalid configuration environment") + +# environment variables +""" +SET KEY_SECRET_FLASK=nips +SET ID_AUTH0_CLIENT= +SET ID_AUTH0_CLIENT_SECRET= +SET DOMAIN_AUTH0= +SET MAIL_PASSWORD= +SET RECAPTCHA_PUBLIC_KEY= +SET RECAPTCHA_PRIVATE_KEY= +SET SQLALCHEMY_DATABASE_URI= +SET URL_HOST= +""" +# SET SQLALCHEMY_DATABASE_URI = mysql://username:password@localhost/dbname + # Replace 'username', 'password', 'localhost', and 'dbname' with your actual database credentials \ No newline at end of file diff --git a/controllers/__init__.py b/controllers/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/controllers/core/__init__.py b/controllers/core/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/controllers/core/contact.py b/controllers/core/contact.py new file mode 100644 index 0000000..a715fc8 --- /dev/null +++ b/controllers/core/contact.py @@ -0,0 +1,143 @@ +""" +Project: PARTS Website +Author: Edward Middleton-Smith + Precision And Research Technology Systems Limited + +Technology: App Routing +Feature: Core - Contact Routes + +Description: +Contact Page Controller. +""" + +# IMPORTS +# internal +from business_objects.api import API +from business_objects.project_hub.command import Command +from datastores.project_hub.datastore_command import DataStore_Command +from forms.contact import Form_Contact +from helpers.helper_app import Helper_App +from models.model_view_contact import Model_View_Contact +from models.model_view_contact_success import Model_View_Contact_Success +from models.model_view_home import Model_View_Home +import lib.argument_validation as av +# external +from flask import Flask, render_template, jsonify, request, render_template_string, send_from_directory, redirect, url_for, session, Blueprint, current_app, flash +from flask_mail import Mail, Message +from extensions import db, oauth, mail +from urllib.parse import quote_plus, urlencode +from authlib.integrations.flask_client import OAuth +from authlib.integrations.base_client import OAuthError +from urllib.parse import quote, urlparse, parse_qs +import json +import base64 +import hmac +import hashlib +import datetime +from altcha import ChallengeOptions, create_challenge, verify_solution + +routes_core_contact = Blueprint('routes_core_contact', __name__) + + +@routes_core_contact.route(Model_View_Contact.HASH_PAGE_CONTACT, methods=['GET']) +def contact(): + try: + form = Form_Contact() + model = Model_View_Contact(form) + html_body = render_template('pages/core/_contact.html', model = model) + return html_body + except Exception as e: + return API.get_standard_response( + success = False, + status_code = 500, + message = f"Error: {e}", + data = None, + errors = [str(e)], + meta = None + ) + +@routes_core_contact.route(Model_View_Contact.HASH_GET_ALTCHA_CHALLENGE, methods=['GET']) +def create_altcha_challenge(): + options = ChallengeOptions( + expires = datetime.datetime.now() + datetime.timedelta(hours=1), + max_number = 100000, # The maximum random number + hmac_key = current_app.app_config.ALTCHA_SECRET_KEY, + ) + challenge = create_challenge(options) + Helper_App.console_log(f"Challenge created: {challenge}") + # return jsonify({"challenge": challenge}) + return jsonify({ + "algorithm": challenge.algorithm, + "challenge": challenge.challenge, + "salt": challenge.salt, + "signature": challenge.signature, + }) + +@routes_core_contact.route(Model_View_Contact.HASH_PAGE_CONTACT, methods=['POST']) +def contact_post(): + try: + form = Form_Contact() + if form.validate_on_submit(): + try: + email = form.email.data + # CC = form.CC.data # not in use + contact_name = form.contact_name.data + company_name = form.company_name.data + message = form.message.data + receive_marketing = form.receive_marketing.data + receive_marketing_text = "I would like to receive marketing emails.\n" if receive_marketing else "" + # send email + mailItem = Message("PARTS Website Contact Us Message", recipients=[current_app.config['MAIL_CONTACT_PUBLIC']]) + mailItem.body = f"Dear Lord Edward Middleton-Smith,\n\n{message}\n{receive_marketing_text}\nKind regards,\n{contact_name}\n{company_name}\n{email}" + mail.send(mailItem) + # save to database + datastore = DataStore_Command() + command = Command.from_json(form.to_json()) + datastore.save_commands( + comment = command.message + , commands = [command] + ) + return redirect(url_for(Model_View_Contact.ENDPOINT_PAGE_CONTACT_SUCCESS)) + except Exception as e: + return API.get_standard_response( + success = False, + status_code = 500, + message = f"Error: {e}", + data = None, + errors = [str(e)], + meta = None + ) + return API.get_standard_response( + success = False, + status_code = 500, + message = f"Error: {form.errors}", + data = None, + errors = [str(form.errors)], + meta = None + ) + # html_body = render_template('pages/core/_contact.html', model = model) + except Exception as e: + return API.get_standard_response( + success = False, + status_code = 500, + message = f"Error: {e}", + data = None, + errors = [str(e)], + meta = None + ) + +@routes_core_contact.route(Model_View_Contact.HASH_PAGE_CONTACT_SUCCESS, methods=['GET']) +def contact_success(): + try: + model = Model_View_Contact_Success() + html_body = render_template('pages/core/_contact_success.html', model = model) + return html_body + except Exception as e: + return API.get_standard_response( + success = False, + status_code = 500, + message = f"Error: {e}", + data = None, + errors = [str(e)], + meta = None + ) diff --git a/controllers/core/home.py b/controllers/core/home.py new file mode 100644 index 0000000..f299424 --- /dev/null +++ b/controllers/core/home.py @@ -0,0 +1,31 @@ +""" +Project: PARTS Website +Author: Edward Middleton-Smith + Precision And Research Technology Systems Limited + +Technology: App Routing +Feature: Core - Home Routes + +Description: +Home Page Controller. +""" + +# internal +from business_objects.api import API +from models.model_view_home import Model_View_Home +# external +from flask import render_template, jsonify, Blueprint + + +routes_core_home = Blueprint('routes_core_home', __name__) + + +@routes_core_home.route(Model_View_Home.HASH_PAGE_HOME, methods=['GET']) +def home(): + try: + model = Model_View_Home() + html_body = render_template('pages/core/_home.html', model = model) + except Exception as e: + return jsonify(error=str(e)), 403 + return html_body + \ No newline at end of file diff --git a/controllers/legal/__init__.py b/controllers/legal/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/controllers/legal/legal.py b/controllers/legal/legal.py new file mode 100644 index 0000000..4161312 --- /dev/null +++ b/controllers/legal/legal.py @@ -0,0 +1,70 @@ +""" +Project: PARTS Website +Author: Edward Middleton-Smith + Precision And Research Technology Systems Limited + +Technology: App Routing +Feature: Legal Routes + +Description: +Legal Section Controller. +""" + +# IMPORTS +# internal +# from models.model_view_home import Model_View_Home +from models.model_view_license import Model_View_License +from models.model_view_privacy_policy import Model_View_Privacy_Policy +from models.model_view_accessibility_report import Model_View_Accessibility_Report +from models.model_view_accessibility_statement import Model_View_Accessibility_Statement +from models.model_view_retention_schedule import Model_View_Retention_Schedule +import lib.argument_validation as av +# external +from flask import render_template, Blueprint + + +routes_legal = Blueprint('routes_legal', __name__) + + +# snore +@routes_legal.route('/license', methods=['GET']) +def license(): + try: + model = Model_View_License() + html_body = render_template('pages/legal/_license.html', model = model) + except Exception as e: + return str(e) + return html_body +@routes_legal.route('/accessibility-statement', methods=['GET']) +def accessibility_statement(): + try: + model = Model_View_Accessibility_Statement() + html_body = render_template('pages/legal/_accessibility_statement.html', model = model) + except Exception as e: + return str(e) + return html_body +@routes_legal.route('/accessibility-report', methods=['GET']) +def accessibility_report(): + try: + model = Model_View_Accessibility_Report() + html_body = render_template('pages/legal/_accessibility_report.html', model = model) + except Exception as e: + return str(e) + return html_body +@routes_legal.route('/retention-schedule', methods=['GET']) +def retention_schedule(): + try: + model = Model_View_Retention_Schedule() + html_body = render_template('pages/legal/_retention_schedule.html', model = model) + except Exception as e: + return str(e) + return html_body +@routes_legal.route('/privacy-policy', methods=['GET']) +def privacy_policy(): + try: + model = Model_View_Privacy_Policy() + html_body = render_template('pages/legal/_privacy_policy.html', model = model) + except Exception as e: + return str(e) + return html_body + diff --git a/datastores/__init__.py b/datastores/__init__.py new file mode 100644 index 0000000..c05a52e --- /dev/null +++ b/datastores/__init__.py @@ -0,0 +1,11 @@ +""" +Project: PARTS Website +Author: Edward Middleton-Smith + Precision And Research Technology Systems Limited + +Technology: Module Initialisation +Feature: DataStores + +Description: +Initialises datastores module. +""" diff --git a/datastores/datastore_base.py b/datastores/datastore_base.py new file mode 100644 index 0000000..bf9f57f --- /dev/null +++ b/datastores/datastore_base.py @@ -0,0 +1,114 @@ +""" +Project: PARTS Website +Author: Edward Middleton-Smith + Precision And Research Technology Systems Limited + +Technology: DataStores +Feature: Base DataStore + +Description: +Datastore for Store +""" + +# internal +# from routes import bp_home +import lib.argument_validation as av +from business_objects.sql_error import SQL_Error +from business_objects.project_hub.user import User +# from helpers.helper_db_mysql import Helper_DB_MySQL +# from models.model_view_store_checkout import Model_View_Store_Checkout # circular! +from extensions import db +from forms.access_level import Filters_Access_Level +from forms.unit_measurement import Filters_Unit_Measurement +from helpers.helper_app import Helper_App +# external +from sqlalchemy import text +from flask import Flask, session, current_app +from pydantic import BaseModel, ConfigDict +import time +from sqlalchemy.exc import OperationalError + + + +class DataStore_Base(BaseModel): + + def __init__(self, **kwargs): + super().__init__(**kwargs) + + @staticmethod + def db_procedure_execute(proc_name, argument_dict_list = None): + # Argument validation + _m = 'DataStore_Base.db_procedure_execute' + av.val_str(proc_name, 'proc_name', _m) + proc_string = f'CALL {proc_name}(' + has_arguments = not str(type(argument_dict_list)) == "" + if has_arguments: + arg_keys = list(argument_dict_list.keys()) + for i in range(len(arg_keys)): + proc_string += f'{"" if i == 0 else ", "}:{arg_keys[i]}' + proc_string += ')' + proc_string = text(proc_string) + Helper_App.console_log(f'{_m}\nproc_string: {proc_string}\nargs: {argument_dict_list}') + + if has_arguments: + result = db.session.execute(proc_string, argument_dict_list) + else: + result = db.session.execute(proc_string) + Helper_App.console_log(f'result: {result}') + # conn.session.remove() + return result + + @staticmethod + def db_cursor_clear(cursor): + while cursor.nextset(): + Helper_App.console_log(f'new result set: {cursor.fetchall()}') + + @staticmethod + def get_user_session(): + Helper_App.console_log('DataStore_Base.get_user_session') + user = User.from_json(session.get(User.FLAG_USER)) + if user.id_user <= 0: + user.id_user = 3 + return user + + @staticmethod + def upload_bulk(permanent_table_name, records, batch_size): + _m = 'DataStore_Base.upload_bulk' + Helper_App.console_log(f'{_m}\nstarting...') + Helper_App.console_log(f'permanent_table_name: {permanent_table_name}') + if db.session.dirty or db.session.new or db.session.deleted: + Helper_App.console_log("Session is not clean") + return + # Assuming `permanent_table_name` is a string representing the table name + table_object = db.metadata.tables.get(permanent_table_name) + if table_object is None: + Helper_App.console_log(f"Table {permanent_table_name} not found in metadata.") + return + else: + expected_columns = set(column.name for column in db.inspect(table_object).columns) + Helper_App.console_log(f'expected_columns: {expected_columns}') + max_retries = 3 + initial_backoff = 1 + for i in range(0, len(records), batch_size): + batch = records[i:i + batch_size] + try: + retries = 0 + while retries < max_retries: + try: + db.session.bulk_save_objects(batch) + db.session.commit() + break + except OperationalError as e: + if "Lock wait timeout exceeded" not in str(e) or retries == max_retries - 1: + raise + + wait_time = initial_backoff * (2 ** retries) + current_app.logger.warning(f"Lock timeout encountered. Retrying in {wait_time} seconds... (Attempt {retries + 1}/{max_retries})") + time.sleep(wait_time) + retries += 1 + + # Ensure the session is clean for the retry + db.session.rollback() + except Exception as e: + db.session.rollback() + raise e diff --git a/datastores/project_hub/datastore_contact_form.py b/datastores/project_hub/datastore_contact_form.py new file mode 100644 index 0000000..5e85411 --- /dev/null +++ b/datastores/project_hub/datastore_contact_form.py @@ -0,0 +1,113 @@ +""" +Project: PARTS Website +Author: Edward Middleton-Smith + Precision And Research Technology Systems Limited + +Technology: DataStores +Feature: User DataStore + +Description: +Datastore for Users +""" + +# internal +# from routes import bp_home +import lib.argument_validation as av +from business_objects.sql_error import SQL_Error +from business_objects.project_hub.command import Command, Command_Temp +from datastores.datastore_base import DataStore_Base +from helpers.helper_app import Helper_App +from helpers.helper_db_mysql import Helper_DB_MySQL +# from models.model_view_store_checkout import Model_View_Store_Checkout # circular! +from extensions import db +# external +from flask_sqlalchemy import SQLAlchemy +from datetime import datetime + +db = SQLAlchemy() + + +class DataStore_Command(DataStore_Base): + + def __init__(self): + super().__init__() + + @classmethod + def get_many_command(cls): + _m = f'{cls.__qualname__}.get_many_command' + user = cls.get_user_session() + argument_dict = { + 'a_id_user': user.id_user + , 'a_debug': 0 + } + Helper_App.console_log(f'argument_dict: {argument_dict}') + result = cls.db_procedure_execute('p_ph_get_many_command', argument_dict) + cursor = result.cursor + + # Commands + result_set_1 = cursor.fetchall() + Helper_App.console_log(f'raw commands: {result_set_1}') + commands = [] + command_indexes = {} + for row in result_set_1: + new_command = Command.from_DB_command(row) + command_indexes[new_command.id_command] = len(commands) + commands.append(new_command) + + # Errors + cursor.nextset() + result_set_e = cursor.fetchall() + Helper_App.console_log(f'raw errors: {result_set_e}') + errors = [] + if len(result_set_e) > 0: + errors = [SQL_Error.from_DB_record(row) for row in result_set_e] + for error in errors: + Helper_App.console_log(f"Error [{error.code}]: {error.msg}") + + cls.db_cursor_clear(cursor) + + return commands, errors + + @classmethod + def save_commands(cls, comment, commands): + _m = f'{cls}.save_commands' + av.val_str(comment, 'comment', _m) + + guid = Helper_DB_MySQL.create_guid_str() + now = datetime.now() + user = cls.get_user_session() + + Helper_App.console_log(f'saving commands: {commands}') + + rows = [] + for command in commands: + row = Command_Temp.from_command(command) + row.guid = guid + rows.append(row) + + cls.upload_bulk(Command_Temp.__tablename__, rows, 1000) + + Helper_App.console_log('Commands uploaded') + + argument_dict_list = { + 'a_comment': comment, + 'a_guid': guid, + 'a_id_user': user.id_user, + 'a_debug': 0 + } + result = cls.db_procedure_execute('p_ph_save_command', argument_dict_list) + + Helper_App.console_log('Commands saved') + + # Errors + cursor = result.cursor + cursor.nextset() + result_set_e = cursor.fetchall() + errors = [] + if len(result_set_e) > 0: + errors = [SQL_Error.from_DB_record(row) for row in result_set_e] + for error in errors: + Helper_App.console_log(f"Error [{error.code}]: {error.msg}") + + cls.db_cursor_clear(cursor) + return errors diff --git a/extensions.py b/extensions.py new file mode 100644 index 0000000..1c15f0c --- /dev/null +++ b/extensions.py @@ -0,0 +1,14 @@ + +from flask import Flask, render_template, jsonify, request, render_template_string, send_from_directory, redirect, url_for, session, current_app +from flask_cors import CORS +from flask_sqlalchemy import SQLAlchemy +from flask_mail import Mail, Message +from flask_wtf.csrf import CSRFProtect +from authlib.integrations.flask_client import OAuth + + +csrf = CSRFProtect() +# cors = CORS() +db = SQLAlchemy() +mail = Mail() +oauth = OAuth() \ No newline at end of file diff --git a/forms/__init__.py b/forms/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/forms/access_level.py b/forms/access_level.py new file mode 100644 index 0000000..5fd6f2f --- /dev/null +++ b/forms/access_level.py @@ -0,0 +1,37 @@ +""" +Project: PARTS Website +Author: Edward Middleton-Smith + Precision And Research Technology Systems Limited + +Technology: Backend +Feature: Forms - Access Level Filters data input + +Description: +Defines Flask-WTF forms for handling access level filter input. +""" + +# internal +from business_objects.base import Base +from forms.base import Form_Base +import lib.argument_validation as av +# external +from flask_wtf import FlaskForm +from wtforms import StringField, TextAreaField, SubmitField, BooleanField, IntegerField, SelectField, FloatField +from wtforms.validators import InputRequired, NumberRange, Regexp, DataRequired, Optional +from flask_wtf.recaptcha import RecaptchaField +from abc import ABCMeta, abstractmethod + + +class Filters_Access_Level(Form_Base): + active = BooleanField("Active only?", default = True) + def __repr__(self): + return f'{self.__class__.__name__}(active={self.active.data})' + @classmethod + def from_json(cls, json): + form = Filters_Access_Level() + form.active.data = av.input_bool(json[Base.FLAG_ACTIVE], Base.FLAG_ACTIVE, f'{cls.__name__}.from_json') + return form + def to_json(self): + return { + Base.FLAG_ACTIVE: 1 if av.input_bool(self.active.data, Base.FLAG_ACTIVE, f'{self.__class__.__name__}.to_json') else 0, + } \ No newline at end of file diff --git a/forms/base.py b/forms/base.py new file mode 100644 index 0000000..567803a --- /dev/null +++ b/forms/base.py @@ -0,0 +1,78 @@ +""" +Project: PARTS Website +Author: Edward Middleton-Smith + Precision And Research Technology Systems Limited + +Technology: Backend +Feature: Form Base and Meta Classes - data input + +Description: +Defines Flask-WTF base forms for handling user input. +""" + +# internal +# external +from flask_wtf import FlaskForm +from abc import ABCMeta, abstractmethod + + +class Form_Base_Meta(type(FlaskForm), ABCMeta): + pass + + +class Form_Base(FlaskForm, metaclass=Form_Base_Meta): + """ + @classmethod + @abstractmethod + def from_filters(cls, filters): + pass + @abstractmethod + def __repr__(self): + pass + """ + def __repr__(self): + fields = ', '.join( + f"{name}={field.data}" for name, field in self._fields.items() + ) + return f"{self.__class__.__name__}({fields})" + @classmethod + @abstractmethod + def from_json(cls, json): + pass + @classmethod + def get_default(cls): + return cls() + """ + @abstractmethod + def test_69(self): + pass + + def get_Filters_Product_Category(data_request): + data_form = data_request[Model_View_Store_Product_Category.FLAG_FORM] + form_filters = Filters_Product_Category(**data_form) + form_filters.is_not_empty.data = av.input_bool(data_form['is_not_empty'], 'is_not_empty', 'filter_category') + form_filters.active.data = av.input_bool(data_form['active'], 'active', 'filter_category') + return form_filters + """ + @classmethod + def get_choices_blank(cls): + return [('', 'Select')] + @classmethod + def get_choice_all(cls): + return ('', 'All') + +''' +class Filters_Stored_Procedure_Base(Form_Base): + """ + @abstractmethod + def __repr__(self): + pass + @classmethod + @abstractmethod + def from_json(cls, json): + pass + """ + @abstractmethod + def to_json(self): + pass +''' \ No newline at end of file diff --git a/forms/contact.py b/forms/contact.py new file mode 100644 index 0000000..df5f0ed --- /dev/null +++ b/forms/contact.py @@ -0,0 +1,100 @@ +""" +Project: PARTS Website +Author: Edward Middleton-Smith + Precision And Research Technology Systems Limited + +Technology: Backend +Feature: Contact Us Form + +Description: +Defines Flask-WTF form for handling user input on Contact Us page. +""" + +# IMPORTS +# internal +from business_objects.base import Base +from business_objects.project_hub.command import Command +# from models.model_view_store import Model_View_Store # circular +from models.model_view_base import Model_View_Base +from forms.base import Form_Base +# external +from flask import Flask, render_template, request, flash, redirect, url_for, current_app +from flask_wtf import FlaskForm +from wtforms import StringField, TextAreaField, SubmitField, HiddenField, BooleanField, Field, EmailField +from wtforms.validators import DataRequired, Email, ValidationError +import markupsafe +from flask_wtf.recaptcha import RecaptchaField +from abc import ABCMeta, abstractmethod +import json +from altcha import verify_solution +import base64 + +class ALTCHAValidator: + def __init__(self, message=None): + self.message = message or 'ALTCHA verification failed' + + def __call__(self, form, field): + altcha_data = field.data + + if not altcha_data: + raise ValidationError(self.message) + + try: + # The data is base64 encoded JSON + try: + # First try to decode it as JSON directly (if it's not base64 encoded) + altcha_payload = json.loads(altcha_data) + except json.JSONDecodeError: + # If direct JSON decoding fails, try base64 decoding first + decoded_data = base64.b64decode(altcha_data).decode('utf-8') + altcha_payload = json.loads(decoded_data) + + ok, err = verify_solution(altcha_payload, current_app.app_config.ALTCHA_SECRET_KEY, check_expires=True) + + if err or not ok: + raise ValidationError(self.message + ': ' + (err or 'Invalid solution')) + + except Exception as e: + raise ValidationError(f'Invalid ALTCHA data: {str(e)}') + +class ALTCHAField(Field): + def __init__(self, label='', validators=None, **kwargs): + validators = validators or [] + validators.append(ALTCHAValidator()) + + super(ALTCHAField, self).__init__(label, validators, **kwargs) + + def __call__(self, **kwargs): + html = f""" + + + """ + return markupsafe.Markup(html) + + +class Form_Contact(FlaskForm): + email = EmailField('Email') + contact_name = StringField('Name') + company_name = StringField('Company') + message = TextAreaField('Message') + receive_marketing = BooleanField('I would like to receive marketing emails.') + # recaptcha = RecaptchaField() + # altcha = HiddenField('ALTCHA') # , validators=[validate_altcha] + altcha = ALTCHAField('Verify you are human') + submit = SubmitField('Send Message') + + def to_json(self): + return { + Base.FLAG_EMAIL: self.email.data + , Command.FLAG_NAME_CONTACT: self.contact_name.data + , Command.FLAG_NAME_COMPANY: self.company_name.data + , Command.FLAG_MESSAGE: self.message.data + , Command.FLAG_RECEIVE_MARKETING_COMMUNICATIONS: self.receive_marketing.data + , Command.FLAG_ALTCHA: self.altcha.data + , Base.FLAG_ACTIVE: True + , Base.FLAG_CREATED_ON: None + } diff --git a/forms/forms.py b/forms/forms.py new file mode 100644 index 0000000..9341971 --- /dev/null +++ b/forms/forms.py @@ -0,0 +1,134 @@ +""" +Project: PARTS Website +Author: Edward Middleton-Smith + Precision And Research Technology Systems Limited + +Technology: Backend +Feature: Forms - User data input + +Description: +Defines Flask-WTF forms for handling user input. +""" + +# IMPORTS +# internal +# from business_objects.store.product_category import Filters_Product_Category # circular +# from models.model_view_store import Model_View_Store # circular +from forms.base import Form_Base +# external +from flask_wtf import FlaskForm +from wtforms import StringField, TextAreaField, SubmitField, BooleanField, IntegerField, SelectField, FloatField +from wtforms.validators import InputRequired, NumberRange, Regexp, DataRequired, Optional +from flask_wtf.recaptcha import RecaptchaField +from abc import ABCMeta, abstractmethod + + + +class Form_Contact(FlaskForm): + email = StringField('Email address') + CC = BooleanField('Would you like to receive a copy of this email request?') # not in use + name = StringField('Name') + message = TextAreaField('Message') + recaptcha = RecaptchaField() + submit = SubmitField('Submit') + +class Form_Register(FlaskForm): + email = StringField('Email address') + CC = BooleanField('Would you like to receive a copy of this email request?') # not in use + name = StringField('Name') + message = TextAreaField('Message') + submit = SubmitField('Submit') + + +""" +class Form_Product(FlaskForm): # for basket, product tiles, product add + # PositiveIntegerField with validation constraints + quantity = IntegerField( + 'Quantity', + validators=[ + # InputRequired(message='Quantity'), + NumberRange(min=1, message='Please enter a positive integer') + ], + default=1 + ) +""" + +class Form_Basket_Add(FlaskForm): # for basket, product tiles, product add + # PositiveIntegerField with validation constraints + quantity = IntegerField( + 'Quantity', + validators=[ + # InputRequired(message='Quantity'), + NumberRange(min=1, message='Please enter a positive integer') + ], + default=1 + # render_kw={'id-product': ''} # {Model_View_Store.attr_id_product: ''} + ) + submit = SubmitField('Add') + form_type = 'Form_Basket_Add' + +class Form_Basket_Edit(FlaskForm): # for basket, product tiles, product add + # PositiveIntegerField with validation constraints + quantity = IntegerField( + 'Quantity', + validators=[ + # InputRequired(message='Quantity'), + NumberRange(min=1, message='Please enter a positive integer') + ], + default=1 + # render_kw={'id-product': ''} # {Model_View_Store.attr_id_product: ''} + ) + submit = SubmitField('Update') + form_type = 'Form_Basket_Edit' + +class Form_Billing(FlaskForm): + identical = BooleanField('Use delivery address') + region = SelectField('Country / region', choices=[('uk', 'UK'), ('international', 'International')], validators=[DataRequired()]) + name_full = StringField('Full name') + phone_number = StringField('Phone number', validators=[Regexp(r'^\+?[0-9\s]{5,20}$', message='Only numbers, plus symbol, and space are allowed.'), DataRequired()]) + postcode = StringField('Post code', validators=[DataRequired()]) + address_1 = StringField('Address line 1', validators=[DataRequired()]) + address_2 = StringField('Address line 2 (optional)') + city = StringField('City', validators=[DataRequired()]) + county = StringField('County', validators=[DataRequired()]) + submit = SubmitField('Submit') + form_type_billing_not_delivery = False + + def output_id(self): + return 'formBilling' if self.form_type_billing_not_delivery else 'formDeliver' + +class Form_Is_Included_VAT(FlaskForm): + is_included = BooleanField('Include VAT') + +class Form_Delivery_Region(FlaskForm): + id_id_region_delivery = 'id_region_delivery' + id_region_delivery = SelectField('Region', id='id_region_delivery') + +class Form_Currency(FlaskForm): + id_id_currency = 'id_currency' + id_currency = SelectField('Currency', id='id_currency') + + +# Store +class Form_Supplier(FlaskForm): + id_id_supplier = 'id_supplier' + id_supplier = SelectField('Supplier', id='id_supplier') + name_company = StringField('Company name') + name_contact = StringField('Contact name') + department_contact = StringField('Contact department') + id_address = SelectField('Address ID') + phone_number = StringField('Phone number') + email = StringField('Email address') + fax = StringField('Fax number') + website = StringField('Website') + id_currency = SelectField('Currency ID') + is_active = BooleanField('Active', default = True) + +# class Form_Supplier_Purchase_Order(FlaskForm): + + + +# User +class Form_Filters_User(FlaskForm): + active = BooleanField('Active only?', default = True) + id_user = SelectField('User ID', validators=[Optional()], choices=[]) \ No newline at end of file diff --git a/forms/unit_measurement.py b/forms/unit_measurement.py new file mode 100644 index 0000000..720da3e --- /dev/null +++ b/forms/unit_measurement.py @@ -0,0 +1,42 @@ +""" +Project: PARTS Website +Author: Edward Middleton-Smith + Precision And Research Technology Systems Limited + +Technology: Backend +Feature: Forms - Unit of Measurement Filters data input + +Description: +Defines Flask-WTF forms for handling unit of measurement filter input. +""" + +# internal +from business_objects.base import Base +from forms.base import Form_Base +import lib.argument_validation as av +# external +from flask_wtf import FlaskForm +from wtforms import StringField, TextAreaField, SubmitField, BooleanField, IntegerField, SelectField, FloatField +from wtforms.validators import InputRequired, NumberRange, Regexp, DataRequired, Optional +from flask_wtf.recaptcha import RecaptchaField +from abc import ABCMeta, abstractmethod + + +class Filters_Unit_Measurement(Form_Base): + active = BooleanField("Active only?", default = True) + @classmethod + def from_filters(cls, filters): + form = Filters_Unit_Measurement() + form.active.data = filters.active + return form + def __repr__(self): + return f'Filters_Unit_Measurement(active={self.active.data})' + @classmethod + def from_json(cls, json): + form = Filters_Unit_Measurement() + form.active.data = av.input_bool(json[Base.FLAG_ACTIVE], 'active', 'Filters_Unit_Measurement') + return form + def to_json(self): + return { + Base.FLAG_ACTIVE: av.input_bool(self.active.data, Base.FLAG_ACTIVE, f'{self.__class__.__name__}.to_json'), + } \ No newline at end of file diff --git a/helpers/__init__.py b/helpers/__init__.py new file mode 100644 index 0000000..54cd370 --- /dev/null +++ b/helpers/__init__.py @@ -0,0 +1,11 @@ +""" +Project: PARTS Website +Author: Edward Middleton-Smith + Precision And Research Technology Systems Limited + +Technology: Module Initialisation +Feature: Helpers + +Description: +Initialises helpers module. +""" diff --git a/helpers/helper_app.py b/helpers/helper_app.py new file mode 100644 index 0000000..793812c --- /dev/null +++ b/helpers/helper_app.py @@ -0,0 +1,43 @@ +""" +Project: PARTS Website +Author: Edward Middleton-Smith + Precision And Research Technology Systems Limited + +Technology: Helpers +Feature: App Helper +""" + +# internal + +# external +from pydantic import BaseModel, ConfigDict +from flask import current_app +# from flask_sqlalchemy import SQLAlchemy + + +class Helper_App(BaseModel): + + @staticmethod + def get_request_data(request): + Helper_App.console_log(f'request={request}') + data = {} + try: + data = request.json + except: + try: + data = request.data + except: + try: + data = request.form + except: + pass + Helper_App.console_log(f'data={data}') + return data + + @staticmethod + def console_log(message): + if current_app.app_config.is_development: + print(message) + elif current_app.app_config.is_production: + pass + current_app.logger.info(message) \ No newline at end of file diff --git a/helpers/helper_db_mysql.py b/helpers/helper_db_mysql.py new file mode 100644 index 0000000..b7801af --- /dev/null +++ b/helpers/helper_db_mysql.py @@ -0,0 +1,42 @@ +""" +Project: PARTS Website +Author: Edward Middleton-Smith + Precision And Research Technology Systems Limited + +Technology: Helpers +Feature: MySQL Database Helper + +Notes: This architecture does not work with Flask-SQLAlchemy - db connection must be initialised with Flask app initialisation +""" + +# internal + +# external +from pydantic import BaseModel, ConfigDict +from flask import Flask, render_template, jsonify, request, render_template_string, send_from_directory, redirect, url_for, session +from flask_sqlalchemy import SQLAlchemy +import uuid + +class Helper_DB_MySQL(BaseModel): + app: Flask + + model_config = ConfigDict(arbitrary_types_allowed=True) + + def __init__(self, app): + super().__init__(app=app) + # self.app = app + + def get_db_connection(self): + db = SQLAlchemy() + db.init_app(self.app) + with self.app.app_context(): + db.create_all() + db.engine.url = self.app.config['SQLALCHEMY_DATABASE_URI'] + return db + + @staticmethod + def create_guid_str(): + return str(uuid.uuid4()) + @staticmethod + def create_guid(): + return uuid.uuid4().bytes \ No newline at end of file diff --git a/lib/__init__.py b/lib/__init__.py new file mode 100644 index 0000000..1b31e3f --- /dev/null +++ b/lib/__init__.py @@ -0,0 +1,11 @@ +""" +Project: PARTS Website +Author: Edward Middleton-Smith + Precision And Research Technology Systems Limited + +Technology: Module Initialisation +Feature: Library + +Description: +Initialises library module. +""" diff --git a/lib/argument_validation.py b/lib/argument_validation.py new file mode 100644 index 0000000..6a9081a --- /dev/null +++ b/lib/argument_validation.py @@ -0,0 +1,1301 @@ +# -*- coding: utf-8 -*- +""" +Created on Thu Apr 27 12:33:59 2023 + +@author: Edward Middleton-Smith + +Argument Validation +""" + +from helpers.helper_app import Helper_App +from typing import Optional + +def error_msg_str(v, v_name, method, v_type, suppress_errors = False, suppress_console_outputs = False, v_arg_type = 'argument'): +# FUNCTION + # return error message string for output of invalid argument / attribute to user +# ARGUMENTS + # str method - name of parent method which calls this function + # str arg_name - name of argument throwing error + # ? v - erroneous variable + # str v_type - desired / expected variable type + # str arg_type - e.g. argument, attribute + # bool suppress_errors - should outputs not be raised as errors? + # bool suppress_console_outputs +# ARGUMENT VALIDATION + my_f = 'error_msg_str' + # suppress_errors + if not val_bool(suppress_errors, 'suppress_errors', my_f): + error_msg = error_msg_str(suppress_errors, 'suppress_errors', my_f, "") + raise ValueError(error_msg) + # suppress_console_outputs + if not val_bool(suppress_console_outputs, 'suppress_console_outputs', my_f, suppress_errors): + error_msg = error_msg_str(suppress_console_outputs, 'suppress_console_outputs', my_f, "", suppress_errors) + if suppress_errors: + Helper_App.console_log(error_msg) + return error_msg + else: + raise ValueError(error_msg) + # method + if not val_str(method, 'method', my_f, suppress_errors=suppress_errors, suppress_console_outputs=suppress_console_outputs): + error_msg = error_msg_str(method, 'method', my_f, "", suppress_errors, suppress_console_outputs) + if suppress_errors: + if not suppress_console_outputs: + Helper_App.console_log(error_msg) + return error_msg + else: + raise ValueError(error_msg) + my_f = method + '.' + my_f + # v_name + if not val_str(v_name, 'v_name', my_f, -1, -1, suppress_errors, suppress_console_outputs): + error_msg = error_msg_str(v_name, 'v_name', my_f, "", suppress_errors, suppress_console_outputs) + if suppress_errors: + if not suppress_console_outputs: + Helper_App.console_log(error_msg) + return error_msg + else: + raise ValueError(error_msg) + # v_type + if isinstance(v_type, type): + v_type = str(v_type) + if not val_str(v_type, 'v_type', my_f, -1, -1, suppress_errors, suppress_console_outputs): + error_msg = error_msg_str(v_type, 'v_type', my_f, "", suppress_errors, suppress_console_outputs) + if suppress_errors: + if not suppress_console_outputs: + Helper_App.console_log(error_msg) + return error_msg + else: + raise ValueError(error_msg) + # v_arg_type + if not val_str(v_arg_type, 'v_arg_type', my_f, -1, -1, suppress_errors, suppress_console_outputs): + error_msg = error_msg_str(v_arg_type, 'v_arg_type', my_f, "", suppress_errors, suppress_console_outputs) + if suppress_errors: + if not suppress_console_outputs: + Helper_App.console_log(error_msg) + return error_msg + else: + raise ValueError(error_msg) +# RETURNS + return f"Invalid {method} {v_type} {v_arg_type} {v_name}. Type = {str(type(v))}. Value = {v}" + +def val_bool(v_input, v_name, method, suppress_errors = False, suppress_console_outputs = False, v_arg_type = 'argument'): +# FUNCTION + # validate that myinput is of type bool +# ARGUMENTS + # bool (hopefully) myinput + # str v_name + # str method + # optional bool suppress_errors + # optional bool suppress_console_outputs + # optional str v_arg_type +# ARGUMENT VALIDATION + # validate bool inputs first + v_type = "" + my_f = 'val_bool' + if str(type(suppress_errors)) != v_type: + raise ValueError(error_msg_str(suppress_errors, 'suppress_errors', my_f, v_type)) + if str(type(suppress_console_outputs)) != v_type: + error_msg = error_msg_str(suppress_console_outputs, 'suppress_console_outputs', my_f, v_type, suppress_errors) + if suppress_errors: + Helper_App.console_log(error_msg) + return False + raise ValueError(error_msg) + v_type = "" + # method + valid = True + if str(type(method)) != v_type: + valid = False + else: + if len(method) < 1: + valid = False + if not valid: + error_msg = error_msg_str(method, 'method', my_f, v_type, suppress_errors, suppress_console_outputs) + if suppress_errors: + if not suppress_console_outputs: + Helper_App.console_log(error_msg) + return False + raise ValueError(error_msg) + my_f = method + '.' + my_f + # v_name + valid = True + if str(type(v_name)) != v_type: + valid = False + else: + if len(v_name) < 1: + valid = False + if not valid: + error_msg = error_msg_str(v_name, 'v_name', my_f, v_type, suppress_errors, suppress_console_outputs) + if suppress_errors: + if not suppress_console_outputs: + Helper_App.console_log(error_msg) + return False + raise ValueError(error_msg) + # v_arg_type + valid = True + if str(type(v_arg_type)) != v_type: + valid = False + else: + if len(v_arg_type) < 1: + valid = False + if not valid: + error_msg = error_msg_str(v_arg_type, 'v_arg_type', my_f, v_type, suppress_errors, suppress_console_outputs) + if suppress_errors: + if not suppress_console_outputs: + Helper_App.console_log(error_msg) + return False + else: + raise ValueError(error_msg) + # v_input + v_type = "" + if (str(type(v_input)) != v_type): + error_msg = error_msg_str(v_input, v_name, method, v_type, suppress_errors, suppress_console_outputs) + if suppress_errors: + if not suppress_console_outputs: + Helper_App.console_log(error_msg) + return False + raise ValueError(error_msg) +# RETURNS + return True + + +def val_str(v_input, v_name, method, min_len = -1, max_len = -1, suppress_errors = False, suppress_console_outputs = False, v_arg_type = 'argument'): +# FUNCTION + # validate that v_input is of type str +# ARGUMENTS + # str (hopefully) v_input + # str v_name + # str method + # optional int min_len + # optional int max_len + # optional bool suppress_errors + # optional bool suppress_console_outputs + # optional str v_arg_type +# ARGUMENT VALIDATION + my_f = 'val_str' + v_type = "" + # suppress_errors + val_bool(suppress_errors, 'suppress_errors', my_f) + # suppress_console_outputs + if not val_bool(suppress_console_outputs, 'suppress_console_outputs', my_f, suppress_errors): + Helper_App.console_log(error_msg_str(suppress_console_outputs, 'suppress_console_outputs', my_f, "", suppress_errors)) + return False + # method + valid = True + if str(type(method)) != v_type: + valid = False + else: + if len(method) < 1: + valid = False + if not valid: + error_msg = error_msg_str(method, 'method', my_f, v_type) + if suppress_errors: + if not suppress_console_outputs: + Helper_App.console_log(error_msg) + return False + raise ValueError(error_msg) + my_f = method + '.' + my_f + # v_name + valid = True + if str(type(v_name)) != v_type: + valid = False + else: + if len(v_name) < 1: + valid = False + if not valid: + error_msg = error_msg_str(v_name, 'v_name', my_f, v_type) + if suppress_errors: + if not suppress_console_outputs: + Helper_App.console_log(error_msg) + return False + raise ValueError(error_msg) + # v_arg_type + valid = True + if str(type(v_arg_type)) != v_type: + valid = False + else: + if len(v_arg_type) < 1: + valid = False + if not valid: + error_msg = error_msg_str(v_arg_type, 'v_arg_type', my_f, v_type) + if suppress_errors: + if not suppress_console_outputs: + Helper_App.console_log(error_msg) + return False + raise ValueError(error_msg) + # min_len + v_type = "" + if str(type(min_len)) != v_type: + error_msg = error_msg_str(min_len, 'min_len', my_f, v_type) + if suppress_errors: + if not suppress_console_outputs: + Helper_App.console_log(error_msg) + return False + raise ValueError(error_msg) + # max_len + v_type = "" + valid = True + if str(type(max_len)) != v_type: + valid = False + else: + if max_len != -1 and max_len < min_len: + valid = False + if not valid: + error_msg = error_msg_str(max_len, 'max_len', my_f, v_type) + if suppress_errors: + if not suppress_console_outputs: + Helper_App.console_log(error_msg) + return False + raise ValueError(error_msg) + # v_input +# VARIABLE INSTANTIATION + v_type = "" + valid = True +# METHODS + if str(type(v_input)) != v_type: + valid = False + else: + L = len(v_input) + if min_len != -1 and L < min_len: + valid = False + Helper_App.console_log(f"Minimum str length {min_len} not met.") + if max_len != -1 and L > max_len: + Helper_App.console_log(f"Maximum str length {max_len} not met.") + valid = False + if not valid: + error_msg = error_msg_str(v_input, v_name, method, v_type, suppress_errors, suppress_console_outputs, v_arg_type) + if suppress_errors: + if not suppress_console_outputs: + Helper_App.console_log(error_msg) + return False + raise ValueError(error_msg) +# RETURNS + return True + +# def val_none(v_input, v_name, method, v_arg_type = 'argument', suppress_errors = False, suppress_console_outputs = False): +# # FUNCTION +# # evaluate if v_input is None +# # ARGUMENTS +# # ARGUMENT VALIDATION +# # VARIABLE INSTANTIATION +# # METHODS +# # RETURNS + +def val_int(v_input, v_name, method, v_min: Optional[int] = None, v_max: Optional[int] = None, suppress_errors = False, suppress_console_outputs = False, v_arg_type = 'argument'): +# FUNCTION + # validate that myinput is of type int, and if not None, limited by v_min and v_max +# ARGUMENTS + # int (hopefully) myinput + # str v_name + # str method + # optional int v_min + # optional int v_max + # optional bool suppress_errors + # optional bool suppress_console_outputs + # optional str v_arg_type +# ARGUMENT VALIDATION + my_f = 'val_int' + # suppress_errors + val_bool(suppress_errors, 'suppress_errors', my_f) + # suppress_console_outputs + if not val_bool(suppress_console_outputs, 'suppress_console_outputs', my_f, suppress_errors): + Helper_App.console_log(error_msg_str(suppress_console_outputs, 'suppress_console_outputs', my_f, "", suppress_errors)) + return False + # method + if not val_str(method, 'method', my_f, 1, -1, suppress_errors, suppress_console_outputs): return False + my_f = method + '.' + my_f + # v_name + if not val_str(v_name, 'v_name', my_f, 1, -1, suppress_errors, suppress_console_outputs): return False + # v_arg_type + if not val_str(v_arg_type, 'v_arg_type', my_f, 1, -1, suppress_errors, suppress_console_outputs): return False + # v_min + if (v_min != None): + if not val_int(v_min, 'v_min', my_f, None, None, suppress_errors, suppress_console_outputs): + return False + # v_max + if (v_max != None): + if not val_int(v_max, 'v_max', my_f, None, None, suppress_errors, suppress_console_outputs): + return False + # v_input +# VARIABLE INSTANTIATION + mytype = "" # str(type(myinput)) + error_msg = error_msg_str(v_input, v_name, method, mytype, suppress_errors, suppress_console_outputs, v_arg_type) +# METHODS + if not mytype == str(type(v_input)): + if suppress_errors: + if not suppress_console_outputs: + Helper_App.console_log(error_msg) + return False + raise ValueError(error_msg) + if (v_min != None and v_max != None): + if (v_min > v_max): + if suppress_errors: + if not suppress_console_outputs: + Helper_App.console_log(error_msg + f"\nInverted minimum and maximum values {v_min} and {v_max}.") + return False + raise ValueError(error_msg + f"\nInverted minimum and maximum values {v_min} and {v_max}.") + if (v_min != None): + if (v_input < v_min): + if suppress_errors: + if not suppress_console_outputs: + Helper_App.console_log(error_msg + f"\nValue less than minimum {v_min}.") + return False + raise ValueError(error_msg + f"\nValue less than minimum {v_min}.") + if (v_max != None): + if (v_input > v_max): + if suppress_errors: + if not suppress_console_outputs: + Helper_App.console_log(error_msg + f"\nValue greater than maximum {v_max}.") + return False + raise ValueError(error_msg + f"\nValue greater than maximum {v_max}.") +# RETURNS + return True + + +def val_float(v_input, v_name, method, v_min = None, v_max = None, suppress_errors = False, suppress_console_outputs = False, v_arg_type = 'argument'): +# FUNCTION + # validate that v_input is of type float, and if not None, limited by v_min and v_max +# ARGUMENTS + # float (hopefully) v_input + # str v_name + # str method + # optional float v_min + # optional float v_max + # optional bool suppress_errors + # optional bool suppress_console_outputs + # optional str v_arg_type +# ARGUMENT VALIDATION + my_f = 'val_float' + # suppress_errors + val_bool(suppress_errors, 'suppress_errors', my_f) + # suppress_console_outputs + if not val_bool(suppress_console_outputs, 'suppress_console_outputs', my_f, suppress_errors): + Helper_App.console_log(error_msg_str(suppress_console_outputs, 'suppress_console_outputs', my_f, "", suppress_errors)) + return False + # v_name + if not val_str(v_name, 'v_name', my_f, 1, -1, suppress_errors, suppress_console_outputs): return False + # method + if not val_str(method, 'method', my_f, 1, -1, suppress_errors, suppress_console_outputs): return False + my_f = method + '.' + my_f + # v_arg_type + if not val_str(v_arg_type, 'v_arg_type', my_f, 1, -1, suppress_errors, suppress_console_outputs): return False + # v_min + if (v_min != None): + if not val_float(v_min, 'v_min', my_f, None, None, suppress_errors, suppress_console_outputs): + return False + # v_max + if (v_max != None): + if not val_float(v_max, 'v_max', my_f, None, None, suppress_errors, suppress_console_outputs): + return False + # v_input +# VARIABLE INSTANTIATION + mytype = "" # str(type(myinput)) + error_msg = error_msg_str(v_input, v_name, method, mytype, suppress_errors, suppress_console_outputs, v_arg_type) +# METHODS + if not mytype == str(type(v_input)): + if suppress_errors: + if not suppress_console_outputs: + Helper_App.console_log(error_msg) + return False + raise ValueError(error_msg) + if (v_min != None and v_max != None): + if (v_min > v_max): + if suppress_errors: + if not suppress_console_outputs: + Helper_App.console_log(error_msg + f"\nInverted minimum and maximum values {v_min} and {v_max}.") + return False + raise ValueError(error_msg + f"\nInverted minimum and maximum values {v_min} and {v_max}.") + if (v_min != None): + if (v_input < v_min): + if suppress_errors: + if not suppress_console_outputs: + Helper_App.console_log(error_msg + f"\nValue less than minimum {v_min}.") + return False + raise ValueError(error_msg + f"\nValue less than minimum {v_min}.") + if (v_max != None): + if (v_input > v_max): + if suppress_errors: + if not suppress_console_outputs: + Helper_App.console_log(error_msg + f"\nValue greater than maximum {v_max}.") + return False + raise ValueError(error_msg + f"\nValue greater than maximum {v_max}.") +# RETURNS + return True + +def input_bool(v_input, v_name, method, suppress_errors = False, suppress_console_outputs = False, v_arg_type = 'argument'): +# FUNCTION + # input valid str, int, or bool representation of bool, or else None +# ARGUMENTS + # bool (hopefully) v_input + # str v_name + # str method + # optional str v_arg_type + # optional bool suppress_errors + # optional bool suppress_console_outputs +# ARGUMENT VALIDATION + my_f = 'input_bool' + if v_input is None: return False + # suppress_errors + val_bool(suppress_errors, 'suppress_errors', my_f) + # suppress_console_outputs + if not val_bool(suppress_console_outputs, 'suppress_console_outputs', my_f, suppress_errors): + Helper_App.console_log(error_msg_str(suppress_console_outputs, 'suppress_console_outputs', my_f, "", suppress_errors)) + return None + # v_name + if not val_str(v_name, 'v_name', my_f, 1, -1, suppress_errors, suppress_console_outputs): return None + # method + if not val_str(method, 'method', my_f, 1, -1, suppress_errors, suppress_console_outputs): return None + my_f = method + '.' + my_f + # v_arg_type + if not val_str(v_arg_type, 'v_arg_type', my_f, 1, -1, suppress_errors, suppress_console_outputs): return None +# METHODS + if not val_bool(v_input, v_name, my_f, True, True): + if not val_int(v_input, v_name, my_f, 0, 1, True, True): + # if str(type(v_input)) == "": + # return bool(v_input) + v_input = str(v_input) + error_msg = error_msg_str(v_input, v_name, method, "", suppress_errors, suppress_console_outputs, v_arg_type) + if not val_str(v_input, v_name, my_f, suppress_errors=True, suppress_console_outputs=True): + if suppress_errors: + if not suppress_console_outputs: + Helper_App.console_log(error_msg) + return None + raise ValueError(error_msg) + else: + my_truths = ['1', 'Y', 'YE', 'YES', 'YS', 'YESH', 'YEA', 'YEAH', 'TRUE', 'TRU', 'TRUTH', 'TURE', 'T', "B'\X01'"] + my_falths = ['0', 'N', 'NO', 'FALSE', 'F', 'FAIL', 'FALS', "B'\X00'"] + v_input = v_input.upper() + for i in range(len(my_truths)): + if my_truths[i] == v_input: + return True + for i in range(len(my_falths)): + if my_falths[i] == v_input: + return False + if suppress_errors: + if not suppress_console_outputs: + Helper_App.console_log(error_msg) + return None + raise ValueError(error_msg) + else: + return False if v_input == 0 else True +# RETURNS + return bool(v_input) + +def full_val_bool(v_input, v_name, method, suppress_errors = False, suppress_console_outputs = False, v_arg_type = 'argument'): +# FUNCTION + # validate that bool input is bool or valid equivalent +# ARGUMENTS + # bool (hopefully) my_input + # str v_name + # str method + # optional bool suppress_errors + # optional bool suppress_console_outputs + # optional str v_arg_type +# ARGUMENT VALIDATION + my_f = 'full_val_bool' + val_bool(suppress_errors, 'suppress_errors', my_f) + if not val_bool(suppress_console_outputs, 'suppress_console_outputs', my_f, suppress_errors): + Helper_App.console_log(error_msg_str(suppress_console_outputs, 'suppress_console_outputs', my_f, "", suppress_errors)) + return False + # method + if not val_str(method, 'method', my_f, 1, -1, suppress_errors, suppress_console_outputs): return False + my_f = method + '.' + my_f + # v_name + if not val_str(v_name, 'v_name', my_f, 1, -1, suppress_errors, suppress_console_outputs): return False + # v_arg_type + if not val_str(v_arg_type, 'v_arg_type', my_f, 1, -1, suppress_errors, suppress_console_outputs): return False +# RETURNS + return not (str(type(input_bool(v_input, v_name, method, suppress_errors, suppress_console_outputs, v_arg_type))) == "") + + +def input_int(v_input, v_name, method, v_min = None, v_max = None, suppress_errors = False, suppress_console_outputs = False, v_arg_type = 'argument'): +# FUNCTION + # input int or valid equivalent, or else None +# ARGUMENTS + # int or str v_input + # str v_name + # str method + # v_min + # v_min + # bool suppress_errors + # bool suppress_console_outputs + # optional str v_arg_type +# ARGUMENT VALIDATION + my_f = 'input_int' + val_bool(suppress_errors, 'suppress_errors', my_f) + if not val_bool(suppress_console_outputs, 'suppress_console_outputs', my_f, suppress_errors): + Helper_App.console_log(error_msg_str(suppress_console_outputs, 'suppress_console_outputs', my_f, "", suppress_errors)) + return None + # method + if not val_str(method, 'method', my_f, 1, -1, suppress_errors, suppress_console_outputs): return None + my_f = method + '.' + my_f + # v_name + if not val_str(v_name, 'v_name', my_f, 1, -1, suppress_errors, suppress_console_outputs): return None + # v_arg_type + if not val_str(v_arg_type, 'v_arg_type', my_f, 1, -1, suppress_errors, suppress_console_outputs): return None + # v_min + if not str(type(v_min)) == "": + v_min = input_int(v_min, 'v_min', my_f, None, v_max, suppress_errors, suppress_console_outputs) + if str(type(v_min)) == "": return None + # v_max + if not str(type(v_max)) == "": + v_max = input_int(v_max, 'v_min', my_f, v_min, None, suppress_errors, suppress_console_outputs) + if str(type(v_max)) == "": return None +# METHODS + error_msg = error_msg_str(v_input, v_name, method, "", suppress_errors, suppress_console_outputs, v_arg_type) + # v_input + try: + my_int = int(v_input) + except: + if suppress_errors: + if not suppress_console_outputs: + Helper_App.console_log(error_msg) + return None + int(v_input) + if not str(type(v_min)) == "": + if my_int < v_min: + if suppress_errors: + if not suppress_console_outputs: + Helper_App.console_log(f"{error_msg}\nInt input less than minimum value. Value = {v_input}, minimum = {v_min}.") + return None + if not str(type(v_max)) == "": + if my_int > v_max: + if suppress_errors: + if not suppress_console_outputs: + Helper_App.console_log(f"{error_msg}\nInt input greater than maximum value. Value = {v_input}, maximum = {v_max}.") + return None +# RETURNS + return my_int + + +def full_val_int(v_input, v_name, method, v_min = None, v_max = None, suppress_errors = False, suppress_console_outputs = False, v_arg_type = 'argument'): +# FUNCTION + # validate that v_input is int or equivalent, else False, limited by v_min and v_max +# ARGUMENTS + # int (hopefully) v_input + # str v_name + # str method + # optional float v_min + # optional float v_max + # optional bool suppress_errors + # optional bool suppress_console_outputs + # optional str v_arg_type +# ARGUMENT VALIDATION + my_f = 'full_val_int' + val_bool(suppress_errors, 'suppress_errors', my_f) + if not val_bool(suppress_console_outputs, 'suppress_console_outputs', my_f, suppress_errors): + Helper_App.console_log(error_msg_str(suppress_console_outputs, 'suppress_console_outputs', my_f, "", suppress_errors)) + return False + # v_name + if not val_str(v_name, 'v_name', my_f, 1, -1, suppress_errors, suppress_console_outputs): return False + # method + if not val_str(method, 'method', my_f, 1, -1, suppress_errors, suppress_console_outputs): return False + # v_min + if not str(type(v_min)) == "": + v_min = input_int(v_min, 'v_min', method, None, v_max, suppress_errors, suppress_console_outputs) + if str(type(v_min)) == "": return False + # v_max + if not str(type(v_max)) == "": + v_max = input_int(v_max, 'v_min', method, v_min, None, suppress_errors, suppress_console_outputs) + if str(type(v_max)) == "": return False +# RETURNS + return not (str(type(input_int(v_input, v_name, method, v_min, v_max, suppress_errors, suppress_console_outputs))) == "") + + +def input_float(v_input, v_name, method, v_min = None, v_max = None, suppress_errors = False, suppress_console_outputs = False, v_arg_type = 'argument'): +# FUNCTION + # input float, else return None +# ARGUMENTS + # float/int/str(numeric) v_input + # str v_name + # str method + # optional float v_min + # optional float v_min + # optional bool suppress_errors + # optional bool suppress_console_outputs + # optional str v_arg_type +# ARGUMENT VALIDATION + my_f = 'input_float' + val_bool(suppress_errors, 'suppress_errors', my_f) + if not val_bool(suppress_console_outputs, 'suppress_console_outputs', my_f, suppress_errors): + Helper_App.console_log(error_msg_str(suppress_console_outputs, 'suppress_console_outputs', my_f, "", suppress_errors)) + return None + # method + if not val_str(method, 'method', my_f, 1, -1, suppress_errors, suppress_console_outputs): return None + my_f = method + '.' + my_f + # v_name + if not val_str(v_name, 'v_name', my_f, 1, -1, suppress_errors, suppress_console_outputs): return None + # v_arg_type + if not val_str(v_arg_type, 'v_arg_type', my_f, 1, -1, suppress_errors, suppress_console_outputs): return None + # v_min + if not str(type(v_min)) == "": + v_min = input_float(v_min, 'v_min', my_f, None, v_max, suppress_errors, suppress_console_outputs) + if str(type(v_min)) == "": return None + # v_max + if not str(type(v_max)) == "": + v_max = input_float(v_max, 'v_min', my_f, v_min, None, suppress_errors, suppress_console_outputs) + if str(type(v_max)) == "": return None +# METHODS + error_msg = error_msg_str(v_input, v_name, method, "", suppress_errors, suppress_console_outputs, v_arg_type) + # v_input + try: + my_float = float(v_input) + except: + if suppress_errors: + if not suppress_console_outputs: + Helper_App.console_log(error_msg) + return None + float(v_input) + if not str(type(v_min)) == "": + if v_input < v_min: + if suppress_errors: + if not suppress_console_outputs: + Helper_App.console_log(f"{error_msg}\nInt input less than minimum value. Value = {v_input}, minimum = {v_min}.") + return None + if not str(type(v_max)) == "": + if v_input > v_max: + if suppress_errors: + if not suppress_console_outputs: + Helper_App.console_log(f"{error_msg}\nInt input greater than maximum value. Value = {v_input}, maximum = {v_max}.") + return None +# RETURNS + return my_float + + +def full_val_float(v_input, v_name, method, v_min = None, v_max = None, suppress_errors = False, suppress_console_outputs = False, v_arg_type = 'argument'): +# FUNCTION + # validate that v_input is numeric, and if not False, limited by v_min and v_max +# ARGUMENTS + # float (hopefully) v_input + # str v_name + # str method + # optional float v_min + # optional float v_max + # optional bool suppress_errors + # optional bool suppress_console_outputs +# ARGUMENT VALIDATION + my_f = 'full_val_float' + val_bool(suppress_errors, 'suppress_errors', my_f) + if not val_bool(suppress_console_outputs, 'suppress_console_outputs', my_f, suppress_errors): + Helper_App.console_log(error_msg_str(suppress_console_outputs, 'suppress_console_outputs', my_f, "", suppress_errors)) + return False + # method + if not val_str(method, 'method', my_f, 1, -1, suppress_errors, suppress_console_outputs): return False + my_f = method + '.' + my_f + # v_name + if not val_str(v_name, 'v_name', my_f, 1, -1, suppress_errors, suppress_console_outputs): return False + # v_arg_type + if not val_str(v_arg_type, 'v_arg_type', my_f, 1, -1, suppress_errors, suppress_console_outputs): return False + # v_min + if not str(type(v_min)) == "": + v_min = input_float(v_min, 'v_min', method, None, v_max, suppress_errors, suppress_console_outputs) + if str(type(v_min)) == "": return False + # v_max + if not str(type(v_max)) == "": + v_max = input_float(v_max, 'v_min', method, v_min, None, suppress_errors, suppress_console_outputs) + if str(type(v_max)) == "": return False +# RETURNS + return not (str(type(input_float(v_input, v_name, method, v_min, v_max, suppress_errors, suppress_console_outputs))) == "") + + +def make_ordinal(n): +# FUNCTION + # Get ordinal representation of number +# ARGUMENTS + # int n +# ARGUMENT VALIDATION + full_val_int(n, 'n', 'make_ordinal', 0) +# VARIABLE INSTANTIATION + n = int(n) +# METHODS + if 11 <= (n % 100): + suffix= 'th' + else: + suffix = ['th', 'st', 'nd', 'rd', 'th'][min(n % 10, 4)] +# RETURNS + return str(n) + suffix + + +def val_type(v_input, v_name, method, v_type, suppress_errors = False, suppress_console_outputs = False, v_arg_type = 'argument'): +# FUNCTION + # validate that v_input is of type v_type +# ARGUMENTS + # v_type (hopefully) v_input + # str v_name + # str method + # str v_type + # optional bool suppress_errors + # optional bool suppress_console_outputs + # str v_arg_type +# ARGUMENT VALIDATION + my_f = 'val_type' + val_bool(suppress_errors, 'suppress_errors', my_f) + if not val_bool(suppress_console_outputs, 'suppress_console_outputs', my_f, suppress_errors): + Helper_App.console_log(error_msg_str(suppress_console_outputs, 'suppress_console_outputs', my_f, "", suppress_errors)) + return False + # method + if not val_str(method, 'method', my_f, 1, -1, suppress_errors, suppress_console_outputs): return False + my_f = method + '.' + my_f + # v_name + if not val_str(v_name, 'v_name', my_f, 1, -1, suppress_errors, suppress_console_outputs): return False + # v_arg_type + if not val_str(v_arg_type, 'v_arg_type', my_f, 1, -1, suppress_errors, suppress_console_outputs): return False + # v_type + # error_message = error_msg_str(v_type, 'v_type', my_f, v_arg_type) + if not val_str(v_type, 'v_type', my_f, 6, -1, suppress_errors, suppress_console_outputs): return False + # v_input + error_message = error_msg_str(v_input, v_name, method, v_arg_type) + mytype = str(type(v_input)) + # if not (v_type == 'int' or v_type == 'bool' or v_type == 'float' or v_type == 'complex' or v_type == 'str' or v_type == 'NoneType'): + if not mytype == v_type: # f"": + if suppress_errors: + if not suppress_console_outputs: + Helper_App.console_log(error_message) + return False + raise ValueError(error_message) +# RETURNS + return True + + +def val_instance(v_input, v_name, method, v_type, suppress_errors = False, suppress_console_outputs = False, v_arg_type = 'argument'): +# FUNCTION + # validate that v_input is of type v_type +# ARGUMENTS + # v_type (hopefully) v_input + # str v_name + # str method + # type v_type + # optional bool suppress_errors + # optional bool suppress_console_outputs + # str v_arg_type +# ARGUMENT VALIDATION + my_f = 'val_type' + val_bool(suppress_errors, 'suppress_errors', my_f) + if not val_bool(suppress_console_outputs, 'suppress_console_outputs', my_f, suppress_errors): + Helper_App.console_log(error_msg_str(suppress_console_outputs, 'suppress_console_outputs', my_f, "", suppress_errors)) + return False + # method + if not val_str(method, 'method', my_f, 1, -1, suppress_errors, suppress_console_outputs): return False + my_f = method + '.' + my_f + # v_name + if not val_str(v_name, 'v_name', my_f, 1, -1, suppress_errors, suppress_console_outputs): return False + # v_arg_type + if not val_str(v_arg_type, 'v_arg_type', my_f, 1, -1, suppress_errors, suppress_console_outputs): return False + # v_type + error_message = error_msg_str(v_type, 'v_type', my_f, v_arg_type) + if not isinstance(v_type, type): # mytype == v_type: # f"": + if suppress_errors: + if not suppress_console_outputs: + Helper_App.console_log(error_message) + return False + raise ValueError(error_message) # val_str(v_type, 'v_type', my_f, 6, -1, suppress_errors, suppress_console_outputs): return False + # v_input + error_message = error_msg_str(v_input, v_name, method, v_arg_type) + # mytype = str(type(v_input)) + # if not (v_type == 'int' or v_type == 'bool' or v_type == 'float' or v_type == 'complex' or v_type == 'str' or v_type == 'NoneType'): + if not isinstance(v_input, v_type): # mytype == v_type: # f"": + if suppress_errors: + if not suppress_console_outputs: + Helper_App.console_log(error_message) + return False + raise ValueError(error_message) +# RETURNS + return True + + +def val_list(v_input, v_name, method, v_type = '', min_len = -1, max_len = -1, suppress_errors = False, suppress_console_outputs: bool = False, allow_nuns = False, v_arg_type = 'argument'): +# FUNCTION + # validate that v_input is of type list, and if defined: has v_len elements of type v_type +# ARGUMENTS + # list[v_type] (hopefully) v_input + # str v_name - variable name + # str method - parent method + # str v_type - type of list items + # int min_len - minimum length of list + # int max_len - maximum length of list + # optional bool suppress_errors + # optional bool suppress_console_outputs + # optional bool allow_nuns + # optional str v_arg_type +# ARGUMENT VALIDATION + my_f = 'val_list' + val_bool(suppress_errors, 'suppress_errors', my_f) + if not val_bool(suppress_console_outputs, 'suppress_console_outputs', my_f, suppress_errors): + Helper_App.console_log(error_msg_str(suppress_console_outputs, 'suppress_console_outputs', my_f, "", suppress_errors)) + return False + # method + if not val_str(method, 'method', my_f, 1, -1, suppress_errors, suppress_console_outputs): return False + my_f = method + '.' + my_f + # v_name + if not val_str(v_name, 'v_name', my_f, 1, -1, suppress_errors, suppress_console_outputs): return False + # v_arg_type + if not val_str(v_arg_type, 'v_arg_type', my_f, 1, -1, suppress_errors, suppress_console_outputs): return False + # v_type + # if not val_type(v_type, 'v_type', my_f, type, suppress_errors, suppress_console_outputs): return False + if not val_str(v_type, 'v_type', my_f, -1, -1, suppress_errors, suppress_console_outputs): return False + # min_len + if not full_val_int(min_len, 'min_len', my_f, None, None if max_len == -1 else max_len, suppress_errors, suppress_console_outputs): return False + # min_len = input_int(min_len, 'min_len', method, None, max_len, suppress_errors, suppress_console_outputs) + # if str(type(min_len)) == "": return False + # max_len + if not full_val_int(max_len, 'max_len', my_f, None if max_len == -1 else (None if min_len == -1 else min_len), None, suppress_errors, suppress_console_outputs): return False + # if not str(type(max_len)) == "": + # max_len = input_int(max_len, 'max_len', method, min_len, None, suppress_errors, suppress_console_outputs) + # if str(type(max_len)) == "": return False + # allow_nuns + if not val_bool(allow_nuns, 'allow_nuns', my_f, suppress_errors, suppress_console_outputs): return False + # v_input + # mytype = str(type(v_input)) + error_msg = error_msg_str(v_input, v_name, method, "") + if not str(type(v_input)) == "": + if suppress_errors: + if not suppress_console_outputs: + Helper_App.console_log(error_msg) + return False + raise ValueError(error_msg) + L = len(v_input) + if max_len > -1 and L > max_len: + if suppress_errors: + if not suppress_console_outputs: + Helper_App.console_log(error_msg + f'\nInvalid list length. Maximum = {max_len}, length = {L}') + return False + raise ValueError(error_msg + f'\nInvalid list length. Maximum = {max_len}, length = {L}') + if L < min_len: + if suppress_errors: + if not suppress_console_outputs: + Helper_App.console_log(error_msg + f"Invalid list length. Minimum = {min_len}, length = {L}") + return False + raise ValueError(error_msg + f'\nInvalid list length. Minimum = {min_len}, length = {L}') + if v_type != '' and L > 0: + for i in range(L): + # mytype = str(type(v_input[i])) + if not (val_type(v_input[i], f'{v_name}[{i}]', my_f, v_type, True) or allow_nuns and val_type(v_input[i], f'{v_name}[{i}]', my_f, "", True)): # mytype == v_type: + error_msg = error_msg + '\n' + error_msg_str(v_input[i], f'{v_name}[{i}]', my_f, v_type, False, False, 'list element') + if suppress_errors: + if not suppress_console_outputs: + Helper_App.console_log(error_msg) + return False + raise ValueError(error_msg) +# RETURNS + return True + + +def val_list_instances(v_input, v_name, method, v_type = None, min_len = -1, max_len = -1, suppress_errors = False, suppress_console_outputs: bool = False, allow_nuns = False, v_arg_type = 'argument'): +# FUNCTION + # validate that v_input is of type list, and if defined: has v_len elements of type v_type +# ARGUMENTS + # list[v_type] (hopefully) v_input + # str v_name - variable name + # str method - parent method + # type v_type - type of list items + # int min_len - minimum length of list + # int max_len - maximum length of list + # optional bool suppress_errors + # optional bool suppress_console_outputs + # optional bool allow_nuns + # optional str v_arg_type +# ARGUMENT VALIDATION + my_f = 'val_list_instances' + val_bool(suppress_errors, 'suppress_errors', my_f) + if not val_bool(suppress_console_outputs, 'suppress_console_outputs', my_f, suppress_errors): + Helper_App.console_log(error_msg_str(suppress_console_outputs, 'suppress_console_outputs', my_f, "", suppress_errors)) + return False + # method + if not val_str(method, 'method', my_f, 1, -1, suppress_errors, suppress_console_outputs): return False + my_f = method + '.' + my_f + # v_name + if not val_str(v_name, 'v_name', my_f, 1, -1, suppress_errors, suppress_console_outputs): return False + # v_arg_type + if not val_str(v_arg_type, 'v_arg_type', my_f, 1, -1, suppress_errors, suppress_console_outputs): return False + # v_type + if not val_type(v_type, 'v_type', my_f, type, suppress_errors, suppress_console_outputs): return False + # if not val_str(v_type, 'v_type', my_f, 6, -1, suppress_errors, suppress_console_outputs): return False + # min_len + if not full_val_int(min_len, 'min_len', my_f, None, None if max_len == -1 else max_len, suppress_errors, suppress_console_outputs): return False + # min_len = input_int(min_len, 'min_len', method, None, max_len, suppress_errors, suppress_console_outputs) + # if str(type(min_len)) == "": return False + # max_len + if not full_val_int(max_len, 'max_len', my_f, None if max_len == -1 else (None if min_len == -1 else min_len), None, suppress_errors, suppress_console_outputs): return False + # if not str(type(max_len)) == "": + # max_len = input_int(max_len, 'max_len', method, min_len, None, suppress_errors, suppress_console_outputs) + # if str(type(max_len)) == "": return False + # allow_nuns + if not val_bool(allow_nuns, 'allow_nuns', my_f, suppress_errors, suppress_console_outputs): return False + # v_input + # mytype = str(type(v_input)) + error_msg = error_msg_str(v_input, v_name, method, "") + if not str(type(v_input)) == "": + if suppress_errors: + if not suppress_console_outputs: + Helper_App.console_log(error_msg) + return False + raise ValueError(error_msg) + L = len(v_input) + if max_len > -1 and L > max_len: + if suppress_errors: + if not suppress_console_outputs: + Helper_App.console_log(error_msg + f'\nInvalid list length. Maximum = {max_len}, length = {L}') + return False + raise ValueError(error_msg + f'\nInvalid list length. Maximum = {max_len}, length = {L}') + if L < min_len: + if suppress_errors: + if not suppress_console_outputs: + Helper_App.console_log(error_msg + f"Invalid list length. Minimum = {min_len}, length = {L}") + return False + raise ValueError(error_msg + f'\nInvalid list length. Minimum = {min_len}, length = {L}') + if v_type != '' and L > 0: + for i in range(L): + # mytype = str(type(v_input[i])) + if not (val_instance(v_input[i], f'{v_name}[{i}]', my_f, v_type, True) or allow_nuns and val_instance(v_input[i], f'{v_name}[{i}]', my_f, type(None), True)): # mytype == v_type: + error_msg = error_msg + '\n' + error_msg_str(v_input[i], f'{v_name}[{i}]', my_f, v_type, False, False, 'list element') + if suppress_errors: + if not suppress_console_outputs: + Helper_App.console_log(error_msg) + return False + raise ValueError(error_msg) +# RETURNS + return True + + +def val_nested_list(v_input, v_name, method, depth_i, depth_max, v_type = '', v_min = -1, v_mins = [], v_max = -1, v_maxs = [], suppress_errors = False, suppress_console_outputs = False, allow_nuns = False, v_arg_type = 'argument'): +# FUNCTION + # validate that v_input is of type list, and if defined: has v_len elements of type v_type + # for nested list of nested-index i +# ARGUMENTS + # list[v_type] (hopefully) v_input + # str v_name + # str method + # int depth_i - current depth of nesting of lists + # int depth_max - maximum depth of nesting of lists - base 0 + # Optional[str] v_type - type of list items + # Optional[int] v_min - minimum sublist size + # Optional[list[int]] v_mins - minimum list sizes + # Optional[int] v_max - maximum sublist size + # Optional[list[int]] v_maxs - maximum list sizes + # optional bool suppress_errors + # optional bool suppress_console_outputs + # optional bool allow_nuns + # optional str v_arg_type +# ARGUMENT VALIDATION + my_f = 'val_nested_list' + val_bool(suppress_errors, 'suppress_errors', my_f) + if not val_bool(suppress_console_outputs, 'suppress_console_outputs', my_f, suppress_errors): + Helper_App.console_log(error_msg_str(suppress_console_outputs, 'suppress_console_outputs', my_f, "")) + return False + # method + if not val_str(method, 'method', my_f, 1, -1, suppress_errors, suppress_console_outputs): return False + my_f = method + '.' + my_f + # v_name + if not val_str(v_name, 'v_name', my_f, 1, -1, suppress_errors, suppress_console_outputs): return False + # v_arg_type + if not val_str(v_arg_type, 'v_arg_type', my_f, 1, -1, suppress_errors, suppress_console_outputs): return False + # v_type + if not val_str(v_type, 'v_type', my_f, -1, -1, suppress_errors, suppress_console_outputs): return False + # if not val_type(v_type, 'v_type', my_f, type, suppress_errors, suppress_console_outputs): return False + # v_min + if not val_int(v_min, 'v_min', my_f, -1, None, suppress_errors, suppress_console_outputs): return False + # v_max + if not val_int(v_max, 'v_max', my_f, -1, None, suppress_errors, suppress_console_outputs): return False + # v_mins + if not (val_list(v_mins, 'v_mins', my_f, "", depth_max + 1, depth_max + 1, True, True) or v_mins == []): + error_msg = error_msg_str(v_mins, 'v_mins', my_f, "") + if not suppress_console_outputs: + Helper_App.console_log(error_msg) + return False + raise ValueError(error_msg) + # v_maxs + if not (val_list(v_maxs, 'v_maxs', my_f, "", depth_max + 1, depth_max + 1, True, True) or v_maxs == []): + error_msg = error_msg_str(v_maxs, 'v_maxs', my_f, "") + if not suppress_console_outputs: + Helper_App.console_log(error_msg) + return False + raise ValueError(error_msg) + # allow_nuns + if not val_bool(allow_nuns, 'allow_nuns', my_f, suppress_errors, suppress_console_outputs): return False + # v_input + mytype = v_type if depth_i == depth_max else "" + error_msg = error_msg_str(v_input, v_name, method, mytype, suppress_errors, suppress_console_outputs, v_arg_type) + if not val_list(v_input, v_name, method, mytype, v_min, v_max, suppress_errors, suppress_console_outputs, allow_nuns, v_arg_type): + if not suppress_console_outputs: + Helper_App.console_log(error_msg) + return False +# METHODS + L = len(v_input) + if L == 0: + if v_min > -1: + if suppress_errors: + if not suppress_console_outputs: + Helper_App.console_log(error_msg + f'\nMinimum length {v_min} not met.') + return False + raise ValueError(error_msg + f'\nMinimum length {v_min} not met.') + elif depth_i < depth_max: + for i in range(L): + if not (v_mins == [] or v_maxs == []): + if not val_nested_list(v_input[i], v_name, method, depth_i + 1, depth_max, v_type, v_mins[depth_i + 1], v_mins, v_maxs[depth_i + 1], v_maxs, suppress_errors, suppress_console_outputs, v_arg_type): + if not suppress_console_outputs: + Helper_App.console_log(error_msg) + return False + elif not v_mins == []: + if not val_nested_list(v_input[i], v_name, method, depth_i + 1, depth_max, v_type, v_mins[depth_i + 1], v_mins, -1, v_maxs, suppress_errors, suppress_console_outputs, v_arg_type): + if not suppress_console_outputs: + Helper_App.console_log(error_msg) + return False + elif not v_maxs == []: + if not val_nested_list(v_input[i], v_name, method, depth_i + 1, depth_max, v_type, -1, v_mins, v_maxs[depth_i + 1], v_maxs, suppress_errors, suppress_console_outputs, v_arg_type): + if not suppress_console_outputs: + Helper_App.console_log(error_msg) + return False + else: + if not val_nested_list(v_input[i], v_name, method, depth_i + 1, depth_max, v_type, -1, v_mins, -1, v_maxs, suppress_errors, suppress_console_outputs, v_arg_type): + if not suppress_console_outputs: + Helper_App.console_log(error_msg) + return False +# RETURNS + return True + + +def val_nested_list_instances(v_input, v_name, method, depth_i, depth_max, v_type = '', v_min = -1, v_mins = [], v_max = -1, v_maxs = [], suppress_errors = False, suppress_console_outputs = False, allow_nuns = False, v_arg_type = 'argument'): +# FUNCTION + # validate that v_input is of type list, and if defined: has v_len elements of type v_type + # for nested list of nested-index i +# ARGUMENTS + # list[v_type] (hopefully) v_input + # str v_name + # str method + # int depth_i - current depth of nesting of lists + # int depth_max - maximum depth of nesting of lists - base 0 + # Optional[str] v_type - type of list items + # Optional[int] v_min - minimum sublist size + # Optional[list[int]] v_mins - minimum list sizes + # Optional[int] v_max - maximum sublist size + # Optional[list[int]] v_maxs - maximum list sizes + # optional bool suppress_errors + # optional bool suppress_console_outputs + # optional bool allow_nuns + # optional str v_arg_type +# ARGUMENT VALIDATION + my_f = 'val_nested_list' + val_bool(suppress_errors, 'suppress_errors', my_f) + if not val_bool(suppress_console_outputs, 'suppress_console_outputs', my_f, suppress_errors): + Helper_App.console_log(error_msg_str(suppress_console_outputs, 'suppress_console_outputs', my_f, "")) + return False + # method + if not val_str(method, 'method', my_f, 1, -1, suppress_errors, suppress_console_outputs): return False + my_f = method + '.' + my_f + # v_name + if not val_str(v_name, 'v_name', my_f, 1, -1, suppress_errors, suppress_console_outputs): return False + # v_arg_type + if not val_str(v_arg_type, 'v_arg_type', my_f, 1, -1, suppress_errors, suppress_console_outputs): return False + # v_type + # if not val_str(v_type, 'v_type', my_f, -1, -1, suppress_errors, suppress_console_outputs): return False + if not val_type(v_type, 'v_type', my_f, type, suppress_errors, suppress_console_outputs): return False + # v_min + if not val_int(v_min, 'v_min', my_f, -1, None, suppress_errors, suppress_console_outputs): return False + # v_max + if not val_int(v_max, 'v_max', my_f, -1, None, suppress_errors, suppress_console_outputs): return False + # v_mins + if not (val_list(v_mins, 'v_mins', my_f, "", depth_max + 1, depth_max + 1, True, True) or v_mins == []): + error_msg = error_msg_str(v_mins, 'v_mins', my_f, "") + if not suppress_console_outputs: + Helper_App.console_log(error_msg) + return False + raise ValueError(error_msg) + # v_maxs + if not (val_list(v_maxs, 'v_maxs', my_f, "", depth_max + 1, depth_max + 1, True, True) or v_maxs == []): + error_msg = error_msg_str(v_maxs, 'v_maxs', my_f, "") + if not suppress_console_outputs: + Helper_App.console_log(error_msg) + return False + raise ValueError(error_msg) + # allow_nuns + if not val_bool(allow_nuns, 'allow_nuns', my_f, suppress_errors, suppress_console_outputs): return False + # v_input + mytype = v_type if depth_i == depth_max else list # "" + error_msg = error_msg_str(v_input, v_name, method, mytype, suppress_errors, suppress_console_outputs, v_arg_type) + if not val_list_instances(v_input, v_name, method, mytype, v_min, v_max, suppress_errors, suppress_console_outputs, allow_nuns, v_arg_type): + if not suppress_console_outputs: + Helper_App.console_log(error_msg) + return False +# METHODS + L = len(v_input) + if L == 0: + if v_min > -1: + if suppress_errors: + if not suppress_console_outputs: + Helper_App.console_log(error_msg + f'\nMinimum length {v_min} not met.') + return False + raise ValueError(error_msg + f'\nMinimum length {v_min} not met.') + elif depth_i < depth_max: + for i in range(L): + if not (v_mins == [] or v_maxs == []): + if not val_nested_list(v_input[i], v_name, method, depth_i + 1, depth_max, v_type, v_mins[depth_i + 1], v_mins, v_maxs[depth_i + 1], v_maxs, suppress_errors, suppress_console_outputs, allow_nuns, v_arg_type): + if not suppress_console_outputs: + Helper_App.console_log(error_msg) + return False + elif not v_mins == []: + if not val_nested_list(v_input[i], v_name, method, depth_i + 1, depth_max, v_type, v_mins[depth_i + 1], v_mins, -1, v_maxs, suppress_errors, suppress_console_outputs, allow_nuns, v_arg_type): + if not suppress_console_outputs: + Helper_App.console_log(error_msg) + return False + elif not v_maxs == []: + if not val_nested_list(v_input[i], v_name, method, depth_i + 1, depth_max, v_type, -1, v_mins, v_maxs[depth_i + 1], v_maxs, suppress_errors, suppress_console_outputs, allow_nuns, v_arg_type): + if not suppress_console_outputs: + Helper_App.console_log(error_msg) + return False + else: + if not val_nested_list(v_input[i], v_name, method, depth_i + 1, depth_max, v_type, -1, v_mins, -1, v_maxs, suppress_errors, suppress_console_outputs, allow_nuns, v_arg_type): + if not suppress_console_outputs: + Helper_App.console_log(error_msg) + return False +# RETURNS + return True + + +def val_url(v_input, v_name, method, min_len = 12, max_len = -1, suppress_errors = False, suppress_console_outputs = False, v_arg_type = 'argument'): +# FUNCTION + # validate that v_input is of type str +# ARGUMENTS + # str (hopefully) v_input + # str v_name + # str method + # optional int min_len + # optional int max_len + # optional bool suppress_errors + # optional bool suppress_console_outputs + # optional str v_arg_type +# ARGUMENT VALIDATION + _m = 'val_url' + v_type = "" + val_bool(suppress_errors, 'suppress_errors', _m) + if not val_bool(suppress_console_outputs, 'suppress_console_outputs', _m, suppress_errors): + Helper_App.console_log(error_msg_str(suppress_console_outputs, 'suppress_console_outputs', _m, "")) + return False + # method + if not val_str(method, 'method', _m, -1, -1, suppress_errors, suppress_console_outputs): return False + _m = method + '.' + _m + # v_arg_type + if not val_str(v_arg_type, 'v_arg_type', _m, 1, -1, suppress_errors, suppress_console_outputs): return False + # v_name + if not val_str(v_name, 'v_name', _m, -1, -1, suppress_errors, suppress_console_outputs): return False + # min_len + if not val_int(min_len, 'min_len', _m, 10, None, suppress_errors, suppress_console_outputs): return False + # max_len + if not val_int(max_len, 'max_len', _m, -1, None, suppress_errors, suppress_console_outputs): return False + # v_input + if not val_str(v_input, v_name, method, min_len, -1, suppress_errors, suppress_console_outputs): return False +# METHODS + error_msg = error_msg_str(v_input, 'v_input', _m, "") + if not (v_input[:8] == r'https://' or v_input[:7] == r'http://'): + if suppress_errors: + if not suppress_console_outputs: + Helper_App.console_log(error_msg) + return False + raise ValueError(error_msg) +# RETURNS + return True + +# def val_nparray(v_input, v_name, method, v_min = None, v_max = None, suppress_errors = False, suppress_console_outputs = False, v_arg_type = 'argument'): +# # FUNCTION +# # validate v_input is numpy ndarray +# # ARGUMENTS +# # numpy.ndarray v_input +# # str v_name +# # str method +# # +# # ARGUMENT VALIDATION +# # METHODS +# # RETURNS + + +def val_DataFrame(v_input, v_name, method, v_types=[], min_col=-1, max_col=-1, cols=[], min_sz=-1, max_sz=-1, suppress_errors=False, suppress_console_outputs=False, v_arg_type='argument'): +# FUNCTION + # validate that v_input is of type list, and if defined: has v_len elements of type v_type + # for nested list of nested-index i +# ARGUMENTS + # pandas.DataFrame (hopefully) v_input + # str v_name + # str method + # optional list[str] v_type - column datatypes + # optional int min_col - minimum number of columns + # optional int max_col - maximum number of columns + # optional list[str] cols - column names + # optional int min_sz - minimum length of columns + # optional int max_sz - maximum length of columns + # optional bool suppress_errors + # optional bool suppress_console_outputs + # optional str v_arg_type +# ARGUMENT VALIDATION + my_f = 'val_DataFrame' + val_bool(suppress_errors, 'suppress_errors', my_f) + if not val_bool(suppress_console_outputs, 'suppress_console_outputs', my_f, suppress_errors): + Helper_App.console_log(error_msg_str(suppress_console_outputs, 'suppress_console_outputs', my_f, "")) + return False + # method + if not val_str(method, 'method', my_f, 1, -1, suppress_errors, suppress_console_outputs): return False + my_f = method + '.' + my_f + # v_name + if not val_str(v_name, 'v_name', my_f, 1, -1, suppress_errors, suppress_console_outputs): return False + # v_arg_type + if not val_str(v_arg_type, 'v_arg_type', my_f, 1, -1, suppress_errors, suppress_console_outputs): return False + # min_col + if not val_int(min_col, 'min_col', my_f, -1, None, suppress_errors, suppress_console_outputs): return False + # max_col + if not val_int(max_col, 'max_col', my_f, -1, None, suppress_errors, suppress_console_outputs): return False + # min_sz + if not val_int(min_sz, 'min_sz', my_f, -1, None, suppress_errors, suppress_console_outputs): return False + # max_sz + if not val_int(max_sz, 'max_sz', my_f, -1, None, suppress_errors, suppress_console_outputs): return False + # v_types + if not (val_list(v_types, 'v_types', my_f, "", min_col, max_col, True, True, True) or v_types == []): + error_msg = error_msg_str(v_types, 'v_types', my_f, str) + if not suppress_console_outputs: + Helper_App.console_log(error_msg) + return False + raise ValueError(error_msg) + # cols + if not (val_list(cols, 'cols', my_f, "", min_col, max_col, True, True) or cols == []): + error_msg = error_msg_str(cols, 'cols', my_f, "") + if not suppress_console_outputs: + Helper_App.console_log(error_msg) + return False + raise ValueError(error_msg) + # v_input + if not val_type(v_input, v_name, my_f, "", suppress_errors, suppress_console_outputs, v_arg_type): return False +# METHODS + error_msg = error_msg_str(v_input, v_name, my_f, "", v_arg_type=v_arg_type) + n_c = len(v_input.columns) + if (min_col > 0 and n_c < min_col) or (max_col > 0 and n_c > max_col): + if suppress_errors: + if not suppress_console_outputs: + Helper_App.console_log(error_msg) + return False + raise ValueError(error_msg) + my_sz = len(v_input.index) + if (min_sz > 0 and my_sz < min_sz) or (max_sz > 0 and my_sz > max_sz): + if suppress_errors: + if not suppress_console_outputs: + Helper_App.console_log(error_msg) + return False + raise ValueError(error_msg) + if not v_types == []: + for col_i in range(n_c): + if not (v_types[col_i] == None or str(type(v_types[col_i])) == "" and val_type(v_input.at[0, v_input.columns[col_i]], 'v_input.at[0, v_input.columns[col_i]]', my_f, v_types[col_i], True, False) or val_instance(v_input.at[0, v_input.columns[col_i]], 'v_input.at[0, v_input.columns[col_i]]', my_f, v_types[col_i], True, False)): # str(type(v_input[v_input.columns[col_i]][0])) == v_types[col_i] or v_types[col_i] == '': + if suppress_errors: + if not suppress_console_outputs: + Helper_App.console_log(error_msg + f'\nInvalid data type {str(type(v_input.at[0, v_input.columns[col_i]]))} in column {v_input.columns[col_i]}') + return False + raise ValueError(error_msg + f'\nInvalid data type {str(type(v_input.at[0, v_input.columns[col_i]]))} in column {v_input.columns[col_i]}') + if not cols == []: + for col_i in range(n_c): + if not v_input.columns[col_i] == cols[col_i] or cols[col_i] == '': + if suppress_errors: + if not suppress_console_outputs: + Helper_App.console_log(error_msg + f'\nInvalid column heading for column {v_input.columns[col_i]}') + return False + raise ValueError(error_msg + f'\nInvalid column heading for column {v_input.columns[col_i]}') +# RETURNS + return True + + + +if __name__ == '__main__': + Helper_App.console_log(input_bool('true', 'input_bool', 'test')) + Helper_App.console_log(input_bool(None, 'input_bool', 'test')) \ No newline at end of file diff --git a/lib/data_types.py b/lib/data_types.py new file mode 100644 index 0000000..53ddd59 --- /dev/null +++ b/lib/data_types.py @@ -0,0 +1,37 @@ +# -*- coding: utf-8 -*- +""" +Created on Thu Apr 27 12:33:59 2023 + +@author: Edward Middleton-Smith + +Argument Validation +""" + +# CLASSES +# ATTRIBUTE DECLARATION +# METHODS + # FUNCTION + # ARGUMENTS + # ARGUMENT VALIDATION + # ATTRIBUTE + VARIABLE INSTANTIATION + # METHODS + # RETURNS + +# NORMAL METHODS +# FUNCTION +# ARGUMENTS +# ARGUMENT VALIDATION +# VARIABLE INSTANTIATION +# METHODS +# RETURNS + +# IMPORTS + +# CLASSES + +# METHODS +def get_enum_member_by_text(enum_class, text): + for member in enum_class.__members__.values(): + if member.name == text: + return member + raise ValueError(f'{text} is not in {enum_class}') \ No newline at end of file diff --git a/models/__init__.py b/models/__init__.py new file mode 100644 index 0000000..615f401 --- /dev/null +++ b/models/__init__.py @@ -0,0 +1,11 @@ +""" +Project: PARTS Website +Author: Edward Middleton-Smith + Precision And Research Technology Systems Limited + +Technology: Module Initialisation +Feature: Models + +Description: +Initialises view data models module. +""" diff --git a/models/model_view_accessibility_report.py b/models/model_view_accessibility_report.py new file mode 100644 index 0000000..1faf5d8 --- /dev/null +++ b/models/model_view_accessibility_report.py @@ -0,0 +1,24 @@ +""" +Project: PARTS Website +Author: Edward Middleton-Smith + Precision And Research Technology Systems Limited + +Technology: Legal View Models +Feature: Accessibility Report View Model + +Description: +Data model for accessibility report view +""" + +# internal +from models.model_view_base import Model_View_Base +# from routes import bp_home +# external + +class Model_View_Accessibility_Report(Model_View_Base): + @property + def title(self): + return 'Accessibility Report' + def __init__(self, hash_page_current=Model_View_Base.HASH_PAGE_ACCESSIBILITY_REPORT): + super().__init__(hash_page_current=hash_page_current) + \ No newline at end of file diff --git a/models/model_view_accessibility_statement.py b/models/model_view_accessibility_statement.py new file mode 100644 index 0000000..2ffcb79 --- /dev/null +++ b/models/model_view_accessibility_statement.py @@ -0,0 +1,24 @@ +""" +Project: PARTS Website +Author: Edward Middleton-Smith + Precision And Research Technology Systems Limited + +Technology: Legal View Models +Feature: Accessibility Statement View Model + +Description: +Data model for accessibility statement view +""" + +# internal +from models.model_view_base import Model_View_Base +# from routes import bp_home +# external + +class Model_View_Accessibility_Statement(Model_View_Base): + @property + def title(self): + return 'Accessibility Statement' + def __init__(self, hash_page_current=Model_View_Base.HASH_PAGE_ACCESSIBILITY_STATEMENT): + super().__init__(hash_page_current=hash_page_current) + \ No newline at end of file diff --git a/models/model_view_base.py b/models/model_view_base.py new file mode 100644 index 0000000..5ad0c1b --- /dev/null +++ b/models/model_view_base.py @@ -0,0 +1,263 @@ +""" +Project: PARTS Website +Author: Edward Middleton-Smith + Precision And Research Technology Systems Limited + +Technology: View Models +Feature: Base View Model + +Description: +Base data model for views +""" + +# IMPORTS +# VARIABLE INSTANTIATION +# METHODS + +# IMPORTS +# internal +# from routes import bp_home +from business_objects.base import Base +from business_objects.project_hub.user import User +from business_objects.project_hub.command import Command +from datastores.datastore_base import DataStore_Base +from datastores.project_hub.datastore_command import DataStore_Command +from forms.access_level import Filters_Access_Level +from forms.forms import Form_Is_Included_VAT, Form_Delivery_Region, Form_Currency +from forms.unit_measurement import Filters_Unit_Measurement +from helpers.helper_app import Helper_App +import lib.argument_validation as av +# external +from abc import ABC, abstractmethod +from flask_sqlalchemy import SQLAlchemy +from flask import Flask, session, current_app, jsonify +from pydantic import BaseModel, ConfigDict +from typing import ClassVar + + +class Model_View_Base(BaseModel, ABC): + ATTR_TEXT_COLLAPSED: ClassVar[str] = 'textCollapsed' + ATTR_TEXT_EXPANDED: ClassVar[str] = 'textExpanded' + ATTR_VALUE_CURRENT: ClassVar[str] = 'current-value' + ATTR_VALUE_PREVIOUS: ClassVar[str] = 'previous-value' + COMPANY_ADDRESS_SHORT: ClassVar[str] = '53 Alfred Green Close, Rugby, United Kingdom, CV22 6DN' + COMPANY_NUMBER: ClassVar[str] = '13587499' + ENDPOINT_GET_ALTCHA_CHALLENGE: ClassVar[str] = 'routes_core_contact.create_altcha_challenge' + ENDPOINT_PAGE_ACCESSIBILITY_REPORT: ClassVar[str] = 'routes_legal.accessibility_report' + ENDPOINT_PAGE_ACCESSIBILITY_STATEMENT: ClassVar[str] = 'routes_legal.accessibility_statement' + ENDPOINT_PAGE_CONTACT: ClassVar[str] = 'routes_core_contact.contact' + ENDPOINT_PAGE_CONTACT_SUCCESS: ClassVar[str] = 'routes_core_contact.contact_success' + ENDPOINT_PAGE_DATA_RETENTION_SCHEDULE: ClassVar[str] = 'routes_legal.retention_schedule' + ENDPOINT_PAGE_ERROR_NO_PERMISSION: ClassVar[str] = 'routes_core.error_no_permission' + ENDPOINT_PAGE_HOME: ClassVar[str] = 'routes_core_home.home' + ENDPOINT_PAGE_LICENSE: ClassVar[str] = 'routes_legal.license' + ENDPOINT_PAGE_PRIVACY_POLICY: ClassVar[str] = 'routes_legal.privacy_policy' + ENDPOINT_POST_COMMAND: ClassVar[str] = 'routes_core_contact.contact_post' + FLAG_ACTIVE: ClassVar[str] = Base.FLAG_ACTIVE + FLAG_ADD: ClassVar[str] = 'add' + # FLAG_ADD_DELETE: ClassVar[str] = 'add-delete' + FLAG_BOOL_FALSE: ClassVar[str] = 'false' + FLAG_BOOL_TRUE: ClassVar[str] = 'true' + FLAG_BUTTON: ClassVar[str] = 'button' + FLAG_BUTTON_LIGHT: ClassVar[str] = 'button-light' + FLAG_BUTTON_PRIMARY: ClassVar[str] = 'button-primary' + FLAG_CANCEL: ClassVar[str] = 'button-cancel' + FLAG_CALLBACK: ClassVar[str] = 'callback' + FLAG_CAPTCHA: ClassVar[str] = 'captcha' + FLAG_CARD: ClassVar[str] = 'card' + FLAG_CLOSE_TEMPORARY_ELEMENT: ClassVar[str] = 'button-temporary-element-close' + FLAG_CODE: ClassVar[str] = Base.FLAG_CODE + FLAG_COLLAPSED: ClassVar[str] = 'collapsed' + FLAG_COLLAPSIBLE: ClassVar[str] = 'collapsible' + FLAG_COLUMN: ClassVar[str] = 'column' + FLAG_COMMENT: ClassVar[str] = 'comment' + FLAG_CONTAINER: ClassVar[str] = 'container' + FLAG_CONTAINER_CHECKBOX: ClassVar[str] = 'container-checkbox' + FLAG_CONTAINER_ICON_AND_LABEL: ClassVar[str] = 'container-icon-label' + FLAG_CONTAINER_INPUT: ClassVar[str] = 'container-input' + FLAG_CSRF_TOKEN: ClassVar[str] = 'X-CSRFToken' + FLAG_DATA: ClassVar[str] = 'data' + FLAG_DATE_FROM: ClassVar[str] = Base.FLAG_DATE_FROM + FLAG_DATE_TO: ClassVar[str] = Base.FLAG_DATE_TO + FLAG_DELETE: ClassVar[str] = 'delete' + FLAG_DESCRIPTION: ClassVar[str] = Base.FLAG_DESCRIPTION + FLAG_DETAIL: ClassVar[str] = 'detail' + FLAG_DIALOG: ClassVar[str] = 'dialog' + FLAG_DIRTY: ClassVar[str] = 'dirty' + FLAG_DISPLAY_ORDER: ClassVar[str] = Base.FLAG_DISPLAY_ORDER + FLAG_EDIT: ClassVar[str] = 'edit' + FLAG_EMAIL: ClassVar[str] = Base.FLAG_EMAIL + FLAG_ERROR: ClassVar[str] = 'error' + FLAG_EXPANDED: ClassVar[str] = 'expanded' + FLAG_FAILURE: ClassVar[str] = 'failure' + FLAG_FILTER: ClassVar[str] = 'filter' + FLAG_FORM: ClassVar[str] = 'form' + FLAG_FORM_FILTERS: ClassVar[str] = 'form-filters' + FLAG_HAMBURGER: ClassVar[str] = 'hamburger' + FLAG_IMAGE_LOGO: ClassVar[str] = 'image-logo' + FLAG_INITIALISED: ClassVar[str] = 'initialised' + FLAG_LEFT_HAND_STUB: ClassVar[str] = 'lhs' + FLAG_LOGO: ClassVar[str] = 'logo' + FLAG_MESSAGE: ClassVar[str] = Command.FLAG_MESSAGE + FLAG_MODAL: ClassVar[str] = 'modal' + FLAG_NAME: ClassVar[str] = Base.FLAG_NAME + FLAG_NAME_ATTR_OPTION_TEXT: ClassVar[str] = Base.FLAG_NAME_ATTR_OPTION_TEXT + FLAG_NAME_ATTR_OPTION_VALUE: ClassVar[str] = Base.FLAG_NAME_ATTR_OPTION_VALUE + FLAG_NAME_PLURAL: ClassVar[str] = Base.FLAG_NAME_PLURAL + # FLAG_NAME_SINGULAR: ClassVar[str] = Base.FLAG_NAME_SINGULAR + FLAG_NAV_CONTACT: ClassVar[str] = 'navContact' + FLAG_NAV_HOME: ClassVar[str] = 'navHome' + FLAG_OVERLAY: ClassVar[str] = 'overlay' + FLAG_PAGE_BODY: ClassVar[str] = 'page-body' + FLAG_RIGHT_HAND_SIDE: ClassVar[str] = 'rhs' + FLAG_ROW: ClassVar[str] = 'row' + FLAG_ROW_NEW: ClassVar[str] = 'row-new' + FLAG_ROWS: ClassVar[str] = Base.FLAG_ROWS + FLAG_SAVE: ClassVar[str] = 'save' + FLAG_SCROLLABLE: ClassVar[str] = 'scrollable' + FLAG_SLIDER: ClassVar[str] = 'slider' + FLAG_STATUS: ClassVar[str] = 'status' + FLAG_SUBMIT: ClassVar[str] = 'submit' + FLAG_SUCCESS: ClassVar[str] = 'success' + FLAG_TEMPORARY_ELEMENT: ClassVar[str] = 'temporary-element' + FLAG_USER: ClassVar[str] = User.FLAG_USER + FLAG_WEBSITE: ClassVar[str] = Base.FLAG_WEBSITE + HASH_GET_ALTCHA_CHALLENGE: ClassVar[str] = '/altcha/create-challenge' + HASH_PAGE_ACCESSIBILITY_REPORT: ClassVar[str] = '/accessibility-report' + HASH_PAGE_ACCESSIBILITY_STATEMENT: ClassVar[str] = '/accessibility-statement' + HASH_PAGE_CONTACT: ClassVar[str] = '/contact' + HASH_PAGE_CONTACT_SUCCESS: ClassVar[str] = '/contact-success' + HASH_PAGE_DATA_RETENTION_SCHEDULE: ClassVar[str] = '/retention-schedule' + HASH_PAGE_ERROR_NO_PERMISSION: ClassVar[str] = '/error' + HASH_PAGE_HOME: ClassVar[str] = '/' + HASH_PAGE_LICENSE: ClassVar[str] = '/license' + HASH_PAGE_PRIVACY_POLICY: ClassVar[str] = '/privacy-policy' + ID_BUTTON_ADD: ClassVar[str] = 'buttonAdd' + ID_BUTTON_APPLY_FILTERS: ClassVar[str] = 'buttonApplyFilters' + ID_BUTTON_CANCEL: ClassVar[str] = 'buttonCancel' + ID_BUTTON_HAMBURGER: ClassVar[str] = 'buttonHamburger' + ID_BUTTON_SAVE: ClassVar[str] = 'buttonSave' + ID_CSRF_TOKEN: ClassVar[str] = 'X-CSRFToken' + ID_FORM_CONTACT: ClassVar[str] = 'formContact' + ID_FORM_FILTERS: ClassVar[str] = 'formFilters' + ID_LABEL_ERROR: ClassVar[str] = 'labelError' + ID_OVERLAY_CONFIRM: ClassVar[str] = 'overlayConfirm' + ID_OVERLAY_ERROR: ClassVar[str] = 'overlayError' + ID_OVERLAY_HAMBURGER: ClassVar[str] = 'overlayHamburger' + ID_PAGE_BODY: ClassVar[str] = 'pageBody' + ID_TABLE_MAIN: ClassVar[str] = 'tableMain' + ID_TEXTAREA_CONFIRM: ClassVar[str] = 'textareaConfirm' + NAME_COMPANY: ClassVar[str] = 'Precision And Research Technology Systems Limited' + NAME_COMPANY_SHORT: ClassVar[str] = 'PARTS Ltd' + NAME_CSRF_TOKEN: ClassVar[str] = 'csrf-token' + URL_GITHUB: ClassVar[str] = 'https://github.com/Teddy-1024' + URL_LINKEDIN: ClassVar[str] = 'https://uk.linkedin.com/in/teddyms' + + hash_page_current: str + app: Flask = None + session: None = None + is_page_store: bool = None + is_user_logged_in: bool = None + user: User = None + access_levels: list = None + + model_config = ConfigDict(arbitrary_types_allowed=True) + + @property + @abstractmethod + def title(self): + pass + + def __init__(self, hash_page_current, **kwargs): + BaseModel.__init__(self, hash_page_current=hash_page_current, **kwargs) + self.app = current_app + with self.app.app_context(): + self.session = session + self.is_page_store = False + Helper_App.console_log(f'session: {self.session}') + + datastore_base = DataStore_Base() + self.user = datastore_base.get_user_session() + self.is_user_logged_in = self.user.get_is_logged_in() + # Helper_App.console_log(f'model_view_base init end - model.user: {self.user}') + + def output_bool(self, boolean): + return str(boolean).lower() + + def get_url_host(self): + return self.app.config['URL_HOST'] + + def get_user_session(self): + datastore_user = DataStore_User() + return datastore_user.get_user_session() + + def get_many_access_level(self, filters=None): + _m = 'Model_View_Store.get_many_access_level' + # av.val_instance(filters, 'filters', _m, Filters_Access_Level) + access_levels, errors = DataStore_Base.get_many_access_level(filters) + return access_levels + def get_many_unit_measurement(self, filters=None): + _m = 'Model_View_Store.get_many_unit_measurement' + # av.val_instance(filters, 'filters', _m, Filters_Unit_Measurement) + units_measurement, errors = DataStore_Base.get_many_unit_measurement(filters) + return units_measurement + + @staticmethod + def convert_list_objects_to_json(list_objects): + return [obj.to_json() for obj in list_objects] + @staticmethod + def convert_list_objects_to_list_options(list_objects): + return Base.convert_list_objects_to_list_options(list_objects) + @staticmethod + def convert_list_objects_to_dict_by_attribute_key(list_objects, key): + return {getattr(obj, key): obj for obj in list_objects} + @staticmethod + def convert_list_objects_to_dict_json_by_attribute_key(list_objects, key): + return {getattr(obj, key): obj.to_json() for obj in list_objects} + @staticmethod + def convert_list_objects_to_dict_by_attribute_key_default(list_objects): + if list_objects is None or len(list_objects) == 0: + return {} + obj_class = list_objects[0].__class__ + return Model_View_Base.convert_list_objects_to_dict_by_attribute_key(list_objects, getattr(obj_class, obj_class.FLAG_NAME_ATTR_OPTION_VALUE)) + @staticmethod + def convert_list_objects_to_dict_json_by_attribute_key_default(list_objects): + if list_objects is None or len(list_objects) == 0: + return {} + obj_class = list_objects[0].__class__ + return Model_View_Base.convert_list_objects_to_dict_json_by_attribute_key(list_objects, getattr(obj_class, obj_class.FLAG_NAME_ATTR_OPTION_VALUE)) + @staticmethod + def convert_dict_values_to_json(dict): + return {key: dict[key].to_json() for key in dict.keys()} + @staticmethod + def convert_list_objects_to_preview_str(list_objects): + preview_str = '' + for obj in list_objects: + if preview_str != '': + preview_str += '\n' + obj_json = obj.to_json() + preview_str += obj_json[obj_json[Base.FLAG_NAME_ATTR_OPTION_TEXT]] + return preview_str + @staticmethod + def join_with_linebreaks(strs): + str_multiline = '' + for str in strs: + if str_multiline != '': + str_multiline += '\n' + str_multiline += str + return str_multiline + @staticmethod + def format_date(date): + if date is None: + return '' + return date.strftime('%Y-%m-%d') + @staticmethod + def format_datetime(date_time): + if date_time is None: + return '' + return date_time.strftime('%Y-%m-%dT%H:%M') + @staticmethod + def jsonify(data): + return jsonify(data) + def get_mail_contact_public(self): + return self.app.config['MAIL_CONTACT_PUBLIC'] \ No newline at end of file diff --git a/models/model_view_contact.py b/models/model_view_contact.py new file mode 100644 index 0000000..37ee540 --- /dev/null +++ b/models/model_view_contact.py @@ -0,0 +1,35 @@ +""" +Project: PARTS Website +Author: Edward Middleton-Smith + Precision And Research Technology Systems Limited + +Technology: View Models +Feature: Contact View Model + +Description: +Data model for contact view +""" + +# internal +from business_objects.project_hub.command import Command +from models.model_view_base import Model_View_Base +# from routes import bp_home +from lib import argument_validation as av +from forms.contact import Form_Contact +# external +from flask_wtf import FlaskForm +from abc import abstractproperty +from pydantic import BaseModel +from typing import ClassVar + +class Model_View_Contact(Model_View_Base): + + form_contact: Form_Contact + + @property + def title(self): + return 'Contact' + + def __init__(self, form_contact, hash_page_current=Model_View_Base.HASH_PAGE_CONTACT, **kwargs): + super().__init__(hash_page_current=hash_page_current, form_contact=form_contact, **kwargs) + # self.form = form diff --git a/models/model_view_contact_success.py b/models/model_view_contact_success.py new file mode 100644 index 0000000..178a0be --- /dev/null +++ b/models/model_view_contact_success.py @@ -0,0 +1,31 @@ +""" +Project: PARTS Website +Author: Edward Middleton-Smith + Precision And Research Technology Systems Limited + +Technology: View Models +Feature: Contact View Model + +Description: +Data model for contact view +""" + +# internal +from models.model_view_base import Model_View_Base +# from routes import bp_home +from lib import argument_validation as av +# from forms.contact import Form_Contact +# external +from flask_wtf import FlaskForm +from abc import abstractproperty +from pydantic import BaseModel +from typing import ClassVar + +class Model_View_Contact_Success(Model_View_Base): + + @property + def title(self): + return 'Contact Success' + + def __init__(self, hash_page_current=Model_View_Base.HASH_PAGE_CONTACT_SUCCESS, **kwargs): + super().__init__(hash_page_current=hash_page_current, **kwargs) diff --git a/models/model_view_home.py b/models/model_view_home.py new file mode 100644 index 0000000..f7bb6e2 --- /dev/null +++ b/models/model_view_home.py @@ -0,0 +1,24 @@ +""" +Project: PARTS Website +Author: Edward Middleton-Smith + Precision And Research Technology Systems Limited + +Technology: Core View Models +Feature: Home View Model + +Description: +Data model for home view +""" + +# internal +from models.model_view_base import Model_View_Base +# from routes import bp_home +# external + +class Model_View_Home(Model_View_Base): + @property + def title(self): + return 'Home' + def __init__(self, hash_page_current=Model_View_Base.HASH_PAGE_HOME): + super().__init__(hash_page_current=hash_page_current) + \ No newline at end of file diff --git a/models/model_view_license.py b/models/model_view_license.py new file mode 100644 index 0000000..f891df1 --- /dev/null +++ b/models/model_view_license.py @@ -0,0 +1,24 @@ +""" +Project: PARTS Website +Author: Edward Middleton-Smith + Precision And Research Technology Systems Limited + +Technology: Legal View Models +Feature: License View Model + +Description: +Data model for license view +""" + +# internal +from models.model_view_base import Model_View_Base +# from routes import bp_home +# external + +class Model_View_License(Model_View_Base): + @property + def title(self): + return 'License' + def __init__(self, hash_page_current=Model_View_Base.HASH_PAGE_LICENSE): + super().__init__(hash_page_current=hash_page_current) + \ No newline at end of file diff --git a/models/model_view_privacy_policy.py b/models/model_view_privacy_policy.py new file mode 100644 index 0000000..0424333 --- /dev/null +++ b/models/model_view_privacy_policy.py @@ -0,0 +1,24 @@ +""" +Project: PARTS Website +Author: Edward Middleton-Smith + Precision And Research Technology Systems Limited + +Technology: Legal View Models +Feature: Privacy Policy View Model + +Description: +Data model for privacy policy view +""" + +# internal +from models.model_view_base import Model_View_Base +# from routes import bp_home +# external + +class Model_View_Privacy_Policy(Model_View_Base): + @property + def title(self): + return 'Privacy Policy' + def __init__(self, hash_page_current=Model_View_Base.HASH_PAGE_PRIVACY_POLICY): + super().__init__(hash_page_current=hash_page_current) + \ No newline at end of file diff --git a/models/model_view_retention_schedule.py b/models/model_view_retention_schedule.py new file mode 100644 index 0000000..3f28d20 --- /dev/null +++ b/models/model_view_retention_schedule.py @@ -0,0 +1,24 @@ +""" +Project: PARTS Website +Author: Edward Middleton-Smith + Precision And Research Technology Systems Limited + +Technology: Legal View Models +Feature: Retention Schedule View Model + +Description: +Data model for retention schedule view +""" + +# internal +from models.model_view_base import Model_View_Base +# from routes import bp_home +# external + +class Model_View_Retention_Schedule(Model_View_Base): + @property + def title(self): + return 'Retention Schedule' + def __init__(self, hash_page_current=Model_View_Base.HASH_PAGE_DATA_RETENTION_SCHEDULE): + super().__init__(hash_page_current=hash_page_current) + \ No newline at end of file diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..8b32eae --- /dev/null +++ b/package-lock.json @@ -0,0 +1,4296 @@ +{ + "name": "app", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "app", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "aos": "^2.3.4" + }, + "devDependencies": { + "@babel/core": "^7.25.2", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/preset-env": "^7.25.4", + "babel-loader": "^9.1.3", + "css-loader": "^7.1.2", + "glob": "^11.0.0", + "mini-css-extract-plugin": "^2.9.1", + "style-loader": "^4.0.0", + "webpack": "^5.94.0", + "webpack-cli": "^5.1.4" + } + }, + "node_modules/@ampproject/remapping": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", + "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", + "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.25.9", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.26.5", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.5.tgz", + "integrity": "sha512-XvcZi1KWf88RVbF9wn8MN6tYFloU5qX8KjuF3E1PVBmJ9eypXfs4GRiJwLuTZL0iSnJUKn1BFPa5BPZZJyFzPg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.0.tgz", + "integrity": "sha512-i1SLeK+DzNnQ3LL/CswPCa/E5u4lh1k6IAEphON8F+cXt0t9euTshDru0q7/IqMa1PMPz5RnHuHscF8/ZJsStg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.26.0", + "@babel/generator": "^7.26.0", + "@babel/helper-compilation-targets": "^7.25.9", + "@babel/helper-module-transforms": "^7.26.0", + "@babel/helpers": "^7.26.0", + "@babel/parser": "^7.26.0", + "@babel/template": "^7.25.9", + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.26.0", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/generator": { + "version": "7.26.5", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.5.tgz", + "integrity": "sha512-2caSP6fN9I7HOe6nqhtft7V4g7/V/gfDsC3Ag4W7kEzzvRGKqiv0pu0HogPiZ3KaVSoNDhUws6IJjDjpfmYIXw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.26.5", + "@babel/types": "^7.26.5", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-annotate-as-pure": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.25.9.tgz", + "integrity": "sha512-gv7320KBUFJz1RnylIg5WWYPRXKZ884AGkYpgpWW02TH66Dl+HaC1t1CKd0z3R4b6hdYEcmrNZHUmfCP+1u3/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.26.5", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.26.5.tgz", + "integrity": "sha512-IXuyn5EkouFJscIDuFF5EsiSolseme1s0CZB+QxVugqJLYmKdxI1VfIBOst0SUu4rnk2Z7kqTwmoO1lp3HIfnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.26.5", + "@babel/helper-validator-option": "^7.25.9", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-create-class-features-plugin": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.25.9.tgz", + "integrity": "sha512-UTZQMvt0d/rSz6KI+qdu7GQze5TIajwTS++GUozlw8VBJDEOAqSXwm1WvmYEZwqdqSGQshRocPDqrt4HBZB3fQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.25.9", + "@babel/helper-member-expression-to-functions": "^7.25.9", + "@babel/helper-optimise-call-expression": "^7.25.9", + "@babel/helper-replace-supers": "^7.25.9", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9", + "@babel/traverse": "^7.25.9", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-create-regexp-features-plugin": { + "version": "7.26.3", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.26.3.tgz", + "integrity": "sha512-G7ZRb40uUgdKOQqPLjfD12ZmGA54PzqDFUv2BKImnC9QIfGhIHKvVML0oN8IUiDq4iRqpq74ABpvOaerfWdong==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.25.9", + "regexpu-core": "^6.2.0", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-define-polyfill-provider": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.3.tgz", + "integrity": "sha512-HK7Bi+Hj6H+VTHA3ZvBis7V/6hu9QuTrnMXNybfUf2iiuU/N97I8VjB+KbhFF8Rld/Lx5MzoCwPCpPjfK+n8Cg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-compilation-targets": "^7.22.6", + "@babel/helper-plugin-utils": "^7.22.5", + "debug": "^4.1.1", + "lodash.debounce": "^4.0.8", + "resolve": "^1.14.2" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/@babel/helper-member-expression-to-functions": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.25.9.tgz", + "integrity": "sha512-wbfdZ9w5vk0C0oyHqAJbc62+vet5prjj01jjJ8sKn3j9h3MQQlflEdXYvuqRWjHnM12coDEqiC1IRCi0U/EKwQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz", + "integrity": "sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz", + "integrity": "sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9", + "@babel/traverse": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-optimise-call-expression": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.25.9.tgz", + "integrity": "sha512-FIpuNaz5ow8VyrYcnXQTDRGvV6tTjkNtCK/RYNDXGSLlUD6cBuQTSw43CShGxjvfBTfcUA/r6UhUCbtYqkhcuQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.26.5", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.26.5.tgz", + "integrity": "sha512-RS+jZcRdZdRFzMyr+wcsaqOmld1/EqTghfaBGQQd/WnRdzdlvSZ//kF7U8VQTxf1ynZ4cjUcYgjVGx13ewNPMg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-remap-async-to-generator": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.25.9.tgz", + "integrity": "sha512-IZtukuUeBbhgOcaW2s06OXTzVNJR0ybm4W5xC1opWFFJMZbwRj5LCk+ByYH7WdZPZTt8KnFwA8pvjN2yqcPlgw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.25.9", + "@babel/helper-wrap-function": "^7.25.9", + "@babel/traverse": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-replace-supers": { + "version": "7.26.5", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.26.5.tgz", + "integrity": "sha512-bJ6iIVdYX1YooY2X7w1q6VITt+LnUILtNk7zT78ykuwStx8BauCzxvFqFaHjOpW1bVnSUM1PN1f0p5P21wHxvg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-member-expression-to-functions": "^7.25.9", + "@babel/helper-optimise-call-expression": "^7.25.9", + "@babel/traverse": "^7.26.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.25.9.tgz", + "integrity": "sha512-K4Du3BFa3gvyhzgPcntrkDgZzQaq6uozzcpGbOO1OEJaI+EJdqWIMTLgFgQf6lrfiDFo5FU+BxKepI9RmZqahA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", + "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", + "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.25.9.tgz", + "integrity": "sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-wrap-function": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.25.9.tgz", + "integrity": "sha512-ETzz9UTjQSTmw39GboatdymDq4XIQbR8ySgVrylRhPOFpsd+JrKHIuF0de7GCWmem+T4uC5z7EZguod7Wj4A4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.25.9", + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.26.0.tgz", + "integrity": "sha512-tbhNuIxNcVb21pInl3ZSjksLCvgdZy9KwJ8brv993QtIVKJBBkYXz4q4ZbAv31GdnC+R90np23L5FbEBlthAEw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.25.9", + "@babel/types": "^7.26.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.26.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.5.tgz", + "integrity": "sha512-SRJ4jYmXRqV1/Xc+TIVG84WjHBXKlxO9sHQnA2Pf12QQEAp1LOh6kDzNHXcUnbH1QI0FDoPPVOt+vyUDucxpaw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.26.5" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-firefox-class-in-computed-class-key": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.25.9.tgz", + "integrity": "sha512-ZkRyVkThtxQ/J6nv3JFYv1RYY+JT5BvU0y3k5bWrmuG4woXypRa4PXmm9RhOwodRkYFWqC0C0cqcJ4OqR7kW+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/traverse": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-safari-class-field-initializer-scope": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-class-field-initializer-scope/-/plugin-bugfix-safari-class-field-initializer-scope-7.25.9.tgz", + "integrity": "sha512-MrGRLZxLD/Zjj0gdU15dfs+HH/OXvnw/U4jJD8vpcP2CJQapPEv1IWwjc/qMg7ItBlPwSv1hRBbb7LeuANdcnw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.25.9.tgz", + "integrity": "sha512-2qUwwfAFpJLZqxd02YW9btUCZHl+RFvdDkNfZwaIJrvB8Tesjsk8pEQkTvGwZXLqXUx/2oyY3ySRhm6HOXuCug==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.25.9.tgz", + "integrity": "sha512-6xWgLZTJXwilVjlnV7ospI3xi+sl8lN8rXXbBD6vYn3UYDlGsag8wrZkKcSI8G6KgqKP7vNFaDgeDnfAABq61g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9", + "@babel/plugin-transform-optional-chaining": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.13.0" + } + }, + "node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.25.9.tgz", + "integrity": "sha512-aLnMXYPnzwwqhYSCyXfKkIkYgJ8zv9RK+roo9DkTXz38ynIhd9XCbN08s3MGvqL2MYGVUGdRQLL/JqBIeJhJBg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/traverse": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-proposal-private-property-in-object": { + "version": "7.21.0-placeholder-for-preset-env.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", + "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-dynamic-import": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", + "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-assertions": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.26.0.tgz", + "integrity": "sha512-QCWT5Hh830hK5EQa7XzuqIkQU9tT/whqbDz7kuaZMHFl1inRRg7JnuAEOQ0Ur0QUl0NufCk1msK2BeY79Aj/eg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-attributes": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.26.0.tgz", + "integrity": "sha512-e2dttdsJ1ZTpi3B9UYGLw41hifAubg19AtCu/2I/F1QNVclOBr1dYpTdmdyZ84Xiz43BS/tCUkMAZNLv12Pi+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-unicode-sets-regex": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz", + "integrity": "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-arrow-functions": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.25.9.tgz", + "integrity": "sha512-6jmooXYIwn9ca5/RylZADJ+EnSxVUS5sjeJ9UPk6RWRzXCmOJCy6dqItPJFpw2cuCangPK4OYr5uhGKcmrm5Qg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-async-generator-functions": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.25.9.tgz", + "integrity": "sha512-RXV6QAzTBbhDMO9fWwOmwwTuYaiPbggWQ9INdZqAYeSHyG7FzQ+nOZaUUjNwKv9pV3aE4WFqFm1Hnbci5tBCAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-remap-async-to-generator": "^7.25.9", + "@babel/traverse": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-async-to-generator": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.25.9.tgz", + "integrity": "sha512-NT7Ejn7Z/LjUH0Gv5KsBCxh7BH3fbLTV0ptHvpeMvrt3cPThHfJfst9Wrb7S8EvJ7vRTFI7z+VAvFVEQn/m5zQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-remap-async-to-generator": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-block-scoped-functions": { + "version": "7.26.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.26.5.tgz", + "integrity": "sha512-chuTSY+hq09+/f5lMj8ZSYgCFpppV2CbYrhNFJ1BFoXpiWPnnAb7R0MqrafCpN8E1+YRrtM1MXZHJdIx8B6rMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.26.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-block-scoping": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.25.9.tgz", + "integrity": "sha512-1F05O7AYjymAtqbsFETboN1NvBdcnzMerO+zlMyJBEz6WkMdejvGWw9p05iTSjC85RLlBseHHQpYaM4gzJkBGg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-class-properties": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.25.9.tgz", + "integrity": "sha512-bbMAII8GRSkcd0h0b4X+36GksxuheLFjP65ul9w6C3KgAamI3JqErNgSrosX6ZPj+Mpim5VvEbawXxJCyEUV3Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-class-static-block": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.26.0.tgz", + "integrity": "sha512-6J2APTs7BDDm+UMqP1useWqhcRAXo0WIoVj26N7kPFB6S73Lgvyka4KTZYIxtgYXiN5HTyRObA72N2iu628iTQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.12.0" + } + }, + "node_modules/@babel/plugin-transform-classes": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.25.9.tgz", + "integrity": "sha512-mD8APIXmseE7oZvZgGABDyM34GUmK45Um2TXiBUt7PnuAxrgoSVf123qUzPxEr/+/BHrRn5NMZCdE2m/1F8DGg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.25.9", + "@babel/helper-compilation-targets": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-replace-supers": "^7.25.9", + "@babel/traverse": "^7.25.9", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-computed-properties": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.25.9.tgz", + "integrity": "sha512-HnBegGqXZR12xbcTHlJ9HGxw1OniltT26J5YpfruGqtUHlz/xKf/G2ak9e+t0rVqrjXa9WOhvYPz1ERfMj23AA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/template": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-destructuring": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.25.9.tgz", + "integrity": "sha512-WkCGb/3ZxXepmMiX101nnGiU+1CAdut8oHyEOHxkKuS1qKpU2SMXE2uSvfz8PBuLd49V6LEsbtyPhWC7fnkgvQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-dotall-regex": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.25.9.tgz", + "integrity": "sha512-t7ZQ7g5trIgSRYhI9pIJtRl64KHotutUJsh4Eze5l7olJv+mRSg4/MmbZ0tv1eeqRbdvo/+trvJD/Oc5DmW2cA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-duplicate-keys": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.25.9.tgz", + "integrity": "sha512-LZxhJ6dvBb/f3x8xwWIuyiAHy56nrRG3PeYTpBkkzkYRRQ6tJLu68lEF5VIqMUZiAV7a8+Tb78nEoMCMcqjXBw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-duplicate-named-capturing-groups-regex": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-named-capturing-groups-regex/-/plugin-transform-duplicate-named-capturing-groups-regex-7.25.9.tgz", + "integrity": "sha512-0UfuJS0EsXbRvKnwcLjFtJy/Sxc5J5jhLHnFhy7u4zih97Hz6tJkLU+O+FMMrNZrosUPxDi6sYxJ/EA8jDiAog==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-dynamic-import": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.25.9.tgz", + "integrity": "sha512-GCggjexbmSLaFhqsojeugBpeaRIgWNTcgKVq/0qIteFEqY2A+b9QidYadrWlnbWQUrW5fn+mCvf3tr7OeBFTyg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-exponentiation-operator": { + "version": "7.26.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.26.3.tgz", + "integrity": "sha512-7CAHcQ58z2chuXPWblnn1K6rLDnDWieghSOEmqQsrBenH0P9InCUtOJYD89pvngljmZlJcz3fcmgYsXFNGa1ZQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-export-namespace-from": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.25.9.tgz", + "integrity": "sha512-2NsEz+CxzJIVOPx2o9UsW1rXLqtChtLoVnwYHHiB04wS5sgn7mrV45fWMBX0Kk+ub9uXytVYfNP2HjbVbCB3Ww==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-for-of": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.25.9.tgz", + "integrity": "sha512-LqHxduHoaGELJl2uhImHwRQudhCM50pT46rIBNvtT/Oql3nqiS3wOwP+5ten7NpYSXrrVLgtZU3DZmPtWZo16A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-function-name": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.25.9.tgz", + "integrity": "sha512-8lP+Yxjv14Vc5MuWBpJsoUCd3hD6V9DgBon2FVYL4jJgbnVQ9fTgYmonchzZJOVNgzEgbxp4OwAf6xz6M/14XA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-compilation-targets": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/traverse": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-json-strings": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.25.9.tgz", + "integrity": "sha512-xoTMk0WXceiiIvsaquQQUaLLXSW1KJ159KP87VilruQm0LNNGxWzahxSS6T6i4Zg3ezp4vA4zuwiNUR53qmQAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-literals": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.25.9.tgz", + "integrity": "sha512-9N7+2lFziW8W9pBl2TzaNht3+pgMIRP74zizeCSrtnSKVdUl8mAjjOP2OOVQAfZ881P2cNjDj1uAMEdeD50nuQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-logical-assignment-operators": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.25.9.tgz", + "integrity": "sha512-wI4wRAzGko551Y8eVf6iOY9EouIDTtPb0ByZx+ktDGHwv6bHFimrgJM/2T021txPZ2s4c7bqvHbd+vXG6K948Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-member-expression-literals": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.25.9.tgz", + "integrity": "sha512-PYazBVfofCQkkMzh2P6IdIUaCEWni3iYEerAsRWuVd8+jlM1S9S9cz1dF9hIzyoZ8IA3+OwVYIp9v9e+GbgZhA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-amd": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.25.9.tgz", + "integrity": "sha512-g5T11tnI36jVClQlMlt4qKDLlWnG5pP9CSM4GhdRciTNMRgkfpo5cR6b4rGIOYPgRRuFAvwjPQ/Yk+ql4dyhbw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-transforms": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-commonjs": { + "version": "7.26.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.26.3.tgz", + "integrity": "sha512-MgR55l4q9KddUDITEzEFYn5ZsGDXMSsU9E+kh7fjRXTIC3RHqfCo8RPRbyReYJh44HQ/yomFkqbOFohXvDCiIQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-transforms": "^7.26.0", + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-systemjs": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.25.9.tgz", + "integrity": "sha512-hyss7iIlH/zLHaehT+xwiymtPOpsiwIIRlCAOwBB04ta5Tt+lNItADdlXw3jAWZ96VJ2jlhl/c+PNIQPKNfvcA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-transforms": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9", + "@babel/traverse": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-umd": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.25.9.tgz", + "integrity": "sha512-bS9MVObUgE7ww36HEfwe6g9WakQ0KF07mQF74uuXdkoziUPfKyu/nIm663kz//e5O1nPInPFx36z7WJmJ4yNEw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-transforms": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.25.9.tgz", + "integrity": "sha512-oqB6WHdKTGl3q/ItQhpLSnWWOpjUJLsOCLVyeFgeTktkBSCiurvPOsyt93gibI9CmuKvTUEtWmG5VhZD+5T/KA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-new-target": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.25.9.tgz", + "integrity": "sha512-U/3p8X1yCSoKyUj2eOBIx3FOn6pElFOKvAAGf8HTtItuPyB+ZeOqfn+mvTtg9ZlOAjsPdK3ayQEjqHjU/yLeVQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-nullish-coalescing-operator": { + "version": "7.26.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.26.6.tgz", + "integrity": "sha512-CKW8Vu+uUZneQCPtXmSBUC6NCAUdya26hWCElAWh5mVSlSRsmiCPUUDKb3Z0szng1hiAJa098Hkhg9o4SE35Qw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.26.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-numeric-separator": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.25.9.tgz", + "integrity": "sha512-TlprrJ1GBZ3r6s96Yq8gEQv82s8/5HnCVHtEJScUj90thHQbwe+E5MLhi2bbNHBEJuzrvltXSru+BUxHDoog7Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-object-rest-spread": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.25.9.tgz", + "integrity": "sha512-fSaXafEE9CVHPweLYw4J0emp1t8zYTXyzN3UuG+lylqkvYd7RMrsOQ8TYx5RF231be0vqtFC6jnx3UmpJmKBYg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-compilation-targets": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/plugin-transform-parameters": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-object-super": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.25.9.tgz", + "integrity": "sha512-Kj/Gh+Rw2RNLbCK1VAWj2U48yxxqL2x0k10nPtSdRa0O2xnHXalD0s+o1A6a0W43gJ00ANo38jxkQreckOzv5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-replace-supers": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-optional-catch-binding": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.25.9.tgz", + "integrity": "sha512-qM/6m6hQZzDcZF3onzIhZeDHDO43bkNNlOX0i8n3lR6zLbu0GN2d8qfM/IERJZYauhAHSLHy39NF0Ctdvcid7g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-optional-chaining": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.25.9.tgz", + "integrity": "sha512-6AvV0FsLULbpnXeBjrY4dmWF8F7gf8QnvTEoO/wX/5xm/xE1Xo8oPuD3MPS+KS9f9XBEAWN7X1aWr4z9HdOr7A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-parameters": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.25.9.tgz", + "integrity": "sha512-wzz6MKwpnshBAiRmn4jR8LYz/g8Ksg0o80XmwZDlordjwEk9SxBzTWC7F5ef1jhbrbOW2DJ5J6ayRukrJmnr0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-private-methods": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.25.9.tgz", + "integrity": "sha512-D/JUozNpQLAPUVusvqMxyvjzllRaF8/nSrP1s2YGQT/W4LHK4xxsMcHjhOGTS01mp9Hda8nswb+FblLdJornQw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-private-property-in-object": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.25.9.tgz", + "integrity": "sha512-Evf3kcMqzXA3xfYJmZ9Pg1OvKdtqsDMSWBDzZOPLvHiTt36E75jLDQo5w1gtRU95Q4E5PDttrTf25Fw8d/uWLw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.25.9", + "@babel/helper-create-class-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-property-literals": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.25.9.tgz", + "integrity": "sha512-IvIUeV5KrS/VPavfSM/Iu+RE6llrHrYIKY1yfCzyO/lMXHQ+p7uGhonmGVisv6tSBSVgWzMBohTcvkC9vQcQFA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-regenerator": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.25.9.tgz", + "integrity": "sha512-vwDcDNsgMPDGP0nMqzahDWE5/MLcX8sv96+wfX7as7LoF/kr97Bo/7fI00lXY4wUXYfVmwIIyG80fGZ1uvt2qg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9", + "regenerator-transform": "^0.15.2" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-regexp-modifiers": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regexp-modifiers/-/plugin-transform-regexp-modifiers-7.26.0.tgz", + "integrity": "sha512-vN6saax7lrA2yA/Pak3sCxuD6F5InBjn9IcrIKQPjpsLvuHYLVroTxjdlVRHjjBWxKOqIwpTXDkOssYT4BFdRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-reserved-words": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.25.9.tgz", + "integrity": "sha512-7DL7DKYjn5Su++4RXu8puKZm2XBPHyjWLUidaPEkCUBbE7IPcsrkRHggAOOKydH1dASWdcUBxrkOGNxUv5P3Jg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-shorthand-properties": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.25.9.tgz", + "integrity": "sha512-MUv6t0FhO5qHnS/W8XCbHmiRWOphNufpE1IVxhK5kuN3Td9FT1x4rx4K42s3RYdMXCXpfWkGSbCSd0Z64xA7Ng==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-spread": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.25.9.tgz", + "integrity": "sha512-oNknIB0TbURU5pqJFVbOOFspVlrpVwo2H1+HUIsVDvp5VauGGDP1ZEvO8Nn5xyMEs3dakajOxlmkNW7kNgSm6A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-sticky-regex": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.25.9.tgz", + "integrity": "sha512-WqBUSgeVwucYDP9U/xNRQam7xV8W5Zf+6Eo7T2SRVUFlhRiMNFdFz58u0KZmCVVqs2i7SHgpRnAhzRNmKfi2uA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-template-literals": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.25.9.tgz", + "integrity": "sha512-o97AE4syN71M/lxrCtQByzphAdlYluKPDBzDVzMmfCobUjjhAryZV0AIpRPrxN0eAkxXO6ZLEScmt+PNhj2OTw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-typeof-symbol": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.25.9.tgz", + "integrity": "sha512-v61XqUMiueJROUv66BVIOi0Fv/CUuZuZMl5NkRoCVxLAnMexZ0A3kMe7vvZ0nulxMuMp0Mk6S5hNh48yki08ZA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-escapes": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.25.9.tgz", + "integrity": "sha512-s5EDrE6bW97LtxOcGj1Khcx5AaXwiMmi4toFWRDP9/y0Woo6pXC+iyPu/KuhKtfSrNFd7jJB+/fkOtZy6aIC6Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-property-regex": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.25.9.tgz", + "integrity": "sha512-Jt2d8Ga+QwRluxRQ307Vlxa6dMrYEMZCgGxoPR8V52rxPyldHu3hdlHspxaqYmE7oID5+kB+UKUB/eWS+DkkWg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-regex": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.25.9.tgz", + "integrity": "sha512-yoxstj7Rg9dlNn9UQxzk4fcNivwv4nUYz7fYXBaKxvw/lnmPuOm/ikoELygbYq68Bls3D/D+NBPHiLwZdZZ4HA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-sets-regex": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.25.9.tgz", + "integrity": "sha512-8BYqO3GeVNHtx69fdPshN3fnzUNLrWdHhk/icSwigksJGczKSizZ+Z6SBCxTs723Fr5VSNorTIK7a+R2tISvwQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/preset-env": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.26.0.tgz", + "integrity": "sha512-H84Fxq0CQJNdPFT2DrfnylZ3cf5K43rGfWK4LJGPpjKHiZlk0/RzwEus3PDDZZg+/Er7lCA03MVacueUuXdzfw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.26.0", + "@babel/helper-compilation-targets": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-validator-option": "^7.25.9", + "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.25.9", + "@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.25.9", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.25.9", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.25.9", + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.25.9", + "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", + "@babel/plugin-syntax-import-assertions": "^7.26.0", + "@babel/plugin-syntax-import-attributes": "^7.26.0", + "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", + "@babel/plugin-transform-arrow-functions": "^7.25.9", + "@babel/plugin-transform-async-generator-functions": "^7.25.9", + "@babel/plugin-transform-async-to-generator": "^7.25.9", + "@babel/plugin-transform-block-scoped-functions": "^7.25.9", + "@babel/plugin-transform-block-scoping": "^7.25.9", + "@babel/plugin-transform-class-properties": "^7.25.9", + "@babel/plugin-transform-class-static-block": "^7.26.0", + "@babel/plugin-transform-classes": "^7.25.9", + "@babel/plugin-transform-computed-properties": "^7.25.9", + "@babel/plugin-transform-destructuring": "^7.25.9", + "@babel/plugin-transform-dotall-regex": "^7.25.9", + "@babel/plugin-transform-duplicate-keys": "^7.25.9", + "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.25.9", + "@babel/plugin-transform-dynamic-import": "^7.25.9", + "@babel/plugin-transform-exponentiation-operator": "^7.25.9", + "@babel/plugin-transform-export-namespace-from": "^7.25.9", + "@babel/plugin-transform-for-of": "^7.25.9", + "@babel/plugin-transform-function-name": "^7.25.9", + "@babel/plugin-transform-json-strings": "^7.25.9", + "@babel/plugin-transform-literals": "^7.25.9", + "@babel/plugin-transform-logical-assignment-operators": "^7.25.9", + "@babel/plugin-transform-member-expression-literals": "^7.25.9", + "@babel/plugin-transform-modules-amd": "^7.25.9", + "@babel/plugin-transform-modules-commonjs": "^7.25.9", + "@babel/plugin-transform-modules-systemjs": "^7.25.9", + "@babel/plugin-transform-modules-umd": "^7.25.9", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.25.9", + "@babel/plugin-transform-new-target": "^7.25.9", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.25.9", + "@babel/plugin-transform-numeric-separator": "^7.25.9", + "@babel/plugin-transform-object-rest-spread": "^7.25.9", + "@babel/plugin-transform-object-super": "^7.25.9", + "@babel/plugin-transform-optional-catch-binding": "^7.25.9", + "@babel/plugin-transform-optional-chaining": "^7.25.9", + "@babel/plugin-transform-parameters": "^7.25.9", + "@babel/plugin-transform-private-methods": "^7.25.9", + "@babel/plugin-transform-private-property-in-object": "^7.25.9", + "@babel/plugin-transform-property-literals": "^7.25.9", + "@babel/plugin-transform-regenerator": "^7.25.9", + "@babel/plugin-transform-regexp-modifiers": "^7.26.0", + "@babel/plugin-transform-reserved-words": "^7.25.9", + "@babel/plugin-transform-shorthand-properties": "^7.25.9", + "@babel/plugin-transform-spread": "^7.25.9", + "@babel/plugin-transform-sticky-regex": "^7.25.9", + "@babel/plugin-transform-template-literals": "^7.25.9", + "@babel/plugin-transform-typeof-symbol": "^7.25.9", + "@babel/plugin-transform-unicode-escapes": "^7.25.9", + "@babel/plugin-transform-unicode-property-regex": "^7.25.9", + "@babel/plugin-transform-unicode-regex": "^7.25.9", + "@babel/plugin-transform-unicode-sets-regex": "^7.25.9", + "@babel/preset-modules": "0.1.6-no-external-plugins", + "babel-plugin-polyfill-corejs2": "^0.4.10", + "babel-plugin-polyfill-corejs3": "^0.10.6", + "babel-plugin-polyfill-regenerator": "^0.6.1", + "core-js-compat": "^3.38.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-modules": { + "version": "0.1.6-no-external-plugins", + "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz", + "integrity": "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/types": "^7.4.4", + "esutils": "^2.0.2" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/@babel/runtime": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.26.0.tgz", + "integrity": "sha512-FDSOghenHTiToteC/QRlv2q3DhPZ/oOXTBoirfWNx1Cx3TMVcGWQtMMmQcSvb/JjpNeGzx8Pq/b4fKEJuWm1sw==", + "dev": true, + "license": "MIT", + "dependencies": { + "regenerator-runtime": "^0.14.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/template": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.9.tgz", + "integrity": "sha512-9DGttpmPvIxBb/2uwpVo3dqJ+O6RooAFOS+lB+xDqoE2PVCE8nfoHMdZLpfCQRLwvohzXISPZcgxt80xLfsuwg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.25.9", + "@babel/parser": "^7.25.9", + "@babel/types": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.26.5", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.26.5.tgz", + "integrity": "sha512-rkOSPOw+AXbgtwUga3U4u8RpoK9FEFWBNAlTpcnkLFjL5CT+oyHNuUUC/xx6XefEJ16r38r8Bc/lfp6rYuHeJQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.26.2", + "@babel/generator": "^7.26.5", + "@babel/parser": "^7.26.5", + "@babel/template": "^7.25.9", + "@babel/types": "^7.26.5", + "debug": "^4.3.1", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.26.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.5.tgz", + "integrity": "sha512-L6mZmwFDK6Cjh1nRCLXpa6no13ZIioJDz7mdkzHv399pThrTa/k0nUlNaenOeh2kWu/iaOQYElEpKPUswUa9Vg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@discoveryjs/json-ext": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", + "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz", + "integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/source-map": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz", + "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@types/eslint": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.1.tgz", + "integrity": "sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "*", + "@types/json-schema": "*" + } + }, + "node_modules/@types/eslint-scope": { + "version": "3.7.7", + "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz", + "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/eslint": "*", + "@types/estree": "*" + } + }, + "node_modules/@types/estree": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", + "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "22.10.6", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.6.tgz", + "integrity": "sha512-qNiuwC4ZDAUNcY47xgaSuS92cjf8JbSUoaKS77bmLG1rU7MlATVSiw/IlrjtIyyskXBZ8KkNfjK/P5na7rgXbQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.20.0" + } + }, + "node_modules/@webassemblyjs/ast": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.14.1.tgz", + "integrity": "sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@webassemblyjs/helper-numbers": "1.13.2", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2" + } + }, + "node_modules/@webassemblyjs/floating-point-hex-parser": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.13.2.tgz", + "integrity": "sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@webassemblyjs/helper-api-error": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.13.2.tgz", + "integrity": "sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@webassemblyjs/helper-buffer": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.14.1.tgz", + "integrity": "sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@webassemblyjs/helper-numbers": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.13.2.tgz", + "integrity": "sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@webassemblyjs/floating-point-hex-parser": "1.13.2", + "@webassemblyjs/helper-api-error": "1.13.2", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/helper-wasm-bytecode": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.13.2.tgz", + "integrity": "sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@webassemblyjs/helper-wasm-section": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.14.1.tgz", + "integrity": "sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/wasm-gen": "1.14.1" + } + }, + "node_modules/@webassemblyjs/ieee754": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.13.2.tgz", + "integrity": "sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "node_modules/@webassemblyjs/leb128": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.13.2.tgz", + "integrity": "sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/utf8": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.13.2.tgz", + "integrity": "sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@webassemblyjs/wasm-edit": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.14.1.tgz", + "integrity": "sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/helper-wasm-section": "1.14.1", + "@webassemblyjs/wasm-gen": "1.14.1", + "@webassemblyjs/wasm-opt": "1.14.1", + "@webassemblyjs/wasm-parser": "1.14.1", + "@webassemblyjs/wast-printer": "1.14.1" + } + }, + "node_modules/@webassemblyjs/wasm-gen": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.14.1.tgz", + "integrity": "sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/ieee754": "1.13.2", + "@webassemblyjs/leb128": "1.13.2", + "@webassemblyjs/utf8": "1.13.2" + } + }, + "node_modules/@webassemblyjs/wasm-opt": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.14.1.tgz", + "integrity": "sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/wasm-gen": "1.14.1", + "@webassemblyjs/wasm-parser": "1.14.1" + } + }, + "node_modules/@webassemblyjs/wasm-parser": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.14.1.tgz", + "integrity": "sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-api-error": "1.13.2", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/ieee754": "1.13.2", + "@webassemblyjs/leb128": "1.13.2", + "@webassemblyjs/utf8": "1.13.2" + } + }, + "node_modules/@webassemblyjs/wast-printer": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.14.1.tgz", + "integrity": "sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webpack-cli/configtest": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-2.1.1.tgz", + "integrity": "sha512-wy0mglZpDSiSS0XHrVR+BAdId2+yxPSoJW8fsna3ZpYSlufjvxnP4YbKTCBZnNIcGN4r6ZPXV55X4mYExOfLmw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.15.0" + }, + "peerDependencies": { + "webpack": "5.x.x", + "webpack-cli": "5.x.x" + } + }, + "node_modules/@webpack-cli/info": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-2.0.2.tgz", + "integrity": "sha512-zLHQdI/Qs1UyT5UBdWNqsARasIA+AaF8t+4u2aS2nEpBQh2mWIVb8qAklq0eUENnC5mOItrIB4LiS9xMtph18A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.15.0" + }, + "peerDependencies": { + "webpack": "5.x.x", + "webpack-cli": "5.x.x" + } + }, + "node_modules/@webpack-cli/serve": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-2.0.5.tgz", + "integrity": "sha512-lqaoKnRYBdo1UgDX8uF24AfGMifWK19TxPmM5FHc2vAGxrJ/qtyUyFBWoY1tISZdelsQ5fBcOusifo5o5wSJxQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.15.0" + }, + "peerDependencies": { + "webpack": "5.x.x", + "webpack-cli": "5.x.x" + }, + "peerDependenciesMeta": { + "webpack-dev-server": { + "optional": true + } + } + }, + "node_modules/@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@xtuc/long": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/acorn": { + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", + "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/ajv": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-formats": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", + "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "node_modules/ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3" + }, + "peerDependencies": { + "ajv": "^8.8.2" + } + }, + "node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/aos": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/aos/-/aos-2.3.4.tgz", + "integrity": "sha512-zh/ahtR2yME4I51z8IttIt4lC1Nw0ktsFtmeDzID1m9naJnWXhCoARaCgNOGXb5CLy3zm+wqmRAEgMYB5E2HUw==", + "license": "MIT", + "dependencies": { + "classlist-polyfill": "^1.0.3", + "lodash.debounce": "^4.0.6", + "lodash.throttle": "^4.0.1" + } + }, + "node_modules/babel-loader": { + "version": "9.2.1", + "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-9.2.1.tgz", + "integrity": "sha512-fqe8naHt46e0yIdkjUZYqddSXfej3AHajX+CSO5X7oy0EmPc6o5Xh+RClNoHjnieWz9AW4kZxW9yyFMhVB1QLA==", + "dev": true, + "license": "MIT", + "dependencies": { + "find-cache-dir": "^4.0.0", + "schema-utils": "^4.0.0" + }, + "engines": { + "node": ">= 14.15.0" + }, + "peerDependencies": { + "@babel/core": "^7.12.0", + "webpack": ">=5" + } + }, + "node_modules/babel-plugin-polyfill-corejs2": { + "version": "0.4.12", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.12.tgz", + "integrity": "sha512-CPWT6BwvhrTO2d8QVorhTCQw9Y43zOu7G9HigcfxvepOU6b8o3tcWad6oVgZIsZCTt42FFv97aA7ZJsbM4+8og==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.22.6", + "@babel/helper-define-polyfill-provider": "^0.6.3", + "semver": "^6.3.1" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-polyfill-corejs3": { + "version": "0.10.6", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.10.6.tgz", + "integrity": "sha512-b37+KR2i/khY5sKmWNVQAnitvquQbNdWy6lJdsr0kmquCKEEUgMKK4SboVM3HtfnZilfjr4MMQ7vY58FVWDtIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.6.2", + "core-js-compat": "^3.38.0" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-polyfill-regenerator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.3.tgz", + "integrity": "sha512-LiWSbl4CRSIa5x/JAU6jZiG9eit9w6mz+yVMFwDE83LAWvt0AfGBoZ7HS/mkhrKuh2ZlzfVZYKoLjXdqw6Yt7Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.6.3" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/browserslist": { + "version": "4.24.4", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.4.tgz", + "integrity": "sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "caniuse-lite": "^1.0.30001688", + "electron-to-chromium": "^1.5.73", + "node-releases": "^2.0.19", + "update-browserslist-db": "^1.1.1" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001692", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001692.tgz", + "integrity": "sha512-A95VKan0kdtrsnMubMKxEKUKImOPSuCpYgxSQBo036P5YYgVIcOYJEgt/txJWqObiRQeISNCfef9nvlQ0vbV7A==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/chrome-trace-event": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz", + "integrity": "sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0" + } + }, + "node_modules/classlist-polyfill": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/classlist-polyfill/-/classlist-polyfill-1.2.0.tgz", + "integrity": "sha512-GzIjNdcEtH4ieA2S8NmrSxv7DfEV5fmixQeyTmqmRmRJPGpRBaSnA2a0VrCjyT8iW8JjEdMbKzDotAJf+ajgaQ==", + "license": "Unlicense" + }, + "node_modules/clone-deep": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", + "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-plain-object": "^2.0.4", + "kind-of": "^6.0.2", + "shallow-clone": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/colorette": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", + "dev": true, + "license": "MIT" + }, + "node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/common-path-prefix": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/common-path-prefix/-/common-path-prefix-3.0.0.tgz", + "integrity": "sha512-QE33hToZseCH3jS0qN96O/bSh3kaw/h+Tq7ngyY9eWDUnTlTNUyqfqvCXioLe5Na5jFsL78ra/wuBU4iuEgd4w==", + "dev": true, + "license": "ISC" + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true, + "license": "MIT" + }, + "node_modules/core-js-compat": { + "version": "3.40.0", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.40.0.tgz", + "integrity": "sha512-0XEDpr5y5mijvw8Lbc6E5AkjrHfp7eEoPlu36SWeAbcL8fn1G1ANe8DBlo2XoNN89oVpxWwOjYIPVzR4ZvsKCQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "browserslist": "^4.24.3" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/css-loader": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-7.1.2.tgz", + "integrity": "sha512-6WvYYn7l/XEGN8Xu2vWFt9nVzrCn39vKyTEFf/ExEyoksJjjSZV/0/35XPlMbpnr6VGhZIUg5yJrL8tGfes/FA==", + "dev": true, + "license": "MIT", + "dependencies": { + "icss-utils": "^5.1.0", + "postcss": "^8.4.33", + "postcss-modules-extract-imports": "^3.1.0", + "postcss-modules-local-by-default": "^4.0.5", + "postcss-modules-scope": "^3.2.0", + "postcss-modules-values": "^4.0.0", + "postcss-value-parser": "^4.2.0", + "semver": "^7.5.4" + }, + "engines": { + "node": ">= 18.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "@rspack/core": "0.x || 1.x", + "webpack": "^5.27.0" + }, + "peerDependenciesMeta": { + "@rspack/core": { + "optional": true + }, + "webpack": { + "optional": true + } + } + }, + "node_modules/css-loader/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true, + "license": "MIT", + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/debug": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true, + "license": "MIT" + }, + "node_modules/electron-to-chromium": { + "version": "1.5.82", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.82.tgz", + "integrity": "sha512-Zq16uk1hfQhyGx5GpwPAYDwddJuSGhtRhgOA2mCxANYaDT79nAeGnaXogMGng4KqLaJUVnOnuL0+TDop9nLOiA==", + "dev": true, + "license": "ISC" + }, + "node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true, + "license": "MIT" + }, + "node_modules/enhanced-resolve": { + "version": "5.18.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.0.tgz", + "integrity": "sha512-0/r0MySGYG8YqlayBZ6MuCfECmHFdJ5qyPh8s8wa5Hnm6SaFLSK1VYCbj+NKp090Nm1caZhD+QTnmxO7esYGyQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/envinfo": { + "version": "7.14.0", + "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.14.0.tgz", + "integrity": "sha512-CO40UI41xDQzhLB1hWyqUKgFhs250pNcGbyGKe1l/e4FSaI/+YE4IMG76GDt0In67WLPACIITC+sOi08x4wIvg==", + "dev": true, + "license": "MIT", + "bin": { + "envinfo": "dist/cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/es-module-lexer": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.6.0.tgz", + "integrity": "sha512-qqnD1yMU6tk/jnaMosogGySTZP8YtUgAffA9nMN+E/rjxcfRQ6IEk7IiozUjgxKoFHBGjTLnrHB/YC45r/59EQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-uri": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.5.tgz", + "integrity": "sha512-5JnBCWpFlMo0a3ciDy/JckMzzv1U9coZrIhedq+HXxxUfDTAiS0LA8OKVao4G9BxmCVck/jtA5r3KAtRWEyD8Q==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/fastest-levenshtein": { + "version": "1.0.16", + "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", + "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4.9.1" + } + }, + "node_modules/find-cache-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-4.0.0.tgz", + "integrity": "sha512-9ZonPT4ZAK4a+1pUPVPZJapbi7O5qbbJPdYw/NOQWZZbVLdDTYM3A4R9z/DpAM08IDaFGsvPgiGZ82WEwUDWjg==", + "dev": true, + "license": "MIT", + "dependencies": { + "common-path-prefix": "^3.0.0", + "pkg-dir": "^7.0.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/find-up": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-6.3.0.tgz", + "integrity": "sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^7.1.0", + "path-exists": "^5.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "dev": true, + "license": "BSD-3-Clause", + "bin": { + "flat": "cli.js" + } + }, + "node_modules/foreground-child": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz", + "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==", + "dev": true, + "license": "ISC", + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/glob": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/glob/-/glob-11.0.1.tgz", + "integrity": "sha512-zrQDm8XPnYEKawJScsnM0QzobJxlT/kHOOlRTio8IH/GrmxRE5fjllkzdaHclIuNjUQTJYH2xHNIGfdpJkDJUw==", + "dev": true, + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^4.0.1", + "minimatch": "^10.0.0", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^2.0.0" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-to-regexp": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", + "dev": true, + "license": "BSD-2-Clause" + }, + "node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/icss-utils": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", + "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", + "dev": true, + "license": "ISC", + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/import-local": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz", + "integrity": "sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==", + "dev": true, + "license": "MIT", + "dependencies": { + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + }, + "bin": { + "import-local-fixture": "fixtures/cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/import-local/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/import-local/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/import-local/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/import-local/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/import-local/node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/import-local/node_modules/pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "find-up": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/interpret": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-3.1.1.tgz", + "integrity": "sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/is-core-module": { + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", + "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", + "dev": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "license": "MIT", + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" + }, + "node_modules/isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/jackspeak": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.0.2.tgz", + "integrity": "sha512-bZsjR/iRjl1Nk1UkjGpAzLNfQtzuijhn2g+pbZb98HQ1Gk8vM9hfbxeMBP+M2/UUdwj0RqGG3mlvk2MsAqwvEw==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/jest-worker": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", + "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "dev": true, + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true, + "license": "MIT" + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/loader-runner": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", + "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.11.5" + } + }, + "node_modules/locate-path": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-7.2.0.tgz", + "integrity": "sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^6.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", + "license": "MIT" + }, + "node_modules/lodash.throttle": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz", + "integrity": "sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ==", + "license": "MIT" + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true, + "license": "MIT" + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dev": true, + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mini-css-extract-plugin": { + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.9.2.tgz", + "integrity": "sha512-GJuACcS//jtq4kCtd5ii/M0SZf7OZRH+BxdqXZHaJfb8TJiVl+NgQRPwiYt2EuqeSkNydn/7vP+bcE27C5mb9w==", + "dev": true, + "license": "MIT", + "dependencies": { + "schema-utils": "^4.0.0", + "tapable": "^2.2.1" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + } + }, + "node_modules/minimatch": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.1.tgz", + "integrity": "sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/nanoid": { + "version": "3.3.8", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz", + "integrity": "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true, + "license": "MIT" + }, + "node_modules/node-releases": { + "version": "2.0.19", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", + "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==", + "dev": true, + "license": "MIT" + }, + "node_modules/p-limit": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz", + "integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^1.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-6.0.0.tgz", + "integrity": "sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "dev": true, + "license": "BlueOak-1.0.0" + }, + "node_modules/path-exists": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-5.0.0.tgz", + "integrity": "sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true, + "license": "MIT" + }, + "node_modules/path-scurry": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.0.tgz", + "integrity": "sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^11.0.0", + "minipass": "^7.1.2" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "11.0.2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.0.2.tgz", + "integrity": "sha512-123qHRfJBmo2jXDbo/a5YOQrJoHF/GNQTLzQ5+IdK5pWpceK17yRc6ozlWd25FxvGKQbIUs91fDFkXmDHTKcyA==", + "dev": true, + "license": "ISC", + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, + "node_modules/pkg-dir": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-7.0.0.tgz", + "integrity": "sha512-Ie9z/WINcxxLp27BKOCHGde4ITq9UklYKDzVo1nhk5sqGEXU3FpkwP5GM2voTGJkGd9B3Otl+Q4uwSOeSUtOBA==", + "dev": true, + "license": "MIT", + "dependencies": { + "find-up": "^6.3.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/postcss": { + "version": "8.5.1", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.1.tgz", + "integrity": "sha512-6oz2beyjc5VMn/KV1pPw8fliQkhBXrVn1Z3TVyqZxU8kZpzEKhBdmCFqI6ZbmGtamQvQGuU1sgPTk8ZrXDD7jQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.8", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-modules-extract-imports": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.1.0.tgz", + "integrity": "sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q==", + "dev": true, + "license": "ISC", + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-local-by-default": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.2.0.tgz", + "integrity": "sha512-5kcJm/zk+GJDSfw+V/42fJ5fhjL5YbFDl8nVdXkJPLLW+Vf9mTD5Xe0wqIaDnLuL2U6cDNpTr+UQ+v2HWIBhzw==", + "dev": true, + "license": "MIT", + "dependencies": { + "icss-utils": "^5.0.0", + "postcss-selector-parser": "^7.0.0", + "postcss-value-parser": "^4.1.0" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-scope": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.2.1.tgz", + "integrity": "sha512-m9jZstCVaqGjTAuny8MdgE88scJnCiQSlSrOWcTQgM2t32UBe+MUmFSO5t7VMSfAf/FJKImAxBav8ooCHJXCJA==", + "dev": true, + "license": "ISC", + "dependencies": { + "postcss-selector-parser": "^7.0.0" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-values": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", + "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "icss-utils": "^5.0.0" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-selector-parser": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.0.0.tgz", + "integrity": "sha512-9RbEr1Y7FFfptd/1eEdntyjMwLeghW1bHX9GWjXo19vx4ytPQhANltvVxDggzJl7mnWM+dX28kb6cyS/4iQjlQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/rechoir": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.8.0.tgz", + "integrity": "sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "resolve": "^1.20.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/regenerate": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", + "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", + "dev": true, + "license": "MIT" + }, + "node_modules/regenerate-unicode-properties": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.2.0.tgz", + "integrity": "sha512-DqHn3DwbmmPVzeKj9woBadqmXxLvQoQIwu7nopMc72ztvxVmVk2SBhSnx67zuye5TP+lJsb/TBQsjLKhnDf3MA==", + "dev": true, + "license": "MIT", + "dependencies": { + "regenerate": "^1.4.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/regenerator-runtime": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", + "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==", + "dev": true, + "license": "MIT" + }, + "node_modules/regenerator-transform": { + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.2.tgz", + "integrity": "sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.8.4" + } + }, + "node_modules/regexpu-core": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-6.2.0.tgz", + "integrity": "sha512-H66BPQMrv+V16t8xtmq+UC0CBpiTBA60V8ibS1QVReIp8T1z8hwFxqcGzm9K6lgsN7sB5edVH8a+ze6Fqm4weA==", + "dev": true, + "license": "MIT", + "dependencies": { + "regenerate": "^1.4.2", + "regenerate-unicode-properties": "^10.2.0", + "regjsgen": "^0.8.0", + "regjsparser": "^0.12.0", + "unicode-match-property-ecmascript": "^2.0.0", + "unicode-match-property-value-ecmascript": "^2.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/regjsgen": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.8.0.tgz", + "integrity": "sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/regjsparser": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.12.0.tgz", + "integrity": "sha512-cnE+y8bz4NhMjISKbgeVJtqNbtf5QpjZP+Bslo+UqkIt9QPnX9q095eiRRASJG1/tz6dlNr6Z5NsBiWYokp6EQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "jsesc": "~3.0.2" + }, + "bin": { + "regjsparser": "bin/parser" + } + }, + "node_modules/regjsparser/node_modules/jsesc": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.0.2.tgz", + "integrity": "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==", + "dev": true, + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve": { + "version": "1.22.10", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", + "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-core-module": "^2.16.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/schema-utils": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.0.tgz", + "integrity": "sha512-Gf9qqc58SpCA/xdziiHz35F4GNIWYWZrEshUc/G/r5BnLph6xpKuLeoJoQuj5WfBIx/eQLf+hmVPYHaxJu7V2g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/json-schema": "^7.0.9", + "ajv": "^8.9.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.1.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/serialize-javascript": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", + "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/shallow-clone": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", + "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", + "dev": true, + "license": "MIT", + "dependencies": { + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/string-width-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/style-loader": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-4.0.0.tgz", + "integrity": "sha512-1V4WqhhZZgjVAVJyt7TdDPZoPBPNHbekX4fWnCJL1yQukhCeZhJySUL+gL9y6sNdN95uEOS83Y55SqHcP7MzLA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 18.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.27.0" + } + }, + "node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/terser": { + "version": "5.37.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.37.0.tgz", + "integrity": "sha512-B8wRRkmre4ERucLM/uXx4MOV5cbnOlVAqUst+1+iLKPI0dOgFO28f84ptoQt9HEI537PMzfYa/d+GEPKTRXmYA==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.8.2", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/terser-webpack-plugin": { + "version": "5.3.11", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.11.tgz", + "integrity": "sha512-RVCsMfuD0+cTt3EwX8hSl2Ks56EbFHWmhluwcqoPKtBnfjiT6olaq7PRIRfhyU8nnC2MrnDrBLfrD/RGE+cVXQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.25", + "jest-worker": "^27.4.5", + "schema-utils": "^4.3.0", + "serialize-javascript": "^6.0.2", + "terser": "^5.31.1" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.1.0" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "uglify-js": { + "optional": true + } + } + }, + "node_modules/undici-types": { + "version": "6.20.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", + "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", + "dev": true, + "license": "MIT" + }, + "node_modules/unicode-canonical-property-names-ecmascript": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.1.tgz", + "integrity": "sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", + "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "unicode-canonical-property-names-ecmascript": "^2.0.0", + "unicode-property-aliases-ecmascript": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-value-ecmascript": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.2.0.tgz", + "integrity": "sha512-4IehN3V/+kkr5YeSSDDQG8QLqO26XpL2XP3GQtqwlT/QYSECAwFztxVHjlbh0+gjJ3XmNLS0zDsbgs9jWKExLg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-property-aliases-ecmascript": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz", + "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.2.tgz", + "integrity": "sha512-PPypAm5qvlD7XMZC3BujecnaOxwhrtoFR+Dqkk5Aa/6DssiH0ibKoketaj9w8LP7Bont1rYeoV5plxD7RTEPRg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true, + "license": "MIT" + }, + "node_modules/watchpack": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.2.tgz", + "integrity": "sha512-TnbFSbcOCcDgjZ4piURLCbJ3nJhznVh9kw6F6iokjiFPl8ONxe9A6nMDVXDiNbrSfLILs6vB07F7wLBrwPYzJw==", + "dev": true, + "license": "MIT", + "dependencies": { + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.1.2" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/webpack": { + "version": "5.97.1", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.97.1.tgz", + "integrity": "sha512-EksG6gFY3L1eFMROS/7Wzgrii5mBAFe4rIr3r2BTfo7bcc+DWwFZ4OJ/miOuHJO/A85HwyI4eQ0F6IKXesO7Fg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/eslint-scope": "^3.7.7", + "@types/estree": "^1.0.6", + "@webassemblyjs/ast": "^1.14.1", + "@webassemblyjs/wasm-edit": "^1.14.1", + "@webassemblyjs/wasm-parser": "^1.14.1", + "acorn": "^8.14.0", + "browserslist": "^4.24.0", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^5.17.1", + "es-module-lexer": "^1.2.1", + "eslint-scope": "5.1.1", + "events": "^3.2.0", + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.2.11", + "json-parse-even-better-errors": "^2.3.1", + "loader-runner": "^4.2.0", + "mime-types": "^2.1.27", + "neo-async": "^2.6.2", + "schema-utils": "^3.2.0", + "tapable": "^2.1.1", + "terser-webpack-plugin": "^5.3.10", + "watchpack": "^2.4.1", + "webpack-sources": "^3.2.3" + }, + "bin": { + "webpack": "bin/webpack.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependenciesMeta": { + "webpack-cli": { + "optional": true + } + } + }, + "node_modules/webpack-cli": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-5.1.4.tgz", + "integrity": "sha512-pIDJHIEI9LR0yxHXQ+Qh95k2EvXpWzZ5l+d+jIo+RdSm9MiHfzazIxwwni/p7+x4eJZuvG1AJwgC4TNQ7NRgsg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@discoveryjs/json-ext": "^0.5.0", + "@webpack-cli/configtest": "^2.1.1", + "@webpack-cli/info": "^2.0.2", + "@webpack-cli/serve": "^2.0.5", + "colorette": "^2.0.14", + "commander": "^10.0.1", + "cross-spawn": "^7.0.3", + "envinfo": "^7.7.3", + "fastest-levenshtein": "^1.0.12", + "import-local": "^3.0.2", + "interpret": "^3.1.1", + "rechoir": "^0.8.0", + "webpack-merge": "^5.7.3" + }, + "bin": { + "webpack-cli": "bin/cli.js" + }, + "engines": { + "node": ">=14.15.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "5.x.x" + }, + "peerDependenciesMeta": { + "@webpack-cli/generators": { + "optional": true + }, + "webpack-bundle-analyzer": { + "optional": true + }, + "webpack-dev-server": { + "optional": true + } + } + }, + "node_modules/webpack-cli/node_modules/commander": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", + "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + } + }, + "node_modules/webpack-merge": { + "version": "5.10.0", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.10.0.tgz", + "integrity": "sha512-+4zXKdx7UnO+1jaN4l2lHVD+mFvnlZQP/6ljaJVb4SZiwIKeUnrT5l0gkT8z+n4hKpC+jpOv6O9R+gLtag7pSA==", + "dev": true, + "license": "MIT", + "dependencies": { + "clone-deep": "^4.0.1", + "flat": "^5.0.2", + "wildcard": "^2.0.0" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/webpack-sources": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", + "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/webpack/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/webpack/node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/webpack/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, + "node_modules/webpack/node_modules/schema-utils": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/wildcard": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.1.tgz", + "integrity": "sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/wrap-ansi-cjs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true, + "license": "ISC" + }, + "node_modules/yocto-queue": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.1.1.tgz", + "integrity": "sha512-b4JR1PFR10y1mKjhHY9LaGo6tmrgjit7hxVIeAmyMw3jegXR4dhYqLaQF5zMXZxY7tLpMyJeLjr1C4rLmkVe8g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..3497ad3 --- /dev/null +++ b/package.json @@ -0,0 +1,40 @@ +{ + "name": "app", + "version": "1.0.0", + "description": "Precision and Research Technology Systems Limited\r Website with online store", + "main": "webpack.config.js", + "directories": { + "lib": "lib" + }, + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1", + "build": "webpack --mode production", + "watch": "webpack --mode development --watch" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/Teddy-1024/parts_website.git" + }, + "keywords": [], + "author": "", + "license": "ISC", + "bugs": { + "url": "https://github.com/Teddy-1024/parts_website/issues" + }, + "homepage": "https://github.com/Teddy-1024/parts_website#readme", + "devDependencies": { + "@babel/core": "^7.25.2", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/preset-env": "^7.25.4", + "babel-loader": "^9.1.3", + "css-loader": "^7.1.2", + "glob": "^11.0.0", + "mini-css-extract-plugin": "^2.9.1", + "style-loader": "^4.0.0", + "webpack": "^5.94.0", + "webpack-cli": "^5.1.4" + }, + "dependencies": { + "aos": "^2.3.4" + } +} diff --git a/packages-microsoft-prod.deb b/packages-microsoft-prod.deb new file mode 100644 index 0000000..14e3c62 Binary files /dev/null and b/packages-microsoft-prod.deb differ diff --git a/passenger_wsgi.py b/passenger_wsgi.py new file mode 100644 index 0000000..5e871cd --- /dev/null +++ b/passenger_wsgi.py @@ -0,0 +1,15 @@ +import os +import sys + + +sys.path.insert(0, os.path.dirname(__file__)) + + +def application(environ, start_response): + start_response('200 OK', [('Content-Type', 'text/plain')]) + message = 'It works!\n' + version = 'Python %s\n' % sys.version.split()[0] + response = '\n'.join([message, version]) + return [response.encode()] + +from app import app as application # Import the Flask application from app.py \ No newline at end of file diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..bdac419 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,18 @@ + +Flask==3.0.3 +gunicorn==23.0.0 +flask_wtf +flask_sqlalchemy +flask_cors +flask_mail +authlib +jwt +mysqlclient +stripe +python_dotenv +authlib +pydantic +# psycopg2 +requests +cryptography +altcha \ No newline at end of file diff --git a/robots.txt b/robots.txt new file mode 100644 index 0000000..2730005 --- /dev/null +++ b/robots.txt @@ -0,0 +1,3 @@ +User-agent: * +Disallow: /qa +Disallow: /dev \ No newline at end of file diff --git a/routes.py b/routes.py new file mode 100644 index 0000000..d93a97a --- /dev/null +++ b/routes.py @@ -0,0 +1,54 @@ +""" +Project: PARTS Website +Author: Edward Middleton-Smith + Precision And Research Technology Systems Limited + +Technology: Backend +Feature: Controller - Webpage routing + +Description: +Defines the routes and view functions for each page. +Manages the interaction between the frontend and backend. +""" + +from flask import render_template, url_for, Blueprint +from app import app +from app.forms import Form_Contact +# from forms import MyForm +# from app import MyForm +from model_view_contact import Model_View_Contact + +""" +@app.route('/', methods=['GET']) +def home(): + return render_template('_home.html', title='Home') + +@app.route('/store', methods=['GET']) +def store_home(): + return render_template('_store_home.html', title='Store Home') + +@app.route('/contact', methods=['GET', 'POST']) +def contact(): + form = Form_Contact() + if form.validate_on_submit(): + # Handle form submission + email = form.sender_email.data + CC = form.sender_CC.data + name = form.sender_name.data + msg = form.sender_message.data + # return render_template('contact.html', form=form) + # return render_template('_contact.html', title='Contact Us') + return render_template('contact.html', model=Model_View_Contact(form)) + +@app.route('/about') +def about(): + return render_template('about.html') + +@app.route('/contact', methods=['GET', 'POST']) +def contact(): + form = MyForm() + if form.validate_on_submit(): + # Handle form submission + pass + return render_template('contact.html', form=form) +""" \ No newline at end of file diff --git a/run.py b/run.py new file mode 100644 index 0000000..bac5ef0 --- /dev/null +++ b/run.py @@ -0,0 +1,17 @@ +""" +Project: PARTS Website +Author: Edward Middleton-Smith + Precision And Research Technology Systems Limited + +Technology: Backend +Feature: Launcher + +Description: +Runs project. +""" + +from app import app + +if __name__ == '__main__': + app.run(debug=True) + # app.run(debug=True, host="0.0.0.0", port=5000) \ No newline at end of file diff --git a/static/MySQL/0000_combined.sql b/static/MySQL/0000_combined.sql new file mode 100644 index 0000000..6a335d4 --- /dev/null +++ b/static/MySQL/0000_combined.sql @@ -0,0 +1,5769 @@ + +CREATE DATABASE IF NOT EXISTS parts; + +GRANT ALL PRIVILEGES ON parts.* TO 'teddy'@'%'; +FLUSH PRIVILEGES; + +USE parts; + +-- Permanent Temp Tables +DROP TABLE IF EXISTS parts.tmp_DOG_Calc_User; +-- DROP TABLE IF EXISTS parts.tmp_core_Msg_Error; +DROP TABLE IF EXISTS parts.tmp_DOG_User; +DROP TABLE IF EXISTS parts.tmp_DOG_User_Role_Link; + + +-- Permanent Tables +DROP TABLE IF EXISTS parts.DOG_Dog_Drive_Link_Temp; +DROP TABLE IF EXISTS parts.DOG_Dog_Drive_Link_Audit; +DROP TABLE IF EXISTS parts.DOG_Dog_Drive_Link; + +DROP TABLE IF EXISTS parts.DOG_Drive_Temp; +DROP TABLE IF EXISTS parts.DOG_Drive_Audit; +DROP TABLE IF EXISTS parts.DOG_Drive; + +DROP TABLE IF EXISTS parts.DOG_Command_Button_Link_Temp; +DROP TABLE IF EXISTS parts.DOG_Command_Button_Link_Audit; +DROP TABLE IF EXISTS parts.DOG_Command_Button_Link; + +DROP TABLE IF EXISTS parts.DOG_Button_Icon_Temp; +DROP TABLE IF EXISTS parts.DOG_Button_Icon_Audit; +DROP TABLE IF EXISTS parts.DOG_Button_Icon; + +DROP TABLE IF EXISTS parts.DOG_Image_Temp; +DROP TABLE IF EXISTS parts.DOG_Image_Audit; +DROP TABLE IF EXISTS parts.DOG_Image; + +DROP TABLE IF EXISTS parts.DOG_Button_Shape_Temp; +DROP TABLE IF EXISTS parts.DOG_Button_Shape_Audit; +DROP TABLE IF EXISTS parts.DOG_Button_Shape; + +DROP TABLE IF EXISTS parts.DOG_Colour_Temp; +DROP TABLE IF EXISTS parts.DOG_Colour_Audit; +DROP TABLE IF EXISTS parts.DOG_Colour; + +DROP TABLE IF EXISTS parts.DOG_Location_Link_Temp; +DROP TABLE IF EXISTS parts.DOG_Location_Link_Audit; +DROP TABLE IF EXISTS parts.DOG_Location_Link; + +DROP TABLE IF EXISTS parts.DOG_Location_Temp; +DROP TABLE IF EXISTS parts.DOG_Location_Audit; +DROP TABLE IF EXISTS parts.DOG_Location; + +DROP TABLE IF EXISTS parts.DOG_Personal_Best_Temp; +DROP TABLE IF EXISTS parts.DOG_Personal_Best_Audit; +DROP TABLE IF EXISTS parts.DOG_Personal_Best; + +DROP TABLE IF EXISTS parts.DOG_Dog_Command_Link_Temp; +DROP TABLE IF EXISTS parts.DOG_Dog_Command_Link_Audit; +DROP TABLE IF EXISTS parts.DOG_Dog_Command_Link; + +DROP TABLE IF EXISTS parts.DOG_Command_Temp; +DROP TABLE IF EXISTS parts.DOG_Command_Audit; +DROP TABLE IF EXISTS parts.DOG_Command; + +DROP TABLE IF EXISTS parts.DOG_Command_Category_Temp; +DROP TABLE IF EXISTS parts.DOG_Command_Category_Audit; +DROP TABLE IF EXISTS parts.DOG_Command_Category; + +DROP TABLE IF EXISTS parts.DOG_Obedience_Level_Temp; +DROP TABLE IF EXISTS parts.DOG_Obedience_Level_Audit; +DROP TABLE IF EXISTS parts.DOG_Obedience_Level; + +DROP TABLE IF EXISTS parts.DOG_Understanding_Level_Temp; +DROP TABLE IF EXISTS parts.DOG_Understanding_Level_Audit; +DROP TABLE IF EXISTS parts.DOG_Understanding_Level; + +DROP TABLE IF EXISTS parts.DOG_Competency_Level_Temp; +DROP TABLE IF EXISTS parts.DOG_Competency_Level_Audit; +DROP TABLE IF EXISTS parts.DOG_Competency_Level; + +DROP TABLE IF EXISTS parts.DOG_Dog_Breed_Link_Temp; +DROP TABLE IF EXISTS parts.DOG_Dog_Breed_Link_Audit; +DROP TABLE IF EXISTS parts.DOG_Dog_Breed_Link; + +DROP TABLE IF EXISTS parts.DOG_Breed_Temp; +DROP TABLE IF EXISTS parts.DOG_Breed_Audit; +DROP TABLE IF EXISTS parts.DOG_Breed; + +DROP TABLE IF EXISTS parts.DOG_Dog_Temp; +DROP TABLE IF EXISTS parts.DOG_Dog_Audit; +DROP TABLE IF EXISTS parts.DOG_Dog; + +DROP TABLE IF EXISTS parts.DOG_Dog_Change_Set; + +DROP TABLE IF EXISTS parts.DOG_Calc_User_Temp; + +DROP TABLE IF EXISTS parts.DOG_User_Role_Link_Audit; +DROP TABLE IF EXISTS parts.DOG_User_Role_Link; + +DROP TABLE IF EXISTS parts.DOG_Role_Permission_Link_Audit; +DROP TABLE IF EXISTS parts.DOG_Role_Permission_Link; + +DROP TABLE IF EXISTS parts.DOG_Role_Audit; +DROP TABLE IF EXISTS parts.DOG_Role; + +DROP TABLE IF EXISTS parts.DOG_User_Temp; +DROP TABLE IF EXISTS parts.DOG_User_Audit; +DROP TABLE IF EXISTS parts.DOG_User; + +DROP TABLE IF EXISTS parts.DOG_Permission_Audit; +DROP TABLE IF EXISTS parts.DOG_Permission; + +DROP TABLE IF EXISTS parts.DOG_Permission_Group_Audit; +DROP TABLE IF EXISTS parts.DOG_Permission_Group; + +DROP TABLE IF EXISTS parts.DOG_Access_Level_Audit; +DROP TABLE IF EXISTS parts.DOG_Access_Level; + +DROP TABLE IF EXISTS parts.DOG_User_Change_Set; + +/* +DROP TABLE IF EXISTS parts.CORE_Split_Key_Value_Pair_Csv_Temp; +DROP TABLE IF EXISTS parts.CORE_Split_Temp; + +*/ +DROP TABLE IF EXISTS parts.CORE_File_Type; +DROP TABLE IF EXISTS parts.CORE_Msg_Error_Type; + +-- Stored Procedures +DROP PROCEDURE IF EXISTS parts.p_DOG_test_get_many_dog_command; +DROP PROCEDURE IF EXISTS parts.p_DOG_test_get_many_command; +DROP PROCEDURE IF EXISTS parts.p_DOG_get_many_command; +DROP PROCEDURE IF EXISTS parts.p_DOG_test_save_command; +DROP PROCEDURE IF EXISTS parts.p_DOG_save_command; + +DROP PROCEDURE IF EXISTS parts.p_DOG_clear_calc_user; +DROP PROCEDURE IF EXISTS parts.p_DOG_calc_user; + +/* +DROP PROCEDURE IF EXISTS parts.p_core_clear_split_key_value_pair_csv; +DROP PROCEDURE IF EXISTS parts.p_core_split_key_value_pair_csv; +DROP PROCEDURE IF EXISTS parts.p_core_clear_split; +DROP PROCEDURE IF EXISTS parts.p_core_split; +DROP PROCEDURE IF EXISTS parts.p_clear_split_key_value_pair_csv; +DROP PROCEDURE IF EXISTS parts.p_split_key_value_pair_csv; +DROP PROCEDURE IF EXISTS parts.p_clear_split; +DROP PROCEDURE IF EXISTS parts.p_split; + +DROP PROCEDURE IF EXISTS parts.p_core_debug_timing_reporting; +DROP PROCEDURE IF EXISTS parts.p_debug_timing_reporting; +DROP PROCEDURE IF EXISTS parts.p_core_validate_guid; +DROP PROCEDURE IF EXISTS parts.p_core_validate_guid_test; +*/ +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'CORE_Msg_Error_Type' +; + +CREATE TABLE IF NOT EXISTS parts.CORE_Msg_Error_Type ( + id_type INT NOT NULL AUTO_INCREMENT PRIMARY KEY + , code VARCHAR(100) NOT NULL + , name VARCHAR(500) NOT NULL + , description VARCHAR(1000) + , is_breaking_error BIT NOT NULL + , background_colour VARCHAR(32) NOT NULL DEFAULT '#111111' + , text_colour VARCHAR(32) NOT NULL DEFAULT '#110000' +); + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'CORE_File_Type' +; + +CREATE TABLE IF NOT EXISTS parts.CORE_File_Type ( + id_file_type INT NOT NULL AUTO_INCREMENT PRIMARY KEY + , code VARCHAR(100) NOT NULL + , name VARCHAR(250) NOT NULL + , is_image BIT NOT NULL DEFAULT 0 + , active BIT NOT NULL DEFAULT 1 +); + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'CORE_Split_Temp' +; + +CREATE TABLE IF NOT EXISTS parts.CORE_Split_Temp ( + guid BINARY(36) NOT NULL + , display_order INT NOT NULL + , substring VARCHAR(4000) NOT NULL +); + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'CORE_Split_Key_Value_Pair_Csv_Temp' +; + +CREATE TABLE IF NOT EXISTS parts.CORE_Split_Key_Value_Pair_Csv_Temp ( + guid BINARY(36) NOT NULL + , id INT NOT NULL + , key_column VARCHAR(4000) NULL + , value_column VARCHAR(4000) NULL +); + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_User_Change_Set' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_User_Change_Set ( + id_change_set INT NOT NULL AUTO_INCREMENT PRIMARY KEY + , comment VARCHAR(500) + , updated_last_on DATETIME + , id_user_updated_last_by INT +); +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Access_Level' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Access_Level ( + id_access_level INT NOT NULL AUTO_INCREMENT PRIMARY KEY + , code VARCHAR(100) + , name VARCHAR(250) + , priority INT NOT NULL + , display_order INT NOT NULL + , active BIT NOT NULL DEFAULT 1 +); + + + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Permission_Group' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Permission_Group ( + id_group INT NOT NULL AUTO_INCREMENT PRIMARY KEY + , code VARCHAR(100) + , name VARCHAR(250) + , display_order INT NOT NULL + , active BIT NOT NULL DEFAULT 1 +); +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Permission' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Permission ( + id_permission INT NOT NULL AUTO_INCREMENT PRIMARY KEY + , code VARCHAR(100) + , name VARCHAR(250) + , id_permission_group INT NOT NULL + , CONSTRAINT FK_DOG_Permission_id_permission_group + FOREIGN KEY (id_permission_group) + REFERENCES parts.DOG_Permission_Group(id_group) + , id_access_level_required INT NOT NULL + , CONSTRAINT FK_DOG_Permission_id_access_level_required + FOREIGN KEY (id_access_level_required) + REFERENCES parts.DOG_Access_Level(id_access_level) + , display_order INT NOT NULL + , active BIT NOT NULL DEFAULT 1 +); +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_User' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_User ( + id_user INT NOT NULL AUTO_INCREMENT PRIMARY KEY + , id_user_auth0 VARCHAR(200) + , firstname VARCHAR(250) + , surname VARCHAR(250) + , email VARCHAR(254) + , is_email_verified BIT NOT NULL DEFAULT 0 + , is_super_user BIT NOT NULL DEFAULT 0 + , active BIT NOT NULL DEFAULT 1 + , created_on DATETIME + , id_user_created_by INT + , CONSTRAINT FK_DOG_User_id_user_created_by + FOREIGN KEY (id_user_created_by) + REFERENCES parts.DOG_User(id_user) + , id_change_set INT + , CONSTRAINT FK_DOG_User_id_change_set + FOREIGN KEY (id_change_set) + REFERENCES parts.DOG_User_Change_Set(id_change_set) +); + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_User_Audit' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_User_Audit ( + id_audit INT NOT NULL AUTO_INCREMENT PRIMARY KEY + , id_user INT NOT NULL + , CONSTRAINT FK_DOG_User_Audit_id_user + FOREIGN KEY (id_user) + REFERENCES parts.DOG_User(id_user) + , name_field VARCHAR(100) NOT NULL + , value_prev VARCHAR(500) + , value_new VARCHAR(500) + , id_change_set INT NOT NULL + , CONSTRAINT FK_DOG_User_Audit_id_change_set + FOREIGN KEY (id_change_set) + REFERENCES parts.DOG_User_Change_Set(id_change_set) +); +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_User_Temp' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_User_Temp ( + id_temp INT NOT NULL AUTO_INCREMENT PRIMARY KEY + , id_user INT NOT NULL + , id_user_auth0 VARCHAR(200) + , firstname VARCHAR(250) + , surname VARCHAR(250) + , email VARCHAR(254) + , is_email_verified BIT + , is_super_user BIT + , active BIT + , guid BINARY(36) NOT NULL +); + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Role' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Role ( + id_role INT NOT NULL AUTO_INCREMENT PRIMARY KEY + , code VARCHAR(100) + , name VARCHAR(250) + , display_order INT NOT NULL + , active BIT NOT NULL DEFAULT 1 + , created_on DATETIME + , id_user_created_by INT + , CONSTRAINT FK_DOG_Role_id_user_created_by + FOREIGN KEY (id_user_created_by) + REFERENCES parts.DOG_User(id_user) + , id_change_set INT + , CONSTRAINT FK_DOG_Role_id_change_set + FOREIGN KEY (id_change_set) + REFERENCES parts.DOG_User_Change_Set(id_change_set) +); +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Role_Audit' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Role_Audit ( + id_audit INT NOT NULL AUTO_INCREMENT PRIMARY KEY + , id_role INT NOT NULL + , CONSTRAINT FK_DOG_Role_Audit_id_role + FOREIGN KEY (id_role) + REFERENCES parts.DOG_Role(id_role) + , name_field VARCHAR(100) NOT NULL + , value_prev VARCHAR(500) + , value_new VARCHAR(500) + , id_change_set INT NOT NULL + , CONSTRAINT FK_DOG_Role_Audit_id_change_set + FOREIGN KEY (id_change_set) + REFERENCES parts.DOG_User_Change_Set(id_change_set) +); +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Role_Permission_Link' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Role_Permission_Link ( + id_link INT NOT NULL AUTO_INCREMENT PRIMARY KEY + , id_role INT NOT NULL + , CONSTRAINT FK_DOG_Role_Permission_Link_id_role + FOREIGN KEY (id_role) + REFERENCES parts.DOG_Role(id_role) + , id_permission INT NOT NULL + , CONSTRAINT FK_DOG_Role_Permission_Link_id_permission + FOREIGN KEY (id_permission) + REFERENCES parts.DOG_Permission(id_permission) + , id_access_level INT NOT NULL + , CONSTRAINT FK_DOG_Role_Permission_Link_id_access_level + FOREIGN KEY (id_access_level) + REFERENCES parts.DOG_Access_Level(id_access_level) + , active BIT NOT NULL DEFAULT 1 + , created_on DATETIME + , id_user_created_by INT + , CONSTRAINT FK_DOG_Role_Permission_Link_id_user_created_by + FOREIGN KEY (id_user_created_by) + REFERENCES parts.DOG_User(id_user) + , id_change_set INT + , CONSTRAINT FK_DOG_Role_Permission_Link_id_change_set + FOREIGN KEY (id_change_set) + REFERENCES parts.DOG_User_Change_Set(id_change_set) +); +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Role_Permission_Link_Audit'; + +CREATE TABLE IF NOT EXISTS parts.DOG_Role_Permission_Link_Audit ( + id_audit INT NOT NULL AUTO_INCREMENT PRIMARY KEY + , id_link INT NOT NULL + , CONSTRAINT FK_DOG_Role_Permission_Link_Audit_id_link + FOREIGN KEY (id_link) + REFERENCES parts.DOG_Role_Permission_Link(id_link) + , name_field VARCHAR(100) NOT NULL + , value_prev VARCHAR(500) + , value_new VARCHAR(500) + , id_change_set INT NOT NULL + , CONSTRAINT FK_DOG_Role_Permission_Link_Audit_id_change_set + FOREIGN KEY (id_change_set) + REFERENCES parts.DOG_User_Change_Set(id_change_set) +); +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_User_Role_Link' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_User_Role_Link ( + id_link INT NOT NULL AUTO_INCREMENT PRIMARY KEY + , id_user INT NOT NULL + , CONSTRAINT FK_DOG_User_Role_Link_id_user + FOREIGN KEY (id_user) + REFERENCES parts.DOG_User(id_user) + , id_role INT NOT NULL + , CONSTRAINT FK_DOG_User_Role_Link_id_role + FOREIGN KEY (id_role) + REFERENCES parts.DOG_Role(id_role) + , active BIT NOT NULL DEFAULT 1 + , created_on DATETIME + , id_user_created_by INT + , CONSTRAINT FK_DOG_User_Role_Link_id_user_created_by + FOREIGN KEY (id_user_created_by) + REFERENCES parts.DOG_User(id_user) + , id_change_set INT + , CONSTRAINT FK_DOG_User_Role_Link_id_change_set + FOREIGN KEY (id_change_set) + REFERENCES parts.DOG_User_Change_Set(id_change_set) +); +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_User_Role_Link_Audit' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_User_Role_Link_Audit ( + id_audit INT NOT NULL AUTO_INCREMENT PRIMARY KEY + , id_link INT NOT NULL + , CONSTRAINT FK_DOG_User_Role_Link_Audit_id_link + FOREIGN KEY (id_link) + REFERENCES parts.DOG_User_Role_Link(id_link) + , name_field VARCHAR(100) NOT NULL + , value_prev VARCHAR(500) + , value_new VARCHAR(500) + , id_change_set INT NOT NULL + , CONSTRAINT FK_DOG_User_Role_Link_Audit_id_change_set + FOREIGN KEY (id_change_set) + REFERENCES parts.DOG_User_Change_Set(id_change_set) +); + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Calc_User_Temp' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Calc_User_Temp ( + guid BINARY(36) NOT NULL + , id_user INT + , id_permission_required INT NOT NULL + , CONSTRAINT FK_DOG_Calc_User_Temp_id_permission_required + FOREIGN KEY (id_permission_required) + REFERENCES parts.DOG_Permission (id_permission) + , priority_access_level_required INT NOT NULL + , is_super_user BIT + , priority_access_level_user INT + , has_access BIT +); +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Dog_Change_Set' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Dog_Change_Set ( + id_change_set INT NOT NULL AUTO_INCREMENT PRIMARY KEY + , comment VARCHAR(500) + , updated_last_on DATETIME + , id_user_updated_last_by INT + , CONSTRAINT FK_DOG_Role_id_user_updated_last_by + FOREIGN KEY (id_user_updated_last_by) + REFERENCES parts.DOG_User(id_user) +); +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Dog' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Dog ( + id_dog INT NOT NULL AUTO_INCREMENT PRIMARY KEY + , name VARCHAR(250) NOT NULL + , appearance VARCHAR(1000) + , mass_kg DECIMAL(7, 3) + , notes TEXT + , active BIT NOT NULL DEFAULT 1 + , created_on DATETIME + , id_user_created_by INT + , CONSTRAINT FK_DOG_Dog_id_user_created_by + FOREIGN KEY (id_user_created_by) + REFERENCES parts.DOG_User(id_user) + , id_change_set INT + , CONSTRAINT FK_DOG_Dog_id_change_set + FOREIGN KEY (id_change_set) + REFERENCES parts.DOG_Dog_Change_Set(id_change_set) +); + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Dog_Audit' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Dog_Audit ( + id_audit INT NOT NULL AUTO_INCREMENT PRIMARY KEY + , id_dog INT NOT NULL + , CONSTRAINT FK_DOG_Dog_Audit_id_dog + FOREIGN KEY (id_dog) + REFERENCES parts.DOG_Dog(id_dog) + , name_field VARCHAR(100) NOT NULL + , value_prev TEXT + , value_new TEXT + , id_change_set INT NOT NULL + , CONSTRAINT FK_DOG_Dog_Audit_id_change_set + FOREIGN KEY (id_change_set) + REFERENCES parts.DOG_Dog_Change_Set(id_change_set) +); + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Dog_Temp' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Dog_Temp ( + id_temp INT NOT NULL PRIMARY KEY AUTO_INCREMENT + , id_dog INT + , name VARCHAR(250) + , appearance VARCHAR(1000) + , mass_kg DECIMAL(7, 3) + , notes TEXT + , active BIT + , guid BINARY(36) +); + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Breed' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Breed ( + id_breed INT NOT NULL AUTO_INCREMENT PRIMARY KEY + , code VARCHAR(100) NOT NULL + , name VARCHAR(250) NOT NULL + , active BIT NOT NULL DEFAULT 1 + , created_on DATETIME + , id_user_created_by INT + , CONSTRAINT FK_DOG_Breed_id_user_created_by + FOREIGN KEY (id_user_created_by) + REFERENCES parts.DOG_User(id_user) + , id_change_set INT + , CONSTRAINT FK_DOG_Breed_id_change_set + FOREIGN KEY (id_change_set) + REFERENCES parts.DOG_Dog_Change_Set(id_change_set) +); + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Breed_Audit' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Breed_Audit ( + id_audit INT NOT NULL AUTO_INCREMENT PRIMARY KEY + , id_breed INT NOT NULL + , CONSTRAINT FK_DOG_Breed_Audit_id_breed + FOREIGN KEY (id_breed) + REFERENCES parts.DOG_Breed(id_breed) + , name_field VARCHAR(100) NOT NULL + , value_prev TEXT + , value_new TEXT + , id_change_set INT NOT NULL + , CONSTRAINT FK_DOG_Breed_Audit_id_change_set + FOREIGN KEY (id_change_set) + REFERENCES parts.DOG_Dog_Change_Set(id_change_set) +); + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Breed_Temp' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Breed_Temp ( + id_temp INT NOT NULL PRIMARY KEY AUTO_INCREMENT + , id_breed INT + , code VARCHAR(100) + , name VARCHAR(250) + , active BIT + , guid BINARY(36) +); + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Dog_Breed_Link' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Dog_Breed_Link ( + id_link INT NOT NULL AUTO_INCREMENT PRIMARY KEY + , id_dog INT NOT NULL + , CONSTRAINT FK_DOG_Dog_Breed_Link_id_dog + FOREIGN KEY (id_dog) + REFERENCES parts.DOG_Dog(id_dog) + , id_breed INT NOT NULL + , CONSTRAINT FK_DOG_Dog_Breed_Link_id_breed + FOREIGN KEY (id_breed) + REFERENCES parts.DOG_Breed(id_breed) + , lineage_ratio DECIMAL(5, 4) NOT NULL + , active BIT NOT NULL DEFAULT 1 + , created_on DATETIME + , id_user_created_by INT + , CONSTRAINT FK_DOG_Dog_Breed_Link_id_user_created_by + FOREIGN KEY (id_user_created_by) + REFERENCES parts.DOG_User(id_user) + , id_change_set INT + , CONSTRAINT FK_DOG_Dog_Breed_Link_id_change_set + FOREIGN KEY (id_change_set) + REFERENCES parts.DOG_Dog_Change_Set(id_change_set) +); + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Dog_Breed_Link_Audit' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Dog_Breed_Link_Audit ( + id_audit INT NOT NULL AUTO_INCREMENT PRIMARY KEY + , id_link INT NOT NULL + , CONSTRAINT FK_DOG_Dog_Breed_Link_Audit_id_link + FOREIGN KEY (id_link) + REFERENCES parts.DOG_Dog_Breed_Link(id_link) + , name_field VARCHAR(100) NOT NULL + , value_prev TEXT + , value_new TEXT + , id_change_set INT NOT NULL + , CONSTRAINT FK_DOG_Dog_Breed_Link_Audit_id_change_set + FOREIGN KEY (id_change_set) + REFERENCES parts.DOG_Dog_Change_Set(id_change_set) +); + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Dog_Breed_Link_Temp' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Dog_Breed_Link_Temp ( + id_temp INT NOT NULL PRIMARY KEY AUTO_INCREMENT + , id_link INT + , id_dog INT + , id_breed INT + , lineage_ratio DECIMAL(5, 4) + , active BIT + , guid BINARY(36) +); + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Understanding_Level' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Understanding_Level ( + id_understanding_level INT NOT NULL AUTO_INCREMENT PRIMARY KEY + , code VARCHAR(100) NOT NULL + , name VARCHAR(250) NOT NULL + , active BIT NOT NULL DEFAULT 1 + , created_on DATETIME + , id_user_created_by INT + , CONSTRAINT FK_DOG_Understanding_Level_id_user_created_by + FOREIGN KEY (id_user_created_by) + REFERENCES parts.DOG_User(id_user) + , id_change_set INT + , CONSTRAINT FK_DOG_Understanding_Level_id_change_set + FOREIGN KEY (id_change_set) + REFERENCES parts.DOG_Dog_Change_Set(id_change_set) +); + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Understanding_Level_Audit' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Understanding_Level_Audit ( + id_audit INT NOT NULL AUTO_INCREMENT PRIMARY KEY + , id_understanding_level INT NOT NULL + , CONSTRAINT FK_DOG_Understanding_Level_Audit_id_understanding_level + FOREIGN KEY (id_understanding_level) + REFERENCES parts.DOG_Understanding_Level(id_understanding_level) + , name_field VARCHAR(100) NOT NULL + , value_prev TEXT + , value_new TEXT + , id_change_set INT NOT NULL + , CONSTRAINT FK_DOG_Understanding_Level_Audit_id_change_set + FOREIGN KEY (id_change_set) + REFERENCES parts.DOG_Dog_Change_Set(id_change_set) +); + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Understanding_Level_Temp' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Understanding_Level_Temp ( + id_temp INT NOT NULL PRIMARY KEY AUTO_INCREMENT + , id_understanding_level INT + , code VARCHAR(100) + , name VARCHAR(250) + , active BIT + , guid BINARY(36) +); + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Obedience_Level' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Obedience_Level ( + id_obedience_level INT NOT NULL AUTO_INCREMENT PRIMARY KEY + , code VARCHAR(100) NOT NULL + , name VARCHAR(250) NOT NULL + , active BIT NOT NULL DEFAULT 1 + , created_on DATETIME + , id_user_created_by INT + , CONSTRAINT FK_DOG_Obedience_Level_id_user_created_by + FOREIGN KEY (id_user_created_by) + REFERENCES parts.DOG_User(id_user) + , id_change_set INT + , CONSTRAINT FK_DOG_Obedience_Level_id_change_set + FOREIGN KEY (id_change_set) + REFERENCES parts.DOG_Dog_Change_Set(id_change_set) +); + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Obedience_Level_Audit' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Obedience_Level_Audit ( + id_audit INT NOT NULL AUTO_INCREMENT PRIMARY KEY + , id_obedience_level INT NOT NULL + , CONSTRAINT FK_DOG_Obedience_Level_Audit_id_obedience_level + FOREIGN KEY (id_obedience_level) + REFERENCES parts.DOG_Obedience_Level(id_obedience_level) + , name_field VARCHAR(100) NOT NULL + , value_prev TEXT + , value_new TEXT + , id_change_set INT NOT NULL + , CONSTRAINT FK_DOG_Obedience_Level_Audit_id_change_set + FOREIGN KEY (id_change_set) + REFERENCES parts.DOG_Dog_Change_Set(id_change_set) +); + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Obedience_Level_Temp' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Obedience_Level_Temp ( + id_temp INT NOT NULL PRIMARY KEY AUTO_INCREMENT + , id_obedience_level INT + , code VARCHAR(100) + , name VARCHAR(250) + , active BIT + , guid BINARY(36) +); + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Command_Category' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Command_Category ( + id_command_category INT NOT NULL AUTO_INCREMENT PRIMARY KEY + , code VARCHAR(100) NOT NULL + , name VARCHAR(250) NOT NULL + , active BIT NOT NULL DEFAULT 1 + , created_on DATETIME + , id_user_created_by INT + , CONSTRAINT FK_DOG_Command_Category_id_user_created_by + FOREIGN KEY (id_user_created_by) + REFERENCES parts.DOG_User(id_user) + , id_change_set INT + , CONSTRAINT FK_DOG_Command_Category_id_change_set + FOREIGN KEY (id_change_set) + REFERENCES parts.DOG_Dog_Change_Set(id_change_set) +); + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Command_Category_Audit' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Command_Category_Audit ( + id_audit INT NOT NULL AUTO_INCREMENT PRIMARY KEY + , id_command_category INT NOT NULL + , CONSTRAINT FK_DOG_Command_Category_Audit_id_command_category + FOREIGN KEY (id_command_category) + REFERENCES parts.DOG_Command_Category(id_command_category) + , name_field VARCHAR(100) NOT NULL + , value_prev TEXT + , value_new TEXT + , id_change_set INT NOT NULL + , CONSTRAINT FK_DOG_Command_Category_Audit_id_change_set + FOREIGN KEY (id_change_set) + REFERENCES parts.DOG_Dog_Change_Set(id_change_set) +); + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Command_Category_Temp' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Command_Category_Temp ( + id_temp INT NOT NULL PRIMARY KEY AUTO_INCREMENT + , id_command_category INT + , code VARCHAR(100) + , name VARCHAR(250) + , active BIT + , guid BINARY(36) +); +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Command' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Command ( + id_command INT NOT NULL AUTO_INCREMENT PRIMARY KEY + , id_command_category INT NOT NULL + , CONSTRAINT FK_DOG_Command_id_command_category + FOREIGN KEY (id_command_category) + REFERENCES parts.DOG_Command_Category(id_command_category) + , name VARCHAR(250) NOT NULL + , hand_signal_default_description TEXT + , can_have_button BIT NOT NULL DEFAULT 0 + , notes TEXT + , active BIT NOT NULL DEFAULT 1 + , created_on DATETIME + , id_user_created_by INT + , CONSTRAINT FK_DOG_Command_id_user_created_by + FOREIGN KEY (id_user_created_by) + REFERENCES parts.DOG_User(id_user) + , id_change_set INT + , CONSTRAINT FK_DOG_Command_id_change_set + FOREIGN KEY (id_change_set) + REFERENCES parts.DOG_Dog_Change_Set(id_change_set) +); + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Command_Audit' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Command_Audit ( + id_audit INT NOT NULL AUTO_INCREMENT PRIMARY KEY + , id_command INT NOT NULL + , CONSTRAINT FK_DOG_Command_Audit_id_command + FOREIGN KEY (id_command) + REFERENCES parts.DOG_Command(id_command) + , name_field VARCHAR(100) NOT NULL + , value_prev TEXT + , value_new TEXT + , id_change_set INT NOT NULL + , CONSTRAINT FK_DOG_Command_Audit_id_change_set + FOREIGN KEY (id_change_set) + REFERENCES parts.DOG_Dog_Change_Set(id_change_set) +); + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Command_Temp' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Command_Temp ( + id_temp INT NOT NULL PRIMARY KEY AUTO_INCREMENT + , id_command INT + , id_command_category INT + , name VARCHAR(250) + , hand_signal_default_description TEXT + , can_have_button BIT + , notes TEXT + , active BIT + , guid BINARY(36) + + , name_command_category VARCHAR(250) +); + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Dog_Command_Link' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Dog_Command_Link ( + id_link INT NOT NULL AUTO_INCREMENT PRIMARY KEY + , id_dog INT NOT NULL + , CONSTRAINT FK_DOG_Dog_Command_Link_id_dog + FOREIGN KEY (id_dog) + REFERENCES parts.DOG_Dog(id_dog) + , id_command INT NOT NULL + , CONSTRAINT FK_DOG_Dog_Command_Link_id_command + FOREIGN KEY (id_command) + REFERENCES parts.DOG_Command(id_command) + , id_understanding_level INT NOT NULL + , CONSTRAINT FK_DOG_Dog_Command_Link_id_understanding_level + FOREIGN KEY (id_understanding_level) + REFERENCES parts.DOG_Understanding_Level(id_understanding_level) + , id_obedience_level INT NOT NULL + , CONSTRAINT FK_DOG_Dog_Command_Link_id_obedience_level + FOREIGN KEY (id_obedience_level) + REFERENCES parts.DOG_Obedience_Level(id_obedience_level) + , hand_signal_description TEXT + , notes TEXT +-- , has_button BIT NOT NULL DEFAULT 0 + , active BIT NOT NULL DEFAULT 1 + , created_on DATETIME + , id_user_created_by INT + , CONSTRAINT FK_DOG_Dog_Command_Link_id_user_created_by + FOREIGN KEY (id_user_created_by) + REFERENCES parts.DOG_User(id_user) + , id_change_set INT + , CONSTRAINT FK_DOG_Dog_Command_Link_id_change_set + FOREIGN KEY (id_change_set) + REFERENCES parts.DOG_Dog_Change_Set(id_change_set) +); + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Dog_Command_Link_Audit' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Dog_Command_Link_Audit ( + id_audit INT NOT NULL AUTO_INCREMENT PRIMARY KEY + , id_link INT NOT NULL + , CONSTRAINT FK_DOG_Dog_Command_Link_Audit_id_link + FOREIGN KEY (id_link) + REFERENCES parts.DOG_Dog_Command_Link(id_link) + , name_field VARCHAR(100) NOT NULL + , value_prev TEXT + , value_new TEXT + , id_change_set INT NOT NULL + , CONSTRAINT FK_DOG_Dog_Command_Link_Audit_id_change_set + FOREIGN KEY (id_change_set) + REFERENCES parts.DOG_Dog_Change_Set(id_change_set) +); + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Dog_Command_Link_Temp' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Dog_Command_Link_Temp ( + id_temp INT NOT NULL PRIMARY KEY AUTO_INCREMENT + , id_link INT + , id_dog INT + , id_command INT + , id_understanding_level INT + , id_obedience_level INT + , hand_signal_description TEXT + , notes TEXT +-- , has_button BIT + , active BIT + , guid BINARY(36) +); + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Personal_Best' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Personal_Best ( + id_personal_best INT NOT NULL AUTO_INCREMENT PRIMARY KEY + , id_dog_command_link INT NOT NULL + , CONSTRAINT FK_DOG_Personal_Best_id_dog_command_link + FOREIGN KEY (id_dog_command_link) + REFERENCES parts.DOG_Dog_Command_Link(id_link) + , is_achieved_using_button BIT NOT NULL DEFAULT 0 + , situation TEXT NOT NULL + , duration_seconds INT + , quantity INT + , active BIT NOT NULL DEFAULT 1 + , created_on DATETIME + , id_user_created_by INT + , CONSTRAINT FK_DOG_Personal_Best_id_user_created_by + FOREIGN KEY (id_user_created_by) + REFERENCES parts.DOG_User(id_user) + , id_change_set INT + , CONSTRAINT FK_DOG_Personal_Best_id_change_set + FOREIGN KEY (id_change_set) + REFERENCES parts.DOG_Dog_Change_Set(id_change_set) +); + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Personal_Best_Audit' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Personal_Best_Audit ( + id_audit INT NOT NULL AUTO_INCREMENT PRIMARY KEY + , id_personal_best INT NOT NULL + , CONSTRAINT FK_DOG_Personal_Best_Audit_id_personal_best + FOREIGN KEY (id_personal_best) + REFERENCES parts.DOG_Personal_Best(id_personal_best) + , name_field VARCHAR(100) NOT NULL + , value_prev TEXT + , value_new TEXT + , id_change_set INT NOT NULL + , CONSTRAINT FK_DOG_Personal_Best_Audit_id_change_set + FOREIGN KEY (id_change_set) + REFERENCES parts.DOG_Dog_Change_Set(id_change_set) +); + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Personal_Best_Temp' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Personal_Best_Temp ( + id_temp INT NOT NULL PRIMARY KEY AUTO_INCREMENT + , id_personal_best INT + , id_dog_command_link INT + , is_achieved_using_button BIT + , situation TEXT + , duration_seconds INT + , quantity INT + , active BIT + , guid BINARY(36) +); + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Location' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Location ( + id_location INT NOT NULL AUTO_INCREMENT PRIMARY KEY + , code VARCHAR(100) NOT NULL + , name VARCHAR(250) NOT NULL + , active BIT NOT NULL DEFAULT 1 + , created_on DATETIME + , id_user_created_by INT + , CONSTRAINT FK_DOG_Location_id_user_created_by + FOREIGN KEY (id_user_created_by) + REFERENCES parts.DOG_User(id_user) + , id_change_set INT + , CONSTRAINT FK_DOG_Location_id_change_set + FOREIGN KEY (id_change_set) + REFERENCES parts.DOG_Dog_Change_Set(id_change_set) +); + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Location_Audit' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Location_Audit ( + id_audit INT NOT NULL AUTO_INCREMENT PRIMARY KEY + , id_location INT NOT NULL + , CONSTRAINT FK_DOG_Location_Audit_id_location + FOREIGN KEY (id_location) + REFERENCES parts.DOG_Location(id_location) + , name_field VARCHAR(100) NOT NULL + , value_prev TEXT + , value_new TEXT + , id_change_set INT NOT NULL + , CONSTRAINT FK_DOG_Location_Audit_id_change_set + FOREIGN KEY (id_change_set) + REFERENCES parts.DOG_Dog_Change_Set(id_change_set) +); + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Location_Temp' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Location_Temp ( + id_temp INT NOT NULL PRIMARY KEY AUTO_INCREMENT + , id_location INT + , code VARCHAR(100) + , name VARCHAR(250) + , active BIT + , guid BINARY(36) +); + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Location_Link' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Location_Link ( + id_link INT NOT NULL AUTO_INCREMENT PRIMARY KEY + , id_location_parent INT + , CONSTRAINT FK_DOG_Location_Link_id_location_parent + FOREIGN KEY (id_location_parent) + REFERENCES parts.DOG_Location(id_location) + , id_location_child INT + , CONSTRAINT FK_DOG_Location_Link_id_location_child + FOREIGN KEY (id_location_child) + REFERENCES parts.DOG_Location(id_location) + , active BIT NOT NULL DEFAULT 1 + , created_on DATETIME + , id_user_created_by INT + , CONSTRAINT FK_DOG_Location_Link_id_user_created_by + FOREIGN KEY (id_user_created_by) + REFERENCES parts.DOG_User(id_user) + , id_change_set INT + , CONSTRAINT FK_DOG_Location_Link_id_change_set + FOREIGN KEY (id_change_set) + REFERENCES parts.DOG_Dog_Change_Set(id_change_set) +); + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Location_Link_Audit' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Location_Link_Audit ( + id_audit INT NOT NULL AUTO_INCREMENT PRIMARY KEY + , id_link INT NOT NULL + , CONSTRAINT FK_DOG_Location_Link_Audit_id_link + FOREIGN KEY (id_link) + REFERENCES parts.DOG_Location_Link(id_link) + , name_field VARCHAR(100) NOT NULL + , value_prev TEXT + , value_new TEXT + , id_change_set INT NOT NULL + , CONSTRAINT FK_DOG_Location_Link_Audit_id_change_set + FOREIGN KEY (id_change_set) + REFERENCES parts.DOG_Dog_Change_Set(id_change_set) +); + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Location_Link_Temp' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Location_Link_Temp ( + id_temp INT NOT NULL PRIMARY KEY AUTO_INCREMENT + , id_link INT + , id_location_parent INT + , id_location_child INT + , active BIT + , guid BINARY(36) +); + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Colour' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Colour ( + id_colour INT NOT NULL AUTO_INCREMENT PRIMARY KEY + , code VARCHAR(100) NOT NULL + , name VARCHAR(250) NOT NULL + , active BIT NOT NULL DEFAULT 1 + , created_on DATETIME + , id_user_created_by INT + , CONSTRAINT FK_DOG_Colour_id_user_created_by + FOREIGN KEY (id_user_created_by) + REFERENCES parts.DOG_User(id_user) + , id_change_set INT + , CONSTRAINT FK_DOG_Colour_id_change_set + FOREIGN KEY (id_change_set) + REFERENCES parts.DOG_Dog_Change_Set(id_change_set) +); + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Colour_Audit' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Colour_Audit ( + id_audit INT NOT NULL AUTO_INCREMENT PRIMARY KEY + , id_colour INT NOT NULL + , CONSTRAINT FK_DOG_Colour_Audit_id_colour + FOREIGN KEY (id_colour) + REFERENCES parts.DOG_Colour(id_colour) + , name_field VARCHAR(100) NOT NULL + , value_prev TEXT + , value_new TEXT + , id_change_set INT NOT NULL + , CONSTRAINT FK_DOG_Colour_Audit_id_change_set + FOREIGN KEY (id_change_set) + REFERENCES parts.DOG_Dog_Change_Set(id_change_set) +); + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Colour_Temp' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Colour_Temp ( + id_temp INT NOT NULL PRIMARY KEY AUTO_INCREMENT + , id_colour INT + , code VARCHAR(100) + , name VARCHAR(250) + , active BIT + , guid BINARY(36) +); + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Button_Shape' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Button_Shape ( + id_button_shape INT NOT NULL AUTO_INCREMENT PRIMARY KEY + , code VARCHAR(100) NOT NULL + , name VARCHAR(250) NOT NULL + , description TEXT + , active BIT NOT NULL DEFAULT 1 + , created_on DATETIME + , id_user_created_by INT + , CONSTRAINT FK_DOG_Button_Shape_id_user_created_by + FOREIGN KEY (id_user_created_by) + REFERENCES parts.DOG_User(id_user) + , id_change_set INT + , CONSTRAINT FK_DOG_Button_Shape_id_change_set + FOREIGN KEY (id_change_set) + REFERENCES parts.DOG_Dog_Change_Set(id_change_set) +); + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Button_Shape_Audit' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Button_Shape_Audit ( + id_audit INT NOT NULL AUTO_INCREMENT PRIMARY KEY + , id_button_shape INT NOT NULL + , CONSTRAINT FK_DOG_Button_Shape_Audit_id_button_shape + FOREIGN KEY (id_button_shape) + REFERENCES parts.DOG_Button_Shape(id_button_shape) + , name_field VARCHAR(100) NOT NULL + , value_prev TEXT + , value_new TEXT + , id_change_set INT NOT NULL + , CONSTRAINT FK_DOG_Button_Shape_Audit_id_change_set + FOREIGN KEY (id_change_set) + REFERENCES parts.DOG_Dog_Change_Set(id_change_set) +); + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Button_Shape_Temp' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Button_Shape_Temp ( + id_temp INT NOT NULL PRIMARY KEY AUTO_INCREMENT + , id_button_shape INT + , code VARCHAR(100) + , name VARCHAR(250) + , description TEXT + , active BIT + , guid BINARY(36) +); + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Image' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Image ( + id_image INT NOT NULL AUTO_INCREMENT PRIMARY KEY + , id_file_type INT NOT NULL + , CONSTRAINT FK_DOG_Image_id_file_type + FOREIGN KEY (id_file_type) + REFERENCES parts.CORE_File_Type(id_file_type) + , id_dog INT + , CONSTRAINT FK_DOG_Image_id_dog + FOREIGN KEY (id_dog) + REFERENCES parts.DOG_Dog(id_dog) + , path VARCHAR(1024) NOT NULL + , display_order INT + , active BIT NOT NULL DEFAULT 1 + , created_on DATETIME + , id_user_created_by INT + , CONSTRAINT FK_DOG_Image_id_user_created_by + FOREIGN KEY (id_user_created_by) + REFERENCES parts.DOG_User(id_user) + , id_change_set INT + , CONSTRAINT FK_DOG_Image_id_change_set + FOREIGN KEY (id_change_set) + REFERENCES parts.DOG_Dog_Change_Set(id_change_set) +); + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Image_Audit' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Image_Audit ( + id_audit INT NOT NULL AUTO_INCREMENT PRIMARY KEY + , id_image INT NOT NULL + , CONSTRAINT FK_DOG_Image_Audit_id_image + FOREIGN KEY (id_image) + REFERENCES parts.DOG_Image(id_image) + , name_field VARCHAR(100) NOT NULL + , value_prev TEXT + , value_new TEXT + , id_change_set INT NOT NULL + , CONSTRAINT FK_DOG_Image_Audit_id_change_set + FOREIGN KEY (id_change_set) + REFERENCES parts.DOG_Dog_Change_Set(id_change_set) +); + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Image_Temp' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Image_Temp ( + id_temp INT NOT NULL PRIMARY KEY AUTO_INCREMENT + , id_image INT + , id_file_type INT NOT NULL + , id_dog INT + , path VARCHAR(1024) NOT NULL + , display_order INT + , active BIT + , guid BINARY(36) +); + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Button_Icon' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Button_Icon ( + id_button_icon INT NOT NULL AUTO_INCREMENT PRIMARY KEY + , id_image INT + , CONSTRAINT FK_DOG_Button_Icon_id_image + FOREIGN KEY (id_image) + REFERENCES parts.DOG_Image(id_image) + , code VARCHAR(100) NOT NULL + , name VARCHAR(250) NOT NULL + , description TEXT + , active BIT NOT NULL DEFAULT 1 + , created_on DATETIME + , id_user_created_by INT + , CONSTRAINT FK_DOG_Button_Icon_id_user_created_by + FOREIGN KEY (id_user_created_by) + REFERENCES parts.DOG_User(id_user) + , id_change_set INT + , CONSTRAINT FK_DOG_Button_Icon_id_change_set + FOREIGN KEY (id_change_set) + REFERENCES parts.DOG_Dog_Change_Set(id_change_set) +); + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Button_Icon_Audit' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Button_Icon_Audit ( + id_audit INT NOT NULL AUTO_INCREMENT PRIMARY KEY + , id_button_icon INT NOT NULL + , CONSTRAINT FK_DOG_Button_Icon_Audit_id_button_icon + FOREIGN KEY (id_button_icon) + REFERENCES parts.DOG_Button_Icon(id_button_icon) + , name_field VARCHAR(100) NOT NULL + , value_prev TEXT + , value_new TEXT + , id_change_set INT NOT NULL + , CONSTRAINT FK_DOG_Button_Icon_Audit_id_change_set + FOREIGN KEY (id_change_set) + REFERENCES parts.DOG_Dog_Change_Set(id_change_set) +); + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Button_Icon_Temp' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Button_Icon_Temp ( + id_temp INT NOT NULL PRIMARY KEY AUTO_INCREMENT + , id_button_icon INT + , id_image INT + , code VARCHAR(100) + , name VARCHAR(250) + , description TEXT + , active BIT + , guid BINARY(36) +); + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Command_Button_Link' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Command_Button_Link ( + id_link INT NOT NULL AUTO_INCREMENT PRIMARY KEY + , id_command INT NOT NULL + , CONSTRAINT FK_DOG_Command_Button_Link_id_command + FOREIGN KEY (id_command) + REFERENCES parts.DOG_Command(id_command) + , id_button_shape INT NOT NULL + , CONSTRAINT FK_DOG_Command_Button_Link_id_button_shape + FOREIGN KEY (id_button_shape) + REFERENCES parts.DOG_Button_Shape(id_button_shape) + , id_button_colour INT NOT NULL + , CONSTRAINT FK_DOG_Command_Button_Link_id_button_colour + FOREIGN KEY (id_button_colour) + REFERENCES parts.DOG_Colour(id_colour) + , id_button_icon INT + , CONSTRAINT FK_DOG_Command_Button_Link_id_button_icon + FOREIGN KEY (id_button_icon) + REFERENCES parts.DOG_Button_Icon(id_button_icon) + , id_location INT NOT NULL + , CONSTRAINT FK_DOG_Command_Button_Link_id_location + FOREIGN KEY (id_location) + REFERENCES parts.DOG_Location(id_location) + , active BIT NOT NULL DEFAULT 1 + , created_on DATETIME + , id_user_created_by INT + , CONSTRAINT FK_DOG_Command_Button_Link_id_user_created_by + FOREIGN KEY (id_user_created_by) + REFERENCES parts.DOG_User(id_user) + , id_change_set INT + , CONSTRAINT FK_DOG_Command_Button_Link_id_change_set + FOREIGN KEY (id_change_set) + REFERENCES parts.DOG_Dog_Change_Set(id_change_set) +); + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Command_Button_Link_Audit' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Command_Button_Link_Audit ( + id_audit INT NOT NULL AUTO_INCREMENT PRIMARY KEY + , id_link INT NOT NULL + , CONSTRAINT FK_DOG_Command_Button_Link_Audit_id_link + FOREIGN KEY (id_link) + REFERENCES parts.DOG_Command_Button_Link(id_link) + , name_field VARCHAR(100) NOT NULL + , value_prev TEXT + , value_new TEXT + , id_change_set INT NOT NULL + , CONSTRAINT FK_DOG_Command_Button_Link_Audit_id_change_set + FOREIGN KEY (id_change_set) + REFERENCES parts.DOG_Dog_Change_Set(id_change_set) +); + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Command_Button_Link_Temp' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Command_Button_Link_Temp ( + id_temp INT NOT NULL PRIMARY KEY AUTO_INCREMENT + , id_link INT + , id_command INT + , id_button_shape INT + , id_button_colour INT + , id_button_icon INT + , id_location INT + , has_button BIT + , active BIT + , guid BINARY(36) +); + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Drive' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Drive ( + id_drive INT NOT NULL AUTO_INCREMENT PRIMARY KEY + , code VARCHAR(100) NOT NULL + , name VARCHAR(250) NOT NULL + , active BIT NOT NULL DEFAULT 1 + , created_on DATETIME + , id_user_created_by INT + , CONSTRAINT FK_DOG_Drive_id_user_created_by + FOREIGN KEY (id_user_created_by) + REFERENCES parts.DOG_User(id_user) + , id_change_set INT + , CONSTRAINT FK_DOG_Drive_id_change_set + FOREIGN KEY (id_change_set) + REFERENCES parts.DOG_Dog_Change_Set(id_change_set) +); + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Drive_Audit' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Drive_Audit ( + id_audit INT NOT NULL AUTO_INCREMENT PRIMARY KEY + , id_drive INT NOT NULL + , CONSTRAINT FK_DOG_Drive_Audit_id_drive + FOREIGN KEY (id_drive) + REFERENCES parts.DOG_Drive(id_drive) + , name_field VARCHAR(100) NOT NULL + , value_prev TEXT + , value_new TEXT + , id_change_set INT NOT NULL + , CONSTRAINT FK_DOG_Drive_Audit_id_change_set + FOREIGN KEY (id_change_set) + REFERENCES parts.DOG_Dog_Change_Set(id_change_set) +); + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Drive_Temp' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Drive_Temp ( + id_temp INT NOT NULL PRIMARY KEY AUTO_INCREMENT + , id_drive INT + , code VARCHAR(100) + , name VARCHAR(250) + , active BIT + , guid BINARY(36) +); + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Dog_Drive_Link' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Dog_Drive_Link ( + id_link INT NOT NULL AUTO_INCREMENT PRIMARY KEY + , id_dog INT NOT NULL + , CONSTRAINT FK_DOG_Dog_Drive_Link_id_dog + FOREIGN KEY (id_dog) + REFERENCES parts.DOG_Dog(id_dog) + , id_drive INT NOT NULL + , CONSTRAINT FK_DOG_Dog_Drive_Link_id_drive + FOREIGN KEY (id_drive) + REFERENCES parts.DOG_Drive(id_drive) + , dominance_ratio DECIMAL(5, 4) + , active BIT NOT NULL DEFAULT 1 + , created_on DATETIME + , id_user_created_by INT + , CONSTRAINT FK_DOG_Dog_Drive_Link_id_user_created_by + FOREIGN KEY (id_user_created_by) + REFERENCES parts.DOG_User(id_user) + , id_change_set INT + , CONSTRAINT FK_DOG_Dog_Drive_Link_id_change_set + FOREIGN KEY (id_change_set) + REFERENCES parts.DOG_Dog_Change_Set(id_change_set) +); + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Dog_Drive_Link_Audit' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Dog_Drive_Link_Audit ( + id_audit INT NOT NULL AUTO_INCREMENT PRIMARY KEY + , id_link INT NOT NULL + , CONSTRAINT FK_DOG_Dog_Drive_Link_Audit_id_link + FOREIGN KEY (id_link) + REFERENCES parts.DOG_Dog_Drive_Link(id_link) + , name_field VARCHAR(100) NOT NULL + , value_prev TEXT + , value_new TEXT + , id_change_set INT NOT NULL + , CONSTRAINT FK_DOG_Dog_Drive_Link_Audit_id_change_set + FOREIGN KEY (id_change_set) + REFERENCES parts.DOG_Dog_Change_Set(id_change_set) +); + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Dog_Drive_Link_Temp' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Dog_Drive_Link_Temp ( + id_temp INT NOT NULL PRIMARY KEY AUTO_INCREMENT + , id_link INT + , id_dog INT + , id_drive INT + , dominance_ratio DECIMAL(5, 4) + , active BIT + , guid BINARY(36) +); +USE parts; + +DROP TRIGGER IF EXISTS parts.before_insert_DOG_User_Change_Set; + +DELIMITER // +CREATE TRIGGER parts.before_insert_DOG_User_Change_Set +BEFORE INSERT ON parts.DOG_User_Change_Set +FOR EACH ROW +BEGIN + IF NEW.updated_last_on <=> NULL THEN + SET NEW.updated_last_on = NOW(); + END IF; +END // +DELIMITER ; + + +DELIMITER // +CREATE TRIGGER parts.before_update_DOG_User_Change_Set +BEFORE UPDATE ON parts.DOG_User_Change_Set +FOR EACH ROW +BEGIN + IF NOT EXISTS(SELECT * FROM parts.DOG_User WHERE id_user = NEW.id_user_updated_last_by) THEN + SIGNAL SQLSTATE '45000' + SET MESSAGE_TEXT = 'New Updated-Last-By User ID must be provided.'; + END IF; +END // +DELIMITER ; + +USE parts; + +DROP TRIGGER IF EXISTS parts.before_insert_DOG_User; +DROP TRIGGER IF EXISTS parts.before_update_DOG_User; + + +DELIMITER // +CREATE TRIGGER parts.before_insert_DOG_User +BEFORE INSERT ON parts.DOG_User +FOR EACH ROW +BEGIN + SET NEW.created_on := IFNULL(NEW.created_on, NOW()); +END // +DELIMITER ; + + +DELIMITER // +CREATE TRIGGER parts.before_update_DOG_User +BEFORE UPDATE ON parts.DOG_User +FOR EACH ROW +BEGIN + IF OLD.id_change_set <=> NEW.id_change_set THEN + SIGNAL SQLSTATE '45000' + SET MESSAGE_TEXT = 'New change Set ID must be provided.'; + END IF; + + INSERT INTO parts.DOG_User_Audit ( + id_user, + name_field, + value_prev, + value_new, + id_change_set + ) + -- Changed id_user_auth0 + SELECT NEW.id_user, 'id_user_auth0', OLD.id_user_auth0, NEW.id_user_auth0, NEW.id_change_set + WHERE NOT (OLD.id_user_auth0 <=> NEW.id_user_auth0) + UNION + -- Changed firstname + SELECT NEW.id_user, 'firstname', OLD.firstname, NEW.firstname, NEW.id_change_set + WHERE NOT (OLD.firstname <=> NEW.firstname) + UNION + -- Changed surname + SELECT NEW.id_user, 'surname', OLD.surname, NEW.surname, NEW.id_change_set + WHERE NOT (OLD.surname <=> NEW.surname) + UNION + -- Changed email + SELECT NEW.id_user, 'email', OLD.email, NEW.email, NEW.id_change_set + WHERE NOT (OLD.email <=> NEW.email) + UNION + -- Changed is_email_verified + SELECT NEW.id_user, 'is_email_verified', CONVERT(CONVERT(OLD.is_email_verified, SIGNED), CHAR), CONVERT(CONVERT(NEW.is_email_verified, SIGNED), CHAR), NEW.id_change_set + WHERE NOT (OLD.is_email_verified <=> NEW.is_email_verified) + UNION + -- Changed is_super_user + SELECT NEW.id_user, 'is_super_user', CONVERT(CONVERT(OLD.is_super_user, SIGNED), CHAR), CONVERT(CONVERT(NEW.is_super_user, SIGNED), CHAR), NEW.id_change_set + WHERE NOT (OLD.is_super_user <=> NEW.is_super_user) + UNION + -- Changed active + SELECT NEW.id_user, 'active', CONVERT(CONVERT(OLD.active, SIGNED), CHAR), CONVERT(CONVERT(NEW.active, SIGNED), CHAR), NEW.id_change_set + WHERE NOT (OLD.active <=> NEW.active) + ; +END // +DELIMITER ; +USE parts; + +DROP TRIGGER IF EXISTS parts.before_insert_DOG_Role; +DROP TRIGGER IF EXISTS parts.before_update_DOG_Role; + + +DELIMITER // +CREATE TRIGGER parts.before_insert_DOG_Role +BEFORE INSERT ON parts.DOG_Role +FOR EACH ROW +BEGIN + SET NEW.created_on := IFNULL(NEW.created_on, NOW()); +END // +DELIMITER ; + + +DELIMITER // +CREATE TRIGGER parts.before_update_DOG_Role +BEFORE UPDATE ON parts.DOG_Role +FOR EACH ROW +BEGIN + IF OLD.id_change_set <=> NEW.id_change_set THEN + SIGNAL SQLSTATE '45000' + SET MESSAGE_TEXT = 'New change Set ID must be provided.'; + END IF; + + INSERT INTO parts.DOG_Role_Audit ( + id_role, + name_field, + value_prev, + value_new, + id_change_set + ) + -- Changed code + SELECT NEW.id_role, 'code', OLD.code, NEW.code, NEW.id_change_set + WHERE NOT OLD.code <=> NEW.code + UNION + -- Changed name + SELECT NEW.id_role, 'name', OLD.name, NEW.name, NEW.id_change_set + WHERE NOT OLD.name <=> NEW.name + UNION + -- Changed active + SELECT NEW.id_role, 'active', CONVERT(CONVERT(OLD.active, SIGNED), CHAR), CONVERT(CONVERT(NEW.active, SIGNED), CHAR), NEW.id_change_set + WHERE NOT (OLD.active <=> NEW.active) + UNION + -- Changed display_order + SELECT NEW.id_role, 'display_order', CONVERT(OLD.display_order, CHAR), CONVERT(NEW.display_order, CHAR), NEW.id_change_set + WHERE NOT OLD.display_order <=> NEW.display_order + ; +END // +DELIMITER ; + +USE parts; + +DROP TRIGGER IF EXISTS parts.before_insert_DOG_Role_Permission_Link; +DROP TRIGGER IF EXISTS parts.before_update_DOG_Role_Permission_Link; + + +DELIMITER // +CREATE TRIGGER parts.before_insert_DOG_Role_Permission_Link +BEFORE INSERT ON parts.DOG_Role_Permission_Link +FOR EACH ROW +BEGIN + SET NEW.created_on := IFNULL(NEW.created_on, NOW()); +END // +DELIMITER ; + + +DELIMITER // +CREATE TRIGGER parts.before_update_DOG_Role_Permission_Link +BEFORE UPDATE ON parts.DOG_Role_Permission_Link +FOR EACH ROW +BEGIN + IF OLD.id_change_set <=> NEW.id_change_set THEN + SIGNAL SQLSTATE '45000' + SET MESSAGE_TEXT = 'New change Set ID must be provided.'; + END IF; + + INSERT INTO parts.DOG_Role_Permission_Link_Audit ( + id_link, + name_field, + value_prev, + value_new, + id_change_set + ) + -- Changed id_role + SELECT NEW.id_link, 'id_role', CONVERT(OLD.id_role, CHAR), CONVERT(NEW.id_role, CHAR), NEW.id_change_set + WHERE NOT OLD.id_role <=> NEW.id_role + UNION + -- Changed id_permission + SELECT NEW.id_link, 'id_permission', CONVERT(OLD.id_permission, CHAR), CONVERT(NEW.id_permission, CHAR), NEW.id_change_set + WHERE NOT OLD.id_permission <=> NEW.id_permission + UNION + -- Changed id_access_level + SELECT NEW.id_link, 'id_access_level', CONVERT(OLD.id_access_level, CHAR), CONVERT(NEW.id_access_level, CHAR), NEW.id_change_set + WHERE NOT OLD.id_access_level <=> NEW.id_access_level + UNION + -- Changed active + SELECT NEW.id_link, 'active', CONVERT(CONVERT(OLD.active, SIGNED), CHAR), CONVERT(CONVERT(NEW.active, SIGNED), CHAR), NEW.id_change_set + WHERE NOT (OLD.active <=> NEW.active) + ; +END // +DELIMITER ; + +USE parts; + +DROP TRIGGER IF EXISTS parts.before_insert_DOG_User_Role_Link; +DROP TRIGGER IF EXISTS parts.before_update_DOG_User_Role_Link; + + +DELIMITER // +CREATE TRIGGER parts.before_insert_DOG_User_Role_Link +BEFORE INSERT ON parts.DOG_User_Role_Link +FOR EACH ROW +BEGIN + SET NEW.created_on := IFNULL(NEW.created_on, NOW()); +END // +DELIMITER ; + + +DELIMITER // +CREATE TRIGGER parts.before_update_DOG_User_Role_Link +BEFORE UPDATE ON parts.DOG_User_Role_Link +FOR EACH ROW +BEGIN + IF OLD.id_change_set <=> NEW.id_change_set THEN + SIGNAL SQLSTATE '45000' + SET MESSAGE_TEXT = 'New change Set ID must be provided.'; + END IF; + + INSERT INTO parts.DOG_User_Role_Link_Audit ( + id_link, + name_field, + value_prev, + value_new, + id_change_set + ) + -- Changed id_user + SELECT NEW.id_link, 'id_user', CONVERT(OLD.id_user, CHAR), CONVERT(NEW.id_user, CHAR), NEW.id_change_set + WHERE NOT OLD.id_user <=> NEW.id_user + UNION + -- Changed id_role + SELECT NEW.id_link, 'id_role', CONVERT(OLD.id_role, CHAR), CONVERT(NEW.id_role, CHAR), NEW.id_change_set + WHERE NOT OLD.id_role <=> NEW.id_role + UNION + -- Changed active + SELECT NEW.id_link, 'active', CONVERT(CONVERT(OLD.active, SIGNED), CHAR), CONVERT(CONVERT(NEW.active, SIGNED), CHAR), NEW.id_change_set + WHERE NOT (OLD.active <=> NEW.active) + ; +END // +DELIMITER ;USE parts; + +DROP TRIGGER IF EXISTS parts.before_insert_DOG_Dog_Change_Set; + +DELIMITER // +CREATE TRIGGER parts.before_insert_DOG_Dog_Change_Set +BEFORE INSERT ON parts.DOG_Dog_Change_Set +FOR EACH ROW +BEGIN + IF NEW.updated_last_on <=> NULL THEN + SET NEW.updated_last_on = NOW(); + END IF; +END // +DELIMITER ; + +USE parts; + +DROP TRIGGER IF EXISTS parts.before_insert_DOG_Dog; +DROP TRIGGER IF EXISTS parts.before_update_DOG_Dog; + +DELIMITER // +CREATE TRIGGER parts.before_insert_DOG_Dog +BEFORE INSERT ON parts.DOG_Dog +FOR EACH ROW +BEGIN + SET NEW.created_on := IFNULL(NEW.created_on, NOW()); +END // +DELIMITER ; + +DELIMITER // +CREATE TRIGGER parts.before_update_DOG_Dog +BEFORE UPDATE ON parts.DOG_Dog +FOR EACH ROW +BEGIN + IF OLD.id_change_set <=> NEW.id_change_set THEN + SIGNAL SQLSTATE '45000' + SET MESSAGE_TEXT = 'New change Set ID must be provided.'; + END IF; + + INSERT INTO parts.DOG_Dog_Audit ( + id_dog + , name_field + , value_prev + , value_new + , id_change_set + ) + -- Changed name + SELECT NEW.id_dog, 'name', OLD.name, NEW.name, NEW.id_change_set + WHERE NOT OLD.name <=> NEW.name + UNION + -- Changed appearance + SELECT NEW.id_dog, 'appearance', OLD.appearance, NEW.appearance, NEW.id_change_set + WHERE NOT OLD.appearance <=> NEW.appearance + UNION + -- Changed mass_kg + SELECT NEW.id_dog, 'mass_kg', CONVERT(OLD.mass_kg, CHAR), CONVERT(NEW.mass_kg, CHAR), NEW.id_change_set + WHERE NOT (OLD.mass_kg <=> NEW.mass_kg) + UNION + -- Changed active + SELECT NEW.id_dog, 'active', CONVERT(CONVERT(OLD.active, SIGNED), CHAR), CONVERT(CONVERT(NEW.active, SIGNED), CHAR), NEW.id_change_set + WHERE NOT (OLD.active <=> NEW.active) + ; +END // +DELIMITER ; + +USE parts; + +DROP TRIGGER IF EXISTS parts.before_insert_DOG_Breed; +DROP TRIGGER IF EXISTS parts.before_update_DOG_Breed; + +DELIMITER // +CREATE TRIGGER parts.before_insert_DOG_Breed +BEFORE INSERT ON parts.DOG_Breed +FOR EACH ROW +BEGIN + SET NEW.created_on := IFNULL(NEW.created_on, NOW()); +END // +DELIMITER ; + +DELIMITER // +CREATE TRIGGER parts.before_update_DOG_Breed +BEFORE UPDATE ON parts.DOG_Breed +FOR EACH ROW +BEGIN + IF OLD.id_change_set <=> NEW.id_change_set THEN + SIGNAL SQLSTATE '45000' + SET MESSAGE_TEXT = 'New change Set ID must be provided.'; + END IF; + + INSERT INTO parts.DOG_Breed_Audit ( + id_breed + , name_field + , value_prev + , value_new + , id_change_set + ) + -- Changed code + SELECT NEW.id_breed, 'code', OLD.code, NEW.code, NEW.id_change_set + WHERE NOT OLD.code <=> NEW.code + UNION + -- Changed name + SELECT NEW.id_breed, 'name', OLD.name, NEW.name, NEW.id_change_set + WHERE NOT OLD.name <=> NEW.name + UNION + -- Changed active + SELECT NEW.id_breed, 'active', CONVERT(CONVERT(OLD.active, SIGNED), CHAR), CONVERT(CONVERT(NEW.active, SIGNED), CHAR), NEW.id_change_set + WHERE NOT (OLD.active <=> NEW.active) + ; +END // +DELIMITER ; + +USE parts; + +DROP TRIGGER IF EXISTS parts.before_insert_DOG_Dog_Breed_Link; +DROP TRIGGER IF EXISTS parts.before_update_DOG_Dog_Breed_Link; + +DELIMITER // +CREATE TRIGGER parts.before_insert_DOG_Dog_Breed_Link +BEFORE INSERT ON parts.DOG_Dog_Breed_Link +FOR EACH ROW +BEGIN + SET NEW.created_on := IFNULL(NEW.created_on, NOW()); +END // +DELIMITER ; + +DELIMITER // +CREATE TRIGGER parts.before_update_DOG_Dog_Breed_Link +BEFORE UPDATE ON parts.DOG_Dog_Breed_Link +FOR EACH ROW +BEGIN + IF OLD.id_change_set <=> NEW.id_change_set THEN + SIGNAL SQLSTATE '45000' + SET MESSAGE_TEXT = 'New change Set ID must be provided.'; + END IF; + + INSERT INTO parts.DOG_Dog_Breed_Link_Audit ( + id_link + , name_field + , value_prev + , value_new + , id_change_set + ) + -- Changed id_dog + SELECT NEW.id_link, 'id_dog', CONVERT(OLD.id_dog, CHAR), CONVERT(NEW.id_dog, CHAR), NEW.id_change_set + WHERE NOT (OLD.id_dog <=> NEW.id_dog) + UNION + -- Changed id_breed + SELECT NEW.id_link, 'id_breed', CONVERT(OLD.id_breed, CHAR), CONVERT(NEW.id_breed, CHAR), NEW.id_change_set + WHERE NOT (OLD.id_breed <=> NEW.id_breed) + UNION + -- Changed lineage_ratio + SELECT NEW.id_link, 'lineage_ratio', CONVERT(OLD.lineage_ratio, CHAR), CONVERT(NEW.lineage_ratio, CHAR), NEW.id_change_set + WHERE NOT (OLD.lineage_ratio <=> NEW.lineage_ratio) + UNION + -- Changed active + SELECT NEW.id_link, 'active', CONVERT(CONVERT(OLD.active, SIGNED), CHAR), CONVERT(CONVERT(NEW.active, SIGNED), CHAR), NEW.id_change_set + WHERE NOT (OLD.active <=> NEW.active) + ; +END // +DELIMITER ; + +USE parts; + +DROP TRIGGER IF EXISTS parts.before_insert_DOG_Understanding_Level; +DROP TRIGGER IF EXISTS parts.before_update_DOG_Understanding_Level; + +DELIMITER // +CREATE TRIGGER parts.before_insert_DOG_Understanding_Level +BEFORE INSERT ON parts.DOG_Understanding_Level +FOR EACH ROW +BEGIN + SET NEW.created_on := IFNULL(NEW.created_on, NOW()); +END // +DELIMITER ; + +DELIMITER // +CREATE TRIGGER parts.before_update_DOG_Understanding_Level +BEFORE UPDATE ON parts.DOG_Understanding_Level +FOR EACH ROW +BEGIN + IF OLD.id_change_set <=> NEW.id_change_set THEN + SIGNAL SQLSTATE '45000' + SET MESSAGE_TEXT = 'New change Set ID must be provided.'; + END IF; + + INSERT INTO parts.DOG_Understanding_Level_Audit ( + id_understanding_level + , name_field + , value_prev + , value_new + , id_change_set + ) + -- Changed code + SELECT NEW.id_understanding_level, 'code', OLD.code, NEW.code, NEW.id_change_set + WHERE NOT OLD.code <=> NEW.code + UNION + -- Changed name + SELECT NEW.id_understanding_level, 'name', OLD.name, NEW.name, NEW.id_change_set + WHERE NOT OLD.name <=> NEW.name + UNION + -- Changed active + SELECT NEW.id_understanding_level, 'active', CONVERT(CONVERT(OLD.active, SIGNED), CHAR), CONVERT(CONVERT(NEW.active, SIGNED), CHAR), NEW.id_change_set + WHERE NOT (OLD.active <=> NEW.active) + ; +END // +DELIMITER ; + +USE parts; + +DROP TRIGGER IF EXISTS parts.before_insert_DOG_Obedience_Level; +DROP TRIGGER IF EXISTS parts.before_update_DOG_Obedience_Level; + +DELIMITER // +CREATE TRIGGER parts.before_insert_DOG_Obedience_Level +BEFORE INSERT ON parts.DOG_Obedience_Level +FOR EACH ROW +BEGIN + SET NEW.created_on := IFNULL(NEW.created_on, NOW()); +END // +DELIMITER ; + +DELIMITER // +CREATE TRIGGER parts.before_update_DOG_Obedience_Level +BEFORE UPDATE ON parts.DOG_Obedience_Level +FOR EACH ROW +BEGIN + IF OLD.id_change_set <=> NEW.id_change_set THEN + SIGNAL SQLSTATE '45000' + SET MESSAGE_TEXT = 'New change Set ID must be provided.'; + END IF; + + INSERT INTO parts.DOG_Obedience_Level_Audit ( + id_obedience_level + , name_field + , value_prev + , value_new + , id_change_set + ) + -- Changed code + SELECT NEW.id_obedience_level, 'code', OLD.code, NEW.code, NEW.id_change_set + WHERE NOT OLD.code <=> NEW.code + UNION + -- Changed name + SELECT NEW.id_obedience_level, 'name', OLD.name, NEW.name, NEW.id_change_set + WHERE NOT OLD.name <=> NEW.name + UNION + -- Changed active + SELECT NEW.id_obedience_level, 'active', CONVERT(CONVERT(OLD.active, SIGNED), CHAR), CONVERT(CONVERT(NEW.active, SIGNED), CHAR), NEW.id_change_set + WHERE NOT (OLD.active <=> NEW.active) + ; +END // +DELIMITER ; + +USE parts; + +DROP TRIGGER IF EXISTS parts.before_insert_DOG_Command_Category; +DROP TRIGGER IF EXISTS parts.before_update_DOG_Command_Category; + +DELIMITER // +CREATE TRIGGER parts.before_insert_DOG_Command_Category +BEFORE INSERT ON parts.DOG_Command_Category +FOR EACH ROW +BEGIN + SET NEW.created_on := IFNULL(NEW.created_on, NOW()); +END // +DELIMITER ; + +DELIMITER // +CREATE TRIGGER parts.before_update_DOG_Command_Category +BEFORE UPDATE ON parts.DOG_Command_Category +FOR EACH ROW +BEGIN + IF OLD.id_change_set <=> NEW.id_change_set THEN + SIGNAL SQLSTATE '45000' + SET MESSAGE_TEXT = 'New change Set ID must be provided.'; + END IF; + + INSERT INTO parts.DOG_Command_Category_Audit ( + id_command_category + , name_field + , value_prev + , value_new + , id_change_set + ) + -- Changed code + SELECT NEW.id_command_category, 'code', OLD.code, NEW.code, NEW.id_change_set + WHERE NOT OLD.code <=> NEW.code + UNION + -- Changed name + SELECT NEW.id_command_category, 'name', OLD.name, NEW.name, NEW.id_change_set + WHERE NOT OLD.name <=> NEW.name + UNION + -- Changed active + SELECT NEW.id_command_category, 'active', CONVERT(CONVERT(OLD.active, SIGNED), CHAR), CONVERT(CONVERT(NEW.active, SIGNED), CHAR), NEW.id_change_set + WHERE NOT (OLD.active <=> NEW.active) + ; +END // +DELIMITER ; + +USE parts; + +DROP TRIGGER IF EXISTS parts.before_insert_DOG_Command; +DROP TRIGGER IF EXISTS parts.before_update_DOG_Command; + +DELIMITER // +CREATE TRIGGER parts.before_insert_DOG_Command +BEFORE INSERT ON parts.DOG_Command +FOR EACH ROW +BEGIN + SET NEW.created_on := IFNULL(NEW.created_on, NOW()); +END // +DELIMITER ; + +DELIMITER // +CREATE TRIGGER parts.before_update_DOG_Command +BEFORE UPDATE ON parts.DOG_Command +FOR EACH ROW +BEGIN + IF OLD.id_change_set <=> NEW.id_change_set THEN + SIGNAL SQLSTATE '45000' + SET MESSAGE_TEXT = 'New change Set ID must be provided.'; + END IF; + + INSERT INTO parts.DOG_Command_Audit ( + id_command + , name_field + , value_prev + , value_new + , id_change_set + ) + -- Changed id_command_category + SELECT NEW.id_command, 'id_command_category', CONVERT(OLD.id_command_category, CHAR), CONVERT(NEW.id_command_category, CHAR), NEW.id_change_set + WHERE NOT (OLD.id_command_category <=> NEW.id_command_category) + UNION + -- Changed name + SELECT NEW.id_command, 'name', OLD.name, NEW.name, NEW.id_change_set + WHERE NOT OLD.name <=> NEW.name + UNION + -- Changed hand_signal_default_description + SELECT NEW.id_command, 'hand_signal_default_description', OLD.hand_signal_default_description, NEW.hand_signal_default_description, NEW.id_change_set + WHERE NOT OLD.hand_signal_default_description <=> NEW.hand_signal_default_description + UNION + -- Changed can_have_button + SELECT NEW.id_command, 'can_have_button', CONVERT(CONVERT(OLD.can_have_button, SIGNED), CHAR), CONVERT(CONVERT(NEW.can_have_button, SIGNED), CHAR), NEW.id_change_set + WHERE NOT (OLD.can_have_button <=> NEW.can_have_button) + UNION + -- Changed notes + SELECT NEW.id_command, 'notes', OLD.notes, NEW.notes, NEW.id_change_set + WHERE NOT OLD.notes <=> NEW.notes + UNION + -- Changed active + SELECT NEW.id_command, 'active', CONVERT(CONVERT(OLD.active, SIGNED), CHAR), CONVERT(CONVERT(NEW.active, SIGNED), CHAR), NEW.id_change_set + WHERE NOT (OLD.active <=> NEW.active) + ; +END // +DELIMITER ; + +USE parts; + +DROP TRIGGER IF EXISTS parts.before_insert_DOG_Dog_Command_Link; +DROP TRIGGER IF EXISTS parts.before_update_DOG_Dog_Command_Link; + +DELIMITER // +CREATE TRIGGER parts.before_insert_DOG_Dog_Command_Link +BEFORE INSERT ON parts.DOG_Dog_Command_Link +FOR EACH ROW +BEGIN + SET NEW.created_on := IFNULL(NEW.created_on, NOW()); +END // +DELIMITER ; + +DELIMITER // +CREATE TRIGGER parts.before_update_DOG_Dog_Command_Link +BEFORE UPDATE ON parts.DOG_Dog_Command_Link +FOR EACH ROW +BEGIN + IF OLD.id_change_set <=> NEW.id_change_set THEN + SIGNAL SQLSTATE '45000' + SET MESSAGE_TEXT = 'New change Set ID must be provided.'; + END IF; + + INSERT INTO parts.DOG_Dog_Command_Link_Audit ( + id_link + , name_field + , value_prev + , value_new + , id_change_set + ) + -- Changed id_dog + SELECT NEW.id_link, 'id_dog', CONVERT(OLD.id_dog, CHAR), CONVERT(NEW.id_dog, CHAR), NEW.id_change_set + WHERE NOT (OLD.id_dog <=> NEW.id_dog) + UNION + -- Changed id_command + SELECT NEW.id_link, 'id_command', CONVERT(OLD.id_command, CHAR), CONVERT(NEW.id_command, CHAR), NEW.id_change_set + WHERE NOT (OLD.id_command <=> NEW.id_command) + UNION + -- Changed id_understanding_level + SELECT NEW.id_link, 'id_understanding_level', CONVERT(OLD.id_understanding_level, CHAR), CONVERT(NEW.id_understanding_level, CHAR), NEW.id_change_set + WHERE NOT (OLD.id_understanding_level <=> NEW.id_understanding_level) + UNION + -- Changed id_obedience_level + SELECT NEW.id_link, 'id_obedience_level', CONVERT(OLD.id_obedience_level, CHAR), CONVERT(NEW.id_obedience_level, CHAR), NEW.id_change_set + WHERE NOT (OLD.id_obedience_level <=> NEW.id_obedience_level) + UNION + -- Changed hand_signal_description + SELECT NEW.id_link, 'hand_signal_description', OLD.hand_signal_description, NEW.hand_signal_description, NEW.id_change_set + WHERE NOT OLD.hand_signal_description <=> NEW.hand_signal_description + UNION + -- Changed notes + SELECT NEW.id_link, 'notes', OLD.notes, NEW.notes, NEW.id_change_set + WHERE NOT OLD.notes <=> NEW.notes + UNION + /* + -- Changed has_button + SELECT NEW.id_link, 'has_button', CONVERT(CONVERT(OLD.has_button, SIGNED), CHAR), CONVERT(CONVERT(NEW.has_button, SIGNED), CHAR), NEW.id_change_set + WHERE NOT (OLD.has_button <=> NEW.has_button) + UNION + */ + -- Changed active + SELECT NEW.id_link, 'active', CONVERT(CONVERT(OLD.active, SIGNED), CHAR), CONVERT(CONVERT(NEW.active, SIGNED), CHAR), NEW.id_change_set + WHERE NOT (OLD.active <=> NEW.active) + ; +END // +DELIMITER ; + +USE parts; + +DROP TRIGGER IF EXISTS parts.before_insert_DOG_Personal_Best; +DROP TRIGGER IF EXISTS parts.before_update_DOG_Personal_Best; + +DELIMITER // +CREATE TRIGGER parts.before_insert_DOG_Personal_Best +BEFORE INSERT ON parts.DOG_Personal_Best +FOR EACH ROW +BEGIN + SET NEW.created_on := IFNULL(NEW.created_on, NOW()); +END // +DELIMITER ; + +DELIMITER // +CREATE TRIGGER parts.before_update_DOG_Personal_Best +BEFORE UPDATE ON parts.DOG_Personal_Best +FOR EACH ROW +BEGIN + IF OLD.id_change_set <=> NEW.id_change_set THEN + SIGNAL SQLSTATE '45000' + SET MESSAGE_TEXT = 'New change Set ID must be provided.'; + END IF; + + INSERT INTO parts.DOG_Personal_Best_Audit ( + id_personal_best + , name_field + , value_prev + , value_new + , id_change_set + ) + -- Changed id_dog_command_link + SELECT NEW.id_personal_best, 'id_dog_command_link', CONVERT(OLD.id_dog_command_link, CHAR), CONVERT(NEW.id_dog_command_link, CHAR), NEW.id_change_set + WHERE NOT (OLD.id_dog_command_link <=> NEW.id_dog_command_link) + UNION + -- Changed is_achieved_using_button + SELECT NEW.id_personal_best, 'is_achieved_using_button', CONVERT(CONVERT(OLD.is_achieved_using_button, SIGNED), CHAR), CONVERT(CONVERT(NEW.is_achieved_using_button, SIGNED), CHAR), NEW.id_change_set + WHERE NOT (OLD.is_achieved_using_button <=> NEW.is_achieved_using_button) + UNION + -- Changed situation + SELECT NEW.id_personal_best, 'situation', OLD.situation, NEW.situation, NEW.id_change_set + WHERE NOT OLD.situation <=> NEW.situation + UNION + -- Changed quantity + SELECT NEW.id_personal_best, 'quantity', CONVERT(OLD.quantity, CHAR), CONVERT(NEW.quantity, CHAR), NEW.id_change_set + WHERE NOT (OLD.quantity <=> NEW.quantity) + UNION + -- Changed duration_seconds + SELECT NEW.id_personal_best, 'duration_seconds', CONVERT(OLD.duration_seconds, CHAR), CONVERT(NEW.duration_seconds, CHAR), NEW.id_change_set + WHERE NOT (OLD.duration_seconds <=> NEW.duration_seconds) + UNION + -- Changed active + SELECT NEW.id_personal_best, 'active', CONVERT(CONVERT(OLD.active, SIGNED), CHAR), CONVERT(CONVERT(NEW.active, SIGNED), CHAR), NEW.id_change_set + WHERE NOT (OLD.active <=> NEW.active) + ; +END // +DELIMITER ; + +USE parts; + +DROP TRIGGER IF EXISTS parts.before_insert_DOG_Location; +DROP TRIGGER IF EXISTS parts.before_update_DOG_Location; + +DELIMITER // +CREATE TRIGGER parts.before_insert_DOG_Location +BEFORE INSERT ON parts.DOG_Location +FOR EACH ROW +BEGIN + SET NEW.created_on := IFNULL(NEW.created_on, NOW()); +END // +DELIMITER ; + +DELIMITER // +CREATE TRIGGER parts.before_update_DOG_Location +BEFORE UPDATE ON parts.DOG_Location +FOR EACH ROW +BEGIN + IF OLD.id_change_set <=> NEW.id_change_set THEN + SIGNAL SQLSTATE '45000' + SET MESSAGE_TEXT = 'New change Set ID must be provided.'; + END IF; + + INSERT INTO parts.DOG_Location_Audit ( + id_location + , name_field + , value_prev + , value_new + , id_change_set + ) + -- Changed code + SELECT NEW.id_location, 'code', OLD.code, NEW.code, NEW.id_change_set + WHERE NOT (OLD.code <=> NEW.code) + UNION + -- Changed name + SELECT NEW.id_location, 'name', OLD.name, NEW.name, NEW.id_change_set + WHERE NOT (OLD.name <=> NEW.name) + UNION + -- Changed active + SELECT NEW.id_location, 'active', CONVERT(CONVERT(OLD.active, SIGNED), CHAR), CONVERT(CONVERT(NEW.active, SIGNED), CHAR), NEW.id_change_set + WHERE NOT (OLD.active <=> NEW.active) + ; +END // +DELIMITER ; + +USE parts; + +DROP TRIGGER IF EXISTS parts.before_insert_DOG_Location_Link; +DROP TRIGGER IF EXISTS parts.before_update_DOG_Location_Link; + +DELIMITER // +CREATE TRIGGER parts.before_insert_DOG_Location_Link +BEFORE INSERT ON parts.DOG_Location_Link +FOR EACH ROW +BEGIN + SET NEW.created_on := IFNULL(NEW.created_on, NOW()); +END // +DELIMITER ; + +DELIMITER // +CREATE TRIGGER parts.before_update_DOG_Location_Link +BEFORE UPDATE ON parts.DOG_Location_Link +FOR EACH ROW +BEGIN + IF OLD.id_change_set <=> NEW.id_change_set THEN + SIGNAL SQLSTATE '45000' + SET MESSAGE_TEXT = 'New change Set ID must be provided.'; + END IF; + + INSERT INTO parts.DOG_Location_Link_Audit ( + id_link + , name_field + , value_prev + , value_new + , id_change_set + ) + -- Changed id_location_parent + SELECT NEW.id_link, 'id_location_parent', CONVERT(OLD.id_location_parent, CHAR), CONVERT(NEW.id_location_parent, CHAR), NEW.id_change_set + WHERE NOT (OLD.id_location_parent <=> NEW.id_location_parent) + UNION + -- Changed id_location_child + SELECT NEW.id_link, 'id_location_child', CONVERT(OLD.id_location_child, CHAR), CONVERT(NEW.id_location_child, CHAR), NEW.id_change_set + WHERE NOT (OLD.id_location_child <=> NEW.id_location_child) + UNION + -- Changed active + SELECT NEW.id_link, 'active', CONVERT(CONVERT(OLD.active, SIGNED), CHAR), CONVERT(CONVERT(NEW.active, SIGNED), CHAR), NEW.id_change_set + WHERE NOT (OLD.active <=> NEW.active) + ; +END // +DELIMITER ; + +USE parts; + +DROP TRIGGER IF EXISTS parts.before_insert_DOG_Colour; +DROP TRIGGER IF EXISTS parts.before_update_DOG_Colour; + +DELIMITER // +CREATE TRIGGER parts.before_insert_DOG_Colour +BEFORE INSERT ON parts.DOG_Colour +FOR EACH ROW +BEGIN + SET NEW.created_on := IFNULL(NEW.created_on, NOW()); +END // +DELIMITER ; + +DELIMITER // +CREATE TRIGGER parts.before_update_DOG_Colour +BEFORE UPDATE ON parts.DOG_Colour +FOR EACH ROW +BEGIN + IF OLD.id_change_set <=> NEW.id_change_set THEN + SIGNAL SQLSTATE '45000' + SET MESSAGE_TEXT = 'New change Set ID must be provided.'; + END IF; + + INSERT INTO parts.DOG_Colour_Audit ( + id_colour + , name_field + , value_prev + , value_new + , id_change_set + ) + -- Changed code + SELECT NEW.id_colour, 'code', OLD.code, NEW.code, NEW.id_change_set + WHERE NOT (OLD.code <=> NEW.code) + UNION + -- Changed name + SELECT NEW.id_colour, 'name', OLD.name, NEW.name, NEW.id_change_set + WHERE NOT (OLD.name <=> NEW.name) + UNION + -- Changed active + SELECT NEW.id_colour, 'active', CONVERT(CONVERT(OLD.active, SIGNED), CHAR), CONVERT(CONVERT(NEW.active, SIGNED), CHAR), NEW.id_change_set + WHERE NOT (OLD.active <=> NEW.active) + ; +END // +DELIMITER ; + +USE parts; + +DROP TRIGGER IF EXISTS parts.before_insert_DOG_Button_Shape; +DROP TRIGGER IF EXISTS parts.before_update_DOG_Button_Shape; + +DELIMITER // +CREATE TRIGGER parts.before_insert_DOG_Button_Shape +BEFORE INSERT ON parts.DOG_Button_Shape +FOR EACH ROW +BEGIN + SET NEW.created_on := IFNULL(NEW.created_on, NOW()); +END // +DELIMITER ; + +DELIMITER // +CREATE TRIGGER parts.before_update_DOG_Button_Shape +BEFORE UPDATE ON parts.DOG_Button_Shape +FOR EACH ROW +BEGIN + IF OLD.id_change_set <=> NEW.id_change_set THEN + SIGNAL SQLSTATE '45000' + SET MESSAGE_TEXT = 'New change Set ID must be provided.'; + END IF; + + INSERT INTO parts.DOG_Button_Shape_Audit ( + id_button_shape + , name_field + , value_prev + , value_new + , id_change_set + ) + -- Changed code + SELECT NEW.id_button_shape, 'code', OLD.code, NEW.code, NEW.id_change_set + WHERE NOT (OLD.code <=> NEW.code) + UNION + -- Changed name + SELECT NEW.id_button_shape, 'name', OLD.name, NEW.name, NEW.id_change_set + WHERE NOT (OLD.name <=> NEW.name) + UNION + -- Changed description + SELECT NEW.id_button_shape, 'description', OLD.description, NEW.description, NEW.id_change_set + WHERE NOT (OLD.description <=> NEW.description) + UNION + -- Changed active + SELECT NEW.id_button_shape, 'active', CONVERT(CONVERT(OLD.active, SIGNED), CHAR), CONVERT(CONVERT(NEW.active, SIGNED), CHAR), NEW.id_change_set + WHERE NOT (OLD.active <=> NEW.active) + ; +END // +DELIMITER ; + +USE parts; + +DROP TRIGGER IF EXISTS parts.before_insert_DOG_Image; +DROP TRIGGER IF EXISTS parts.before_update_DOG_Image; + +DELIMITER // +CREATE TRIGGER parts.before_insert_DOG_Image +BEFORE INSERT ON parts.DOG_Image +FOR EACH ROW +BEGIN + SET NEW.created_on := IFNULL(NEW.created_on, NOW()); +END // +DELIMITER ; + +DELIMITER // +CREATE TRIGGER parts.before_update_DOG_Image +BEFORE UPDATE ON parts.DOG_Image +FOR EACH ROW +BEGIN + IF OLD.id_change_set <=> NEW.id_change_set THEN + SIGNAL SQLSTATE '45000' + SET MESSAGE_TEXT = 'New change Set ID must be provided.'; + END IF; + + INSERT INTO parts.DOG_Image_Audit ( + id_image + , name_field + , value_prev + , value_new + , id_change_set + ) + -- Changed id_file_type + SELECT NEW.id_image, 'id_file_type', CONVERT(OLD.id_file_type, CHAR), CONVERT(NEW.id_file_type, CHAR), NEW.id_change_set + WHERE NOT (OLD.id_file_type <=> NEW.id_file_type) + UNION + -- Changed id_dog + SELECT NEW.id_image, 'id_dog', CONVERT(OLD.id_dog, CHAR), CONVERT(NEW.id_dog, CHAR), NEW.id_change_set + WHERE NOT (OLD.id_dog <=> NEW.id_dog) + UNION + -- Changed path + SELECT NEW.id_image, 'path', OLD.path, NEW.path, NEW.id_change_set + WHERE NOT (OLD.path <=> NEW.path) + UNION + -- Changed display_order + SELECT NEW.id_image, 'display_order', CONVERT(OLD.display_order, CHAR), CONVERT(NEW.display_order, CHAR), NEW.id_change_set + WHERE NOT (OLD.display_order <=> NEW.display_order) + UNION + -- Changed active + SELECT NEW.id_image, 'active', CONVERT(CONVERT(OLD.active, SIGNED), CHAR), CONVERT(CONVERT(NEW.active, SIGNED), CHAR), NEW.id_change_set + WHERE NOT (OLD.active <=> NEW.active) + ; +END // +DELIMITER ; + +USE parts; + +DROP TRIGGER IF EXISTS parts.before_insert_DOG_Button_Icon; +DROP TRIGGER IF EXISTS parts.before_update_DOG_Button_Icon; + +DELIMITER // +CREATE TRIGGER parts.before_insert_DOG_Button_Icon +BEFORE INSERT ON parts.DOG_Button_Icon +FOR EACH ROW +BEGIN + SET NEW.created_on := IFNULL(NEW.created_on, NOW()); +END // +DELIMITER ; + +DELIMITER // +CREATE TRIGGER parts.before_update_DOG_Button_Icon +BEFORE UPDATE ON parts.DOG_Button_Icon +FOR EACH ROW +BEGIN + IF OLD.id_change_set <=> NEW.id_change_set THEN + SIGNAL SQLSTATE '45000' + SET MESSAGE_TEXT = 'New change Set ID must be provided.'; + END IF; + + INSERT INTO parts.DOG_Button_Icon_Audit ( + id_button_icon + , name_field + , value_prev + , value_new + , id_change_set + ) + -- Changed id_image + SELECT NEW.id_button_icon, 'id_image', CONVERT(OLD.id_image, CHAR), CONVERT(NEW.id_image, CHAR), NEW.id_change_set + WHERE NOT (OLD.id_image <=> NEW.id_image) + UNION + -- Changed code + SELECT NEW.id_button_icon, 'code', OLD.code, NEW.code, NEW.id_change_set + WHERE NOT (OLD.code <=> NEW.code) + UNION + -- Changed name + SELECT NEW.id_button_icon, 'name', OLD.name, NEW.name, NEW.id_change_set + WHERE NOT (OLD.name <=> NEW.name) + UNION + -- Changed description + SELECT NEW.id_button_icon, 'description', OLD.description, NEW.description, NEW.id_change_set + WHERE NOT (OLD.description <=> NEW.description) + UNION + -- Changed active + SELECT NEW.id_button_icon, 'active', CONVERT(CONVERT(OLD.active, SIGNED), CHAR), CONVERT(CONVERT(NEW.active, SIGNED), CHAR), NEW.id_change_set + WHERE NOT (OLD.active <=> NEW.active) + ; +END // +DELIMITER ; + +USE parts; + +DROP TRIGGER IF EXISTS parts.before_insert_DOG_Command_Button_Link; +DROP TRIGGER IF EXISTS parts.before_update_DOG_Command_Button_Link; + +DELIMITER // +CREATE TRIGGER parts.before_insert_DOG_Command_Button_Link +BEFORE INSERT ON parts.DOG_Command_Button_Link +FOR EACH ROW +BEGIN + SET NEW.created_on := IFNULL(NEW.created_on, NOW()); +END // +DELIMITER ; + +DELIMITER // +CREATE TRIGGER parts.before_update_DOG_Command_Button_Link +BEFORE UPDATE ON parts.DOG_Command_Button_Link +FOR EACH ROW +BEGIN + IF OLD.id_change_set <=> NEW.id_change_set THEN + SIGNAL SQLSTATE '45000' + SET MESSAGE_TEXT = 'New change Set ID must be provided.'; + END IF; + + INSERT INTO parts.DOG_Command_Button_Link_Audit ( + id_link + , name_field + , value_prev + , value_new + , id_change_set + ) + -- Changed id_command + SELECT NEW.id_link, 'id_command', CONVERT(OLD.id_command, CHAR), CONVERT(NEW.id_command, CHAR), NEW.id_change_set + WHERE NOT (OLD.id_command <=> NEW.id_command) + UNION + -- Changed id_button_shape + SELECT NEW.id_link, 'id_button_shape', CONVERT(OLD.id_button_shape, CHAR), CONVERT(NEW.id_button_shape, CHAR), NEW.id_change_set + WHERE NOT (OLD.id_button_shape <=> NEW.id_button_shape) + UNION + -- Changed id_button_colour + SELECT NEW.id_link, 'id_button_colour', CONVERT(OLD.id_button_colour, CHAR), CONVERT(NEW.id_button_colour, CHAR), NEW.id_change_set + WHERE NOT (OLD.id_button_colour <=> NEW.id_button_colour) + UNION + -- Changed id_button_icon + SELECT NEW.id_link, 'id_button_icon', CONVERT(OLD.id_button_icon, CHAR), CONVERT(NEW.id_button_icon, CHAR), NEW.id_change_set + WHERE NOT (OLD.id_button_icon <=> NEW.id_button_icon) + UNION + -- Changed id_location + SELECT NEW.id_link, 'id_location', CONVERT(OLD.id_location, CHAR), CONVERT(NEW.id_location, CHAR), NEW.id_change_set + WHERE NOT (OLD.id_location <=> NEW.id_location) + UNION + -- Changed active + SELECT NEW.id_link, 'active', CONVERT(CONVERT(OLD.active, SIGNED), CHAR), CONVERT(CONVERT(NEW.active, SIGNED), CHAR), NEW.id_change_set + WHERE NOT (OLD.active <=> NEW.active) + ; +END // +DELIMITER ; + +USE parts; + +DROP TRIGGER IF EXISTS parts.before_insert_DOG_Drive; +DROP TRIGGER IF EXISTS parts.before_update_DOG_Drive; + +DELIMITER // +CREATE TRIGGER parts.before_insert_DOG_Drive +BEFORE INSERT ON parts.DOG_Drive +FOR EACH ROW +BEGIN + SET NEW.created_on := IFNULL(NEW.created_on, NOW()); +END // +DELIMITER ; + +DELIMITER // +CREATE TRIGGER parts.before_update_DOG_Drive +BEFORE UPDATE ON parts.DOG_Drive +FOR EACH ROW +BEGIN + IF OLD.id_change_set <=> NEW.id_change_set THEN + SIGNAL SQLSTATE '45000' + SET MESSAGE_TEXT = 'New change Set ID must be provided.'; + END IF; + + INSERT INTO parts.DOG_Drive_Audit ( + id_drive + , name_field + , value_prev + , value_new + , id_change_set + ) + -- Changed code + SELECT NEW.id_drive, 'code', OLD.code, NEW.code, NEW.id_change_set + WHERE NOT (OLD.code <=> NEW.code) + UNION + -- Changed name + SELECT NEW.id_drive, 'name', OLD.name, NEW.name, NEW.id_change_set + WHERE NOT (OLD.name <=> NEW.name) + UNION + -- Changed active + SELECT NEW.id_drive, 'active', CONVERT(CONVERT(OLD.active, SIGNED), CHAR), CONVERT(CONVERT(NEW.active, SIGNED), CHAR), NEW.id_change_set + WHERE NOT (OLD.active <=> NEW.active) + ; +END // +DELIMITER ; + +USE parts; + +DROP TRIGGER IF EXISTS parts.before_insert_DOG_Dog_Drive_Link; +DROP TRIGGER IF EXISTS parts.before_update_DOG_Dog_Drive_Link; + +DELIMITER // +CREATE TRIGGER parts.before_insert_DOG_Dog_Drive_Link +BEFORE INSERT ON parts.DOG_Dog_Drive_Link +FOR EACH ROW +BEGIN + SET NEW.created_on := IFNULL(NEW.created_on, NOW()); +END // +DELIMITER ; + +DELIMITER // +CREATE TRIGGER parts.before_update_DOG_Dog_Drive_Link +BEFORE UPDATE ON parts.DOG_Dog_Drive_Link +FOR EACH ROW +BEGIN + IF OLD.id_change_set <=> NEW.id_change_set THEN + SIGNAL SQLSTATE '45000' + SET MESSAGE_TEXT = 'New change Set ID must be provided.'; + END IF; + + INSERT INTO parts.DOG_Dog_Drive_Link_Audit ( + id_link + , name_field + , value_prev + , value_new + , id_change_set + ) + -- Changed id_dog + SELECT NEW.id_link, 'id_dog', CONVERT(OLD.id_dog, CHAR), CONVERT(NEW.id_dog, CHAR), NEW.id_change_set + WHERE NOT (OLD.id_dog <=> NEW.id_dog) + UNION + -- Changed id_drive + SELECT NEW.id_link, 'id_drive', CONVERT(OLD.id_drive, CHAR), CONVERT(NEW.id_drive, CHAR), NEW.id_change_set + WHERE NOT (OLD.id_drive <=> NEW.id_drive) + UNION + -- Changed dominance_ratio + SELECT NEW.id_link, 'dominance_ratio', CONVERT(OLD.dominance_ratio, CHAR), CONVERT(NEW.dominance_ratio, CHAR), NEW.id_change_set + WHERE NOT (OLD.dominance_ratio <=> NEW.dominance_ratio) + UNION + -- Changed active + SELECT NEW.id_link, 'active', CONVERT(CONVERT(OLD.active, SIGNED), CHAR), CONVERT(CONVERT(NEW.active, SIGNED), CHAR), NEW.id_change_set + WHERE NOT (OLD.active <=> NEW.active) + ; +END // +DELIMITER ; + +USE parts; + +DROP PROCEDURE IF EXISTS parts.p_core_validate_guid; +DROP PROCEDURE IF EXISTS parts.p_core_validate_guid_test; + +DELIMITER // +CREATE PROCEDURE parts.p_core_validate_guid ( + IN a_guid BINARY(36) +) +BEGIN + IF ISNULL(a_guid) THEN + SIGNAL SQLSTATE '45000' + SET MESSAGE_TEXT = 'GUID is required.' + ; + END IF; +END // +DELIMITER ; + + +DELIMITER // +CREATE PROCEDURE parts.p_core_validate_guid_test () +BEGIN + CALL parts.p_core_validate_guid ( 'nips' ); + CALL parts.p_core_validate_guid ( NULL ); +END // +DELIMITER ; + +-- CALL parts.p_core_validate_guid_test(); +USE parts; + +DROP PROCEDURE IF EXISTS parts.p_core_debug_timing_reporting; + +DELIMITER // +CREATE PROCEDURE parts.p_core_debug_timing_reporting ( + IN a_time_start TIMESTAMP(6) +) +BEGIN +/* + PROCEDURE parts.p_core_debug_timing_reporting + Shared method timing reporting +*/ + DECLARE v_time_end TIMESTAMP(6); + + SET v_time_end := CURRENT_TIMESTAMP(6); + SELECT + a_time_start + , UNIX_TIMESTAMP(a_time_start) + , MICROSECOND(a_time_start) / 1000 + , v_time_end + , UNIX_TIMESTAMP(v_time_end) + , MICROSECOND(v_time_end) / 1000 + , v_time_end - a_time_start AS timestamp_delta + , UNIX_TIMESTAMP(v_time_end - a_time_start) AS UNIX_TIMESTAMP_timestamp_delta + , MICROSECOND(v_time_end - a_time_start) AS MICROSECOND_timestamp_delta + -- , TIME_FORMAT(TIMEDIFF(v_time_end, a_time_start), '%H:%i:%s') AS time_difference + , CONCAT( + TIME_FORMAT(TIMEDIFF(v_time_end, a_time_start), '%H hours, %i minutes, %s seconds'), + ', ', + TIMESTAMPDIFF(MICROSECOND, a_time_start, v_time_end) % 1000000 / 1000, ' milliseconds' + ) AS time_difference + ; + +END // +DELIMITER ; + +/* +CALL parts.p_core_debug_timing_reporting ( + CURRENT_TIMESTAMP(6) +); +*/ +USE parts; + +DROP PROCEDURE IF EXISTS parts.p_core_split; + +DELIMITER // +CREATE PROCEDURE parts.p_core_split ( + IN a_guid BINARY(36) + , IN a_string LONGTEXT + , IN a_separator VARCHAR(1000) + -- IN a_allow_empty BIT + , IN a_debug BIT +) +BEGIN + DECLARE v_has_string BIT; + DECLARE v_has_separator BIT; + DECLARE v_i_separator INT; + DECLARE v_i_start INT; + DECLARE v_i_end INT; + DECLARE v_current_item VARCHAR(4000); + DECLARE v_time_start TIMESTAMP(6); + + SET v_time_start := CURRENT_TIMESTAMP(6); + SET a_string := IFNULL(a_string, ''); + SET a_separator := IFNULL(a_separator, ''); + SET a_debug := IFNULL(a_debug, 0); + + IF a_debug = 1 THEN + SELECT + a_guid + , a_string + , a_separator + , a_debug + ; + END IF; + + CALL parts.p_core_validate_guid ( a_guid ); + + DROP TABLE IF EXISTS tmp_Split_Split; + + CREATE TEMPORARY TABLE tmp_Split_Split ( + display_order INT NOT NULL PRIMARY KEY AUTO_INCREMENT, + substring VARCHAR(4000) NOT NULL + ); + + SET v_has_string = CASE WHEN a_string = '' THEN 0 ELSE 1 END; + SET v_has_separator = CASE WHEN a_separator = '' THEN 0 ELSE 1 END; + + IF v_has_string THEN + + SET v_i_start = 1; + SET v_i_end = LOCATE(',', a_string); + + WHILE v_i_end > 0 DO + SET v_current_item = SUBSTRING(a_string, v_i_start, v_i_end - v_i_start); + INSERT INTO tmp_Split_Split (substring) VALUES (v_current_item); + + SET v_i_start = v_i_end + 1; + SET v_i_end = LOCATE(',', a_string, v_i_start); + END WHILE; + + SET v_current_item = SUBSTRING(a_string, v_i_start); + INSERT INTO tmp_Split_Split (substring) VALUES (TRIM(v_current_item)); + END IF; + + IF EXISTS (SELECT * FROM tmp_Split_Split LIMIT 1) THEN + START TRANSACTION; + INSERT INTO parts.CORE_Split_Temp ( + guid + , display_order + , substring + ) + SELECT + a_guid + , display_order + , substring + FROM tmp_Split_Split + ; + COMMIT; + END IF; + + DROP TABLE IF EXISTS tmp_Split_Split; + + IF a_debug = 1 THEN + CALL parts.p_core_debug_timing_reporting ( v_time_start ); + END IF; +END // +DELIMITER ; + + +/* +CALL parts.p_core_split ( + 'nips' + , 'noods, cheese ' -- a_string + , ',' -- a_separator + -- '0', -- a_allow_empty + , 1 +); + +SELECT * +FROM parts.CORE_Split_Temp +WHERE GUID = 'nips'; + +CALL parts.p_core_clear_split_temp( 'nips' ); +*/ + +USE parts; + +DROP PROCEDURE IF EXISTS parts.p_core_clear_split; + + +DELIMITER // +CREATE PROCEDURE parts.p_core_clear_split ( + IN a_guid BINARY(36) +) +BEGIN + CALL parts.p_core_validate_guid( a_guid ); + + START TRANSACTION; + + -- DROP TABLE IF EXISTS + DELETE FROM parts.CORE_Split_Temp + WHERE GUID = a_guid + ; + + COMMIT; +END // +DELIMITER ; + +/* + +CALL parts.p_core_clear_split ( 'nips' ); + + +*/ + +USE parts; + +DROP PROCEDURE IF EXISTS parts.p_core_split_key_value_pair_csv; + +DELIMITER // +CREATE PROCEDURE parts.p_core_split_key_value_pair_csv ( + IN a_guid BINARY(36) + , IN a_string LONGTEXT + , IN a_debug BIT +) +BEGIN + DECLARE v_has_string BIT; + DECLARE v_current_item VARCHAR(4000); + DECLARE v_time_start TIMESTAMP(6); + + SET v_time_start := CURRENT_TIMESTAMP(6); + SET a_string := IFNULL(a_string, ''); + SET a_debug := IFNULL(a_debug, 0); + + SET v_has_string = CASE WHEN a_string = '' THEN 0 ELSE 1 END; + + IF a_debug = 1 THEN + SELECT + a_guid + , a_string + , a_debug + ; + END IF; + + CALL parts.p_core_validate_guid ( a_guid ); + + DROP TABLE IF EXISTS tmp_Input_Split_Key_Value_Pair_Csv; + DROP TABLE IF EXISTS tmp_Split_Split_Key_Value_Pair_Csv; + + CREATE TEMPORARY TABLE tmp_Input_Split_Key_Value_Pair_Csv ( + input_string TEXT + ); + + CREATE TEMPORARY TABLE tmp_Split_Split_Key_Value_Pair_Csv ( + id INT AUTO_INCREMENT PRIMARY KEY + , key_column VARCHAR(4000) + , value_column VARCHAR(4000) + ); + + INSERT INTO tmp_Input_Split_Key_Value_Pair_Csv ( + input_string + ) + VALUES ( + a_string + ); + + INSERT INTO tmp_Split_Split_Key_Value_Pair_Csv (key_column, value_column) + SELECT + SUBSTRING_INDEX(SUBSTRING_INDEX(t.pair, ':', 1), ',', -1) AS key_column, + SUBSTRING_INDEX(t.pair, ':', -1) AS value_column + FROM ( + SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(input_string, ',', n), ',', -1) pair + FROM temp_input + CROSS JOIN ( + SELECT a.N + b.N * 10 + 1 n + FROM (SELECT 0 AS N UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) a + CROSS JOIN (SELECT 0 AS N UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) b + ORDER BY n + ) numbers + WHERE n <= 1 + (LENGTH(input_string) - LENGTH(REPLACE(input_string, ',', ''))) + ) t; + + IF EXISTS (SELECT * FROM tmp_Split_Split_Key_Value_Pair_Csv LIMIT 1) THEN + START TRANSACTION; + INSERT INTO parts.CORE_Split_Key_Value_Pair_Csv_Temp ( + guid + , id + , key_column + , value_column + ) + SELECT + a_guid + , id + , key_column + , value_column + FROM tmp_Split_Split_Key_Value_Pair_Csv + ; + COMMIT; + END IF; + + DROP TEMPORARY TABLE IF EXISTS tmp_Input_Split_Key_Value_Pair_Csv; + DROP TEMPORARY TABLE IF EXISTS tmp_Split_Split_Key_Value_Pair_Csv; + + IF a_debug = 1 THEN + CALL parts.p_core_debug_timing_reporting ( v_time_start ); + END IF; +END // +DELIMITER ; + + +/* +CALL parts.p_core_split_key_value_pair_csv ( + 'nipsnipsnipsnipsnipsnipsnipsnipsnips' + , '1:100,2:200,3:300,4:400' -- a_string + , 1 +); + +SELECT * +FROM parts.CORE_Split_key_value_pair_csv_Temp +WHERE GUID = 'nipsnipsnipsnipsnipsnipsnipsnipsnips'; + +CALL parts.p_core_clear_split_key_value_pair_csv_temp( 'nipsnipsnipsnipsnipsnipsnipsnipsnips' ); +*/ + +USE parts; + +DROP PROCEDURE IF EXISTS parts.p_core_clear_split_key_value_pair_csv; + + +DELIMITER // +CREATE PROCEDURE parts.p_core_clear_split_key_value_pair_csv ( + IN a_guid BINARY(36) +) +BEGIN + CALL parts.p_core_validate_guid( a_guid ); + + START TRANSACTION; + + -- DROP TABLE IF EXISTS + DELETE FROM parts.CORE_Split_Key_Value_Pair_Csv_Temp + WHERE GUID = a_guid + ; + + COMMIT; +END // +DELIMITER ; + +/* + +CALL parts.p_core_clear_split_key_value_pair_csv ( 'nips' ); + + +*/ + +USE parts; + +DROP PROCEDURE IF EXISTS parts.p_DOG_user_eval; +DROP PROCEDURE IF EXISTS parts.p_DOG_calc_user; + +DELIMITER // +CREATE PROCEDURE parts.p_DOG_calc_user ( + IN a_guid BINARY(36) + , IN a_ids_user TEXT + , IN a_get_inactive_user BIT + , IN a_ids_permission VARCHAR(4000) + , IN a_debug BIT +) +BEGIN + DECLARE v_has_filter_permission BIT; + DECLARE v_has_filter_user BIT; + DECLARE v_id_permission INT; + DECLARE v_time_start TIMESTAMP(6); + DECLARE v_ids_row_delete VARCHAR(500); + DECLARE v_code_type_error_bad_data VARCHAR(200); + DECLARE v_id_type_error_bad_data INT; + DECLARE v_code_error_permission VARCHAR(200); + DECLARE v_id_permission_required INT; + DECLARE v_priority_access_level_required INT; + DECLARE v_priority_access_level_view INT; + + SET v_time_start := CURRENT_TIMESTAMP(6); + SET v_code_type_error_bad_data := (SELECT code FROM parts.CORE_Msg_Error_Type WHERE code = 'BAD_DATA'); + SET v_id_type_error_bad_data := (SELECT id_type FROM parts.CORE_Msg_Error_Type WHERE code = v_code_type_error_bad_data); + SET v_code_error_permission := (SELECT code FROM parts.CORE_Msg_Error_Type WHERE id_type = 2); + SET v_priority_access_level_view := (SELECT priority FROM parts.DOG_Access_Level WHERE code = 'VIEW' LIMIT 1); + + CALL parts.p_core_validate_guid ( a_guid ); + SET a_ids_user := TRIM(IFNULL(a_ids_user, '')); + SET a_get_inactive_user := IFNULL(a_get_inactive_user, 0); + SET a_ids_permission := TRIM(IFNULL(a_ids_permission, '')); + SET a_debug := IFNULL(a_debug, 0); + + IF a_debug = 1 THEN + SELECT + a_guid + , a_ids_user + , a_get_inactive_user + , a_ids_permission + , a_debug + ; + END IF; + + DROP TABLE IF EXISTS tmp_Calc_User; + DROP TABLE IF EXISTS tmp_User_Calc_User; + DROP TABLE IF EXISTS tmp_Split_Calc_User; + + CREATE TEMPORARY TABLE tmp_Calc_User ( + id_row INT PRIMARY KEY AUTO_INCREMENT NOT NULL + , id_user INT NULL + , id_permission_required INT NOT NULL + , priority_access_level_required INT NOT NULL + , is_super_user BIT NULL + , priority_access_level_user INT NULL + , has_access BIT + ); + + CREATE TEMPORARY TABLE tmp_User_Calc_User ( + id_user INT NOT NULL + , is_super_user BIT NOT NULL + -- , id_access_level INT + , priority_access_level INT NOT NULL + ); + + CREATE TEMPORARY TABLE IF NOT EXISTS tmp_Msg_Error_Calc_User ( + display_order INT NOT NULL PRIMARY KEY AUTO_INCREMENT + , id_type INT NULL + , code VARCHAR(100) NOT NULL + , msg VARCHAR(4000) NOT NULL + ); + + CREATE TEMPORARY TABLE IF NOT EXISTS tmp_Split_Calc_User ( + substring VARCHAR(4000) NOT NULL + , as_int INT NULL + ); + DELETE FROM tmp_Split_Calc_User; + + SET v_has_filter_user = CASE WHEN a_ids_user = '' THEN 0 ELSE 1 END; + SET a_ids_permission = REPLACE(a_ids_permission, '|', ','); + SET v_has_filter_permission = CASE WHEN a_ids_permission = '' THEN 0 ELSE 1 END; + -- SET v_id_access_level_view = (SELECT id_access_level FROM parts.DOG_Access_Level WHERE code = 'VIEW' LIMIT 1); + + + -- Permission IDs + IF NOT v_has_filter_permission THEN + INSERT INTO tmp_Msg_Error_Calc_User ( + id_type + , code + , msg + ) + SELECT + v_id_type_error_bad_data + , v_code_type_error_bad_data + , 'Permission ID required.' + ; + ELSE + CALL parts.p_core_split(a_guid, a_ids_permission, ',', a_debug); + + INSERT INTO tmp_Split_Calc_User ( + substring + , as_int + ) + SELECT + substring + , CONVERT(substring, DECIMAL(10,0)) AS as_int + FROM parts.CORE_Split_Temp + WHERE + GUID = a_guid + AND NOT ISNULL(substring) + AND substring != '' + ; + + CALL parts.p_core_clear_split( a_guid ); + + -- Invalid or inactive + IF EXISTS ( + SELECT PERM.id_permission + FROM tmp_Split_Calc_User t_S + LEFT JOIN parts.DOG_Permission PERM ON t_S.as_int = PERM.id_permission + WHERE + ISNULL(t_S.as_int) + OR ISNULL(PERM.id_permission) + OR PERM.active = 0 + ) THEN + INSERT INTO tmp_Msg_Error_Calc_User ( + id_type + , code + , msg + ) + SELECT + v_id_type_error_bad_data + , v_code_type_error_bad_data + , CONCAT('Invalid or inactive permission IDs: ', IFNULL(GROUP_CONCAT(t_S.substring SEPARATOR ', '), 'NULL')) + FROM tmp_Split_Calc_User t_S + LEFT JOIN parts.DOG_Permission PERM ON t_S.as_int = PERM.id_permission + WHERE + ISNULL(t_S.as_int) + OR ISNULL(PERM.id_permission) + OR PERM.active = 0 + ; + ELSE + SELECT + PERM.id_permission + , PERM.id_access_level_required + INTO + v_id_permission_required + , v_priority_access_level_required + FROM tmp_Split_Calc_User t_S + LEFT JOIN parts.DOG_Permission PERM ON t_S.as_int = PERM.id_permission + INNER JOIN parts.DOG_Access_Level AL ON PERM.id_access_level_required = AL.id_access_level + ORDER BY AL.priority ASC + LIMIT 1 + ; + + IF ISNULL(v_id_permission_required) THEN + INSERT INTO tmp_Msg_Error_Calc_User ( + id_type + , code + , msg + ) + SELECT + v_id_type_error_bad_data + , v_code_type_error_bad_data + , 'Valid Permission ID required.' + ; + END IF; + END IF; + END IF; + DELETE FROM tmp_Split_Calc_User; + + -- Users + CALL parts.p_core_split(a_guid, a_ids_user, ',', a_debug); + + INSERT INTO tmp_Split_Calc_User ( + substring + , as_int + ) + SELECT + substring + , CONVERT(substring, DECIMAL(10,0)) AS as_int + FROM parts.CORE_Split_Temp + WHERE + GUID = a_guid + AND NOT ISNULL(substring) + AND substring != '' + ; + + CALL parts.p_core_clear_split( a_guid ); + + -- Invalid or inactive + IF EXISTS (SELECT U.id_user FROM tmp_Split_Calc_User t_S LEFT JOIN parts.DOG_User U ON t_S.as_int = U.id_user WHERE ISNULL(t_S.as_int) OR ISNULL(U.id_user) OR (a_get_inactive_user = 0 AND U.active = 0)) THEN + INSERT INTO tmp_Msg_Error_Calc_User ( + id_type + , code + , msg + ) + SELECT + v_id_type_error_bad_data + , v_code_type_error_bad_data + , CONCAT('Invalid or inactive user IDs: ', IFNULL(GROUP_CONCAT(t_S.substring SEPARATOR ', '), 'NULL')) + FROM tmp_Split_Calc_User t_S + LEFT JOIN parts.DOG_User U ON t_S.as_int = U.id_user + WHERE + ISNULL(t_S.as_int) + OR ISNULL(U.id_user) + OR ( + a_get_inactive_user = 0 + AND U.active = 0 + ) + ; + ELSE + IF NOT EXISTS (SELECT * FROM tmp_Split_Calc_User) THEN + INSERT INTO tmp_Split_Calc_User (substring, as_int) + VALUES ( '', NULL ); + END IF; + + IF a_debug = 1 THEN + SELECT * + FROM tmp_Split_Calc_User; + END IF; + + INSERT INTO tmp_User_Calc_User ( + id_user + , is_super_user + , priority_access_level + ) + SELECT + U.id_user + , IFNULL(U.is_super_user, 0) AS is_super_user + , IFNULL(MIN(AL_U.priority), v_priority_access_level_view) AS priority_access_level + FROM tmp_Split_Calc_User t_S + INNER JOIN parts.DOG_User U ON t_S.as_int = U.id_user + LEFT JOIN parts.DOG_User_Role_Link URL + ON U.id_user = URL.id_user + AND URL.active + LEFT JOIN parts.DOG_Role_Permission_Link RPL + ON URL.id_role = RPL.id_role + AND RPL.active + LEFT JOIN parts.DOG_Access_Level AL_U + ON RPL.id_access_level = AL_U.id_access_level + AND AL_U.active + GROUP BY U.id_user + ; + + INSERT INTO tmp_Calc_User ( + id_user + , id_permission_required + , priority_access_level_required + , priority_access_level_user + , is_super_user + ) + SELECT + t_UCU.id_user + , v_id_permission_required + , v_priority_access_level_required + , t_UCU.priority_access_level AS priority_access_level_user + , t_UCU.is_super_user AS is_super_user + FROM tmp_User_Calc_User t_UCU + ; + END IF; + DELETE FROM tmp_Split_Calc_User; + + + -- Calculated fields + UPDATE tmp_Calc_User t_CU + SET + t_CU.has_access = ( + (t_CU.is_super_user = 1) + OR (t_CU.priority_access_level_user <= t_CU.priority_access_level_required) + ) + ; + + -- Export data to staging table + IF NOT EXISTS (SELECT * FROM tmp_Msg_Error_Calc_User) THEN + START TRANSACTION; + INSERT INTO parts.DOG_Calc_User_Temp ( + guid + , id_user + , id_permission_required + , priority_access_level_required + , priority_access_level_user + , is_super_user + , has_access + ) + SELECT + a_guid + , t_CU.id_user + , t_CU.id_permission_required + , t_CU.priority_access_level_required + , t_CU.priority_access_level_user + , t_CU.is_super_user + , t_CU.has_access + FROM tmp_Calc_User t_CU + ; + COMMIT; + END IF; + + IF a_debug = 1 THEN + SELECT * FROM tmp_Msg_Error_Calc_User; + SELECT * FROM tmp_Calc_User; + SELECT * FROM tmp_User_Calc_User; + SELECT * FROM parts.DOG_Calc_User_Temp WHERE GUID = a_guid; + CALL parts.p_DOG_clear_calc_user ( a_guid, a_debug ); + END IF; + + -- Clean up + DROP TABLE IF EXISTS tmp_Calc_User; + DROP TABLE IF EXISTS tmp_User_Calc_User; + DELETE FROM tmp_Split_Calc_User; + + IF a_debug = 1 THEN + CALL parts.p_debug_timing_reporting( v_time_start ); + END IF; +END // +DELIMITER ; + +/* + +CALL parts.p_DOG_calc_user ( + 'chips ' -- a_guid + , 1 -- a_ids_user + , 0 -- a_get_inactive_user + , '2' -- a_ids_permission + , '1' -- a_ids_access_level + , 0 -- a_debug +); +CALL parts.p_DOG_calc_user ( + 'chips ' -- a_guid + , 1 -- a_ids_user + , 0 -- a_get_inactive_user + , '2' -- a_ids_permission + , '1' -- a_ids_access_level + , 0 -- a_debug +); +*/ +USE parts; + +DROP PROCEDURE IF EXISTS parts.p_DOG_clear_calc_user; + +DELIMITER // +CREATE PROCEDURE parts.p_DOG_clear_calc_user ( + IN a_guid BINARY(36) + , IN a_debug BIT +) +BEGIN + DECLARE v_time_start TIMESTAMP(6); + SET v_time_start := CURRENT_TIMESTAMP(6); + + CALL parts.p_core_validate_guid ( a_guid ); + + START TRANSACTION; + + DELETE FROM parts.DOG_Calc_User_Temp + WHERE GUID = a_guid + ; + + COMMIT; + + IF a_debug = 1 THEN + CALL parts.p_debug_timing_reporting( v_time_start ); + END IF; +END // +DELIMITER ; + +/* + +CALL parts.p_DOG_clear_calc_user ( + 'chips ' -- a_guid + , 1 -- debug +); + +SELECT * +FROM parts.DOG_Calc_User_Temp +WHERE GUID = 'chips ' +; + +*/ + +USE parts; + +DROP PROCEDURE IF EXISTS parts.p_DOG_save_command; + +DELIMITER // +CREATE PROCEDURE parts.p_DOG_save_command ( + IN a_comment VARCHAR(500), + IN a_guid BINARY(36), + IN a_id_user INT, + IN a_debug BIT +) +BEGIN + DECLARE v_code_type_error_bad_data VARCHAR(100); + DECLARE v_id_type_error_bad_data INT; + DECLARE v_id_permission_dog_admin INT; + DECLARE v_id_permission_dog_new INT; + DECLARE v_id_change_set INT; + DECLARE v_time_start TIMESTAMP(6); + DECLARE v_can_admin BIT; + DECLARE v_can_create BIT; + + DECLARE exit handler for SQLEXCEPTION + BEGIN + GET DIAGNOSTICS CONDITION 1 + @sqlstate = RETURNED_SQLSTATE + , @errno = MYSQL_ERRNO + , @text = MESSAGE_TEXT + ; + + ROLLBACK; + + CREATE TEMPORARY TABLE IF NOT EXISTS tmp_Msg_Error ( + id_error INT NOT NULL PRIMARY KEY AUTO_INCREMENT + , id_type INT NULL + , code VARCHAR(100) + , msg VARCHAR(4000) NOT NULL + ); + + INSERT INTO tmp_Msg_Error ( + id_type + , code + , msg + ) + SELECT + MET.id_type + , @errno + , @text + FROM parts.CORE_Msg_Error_Type MET + WHERE MET.code = 'MYSQL_ERROR' + ; + + SELECT + t_ERROR.id_error + , t_ERROR.id_type + , t_ERROR.code + , ERROR_TYPE.name + , ERROR_TYPE.description + , ERROR_TYPE.is_breaking_error + , ERROR_TYPE.background_colour + , ERROR_TYPE.text_colour + , t_ERROR.msg + FROM tmp_Msg_Error t_ERROR + INNER JOIN parts.CORE_Msg_Error_Type ERROR_TYPE ON t_ERROR.id_type = ERROR_TYPE.id_type + ; + + DROP TABLE IF EXISTS tmp_Msg_Error; + END; + + SET v_time_start := CURRENT_TIMESTAMP(6); + SET v_code_type_error_bad_data := 'BAD_DATA'; + SET v_id_type_error_bad_data := (SELECT ERROR_TYPE.id_type FROM parts.CORE_Msg_Error_Type ERROR_TYPE WHERE ERROR_TYPE.code = v_code_type_error_bad_data LIMIT 1); + SET v_id_permission_dog_admin := (SELECT PERMISSION.id_permission FROM parts.DOG_Permission PERMISSION WHERE PERMISSION.code = 'DOG_ADMIN' LIMIT 1); + SET v_id_permission_dog_new := (SELECT PERMISSION.id_permission FROM parts.DOG_Permission PERMISSION WHERE PERMISSION.code = 'DOG_CREATE' LIMIT 1); + + CALL parts.p_core_validate_guid ( a_guid ); + + DROP TABLE IF EXISTS tmp_Command; + + CREATE TEMPORARY TABLE tmp_Command ( + id_command INT + , id_command_category INT + , name VARCHAR(250) + , hand_signal_default_description TEXT + , can_have_button BIT + , notes TEXT + , active BIT + , is_new BIT + , name_error VARCHAR(250) + + , name_command_category VARCHAR(250) + ); + + CREATE TEMPORARY TABLE IF NOT EXISTS tmp_Msg_Error ( + id_error INT NOT NULL PRIMARY KEY AUTO_INCREMENT + , id_type INT NULL + , code VARCHAR(100) + , msg VARCHAR(4000) NOT NULL + ); + + + -- Get data from Temp table + INSERT INTO tmp_Command ( + id_command + , id_command_category + , name + , hand_signal_default_description + , can_have_button + , notes + , active + , is_new + + , name_command_category + ) + SELECT + COMMAND_T.id_command AS id_command + , COMMAND_T.id_command_category AS id_command_category + , COALESCE(COMMAND_T.name, COMMAND.name) AS name + , COALESCE(COMMAND_T.hand_signal_default_description, COMMAND.hand_signal_default_description) AS hand_signal_default_description + , COALESCE(COMMAND_T.can_have_button, COMMAND.can_have_button) AS can_have_button + , COALESCE(COMMAND_T.notes, COMMAND.notes) AS notes + , COALESCE(COMMAND_T.active, COMMAND.active, 1) AS active + , CASE WHEN IFNULL(COMMAND_T.id_command, 0) < 1 THEN 1 ELSE 0 END AS is_new + + , COMMAND_T.name_command_category AS name_command_category + FROM parts.DOG_Command_Temp COMMAND_T + LEFT JOIN parts.DOG_Command COMMAND ON COMMAND_T.id_command = COMMAND.id_command + WHERE COMMAND_T.guid = a_guid + ; + + UPDATE tmp_Command t_COMMAND + SET name_error = COALESCE(t_COMMAND.name, t_COMMAND.notes, t_COMMAND.name_command_category, '(No Command)') + ; + + -- Find missing id_command_category by name_command_category + UPDATE tmp_Command t_COMMAND + INNER JOIN parts.DOG_Command_Category COMMAND_CATEGORY ON t_COMMAND.name_command_category = COMMAND_CATEGORY.name + SET t_COMMAND.id_command_category = COMMAND_CATEGORY.id_command_category + WHERE t_COMMAND.id_command_category IS NULL + ; + + IF EXISTS ( + SELECT * + FROM tmp_Command t_COMMAND + WHERE ISNULL(t_COMMAND.id_command_category) + LIMIT 1 + ) THEN + INSERT INTO tmp_Msg_Error ( + id_type + , code + , msg + ) + SELECT + v_id_type_error_bad_data + , v_code_type_error_bad_data + , CONCAT('The following Command(s) do not have a Category: ', GROUP_CONCAT(t_COMMAND.name_error SEPARATOR ', ')) AS msg + FROM tmp_Command t_COMMAND + WHERE t_COMMAND.id_command_category IS NULL + ; + END IF; + + -- Validation + -- Missing mandatory fields + -- id_command_category + IF EXISTS (SELECT * FROM tmp_Command t_COMMAND WHERE ISNULL(t_COMMAND.id_command_category) LIMIT 1) THEN + INSERT INTO tmp_Msg_Error ( + id_type + , code + , msg + ) + SELECT + v_id_type_error_bad_data + , v_code_type_error_bad_data + , CONCAT('The following Command(s) do not have a Category: ', GROUP_CONCAT(t_COMMAND.name_error SEPARATOR ', ')) AS msg + FROM tmp_Command t_COMMAND + WHERE ISNULL(t_COMMAND.id_command_category) + ; + END IF; + -- name + IF EXISTS (SELECT * FROM tmp_Command t_COMMAND WHERE ISNULL(t_COMMAND.name) LIMIT 1) THEN + INSERT INTO tmp_Msg_Error ( + id_type + , code + , msg + ) + SELECT + v_id_type_error_bad_data + , v_code_type_error_bad_data + , CONCAT('The following Command(s) do not have a Name: ', GROUP_CONCAT(t_COMMAND.name_error SEPARATOR ', ')) AS msg + FROM tmp_Command t_COMMAND + WHERE ISNULL(t_COMMAND.name) + ; + END IF; + -- can_have_button + IF EXISTS (SELECT * FROM tmp_Command t_COMMAND WHERE ISNULL(t_COMMAND.can_have_button) LIMIT 1) THEN + INSERT INTO tmp_Msg_Error ( + id_type + , code + , msg + ) + SELECT + v_id_type_error_bad_data + , v_code_type_error_bad_data + , CONCAT('The following Command(s) do not have a Can-Have-Button: ', GROUP_CONCAT(t_COMMAND.name_error SEPARATOR ', ')) AS msg + FROM tmp_Command t_COMMAND + WHERE ISNULL(t_COMMAND.can_have_button) + ; + END IF; + + -- Permissions + IF a_debug = 1 THEN + SELECT + a_guid + , a_id_user + , FALSE -- a_get_inactive_user + , v_id_permission_dog_admin + , v_id_permission_dog_new + , 0 -- a_debug + ; + END IF; + + CALL parts.p_DOG_calc_user( + a_guid + , a_id_user + , FALSE -- a_get_inactive_user + , v_id_permission_dog_admin + , 0 -- a_debug + ); + + SELECT + IFNULL(CU_T.has_access, 0) + INTO + v_can_admin + FROM parts.DOG_Calc_User_Temp CU_T + WHERE CU_T.GUID = a_guid + LIMIT 1 + ; + + CALL parts.p_DOG_clear_calc_user( + a_guid + , 0 -- a_debug + ); + + CALL parts.p_DOG_calc_user( + a_guid + , a_id_user + , FALSE -- a_get_inactive_user + , v_id_permission_dog_new + , 0 -- a_debug + ); + + SELECT + IFNULL(CU_T.has_access, 0) + INTO + v_can_create + FROM parts.DOG_Calc_User_Temp CU_T + WHERE CU_T.GUID = a_guid + LIMIT 1 + ; + + CALL parts.p_DOG_clear_calc_user( + a_guid + , 0 -- a_debug + ); + + IF (v_can_create = 0 AND EXISTS(SELECT * FROM tmp_Command WHERE is_new = 1)) THEN + DELETE t_ME + FROM tmp_Msg_Error t_ME + WHERE t_ME.id_type <> v_id_type_error_no_permission + ; + INSERT INTO tmp_Msg_Error ( + id_type + , code + , msg + ) + VALUES ( + v_id_type_error_no_permission + , v_code_type_error_no_permission + , 'You do not have permission to create new Commands.' + ) + ; + END IF; + + IF (v_can_admin = 0 AND EXISTS(SELECT * FROM tmp_Command WHERE is_new = 0)) THEN + DELETE t_ME + FROM tmp_Msg_Error t_ME + WHERE t_ME.id_type <> v_id_type_error_no_permission + ; + INSERT INTO tmp_Msg_Error ( + id_type + , code + , msg + ) + VALUES ( + v_id_type_error_no_permission + , v_code_type_error_no_permission + , 'You do not have permission to admin Commands.' + ) + ; + END IF; + + IF EXISTS (SELECT * FROM tmp_Msg_Error t_ERROR INNER JOIN parts.CORE_Msg_Error_Type ERROR_TYPE ON t_ERROR.id_type = ERROR_TYPE.id_type WHERE ERROR_TYPE.is_breaking_error = 1 LIMIT 1) THEN + IF a_debug = 1 THEN + SELECT * from tmp_Command; + END IF; + + DELETE FROM tmp_Command; + END IF; + + IF NOT EXISTS (SELECT * FROM tmp_Msg_Error t_ERROR INNER JOIN parts.CORE_Msg_Error_Type ERROR_TYPE ON t_ERROR.id_type = ERROR_TYPE.id_type WHERE ERROR_TYPE.is_breaking_error = 1 LIMIT 1) THEN + START TRANSACTION; + + INSERT INTO parts.DOG_Dog_Change_Set ( + comment + , id_user_updated_last_by + , updated_last_on + ) + VALUES ( + a_comment + , a_id_user + , v_time_start + ) + ; + + SET v_id_change_set := LAST_INSERT_ID(); + + UPDATE parts.DOG_Command COMMAND + INNER JOIN tmp_Command t_COMMAND + ON COMMAND.id_command = t_COMMAND.id_command + AND t_COMMAND.is_new = 0 + SET + COMMAND.id_command_category = t_COMMAND.id_command_category + , COMMAND.name = t_COMMAND.name + , COMMAND.hand_signal_default_description = t_COMMAND.hand_signal_default_description + , COMMAND.can_have_button = t_COMMAND.can_have_button + , COMMAND.notes = t_COMMAND.notes + , COMMAND.active = t_COMMAND.active + , COMMAND.id_change_set = v_id_change_set + ; + + INSERT INTO parts.DOG_Command ( + id_command_category + , name + , hand_signal_default_description + , can_have_button + , notes + , active + , id_user_created_by + , created_on + ) + SELECT + t_COMMAND.id_command_category AS id_command_category + , t_COMMAND.name AS name + , t_COMMAND.hand_signal_default_description AS hand_signal_default_description + , t_COMMAND.can_have_button AS can_have_button + , t_COMMAND.notes AS notes + , t_COMMAND.active AS active + , a_id_user AS created_by + , v_time_start AS created_on + FROM tmp_Command t_COMMAND + WHERE + t_COMMAND.is_new = 1 + AND t_COMMAND.active = 1 + ; + + COMMIT; + END IF; + + START TRANSACTION; + + DELETE FROM parts.DOG_Command_Temp + WHERE GUID = a_guid + ; + + COMMIT; + + -- Errors + SELECT + t_ERROR.id_error + , t_ERROR.id_type + , t_ERROR.code + , ERROR_TYPE.name + , ERROR_TYPE.description + , ERROR_TYPE.is_breaking_error + , ERROR_TYPE.background_colour + , ERROR_TYPE.text_colour + , t_ERROR.msg + FROM tmp_Msg_Error t_ERROR + INNER JOIN parts.CORE_Msg_Error_Type ERROR_TYPE ON t_ERROR.id_type = ERROR_TYPE.id_type + ; + + IF a_debug = 1 THEN + SELECT * from tmp_Command; + END IF; + + DROP TEMPORARY TABLE tmp_Command; + DROP TEMPORARY TABLE tmp_Msg_Error; + + IF a_debug = 1 THEN + CALL parts.p_core_debug_timing_reporting ( v_time_start ); + END IF; +END // +DELIMITER ; + + + +/* + + +select + * + -- COUNT(*) +-- delete +from parts.DOG_Command_Temp +; +select COUNT(*) +from parts.DOG_Command_Temp +; +select + * + -- COUNT(*) +-- delete +from parts.DOG_Command +; +select COUNT(*) +from parts.DOG_Command +; + + +CALL parts.p_DOG_save_command ( + 'nipples' + , (SELECT GUID FROM parts.DOG_Command_Temp COMMAND_TEMP ORDER BY id_temp DESC LIMIT 1) + , 1 + , 1 +); + + +select + * + -- COUNT(*) +-- delete +from parts.DOG_Command_Temp +; +select COUNT(*) +from parts.DOG_Command_Temp +; +select + * + -- COUNT(*) +-- delete +from parts.DOG_Command +; +select COUNT(*) +from parts.DOG_Command +; + +*/ +USE parts; + +DROP PROCEDURE IF EXISTS parts.p_DOG_test_save_command; + + +DELIMITER // +CREATE PROCEDURE parts.p_DOG_test_save_command () +BEGIN + + DECLARE v_guid BINARY(36); + DECLARE v_time_start TIMESTAMP(6); + + SET v_time_start := CURRENT_TIMESTAMP(6); + SET v_guid := 'nipple_ripple_chipple_spittle_pickle'; -- 123456789012345678901234567890123456 + + SELECT 'Start of Test'; + + SELECT * + FROM parts.DOG_Command + ; + SELECT * + FROM parts.DOG_Command_Temp + ; + + START TRANSACTION; + + INSERT INTO parts.DOG_Command_Temp ( + id_command + , email + , name_contact + , name_company + , message + , guid + , active + ) + /* + VALUES ( + -1 -- id_command + , 'edward.middletonsmith@gmail.com' -- email + , 'Teddy' -- name_contact + , 'PARTS Ltd' -- name_company + , 'Sa dude' -- message + , v_guid + ) + */ + VALUES ( + -1 -- id_command + , 'edward.middletonsmith@gmail.com' -- email + , 'Teddy' -- name_contact + , 'PARTS Ltd' -- name_company + , 'hegrodorf is good' -- message + , v_guid + , 1 -- active + ) + ; + + COMMIT; + + SELECT * + FROM parts.DOG_Command_Temp + -- WHERE GUID = v_guid + ; + + CALL parts.p_DOG_save_command ( + 'Test save Command' -- comment + , v_guid -- guid + , 3 -- 1 -- id_user + , 1 -- debug + ); + + SELECT * + FROM parts.DOG_Command + ; + SELECT * + FROM parts.DOG_Command_Temp + ; + + CALL parts.p_debug_timing_reporting ( v_time_start ); +END // +DELIMITER ; + + +/* +SELECT 'Before Test'; +SELECT * +FROM parts.DOG_Command +; +SELECT * +FROM parts.DOG_Command_Temp +; + + +CALL parts.p_DOG_test_save_command (); + +SELECT 'After Test'; +SELECT * +FROM parts.DOG_Command +; +SELECT * +FROM parts.DOG_Command_Temp +; + +DELETE FROM parts.DOG_Command_Temp; + +DROP TABLE IF EXISTS tmp_Msg_Error; + + +*/ + +USE parts; + +DROP PROCEDURE IF EXISTS parts.p_DOG_get_many_dog_command; + +DELIMITER // +CREATE PROCEDURE parts.p_DOG_get_many_dog_command ( + IN a_id_user INT + , IN a_get_all_dog BIT + , IN a_get_inactive_dog BIT + , IN a_ids_dog TEXT + , IN a_get_all_command BIT + , IN a_get_inactive_command BIT + , IN a_ids_command TEXT + , IN a_get_all_understanding_level BIT + , IN a_get_inactive_understanding_level BIT + , IN a_ids_understanding_level TEXT + , IN a_get_all_obedience_level BIT + , IN a_get_inactive_obedience_level BIT + , IN a_ids_obedience_level TEXT + , IN a_debug BIT +) +BEGIN + DECLARE v_code_type_error_bad_data VARCHAR(100); + DECLARE v_code_type_error_no_permission VARCHAR(100); + DECLARE v_id_type_error_bad_data INT; + DECLARE v_id_type_error_no_permission INT; + DECLARE v_has_filter_command BIT; + DECLARE v_has_filter_dog BIT; + DECLARE v_has_filter_obedience_level BIT; + DECLARE v_has_filter_understanding_level BIT; + DECLARE v_guid BINARY(36); + DECLARE v_id_permission_dog_view INT; + DECLARE v_id_minimum INT; + DECLARE v_time_start TIMESTAMP(6); + DECLARE v_can_view BIT; + + DECLARE exit handler for SQLEXCEPTION + BEGIN + GET DIAGNOSTICS CONDITION 1 + @sqlstate = RETURNED_SQLSTATE + , @errno = MYSQL_ERRNO + , @text = MESSAGE_TEXT + ; + + ROLLBACK; + + CREATE TEMPORARY TABLE IF NOT EXISTS tmp_Msg_Error ( + id_error INT NOT NULL PRIMARY KEY AUTO_INCREMENT + , id_type INT NULL + , code VARCHAR(100) NOT NULL + , msg VARCHAR(4000) NOT NULL + ); + + INSERT INTO tmp_Msg_Error ( + id_type + , code + , msg + ) + SELECT + MET.id_type + , @errno + , @text + FROM parts.CORE_Msg_Error_Type MET + WHERE MET.code = 'MYSQL_ERROR' + ; + + SELECT + t_ERROR.id_error + , t_ERROR.id_type + , t_ERROR.code + , ERROR_TYPE.name + , ERROR_TYPE.description + , ERROR_TYPE.is_breaking_error + , ERROR_TYPE.background_colour + , ERROR_TYPE.text_colour + , t_ERROR.msg + FROM tmp_Msg_Error t_ERROR + INNER JOIN parts.CORE_Msg_Error_Type ERROR_TYPE ON t_ERROR.id_type = ERROR_TYPE.id_type + ; + + DROP TABLE IF EXISTS tmp_Msg_Error; + END; + + SET v_time_start := CURRENT_TIMESTAMP(6); + SET v_guid := UUID(); + SET v_code_type_error_bad_data := 'BAD_DATA'; + SET v_code_type_error_no_permission := 'NO_PERMISSION'; + SET v_id_type_error_bad_data := (SELECT ERROR_TYPE.id_type FROM parts.CORE_Msg_Error_Type ERROR_TYPE WHERE ERROR_TYPE.code = v_code_type_error_bad_data LIMIT 1); + SET v_id_type_error_no_permission := (SELECT ERROR_TYPE.id_type FROM parts.CORE_Msg_Error_Type ERROR_TYPE WHERE ERROR_TYPE.code = v_code_type_error_no_permission LIMIT 1); + SET v_id_permission_dog_view := (SELECT PERMISSION.id_permission FROM parts.DOG_Permission PERMISSION WHERE PERMISSION.code = 'DOG_VIEW' LIMIT 1); + + SET a_id_user := IFNULL(a_id_user, 0); + SET a_get_all_dog := IFNULL(a_get_all_dog, 0); + SET a_get_inactive_dog := IFNULL(a_get_inactive_dog, 0); + SET a_ids_dog := TRIM(IFNULL(a_ids_dog, '')); + SET a_get_all_command := IFNULL(a_get_all_command, 0); + SET a_get_inactive_command := IFNULL(a_get_inactive_command, 0); + SET a_ids_command := TRIM(IFNULL(a_ids_command, '')); + SET a_get_all_understanding_level := IFNULL(a_get_all_understanding_level, 0); + SET a_get_inactive_understanding_level := IFNULL(a_get_inactive_understanding_level, 0); + SET a_ids_understanding_level := TRIM(IFNULL(a_ids_understanding_level, '')); + SET a_get_all_obedience_level := IFNULL(a_get_all_obedience_level, 0); + SET a_get_inactive_obedience_level := IFNULL(a_get_inactive_obedience_level, 0); + SET a_ids_obedience_level := TRIM(IFNULL(a_ids_obedience_level, '')); + SET a_debug := IFNULL(a_debug, 0); + + IF a_debug = 1 THEN + SELECT + a_id_user + , a_get_all_dog + , a_get_inactive_dog + , a_ids_dog + , a_get_all_command + , a_get_inactive_command + , a_ids_command + , a_get_all_understanding_level + , a_get_inactive_understanding_level + , a_ids_understanding_level + , a_get_all_obedience_level + , a_get_inactive_obedience_level + , a_ids_obedience_level + , a_debug + ; + + SELECT + v_id_type_error_bad_data + , v_id_type_error_no_permission + , v_guid + , v_id_permission_dog_view + , v_time_start + ; + END IF; + + DROP TEMPORARY TABLE IF EXISTS tmp_Split; + DROP TEMPORARY TABLE IF EXISTS tmp_Msg_Error; + DROP TEMPORARY TABLE IF EXISTS tmp_Obedience_Level; + DROP TEMPORARY TABLE IF EXISTS tmp_Understanding_Level; + DROP TEMPORARY TABLE IF EXISTS tmp_Command; + DROP TEMPORARY TABLE IF EXISTS tmp_Dog; + + CREATE TEMPORARY TABLE tmp_Dog ( + id_dog INT NOT NULL + , name VARCHAR(250) + ); + + CREATE TEMPORARY TABLE tmp_Command ( + id_command INT NOT NULL + -- , code VARCHAR(100) + , name VARCHAR(250) + ); + + CREATE TEMPORARY TABLE tmp_Understanding_Level ( + id_understanding_level INT NOT NULL + , code VARCHAR(100) + , name VARCHAR(250) + ); + + CREATE TEMPORARY TABLE tmp_Obedience_Level ( + id_obedience_level INT NOT NULL + , code VARCHAR(100) + , name VARCHAR(250) + ); + + CREATE TEMPORARY TABLE IF NOT EXISTS tmp_Msg_Error ( + id_error INT NOT NULL PRIMARY KEY AUTO_INCREMENT + , id_type INT NULL + , code VARCHAR(100) NOT NULL + , msg VARCHAR(4000) NOT NULL + ); + + CREATE TEMPORARY TABLE IF NOT EXISTS tmp_Split ( + substring VARCHAR(4000) NOT NULL + , as_int INT NULL + ); + DELETE FROM tmp_Split; + + CALL parts.p_core_validate_guid ( v_guid ); + + SET v_has_filter_dog = CASE WHEN a_ids_dog = '' THEN 0 ELSE 1 END; + SET v_has_filter_command = CASE WHEN a_ids_command = '' THEN 0 ELSE 1 END; + SET v_has_filter_understanding_level = CASE WHEN a_ids_understanding_level = '' THEN 0 ELSE 1 END; + SET v_has_filter_obedience_level = CASE WHEN a_ids_obedience_level = '' THEN 0 ELSE 1 END; + + -- Dogs + IF v_has_filter_dog = 1 THEN + CALL parts.p_split(v_guid, a_ids_dog, ',', a_debug); + + INSERT INTO tmp_Split ( + substring + , as_int + ) + SELECT + SPLIT_T.substring + , CONVERT(SPLIT_T.substring, DECIMAL(10,0)) AS as_int + FROM parts.CORE_Split_Temp SPLIT_T + WHERE + SPLIT_T.GUID = v_guid + AND IFNULL(SPLIT_T.substring, '') <> '' + ; + + CALL parts.p_clear_split_temp( v_guid ); + END IF; + + IF NOT EXISTS (SELECT * FROM tmp_Msg_Error t_ERROR INNER JOIN parts.CORE_Msg_Error_Type ERROR_TYPE ON t_ERROR.id_type = ERROR_TYPE.id_type WHERE ERROR_TYPE.is_breaking_error = 1 LIMIT 1) THEN + IF EXISTS ( + SELECT * + FROM tmp_Split t_SPLIT + LEFT JOIN parts.DOG_Dog DOG ON t_SPLIT.as_int = DOG.id_dog + WHERE + ISNULL(t_SPLIT.as_int) + OR ISNULL(DOG.id_dog) + OR ( + DOG.active = 0 + AND a_get_inactive_dog = 0 + ) + ) THEN + INSERT INTO tmp_Msg_Error ( + id_type + , code + , msg + ) + SELECT + v_id_type_error_bad_data + , v_code_type_error_bad_data + , CONCAT('Invalid or inactive Dog IDs: ', IFNULL(GROUP_CONCAT(t_SPLIT.substring SEPARATOR ', '), 'NULL')) + FROM tmp_Split t_SPLIT + LEFT JOIN parts.DOG_Dog DOG ON t_SPLIT.as_int = DOG.id_dog + WHERE + ISNULL(t_SPLIT.as_int) + OR ISNULL(DOG.id_dog) + OR ( + DOG.active = 0 + AND a_get_inactive_dog = 0 + ) + ; + ELSE + INSERT INTO tmp_Dog ( + id_dog + , name + ) + SELECT + DOG.id_dog + , DOG.name + FROM tmp_Split t_SPLIT + RIGHT JOIN parts.DOG_Dog DOG ON t_SPLIT.as_int = DOG.id_dog + WHERE + ( + a_get_all_dog = 1 + OR ( + v_has_filter_dog = 1 + AND NOT ISNULL(t_SPLIT.as_int) + ) + ) + AND ( + a_get_inactive_dog = 1 + OR DOG.active = 1 + ) + ; + END IF; + END IF; + + DELETE FROM tmp_Split; + + -- Commands + IF v_has_filter_command = 1 THEN + CALL parts.p_split(v_guid, a_ids_command, ',', a_debug); + + INSERT INTO tmp_Split ( + substring + , as_int + ) + SELECT + substring + , CONVERT(substring, DECIMAL(10,0)) AS as_int + FROM parts.CORE_Split_Temp + WHERE + GUID = v_guid + AND NOT ISNULL(substring) + AND substring <> '' + ; + + CALL parts.p_clear_split_temp( v_guid ); + END IF; + + IF NOT EXISTS (SELECT * FROM tmp_Msg_Error t_ERROR INNER JOIN parts.CORE_Msg_Error_Type ERROR_TYPE ON t_ERROR.id_type = ERROR_TYPE.id_type WHERE ERROR_TYPE.is_breaking_error = 1 LIMIT 1) THEN + IF EXISTS ( + SELECT * + FROM tmp_Split t_SPLIT + LEFT JOIN parts.DOG_Command COMMAND ON t_SPLIT.as_int = COMMAND.id_command + WHERE + ISNULL(t_SPLIT.as_int) + OR ISNULL(COMMAND.id_command) + OR ( + COMMAND.active = 0 + AND a_get_inactive_command = 0 + ) + ) THEN + INSERT INTO tmp_Msg_Error ( + id_type + , code + , msg + ) + SELECT + v_id_type_error_bad_data + , v_code_type_error_bad_data + , CONCAT('Invalid or inactive Command IDs: ', IFNULL(GROUP_CONCAT(t_SPLIT.substring SEPARATOR ', '), 'NULL')) + FROM tmp_Split t_SPLIT + LEFT JOIN parts.DOG_Command COMMAND ON t_SPLIT.as_int = COMMAND.id_command + WHERE + ISNULL(t_SPLIT.as_int) + OR ISNULL(COMMAND.id_command) + OR ( + COMMAND.active = 0 + AND a_get_inactive_command = 0 + ) + ; + ELSE + INSERT INTO tmp_Command ( + id_command + , name + ) + SELECT + COMMAND.id_command + -- , COMMAND.code + , COMMAND.name + FROM tmp_Split t_SPLIT + RIGHT JOIN parts.DOG_Command COMMAND ON t_SPLIT.as_int = COMMAND.id_command + WHERE + ( + a_get_all_command = 1 + OR ( + v_has_filter_command = 1 + AND NOT ISNULL(t_SPLIT.as_int) + ) + ) + AND ( + a_get_inactive_command = 1 + OR COMMAND.active = 1 + ) + ; + END IF; + END IF; + + DELETE FROM tmp_Split; + + -- Understanding Levels + IF v_has_filter_understanding_level = 1 THEN + CALL parts.p_split(v_guid, a_ids_understanding_level, ',', a_debug); + + INSERT INTO tmp_Split ( + substring + , as_int + ) + SELECT + substring + , CONVERT(substring, DECIMAL(10,0)) AS as_int + FROM parts.CORE_Split_Temp + WHERE + GUID = v_guid + AND NOT ISNULL(substring) + AND substring <> '' + ; + + CALL parts.p_clear_split_temp( v_guid ); + END IF; + + IF NOT EXISTS (SELECT * FROM tmp_Msg_Error t_ERROR INNER JOIN parts.CORE_Msg_Error_Type ERROR_TYPE ON t_ERROR.id_type = ERROR_TYPE.id_type WHERE ERROR_TYPE.is_breaking_error = 1 LIMIT 1) THEN + IF EXISTS ( + SELECT * + FROM tmp_Split t_SPLIT + LEFT JOIN parts.DOG_Understanding_Level UNDERSTANDING_LEVEL ON t_SPLIT.as_int = UNDERSTANDING_LEVEL.id_understanding_level + WHERE + ISNULL(t_SPLIT.as_int) + OR ISNULL(UNDERSTANDING_LEVEL.id_understanding_level) + OR ( + UNDERSTANDING_LEVEL.active = 0 + AND a_get_inactive_understanding_level = 0 + ) + ) THEN + INSERT INTO tmp_Msg_Error ( + id_type + , code + , msg + ) + SELECT + v_id_type_error_bad_data + , v_code_type_error_bad_data + , CONCAT('Invalid or inactive Understanding Level IDs: ', IFNULL(GROUP_CONCAT(t_SPLIT.substring SEPARATOR ', '), 'NULL')) + FROM tmp_Split t_SPLIT + LEFT JOIN parts.DOG_Understanding_Level UNDERSTANDING_LEVEL ON t_SPLIT.as_int = UNDERSTANDING_LEVEL.id_understanding_level + WHERE + ISNULL(t_SPLIT.as_int) + OR ISNULL(UNDERSTANDING_LEVEL.id_understanding_level) + OR ( + UNDERSTANDING_LEVEL.active = 0 + AND a_get_inactive_understanding_level = 0 + ) + ; + ELSE + INSERT INTO tmp_Understanding_Level ( + id_understanding_level + , code + , name + ) + SELECT + UNDERSTANDING_LEVEL.id_understanding_level + , UNDERSTANDING_LEVEL.code + , UNDERSTANDING_LEVEL.name + FROM tmp_Split t_SPLIT + RIGHT JOIN parts.DOG_Understanding_Level UNDERSTANDING_LEVEL ON t_SPLIT.as_int = UNDERSTANDING_LEVEL.id_understanding_level + WHERE + ( + a_get_all_understanding_level = 1 + OR ( + v_has_filter_understanding_level = 1 + AND NOT ISNULL(t_SPLIT.as_int) + ) + ) + AND ( + a_get_inactive_understanding_level = 1 + OR UNDERSTANDING_LEVEL.active = 1 + ) + ; + END IF; + END IF; + + DELETE FROM tmp_Split; + + -- Obedience Levels + IF v_has_filter_obedience_level = 1 THEN + CALL parts.p_split(v_guid, a_ids_obedience_level, ',', a_debug); + + INSERT INTO tmp_Split ( + substring + , as_int + ) + SELECT + substring + , CONVERT(substring, DECIMAL(10,0)) AS as_int + FROM parts.CORE_Split_Temp + WHERE + GUID = v_guid + AND NOT ISNULL(substring) + AND substring <> '' + ; + + CALL parts.p_clear_split_temp( v_guid ); + END IF; + + IF NOT EXISTS (SELECT * FROM tmp_Msg_Error t_ERROR INNER JOIN parts.CORE_Msg_Error_Type ERROR_TYPE ON t_ERROR.id_type = ERROR_TYPE.id_type WHERE ERROR_TYPE.is_breaking_error = 1 LIMIT 1) THEN + IF EXISTS ( + SELECT * + FROM tmp_Split t_SPLIT + LEFT JOIN parts.DOG_Obedience_Level OBEDIENCE_LEVEL ON t_SPLIT.as_int = OBEDIENCE_LEVEL.id_obedience_level + WHERE + ISNULL(t_SPLIT.as_int) + OR ISNULL(OBEDIENCE_LEVEL.id_obedience_level) + OR ( + OBEDIENCE_LEVEL.active = 0 + AND a_get_inactive_obedience_level = 0 + ) + ) THEN + INSERT INTO tmp_Msg_Error ( + id_type + , code + , msg + ) + SELECT + v_id_type_error_bad_data + , v_code_type_error_bad_data + , CONCAT('Invalid or inactive Obedience Level IDs: ', IFNULL(GROUP_CONCAT(t_SPLIT.substring SEPARATOR ', '), 'NULL')) + FROM tmp_Split t_SPLIT + LEFT JOIN parts.DOG_Obedience_Level OBEDIENCE_LEVEL ON t_SPLIT.as_int = OBEDIENCE_LEVEL.id_obedience_level + WHERE + ISNULL(t_SPLIT.as_int) + OR ISNULL(OBEDIENCE_LEVEL.id_obedience_level) + OR ( + OBEDIENCE_LEVEL.active = 0 + AND a_get_inactive_obedience_level = 0 + ) + ; + ELSE + INSERT INTO tmp_Obedience_Level ( + id_obedience_level + , code + , name + ) + SELECT + OBEDIENCE_LEVEL.id_obedience_level + , OBEDIENCE_LEVEL.code + , OBEDIENCE_LEVEL.name + FROM tmp_Split t_SPLIT + RIGHT JOIN parts.DOG_Obedience_Level OBEDIENCE_LEVEL ON t_SPLIT.as_int = OBEDIENCE_LEVEL.id_obedience_level + WHERE + ( + a_get_all_obedience_level = 1 + OR ( + v_has_filter_obedience_level = 1 + AND NOT ISNULL(t_SPLIT.as_int) + ) + ) + AND ( + a_get_inactive_obedience_level = 1 + OR OBEDIENCE_LEVEL.active = 1 + ) + ; + END IF; + END IF; + + DELETE FROM tmp_Split; + + + -- Permissions + IF a_debug = 1 THEN + SELECT + v_guid + , a_id_user + , FALSE -- a_get_inactive_user + , v_id_permission_dog_view + , 0 -- a_debug + ; + END IF; + + CALL parts.p_DOG_calc_user( + v_guid + , a_id_user + , FALSE -- a_get_inactive_user + , v_id_permission_dog_view + , 0 -- a_debug + ); + + SELECT + IFNULL(CALC_USER_T.has_access, 0) + INTO + v_can_view + FROM parts.DOG_Calc_User_Temp CALC_USER_T + WHERE CALC_USER_T.GUID = v_guid + LIMIT 1 + ; + + IF a_debug = 1 THEN + SELECT v_can_view; + END IF; + + IF (v_can_view = 0) THEN + DELETE t_ME + FROM tmp_Msg_Error t_ME + WHERE t_ME.id_type <> v_id_type_error_no_permission + ; + INSERT INTO tmp_Msg_Error ( + id_type + , code + , msg + ) + VALUES ( + v_id_type_error_no_permission + , v_code_type_error_no_permission + , 'You do not have permission to view Commands.' + ) + ; + END IF; + + CALL parts.p_DOG_clear_calc_user( + v_guid + , 0 -- a_debug + ); + + IF EXISTS(SELECT * FROM tmp_Msg_Error t_ERROR INNER JOIN parts.CORE_Msg_Error_Type ERROR_TYPE ON t_ERROR.id_type = ERROR_TYPE.id_type WHERE ERROR_TYPE.is_breaking_error = 1 LIMIT 1) THEN + IF a_debug = 1 THEN + SELECT * FROM tmp_Dog; + SELECT * FROM tmp_Command; + SELECT * FROM tmp_Obedience_Level; + END IF; + + DELETE FROM tmp_Dog; + DELETE FROM tmp_Command; + SELECT * FROM tmp_Understanding_Level; + DELETE FROM tmp_Obedience_Level; + END IF; + + -- Outputs + -- Commands + SELECT + DOG_COMMAND_LINK.id_link AS id_dog_command_link + , t_DOG.id_dog + , t_DOG.name + , t_COMMAND.id_command + -- , t_COMMAND.code + , t_COMMAND.name + , t_UNDERSTANDING_LEVEL.id_understanding_level + , t_UNDERSTANDING_LEVEL.code AS code_understanding_level + , t_UNDERSTANDING_LEVEL.name AS name_understanding_level + , t_OBEDIENCE_LEVEL.id_obedience_level + , t_OBEDIENCE_LEVEL.code AS code_obedience_level + , t_OBEDIENCE_LEVEL.name AS name_obedience_level + , DOG_COMMAND_LINK.active + FROM parts.DOG_Dog_Command_Link DOG_COMMAND_LINK + INNER JOIN tmp_Dog t_DOG ON DOG_COMMAND_LINK.id_dog = t_DOG.id_dog + INNER JOIN tmp_Command t_COMMAND ON DOG_COMMAND_LINK.id_command = t_COMMAND.id_command + INNER JOIN tmp_Understanding_Level t_UNDERSTANDING_LEVEL ON DOG_COMMAND_LINK.id_understanding_level = t_UNDERSTANDING_LEVEL.id_understanding_level + INNER JOIN tmp_Obedience_Level t_OBEDIENCE_LEVEL ON DOG_COMMAND_LINK.id_obedience_level = t_OBEDIENCE_LEVEL.id_obedience_level + ; + + -- Errors + SELECT + t_ERROR.id_error + , t_ERROR.id_type + , t_ERROR.code + , ERROR_TYPE.name + , ERROR_TYPE.description + , ERROR_TYPE.is_breaking_error + , ERROR_TYPE.background_colour + , ERROR_TYPE.text_colour + , t_ERROR.msg + FROM tmp_Msg_Error t_ERROR + INNER JOIN parts.CORE_Msg_Error_Type ERROR_TYPE ON t_ERROR.id_type = ERROR_TYPE.id_type + ; + + IF a_debug = 1 AND v_can_view = 1 THEN + SELECT * FROM tmp_Dog; + SELECT * FROM tmp_Command; + SELECT * FROM tmp_Understanding_Level; + SELECT * FROM tmp_Obedience_Level; + END IF; + + DROP TEMPORARY TABLE IF EXISTS tmp_Split; + DROP TEMPORARY TABLE IF EXISTS tmp_Msg_Error; + DROP TEMPORARY TABLE IF EXISTS tmp_Obedience_Level; + DROP TEMPORARY TABLE IF EXISTS tmp_Understanding_Level; + DROP TEMPORARY TABLE IF EXISTS tmp_Command; + DROP TEMPORARY TABLE IF EXISTS tmp_Dog; + + IF a_debug = 1 THEN + CALL parts.p_core_debug_timing_reporting ( v_time_start ); + END IF; +END // +DELIMITER ; + + +/* + +CALL parts.p_DOG_get_many_dog_command ( + 1 -- 'auth0|6582b95c895d09a70ba10fef', -- a_id_user + , 1 -- a_get_all_dog + , 0 -- a_get_inactive_dog + , '' -- a_ids_dog + , 1 -- a_get_all_command + , 0 -- a_get_inactive_command + , '' -- a_ids_command + , 1 -- a_get_all_understanding_level + , 0 -- a_get_inactive_understanding_level + , '' -- a_ids_understanding_level + , 1 -- a_get_all_obedience_level + , 0 -- a_get_inactive_obedience_level + , '' -- a_ids_obedience_level + , 1 -- a_debug +); + +*/ +USE parts; + + +-- Error Message Types +/* Existing table */ +INSERT INTO parts.CORE_Msg_Error_Type ( + code + , name + , description + , is_breaking_error +) +VALUES + ( + 'BAD_DATA' + , 'Invalid data' + , 'Rubbish data' + , 1 + ) + , ( + 'NO_PERMISSION' + , 'No permission' + , 'Not authorised' + , 1 + ) + , ( + 'MYSQL_ERROR' + , 'MySQL error' + , 'MySQL execution error.' + , 1 + ) + , ( + 'WARNING' + , 'Warning' + , 'Non-breaking error.' + , 0 + ) +; + +INSERT INTO parts.CORE_File_Type ( + code + , name + , is_image +) +VALUES + ( + 'JPG' + , 'JPG' + , 1 + ) +; + +-- Access Levels +INSERT INTO parts.DOG_Access_Level ( + display_order + , code + , name + , priority +) +VALUES + ( + 1 + , 'VIEW' + , 'View' + , 3 + ) + , ( + 2 + , 'EDIT' + , 'Edit' + , 2 + ) + , ( + 3 + , 'ADMIN' + , 'Admin' + , 1 + ) +; + +-- Permission Groups +INSERT INTO parts.DOG_Permission_Group ( + display_order + , code + , name +) +VALUES + ( + 0 + , 'DOG' + , 'Dog' + ) + , ( + 1 + , 'USER' + , 'Admin User' + ) +; + +-- Permissions +INSERT INTO parts.DOG_Permission ( + display_order + , code + , name + , id_permission_group + , id_access_level_required +) +VALUES + ( + 1 + , 'DOG_VIEW' + , 'View Dog' + , 1 + , 3 + ) + , ( + 1 + , 'DOG_ADMIN' + , 'Admin Dog' + , 1 + , 3 + ) + , ( + 1 + , 'DOG_CREATE' + , 'Create Dog' + , 1 + , 1 + ) +; + +-- Users +INSERT INTO parts.DOG_User ( + id_user_auth0 + , firstname + , surname + , email + , is_super_user + , active +) +VALUES + ( + 'auth0|6582b95c895d09a70ba10fef' -- id_user_auth0 + , 'Teddy' -- firstname + , 'Middleton-Smith' -- surname + , 'edward.middletonsmith@gmail.com' -- email + , 1 -- is_super_user + , 1 -- active + ) + , ( + 'auth0|672659014296b7f94a9bab45' -- id_user_auth0 + , 'Tierney' -- firstname + , 'Gullen' -- surname + , 'tierneybailey13@gmail.com' -- email + , 1 -- is_super_user + , 1 -- active + ) + , ( + NULL -- id_user_auth0 + , 'Command Bot' -- firstname + , 'Bot' -- surname + , 'teddy@partsltd.co.uk' -- email + , 0 -- is_super_user + , 1 -- active + ) +; + +-- Roles +INSERT INTO parts.DOG_Role ( + display_order + , code + , name + , id_user_created_by +) +VALUES + ( + 1 + , 'MANAGER' + , 'Manager' + , 1 + ) + , ( + 2 + , 'USER' + , 'User' + , 1 + ) +; + +-- Role Permission link +INSERT INTO parts.DOG_Role_Permission_Link ( + id_role + , id_permission + , id_access_level + , id_user_created_by +) +VALUES + ( + 1 + , 1 + , 3 + , 1 + ) + , ( + 1 + , 2 + , 3 + , 1 + ) + , ( + 1 + , 3 + , 3 + , 1 + ) + , ( + 2 + , 1 + , 1 + , 1 + ) + , ( + 2 + , 2 + , 1 + , 1 + ) + , ( + 2 + , 3 + , 1 + , 1 + ) +; + +-- User Role link +INSERT INTO parts.DOG_User_Role_Link ( + id_user + , id_role + , id_user_created_by +) +VALUES + ( + 1 + , 1 + , 1 + ) + , ( + 2 + , 2 + , 1 + ) + , ( + 3 + , 2 + , 1 + ) +; + +-- Project-specific tables +INSERT INTO parts.DOG_Dog ( + name + , appearance + , mass_kg +) +VALUES + ( + 'Molly' + , 'Cute' + , 20 + ) +; + +INSERT INTO parts.DOG_Breed ( + code + , name +) +VALUES + ( + 'BORDER_COLLIE' + , 'Border Collie' + ) +; + +INSERT INTO parts.DOG_Dog_Breed_Link ( + id_dog + , id_breed + , lineage_ratio +) +VALUES + ( + 1 + , 1 + , 1 + ) +; + +INSERT INTO parts.DOG_Understanding_Level ( + code + , name +) +VALUES + ( + 'UNKNOWN' + , 'Not known' + ) + , ( + 'INTRODUCED' + , 'Has been introduced' + ) + , ( + 'RECOGNISES_COMBINED_VISUAL_AND_VERBAL_SIGNAL' + , 'Combined visual and verbal signal recognised' + ) + , ( + 'RECOGNISES_VISUAL_SIGNAL' + , 'Visual signal alone recognised' + ) + , ( + 'RECOGNISES_VERBAL_SIGNAL' + , 'Verbal signal alone recognised' + ) + , ( + 'UNDERSTOOD' + , 'Understood' + ) +; + +INSERT INTO parts.DOG_Obedience_Level ( + code + , name +) +VALUES + ( + 'REFUSAL' + , 'Refuses to obey' + ) + , ( + 'ON_HER_TERMS' + , 'Might obey if she feels like it' + ) + , ( + 'OBEYS_UNDISTRACTED' + , 'Obeys without distractions' + ) + , ( + 'OBEYS_MILDLY_DISTRACTED' + , 'Obeys when mildly distracted' + ) + , ( + 'OBEYS_PERFECTLY' + , 'Obeys in all situations' + ) +; + +INSERT INTO parts.DOG_Command_Category ( + code + , name +) +VALUES + ( + 'ACTIVITIES' + , 'Activities' + ) + , ( + 'BASIC_OBEDIENCE' + , 'Basic obedience' + ) + , ( + 'BEHAVIOUR_MODIFICATION' + , 'Behaviour modification' + ) + , ( + 'BODY_PARTS' + , 'Body parts' + ) + , ( + 'CLOTHING_AND_EQUIPMENT' + , 'Clothing and equipment' + ) + , ( + 'COMPARISON' + , 'Comparison' + ) + , ( + 'ADJECTIVES' + , 'Compliments and insults (adjectives)' + ) + , ( + 'EMOTIONAL_STATE' + , 'Emotional state' + ) + , ( + 'ENVIRONMENT' + , 'Environment' + ) + , ( + 'ESSENTIAL_NEEDS' + , 'Essential needs' + ) + , ( + 'IMPULSE_CONTROL' + , 'Impulse control' + ) + , ( + 'LOCATION' + , 'Location' + ) + , ( + 'MANNERS' + , 'Manners' + ) + , ( + 'MEALTIME' + , 'Mealtime' + ) + , ( + 'PARTY_TRICK' + , 'Party trick' + ) + , ( + 'PEOPLE' + , 'People' + ) + , ( + 'PLAY' + , 'Play' + ) + , ( + 'POSITION' + , 'Position' + ) + , ( + 'QUESTIONS' + , 'Questions' + ) + , ( + 'SERVICE' + , 'Service' + ) + , ( + 'TIME_AND_SCHEDULING' + , 'Time and scheduling' + ) + , ( + 'UTILITY' + , 'Utility' + ) +; + +/* +INSERT INTO parts.DOG_Command ( + code + , name +) +VALUES + ( + 'lick' + , 'nips' + ) +; +*/ + +/* +INSERT INTO parts.DOG_Dog_Command_Link ( + id_dog + , id_command + , id_understanding_level + , id_obedience_level + , notes +) +VALUES + ( + 'lick' + , 'nips' + ) +; +*/ + +INSERT INTO parts.DOG_Location ( + code + , name +) +VALUES + ( + 'LOUNGE' + , 'Lounge' + ) +; + +/* +INSERT INTO parts.DOG_Location_Link ( + id_location_parent + , id_location_child +) +VALUES + ( + 1 + , 2 + ) +; +*/ + +INSERT INTO parts.DOG_Colour ( + code + , name +) +VALUES + ( + 'RED' + , 'Red' + ) + , ( + 'GREEN' + , 'Green' + ) +; + +INSERT INTO parts.DOG_Button_Shape ( + code + , name + , description +) +VALUES + ( + 'ROUND' + , 'Round' + , 'Cylindrical' + ) + , ( + 'HEXAGONAL' + , 'Hexagonal' + , 'Hexagonal prism' + ) +; + +/* +INSERT INTO parts.DOG_Image ( + id_file_type + , id_dog + , path + , display_order +) +VALUES + ( + 1 + , 1 + , NULL + , NULL + ) +; +*/ + +/* +INSERT INTO parts.DOG_Button_Icon ( + id_image + , code + , name + , description +) +VALUES + ( + 1 + , NULL + ) +; +*/ + +/* +INSERT INTO parts.DOG_Command_Button_Link ( + id_command + , id_button_shape + , id_button_colour + , id_button_icon + , id_location +) +VALUES + ( + 1 -- AS id_command + , 1 -- AS id_button_shape + , 1 -- AS id_button_colour + , NULL -- AS id_button_icon + , 1 -- AS id_location + ) +; +*/ + +INSERT INTO parts.DOG_Drive ( + code + , name +) +VALUES + ( + 'PREY' + , 'Prey' + ) + , ( + 'PACK' + , 'Pack' + ) +; + +INSERT INTO parts.DOG_Dog_Drive_Link ( + id_dog + , id_drive + , dominance_ratio +) +VALUES + ( + 1 + , 1 + , 0.5 + ) + , ( + 1 + , 2 + , 0.5 + ) +; + + + +/* + Post Excel-insert: + + +SELECT * +FROM demo.DOG_Dog; + +/ * +SELECT * +FROM demo.DOG_Command; +* / + +SELECT * +-- DELETE +FROM demo.DOG_Understanding_Level; + +SELECT * +-- DELETE +FROM demo.DOG_Obedience_Level; + +/ * +INSERT INTO demo.DOG_Dog_Command_Link ( + id_dog + , id_command + , id_understanding_level + , id_obedience_level + , notes +) +SELECT + DOG.id_dog + , COMMAND.id_command + , +FROM demo.DOG_Dog DOG +CROSS JOIN demo.DOG_Command COMMAND +WHERE DOG.name = 'Molly' + +* / + +*/ + +-- Core tables +-- Error Message type +SELECT * FROM parts.CORE_Msg_Error_Type; + + +-- Common project tables +-- User Change Sets +SELECT * FROM parts.DOG_User_Change_Set; + +-- Access Levels +SELECT * FROM parts.DOG_Access_Level; + +-- Permission Groups +SELECT * FROM parts.DOG_Permission_Group; + +-- Permissions +SELECT * FROM parts.DOG_Permission; + +-- Users +SELECT * FROM parts.DOG_User; +SELECT * FROM parts.DOG_User_Audit; + +-- Roles +SELECT * FROM parts.DOG_Role; +SELECT * FROM parts.DOG_Role_Audit; + +-- Role Permission link +SELECT * FROM parts.DOG_Role_Permission_Link; +SELECT * FROM parts.DOG_Role_Permission_Link_Audit; + +-- User Role link +SELECT * FROM parts.DOG_User_Role_Link; +SELECT * FROM parts.DOG_User_Role_Link_Audit; + + +-- Project-specific tables +-- Command Change Sets +SELECT * FROM parts.DOG_Dog_Change_Set; + +-- Commands +SELECT * FROM parts.DOG_Dog; +SELECT * FROM parts.DOG_Dog_Audit; +SELECT * FROM parts.DOG_Dog_Temp; + +SELECT * FROM parts.DOG_Breed; +SELECT * FROM parts.DOG_Breed_Audit; +SELECT * FROM parts.DOG_Breed_Temp; + +SELECT * FROM parts.DOG_Dog_Breed_Link; +SELECT * FROM parts.DOG_Dog_Breed_Link_Audit; +SELECT * FROM parts.DOG_Dog_Breed_Link_Temp; + +SELECT * FROM parts.DOG_Obedience_Level; +SELECT * FROM parts.DOG_Obedience_Level_Audit; +SELECT * FROM parts.DOG_Obedience_Level_Temp; + +SELECT * FROM parts.DOG_Command_Category; +SELECT * FROM parts.DOG_Command_Category_Audit; +SELECT * FROM parts.DOG_Command_Category_Temp; + +SELECT * FROM parts.DOG_Command; +SELECT * FROM parts.DOG_Command_Audit; +SELECT * FROM parts.DOG_Command_Temp; + +SELECT * FROM parts.DOG_Dog_Command_Link; +SELECT * FROM parts.DOG_Dog_Command_Link_Audit; +SELECT * FROM parts.DOG_Dog_Command_Link_Temp; + +SELECT * FROM parts.DOG_Location; +SELECT * FROM parts.DOG_Location_Audit; +SELECT * FROM parts.DOG_Location_Temp; + +SELECT * FROM parts.DOG_Location_Link; +SELECT * FROM parts.DOG_Location_Link_Audit; +SELECT * FROM parts.DOG_Location_Link_Temp; + +SELECT * FROM parts.DOG_Colour; +SELECT * FROM parts.DOG_Colour_Audit; +SELECT * FROM parts.DOG_Colour_Temp; + +SELECT * FROM parts.DOG_Button_Shape; +SELECT * FROM parts.DOG_Button_Shape_Audit; +SELECT * FROM parts.DOG_Button_Shape_Temp; + +SELECT * FROM parts.DOG_Image; +SELECT * FROM parts.DOG_Image_Audit; +SELECT * FROM parts.DOG_Image_Temp; + +SELECT * FROM parts.DOG_Button_Icon; +SELECT * FROM parts.DOG_Button_Icon_Audit; +SELECT * FROM parts.DOG_Button_Icon_Temp; + +SELECT * FROM parts.DOG_Command_Button_Link; +SELECT * FROM parts.DOG_Command_Button_Link_Audit; +SELECT * FROM parts.DOG_Command_Button_Link_Temp; + +SELECT * FROM parts.DOG_Drive; +SELECT * FROM parts.DOG_Drive_Audit; +SELECT * FROM parts.DOG_Drive_Temp; + +SELECT * FROM parts.DOG_Dog_Drive_Link; +SELECT * FROM parts.DOG_Dog_Drive_Link_Audit; +SELECT * FROM parts.DOG_Dog_Drive_Link_Temp; + diff --git a/static/MySQL/0001_destroy.sql b/static/MySQL/0001_destroy.sql new file mode 100644 index 0000000..0affff6 --- /dev/null +++ b/static/MySQL/0001_destroy.sql @@ -0,0 +1,153 @@ + +CREATE DATABASE IF NOT EXISTS parts; + +GRANT ALL PRIVILEGES ON parts.* TO 'teddy'@'%'; +FLUSH PRIVILEGES; + +USE parts; + +-- Permanent Temp Tables +DROP TABLE IF EXISTS parts.tmp_DOG_Calc_User; +-- DROP TABLE IF EXISTS parts.tmp_core_Msg_Error; +DROP TABLE IF EXISTS parts.tmp_DOG_User; +DROP TABLE IF EXISTS parts.tmp_DOG_User_Role_Link; + + +-- Permanent Tables +DROP TABLE IF EXISTS parts.DOG_Dog_Drive_Link_Temp; +DROP TABLE IF EXISTS parts.DOG_Dog_Drive_Link_Audit; +DROP TABLE IF EXISTS parts.DOG_Dog_Drive_Link; + +DROP TABLE IF EXISTS parts.DOG_Drive_Temp; +DROP TABLE IF EXISTS parts.DOG_Drive_Audit; +DROP TABLE IF EXISTS parts.DOG_Drive; + +DROP TABLE IF EXISTS parts.DOG_Command_Button_Link_Temp; +DROP TABLE IF EXISTS parts.DOG_Command_Button_Link_Audit; +DROP TABLE IF EXISTS parts.DOG_Command_Button_Link; + +DROP TABLE IF EXISTS parts.DOG_Button_Icon_Temp; +DROP TABLE IF EXISTS parts.DOG_Button_Icon_Audit; +DROP TABLE IF EXISTS parts.DOG_Button_Icon; + +DROP TABLE IF EXISTS parts.DOG_Image_Temp; +DROP TABLE IF EXISTS parts.DOG_Image_Audit; +DROP TABLE IF EXISTS parts.DOG_Image; + +DROP TABLE IF EXISTS parts.DOG_Button_Shape_Temp; +DROP TABLE IF EXISTS parts.DOG_Button_Shape_Audit; +DROP TABLE IF EXISTS parts.DOG_Button_Shape; + +DROP TABLE IF EXISTS parts.DOG_Colour_Temp; +DROP TABLE IF EXISTS parts.DOG_Colour_Audit; +DROP TABLE IF EXISTS parts.DOG_Colour; + +DROP TABLE IF EXISTS parts.DOG_Location_Link_Temp; +DROP TABLE IF EXISTS parts.DOG_Location_Link_Audit; +DROP TABLE IF EXISTS parts.DOG_Location_Link; + +DROP TABLE IF EXISTS parts.DOG_Location_Temp; +DROP TABLE IF EXISTS parts.DOG_Location_Audit; +DROP TABLE IF EXISTS parts.DOG_Location; + +DROP TABLE IF EXISTS parts.DOG_Personal_Best_Temp; +DROP TABLE IF EXISTS parts.DOG_Personal_Best_Audit; +DROP TABLE IF EXISTS parts.DOG_Personal_Best; + +DROP TABLE IF EXISTS parts.DOG_Dog_Command_Link_Temp; +DROP TABLE IF EXISTS parts.DOG_Dog_Command_Link_Audit; +DROP TABLE IF EXISTS parts.DOG_Dog_Command_Link; + +DROP TABLE IF EXISTS parts.DOG_Command_Temp; +DROP TABLE IF EXISTS parts.DOG_Command_Audit; +DROP TABLE IF EXISTS parts.DOG_Command; + +DROP TABLE IF EXISTS parts.DOG_Command_Category_Temp; +DROP TABLE IF EXISTS parts.DOG_Command_Category_Audit; +DROP TABLE IF EXISTS parts.DOG_Command_Category; + +DROP TABLE IF EXISTS parts.DOG_Obedience_Level_Temp; +DROP TABLE IF EXISTS parts.DOG_Obedience_Level_Audit; +DROP TABLE IF EXISTS parts.DOG_Obedience_Level; + +DROP TABLE IF EXISTS parts.DOG_Understanding_Level_Temp; +DROP TABLE IF EXISTS parts.DOG_Understanding_Level_Audit; +DROP TABLE IF EXISTS parts.DOG_Understanding_Level; + +DROP TABLE IF EXISTS parts.DOG_Competency_Level_Temp; +DROP TABLE IF EXISTS parts.DOG_Competency_Level_Audit; +DROP TABLE IF EXISTS parts.DOG_Competency_Level; + +DROP TABLE IF EXISTS parts.DOG_Dog_Breed_Link_Temp; +DROP TABLE IF EXISTS parts.DOG_Dog_Breed_Link_Audit; +DROP TABLE IF EXISTS parts.DOG_Dog_Breed_Link; + +DROP TABLE IF EXISTS parts.DOG_Breed_Temp; +DROP TABLE IF EXISTS parts.DOG_Breed_Audit; +DROP TABLE IF EXISTS parts.DOG_Breed; + +DROP TABLE IF EXISTS parts.DOG_Dog_Temp; +DROP TABLE IF EXISTS parts.DOG_Dog_Audit; +DROP TABLE IF EXISTS parts.DOG_Dog; + +DROP TABLE IF EXISTS parts.DOG_Dog_Change_Set; + +DROP TABLE IF EXISTS parts.DOG_Calc_User_Temp; + +DROP TABLE IF EXISTS parts.DOG_User_Role_Link_Audit; +DROP TABLE IF EXISTS parts.DOG_User_Role_Link; + +DROP TABLE IF EXISTS parts.DOG_Role_Permission_Link_Audit; +DROP TABLE IF EXISTS parts.DOG_Role_Permission_Link; + +DROP TABLE IF EXISTS parts.DOG_Role_Audit; +DROP TABLE IF EXISTS parts.DOG_Role; + +DROP TABLE IF EXISTS parts.DOG_User_Temp; +DROP TABLE IF EXISTS parts.DOG_User_Audit; +DROP TABLE IF EXISTS parts.DOG_User; + +DROP TABLE IF EXISTS parts.DOG_Permission_Audit; +DROP TABLE IF EXISTS parts.DOG_Permission; + +DROP TABLE IF EXISTS parts.DOG_Permission_Group_Audit; +DROP TABLE IF EXISTS parts.DOG_Permission_Group; + +DROP TABLE IF EXISTS parts.DOG_Access_Level_Audit; +DROP TABLE IF EXISTS parts.DOG_Access_Level; + +DROP TABLE IF EXISTS parts.DOG_User_Change_Set; + +/* +DROP TABLE IF EXISTS parts.CORE_Split_Key_Value_Pair_Csv_Temp; +DROP TABLE IF EXISTS parts.CORE_Split_Temp; + +*/ +DROP TABLE IF EXISTS parts.CORE_File_Type; +DROP TABLE IF EXISTS parts.CORE_Msg_Error_Type; + +-- Stored Procedures +DROP PROCEDURE IF EXISTS parts.p_DOG_test_get_many_dog_command; +DROP PROCEDURE IF EXISTS parts.p_DOG_test_get_many_command; +DROP PROCEDURE IF EXISTS parts.p_DOG_get_many_command; +DROP PROCEDURE IF EXISTS parts.p_DOG_test_save_command; +DROP PROCEDURE IF EXISTS parts.p_DOG_save_command; + +DROP PROCEDURE IF EXISTS parts.p_DOG_clear_calc_user; +DROP PROCEDURE IF EXISTS parts.p_DOG_calc_user; + +/* +DROP PROCEDURE IF EXISTS parts.p_core_clear_split_key_value_pair_csv; +DROP PROCEDURE IF EXISTS parts.p_core_split_key_value_pair_csv; +DROP PROCEDURE IF EXISTS parts.p_core_clear_split; +DROP PROCEDURE IF EXISTS parts.p_core_split; +DROP PROCEDURE IF EXISTS parts.p_clear_split_key_value_pair_csv; +DROP PROCEDURE IF EXISTS parts.p_split_key_value_pair_csv; +DROP PROCEDURE IF EXISTS parts.p_clear_split; +DROP PROCEDURE IF EXISTS parts.p_split; + +DROP PROCEDURE IF EXISTS parts.p_core_debug_timing_reporting; +DROP PROCEDURE IF EXISTS parts.p_debug_timing_reporting; +DROP PROCEDURE IF EXISTS parts.p_core_validate_guid; +DROP PROCEDURE IF EXISTS parts.p_core_validate_guid_test; +*/ \ No newline at end of file diff --git a/static/MySQL/1000_tbl_CORE_Msg_Error_Type.sql b/static/MySQL/1000_tbl_CORE_Msg_Error_Type.sql new file mode 100644 index 0000000..f5cb3d8 --- /dev/null +++ b/static/MySQL/1000_tbl_CORE_Msg_Error_Type.sql @@ -0,0 +1,19 @@ + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'CORE_Msg_Error_Type' +; + +CREATE TABLE IF NOT EXISTS parts.CORE_Msg_Error_Type ( + id_type INT NOT NULL AUTO_INCREMENT PRIMARY KEY + , code VARCHAR(100) NOT NULL + , name VARCHAR(500) NOT NULL + , description VARCHAR(1000) + , is_breaking_error BIT NOT NULL + , background_colour VARCHAR(32) NOT NULL DEFAULT '#111111' + , text_colour VARCHAR(32) NOT NULL DEFAULT '#110000' +); diff --git a/static/MySQL/1020_tbl_CORE_File_Type.sql b/static/MySQL/1020_tbl_CORE_File_Type.sql new file mode 100644 index 0000000..8b97b95 --- /dev/null +++ b/static/MySQL/1020_tbl_CORE_File_Type.sql @@ -0,0 +1,17 @@ + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'CORE_File_Type' +; + +CREATE TABLE IF NOT EXISTS parts.CORE_File_Type ( + id_file_type INT NOT NULL AUTO_INCREMENT PRIMARY KEY + , code VARCHAR(100) NOT NULL + , name VARCHAR(250) NOT NULL + , is_image BIT NOT NULL DEFAULT 0 + , active BIT NOT NULL DEFAULT 1 +); diff --git a/static/MySQL/1090_tbl_CORE_Split_Temp.sql b/static/MySQL/1090_tbl_CORE_Split_Temp.sql new file mode 100644 index 0000000..91abcd2 --- /dev/null +++ b/static/MySQL/1090_tbl_CORE_Split_Temp.sql @@ -0,0 +1,15 @@ + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'CORE_Split_Temp' +; + +CREATE TABLE IF NOT EXISTS parts.CORE_Split_Temp ( + guid BINARY(36) NOT NULL + , display_order INT NOT NULL + , substring VARCHAR(4000) NOT NULL +); diff --git a/static/MySQL/1091_tbl_CORE_Split_Key_Value_Pair_Csv_Temp.sql b/static/MySQL/1091_tbl_CORE_Split_Key_Value_Pair_Csv_Temp.sql new file mode 100644 index 0000000..a8cac6f --- /dev/null +++ b/static/MySQL/1091_tbl_CORE_Split_Key_Value_Pair_Csv_Temp.sql @@ -0,0 +1,16 @@ + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'CORE_Split_Key_Value_Pair_Csv_Temp' +; + +CREATE TABLE IF NOT EXISTS parts.CORE_Split_Key_Value_Pair_Csv_Temp ( + guid BINARY(36) NOT NULL + , id INT NOT NULL + , key_column VARCHAR(4000) NULL + , value_column VARCHAR(4000) NULL +); diff --git a/static/MySQL/1100_tbl_DOG_User_Change_Set.sql b/static/MySQL/1100_tbl_DOG_User_Change_Set.sql new file mode 100644 index 0000000..2326dc7 --- /dev/null +++ b/static/MySQL/1100_tbl_DOG_User_Change_Set.sql @@ -0,0 +1,16 @@ + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_User_Change_Set' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_User_Change_Set ( + id_change_set INT NOT NULL AUTO_INCREMENT PRIMARY KEY + , comment VARCHAR(500) + , updated_last_on DATETIME + , id_user_updated_last_by INT +); \ No newline at end of file diff --git a/static/MySQL/1104_tbl_DOG_Access_Level.sql b/static/MySQL/1104_tbl_DOG_Access_Level.sql new file mode 100644 index 0000000..a36a6a1 --- /dev/null +++ b/static/MySQL/1104_tbl_DOG_Access_Level.sql @@ -0,0 +1,20 @@ + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Access_Level' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Access_Level ( + id_access_level INT NOT NULL AUTO_INCREMENT PRIMARY KEY + , code VARCHAR(100) + , name VARCHAR(250) + , priority INT NOT NULL + , display_order INT NOT NULL + , active BIT NOT NULL DEFAULT 1 +); + + diff --git a/static/MySQL/1108_tbl_DOG_Permission_Group.sql b/static/MySQL/1108_tbl_DOG_Permission_Group.sql new file mode 100644 index 0000000..506031d --- /dev/null +++ b/static/MySQL/1108_tbl_DOG_Permission_Group.sql @@ -0,0 +1,17 @@ + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Permission_Group' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Permission_Group ( + id_group INT NOT NULL AUTO_INCREMENT PRIMARY KEY + , code VARCHAR(100) + , name VARCHAR(250) + , display_order INT NOT NULL + , active BIT NOT NULL DEFAULT 1 +); \ No newline at end of file diff --git a/static/MySQL/1112_tbl_DOG_Permission.sql b/static/MySQL/1112_tbl_DOG_Permission.sql new file mode 100644 index 0000000..8dba507 --- /dev/null +++ b/static/MySQL/1112_tbl_DOG_Permission.sql @@ -0,0 +1,25 @@ + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Permission' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Permission ( + id_permission INT NOT NULL AUTO_INCREMENT PRIMARY KEY + , code VARCHAR(100) + , name VARCHAR(250) + , id_permission_group INT NOT NULL + , CONSTRAINT FK_DOG_Permission_id_permission_group + FOREIGN KEY (id_permission_group) + REFERENCES parts.DOG_Permission_Group(id_group) + , id_access_level_required INT NOT NULL + , CONSTRAINT FK_DOG_Permission_id_access_level_required + FOREIGN KEY (id_access_level_required) + REFERENCES parts.DOG_Access_Level(id_access_level) + , display_order INT NOT NULL + , active BIT NOT NULL DEFAULT 1 +); \ No newline at end of file diff --git a/static/MySQL/1116_tbl_DOG_User.sql b/static/MySQL/1116_tbl_DOG_User.sql new file mode 100644 index 0000000..850b9de --- /dev/null +++ b/static/MySQL/1116_tbl_DOG_User.sql @@ -0,0 +1,29 @@ + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_User' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_User ( + id_user INT NOT NULL AUTO_INCREMENT PRIMARY KEY + , id_user_auth0 VARCHAR(200) + , firstname VARCHAR(250) + , surname VARCHAR(250) + , email VARCHAR(254) + , is_email_verified BIT NOT NULL DEFAULT 0 + , is_super_user BIT NOT NULL DEFAULT 0 + , active BIT NOT NULL DEFAULT 1 + , created_on DATETIME + , id_user_created_by INT + , CONSTRAINT FK_DOG_User_id_user_created_by + FOREIGN KEY (id_user_created_by) + REFERENCES parts.DOG_User(id_user) + , id_change_set INT + , CONSTRAINT FK_DOG_User_id_change_set + FOREIGN KEY (id_change_set) + REFERENCES parts.DOG_User_Change_Set(id_change_set) +); diff --git a/static/MySQL/1118_tbl_DOG_User_Audit.sql b/static/MySQL/1118_tbl_DOG_User_Audit.sql new file mode 100644 index 0000000..189d9df --- /dev/null +++ b/static/MySQL/1118_tbl_DOG_User_Audit.sql @@ -0,0 +1,24 @@ + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_User_Audit' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_User_Audit ( + id_audit INT NOT NULL AUTO_INCREMENT PRIMARY KEY + , id_user INT NOT NULL + , CONSTRAINT FK_DOG_User_Audit_id_user + FOREIGN KEY (id_user) + REFERENCES parts.DOG_User(id_user) + , name_field VARCHAR(100) NOT NULL + , value_prev VARCHAR(500) + , value_new VARCHAR(500) + , id_change_set INT NOT NULL + , CONSTRAINT FK_DOG_User_Audit_id_change_set + FOREIGN KEY (id_change_set) + REFERENCES parts.DOG_User_Change_Set(id_change_set) +); \ No newline at end of file diff --git a/static/MySQL/1119_tbl_DOG_User_Temp.sql b/static/MySQL/1119_tbl_DOG_User_Temp.sql new file mode 100644 index 0000000..541daa7 --- /dev/null +++ b/static/MySQL/1119_tbl_DOG_User_Temp.sql @@ -0,0 +1,22 @@ + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_User_Temp' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_User_Temp ( + id_temp INT NOT NULL AUTO_INCREMENT PRIMARY KEY + , id_user INT NOT NULL + , id_user_auth0 VARCHAR(200) + , firstname VARCHAR(250) + , surname VARCHAR(250) + , email VARCHAR(254) + , is_email_verified BIT + , is_super_user BIT + , active BIT + , guid BINARY(36) NOT NULL +); diff --git a/static/MySQL/1120_tbl_DOG_Role.sql b/static/MySQL/1120_tbl_DOG_Role.sql new file mode 100644 index 0000000..70be93d --- /dev/null +++ b/static/MySQL/1120_tbl_DOG_Role.sql @@ -0,0 +1,26 @@ + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Role' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Role ( + id_role INT NOT NULL AUTO_INCREMENT PRIMARY KEY + , code VARCHAR(100) + , name VARCHAR(250) + , display_order INT NOT NULL + , active BIT NOT NULL DEFAULT 1 + , created_on DATETIME + , id_user_created_by INT + , CONSTRAINT FK_DOG_Role_id_user_created_by + FOREIGN KEY (id_user_created_by) + REFERENCES parts.DOG_User(id_user) + , id_change_set INT + , CONSTRAINT FK_DOG_Role_id_change_set + FOREIGN KEY (id_change_set) + REFERENCES parts.DOG_User_Change_Set(id_change_set) +); \ No newline at end of file diff --git a/static/MySQL/1121_tbl_DOG_Role_Audit.sql b/static/MySQL/1121_tbl_DOG_Role_Audit.sql new file mode 100644 index 0000000..e27c850 --- /dev/null +++ b/static/MySQL/1121_tbl_DOG_Role_Audit.sql @@ -0,0 +1,24 @@ + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Role_Audit' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Role_Audit ( + id_audit INT NOT NULL AUTO_INCREMENT PRIMARY KEY + , id_role INT NOT NULL + , CONSTRAINT FK_DOG_Role_Audit_id_role + FOREIGN KEY (id_role) + REFERENCES parts.DOG_Role(id_role) + , name_field VARCHAR(100) NOT NULL + , value_prev VARCHAR(500) + , value_new VARCHAR(500) + , id_change_set INT NOT NULL + , CONSTRAINT FK_DOG_Role_Audit_id_change_set + FOREIGN KEY (id_change_set) + REFERENCES parts.DOG_User_Change_Set(id_change_set) +); \ No newline at end of file diff --git a/static/MySQL/1124_tbl_DOG_Role_Permission_Link.sql b/static/MySQL/1124_tbl_DOG_Role_Permission_Link.sql new file mode 100644 index 0000000..81ca826 --- /dev/null +++ b/static/MySQL/1124_tbl_DOG_Role_Permission_Link.sql @@ -0,0 +1,35 @@ + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Role_Permission_Link' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Role_Permission_Link ( + id_link INT NOT NULL AUTO_INCREMENT PRIMARY KEY + , id_role INT NOT NULL + , CONSTRAINT FK_DOG_Role_Permission_Link_id_role + FOREIGN KEY (id_role) + REFERENCES parts.DOG_Role(id_role) + , id_permission INT NOT NULL + , CONSTRAINT FK_DOG_Role_Permission_Link_id_permission + FOREIGN KEY (id_permission) + REFERENCES parts.DOG_Permission(id_permission) + , id_access_level INT NOT NULL + , CONSTRAINT FK_DOG_Role_Permission_Link_id_access_level + FOREIGN KEY (id_access_level) + REFERENCES parts.DOG_Access_Level(id_access_level) + , active BIT NOT NULL DEFAULT 1 + , created_on DATETIME + , id_user_created_by INT + , CONSTRAINT FK_DOG_Role_Permission_Link_id_user_created_by + FOREIGN KEY (id_user_created_by) + REFERENCES parts.DOG_User(id_user) + , id_change_set INT + , CONSTRAINT FK_DOG_Role_Permission_Link_id_change_set + FOREIGN KEY (id_change_set) + REFERENCES parts.DOG_User_Change_Set(id_change_set) +); \ No newline at end of file diff --git a/static/MySQL/1125_tbl_DOG_Role_Permission_Link_Audit.sql b/static/MySQL/1125_tbl_DOG_Role_Permission_Link_Audit.sql new file mode 100644 index 0000000..8ad4576 --- /dev/null +++ b/static/MySQL/1125_tbl_DOG_Role_Permission_Link_Audit.sql @@ -0,0 +1,23 @@ + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Role_Permission_Link_Audit'; + +CREATE TABLE IF NOT EXISTS parts.DOG_Role_Permission_Link_Audit ( + id_audit INT NOT NULL AUTO_INCREMENT PRIMARY KEY + , id_link INT NOT NULL + , CONSTRAINT FK_DOG_Role_Permission_Link_Audit_id_link + FOREIGN KEY (id_link) + REFERENCES parts.DOG_Role_Permission_Link(id_link) + , name_field VARCHAR(100) NOT NULL + , value_prev VARCHAR(500) + , value_new VARCHAR(500) + , id_change_set INT NOT NULL + , CONSTRAINT FK_DOG_Role_Permission_Link_Audit_id_change_set + FOREIGN KEY (id_change_set) + REFERENCES parts.DOG_User_Change_Set(id_change_set) +); \ No newline at end of file diff --git a/static/MySQL/1128_tbl_DOG_User_Role_Link.sql b/static/MySQL/1128_tbl_DOG_User_Role_Link.sql new file mode 100644 index 0000000..ab869b5 --- /dev/null +++ b/static/MySQL/1128_tbl_DOG_User_Role_Link.sql @@ -0,0 +1,31 @@ + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_User_Role_Link' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_User_Role_Link ( + id_link INT NOT NULL AUTO_INCREMENT PRIMARY KEY + , id_user INT NOT NULL + , CONSTRAINT FK_DOG_User_Role_Link_id_user + FOREIGN KEY (id_user) + REFERENCES parts.DOG_User(id_user) + , id_role INT NOT NULL + , CONSTRAINT FK_DOG_User_Role_Link_id_role + FOREIGN KEY (id_role) + REFERENCES parts.DOG_Role(id_role) + , active BIT NOT NULL DEFAULT 1 + , created_on DATETIME + , id_user_created_by INT + , CONSTRAINT FK_DOG_User_Role_Link_id_user_created_by + FOREIGN KEY (id_user_created_by) + REFERENCES parts.DOG_User(id_user) + , id_change_set INT + , CONSTRAINT FK_DOG_User_Role_Link_id_change_set + FOREIGN KEY (id_change_set) + REFERENCES parts.DOG_User_Change_Set(id_change_set) +); \ No newline at end of file diff --git a/static/MySQL/1129_tbl_DOG_User_Role_Link_Audit.sql b/static/MySQL/1129_tbl_DOG_User_Role_Link_Audit.sql new file mode 100644 index 0000000..5cc791e --- /dev/null +++ b/static/MySQL/1129_tbl_DOG_User_Role_Link_Audit.sql @@ -0,0 +1,24 @@ + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_User_Role_Link_Audit' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_User_Role_Link_Audit ( + id_audit INT NOT NULL AUTO_INCREMENT PRIMARY KEY + , id_link INT NOT NULL + , CONSTRAINT FK_DOG_User_Role_Link_Audit_id_link + FOREIGN KEY (id_link) + REFERENCES parts.DOG_User_Role_Link(id_link) + , name_field VARCHAR(100) NOT NULL + , value_prev VARCHAR(500) + , value_new VARCHAR(500) + , id_change_set INT NOT NULL + , CONSTRAINT FK_DOG_User_Role_Link_Audit_id_change_set + FOREIGN KEY (id_change_set) + REFERENCES parts.DOG_User_Change_Set(id_change_set) +); diff --git a/static/MySQL/1130_tbl_DOG_Calc_User_Temp.sql b/static/MySQL/1130_tbl_DOG_Calc_User_Temp.sql new file mode 100644 index 0000000..2ac3c5c --- /dev/null +++ b/static/MySQL/1130_tbl_DOG_Calc_User_Temp.sql @@ -0,0 +1,22 @@ + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Calc_User_Temp' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Calc_User_Temp ( + guid BINARY(36) NOT NULL + , id_user INT + , id_permission_required INT NOT NULL + , CONSTRAINT FK_DOG_Calc_User_Temp_id_permission_required + FOREIGN KEY (id_permission_required) + REFERENCES parts.DOG_Permission (id_permission) + , priority_access_level_required INT NOT NULL + , is_super_user BIT + , priority_access_level_user INT + , has_access BIT +); \ No newline at end of file diff --git a/static/MySQL/1200_tbl_DOG_Dog_Change_Set.sql b/static/MySQL/1200_tbl_DOG_Dog_Change_Set.sql new file mode 100644 index 0000000..62b0c9f --- /dev/null +++ b/static/MySQL/1200_tbl_DOG_Dog_Change_Set.sql @@ -0,0 +1,19 @@ + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Dog_Change_Set' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Dog_Change_Set ( + id_change_set INT NOT NULL AUTO_INCREMENT PRIMARY KEY + , comment VARCHAR(500) + , updated_last_on DATETIME + , id_user_updated_last_by INT + , CONSTRAINT FK_DOG_Role_id_user_updated_last_by + FOREIGN KEY (id_user_updated_last_by) + REFERENCES parts.DOG_User(id_user) +); \ No newline at end of file diff --git a/static/MySQL/1201_tbl_DOG_Dog.sql b/static/MySQL/1201_tbl_DOG_Dog.sql new file mode 100644 index 0000000..eb02028 --- /dev/null +++ b/static/MySQL/1201_tbl_DOG_Dog.sql @@ -0,0 +1,27 @@ + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Dog' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Dog ( + id_dog INT NOT NULL AUTO_INCREMENT PRIMARY KEY + , name VARCHAR(250) NOT NULL + , appearance VARCHAR(1000) + , mass_kg DECIMAL(7, 3) + , notes TEXT + , active BIT NOT NULL DEFAULT 1 + , created_on DATETIME + , id_user_created_by INT + , CONSTRAINT FK_DOG_Dog_id_user_created_by + FOREIGN KEY (id_user_created_by) + REFERENCES parts.DOG_User(id_user) + , id_change_set INT + , CONSTRAINT FK_DOG_Dog_id_change_set + FOREIGN KEY (id_change_set) + REFERENCES parts.DOG_Dog_Change_Set(id_change_set) +); diff --git a/static/MySQL/1202_tbl_DOG_Dog_Audit.sql b/static/MySQL/1202_tbl_DOG_Dog_Audit.sql new file mode 100644 index 0000000..c584706 --- /dev/null +++ b/static/MySQL/1202_tbl_DOG_Dog_Audit.sql @@ -0,0 +1,24 @@ + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Dog_Audit' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Dog_Audit ( + id_audit INT NOT NULL AUTO_INCREMENT PRIMARY KEY + , id_dog INT NOT NULL + , CONSTRAINT FK_DOG_Dog_Audit_id_dog + FOREIGN KEY (id_dog) + REFERENCES parts.DOG_Dog(id_dog) + , name_field VARCHAR(100) NOT NULL + , value_prev TEXT + , value_new TEXT + , id_change_set INT NOT NULL + , CONSTRAINT FK_DOG_Dog_Audit_id_change_set + FOREIGN KEY (id_change_set) + REFERENCES parts.DOG_Dog_Change_Set(id_change_set) +); diff --git a/static/MySQL/1203_tbl_DOG_Dog_Temp.sql b/static/MySQL/1203_tbl_DOG_Dog_Temp.sql new file mode 100644 index 0000000..1b7705b --- /dev/null +++ b/static/MySQL/1203_tbl_DOG_Dog_Temp.sql @@ -0,0 +1,20 @@ + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Dog_Temp' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Dog_Temp ( + id_temp INT NOT NULL PRIMARY KEY AUTO_INCREMENT + , id_dog INT + , name VARCHAR(250) + , appearance VARCHAR(1000) + , mass_kg DECIMAL(7, 3) + , notes TEXT + , active BIT + , guid BINARY(36) +); diff --git a/static/MySQL/1205_tbl_DOG_Breed.sql b/static/MySQL/1205_tbl_DOG_Breed.sql new file mode 100644 index 0000000..298c693 --- /dev/null +++ b/static/MySQL/1205_tbl_DOG_Breed.sql @@ -0,0 +1,25 @@ + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Breed' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Breed ( + id_breed INT NOT NULL AUTO_INCREMENT PRIMARY KEY + , code VARCHAR(100) NOT NULL + , name VARCHAR(250) NOT NULL + , active BIT NOT NULL DEFAULT 1 + , created_on DATETIME + , id_user_created_by INT + , CONSTRAINT FK_DOG_Breed_id_user_created_by + FOREIGN KEY (id_user_created_by) + REFERENCES parts.DOG_User(id_user) + , id_change_set INT + , CONSTRAINT FK_DOG_Breed_id_change_set + FOREIGN KEY (id_change_set) + REFERENCES parts.DOG_Dog_Change_Set(id_change_set) +); diff --git a/static/MySQL/1206_tbl_DOG_Breed_Audit.sql b/static/MySQL/1206_tbl_DOG_Breed_Audit.sql new file mode 100644 index 0000000..1690045 --- /dev/null +++ b/static/MySQL/1206_tbl_DOG_Breed_Audit.sql @@ -0,0 +1,24 @@ + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Breed_Audit' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Breed_Audit ( + id_audit INT NOT NULL AUTO_INCREMENT PRIMARY KEY + , id_breed INT NOT NULL + , CONSTRAINT FK_DOG_Breed_Audit_id_breed + FOREIGN KEY (id_breed) + REFERENCES parts.DOG_Breed(id_breed) + , name_field VARCHAR(100) NOT NULL + , value_prev TEXT + , value_new TEXT + , id_change_set INT NOT NULL + , CONSTRAINT FK_DOG_Breed_Audit_id_change_set + FOREIGN KEY (id_change_set) + REFERENCES parts.DOG_Dog_Change_Set(id_change_set) +); diff --git a/static/MySQL/1207_tbl_DOG_Breed_Temp.sql b/static/MySQL/1207_tbl_DOG_Breed_Temp.sql new file mode 100644 index 0000000..e60db87 --- /dev/null +++ b/static/MySQL/1207_tbl_DOG_Breed_Temp.sql @@ -0,0 +1,18 @@ + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Breed_Temp' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Breed_Temp ( + id_temp INT NOT NULL PRIMARY KEY AUTO_INCREMENT + , id_breed INT + , code VARCHAR(100) + , name VARCHAR(250) + , active BIT + , guid BINARY(36) +); diff --git a/static/MySQL/1209_tbl_DOG_Dog_Breed_Link.sql b/static/MySQL/1209_tbl_DOG_Dog_Breed_Link.sql new file mode 100644 index 0000000..9b05f8e --- /dev/null +++ b/static/MySQL/1209_tbl_DOG_Dog_Breed_Link.sql @@ -0,0 +1,32 @@ + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Dog_Breed_Link' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Dog_Breed_Link ( + id_link INT NOT NULL AUTO_INCREMENT PRIMARY KEY + , id_dog INT NOT NULL + , CONSTRAINT FK_DOG_Dog_Breed_Link_id_dog + FOREIGN KEY (id_dog) + REFERENCES parts.DOG_Dog(id_dog) + , id_breed INT NOT NULL + , CONSTRAINT FK_DOG_Dog_Breed_Link_id_breed + FOREIGN KEY (id_breed) + REFERENCES parts.DOG_Breed(id_breed) + , lineage_ratio DECIMAL(5, 4) NOT NULL + , active BIT NOT NULL DEFAULT 1 + , created_on DATETIME + , id_user_created_by INT + , CONSTRAINT FK_DOG_Dog_Breed_Link_id_user_created_by + FOREIGN KEY (id_user_created_by) + REFERENCES parts.DOG_User(id_user) + , id_change_set INT + , CONSTRAINT FK_DOG_Dog_Breed_Link_id_change_set + FOREIGN KEY (id_change_set) + REFERENCES parts.DOG_Dog_Change_Set(id_change_set) +); diff --git a/static/MySQL/1210_tbl_DOG_Dog_Breed_Link_Audit.sql b/static/MySQL/1210_tbl_DOG_Dog_Breed_Link_Audit.sql new file mode 100644 index 0000000..db17b9a --- /dev/null +++ b/static/MySQL/1210_tbl_DOG_Dog_Breed_Link_Audit.sql @@ -0,0 +1,24 @@ + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Dog_Breed_Link_Audit' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Dog_Breed_Link_Audit ( + id_audit INT NOT NULL AUTO_INCREMENT PRIMARY KEY + , id_link INT NOT NULL + , CONSTRAINT FK_DOG_Dog_Breed_Link_Audit_id_link + FOREIGN KEY (id_link) + REFERENCES parts.DOG_Dog_Breed_Link(id_link) + , name_field VARCHAR(100) NOT NULL + , value_prev TEXT + , value_new TEXT + , id_change_set INT NOT NULL + , CONSTRAINT FK_DOG_Dog_Breed_Link_Audit_id_change_set + FOREIGN KEY (id_change_set) + REFERENCES parts.DOG_Dog_Change_Set(id_change_set) +); diff --git a/static/MySQL/1211_tbl_DOG_Dog_Breed_Link_Temp.sql b/static/MySQL/1211_tbl_DOG_Dog_Breed_Link_Temp.sql new file mode 100644 index 0000000..bd959e3 --- /dev/null +++ b/static/MySQL/1211_tbl_DOG_Dog_Breed_Link_Temp.sql @@ -0,0 +1,19 @@ + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Dog_Breed_Link_Temp' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Dog_Breed_Link_Temp ( + id_temp INT NOT NULL PRIMARY KEY AUTO_INCREMENT + , id_link INT + , id_dog INT + , id_breed INT + , lineage_ratio DECIMAL(5, 4) + , active BIT + , guid BINARY(36) +); diff --git a/static/MySQL/1213_0_tbl_DOG_Understanding_Level.sql b/static/MySQL/1213_0_tbl_DOG_Understanding_Level.sql new file mode 100644 index 0000000..9260320 --- /dev/null +++ b/static/MySQL/1213_0_tbl_DOG_Understanding_Level.sql @@ -0,0 +1,25 @@ + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Understanding_Level' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Understanding_Level ( + id_understanding_level INT NOT NULL AUTO_INCREMENT PRIMARY KEY + , code VARCHAR(100) NOT NULL + , name VARCHAR(250) NOT NULL + , active BIT NOT NULL DEFAULT 1 + , created_on DATETIME + , id_user_created_by INT + , CONSTRAINT FK_DOG_Understanding_Level_id_user_created_by + FOREIGN KEY (id_user_created_by) + REFERENCES parts.DOG_User(id_user) + , id_change_set INT + , CONSTRAINT FK_DOG_Understanding_Level_id_change_set + FOREIGN KEY (id_change_set) + REFERENCES parts.DOG_Dog_Change_Set(id_change_set) +); diff --git a/static/MySQL/1213_1_tbl_DOG_Understanding_Level_Audit.sql b/static/MySQL/1213_1_tbl_DOG_Understanding_Level_Audit.sql new file mode 100644 index 0000000..aee6d3e --- /dev/null +++ b/static/MySQL/1213_1_tbl_DOG_Understanding_Level_Audit.sql @@ -0,0 +1,24 @@ + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Understanding_Level_Audit' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Understanding_Level_Audit ( + id_audit INT NOT NULL AUTO_INCREMENT PRIMARY KEY + , id_understanding_level INT NOT NULL + , CONSTRAINT FK_DOG_Understanding_Level_Audit_id_understanding_level + FOREIGN KEY (id_understanding_level) + REFERENCES parts.DOG_Understanding_Level(id_understanding_level) + , name_field VARCHAR(100) NOT NULL + , value_prev TEXT + , value_new TEXT + , id_change_set INT NOT NULL + , CONSTRAINT FK_DOG_Understanding_Level_Audit_id_change_set + FOREIGN KEY (id_change_set) + REFERENCES parts.DOG_Dog_Change_Set(id_change_set) +); diff --git a/static/MySQL/1213_2_tbl_DOG_Understanding_Level_Temp.sql b/static/MySQL/1213_2_tbl_DOG_Understanding_Level_Temp.sql new file mode 100644 index 0000000..9c71779 --- /dev/null +++ b/static/MySQL/1213_2_tbl_DOG_Understanding_Level_Temp.sql @@ -0,0 +1,18 @@ + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Understanding_Level_Temp' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Understanding_Level_Temp ( + id_temp INT NOT NULL PRIMARY KEY AUTO_INCREMENT + , id_understanding_level INT + , code VARCHAR(100) + , name VARCHAR(250) + , active BIT + , guid BINARY(36) +); diff --git a/static/MySQL/1213_tbl_DOG_Obedience_Level.sql b/static/MySQL/1213_tbl_DOG_Obedience_Level.sql new file mode 100644 index 0000000..08b531c --- /dev/null +++ b/static/MySQL/1213_tbl_DOG_Obedience_Level.sql @@ -0,0 +1,25 @@ + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Obedience_Level' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Obedience_Level ( + id_obedience_level INT NOT NULL AUTO_INCREMENT PRIMARY KEY + , code VARCHAR(100) NOT NULL + , name VARCHAR(250) NOT NULL + , active BIT NOT NULL DEFAULT 1 + , created_on DATETIME + , id_user_created_by INT + , CONSTRAINT FK_DOG_Obedience_Level_id_user_created_by + FOREIGN KEY (id_user_created_by) + REFERENCES parts.DOG_User(id_user) + , id_change_set INT + , CONSTRAINT FK_DOG_Obedience_Level_id_change_set + FOREIGN KEY (id_change_set) + REFERENCES parts.DOG_Dog_Change_Set(id_change_set) +); diff --git a/static/MySQL/1214_tbl_DOG_Obedience_Level_Audit.sql b/static/MySQL/1214_tbl_DOG_Obedience_Level_Audit.sql new file mode 100644 index 0000000..5db92fb --- /dev/null +++ b/static/MySQL/1214_tbl_DOG_Obedience_Level_Audit.sql @@ -0,0 +1,24 @@ + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Obedience_Level_Audit' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Obedience_Level_Audit ( + id_audit INT NOT NULL AUTO_INCREMENT PRIMARY KEY + , id_obedience_level INT NOT NULL + , CONSTRAINT FK_DOG_Obedience_Level_Audit_id_obedience_level + FOREIGN KEY (id_obedience_level) + REFERENCES parts.DOG_Obedience_Level(id_obedience_level) + , name_field VARCHAR(100) NOT NULL + , value_prev TEXT + , value_new TEXT + , id_change_set INT NOT NULL + , CONSTRAINT FK_DOG_Obedience_Level_Audit_id_change_set + FOREIGN KEY (id_change_set) + REFERENCES parts.DOG_Dog_Change_Set(id_change_set) +); diff --git a/static/MySQL/1215_tbl_DOG_Obedience_Level_Temp.sql b/static/MySQL/1215_tbl_DOG_Obedience_Level_Temp.sql new file mode 100644 index 0000000..fc9aab4 --- /dev/null +++ b/static/MySQL/1215_tbl_DOG_Obedience_Level_Temp.sql @@ -0,0 +1,18 @@ + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Obedience_Level_Temp' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Obedience_Level_Temp ( + id_temp INT NOT NULL PRIMARY KEY AUTO_INCREMENT + , id_obedience_level INT + , code VARCHAR(100) + , name VARCHAR(250) + , active BIT + , guid BINARY(36) +); diff --git a/static/MySQL/1217_tbl_DOG_Command_Category.sql b/static/MySQL/1217_tbl_DOG_Command_Category.sql new file mode 100644 index 0000000..8c029f9 --- /dev/null +++ b/static/MySQL/1217_tbl_DOG_Command_Category.sql @@ -0,0 +1,25 @@ + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Command_Category' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Command_Category ( + id_command_category INT NOT NULL AUTO_INCREMENT PRIMARY KEY + , code VARCHAR(100) NOT NULL + , name VARCHAR(250) NOT NULL + , active BIT NOT NULL DEFAULT 1 + , created_on DATETIME + , id_user_created_by INT + , CONSTRAINT FK_DOG_Command_Category_id_user_created_by + FOREIGN KEY (id_user_created_by) + REFERENCES parts.DOG_User(id_user) + , id_change_set INT + , CONSTRAINT FK_DOG_Command_Category_id_change_set + FOREIGN KEY (id_change_set) + REFERENCES parts.DOG_Dog_Change_Set(id_change_set) +); diff --git a/static/MySQL/1218_tbl_DOG_Command_Category_Audit.sql b/static/MySQL/1218_tbl_DOG_Command_Category_Audit.sql new file mode 100644 index 0000000..599637c --- /dev/null +++ b/static/MySQL/1218_tbl_DOG_Command_Category_Audit.sql @@ -0,0 +1,24 @@ + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Command_Category_Audit' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Command_Category_Audit ( + id_audit INT NOT NULL AUTO_INCREMENT PRIMARY KEY + , id_command_category INT NOT NULL + , CONSTRAINT FK_DOG_Command_Category_Audit_id_command_category + FOREIGN KEY (id_command_category) + REFERENCES parts.DOG_Command_Category(id_command_category) + , name_field VARCHAR(100) NOT NULL + , value_prev TEXT + , value_new TEXT + , id_change_set INT NOT NULL + , CONSTRAINT FK_DOG_Command_Category_Audit_id_change_set + FOREIGN KEY (id_change_set) + REFERENCES parts.DOG_Dog_Change_Set(id_change_set) +); diff --git a/static/MySQL/1219_tbl_DOG_Command_Category_Temp.sql b/static/MySQL/1219_tbl_DOG_Command_Category_Temp.sql new file mode 100644 index 0000000..ad64d87 --- /dev/null +++ b/static/MySQL/1219_tbl_DOG_Command_Category_Temp.sql @@ -0,0 +1,18 @@ + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Command_Category_Temp' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Command_Category_Temp ( + id_temp INT NOT NULL PRIMARY KEY AUTO_INCREMENT + , id_command_category INT + , code VARCHAR(100) + , name VARCHAR(250) + , active BIT + , guid BINARY(36) +); \ No newline at end of file diff --git a/static/MySQL/1221_tbl_DOG_Command.sql b/static/MySQL/1221_tbl_DOG_Command.sql new file mode 100644 index 0000000..ea887e8 --- /dev/null +++ b/static/MySQL/1221_tbl_DOG_Command.sql @@ -0,0 +1,31 @@ + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Command' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Command ( + id_command INT NOT NULL AUTO_INCREMENT PRIMARY KEY + , id_command_category INT NOT NULL + , CONSTRAINT FK_DOG_Command_id_command_category + FOREIGN KEY (id_command_category) + REFERENCES parts.DOG_Command_Category(id_command_category) + , name VARCHAR(250) NOT NULL + , hand_signal_default_description TEXT + , can_have_button BIT NOT NULL DEFAULT 0 + , notes TEXT + , active BIT NOT NULL DEFAULT 1 + , created_on DATETIME + , id_user_created_by INT + , CONSTRAINT FK_DOG_Command_id_user_created_by + FOREIGN KEY (id_user_created_by) + REFERENCES parts.DOG_User(id_user) + , id_change_set INT + , CONSTRAINT FK_DOG_Command_id_change_set + FOREIGN KEY (id_change_set) + REFERENCES parts.DOG_Dog_Change_Set(id_change_set) +); diff --git a/static/MySQL/1222_tbl_DOG_Command_Audit.sql b/static/MySQL/1222_tbl_DOG_Command_Audit.sql new file mode 100644 index 0000000..6c42cb6 --- /dev/null +++ b/static/MySQL/1222_tbl_DOG_Command_Audit.sql @@ -0,0 +1,24 @@ + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Command_Audit' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Command_Audit ( + id_audit INT NOT NULL AUTO_INCREMENT PRIMARY KEY + , id_command INT NOT NULL + , CONSTRAINT FK_DOG_Command_Audit_id_command + FOREIGN KEY (id_command) + REFERENCES parts.DOG_Command(id_command) + , name_field VARCHAR(100) NOT NULL + , value_prev TEXT + , value_new TEXT + , id_change_set INT NOT NULL + , CONSTRAINT FK_DOG_Command_Audit_id_change_set + FOREIGN KEY (id_change_set) + REFERENCES parts.DOG_Dog_Change_Set(id_change_set) +); diff --git a/static/MySQL/1223_tbl_DOG_Command_Temp.sql b/static/MySQL/1223_tbl_DOG_Command_Temp.sql new file mode 100644 index 0000000..65bf367 --- /dev/null +++ b/static/MySQL/1223_tbl_DOG_Command_Temp.sql @@ -0,0 +1,23 @@ + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Command_Temp' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Command_Temp ( + id_temp INT NOT NULL PRIMARY KEY AUTO_INCREMENT + , id_command INT + , id_command_category INT + , name VARCHAR(250) + , hand_signal_default_description TEXT + , can_have_button BIT + , notes TEXT + , active BIT + , guid BINARY(36) + + , name_command_category VARCHAR(250) +); diff --git a/static/MySQL/1225_tbl_DOG_Dog_Command_Link.sql b/static/MySQL/1225_tbl_DOG_Dog_Command_Link.sql new file mode 100644 index 0000000..3df793b --- /dev/null +++ b/static/MySQL/1225_tbl_DOG_Dog_Command_Link.sql @@ -0,0 +1,42 @@ + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Dog_Command_Link' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Dog_Command_Link ( + id_link INT NOT NULL AUTO_INCREMENT PRIMARY KEY + , id_dog INT NOT NULL + , CONSTRAINT FK_DOG_Dog_Command_Link_id_dog + FOREIGN KEY (id_dog) + REFERENCES parts.DOG_Dog(id_dog) + , id_command INT NOT NULL + , CONSTRAINT FK_DOG_Dog_Command_Link_id_command + FOREIGN KEY (id_command) + REFERENCES parts.DOG_Command(id_command) + , id_understanding_level INT NOT NULL + , CONSTRAINT FK_DOG_Dog_Command_Link_id_understanding_level + FOREIGN KEY (id_understanding_level) + REFERENCES parts.DOG_Understanding_Level(id_understanding_level) + , id_obedience_level INT NOT NULL + , CONSTRAINT FK_DOG_Dog_Command_Link_id_obedience_level + FOREIGN KEY (id_obedience_level) + REFERENCES parts.DOG_Obedience_Level(id_obedience_level) + , hand_signal_description TEXT + , notes TEXT +-- , has_button BIT NOT NULL DEFAULT 0 + , active BIT NOT NULL DEFAULT 1 + , created_on DATETIME + , id_user_created_by INT + , CONSTRAINT FK_DOG_Dog_Command_Link_id_user_created_by + FOREIGN KEY (id_user_created_by) + REFERENCES parts.DOG_User(id_user) + , id_change_set INT + , CONSTRAINT FK_DOG_Dog_Command_Link_id_change_set + FOREIGN KEY (id_change_set) + REFERENCES parts.DOG_Dog_Change_Set(id_change_set) +); diff --git a/static/MySQL/1226_tbl_DOG_Dog_Command_Link_Audit.sql b/static/MySQL/1226_tbl_DOG_Dog_Command_Link_Audit.sql new file mode 100644 index 0000000..f0f43e0 --- /dev/null +++ b/static/MySQL/1226_tbl_DOG_Dog_Command_Link_Audit.sql @@ -0,0 +1,24 @@ + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Dog_Command_Link_Audit' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Dog_Command_Link_Audit ( + id_audit INT NOT NULL AUTO_INCREMENT PRIMARY KEY + , id_link INT NOT NULL + , CONSTRAINT FK_DOG_Dog_Command_Link_Audit_id_link + FOREIGN KEY (id_link) + REFERENCES parts.DOG_Dog_Command_Link(id_link) + , name_field VARCHAR(100) NOT NULL + , value_prev TEXT + , value_new TEXT + , id_change_set INT NOT NULL + , CONSTRAINT FK_DOG_Dog_Command_Link_Audit_id_change_set + FOREIGN KEY (id_change_set) + REFERENCES parts.DOG_Dog_Change_Set(id_change_set) +); diff --git a/static/MySQL/1227_tbl_DOG_Dog_Command_Link_Temp.sql b/static/MySQL/1227_tbl_DOG_Dog_Command_Link_Temp.sql new file mode 100644 index 0000000..236d7ee --- /dev/null +++ b/static/MySQL/1227_tbl_DOG_Dog_Command_Link_Temp.sql @@ -0,0 +1,23 @@ + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Dog_Command_Link_Temp' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Dog_Command_Link_Temp ( + id_temp INT NOT NULL PRIMARY KEY AUTO_INCREMENT + , id_link INT + , id_dog INT + , id_command INT + , id_understanding_level INT + , id_obedience_level INT + , hand_signal_description TEXT + , notes TEXT +-- , has_button BIT + , active BIT + , guid BINARY(36) +); diff --git a/static/MySQL/1229_0_tbl_DOG_Personal_Best.sql b/static/MySQL/1229_0_tbl_DOG_Personal_Best.sql new file mode 100644 index 0000000..97a8661 --- /dev/null +++ b/static/MySQL/1229_0_tbl_DOG_Personal_Best.sql @@ -0,0 +1,31 @@ + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Personal_Best' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Personal_Best ( + id_personal_best INT NOT NULL AUTO_INCREMENT PRIMARY KEY + , id_dog_command_link INT NOT NULL + , CONSTRAINT FK_DOG_Personal_Best_id_dog_command_link + FOREIGN KEY (id_dog_command_link) + REFERENCES parts.DOG_Dog_Command_Link(id_link) + , is_achieved_using_button BIT NOT NULL DEFAULT 0 + , situation TEXT NOT NULL + , duration_seconds INT + , quantity INT + , active BIT NOT NULL DEFAULT 1 + , created_on DATETIME + , id_user_created_by INT + , CONSTRAINT FK_DOG_Personal_Best_id_user_created_by + FOREIGN KEY (id_user_created_by) + REFERENCES parts.DOG_User(id_user) + , id_change_set INT + , CONSTRAINT FK_DOG_Personal_Best_id_change_set + FOREIGN KEY (id_change_set) + REFERENCES parts.DOG_Dog_Change_Set(id_change_set) +); diff --git a/static/MySQL/1229_1_tbl_DOG_Personal_Best_Audit.sql b/static/MySQL/1229_1_tbl_DOG_Personal_Best_Audit.sql new file mode 100644 index 0000000..69cce9f --- /dev/null +++ b/static/MySQL/1229_1_tbl_DOG_Personal_Best_Audit.sql @@ -0,0 +1,24 @@ + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Personal_Best_Audit' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Personal_Best_Audit ( + id_audit INT NOT NULL AUTO_INCREMENT PRIMARY KEY + , id_personal_best INT NOT NULL + , CONSTRAINT FK_DOG_Personal_Best_Audit_id_personal_best + FOREIGN KEY (id_personal_best) + REFERENCES parts.DOG_Personal_Best(id_personal_best) + , name_field VARCHAR(100) NOT NULL + , value_prev TEXT + , value_new TEXT + , id_change_set INT NOT NULL + , CONSTRAINT FK_DOG_Personal_Best_Audit_id_change_set + FOREIGN KEY (id_change_set) + REFERENCES parts.DOG_Dog_Change_Set(id_change_set) +); diff --git a/static/MySQL/1229_2_tbl_DOG_Personal_Best_Temp.sql b/static/MySQL/1229_2_tbl_DOG_Personal_Best_Temp.sql new file mode 100644 index 0000000..9f34ef0 --- /dev/null +++ b/static/MySQL/1229_2_tbl_DOG_Personal_Best_Temp.sql @@ -0,0 +1,21 @@ + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Personal_Best_Temp' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Personal_Best_Temp ( + id_temp INT NOT NULL PRIMARY KEY AUTO_INCREMENT + , id_personal_best INT + , id_dog_command_link INT + , is_achieved_using_button BIT + , situation TEXT + , duration_seconds INT + , quantity INT + , active BIT + , guid BINARY(36) +); diff --git a/static/MySQL/1229_tbl_DOG_Location.sql b/static/MySQL/1229_tbl_DOG_Location.sql new file mode 100644 index 0000000..21e3e38 --- /dev/null +++ b/static/MySQL/1229_tbl_DOG_Location.sql @@ -0,0 +1,25 @@ + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Location' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Location ( + id_location INT NOT NULL AUTO_INCREMENT PRIMARY KEY + , code VARCHAR(100) NOT NULL + , name VARCHAR(250) NOT NULL + , active BIT NOT NULL DEFAULT 1 + , created_on DATETIME + , id_user_created_by INT + , CONSTRAINT FK_DOG_Location_id_user_created_by + FOREIGN KEY (id_user_created_by) + REFERENCES parts.DOG_User(id_user) + , id_change_set INT + , CONSTRAINT FK_DOG_Location_id_change_set + FOREIGN KEY (id_change_set) + REFERENCES parts.DOG_Dog_Change_Set(id_change_set) +); diff --git a/static/MySQL/1230_tbl_DOG_Location_Audit.sql b/static/MySQL/1230_tbl_DOG_Location_Audit.sql new file mode 100644 index 0000000..02df6ed --- /dev/null +++ b/static/MySQL/1230_tbl_DOG_Location_Audit.sql @@ -0,0 +1,24 @@ + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Location_Audit' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Location_Audit ( + id_audit INT NOT NULL AUTO_INCREMENT PRIMARY KEY + , id_location INT NOT NULL + , CONSTRAINT FK_DOG_Location_Audit_id_location + FOREIGN KEY (id_location) + REFERENCES parts.DOG_Location(id_location) + , name_field VARCHAR(100) NOT NULL + , value_prev TEXT + , value_new TEXT + , id_change_set INT NOT NULL + , CONSTRAINT FK_DOG_Location_Audit_id_change_set + FOREIGN KEY (id_change_set) + REFERENCES parts.DOG_Dog_Change_Set(id_change_set) +); diff --git a/static/MySQL/1231_tbl_DOG_Location_Temp.sql b/static/MySQL/1231_tbl_DOG_Location_Temp.sql new file mode 100644 index 0000000..07bd7b8 --- /dev/null +++ b/static/MySQL/1231_tbl_DOG_Location_Temp.sql @@ -0,0 +1,18 @@ + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Location_Temp' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Location_Temp ( + id_temp INT NOT NULL PRIMARY KEY AUTO_INCREMENT + , id_location INT + , code VARCHAR(100) + , name VARCHAR(250) + , active BIT + , guid BINARY(36) +); diff --git a/static/MySQL/1233_tbl_DOG_Location_Link.sql b/static/MySQL/1233_tbl_DOG_Location_Link.sql new file mode 100644 index 0000000..d410b18 --- /dev/null +++ b/static/MySQL/1233_tbl_DOG_Location_Link.sql @@ -0,0 +1,31 @@ + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Location_Link' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Location_Link ( + id_link INT NOT NULL AUTO_INCREMENT PRIMARY KEY + , id_location_parent INT + , CONSTRAINT FK_DOG_Location_Link_id_location_parent + FOREIGN KEY (id_location_parent) + REFERENCES parts.DOG_Location(id_location) + , id_location_child INT + , CONSTRAINT FK_DOG_Location_Link_id_location_child + FOREIGN KEY (id_location_child) + REFERENCES parts.DOG_Location(id_location) + , active BIT NOT NULL DEFAULT 1 + , created_on DATETIME + , id_user_created_by INT + , CONSTRAINT FK_DOG_Location_Link_id_user_created_by + FOREIGN KEY (id_user_created_by) + REFERENCES parts.DOG_User(id_user) + , id_change_set INT + , CONSTRAINT FK_DOG_Location_Link_id_change_set + FOREIGN KEY (id_change_set) + REFERENCES parts.DOG_Dog_Change_Set(id_change_set) +); diff --git a/static/MySQL/1234_tbl_DOG_Location_Link_Audit.sql b/static/MySQL/1234_tbl_DOG_Location_Link_Audit.sql new file mode 100644 index 0000000..c993dc1 --- /dev/null +++ b/static/MySQL/1234_tbl_DOG_Location_Link_Audit.sql @@ -0,0 +1,24 @@ + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Location_Link_Audit' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Location_Link_Audit ( + id_audit INT NOT NULL AUTO_INCREMENT PRIMARY KEY + , id_link INT NOT NULL + , CONSTRAINT FK_DOG_Location_Link_Audit_id_link + FOREIGN KEY (id_link) + REFERENCES parts.DOG_Location_Link(id_link) + , name_field VARCHAR(100) NOT NULL + , value_prev TEXT + , value_new TEXT + , id_change_set INT NOT NULL + , CONSTRAINT FK_DOG_Location_Link_Audit_id_change_set + FOREIGN KEY (id_change_set) + REFERENCES parts.DOG_Dog_Change_Set(id_change_set) +); diff --git a/static/MySQL/1235_tbl_DOG_Location_Link_Temp.sql b/static/MySQL/1235_tbl_DOG_Location_Link_Temp.sql new file mode 100644 index 0000000..b659c54 --- /dev/null +++ b/static/MySQL/1235_tbl_DOG_Location_Link_Temp.sql @@ -0,0 +1,18 @@ + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Location_Link_Temp' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Location_Link_Temp ( + id_temp INT NOT NULL PRIMARY KEY AUTO_INCREMENT + , id_link INT + , id_location_parent INT + , id_location_child INT + , active BIT + , guid BINARY(36) +); diff --git a/static/MySQL/1237_tbl_DOG_Colour.sql b/static/MySQL/1237_tbl_DOG_Colour.sql new file mode 100644 index 0000000..c246452 --- /dev/null +++ b/static/MySQL/1237_tbl_DOG_Colour.sql @@ -0,0 +1,25 @@ + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Colour' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Colour ( + id_colour INT NOT NULL AUTO_INCREMENT PRIMARY KEY + , code VARCHAR(100) NOT NULL + , name VARCHAR(250) NOT NULL + , active BIT NOT NULL DEFAULT 1 + , created_on DATETIME + , id_user_created_by INT + , CONSTRAINT FK_DOG_Colour_id_user_created_by + FOREIGN KEY (id_user_created_by) + REFERENCES parts.DOG_User(id_user) + , id_change_set INT + , CONSTRAINT FK_DOG_Colour_id_change_set + FOREIGN KEY (id_change_set) + REFERENCES parts.DOG_Dog_Change_Set(id_change_set) +); diff --git a/static/MySQL/1238_tbl_DOG_Colour_Audit.sql b/static/MySQL/1238_tbl_DOG_Colour_Audit.sql new file mode 100644 index 0000000..c0a1eb9 --- /dev/null +++ b/static/MySQL/1238_tbl_DOG_Colour_Audit.sql @@ -0,0 +1,24 @@ + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Colour_Audit' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Colour_Audit ( + id_audit INT NOT NULL AUTO_INCREMENT PRIMARY KEY + , id_colour INT NOT NULL + , CONSTRAINT FK_DOG_Colour_Audit_id_colour + FOREIGN KEY (id_colour) + REFERENCES parts.DOG_Colour(id_colour) + , name_field VARCHAR(100) NOT NULL + , value_prev TEXT + , value_new TEXT + , id_change_set INT NOT NULL + , CONSTRAINT FK_DOG_Colour_Audit_id_change_set + FOREIGN KEY (id_change_set) + REFERENCES parts.DOG_Dog_Change_Set(id_change_set) +); diff --git a/static/MySQL/1239_tbl_DOG_Colour_Temp.sql b/static/MySQL/1239_tbl_DOG_Colour_Temp.sql new file mode 100644 index 0000000..4153b41 --- /dev/null +++ b/static/MySQL/1239_tbl_DOG_Colour_Temp.sql @@ -0,0 +1,18 @@ + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Colour_Temp' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Colour_Temp ( + id_temp INT NOT NULL PRIMARY KEY AUTO_INCREMENT + , id_colour INT + , code VARCHAR(100) + , name VARCHAR(250) + , active BIT + , guid BINARY(36) +); diff --git a/static/MySQL/1241_tbl_DOG_Button_Shape.sql b/static/MySQL/1241_tbl_DOG_Button_Shape.sql new file mode 100644 index 0000000..cebceaa --- /dev/null +++ b/static/MySQL/1241_tbl_DOG_Button_Shape.sql @@ -0,0 +1,26 @@ + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Button_Shape' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Button_Shape ( + id_button_shape INT NOT NULL AUTO_INCREMENT PRIMARY KEY + , code VARCHAR(100) NOT NULL + , name VARCHAR(250) NOT NULL + , description TEXT + , active BIT NOT NULL DEFAULT 1 + , created_on DATETIME + , id_user_created_by INT + , CONSTRAINT FK_DOG_Button_Shape_id_user_created_by + FOREIGN KEY (id_user_created_by) + REFERENCES parts.DOG_User(id_user) + , id_change_set INT + , CONSTRAINT FK_DOG_Button_Shape_id_change_set + FOREIGN KEY (id_change_set) + REFERENCES parts.DOG_Dog_Change_Set(id_change_set) +); diff --git a/static/MySQL/1242_tbl_DOG_Button_Shape_Audit.sql b/static/MySQL/1242_tbl_DOG_Button_Shape_Audit.sql new file mode 100644 index 0000000..8780a53 --- /dev/null +++ b/static/MySQL/1242_tbl_DOG_Button_Shape_Audit.sql @@ -0,0 +1,24 @@ + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Button_Shape_Audit' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Button_Shape_Audit ( + id_audit INT NOT NULL AUTO_INCREMENT PRIMARY KEY + , id_button_shape INT NOT NULL + , CONSTRAINT FK_DOG_Button_Shape_Audit_id_button_shape + FOREIGN KEY (id_button_shape) + REFERENCES parts.DOG_Button_Shape(id_button_shape) + , name_field VARCHAR(100) NOT NULL + , value_prev TEXT + , value_new TEXT + , id_change_set INT NOT NULL + , CONSTRAINT FK_DOG_Button_Shape_Audit_id_change_set + FOREIGN KEY (id_change_set) + REFERENCES parts.DOG_Dog_Change_Set(id_change_set) +); diff --git a/static/MySQL/1243_tbl_DOG_Button_Shape_Temp.sql b/static/MySQL/1243_tbl_DOG_Button_Shape_Temp.sql new file mode 100644 index 0000000..2c1b783 --- /dev/null +++ b/static/MySQL/1243_tbl_DOG_Button_Shape_Temp.sql @@ -0,0 +1,19 @@ + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Button_Shape_Temp' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Button_Shape_Temp ( + id_temp INT NOT NULL PRIMARY KEY AUTO_INCREMENT + , id_button_shape INT + , code VARCHAR(100) + , name VARCHAR(250) + , description TEXT + , active BIT + , guid BINARY(36) +); diff --git a/static/MySQL/1245_tbl_DOG_Image.sql b/static/MySQL/1245_tbl_DOG_Image.sql new file mode 100644 index 0000000..3e36b47 --- /dev/null +++ b/static/MySQL/1245_tbl_DOG_Image.sql @@ -0,0 +1,33 @@ + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Image' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Image ( + id_image INT NOT NULL AUTO_INCREMENT PRIMARY KEY + , id_file_type INT NOT NULL + , CONSTRAINT FK_DOG_Image_id_file_type + FOREIGN KEY (id_file_type) + REFERENCES parts.CORE_File_Type(id_file_type) + , id_dog INT + , CONSTRAINT FK_DOG_Image_id_dog + FOREIGN KEY (id_dog) + REFERENCES parts.DOG_Dog(id_dog) + , path VARCHAR(1024) NOT NULL + , display_order INT + , active BIT NOT NULL DEFAULT 1 + , created_on DATETIME + , id_user_created_by INT + , CONSTRAINT FK_DOG_Image_id_user_created_by + FOREIGN KEY (id_user_created_by) + REFERENCES parts.DOG_User(id_user) + , id_change_set INT + , CONSTRAINT FK_DOG_Image_id_change_set + FOREIGN KEY (id_change_set) + REFERENCES parts.DOG_Dog_Change_Set(id_change_set) +); diff --git a/static/MySQL/1246_tbl_DOG_Image_Audit.sql b/static/MySQL/1246_tbl_DOG_Image_Audit.sql new file mode 100644 index 0000000..566a229 --- /dev/null +++ b/static/MySQL/1246_tbl_DOG_Image_Audit.sql @@ -0,0 +1,24 @@ + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Image_Audit' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Image_Audit ( + id_audit INT NOT NULL AUTO_INCREMENT PRIMARY KEY + , id_image INT NOT NULL + , CONSTRAINT FK_DOG_Image_Audit_id_image + FOREIGN KEY (id_image) + REFERENCES parts.DOG_Image(id_image) + , name_field VARCHAR(100) NOT NULL + , value_prev TEXT + , value_new TEXT + , id_change_set INT NOT NULL + , CONSTRAINT FK_DOG_Image_Audit_id_change_set + FOREIGN KEY (id_change_set) + REFERENCES parts.DOG_Dog_Change_Set(id_change_set) +); diff --git a/static/MySQL/1247_tbl_DOG_Image_Temp.sql b/static/MySQL/1247_tbl_DOG_Image_Temp.sql new file mode 100644 index 0000000..edfddf4 --- /dev/null +++ b/static/MySQL/1247_tbl_DOG_Image_Temp.sql @@ -0,0 +1,20 @@ + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Image_Temp' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Image_Temp ( + id_temp INT NOT NULL PRIMARY KEY AUTO_INCREMENT + , id_image INT + , id_file_type INT NOT NULL + , id_dog INT + , path VARCHAR(1024) NOT NULL + , display_order INT + , active BIT + , guid BINARY(36) +); diff --git a/static/MySQL/1249_tbl_DOG_Button_Icon.sql b/static/MySQL/1249_tbl_DOG_Button_Icon.sql new file mode 100644 index 0000000..668fa8d --- /dev/null +++ b/static/MySQL/1249_tbl_DOG_Button_Icon.sql @@ -0,0 +1,30 @@ + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Button_Icon' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Button_Icon ( + id_button_icon INT NOT NULL AUTO_INCREMENT PRIMARY KEY + , id_image INT + , CONSTRAINT FK_DOG_Button_Icon_id_image + FOREIGN KEY (id_image) + REFERENCES parts.DOG_Image(id_image) + , code VARCHAR(100) NOT NULL + , name VARCHAR(250) NOT NULL + , description TEXT + , active BIT NOT NULL DEFAULT 1 + , created_on DATETIME + , id_user_created_by INT + , CONSTRAINT FK_DOG_Button_Icon_id_user_created_by + FOREIGN KEY (id_user_created_by) + REFERENCES parts.DOG_User(id_user) + , id_change_set INT + , CONSTRAINT FK_DOG_Button_Icon_id_change_set + FOREIGN KEY (id_change_set) + REFERENCES parts.DOG_Dog_Change_Set(id_change_set) +); diff --git a/static/MySQL/1250_tbl_DOG_Button_Icon_Audit.sql b/static/MySQL/1250_tbl_DOG_Button_Icon_Audit.sql new file mode 100644 index 0000000..a8a8698 --- /dev/null +++ b/static/MySQL/1250_tbl_DOG_Button_Icon_Audit.sql @@ -0,0 +1,24 @@ + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Button_Icon_Audit' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Button_Icon_Audit ( + id_audit INT NOT NULL AUTO_INCREMENT PRIMARY KEY + , id_button_icon INT NOT NULL + , CONSTRAINT FK_DOG_Button_Icon_Audit_id_button_icon + FOREIGN KEY (id_button_icon) + REFERENCES parts.DOG_Button_Icon(id_button_icon) + , name_field VARCHAR(100) NOT NULL + , value_prev TEXT + , value_new TEXT + , id_change_set INT NOT NULL + , CONSTRAINT FK_DOG_Button_Icon_Audit_id_change_set + FOREIGN KEY (id_change_set) + REFERENCES parts.DOG_Dog_Change_Set(id_change_set) +); diff --git a/static/MySQL/1251_tbl_DOG_Button_Icon_Temp.sql b/static/MySQL/1251_tbl_DOG_Button_Icon_Temp.sql new file mode 100644 index 0000000..e07bc2d --- /dev/null +++ b/static/MySQL/1251_tbl_DOG_Button_Icon_Temp.sql @@ -0,0 +1,20 @@ + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Button_Icon_Temp' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Button_Icon_Temp ( + id_temp INT NOT NULL PRIMARY KEY AUTO_INCREMENT + , id_button_icon INT + , id_image INT + , code VARCHAR(100) + , name VARCHAR(250) + , description TEXT + , active BIT + , guid BINARY(36) +); diff --git a/static/MySQL/1253_tbl_DOG_Command_Button_Link.sql b/static/MySQL/1253_tbl_DOG_Command_Button_Link.sql new file mode 100644 index 0000000..9911e73 --- /dev/null +++ b/static/MySQL/1253_tbl_DOG_Command_Button_Link.sql @@ -0,0 +1,43 @@ + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Command_Button_Link' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Command_Button_Link ( + id_link INT NOT NULL AUTO_INCREMENT PRIMARY KEY + , id_command INT NOT NULL + , CONSTRAINT FK_DOG_Command_Button_Link_id_command + FOREIGN KEY (id_command) + REFERENCES parts.DOG_Command(id_command) + , id_button_shape INT NOT NULL + , CONSTRAINT FK_DOG_Command_Button_Link_id_button_shape + FOREIGN KEY (id_button_shape) + REFERENCES parts.DOG_Button_Shape(id_button_shape) + , id_button_colour INT NOT NULL + , CONSTRAINT FK_DOG_Command_Button_Link_id_button_colour + FOREIGN KEY (id_button_colour) + REFERENCES parts.DOG_Colour(id_colour) + , id_button_icon INT + , CONSTRAINT FK_DOG_Command_Button_Link_id_button_icon + FOREIGN KEY (id_button_icon) + REFERENCES parts.DOG_Button_Icon(id_button_icon) + , id_location INT NOT NULL + , CONSTRAINT FK_DOG_Command_Button_Link_id_location + FOREIGN KEY (id_location) + REFERENCES parts.DOG_Location(id_location) + , active BIT NOT NULL DEFAULT 1 + , created_on DATETIME + , id_user_created_by INT + , CONSTRAINT FK_DOG_Command_Button_Link_id_user_created_by + FOREIGN KEY (id_user_created_by) + REFERENCES parts.DOG_User(id_user) + , id_change_set INT + , CONSTRAINT FK_DOG_Command_Button_Link_id_change_set + FOREIGN KEY (id_change_set) + REFERENCES parts.DOG_Dog_Change_Set(id_change_set) +); diff --git a/static/MySQL/1254_tbl_DOG_Command_Button_Link_Audit.sql b/static/MySQL/1254_tbl_DOG_Command_Button_Link_Audit.sql new file mode 100644 index 0000000..ece2abe --- /dev/null +++ b/static/MySQL/1254_tbl_DOG_Command_Button_Link_Audit.sql @@ -0,0 +1,24 @@ + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Command_Button_Link_Audit' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Command_Button_Link_Audit ( + id_audit INT NOT NULL AUTO_INCREMENT PRIMARY KEY + , id_link INT NOT NULL + , CONSTRAINT FK_DOG_Command_Button_Link_Audit_id_link + FOREIGN KEY (id_link) + REFERENCES parts.DOG_Command_Button_Link(id_link) + , name_field VARCHAR(100) NOT NULL + , value_prev TEXT + , value_new TEXT + , id_change_set INT NOT NULL + , CONSTRAINT FK_DOG_Command_Button_Link_Audit_id_change_set + FOREIGN KEY (id_change_set) + REFERENCES parts.DOG_Dog_Change_Set(id_change_set) +); diff --git a/static/MySQL/1255_tbl_DOG_Command_Button_Link_Temp.sql b/static/MySQL/1255_tbl_DOG_Command_Button_Link_Temp.sql new file mode 100644 index 0000000..cdf410a --- /dev/null +++ b/static/MySQL/1255_tbl_DOG_Command_Button_Link_Temp.sql @@ -0,0 +1,22 @@ + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Command_Button_Link_Temp' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Command_Button_Link_Temp ( + id_temp INT NOT NULL PRIMARY KEY AUTO_INCREMENT + , id_link INT + , id_command INT + , id_button_shape INT + , id_button_colour INT + , id_button_icon INT + , id_location INT + , has_button BIT + , active BIT + , guid BINARY(36) +); diff --git a/static/MySQL/1257_tbl_DOG_Drive.sql b/static/MySQL/1257_tbl_DOG_Drive.sql new file mode 100644 index 0000000..f344727 --- /dev/null +++ b/static/MySQL/1257_tbl_DOG_Drive.sql @@ -0,0 +1,25 @@ + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Drive' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Drive ( + id_drive INT NOT NULL AUTO_INCREMENT PRIMARY KEY + , code VARCHAR(100) NOT NULL + , name VARCHAR(250) NOT NULL + , active BIT NOT NULL DEFAULT 1 + , created_on DATETIME + , id_user_created_by INT + , CONSTRAINT FK_DOG_Drive_id_user_created_by + FOREIGN KEY (id_user_created_by) + REFERENCES parts.DOG_User(id_user) + , id_change_set INT + , CONSTRAINT FK_DOG_Drive_id_change_set + FOREIGN KEY (id_change_set) + REFERENCES parts.DOG_Dog_Change_Set(id_change_set) +); diff --git a/static/MySQL/1258_tbl_DOG_Drive_Audit.sql b/static/MySQL/1258_tbl_DOG_Drive_Audit.sql new file mode 100644 index 0000000..a35b69e --- /dev/null +++ b/static/MySQL/1258_tbl_DOG_Drive_Audit.sql @@ -0,0 +1,24 @@ + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Drive_Audit' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Drive_Audit ( + id_audit INT NOT NULL AUTO_INCREMENT PRIMARY KEY + , id_drive INT NOT NULL + , CONSTRAINT FK_DOG_Drive_Audit_id_drive + FOREIGN KEY (id_drive) + REFERENCES parts.DOG_Drive(id_drive) + , name_field VARCHAR(100) NOT NULL + , value_prev TEXT + , value_new TEXT + , id_change_set INT NOT NULL + , CONSTRAINT FK_DOG_Drive_Audit_id_change_set + FOREIGN KEY (id_change_set) + REFERENCES parts.DOG_Dog_Change_Set(id_change_set) +); diff --git a/static/MySQL/1259_tbl_DOG_Drive_Temp.sql b/static/MySQL/1259_tbl_DOG_Drive_Temp.sql new file mode 100644 index 0000000..e5b274e --- /dev/null +++ b/static/MySQL/1259_tbl_DOG_Drive_Temp.sql @@ -0,0 +1,18 @@ + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Drive_Temp' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Drive_Temp ( + id_temp INT NOT NULL PRIMARY KEY AUTO_INCREMENT + , id_drive INT + , code VARCHAR(100) + , name VARCHAR(250) + , active BIT + , guid BINARY(36) +); diff --git a/static/MySQL/1261_tbl_DOG_Dog_Drive_Link.sql b/static/MySQL/1261_tbl_DOG_Dog_Drive_Link.sql new file mode 100644 index 0000000..75b7d5c --- /dev/null +++ b/static/MySQL/1261_tbl_DOG_Dog_Drive_Link.sql @@ -0,0 +1,32 @@ + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Dog_Drive_Link' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Dog_Drive_Link ( + id_link INT NOT NULL AUTO_INCREMENT PRIMARY KEY + , id_dog INT NOT NULL + , CONSTRAINT FK_DOG_Dog_Drive_Link_id_dog + FOREIGN KEY (id_dog) + REFERENCES parts.DOG_Dog(id_dog) + , id_drive INT NOT NULL + , CONSTRAINT FK_DOG_Dog_Drive_Link_id_drive + FOREIGN KEY (id_drive) + REFERENCES parts.DOG_Drive(id_drive) + , dominance_ratio DECIMAL(5, 4) + , active BIT NOT NULL DEFAULT 1 + , created_on DATETIME + , id_user_created_by INT + , CONSTRAINT FK_DOG_Dog_Drive_Link_id_user_created_by + FOREIGN KEY (id_user_created_by) + REFERENCES parts.DOG_User(id_user) + , id_change_set INT + , CONSTRAINT FK_DOG_Dog_Drive_Link_id_change_set + FOREIGN KEY (id_change_set) + REFERENCES parts.DOG_Dog_Change_Set(id_change_set) +); diff --git a/static/MySQL/1262_tbl_DOG_Dog_Drive_Link_Audit.sql b/static/MySQL/1262_tbl_DOG_Dog_Drive_Link_Audit.sql new file mode 100644 index 0000000..79824b6 --- /dev/null +++ b/static/MySQL/1262_tbl_DOG_Dog_Drive_Link_Audit.sql @@ -0,0 +1,24 @@ + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Dog_Drive_Link_Audit' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Dog_Drive_Link_Audit ( + id_audit INT NOT NULL AUTO_INCREMENT PRIMARY KEY + , id_link INT NOT NULL + , CONSTRAINT FK_DOG_Dog_Drive_Link_Audit_id_link + FOREIGN KEY (id_link) + REFERENCES parts.DOG_Dog_Drive_Link(id_link) + , name_field VARCHAR(100) NOT NULL + , value_prev TEXT + , value_new TEXT + , id_change_set INT NOT NULL + , CONSTRAINT FK_DOG_Dog_Drive_Link_Audit_id_change_set + FOREIGN KEY (id_change_set) + REFERENCES parts.DOG_Dog_Change_Set(id_change_set) +); diff --git a/static/MySQL/1263_tbl_DOG_Dog_Drive_Link_Temp.sql b/static/MySQL/1263_tbl_DOG_Dog_Drive_Link_Temp.sql new file mode 100644 index 0000000..d6ef920 --- /dev/null +++ b/static/MySQL/1263_tbl_DOG_Dog_Drive_Link_Temp.sql @@ -0,0 +1,19 @@ + +USE parts; + +SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning +FROM INFORMATION_SCHEMA.TABLES +WHERE + TABLE_SCHEMA = 'parts' + AND TABLE_NAME = 'DOG_Dog_Drive_Link_Temp' +; + +CREATE TABLE IF NOT EXISTS parts.DOG_Dog_Drive_Link_Temp ( + id_temp INT NOT NULL PRIMARY KEY AUTO_INCREMENT + , id_link INT + , id_dog INT + , id_drive INT + , dominance_ratio DECIMAL(5, 4) + , active BIT + , guid BINARY(36) +); diff --git a/static/MySQL/3100_tri_DOG_User_Change_Set.sql b/static/MySQL/3100_tri_DOG_User_Change_Set.sql new file mode 100644 index 0000000..f7f0461 --- /dev/null +++ b/static/MySQL/3100_tri_DOG_User_Change_Set.sql @@ -0,0 +1,27 @@ +USE parts; + +DROP TRIGGER IF EXISTS parts.before_insert_DOG_User_Change_Set; + +DELIMITER // +CREATE TRIGGER parts.before_insert_DOG_User_Change_Set +BEFORE INSERT ON parts.DOG_User_Change_Set +FOR EACH ROW +BEGIN + IF NEW.updated_last_on <=> NULL THEN + SET NEW.updated_last_on = NOW(); + END IF; +END // +DELIMITER ; + + +DELIMITER // +CREATE TRIGGER parts.before_update_DOG_User_Change_Set +BEFORE UPDATE ON parts.DOG_User_Change_Set +FOR EACH ROW +BEGIN + IF NOT EXISTS(SELECT * FROM parts.DOG_User WHERE id_user = NEW.id_user_updated_last_by) THEN + SIGNAL SQLSTATE '45000' + SET MESSAGE_TEXT = 'New Updated-Last-By User ID must be provided.'; + END IF; +END // +DELIMITER ; diff --git a/static/MySQL/3116_tri_DOG_User.sql b/static/MySQL/3116_tri_DOG_User.sql new file mode 100644 index 0000000..c93477b --- /dev/null +++ b/static/MySQL/3116_tri_DOG_User.sql @@ -0,0 +1,64 @@ + +USE parts; + +DROP TRIGGER IF EXISTS parts.before_insert_DOG_User; +DROP TRIGGER IF EXISTS parts.before_update_DOG_User; + + +DELIMITER // +CREATE TRIGGER parts.before_insert_DOG_User +BEFORE INSERT ON parts.DOG_User +FOR EACH ROW +BEGIN + SET NEW.created_on := IFNULL(NEW.created_on, NOW()); +END // +DELIMITER ; + + +DELIMITER // +CREATE TRIGGER parts.before_update_DOG_User +BEFORE UPDATE ON parts.DOG_User +FOR EACH ROW +BEGIN + IF OLD.id_change_set <=> NEW.id_change_set THEN + SIGNAL SQLSTATE '45000' + SET MESSAGE_TEXT = 'New change Set ID must be provided.'; + END IF; + + INSERT INTO parts.DOG_User_Audit ( + id_user, + name_field, + value_prev, + value_new, + id_change_set + ) + -- Changed id_user_auth0 + SELECT NEW.id_user, 'id_user_auth0', OLD.id_user_auth0, NEW.id_user_auth0, NEW.id_change_set + WHERE NOT (OLD.id_user_auth0 <=> NEW.id_user_auth0) + UNION + -- Changed firstname + SELECT NEW.id_user, 'firstname', OLD.firstname, NEW.firstname, NEW.id_change_set + WHERE NOT (OLD.firstname <=> NEW.firstname) + UNION + -- Changed surname + SELECT NEW.id_user, 'surname', OLD.surname, NEW.surname, NEW.id_change_set + WHERE NOT (OLD.surname <=> NEW.surname) + UNION + -- Changed email + SELECT NEW.id_user, 'email', OLD.email, NEW.email, NEW.id_change_set + WHERE NOT (OLD.email <=> NEW.email) + UNION + -- Changed is_email_verified + SELECT NEW.id_user, 'is_email_verified', CONVERT(CONVERT(OLD.is_email_verified, SIGNED), CHAR), CONVERT(CONVERT(NEW.is_email_verified, SIGNED), CHAR), NEW.id_change_set + WHERE NOT (OLD.is_email_verified <=> NEW.is_email_verified) + UNION + -- Changed is_super_user + SELECT NEW.id_user, 'is_super_user', CONVERT(CONVERT(OLD.is_super_user, SIGNED), CHAR), CONVERT(CONVERT(NEW.is_super_user, SIGNED), CHAR), NEW.id_change_set + WHERE NOT (OLD.is_super_user <=> NEW.is_super_user) + UNION + -- Changed active + SELECT NEW.id_user, 'active', CONVERT(CONVERT(OLD.active, SIGNED), CHAR), CONVERT(CONVERT(NEW.active, SIGNED), CHAR), NEW.id_change_set + WHERE NOT (OLD.active <=> NEW.active) + ; +END // +DELIMITER ; \ No newline at end of file diff --git a/static/MySQL/3120_tri_DOG_Role.sql b/static/MySQL/3120_tri_DOG_Role.sql new file mode 100644 index 0000000..d23a9fd --- /dev/null +++ b/static/MySQL/3120_tri_DOG_Role.sql @@ -0,0 +1,52 @@ + +USE parts; + +DROP TRIGGER IF EXISTS parts.before_insert_DOG_Role; +DROP TRIGGER IF EXISTS parts.before_update_DOG_Role; + + +DELIMITER // +CREATE TRIGGER parts.before_insert_DOG_Role +BEFORE INSERT ON parts.DOG_Role +FOR EACH ROW +BEGIN + SET NEW.created_on := IFNULL(NEW.created_on, NOW()); +END // +DELIMITER ; + + +DELIMITER // +CREATE TRIGGER parts.before_update_DOG_Role +BEFORE UPDATE ON parts.DOG_Role +FOR EACH ROW +BEGIN + IF OLD.id_change_set <=> NEW.id_change_set THEN + SIGNAL SQLSTATE '45000' + SET MESSAGE_TEXT = 'New change Set ID must be provided.'; + END IF; + + INSERT INTO parts.DOG_Role_Audit ( + id_role, + name_field, + value_prev, + value_new, + id_change_set + ) + -- Changed code + SELECT NEW.id_role, 'code', OLD.code, NEW.code, NEW.id_change_set + WHERE NOT OLD.code <=> NEW.code + UNION + -- Changed name + SELECT NEW.id_role, 'name', OLD.name, NEW.name, NEW.id_change_set + WHERE NOT OLD.name <=> NEW.name + UNION + -- Changed active + SELECT NEW.id_role, 'active', CONVERT(CONVERT(OLD.active, SIGNED), CHAR), CONVERT(CONVERT(NEW.active, SIGNED), CHAR), NEW.id_change_set + WHERE NOT (OLD.active <=> NEW.active) + UNION + -- Changed display_order + SELECT NEW.id_role, 'display_order', CONVERT(OLD.display_order, CHAR), CONVERT(NEW.display_order, CHAR), NEW.id_change_set + WHERE NOT OLD.display_order <=> NEW.display_order + ; +END // +DELIMITER ; diff --git a/static/MySQL/3124_tri_DOG_Role_Permission_Link.sql b/static/MySQL/3124_tri_DOG_Role_Permission_Link.sql new file mode 100644 index 0000000..bc797c2 --- /dev/null +++ b/static/MySQL/3124_tri_DOG_Role_Permission_Link.sql @@ -0,0 +1,52 @@ + +USE parts; + +DROP TRIGGER IF EXISTS parts.before_insert_DOG_Role_Permission_Link; +DROP TRIGGER IF EXISTS parts.before_update_DOG_Role_Permission_Link; + + +DELIMITER // +CREATE TRIGGER parts.before_insert_DOG_Role_Permission_Link +BEFORE INSERT ON parts.DOG_Role_Permission_Link +FOR EACH ROW +BEGIN + SET NEW.created_on := IFNULL(NEW.created_on, NOW()); +END // +DELIMITER ; + + +DELIMITER // +CREATE TRIGGER parts.before_update_DOG_Role_Permission_Link +BEFORE UPDATE ON parts.DOG_Role_Permission_Link +FOR EACH ROW +BEGIN + IF OLD.id_change_set <=> NEW.id_change_set THEN + SIGNAL SQLSTATE '45000' + SET MESSAGE_TEXT = 'New change Set ID must be provided.'; + END IF; + + INSERT INTO parts.DOG_Role_Permission_Link_Audit ( + id_link, + name_field, + value_prev, + value_new, + id_change_set + ) + -- Changed id_role + SELECT NEW.id_link, 'id_role', CONVERT(OLD.id_role, CHAR), CONVERT(NEW.id_role, CHAR), NEW.id_change_set + WHERE NOT OLD.id_role <=> NEW.id_role + UNION + -- Changed id_permission + SELECT NEW.id_link, 'id_permission', CONVERT(OLD.id_permission, CHAR), CONVERT(NEW.id_permission, CHAR), NEW.id_change_set + WHERE NOT OLD.id_permission <=> NEW.id_permission + UNION + -- Changed id_access_level + SELECT NEW.id_link, 'id_access_level', CONVERT(OLD.id_access_level, CHAR), CONVERT(NEW.id_access_level, CHAR), NEW.id_change_set + WHERE NOT OLD.id_access_level <=> NEW.id_access_level + UNION + -- Changed active + SELECT NEW.id_link, 'active', CONVERT(CONVERT(OLD.active, SIGNED), CHAR), CONVERT(CONVERT(NEW.active, SIGNED), CHAR), NEW.id_change_set + WHERE NOT (OLD.active <=> NEW.active) + ; +END // +DELIMITER ; diff --git a/static/MySQL/3128_tri_DOG_User_Role_Link.sql b/static/MySQL/3128_tri_DOG_User_Role_Link.sql new file mode 100644 index 0000000..0a6e990 --- /dev/null +++ b/static/MySQL/3128_tri_DOG_User_Role_Link.sql @@ -0,0 +1,48 @@ + +USE parts; + +DROP TRIGGER IF EXISTS parts.before_insert_DOG_User_Role_Link; +DROP TRIGGER IF EXISTS parts.before_update_DOG_User_Role_Link; + + +DELIMITER // +CREATE TRIGGER parts.before_insert_DOG_User_Role_Link +BEFORE INSERT ON parts.DOG_User_Role_Link +FOR EACH ROW +BEGIN + SET NEW.created_on := IFNULL(NEW.created_on, NOW()); +END // +DELIMITER ; + + +DELIMITER // +CREATE TRIGGER parts.before_update_DOG_User_Role_Link +BEFORE UPDATE ON parts.DOG_User_Role_Link +FOR EACH ROW +BEGIN + IF OLD.id_change_set <=> NEW.id_change_set THEN + SIGNAL SQLSTATE '45000' + SET MESSAGE_TEXT = 'New change Set ID must be provided.'; + END IF; + + INSERT INTO parts.DOG_User_Role_Link_Audit ( + id_link, + name_field, + value_prev, + value_new, + id_change_set + ) + -- Changed id_user + SELECT NEW.id_link, 'id_user', CONVERT(OLD.id_user, CHAR), CONVERT(NEW.id_user, CHAR), NEW.id_change_set + WHERE NOT OLD.id_user <=> NEW.id_user + UNION + -- Changed id_role + SELECT NEW.id_link, 'id_role', CONVERT(OLD.id_role, CHAR), CONVERT(NEW.id_role, CHAR), NEW.id_change_set + WHERE NOT OLD.id_role <=> NEW.id_role + UNION + -- Changed active + SELECT NEW.id_link, 'active', CONVERT(CONVERT(OLD.active, SIGNED), CHAR), CONVERT(CONVERT(NEW.active, SIGNED), CHAR), NEW.id_change_set + WHERE NOT (OLD.active <=> NEW.active) + ; +END // +DELIMITER ; \ No newline at end of file diff --git a/static/MySQL/3200_tri_DOG_Dog_Change_Set.sql b/static/MySQL/3200_tri_DOG_Dog_Change_Set.sql new file mode 100644 index 0000000..0eb4b29 --- /dev/null +++ b/static/MySQL/3200_tri_DOG_Dog_Change_Set.sql @@ -0,0 +1,14 @@ +USE parts; + +DROP TRIGGER IF EXISTS parts.before_insert_DOG_Dog_Change_Set; + +DELIMITER // +CREATE TRIGGER parts.before_insert_DOG_Dog_Change_Set +BEFORE INSERT ON parts.DOG_Dog_Change_Set +FOR EACH ROW +BEGIN + IF NEW.updated_last_on <=> NULL THEN + SET NEW.updated_last_on = NOW(); + END IF; +END // +DELIMITER ; diff --git a/static/MySQL/3201_tri_DOG_Dog.sql b/static/MySQL/3201_tri_DOG_Dog.sql new file mode 100644 index 0000000..b888b43 --- /dev/null +++ b/static/MySQL/3201_tri_DOG_Dog.sql @@ -0,0 +1,50 @@ + +USE parts; + +DROP TRIGGER IF EXISTS parts.before_insert_DOG_Dog; +DROP TRIGGER IF EXISTS parts.before_update_DOG_Dog; + +DELIMITER // +CREATE TRIGGER parts.before_insert_DOG_Dog +BEFORE INSERT ON parts.DOG_Dog +FOR EACH ROW +BEGIN + SET NEW.created_on := IFNULL(NEW.created_on, NOW()); +END // +DELIMITER ; + +DELIMITER // +CREATE TRIGGER parts.before_update_DOG_Dog +BEFORE UPDATE ON parts.DOG_Dog +FOR EACH ROW +BEGIN + IF OLD.id_change_set <=> NEW.id_change_set THEN + SIGNAL SQLSTATE '45000' + SET MESSAGE_TEXT = 'New change Set ID must be provided.'; + END IF; + + INSERT INTO parts.DOG_Dog_Audit ( + id_dog + , name_field + , value_prev + , value_new + , id_change_set + ) + -- Changed name + SELECT NEW.id_dog, 'name', OLD.name, NEW.name, NEW.id_change_set + WHERE NOT OLD.name <=> NEW.name + UNION + -- Changed appearance + SELECT NEW.id_dog, 'appearance', OLD.appearance, NEW.appearance, NEW.id_change_set + WHERE NOT OLD.appearance <=> NEW.appearance + UNION + -- Changed mass_kg + SELECT NEW.id_dog, 'mass_kg', CONVERT(OLD.mass_kg, CHAR), CONVERT(NEW.mass_kg, CHAR), NEW.id_change_set + WHERE NOT (OLD.mass_kg <=> NEW.mass_kg) + UNION + -- Changed active + SELECT NEW.id_dog, 'active', CONVERT(CONVERT(OLD.active, SIGNED), CHAR), CONVERT(CONVERT(NEW.active, SIGNED), CHAR), NEW.id_change_set + WHERE NOT (OLD.active <=> NEW.active) + ; +END // +DELIMITER ; diff --git a/static/MySQL/3205_tri_DOG_Breed.sql b/static/MySQL/3205_tri_DOG_Breed.sql new file mode 100644 index 0000000..5daa790 --- /dev/null +++ b/static/MySQL/3205_tri_DOG_Breed.sql @@ -0,0 +1,46 @@ + +USE parts; + +DROP TRIGGER IF EXISTS parts.before_insert_DOG_Breed; +DROP TRIGGER IF EXISTS parts.before_update_DOG_Breed; + +DELIMITER // +CREATE TRIGGER parts.before_insert_DOG_Breed +BEFORE INSERT ON parts.DOG_Breed +FOR EACH ROW +BEGIN + SET NEW.created_on := IFNULL(NEW.created_on, NOW()); +END // +DELIMITER ; + +DELIMITER // +CREATE TRIGGER parts.before_update_DOG_Breed +BEFORE UPDATE ON parts.DOG_Breed +FOR EACH ROW +BEGIN + IF OLD.id_change_set <=> NEW.id_change_set THEN + SIGNAL SQLSTATE '45000' + SET MESSAGE_TEXT = 'New change Set ID must be provided.'; + END IF; + + INSERT INTO parts.DOG_Breed_Audit ( + id_breed + , name_field + , value_prev + , value_new + , id_change_set + ) + -- Changed code + SELECT NEW.id_breed, 'code', OLD.code, NEW.code, NEW.id_change_set + WHERE NOT OLD.code <=> NEW.code + UNION + -- Changed name + SELECT NEW.id_breed, 'name', OLD.name, NEW.name, NEW.id_change_set + WHERE NOT OLD.name <=> NEW.name + UNION + -- Changed active + SELECT NEW.id_breed, 'active', CONVERT(CONVERT(OLD.active, SIGNED), CHAR), CONVERT(CONVERT(NEW.active, SIGNED), CHAR), NEW.id_change_set + WHERE NOT (OLD.active <=> NEW.active) + ; +END // +DELIMITER ; diff --git a/static/MySQL/3209_tri_DOG_Dog_Breed_Link.sql b/static/MySQL/3209_tri_DOG_Dog_Breed_Link.sql new file mode 100644 index 0000000..d3cf927 --- /dev/null +++ b/static/MySQL/3209_tri_DOG_Dog_Breed_Link.sql @@ -0,0 +1,50 @@ + +USE parts; + +DROP TRIGGER IF EXISTS parts.before_insert_DOG_Dog_Breed_Link; +DROP TRIGGER IF EXISTS parts.before_update_DOG_Dog_Breed_Link; + +DELIMITER // +CREATE TRIGGER parts.before_insert_DOG_Dog_Breed_Link +BEFORE INSERT ON parts.DOG_Dog_Breed_Link +FOR EACH ROW +BEGIN + SET NEW.created_on := IFNULL(NEW.created_on, NOW()); +END // +DELIMITER ; + +DELIMITER // +CREATE TRIGGER parts.before_update_DOG_Dog_Breed_Link +BEFORE UPDATE ON parts.DOG_Dog_Breed_Link +FOR EACH ROW +BEGIN + IF OLD.id_change_set <=> NEW.id_change_set THEN + SIGNAL SQLSTATE '45000' + SET MESSAGE_TEXT = 'New change Set ID must be provided.'; + END IF; + + INSERT INTO parts.DOG_Dog_Breed_Link_Audit ( + id_link + , name_field + , value_prev + , value_new + , id_change_set + ) + -- Changed id_dog + SELECT NEW.id_link, 'id_dog', CONVERT(OLD.id_dog, CHAR), CONVERT(NEW.id_dog, CHAR), NEW.id_change_set + WHERE NOT (OLD.id_dog <=> NEW.id_dog) + UNION + -- Changed id_breed + SELECT NEW.id_link, 'id_breed', CONVERT(OLD.id_breed, CHAR), CONVERT(NEW.id_breed, CHAR), NEW.id_change_set + WHERE NOT (OLD.id_breed <=> NEW.id_breed) + UNION + -- Changed lineage_ratio + SELECT NEW.id_link, 'lineage_ratio', CONVERT(OLD.lineage_ratio, CHAR), CONVERT(NEW.lineage_ratio, CHAR), NEW.id_change_set + WHERE NOT (OLD.lineage_ratio <=> NEW.lineage_ratio) + UNION + -- Changed active + SELECT NEW.id_link, 'active', CONVERT(CONVERT(OLD.active, SIGNED), CHAR), CONVERT(CONVERT(NEW.active, SIGNED), CHAR), NEW.id_change_set + WHERE NOT (OLD.active <=> NEW.active) + ; +END // +DELIMITER ; diff --git a/static/MySQL/3213_0_tri_DOG_Understanding_Level.sql b/static/MySQL/3213_0_tri_DOG_Understanding_Level.sql new file mode 100644 index 0000000..17aa34b --- /dev/null +++ b/static/MySQL/3213_0_tri_DOG_Understanding_Level.sql @@ -0,0 +1,46 @@ + +USE parts; + +DROP TRIGGER IF EXISTS parts.before_insert_DOG_Understanding_Level; +DROP TRIGGER IF EXISTS parts.before_update_DOG_Understanding_Level; + +DELIMITER // +CREATE TRIGGER parts.before_insert_DOG_Understanding_Level +BEFORE INSERT ON parts.DOG_Understanding_Level +FOR EACH ROW +BEGIN + SET NEW.created_on := IFNULL(NEW.created_on, NOW()); +END // +DELIMITER ; + +DELIMITER // +CREATE TRIGGER parts.before_update_DOG_Understanding_Level +BEFORE UPDATE ON parts.DOG_Understanding_Level +FOR EACH ROW +BEGIN + IF OLD.id_change_set <=> NEW.id_change_set THEN + SIGNAL SQLSTATE '45000' + SET MESSAGE_TEXT = 'New change Set ID must be provided.'; + END IF; + + INSERT INTO parts.DOG_Understanding_Level_Audit ( + id_understanding_level + , name_field + , value_prev + , value_new + , id_change_set + ) + -- Changed code + SELECT NEW.id_understanding_level, 'code', OLD.code, NEW.code, NEW.id_change_set + WHERE NOT OLD.code <=> NEW.code + UNION + -- Changed name + SELECT NEW.id_understanding_level, 'name', OLD.name, NEW.name, NEW.id_change_set + WHERE NOT OLD.name <=> NEW.name + UNION + -- Changed active + SELECT NEW.id_understanding_level, 'active', CONVERT(CONVERT(OLD.active, SIGNED), CHAR), CONVERT(CONVERT(NEW.active, SIGNED), CHAR), NEW.id_change_set + WHERE NOT (OLD.active <=> NEW.active) + ; +END // +DELIMITER ; diff --git a/static/MySQL/3213_tri_DOG_Obedience_Level.sql b/static/MySQL/3213_tri_DOG_Obedience_Level.sql new file mode 100644 index 0000000..bcad477 --- /dev/null +++ b/static/MySQL/3213_tri_DOG_Obedience_Level.sql @@ -0,0 +1,46 @@ + +USE parts; + +DROP TRIGGER IF EXISTS parts.before_insert_DOG_Obedience_Level; +DROP TRIGGER IF EXISTS parts.before_update_DOG_Obedience_Level; + +DELIMITER // +CREATE TRIGGER parts.before_insert_DOG_Obedience_Level +BEFORE INSERT ON parts.DOG_Obedience_Level +FOR EACH ROW +BEGIN + SET NEW.created_on := IFNULL(NEW.created_on, NOW()); +END // +DELIMITER ; + +DELIMITER // +CREATE TRIGGER parts.before_update_DOG_Obedience_Level +BEFORE UPDATE ON parts.DOG_Obedience_Level +FOR EACH ROW +BEGIN + IF OLD.id_change_set <=> NEW.id_change_set THEN + SIGNAL SQLSTATE '45000' + SET MESSAGE_TEXT = 'New change Set ID must be provided.'; + END IF; + + INSERT INTO parts.DOG_Obedience_Level_Audit ( + id_obedience_level + , name_field + , value_prev + , value_new + , id_change_set + ) + -- Changed code + SELECT NEW.id_obedience_level, 'code', OLD.code, NEW.code, NEW.id_change_set + WHERE NOT OLD.code <=> NEW.code + UNION + -- Changed name + SELECT NEW.id_obedience_level, 'name', OLD.name, NEW.name, NEW.id_change_set + WHERE NOT OLD.name <=> NEW.name + UNION + -- Changed active + SELECT NEW.id_obedience_level, 'active', CONVERT(CONVERT(OLD.active, SIGNED), CHAR), CONVERT(CONVERT(NEW.active, SIGNED), CHAR), NEW.id_change_set + WHERE NOT (OLD.active <=> NEW.active) + ; +END // +DELIMITER ; diff --git a/static/MySQL/3217_tri_DOG_Command_Category.sql b/static/MySQL/3217_tri_DOG_Command_Category.sql new file mode 100644 index 0000000..870d4e3 --- /dev/null +++ b/static/MySQL/3217_tri_DOG_Command_Category.sql @@ -0,0 +1,46 @@ + +USE parts; + +DROP TRIGGER IF EXISTS parts.before_insert_DOG_Command_Category; +DROP TRIGGER IF EXISTS parts.before_update_DOG_Command_Category; + +DELIMITER // +CREATE TRIGGER parts.before_insert_DOG_Command_Category +BEFORE INSERT ON parts.DOG_Command_Category +FOR EACH ROW +BEGIN + SET NEW.created_on := IFNULL(NEW.created_on, NOW()); +END // +DELIMITER ; + +DELIMITER // +CREATE TRIGGER parts.before_update_DOG_Command_Category +BEFORE UPDATE ON parts.DOG_Command_Category +FOR EACH ROW +BEGIN + IF OLD.id_change_set <=> NEW.id_change_set THEN + SIGNAL SQLSTATE '45000' + SET MESSAGE_TEXT = 'New change Set ID must be provided.'; + END IF; + + INSERT INTO parts.DOG_Command_Category_Audit ( + id_command_category + , name_field + , value_prev + , value_new + , id_change_set + ) + -- Changed code + SELECT NEW.id_command_category, 'code', OLD.code, NEW.code, NEW.id_change_set + WHERE NOT OLD.code <=> NEW.code + UNION + -- Changed name + SELECT NEW.id_command_category, 'name', OLD.name, NEW.name, NEW.id_change_set + WHERE NOT OLD.name <=> NEW.name + UNION + -- Changed active + SELECT NEW.id_command_category, 'active', CONVERT(CONVERT(OLD.active, SIGNED), CHAR), CONVERT(CONVERT(NEW.active, SIGNED), CHAR), NEW.id_change_set + WHERE NOT (OLD.active <=> NEW.active) + ; +END // +DELIMITER ; diff --git a/static/MySQL/3221_tri_DOG_Command.sql b/static/MySQL/3221_tri_DOG_Command.sql new file mode 100644 index 0000000..2e5d31d --- /dev/null +++ b/static/MySQL/3221_tri_DOG_Command.sql @@ -0,0 +1,58 @@ + +USE parts; + +DROP TRIGGER IF EXISTS parts.before_insert_DOG_Command; +DROP TRIGGER IF EXISTS parts.before_update_DOG_Command; + +DELIMITER // +CREATE TRIGGER parts.before_insert_DOG_Command +BEFORE INSERT ON parts.DOG_Command +FOR EACH ROW +BEGIN + SET NEW.created_on := IFNULL(NEW.created_on, NOW()); +END // +DELIMITER ; + +DELIMITER // +CREATE TRIGGER parts.before_update_DOG_Command +BEFORE UPDATE ON parts.DOG_Command +FOR EACH ROW +BEGIN + IF OLD.id_change_set <=> NEW.id_change_set THEN + SIGNAL SQLSTATE '45000' + SET MESSAGE_TEXT = 'New change Set ID must be provided.'; + END IF; + + INSERT INTO parts.DOG_Command_Audit ( + id_command + , name_field + , value_prev + , value_new + , id_change_set + ) + -- Changed id_command_category + SELECT NEW.id_command, 'id_command_category', CONVERT(OLD.id_command_category, CHAR), CONVERT(NEW.id_command_category, CHAR), NEW.id_change_set + WHERE NOT (OLD.id_command_category <=> NEW.id_command_category) + UNION + -- Changed name + SELECT NEW.id_command, 'name', OLD.name, NEW.name, NEW.id_change_set + WHERE NOT OLD.name <=> NEW.name + UNION + -- Changed hand_signal_default_description + SELECT NEW.id_command, 'hand_signal_default_description', OLD.hand_signal_default_description, NEW.hand_signal_default_description, NEW.id_change_set + WHERE NOT OLD.hand_signal_default_description <=> NEW.hand_signal_default_description + UNION + -- Changed can_have_button + SELECT NEW.id_command, 'can_have_button', CONVERT(CONVERT(OLD.can_have_button, SIGNED), CHAR), CONVERT(CONVERT(NEW.can_have_button, SIGNED), CHAR), NEW.id_change_set + WHERE NOT (OLD.can_have_button <=> NEW.can_have_button) + UNION + -- Changed notes + SELECT NEW.id_command, 'notes', OLD.notes, NEW.notes, NEW.id_change_set + WHERE NOT OLD.notes <=> NEW.notes + UNION + -- Changed active + SELECT NEW.id_command, 'active', CONVERT(CONVERT(OLD.active, SIGNED), CHAR), CONVERT(CONVERT(NEW.active, SIGNED), CHAR), NEW.id_change_set + WHERE NOT (OLD.active <=> NEW.active) + ; +END // +DELIMITER ; diff --git a/static/MySQL/3225_tri_DOG_Dog_Command_Link.sql b/static/MySQL/3225_tri_DOG_Dog_Command_Link.sql new file mode 100644 index 0000000..3687241 --- /dev/null +++ b/static/MySQL/3225_tri_DOG_Dog_Command_Link.sql @@ -0,0 +1,68 @@ + +USE parts; + +DROP TRIGGER IF EXISTS parts.before_insert_DOG_Dog_Command_Link; +DROP TRIGGER IF EXISTS parts.before_update_DOG_Dog_Command_Link; + +DELIMITER // +CREATE TRIGGER parts.before_insert_DOG_Dog_Command_Link +BEFORE INSERT ON parts.DOG_Dog_Command_Link +FOR EACH ROW +BEGIN + SET NEW.created_on := IFNULL(NEW.created_on, NOW()); +END // +DELIMITER ; + +DELIMITER // +CREATE TRIGGER parts.before_update_DOG_Dog_Command_Link +BEFORE UPDATE ON parts.DOG_Dog_Command_Link +FOR EACH ROW +BEGIN + IF OLD.id_change_set <=> NEW.id_change_set THEN + SIGNAL SQLSTATE '45000' + SET MESSAGE_TEXT = 'New change Set ID must be provided.'; + END IF; + + INSERT INTO parts.DOG_Dog_Command_Link_Audit ( + id_link + , name_field + , value_prev + , value_new + , id_change_set + ) + -- Changed id_dog + SELECT NEW.id_link, 'id_dog', CONVERT(OLD.id_dog, CHAR), CONVERT(NEW.id_dog, CHAR), NEW.id_change_set + WHERE NOT (OLD.id_dog <=> NEW.id_dog) + UNION + -- Changed id_command + SELECT NEW.id_link, 'id_command', CONVERT(OLD.id_command, CHAR), CONVERT(NEW.id_command, CHAR), NEW.id_change_set + WHERE NOT (OLD.id_command <=> NEW.id_command) + UNION + -- Changed id_understanding_level + SELECT NEW.id_link, 'id_understanding_level', CONVERT(OLD.id_understanding_level, CHAR), CONVERT(NEW.id_understanding_level, CHAR), NEW.id_change_set + WHERE NOT (OLD.id_understanding_level <=> NEW.id_understanding_level) + UNION + -- Changed id_obedience_level + SELECT NEW.id_link, 'id_obedience_level', CONVERT(OLD.id_obedience_level, CHAR), CONVERT(NEW.id_obedience_level, CHAR), NEW.id_change_set + WHERE NOT (OLD.id_obedience_level <=> NEW.id_obedience_level) + UNION + -- Changed hand_signal_description + SELECT NEW.id_link, 'hand_signal_description', OLD.hand_signal_description, NEW.hand_signal_description, NEW.id_change_set + WHERE NOT OLD.hand_signal_description <=> NEW.hand_signal_description + UNION + -- Changed notes + SELECT NEW.id_link, 'notes', OLD.notes, NEW.notes, NEW.id_change_set + WHERE NOT OLD.notes <=> NEW.notes + UNION + /* + -- Changed has_button + SELECT NEW.id_link, 'has_button', CONVERT(CONVERT(OLD.has_button, SIGNED), CHAR), CONVERT(CONVERT(NEW.has_button, SIGNED), CHAR), NEW.id_change_set + WHERE NOT (OLD.has_button <=> NEW.has_button) + UNION + */ + -- Changed active + SELECT NEW.id_link, 'active', CONVERT(CONVERT(OLD.active, SIGNED), CHAR), CONVERT(CONVERT(NEW.active, SIGNED), CHAR), NEW.id_change_set + WHERE NOT (OLD.active <=> NEW.active) + ; +END // +DELIMITER ; diff --git a/static/MySQL/3229_0_tri_DOG_Personal_Best.sql b/static/MySQL/3229_0_tri_DOG_Personal_Best.sql new file mode 100644 index 0000000..d9cf15b --- /dev/null +++ b/static/MySQL/3229_0_tri_DOG_Personal_Best.sql @@ -0,0 +1,58 @@ + +USE parts; + +DROP TRIGGER IF EXISTS parts.before_insert_DOG_Personal_Best; +DROP TRIGGER IF EXISTS parts.before_update_DOG_Personal_Best; + +DELIMITER // +CREATE TRIGGER parts.before_insert_DOG_Personal_Best +BEFORE INSERT ON parts.DOG_Personal_Best +FOR EACH ROW +BEGIN + SET NEW.created_on := IFNULL(NEW.created_on, NOW()); +END // +DELIMITER ; + +DELIMITER // +CREATE TRIGGER parts.before_update_DOG_Personal_Best +BEFORE UPDATE ON parts.DOG_Personal_Best +FOR EACH ROW +BEGIN + IF OLD.id_change_set <=> NEW.id_change_set THEN + SIGNAL SQLSTATE '45000' + SET MESSAGE_TEXT = 'New change Set ID must be provided.'; + END IF; + + INSERT INTO parts.DOG_Personal_Best_Audit ( + id_personal_best + , name_field + , value_prev + , value_new + , id_change_set + ) + -- Changed id_dog_command_link + SELECT NEW.id_personal_best, 'id_dog_command_link', CONVERT(OLD.id_dog_command_link, CHAR), CONVERT(NEW.id_dog_command_link, CHAR), NEW.id_change_set + WHERE NOT (OLD.id_dog_command_link <=> NEW.id_dog_command_link) + UNION + -- Changed is_achieved_using_button + SELECT NEW.id_personal_best, 'is_achieved_using_button', CONVERT(CONVERT(OLD.is_achieved_using_button, SIGNED), CHAR), CONVERT(CONVERT(NEW.is_achieved_using_button, SIGNED), CHAR), NEW.id_change_set + WHERE NOT (OLD.is_achieved_using_button <=> NEW.is_achieved_using_button) + UNION + -- Changed situation + SELECT NEW.id_personal_best, 'situation', OLD.situation, NEW.situation, NEW.id_change_set + WHERE NOT OLD.situation <=> NEW.situation + UNION + -- Changed quantity + SELECT NEW.id_personal_best, 'quantity', CONVERT(OLD.quantity, CHAR), CONVERT(NEW.quantity, CHAR), NEW.id_change_set + WHERE NOT (OLD.quantity <=> NEW.quantity) + UNION + -- Changed duration_seconds + SELECT NEW.id_personal_best, 'duration_seconds', CONVERT(OLD.duration_seconds, CHAR), CONVERT(NEW.duration_seconds, CHAR), NEW.id_change_set + WHERE NOT (OLD.duration_seconds <=> NEW.duration_seconds) + UNION + -- Changed active + SELECT NEW.id_personal_best, 'active', CONVERT(CONVERT(OLD.active, SIGNED), CHAR), CONVERT(CONVERT(NEW.active, SIGNED), CHAR), NEW.id_change_set + WHERE NOT (OLD.active <=> NEW.active) + ; +END // +DELIMITER ; diff --git a/static/MySQL/3229_tri_DOG_Location.sql b/static/MySQL/3229_tri_DOG_Location.sql new file mode 100644 index 0000000..4e160e0 --- /dev/null +++ b/static/MySQL/3229_tri_DOG_Location.sql @@ -0,0 +1,46 @@ + +USE parts; + +DROP TRIGGER IF EXISTS parts.before_insert_DOG_Location; +DROP TRIGGER IF EXISTS parts.before_update_DOG_Location; + +DELIMITER // +CREATE TRIGGER parts.before_insert_DOG_Location +BEFORE INSERT ON parts.DOG_Location +FOR EACH ROW +BEGIN + SET NEW.created_on := IFNULL(NEW.created_on, NOW()); +END // +DELIMITER ; + +DELIMITER // +CREATE TRIGGER parts.before_update_DOG_Location +BEFORE UPDATE ON parts.DOG_Location +FOR EACH ROW +BEGIN + IF OLD.id_change_set <=> NEW.id_change_set THEN + SIGNAL SQLSTATE '45000' + SET MESSAGE_TEXT = 'New change Set ID must be provided.'; + END IF; + + INSERT INTO parts.DOG_Location_Audit ( + id_location + , name_field + , value_prev + , value_new + , id_change_set + ) + -- Changed code + SELECT NEW.id_location, 'code', OLD.code, NEW.code, NEW.id_change_set + WHERE NOT (OLD.code <=> NEW.code) + UNION + -- Changed name + SELECT NEW.id_location, 'name', OLD.name, NEW.name, NEW.id_change_set + WHERE NOT (OLD.name <=> NEW.name) + UNION + -- Changed active + SELECT NEW.id_location, 'active', CONVERT(CONVERT(OLD.active, SIGNED), CHAR), CONVERT(CONVERT(NEW.active, SIGNED), CHAR), NEW.id_change_set + WHERE NOT (OLD.active <=> NEW.active) + ; +END // +DELIMITER ; diff --git a/static/MySQL/3233_tri_DOG_Location_Link.sql b/static/MySQL/3233_tri_DOG_Location_Link.sql new file mode 100644 index 0000000..2564933 --- /dev/null +++ b/static/MySQL/3233_tri_DOG_Location_Link.sql @@ -0,0 +1,46 @@ + +USE parts; + +DROP TRIGGER IF EXISTS parts.before_insert_DOG_Location_Link; +DROP TRIGGER IF EXISTS parts.before_update_DOG_Location_Link; + +DELIMITER // +CREATE TRIGGER parts.before_insert_DOG_Location_Link +BEFORE INSERT ON parts.DOG_Location_Link +FOR EACH ROW +BEGIN + SET NEW.created_on := IFNULL(NEW.created_on, NOW()); +END // +DELIMITER ; + +DELIMITER // +CREATE TRIGGER parts.before_update_DOG_Location_Link +BEFORE UPDATE ON parts.DOG_Location_Link +FOR EACH ROW +BEGIN + IF OLD.id_change_set <=> NEW.id_change_set THEN + SIGNAL SQLSTATE '45000' + SET MESSAGE_TEXT = 'New change Set ID must be provided.'; + END IF; + + INSERT INTO parts.DOG_Location_Link_Audit ( + id_link + , name_field + , value_prev + , value_new + , id_change_set + ) + -- Changed id_location_parent + SELECT NEW.id_link, 'id_location_parent', CONVERT(OLD.id_location_parent, CHAR), CONVERT(NEW.id_location_parent, CHAR), NEW.id_change_set + WHERE NOT (OLD.id_location_parent <=> NEW.id_location_parent) + UNION + -- Changed id_location_child + SELECT NEW.id_link, 'id_location_child', CONVERT(OLD.id_location_child, CHAR), CONVERT(NEW.id_location_child, CHAR), NEW.id_change_set + WHERE NOT (OLD.id_location_child <=> NEW.id_location_child) + UNION + -- Changed active + SELECT NEW.id_link, 'active', CONVERT(CONVERT(OLD.active, SIGNED), CHAR), CONVERT(CONVERT(NEW.active, SIGNED), CHAR), NEW.id_change_set + WHERE NOT (OLD.active <=> NEW.active) + ; +END // +DELIMITER ; diff --git a/static/MySQL/3237_tri_DOG_Dog_Colour.sql b/static/MySQL/3237_tri_DOG_Dog_Colour.sql new file mode 100644 index 0000000..52f07f2 --- /dev/null +++ b/static/MySQL/3237_tri_DOG_Dog_Colour.sql @@ -0,0 +1,46 @@ + +USE parts; + +DROP TRIGGER IF EXISTS parts.before_insert_DOG_Colour; +DROP TRIGGER IF EXISTS parts.before_update_DOG_Colour; + +DELIMITER // +CREATE TRIGGER parts.before_insert_DOG_Colour +BEFORE INSERT ON parts.DOG_Colour +FOR EACH ROW +BEGIN + SET NEW.created_on := IFNULL(NEW.created_on, NOW()); +END // +DELIMITER ; + +DELIMITER // +CREATE TRIGGER parts.before_update_DOG_Colour +BEFORE UPDATE ON parts.DOG_Colour +FOR EACH ROW +BEGIN + IF OLD.id_change_set <=> NEW.id_change_set THEN + SIGNAL SQLSTATE '45000' + SET MESSAGE_TEXT = 'New change Set ID must be provided.'; + END IF; + + INSERT INTO parts.DOG_Colour_Audit ( + id_colour + , name_field + , value_prev + , value_new + , id_change_set + ) + -- Changed code + SELECT NEW.id_colour, 'code', OLD.code, NEW.code, NEW.id_change_set + WHERE NOT (OLD.code <=> NEW.code) + UNION + -- Changed name + SELECT NEW.id_colour, 'name', OLD.name, NEW.name, NEW.id_change_set + WHERE NOT (OLD.name <=> NEW.name) + UNION + -- Changed active + SELECT NEW.id_colour, 'active', CONVERT(CONVERT(OLD.active, SIGNED), CHAR), CONVERT(CONVERT(NEW.active, SIGNED), CHAR), NEW.id_change_set + WHERE NOT (OLD.active <=> NEW.active) + ; +END // +DELIMITER ; diff --git a/static/MySQL/3241_tri_DOG_Button_Shape.sql b/static/MySQL/3241_tri_DOG_Button_Shape.sql new file mode 100644 index 0000000..3fbaa3e --- /dev/null +++ b/static/MySQL/3241_tri_DOG_Button_Shape.sql @@ -0,0 +1,50 @@ + +USE parts; + +DROP TRIGGER IF EXISTS parts.before_insert_DOG_Button_Shape; +DROP TRIGGER IF EXISTS parts.before_update_DOG_Button_Shape; + +DELIMITER // +CREATE TRIGGER parts.before_insert_DOG_Button_Shape +BEFORE INSERT ON parts.DOG_Button_Shape +FOR EACH ROW +BEGIN + SET NEW.created_on := IFNULL(NEW.created_on, NOW()); +END // +DELIMITER ; + +DELIMITER // +CREATE TRIGGER parts.before_update_DOG_Button_Shape +BEFORE UPDATE ON parts.DOG_Button_Shape +FOR EACH ROW +BEGIN + IF OLD.id_change_set <=> NEW.id_change_set THEN + SIGNAL SQLSTATE '45000' + SET MESSAGE_TEXT = 'New change Set ID must be provided.'; + END IF; + + INSERT INTO parts.DOG_Button_Shape_Audit ( + id_button_shape + , name_field + , value_prev + , value_new + , id_change_set + ) + -- Changed code + SELECT NEW.id_button_shape, 'code', OLD.code, NEW.code, NEW.id_change_set + WHERE NOT (OLD.code <=> NEW.code) + UNION + -- Changed name + SELECT NEW.id_button_shape, 'name', OLD.name, NEW.name, NEW.id_change_set + WHERE NOT (OLD.name <=> NEW.name) + UNION + -- Changed description + SELECT NEW.id_button_shape, 'description', OLD.description, NEW.description, NEW.id_change_set + WHERE NOT (OLD.description <=> NEW.description) + UNION + -- Changed active + SELECT NEW.id_button_shape, 'active', CONVERT(CONVERT(OLD.active, SIGNED), CHAR), CONVERT(CONVERT(NEW.active, SIGNED), CHAR), NEW.id_change_set + WHERE NOT (OLD.active <=> NEW.active) + ; +END // +DELIMITER ; diff --git a/static/MySQL/3245_tri_DOG_Image.sql b/static/MySQL/3245_tri_DOG_Image.sql new file mode 100644 index 0000000..83fa7c4 --- /dev/null +++ b/static/MySQL/3245_tri_DOG_Image.sql @@ -0,0 +1,54 @@ + +USE parts; + +DROP TRIGGER IF EXISTS parts.before_insert_DOG_Image; +DROP TRIGGER IF EXISTS parts.before_update_DOG_Image; + +DELIMITER // +CREATE TRIGGER parts.before_insert_DOG_Image +BEFORE INSERT ON parts.DOG_Image +FOR EACH ROW +BEGIN + SET NEW.created_on := IFNULL(NEW.created_on, NOW()); +END // +DELIMITER ; + +DELIMITER // +CREATE TRIGGER parts.before_update_DOG_Image +BEFORE UPDATE ON parts.DOG_Image +FOR EACH ROW +BEGIN + IF OLD.id_change_set <=> NEW.id_change_set THEN + SIGNAL SQLSTATE '45000' + SET MESSAGE_TEXT = 'New change Set ID must be provided.'; + END IF; + + INSERT INTO parts.DOG_Image_Audit ( + id_image + , name_field + , value_prev + , value_new + , id_change_set + ) + -- Changed id_file_type + SELECT NEW.id_image, 'id_file_type', CONVERT(OLD.id_file_type, CHAR), CONVERT(NEW.id_file_type, CHAR), NEW.id_change_set + WHERE NOT (OLD.id_file_type <=> NEW.id_file_type) + UNION + -- Changed id_dog + SELECT NEW.id_image, 'id_dog', CONVERT(OLD.id_dog, CHAR), CONVERT(NEW.id_dog, CHAR), NEW.id_change_set + WHERE NOT (OLD.id_dog <=> NEW.id_dog) + UNION + -- Changed path + SELECT NEW.id_image, 'path', OLD.path, NEW.path, NEW.id_change_set + WHERE NOT (OLD.path <=> NEW.path) + UNION + -- Changed display_order + SELECT NEW.id_image, 'display_order', CONVERT(OLD.display_order, CHAR), CONVERT(NEW.display_order, CHAR), NEW.id_change_set + WHERE NOT (OLD.display_order <=> NEW.display_order) + UNION + -- Changed active + SELECT NEW.id_image, 'active', CONVERT(CONVERT(OLD.active, SIGNED), CHAR), CONVERT(CONVERT(NEW.active, SIGNED), CHAR), NEW.id_change_set + WHERE NOT (OLD.active <=> NEW.active) + ; +END // +DELIMITER ; diff --git a/static/MySQL/3249_tri_DOG_Button_Icon.sql b/static/MySQL/3249_tri_DOG_Button_Icon.sql new file mode 100644 index 0000000..ff1fa62 --- /dev/null +++ b/static/MySQL/3249_tri_DOG_Button_Icon.sql @@ -0,0 +1,54 @@ + +USE parts; + +DROP TRIGGER IF EXISTS parts.before_insert_DOG_Button_Icon; +DROP TRIGGER IF EXISTS parts.before_update_DOG_Button_Icon; + +DELIMITER // +CREATE TRIGGER parts.before_insert_DOG_Button_Icon +BEFORE INSERT ON parts.DOG_Button_Icon +FOR EACH ROW +BEGIN + SET NEW.created_on := IFNULL(NEW.created_on, NOW()); +END // +DELIMITER ; + +DELIMITER // +CREATE TRIGGER parts.before_update_DOG_Button_Icon +BEFORE UPDATE ON parts.DOG_Button_Icon +FOR EACH ROW +BEGIN + IF OLD.id_change_set <=> NEW.id_change_set THEN + SIGNAL SQLSTATE '45000' + SET MESSAGE_TEXT = 'New change Set ID must be provided.'; + END IF; + + INSERT INTO parts.DOG_Button_Icon_Audit ( + id_button_icon + , name_field + , value_prev + , value_new + , id_change_set + ) + -- Changed id_image + SELECT NEW.id_button_icon, 'id_image', CONVERT(OLD.id_image, CHAR), CONVERT(NEW.id_image, CHAR), NEW.id_change_set + WHERE NOT (OLD.id_image <=> NEW.id_image) + UNION + -- Changed code + SELECT NEW.id_button_icon, 'code', OLD.code, NEW.code, NEW.id_change_set + WHERE NOT (OLD.code <=> NEW.code) + UNION + -- Changed name + SELECT NEW.id_button_icon, 'name', OLD.name, NEW.name, NEW.id_change_set + WHERE NOT (OLD.name <=> NEW.name) + UNION + -- Changed description + SELECT NEW.id_button_icon, 'description', OLD.description, NEW.description, NEW.id_change_set + WHERE NOT (OLD.description <=> NEW.description) + UNION + -- Changed active + SELECT NEW.id_button_icon, 'active', CONVERT(CONVERT(OLD.active, SIGNED), CHAR), CONVERT(CONVERT(NEW.active, SIGNED), CHAR), NEW.id_change_set + WHERE NOT (OLD.active <=> NEW.active) + ; +END // +DELIMITER ; diff --git a/static/MySQL/3253_tri_DOG_Command_Button_Link.sql b/static/MySQL/3253_tri_DOG_Command_Button_Link.sql new file mode 100644 index 0000000..ba3db66 --- /dev/null +++ b/static/MySQL/3253_tri_DOG_Command_Button_Link.sql @@ -0,0 +1,58 @@ + +USE parts; + +DROP TRIGGER IF EXISTS parts.before_insert_DOG_Command_Button_Link; +DROP TRIGGER IF EXISTS parts.before_update_DOG_Command_Button_Link; + +DELIMITER // +CREATE TRIGGER parts.before_insert_DOG_Command_Button_Link +BEFORE INSERT ON parts.DOG_Command_Button_Link +FOR EACH ROW +BEGIN + SET NEW.created_on := IFNULL(NEW.created_on, NOW()); +END // +DELIMITER ; + +DELIMITER // +CREATE TRIGGER parts.before_update_DOG_Command_Button_Link +BEFORE UPDATE ON parts.DOG_Command_Button_Link +FOR EACH ROW +BEGIN + IF OLD.id_change_set <=> NEW.id_change_set THEN + SIGNAL SQLSTATE '45000' + SET MESSAGE_TEXT = 'New change Set ID must be provided.'; + END IF; + + INSERT INTO parts.DOG_Command_Button_Link_Audit ( + id_link + , name_field + , value_prev + , value_new + , id_change_set + ) + -- Changed id_command + SELECT NEW.id_link, 'id_command', CONVERT(OLD.id_command, CHAR), CONVERT(NEW.id_command, CHAR), NEW.id_change_set + WHERE NOT (OLD.id_command <=> NEW.id_command) + UNION + -- Changed id_button_shape + SELECT NEW.id_link, 'id_button_shape', CONVERT(OLD.id_button_shape, CHAR), CONVERT(NEW.id_button_shape, CHAR), NEW.id_change_set + WHERE NOT (OLD.id_button_shape <=> NEW.id_button_shape) + UNION + -- Changed id_button_colour + SELECT NEW.id_link, 'id_button_colour', CONVERT(OLD.id_button_colour, CHAR), CONVERT(NEW.id_button_colour, CHAR), NEW.id_change_set + WHERE NOT (OLD.id_button_colour <=> NEW.id_button_colour) + UNION + -- Changed id_button_icon + SELECT NEW.id_link, 'id_button_icon', CONVERT(OLD.id_button_icon, CHAR), CONVERT(NEW.id_button_icon, CHAR), NEW.id_change_set + WHERE NOT (OLD.id_button_icon <=> NEW.id_button_icon) + UNION + -- Changed id_location + SELECT NEW.id_link, 'id_location', CONVERT(OLD.id_location, CHAR), CONVERT(NEW.id_location, CHAR), NEW.id_change_set + WHERE NOT (OLD.id_location <=> NEW.id_location) + UNION + -- Changed active + SELECT NEW.id_link, 'active', CONVERT(CONVERT(OLD.active, SIGNED), CHAR), CONVERT(CONVERT(NEW.active, SIGNED), CHAR), NEW.id_change_set + WHERE NOT (OLD.active <=> NEW.active) + ; +END // +DELIMITER ; diff --git a/static/MySQL/3257_tri_DOG_Drive.sql b/static/MySQL/3257_tri_DOG_Drive.sql new file mode 100644 index 0000000..bb20f98 --- /dev/null +++ b/static/MySQL/3257_tri_DOG_Drive.sql @@ -0,0 +1,46 @@ + +USE parts; + +DROP TRIGGER IF EXISTS parts.before_insert_DOG_Drive; +DROP TRIGGER IF EXISTS parts.before_update_DOG_Drive; + +DELIMITER // +CREATE TRIGGER parts.before_insert_DOG_Drive +BEFORE INSERT ON parts.DOG_Drive +FOR EACH ROW +BEGIN + SET NEW.created_on := IFNULL(NEW.created_on, NOW()); +END // +DELIMITER ; + +DELIMITER // +CREATE TRIGGER parts.before_update_DOG_Drive +BEFORE UPDATE ON parts.DOG_Drive +FOR EACH ROW +BEGIN + IF OLD.id_change_set <=> NEW.id_change_set THEN + SIGNAL SQLSTATE '45000' + SET MESSAGE_TEXT = 'New change Set ID must be provided.'; + END IF; + + INSERT INTO parts.DOG_Drive_Audit ( + id_drive + , name_field + , value_prev + , value_new + , id_change_set + ) + -- Changed code + SELECT NEW.id_drive, 'code', OLD.code, NEW.code, NEW.id_change_set + WHERE NOT (OLD.code <=> NEW.code) + UNION + -- Changed name + SELECT NEW.id_drive, 'name', OLD.name, NEW.name, NEW.id_change_set + WHERE NOT (OLD.name <=> NEW.name) + UNION + -- Changed active + SELECT NEW.id_drive, 'active', CONVERT(CONVERT(OLD.active, SIGNED), CHAR), CONVERT(CONVERT(NEW.active, SIGNED), CHAR), NEW.id_change_set + WHERE NOT (OLD.active <=> NEW.active) + ; +END // +DELIMITER ; diff --git a/static/MySQL/3261_tri_DOG_Dog_Drive_Link.sql b/static/MySQL/3261_tri_DOG_Dog_Drive_Link.sql new file mode 100644 index 0000000..b414a3a --- /dev/null +++ b/static/MySQL/3261_tri_DOG_Dog_Drive_Link.sql @@ -0,0 +1,50 @@ + +USE parts; + +DROP TRIGGER IF EXISTS parts.before_insert_DOG_Dog_Drive_Link; +DROP TRIGGER IF EXISTS parts.before_update_DOG_Dog_Drive_Link; + +DELIMITER // +CREATE TRIGGER parts.before_insert_DOG_Dog_Drive_Link +BEFORE INSERT ON parts.DOG_Dog_Drive_Link +FOR EACH ROW +BEGIN + SET NEW.created_on := IFNULL(NEW.created_on, NOW()); +END // +DELIMITER ; + +DELIMITER // +CREATE TRIGGER parts.before_update_DOG_Dog_Drive_Link +BEFORE UPDATE ON parts.DOG_Dog_Drive_Link +FOR EACH ROW +BEGIN + IF OLD.id_change_set <=> NEW.id_change_set THEN + SIGNAL SQLSTATE '45000' + SET MESSAGE_TEXT = 'New change Set ID must be provided.'; + END IF; + + INSERT INTO parts.DOG_Dog_Drive_Link_Audit ( + id_link + , name_field + , value_prev + , value_new + , id_change_set + ) + -- Changed id_dog + SELECT NEW.id_link, 'id_dog', CONVERT(OLD.id_dog, CHAR), CONVERT(NEW.id_dog, CHAR), NEW.id_change_set + WHERE NOT (OLD.id_dog <=> NEW.id_dog) + UNION + -- Changed id_drive + SELECT NEW.id_link, 'id_drive', CONVERT(OLD.id_drive, CHAR), CONVERT(NEW.id_drive, CHAR), NEW.id_change_set + WHERE NOT (OLD.id_drive <=> NEW.id_drive) + UNION + -- Changed dominance_ratio + SELECT NEW.id_link, 'dominance_ratio', CONVERT(OLD.dominance_ratio, CHAR), CONVERT(NEW.dominance_ratio, CHAR), NEW.id_change_set + WHERE NOT (OLD.dominance_ratio <=> NEW.dominance_ratio) + UNION + -- Changed active + SELECT NEW.id_link, 'active', CONVERT(CONVERT(OLD.active, SIGNED), CHAR), CONVERT(CONVERT(NEW.active, SIGNED), CHAR), NEW.id_change_set + WHERE NOT (OLD.active <=> NEW.active) + ; +END // +DELIMITER ; diff --git a/static/MySQL/6000_p_core_validate_guid.sql b/static/MySQL/6000_p_core_validate_guid.sql new file mode 100644 index 0000000..62ae363 --- /dev/null +++ b/static/MySQL/6000_p_core_validate_guid.sql @@ -0,0 +1,29 @@ + +USE parts; + +DROP PROCEDURE IF EXISTS parts.p_core_validate_guid; +DROP PROCEDURE IF EXISTS parts.p_core_validate_guid_test; + +DELIMITER // +CREATE PROCEDURE parts.p_core_validate_guid ( + IN a_guid BINARY(36) +) +BEGIN + IF ISNULL(a_guid) THEN + SIGNAL SQLSTATE '45000' + SET MESSAGE_TEXT = 'GUID is required.' + ; + END IF; +END // +DELIMITER ; + + +DELIMITER // +CREATE PROCEDURE parts.p_core_validate_guid_test () +BEGIN + CALL parts.p_core_validate_guid ( 'nips' ); + CALL parts.p_core_validate_guid ( NULL ); +END // +DELIMITER ; + +-- CALL parts.p_core_validate_guid_test(); \ No newline at end of file diff --git a/static/MySQL/6001_p_core_debug_timing_reporting.sql b/static/MySQL/6001_p_core_debug_timing_reporting.sql new file mode 100644 index 0000000..da42e29 --- /dev/null +++ b/static/MySQL/6001_p_core_debug_timing_reporting.sql @@ -0,0 +1,43 @@ + +USE parts; + +DROP PROCEDURE IF EXISTS parts.p_core_debug_timing_reporting; + +DELIMITER // +CREATE PROCEDURE parts.p_core_debug_timing_reporting ( + IN a_time_start TIMESTAMP(6) +) +BEGIN +/* + PROCEDURE parts.p_core_debug_timing_reporting + Shared method timing reporting +*/ + DECLARE v_time_end TIMESTAMP(6); + + SET v_time_end := CURRENT_TIMESTAMP(6); + SELECT + a_time_start + , UNIX_TIMESTAMP(a_time_start) + , MICROSECOND(a_time_start) / 1000 + , v_time_end + , UNIX_TIMESTAMP(v_time_end) + , MICROSECOND(v_time_end) / 1000 + , v_time_end - a_time_start AS timestamp_delta + , UNIX_TIMESTAMP(v_time_end - a_time_start) AS UNIX_TIMESTAMP_timestamp_delta + , MICROSECOND(v_time_end - a_time_start) AS MICROSECOND_timestamp_delta + -- , TIME_FORMAT(TIMEDIFF(v_time_end, a_time_start), '%H:%i:%s') AS time_difference + , CONCAT( + TIME_FORMAT(TIMEDIFF(v_time_end, a_time_start), '%H hours, %i minutes, %s seconds'), + ', ', + TIMESTAMPDIFF(MICROSECOND, a_time_start, v_time_end) % 1000000 / 1000, ' milliseconds' + ) AS time_difference + ; + +END // +DELIMITER ; + +/* +CALL parts.p_core_debug_timing_reporting ( + CURRENT_TIMESTAMP(6) +); +*/ \ No newline at end of file diff --git a/static/MySQL/6010_p_core_split.sql b/static/MySQL/6010_p_core_split.sql new file mode 100644 index 0000000..29d573b --- /dev/null +++ b/static/MySQL/6010_p_core_split.sql @@ -0,0 +1,105 @@ + +USE parts; + +DROP PROCEDURE IF EXISTS parts.p_core_split; + +DELIMITER // +CREATE PROCEDURE parts.p_core_split ( + IN a_guid BINARY(36) + , IN a_string LONGTEXT + , IN a_separator VARCHAR(1000) + -- IN a_allow_empty BIT + , IN a_debug BIT +) +BEGIN + DECLARE v_has_string BIT; + DECLARE v_has_separator BIT; + DECLARE v_i_separator INT; + DECLARE v_i_start INT; + DECLARE v_i_end INT; + DECLARE v_current_item VARCHAR(4000); + DECLARE v_time_start TIMESTAMP(6); + + SET v_time_start := CURRENT_TIMESTAMP(6); + SET a_string := IFNULL(a_string, ''); + SET a_separator := IFNULL(a_separator, ''); + SET a_debug := IFNULL(a_debug, 0); + + IF a_debug = 1 THEN + SELECT + a_guid + , a_string + , a_separator + , a_debug + ; + END IF; + + CALL parts.p_core_validate_guid ( a_guid ); + + DROP TABLE IF EXISTS tmp_Split_Split; + + CREATE TEMPORARY TABLE tmp_Split_Split ( + display_order INT NOT NULL PRIMARY KEY AUTO_INCREMENT, + substring VARCHAR(4000) NOT NULL + ); + + SET v_has_string = CASE WHEN a_string = '' THEN 0 ELSE 1 END; + SET v_has_separator = CASE WHEN a_separator = '' THEN 0 ELSE 1 END; + + IF v_has_string THEN + + SET v_i_start = 1; + SET v_i_end = LOCATE(',', a_string); + + WHILE v_i_end > 0 DO + SET v_current_item = SUBSTRING(a_string, v_i_start, v_i_end - v_i_start); + INSERT INTO tmp_Split_Split (substring) VALUES (v_current_item); + + SET v_i_start = v_i_end + 1; + SET v_i_end = LOCATE(',', a_string, v_i_start); + END WHILE; + + SET v_current_item = SUBSTRING(a_string, v_i_start); + INSERT INTO tmp_Split_Split (substring) VALUES (TRIM(v_current_item)); + END IF; + + IF EXISTS (SELECT * FROM tmp_Split_Split LIMIT 1) THEN + START TRANSACTION; + INSERT INTO parts.CORE_Split_Temp ( + guid + , display_order + , substring + ) + SELECT + a_guid + , display_order + , substring + FROM tmp_Split_Split + ; + COMMIT; + END IF; + + DROP TABLE IF EXISTS tmp_Split_Split; + + IF a_debug = 1 THEN + CALL parts.p_core_debug_timing_reporting ( v_time_start ); + END IF; +END // +DELIMITER ; + + +/* +CALL parts.p_core_split ( + 'nips' + , 'noods, cheese ' -- a_string + , ',' -- a_separator + -- '0', -- a_allow_empty + , 1 +); + +SELECT * +FROM parts.CORE_Split_Temp +WHERE GUID = 'nips'; + +CALL parts.p_core_clear_split_temp( 'nips' ); +*/ diff --git a/static/MySQL/6011_p_core_clear_split.sql b/static/MySQL/6011_p_core_clear_split.sql new file mode 100644 index 0000000..45434a0 --- /dev/null +++ b/static/MySQL/6011_p_core_clear_split.sql @@ -0,0 +1,30 @@ + +USE parts; + +DROP PROCEDURE IF EXISTS parts.p_core_clear_split; + + +DELIMITER // +CREATE PROCEDURE parts.p_core_clear_split ( + IN a_guid BINARY(36) +) +BEGIN + CALL parts.p_core_validate_guid( a_guid ); + + START TRANSACTION; + + -- DROP TABLE IF EXISTS + DELETE FROM parts.CORE_Split_Temp + WHERE GUID = a_guid + ; + + COMMIT; +END // +DELIMITER ; + +/* + +CALL parts.p_core_clear_split ( 'nips' ); + + +*/ diff --git a/static/MySQL/6012_p_core_split_key_value_pair_csv.sql b/static/MySQL/6012_p_core_split_key_value_pair_csv.sql new file mode 100644 index 0000000..78e519e --- /dev/null +++ b/static/MySQL/6012_p_core_split_key_value_pair_csv.sql @@ -0,0 +1,109 @@ + +USE parts; + +DROP PROCEDURE IF EXISTS parts.p_core_split_key_value_pair_csv; + +DELIMITER // +CREATE PROCEDURE parts.p_core_split_key_value_pair_csv ( + IN a_guid BINARY(36) + , IN a_string LONGTEXT + , IN a_debug BIT +) +BEGIN + DECLARE v_has_string BIT; + DECLARE v_current_item VARCHAR(4000); + DECLARE v_time_start TIMESTAMP(6); + + SET v_time_start := CURRENT_TIMESTAMP(6); + SET a_string := IFNULL(a_string, ''); + SET a_debug := IFNULL(a_debug, 0); + + SET v_has_string = CASE WHEN a_string = '' THEN 0 ELSE 1 END; + + IF a_debug = 1 THEN + SELECT + a_guid + , a_string + , a_debug + ; + END IF; + + CALL parts.p_core_validate_guid ( a_guid ); + + DROP TABLE IF EXISTS tmp_Input_Split_Key_Value_Pair_Csv; + DROP TABLE IF EXISTS tmp_Split_Split_Key_Value_Pair_Csv; + + CREATE TEMPORARY TABLE tmp_Input_Split_Key_Value_Pair_Csv ( + input_string TEXT + ); + + CREATE TEMPORARY TABLE tmp_Split_Split_Key_Value_Pair_Csv ( + id INT AUTO_INCREMENT PRIMARY KEY + , key_column VARCHAR(4000) + , value_column VARCHAR(4000) + ); + + INSERT INTO tmp_Input_Split_Key_Value_Pair_Csv ( + input_string + ) + VALUES ( + a_string + ); + + INSERT INTO tmp_Split_Split_Key_Value_Pair_Csv (key_column, value_column) + SELECT + SUBSTRING_INDEX(SUBSTRING_INDEX(t.pair, ':', 1), ',', -1) AS key_column, + SUBSTRING_INDEX(t.pair, ':', -1) AS value_column + FROM ( + SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(input_string, ',', n), ',', -1) pair + FROM temp_input + CROSS JOIN ( + SELECT a.N + b.N * 10 + 1 n + FROM (SELECT 0 AS N UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) a + CROSS JOIN (SELECT 0 AS N UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) b + ORDER BY n + ) numbers + WHERE n <= 1 + (LENGTH(input_string) - LENGTH(REPLACE(input_string, ',', ''))) + ) t; + + IF EXISTS (SELECT * FROM tmp_Split_Split_Key_Value_Pair_Csv LIMIT 1) THEN + START TRANSACTION; + INSERT INTO parts.CORE_Split_Key_Value_Pair_Csv_Temp ( + guid + , id + , key_column + , value_column + ) + SELECT + a_guid + , id + , key_column + , value_column + FROM tmp_Split_Split_Key_Value_Pair_Csv + ; + COMMIT; + END IF; + + DROP TEMPORARY TABLE IF EXISTS tmp_Input_Split_Key_Value_Pair_Csv; + DROP TEMPORARY TABLE IF EXISTS tmp_Split_Split_Key_Value_Pair_Csv; + + IF a_debug = 1 THEN + CALL parts.p_core_debug_timing_reporting ( v_time_start ); + END IF; +END // +DELIMITER ; + + +/* +CALL parts.p_core_split_key_value_pair_csv ( + 'nipsnipsnipsnipsnipsnipsnipsnipsnips' + , '1:100,2:200,3:300,4:400' -- a_string + , 1 +); + +SELECT * +FROM parts.CORE_Split_key_value_pair_csv_Temp +WHERE GUID = 'nipsnipsnipsnipsnipsnipsnipsnipsnips'; + +CALL parts.p_core_clear_split_key_value_pair_csv_temp( 'nipsnipsnipsnipsnipsnipsnipsnipsnips' ); +*/ diff --git a/static/MySQL/6013_p_core_clear_split_key_value_pair_csv.sql b/static/MySQL/6013_p_core_clear_split_key_value_pair_csv.sql new file mode 100644 index 0000000..8a0804c --- /dev/null +++ b/static/MySQL/6013_p_core_clear_split_key_value_pair_csv.sql @@ -0,0 +1,30 @@ + +USE parts; + +DROP PROCEDURE IF EXISTS parts.p_core_clear_split_key_value_pair_csv; + + +DELIMITER // +CREATE PROCEDURE parts.p_core_clear_split_key_value_pair_csv ( + IN a_guid BINARY(36) +) +BEGIN + CALL parts.p_core_validate_guid( a_guid ); + + START TRANSACTION; + + -- DROP TABLE IF EXISTS + DELETE FROM parts.CORE_Split_Key_Value_Pair_Csv_Temp + WHERE GUID = a_guid + ; + + COMMIT; +END // +DELIMITER ; + +/* + +CALL parts.p_core_clear_split_key_value_pair_csv ( 'nips' ); + + +*/ diff --git a/static/MySQL/7130_p_dog_calc_user.sql b/static/MySQL/7130_p_dog_calc_user.sql new file mode 100644 index 0000000..159f549 --- /dev/null +++ b/static/MySQL/7130_p_dog_calc_user.sql @@ -0,0 +1,341 @@ + +USE parts; + +DROP PROCEDURE IF EXISTS parts.p_DOG_user_eval; +DROP PROCEDURE IF EXISTS parts.p_DOG_calc_user; + +DELIMITER // +CREATE PROCEDURE parts.p_DOG_calc_user ( + IN a_guid BINARY(36) + , IN a_ids_user TEXT + , IN a_get_inactive_user BIT + , IN a_ids_permission VARCHAR(4000) + , IN a_debug BIT +) +BEGIN + DECLARE v_has_filter_permission BIT; + DECLARE v_has_filter_user BIT; + DECLARE v_id_permission INT; + DECLARE v_time_start TIMESTAMP(6); + DECLARE v_ids_row_delete VARCHAR(500); + DECLARE v_code_type_error_bad_data VARCHAR(200); + DECLARE v_id_type_error_bad_data INT; + DECLARE v_code_error_permission VARCHAR(200); + DECLARE v_id_permission_required INT; + DECLARE v_priority_access_level_required INT; + DECLARE v_priority_access_level_view INT; + + SET v_time_start := CURRENT_TIMESTAMP(6); + SET v_code_type_error_bad_data := (SELECT code FROM parts.CORE_Msg_Error_Type WHERE code = 'BAD_DATA'); + SET v_id_type_error_bad_data := (SELECT id_type FROM parts.CORE_Msg_Error_Type WHERE code = v_code_type_error_bad_data); + SET v_code_error_permission := (SELECT code FROM parts.CORE_Msg_Error_Type WHERE id_type = 2); + SET v_priority_access_level_view := (SELECT priority FROM parts.DOG_Access_Level WHERE code = 'VIEW' LIMIT 1); + + CALL parts.p_core_validate_guid ( a_guid ); + SET a_ids_user := TRIM(IFNULL(a_ids_user, '')); + SET a_get_inactive_user := IFNULL(a_get_inactive_user, 0); + SET a_ids_permission := TRIM(IFNULL(a_ids_permission, '')); + SET a_debug := IFNULL(a_debug, 0); + + IF a_debug = 1 THEN + SELECT + a_guid + , a_ids_user + , a_get_inactive_user + , a_ids_permission + , a_debug + ; + END IF; + + DROP TABLE IF EXISTS tmp_Calc_User; + DROP TABLE IF EXISTS tmp_User_Calc_User; + DROP TABLE IF EXISTS tmp_Split_Calc_User; + + CREATE TEMPORARY TABLE tmp_Calc_User ( + id_row INT PRIMARY KEY AUTO_INCREMENT NOT NULL + , id_user INT NULL + , id_permission_required INT NOT NULL + , priority_access_level_required INT NOT NULL + , is_super_user BIT NULL + , priority_access_level_user INT NULL + , has_access BIT + ); + + CREATE TEMPORARY TABLE tmp_User_Calc_User ( + id_user INT NOT NULL + , is_super_user BIT NOT NULL + -- , id_access_level INT + , priority_access_level INT NOT NULL + ); + + CREATE TEMPORARY TABLE IF NOT EXISTS tmp_Msg_Error_Calc_User ( + display_order INT NOT NULL PRIMARY KEY AUTO_INCREMENT + , id_type INT NULL + , code VARCHAR(100) NOT NULL + , msg VARCHAR(4000) NOT NULL + ); + + CREATE TEMPORARY TABLE IF NOT EXISTS tmp_Split_Calc_User ( + substring VARCHAR(4000) NOT NULL + , as_int INT NULL + ); + DELETE FROM tmp_Split_Calc_User; + + SET v_has_filter_user = CASE WHEN a_ids_user = '' THEN 0 ELSE 1 END; + SET a_ids_permission = REPLACE(a_ids_permission, '|', ','); + SET v_has_filter_permission = CASE WHEN a_ids_permission = '' THEN 0 ELSE 1 END; + -- SET v_id_access_level_view = (SELECT id_access_level FROM parts.DOG_Access_Level WHERE code = 'VIEW' LIMIT 1); + + + -- Permission IDs + IF NOT v_has_filter_permission THEN + INSERT INTO tmp_Msg_Error_Calc_User ( + id_type + , code + , msg + ) + SELECT + v_id_type_error_bad_data + , v_code_type_error_bad_data + , 'Permission ID required.' + ; + ELSE + CALL parts.p_core_split(a_guid, a_ids_permission, ',', a_debug); + + INSERT INTO tmp_Split_Calc_User ( + substring + , as_int + ) + SELECT + substring + , CONVERT(substring, DECIMAL(10,0)) AS as_int + FROM parts.CORE_Split_Temp + WHERE + GUID = a_guid + AND NOT ISNULL(substring) + AND substring != '' + ; + + CALL parts.p_core_clear_split( a_guid ); + + -- Invalid or inactive + IF EXISTS ( + SELECT PERM.id_permission + FROM tmp_Split_Calc_User t_S + LEFT JOIN parts.DOG_Permission PERM ON t_S.as_int = PERM.id_permission + WHERE + ISNULL(t_S.as_int) + OR ISNULL(PERM.id_permission) + OR PERM.active = 0 + ) THEN + INSERT INTO tmp_Msg_Error_Calc_User ( + id_type + , code + , msg + ) + SELECT + v_id_type_error_bad_data + , v_code_type_error_bad_data + , CONCAT('Invalid or inactive permission IDs: ', IFNULL(GROUP_CONCAT(t_S.substring SEPARATOR ', '), 'NULL')) + FROM tmp_Split_Calc_User t_S + LEFT JOIN parts.DOG_Permission PERM ON t_S.as_int = PERM.id_permission + WHERE + ISNULL(t_S.as_int) + OR ISNULL(PERM.id_permission) + OR PERM.active = 0 + ; + ELSE + SELECT + PERM.id_permission + , PERM.id_access_level_required + INTO + v_id_permission_required + , v_priority_access_level_required + FROM tmp_Split_Calc_User t_S + LEFT JOIN parts.DOG_Permission PERM ON t_S.as_int = PERM.id_permission + INNER JOIN parts.DOG_Access_Level AL ON PERM.id_access_level_required = AL.id_access_level + ORDER BY AL.priority ASC + LIMIT 1 + ; + + IF ISNULL(v_id_permission_required) THEN + INSERT INTO tmp_Msg_Error_Calc_User ( + id_type + , code + , msg + ) + SELECT + v_id_type_error_bad_data + , v_code_type_error_bad_data + , 'Valid Permission ID required.' + ; + END IF; + END IF; + END IF; + DELETE FROM tmp_Split_Calc_User; + + -- Users + CALL parts.p_core_split(a_guid, a_ids_user, ',', a_debug); + + INSERT INTO tmp_Split_Calc_User ( + substring + , as_int + ) + SELECT + substring + , CONVERT(substring, DECIMAL(10,0)) AS as_int + FROM parts.CORE_Split_Temp + WHERE + GUID = a_guid + AND NOT ISNULL(substring) + AND substring != '' + ; + + CALL parts.p_core_clear_split( a_guid ); + + -- Invalid or inactive + IF EXISTS (SELECT U.id_user FROM tmp_Split_Calc_User t_S LEFT JOIN parts.DOG_User U ON t_S.as_int = U.id_user WHERE ISNULL(t_S.as_int) OR ISNULL(U.id_user) OR (a_get_inactive_user = 0 AND U.active = 0)) THEN + INSERT INTO tmp_Msg_Error_Calc_User ( + id_type + , code + , msg + ) + SELECT + v_id_type_error_bad_data + , v_code_type_error_bad_data + , CONCAT('Invalid or inactive user IDs: ', IFNULL(GROUP_CONCAT(t_S.substring SEPARATOR ', '), 'NULL')) + FROM tmp_Split_Calc_User t_S + LEFT JOIN parts.DOG_User U ON t_S.as_int = U.id_user + WHERE + ISNULL(t_S.as_int) + OR ISNULL(U.id_user) + OR ( + a_get_inactive_user = 0 + AND U.active = 0 + ) + ; + ELSE + IF NOT EXISTS (SELECT * FROM tmp_Split_Calc_User) THEN + INSERT INTO tmp_Split_Calc_User (substring, as_int) + VALUES ( '', NULL ); + END IF; + + IF a_debug = 1 THEN + SELECT * + FROM tmp_Split_Calc_User; + END IF; + + INSERT INTO tmp_User_Calc_User ( + id_user + , is_super_user + , priority_access_level + ) + SELECT + U.id_user + , IFNULL(U.is_super_user, 0) AS is_super_user + , IFNULL(MIN(AL_U.priority), v_priority_access_level_view) AS priority_access_level + FROM tmp_Split_Calc_User t_S + INNER JOIN parts.DOG_User U ON t_S.as_int = U.id_user + LEFT JOIN parts.DOG_User_Role_Link URL + ON U.id_user = URL.id_user + AND URL.active + LEFT JOIN parts.DOG_Role_Permission_Link RPL + ON URL.id_role = RPL.id_role + AND RPL.active + LEFT JOIN parts.DOG_Access_Level AL_U + ON RPL.id_access_level = AL_U.id_access_level + AND AL_U.active + GROUP BY U.id_user + ; + + INSERT INTO tmp_Calc_User ( + id_user + , id_permission_required + , priority_access_level_required + , priority_access_level_user + , is_super_user + ) + SELECT + t_UCU.id_user + , v_id_permission_required + , v_priority_access_level_required + , t_UCU.priority_access_level AS priority_access_level_user + , t_UCU.is_super_user AS is_super_user + FROM tmp_User_Calc_User t_UCU + ; + END IF; + DELETE FROM tmp_Split_Calc_User; + + + -- Calculated fields + UPDATE tmp_Calc_User t_CU + SET + t_CU.has_access = ( + (t_CU.is_super_user = 1) + OR (t_CU.priority_access_level_user <= t_CU.priority_access_level_required) + ) + ; + + -- Export data to staging table + IF NOT EXISTS (SELECT * FROM tmp_Msg_Error_Calc_User) THEN + START TRANSACTION; + INSERT INTO parts.DOG_Calc_User_Temp ( + guid + , id_user + , id_permission_required + , priority_access_level_required + , priority_access_level_user + , is_super_user + , has_access + ) + SELECT + a_guid + , t_CU.id_user + , t_CU.id_permission_required + , t_CU.priority_access_level_required + , t_CU.priority_access_level_user + , t_CU.is_super_user + , t_CU.has_access + FROM tmp_Calc_User t_CU + ; + COMMIT; + END IF; + + IF a_debug = 1 THEN + SELECT * FROM tmp_Msg_Error_Calc_User; + SELECT * FROM tmp_Calc_User; + SELECT * FROM tmp_User_Calc_User; + SELECT * FROM parts.DOG_Calc_User_Temp WHERE GUID = a_guid; + CALL parts.p_DOG_clear_calc_user ( a_guid, a_debug ); + END IF; + + -- Clean up + DROP TABLE IF EXISTS tmp_Calc_User; + DROP TABLE IF EXISTS tmp_User_Calc_User; + DELETE FROM tmp_Split_Calc_User; + + IF a_debug = 1 THEN + CALL parts.p_debug_timing_reporting( v_time_start ); + END IF; +END // +DELIMITER ; + +/* + +CALL parts.p_DOG_calc_user ( + 'chips ' -- a_guid + , 1 -- a_ids_user + , 0 -- a_get_inactive_user + , '2' -- a_ids_permission + , '1' -- a_ids_access_level + , 0 -- a_debug +); +CALL parts.p_DOG_calc_user ( + 'chips ' -- a_guid + , 1 -- a_ids_user + , 0 -- a_get_inactive_user + , '2' -- a_ids_permission + , '1' -- a_ids_access_level + , 0 -- a_debug +); +*/ \ No newline at end of file diff --git a/static/MySQL/7131_p_dog_clear_calc_user.sql b/static/MySQL/7131_p_dog_clear_calc_user.sql new file mode 100644 index 0000000..61dad04 --- /dev/null +++ b/static/MySQL/7131_p_dog_clear_calc_user.sql @@ -0,0 +1,43 @@ + +USE parts; + +DROP PROCEDURE IF EXISTS parts.p_DOG_clear_calc_user; + +DELIMITER // +CREATE PROCEDURE parts.p_DOG_clear_calc_user ( + IN a_guid BINARY(36) + , IN a_debug BIT +) +BEGIN + DECLARE v_time_start TIMESTAMP(6); + SET v_time_start := CURRENT_TIMESTAMP(6); + + CALL parts.p_core_validate_guid ( a_guid ); + + START TRANSACTION; + + DELETE FROM parts.DOG_Calc_User_Temp + WHERE GUID = a_guid + ; + + COMMIT; + + IF a_debug = 1 THEN + CALL parts.p_debug_timing_reporting( v_time_start ); + END IF; +END // +DELIMITER ; + +/* + +CALL parts.p_DOG_clear_calc_user ( + 'chips ' -- a_guid + , 1 -- debug +); + +SELECT * +FROM parts.DOG_Calc_User_Temp +WHERE GUID = 'chips ' +; + +*/ diff --git a/static/MySQL/7201_p_dog_save_command.sql b/static/MySQL/7201_p_dog_save_command.sql new file mode 100644 index 0000000..481087c --- /dev/null +++ b/static/MySQL/7201_p_dog_save_command.sql @@ -0,0 +1,457 @@ + +USE parts; + +DROP PROCEDURE IF EXISTS parts.p_DOG_save_command; + +DELIMITER // +CREATE PROCEDURE parts.p_DOG_save_command ( + IN a_comment VARCHAR(500), + IN a_guid BINARY(36), + IN a_id_user INT, + IN a_debug BIT +) +BEGIN + DECLARE v_code_type_error_bad_data VARCHAR(100); + DECLARE v_id_type_error_bad_data INT; + DECLARE v_id_permission_dog_admin INT; + DECLARE v_id_permission_dog_new INT; + DECLARE v_id_change_set INT; + DECLARE v_time_start TIMESTAMP(6); + DECLARE v_can_admin BIT; + DECLARE v_can_create BIT; + + DECLARE exit handler for SQLEXCEPTION + BEGIN + GET DIAGNOSTICS CONDITION 1 + @sqlstate = RETURNED_SQLSTATE + , @errno = MYSQL_ERRNO + , @text = MESSAGE_TEXT + ; + + ROLLBACK; + + CREATE TEMPORARY TABLE IF NOT EXISTS tmp_Msg_Error ( + id_error INT NOT NULL PRIMARY KEY AUTO_INCREMENT + , id_type INT NULL + , code VARCHAR(100) + , msg VARCHAR(4000) NOT NULL + ); + + INSERT INTO tmp_Msg_Error ( + id_type + , code + , msg + ) + SELECT + MET.id_type + , @errno + , @text + FROM parts.CORE_Msg_Error_Type MET + WHERE MET.code = 'MYSQL_ERROR' + ; + + SELECT + t_ERROR.id_error + , t_ERROR.id_type + , t_ERROR.code + , ERROR_TYPE.name + , ERROR_TYPE.description + , ERROR_TYPE.is_breaking_error + , ERROR_TYPE.background_colour + , ERROR_TYPE.text_colour + , t_ERROR.msg + FROM tmp_Msg_Error t_ERROR + INNER JOIN parts.CORE_Msg_Error_Type ERROR_TYPE ON t_ERROR.id_type = ERROR_TYPE.id_type + ; + + DROP TABLE IF EXISTS tmp_Msg_Error; + END; + + SET v_time_start := CURRENT_TIMESTAMP(6); + SET v_code_type_error_bad_data := 'BAD_DATA'; + SET v_id_type_error_bad_data := (SELECT ERROR_TYPE.id_type FROM parts.CORE_Msg_Error_Type ERROR_TYPE WHERE ERROR_TYPE.code = v_code_type_error_bad_data LIMIT 1); + SET v_id_permission_dog_admin := (SELECT PERMISSION.id_permission FROM parts.DOG_Permission PERMISSION WHERE PERMISSION.code = 'DOG_ADMIN' LIMIT 1); + SET v_id_permission_dog_new := (SELECT PERMISSION.id_permission FROM parts.DOG_Permission PERMISSION WHERE PERMISSION.code = 'DOG_CREATE' LIMIT 1); + + CALL parts.p_core_validate_guid ( a_guid ); + + DROP TABLE IF EXISTS tmp_Command; + + CREATE TEMPORARY TABLE tmp_Command ( + id_command INT + , id_command_category INT + , name VARCHAR(250) + , hand_signal_default_description TEXT + , can_have_button BIT + , notes TEXT + , active BIT + , is_new BIT + , name_error VARCHAR(250) + + , name_command_category VARCHAR(250) + ); + + CREATE TEMPORARY TABLE IF NOT EXISTS tmp_Msg_Error ( + id_error INT NOT NULL PRIMARY KEY AUTO_INCREMENT + , id_type INT NULL + , code VARCHAR(100) + , msg VARCHAR(4000) NOT NULL + ); + + + -- Get data from Temp table + INSERT INTO tmp_Command ( + id_command + , id_command_category + , name + , hand_signal_default_description + , can_have_button + , notes + , active + , is_new + + , name_command_category + ) + SELECT + COMMAND_T.id_command AS id_command + , COMMAND_T.id_command_category AS id_command_category + , COALESCE(COMMAND_T.name, COMMAND.name) AS name + , COALESCE(COMMAND_T.hand_signal_default_description, COMMAND.hand_signal_default_description) AS hand_signal_default_description + , COALESCE(COMMAND_T.can_have_button, COMMAND.can_have_button) AS can_have_button + , COALESCE(COMMAND_T.notes, COMMAND.notes) AS notes + , COALESCE(COMMAND_T.active, COMMAND.active, 1) AS active + , CASE WHEN IFNULL(COMMAND_T.id_command, 0) < 1 THEN 1 ELSE 0 END AS is_new + + , COMMAND_T.name_command_category AS name_command_category + FROM parts.DOG_Command_Temp COMMAND_T + LEFT JOIN parts.DOG_Command COMMAND ON COMMAND_T.id_command = COMMAND.id_command + WHERE COMMAND_T.guid = a_guid + ; + + UPDATE tmp_Command t_COMMAND + SET name_error = COALESCE(t_COMMAND.name, t_COMMAND.notes, t_COMMAND.name_command_category, '(No Command)') + ; + + -- Find missing id_command_category by name_command_category + UPDATE tmp_Command t_COMMAND + INNER JOIN parts.DOG_Command_Category COMMAND_CATEGORY ON t_COMMAND.name_command_category = COMMAND_CATEGORY.name + SET t_COMMAND.id_command_category = COMMAND_CATEGORY.id_command_category + WHERE t_COMMAND.id_command_category IS NULL + ; + + IF EXISTS ( + SELECT * + FROM tmp_Command t_COMMAND + WHERE ISNULL(t_COMMAND.id_command_category) + LIMIT 1 + ) THEN + INSERT INTO tmp_Msg_Error ( + id_type + , code + , msg + ) + SELECT + v_id_type_error_bad_data + , v_code_type_error_bad_data + , CONCAT('The following Command(s) do not have a Category: ', GROUP_CONCAT(t_COMMAND.name_error SEPARATOR ', ')) AS msg + FROM tmp_Command t_COMMAND + WHERE t_COMMAND.id_command_category IS NULL + ; + END IF; + + -- Validation + -- Missing mandatory fields + -- id_command_category + IF EXISTS (SELECT * FROM tmp_Command t_COMMAND WHERE ISNULL(t_COMMAND.id_command_category) LIMIT 1) THEN + INSERT INTO tmp_Msg_Error ( + id_type + , code + , msg + ) + SELECT + v_id_type_error_bad_data + , v_code_type_error_bad_data + , CONCAT('The following Command(s) do not have a Category: ', GROUP_CONCAT(t_COMMAND.name_error SEPARATOR ', ')) AS msg + FROM tmp_Command t_COMMAND + WHERE ISNULL(t_COMMAND.id_command_category) + ; + END IF; + -- name + IF EXISTS (SELECT * FROM tmp_Command t_COMMAND WHERE ISNULL(t_COMMAND.name) LIMIT 1) THEN + INSERT INTO tmp_Msg_Error ( + id_type + , code + , msg + ) + SELECT + v_id_type_error_bad_data + , v_code_type_error_bad_data + , CONCAT('The following Command(s) do not have a Name: ', GROUP_CONCAT(t_COMMAND.name_error SEPARATOR ', ')) AS msg + FROM tmp_Command t_COMMAND + WHERE ISNULL(t_COMMAND.name) + ; + END IF; + -- can_have_button + IF EXISTS (SELECT * FROM tmp_Command t_COMMAND WHERE ISNULL(t_COMMAND.can_have_button) LIMIT 1) THEN + INSERT INTO tmp_Msg_Error ( + id_type + , code + , msg + ) + SELECT + v_id_type_error_bad_data + , v_code_type_error_bad_data + , CONCAT('The following Command(s) do not have a Can-Have-Button: ', GROUP_CONCAT(t_COMMAND.name_error SEPARATOR ', ')) AS msg + FROM tmp_Command t_COMMAND + WHERE ISNULL(t_COMMAND.can_have_button) + ; + END IF; + + -- Permissions + IF a_debug = 1 THEN + SELECT + a_guid + , a_id_user + , FALSE -- a_get_inactive_user + , v_id_permission_dog_admin + , v_id_permission_dog_new + , 0 -- a_debug + ; + END IF; + + CALL parts.p_DOG_calc_user( + a_guid + , a_id_user + , FALSE -- a_get_inactive_user + , v_id_permission_dog_admin + , 0 -- a_debug + ); + + SELECT + IFNULL(CU_T.has_access, 0) + INTO + v_can_admin + FROM parts.DOG_Calc_User_Temp CU_T + WHERE CU_T.GUID = a_guid + LIMIT 1 + ; + + CALL parts.p_DOG_clear_calc_user( + a_guid + , 0 -- a_debug + ); + + CALL parts.p_DOG_calc_user( + a_guid + , a_id_user + , FALSE -- a_get_inactive_user + , v_id_permission_dog_new + , 0 -- a_debug + ); + + SELECT + IFNULL(CU_T.has_access, 0) + INTO + v_can_create + FROM parts.DOG_Calc_User_Temp CU_T + WHERE CU_T.GUID = a_guid + LIMIT 1 + ; + + CALL parts.p_DOG_clear_calc_user( + a_guid + , 0 -- a_debug + ); + + IF (v_can_create = 0 AND EXISTS(SELECT * FROM tmp_Command WHERE is_new = 1)) THEN + DELETE t_ME + FROM tmp_Msg_Error t_ME + WHERE t_ME.id_type <> v_id_type_error_no_permission + ; + INSERT INTO tmp_Msg_Error ( + id_type + , code + , msg + ) + VALUES ( + v_id_type_error_no_permission + , v_code_type_error_no_permission + , 'You do not have permission to create new Commands.' + ) + ; + END IF; + + IF (v_can_admin = 0 AND EXISTS(SELECT * FROM tmp_Command WHERE is_new = 0)) THEN + DELETE t_ME + FROM tmp_Msg_Error t_ME + WHERE t_ME.id_type <> v_id_type_error_no_permission + ; + INSERT INTO tmp_Msg_Error ( + id_type + , code + , msg + ) + VALUES ( + v_id_type_error_no_permission + , v_code_type_error_no_permission + , 'You do not have permission to admin Commands.' + ) + ; + END IF; + + IF EXISTS (SELECT * FROM tmp_Msg_Error t_ERROR INNER JOIN parts.CORE_Msg_Error_Type ERROR_TYPE ON t_ERROR.id_type = ERROR_TYPE.id_type WHERE ERROR_TYPE.is_breaking_error = 1 LIMIT 1) THEN + IF a_debug = 1 THEN + SELECT * from tmp_Command; + END IF; + + DELETE FROM tmp_Command; + END IF; + + IF NOT EXISTS (SELECT * FROM tmp_Msg_Error t_ERROR INNER JOIN parts.CORE_Msg_Error_Type ERROR_TYPE ON t_ERROR.id_type = ERROR_TYPE.id_type WHERE ERROR_TYPE.is_breaking_error = 1 LIMIT 1) THEN + START TRANSACTION; + + INSERT INTO parts.DOG_Dog_Change_Set ( + comment + , id_user_updated_last_by + , updated_last_on + ) + VALUES ( + a_comment + , a_id_user + , v_time_start + ) + ; + + SET v_id_change_set := LAST_INSERT_ID(); + + UPDATE parts.DOG_Command COMMAND + INNER JOIN tmp_Command t_COMMAND + ON COMMAND.id_command = t_COMMAND.id_command + AND t_COMMAND.is_new = 0 + SET + COMMAND.id_command_category = t_COMMAND.id_command_category + , COMMAND.name = t_COMMAND.name + , COMMAND.hand_signal_default_description = t_COMMAND.hand_signal_default_description + , COMMAND.can_have_button = t_COMMAND.can_have_button + , COMMAND.notes = t_COMMAND.notes + , COMMAND.active = t_COMMAND.active + , COMMAND.id_change_set = v_id_change_set + ; + + INSERT INTO parts.DOG_Command ( + id_command_category + , name + , hand_signal_default_description + , can_have_button + , notes + , active + , id_user_created_by + , created_on + ) + SELECT + t_COMMAND.id_command_category AS id_command_category + , t_COMMAND.name AS name + , t_COMMAND.hand_signal_default_description AS hand_signal_default_description + , t_COMMAND.can_have_button AS can_have_button + , t_COMMAND.notes AS notes + , t_COMMAND.active AS active + , a_id_user AS created_by + , v_time_start AS created_on + FROM tmp_Command t_COMMAND + WHERE + t_COMMAND.is_new = 1 + AND t_COMMAND.active = 1 + ; + + COMMIT; + END IF; + + START TRANSACTION; + + DELETE FROM parts.DOG_Command_Temp + WHERE GUID = a_guid + ; + + COMMIT; + + -- Errors + SELECT + t_ERROR.id_error + , t_ERROR.id_type + , t_ERROR.code + , ERROR_TYPE.name + , ERROR_TYPE.description + , ERROR_TYPE.is_breaking_error + , ERROR_TYPE.background_colour + , ERROR_TYPE.text_colour + , t_ERROR.msg + FROM tmp_Msg_Error t_ERROR + INNER JOIN parts.CORE_Msg_Error_Type ERROR_TYPE ON t_ERROR.id_type = ERROR_TYPE.id_type + ; + + IF a_debug = 1 THEN + SELECT * from tmp_Command; + END IF; + + DROP TEMPORARY TABLE tmp_Command; + DROP TEMPORARY TABLE tmp_Msg_Error; + + IF a_debug = 1 THEN + CALL parts.p_core_debug_timing_reporting ( v_time_start ); + END IF; +END // +DELIMITER ; + + + +/* + + +select + * + -- COUNT(*) +-- delete +from parts.DOG_Command_Temp +; +select COUNT(*) +from parts.DOG_Command_Temp +; +select + * + -- COUNT(*) +-- delete +from parts.DOG_Command +; +select COUNT(*) +from parts.DOG_Command +; + + +CALL parts.p_DOG_save_command ( + 'nipples' + , (SELECT GUID FROM parts.DOG_Command_Temp COMMAND_TEMP ORDER BY id_temp DESC LIMIT 1) + , 1 + , 1 +); + + +select + * + -- COUNT(*) +-- delete +from parts.DOG_Command_Temp +; +select COUNT(*) +from parts.DOG_Command_Temp +; +select + * + -- COUNT(*) +-- delete +from parts.DOG_Command +; +select COUNT(*) +from parts.DOG_Command +; + +*/ diff --git a/static/MySQL/7202_p_dog_test_save_command.sql b/static/MySQL/7202_p_dog_test_save_command.sql new file mode 100644 index 0000000..c6f90be --- /dev/null +++ b/static/MySQL/7202_p_dog_test_save_command.sql @@ -0,0 +1,108 @@ +USE parts; + +DROP PROCEDURE IF EXISTS parts.p_DOG_test_save_command; + + +DELIMITER // +CREATE PROCEDURE parts.p_DOG_test_save_command () +BEGIN + + DECLARE v_guid BINARY(36); + DECLARE v_time_start TIMESTAMP(6); + + SET v_time_start := CURRENT_TIMESTAMP(6); + SET v_guid := 'nipple_ripple_chipple_spittle_pickle'; -- 123456789012345678901234567890123456 + + SELECT 'Start of Test'; + + SELECT * + FROM parts.DOG_Command + ; + SELECT * + FROM parts.DOG_Command_Temp + ; + + START TRANSACTION; + + INSERT INTO parts.DOG_Command_Temp ( + id_command + , email + , name_contact + , name_company + , message + , guid + , active + ) + /* + VALUES ( + -1 -- id_command + , 'edward.middletonsmith@gmail.com' -- email + , 'Teddy' -- name_contact + , 'PARTS Ltd' -- name_company + , 'Sa dude' -- message + , v_guid + ) + */ + VALUES ( + -1 -- id_command + , 'edward.middletonsmith@gmail.com' -- email + , 'Teddy' -- name_contact + , 'PARTS Ltd' -- name_company + , 'hegrodorf is good' -- message + , v_guid + , 1 -- active + ) + ; + + COMMIT; + + SELECT * + FROM parts.DOG_Command_Temp + -- WHERE GUID = v_guid + ; + + CALL parts.p_DOG_save_command ( + 'Test save Command' -- comment + , v_guid -- guid + , 3 -- 1 -- id_user + , 1 -- debug + ); + + SELECT * + FROM parts.DOG_Command + ; + SELECT * + FROM parts.DOG_Command_Temp + ; + + CALL parts.p_debug_timing_reporting ( v_time_start ); +END // +DELIMITER ; + + +/* +SELECT 'Before Test'; +SELECT * +FROM parts.DOG_Command +; +SELECT * +FROM parts.DOG_Command_Temp +; + + +CALL parts.p_DOG_test_save_command (); + +SELECT 'After Test'; +SELECT * +FROM parts.DOG_Command +; +SELECT * +FROM parts.DOG_Command_Temp +; + +DELETE FROM parts.DOG_Command_Temp; + +DROP TABLE IF EXISTS tmp_Msg_Error; + + +*/ diff --git a/static/MySQL/7203_p_dog_get_many_dog_command.sql b/static/MySQL/7203_p_dog_get_many_dog_command.sql new file mode 100644 index 0000000..aefae05 --- /dev/null +++ b/static/MySQL/7203_p_dog_get_many_dog_command.sql @@ -0,0 +1,662 @@ + +USE parts; + +DROP PROCEDURE IF EXISTS parts.p_DOG_get_many_dog_command; + +DELIMITER // +CREATE PROCEDURE parts.p_DOG_get_many_dog_command ( + IN a_id_user INT + , IN a_get_all_dog BIT + , IN a_get_inactive_dog BIT + , IN a_ids_dog TEXT + , IN a_get_all_command BIT + , IN a_get_inactive_command BIT + , IN a_ids_command TEXT + , IN a_get_all_understanding_level BIT + , IN a_get_inactive_understanding_level BIT + , IN a_ids_understanding_level TEXT + , IN a_get_all_obedience_level BIT + , IN a_get_inactive_obedience_level BIT + , IN a_ids_obedience_level TEXT + , IN a_debug BIT +) +BEGIN + DECLARE v_code_type_error_bad_data VARCHAR(100); + DECLARE v_code_type_error_no_permission VARCHAR(100); + DECLARE v_id_type_error_bad_data INT; + DECLARE v_id_type_error_no_permission INT; + DECLARE v_has_filter_command BIT; + DECLARE v_has_filter_dog BIT; + DECLARE v_has_filter_obedience_level BIT; + DECLARE v_has_filter_understanding_level BIT; + DECLARE v_guid BINARY(36); + DECLARE v_id_permission_dog_view INT; + DECLARE v_id_minimum INT; + DECLARE v_time_start TIMESTAMP(6); + DECLARE v_can_view BIT; + + DECLARE exit handler for SQLEXCEPTION + BEGIN + GET DIAGNOSTICS CONDITION 1 + @sqlstate = RETURNED_SQLSTATE + , @errno = MYSQL_ERRNO + , @text = MESSAGE_TEXT + ; + + ROLLBACK; + + CREATE TEMPORARY TABLE IF NOT EXISTS tmp_Msg_Error ( + id_error INT NOT NULL PRIMARY KEY AUTO_INCREMENT + , id_type INT NULL + , code VARCHAR(100) NOT NULL + , msg VARCHAR(4000) NOT NULL + ); + + INSERT INTO tmp_Msg_Error ( + id_type + , code + , msg + ) + SELECT + MET.id_type + , @errno + , @text + FROM parts.CORE_Msg_Error_Type MET + WHERE MET.code = 'MYSQL_ERROR' + ; + + SELECT + t_ERROR.id_error + , t_ERROR.id_type + , t_ERROR.code + , ERROR_TYPE.name + , ERROR_TYPE.description + , ERROR_TYPE.is_breaking_error + , ERROR_TYPE.background_colour + , ERROR_TYPE.text_colour + , t_ERROR.msg + FROM tmp_Msg_Error t_ERROR + INNER JOIN parts.CORE_Msg_Error_Type ERROR_TYPE ON t_ERROR.id_type = ERROR_TYPE.id_type + ; + + DROP TABLE IF EXISTS tmp_Msg_Error; + END; + + SET v_time_start := CURRENT_TIMESTAMP(6); + SET v_guid := UUID(); + SET v_code_type_error_bad_data := 'BAD_DATA'; + SET v_code_type_error_no_permission := 'NO_PERMISSION'; + SET v_id_type_error_bad_data := (SELECT ERROR_TYPE.id_type FROM parts.CORE_Msg_Error_Type ERROR_TYPE WHERE ERROR_TYPE.code = v_code_type_error_bad_data LIMIT 1); + SET v_id_type_error_no_permission := (SELECT ERROR_TYPE.id_type FROM parts.CORE_Msg_Error_Type ERROR_TYPE WHERE ERROR_TYPE.code = v_code_type_error_no_permission LIMIT 1); + SET v_id_permission_dog_view := (SELECT PERMISSION.id_permission FROM parts.DOG_Permission PERMISSION WHERE PERMISSION.code = 'DOG_VIEW' LIMIT 1); + + SET a_id_user := IFNULL(a_id_user, 0); + SET a_get_all_dog := IFNULL(a_get_all_dog, 0); + SET a_get_inactive_dog := IFNULL(a_get_inactive_dog, 0); + SET a_ids_dog := TRIM(IFNULL(a_ids_dog, '')); + SET a_get_all_command := IFNULL(a_get_all_command, 0); + SET a_get_inactive_command := IFNULL(a_get_inactive_command, 0); + SET a_ids_command := TRIM(IFNULL(a_ids_command, '')); + SET a_get_all_understanding_level := IFNULL(a_get_all_understanding_level, 0); + SET a_get_inactive_understanding_level := IFNULL(a_get_inactive_understanding_level, 0); + SET a_ids_understanding_level := TRIM(IFNULL(a_ids_understanding_level, '')); + SET a_get_all_obedience_level := IFNULL(a_get_all_obedience_level, 0); + SET a_get_inactive_obedience_level := IFNULL(a_get_inactive_obedience_level, 0); + SET a_ids_obedience_level := TRIM(IFNULL(a_ids_obedience_level, '')); + SET a_debug := IFNULL(a_debug, 0); + + IF a_debug = 1 THEN + SELECT + a_id_user + , a_get_all_dog + , a_get_inactive_dog + , a_ids_dog + , a_get_all_command + , a_get_inactive_command + , a_ids_command + , a_get_all_understanding_level + , a_get_inactive_understanding_level + , a_ids_understanding_level + , a_get_all_obedience_level + , a_get_inactive_obedience_level + , a_ids_obedience_level + , a_debug + ; + + SELECT + v_id_type_error_bad_data + , v_id_type_error_no_permission + , v_guid + , v_id_permission_dog_view + , v_time_start + ; + END IF; + + DROP TEMPORARY TABLE IF EXISTS tmp_Split; + DROP TEMPORARY TABLE IF EXISTS tmp_Msg_Error; + DROP TEMPORARY TABLE IF EXISTS tmp_Obedience_Level; + DROP TEMPORARY TABLE IF EXISTS tmp_Understanding_Level; + DROP TEMPORARY TABLE IF EXISTS tmp_Command; + DROP TEMPORARY TABLE IF EXISTS tmp_Dog; + + CREATE TEMPORARY TABLE tmp_Dog ( + id_dog INT NOT NULL + , name VARCHAR(250) + ); + + CREATE TEMPORARY TABLE tmp_Command ( + id_command INT NOT NULL + -- , code VARCHAR(100) + , name VARCHAR(250) + ); + + CREATE TEMPORARY TABLE tmp_Understanding_Level ( + id_understanding_level INT NOT NULL + , code VARCHAR(100) + , name VARCHAR(250) + ); + + CREATE TEMPORARY TABLE tmp_Obedience_Level ( + id_obedience_level INT NOT NULL + , code VARCHAR(100) + , name VARCHAR(250) + ); + + CREATE TEMPORARY TABLE IF NOT EXISTS tmp_Msg_Error ( + id_error INT NOT NULL PRIMARY KEY AUTO_INCREMENT + , id_type INT NULL + , code VARCHAR(100) NOT NULL + , msg VARCHAR(4000) NOT NULL + ); + + CREATE TEMPORARY TABLE IF NOT EXISTS tmp_Split ( + substring VARCHAR(4000) NOT NULL + , as_int INT NULL + ); + DELETE FROM tmp_Split; + + CALL parts.p_core_validate_guid ( v_guid ); + + SET v_has_filter_dog = CASE WHEN a_ids_dog = '' THEN 0 ELSE 1 END; + SET v_has_filter_command = CASE WHEN a_ids_command = '' THEN 0 ELSE 1 END; + SET v_has_filter_understanding_level = CASE WHEN a_ids_understanding_level = '' THEN 0 ELSE 1 END; + SET v_has_filter_obedience_level = CASE WHEN a_ids_obedience_level = '' THEN 0 ELSE 1 END; + + -- Dogs + IF v_has_filter_dog = 1 THEN + CALL parts.p_split(v_guid, a_ids_dog, ',', a_debug); + + INSERT INTO tmp_Split ( + substring + , as_int + ) + SELECT + SPLIT_T.substring + , CONVERT(SPLIT_T.substring, DECIMAL(10,0)) AS as_int + FROM parts.CORE_Split_Temp SPLIT_T + WHERE + SPLIT_T.GUID = v_guid + AND IFNULL(SPLIT_T.substring, '') <> '' + ; + + CALL parts.p_clear_split_temp( v_guid ); + END IF; + + IF NOT EXISTS (SELECT * FROM tmp_Msg_Error t_ERROR INNER JOIN parts.CORE_Msg_Error_Type ERROR_TYPE ON t_ERROR.id_type = ERROR_TYPE.id_type WHERE ERROR_TYPE.is_breaking_error = 1 LIMIT 1) THEN + IF EXISTS ( + SELECT * + FROM tmp_Split t_SPLIT + LEFT JOIN parts.DOG_Dog DOG ON t_SPLIT.as_int = DOG.id_dog + WHERE + ISNULL(t_SPLIT.as_int) + OR ISNULL(DOG.id_dog) + OR ( + DOG.active = 0 + AND a_get_inactive_dog = 0 + ) + ) THEN + INSERT INTO tmp_Msg_Error ( + id_type + , code + , msg + ) + SELECT + v_id_type_error_bad_data + , v_code_type_error_bad_data + , CONCAT('Invalid or inactive Dog IDs: ', IFNULL(GROUP_CONCAT(t_SPLIT.substring SEPARATOR ', '), 'NULL')) + FROM tmp_Split t_SPLIT + LEFT JOIN parts.DOG_Dog DOG ON t_SPLIT.as_int = DOG.id_dog + WHERE + ISNULL(t_SPLIT.as_int) + OR ISNULL(DOG.id_dog) + OR ( + DOG.active = 0 + AND a_get_inactive_dog = 0 + ) + ; + ELSE + INSERT INTO tmp_Dog ( + id_dog + , name + ) + SELECT + DOG.id_dog + , DOG.name + FROM tmp_Split t_SPLIT + RIGHT JOIN parts.DOG_Dog DOG ON t_SPLIT.as_int = DOG.id_dog + WHERE + ( + a_get_all_dog = 1 + OR ( + v_has_filter_dog = 1 + AND NOT ISNULL(t_SPLIT.as_int) + ) + ) + AND ( + a_get_inactive_dog = 1 + OR DOG.active = 1 + ) + ; + END IF; + END IF; + + DELETE FROM tmp_Split; + + -- Commands + IF v_has_filter_command = 1 THEN + CALL parts.p_split(v_guid, a_ids_command, ',', a_debug); + + INSERT INTO tmp_Split ( + substring + , as_int + ) + SELECT + substring + , CONVERT(substring, DECIMAL(10,0)) AS as_int + FROM parts.CORE_Split_Temp + WHERE + GUID = v_guid + AND NOT ISNULL(substring) + AND substring <> '' + ; + + CALL parts.p_clear_split_temp( v_guid ); + END IF; + + IF NOT EXISTS (SELECT * FROM tmp_Msg_Error t_ERROR INNER JOIN parts.CORE_Msg_Error_Type ERROR_TYPE ON t_ERROR.id_type = ERROR_TYPE.id_type WHERE ERROR_TYPE.is_breaking_error = 1 LIMIT 1) THEN + IF EXISTS ( + SELECT * + FROM tmp_Split t_SPLIT + LEFT JOIN parts.DOG_Command COMMAND ON t_SPLIT.as_int = COMMAND.id_command + WHERE + ISNULL(t_SPLIT.as_int) + OR ISNULL(COMMAND.id_command) + OR ( + COMMAND.active = 0 + AND a_get_inactive_command = 0 + ) + ) THEN + INSERT INTO tmp_Msg_Error ( + id_type + , code + , msg + ) + SELECT + v_id_type_error_bad_data + , v_code_type_error_bad_data + , CONCAT('Invalid or inactive Command IDs: ', IFNULL(GROUP_CONCAT(t_SPLIT.substring SEPARATOR ', '), 'NULL')) + FROM tmp_Split t_SPLIT + LEFT JOIN parts.DOG_Command COMMAND ON t_SPLIT.as_int = COMMAND.id_command + WHERE + ISNULL(t_SPLIT.as_int) + OR ISNULL(COMMAND.id_command) + OR ( + COMMAND.active = 0 + AND a_get_inactive_command = 0 + ) + ; + ELSE + INSERT INTO tmp_Command ( + id_command + , name + ) + SELECT + COMMAND.id_command + -- , COMMAND.code + , COMMAND.name + FROM tmp_Split t_SPLIT + RIGHT JOIN parts.DOG_Command COMMAND ON t_SPLIT.as_int = COMMAND.id_command + WHERE + ( + a_get_all_command = 1 + OR ( + v_has_filter_command = 1 + AND NOT ISNULL(t_SPLIT.as_int) + ) + ) + AND ( + a_get_inactive_command = 1 + OR COMMAND.active = 1 + ) + ; + END IF; + END IF; + + DELETE FROM tmp_Split; + + -- Understanding Levels + IF v_has_filter_understanding_level = 1 THEN + CALL parts.p_split(v_guid, a_ids_understanding_level, ',', a_debug); + + INSERT INTO tmp_Split ( + substring + , as_int + ) + SELECT + substring + , CONVERT(substring, DECIMAL(10,0)) AS as_int + FROM parts.CORE_Split_Temp + WHERE + GUID = v_guid + AND NOT ISNULL(substring) + AND substring <> '' + ; + + CALL parts.p_clear_split_temp( v_guid ); + END IF; + + IF NOT EXISTS (SELECT * FROM tmp_Msg_Error t_ERROR INNER JOIN parts.CORE_Msg_Error_Type ERROR_TYPE ON t_ERROR.id_type = ERROR_TYPE.id_type WHERE ERROR_TYPE.is_breaking_error = 1 LIMIT 1) THEN + IF EXISTS ( + SELECT * + FROM tmp_Split t_SPLIT + LEFT JOIN parts.DOG_Understanding_Level UNDERSTANDING_LEVEL ON t_SPLIT.as_int = UNDERSTANDING_LEVEL.id_understanding_level + WHERE + ISNULL(t_SPLIT.as_int) + OR ISNULL(UNDERSTANDING_LEVEL.id_understanding_level) + OR ( + UNDERSTANDING_LEVEL.active = 0 + AND a_get_inactive_understanding_level = 0 + ) + ) THEN + INSERT INTO tmp_Msg_Error ( + id_type + , code + , msg + ) + SELECT + v_id_type_error_bad_data + , v_code_type_error_bad_data + , CONCAT('Invalid or inactive Understanding Level IDs: ', IFNULL(GROUP_CONCAT(t_SPLIT.substring SEPARATOR ', '), 'NULL')) + FROM tmp_Split t_SPLIT + LEFT JOIN parts.DOG_Understanding_Level UNDERSTANDING_LEVEL ON t_SPLIT.as_int = UNDERSTANDING_LEVEL.id_understanding_level + WHERE + ISNULL(t_SPLIT.as_int) + OR ISNULL(UNDERSTANDING_LEVEL.id_understanding_level) + OR ( + UNDERSTANDING_LEVEL.active = 0 + AND a_get_inactive_understanding_level = 0 + ) + ; + ELSE + INSERT INTO tmp_Understanding_Level ( + id_understanding_level + , code + , name + ) + SELECT + UNDERSTANDING_LEVEL.id_understanding_level + , UNDERSTANDING_LEVEL.code + , UNDERSTANDING_LEVEL.name + FROM tmp_Split t_SPLIT + RIGHT JOIN parts.DOG_Understanding_Level UNDERSTANDING_LEVEL ON t_SPLIT.as_int = UNDERSTANDING_LEVEL.id_understanding_level + WHERE + ( + a_get_all_understanding_level = 1 + OR ( + v_has_filter_understanding_level = 1 + AND NOT ISNULL(t_SPLIT.as_int) + ) + ) + AND ( + a_get_inactive_understanding_level = 1 + OR UNDERSTANDING_LEVEL.active = 1 + ) + ; + END IF; + END IF; + + DELETE FROM tmp_Split; + + -- Obedience Levels + IF v_has_filter_obedience_level = 1 THEN + CALL parts.p_split(v_guid, a_ids_obedience_level, ',', a_debug); + + INSERT INTO tmp_Split ( + substring + , as_int + ) + SELECT + substring + , CONVERT(substring, DECIMAL(10,0)) AS as_int + FROM parts.CORE_Split_Temp + WHERE + GUID = v_guid + AND NOT ISNULL(substring) + AND substring <> '' + ; + + CALL parts.p_clear_split_temp( v_guid ); + END IF; + + IF NOT EXISTS (SELECT * FROM tmp_Msg_Error t_ERROR INNER JOIN parts.CORE_Msg_Error_Type ERROR_TYPE ON t_ERROR.id_type = ERROR_TYPE.id_type WHERE ERROR_TYPE.is_breaking_error = 1 LIMIT 1) THEN + IF EXISTS ( + SELECT * + FROM tmp_Split t_SPLIT + LEFT JOIN parts.DOG_Obedience_Level OBEDIENCE_LEVEL ON t_SPLIT.as_int = OBEDIENCE_LEVEL.id_obedience_level + WHERE + ISNULL(t_SPLIT.as_int) + OR ISNULL(OBEDIENCE_LEVEL.id_obedience_level) + OR ( + OBEDIENCE_LEVEL.active = 0 + AND a_get_inactive_obedience_level = 0 + ) + ) THEN + INSERT INTO tmp_Msg_Error ( + id_type + , code + , msg + ) + SELECT + v_id_type_error_bad_data + , v_code_type_error_bad_data + , CONCAT('Invalid or inactive Obedience Level IDs: ', IFNULL(GROUP_CONCAT(t_SPLIT.substring SEPARATOR ', '), 'NULL')) + FROM tmp_Split t_SPLIT + LEFT JOIN parts.DOG_Obedience_Level OBEDIENCE_LEVEL ON t_SPLIT.as_int = OBEDIENCE_LEVEL.id_obedience_level + WHERE + ISNULL(t_SPLIT.as_int) + OR ISNULL(OBEDIENCE_LEVEL.id_obedience_level) + OR ( + OBEDIENCE_LEVEL.active = 0 + AND a_get_inactive_obedience_level = 0 + ) + ; + ELSE + INSERT INTO tmp_Obedience_Level ( + id_obedience_level + , code + , name + ) + SELECT + OBEDIENCE_LEVEL.id_obedience_level + , OBEDIENCE_LEVEL.code + , OBEDIENCE_LEVEL.name + FROM tmp_Split t_SPLIT + RIGHT JOIN parts.DOG_Obedience_Level OBEDIENCE_LEVEL ON t_SPLIT.as_int = OBEDIENCE_LEVEL.id_obedience_level + WHERE + ( + a_get_all_obedience_level = 1 + OR ( + v_has_filter_obedience_level = 1 + AND NOT ISNULL(t_SPLIT.as_int) + ) + ) + AND ( + a_get_inactive_obedience_level = 1 + OR OBEDIENCE_LEVEL.active = 1 + ) + ; + END IF; + END IF; + + DELETE FROM tmp_Split; + + + -- Permissions + IF a_debug = 1 THEN + SELECT + v_guid + , a_id_user + , FALSE -- a_get_inactive_user + , v_id_permission_dog_view + , 0 -- a_debug + ; + END IF; + + CALL parts.p_DOG_calc_user( + v_guid + , a_id_user + , FALSE -- a_get_inactive_user + , v_id_permission_dog_view + , 0 -- a_debug + ); + + SELECT + IFNULL(CALC_USER_T.has_access, 0) + INTO + v_can_view + FROM parts.DOG_Calc_User_Temp CALC_USER_T + WHERE CALC_USER_T.GUID = v_guid + LIMIT 1 + ; + + IF a_debug = 1 THEN + SELECT v_can_view; + END IF; + + IF (v_can_view = 0) THEN + DELETE t_ME + FROM tmp_Msg_Error t_ME + WHERE t_ME.id_type <> v_id_type_error_no_permission + ; + INSERT INTO tmp_Msg_Error ( + id_type + , code + , msg + ) + VALUES ( + v_id_type_error_no_permission + , v_code_type_error_no_permission + , 'You do not have permission to view Commands.' + ) + ; + END IF; + + CALL parts.p_DOG_clear_calc_user( + v_guid + , 0 -- a_debug + ); + + IF EXISTS(SELECT * FROM tmp_Msg_Error t_ERROR INNER JOIN parts.CORE_Msg_Error_Type ERROR_TYPE ON t_ERROR.id_type = ERROR_TYPE.id_type WHERE ERROR_TYPE.is_breaking_error = 1 LIMIT 1) THEN + IF a_debug = 1 THEN + SELECT * FROM tmp_Dog; + SELECT * FROM tmp_Command; + SELECT * FROM tmp_Obedience_Level; + END IF; + + DELETE FROM tmp_Dog; + DELETE FROM tmp_Command; + SELECT * FROM tmp_Understanding_Level; + DELETE FROM tmp_Obedience_Level; + END IF; + + -- Outputs + -- Commands + SELECT + DOG_COMMAND_LINK.id_link AS id_dog_command_link + , t_DOG.id_dog + , t_DOG.name + , t_COMMAND.id_command + -- , t_COMMAND.code + , t_COMMAND.name + , t_UNDERSTANDING_LEVEL.id_understanding_level + , t_UNDERSTANDING_LEVEL.code AS code_understanding_level + , t_UNDERSTANDING_LEVEL.name AS name_understanding_level + , t_OBEDIENCE_LEVEL.id_obedience_level + , t_OBEDIENCE_LEVEL.code AS code_obedience_level + , t_OBEDIENCE_LEVEL.name AS name_obedience_level + , DOG_COMMAND_LINK.hand_signal_description + , DOG_COMMAND_LINK.notes + , DOG_COMMAND_LINK.active + FROM parts.DOG_Dog_Command_Link DOG_COMMAND_LINK + INNER JOIN tmp_Dog t_DOG ON DOG_COMMAND_LINK.id_dog = t_DOG.id_dog + INNER JOIN tmp_Command t_COMMAND ON DOG_COMMAND_LINK.id_command = t_COMMAND.id_command + INNER JOIN tmp_Understanding_Level t_UNDERSTANDING_LEVEL ON DOG_COMMAND_LINK.id_understanding_level = t_UNDERSTANDING_LEVEL.id_understanding_level + INNER JOIN tmp_Obedience_Level t_OBEDIENCE_LEVEL ON DOG_COMMAND_LINK.id_obedience_level = t_OBEDIENCE_LEVEL.id_obedience_level + ; + + -- Errors + SELECT + t_ERROR.id_error + , t_ERROR.id_type + , t_ERROR.code + , ERROR_TYPE.name + , ERROR_TYPE.description + , ERROR_TYPE.is_breaking_error + , ERROR_TYPE.background_colour + , ERROR_TYPE.text_colour + , t_ERROR.msg + FROM tmp_Msg_Error t_ERROR + INNER JOIN parts.CORE_Msg_Error_Type ERROR_TYPE ON t_ERROR.id_type = ERROR_TYPE.id_type + ; + + IF a_debug = 1 AND v_can_view = 1 THEN + SELECT * FROM tmp_Dog; + SELECT * FROM tmp_Command; + SELECT * FROM tmp_Understanding_Level; + SELECT * FROM tmp_Obedience_Level; + END IF; + + DROP TEMPORARY TABLE IF EXISTS tmp_Split; + DROP TEMPORARY TABLE IF EXISTS tmp_Msg_Error; + DROP TEMPORARY TABLE IF EXISTS tmp_Obedience_Level; + DROP TEMPORARY TABLE IF EXISTS tmp_Understanding_Level; + DROP TEMPORARY TABLE IF EXISTS tmp_Command; + DROP TEMPORARY TABLE IF EXISTS tmp_Dog; + + IF a_debug = 1 THEN + CALL parts.p_core_debug_timing_reporting ( v_time_start ); + END IF; +END // +DELIMITER ; + + +/* + +CALL parts.p_DOG_get_many_dog_command ( + 1 -- 'auth0|6582b95c895d09a70ba10fef', -- a_id_user + , 1 -- a_get_all_dog + , 0 -- a_get_inactive_dog + , '' -- a_ids_dog + , 1 -- a_get_all_command + , 0 -- a_get_inactive_command + , '' -- a_ids_command + , 1 -- a_get_all_understanding_level + , 0 -- a_get_inactive_understanding_level + , '' -- a_ids_understanding_level + , 1 -- a_get_all_obedience_level + , 0 -- a_get_inactive_obedience_level + , '' -- a_ids_obedience_level + , 1 -- a_debug +); + +*/ \ No newline at end of file diff --git a/static/MySQL/7204_p_dog_test_get_many_command.sql b/static/MySQL/7204_p_dog_test_get_many_command.sql new file mode 100644 index 0000000..e69de29 diff --git a/static/MySQL/9000_populate.sql b/static/MySQL/9000_populate.sql new file mode 100644 index 0000000..d669235 --- /dev/null +++ b/static/MySQL/9000_populate.sql @@ -0,0 +1,661 @@ + +USE parts; + + +-- Error Message Types +/* Existing table */ +INSERT INTO parts.CORE_Msg_Error_Type ( + code + , name + , description + , is_breaking_error +) +VALUES + ( + 'BAD_DATA' + , 'Invalid data' + , 'Rubbish data' + , 1 + ) + , ( + 'NO_PERMISSION' + , 'No permission' + , 'Not authorised' + , 1 + ) + , ( + 'MYSQL_ERROR' + , 'MySQL error' + , 'MySQL execution error.' + , 1 + ) + , ( + 'WARNING' + , 'Warning' + , 'Non-breaking error.' + , 0 + ) +; + +INSERT INTO parts.CORE_File_Type ( + code + , name + , is_image +) +VALUES + ( + 'JPG' + , 'JPG' + , 1 + ) +; + +-- Access Levels +INSERT INTO parts.DOG_Access_Level ( + display_order + , code + , name + , priority +) +VALUES + ( + 1 + , 'VIEW' + , 'View' + , 3 + ) + , ( + 2 + , 'EDIT' + , 'Edit' + , 2 + ) + , ( + 3 + , 'ADMIN' + , 'Admin' + , 1 + ) +; + +-- Permission Groups +INSERT INTO parts.DOG_Permission_Group ( + display_order + , code + , name +) +VALUES + ( + 0 + , 'DOG' + , 'Dog' + ) + , ( + 1 + , 'USER' + , 'Admin User' + ) +; + +-- Permissions +INSERT INTO parts.DOG_Permission ( + display_order + , code + , name + , id_permission_group + , id_access_level_required +) +VALUES + ( + 1 + , 'DOG_VIEW' + , 'View Dog' + , 1 + , 3 + ) + , ( + 1 + , 'DOG_ADMIN' + , 'Admin Dog' + , 1 + , 3 + ) + , ( + 1 + , 'DOG_CREATE' + , 'Create Dog' + , 1 + , 1 + ) +; + +-- Users +INSERT INTO parts.DOG_User ( + id_user_auth0 + , firstname + , surname + , email + , is_super_user + , active +) +VALUES + ( + 'auth0|6582b95c895d09a70ba10fef' -- id_user_auth0 + , 'Teddy' -- firstname + , 'Middleton-Smith' -- surname + , 'edward.middletonsmith@gmail.com' -- email + , 1 -- is_super_user + , 1 -- active + ) + , ( + 'auth0|672659014296b7f94a9bab45' -- id_user_auth0 + , 'Tierney' -- firstname + , 'Gullen' -- surname + , 'tierneybailey13@gmail.com' -- email + , 1 -- is_super_user + , 1 -- active + ) + , ( + NULL -- id_user_auth0 + , 'Command Bot' -- firstname + , 'Bot' -- surname + , 'teddy@partsltd.co.uk' -- email + , 0 -- is_super_user + , 1 -- active + ) +; + +-- Roles +INSERT INTO parts.DOG_Role ( + display_order + , code + , name + , id_user_created_by +) +VALUES + ( + 1 + , 'MANAGER' + , 'Manager' + , 1 + ) + , ( + 2 + , 'USER' + , 'User' + , 1 + ) +; + +-- Role Permission link +INSERT INTO parts.DOG_Role_Permission_Link ( + id_role + , id_permission + , id_access_level + , id_user_created_by +) +VALUES + ( + 1 + , 1 + , 3 + , 1 + ) + , ( + 1 + , 2 + , 3 + , 1 + ) + , ( + 1 + , 3 + , 3 + , 1 + ) + , ( + 2 + , 1 + , 1 + , 1 + ) + , ( + 2 + , 2 + , 1 + , 1 + ) + , ( + 2 + , 3 + , 1 + , 1 + ) +; + +-- User Role link +INSERT INTO parts.DOG_User_Role_Link ( + id_user + , id_role + , id_user_created_by +) +VALUES + ( + 1 + , 1 + , 1 + ) + , ( + 2 + , 2 + , 1 + ) + , ( + 3 + , 2 + , 1 + ) +; + +-- Project-specific tables +INSERT INTO parts.DOG_Dog ( + name + , appearance + , mass_kg +) +VALUES + ( + 'Molly' + , 'Cute' + , 20 + ) +; + +INSERT INTO parts.DOG_Breed ( + code + , name +) +VALUES + ( + 'BORDER_COLLIE' + , 'Border Collie' + ) +; + +INSERT INTO parts.DOG_Dog_Breed_Link ( + id_dog + , id_breed + , lineage_ratio +) +VALUES + ( + 1 + , 1 + , 1 + ) +; + +INSERT INTO parts.DOG_Understanding_Level ( + code + , name +) +VALUES + ( + 'UNKNOWN' + , 'Not known' + ) + , ( + 'INTRODUCED' + , 'Has been introduced' + ) + , ( + 'RECOGNISES_COMBINED_VISUAL_AND_VERBAL_SIGNAL' + , 'Combined visual and verbal signal recognised' + ) + , ( + 'RECOGNISES_VISUAL_SIGNAL' + , 'Visual signal alone recognised' + ) + , ( + 'RECOGNISES_VERBAL_SIGNAL' + , 'Verbal signal alone recognised' + ) + , ( + 'UNDERSTOOD' + , 'Understood' + ) +; + +INSERT INTO parts.DOG_Obedience_Level ( + code + , name +) +VALUES + ( + 'REFUSAL' + , 'Refuses to obey' + ) + , ( + 'ON_HER_TERMS' + , 'Might obey if she feels like it' + ) + , ( + 'OBEYS_UNDISTRACTED' + , 'Obeys without distractions' + ) + , ( + 'OBEYS_MILDLY_DISTRACTED' + , 'Obeys when mildly distracted' + ) + , ( + 'OBEYS_PERFECTLY' + , 'Obeys in all situations' + ) +; + +INSERT INTO parts.DOG_Command_Category ( + code + , name +) +VALUES + ( + 'ACTIVITIES' + , 'Activities' + ) + , ( + 'BASIC_OBEDIENCE' + , 'Basic obedience' + ) + , ( + 'BEHAVIOUR_MODIFICATION' + , 'Behaviour modification' + ) + , ( + 'BODY_PARTS' + , 'Body parts' + ) + , ( + 'CLOTHING_AND_EQUIPMENT' + , 'Clothing and equipment' + ) + , ( + 'COMPARISON' + , 'Comparison' + ) + , ( + 'ADJECTIVES' + , 'Compliments and insults (adjectives)' + ) + , ( + 'EMOTIONAL_STATE' + , 'Emotional state' + ) + , ( + 'ENVIRONMENT' + , 'Environment' + ) + , ( + 'ESSENTIAL_NEEDS' + , 'Essential needs' + ) + , ( + 'IMPULSE_CONTROL' + , 'Impulse control' + ) + , ( + 'LOCATION' + , 'Location' + ) + , ( + 'MANNERS' + , 'Manners' + ) + , ( + 'MEALTIME' + , 'Mealtime' + ) + , ( + 'PARTY_TRICK' + , 'Party trick' + ) + , ( + 'PEOPLE' + , 'People' + ) + , ( + 'PLAY' + , 'Play' + ) + , ( + 'POSITION' + , 'Position' + ) + , ( + 'QUESTIONS' + , 'Questions' + ) + , ( + 'SERVICE' + , 'Service' + ) + , ( + 'TIME_AND_SCHEDULING' + , 'Time and scheduling' + ) + , ( + 'UTILITY' + , 'Utility' + ) +; + +/* +INSERT INTO parts.DOG_Command ( + code + , name +) +VALUES + ( + 'lick' + , 'nips' + ) +; +*/ + +/* +INSERT INTO parts.DOG_Dog_Command_Link ( + id_dog + , id_command + , id_understanding_level + , id_obedience_level + , notes +) +VALUES + ( + 'lick' + , 'nips' + ) +; +*/ + +INSERT INTO parts.DOG_Location ( + code + , name +) +VALUES + ( + 'LOUNGE' + , 'Lounge' + ) +; + +/* +INSERT INTO parts.DOG_Location_Link ( + id_location_parent + , id_location_child +) +VALUES + ( + 1 + , 2 + ) +; +*/ + +INSERT INTO parts.DOG_Colour ( + code + , name +) +VALUES + ( + 'RED' + , 'Red' + ) + , ( + 'GREEN' + , 'Green' + ) +; + +INSERT INTO parts.DOG_Button_Shape ( + code + , name + , description +) +VALUES + ( + 'ROUND' + , 'Round' + , 'Cylindrical' + ) + , ( + 'HEXAGONAL' + , 'Hexagonal' + , 'Hexagonal prism' + ) +; + +/* +INSERT INTO parts.DOG_Image ( + id_file_type + , id_dog + , path + , display_order +) +VALUES + ( + 1 + , 1 + , NULL + , NULL + ) +; +*/ + +/* +INSERT INTO parts.DOG_Button_Icon ( + id_image + , code + , name + , description +) +VALUES + ( + 1 + , NULL + ) +; +*/ + +/* +INSERT INTO parts.DOG_Command_Button_Link ( + id_command + , id_button_shape + , id_button_colour + , id_button_icon + , id_location +) +VALUES + ( + 1 -- AS id_command + , 1 -- AS id_button_shape + , 1 -- AS id_button_colour + , NULL -- AS id_button_icon + , 1 -- AS id_location + ) +; +*/ + +INSERT INTO parts.DOG_Drive ( + code + , name +) +VALUES + ( + 'PREY' + , 'Prey' + ) + , ( + 'PACK' + , 'Pack' + ) +; + +INSERT INTO parts.DOG_Dog_Drive_Link ( + id_dog + , id_drive + , dominance_ratio +) +VALUES + ( + 1 + , 1 + , 0.5 + ) + , ( + 1 + , 2 + , 0.5 + ) +; + + + +/* + Post Excel-insert: + + +SELECT * +FROM demo.DOG_Dog; + +/ * +SELECT * +FROM demo.DOG_Command; +* / + +SELECT * +-- DELETE +FROM demo.DOG_Understanding_Level; + +SELECT * +-- DELETE +FROM demo.DOG_Obedience_Level; + +/ * +INSERT INTO demo.DOG_Dog_Command_Link ( + id_dog + , id_command + , id_understanding_level + , id_obedience_level + , notes +) +SELECT + DOG.id_dog + , COMMAND.id_command + , +FROM demo.DOG_Dog DOG +CROSS JOIN demo.DOG_Command COMMAND +WHERE DOG.name = 'Molly' + +* / + +*/ diff --git a/static/MySQL/9001_view.sql b/static/MySQL/9001_view.sql new file mode 100644 index 0000000..b818d91 --- /dev/null +++ b/static/MySQL/9001_view.sql @@ -0,0 +1,105 @@ + +-- Core tables +-- Error Message type +SELECT * FROM parts.CORE_Msg_Error_Type; + + +-- Common project tables +-- User Change Sets +SELECT * FROM parts.DOG_User_Change_Set; + +-- Access Levels +SELECT * FROM parts.DOG_Access_Level; + +-- Permission Groups +SELECT * FROM parts.DOG_Permission_Group; + +-- Permissions +SELECT * FROM parts.DOG_Permission; + +-- Users +SELECT * FROM parts.DOG_User; +SELECT * FROM parts.DOG_User_Audit; + +-- Roles +SELECT * FROM parts.DOG_Role; +SELECT * FROM parts.DOG_Role_Audit; + +-- Role Permission link +SELECT * FROM parts.DOG_Role_Permission_Link; +SELECT * FROM parts.DOG_Role_Permission_Link_Audit; + +-- User Role link +SELECT * FROM parts.DOG_User_Role_Link; +SELECT * FROM parts.DOG_User_Role_Link_Audit; + + +-- Project-specific tables +-- Command Change Sets +SELECT * FROM parts.DOG_Dog_Change_Set; + +-- Commands +SELECT * FROM parts.DOG_Dog; +SELECT * FROM parts.DOG_Dog_Audit; +SELECT * FROM parts.DOG_Dog_Temp; + +SELECT * FROM parts.DOG_Breed; +SELECT * FROM parts.DOG_Breed_Audit; +SELECT * FROM parts.DOG_Breed_Temp; + +SELECT * FROM parts.DOG_Dog_Breed_Link; +SELECT * FROM parts.DOG_Dog_Breed_Link_Audit; +SELECT * FROM parts.DOG_Dog_Breed_Link_Temp; + +SELECT * FROM parts.DOG_Obedience_Level; +SELECT * FROM parts.DOG_Obedience_Level_Audit; +SELECT * FROM parts.DOG_Obedience_Level_Temp; + +SELECT * FROM parts.DOG_Command_Category; +SELECT * FROM parts.DOG_Command_Category_Audit; +SELECT * FROM parts.DOG_Command_Category_Temp; + +SELECT * FROM parts.DOG_Command; +SELECT * FROM parts.DOG_Command_Audit; +SELECT * FROM parts.DOG_Command_Temp; + +SELECT * FROM parts.DOG_Dog_Command_Link; +SELECT * FROM parts.DOG_Dog_Command_Link_Audit; +SELECT * FROM parts.DOG_Dog_Command_Link_Temp; + +SELECT * FROM parts.DOG_Location; +SELECT * FROM parts.DOG_Location_Audit; +SELECT * FROM parts.DOG_Location_Temp; + +SELECT * FROM parts.DOG_Location_Link; +SELECT * FROM parts.DOG_Location_Link_Audit; +SELECT * FROM parts.DOG_Location_Link_Temp; + +SELECT * FROM parts.DOG_Colour; +SELECT * FROM parts.DOG_Colour_Audit; +SELECT * FROM parts.DOG_Colour_Temp; + +SELECT * FROM parts.DOG_Button_Shape; +SELECT * FROM parts.DOG_Button_Shape_Audit; +SELECT * FROM parts.DOG_Button_Shape_Temp; + +SELECT * FROM parts.DOG_Image; +SELECT * FROM parts.DOG_Image_Audit; +SELECT * FROM parts.DOG_Image_Temp; + +SELECT * FROM parts.DOG_Button_Icon; +SELECT * FROM parts.DOG_Button_Icon_Audit; +SELECT * FROM parts.DOG_Button_Icon_Temp; + +SELECT * FROM parts.DOG_Command_Button_Link; +SELECT * FROM parts.DOG_Command_Button_Link_Audit; +SELECT * FROM parts.DOG_Command_Button_Link_Temp; + +SELECT * FROM parts.DOG_Drive; +SELECT * FROM parts.DOG_Drive_Audit; +SELECT * FROM parts.DOG_Drive_Temp; + +SELECT * FROM parts.DOG_Dog_Drive_Link; +SELECT * FROM parts.DOG_Dog_Drive_Link_Audit; +SELECT * FROM parts.DOG_Dog_Drive_Link_Temp; + diff --git a/static/batch/sql_combine.bat b/static/batch/sql_combine.bat new file mode 100644 index 0000000..997fadb --- /dev/null +++ b/static/batch/sql_combine.bat @@ -0,0 +1,92 @@ +@echo off +setlocal enabledelayedexpansion + +set dir_parent=C:\Users\edwar\OneDrive\Documents\Programming\Visual Studio 2022\PARTS_Web\app\static\MySQL +:: set dir_parent=C:\Users\edwar\OneDrive\Documents\Programming\Visual Studio 2022\PARTS_Web\app\static\PostgreSQL +set "f_list=file_list.txt" +set dir_current=%cd% +set "f_tmp=temp.txt" +set "f_combine=0000_combine.sql" +set verbose=0 +set "strs_delete_0=920_edit_permissions.sql" +set "strs_delete_1=910_anal.sql" +set "strs_delete_2=deprecated" +set "strs_delete_3=%f_list%" +set "strs_delete_4=%f_tmp%" +set "strs_delete_5=701_p_shop_get_many_role_permission.sql" +set "strs_delete_6=600_p_shop_save_product.sql" +set "strs_delete_7=170_ish_tbl_ERP_Order.sql" +set "strs_delete_7=dump.sql" +set strs_n_max=8 + +set "str_list=" + +set max_length=8191 +set threshold=1000 + +echo temp = %f_tmp% +echo dir_parent = !%dir_parent%! +echo dir_current = !%dir_current%! +echo file_list = %f_list% +echo file = %f_combine% +echo n strings = !strs_n_max! + +cd %dir_parent% +del %f_tmp% +del %f_list% +del %f_combine% + +dir /b *.sql > %f_list% + + +echo loopy + +(for /f "delims=" %%a in (%f_list%) do ( + set "line=%%a" + set include_line=1 + for /L %%i in (0, 1, %strs_n_max%) do ( + if !line! equ !strs_delete_%%i! ( + set include_line=0 + ) + set "line=!line!" + ) + if !include_line! gtr 0 ( + echo !line! + ::set "str_list=!str_list! !line!" + ::set length=0 + ::for %%i in (!str_list!) do ( + :: set /a length+=1 + ::) + ::if !length! geq !threshold! ( + :: echo !str_list! + :: echo !str_list! > %f_combine% + :: set "str_list=" + ::) + type !line! >> %f_combine% + ) + set "line=!line!" +)) > %f_tmp% + + +echo output list: +type %f_tmp% + +del %f_list% +echo file_tmp: %f_tmp% +echo file_list: %f_list% +echo combining files +echo !str_list! + +echo cmd: +::echo "type !str_list! > %f_combine%" +::type !str_list! > %f_combine% +::(for %%f in (!str_list!) do ( +:: echo %%f +:: type "%%f" >> %f_combine% +::)) + +cd %dir_current% + +echo Current Time: %TIME% + +endlocal \ No newline at end of file diff --git a/static/batch/sql_combine.ps1 b/static/batch/sql_combine.ps1 new file mode 100644 index 0000000..5595a02 --- /dev/null +++ b/static/batch/sql_combine.ps1 @@ -0,0 +1,44 @@ + +# Combine-SqlFiles.ps1 +param( + [string]$sourceFolder = "C:\Users\edwar\OneDrive\Documents\Programming\Visual Studio 2022\PARTS_Web\app\static\MySQL\", + [string]$outputFileName = "0000_combined.sql", + [string]$filePattern = "*.sql", + [string[]]$excludeFiles = @("dump.sql") # Array of filenames to exclude +) + +$outputFile = Join-Path $sourceFolder $outputFileName +$outputDir = Split-Path -Parent $outputFile + +# Remove output file if it exists +if (Test-Path $outputFile) { + Remove-Item $outputFile -Force +} + +# Create directory if needed +if (!(Test-Path -Path $outputDir)) { + New-Item -ItemType Directory -Force -Path $outputDir +} + +# Create a StringBuilder for efficiency +$output = New-Object System.Text.StringBuilder + +# Process each file +Get-ChildItem -Path $sourceFolder -Filter $filePattern -File | + Where-Object { $_.Name -notin $excludeFiles -and $_.Name -ne $outputFileName } | + ForEach-Object { + Write-Host "Processing file: $($_.Name)" + [void]$output.AppendLine("-- File: $($_.Name)") + # Read file content and remove BOM if present + $content = [System.IO.File]::ReadAllBytes($_.FullName) + if ($content[0] -eq 0xEF -and $content[1] -eq 0xBB -and $content[2] -eq 0xBF) { + $content = $content[3..($content.Length-1)] + } + [void]$output.AppendLine([System.Text.Encoding]::UTF8.GetString($content)) + [void]$output.AppendLine() + } + +# Write final output +[System.IO.File]::WriteAllText($outputFile, $output.ToString(), [System.Text.UTF8Encoding]::new($false)) + +Write-Host "Files combined successfully into $outputFile" \ No newline at end of file diff --git a/static/css/components/button.css b/static/css/components/button.css new file mode 100644 index 0000000..fb55ad0 --- /dev/null +++ b/static/css/components/button.css @@ -0,0 +1,31 @@ +.button { + display: inline-block; + padding: 0.75rem 1.5rem; + border-radius: 6px; + text-decoration: none; + font-weight: 500; + transition: all 0.3s ease; + width: fit-content; +} + +.button-primary { + background: var(--primary); + color: white; +} + +.button-primary:hover { + background: var(--secondary); +} + +.button-light { + background: white; + color: var(--primary); +} + +.button-light:hover { + background: var(--light); +} + +.logo:hover{ + cursor: pointer; +} \ No newline at end of file diff --git a/static/css/layouts/footer.css b/static/css/layouts/footer.css new file mode 100644 index 0000000..7ab4517 --- /dev/null +++ b/static/css/layouts/footer.css @@ -0,0 +1,57 @@ + +.footer { + background: #1f2937; + color: #f3f4f6; + padding: 4rem 0 2rem; +} + +.footer-content { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); + gap: 2rem; + margin-bottom: 2rem; +} + +.footer-section h3 { + color: #fff; + margin-bottom: 1rem; + font-size: 1.2rem; +} + +.footer-section ul { + list-style: none; + padding: 0; +} + +.footer-section ul li { + margin-bottom: 0.5rem; +} + +.footer-section a { + color: #f3f4f6; + text-decoration: none; + transition: color 0.3s ease; +} + +.footer-section a:hover { + color: #fff; + text-decoration: underline; +} + +.footer-bottom { + border-top: 1px solid #374151; + padding-top: 2rem; + text-align: center; + font-size: 0.9rem; +} + +.footer-bottom a { + color: aquamarine; +} + +@media (max-width: 768px) { + .footer-content { + grid-template-columns: 1fr; + text-align: center; + } +} \ No newline at end of file diff --git a/static/css/layouts/header.css b/static/css/layouts/header.css new file mode 100644 index 0000000..a0d1656 --- /dev/null +++ b/static/css/layouts/header.css @@ -0,0 +1,37 @@ + +header { + background: white; + box-shadow: 0 2px 4px rgba(0,0,0,0.1); + /* position: fixed; + top: 0; */ + width: 100%; + z-index: 1000; +} + +.navbar { + display: flex; + justify-content: space-between; + align-items: center; + padding: 1rem 0; +} + +.logo { + font-size: 1.5rem; + font-weight: bold; + color: var(--primary); +} + +.nav-links { + display: flex; + gap: 2rem; +} + +.nav-links a { + text-decoration: none; + color: var(--text); + font-weight: 500; + align-content: center; +} +.nav-links a.button { + color: white; +} \ No newline at end of file diff --git a/static/css/lib/reset.css b/static/css/lib/reset.css new file mode 100644 index 0000000..e69de29 diff --git a/static/css/lib/typography.css b/static/css/lib/typography.css new file mode 100644 index 0000000..e69de29 diff --git a/static/css/lib/utils.css b/static/css/lib/utils.css new file mode 100644 index 0000000..d2aba3e --- /dev/null +++ b/static/css/lib/utils.css @@ -0,0 +1,22 @@ +.text-center { + text-align: center; +} + +.section-title { + font-size: 2rem; + margin-bottom: 1rem; +} + +.section-subtitle { + margin-bottom: 2rem; +} + +@media (max-width: 768px) { + .hero h1 { + font-size: 2.5rem; + } + + .nav-links { + display: none; + } +} \ No newline at end of file diff --git a/static/css/lib/variables.css b/static/css/lib/variables.css new file mode 100644 index 0000000..e69de29 diff --git a/static/css/main.css b/static/css/main.css new file mode 100644 index 0000000..88813b4 --- /dev/null +++ b/static/css/main.css @@ -0,0 +1,33 @@ + +:root { + --primary: #2563eb; + --secondary: #1e40af; + --text: #1f2937; + --subheading: #4b5563; + --light: #f3f4f6; +} + +* { + margin: 0; + padding: 0; + box-sizing: border-box; + font-family: system-ui, -apple-system, sans-serif; +} + +body { + line-height: 1.6; + color: var(--text); +} + +.container { + max-width: 1200px; + margin: 0 auto; + padding: 0 1.5rem; +} + +/* +.page_body { + position: fixed; + top: +} +*/ diff --git a/static/css/pages/core/contact.css b/static/css/pages/core/contact.css new file mode 100644 index 0000000..461239c --- /dev/null +++ b/static/css/pages/core/contact.css @@ -0,0 +1,129 @@ + +.contact-section { + padding: 2rem 2rem 4rem; +} + +.command { + max-width: 60vw; + width: fit-content; + margin: 0 auto; + background: #fff; + padding: 2rem; + border-radius: 8px; + box-shadow: 0 2px 4px rgba(0,0,0,0.1); +} +.command textarea { + max-width: 40vw; +} + +.form-grid { + display: grid; + grid-template-columns: 200px 1fr; + gap: 1.5rem; + margin-bottom: 1rem; +} +.form-label { + padding-top: 0.5rem; + font-weight: 500; +} +.form-input { + width: 100%; + padding: 0.5rem; + border: 1px solid #d1d5db; + border-radius: 4px; + font-size: 1rem; +} +textarea.form-input { + min-height: 120px; +} + +.marketing-consent input { + display: inline-block; + margin-left: 20%; + margin-bottom: 1.25rem; +} + +.container.captcha > div:first-child > label:first-child { + display: flex; + justify-content: center; + width: fit-content; + text-align: center; + margin: 0 auto; +} +.container.captcha > p:last-child{ + font-size: 0.9rem; + margin: 1vh 0; +} +.container.captcha .altcha-main { + padding-left: 1rem; + padding-top: 0.75rem; + padding-bottom: 0; +} +.container.captcha .altcha-main > :last-child { + display: none; +} +.container.captcha .altcha, +altcha-widget > div:first-child, +.container.captcha > div > .altcha-widget > div { + width: fit-content; + display: flex; + margin-left: auto; + margin-right: auto; +} + +input[type="submit"] { + margin-left: 40%; + padding: 0.75rem 1.5rem; + background: #2563eb; + color: white; + border: none; + border-radius: 4px; + cursor: pointer; + font-size: 1rem; +} + +input[type="submit"]:hover { + background: #1d4ed8; +} + +.data-notice { + margin-top: 3rem; + padding: 1.5rem; + background: #f3f4f6; + border-radius: 4px; + font-size: 0.95rem; +} + +.data-notice h3 { + margin-bottom: 1rem; + font-size: 1.1rem; +} + +.data-notice ul li { + list-style-position: inside; +} + +@media (max-width: 768px) { + .command { + max-width: 80vw; + } + .command textarea { + max-width: 60vw; + } + .form-grid { + grid-template-columns: 1fr; + gap: 0.5rem; + } + + .form-label { + padding-top: 0; + } + + .submit-button { + margin-left: 0; + width: 100%; + } +} + +@media (max-width: 400px) { +} \ No newline at end of file diff --git a/static/css/pages/core/home.css b/static/css/pages/core/home.css new file mode 100644 index 0000000..7d5fa20 --- /dev/null +++ b/static/css/pages/core/home.css @@ -0,0 +1,126 @@ + +/* Hero Section */ +.hero { + padding: 8rem 0 4rem; + background: linear-gradient(45deg, #f8fafc, #eff6ff); +} + +.hero-content { + max-width: 600px; +} + +.hero h1 { + font-size: 3rem; + line-height: 1.2; + margin-bottom: 1.5rem; + color: var(--text); +} + +.hero p { + font-size: 1.25rem; + margin-bottom: 2rem; + color: var(--subheading); +} + +/* Services Section */ +.services { + padding: 6rem 0; + background: white; +} + +.services-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); + gap: 2rem; + margin-top: 3rem; +} + +.service-card { + padding: 2rem; + background: var(--light); + border-radius: 8px; + transition: transform 0.3s ease; +} + +.service-card:hover { + transform: translateY(-5px); +} + +/* Testimonial Section */ +.testimonial { + padding: 6rem 0; + background: var(--light); +} + +.testimonial-card { + background: white; + padding: 2rem; + border-radius: 8px; + max-width: 800px; + margin: 3rem auto 0; + box-shadow: 0 4px 6px rgba(0,0,0,0.1); +} + +/* Pricing Section */ +.pricing { + padding: 6rem 0; + background: white; +} + +.pricing-card { + background: var(--light); + padding: 2rem; + border-radius: 8px; + text-align: center; + max-width: 400px; + margin: 3rem auto 0; +} + +.price { + font-size: 2.5rem; + color: var(--primary); + font-weight: bold; + margin: 1rem 0; +} + +/* CTA Section */ +.cta { + padding: 6rem 0; + background: var(--primary); + color: white; + text-align: center; +} + + +/* Animations */ +/* Fallback styles to ensure content is visible without JS */ +.reveal { + opacity: 1; /* Default visible state */ +} + +/* Only hide elements if browser supports Intersection Observer */ +@supports (animation-name: fade) { + .reveal { + opacity: 0; + } + + .reveal.active { + animation: fade-up 0.8s ease-out forwards; + } +} + +@keyframes fade-up { + 0% { + opacity: 0; + transform: translateY(30px); + } + 100% { + opacity: 1; + transform: translateY(0); + } +} + +.delay-1 { animation-delay: 0.1s; } +.delay-2 { animation-delay: 0.2s; } +.delay-3 { animation-delay: 0.3s; } +.delay-4 { animation-delay: 0.4s; } \ No newline at end of file diff --git a/static/css/pages/legal/accessibility_report.css b/static/css/pages/legal/accessibility_report.css new file mode 100644 index 0000000..e69de29 diff --git a/static/css/pages/legal/accessibility_statement.css b/static/css/pages/legal/accessibility_statement.css new file mode 100644 index 0000000..e69de29 diff --git a/static/css/pages/legal/license.css b/static/css/pages/legal/license.css new file mode 100644 index 0000000..0cce299 --- /dev/null +++ b/static/css/pages/legal/license.css @@ -0,0 +1,7 @@ + +.page-body > * { +} +#pageBody > * :first-child{ +} +#pageBody > * :last-child { +} diff --git a/static/css/pages/legal/privacy_policy.css b/static/css/pages/legal/privacy_policy.css new file mode 100644 index 0000000..e69de29 diff --git a/static/css/pages/legal/retention_schedule.css b/static/css/pages/legal/retention_schedule.css new file mode 100644 index 0000000..e69de29 diff --git a/static/css/sections/core.css b/static/css/sections/core.css new file mode 100644 index 0000000..e69de29 diff --git a/static/css/sections/legal.css b/static/css/sections/legal.css new file mode 100644 index 0000000..e69de29 diff --git a/static/css/themes/dark.css b/static/css/themes/dark.css new file mode 100644 index 0000000..5c30a95 --- /dev/null +++ b/static/css/themes/dark.css @@ -0,0 +1,45 @@ +:root { + --background-color: #121212; + --text-color: #e0e0e0; + --primary-color: #bb86fc; + --secondary-color: #03dac6; + --success-color: #00c853; + --danger-color: #cf6679; + --warning-color: #ffab00; + --info-color: #2196f3; + --light-color: #2c2c2c; + --dark-color: #1f1f1f; + --border-color: #333333; + --shadow-color: rgba(255, 255, 255, 0.1); + + /* Header */ + --header-bg: #1f1f1f; + --header-text: #e0e0e0; + + /* Footer */ + --footer-bg: #1f1f1f; + --footer-text: #a0a0a0; + + /* Navigation */ + --nav-bg: #1f1f1f; + --nav-text: #e0e0e0; + --nav-hover-bg: #2c2c2c; + --nav-hover-text: #bb86fc; + + /* Buttons */ + --Button-primary-bg: #bb86fc; + --Button-primary-text: #121212; + --Button-secondary-bg: #03dac6; + --Button-secondary-text: #121212; + + /* Forms */ + --input-bg: #2c2c2c; + --input-border: #454545; + --input-text: #e0e0e0; + --input-focus-border: #bb86fc; + + /* Cards */ + --card-bg: #1f1f1f; + --card-border: #333333; + --card-shadow: 0 0.125rem 0.25rem rgba(255, 255, 255, 0.05); +} \ No newline at end of file diff --git a/static/css/themes/light.css b/static/css/themes/light.css new file mode 100644 index 0000000..c1faf9a --- /dev/null +++ b/static/css/themes/light.css @@ -0,0 +1 @@ +/* Default */ \ No newline at end of file diff --git a/static/docs/Dog Training(Sheet1).csv b/static/docs/Dog Training(Sheet1).csv new file mode 100644 index 0000000..91e925f --- /dev/null +++ b/static/docs/Dog Training(Sheet1).csv @@ -0,0 +1,222 @@ +Bath,BATH,Activities,, +Cuddle,CUDDLE,Activities,, +Dreaming,DREAMING,Activities,, +Exercise,EXERCISE,Activities,, +Go on then (go explore on walk),GO_ON_THEN_(GO_EXPLORE_ON_WALK),Activities,Swing arm forwards towards the horizon, +Good night (bedtime),GOOD_NIGHT_(BEDTIME),Activities,, +Panting,PANTING,Activities,, +Patrol,PATROL,Activities,, +Protect,PROTECT,Activities,, +Resting,RESTING,Activities,, +Rotate,ROTATE,Activities,Point or push/pull to desired direction, +Scratch,SCRATCH,Activities,, +Sleeping,SLEEPING,Activities,, +Stretching,STRETCHING,Activities,, +Take (it),TAKE_(IT),Activities,, +Tug,TUG,Activities,, +Wake up,WAKE_UP,Activities,, +Walk,WALK,Activities,"Walking legs with fingers or multiple firm, fast pats to the chest",TRUE +Yawning,YAWNING,Activities,, +Come,COME,Basic Obedience,"Palm forwards, arm down and 20 degrees from torso", +Down ,DOWN,Basic Obedience,Point to ground, +Go,GO,Basic Obedience,Point in direction , +Okay,OKAY,Basic Obedience,, +Sit,SIT,Basic Obedience,Bring closed fist to chin with elbow tucked against torso, +Stay,STAY,Basic Obedience,Push hand towards dog with only index finger extended and pointing upwards, +Easy,EASY,Behaviour Modification,, +Heel,HEEL,Behaviour Modification,Point down with index finger to floor next to foot using same side finger and foot that you wish dog to heel to, +Noisy,NOISY,Behaviour Modification,, +Pull,PULL,Behaviour Modification,, +Push,PUSH,Behaviour Modification,, +Quiet,QUIET,Behaviour Modification,Index finger to lips, +Settle,SETTLE,Behaviour Modification,, +Back,BACK,Body parts,, +Belly,BELLY,Body parts,, +Ear,EAR,Body parts,, +Mouth,MOUTH,Body parts,, +Neck,NECK,Body parts,, +Nose,NOSE,Body parts,, +Paw,PAW,Body parts,Present hand close to your body with palm facing upwards, +Tail,TAIL,Body parts,, +Teeth,TEETH,Body parts,, +Harness,HARNESS,Clothing and equipment,, +Better,BETTER,Comparison,, +Is,IS,Comparison,, +Like,LIKE,Comparison,, +Too,TOO,Comparison,, +Worse,WORSE,Comparison,, +Baby,BABY,Compliments and insults (adjectives),, +Bad,BAD,Compliments and insults (adjectives),, +Beautiful ,BEAUTIFUL,Compliments and insults (adjectives),, +Big,BIG,Compliments and insults (adjectives),, +Clever,CLEVER,Compliments and insults (adjectives),, +Cute,CUTE,Compliments and insults (adjectives),, +Dirty,DIRTY,Compliments and insults (adjectives),, +Fat,FAT,Compliments and insults (adjectives),, +Food,FOOD,Compliments and insults (adjectives),, +Good,GOOD,Compliments and insults (adjectives),, +Gorgeous ,GORGEOUS,Compliments and insults (adjectives),, +Hairy,HAIRY,Compliments and insults (adjectives),, +Idea,IDEA,Compliments and insults (adjectives),, +Little,LITTLE,Compliments and insults (adjectives),, +Naughty,NAUGHTY,Compliments and insults (adjectives),, +Old,OLD,Compliments and insults (adjectives),, +Pretty,PRETTY,Compliments and insults (adjectives),, +Stinky,STINKY,Compliments and insults (adjectives),, +Young,YOUNG,Compliments and insults (adjectives),, +Choose ... or ...,CHOOSE_..._OR_...,Emotional state,, +Comfy,COMFY,Emotional state,, +Energetic,ENERGETIC,Emotional state,, +Excited,EXCITED,Emotional state,, +Favourite,FAVOURITE,Emotional state,, +Gross,GROSS,Emotional state,, +Happy,HAPPY,Emotional state,, +Help,HELP,Emotional state,, +Hungry,HUNGRY,Emotional state,, +Hurt / that hurts,HURT_/_THAT_HURTS,Emotional state,, +Itch,ITCH,Emotional state,, +Like,LIKE,Emotional state,, +Limping,LIMPING,Emotional state,, +Love,LOVE,Emotional state,, +Ouch,OUCH,Emotional state,, +Poorly,POORLY,Emotional state,, +Sad,SAD,Emotional state,, +Smell(s),SMELL(S),Emotional state,Wofting in front of nose with hand (stinky) action, +Tasty,TASTY,Emotional state,, +Thirsty,THIRSTY,Emotional state,, +Tired,TIRED,Emotional state,, +Want,WANT,Emotional state,, +Bright,BRIGHT,Environment,, +Cold,COLD,Environment,, +Crowded,CROWDED,Environment,, +Danger,DANGER,Environment,, +Dark,DARK,Environment,, +Empty,EMPTY,Environment,, +Hot,HOT,Environment,, +Lightning,LIGHTNING,Environment,, +Rainy,RAINY,Environment,, +Safe,SAFE,Environment,, +Shade,SHADE,Environment,, +Snow,SNOW,Environment,, +Storm,STORM,Environment,, +Sunshine,SUNSHINE,Environment,, +Thunder,THUNDER,Environment,, +Weather,WEATHER,Environment,, +Wet,WET,Environment,, +Be quick,BE_QUICK,Essential needs,Pointing, +Brush,BRUSH,Essential needs,Show her the brush, +Kisses,KISSES,Essential needs,Blow kiss, +Medicine,MEDICINE,Essential needs,, +Gently,GENTLY,Impulse Control,, +Leave (it),LEAVE_(IT),Impulse Control,Palm up towards dog, +Bed,BED,Location,Pointing, +Bedroom,BEDROOM,Location,, +Car,CAR,Location,, +Downstairs ,DOWNSTAIRS,Location,Pointing, +Go far away,GO_FAR_AWAY,Location,Pointing, +Go over there,GO_OVER_THERE,Location,Pointing, +Grass,GRASS,Location,, +Hedge,HEDGE,Location,, +Here / There,HERE_/_THERE,Location,Pointing, +Home,HOME,Location,Hands above head into home symbol, +Kitchen,KITCHEN,Location,, +Lounge,LOUNGE,Location,, +Off,OFF,Location,Swiping motion of arm from pointing at dog to area they should move to , +Office,OFFICE,Location,, +On,ON,Location,, +Outside,OUTSIDE,Location,Pointing,TRUE +Park,PARK,Location,, +Pointing directions,POINTING_DIRECTIONS,Location,Pointing, +River,RIVER,Location,, +Road,ROAD,Location,, +Room,ROOM,Location,, +This way / that way,THIS_WAY_/_THAT_WAY,Location,Pointing, +Toilet,TOILET,Location,, +Tree,TREE,Location,, +Upstairs ,UPSTAIRS,Location,Pointing, +Vets,VETS,Location,, +Excuse me,EXCUSE_ME,Manners,Point to where you want to go, +Son of a bitch,SON_OF_A_BITCH,Manners,, +Sorry,SORRY,Manners,, +Thank you,THANK_YOU,Manners,, +Carrot,CARROT,Mealtime,, +Cheese,CHEESE,Mealtime,, +"Dinner, breakfast?","DINNER,_BREAKFAST?",Mealtime,, +Eat (it),EAT_(IT),Mealtime,Pointing, +Full (of food),FULL_(OF_FOOD),Mealtime,, +Meat,MEAT,Mealtime,, +Nutrients,NUTRIENTS,Mealtime,, +Treat,TREAT,Mealtime,,TRUE +Water,WATER,Mealtime,, +Centre ,CENTRE,Party Trick,Separate legs wider than shoulders and point to clung, +Crawl ,CRAWL,Party Trick,, +Meerkat,MEERKAT,Party Trick,, +Roll Over ,ROLL_OVER,Party Trick,, +Round,ROUND,Party Trick,, +Touch ,TOUCH,Party Trick,, +Twirl,TWIRL,Party Trick,, +Athena,ATHENA,People,, +Dog,DOG,People,, +Egg,EGG,People,, +Friend,FRIEND,People,, +Girl,GIRL,People,, +Hannah,HANNAH,People,, +Human,HUMAN,People,, +Molly / whistle,MOLLY_/_WHISTLE,People,, +Stranger,STRANGER,People,, +Teddy,TEDDY,People,, +Drop (it),DROP_(IT),Play,, +Fetch,FETCH,Play,Pointing, +Found,FOUND,Play,, +Give (it),GIVE_(IT),Play,Present hand close to your body with palm facing upwards, +Lost,LOST,Play,, +Pillow,PILLOW,Play,, +Play,PLAY,Play,, +Squeaky (toy),SQUEAKY_(TOY),Play,, +Stick,STICK,Play,, +Toy,TOY,Play,, +Back up / off,BACK_UP_/_OFF,Position,Hand facing down with alternating between fingers pointing to floor then fingers flat with hand, +Backwards,BACKWARDS,Position,, +Fast,FAST,Position,, +Forwards,FORWARDS,Position,, +Go in(side),GO_IN(SIDE),Position,Pointing, +Go lie down over there,GO_LIE_DOWN_OVER_THERE,Position,Pointing, +In,IN,Position,Pointing, +Jump,JUMP,Position,Point finger upwards, +Left,LEFT,Position,, +Move,MOVE,Position,, +Out,OUT,Position,, +Right,RIGHT,Position,, +Slow,SLOW,Position,, +Up,UP,Position,Raise hand upwards with palm facing upwards, +How,HOW,Questions,, +No,NO,Questions,, +What,WHAT,Questions,, +When,WHEN,Questions,, +Where,WHERE,Questions,, +Who,WHO,Questions,, +Why,WHY,Questions,, +Yes,YES,Questions,, +Attack,ATTACK,Service,, +After,AFTER,Time and scheduling,, +Before,BEFORE,Time and scheduling,, +Before,BEFORE,Time and scheduling,, +First,FIRST,Time and scheduling,, +Last,LAST,Time and scheduling,, +Later,LATER,Time and scheduling,, +Next,NEXT,Time and scheduling,, +Now,NOW,Time and scheduling,, +Ready,READY,Time and scheduling,, +Soon,SOON,Time and scheduling,, +Then,THEN,Time and scheduling,, +All Done ,ALL_DONE,Utility,, +Collar,COLLAR,Utility,, +Dry you off,DRY_YOU_OFF,Utility,, +Number 0,NUMBER_0,Utility,, +Number 1,NUMBER_1,Utility,, +Number 2,NUMBER_2,Utility,, +Number 3,NUMBER_3,Utility,, +Piece,PIECE,Utility,, +Press,PRESS,Utility,Point to button, +Shake,SHAKE,Utility,Mimic dog shaking action, +Speak,SPEAK,Utility,Dog barking action with hand, diff --git a/static/docs/Kitchen Stock Take.xlsx b/static/docs/Kitchen Stock Take.xlsx new file mode 100644 index 0000000..970eacf Binary files /dev/null and b/static/docs/Kitchen Stock Take.xlsx differ diff --git a/static/docs/Logo.png b/static/docs/Logo.png new file mode 100644 index 0000000..d49d228 Binary files /dev/null and b/static/docs/Logo.png differ diff --git a/static/docs/PARTS ERP.xlsx b/static/docs/PARTS ERP.xlsx new file mode 100644 index 0000000..e9e9dd9 Binary files /dev/null and b/static/docs/PARTS ERP.xlsx differ diff --git a/static/docs/example abstract base class.py b/static/docs/example abstract base class.py new file mode 100644 index 0000000..0fee61a --- /dev/null +++ b/static/docs/example abstract base class.py @@ -0,0 +1,88 @@ +from abc import abstractmethod +import types + +class AbstractBaseClass: + def __init_subclass__(cls, **kwargs): + super().__init_subclass__(**kwargs) + for name, value in vars(AbstractBaseClass).items(): + if getattr(value, "__isabstractmethod__", False): + if name not in cls.__dict__: + raise TypeError(f"Can't instantiate class {cls.__name__} " + f"without implementation of abstract method {name}") + subclass_value = cls.__dict__[name] + if (isinstance(value, (staticmethod, classmethod)) and + not isinstance(subclass_value, type(value))): + raise TypeError(f"Abstract {type(value).__name__} {name} in {cls.__name__} " + f"must be implemented as a {type(value).__name__}") + + def __new__(cls, *args, **kwargs): + if cls is AbstractBaseClass: + raise TypeError("Can't instantiate abstract class AbstractBaseClass directly") + return super().__new__(cls) + + @abstractmethod + def instance_method(self): + pass + + @classmethod + @abstractmethod + def class_method(cls): + pass + + @staticmethod + @abstractmethod + def static_method(): + pass + +class ConcreteClass(AbstractBaseClass): + def instance_method(self): + return "Implemented instance method" + + @classmethod + def class_method(cls): + return "Implemented class method" + + @staticmethod + def static_method(): + return "Implemented static method" + +class IncompleteClass(AbstractBaseClass): + def instance_method(self): + return "Only implemented instance method" + # class_method and static_method are not implemented + +class IncorrectImplementationClass(AbstractBaseClass): + def instance_method(self): + return "Implemented instance method" + + @classmethod + def class_method(cls): + return "Implemented class method" + + def static_method(self): # This should be a static method, not an instance method + return "Incorrectly implemented static method" + +# Usage +if __name__ == "__main__": + try: + concrete = ConcreteClass() + print(concrete.instance_method()) + print(ConcreteClass.class_method()) + print(ConcreteClass.static_method()) + except TypeError as e: + print(f"Error with ConcreteClass: {e}") + + try: + IncompleteClass() + except TypeError as e: + print(f"Error with IncompleteClass: {e}") + + try: + IncorrectImplementationClass() + except TypeError as e: + print(f"Error with IncorrectImplementationClass: {e}") + + try: + AbstractBaseClass() + except TypeError as e: + print(f"Error with AbstractBaseClass: {e}") diff --git a/static/docs/generated-privacy-notice-general-business.docx b/static/docs/generated-privacy-notice-general-business.docx new file mode 100644 index 0000000..0e81a38 Binary files /dev/null and b/static/docs/generated-privacy-notice-general-business.docx differ diff --git a/static/docs/generated-privacy-notice-general-business.odt b/static/docs/generated-privacy-notice-general-business.odt new file mode 100644 index 0000000..cafb0af Binary files /dev/null and b/static/docs/generated-privacy-notice-general-business.odt differ diff --git a/static/docs/naming conventions.txt b/static/docs/naming conventions.txt new file mode 100644 index 0000000..8bb6f7b --- /dev/null +++ b/static/docs/naming conventions.txt @@ -0,0 +1,119 @@ +Precision and Research Technology Systems Limited +Naming Conventions + + +Language: CSS +File naming convention: + kebab-case + lowercase + + +Language: HTML +File naming convention: + prefix with underscore for templates + snake_case + lowercase + + +Language: JavaScript +Variable naming convention: + prefix with underscore for private variables + camelCase for mutable variables + uppercase with underscore spacing for constants + top-down heirarchy of objects flows left to right + suffix with type for type hinting +Function naming convention: + camelCase + verb is first word + top-down heirarchy of objects flows left to right + suffix with type for type hinting +Class naming convention: + PascalCase (UpperCamelCase) + singular noun or noun phrase +File naming convention: + kebab-case + lowercase + suffix with type for type hinting +Folder naming convention: + kebab-case + lowercase + + +Language: MySQL +Database naming convention: + snake_case + lowercase +Variable naming convention: + lowercase and prefix with 'v_' for mutable variables + uppercase and prefix with 'C_' for constants + snake_case + top-down heirarchy of objects flows left to right + suffix with type for type hinting +Function, Store Procedure, Trigger, and View naming convention: + prefix with 'fn_' for functions + prefix with 'vw_' for views + prefix with 'p_' for stored procedures + prefix with 'tri_' for triggers + suffix with action then event timing for triggers + lowercase + snake_case + verb is first word + top-down heirarchy of objects flows left to right + suffix with type for type hinting +Table naming convention: + prefix with project + prefix with 'tmp' for temporary tables + singular noun or noun phrase + Upper_Snake_Case +Column naming convention: + prefix with project + prefix with 'idx_' for indices + singular noun or noun phrase + snake_case + lowercase +Constraint naming convention: + prefix with 'pk_' for primary keys + prefix with 'fk_' for foreign keys + prefix with 'chk_' for check + singular noun or noun phrase + snake_case + lowercase +File naming convention: + snake_case + lowercase + suffix with type for type hinting +Folder naming convention: + kebab-case + lowercase + + +Language: Python +Variable naming convention: + prefix with underscore for private variables + prefix with double underscore for private variables that are not inherited + lowercase for mutable variables + uppercase for constants + snake_case + top-down heirarchy of objects flows left to right + suffix with type for type hinting +Function naming convention: + lowercase + snake_case + verb is first word + top-down heirarchy of objects flows left to right + suffix with type for type hinting +Class naming convention: + suffix with 'Base' for base classes + prefix with 'Abstract' for abstract classes + prefix with 'Abstract' for abstract classes + PascalCase (UpperCamelCase) + singular noun or noun phrase +File naming convention: + snake_case + lowercase + suffix with type for type hinting +Folder naming convention: + snake_case + lowercase + + diff --git a/static/docs/server.py b/static/docs/server.py new file mode 100644 index 0000000..8b30117 --- /dev/null +++ b/static/docs/server.py @@ -0,0 +1,124 @@ +#! /usr/bin/env python3.6 + +""" +server.py +Stripe Sample. +Python 3.6 or newer required. +""" + +import stripe +import json +import os + +from flask import Flask, render_template, jsonify, request, send_from_directory, redirect +from dotenv import load_dotenv, find_dotenv + +# Setup Stripe python client library. +load_dotenv(find_dotenv()) + +# Ensure environment variables are set. +price = os.getenv('PRICE') +if price is None or price == 'price_12345' or price == '': + print('You must set a Price ID in .env. Please see the README.') + exit(0) + +# For sample support and debugging, not required for production: +stripe.set_app_info( + 'stripe-samples/checkout-one-time-payments', + version='0.0.1', + url='https://github.com/stripe-samples/checkout-one-time-payments') + +stripe.api_version = '2020-08-27' +stripe.api_key = os.getenv('STRIPE_KEY_SECRET') + +static_dir = str(os.path.abspath(os.path.join( + __file__, "..", os.getenv("STATIC_DIR")))) +app = Flask(__name__, static_folder=static_dir, + static_url_path="", template_folder=static_dir) + + +@app.route('/', methods=['GET']) +def get_example(): + return render_template('index.html') + + +@app.route('/config', methods=['GET']) +def get_publishable_key(): + price = stripe.Price.retrieve(os.getenv('PRICE')) + return jsonify({ + 'publicKey': os.getenv('STRIPE_PUBLISHABLE_KEY'), + 'unitAmount': price['unit_amount'], + 'currency': price['currency'] + }) + +# Fetch the Checkout Session to display the JSON result on the success page +@app.route('/checkout-session', methods=['GET']) +def get_checkout_session(): + id = request.args.get('sessionId') + checkout_session = stripe.checkout.Session.retrieve(id) + return jsonify(checkout_session) + + +@app.route('/create-checkout-session', methods=['POST']) +def create_checkout_session(): + quantity = request.form.get('quantity', 1) + domain_url = os.getenv('DOMAIN') + + try: + # Create new Checkout Session for the order + # Other optional params include: + # [billing_address_collection] - to display billing address details on the page + # [customer] - if you have an existing Stripe Customer ID + # [payment_intent_data] - lets capture the payment later + # [customer_email] - lets you prefill the email input in the form + # [automatic_tax] - to automatically calculate sales tax, VAT and GST in the checkout page + # For full details see https://stripe.com/docs/api/checkout/sessions/create + + # ?session_id={CHECKOUT_SESSION_ID} means the redirect will have the session ID set as a query param + checkout_session = stripe.checkout.Session.create( + success_url=domain_url + '/success.html?session_id={CHECKOUT_SESSION_ID}', + cancel_url=domain_url + '/canceled.html', + mode='payment', + # automatic_tax={'enabled': True}, + line_items=[{ + 'price': os.getenv('PRICE'), + 'quantity': quantity, + }] + ) + return redirect(checkout_session.url, code=303) + except Exception as e: + return jsonify(error=str(e)), 403 + + +@app.route('/webhook', methods=['POST']) +def webhook_received(): + # You can use webhooks to receive information about asynchronous payment events. + # For more about our webhook events check out https://stripe.com/docs/webhooks. + webhook_secret = os.getenv('STRIPE_WEBHOOK_SECRET') + request_data = json.loads(request.data) + + if webhook_secret: + # Retrieve the event by verifying the signature using the raw body and secret if webhook signing is configured. + signature = request.headers.get('stripe-signature') + try: + event = stripe.Webhook.construct_event( + payload=request.data, sig_header=signature, secret=webhook_secret) + data = event['data'] + except Exception as e: + return e + # Get the type of webhook event sent - used to check the status of PaymentIntents. + event_type = event['type'] + else: + data = request_data['data'] + event_type = request_data['type'] + data_object = data['object'] + + print('event ' + event_type) + + if event_type == 'checkout.session.completed': + print('🔔 Payment succeeded!') + + return jsonify({Model_View_Base.FLAG_STATUS: Model_View_Base.FLAG_SUCCESS}) + +if __name__ == '__main__': + app.run(port=4242, debug=True) \ No newline at end of file diff --git a/static/docs/template webpage.html b/static/docs/template webpage.html new file mode 100644 index 0000000..600d332 --- /dev/null +++ b/static/docs/template webpage.html @@ -0,0 +1,63 @@ + + + + + + + +
+

My Website

+

Resize the browser window to see the effect.

+
+ +
+ Link + Link + Link + Link +
+ +
+
+
+

TITLE HEADING

+
Title description, Dec 7, 2017
+
Image
+

Some text..

+

Sunt in culpa qui officia deserunt mollit anim id est laborum consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco.

+
+
+

TITLE HEADING

+
Title description, Sep 2, 2017
+
Image
+

Some text..

+

Sunt in culpa qui officia deserunt mollit anim id est laborum consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco.

+
+
+
+
+

About Me

+
Image
+

Some text about me in culpa qui officia deserunt mollit anim..

+
+
+

Popular Post

+

Image

+

Image

+

Image

+
+
+

Follow Me

+

Some text..

+
+
+
+ + + + + + + diff --git a/static/docs/test.py b/static/docs/test.py new file mode 100644 index 0000000..729ffc9 --- /dev/null +++ b/static/docs/test.py @@ -0,0 +1 @@ +print(not None) \ No newline at end of file diff --git a/static/docs/wcag_2.2AA_public-website-of-precision-and-research-technology-systems-limited-evaluation.json b/static/docs/wcag_2.2AA_public-website-of-precision-and-research-technology-systems-limited-evaluation.json new file mode 100644 index 0000000..53c592b --- /dev/null +++ b/static/docs/wcag_2.2AA_public-website-of-precision-and-research-technology-systems-limited-evaluation.json @@ -0,0 +1 @@ +{"@context":{"reporter":"http://github.com/w3c/wai-wcag-em-report-tool/","wcagem":"http://www.w3.org/TR/WCAG-EM/#","Evaluation":"wcagem:procedure","defineScope":"wcagem:step1","scope":"wcagem:step1a","step1b":{"@id":"wcagem:step1b","@type":"@id"},"conformanceTarget":"step1b","accessibilitySupportBaseline":"wcagem:step1c","additionalEvaluationRequirements":"wcagem:step1d","exploreTarget":"wcagem:step2","essentialFunctionality":"wcagem:step2b","pageTypeVariety":"wcagem:step2c","technologiesReliedUpon":"wcagem:step2d","selectSample":"wcagem:step3","structuredSample":"wcagem:step3a","randomSample":"wcagem:step3b","Website":"wcagem:website","Webpage":"wcagem:webpage","auditSample":"wcagem:step4","reportFindings":"wcagem:step5","documentSteps":"wcagem:step5a","commissioner":"wcagem:commissioner","evaluator":"wcagem:evaluator","evaluationSpecifics":"wcagem:step5b","WCAG":"http://www.w3.org/TR/WCAG/#","WCAG20":"http://www.w3.org/TR/WCAG20/#","WCAG21":"http://www.w3.org/TR/WCAG21/#","WAI":"http://www.w3.org/WAI/","A":"WAI:WCAG2A-Conformance","AA":"WAI:WCAG2AA-Conformance","AAA":"WAI:WCAG2AAA-Conformance","wcagVersion":"WAI:standards-guidelines/wcag/#versions","reportToolVersion":"wcagem:reportToolVersion","earl":"http://www.w3.org/ns/earl#","Assertion":"earl:Assertion","TestMode":"earl:TestMode","TestCriterion":"earl:TestCriterion","TestCase":"earl:TestCase","TestRequirement":"earl:TestRequirement","TestSubject":"earl:TestSubject","TestResult":"earl:TestResult","OutcomeValue":"earl:OutcomeValue","Pass":"earl:Pass","Fail":"earl:Fail","CannotTell":"earl:CannotTell","NotApplicable":"earl:NotApplicable","NotTested":"earl:NotTested","assertedBy":"earl:assertedBy","mode":"earl:mode","result":"earl:result","subject":"earl:subject","test":"earl:test","outcome":"earl:outcome","dcterms":"http://purl.org/dc/terms/","title":"dcterms:title","description":"dcterms:description","summary":"dcterms:summary","date":"dcterms:date","hasPart":"dcterms:hasPart","isPartOf":"dcterms:isPartOf","id":"@id","type":"@type","language":"@language"},"language":"en","type":"Evaluation","reportToolVersion":"3.0.3","defineScope":{"id":"_:defineScope","scope":{"description":"'All web content of the public mobile and desktop website of Precision And Research Technology Systems Limited located at https://www.partsltd.co.uk/","title":"Public Website of Precision And Research Technology Systems Limited"},"conformanceTarget":"AA","accessibilitySupportBaseline":"Google Chrome with NVDA, FireFox with NVDA, Ecosia mobile browser with TalkBack.","additionalEvaluationRequirements":"","wcagVersion":"2.2"},"exploreTarget":{"id":"_:exploreTarget","essentialFunctionality":"1. Navigation\n2. User input form\n3. Scripted text","pageTypeVariety":"1. Navigation\n2. User input form\n3. Scripted text","technologiesReliedUpon":["HTML","CSS","JavaScript","python Flask"]},"selectSample":{"id":"_:selectSample","structuredSample":[{"id":"_:subject_2","type":["TestSubject","Webpage"],"date":"2024-04-30T16:11:16.199Z","description":"https://www.partsltd.co.uk/","title":"Home"},{"id":"_:subject_3","type":["TestSubject","Webpage"],"date":"2024-04-30T16:11:32.890Z","description":"https://www.partsltd.co.uk/contact","title":"Contact us"},{"id":"_:subject_4","type":["TestSubject","Webpage"],"date":"2024-04-30T16:11:48.238Z","description":"https://www.partsltd.co.uk/services","title":"Services"}],"randomSample":{"id":"_:subject_5","type":["TestSubject","Webpage"],"date":"2024-04-30T16:12:19.332Z","description":"","title":""}},"auditSample":[{"type":"Assertion","date":"2024-04-30T15:48:00.008Z","mode":{"type":"TestMode","@value":"earl:manual"},"result":{"type":"TestResult","date":"2024-04-30T16:19:30.651Z","description":"All user input controls have descriptive names and v2 Google reCaptcha used with text label to identify to user that they must check the box to prove they are not a bot.","outcome":{"id":"earl:passed","type":["OutcomeValue","Pass"],"title":"Passed"}},"subject":{"id":"_:subject_1","type":["TestSubject","Website"],"date":"2024-04-30T15:47:59.864Z","description":"'All web content of the public mobile and desktop website of Precision And Research Technology Systems Limited located at https://www.partsltd.co.uk/","title":"Public Website of Precision And Research Technology Systems Limited"},"test":{"id":"WCAG22:non-text-content","type":["TestCriterion","TestRequirement"],"date":"2024-04-30T15:47:59.865Z"}},{"type":"Assertion","date":"2024-04-30T15:48:00.009Z","mode":{"type":"TestMode","@value":"earl:manual"},"result":{"type":"TestResult","date":"2024-04-30T16:20:00.306Z","description":"","outcome":{"id":"earl:inapplicable","type":["OutcomeValue","NotApplicable"],"title":"Not present"}},"subject":{"id":"_:subject_1","type":["TestSubject","Website"],"date":"2024-04-30T15:47:59.864Z","description":"'All web content of the public mobile and desktop website of Precision And Research Technology Systems Limited located at https://www.partsltd.co.uk/","title":"Public Website of Precision And Research Technology Systems Limited"},"test":{"id":"WCAG22:audio-only-and-video-only-prerecorded","type":["TestCriterion","TestRequirement"],"date":"2024-04-30T15:47:59.865Z"}},{"type":"Assertion","date":"2024-04-30T15:48:00.009Z","mode":{"type":"TestMode","@value":"earl:manual"},"result":{"type":"TestResult","date":"2024-04-30T16:20:04.748Z","description":"","outcome":{"id":"earl:inapplicable","type":["OutcomeValue","NotApplicable"],"title":"Not present"}},"subject":{"id":"_:subject_1","type":["TestSubject","Website"],"date":"2024-04-30T15:47:59.864Z","description":"'All web content of the public mobile and desktop website of Precision And Research Technology Systems Limited located at https://www.partsltd.co.uk/","title":"Public Website of Precision And Research Technology Systems Limited"},"test":{"id":"WCAG22:captions-prerecorded","type":["TestCriterion","TestRequirement"],"date":"2024-04-30T15:47:59.865Z"}},{"type":"Assertion","date":"2024-04-30T15:48:00.009Z","mode":{"type":"TestMode","@value":"earl:manual"},"result":{"type":"TestResult","date":"2024-04-30T16:20:08.119Z","description":"","outcome":{"id":"earl:inapplicable","type":["OutcomeValue","NotApplicable"],"title":"Not present"}},"subject":{"id":"_:subject_1","type":["TestSubject","Website"],"date":"2024-04-30T15:47:59.864Z","description":"'All web content of the public mobile and desktop website of Precision And Research Technology Systems Limited located at https://www.partsltd.co.uk/","title":"Public Website of Precision And Research Technology Systems Limited"},"test":{"id":"WCAG22:audio-description-or-media-alternative-prerecorded","type":["TestCriterion","TestRequirement"],"date":"2024-04-30T15:47:59.865Z"}},{"type":"Assertion","date":"2024-04-30T15:48:00.009Z","mode":{"type":"TestMode","@value":"earl:manual"},"result":{"type":"TestResult","date":"2024-04-30T16:20:10.538Z","description":"","outcome":{"id":"earl:inapplicable","type":["OutcomeValue","NotApplicable"],"title":"Not present"}},"subject":{"id":"_:subject_1","type":["TestSubject","Website"],"date":"2024-04-30T15:47:59.864Z","description":"'All web content of the public mobile and desktop website of Precision And Research Technology Systems Limited located at https://www.partsltd.co.uk/","title":"Public Website of Precision And Research Technology Systems Limited"},"test":{"id":"WCAG22:captions-live","type":["TestCriterion","TestRequirement"],"date":"2024-04-30T15:47:59.865Z"}},{"type":"Assertion","date":"2024-04-30T15:48:00.009Z","mode":{"type":"TestMode","@value":"earl:manual"},"result":{"type":"TestResult","date":"2024-04-30T16:20:14.224Z","description":"","outcome":{"id":"earl:inapplicable","type":["OutcomeValue","NotApplicable"],"title":"Not present"}},"subject":{"id":"_:subject_1","type":["TestSubject","Website"],"date":"2024-04-30T15:47:59.864Z","description":"'All web content of the public mobile and desktop website of Precision And Research Technology Systems Limited located at https://www.partsltd.co.uk/","title":"Public Website of Precision And Research Technology Systems Limited"},"test":{"id":"WCAG22:audio-description-prerecorded","type":["TestCriterion","TestRequirement"],"date":"2024-04-30T15:47:59.865Z"}},{"type":"Assertion","date":"2024-04-30T15:48:00.009Z","mode":{"type":"TestMode","@value":"earl:manual"},"result":{"type":"TestResult","date":"2024-04-30T17:11:01.128Z","description":"Elements change in response to zoom and viewport dimensions properly. Aria-label provided for all images.","outcome":{"id":"earl:passed","type":["OutcomeValue","Pass"],"title":"Passed"}},"subject":{"id":"_:subject_1","type":["TestSubject","Website"],"date":"2024-04-30T15:47:59.864Z","description":"'All web content of the public mobile and desktop website of Precision And Research Technology Systems Limited located at https://www.partsltd.co.uk/","title":"Public Website of Precision And Research Technology Systems Limited"},"test":{"id":"WCAG22:info-and-relationships","type":["TestCriterion","TestRequirement"],"date":"2024-04-30T15:47:59.865Z"}},{"type":"Assertion","date":"2024-04-30T15:48:00.009Z","mode":{"type":"TestMode","@value":"earl:manual"},"result":{"type":"TestResult","date":"2024-04-30T16:32:41.865Z","description":"Flow layout keeps associated sections together but allows dynamic structure depending on size of elements relative to screen.","outcome":{"id":"earl:passed","type":["OutcomeValue","Pass"],"title":"Passed"}},"subject":{"id":"_:subject_1","type":["TestSubject","Website"],"date":"2024-04-30T15:47:59.864Z","description":"'All web content of the public mobile and desktop website of Precision And Research Technology Systems Limited located at https://www.partsltd.co.uk/","title":"Public Website of Precision And Research Technology Systems Limited"},"test":{"id":"WCAG22:meaningful-sequence","type":["TestCriterion","TestRequirement"],"date":"2024-04-30T15:47:59.865Z"}},{"type":"Assertion","date":"2024-04-30T15:48:00.009Z","mode":{"type":"TestMode","@value":"earl:manual"},"result":{"type":"TestResult","date":"2024-04-30T17:11:04.668Z","description":"Content reads properly as raw text in default order. Aria-label provided for all images and names for all form input components.","outcome":{"id":"earl:passed","type":["OutcomeValue","Pass"],"title":"Passed"}},"subject":{"id":"_:subject_1","type":["TestSubject","Website"],"date":"2024-04-30T15:47:59.864Z","description":"'All web content of the public mobile and desktop website of Precision And Research Technology Systems Limited located at https://www.partsltd.co.uk/","title":"Public Website of Precision And Research Technology Systems Limited"},"test":{"id":"WCAG22:sensory-characteristics","type":["TestCriterion","TestRequirement"],"date":"2024-04-30T15:47:59.865Z"}},{"type":"Assertion","date":"2024-04-30T15:48:00.009Z","mode":{"type":"TestMode","@value":"earl:manual"},"result":{"type":"TestResult","date":"2024-04-30T16:35:31.858Z","description":"Orientation of content is not locked.","outcome":{"id":"earl:passed","type":["OutcomeValue","Pass"],"title":"Passed"}},"subject":{"id":"_:subject_1","type":["TestSubject","Website"],"date":"2024-04-30T15:47:59.864Z","description":"'All web content of the public mobile and desktop website of Precision And Research Technology Systems Limited located at https://www.partsltd.co.uk/","title":"Public Website of Precision And Research Technology Systems Limited"},"test":{"id":"WCAG22:orientation","type":["TestCriterion","TestRequirement"],"date":"2024-04-30T15:47:59.865Z"}},{"type":"Assertion","date":"2024-04-30T15:48:00.009Z","mode":{"type":"TestMode","@value":"earl:manual"},"result":{"type":"TestResult","date":"2024-04-30T16:38:55.478Z","description":"Appropriate visible labels used alongside name attributes for form input elements.","outcome":{"id":"earl:passed","type":["OutcomeValue","Pass"],"title":"Passed"}},"subject":{"id":"_:subject_1","type":["TestSubject","Website"],"date":"2024-04-30T15:47:59.864Z","description":"'All web content of the public mobile and desktop website of Precision And Research Technology Systems Limited located at https://www.partsltd.co.uk/","title":"Public Website of Precision And Research Technology Systems Limited"},"test":{"id":"WCAG22:identify-input-purpose","type":["TestCriterion","TestRequirement"],"date":"2024-04-30T15:47:59.865Z"}},{"type":"Assertion","date":"2024-04-30T15:48:00.009Z","mode":{"type":"TestMode","@value":"earl:manual"},"result":{"type":"TestResult","date":"2024-04-30T16:40:53.059Z","description":"Colour only used to convey meaning for text hyperlinks, which have alt-text attributes to identify their purpose and presence.","outcome":{"id":"earl:passed","type":["OutcomeValue","Pass"],"title":"Passed"}},"subject":{"id":"_:subject_1","type":["TestSubject","Website"],"date":"2024-04-30T15:47:59.864Z","description":"'All web content of the public mobile and desktop website of Precision And Research Technology Systems Limited located at https://www.partsltd.co.uk/","title":"Public Website of Precision And Research Technology Systems Limited"},"test":{"id":"WCAG22:use-of-color","type":["TestCriterion","TestRequirement"],"date":"2024-04-30T15:47:59.865Z"}},{"type":"Assertion","date":"2024-04-30T15:48:00.009Z","mode":{"type":"TestMode","@value":"earl:manual"},"result":{"type":"TestResult","date":"2024-04-30T16:39:24.368Z","description":"","outcome":{"id":"earl:inapplicable","type":["OutcomeValue","NotApplicable"],"title":"Not present"}},"subject":{"id":"_:subject_1","type":["TestSubject","Website"],"date":"2024-04-30T15:47:59.864Z","description":"'All web content of the public mobile and desktop website of Precision And Research Technology Systems Limited located at https://www.partsltd.co.uk/","title":"Public Website of Precision And Research Technology Systems Limited"},"test":{"id":"WCAG22:audio-control","type":["TestCriterion","TestRequirement"],"date":"2024-04-30T15:47:59.865Z"}},{"type":"Assertion","date":"2024-04-30T15:48:00.009Z","mode":{"type":"TestMode","@value":"earl:manual"},"result":{"type":"TestResult","date":"2024-04-30T16:46:29.787Z","description":"Webpage text contrast assessed with tool at this website: https://accessibleweb.com/color-contrast-checker/","outcome":{"id":"earl:passed","type":["OutcomeValue","Pass"],"title":"Passed"}},"subject":{"id":"_:subject_1","type":["TestSubject","Website"],"date":"2024-04-30T15:47:59.864Z","description":"'All web content of the public mobile and desktop website of Precision And Research Technology Systems Limited located at https://www.partsltd.co.uk/","title":"Public Website of Precision And Research Technology Systems Limited"},"test":{"id":"WCAG22:contrast-minimum","type":["TestCriterion","TestRequirement"],"date":"2024-04-30T15:47:59.865Z"}},{"type":"Assertion","date":"2024-04-30T15:48:00.009Z","mode":{"type":"TestMode","@value":"earl:manual"},"result":{"type":"TestResult","date":"2024-04-30T16:47:26.364Z","description":"All webpages can be scaled to up to 500% while maintaining structure and visible components.","outcome":{"id":"earl:passed","type":["OutcomeValue","Pass"],"title":"Passed"}},"subject":{"id":"_:subject_1","type":["TestSubject","Website"],"date":"2024-04-30T15:47:59.864Z","description":"'All web content of the public mobile and desktop website of Precision And Research Technology Systems Limited located at https://www.partsltd.co.uk/","title":"Public Website of Precision And Research Technology Systems Limited"},"test":{"id":"WCAG22:resize-text","type":["TestCriterion","TestRequirement"],"date":"2024-04-30T15:47:59.865Z"}},{"type":"Assertion","date":"2024-04-30T15:48:00.009Z","mode":{"type":"TestMode","@value":"earl:manual"},"result":{"type":"TestResult","date":"2024-04-30T16:47:30.067Z","description":"","outcome":{"id":"earl:inapplicable","type":["OutcomeValue","NotApplicable"],"title":"Not present"}},"subject":{"id":"_:subject_1","type":["TestSubject","Website"],"date":"2024-04-30T15:47:59.864Z","description":"'All web content of the public mobile and desktop website of Precision And Research Technology Systems Limited located at https://www.partsltd.co.uk/","title":"Public Website of Precision And Research Technology Systems Limited"},"test":{"id":"WCAG22:images-of-text","type":["TestCriterion","TestRequirement"],"date":"2024-04-30T15:47:59.865Z"}},{"type":"Assertion","date":"2024-04-30T15:48:00.009Z","mode":{"type":"TestMode","@value":"earl:manual"},"result":{"type":"TestResult","date":"2024-04-30T16:50:44.949Z","description":"Flex layout forces only vertical scrolling at required viewport dimensions.","outcome":{"id":"earl:passed","type":["OutcomeValue","Pass"],"title":"Passed"}},"subject":{"id":"_:subject_1","type":["TestSubject","Website"],"date":"2024-04-30T15:47:59.864Z","description":"'All web content of the public mobile and desktop website of Precision And Research Technology Systems Limited located at https://www.partsltd.co.uk/","title":"Public Website of Precision And Research Technology Systems Limited"},"test":{"id":"WCAG22:reflow","type":["TestCriterion","TestRequirement"],"date":"2024-04-30T15:47:59.865Z"}},{"type":"Assertion","date":"2024-04-30T15:48:00.009Z","mode":{"type":"TestMode","@value":"earl:manual"},"result":{"type":"TestResult","date":"2024-04-30T16:51:34.482Z","description":"Strong borders used for form input components.","outcome":{"id":"earl:passed","type":["OutcomeValue","Pass"],"title":"Passed"}},"subject":{"id":"_:subject_1","type":["TestSubject","Website"],"date":"2024-04-30T15:47:59.864Z","description":"'All web content of the public mobile and desktop website of Precision And Research Technology Systems Limited located at https://www.partsltd.co.uk/","title":"Public Website of Precision And Research Technology Systems Limited"},"test":{"id":"WCAG22:non-text-contrast","type":["TestCriterion","TestRequirement"],"date":"2024-04-30T15:47:59.865Z"}},{"type":"Assertion","date":"2024-04-30T15:48:00.009Z","mode":{"type":"TestMode","@value":"earl:manual"},"result":{"type":"TestResult","date":"2024-04-30T16:55:05.024Z","description":"Content becomes vertically scrollable as necessary.","outcome":{"id":"earl:passed","type":["OutcomeValue","Pass"],"title":"Passed"}},"subject":{"id":"_:subject_1","type":["TestSubject","Website"],"date":"2024-04-30T15:47:59.864Z","description":"'All web content of the public mobile and desktop website of Precision And Research Technology Systems Limited located at https://www.partsltd.co.uk/","title":"Public Website of Precision And Research Technology Systems Limited"},"test":{"id":"WCAG22:text-spacing","type":["TestCriterion","TestRequirement"],"date":"2024-04-30T15:47:59.865Z"}},{"type":"Assertion","date":"2024-04-30T15:48:00.009Z","mode":{"type":"TestMode","@value":"earl:manual"},"result":{"type":"TestResult","date":"2024-04-30T16:57:32.588Z","description":"Hamburger menu button for navigation overlay used. The button remains stationary with no elements above it, throughout use of navigation.","outcome":{"id":"earl:passed","type":["OutcomeValue","Pass"],"title":"Passed"}},"subject":{"id":"_:subject_1","type":["TestSubject","Website"],"date":"2024-04-30T15:47:59.864Z","description":"'All web content of the public mobile and desktop website of Precision And Research Technology Systems Limited located at https://www.partsltd.co.uk/","title":"Public Website of Precision And Research Technology Systems Limited"},"test":{"id":"WCAG22:content-on-hover-or-focus","type":["TestCriterion","TestRequirement"],"date":"2024-04-30T15:47:59.865Z"}},{"type":"Assertion","date":"2024-04-30T15:48:00.009Z","mode":{"type":"TestMode","@value":"earl:manual"},"result":{"type":"TestResult","date":"2024-04-30T16:58:42.536Z","description":"Tab indices set to enable correct transition around page by keyboard. Other keyboard shortcuts not changed.","outcome":{"id":"earl:passed","type":["OutcomeValue","Pass"],"title":"Passed"}},"subject":{"id":"_:subject_1","type":["TestSubject","Website"],"date":"2024-04-30T15:47:59.864Z","description":"'All web content of the public mobile and desktop website of Precision And Research Technology Systems Limited located at https://www.partsltd.co.uk/","title":"Public Website of Precision And Research Technology Systems Limited"},"test":{"id":"WCAG22:keyboard","type":["TestCriterion","TestRequirement"],"date":"2024-04-30T15:47:59.865Z"}},{"type":"Assertion","date":"2024-04-30T15:48:00.009Z","mode":{"type":"TestMode","@value":"earl:manual"},"result":{"type":"TestResult","date":"2024-04-30T16:58:59.976Z","description":"Tab indices set to enable correct transition around page by keyboard.","outcome":{"id":"earl:passed","type":["OutcomeValue","Pass"],"title":"Passed"}},"subject":{"id":"_:subject_1","type":["TestSubject","Website"],"date":"2024-04-30T15:47:59.864Z","description":"'All web content of the public mobile and desktop website of Precision And Research Technology Systems Limited located at https://www.partsltd.co.uk/","title":"Public Website of Precision And Research Technology Systems Limited"},"test":{"id":"WCAG22:no-keyboard-trap","type":["TestCriterion","TestRequirement"],"date":"2024-04-30T15:47:59.865Z"}},{"type":"Assertion","date":"2024-04-30T15:48:00.009Z","mode":{"type":"TestMode","@value":"earl:manual"},"result":{"type":"TestResult","date":"2024-04-30T16:59:38.989Z","description":"Tab indices set to enable correct transition around page by keyboard. Other keyboard shortcuts not changed, and can be set by user's device settings.","outcome":{"id":"earl:passed","type":["OutcomeValue","Pass"],"title":"Passed"}},"subject":{"id":"_:subject_1","type":["TestSubject","Website"],"date":"2024-04-30T15:47:59.864Z","description":"'All web content of the public mobile and desktop website of Precision And Research Technology Systems Limited located at https://www.partsltd.co.uk/","title":"Public Website of Precision And Research Technology Systems Limited"},"test":{"id":"WCAG22:character-key-shortcuts","type":["TestCriterion","TestRequirement"],"date":"2024-04-30T15:47:59.865Z"}},{"type":"Assertion","date":"2024-04-30T15:48:00.009Z","mode":{"type":"TestMode","@value":"earl:manual"},"result":{"type":"TestResult","date":"2024-04-30T17:00:42.868Z","description":"No session time limits imposed on user.","outcome":{"id":"earl:inapplicable","type":["OutcomeValue","NotApplicable"],"title":"Not present"}},"subject":{"id":"_:subject_1","type":["TestSubject","Website"],"date":"2024-04-30T15:47:59.864Z","description":"'All web content of the public mobile and desktop website of Precision And Research Technology Systems Limited located at https://www.partsltd.co.uk/","title":"Public Website of Precision And Research Technology Systems Limited"},"test":{"id":"WCAG22:timing-adjustable","type":["TestCriterion","TestRequirement"],"date":"2024-04-30T15:47:59.865Z"}},{"type":"Assertion","date":"2024-04-30T15:48:00.009Z","mode":{"type":"TestMode","@value":"earl:manual"},"result":{"type":"TestResult","date":"2024-04-30T17:01:05.985Z","description":"","outcome":{"id":"earl:inapplicable","type":["OutcomeValue","NotApplicable"],"title":"Not present"}},"subject":{"id":"_:subject_1","type":["TestSubject","Website"],"date":"2024-04-30T15:47:59.864Z","description":"'All web content of the public mobile and desktop website of Precision And Research Technology Systems Limited located at https://www.partsltd.co.uk/","title":"Public Website of Precision And Research Technology Systems Limited"},"test":{"id":"WCAG22:pause-stop-hide","type":["TestCriterion","TestRequirement"],"date":"2024-04-30T15:47:59.865Z"}},{"type":"Assertion","date":"2024-04-30T15:48:00.009Z","mode":{"type":"TestMode","@value":"earl:manual"},"result":{"type":"TestResult","date":"2024-04-30T17:01:18.827Z","description":"","outcome":{"id":"earl:passed","type":["OutcomeValue","Pass"],"title":"Passed"}},"subject":{"id":"_:subject_1","type":["TestSubject","Website"],"date":"2024-04-30T15:47:59.864Z","description":"'All web content of the public mobile and desktop website of Precision And Research Technology Systems Limited located at https://www.partsltd.co.uk/","title":"Public Website of Precision And Research Technology Systems Limited"},"test":{"id":"WCAG22:three-flashes-or-below-threshold","type":["TestCriterion","TestRequirement"],"date":"2024-04-30T15:47:59.865Z"}},{"type":"Assertion","date":"2024-04-30T15:48:00.009Z","mode":{"type":"TestMode","@value":"earl:manual"},"result":{"type":"TestResult","date":"2024-04-30T17:01:53.694Z","description":"","outcome":{"id":"earl:inapplicable","type":["OutcomeValue","NotApplicable"],"title":"Not present"}},"subject":{"id":"_:subject_1","type":["TestSubject","Website"],"date":"2024-04-30T15:47:59.864Z","description":"'All web content of the public mobile and desktop website of Precision And Research Technology Systems Limited located at https://www.partsltd.co.uk/","title":"Public Website of Precision And Research Technology Systems Limited"},"test":{"id":"WCAG22:bypass-blocks","type":["TestCriterion","TestRequirement"],"date":"2024-04-30T15:47:59.865Z"}},{"type":"Assertion","date":"2024-04-30T15:48:00.009Z","mode":{"type":"TestMode","@value":"earl:manual"},"result":{"type":"TestResult","date":"2024-04-30T17:02:13.542Z","description":"Descriptive titles used on all webpages.","outcome":{"id":"earl:passed","type":["OutcomeValue","Pass"],"title":"Passed"}},"subject":{"id":"_:subject_1","type":["TestSubject","Website"],"date":"2024-04-30T15:47:59.864Z","description":"'All web content of the public mobile and desktop website of Precision And Research Technology Systems Limited located at https://www.partsltd.co.uk/","title":"Public Website of Precision And Research Technology Systems Limited"},"test":{"id":"WCAG22:page-titled","type":["TestCriterion","TestRequirement"],"date":"2024-04-30T15:47:59.865Z"}},{"type":"Assertion","date":"2024-04-30T15:48:00.009Z","mode":{"type":"TestMode","@value":"earl:manual"},"result":{"type":"TestResult","date":"2024-04-30T17:02:30.677Z","description":"Keyboard tab indices set for logical navigation around pages.","outcome":{"id":"earl:passed","type":["OutcomeValue","Pass"],"title":"Passed"}},"subject":{"id":"_:subject_1","type":["TestSubject","Website"],"date":"2024-04-30T15:47:59.864Z","description":"'All web content of the public mobile and desktop website of Precision And Research Technology Systems Limited located at https://www.partsltd.co.uk/","title":"Public Website of Precision And Research Technology Systems Limited"},"test":{"id":"WCAG22:focus-order","type":["TestCriterion","TestRequirement"],"date":"2024-04-30T15:47:59.865Z"}},{"type":"Assertion","date":"2024-04-30T15:48:00.009Z","mode":{"type":"TestMode","@value":"earl:manual"},"result":{"type":"TestResult","date":"2024-04-30T17:11:09.564Z","description":"Descriptive aria-label provided for all text hyperlinks.","outcome":{"id":"earl:passed","type":["OutcomeValue","Pass"],"title":"Passed"}},"subject":{"id":"_:subject_1","type":["TestSubject","Website"],"date":"2024-04-30T15:47:59.864Z","description":"'All web content of the public mobile and desktop website of Precision And Research Technology Systems Limited located at https://www.partsltd.co.uk/","title":"Public Website of Precision And Research Technology Systems Limited"},"test":{"id":"WCAG22:link-purpose-in-context","type":["TestCriterion","TestRequirement"],"date":"2024-04-30T15:47:59.865Z"}},{"type":"Assertion","date":"2024-04-30T15:48:00.009Z","mode":{"type":"TestMode","@value":"earl:manual"},"result":{"type":"TestResult","date":"2024-04-30T17:03:56.473Z","description":"Navigation on all webpages and company logo links to home page.","outcome":{"id":"earl:passed","type":["OutcomeValue","Pass"],"title":"Passed"}},"subject":{"id":"_:subject_1","type":["TestSubject","Website"],"date":"2024-04-30T15:47:59.864Z","description":"'All web content of the public mobile and desktop website of Precision And Research Technology Systems Limited located at https://www.partsltd.co.uk/","title":"Public Website of Precision And Research Technology Systems Limited"},"test":{"id":"WCAG22:multiple-ways","type":["TestCriterion","TestRequirement"],"date":"2024-04-30T15:47:59.865Z"}},{"type":"Assertion","date":"2024-04-30T15:48:00.009Z","mode":{"type":"TestMode","@value":"earl:manual"},"result":{"type":"TestResult","date":"2024-04-30T17:06:48.832Z","description":"","outcome":{"id":"earl:passed","type":["OutcomeValue","Pass"],"title":"Passed"}},"subject":{"id":"_:subject_1","type":["TestSubject","Website"],"date":"2024-04-30T15:47:59.864Z","description":"'All web content of the public mobile and desktop website of Precision And Research Technology Systems Limited located at https://www.partsltd.co.uk/","title":"Public Website of Precision And Research Technology Systems Limited"},"test":{"id":"WCAG22:headings-and-labels","type":["TestCriterion","TestRequirement"],"date":"2024-04-30T15:47:59.865Z"}},{"type":"Assertion","date":"2024-04-30T15:48:00.009Z","mode":{"type":"TestMode","@value":"earl:manual"},"result":{"type":"TestResult","date":"2024-04-30T17:06:52.238Z","description":"","outcome":{"id":"earl:passed","type":["OutcomeValue","Pass"],"title":"Passed"}},"subject":{"id":"_:subject_1","type":["TestSubject","Website"],"date":"2024-04-30T15:47:59.864Z","description":"'All web content of the public mobile and desktop website of Precision And Research Technology Systems Limited located at https://www.partsltd.co.uk/","title":"Public Website of Precision And Research Technology Systems Limited"},"test":{"id":"WCAG22:focus-visible","type":["TestCriterion","TestRequirement"],"date":"2024-04-30T15:47:59.865Z"}},{"type":"Assertion","date":"2024-04-30T15:48:00.009Z","mode":{"type":"TestMode","@value":"earl:manual"},"result":{"type":"TestResult","date":"2024-04-30T17:07:05.561Z","description":"","outcome":{"id":"earl:passed","type":["OutcomeValue","Pass"],"title":"Passed"}},"subject":{"id":"_:subject_1","type":["TestSubject","Website"],"date":"2024-04-30T15:47:59.864Z","description":"'All web content of the public mobile and desktop website of Precision And Research Technology Systems Limited located at https://www.partsltd.co.uk/","title":"Public Website of Precision And Research Technology Systems Limited"},"test":{"id":"WCAG22:focus-not-obscured-minimum","type":["TestCriterion","TestRequirement"],"date":"2024-04-30T15:47:59.865Z"}},{"type":"Assertion","date":"2024-04-30T15:48:00.009Z","mode":{"type":"TestMode","@value":"earl:manual"},"result":{"type":"TestResult","date":"2024-04-30T17:07:25.308Z","description":"","outcome":{"id":"earl:inapplicable","type":["OutcomeValue","NotApplicable"],"title":"Not present"}},"subject":{"id":"_:subject_1","type":["TestSubject","Website"],"date":"2024-04-30T15:47:59.864Z","description":"'All web content of the public mobile and desktop website of Precision And Research Technology Systems Limited located at https://www.partsltd.co.uk/","title":"Public Website of Precision And Research Technology Systems Limited"},"test":{"id":"WCAG22:pointer-gestures","type":["TestCriterion","TestRequirement"],"date":"2024-04-30T15:47:59.865Z"}},{"type":"Assertion","date":"2024-04-30T15:48:00.009Z","mode":{"type":"TestMode","@value":"earl:manual"},"result":{"type":"TestResult","date":"2024-04-30T17:08:50.776Z","description":"Up event used to trigger events across website.","outcome":{"id":"earl:passed","type":["OutcomeValue","Pass"],"title":"Passed"}},"subject":{"id":"_:subject_1","type":["TestSubject","Website"],"date":"2024-04-30T15:47:59.864Z","description":"'All web content of the public mobile and desktop website of Precision And Research Technology Systems Limited located at https://www.partsltd.co.uk/","title":"Public Website of Precision And Research Technology Systems Limited"},"test":{"id":"WCAG22:pointer-cancellation","type":["TestCriterion","TestRequirement"],"date":"2024-04-30T15:47:59.865Z"}},{"type":"Assertion","date":"2024-04-30T15:48:00.009Z","mode":{"type":"TestMode","@value":"earl:manual"},"result":{"type":"TestResult","date":"2024-04-30T17:13:48.959Z","description":"Input label for attributes used to associate with input elements.\nAria-label attributes used for text hyperlinks.","outcome":{"id":"earl:passed","type":["OutcomeValue","Pass"],"title":"Passed"}},"subject":{"id":"_:subject_1","type":["TestSubject","Website"],"date":"2024-04-30T15:47:59.864Z","description":"'All web content of the public mobile and desktop website of Precision And Research Technology Systems Limited located at https://www.partsltd.co.uk/","title":"Public Website of Precision And Research Technology Systems Limited"},"test":{"id":"WCAG22:label-in-name","type":["TestCriterion","TestRequirement"],"date":"2024-04-30T15:47:59.865Z"}},{"type":"Assertion","date":"2024-04-30T15:48:00.009Z","mode":{"type":"TestMode","@value":"earl:manual"},"result":{"type":"TestResult","date":"2024-04-30T17:13:54.759Z","description":"","outcome":{"id":"earl:inapplicable","type":["OutcomeValue","NotApplicable"],"title":"Not present"}},"subject":{"id":"_:subject_1","type":["TestSubject","Website"],"date":"2024-04-30T15:47:59.864Z","description":"'All web content of the public mobile and desktop website of Precision And Research Technology Systems Limited located at https://www.partsltd.co.uk/","title":"Public Website of Precision And Research Technology Systems Limited"},"test":{"id":"WCAG22:motion-actuation","type":["TestCriterion","TestRequirement"],"date":"2024-04-30T15:47:59.865Z"}},{"type":"Assertion","date":"2024-04-30T15:48:00.009Z","mode":{"type":"TestMode","@value":"earl:manual"},"result":{"type":"TestResult","date":"2024-04-30T17:13:56.851Z","description":"","outcome":{"id":"earl:inapplicable","type":["OutcomeValue","NotApplicable"],"title":"Not present"}},"subject":{"id":"_:subject_1","type":["TestSubject","Website"],"date":"2024-04-30T15:47:59.864Z","description":"'All web content of the public mobile and desktop website of Precision And Research Technology Systems Limited located at https://www.partsltd.co.uk/","title":"Public Website of Precision And Research Technology Systems Limited"},"test":{"id":"WCAG22:dragging-movements","type":["TestCriterion","TestRequirement"],"date":"2024-04-30T15:47:59.865Z"}},{"type":"Assertion","date":"2024-04-30T15:48:00.009Z","mode":{"type":"TestMode","@value":"earl:manual"},"result":{"type":"TestResult","date":"2024-04-30T17:18:22.901Z","description":"Minimum control dimension is 27 CSS pixels.","outcome":{"id":"earl:passed","type":["OutcomeValue","Pass"],"title":"Passed"}},"subject":{"id":"_:subject_1","type":["TestSubject","Website"],"date":"2024-04-30T15:47:59.864Z","description":"'All web content of the public mobile and desktop website of Precision And Research Technology Systems Limited located at https://www.partsltd.co.uk/","title":"Public Website of Precision And Research Technology Systems Limited"},"test":{"id":"WCAG22:target-size-minimum","type":["TestCriterion","TestRequirement"],"date":"2024-04-30T15:47:59.866Z"}},{"type":"Assertion","date":"2024-04-30T15:48:00.009Z","mode":{"type":"TestMode","@value":"earl:manual"},"result":{"type":"TestResult","date":"2024-04-30T17:19:45.079Z","description":"English - Great Britain on all pages.","outcome":{"id":"earl:passed","type":["OutcomeValue","Pass"],"title":"Passed"}},"subject":{"id":"_:subject_1","type":["TestSubject","Website"],"date":"2024-04-30T15:47:59.864Z","description":"'All web content of the public mobile and desktop website of Precision And Research Technology Systems Limited located at https://www.partsltd.co.uk/","title":"Public Website of Precision And Research Technology Systems Limited"},"test":{"id":"WCAG22:language-of-page","type":["TestCriterion","TestRequirement"],"date":"2024-04-30T15:47:59.866Z"}},{"type":"Assertion","date":"2024-04-30T15:48:00.010Z","mode":{"type":"TestMode","@value":"earl:manual"},"result":{"type":"TestResult","date":"2024-04-30T17:20:10.271Z","description":"No language changes across website.","outcome":{"id":"earl:passed","type":["OutcomeValue","Pass"],"title":"Passed"}},"subject":{"id":"_:subject_1","type":["TestSubject","Website"],"date":"2024-04-30T15:47:59.864Z","description":"'All web content of the public mobile and desktop website of Precision And Research Technology Systems Limited located at https://www.partsltd.co.uk/","title":"Public Website of Precision And Research Technology Systems Limited"},"test":{"id":"WCAG22:language-of-parts","type":["TestCriterion","TestRequirement"],"date":"2024-04-30T15:47:59.866Z"}},{"type":"Assertion","date":"2024-04-30T15:48:00.010Z","mode":{"type":"TestMode","@value":"earl:manual"},"result":{"type":"TestResult","date":"2024-04-30T17:23:41.854Z","description":"No change of context initiated except by button click to navigate to submit a form and/or navigate to a new page.","outcome":{"id":"earl:passed","type":["OutcomeValue","Pass"],"title":"Passed"}},"subject":{"id":"_:subject_1","type":["TestSubject","Website"],"date":"2024-04-30T15:47:59.864Z","description":"'All web content of the public mobile and desktop website of Precision And Research Technology Systems Limited located at https://www.partsltd.co.uk/","title":"Public Website of Precision And Research Technology Systems Limited"},"test":{"id":"WCAG22:on-focus","type":["TestCriterion","TestRequirement"],"date":"2024-04-30T15:47:59.866Z"}},{"type":"Assertion","date":"2024-04-30T15:48:00.010Z","mode":{"type":"TestMode","@value":"earl:manual"},"result":{"type":"TestResult","date":"2024-04-30T17:23:56.660Z","description":"No change of context initiated except by button click to navigate to submit a form and/or navigate to a new page.","outcome":{"id":"earl:passed","type":["OutcomeValue","Pass"],"title":"Passed"}},"subject":{"id":"_:subject_1","type":["TestSubject","Website"],"date":"2024-04-30T15:47:59.864Z","description":"'All web content of the public mobile and desktop website of Precision And Research Technology Systems Limited located at https://www.partsltd.co.uk/","title":"Public Website of Precision And Research Technology Systems Limited"},"test":{"id":"WCAG22:on-input","type":["TestCriterion","TestRequirement"],"date":"2024-04-30T15:47:59.866Z"}},{"type":"Assertion","date":"2024-04-30T15:48:00.010Z","mode":{"type":"TestMode","@value":"earl:manual"},"result":{"type":"TestResult","date":"2024-04-30T17:24:11.721Z","description":"Navigation component and mechanisms shared across all pages.","outcome":{"id":"earl:passed","type":["OutcomeValue","Pass"],"title":"Passed"}},"subject":{"id":"_:subject_1","type":["TestSubject","Website"],"date":"2024-04-30T15:47:59.864Z","description":"'All web content of the public mobile and desktop website of Precision And Research Technology Systems Limited located at https://www.partsltd.co.uk/","title":"Public Website of Precision And Research Technology Systems Limited"},"test":{"id":"WCAG22:consistent-navigation","type":["TestCriterion","TestRequirement"],"date":"2024-04-30T15:47:59.866Z"}},{"type":"Assertion","date":"2024-04-30T15:48:00.010Z","mode":{"type":"TestMode","@value":"earl:manual"},"result":{"type":"TestResult","date":"2024-04-30T17:25:13.874Z","description":"Classes and CSS styles used to group collections of elements by purpose and functionality.","outcome":{"id":"earl:passed","type":["OutcomeValue","Pass"],"title":"Passed"}},"subject":{"id":"_:subject_1","type":["TestSubject","Website"],"date":"2024-04-30T15:47:59.864Z","description":"'All web content of the public mobile and desktop website of Precision And Research Technology Systems Limited located at https://www.partsltd.co.uk/","title":"Public Website of Precision And Research Technology Systems Limited"},"test":{"id":"WCAG22:consistent-identification","type":["TestCriterion","TestRequirement"],"date":"2024-04-30T15:47:59.866Z"}},{"type":"Assertion","date":"2024-04-30T15:48:00.010Z","mode":{"type":"TestMode","@value":"earl:manual"},"result":{"type":"TestResult","date":"2024-04-30T17:26:06.583Z","description":"Contact us button provided in a consistent format.","outcome":{"id":"earl:passed","type":["OutcomeValue","Pass"],"title":"Passed"}},"subject":{"id":"_:subject_1","type":["TestSubject","Website"],"date":"2024-04-30T15:47:59.864Z","description":"'All web content of the public mobile and desktop website of Precision And Research Technology Systems Limited located at https://www.partsltd.co.uk/","title":"Public Website of Precision And Research Technology Systems Limited"},"test":{"id":"WCAG22:consistent-help","type":["TestCriterion","TestRequirement"],"date":"2024-04-30T15:47:59.866Z"}},{"type":"Assertion","date":"2024-04-30T15:48:00.010Z","mode":{"type":"TestMode","@value":"earl:manual"},"result":{"type":"TestResult","date":"2024-04-30T17:26:47.172Z","description":"Each input element has an associated error display label which are triggered when input validation is not met.","outcome":{"id":"earl:passed","type":["OutcomeValue","Pass"],"title":"Passed"}},"subject":{"id":"_:subject_1","type":["TestSubject","Website"],"date":"2024-04-30T15:47:59.864Z","description":"'All web content of the public mobile and desktop website of Precision And Research Technology Systems Limited located at https://www.partsltd.co.uk/","title":"Public Website of Precision And Research Technology Systems Limited"},"test":{"id":"WCAG22:error-identification","type":["TestCriterion","TestRequirement"],"date":"2024-04-30T15:47:59.866Z"}},{"type":"Assertion","date":"2024-04-30T15:48:00.010Z","mode":{"type":"TestMode","@value":"earl:manual"},"result":{"type":"TestResult","date":"2024-04-30T17:27:08.142Z","description":"Each user input has a descriptive label.","outcome":{"id":"earl:passed","type":["OutcomeValue","Pass"],"title":"Passed"}},"subject":{"id":"_:subject_1","type":["TestSubject","Website"],"date":"2024-04-30T15:47:59.864Z","description":"'All web content of the public mobile and desktop website of Precision And Research Technology Systems Limited located at https://www.partsltd.co.uk/","title":"Public Website of Precision And Research Technology Systems Limited"},"test":{"id":"WCAG22:labels-or-instructions","type":["TestCriterion","TestRequirement"],"date":"2024-04-30T15:47:59.866Z"}},{"type":"Assertion","date":"2024-04-30T15:48:00.010Z","mode":{"type":"TestMode","@value":"earl:manual"},"result":{"type":"TestResult","date":"2024-04-30T17:30:48.127Z","description":"Text description of incomplete required fields is provided. Description of what caused error is issued when it involves simple regular expression validation.","outcome":{"id":"earl:passed","type":["OutcomeValue","Pass"],"title":"Passed"}},"subject":{"id":"_:subject_1","type":["TestSubject","Website"],"date":"2024-04-30T15:47:59.864Z","description":"'All web content of the public mobile and desktop website of Precision And Research Technology Systems Limited located at https://www.partsltd.co.uk/","title":"Public Website of Precision And Research Technology Systems Limited"},"test":{"id":"WCAG22:error-suggestion","type":["TestCriterion","TestRequirement"],"date":"2024-04-30T15:47:59.866Z"}},{"type":"Assertion","date":"2024-04-30T15:48:00.010Z","mode":{"type":"TestMode","@value":"earl:manual"},"result":{"type":"TestResult","date":"2024-04-30T17:31:12.544Z","description":"","outcome":{"id":"earl:inapplicable","type":["OutcomeValue","NotApplicable"],"title":"Not present"}},"subject":{"id":"_:subject_1","type":["TestSubject","Website"],"date":"2024-04-30T15:47:59.864Z","description":"'All web content of the public mobile and desktop website of Precision And Research Technology Systems Limited located at https://www.partsltd.co.uk/","title":"Public Website of Precision And Research Technology Systems Limited"},"test":{"id":"WCAG22:error-prevention-legal-financial-data","type":["TestCriterion","TestRequirement"],"date":"2024-04-30T15:47:59.866Z"}},{"type":"Assertion","date":"2024-04-30T15:48:00.010Z","mode":{"type":"TestMode","@value":"earl:manual"},"result":{"type":"TestResult","date":"2024-04-30T17:33:08.124Z","description":"No redundant data entry required. User's browser cache stores form data for rapid re-entry on crash or any other occasion.","outcome":{"id":"earl:passed","type":["OutcomeValue","Pass"],"title":"Passed"}},"subject":{"id":"_:subject_1","type":["TestSubject","Website"],"date":"2024-04-30T15:47:59.864Z","description":"'All web content of the public mobile and desktop website of Precision And Research Technology Systems Limited located at https://www.partsltd.co.uk/","title":"Public Website of Precision And Research Technology Systems Limited"},"test":{"id":"WCAG22:redundant-entry","type":["TestCriterion","TestRequirement"],"date":"2024-04-30T15:47:59.866Z"}},{"type":"Assertion","date":"2024-04-30T15:48:00.010Z","mode":{"type":"TestMode","@value":"earl:manual"},"result":{"type":"TestResult","date":"2024-04-30T17:34:17.347Z","description":"Alternative sign in methods provided, including recovery by code by phone and email.","outcome":{"id":"earl:passed","type":["OutcomeValue","Pass"],"title":"Passed"}},"subject":{"id":"_:subject_1","type":["TestSubject","Website"],"date":"2024-04-30T15:47:59.864Z","description":"'All web content of the public mobile and desktop website of Precision And Research Technology Systems Limited located at https://www.partsltd.co.uk/","title":"Public Website of Precision And Research Technology Systems Limited"},"test":{"id":"WCAG22:accessible-authentication-minimum","type":["TestCriterion","TestRequirement"],"date":"2024-04-30T15:47:59.866Z"}},{"type":"Assertion","date":"2024-04-30T15:48:00.010Z","mode":{"type":"TestMode","@value":"earl:manual"},"result":{"type":"TestResult","date":"2024-04-30T17:37:16.977Z","description":"Aria-label attribute maintained for all images and text hyperlinks. Label for attribute used to associate input elements with descriptive labels.","outcome":{"id":"earl:passed","type":["OutcomeValue","Pass"],"title":"Passed"}},"subject":{"id":"_:subject_1","type":["TestSubject","Website"],"date":"2024-04-30T15:47:59.864Z","description":"'All web content of the public mobile and desktop website of Precision And Research Technology Systems Limited located at https://www.partsltd.co.uk/","title":"Public Website of Precision And Research Technology Systems Limited"},"test":{"id":"WCAG22:name-role-value","type":["TestCriterion","TestRequirement"],"date":"2024-04-30T15:47:59.866Z"}},{"type":"Assertion","date":"2024-04-30T15:48:00.010Z","mode":{"type":"TestMode","@value":"earl:manual"},"result":{"type":"TestResult","date":"2024-04-30T17:38:13.227Z","description":"Success feedback provided on form submission, with descriptive errors on failure.","outcome":{"id":"earl:passed","type":["OutcomeValue","Pass"],"title":"Passed"}},"subject":{"id":"_:subject_1","type":["TestSubject","Website"],"date":"2024-04-30T15:47:59.864Z","description":"'All web content of the public mobile and desktop website of Precision And Research Technology Systems Limited located at https://www.partsltd.co.uk/","title":"Public Website of Precision And Research Technology Systems Limited"},"test":{"id":"WCAG22:status-messages","type":["TestCriterion","TestRequirement"],"date":"2024-04-30T15:47:59.866Z"}}],"reportFindings":{"date":{"type":"http://www.w3.org/TR/NOTE-datetime","@value":"Tue Apr 30 2024"},"summary":"","title":"","commissioner":"Lord Edward Middleton-Smith","evaluator":"Lord Edward Middleton-Smith","documentSteps":[{"id":"_:about"},{"id":"_:defineScope"},{"id":"_:exploreTarget"},{"id":"_:selectSample"}],"evaluationSpecifics":""}} \ No newline at end of file diff --git a/static/docs/wcag_2.2AA_public-website-of-precision-and-research-technology-systems-limited-report.html b/static/docs/wcag_2.2AA_public-website-of-precision-and-research-technology-systems-limited-report.html new file mode 100644 index 0000000..527d424 --- /dev/null +++ b/static/docs/wcag_2.2AA_public-website-of-precision-and-research-technology-systems-limited-report.html @@ -0,0 +1,60 @@ +public-website-of-precision-and-research-technology-systems-limited-report.html

Report

About the Evaluation

Report Creator
Lord Edward Middleton-Smith
Evaluation Commissioner
Lord Edward Middleton-Smith
Evaluation date
Tue Apr 30 2024

Executive Summary

Not provided

Scope of the Evaluation

Website name
Public Website of Precision And Research Technology Systems Limited
Scope of the website
'All web content of the public mobile and desktop website of Precision And Research Technology Systems Limited located at https://www.partsltd.co.uk/
WCAG Version
2.2
Conformance target
AA
Accessibility support baseline
Google Chrome with NVDA, FireFox with NVDA, Ecosia mobile browser with TalkBack.
Additional evaluation requirements
Not provided

Detailed Audit Results

Summary

Reported on 55 of 55 WCAG 2.2 AA + Success Criteria.

  • 41 Passed
  • 0 Failed
  • 0 Cannot tell
  • 14 Not present
  • 0 Not checked

All Results

1 Perceivable

1.1 Text Alternatives
Success Criterion Result Observations
1.1.1: Non-text Content

Result: Passed

Observations:

All user input controls have descriptive names and v2 Google reCaptcha used with text label to identify to user that they must check the box to prove they are not a bot.

+
1.2 Time-based Media
Success Criterion Result Observations
1.2.1: Audio-only and Video-only (Prerecorded)

Result: Not present

1.2.2: Captions (Prerecorded)

Result: Not present

1.2.3: Audio Description or Media Alternative (Prerecorded)

Result: Not present

1.2.4: Captions (Live)

Result: Not present

1.2.5: Audio Description (Prerecorded)

Result: Not present

1.3 Adaptable
Success Criterion Result Observations
1.3.1: Info and Relationships

Result: Passed

Observations:

Elements change in response to zoom and viewport dimensions properly. Aria-label provided for all images.

+
1.3.2: Meaningful Sequence

Result: Passed

Observations:

Flow layout keeps associated sections together but allows dynamic structure depending on size of elements relative to screen.

+
1.3.3: Sensory Characteristics

Result: Passed

Observations:

Content reads properly as raw text in default order. Aria-label provided for all images and names for all form input components.

+
1.3.4: Orientation

Result: Passed

Observations:

Orientation of content is not locked.

+
1.3.5: Identify Input Purpose

Result: Passed

Observations:

Appropriate visible labels used alongside name attributes for form input elements.

+
1.4 Distinguishable
Success Criterion Result Observations
1.4.1: Use of Color

Result: Passed

Observations:

Colour only used to convey meaning for text hyperlinks, which have alt-text attributes to identify their purpose and presence.

+
1.4.2: Audio Control

Result: Not present

1.4.3: Contrast (Minimum)

Result: Passed

Observations:

Webpage text contrast assessed with tool at this website: https://accessibleweb.com/color-contrast-checker/

+
1.4.4: Resize text

Result: Passed

Observations:

All webpages can be scaled to up to 500% while maintaining structure and visible components.

+
1.4.5: Images of Text

Result: Not present

1.4.10: Reflow

Result: Passed

Observations:

Flex layout forces only vertical scrolling at required viewport dimensions.

+
1.4.11: Non-text Contrast

Result: Passed

Observations:

Strong borders used for form input components.

+
1.4.12: Text Spacing

Result: Passed

Observations:

Content becomes vertically scrollable as necessary.

+
1.4.13: Content on Hover or Focus

Result: Passed

Observations:

Hamburger menu button for navigation overlay used. The button remains stationary with no elements above it, throughout use of navigation.

+

2 Operable

2.1 Keyboard Accessible
Success Criterion Result Observations
2.1.1: Keyboard

Result: Passed

Observations:

Tab indices set to enable correct transition around page by keyboard. Other keyboard shortcuts not changed.

+
2.1.2: No Keyboard Trap

Result: Passed

Observations:

Tab indices set to enable correct transition around page by keyboard.

+
2.1.4: Character Key Shortcuts

Result: Passed

Observations:

Tab indices set to enable correct transition around page by keyboard. Other keyboard shortcuts not changed, and can be set by user's device settings.

+
2.2 Enough Time
Success Criterion Result Observations
2.2.1: Timing Adjustable

Result: Not present

Observations:

No session time limits imposed on user.

+
2.2.2: Pause, Stop, Hide

Result: Not present

2.3 Seizures and Physical Reactions
Success Criterion Result Observations
2.3.1: Three Flashes or Below Threshold

Result: Passed

2.4 Navigable
Success Criterion Result Observations
2.4.1: Bypass Blocks

Result: Not present

2.4.2: Page Titled

Result: Passed

Observations:

Descriptive titles used on all webpages.

+
2.4.3: Focus Order

Result: Passed

Observations:

Keyboard tab indices set for logical navigation around pages.

+
2.4.4: Link Purpose (In Context)

Result: Passed

Observations:

Descriptive aria-label provided for all text hyperlinks.

+
2.4.5: Multiple Ways

Result: Passed

Observations:

Navigation on all webpages and company logo links to home page.

+
2.4.6: Headings and Labels

Result: Passed

2.4.7: Focus Visible

Result: Passed

2.4.11: Focus Not Obscured (Minimum)

Result: Passed

2.5 Input Modalities
Success Criterion Result Observations
2.5.1: Pointer Gestures

Result: Not present

2.5.2: Pointer Cancellation

Result: Passed

Observations:

Up event used to trigger events across website.

+
2.5.3: Label in Name

Result: Passed

Observations:

Input label for attributes used to associate with input elements. +Aria-label attributes used for text hyperlinks.

+
2.5.4: Motion Actuation

Result: Not present

2.5.7: Dragging Movements

Result: Not present

2.5.8: Target Size (Minimum)

Result: Passed

Observations:

Minimum control dimension is 27 CSS pixels.

+

3 Understandable

3.1 Readable
Success Criterion Result Observations
3.1.1: Language of Page

Result: Passed

Observations:

English - Great Britain on all pages.

+
3.1.2: Language of Parts

Result: Passed

Observations:

No language changes across website.

+
3.2 Predictable
Success Criterion Result Observations
3.2.1: On Focus

Result: Passed

Observations:

No change of context initiated except by button click to navigate to submit a form and/or navigate to a new page.

+
3.2.2: On Input

Result: Passed

Observations:

No change of context initiated except by button click to navigate to submit a form and/or navigate to a new page.

+
3.2.3: Consistent Navigation

Result: Passed

Observations:

Navigation component and mechanisms shared across all pages.

+
3.2.4: Consistent Identification

Result: Passed

Observations:

Classes and CSS styles used to group collections of elements by purpose and functionality.

+
3.2.6: Consistent Help

Result: Passed

Observations:

Contact us button provided in a consistent format.

+
3.3 Input Assistance
Success Criterion Result Observations
3.3.1: Error Identification

Result: Passed

Observations:

Each input element has an associated error display label which are triggered when input validation is not met.

+
3.3.2: Labels or Instructions

Result: Passed

Observations:

Each user input has a descriptive label.

+
3.3.3: Error Suggestion

Result: Passed

Observations:

Text description of incomplete required fields is provided. Description of what caused error is issued when it involves simple regular expression validation.

+
3.3.4: Error Prevention (Legal, Financial, Data)

Result: Not present

3.3.7: Redundant Entry

Result: Passed

Observations:

No redundant data entry required. User's browser cache stores form data for rapid re-entry on crash or any other occasion.

+
3.3.8: Accessible Authentication (Minimum)

Result: Passed

Observations:

Alternative sign in methods provided, including recovery by code by phone and email.

+

4 Robust

4.1 Compatible
Success Criterion Result Observations
4.1.2: Name, Role, Value

Result: Passed

Observations:

Aria-label attribute maintained for all images and text hyperlinks. Label for attribute used to associate input elements with descriptive labels.

+
4.1.3: Status Messages

Result: Passed

Observations:

Success feedback provided on form submission, with descriptive errors on failure.

+

Sample of Audited Web Pages

  1. Home - https://www.partsltd.co.uk/
  2. Contact us - https://www.partsltd.co.uk/contact
  3. Services - https://www.partsltd.co.uk/services
  4. -

Web Technology

HTML,CSS,JavaScript,python Flask

Recording of Evaluation Specifics

Not provided

\ No newline at end of file diff --git a/static/images/Braille_Translator_Demo.png b/static/images/Braille_Translator_Demo.png new file mode 100644 index 0000000..17c7a69 Binary files /dev/null and b/static/images/Braille_Translator_Demo.png differ diff --git a/static/images/CAD.gif b/static/images/CAD.gif new file mode 100644 index 0000000..5e53287 Binary files /dev/null and b/static/images/CAD.gif differ diff --git a/static/images/CSS3.jpg b/static/images/CSS3.jpg new file mode 100644 index 0000000..62b709e Binary files /dev/null and b/static/images/CSS3.jpg differ diff --git a/static/images/Csharp_NET.png b/static/images/Csharp_NET.png new file mode 100644 index 0000000..98c8174 Binary files /dev/null and b/static/images/Csharp_NET.png differ diff --git a/static/images/Firebase.png b/static/images/Firebase.png new file mode 100644 index 0000000..082d4a2 Binary files /dev/null and b/static/images/Firebase.png differ diff --git a/static/images/Flask.png b/static/images/Flask.png new file mode 100644 index 0000000..090f641 Binary files /dev/null and b/static/images/Flask.png differ diff --git a/static/images/Fractal Fortune Teller.mp4 b/static/images/Fractal Fortune Teller.mp4 new file mode 100644 index 0000000..08ebcff Binary files /dev/null and b/static/images/Fractal Fortune Teller.mp4 differ diff --git a/static/images/HTML5.png b/static/images/HTML5.png new file mode 100644 index 0000000..c6dd245 Binary files /dev/null and b/static/images/HTML5.png differ diff --git a/static/images/Invoice Generator.mp4 b/static/images/Invoice Generator.mp4 new file mode 100644 index 0000000..06490e9 Binary files /dev/null and b/static/images/Invoice Generator.mp4 differ diff --git a/static/images/Java.png b/static/images/Java.png new file mode 100644 index 0000000..aa24d48 Binary files /dev/null and b/static/images/Java.png differ diff --git a/static/images/JavaScript.png b/static/images/JavaScript.png new file mode 100644 index 0000000..f96024f Binary files /dev/null and b/static/images/JavaScript.png differ diff --git a/static/images/Logo.png b/static/images/Logo.png new file mode 100644 index 0000000..5468e5d Binary files /dev/null and b/static/images/Logo.png differ diff --git a/static/images/Logo_GitHub.png b/static/images/Logo_GitHub.png new file mode 100644 index 0000000..04999f3 Binary files /dev/null and b/static/images/Logo_GitHub.png differ diff --git a/static/images/Logo_LinkedIn.png b/static/images/Logo_LinkedIn.png new file mode 100644 index 0000000..67a756f Binary files /dev/null and b/static/images/Logo_LinkedIn.png differ diff --git a/static/images/Logo_v1a.png b/static/images/Logo_v1a.png new file mode 100644 index 0000000..d49d228 Binary files /dev/null and b/static/images/Logo_v1a.png differ diff --git a/static/images/MS_SQL_Server.svg b/static/images/MS_SQL_Server.svg new file mode 100644 index 0000000..ea08894 --- /dev/null +++ b/static/images/MS_SQL_Server.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/static/images/MVC.png b/static/images/MVC.png new file mode 100644 index 0000000..9b12dd2 Binary files /dev/null and b/static/images/MVC.png differ diff --git a/static/images/MySQL.png b/static/images/MySQL.png new file mode 100644 index 0000000..b3e9ceb Binary files /dev/null and b/static/images/MySQL.png differ diff --git a/static/images/Node_js.png b/static/images/Node_js.png new file mode 100644 index 0000000..999c4ea Binary files /dev/null and b/static/images/Node_js.png differ diff --git a/static/images/Prosthetics_Demo.gif b/static/images/Prosthetics_Demo.gif new file mode 100644 index 0000000..2fadcca Binary files /dev/null and b/static/images/Prosthetics_Demo.gif differ diff --git a/static/images/REST.png b/static/images/REST.png new file mode 100644 index 0000000..a350006 Binary files /dev/null and b/static/images/REST.png differ diff --git a/static/images/React.png b/static/images/React.png new file mode 100644 index 0000000..614f78b Binary files /dev/null and b/static/images/React.png differ diff --git a/static/images/Tag_Molly1.jpg b/static/images/Tag_Molly1.jpg new file mode 100644 index 0000000..8ca5c74 Binary files /dev/null and b/static/images/Tag_Molly1.jpg differ diff --git a/static/images/Warhammer Jiggler.gif b/static/images/Warhammer Jiggler.gif new file mode 100644 index 0000000..fbb5363 Binary files /dev/null and b/static/images/Warhammer Jiggler.gif differ diff --git a/static/images/icon_basket.png b/static/images/icon_basket.png new file mode 100644 index 0000000..6d6161d Binary files /dev/null and b/static/images/icon_basket.png differ diff --git a/static/images/mechatronics_design.gif b/static/images/mechatronics_design.gif new file mode 100644 index 0000000..fbb5363 Binary files /dev/null and b/static/images/mechatronics_design.gif differ diff --git a/static/images/ms_automation.mp4 b/static/images/ms_automation.mp4 new file mode 100644 index 0000000..a7850ff Binary files /dev/null and b/static/images/ms_automation.mp4 differ diff --git a/static/images/prod_.jpg b/static/images/prod_.jpg new file mode 100644 index 0000000..9ad384d Binary files /dev/null and b/static/images/prod_.jpg differ diff --git a/static/images/prod_1.jpg b/static/images/prod_1.jpg new file mode 100644 index 0000000..475f011 Binary files /dev/null and b/static/images/prod_1.jpg differ diff --git a/static/images/prod_2.jpg b/static/images/prod_2.jpg new file mode 100644 index 0000000..552d0f8 Binary files /dev/null and b/static/images/prod_2.jpg differ diff --git a/static/images/prod_PB0NUOSEs06ymG.jpg b/static/images/prod_PB0NUOSEs06ymG.jpg new file mode 100644 index 0000000..892c812 Binary files /dev/null and b/static/images/prod_PB0NUOSEs06ymG.jpg differ diff --git a/static/images/programming_services.mp4 b/static/images/programming_services.mp4 new file mode 100644 index 0000000..978c468 Binary files /dev/null and b/static/images/programming_services.mp4 differ diff --git a/static/images/python.png b/static/images/python.png new file mode 100644 index 0000000..db84614 Binary files /dev/null and b/static/images/python.png differ diff --git a/static/images/webapp_db_design.mp4 b/static/images/webapp_db_design.mp4 new file mode 100644 index 0000000..2daccdd Binary files /dev/null and b/static/images/webapp_db_design.mp4 differ diff --git a/static/js/accessibility_statement.js b/static/js/accessibility_statement.js new file mode 100644 index 0000000..1a4f23a --- /dev/null +++ b/static/js/accessibility_statement.js @@ -0,0 +1,5 @@ +var _loading = true; + +function hookupPageAccessibilityStatement() { + _loading = false; +} diff --git a/static/js/api.js b/static/js/api.js new file mode 100644 index 0000000..1a31ca0 --- /dev/null +++ b/static/js/api.js @@ -0,0 +1,59 @@ +import DOM from './dom.js'; + +export default class API { + + static getCsrfToken() { + return document.querySelector(idCSRFToken).getAttribute('content'); + } + + static async request(hashEndpoint, method = 'GET', data = null, params = null) { + const url = API.getUrlFromHash(hashEndpoint, params); + const csrfToken = API.getCsrfToken(); + const options = { + method, + headers: { + 'Content-Type': 'application/json', + [flagCsrfToken]: csrfToken, + } + }; + + if (data && (method === 'POST' || method === 'PUT' || method === 'PATCH')) { + data = { + ...data, + [flagCsrfToken]: csrfToken, + }; + options.body = JSON.stringify(data); + } + + try { + const response = await fetch(url, options); + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } + return await response.json(); + } catch (error) { + console.error('API request failed:', error); + throw error; + } + } + + static getUrlFromHash(hash, params = null) { + if (hash == null) hash = hashPageHome; + let url = API.parameteriseUrl(_pathHost + hash, params); + return url; + } + static parameteriseUrl(url, params) { + if (params) { + url += '?' + new URLSearchParams(params).toString(); + } + return url; + } + static goToUrl(url) { + window.location.href = url; + } + static goToHash(hash, params = null) { + const url = API.getUrlFromHash(hash, params); + API.goToUrl(url); + } + +} diff --git a/static/js/app.js b/static/js/app.js new file mode 100644 index 0000000..4215690 --- /dev/null +++ b/static/js/app.js @@ -0,0 +1,52 @@ + +'use strict'; + +import DOM from './dom.js'; +import Router from './router.js'; + + +class App { + constructor() { + this.dom = new DOM(); + this.router = new Router(); + } + + initialize() { + this.setupEventListeners(); + this.start(); + } + + setupEventListeners() { + // document.addEventListener('click', this.handleGlobalClick.bind(this)); + } + + handleGlobalClick(event) { + } + + start() { + this.initPageCurrent(); + } + + initPageCurrent() { + this.router.loadPageCurrent(); + } + +} + +const app = new App(); + +function domReady(fn) { + if (document.readyState !== 'loading') { + fn(); + } else { + document.addEventListener('DOMContentLoaded', fn); + } +} + +domReady(() => { + app.initialize(); +}); + +window.app = app; + +export default app; \ No newline at end of file diff --git a/static/js/components/common/inputs/input_date.js b/static/js/components/common/inputs/input_date.js new file mode 100644 index 0000000..df12608 --- /dev/null +++ b/static/js/components/common/inputs/input_date.js @@ -0,0 +1,183 @@ + +import Validation from "../../../lib/validation.js"; + + +// Date picker inputs +/* +function hookupInputDatePickers(dateInputs, notFuture, notPast, parent, addClearOption) { + + if (!Validation.isEmpty(dateInputs)) { + + let currentInput, currentDateString, currentDate, exceptionsArray; + + for (let i = 0; i < dateInputs.length; i++) { + + currentInput = document.querySelectorAll(dateInputs[i]); + currentDateString = currentInput.val(); + currentDate = (!Validation.isEmpty(currentDateString)) ? convertDDMMYYYYString2Date(currentDateString, false) : null; + exceptionsArray = (currentDate != null) ? [currentDate] : null; + + turnInputIntoDatePicker(currentInput, notFuture, notPast, exceptionsArray); + } + + if (!Validation.isEmpty(parent)) { + // stop user from manually typing date except backspace and delete + // which will clear the whole value to ensure we either have a whole + // date string or none + + parent.addEventListener("keydown", isDatePickerSelector, function(event) { + if (event.keyCode == 46 | event.keyCode == 8) { // delete or backspace + this.val(''); + } + else { + event.preventDefault(); + event.stopPropagation(); + } + + return false + }); + + if (addClearOption) { + + // if user right-clicks in date input, give option to clear the date + parent.contextMenu({ + selector: isDatePickerSelector, + delay: 100, + autoHide: true, + position: function(opt, x, y) { + var event = opt.$trigger[0]?.ownerDocument?.defaultView?.event || event; + opt.$menu.position({ my: 'center top', at: 'center top', of: event }); + }, + items: { + "clears": { + name: "Clear Date", + icon: "delete", + disabled: function(key, opt) { return Validation.isEmpty(document.querySelectorAll(opt.$trigger)); }, // if it's already empty, don't do anything + callback: function(itemKey, opt, rootMenu, originalEvent) { var input = document.querySelectorAll(opt.$trigger); input.val(''); input.trigger('change'); } + } + } + }); + } + } + } +} + +function turnInputIntoDatePicker(input, notFuture, notPast, exceptionValueArray) { + + var beforeShowDayCallBack = null; + + if (notFuture || notPast) { + + var today = new Date(); + today.setHours(0, 0, 0, 0); + + var tomorrow = new Date(); + tomorrow.setDate(today.getDate() + 1); + tomorrow.setHours(0, 0, 0, 0); + + var hasExceptions = !Validation.isEmpty(exceptionValueArray); + + beforeShowDayCallBack = function(date) { + + var selectedDate = date.getTime(); + var fieldHasException = hasExceptions && Validation.arrayContainsItem(exceptionValueArray, date); + + if (notFuture && (tomorrow < selectedDate) && fieldHasException) return [false, 'redday', 'You cannot choose a future date']; + if (notPast && (selectedDate < today) && fieldHasException) return [false, 'redday', 'You cannot choose a past date']; + + return [true, '', '']; + }; + } + + input.datepicker({ + dateFormat: 'dd-mm-yy', + navigationAsDateFormat: true, + beforeShowDay: beforeShowDayCallBack + }); + + // prevent datepicker from appearing on right click + input.addEventListener('contextmenu', function() { this.datepicker('hide'); }); + + // Disable autocomplete suggestions appearing when clicking on input + input.getAttribute('autocomplete', 'off'); +} + +function setDatePickerDate(input, objDate) { + if (!Validation.isEmpty(objDate)) { + input.val(''); + } + else { + input.datepicker('setDate', objDate); + } +} + +function getDatePickerDate(input, adjust4DayLightSavings) { + + var date = null; + + if (!Validation.isEmpty(input)) { + date = input.datepicker('getDate'); + + if (adjust4DayLightSavings) { + formatDateDayLightSavingsTime(date); + } + } + + return date; +} + +function formatDateDayLightSavingsTime(date) { + // JSON.stringify removes hour delta for daylight savings + // e.g. 13/11/2023 01:00:00 goes to 13/11/2023 00:00:00 + // this adds an hour so it becomes the correct time when stringified + if (!Validation.isEmpty(date)) { + date.setTime(date.getTime() - date.getTimezoneOffset() * 60 * 1000) + } +} +*/ +function convertJSONDateString2Date(dateStr) { + if (Validation.isEmpty(dateStr)) return null; + if (dateStr instanceof Date) return dateStr; + return new Date(parseInt(dateStr.substr(6))); +} + +function convertDDMMYYYYString2Date(dateStr, adjust4DayLightSavings) { + var date = null; + + if (!Validation.isEmpty(dateStr)) { + if (dateStr instanceof Date) { + date = dateStr; + } + else { + var dateParts = dateStr.split('-'); + + if (dateParts.length == 3) { + date = new Date(dateParts[2], dateParts[1] - 1, dateParts[0]); + } + } + + if (adjust4DayLightSavings && !Validation.isEmpty(date)) { + formatDateDayLightSavingsTime(date); + } + } + + return date; +} + +function convertDate2DDMMYYYYString(date) { + if (Validation.isEmpty(date)) return ''; + + try { + var dd = date.getDate(); + var mm = date.getMonth() + 1; + var yyyy = date.getFullYear(); + + if (dd < 10) dd = '0' + dd; + if (dd < 10) mm = '0' + mm; + + return dd + '-' + mm + '-' + yyyy; + } + catch (err) { + return 'Formatting error'; + } +} diff --git a/static/js/components/common/inputs/select.js b/static/js/components/common/inputs/select.js new file mode 100644 index 0000000..dbc0ec6 --- /dev/null +++ b/static/js/components/common/inputs/select.js @@ -0,0 +1,14 @@ + + +function handleSelectCollapse(elementSelect) { + let optionSelected = document.querySelectorAll(elementSelect).querySelector('option:selected'); + optionSelected.text(optionSelected.getAttribute(attrTextCollapsed)); + optionSelected.classList.remove(flagExpanded); + optionSelected.classList.add(flagCollapsed); +} +function handleSelectExpand(elementSelect) { + let optionSelected = document.querySelectorAll(elementSelect).querySelector('option:selected'); + optionSelected.text(optionSelected.getAttribute(attrTextExpanded)); + optionSelected.classList.remove(flagCollapsed); + optionSelected.classList.add(flagExpanded); +} \ No newline at end of file diff --git a/static/js/components/common/inputs/textarea.js b/static/js/components/common/inputs/textarea.js new file mode 100644 index 0000000..b437fd1 --- /dev/null +++ b/static/js/components/common/inputs/textarea.js @@ -0,0 +1,45 @@ + +import Common from "../../../lib/common.js"; +import Validation from "../../../lib/validation.js"; + +export default class TextArea { + removeBlankTextAreaLines(textarea) { + textarea.val(textarea.val.replace(/(?:(?:\r\n|\r|\n)\s*){2}/gm, '')); + } + + fitTextAreasToContent(parent) { + var textareas = parent.querySelector('textarea'); + + if (!Validation.isEmpty(textareas)) { + for (var t = 0; t < textareas.length; t++) { + fitTextAreaToContent(document.querySelectorAll(textareas[t])); + } + } + } + + fitTextAreaToContent(textarea) { + // Trim new text + var txtNew = textarea.val().trim(); + textarea.val(txtNew); + + var elTextarea = textarea[0]; + + // Clear style height and set rows = 1 + elTextarea.style.removeProperty('height'); + textarea.getAttribute('rows', 1); + + const paddingTop = Common.parseFloatWithDefault(textarea.style.paddingTop); + const paddingBottom = Common.parseFloatWithDefault(textarea.style.paddingBottom); + const borderTop = Common.parseFloatWithDefault(textarea.style.borderTop); + const borderBottom = Common.parseFloatWithDefault(textarea.style.borderBottom); + let heightDelta = paddingTop + paddingBottom + borderTop + borderBottom; + let heightNew = elTextarea.scrollHeight + heightDelta; + + // If new height is less than 1 linem default to single line height + const heightSingleLine = Common.parseFloatWithDefault(textarea.style.heightSingleLine) + heightDelta; + if (heightNew < heightSingleLine) heightNew = heightSingleLine; + + elTextarea.style.height = heightNew + 'px'; + } +} + diff --git a/static/js/components/common/table.js b/static/js/components/common/table.js new file mode 100644 index 0000000..adba505 --- /dev/null +++ b/static/js/components/common/table.js @@ -0,0 +1,21 @@ + +import Validation from "../../lib/validation.js"; + + +export default class Table { + getDataTableCellByNode(table, elRow, indexColumn) { + // normal jQuery selector won't pick up hidden columns + return document.querySelectorAll(table.DataTable().cells(elRow, indexColumn, null).nodes()); + } + + outputTableElementDateInput(table, elRow, indexColumn, value) { + + let currentCell = getDataTableCellByNode(table, elRow, indexColumn); + + let dateTxt = ''; + + if (!Validation.isEmpty(value)) { + if (typeof value === 'string') value = convertJSONDateString2Date(value); + } + } +} diff --git a/static/js/components/common/temporary/overlay_confirm.js b/static/js/components/common/temporary/overlay_confirm.js new file mode 100644 index 0000000..da3fe69 --- /dev/null +++ b/static/js/components/common/temporary/overlay_confirm.js @@ -0,0 +1,26 @@ + +import Events from "../../../lib/events.js"; + +export default class OverlayConfirm { + static hookup(callbackSuccess) { + Events.initialiseEventHandler(idOverlayConfirm + ' button.' + flagCancel, flagInitialised, (buttonCancel) => { + buttonCancel.addEventListener('click', () => { + let overlay = document.querySelector(idOverlayConfirm); + overlay.style.visibility = 'hidden'; + }); + }); + Events.initialiseEventHandler(idOverlayConfirm + ' button.' + flagSubmit, flagInitialised, (buttonConfirm) => { + buttonConfirm.addEventListener('click', () => { + let overlay = document.querySelector(idOverlayConfirm); + let textarea = overlay.querySelector('textarea'); + overlay.style.visibility = 'hidden'; + callbackSuccess(textarea.value); + }); + }); + } + static show() { + let overlay = document.querySelector(idOverlayConfirm); + overlay.classList.remove(flagCollapsed); + overlay.style.visibility = 'visible'; + } +} \ No newline at end of file diff --git a/static/js/components/common/temporary/overlay_error.js b/static/js/components/common/temporary/overlay_error.js new file mode 100644 index 0000000..4c01d76 --- /dev/null +++ b/static/js/components/common/temporary/overlay_error.js @@ -0,0 +1,19 @@ + +import Events from "../../../lib/events.js"; + +export default class OverlayError { + static hookup() { + Events.initialiseEventHandler(idOverlayError + ' button.' + flagCancel, flagInitialised, (buttonCancel) => { + buttonCancel.addEventListener('click', () => { + let overlay = document.querySelector(idOverlayError); + overlay.style.visibility = 'hidden'; + }); + }); + } + static show(msgError) { + let overlay = document.querySelector(idOverlayError); + let labelError = overlay.querySelector(idLabelError); + labelError.innerText = msgError; + overlay.style.visibility = 'visible'; + } +} \ No newline at end of file diff --git a/static/js/components/common/video.js b/static/js/components/common/video.js new file mode 100644 index 0000000..b283f43 --- /dev/null +++ b/static/js/components/common/video.js @@ -0,0 +1,15 @@ + +import Utils from '../../lib/utils.js'; + +function videoPlay(elemVideo) { + if (!_loading) { // elemVideo.paused && + elemVideo.play(); + Utils.consoleLogIfNotProductionEnvironment("Playing video element: " + elemVideo.name); + } +} + +function videoPause(elemVideo) { + elemVideo.pause(); + Utils.consoleLogIfNotProductionEnvironment("Pausing video element: " + elemVideo.name); +} + diff --git a/static/js/dom.js b/static/js/dom.js new file mode 100644 index 0000000..8907d40 --- /dev/null +++ b/static/js/dom.js @@ -0,0 +1,216 @@ + +import Utils from "./lib/utils.js"; +import Validation from "./lib/validation.js"; + +export default class DOM { + static setElementAttributesValuesCurrentAndPrevious(element, data) { + DOM.setElementAttributeValueCurrent(element, data); + DOM.setElementAttributeValuePrevious(element, data); + } + static setElementAttributeValueCurrent(element, data) { + element.setAttribute(attrValueCurrent, data); + } + static setElementAttributeValuePrevious(element, data) { + element.setAttribute(attrValuePrevious, data); + } + static setElementValuesCurrentAndPrevious(element, data) { + DOM.setElementValueCurrent(element, data); + DOM.setElementAttributeValuePrevious(element, data); + } + static setElementValueCurrent(element, data) { + DOM.setElementAttributeValueCurrent(element, data); + if (element.type === "checkbox") { + element.checked = data; + } + else if (element.tagName === 'INPUT' || element.tagName === 'TEXTAREA' || element.tagName === 'SELECT') { + element.value = data; + } + else { + element.textContent = data; + } + } + static setElementValueCurrentIfEmpty(element, data) { + if (Validation.isEmpty(DOM.getElementValueCurrent(element))) { + DOM.setElementValueCurrent(element, data); + } + } + static getCellFromElement(element) { + return element.closest('td'); + } + static getRowFromElement(element, flagRow) { + let selector = Validation.isEmpty(flagRow) ? 'tr' : 'tr.' + flagRow; + return element.closest(selector); + } + static getClosestParent(element, selector) { + let parent = element.parentElement; + while (parent) { + if (parent.matches(selector)) { + return parent; + } + parent = parent.parentElement; + } + return null; + } + static convertForm2JSON(elementForm) { + let dataForm = {}; + if (Validation.isEmpty(elementForm)) { + return dataForm; + } + let containersFilter = elementForm.querySelectorAll('.' + flagContainerInput + '.' + flagFilter); + let containerFilter, labelFilter, keyFilter, filter; + for (let indexFilter = 0; indexFilter < containersFilter.length; indexFilter++) { + containerFilter = containersFilter[indexFilter]; + labelFilter = containerFilter.querySelector('label'); + keyFilter = labelFilter.getAttribute('for'); + filter = containerFilter.querySelector(`#${keyFilter}`); + dataForm[keyFilter] = DOM.getElementValueCurrent(filter); + } + return dataForm; + } + static loadPageBody(contentNew) { + let pageBody = document.querySelector(idPageBody); + pageBody.innerHTML = contentNew; + } + static getHashPageCurrent() { + const hashPageCurrent = document.body.dataset.page; + return hashPageCurrent; + } + static updateAndCheckIsElementDirty(element) { + element.setAttribute(attrValueCurrent, DOM.getElementValueCurrent(element)); + return DOM.isElementDirty(element); + } + static isElementDirty(element) { + let isDirty = element.getAttribute(attrValuePrevious) != element.getAttribute(attrValueCurrent); + DOM.handleDirtyElement(element, isDirty); + return isDirty; + } + static handleDirtyElement(element, isDirty) { + DOM.toggleElementHasClassnameFlag(element, isDirty, flagDirty); + } + static toggleElementHasClassnameFlag(element, elementHasFlag, flag) { + let elementAlreadyHasFlag = element.classList.contains(flag); + if (elementHasFlag == elementAlreadyHasFlag) return; + if (elementHasFlag) { + element.classList.add(flag); + } else { + element.classList.remove(flag); + } + } + static hasDirtyChildrenContainer(container) { + if (container == null) return false; + return container.querySelector('.' + flagDirty) != null; + } + static hasDirtyChildrenNotDeletedContainer(container) { + if (container == null || container.classList.contains(flagDelete)) return false; + return container.querySelector('.' + flagDirty + ':not(.' + flagDelete + ', .' + flagDelete + ' *)') != null; + } + static getElementValueCurrent(element) { + let returnVal = ''; + + if (!Validation.isEmpty(element)) { + + if (element.type === "checkbox") { + returnVal = element.checked; + } + /* + else if (element.classList.contains(flagIsDatePicker)) { + returnVal = getDatePickerDate(element, adjust4DayLightSavings); + } + */ + else if (element.tagName === 'INPUT' || element.tagName === 'TEXTAREA' || element.tagName === 'SELECT') { + returnVal = element.value; + } + else if (element.tagName === 'BUTTON' && element.classList.contains(flagActive)) { + returnVal = element.classList.contains(flagDelete); + } + else if (element.tagName === 'TD') { + returnVal = DOM.getElementAttributeValueCurrent(element); + } + else { + returnVal = element.textContent; + } + } + + if (Validation.isEmpty(returnVal)) returnVal = ''; + + return returnVal; + } + static getElementAttributeValueCurrent(element) { + debugger; + if (Validation.isEmpty(element)) return null; + return element.getAttribute(attrValueCurrent); + } + static getElementAttributeValuePrevious(element) { + if (Validation.isEmpty(element)) return null; + return element.getAttribute(attrValuePrevious); + } + /* base_table.handleChangeElementCellTable + static updateAndCheckIsTableElementDirty(element) { + let wasDirty = DOM.isElementDirty(element); + let row = DOM.getRowFromElement(element); + let wasDirtyRow = DOM.hasDirtyChildrenNotDeletedContainer(row); + let isDirty = DOM.updateAndCheckIsElementDirty(element); + let cell = DOM.getCellFromElement(element); + Utils.consoleLogIfNotProductionEnvironment({element, row, cell, isDirty, wasDirty}); + if (isDirty != wasDirty) { + DOM.handleDirtyElement(cell, isDirty); + let isDirtyRow = DOM.hasDirtyChildrenNotDeletedContainer(row); + Utils.consoleLogIfNotProductionEnvironment({isDirtyRow, wasDirtyRow}); + if (isDirtyRow != wasDirtyRow) { + DOM.handleDirtyElement(row, isDirtyRow); + } + } + } + */ + static scrollToElement(parent, element) { + // REQUIRED: parent has scroll-bar + parent.scrollTop(parent.scrollTop() + (element.offset().top - parent.offset().top)); + } + static isElementInContainer(container, element) { + + if (typeof jQuery === 'function') { + if (container instanceof jQuery) container = container[0]; + if (element instanceof jQuery) element = element[0]; + } + + var containerBounds = container.getBoundingClientRect(); + var elementBounds = element.getBoundingClientRect(); + + return ( + containerBounds.top <= elementBounds.top && + containerBounds.left <= elementBounds.left && + ((elementBounds.top + elementBounds.height) <= (containerBounds.top + containerBounds.height)) && + ((elementBounds.left + elementBounds.width) <= (containerBounds.left + containerBounds.width)) + ); + } + static alertError(errorType, errorText) { + alert(errorType + '\n' + errorText); + } + static createOptionUnselectedProductVariation() { + return { + [flagProductVariationType]: { + [flagNameAttrOptionText]: [flagName], + [flagNameAttrOptionValue]: [attrIdProductVariationType], + [flagName]: 'Select Variation Type', + [attrIdProductVariationType]: 0, + }, + [flagProductVariation]: { + [flagNameAttrOptionText]: [flagName], + [flagNameAttrOptionValue]: [attrIdProductVariation], + [flagName]: 'Select Variation', + [attrIdProductVariation]: 0, + }, + }; + } + static createOption(optionJson) { + if (Validation.isEmpty(optionJson)) optionJson = { + text: 'Select', + value: 0, + }; + let option = document.createElement('option'); + option.value = optionJson.value; + option.textContent = optionJson.text; + option.selected = optionJson.selected; + return option; + } +} diff --git a/static/js/lib/business_objects/business_objects.js b/static/js/lib/business_objects/business_objects.js new file mode 100644 index 0000000..9566a18 --- /dev/null +++ b/static/js/lib/business_objects/business_objects.js @@ -0,0 +1,29 @@ + +import Utils from '../utils.js'; + +export default class BusinessObjects { + static getOptionJsonFromObjectJsonAndKeys(objectJson, keyText, keyValue, valueSelected = null) { + return { + text: objectJson[keyText], + value: objectJson[keyValue], + selected: (objectJson[keyValue] == valueSelected), + }; + } + static getOptionJsonFromObjectJson(objectJson, valueSelected = null) { + let keyText = objectJson[flagNameAttrOptionText]; + let keyValue = objectJson[flagNameAttrOptionValue]; + Utils.consoleLogIfNotProductionEnvironment({objectJson, keyText, keyValue}); + return BusinessObjects.getOptionJsonFromObjectJsonAndKeys(objectJson, keyText, keyValue, valueSelected); + } + static getObjectText(objectJson) { + return objectJson == null ? '' : objectJson[objectJson[flagNameAttrOptionText]]; + } + static getListObjectsFromIdDictAndCsv(idDict, idCsv) { + let listObjects = []; + let ids = idCsv.split(','); + for (let id of ids) { + listObjects.push(idDict[id]); + } + return listObjects; + } +} \ No newline at end of file diff --git a/static/js/lib/business_objects/store/product_permutation.js b/static/js/lib/business_objects/store/product_permutation.js new file mode 100644 index 0000000..ee5323d --- /dev/null +++ b/static/js/lib/business_objects/store/product_permutation.js @@ -0,0 +1,52 @@ + + +export default class ProductPermutation { + static getProductVariationsFromIdCsv(csvVariations) { + let productVariations = []; + if (!csvVariations) return productVariations; + let variationPairs = csvVariations.split(','); + if (variationPairs.length == 0) return productVariations; + let parts; + variationPairs.forEach((variationPair) => { + parts = variationPair.split(':'); + if (parts.length == 2) { + let productVariationType = productVariationTypes[parts[0]]; + productVariationType[flagProductVariations].some((productVariation) => { + if (productVariation[attrIdProductVariation] == parts[1]) { + productVariations.push([productVariationType, productVariation]); + return true; + } + return false; + }); + } + }); + return productVariations; + } + static getProductVariationsPreviewFromIdCsv(csvVariations) { + let variationPairs = ProductPermutation.getProductVariationsFromIdCsv(csvVariations); + let preview = ''; + if (variationPairs.length == 0) return preview; + let variationType, variation; + variationPairs.forEach((variationPair) => { + if (preview.length > 0) { + preview += '\n'; + } + variationType = variationPair[0]; + variation = variationPair[1]; + preview += variationType[flagName] + ': ' + variation[flagName]; + }); + return preview; + } + + static getProductVariationsIdCsvFromVariationTypeList(variationTypeList) { + let csvVariations = ''; + if (Validation.isEmpty(variationTypeList)) return csvVariations; + variationTypeList.forEach((variationType) => { + if (csvVariations.length > 0) { + csvVariations += ','; + } + csvVariations += variationType[attrIdProductVariationType] + ':' + variationType[flagProductVariations][0][attrIdProductVariation]; + }); + return csvVariations; + } +} \ No newline at end of file diff --git a/static/js/lib/common.js b/static/js/lib/common.js new file mode 100644 index 0000000..afde6fc --- /dev/null +++ b/static/js/lib/common.js @@ -0,0 +1,46 @@ + +import Validation from "./validation.js"; + +export default class Common { + static parseFloatWithDefault(value, defaultValue = 0.00) { + if (!Validation.isEmpty(value) && Validation.isValidNumber(value, true)) { + return parseFloat(value); + } + return defaultValue; + } + + static allowClick() { + return !document.querySelectorAll("body").classList.contains(_dataLoadingFlag); + } + + static displayOverlay(message, show, force) { + + if (show) { + _overlayLoadingCount += 1; + } + else if (force) { + _overlayLoadingCount = 0; + } + else { + _overlayLoadingCount -= 1; + if (_overlayLoadingCount < 0) _overlayLoadingCount = 0; + } + + var loadingImg = document.querySelectorAll(idImageLoading); + var overlay = document.querySelectorAll(loadingImg.closest("div.overlay")); + + if (_overlayLoadingCount == 0) { + + // Prevent short glimpse of prev. content before switch to new content + // caused by data load but not fully rendered + setTimeout(function() { + overlay.fadeOut(); + }, 100); + } + else if (show && _overlayLoadingCount == 1) { + // only show once + loadingImg.innerHTML = message; + overlay.style.display = ""; + } + } +} \ No newline at end of file diff --git a/static/js/lib/constants.js b/static/js/lib/constants.js new file mode 100644 index 0000000..052a3ed --- /dev/null +++ b/static/js/lib/constants.js @@ -0,0 +1,5 @@ + +const _dataLoadingFlag = 'data-loading' +var _domParser = null; +// var hashPageCurrent; // moved to layout +const keyPublicStripe = 'pk_test_51OGrxlL7BuLKjoMpfpfw7bSmZZK1MhqMoQ5VhW2jUj7YtoEejO4vqnxKPiqTHHuh9U4qqkywbPCSI9TpFKtr4SYH007KHMWs68'; diff --git a/static/js/lib/events.js b/static/js/lib/events.js new file mode 100644 index 0000000..77d52a5 --- /dev/null +++ b/static/js/lib/events.js @@ -0,0 +1,10 @@ + +export default class Events { + static initialiseEventHandler(selectorElement, classInitialised, eventHandler) { + document.querySelectorAll(selectorElement).forEach(function(element) { + if (element.classList.contains(classInitialised)) return; + element.classList.add(classInitialised); + eventHandler(element); + }); + } +} \ No newline at end of file diff --git a/static/js/lib/extras.js b/static/js/lib/extras.js new file mode 100644 index 0000000..e69de29 diff --git a/static/js/lib/local_storage.js b/static/js/lib/local_storage.js new file mode 100644 index 0000000..c62b71e --- /dev/null +++ b/static/js/lib/local_storage.js @@ -0,0 +1,62 @@ + +import Validation from "./validation.js"; + +export default class LocalStorage { +/* +function getPageLocalStorage(pageHash) { + + let ls; + try { + ls = JSON.parse(localStorage.getItem(pageHash)); + } catch { + + } + + if (Validation.isEmpty(ls)) return {} + + return ls; +} +function getPageLocalStorageCurrent() { + + return JSON.parse(localStorage.getItem(hashPageCurrent)); +} + +function setPageLocalStorage(pageHash, newLS) { + + localStorage.setItem(pageHash, JSON.stringify(newLS)); +} + +function clearPageLocalStorage(pageHash) { + localStorage.removeItem(pageHash); +} + +function setupPageLocalStorage(pageHash) { + + let ls = getPageLocalStorage(pageHash); + + if (Validation.isEmpty(ls)) ls = {}; + + setPageLocalStorage(pageHash, ls); +} +*/ + + static getLocalStorage(key) { + return JSON.parse(localStorage.getItem(key)); + } + + static setLocalStorage(key, newLS) { + localStorage.setItem(key, JSON.stringify(newLS)); + } + +/* +function setupPageLocalStorageNext(pageHashNext) { + let lsOld = getPageLocalStorage(hashPageCurrent); + hashPageCurrent = pageHashNext; + clearPageLocalStorage(hashPageCurrent); + setupPageLocalStorage(hashPageCurrent); + let lsNew = getPageLocalStorage(hashPageCurrent); + lsNew[keyBasket] = (keyBasket in lsOld) ? lsOld[keyBasket] : {'items': []}; + setPageLocalStorage(hashPageCurrent, lsNew); +} +*/ +} \ No newline at end of file diff --git a/static/js/lib/utils.js b/static/js/lib/utils.js new file mode 100644 index 0000000..3c9ca2b --- /dev/null +++ b/static/js/lib/utils.js @@ -0,0 +1,24 @@ +// Utility functions +/* +function $(selector) { + return document.querySelector(selector); +} + +function $$(selector) { + return document.querySelectorAll(selector); +} +*/ +export default class Utils { + static getListFromDict(dict) { + let list = []; + for (let key in dict) { + list.push(dict[key]); + } + return list; + } + static consoleLogIfNotProductionEnvironment(message) { + if (!environment.is_production) { + console.log(message); + } + } +} \ No newline at end of file diff --git a/static/js/lib/validation.js b/static/js/lib/validation.js new file mode 100644 index 0000000..c5d2271 --- /dev/null +++ b/static/js/lib/validation.js @@ -0,0 +1,158 @@ + +export default class Validation { + /* + isNullOrWhitespace(v) { + let txt = JSON.stringify(v).replace('/\s\g', ''); + return (txt == '' || 'null'); + } + */ + + static isEmpty(object) { + + let isEmpty = true; + + if (object !== null && object !== "null" && object !== undefined && object !== "undefined") { + + if (object.length == undefined) { + isEmpty = false; // object exists but isn't a collection + } + else if (typeof object === "function") { + isEmpty = false; // object is reference + } + else { // string or collection + + let isString = (typeof object == "string"); + + if (isString) object = object.trim(); + + if (object.length > 0) { + + if (isString) { + isEmpty = false; // String greater than length 0 + } + else { + + if (typeof object[0] != "string") { + isEmpty = false; + } + else { + for(let i = 0; i < object.length; i++) { + if (object[i] != "") { + isEmpty = false; + break + } + } + } + } + } + } + } + + return isEmpty; + } + + static isValidNumber(value, positiveOnly) { + return !Validation.isEmpty(value) && !isNaN(value) && (!positiveOnly || parseFloat(value) > 0); + } + + static getDataContentType(params) { + + var data = null; + var contentType = ''; + + if (!Validation.isEmpty(params)) { + + if (typeof params === "string") { + data = params; + contentType = "application/x-www-form-urlencoded; charset=UTF-8"; + } + else { + data = JSON.stringify(params); + contentType = "application/json; charset=UTF-8"; + } + } + + return { Data: data, ContentType: contentType }; + } + + static arrayContainsItem(array, itemValue) { + + var hasItem = false; + + if (!Validation.isEmpty(array) && !Validation.isEmpty(itemValue)) { + + var isJQueryElementArray = array[0] instanceof jQuery; + + if (isJQueryElementArray) { + + for (let i = 0; i < array.length; i++) { + + if (document.querySelectorAll(array[i]).is(itemValue)) { + hasItem = true; + break; + } + } + } + else { + + var isDate = array[0] instanceof Date; + + if (isDate) { + + for (let i = 0; i < array.length; i++) { + + if (array[i].getTime() === itemValue.getTime()) { + hasItem = true; + break; + } + } + } + else { + + for (let i = 0; i < array.length; i++) { + + if (array[i] == itemValue) { + hasItem = true; + break; + } + } + } + } + } + + return hasItem; + } + + static dictHasKey(d, k) { + return (k in d); + } + static areEqualDicts(dict1, dict2) { + const keys1 = Object.keys(dict1); + const keys2 = Object.keys(dict2); + + if (keys1.length !== keys2.length) { + return false; + } + + for (let key of keys1) { + if (dict1[key] !== dict2[key]) { + return false; + } + } + + return true; + } + + static imageExists(url, callback) { + + var img = new Image(); + + img.onload = function() { callback(true); }; + img.onerror = function() { callback(false); }; + img.src = url; + } + + static toFixedOrDefault(value, decimalPlaces, defaultValue = null) { + return Validation.isValidNumber(value) ? parseFloat(value).toFixed(decimalPlaces) : defaultValue; + } +} diff --git a/static/js/pages/base.js b/static/js/pages/base.js new file mode 100644 index 0000000..e6e24f1 --- /dev/null +++ b/static/js/pages/base.js @@ -0,0 +1,123 @@ + +import BusinessObjects from "../lib/business_objects/business_objects.js"; +import Events from "../lib/events.js"; +import LocalStorage from "../lib/local_storage.js"; +import API from "../api.js"; +import DOM from "../dom.js"; +import Utils from "../lib/utils.js"; + +import OverlayConfirm from "../components/common/temporary/overlay_confirm.js"; +import OverlayError from "../components/common/temporary/overlay_error.js"; + +export default class BasePage { + constructor(router) { + if (!router) { + throw new Error("Router is required"); + } + else { + Utils.consoleLogIfNotProductionEnvironment("initialising with router: ", router); + } + this.router = router; + this.title = titlePageCurrent; + if (this.constructor === BasePage) { + throw new Error("Cannot instantiate abstract class"); + } + + if (!this.constructor.hash) { + throw new Error(`Class ${this.constructor.name} must have a static hash attribute.`); + } + } + + initialize() { + throw new Error("Method 'initialize()' must be implemented."); + } + + sharedInitialize() { + this.logInitialisation(); + this.hookupCommonElements(); + } + + logInitialisation() { + Utils.consoleLogIfNotProductionEnvironment('Initializing ' + this.title + ' page'); + } + + hookupCommonElements() { + // hookupVideos(); + this.hookupLogos(); + this.hookupOverlays(); + } + + hookupEventHandler(eventType, selector, callback) { + Events.initialiseEventHandler(selector, flagInitialised, (element) => { + element.addEventListener(eventType, (event) => { + event.stopPropagation(); + callback(event, element); + }); + }); + } + + hookupLogos() { + this.hookupEventHandler("click", "." + flagImageLogo + "," + "." + flagLogo, (event, element) => { + Utils.consoleLogIfNotProductionEnvironment('clicking logo'); + this.router.navigateToHash(hashPageHome); + }); + } + + hookupOverlays() { + this.hookupOverlayFromId(idOverlayConfirm); + this.hookupOverlayFromId(idOverlayError); + } + + hookupOverlayFromId(idOverlay) { + Events.initialiseEventHandler(idOverlay, flagInitialised, (overlay) => { + overlay.querySelector('button.' + flagCancel).addEventListener("click", (event) => { + event.stopPropagation(); + overlay.style.display = 'none'; + }); + }); + } + + hookupButtonSave() { + Events.initialiseEventHandler('form.' + flagFilter + ' button.' + flagSave, flagInitialised, (button) => { + button.addEventListener("click", (event) => { + event.stopPropagation(); + Utils.consoleLogIfNotProductionEnvironment('saving page: ', this.title); + OverlayConfirm.show(); + }); + }); + } + + leave() { + Utils.consoleLogIfNotProductionEnvironment('Leaving ' + this.title + ' page'); + if (this.constructor === BasePage) { + throw new Error("Must implement leave() method."); + } + } + setLocalStoragePage(dataPage) { + LocalStorage.setLocalStorage(this.hash, dataPage); + } + getLocalStoragePage() { + return LocalStorage.getLocalStorage(this.hash); + } + + toggleShowButtonsSaveCancel(show) { // , buttonSave = null, buttonCancel = null + let buttonSave = document.querySelector('form.' + flagFilter + ' button.' + flagSave); + let buttonCancel = document.querySelector('form.' + flagFilter + ' button.' + flagCancel); + if (show) { + buttonCancel.classList.remove(flagCollapsed); + buttonSave.classList.remove(flagCollapsed); + Utils.consoleLogIfNotProductionEnvironment('showing buttons'); + } else { + buttonCancel.classList.add(flagCollapsed); + buttonSave.classList.add(flagCollapsed); + Utils.consoleLogIfNotProductionEnvironment('hiding buttons'); + } + } + + static isDirtyFilter(filter) { + let isDirty = DOM.updateAndCheckIsElementDirty(filter); + if (isDirty) document.querySelectorAll(idTableMain + ' tbody tr').remove(); + return isDirty; + } + +} \ No newline at end of file diff --git a/static/js/pages/base_table.js b/static/js/pages/base_table.js new file mode 100644 index 0000000..d1808b5 --- /dev/null +++ b/static/js/pages/base_table.js @@ -0,0 +1,553 @@ + +import BusinessObjects from "../lib/business_objects/business_objects.js"; +import Events from "../lib/events.js"; +import LocalStorage from "../lib/local_storage.js"; +import Validation from "../lib/validation.js"; +import BasePage from "./base.js"; +import API from "../api.js"; +import DOM from "../dom.js"; +import Utils from "../lib/utils.js"; + +import OverlayConfirm from "../components/common/temporary/overlay_confirm.js"; +import OverlayError from "../components/common/temporary/overlay_error.js"; + +export default class TableBasePage extends BasePage { + // static hash + // static attrIdRowObject + // callSaveTableContent + + constructor(router) { + super(router); + this.cursorYInitial = null; + this.rowInitial = null; + this.placeholder = null; + this.dragSrcEl = null; + this.dragSrcRow = null; + + this.hookupTableCellDdls = this.hookupTableCellDdls.bind(this); + } + + initialize(isPopState = false) { + throw new Error("Must implement initialize() method."); + } + sharedInitialize(isPopState = false, isSinglePageApp = false) { + if (!isPopState) { + super.sharedInitialize(); + this.hookupFilters(); + this.hookupButtonsSaveCancel(); + this.hookupTableMain(); + OverlayConfirm.hookup(() => { + if (isSinglePageApp) { + this.saveRecordsTableDirtySinglePageApp(); + } + else { + this.saveRecordsTableDirty(); + } + }); + } else { + let dataPage = this.getLocalStoragePage(); + let filters = dataPage[flagFormFilters]; + let formFilters = this.getFormFilters(); + let filtersDefault = DOM.convertForm2JSON(formFilters); + if (!Validation.areEqualDicts(filters, filtersDefault)) { + this.callFilterTableContent(); + } + } + } + hookupFilters() { + if (this.constructor === TableBasePage) { + throw new Error("Subclass of TableBasePage must implement method hookupFilters()."); + } + } + sharedHookupFilters() { + this.hookupButtonApplyFilters(); + } + hookupFilterActive() { + this.hookupFilter(flagActive); + } + hookupFilter(filterFlag, handler = (event, filter) => { return TableBasePage.isDirtyFilter(filter); }) { + let filterSelector = idFormFilters + ' .' + filterFlag; + this.hookupEventHandler("change", filterSelector, handler); + } + static isDirtyFilter(filter) { + let isDirty = DOM.updateAndCheckIsElementDirty(filter); + if (isDirty) { + let tbody = document.querySelector(idTableMain + ' tbody'); + tbody.querySelectorAll('tr').remove(); + tbody.appendChild(document.createElement('
Press "Apply Filters" to refresh the table.
')); + } + return isDirty; + } + hookupFilterIsNotEmpty() { + this.hookupFilter(flagIsNotEmpty); + } + hookupButtonApplyFilters() { + this.hookupEventHandler("click", idButtonApplyFilters, (event, button) => { + event.stopPropagation(); + this.callFilterTableContent(); + }); + } + /* + getAndLoadFilteredTableContent = () => { + this.callFilterTableContent() + .catch(error => console.error('Error:', error)); + } + */ + getFormFilters() { + return document.querySelector(idFormFilters); + } + callFilterTableContent() { + let formFilters = this.getFormFilters(); + let filtersJson = DOM.convertForm2JSON(formFilters); + this.leave(); + API.goToHash(this.constructor.hash, filtersJson); + } + callbackLoadTableContent(response) { + let table = TableBasePage.getTableMain(); + let bodyTable = table.querySelector('tbody'); + bodyTable.querySelectorAll('tr').forEach(function(row) { row.remove(); }); + let rowsJson = response.data[flagRows]; + if (!Validation.isEmpty(rowsJson) && rowsJson.every(row => row.hasOwnProperty('display_order'))) { + rowsJson = rowsJson.sort((a, b) => a.display_order - b.display_order); + } + rowsJson.forEach(this.loadRowTable.bind(this)); + this.hookupTableMain(); + } + static getTableMain() { + return document.querySelector(idTableMain); + } + loadRowTable(rowJson) { + throw new Error("Subclass of TableBasePage must implement method loadRowTable()."); + } + getAndLoadFilteredTableContentSinglePageApp() { + this.callFilterTableContent() + .then(data => { + Utils.consoleLogIfNotProductionEnvironment('Table data received:', data); + this.callbackLoadTableContent(data); + }) + .catch(error => console.error('Error:', error)); + } + hookupButtonsSaveCancel() { + this.hookupButtonSave(); + this.hookupButtonCancel(); + this.toggleShowButtonsSaveCancel(false); + } + saveRecordsTableDirty() { + let records = this.getTableRecords(true); + if (records.length == 0) { + OverlayError.show('No records to save'); + return; + } + let formElement = this.getFormFilters(); + let comment = DOM.getElementValueCurrent(document.querySelector(idTextareaConfirm)); + this.callSaveTableContent(records, formElement, comment) + .then(data => { + if (data[flagStatus] == flagSuccess) { + if (_verbose) { + Utils.consoleLogIfNotProductionEnvironment('Records saved!'); + Utils.consoleLogIfNotProductionEnvironment('Data received:', data); + } + this.callFilterTableContent(); + } + else { + Utils.consoleLogIfNotProductionEnvironment("error: ", data[flagMessage]); + OverlayError.show(data[flagMessage]); + } + }) + .catch(error => console.error('Error:', error)); + } + getTableRecords(dirtyOnly = false) { + let records = []; + let record; + document.querySelectorAll(idTableMain + ' > tbody > tr').forEach((row) => { + if (dirtyOnly && !DOM.hasDirtyChildrenContainer(row)) return; + record = this.getJsonRow(row); + records.push(record); + }); + return records; + } + getJsonRow(row) { + throw new Error("Subclass of TableBasePage must implement method getJsonRow()."); + } + saveRecordsTableDirtySinglePageApp() { + let records = this.getTableRecords(true); + if (records.length == 0) { + OverlayError.show('No records to save'); + return; + } + let formElement = this.getFormFilters(); + let comment = DOM.getElementValueCurrent(document.querySelector(idTextareaConfirm)); + this.callSaveTableContent(records, formElement, comment) + .then(data => { + if (data[flagStatus] == flagSuccess) { + if (_verbose) { + Utils.consoleLogIfNotProductionEnvironment('Records saved!'); + Utils.consoleLogIfNotProductionEnvironment('Data received:', data); + } + this.callbackLoadTableContent(data); + } + else { + Utils.consoleLogIfNotProductionEnvironment("error: ", data[flagMessage]); + OverlayError.show(data[flagMessage]); + } + }) + .catch(error => console.error('Error:', error)); + } + hookupButtonCancel() { + Events.initialiseEventHandler(idFormFilters + ' button.' + flagCancel, flagInitialised, (button) => { + button.addEventListener("click", (event) => { + event.stopPropagation(); + this.callFilterTableContent(); + }); + button.classList.add(flagCollapsed); + }); + } + handleClickAddRowTable(event, button) { + event.stopPropagation(); + _rowBlank.setAttribute(this.constructor.attrIdRowObject, -1 - _rowBlank.getAttribute(this.constructor.attrIdRowObject)); + let tbody = document.querySelector(idTableMain + ' tbody'); + let row = _rowBlank.cloneNode(true); + row.classList.remove(flagInitialised); + row.querySelectorAll('.' + flagInitialised).forEach(function(element) { + element.classList.remove(flagInitialised); + }); + let countRows = document.querySelectorAll(idTableMain + ' > tbody > tr').length; + row.setAttribute(this.constructor.attrIdRowObject, -1 - countRows); + this.initialiseRowNew(tbody, row); + tbody.appendChild(row); + this.hookupTableMain(); + } + initialiseRowNew(tbody, row) { + if (this.constructor === TableBasePage) { + throw new Error("Subclass of TableBasePage must implement method initialiseRowNew()."); + } + row.classList.remove(flagRowNew); + } + hookupTableMain() { + if (this.constructor === TableBasePage) { + throw new Error("Must implement hookupTableMain() method."); + } + if (true) { // _rowBlank == null) { + Events.initialiseEventHandler(idTableMain, flagInitialised, (table) => { + this.cacheRowBlank(); + }); + } + } + cacheRowBlank() { + let selectorRowNew = idTableMain + ' tbody tr.' + flagRowNew; + let rowBlankTemp = document.querySelector(selectorRowNew); + Utils.consoleLogIfNotProductionEnvironment("row blank temp: ", rowBlankTemp); + let countRows = document.querySelectorAll(idTableMain + ' > tbody > tr').length; + _rowBlank = rowBlankTemp.cloneNode(true); + document.querySelectorAll(selectorRowNew).forEach(function(row) { + row.remove(); + }); + _rowBlank.setAttribute(this.constructor.attrIdRowObject, -1 - countRows); + } + initialiseSliderDisplayOrderRowNew(tbody, row) { + // let tdSelector = ':scope > tr > td.' + flagDisplayOrder; + // let tbody = document.querySelector('table' + (Validation.isEmpty(flagTable) ? '' : '.' + flagTable) + ' > tbody'); + let slidersDisplayOrder = tbody.querySelectorAll(':scope > tr > td.' + flagDisplayOrder + ' input.' + flagSlider); + let maxDisplayOrder = 0; + slidersDisplayOrder.forEach((slider) => { + maxDisplayOrder = Math.max(maxDisplayOrder, parseFloat(DOM.getElementValueCurrent(slider))); + }); + let sliderDisplayOrder = row.querySelector('td.' + flagDisplayOrder + ' .' + flagSlider); + DOM.setElementValuesCurrentAndPrevious(sliderDisplayOrder, maxDisplayOrder + 1); + } + hookupSlidersDisplayOrderTable() { + let selectorDisplayOrder = idTableMain + ' tbody tr td.' + flagDisplayOrder + ' input.' + flagSlider + '.' + flagDisplayOrder; + this.hookupChangeHandlerTableCells(selectorDisplayOrder); + } + hookupChangeHandlerTableCells(inputSelector, handler = (event, element) => { this.handleChangeNestedElementCellTable(event, element); }) { + Events.initialiseEventHandler(inputSelector, flagInitialised, (input) => { + input.addEventListener("change", (event) => { + handler(event, input); + }); + handler(null, input); + }); + } + /* + handleChangeElementCellTable(event, element) { + let row = DOM.getRowFromElement(element); + let td = DOM.getCellFromElement(element); + let wasDirtyRow = DOM.hasDirtyChildrenContainer(row); + let wasDirtyElement = element.classList.contains(flagDirty); + let isDirtyElement = DOM.updateAndCheckIsElementDirty(element); + if (isDirtyElement != wasDirtyElement) { + DOM.handleDirtyElement(td, isDirtyElement); + let isNowDirtyRow = DOM.hasDirtyChildrenContainer(row); + if (isNowDirtyRow != wasDirtyRow) { + DOM.handleDirtyElement(row, isNowDirtyRow); + let rows = this.getTableRecords(true); + let existsDirtyRecord = rows.length > 0; + this.toggleShowButtonsSaveCancel(existsDirtyRecord); + } + } + } + handleChangeElementNestedCellTable(event, element, flagColumnList = [], orderNesting = 1) { + let orderNestingTemp = orderNesting; + let row, td, nestedRowSelector; + while (orderNestingTemp > 0) { + nestedRowSelector = idTableMain; + for (let indexOrderNesting = 0; indexOrderNesting < orderNestingTemp; indexOrderNesting++) { + nestedRowSelector += ' tbody tr'; + } + row = DOM.getClosestParent(element, nestedRowSelector); + td = row.querySelector('td.' + flag); + } + let row = DOM.getRowFromElement(element); + let td = DOM.getCellFromElement(element); + let wasDirtyRow = DOM.hasDirtyChildrenContainer(row); + let wasDirtyElement = element.classList.contains(flagDirty); + let isDirtyElement = DOM.updateAndCheckIsElementDirty(element); + if (isDirtyElement != wasDirtyElement) { + DOM.handleDirtyElement(td, isDirtyElement); + let isNowDirtyRow = DOM.hasDirtyChildrenContainer(row); + if (isNowDirtyRow != wasDirtyRow) { + DOM.handleDirtyElement(row, isNowDirtyRow); + let rows = this.getTableRecords(true); + let existsDirtyRecord = rows.length > 0; + this.toggleShowButtonsSaveCancel(existsDirtyRecord); + } + } + } + handleChangeElementSubtableCell(event, element, flagFieldSubtable) { + let rowSubtable = element.closest(idTableMain + ' td.' + flagFieldSubtable + ' tbody tr'); + let rowTable = rowSubtable.closest(idTableMain + ' > tbody > tr'); + let td = DOM.getCellFromElement(element); + // let tdSubtable = td.closest('td.' + flagFieldSubtable); + let wasDirtyRowSubtable = DOM.hasDirtyChildrenContainer(rowSubtable); + let wasDirtyRowTable = DOM.hasDirtyChildrenContainer(rowTable); + let wasDirtyElement = element.classList.contains(flagDirty); + let isDirtyElement = DOM.updateAndCheckIsElementDirty(element); + Utils.consoleLogIfNotProductionEnvironment({isDirtyElement, wasDirtyElement}); + if (isDirtyElement != wasDirtyElement) { + DOM.handleDirtyElement(td, isDirtyElement); + let isNowDirtyRowSubtable = DOM.hasDirtyChildrenContainer(rowSubtable); + Utils.consoleLogIfNotProductionEnvironment({isNowDirtyRowSubtable, wasDirtyRowSubtable}); + if (isNowDirtyRowSubtable != wasDirtyRowSubtable) { + DOM.handleDirtyElement(rowSubtable, isNowDirtyRowSubtable); + let isNowDirtyRowTable = DOM.hasDirtyChildrenContainer(rowTable); + Utils.consoleLogIfNotProductionEnvironment({isNowDirtyRowTable, wasDirtyRowTable}); + if (isNowDirtyRowTable != wasDirtyRowTable) { + DOM.handleDirtyElement(rowTable, isNowDirtyRowTable); + let rows = this.getTableRecords(true); + let existsDirtyRecord = rows.length > 0; + this.toggleShowButtonsSaveCancel(existsDirtyRecord); + } + } + } + } + */ + handleChangeNestedElementCellTable(event, element) { + let wasDirtyParentRows = this.getAllIsDirtyRowsInParentTree(element); + let wasDirtyElement = element.classList.contains(flagDirty); + let isDirtyElement = DOM.updateAndCheckIsElementDirty(element); + Utils.consoleLogIfNotProductionEnvironment({isDirtyElement, wasDirtyElement, wasDirtyParentRows}); + let td = DOM.getCellFromElement(element); + DOM.setElementAttributeValueCurrent(td, DOM.getElementAttributeValueCurrent(element)); + if (isDirtyElement != wasDirtyElement) { + DOM.handleDirtyElement(td, isDirtyElement); + this.updateAndToggleShowButtonsSaveCancel(); + this.cascadeChangedIsDirtyNestedElementCellTable(element, isDirtyElement, wasDirtyParentRows); + } + } + getAllIsDirtyRowsInParentTree(element) { + let rows = []; + let parent = element; + let isDirty; + while (parent) { + if (parent.matches('tr')) { + isDirty = parent.classList.contains(flagDirty) + rows.push(isDirty); + } + parent = parent.parentElement; + } + return rows; + } + cascadeChangedIsDirtyNestedElementCellTable(element, isDirtyElement, wasDirtyParentRows) { + if (Validation.isEmpty(wasDirtyParentRows)) return; + let td = DOM.getCellFromElement(element); + let isDirtyTd = isDirtyElement || DOM.hasDirtyChildrenContainer(tr); + DOM.handleDirtyElement(td, isDirtyTd); + let tr = DOM.getRowFromElement(td); + let isDirtyRow = isDirtyTd || DOM.hasDirtyChildrenContainer(tr); + let wasDirtyRow = wasDirtyParentRows.shift(); + Utils.consoleLogIfNotProductionEnvironment({isDirtyRow, wasDirtyRow}); + if (isDirtyRow != wasDirtyRow) { + DOM.handleDirtyElement(tr, isDirtyRow); + this.updateAndToggleShowButtonsSaveCancel(); + this.cascadeChangedIsDirtyNestedElementCellTable(tr.parentElement, isDirtyRow, wasDirtyParentRows); + } + } + hookupChangeHandlerTableCellsWhenNotCollapsed(inputSelector, handler = (event, element) => { + if (!element.classList.contains(flagCollapsed)) this.handleChangeNestedElementCellTable(event, element); + }) { + this.hookupEventHandler("change", inputSelector, handler); + } + hookupTextareasCodeTable() { + this.hookupChangeHandlerTableCells(idTableMain + ' tbody tr td.' + flagCode + ' textarea'); + } + hookupTextareasNameTable() { + this.hookupChangeHandlerTableCells(idTableMain + ' tbody tr td.' + flagName + ' textarea'); + } + hookupTextareasDescriptionTable() { + this.hookupChangeHandlerTableCells(idTableMain + ' tbody tr td.' + flagDescription + ' textarea'); + } + hookupFieldsActive(flagTable = '', handleClickRowNew = (event, element) => { this.handleClickAddRowTable(event, element); }) { + let selectorButton = 'table' + (Validation.isEmpty(flagTable) ? '' : '.' + flagTable) + ' > tbody > tr > td.' + flagActive + ' button'; + let selectorButtonDelete = selectorButton + '.' + flagDelete; + let selectorButtonUndelete = selectorButton + ':not(.' + flagDelete + ')'; + Utils.consoleLogIfNotProductionEnvironment("hookupFieldsActive: ", selectorButtonDelete, selectorButtonUndelete); + this.hookupButtonsRowDelete(selectorButtonDelete, selectorButtonUndelete); + this.hookupButtonsRowUndelete(selectorButtonDelete, selectorButtonUndelete); + this.hookupEventHandler( + "click" + , 'table' + (Validation.isEmpty(flagTable) ? '' : '.' + flagTable) + ' > thead > tr > th.' + flagActive + ' button' + , (event, button) => { handleClickRowNew(event, button); } + ); + } + hookupButtonsRowDelete(selectorButtonDelete, selectorButtonUndelete, changeHandler = (event, element) => { this.handleChangeNestedElementCellTable(event, element); }) { + this.hookupEventHandler("click", selectorButtonDelete, (event, element) => { + this.handleClickButtonRowDelete(event, element, selectorButtonDelete, selectorButtonUndelete, (changeEvent, changeElement) => { changeHandler(changeEvent, changeElement); }); + }); + } + handleClickButtonRowDelete(event, element, selectorButtonDelete, selectorButtonUndelete, changeHandler = (event, element) => { this.handleChangeNestedElementCellTable(event, element); }) { + let row = DOM.getRowFromElement(element); + if (row.classList.contains(flagRowNew) && !DOM.hasDirtyChildrenContainer(row)) { + row.parentNode.removeChild(row); + } + let buttonAdd = element.cloneNode(false); + buttonAdd.classList.remove(flagInitialised); + buttonAdd.classList.remove(flagDelete); + buttonAdd.classList.add(flagAdd); + buttonAdd.textContent = '+'; + element.replaceWith(buttonAdd); + changeHandler(null, buttonAdd); + this.hookupButtonsRowUndelete(selectorButtonDelete, selectorButtonUndelete, (changeEvent, changeElement) => { changeHandler(changeEvent, changeElement); }); + this.updateAndToggleShowButtonsSaveCancel(); + } + hookupButtonsRowUndelete(selectorButtonDelete, selectorButtonUndelete, changeHandler = (event, element) => { this.handleChangeNestedElementCellTable(event, element); }) { + this.hookupEventHandler("click", selectorButtonUndelete, (event, element) => { + this.handleClickButtonRowUndelete(event, element, selectorButtonDelete, selectorButtonUndelete, (changeEvent, changeElement) => { changeHandler(changeEvent, changeElement); }); + }); + } + handleClickButtonRowUndelete(event, element, selectorButtonDelete, selectorButtonUndelete, changeHandler = (event, element) => { this.handleChangeNestedElementCellTable(event, element); }) { + let buttonDelete = element.cloneNode(false); + buttonDelete.classList.remove(flagInitialised); + buttonDelete.classList.remove(flagAdd); + buttonDelete.classList.add(flagDelete); + buttonDelete.textContent = 'x'; + element.replaceWith(buttonDelete); + changeHandler(null, buttonDelete); + this.hookupButtonsRowDelete(selectorButtonDelete, selectorButtonUndelete, (changeEvent, changeElement) => { changeHandler(changeEvent, changeElement); }); + this.updateAndToggleShowButtonsSaveCancel(); + } + hookupTdsAccessLevel() { + let cellSelector = idTableMain + ' tbody td.' + flagAccessLevel; + this.hookupTableCellDdlPreviews(cellSelector, Utils.getListFromDict(accessLevels)); + } + hookupTableCellDdlPreviews( + cellSelector + , optionList + , ddlHookup = (cellSelector) => { this.hookupTableCellDdls(cellSelector); } + , changeHandler = (event, element) => { this.handleChangeNestedElementCellTable(event, element); } + ) { + this.hookupEventHandler("click", cellSelector, (event, td) => { + this.handleClickTableCellDdlPreview( + event + , td + , optionList + , cellSelector + , (cellSelector) => { ddlHookup( + cellSelector + , (event, element) => { changeHandler(event, element); } + ); } + ); + }); + ddlHookup(cellSelector + ' select'); + } + hookupTableCellDdls(ddlSelector, changeHandler = (event, element) => { this.handleChangeNestedElementCellTable(event, element); }) { + this.hookupEventHandler("change", ddlSelector, (event, element) => { changeHandler(event, element); }); + } + handleClickTableCellDdlPreview(event, td, optionObjectList, cellSelector, ddlHookup = (cellSelector) => { this.hookupTableCellDdls(cellSelector); }) { + if (td.querySelector('select')) return; + let tdNew = td.cloneNode(true); + td.parentNode.replaceChild(tdNew, td); + let idSelected = DOM.getElementAttributeValueCurrent(tdNew); + tdNew.innerHTML = ''; + let ddl = document.createElement('select'); + DOM.setElementValuesCurrentAndPrevious(ddl, idSelected); + let optionJson, option; + if (_verbose) { + Utils.consoleLogIfNotProductionEnvironment("click table cell ddl preview"); + Utils.consoleLogIfNotProductionEnvironment({optionObjectList, cellSelector}); + } + option = DOM.createOption(null); + ddl.appendChild(option); + optionObjectList.forEach((optionObjectJson) => { + optionJson = BusinessObjects.getOptionJsonFromObjectJson(optionObjectJson, idSelected); + option = DOM.createOption(optionJson); + ddl.appendChild(option); + }); + tdNew.appendChild(ddl); + let ddlSelector = cellSelector + ' select'; + ddlHookup(ddlSelector); + } + hookupTableCellDDlPreviewsWhenNotCollapsed(cellSelector, optionList, ddlHookup = (event, element) => { this.hookupTableCellDdls(event, element); }) { + this.hookupEventHandler("click", cellSelector, (event, td) => { + let div = td.querySelector('div'); + if (!div || div.classList.contains(flagCollapsed)) return; + this.handleClickTableCellDdlPreview(event, td, optionList, cellSelector, (event, element) => { ddlHookup(event, element); }); + }); + } + toggleColumnCollapsed(flagColumn, isCollapsed) { + this.toggleColumnHasClassnameFlag(flagColumn, isCollapsed, flagCollapsed); + } + toggleColumnHeaderCollapsed(flagColumn, isCollapsed) { + this.toggleColumnHasClassnameFlag(flagColumn, isCollapsed, flagCollapsed); + } + + createTdActive(isActive) { + let tdActive = document.createElement("td"); + tdActive.classList.add(flagActive); + let buttonActive = document.createElement("button"); + buttonActive.classList.add(flagActive); + buttonActive.classList.add(isActive ? flagDelete : flagAdd); + buttonActive.textContent = isActive ? 'x' : '+'; + DOM.setElementAttributesValuesCurrentAndPrevious(buttonActive, isActive); + tdActive.appendChild(buttonActive); + return tdActive; + } + + leave() { + if (this.constructor === TableBasePage) { + throw new Error("Must implement leave() method."); + } + super.leave(); + let formFilters = this.getFormFilters(); + let dataPage = {}; + dataPage[flagFormFilters] = DOM.convertForm2JSON(formFilters); + this.setLocalStoragePage(dataPage); + } + + toggleColumnHasClassnameFlag(columnFlag, isRequiredFlag, classnameFlag) { + let table = TableBasePage.getTableMain(); + let columnTh = table.querySelector('th.' + columnFlag); + let columnThHasFlag = columnTh.classList.contains(classnameFlag); + if (isRequiredFlag == columnThHasFlag) return; + DOM.toggleElementHasClassnameFlag(columnTh, isRequiredFlag, classnameFlag); + } + toggleColumnHeaderHasClassnameFlag(columnFlag, isRequiredFlag, classnameFlag) { + let table = TableBasePage.getTableMain(); + let columnTh = table.querySelector('th.' + columnFlag); + DOM.toggleElementHasClassnameFlag(columnTh, isRequiredFlag, classnameFlag); + } + + updateAndToggleShowButtonsSaveCancel() { + let records = this.getTableRecords(true); + let existsDirtyRecord = records.length > 0; + this.toggleShowButtonsSaveCancel(existsDirtyRecord); + } +} diff --git a/static/js/pages/core/contact-success.js b/static/js/pages/core/contact-success.js new file mode 100644 index 0000000..877be19 --- /dev/null +++ b/static/js/pages/core/contact-success.js @@ -0,0 +1,16 @@ +// internal +import BasePage from "../base.js"; +// vendor +import { Altcha } from "../../vendor/altcha.js"; + +export default class PageContactSuccess extends BasePage { + static hash = hashPageContactSuccess; + + constructor(router) { + super(router); + } + + initialize() { + this.sharedInitialize(); + } +} diff --git a/static/js/pages/core/contact.js b/static/js/pages/core/contact.js new file mode 100644 index 0000000..39e4653 --- /dev/null +++ b/static/js/pages/core/contact.js @@ -0,0 +1,23 @@ +// internal +import BasePage from "../base.js"; +// vendor +import { Altcha } from "../../vendor/altcha.js"; + +export default class PageContact extends BasePage { + static hash = hashPageContact; + + constructor(router) { + super(router); + } + + initialize() { + this.sharedInitialize(); + this.hookupButtonSubmitFormContactUs(); + } + + hookupButtonSubmitFormContactUs() { + const button = document.querySelector('form input[type="submit"]'); + button.classList.add(flagButton); + button.classList.add(flagButtonPrimary); + } +} diff --git a/static/js/pages/core/home.js b/static/js/pages/core/home.js new file mode 100644 index 0000000..b6e063e --- /dev/null +++ b/static/js/pages/core/home.js @@ -0,0 +1,23 @@ + +// internal +import BasePage from "../base.js"; +// external + + +export default class PageHome extends BasePage { + static hash = hashPageHome; + + constructor(router) { + super(router); + } + + initialize() { + this.sharedInitialize(); + this.hookupButtonsNavContact(); + } + + leave() { + super.leave(); + } +} + diff --git a/static/js/pages/legal/accessibility_report.js b/static/js/pages/legal/accessibility_report.js new file mode 100644 index 0000000..bcca12d --- /dev/null +++ b/static/js/pages/legal/accessibility_report.js @@ -0,0 +1,17 @@ +import BasePage from "../base.js"; + +export default class PageAccessibilityReport extends BasePage { + static hash = hashPageAccessibilityReport; + + constructor(router) { + super(router); + } + + initialize() { + this.sharedInitialize(); + } + + leave() { + super.leave(); + } +} diff --git a/static/js/pages/legal/accessibility_statement.js b/static/js/pages/legal/accessibility_statement.js new file mode 100644 index 0000000..ed282c2 --- /dev/null +++ b/static/js/pages/legal/accessibility_statement.js @@ -0,0 +1,17 @@ +import BasePage from "../base.js"; + +export default class PageAccessibilityStatement extends BasePage { + static hash = hashPageAccessibilityStatement; + + constructor(router) { + super(router); + } + + initialize() { + this.sharedInitialize(); + } + + leave() { + super.leave(); + } +} diff --git a/static/js/pages/legal/license.js b/static/js/pages/legal/license.js new file mode 100644 index 0000000..6537b59 --- /dev/null +++ b/static/js/pages/legal/license.js @@ -0,0 +1,18 @@ + +import BasePage from "../base.js"; + +export default class PageLicense extends BasePage { + static hash = hashPageLicense; + + constructor(router) { + super(router); + } + + initialize() { + this.sharedInitialize(); + } + + leave() { + super.leave(); + } +} \ No newline at end of file diff --git a/static/js/pages/legal/privacy_policy.js b/static/js/pages/legal/privacy_policy.js new file mode 100644 index 0000000..c73fd8a --- /dev/null +++ b/static/js/pages/legal/privacy_policy.js @@ -0,0 +1,18 @@ + +import BasePage from "../base.js"; + +export default class PagePrivacyPolicy extends BasePage { + static hash = hashPagePrivacyPolicy; + + constructor(router) { + super(router); + } + + initialize() { + this.sharedInitialize(); + } + + leave() { + super.leave(); + } +} \ No newline at end of file diff --git a/static/js/pages/legal/retention_schedule.js b/static/js/pages/legal/retention_schedule.js new file mode 100644 index 0000000..914aed7 --- /dev/null +++ b/static/js/pages/legal/retention_schedule.js @@ -0,0 +1,17 @@ +import BasePage from "../base.js"; + +export default class PageRetentionSchedule extends BasePage { + static hash = hashPageDataRetentionSchedule; + + constructor(router) { + super(router); + } + + initialize() { + this.sharedInitialize(); + } + + leave() { + super.leave(); + } +} diff --git a/static/js/pages/user/user.js b/static/js/pages/user/user.js new file mode 100644 index 0000000..57d5625 --- /dev/null +++ b/static/js/pages/user/user.js @@ -0,0 +1,19 @@ + +import BasePage from "../base.js"; + +export default class PageUser extends BasePage { + static hash = hashPageUser; + + constructor(router) { + super(router); + } + + initialize() { + this.sharedInitialize(); + this.hookupButtonsNavContact(); + } + + leave() { + super.leave(); + } +} diff --git a/static/js/router.js b/static/js/router.js new file mode 100644 index 0000000..82a73fc --- /dev/null +++ b/static/js/router.js @@ -0,0 +1,91 @@ + +// Pages +// Core +import PageHome from './pages/core/home.js'; +import PageContact from './pages/core/contact.js'; +import PageContactSuccess from './pages/core/contact-success.js'; +// Legal +import PageAccessibilityReport from './pages/legal/accessibility_report.js'; +import PageAccessibilityStatement from './pages/legal/accessibility_statement.js'; +import PageLicense from './pages/legal/license.js'; +import PagePrivacyPolicy from './pages/legal/privacy_policy.js'; +import PageRetentionSchedule from './pages/legal/retention_schedule.js'; + +import API from './api.js'; +import DOM from './dom.js'; +import Utils from './lib/utils.js'; + + +export default class Router { + constructor() { + // Pages + this.pages = {}; + // Core + this.pages[hashPageHome] = { name: 'PageHome', module: PageHome }; + this.pages[hashPageContact] = { name: 'PageContact', module: PageContact }; + this.pages[hashPageContactSuccess] = { name: 'PageContact', module: PageContactSuccess }; + // Legal + this.pages[hashPageAccessibilityStatement] = { name: 'PageAccessibilityStatement', module: PageAccessibilityStatement }; + this.pages[hashPageDataRetentionSchedule] = { name: 'PageDataRetentionSchedule', module: PageRetentionSchedule }; + this.pages[hashPageLicense] = { name: 'PageLicense', module: PageLicense }; + this.pages[hashPagePrivacyPolicy] = { name: 'PagePrivacyPolicy', module: PagePrivacyPolicy }; + // Routes + this.routes = {}; + // Core + this.routes[hashPageHome] = (isPopState = false) => this.navigateToHash(hashPageHome, isPopState); + this.routes[hashPageContact] = (isPopState = false) => this.navigateToHash(hashPageContact, isPopState); + // Legal + this.routes[hashPageAccessibilityStatement] = (isPopState = false) => this.navigateToHash(hashPageAccessibilityStatement, isPopState); + this.routes[hashPageDataRetentionSchedule] = (isPopState = false) => this.navigateToHash(hashPageDataRetentionSchedule, isPopState); + this.routes[hashPageLicense] = (isPopState = false) => this.navigateToHash(hashPageLicense, isPopState); + this.routes[hashPagePrivacyPolicy] = (isPopState = false) => this.navigateToHash(hashPagePrivacyPolicy, isPopState); + this.initialize(); + } + loadPage(hashPage, isPopState = false) { + const PageClass = this.getClassPageFromHash(hashPage); + this.currentPage = new PageClass(this); + this.currentPage.initialize(isPopState); + window.addEventListener('beforeunload', () => this.currentPage.leave()); + } + getClassPageFromHash(hashPage) { + + let pageJson = this.pages[hashPage]; + try { + const module = pageJson.module; + return module; + } + catch (error) { + Utils.consoleLogIfNotProductionEnvironment("this.pages: ", this.pages); + console.error('Page not found:', hashPage); + throw error; + } + } + initialize() { + window.addEventListener('popstate', this.handlePopState.bind(this)); + } + handlePopState(event) { + this.loadPageCurrent(); + } + loadPageCurrent() { + const hashPageCurrent = DOM.getHashPageCurrent(); + this.loadPage(hashPageCurrent); + } + navigateToHash(hash, data = null, params = null, isPopState = false) { + let url = API.getUrlFromHash(hash, params); + history.pushState({data: data, params: params}, '', hash); + API.goToUrl(url, data); + } + + navigateToUrl(url, data = null, appendHistory = true) { + // this.beforeLeave(); + if (appendHistory) history.pushState(data, '', url); + url = API.parameteriseUrl(url, data); + API.goToUrl(url); + } + + static loadPageBodyFromResponse(response) { + DOM.loadPageBody(response.data); + } +} + +export const router = new Router(); diff --git a/static/js/sections/core.js b/static/js/sections/core.js new file mode 100644 index 0000000..e69de29 diff --git a/static/js/sections/legal.js b/static/js/sections/legal.js new file mode 100644 index 0000000..e69de29 diff --git a/static/js/vendor/altcha.js b/static/js/vendor/altcha.js new file mode 100644 index 0000000..e983197 --- /dev/null +++ b/static/js/vendor/altcha.js @@ -0,0 +1,2636 @@ +var hi = Object.defineProperty; +var Or = (e) => { + throw TypeError(e); +}; +var gi = (e, t, r) => t in e ? hi(e, t, { enumerable: !0, configurable: !0, writable: !0, value: r }) : e[t] = r; +var ne = (e, t, r) => gi(e, typeof t != "symbol" ? t + "" : t, r), zr = (e, t, r) => t.has(e) || Or("Cannot " + r); +var H = (e, t, r) => (zr(e, t, "read from private field"), r ? r.call(e) : t.get(e)), Mt = (e, t, r) => t.has(e) ? Or("Cannot add the same private member more than once") : t instanceof WeakSet ? t.add(e) : t.set(e, r), Ut = (e, t, r, l) => (zr(e, t, "write to private field"), l ? l.call(e, r) : t.set(e, r), r); +const en = `(function(){"use strict";const d=new TextEncoder;function p(e){return[...new Uint8Array(e)].map(t=>t.toString(16).padStart(2,"0")).join("")}async function b(e,t,r){if(typeof crypto>"u"||!("subtle"in crypto)||!("digest"in crypto.subtle))throw new Error("Web Crypto is not available. Secure context is required (https://developer.mozilla.org/en-US/docs/Web/Security/Secure_Contexts).");return p(await crypto.subtle.digest(r.toUpperCase(),d.encode(e+t)))}function w(e,t,r="SHA-256",n=1e6,s=0){const o=new AbortController,a=Date.now();return{promise:(async()=>{for(let c=s;c<=n;c+=1){if(o.signal.aborted)return null;if(await b(t,c,r)===e)return{number:c,took:Date.now()-a}}return null})(),controller:o}}function h(e){const t=atob(e),r=new Uint8Array(t.length);for(let n=0;n{for(let u=n;u<=r;u+=1){if(o.signal.aborted||!c||!y)return null;try{const f=await crypto.subtle.decrypt({name:s,iv:g(u)},c,y);if(f)return{clearText:new TextDecoder().decode(f),took:Date.now()-a}}catch{}}return null};let c=null,y=null;try{y=h(e);const u=await crypto.subtle.digest("SHA-256",d.encode(t));c=await crypto.subtle.importKey("raw",u,s,!1,["decrypt"])}catch{return{promise:Promise.reject(),controller:o}}return{promise:l(),controller:o}}let i;onmessage=async e=>{const{type:t,payload:r,start:n,max:s}=e.data;let o=null;if(t==="abort")i==null||i.abort(),i=void 0;else if(t==="work"){if("obfuscated"in r){const{key:a,obfuscated:l}=r||{};o=await m(l,a,s,n)}else{const{algorithm:a,challenge:l,salt:c}=r||{};o=w(l,c,a,s,n)}i=o.controller,o.promise.then(a=>{self.postMessage(a&&{...a,worker:!0})})}}})(); +`, Fr = typeof self < "u" && self.Blob && new Blob([en], { type: "text/javascript;charset=utf-8" }); +function _i(e) { + let t; + try { + if (t = Fr && (self.URL || self.webkitURL).createObjectURL(Fr), !t) throw ""; + const r = new Worker(t, { + name: e == null ? void 0 : e.name + }); + return r.addEventListener("error", () => { + (self.URL || self.webkitURL).revokeObjectURL(t); + }), r; + } catch { + return new Worker( + "data:text/javascript;charset=utf-8," + encodeURIComponent(en), + { + name: e == null ? void 0 : e.name + } + ); + } finally { + t && (self.URL || self.webkitURL).revokeObjectURL(t); + } +} +const mi = "5"; +var Qr; +typeof window < "u" && ((Qr = window.__svelte ?? (window.__svelte = {})).v ?? (Qr.v = /* @__PURE__ */ new Set())).add(mi); +const wi = 1, pi = 4, yi = 8, bi = 16, Ei = 1, xi = 2, Wt = "[", tn = "[!", rn = "]", Je = {}, W = Symbol(), $i = "http://www.w3.org/1999/xhtml", Mr = !1, oe = 2, nn = 4, It = 8, Yt = 16, pe = 32, ze = 64, yt = 128, re = 256, bt = 512, K = 1024, ye = 2048, et = 4096, Ke = 8192, St = 16384, ki = 32768, Zt = 65536, Ci = 1 << 19, ln = 1 << 20, ut = Symbol("$state"), an = Symbol("legacy props"), Ai = Symbol(""); +var on = Array.isArray, Ri = Array.prototype.indexOf, Ii = Array.from, Et = Object.keys, xt = Object.defineProperty, Pe = Object.getOwnPropertyDescriptor, Si = Object.getOwnPropertyDescriptors, Ti = Object.prototype, Ni = Array.prototype, sn = Object.getPrototypeOf; +function fn(e) { + for (var t = 0; t < e.length; t++) + e[t](); +} +const Li = typeof requestIdleCallback > "u" ? (e) => setTimeout(e, 1) : requestIdleCallback; +let dt = [], vt = []; +function un() { + var e = dt; + dt = [], fn(e); +} +function cn() { + var e = vt; + vt = [], fn(e); +} +function Gt(e) { + dt.length === 0 && queueMicrotask(un), dt.push(e); +} +function Di(e) { + vt.length === 0 && Li(cn), vt.push(e); +} +function Ur() { + dt.length > 0 && un(), vt.length > 0 && cn(); +} +function dn(e) { + return e === this.v; +} +function Pi(e, t) { + return e != e ? t == t : e !== t || e !== null && typeof e == "object" || typeof e == "function"; +} +function vn(e) { + return !Pi(e, this.v); +} +function Oi(e) { + throw new Error("https://svelte.dev/e/effect_in_teardown"); +} +function zi() { + throw new Error("https://svelte.dev/e/effect_in_unowned_derived"); +} +function Fi(e) { + throw new Error("https://svelte.dev/e/effect_orphan"); +} +function Mi() { + throw new Error("https://svelte.dev/e/effect_update_depth_exceeded"); +} +function Ui() { + throw new Error("https://svelte.dev/e/hydration_failed"); +} +function ji(e) { + throw new Error("https://svelte.dev/e/props_invalid_value"); +} +function Vi() { + throw new Error("https://svelte.dev/e/state_descriptors_fixed"); +} +function Bi() { + throw new Error("https://svelte.dev/e/state_prototype_fixed"); +} +function qi() { + throw new Error("https://svelte.dev/e/state_unsafe_local_read"); +} +function Hi() { + throw new Error("https://svelte.dev/e/state_unsafe_mutation"); +} +let Wi = !1; +function ue(e, t) { + var r = { + f: 0, + // TODO ideally we could skip this altogether, but it causes type errors + v: e, + reactions: null, + equals: dn, + rv: 0, + wv: 0 + }; + return r; +} +function He(e) { + return /* @__PURE__ */ Yi(ue(e)); +} +// @__NO_SIDE_EFFECTS__ +function hn(e, t = !1) { + const r = ue(e); + return t || (r.equals = vn), r; +} +// @__NO_SIDE_EFFECTS__ +function Yi(e) { + return k !== null && !ae && (k.f & oe) !== 0 && (ce === null ? Qi([e]) : ce.push(e)), e; +} +function P(e, t) { + return k !== null && !ae && Dn() && (k.f & (oe | Yt)) !== 0 && // If the source was created locally within the current derived, then + // we allow the mutation. + (ce === null || !ce.includes(e)) && Hi(), Zi(e, t); +} +function Zi(e, t) { + return e.equals(t) || (e.v, e.v = t, e.wv = En(), gn(e, ye), A !== null && (A.f & K) !== 0 && (A.f & (pe | ze)) === 0 && (ge === null ? el([e]) : ge.push(e))), t; +} +function gn(e, t) { + var r = e.reactions; + if (r !== null) + for (var l = r.length, i = 0; i < l; i++) { + var a = r[i], o = a.f; + (o & ye) === 0 && (de(a, t), (o & (K | re)) !== 0 && ((o & oe) !== 0 ? gn( + /** @type {Derived} */ + a, + et + ) : Lt( + /** @type {Effect} */ + a + ))); + } +} +// @__NO_SIDE_EFFECTS__ +function De(e) { + var t = oe | ye, r = k !== null && (k.f & oe) !== 0 ? ( + /** @type {Derived} */ + k + ) : null; + return A === null || r !== null && (r.f & re) !== 0 ? t |= re : A.f |= ln, { + ctx: B, + deps: null, + effects: null, + equals: dn, + f: t, + fn: e, + reactions: null, + rv: 0, + v: ( + /** @type {V} */ + null + ), + wv: 0, + parent: r ?? A + }; +} +function _n(e) { + var t = e.effects; + if (t !== null) { + e.effects = null; + for (var r = 0; r < t.length; r += 1) + we( + /** @type {Effect} */ + t[r] + ); + } +} +function Gi(e) { + for (var t = e.parent; t !== null; ) { + if ((t.f & oe) === 0) + return ( + /** @type {Effect} */ + t + ); + t = t.parent; + } + return null; +} +function Ji(e) { + var t, r = A; + Se(Gi(e)); + try { + _n(e), t = $n(e); + } finally { + Se(r); + } + return t; +} +function mn(e) { + var t = Ji(e), r = (Ce || (e.f & re) !== 0) && e.deps !== null ? et : K; + de(e, r), e.equals(t) || (e.v = t, e.wv = En()); +} +function Tt(e) { + console.warn("https://svelte.dev/e/hydration_mismatch"); +} +let D = !1; +function Ge(e) { + D = e; +} +let O; +function Re(e) { + if (e === null) + throw Tt(), Je; + return O = e; +} +function Xe() { + return Re( + /** @type {TemplateNode} */ + /* @__PURE__ */ Te(O) + ); +} +function Z(e) { + if (D) { + if (/* @__PURE__ */ Te(O) !== null) + throw Tt(), Je; + O = e; + } +} +function Ki() { + for (var e = 0, t = O; ; ) { + if (t.nodeType === 8) { + var r = ( + /** @type {Comment} */ + t.data + ); + if (r === rn) { + if (e === 0) return t; + e -= 1; + } else (r === Wt || r === tn) && (e += 1); + } + var l = ( + /** @type {TemplateNode} */ + /* @__PURE__ */ Te(t) + ); + t.remove(), t = l; + } +} +function le(e, t = null, r) { + if (typeof e != "object" || e === null || ut in e) + return e; + const l = sn(e); + if (l !== Ti && l !== Ni) + return e; + var i = /* @__PURE__ */ new Map(), a = on(e), o = ue(0); + a && i.set("length", ue( + /** @type {any[]} */ + e.length + )); + var f; + return new Proxy( + /** @type {any} */ + e, + { + defineProperty(s, c, v) { + (!("value" in v) || v.configurable === !1 || v.enumerable === !1 || v.writable === !1) && Vi(); + var h = i.get(c); + return h === void 0 ? (h = ue(v.value), i.set(c, h)) : P(h, le(v.value, f)), !0; + }, + deleteProperty(s, c) { + var v = i.get(c); + if (v === void 0) + c in s && i.set(c, ue(W)); + else { + if (a && typeof c == "string") { + var h = ( + /** @type {Source} */ + i.get("length") + ), g = Number(c); + Number.isInteger(g) && g < h.v && P(h, g); + } + P(v, W), jr(o); + } + return !0; + }, + get(s, c, v) { + var w; + if (c === ut) + return e; + var h = i.get(c), g = c in s; + if (h === void 0 && (!g || (w = Pe(s, c)) != null && w.writable) && (h = ue(le(g ? s[c] : W, f)), i.set(c, h)), h !== void 0) { + var m = d(h); + return m === W ? void 0 : m; + } + return Reflect.get(s, c, v); + }, + getOwnPropertyDescriptor(s, c) { + var v = Reflect.getOwnPropertyDescriptor(s, c); + if (v && "value" in v) { + var h = i.get(c); + h && (v.value = d(h)); + } else if (v === void 0) { + var g = i.get(c), m = g == null ? void 0 : g.v; + if (g !== void 0 && m !== W) + return { + enumerable: !0, + configurable: !0, + value: m, + writable: !0 + }; + } + return v; + }, + has(s, c) { + var m; + if (c === ut) + return !0; + var v = i.get(c), h = v !== void 0 && v.v !== W || Reflect.has(s, c); + if (v !== void 0 || A !== null && (!h || (m = Pe(s, c)) != null && m.writable)) { + v === void 0 && (v = ue(h ? le(s[c], f) : W), i.set(c, v)); + var g = d(v); + if (g === W) + return !1; + } + return h; + }, + set(s, c, v, h) { + var F; + var g = i.get(c), m = c in s; + if (a && c === "length") + for (var w = v; w < /** @type {Source} */ + g.v; w += 1) { + var z = i.get(w + ""); + z !== void 0 ? P(z, W) : w in s && (z = ue(W), i.set(w + "", z)); + } + g === void 0 ? (!m || (F = Pe(s, c)) != null && F.writable) && (g = ue(void 0), P(g, le(v, f)), i.set(c, g)) : (m = g.v !== W, P(g, le(v, f))); + var T = Reflect.getOwnPropertyDescriptor(s, c); + if (T != null && T.set && T.set.call(h, v), !m) { + if (a && typeof c == "string") { + var Y = ( + /** @type {Source} */ + i.get("length") + ), M = Number(c); + Number.isInteger(M) && M >= Y.v && P(Y, M + 1); + } + jr(o); + } + return !0; + }, + ownKeys(s) { + d(o); + var c = Reflect.ownKeys(s).filter((g) => { + var m = i.get(g); + return m === void 0 || m.v !== W; + }); + for (var [v, h] of i) + h.v !== W && !(v in s) && c.push(v); + return c; + }, + setPrototypeOf() { + Bi(); + } + } + ); +} +function jr(e, t = 1) { + P(e, e.v + t); +} +var Vr, wn, pn, yn; +function jt() { + if (Vr === void 0) { + Vr = window, wn = /Firefox/.test(navigator.userAgent); + var e = Element.prototype, t = Node.prototype; + pn = Pe(t, "firstChild").get, yn = Pe(t, "nextSibling").get, e.__click = void 0, e.__className = void 0, e.__attributes = null, e.__style = void 0, e.__e = void 0, Text.prototype.__t = void 0; + } +} +function Jt(e = "") { + return document.createTextNode(e); +} +// @__NO_SIDE_EFFECTS__ +function me(e) { + return pn.call(e); +} +// @__NO_SIDE_EFFECTS__ +function Te(e) { + return yn.call(e); +} +function G(e, t) { + if (!D) + return /* @__PURE__ */ me(e); + var r = ( + /** @type {TemplateNode} */ + /* @__PURE__ */ me(O) + ); + return r === null && (r = O.appendChild(Jt())), Re(r), r; +} +function Br(e, t) { + if (!D) { + var r = ( + /** @type {DocumentFragment} */ + /* @__PURE__ */ me( + /** @type {Node} */ + e + ) + ); + return r instanceof Comment && r.data === "" ? /* @__PURE__ */ Te(r) : r; + } + return O; +} +function he(e, t = 1, r = !1) { + let l = D ? O : e; + for (var i; t--; ) + i = l, l = /** @type {TemplateNode} */ + /* @__PURE__ */ Te(l); + if (!D) + return l; + var a = l == null ? void 0 : l.nodeType; + if (r && a !== 3) { + var o = Jt(); + return l === null ? i == null || i.after(o) : l.before(o), Re(o), o; + } + return Re(l), /** @type {TemplateNode} */ + l; +} +function Xi(e) { + e.textContent = ""; +} +let wt = !1, $t = !1, kt = null, Oe = !1, Kt = !1; +function qr(e) { + Kt = e; +} +let ct = []; +let k = null, ae = !1; +function Ie(e) { + k = e; +} +let A = null; +function Se(e) { + A = e; +} +let ce = null; +function Qi(e) { + ce = e; +} +let V = null, J = 0, ge = null; +function el(e) { + ge = e; +} +let bn = 1, Ct = 0, Ce = !1; +function En() { + return ++bn; +} +function ht(e) { + var h; + var t = e.f; + if ((t & ye) !== 0) + return !0; + if ((t & et) !== 0) { + var r = e.deps, l = (t & re) !== 0; + if (r !== null) { + var i, a, o = (t & bt) !== 0, f = l && A !== null && !Ce, s = r.length; + if (o || f) { + var c = ( + /** @type {Derived} */ + e + ), v = c.parent; + for (i = 0; i < s; i++) + a = r[i], (o || !((h = a == null ? void 0 : a.reactions) != null && h.includes(c))) && (a.reactions ?? (a.reactions = [])).push(c); + o && (c.f ^= bt), f && v !== null && (v.f & re) === 0 && (c.f ^= re); + } + for (i = 0; i < s; i++) + if (a = r[i], ht( + /** @type {Derived} */ + a + ) && mn( + /** @type {Derived} */ + a + ), a.wv > e.wv) + return !0; + } + (!l || A !== null && !Ce) && de(e, K); + } + return !1; +} +function tl(e, t) { + for (var r = t; r !== null; ) { + if ((r.f & yt) !== 0) + try { + r.fn(e); + return; + } catch { + r.f ^= yt; + } + r = r.parent; + } + throw wt = !1, e; +} +function rl(e) { + return (e.f & St) === 0 && (e.parent === null || (e.parent.f & yt) === 0); +} +function Nt(e, t, r, l) { + if (wt) { + if (r === null && (wt = !1), rl(t)) + throw e; + return; + } + r !== null && (wt = !0); + { + tl(e, t); + return; + } +} +function xn(e, t, r = !0) { + var l = e.reactions; + if (l !== null) + for (var i = 0; i < l.length; i++) { + var a = l[i]; + (a.f & oe) !== 0 ? xn( + /** @type {Derived} */ + a, + t, + !1 + ) : t === a && (r ? de(a, ye) : (a.f & K) !== 0 && de(a, et), Lt( + /** @type {Effect} */ + a + )); + } +} +function $n(e) { + var m; + var t = V, r = J, l = ge, i = k, a = Ce, o = ce, f = B, s = ae, c = e.f; + V = /** @type {null | Value[]} */ + null, J = 0, ge = null, Ce = (c & re) !== 0 && (ae || !Oe || k === null), k = (c & (pe | ze)) === 0 ? e : null, ce = null, Wr(e.ctx), ae = !1, Ct++; + try { + var v = ( + /** @type {Function} */ + (0, e.fn)() + ), h = e.deps; + if (V !== null) { + var g; + if (At(e, J), h !== null && J > 0) + for (h.length = J + V.length, g = 0; g < V.length; g++) + h[J + g] = V[g]; + else + e.deps = h = V; + if (!Ce) + for (g = J; g < h.length; g++) + ((m = h[g]).reactions ?? (m.reactions = [])).push(e); + } else h !== null && J < h.length && (At(e, J), h.length = J); + if (Dn() && ge !== null && !ae && h !== null && (e.f & (oe | et | ye)) === 0) + for (g = 0; g < /** @type {Source[]} */ + ge.length; g++) + xn( + ge[g], + /** @type {Effect} */ + e + ); + return i !== null && Ct++, v; + } finally { + V = t, J = r, ge = l, k = i, Ce = a, ce = o, Wr(f), ae = s; + } +} +function nl(e, t) { + let r = t.reactions; + if (r !== null) { + var l = Ri.call(r, e); + if (l !== -1) { + var i = r.length - 1; + i === 0 ? r = t.reactions = null : (r[l] = r[i], r.pop()); + } + } + r === null && (t.f & oe) !== 0 && // Destroying a child effect while updating a parent effect can cause a dependency to appear + // to be unused, when in fact it is used by the currently-updating parent. Checking `new_deps` + // allows us to skip the expensive work of disconnecting and immediately reconnecting it + (V === null || !V.includes(t)) && (de(t, et), (t.f & (re | bt)) === 0 && (t.f ^= bt), _n( + /** @type {Derived} **/ + t + ), At( + /** @type {Derived} **/ + t, + 0 + )); +} +function At(e, t) { + var r = e.deps; + if (r !== null) + for (var l = t; l < r.length; l++) + nl(e, r[l]); +} +function Xt(e) { + var t = e.f; + if ((t & St) === 0) { + de(e, K); + var r = A, l = B, i = Oe; + A = e, Oe = !0; + try { + (t & Yt) !== 0 ? hl(e) : An(e), Cn(e); + var a = $n(e); + e.teardown = typeof a == "function" ? a : null, e.wv = bn; + var o = e.deps, f; + Mr && Wi && e.f & ye; + } catch (s) { + Nt(s, e, r, l || e.ctx); + } finally { + Oe = i, A = r; + } + } +} +function il() { + try { + Mi(); + } catch (e) { + if (kt !== null) + Nt(e, kt, null); + else + throw e; + } +} +function kn() { + var e = Oe; + try { + var t = 0; + for (Oe = !0; ct.length > 0; ) { + t++ > 1e3 && il(); + var r = ct, l = r.length; + ct = []; + for (var i = 0; i < l; i++) { + var a = al(r[i]); + ll(a); + } + } + } finally { + $t = !1, Oe = e, kt = null; + } +} +function ll(e) { + var t = e.length; + if (t !== 0) + for (var r = 0; r < t; r++) { + var l = e[r]; + if ((l.f & (St | Ke)) === 0) + try { + ht(l) && (Xt(l), l.deps === null && l.first === null && l.nodes_start === null && (l.teardown === null ? Rn(l) : l.fn = null)); + } catch (i) { + Nt(i, l, null, l.ctx); + } + } +} +function Lt(e) { + $t || ($t = !0, queueMicrotask(kn)); + for (var t = kt = e; t.parent !== null; ) { + t = t.parent; + var r = t.f; + if ((r & (ze | pe)) !== 0) { + if ((r & K) === 0) return; + t.f ^= K; + } + } + ct.push(t); +} +function al(e) { + for (var t = [], r = e; r !== null; ) { + var l = r.f, i = (l & (pe | ze)) !== 0, a = i && (l & K) !== 0; + if (!a && (l & Ke) === 0) { + if ((l & nn) !== 0) + t.push(r); + else if (i) + r.f ^= K; + else { + var o = k; + try { + k = r, ht(r) && Xt(r); + } catch (c) { + Nt(c, r, null, r.ctx); + } finally { + k = o; + } + } + var f = r.first; + if (f !== null) { + r = f; + continue; + } + } + var s = r.parent; + for (r = r.next; r === null && s !== null; ) + r = s.next, s = s.parent; + } + return t; +} +function $(e) { + var t; + for (Ur(); ct.length > 0; ) + $t = !0, kn(), Ur(); + return ( + /** @type {T} */ + t + ); +} +async function ol() { + await Promise.resolve(), $(); +} +function d(e) { + var t = e.f, r = (t & oe) !== 0; + if (k !== null && !ae) { + ce !== null && ce.includes(e) && qi(); + var l = k.deps; + e.rv < Ct && (e.rv = Ct, V === null && l !== null && l[J] === e ? J++ : V === null ? V = [e] : (!Ce || !V.includes(e)) && V.push(e)); + } else if (r && /** @type {Derived} */ + e.deps === null && /** @type {Derived} */ + e.effects === null) { + var i = ( + /** @type {Derived} */ + e + ), a = i.parent; + a !== null && (a.f & re) === 0 && (i.f ^= re); + } + return r && (i = /** @type {Derived} */ + e, ht(i) && mn(i)), e.v; +} +function Qe(e) { + var t = ae; + try { + return ae = !0, e(); + } finally { + ae = t; + } +} +const sl = -7169; +function de(e, t) { + e.f = e.f & sl | t; +} +function fl(e) { + A === null && k === null && Fi(), k !== null && (k.f & re) !== 0 && A === null && zi(), Kt && Oi(); +} +function ul(e, t) { + var r = t.last; + r === null ? t.last = t.first = e : (r.next = e, e.prev = r, t.last = e); +} +function Fe(e, t, r, l = !0) { + var i = A, a = { + ctx: B, + deps: null, + nodes_start: null, + nodes_end: null, + f: e | ye, + first: null, + fn: t, + last: null, + next: null, + parent: i, + prev: null, + teardown: null, + transitions: null, + wv: 0 + }; + if (r) + try { + Xt(a), a.f |= ki; + } catch (s) { + throw we(a), s; + } + else t !== null && Lt(a); + var o = r && a.deps === null && a.first === null && a.nodes_start === null && a.teardown === null && (a.f & (ln | yt)) === 0; + if (!o && l && (i !== null && ul(a, i), k !== null && (k.f & oe) !== 0)) { + var f = ( + /** @type {Derived} */ + k + ); + (f.effects ?? (f.effects = [])).push(a); + } + return a; +} +function cl(e) { + const t = Fe(It, null, !1); + return de(t, K), t.teardown = e, t; +} +function Vt(e) { + fl(); + var t = A !== null && (A.f & pe) !== 0 && B !== null && !B.m; + if (t) { + var r = ( + /** @type {ComponentContext} */ + B + ); + (r.e ?? (r.e = [])).push({ + fn: e, + effect: A, + reaction: k + }); + } else { + var l = Qt(e); + return l; + } +} +function dl(e) { + const t = Fe(ze, e, !0); + return () => { + we(t); + }; +} +function vl(e) { + const t = Fe(ze, e, !0); + return (r = {}) => new Promise((l) => { + r.outro ? Bt(t, () => { + we(t), l(void 0); + }) : (we(t), l(void 0)); + }); +} +function Qt(e) { + return Fe(nn, e, !1); +} +function er(e) { + return Fe(It, e, !0); +} +function We(e, t = [], r = De) { + const l = t.map(r); + return tr(() => e(...l.map(d))); +} +function tr(e, t = 0) { + return Fe(It | Yt | t, e, !0); +} +function Rt(e, t = !0) { + return Fe(It | pe, e, !0, t); +} +function Cn(e) { + var t = e.teardown; + if (t !== null) { + const r = Kt, l = k; + qr(!0), Ie(null); + try { + t.call(null); + } finally { + qr(r), Ie(l); + } + } +} +function An(e, t = !1) { + var r = e.first; + for (e.first = e.last = null; r !== null; ) { + var l = r.next; + (r.f & ze) !== 0 ? r.parent = null : we(r, t), r = l; + } +} +function hl(e) { + for (var t = e.first; t !== null; ) { + var r = t.next; + (t.f & pe) === 0 && we(t), t = r; + } +} +function we(e, t = !0) { + var r = !1; + if ((t || (e.f & Ci) !== 0) && e.nodes_start !== null) { + for (var l = e.nodes_start, i = e.nodes_end; l !== null; ) { + var a = l === i ? null : ( + /** @type {TemplateNode} */ + /* @__PURE__ */ Te(l) + ); + l.remove(), l = a; + } + r = !0; + } + An(e, t && !r), At(e, 0), de(e, St); + var o = e.transitions; + if (o !== null) + for (const s of o) + s.stop(); + Cn(e); + var f = e.parent; + f !== null && f.first !== null && Rn(e), e.next = e.prev = e.teardown = e.ctx = e.deps = e.fn = e.nodes_start = e.nodes_end = null; +} +function Rn(e) { + var t = e.parent, r = e.prev, l = e.next; + r !== null && (r.next = l), l !== null && (l.prev = r), t !== null && (t.first === e && (t.first = l), t.last === e && (t.last = r)); +} +function Bt(e, t) { + var r = []; + In(e, r, !0), gl(r, () => { + we(e), t && t(); + }); +} +function gl(e, t) { + var r = e.length; + if (r > 0) { + var l = () => --r || t(); + for (var i of e) + i.out(l); + } else + t(); +} +function In(e, t, r) { + if ((e.f & Ke) === 0) { + if (e.f ^= Ke, e.transitions !== null) + for (const o of e.transitions) + (o.is_global || r) && t.push(o); + for (var l = e.first; l !== null; ) { + var i = l.next, a = (l.f & Zt) !== 0 || (l.f & pe) !== 0; + In(l, t, a ? r : !1), l = i; + } + } +} +function Hr(e) { + Sn(e, !0); +} +function Sn(e, t) { + if ((e.f & Ke) !== 0) { + e.f ^= Ke, (e.f & K) === 0 && (e.f ^= K), ht(e) && (de(e, ye), Lt(e)); + for (var r = e.first; r !== null; ) { + var l = r.next, i = (r.f & Zt) !== 0 || (r.f & pe) !== 0; + Sn(r, i ? t : !1), r = l; + } + if (e.transitions !== null) + for (const a of e.transitions) + (a.is_global || t) && a.in(); + } +} +function Tn(e) { + throw new Error("https://svelte.dev/e/lifecycle_outside_component"); +} +let B = null; +function Wr(e) { + B = e; +} +function Nn(e, t = !1, r) { + B = { + p: B, + c: null, + e: null, + m: !1, + s: e, + x: null, + l: null + }; +} +function Ln(e) { + const t = B; + if (t !== null) { + e !== void 0 && (t.x = e); + const o = t.e; + if (o !== null) { + var r = A, l = k; + t.e = null; + try { + for (var i = 0; i < o.length; i++) { + var a = o[i]; + Se(a.effect), Ie(a.reaction), Qt(a.fn); + } + } finally { + Se(r), Ie(l); + } + } + B = t.p, t.m = !0; + } + return e || /** @type {T} */ + {}; +} +function Dn() { + return !0; +} +const _l = ["touchstart", "touchmove"]; +function ml(e) { + return _l.includes(e); +} +let Yr = !1; +function Pn() { + Yr || (Yr = !0, document.addEventListener( + "reset", + (e) => { + Promise.resolve().then(() => { + var t; + if (!e.defaultPrevented) + for ( + const r of + /**@type {HTMLFormElement} */ + e.target.elements + ) + (t = r.__on_r) == null || t.call(r); + }); + }, + // In the capture phase to guarantee we get noticed of it (no possiblity of stopPropagation) + { capture: !0 } + )); +} +function On(e) { + var t = k, r = A; + Ie(null), Se(null); + try { + return e(); + } finally { + Ie(t), Se(r); + } +} +function wl(e, t, r, l = r) { + e.addEventListener(t, () => On(r)); + const i = e.__on_r; + i ? e.__on_r = () => { + i(), l(!0); + } : e.__on_r = () => l(!0), Pn(); +} +const zn = /* @__PURE__ */ new Set(), qt = /* @__PURE__ */ new Set(); +function pl(e, t, r, l = {}) { + function i(a) { + if (l.capture || ft.call(t, a), !a.cancelBubble) + return On(() => r == null ? void 0 : r.call(this, a)); + } + return e.startsWith("pointer") || e.startsWith("touch") || e === "wheel" ? Gt(() => { + t.addEventListener(e, i, l); + }) : t.addEventListener(e, i, l), i; +} +function yl(e, t, r, l, i) { + var a = { capture: l, passive: i }, o = pl(e, t, r, a); + (t === document.body || t === window || t === document) && cl(() => { + t.removeEventListener(e, o, a); + }); +} +function bl(e) { + for (var t = 0; t < e.length; t++) + zn.add(e[t]); + for (var r of qt) + r(e); +} +function ft(e) { + var M; + var t = this, r = ( + /** @type {Node} */ + t.ownerDocument + ), l = e.type, i = ((M = e.composedPath) == null ? void 0 : M.call(e)) || [], a = ( + /** @type {null | Element} */ + i[0] || e.target + ), o = 0, f = e.__root; + if (f) { + var s = i.indexOf(f); + if (s !== -1 && (t === document || t === /** @type {any} */ + window)) { + e.__root = t; + return; + } + var c = i.indexOf(t); + if (c === -1) + return; + s <= c && (o = s); + } + if (a = /** @type {Element} */ + i[o] || e.target, a !== t) { + xt(e, "currentTarget", { + configurable: !0, + get() { + return a || r; + } + }); + var v = k, h = A; + Ie(null), Se(null); + try { + for (var g, m = []; a !== null; ) { + var w = a.assignedSlot || a.parentNode || /** @type {any} */ + a.host || null; + try { + var z = a["__" + l]; + if (z != null && (!/** @type {any} */ + a.disabled || // DOM could've been updated already by the time this is reached, so we check this as well + // -> the target could not have been disabled because it emits the event in the first place + e.target === a)) + if (on(z)) { + var [T, ...Y] = z; + T.apply(a, [e, ...Y]); + } else + z.call(a, e); + } catch (F) { + g ? m.push(F) : g = F; + } + if (e.cancelBubble || w === t || w === null) + break; + a = w; + } + if (g) { + for (let F of m) + queueMicrotask(() => { + throw F; + }); + throw g; + } + } finally { + e.__root = t, delete e.currentTarget, Ie(v), Se(h); + } + } +} +function rr(e) { + var t = document.createElement("template"); + return t.innerHTML = e, t.content; +} +function Ae(e, t) { + var r = ( + /** @type {Effect} */ + A + ); + r.nodes_start === null && (r.nodes_start = e, r.nodes_end = t); +} +// @__NO_SIDE_EFFECTS__ +function ve(e, t) { + var r = (t & Ei) !== 0, l = (t & xi) !== 0, i, a = !e.startsWith(""); + return () => { + if (D) + return Ae(O, null), O; + i === void 0 && (i = rr(a ? e : "" + e), r || (i = /** @type {Node} */ + /* @__PURE__ */ me(i))); + var o = ( + /** @type {TemplateNode} */ + l || wn ? document.importNode(i, !0) : i.cloneNode(!0) + ); + if (r) { + var f = ( + /** @type {TemplateNode} */ + /* @__PURE__ */ me(o) + ), s = ( + /** @type {TemplateNode} */ + o.lastChild + ); + Ae(f, s); + } else + Ae(o, o); + return o; + }; +} +// @__NO_SIDE_EFFECTS__ +function El(e, t, r = "svg") { + var l = !e.startsWith(""), i = `<${r}>${l ? e : "" + e}`, a; + return () => { + if (D) + return Ae(O, null), O; + if (!a) { + var o = ( + /** @type {DocumentFragment} */ + rr(i) + ), f = ( + /** @type {Element} */ + /* @__PURE__ */ me(o) + ); + a = /** @type {Element} */ + /* @__PURE__ */ me(f); + } + var s = ( + /** @type {TemplateNode} */ + a.cloneNode(!0) + ); + return Ae(s, s), s; + }; +} +function ee(e, t) { + if (D) { + A.nodes_end = O, Xe(); + return; + } + e !== null && e.before( + /** @type {Node} */ + t + ); +} +function Fn(e, t) { + return Mn(e, t); +} +function xl(e, t) { + jt(), t.intro = t.intro ?? !1; + const r = t.target, l = D, i = O; + try { + for (var a = ( + /** @type {TemplateNode} */ + /* @__PURE__ */ me(r) + ); a && (a.nodeType !== 8 || /** @type {Comment} */ + a.data !== Wt); ) + a = /** @type {TemplateNode} */ + /* @__PURE__ */ Te(a); + if (!a) + throw Je; + Ge(!0), Re( + /** @type {Comment} */ + a + ), Xe(); + const o = Mn(e, { ...t, anchor: a }); + if (O === null || O.nodeType !== 8 || /** @type {Comment} */ + O.data !== rn) + throw Tt(), Je; + return Ge(!1), /** @type {Exports} */ + o; + } catch (o) { + if (o === Je) + return t.recover === !1 && Ui(), jt(), Xi(r), Ge(!1), Fn(e, t); + throw o; + } finally { + Ge(l), Re(i); + } +} +const Ye = /* @__PURE__ */ new Map(); +function Mn(e, { target: t, anchor: r, props: l = {}, events: i, context: a, intro: o = !0 }) { + jt(); + var f = /* @__PURE__ */ new Set(), s = (h) => { + for (var g = 0; g < h.length; g++) { + var m = h[g]; + if (!f.has(m)) { + f.add(m); + var w = ml(m); + t.addEventListener(m, ft, { passive: w }); + var z = Ye.get(m); + z === void 0 ? (document.addEventListener(m, ft, { passive: w }), Ye.set(m, 1)) : Ye.set(m, z + 1); + } + } + }; + s(Ii(zn)), qt.add(s); + var c = void 0, v = vl(() => { + var h = r ?? t.appendChild(Jt()); + return Rt(() => { + if (a) { + Nn({}); + var g = ( + /** @type {ComponentContext} */ + B + ); + g.c = a; + } + i && (l.$$events = i), D && Ae( + /** @type {TemplateNode} */ + h, + null + ), c = e(h, l) || {}, D && (A.nodes_end = O), a && Ln(); + }), () => { + var w; + for (var g of f) { + t.removeEventListener(g, ft); + var m = ( + /** @type {number} */ + Ye.get(g) + ); + --m === 0 ? (document.removeEventListener(g, ft), Ye.delete(g)) : Ye.set(g, m); + } + qt.delete(s), h !== r && ((w = h.parentNode) == null || w.removeChild(h)); + }; + }); + return Ht.set(c, v), c; +} +let Ht = /* @__PURE__ */ new WeakMap(); +function $l(e, t) { + const r = Ht.get(e); + return r ? (Ht.delete(e), r(t)) : Promise.resolve(); +} +function ke(e, t, [r, l] = [0, 0]) { + D && r === 0 && Xe(); + var i = e, a = null, o = null, f = W, s = r > 0 ? Zt : 0, c = !1; + const v = (g, m = !0) => { + c = !0, h(m, g); + }, h = (g, m) => { + if (f === (f = g)) return; + let w = !1; + if (D && l !== -1) { + if (r === 0) { + const T = ( + /** @type {Comment} */ + i.data + ); + T === Wt ? l = 0 : T === tn ? l = 1 / 0 : (l = parseInt(T.substring(1)), l !== l && (l = f ? 1 / 0 : -1)); + } + const z = l > r; + !!f === z && (i = Ki(), Re(i), Ge(!1), w = !0, l = -1); + } + f ? (a ? Hr(a) : m && (a = Rt(() => m(i))), o && Bt(o, () => { + o = null; + })) : (o ? Hr(o) : m && (o = Rt(() => m(i, [r + 1, l]))), a && Bt(a, () => { + a = null; + })), w && Ge(!0); + }; + tr(() => { + c = !1, t(v), c || h(null, null); + }, s), D && (i = O); +} +function Ze(e, t, r, l, i) { + var a = e, o = "", f; + tr(() => { + if (o === (o = t() ?? "")) { + D && Xe(); + return; + } + f !== void 0 && (we(f), f = void 0), o !== "" && (f = Rt(() => { + if (D) { + O.data; + for (var s = Xe(), c = s; s !== null && (s.nodeType !== 8 || /** @type {Comment} */ + s.data !== ""); ) + c = s, s = /** @type {TemplateNode} */ + /* @__PURE__ */ Te(s); + if (s === null) + throw Tt(), Je; + Ae(O, c), a = Re(s); + return; + } + var v = o + "", h = rr(v); + Ae( + /** @type {TemplateNode} */ + /* @__PURE__ */ me(h), + /** @type {TemplateNode} */ + h.lastChild + ), a.before(h); + })); + }); +} +function kl(e, t, r, l, i) { + var f; + D && Xe(); + var a = (f = t.$$slots) == null ? void 0 : f[r], o = !1; + a === !0 && (a = t.children, o = !0), a === void 0 || a(e, o ? () => l : l); +} +function Cl(e, t) { + Gt(() => { + var r = e.getRootNode(), l = ( + /** @type {ShadowRoot} */ + r.host ? ( + /** @type {ShadowRoot} */ + r + ) : ( + /** @type {Document} */ + r.head ?? /** @type {Document} */ + r.ownerDocument.head + ) + ); + if (!l.querySelector("#" + t.hash)) { + const i = document.createElement("style"); + i.id = t.hash, i.textContent = t.code, l.appendChild(i); + } + }); +} +const Zr = [...` +\r\f \v\uFEFF`]; +function Al(e, t, r) { + var l = "" + e; + if (r) { + for (var i in r) + if (r[i]) + l = l ? l + " " + i : i; + else if (l.length) + for (var a = i.length, o = 0; (o = l.indexOf(i, o)) >= 0; ) { + var f = o + a; + (o === 0 || Zr.includes(l[o - 1])) && (f === l.length || Zr.includes(l[f])) ? l = (o === 0 ? "" : l.substring(0, o)) + l.substring(f + 1) : o = f; + } + } + return l === "" ? null : l; +} +function Rl(e, t, r, l, i, a) { + var o = e.__className; + if (D || o !== r) { + var f = Al(r, l, a); + (!D || f !== e.getAttribute("class")) && (f == null ? e.removeAttribute("class") : e.className = f), e.__className = r; + } else if (a && i !== a) + for (var s in a) { + var c = !!a[s]; + (i == null || c !== !!i[s]) && e.classList.toggle(s, c); + } + return a; +} +const Il = Symbol("is custom element"), Sl = Symbol("is html"); +function Gr(e) { + if (D) { + var t = !1, r = () => { + if (!t) { + if (t = !0, e.hasAttribute("value")) { + var l = e.value; + ie(e, "value", null), e.value = l; + } + if (e.hasAttribute("checked")) { + var i = e.checked; + ie(e, "checked", null), e.checked = i; + } + } + }; + e.__on_r = r, Di(r), Pn(); + } +} +function Tl(e, t) { + var r = Un(e); + r.value === (r.value = // treat null and undefined the same for the initial value + t ?? void 0) || // @ts-expect-error + // `progress` elements always need their value set when it's `0` + e.value === t && (t !== 0 || e.nodeName !== "PROGRESS") || (e.value = t ?? ""); +} +function ie(e, t, r, l) { + var i = Un(e); + D && (i[t] = e.getAttribute(t), t === "src" || t === "srcset" || t === "href" && e.nodeName === "LINK") || i[t] !== (i[t] = r) && (t === "loading" && (e[Ai] = r), r == null ? e.removeAttribute(t) : typeof r != "string" && Nl(e).includes(t) ? e[t] = r : e.setAttribute(t, r)); +} +function Un(e) { + return ( + /** @type {Record} **/ + // @ts-expect-error + e.__attributes ?? (e.__attributes = { + [Il]: e.nodeName.includes("-"), + [Sl]: e.namespaceURI === $i + }) + ); +} +var Jr = /* @__PURE__ */ new Map(); +function Nl(e) { + var t = Jr.get(e.nodeName); + if (t) return t; + Jr.set(e.nodeName, t = []); + for (var r, l = e, i = Element.prototype; i !== l; ) { + r = Si(l); + for (var a in r) + r[a].set && t.push(a); + l = sn(l); + } + return t; +} +function Ll(e, t, r = t) { + wl(e, "change", (l) => { + var i = l ? e.defaultChecked : e.checked; + r(i); + }), // If we are hydrating and the value has since changed, + // then use the update value from the input instead. + (D && e.defaultChecked !== e.checked || // If defaultChecked is set, then checked == defaultChecked + Qe(t) == null) && r(e.checked), er(() => { + var l = t(); + e.checked = !!l; + }); +} +function Kr(e, t) { + return e === t || (e == null ? void 0 : e[ut]) === t; +} +function Xr(e = {}, t, r, l) { + return Qt(() => { + var i, a; + return er(() => { + i = a, a = [], Qe(() => { + e !== r(...a) && (t(e, ...a), i && Kr(r(...i), e) && t(null, ...i)); + }); + }), () => { + Gt(() => { + a && Kr(r(...a), e) && t(null, ...a); + }); + }; + }), e; +} +function jn(e) { + B === null && Tn(), Vt(() => { + const t = Qe(e); + if (typeof t == "function") return ( + /** @type {() => void} */ + t + ); + }); +} +function Dl(e) { + B === null && Tn(), jn(() => () => Qe(e)); +} +let mt = !1; +function Pl(e) { + var t = mt; + try { + return mt = !1, [e(), mt]; + } finally { + mt = t; + } +} +function C(e, t, r, l) { + var be; + var i = (r & wi) !== 0, a = !0, o = (r & yi) !== 0, f = (r & bi) !== 0, s = !1, c; + o ? [c, s] = Pl(() => ( + /** @type {V} */ + e[t] + )) : c = /** @type {V} */ + e[t]; + var v = ut in e || an in e, h = o && (((be = Pe(e, t)) == null ? void 0 : be.set) ?? (v && t in e && ((N) => e[t] = N))) || void 0, g = ( + /** @type {V} */ + l + ), m = !0, w = !1, z = () => (w = !0, m && (m = !1, f ? g = Qe( + /** @type {() => V} */ + l + ) : g = /** @type {V} */ + l), g); + c === void 0 && l !== void 0 && (h && a && ji(), c = z(), h && h(c)); + var T; + if (T = () => { + var N = ( + /** @type {V} */ + e[t] + ); + return N === void 0 ? z() : (m = !0, w = !1, N); + }, (r & pi) === 0) + return T; + if (h) { + var Y = e.$$legacy; + return function(N, X) { + return arguments.length > 0 ? ((!X || Y || s) && h(X ? T() : N), N) : T(); + }; + } + var M = !1, F = /* @__PURE__ */ hn(c), se = /* @__PURE__ */ De(() => { + var N = T(), X = d(F); + return M ? (M = !1, X) : F.v = N; + }); + return i || (se.equals = vn), function(N, X) { + if (arguments.length > 0) { + const U = X ? d(se) : o ? le(N) : N; + return se.equals(U) || (M = !0, P(F, U), w && g !== void 0 && (g = U), Qe(() => d(se))), N; + } + return d(se); + }; +} +function Ol(e) { + return new zl(e); +} +var _e, te; +class zl { + /** + * @param {ComponentConstructorOptions & { + * component: any; + * }} options + */ + constructor(t) { + /** @type {any} */ + Mt(this, _e); + /** @type {Record} */ + Mt(this, te); + var a; + var r = /* @__PURE__ */ new Map(), l = (o, f) => { + var s = /* @__PURE__ */ hn(f); + return r.set(o, s), s; + }; + const i = new Proxy( + { ...t.props || {}, $$events: {} }, + { + get(o, f) { + return d(r.get(f) ?? l(f, Reflect.get(o, f))); + }, + has(o, f) { + return f === an ? !0 : (d(r.get(f) ?? l(f, Reflect.get(o, f))), Reflect.has(o, f)); + }, + set(o, f, s) { + return P(r.get(f) ?? l(f, s), s), Reflect.set(o, f, s); + } + } + ); + Ut(this, te, (t.hydrate ? xl : Fn)(t.component, { + target: t.target, + anchor: t.anchor, + props: i, + context: t.context, + intro: t.intro ?? !1, + recover: t.recover + })), (!((a = t == null ? void 0 : t.props) != null && a.$$host) || t.sync === !1) && $(), Ut(this, _e, i.$$events); + for (const o of Object.keys(H(this, te))) + o === "$set" || o === "$destroy" || o === "$on" || xt(this, o, { + get() { + return H(this, te)[o]; + }, + /** @param {any} value */ + set(f) { + H(this, te)[o] = f; + }, + enumerable: !0 + }); + H(this, te).$set = /** @param {Record} next */ + (o) => { + Object.assign(i, o); + }, H(this, te).$destroy = () => { + $l(H(this, te)); + }; + } + /** @param {Record} props */ + $set(t) { + H(this, te).$set(t); + } + /** + * @param {string} event + * @param {(...args: any[]) => any} callback + * @returns {any} + */ + $on(t, r) { + H(this, _e)[t] = H(this, _e)[t] || []; + const l = (...i) => r.call(this, ...i); + return H(this, _e)[t].push(l), () => { + H(this, _e)[t] = H(this, _e)[t].filter( + /** @param {any} fn */ + (i) => i !== l + ); + }; + } + $destroy() { + H(this, te).$destroy(); + } +} +_e = new WeakMap(), te = new WeakMap(); +let Vn; +typeof HTMLElement == "function" && (Vn = class extends HTMLElement { + /** + * @param {*} $$componentCtor + * @param {*} $$slots + * @param {*} use_shadow_dom + */ + constructor(t, r, l) { + super(); + /** The Svelte component constructor */ + ne(this, "$$ctor"); + /** Slots */ + ne(this, "$$s"); + /** @type {any} The Svelte component instance */ + ne(this, "$$c"); + /** Whether or not the custom element is connected */ + ne(this, "$$cn", !1); + /** @type {Record} Component props data */ + ne(this, "$$d", {}); + /** `true` if currently in the process of reflecting component props back to attributes */ + ne(this, "$$r", !1); + /** @type {Record} Props definition (name, reflected, type etc) */ + ne(this, "$$p_d", {}); + /** @type {Record} Event listeners */ + ne(this, "$$l", {}); + /** @type {Map} Event listener unsubscribe functions */ + ne(this, "$$l_u", /* @__PURE__ */ new Map()); + /** @type {any} The managed render effect for reflecting attributes */ + ne(this, "$$me"); + this.$$ctor = t, this.$$s = r, l && this.attachShadow({ mode: "open" }); + } + /** + * @param {string} type + * @param {EventListenerOrEventListenerObject} listener + * @param {boolean | AddEventListenerOptions} [options] + */ + addEventListener(t, r, l) { + if (this.$$l[t] = this.$$l[t] || [], this.$$l[t].push(r), this.$$c) { + const i = this.$$c.$on(t, r); + this.$$l_u.set(r, i); + } + super.addEventListener(t, r, l); + } + /** + * @param {string} type + * @param {EventListenerOrEventListenerObject} listener + * @param {boolean | AddEventListenerOptions} [options] + */ + removeEventListener(t, r, l) { + if (super.removeEventListener(t, r, l), this.$$c) { + const i = this.$$l_u.get(r); + i && (i(), this.$$l_u.delete(r)); + } + } + async connectedCallback() { + if (this.$$cn = !0, !this.$$c) { + let t = function(i) { + return (a) => { + const o = document.createElement("slot"); + i !== "default" && (o.name = i), ee(a, o); + }; + }; + if (await Promise.resolve(), !this.$$cn || this.$$c) + return; + const r = {}, l = Fl(this); + for (const i of this.$$s) + i in l && (i === "default" && !this.$$d.children ? (this.$$d.children = t(i), r.default = !0) : r[i] = t(i)); + for (const i of this.attributes) { + const a = this.$$g_p(i.name); + a in this.$$d || (this.$$d[a] = pt(a, i.value, this.$$p_d, "toProp")); + } + for (const i in this.$$p_d) + !(i in this.$$d) && this[i] !== void 0 && (this.$$d[i] = this[i], delete this[i]); + this.$$c = Ol({ + component: this.$$ctor, + target: this.shadowRoot || this, + props: { + ...this.$$d, + $$slots: r, + $$host: this + } + }), this.$$me = dl(() => { + er(() => { + var i; + this.$$r = !0; + for (const a of Et(this.$$c)) { + if (!((i = this.$$p_d[a]) != null && i.reflect)) continue; + this.$$d[a] = this.$$c[a]; + const o = pt( + a, + this.$$d[a], + this.$$p_d, + "toAttribute" + ); + o == null ? this.removeAttribute(this.$$p_d[a].attribute || a) : this.setAttribute(this.$$p_d[a].attribute || a, o); + } + this.$$r = !1; + }); + }); + for (const i in this.$$l) + for (const a of this.$$l[i]) { + const o = this.$$c.$on(i, a); + this.$$l_u.set(a, o); + } + this.$$l = {}; + } + } + // We don't need this when working within Svelte code, but for compatibility of people using this outside of Svelte + // and setting attributes through setAttribute etc, this is helpful + /** + * @param {string} attr + * @param {string} _oldValue + * @param {string} newValue + */ + attributeChangedCallback(t, r, l) { + var i; + this.$$r || (t = this.$$g_p(t), this.$$d[t] = pt(t, l, this.$$p_d, "toProp"), (i = this.$$c) == null || i.$set({ [t]: this.$$d[t] })); + } + disconnectedCallback() { + this.$$cn = !1, Promise.resolve().then(() => { + !this.$$cn && this.$$c && (this.$$c.$destroy(), this.$$me(), this.$$c = void 0); + }); + } + /** + * @param {string} attribute_name + */ + $$g_p(t) { + return Et(this.$$p_d).find( + (r) => this.$$p_d[r].attribute === t || !this.$$p_d[r].attribute && r.toLowerCase() === t + ) || t; + } +}); +function pt(e, t, r, l) { + var a; + const i = (a = r[e]) == null ? void 0 : a.type; + if (t = i === "Boolean" && typeof t != "boolean" ? t != null : t, !l || !r[e]) + return t; + if (l === "toAttribute") + switch (i) { + case "Object": + case "Array": + return t == null ? null : JSON.stringify(t); + case "Boolean": + return t ? "" : null; + case "Number": + return t ?? null; + default: + return t; + } + else + switch (i) { + case "Object": + case "Array": + return t && JSON.parse(t); + case "Boolean": + return t; + // conversion already handled above + case "Number": + return t != null ? +t : t; + default: + return t; + } +} +function Fl(e) { + const t = {}; + return e.childNodes.forEach((r) => { + t[ + /** @type {Element} node */ + r.slot || "default" + ] = !0; + }), t; +} +function Ml(e, t, r, l, i, a) { + let o = class extends Vn { + constructor() { + super(e, r, i), this.$$p_d = t; + } + static get observedAttributes() { + return Et(t).map( + (f) => (t[f].attribute || f).toLowerCase() + ); + } + }; + return Et(t).forEach((f) => { + xt(o.prototype, f, { + get() { + return this.$$c && f in this.$$c ? this.$$c[f] : this.$$d[f]; + }, + set(s) { + var h; + s = pt(f, s, t), this.$$d[f] = s; + var c = this.$$c; + if (c) { + var v = (h = Pe(c, f)) == null ? void 0 : h.get; + v ? c[f] = s : c.$set({ [f]: s }); + } + } + }); + }), l.forEach((f) => { + xt(o.prototype, f, { + get() { + var s; + return (s = this.$$c) == null ? void 0 : s[f]; + } + }); + }), e.element = /** @type {any} */ + o, o; +} +const Bn = new TextEncoder(); +function Ul(e) { + return [...new Uint8Array(e)].map((t) => t.toString(16).padStart(2, "0")).join(""); +} +async function jl(e, t = "SHA-256", r = 1e5) { + const l = Date.now().toString(16); + e || (e = Math.round(Math.random() * r)); + const i = await qn(l, e, t); + return { + algorithm: t, + challenge: i, + salt: l, + signature: "" + }; +} +async function qn(e, t, r) { + if (typeof crypto > "u" || !("subtle" in crypto) || !("digest" in crypto.subtle)) + throw new Error("Web Crypto is not available. Secure context is required (https://developer.mozilla.org/en-US/docs/Web/Security/Secure_Contexts)."); + return Ul( + await crypto.subtle.digest( + r.toUpperCase(), + Bn.encode(e + t) + ) + ); +} +function Vl(e, t, r = "SHA-256", l = 1e6, i = 0) { + const a = new AbortController(), o = Date.now(); + return { + promise: (async () => { + for (let s = i; s <= l; s += 1) { + if (a.signal.aborted) + return null; + if (await qn(t, s, r) === e) + return { + number: s, + took: Date.now() - o + }; + } + return null; + })(), + controller: a + }; +} +function Bl() { + try { + return Intl.DateTimeFormat().resolvedOptions().timeZone; + } catch { + } +} +function ql(e) { + const t = atob(e), r = new Uint8Array(t.length); + for (let l = 0; l < t.length; l++) + r[l] = t.charCodeAt(l); + return r; +} +function Hl(e, t = 12) { + const r = new Uint8Array(t); + for (let l = 0; l < t; l++) + r[l] = e % 256, e = Math.floor(e / 256); + return r; +} +async function Wl(e, t = "", r = 1e6, l = 0) { + const i = "AES-GCM", a = new AbortController(), o = Date.now(), f = async () => { + for (let v = l; v <= r; v += 1) { + if (a.signal.aborted || !s || !c) + return null; + try { + const h = await crypto.subtle.decrypt( + { + name: i, + iv: Hl(v) + }, + s, + c + ); + if (h) + return { + clearText: new TextDecoder().decode(h), + took: Date.now() - o + }; + } catch { + } + } + return null; + }; + let s = null, c = null; + try { + c = ql(e); + const v = await crypto.subtle.digest( + "SHA-256", + Bn.encode(t) + ); + s = await crypto.subtle.importKey( + "raw", + v, + i, + !1, + ["decrypt"] + ); + } catch { + return { + promise: Promise.reject(), + controller: a + }; + } + return { + promise: f(), + controller: a + }; +} +var E = /* @__PURE__ */ ((e) => (e.ERROR = "error", e.VERIFIED = "verified", e.VERIFYING = "verifying", e.UNVERIFIED = "unverified", e.EXPIRED = "expired", e))(E || {}), Yl = /* @__PURE__ */ El(''), Zl = /* @__PURE__ */ ve(' ', 1), Gl = /* @__PURE__ */ ve(''), Jl = /* @__PURE__ */ ve(''), Kl = /* @__PURE__ */ ve('
'), Xl = /* @__PURE__ */ ve('
'), Ql = /* @__PURE__ */ ve('
'), ea = /* @__PURE__ */ ve('
'), ta = /* @__PURE__ */ ve(''), ra = /* @__PURE__ */ ve('
'), na = /* @__PURE__ */ ve('
', 1); +const ia = { + hash: "svelte-ddsc3z", + code: `.altcha.svelte-ddsc3z {background:var(--altcha-color-base, transparent);border:var(--altcha-border-width, 1px) solid var(--altcha-color-border, #a0a0a0);border-radius:var(--altcha-border-radius, 3px);color:var(--altcha-color-text, currentColor);display:flex;flex-direction:column;max-width:var(--altcha-max-width, 260px);position:relative;text-align:left;}.altcha.svelte-ddsc3z:focus-within {border-color:var(--altcha-color-border-focus, currentColor);}.altcha[data-floating].svelte-ddsc3z {background:var(--altcha-color-base, white);display:none;filter:drop-shadow(3px 3px 6px rgba(0, 0, 0, 0.2));left:-100%;position:fixed;top:-100%;width:var(--altcha-max-width, 260px);z-index:999999;}.altcha[data-floating=top].svelte-ddsc3z .altcha-anchor-arrow:where(.svelte-ddsc3z) {border-bottom-color:transparent;border-top-color:var(--altcha-color-border, #a0a0a0);bottom:-12px;top:auto;}.altcha[data-floating=bottom].svelte-ddsc3z:focus-within::after {border-bottom-color:var(--altcha-color-border-focus, currentColor);}.altcha[data-floating=top].svelte-ddsc3z:focus-within::after {border-top-color:var(--altcha-color-border-focus, currentColor);}.altcha[data-floating].svelte-ddsc3z:not([data-state=unverified]) {display:block;}.altcha-anchor-arrow.svelte-ddsc3z {border:6px solid transparent;border-bottom-color:var(--altcha-color-border, #a0a0a0);content:"";height:0;left:12px;position:absolute;top:-12px;width:0;}.altcha-main.svelte-ddsc3z {align-items:center;display:flex;gap:0.4rem;padding:0.7rem;}.altcha-label.svelte-ddsc3z {flex-grow:1;}.altcha-label.svelte-ddsc3z label:where(.svelte-ddsc3z) {cursor:pointer;}.altcha-logo.svelte-ddsc3z {color:currentColor;opacity:0.3;}.altcha-logo.svelte-ddsc3z:hover {opacity:1;}.altcha-error.svelte-ddsc3z {color:var(--altcha-color-error-text, #f23939);display:flex;font-size:0.85rem;gap:0.3rem;padding:0 0.7rem 0.7rem;}.altcha-footer.svelte-ddsc3z {align-items:center;background-color:var(--altcha-color-footer-bg, transparent);display:flex;font-size:0.75rem;opacity:0.4;padding:0.2rem 0.7rem;text-align:right;}.altcha-footer.svelte-ddsc3z:hover {opacity:1;}.altcha-footer.svelte-ddsc3z > :where(.svelte-ddsc3z):first-child {flex-grow:1;}.altcha-footer.svelte-ddsc3z a {color:currentColor;}.altcha-checkbox.svelte-ddsc3z {display:flex;align-items:center;height:24px;width:24px;}.altcha-checkbox.svelte-ddsc3z input:where(.svelte-ddsc3z) {width:18px;height:18px;margin:0;}.altcha-hidden.svelte-ddsc3z {display:none;}.altcha-spinner.svelte-ddsc3z { + animation: svelte-ddsc3z-altcha-spinner 0.75s infinite linear;transform-origin:center;} + +@keyframes svelte-ddsc3z-altcha-spinner { + 100% { + transform: rotate(360deg); + } +}` +}; +function la(e, t) { + var Lr, Dr; + Nn(t, !0), Cl(e, ia); + let r = C(t, "auto", 7, void 0), l = C(t, "blockspam", 7, void 0), i = C(t, "challengeurl", 7, void 0), a = C(t, "challengejson", 7, void 0), o = C(t, "customfetch", 7, void 0), f = C(t, "debug", 7, !1), s = C(t, "delay", 7, 0), c = C(t, "expire", 7, void 0), v = C(t, "floating", 7, void 0), h = C(t, "floatinganchor", 7, void 0), g = C(t, "floatingoffset", 7, void 0), m = C(t, "hidefooter", 7, !1), w = C(t, "hidelogo", 7, !1), z = C(t, "id", 7, void 0), T = C(t, "name", 7, "altcha"), Y = C(t, "maxnumber", 7, 1e6), M = C(t, "mockerror", 7, !1), F = C(t, "obfuscated", 7, void 0), se = C(t, "plugins", 7, void 0), be = C(t, "refetchonexpire", 7, !0), N = C(t, "spamfilter", 7, !1), X = C(t, "strings", 7, void 0), U = C(t, "test", 7, !1), Ee = C(t, "verifyurl", 7, void 0), Me = C(t, "workers", 23, () => Math.min(16, navigator.hardwareConcurrency || 8)), tt = C(t, "workerurl", 7, void 0); + const nr = ["SHA-256", "SHA-384", "SHA-512"], ir = "Visit Altcha.org", lr = "https://altcha.org/", rt = (n, u) => { + t.$$host.dispatchEvent(new CustomEvent(n, { detail: u })); + }, ar = (Dr = (Lr = document.documentElement.lang) == null ? void 0 : Lr.split("-")) == null ? void 0 : Dr[0], Dt = /* @__PURE__ */ De(() => { + var n; + return i() && new URL(i(), location.origin).host.endsWith(".altcha.org") && !!((n = i()) != null && n.includes("apiKey=ckey_")); + }), Pt = /* @__PURE__ */ De(() => a() ? wr(a()) : void 0), or = /* @__PURE__ */ De(() => X() ? wr(X()) : {}), Q = /* @__PURE__ */ De(() => { + var n; + return { + ariaLinkLabel: ir, + error: "Verification failed. Try again later.", + expired: "Verification expired. Try again.", + footer: `Protected by ALTCHA`, + label: "I'm not a robot", + verified: "Verified", + verifying: "Verifying...", + waitAlert: "Verifying... please wait.", + ...d(or) + }; + }), sr = /* @__PURE__ */ De(() => z() || `${T()}_checkbox`); + let Ue = He(!1), R = He(le(E.UNVERIFIED)), j = He(void 0), nt = He(null), je = null, y = null, Ve = He(null), fe = null, xe = [], Ne = He(null); + Vt(() => { + Xn(d(Ve)); + }), Vt(() => { + Qn(d(R)); + }), Dl(() => { + Hn(), y && (y.removeEventListener("submit", hr), y.removeEventListener("reset", gr), y.removeEventListener("focusin", vr), y = null), fe && (clearTimeout(fe), fe = null), document.removeEventListener("click", cr), document.removeEventListener("scroll", dr), window.removeEventListener("resize", mr); + }), jn(() => { + var n; + I("mounted", "1.3.0"), I("workers", Me()), Jn(), I("plugins", xe.length ? xe.map((u) => u.constructor.pluginName).join(", ") : "none"), U() && I("using test mode"), c() && Ot(c()), r() !== void 0 && I("auto", r()), v() !== void 0 && pr(v()), y = (n = d(j)) == null ? void 0 : n.closest("form"), y && (y.addEventListener("submit", hr, { capture: !0 }), y.addEventListener("reset", gr), r() === "onfocus" && y.addEventListener("focusin", vr)), r() === "onload" && (F() ? it() : $e()), d(Dt) && (m() || w()) && I("Attributes hidefooter and hidelogo ignored because usage with free API Keys requires attribution."), requestAnimationFrame(() => { + rt("load"); + }); + }); + function fr(n, u) { + return btoa(JSON.stringify({ + algorithm: n.algorithm, + challenge: n.challenge, + number: u.number, + salt: n.salt, + signature: n.signature, + test: U() ? !0 : void 0, + took: u.took + })); + } + function Hn() { + for (const n of xe) + n.destroy(); + } + function ur() { + i() && be() && d(R) === E.VERIFIED ? $e() : lt(E.EXPIRED, d(Q).expired); + } + async function Wn() { + var n; + if (M()) + throw I("mocking error"), new Error("Mocked error."); + if (d(Pt)) + return I("using provided json data"), d(Pt); + if (U()) + return I("generating test challenge", { test: U() }), jl(typeof U() != "boolean" ? +U() : void 0); + { + if (!i() && y) { + const L = y.getAttribute("action"); + L != null && L.includes("/form/") && i(L + "/altcha"); + } + if (!i()) + throw new Error("Attribute challengeurl not set."); + I("fetching challenge from", i()); + let u = null, _ = null; + if (o()) + if (I("using customfetch"), typeof o() == "string") { + if (u = globalThis[o()] || null, !u) + throw new Error(`Custom fetch function not found: ${o()}`); + } else + u = o(); + const b = { + headers: N() !== !1 ? { "x-altcha-spam-filter": "1" } : {} + }; + if (u) { + if (_ = await u(i(), b), !_ || !(_ instanceof Response)) + throw new Error("Custom fetch function did not return a response."); + } else + _ = await fetch(i(), b); + if (_.status !== 200) + throw new Error(`Server responded with ${_.status}.`); + const S = _.headers.get("X-Altcha-Config"), x = await _.json(), p = new URLSearchParams((n = x.salt.split("?")) == null ? void 0 : n[1]), q = p.get("expires") || p.get("expire"); + if (q) { + const L = new Date(+q * 1e3), qe = isNaN(L.getTime()) ? 0 : L.getTime() - Date.now(); + qe > 0 && Ot(qe); + } + if (S) + try { + const L = JSON.parse(S); + L && typeof L == "object" && (L.verifyurl && (L.verifyurl = new URL(L.verifyurl, new URL(i())).toString()), Er(L)); + } catch (L) { + I("unable to configure from X-Altcha-Config", L); + } + return x; + } + } + function Yn(n) { + var _; + const u = y == null ? void 0 : y.querySelector(typeof n == "string" ? `input[name="${n}"]` : 'input[type="email"]:not([data-no-spamfilter])'); + return ((_ = u == null ? void 0 : u.value) == null ? void 0 : _.slice(u.value.indexOf("@"))) || void 0; + } + function Zn() { + return N() === "ipAddress" ? { + blockedCountries: void 0, + classifier: void 0, + disableRules: void 0, + email: !1, + expectedCountries: void 0, + expectedLanguages: void 0, + fields: !1, + ipAddress: void 0, + text: void 0, + timeZone: void 0 + } : typeof N() == "object" ? N() : { + blockedCountries: void 0, + classifier: void 0, + disableRules: void 0, + email: void 0, + expectedCountries: void 0, + expectedLanguages: void 0, + fields: void 0, + ipAddress: void 0, + text: void 0, + timeZone: void 0 + }; + } + function Gn(n) { + return [ + ...(y == null ? void 0 : y.querySelectorAll(n != null && n.length ? n.map((_) => `input[name="${_}"]`).join(", ") : 'input[type="text"]:not([data-no-spamfilter]), textarea:not([data-no-spamfilter])')) || [] + ].reduce( + (_, b) => { + const S = b.name, x = b.value; + return S && x && (_[S] = /\n/.test(x) ? x.replace(new RegExp("(? u instanceof Error)) && console[n[0] instanceof Error ? "error" : "log"]("ALTCHA", `[name=${T()}]`, ...n); + } + function Kn() { + [E.UNVERIFIED, E.ERROR, E.EXPIRED].includes(d(R)) ? N() !== !1 && (y == null ? void 0 : y.reportValidity()) === !1 ? P(Ue, !1) : F() ? it() : $e() : P(Ue, !0); + } + function cr(n) { + const u = n.target; + v() && u && !d(j).contains(u) && (d(R) === E.VERIFIED || r() === "off" && d(R) === E.UNVERIFIED) && (d(j).style.display = "none"); + } + function dr() { + v() && d(R) !== E.UNVERIFIED && gt(); + } + function Xn(n) { + for (const u of xe) + typeof u.onErrorChange == "function" && u.onErrorChange(d(Ve)); + } + function vr(n) { + d(R) === E.UNVERIFIED && $e(); + } + function hr(n) { + y && r() === "onsubmit" ? d(R) === E.UNVERIFIED ? (n.preventDefault(), n.stopPropagation(), $e().then(() => { + y == null || y.requestSubmit(); + })) : d(R) !== E.VERIFIED && (n.preventDefault(), n.stopPropagation(), d(R) === E.VERIFYING && _r()) : y && v() && r() === "off" && d(R) === E.UNVERIFIED && (n.preventDefault(), n.stopPropagation(), d(j).style.display = "block", gt()); + } + function gr() { + lt(); + } + function _r() { + d(R) === E.VERIFYING && d(Q).waitAlert && alert(d(Q).waitAlert); + } + function Qn(n) { + for (const u of xe) + typeof u.onStateChange == "function" && u.onStateChange(d(R)); + v() && d(R) !== E.UNVERIFIED && requestAnimationFrame(() => { + gt(); + }), P(Ue, d(R) === E.VERIFIED); + } + function mr() { + v() && gt(); + } + function wr(n) { + return JSON.parse(n); + } + function gt(n = 20) { + if (d(j)) + if (je || (je = (h() ? document.querySelector(h()) : y == null ? void 0 : y.querySelector('input[type="submit"], button[type="submit"], button:not([type="button"]):not([type="reset"])')) || y), je) { + const u = parseInt(g(), 10) || 12, _ = je.getBoundingClientRect(), b = d(j).getBoundingClientRect(), S = document.documentElement.clientHeight, x = document.documentElement.clientWidth, p = v() === "auto" ? _.bottom + b.height + u + n > S : v() === "top", q = Math.max(n, Math.min(x - n - b.width, _.left + _.width / 2 - b.width / 2)); + if (p ? d(j).style.top = `${_.top - (b.height + u)}px` : d(j).style.top = `${_.bottom + u}px`, d(j).style.left = `${q}px`, d(j).setAttribute("data-floating", p ? "top" : "bottom"), d(nt)) { + const L = d(nt).getBoundingClientRect(); + d(nt).style.left = _.left - q + _.width / 2 - L.width / 2 + "px"; + } + } else + I("unable to find floating anchor element"); + } + async function ei(n) { + if (!Ee()) + throw new Error("Attribute verifyurl not set."); + I("requesting server verification from", Ee()); + const u = { payload: n }; + if (N() !== !1) { + const { + blockedCountries: S, + classifier: x, + disableRules: p, + email: q, + expectedLanguages: L, + expectedCountries: qe, + fields: ot, + ipAddress: st, + text: vi, + timeZone: Pr + } = Zn(); + u.blockedCountries = S, u.classifier = x, u.disableRules = p, u.email = q === !1 ? void 0 : Yn(q), u.expectedCountries = qe, u.expectedLanguages = L || (ar ? [ar] : void 0), u.fields = ot === !1 ? void 0 : Gn(ot), u.ipAddress = st === !1 ? void 0 : st || "auto", u.text = vi, u.timeZone = Pr === !1 ? void 0 : Pr || Bl(); + } + const _ = await fetch(Ee(), { + body: JSON.stringify(u), + headers: { "content-type": "application/json" }, + method: "POST" + }); + if (_.status !== 200) + throw new Error(`Server responded with ${_.status}.`); + const b = await _.json(); + if (b != null && b.payload && P(Ne, le(b.payload)), rt("serververification", b), l() && b.classification === "BAD") + throw new Error("SpamFilter returned negative classification."); + } + function Ot(n) { + I("expire", n), fe && (clearTimeout(fe), fe = null), n < 1 ? ur() : fe = setTimeout(ur, n); + } + function pr(n) { + I("floating", n), v() !== n && (d(j).style.left = "", d(j).style.top = ""), v(n === !0 || n === "" ? "auto" : n === !1 || n === "false" ? void 0 : v()), v() ? (r() || r("onsubmit"), document.addEventListener("scroll", dr), document.addEventListener("click", cr), window.addEventListener("resize", mr)) : r() === "onsubmit" && r(void 0); + } + function yr(n) { + if (!n.algorithm) + throw new Error("Invalid challenge. Property algorithm is missing."); + if (n.signature === void 0) + throw new Error("Invalid challenge. Property signature is missing."); + if (!nr.includes(n.algorithm.toUpperCase())) + throw new Error(`Unknown algorithm value. Allowed values: ${nr.join(", ")}`); + if (!n.challenge || n.challenge.length < 40) + throw new Error("Challenge is too short. Min. 40 chars."); + if (!n.salt || n.salt.length < 10) + throw new Error("Salt is too short. Min. 10 chars."); + } + async function br(n) { + let u = null; + if ("Worker" in window) { + try { + u = await ti(n, n.maxnumber); + } catch (_) { + I(_); + } + if ((u == null ? void 0 : u.number) !== void 0 || "obfuscated" in n) + return { data: n, solution: u }; + } + if ("obfuscated" in n) { + const _ = await Wl(n.obfuscated, n.key, n.maxnumber); + return { data: n, solution: await _.promise }; + } + return { + data: n, + solution: await Vl(n.challenge, n.salt, n.algorithm, n.maxnumber || Y()).promise + }; + } + async function ti(n, u = typeof U() == "number" ? U() : Y(), _ = Math.ceil(Me())) { + const b = []; + _ = Math.min(16, Math.max(1, _)); + for (let p = 0; p < _; p++) + b.push(altchaCreateWorker(tt())); + const S = Math.ceil(u / _), x = await Promise.all(b.map((p, q) => { + const L = q * S; + return new Promise((qe) => { + p.addEventListener("message", (ot) => { + if (ot.data) + for (const st of b) + st !== p && st.postMessage({ type: "abort" }); + qe(ot.data); + }), p.postMessage({ + payload: n, + max: L + S, + start: L, + type: "work" + }); + }); + })); + for (const p of b) + p.terminate(); + return x.find((p) => !!p) || null; + } + async function it() { + if (!F()) { + Le(E.ERROR); + return; + } + const n = xe.find((u) => u.constructor.pluginName === "obfuscation"); + if (!n || !("clarify" in n)) { + Le(E.ERROR), I("Plugin `obfuscation` not found. Import `altcha/plugins/obfuscation` to load it."); + return; + } + if ("clarify" in n && typeof n.clarify == "function") + return n.clarify(); + } + function Er(n) { + n.obfuscated !== void 0 && F(n.obfuscated), n.auto !== void 0 && (r(n.auto), r() === "onload" && (F() ? it() : $e())), n.blockspam !== void 0 && l(!!n.blockspam), n.customfetch !== void 0 && o(n.customfetch), n.floatinganchor !== void 0 && h(n.floatinganchor), n.delay !== void 0 && s(n.delay), n.floatingoffset !== void 0 && g(n.floatingoffset), n.floating !== void 0 && pr(n.floating), n.expire !== void 0 && (Ot(n.expire), c(n.expire)), n.challenge && (a(typeof n.challenge == "string" ? n.challenge : JSON.stringify(n.challenge)), yr(d(Pt))), n.challengeurl !== void 0 && i(n.challengeurl), n.debug !== void 0 && f(!!n.debug), n.hidefooter !== void 0 && m(!!n.hidefooter), n.hidelogo !== void 0 && w(!!n.hidelogo), n.maxnumber !== void 0 && Y(+n.maxnumber), n.mockerror !== void 0 && M(!!n.mockerror), n.name !== void 0 && T(n.name), n.refetchonexpire !== void 0 && be(!!n.refetchonexpire), n.spamfilter !== void 0 && N(typeof n.spamfilter == "object" ? n.spamfilter : !!n.spamfilter), n.strings && X(typeof n.strings == "string" ? n.strings : JSON.stringify(n.strings)), n.test !== void 0 && U(typeof n.test == "number" ? n.test : !!n.test), n.verifyurl !== void 0 && Ee(n.verifyurl), n.workers !== void 0 && Me(+n.workers), n.workerurl !== void 0 && tt(n.workerurl); + } + function xr() { + return { + auto: r(), + blockspam: l(), + challengeurl: i(), + debug: f(), + delay: s(), + expire: c(), + floating: v(), + floatinganchor: h(), + floatingoffset: g(), + hidefooter: m(), + hidelogo: w(), + name: T(), + maxnumber: Y(), + mockerror: M(), + obfuscated: F(), + refetchonexpire: be(), + spamfilter: N(), + strings: d(Q), + test: U(), + verifyurl: Ee(), + workers: Me(), + workerurl: tt() + }; + } + function $r() { + return je; + } + function ri(n) { + return xe.find((u) => u.constructor.pluginName === n); + } + function kr() { + return d(R); + } + function lt(n = E.UNVERIFIED, u = null) { + fe && (clearTimeout(fe), fe = null), P(Ue, !1), P(Ne, null), Le(n, u); + } + function Cr(n) { + je = n; + } + function Le(n, u = null) { + P(R, le(n)), P(Ve, le(u)), rt("statechange", { + payload: d(Ne), + state: d(R) + }); + } + async function $e() { + return lt(E.VERIFYING), await new Promise((n) => setTimeout(n, s() || 0)), Wn().then((n) => (yr(n), I("challenge", n), br(n))).then(({ data: n, solution: u }) => { + if (I("solution", u), "challenge" in n && u && !("clearText" in u)) + if ((u == null ? void 0 : u.number) !== void 0) { + if (Ee()) + return ei(fr(n, u)); + P(Ne, le(fr(n, u))), I("payload", d(Ne)); + } else + throw I("Unable to find a solution. Ensure that the 'maxnumber' attribute is greater than the randomly generated number."), new Error("Unexpected result returned."); + }).then(() => { + Le(E.VERIFIED), I("verified"), ol().then(() => { + rt("verified", { payload: d(Ne) }); + }); + }).catch((n) => { + I(n), Le(E.ERROR, n.message); + }); + } + var Ar = na(), Rr = Br(Ar); + kl(Rr, t, "default", {}); + var at = he(Rr, 2), zt = G(at), Ir = G(zt); + { + var ni = (n) => { + var u = Yl(); + ee(n, u); + }; + ke(Ir, (n) => { + d(R) === E.VERIFYING && n(ni); + }); + } + var _t = he(Ir, 2); + let Sr; + var Be = G(_t); + Gr(Be), Be.__change = Kn, Z(_t); + var Ft = he(_t, 2), ii = G(Ft); + { + var li = (n) => { + var u = Zl(), _ = Br(u), b = G(_); + Ze(b, () => d(Q).verified), Z(_); + var S = he(_, 2); + Gr(S), We(() => { + ie(S, "name", T()), Tl(S, d(Ne)); + }), ee(n, u); + }, ai = (n, u) => { + { + var _ = (S) => { + var x = Gl(), p = G(x); + Ze(p, () => d(Q).verifying), Z(x), ee(S, x); + }, b = (S) => { + var x = Jl(), p = G(x); + Ze(p, () => d(Q).label), Z(x), We(() => ie(x, "for", d(sr))), ee(S, x); + }; + ke( + n, + (S) => { + d(R) === E.VERIFYING ? S(_) : S(b, !1); + }, + u + ); + } + }; + ke(ii, (n) => { + d(R) === E.VERIFIED ? n(li) : n(ai, !1); + }); + } + Z(Ft); + var oi = he(Ft, 2); + { + var si = (n) => { + var u = Kl(), _ = G(u); + ie(_, "href", lr), Z(u), We(() => ie(_, "aria-label", d(Q).ariaLinkLabel)), ee(n, u); + }; + ke(oi, (n) => { + (w() !== !0 || d(Dt)) && n(si); + }); + } + Z(zt); + var Tr = he(zt, 2); + { + var fi = (n) => { + var u = ea(), _ = he(G(u), 2); + { + var b = (x) => { + var p = Xl(), q = G(p); + Ze(q, () => d(Q).expired), Z(p), We(() => ie(p, "title", d(Ve))), ee(x, p); + }, S = (x) => { + var p = Ql(), q = G(p); + Ze(q, () => d(Q).error), Z(p), We(() => ie(p, "title", d(Ve))), ee(x, p); + }; + ke(_, (x) => { + d(R) === E.EXPIRED ? x(b) : x(S, !1); + }); + } + Z(u), ee(n, u); + }; + ke(Tr, (n) => { + (d(Ve) || d(R) === E.EXPIRED) && n(fi); + }); + } + var Nr = he(Tr, 2); + { + var ui = (n) => { + var u = ta(), _ = G(u), b = G(_); + Ze(b, () => d(Q).footer), Z(_), Z(u), ee(n, u); + }; + ke(Nr, (n) => { + d(Q).footer && (m() !== !0 || d(Dt)) && n(ui); + }); + } + var ci = he(Nr, 2); + { + var di = (n) => { + var u = ra(); + Xr(u, (_) => P(nt, _), () => d(nt)), ee(n, u); + }; + ke(ci, (n) => { + v() && n(di); + }); + } + return Z(at), Xr(at, (n) => P(j, n), () => d(j)), We( + (n) => { + ie(at, "data-state", d(R)), ie(at, "data-floating", v()), Sr = Rl(_t, 1, "altcha-checkbox svelte-ddsc3z", null, Sr, n), ie(Be, "id", d(sr)), Be.required = r() !== "onsubmit" && (!v() || r() !== "off"); + }, + [ + () => ({ + "altcha-hidden": d(R) === E.VERIFYING + }) + ] + ), yl("invalid", Be, _r), Ll(Be, () => d(Ue), (n) => P(Ue, n)), ee(e, Ar), Ln({ + clarify: it, + configure: Er, + getConfiguration: xr, + getFloatingAnchor: $r, + getPlugin: ri, + getState: kr, + reset: lt, + setFloatingAnchor: Cr, + setState: Le, + verify: $e, + get auto() { + return r(); + }, + set auto(n = void 0) { + r(n), $(); + }, + get blockspam() { + return l(); + }, + set blockspam(n = void 0) { + l(n), $(); + }, + get challengeurl() { + return i(); + }, + set challengeurl(n = void 0) { + i(n), $(); + }, + get challengejson() { + return a(); + }, + set challengejson(n = void 0) { + a(n), $(); + }, + get customfetch() { + return o(); + }, + set customfetch(n = void 0) { + o(n), $(); + }, + get debug() { + return f(); + }, + set debug(n = !1) { + f(n), $(); + }, + get delay() { + return s(); + }, + set delay(n = 0) { + s(n), $(); + }, + get expire() { + return c(); + }, + set expire(n = void 0) { + c(n), $(); + }, + get floating() { + return v(); + }, + set floating(n = void 0) { + v(n), $(); + }, + get floatinganchor() { + return h(); + }, + set floatinganchor(n = void 0) { + h(n), $(); + }, + get floatingoffset() { + return g(); + }, + set floatingoffset(n = void 0) { + g(n), $(); + }, + get hidefooter() { + return m(); + }, + set hidefooter(n = !1) { + m(n), $(); + }, + get hidelogo() { + return w(); + }, + set hidelogo(n = !1) { + w(n), $(); + }, + get id() { + return z(); + }, + set id(n = void 0) { + z(n), $(); + }, + get name() { + return T(); + }, + set name(n = "altcha") { + T(n), $(); + }, + get maxnumber() { + return Y(); + }, + set maxnumber(n = 1e6) { + Y(n), $(); + }, + get mockerror() { + return M(); + }, + set mockerror(n = !1) { + M(n), $(); + }, + get obfuscated() { + return F(); + }, + set obfuscated(n = void 0) { + F(n), $(); + }, + get plugins() { + return se(); + }, + set plugins(n = void 0) { + se(n), $(); + }, + get refetchonexpire() { + return be(); + }, + set refetchonexpire(n = !0) { + be(n), $(); + }, + get spamfilter() { + return N(); + }, + set spamfilter(n = !1) { + N(n), $(); + }, + get strings() { + return X(); + }, + set strings(n = void 0) { + X(n), $(); + }, + get test() { + return U(); + }, + set test(n = !1) { + U(n), $(); + }, + get verifyurl() { + return Ee(); + }, + set verifyurl(n = void 0) { + Ee(n), $(); + }, + get workers() { + return Me(); + }, + set workers(n = Math.min(16, navigator.hardwareConcurrency || 8)) { + Me(n), $(); + }, + get workerurl() { + return tt(); + }, + set workerurl(n = void 0) { + tt(n), $(); + } + }); +} +bl(["change"]); +customElements.define("altcha-widget", Ml( + la, + { + blockspam: { type: "Boolean" }, + debug: { type: "Boolean" }, + delay: { type: "Number" }, + expire: { type: "Number" }, + floatingoffset: { type: "Number" }, + hidefooter: { type: "Boolean" }, + hidelogo: { type: "Boolean" }, + maxnumber: { type: "Number" }, + mockerror: { type: "Boolean" }, + refetchonexpire: { type: "Boolean" }, + test: { type: "Boolean" }, + workers: { type: "Number" }, + auto: {}, + challengeurl: {}, + challengejson: {}, + customfetch: {}, + floating: {}, + floatinganchor: {}, + id: {}, + name: {}, + obfuscated: {}, + plugins: {}, + spamfilter: {}, + strings: {}, + verifyurl: {}, + workerurl: {} + }, + ["default"], + [ + "clarify", + "configure", + "getConfiguration", + "getFloatingAnchor", + "getPlugin", + "getState", + "reset", + "setFloatingAnchor", + "setState", + "verify" + ], + !1 +)); +globalThis.altchaCreateWorker = (e) => e ? new Worker(new URL(e)) : new _i(); +globalThis.altchaPlugins = globalThis.altchaPlugins || []; +export { + la as Altcha +}; \ No newline at end of file diff --git a/static/python/rename_files.py b/static/python/rename_files.py new file mode 100644 index 0000000..0a9202d --- /dev/null +++ b/static/python/rename_files.py @@ -0,0 +1,21 @@ +import os + +dir_parent = os.path.abspath(__file__ + '/../..') +dir_sql = os.path.abspath(dir_parent + '/sql') + + +# METHODS +for entry in os.scandir(dir_sql): + if entry.is_file(): + if '_tbl_' in entry.name: + + new_name = entry.name + i_underscore = 6 + while i_underscore > 0: + i_underscore = new_name.find('_', i_underscore + 1) + new_name = new_name[:i_underscore + 1] + new_name[i_underscore + 1].upper() + new_name[i_underscore + 2:] + os.rename(entry.path, dir_sql + '/' + new_name) + if entry.is_dir(): + pass + +# SELECT CONCAT('WARNING: Table ', TABLE_NAME, ' already exists.') AS msg_warning FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Shop_Msg_Error_Type'; \ No newline at end of file diff --git a/templates/_shared.html b/templates/_shared.html new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/templates/_shared.html @@ -0,0 +1 @@ + diff --git a/templates/components/common/buttons/_buttons_save_cancel.html b/templates/components/common/buttons/_buttons_save_cancel.html new file mode 100644 index 0000000..512d65b --- /dev/null +++ b/templates/components/common/buttons/_buttons_save_cancel.html @@ -0,0 +1,50 @@ +{% if block_id == 'button_save' %} + +{% elif block_id == 'button_cancel' %} + +{% elif block_id == 'button_add' %} + +{% elif block_id == 'button_confirm' %} + +{% elif block_id == 'button_get_in_touch' %} + +{% elif block_id == 'button_apply_filters' %} + +{% elif block_id == 'button_clear_filters' %} +{% elif block_id == 'buttons_table_default' %} +
+
+
+ {% set block_id = 'button_apply_filters' %} + {% include 'components/common/buttons/_buttons_save_cancel.html' %} +
+ {# +
+ {% set block_id = 'button_add' %} + {% include 'components/common/buttons/_buttons_save_cancel.html' %} +
+ #} +
+
+ {% set block_id = 'button_save' %} + {% include 'components/common/buttons/_buttons_save_cancel.html' %} +
+
+ {% set block_id = 'button_cancel' %} + {% include 'components/common/buttons/_buttons_save_cancel.html' %} +
+
+
+
+{% elif block_id == 'container_buttons_save_cancel' %} +
+
+ {% set block_id = 'button_save' %} + {% include 'components/common/buttons/_buttons_save_cancel.html' %} +
+
+ {% set block_id = 'button_cancel' %} + {% include 'components/common/buttons/_buttons_save_cancel.html' %} +
+
+{% endif %} \ No newline at end of file diff --git a/templates/components/common/buttons/_slider_display_order.html b/templates/components/common/buttons/_slider_display_order.html new file mode 100644 index 0000000..af2d719 --- /dev/null +++ b/templates/components/common/buttons/_slider_display_order.html @@ -0,0 +1,13 @@ +{% if display_order is defined %} +{# Fix this +
+#} + +{% else %} + +{# +
+#} +{% endif %} \ No newline at end of file diff --git a/templates/components/common/inputs/_input_number_plus_minus.html b/templates/components/common/inputs/_input_number_plus_minus.html new file mode 100644 index 0000000..906f8db --- /dev/null +++ b/templates/components/common/inputs/_input_number_plus_minus.html @@ -0,0 +1,17 @@ + + +
+
+
-
+
+
+ {{ form.quantity(value=tmp_quantity) }} +
+
+
+
+
+
\ No newline at end of file diff --git a/templates/components/common/inputs/_option_blank.html b/templates/components/common/inputs/_option_blank.html new file mode 100644 index 0000000..5174fd8 --- /dev/null +++ b/templates/components/common/inputs/_option_blank.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/templates/components/common/temporary/_overlay_address.html b/templates/components/common/temporary/_overlay_address.html new file mode 100644 index 0000000..e35992d --- /dev/null +++ b/templates/components/common/temporary/_overlay_address.html @@ -0,0 +1,10 @@ +{% extends '_template_overlay.html' %} + + +{% block overlay_body %} + {% include 'components/store/_address.html' %} +{% endblock %} \ No newline at end of file diff --git a/templates/components/common/temporary/_overlay_confirm.html b/templates/components/common/temporary/_overlay_confirm.html new file mode 100644 index 0000000..a086d9c --- /dev/null +++ b/templates/components/common/temporary/_overlay_confirm.html @@ -0,0 +1,14 @@ + diff --git a/templates/components/common/temporary/_overlay_error.html b/templates/components/common/temporary/_overlay_error.html new file mode 100644 index 0000000..96dc9df --- /dev/null +++ b/templates/components/common/temporary/_overlay_error.html @@ -0,0 +1,10 @@ + diff --git a/templates/components/common/temporary/template_overlay.html b/templates/components/common/temporary/template_overlay.html new file mode 100644 index 0000000..464f817 --- /dev/null +++ b/templates/components/common/temporary/template_overlay.html @@ -0,0 +1,23 @@ + + + + +
+
+
+
+

{{ overlay_title }}

+
+
+ +
+
+
+ {% block overlay_body %}{% endblock %} +
+
+
+ diff --git a/templates/js/sections/store.js b/templates/js/sections/store.js new file mode 100644 index 0000000..b576a3b --- /dev/null +++ b/templates/js/sections/store.js @@ -0,0 +1,155 @@ + +var attrFormType = "{{ model.ATTR_FORM_TYPE }}"; +var attrIdCustomer = "{{ model.ATTR_ID_CUSTOMER }}"; +var attrIdCustomerAddress = "{{ model.ATTR_ID_CUSTOMER_ADDRESS }}"; +var attrIdCustomerSalesOrder = "{{ model.ATTR_ID_CUSTOMER_SALES_ORDER }}"; +var attrIdDiscount = "{{ model.ATTR_ID_DISCOUNT }}"; +var attrIdManufacturingPurchaseOrder = "{{ model.ATTR_ID_MANUFACTURING_PURCHASE_ORDER }}"; +var attrIdManufacturingPurchaseOrderProductLink = "{{ model.ATTR_ID_MANUFACTURING_PURCHASE_ORDER_PRODUCT_LINK }}"; +var attrIdPlant = "{{ model.ATTR_ID_PLANT }}"; +var attrIdProduct = "{{ model.ATTR_ID_PRODUCT }}"; +var attrIdProductCategory = "{{ model.ATTR_ID_PRODUCT_CATEGORY }}"; +var attrIdProductPermutation = "{{ model.ATTR_ID_PRODUCT_PERMUTATION }}"; +var attrIdProductPrice = "{{ model.ATTR_ID_PRODUCT_PRICE }}"; +var attrIdProductVariation = "{{ model.ATTR_ID_PRODUCT_VARIATION }}"; +var attrIdProductVariationType = "{{ model.ATTR_ID_PRODUCT_VARIATION_TYPE }}"; +var attrIdStockItem = "{{ model.ATTR_ID_STOCK_ITEM }}"; +var attrIdStorageLocation = "{{ model.ATTR_ID_STORAGE_LOCATION }}"; +var attrIdSupplier = "{{ model.ATTR_ID_SUPPLIER }}"; +var attrIdSupplierAddress = "{{ model.ATTR_ID_SUPPLIER_ADDRESS }}"; +var attrIdSupplierPurchaseOrder = "{{ model.ATTR_ID_SUPPLIER_PURCHASE_ORDER }}"; +var attrIdSupplierPurchaseOrderProductLink = "{{ model.ATTR_ID_SUPPLIER_PURCHASE_ORDER_PRODUCT_LINK }}"; +var attrIdUnitMeasurementLatencyManufacture = "{{ model.ATTR_ID_UNIT_MEASUREMENT_LATENCY_MANUFACTURE }}"; +var attrIdUnitMeasurementQuantity = "{{ model.ATTR_ID_UNIT_MEASUREMENT_QUANTITY }}"; +var flagButtonBasketAdd = "{{ model.FLAG_BUTTON_BASKET_ADD }}"; +var flagButtonBuyNow = "{{ model.FLAG_BUTTON_BUY_NOW }}"; +{# +var flagCostLocal = "{{ model.FLAG_COST_LOCAL }}"; +var flagCostLocalVatExcl = "{{ model.FLAG_COST_LOCAL_VAT_EXCL }}"; +var flagCostLocalVatIncl = "{{ model.FLAG_COST_LOCAL_VAT_INCL }}"; +#} +var flagCostTotalLocalVatExcl = "{{ model.FLAG_COST_TOTAL_LOCAL_VAT_EXCL }}"; +var flagCostTotalLocalVatIncl = "{{ model.FLAG_COST_TOTAL_LOCAL_VAT_INCL }}"; +var flagCostUnitLocalVatExcl = "{{ model.FLAG_COST_UNIT_LOCAL_VAT_EXCL }}"; +var flagCostUnitLocalVatIncl = "{{ model.FLAG_COST_UNIT_LOCAL_VAT_INCL }}"; +var flagCountUnitMeasurementIntervalExpirationUnsealed = "{{ model.FLAG_COUNT_UNIT_MEASUREMENT_INTERVAL_EXPIRATION_UNSEALED }}"; +var flagCountUnitMeasurementIntervalRecurrence = "{{ model.FLAG_COUNT_UNIT_MEASUREMENT_INTERVAL_RECURRENCE }}"; +var flagCountUnitMeasurementPerQuantityStep = "{{ model.FLAG_COUNT_UNIT_MEASUREMENT_PER_QUANTITY_STEP }}"; +var flagCurrencyCost = "{{ model.FLAG_CURRENCY_COST }}"; +var flagCustomer = "{{ model.FLAG_CUSTOMER }}"; +var flagCustomerAddress = "{{ model.FLAG_CUSTOMER_ADDRESS }}"; +var flagCustomerSalesOrder = "{{ model.FLAG_CUSTOMER_SALES_ORDER }}"; +var flagDateConsumed = "{{ model.FLAG_DATE_CONSUMED }}"; +var flagDateExpiration = "{{ model.FLAG_DATE_EXPIRATION }}"; +var flagDatePurchased = "{{ model.FLAG_DATE_PURCHASED }}"; +var flagDateReceived = "{{ model.FLAG_DATE_RECEIVED }}"; +var flagDateUnsealed = "{{ model.FLAG_DATE_UNSEALED }}"; +var flagDiscount = "{{ model.FLAG_DISCOUNT }}"; +var flagDoesExpireFasterOnceUnsealed = "{{ model.FLAG_DOES_EXPIRE_FASTER_ONCE_UNSEALED }}"; +var flagHasVariations = "{{ model.FLAG_HAS_VARIATIONS }}"; +var flagIdStripeProduct = "{{ model.FLAG_ID_STRIPE_PRODUCT }}"; +var flagIsConsumed = "{{ model.FLAG_IS_CONSUMED }}"; +var flagIsNotEmpty = "{{ model.FLAG_IS_NOT_EMPTY }}"; +var flagIsOutOfStock = "{{ model.FLAG_IS_OUT_OF_STOCK }}"; +var flagIsSealed = "{{ model.FLAG_IS_SEALED }}"; +var flagIsSubscription = "{{ model.FLAG_IS_SUBSCRIPTION }}"; +var flagLatencyDeliveryDays = "{{ model.FLAG_LATENCY_DELIVERY_DAYS }}"; +var flagLatencyManufacture = "{{ model.FLAG_LATENCY_MANUFACTURE }}"; +var flagManufacturingPurchaseOrder = "{{ model.FLAG_MANUFACTURING_PURCHASE_ORDER }}"; +var flagNamePluralUnitMeasurementIntervalExpirationUnsealed = "{{ model.FLAG_NAME_PLURAL_UNIT_MEASUREMENT_INTERVAL_EXPIRATION_UNSEALED }}"; +var flagNamePluralUnitMeasurementIntervalRecurrence = "{{ model.FLAG_NAME_PLURAL_UNIT_MEASUREMENT_INTERVAL_RECURRENCE }}"; +var flagNamePluralUnitMeasurementQuantity = "{{ model.FLAG_NAME_PLURAL_UNIT_MEASUREMENT_QUANTITY }}"; +var flagNameSingularUnitMeasurementIntervalExpirationUnsealed = "{{ model.FLAG_NAME_SINGULAR_UNIT_MEASUREMENT_INTERVAL_EXPIRATION_UNSEALED }}"; +var flagNameSingularUnitMeasurementIntervalRecurrence = "{{ model.FLAG_NAME_SINGULAR_UNIT_MEASUREMENT_INTERVAL_RECURRENCE }}"; +var flagNameSingularUnitMeasurementQuantity = "{{ model.FLAG_NAME_SINGULAR_UNIT_MEASUREMENT_QUANTITY }}"; +var flagOrderItems = "{{ model.FLAG_ORDER_ITEMS }}"; +var flagPlant = "{{ model.FLAG_PLANT }}"; +{# +var flagPriceLocalVatExcl = "{{ model.FLAG_PRICE_LOCAL_VAT_EXCL }}"; +var flagPriceLocalVatIncl = "{{ model.FLAG_PRICE_LOCAL_VAT_INCL }}"; +#} +var flagPriceTotalLocalVatExcl = "{{ model.FLAG_PRICE_TOTAL_LOCAL_VAT_EXCL }}"; +var flagPriceTotalLocalVatIncl = "{{ model.FLAG_PRICE_TOTAL_LOCAL_VAT_INCL }}"; +var flagPriceUnitLocalVatExcl = "{{ model.FLAG_PRICE_UNIT_LOCAL_VAT_EXCL }}"; +var flagPriceUnitLocalVatIncl = "{{ model.FLAG_PRICE_UNIT_LOCAL_VAT_INCL }}"; +var flagProduct = "{{ model.FLAG_PRODUCT }}"; +var flagProductCategory = "{{ model.FLAG_PRODUCT_CATEGORY }}"; +var flagProductPermutation = "{{ model.FLAG_PRODUCT_PERMUTATION }}"; +var flagProductPrice = "{{ model.FLAG_PRODUCT_PRICE }}"; +var flagProductVariation = "{{ model.FLAG_PRODUCT_VARIATION }}"; +var flagProductVariations = "{{ model.FLAG_PRODUCT_VARIATIONS }}"; +var flagProductVariationType = "{{ model.FLAG_PRODUCT_VARIATION_TYPE }}"; +var flagProfitLocalMin = "{{ model.FLAG_PROFIT_LOCAL_MIN }}"; +var flagQuantity = "{{ model.FLAG_QUANTITY }}"; +var flagQuantityMin = "{{ model.FLAG_QUANTITY_MIN }}"; +var flagQuantityMax = "{{ model.FLAG_QUANTITY_MAX }}"; +var flagQuantityOrdered = "{{ model.FLAG_QUANTITY_ORDERED }}"; +var flagQuantityReceived = "{{ model.FLAG_QUANTITY_RECEIVED }}"; +var flagQuantityStock = "{{ model.FLAG_QUANTITY_STOCK }}"; +var flagRegion = "{{ model.FLAG_REGION }}"; +var flagStockItem = "{{ model.FLAG_STOCK_ITEM }}"; +var flagStorageLocation = "{{ model.FLAG_STORAGE_LOCATION }}"; +var flagSupplier = "{{ model.FLAG_SUPPLIER }}"; +var flagSupplierAddress = "{{ model.FLAG_SUPPLIER_ADDRESS }}"; +var flagSupplierPurchaseOrder = "{{ model.FLAG_SUPPLIER_PURCHASE_ORDER }}"; +var flagSymbolCurrencyCost = "{{ model.FLAG_SYMBOL_CURRENCY_COST }}"; +var flagSymbolIsSuffixNotPrefixUnitMeasurementIntervalExpirationUnsealed = "{{ model.FLAG_SYMBOL_IS_SUFFIX_NOT_PREFIX_UNIT_INTERVAL_EXPIRATION_UNSEALED }}"; +var flagSymbolIsSuffixNotPrefixUnitMeasurementIntervalRecurrence = "{{ model.FLAG_SYMBOL_IS_SUFFIX_NOT_PREFIX_UNIT_MEASUREMENT_INTERVAL_RECURRENCE }}"; +var flagSymbolIsSuffixNotPrefixUnitMeasurementQuantity = "{{ model.FLAG_SYMBOL_IS_SUFFIX_NOT_PREFIX_UNIT_MEASUREMENT_QUANTITY }}"; +var flagSymbolUnitMeasurementIntervalExpirationUnsealed = "{{ model.FLAG_SYMBOL_UNIT_MEASUREMENT_INTERVAL_EXPIRATION_UNSEALED }}"; +var flagSymbolUnitMeasurementIntervalRecurrence = "{{ model.FLAG_SYMBOL_UNIT_MEASUREMENT_INTERVAL_RECURRENCE }}"; +var flagSymbolUnitMeasurementQuantity = "{{ model.FLAG_SYMBOL_UNIT_MEASUREMENT_QUANTITY }}"; +var flagUnitMeasurementIntervalExpirationUnsealed = "{{ model.FLAG_UNIT_MEASUREMENT_INTERVAL_EXPIRATION_UNSEALED }}"; +var flagUnitMeasurementIntervalRecurrence = "{{ model.FLAG_UNIT_MEASUREMENT_INTERVAL_RECURRENCE }}"; +var flagUnitMeasurementLatencyManufacture = "{{ model.FLAG_UNIT_MEASUREMENT_LATENCY_MANUFACTURE }}"; +var flagUnitMeasurementQuantity = "{{ model.FLAG_UNIT_MEASUREMENT_QUANTITY }}"; +{# + var hashGetStoreCustomerSalesOrder = "{{ model.HASH_GET_STORE_CUSTOMER_SALES_ORDER }}"; + var hashGetStoreManufacturingPurchaseOrder = "{{ model.HASH_GET_STORE_MANUFACTURING_PURCHASE_ORDER }}"; + var hashGetStoreProduct = "{{ model.HASH_GET_STORE_PRODUCT }}"; + var hashGetStoreProductCategory = "{{ model.HASH_GET_STORE_PRODUCT_CATEGORY }}"; + var hashGetStoreProductPermutation = "{{ model.HASH_GET_STORE_PRODUCT_PERMUTATION }}"; + var hashGetStoreProductVariation = "{{ model.HASH_GET_STORE_PRODUCT_VARIATION }}"; + var hashGetStoreStockItem = "{{ model.HASH_GET_STORE_STOCK_ITEM }}"; + var hashGetStoreSupplier = "{{ model.HASH_GET_STORE_SUPPLIER }}"; + var hashGetStoreSupplierPurchaseOrder = "{{ model.HASH_GET_STORE_SUPPLIER_PURCHASE_ORDER }}"; +#} +var hashSaveStoreCustomerSalesOrder = "{{ model.HASH_SAVE_STORE_CUSTOMER_SALES_ORDER }}"; +var hashSaveStoreManufacturingPurchaseOrder = "{{ model.HASH_SAVE_STORE_MANUFACTURING_PURCHASE_ORDER }}"; +var hashSaveStoreProduct = "{{ model.HASH_SAVE_STORE_PRODUCT }}"; +var hashSaveStoreProductCategory = "{{ model.HASH_SAVE_STORE_PRODUCT_CATEGORY }}"; +var hashSaveStoreProductPermutation = "{{ model.HASH_SAVE_STORE_PRODUCT_PERMUTATION }}"; +var hashSaveStoreProductVariation = "{{ model.HASH_SAVE_STORE_PRODUCT_VARIATION }}"; +var hashSaveStoreStockItem = "{{ model.HASH_SAVE_STORE_STOCK_ITEM }}"; +var hashSaveStoreSupplier = "{{ model.HASH_SAVE_STORE_SUPPLIER }}"; +var hashSaveStoreSupplierPurchaseOrder = "{{ model.HASH_SAVE_STORE_SUPPLIER_PURCHASE_ORDER }}"; +var hashStoreBasketAdd = "{{ model.HASH_STORE_BASKET_ADD }}"; +var hashStoreBasketDelete = "{{ model.HASH_STORE_BASKET_DELETE }}"; +var hashStoreBasketEdit = "{{ model.HASH_STORE_BASKET_EDIT }}"; +var hashStoreBasketLoad = "{{ model.HASH_STORE_BASKET_LOAD }}"; +var hashStoreSetCurrency = "{{ model.HASH_STORE_SET_CURRENCY }}"; +var hashStoreSetRegion = "{{ model.HASH_STORE_SET_REGION }}"; +var hashStoreSetIsIncludedVAT = "{{ model.HASH_STORE_SET_IS_INCLUDED_VAT }}"; +var hashPageStoreBasket = "{{ model.HASH_PAGE_STORE_BASKET }}"; +var idBasket = "#{{ model.ID_BASKET }}"; +var idBasketContainer = "#{{ model.ID_BASKET_CONTAINER }}"; +var idBasketTotal = "#{{ model.ID_BASKET_TOTAL }}"; +var idButtonBasketAdd = "#{{ model.ID_BUTTON_BASKET_ADD }}"; +var idButtonBuyNow = "#{{ model.ID_BUTTON_BUY_NOW }}"; +var idButtonCheckout = "#{{ model.ID_BUTTON_CHECKOUT }}"; +var idCurrency = "#{{ model.ID_CURRENCY }}"; +var idCurrencyDefault = "#{{ model.ID_CURRENCY_DEFAULT }}"; +var idLabelBasketEmpty = "#{{ model.ID_LABEL_BASKET_EMPTY }}"; +var idProductCategoryDefault = "{{ model.ID_PRODUCT_CATEGORY_DEFAULT }}"; +var idRegionDeliveryDefault = "{{ model.ID_REGION_DELIVERY_DEFAULT }}"; +{# + var keyIdCurrency = "{{ model.KEY_ID_CURRENCY }}"; + var keyItems = "{{ model.KEY_ITEMS }}"; + var keyIdRegionDelivery = "{{ model.KEY_ID_REGION_DELIVERY }}"; + var keyIsIncludedVAT = "{{ model.KEY_IS_INCLUDED_VAT }}"; + var keyNameVariation = "{{ model.KEY_NAME_VARIATION }}"; + var keyNameVariationType = "{{ model.KEY_NAME_VARIATION_TYPE }}"; +#} +var typeFormBasketAdd = "{{ model.TYPE_FORM_BASKET_ADD }}"; +var typeFormBasketEdit = "{{ model.TYPE_FORM_BASKET_EDIT }}"; + diff --git a/templates/layouts/layout.html b/templates/layouts/layout.html new file mode 100644 index 0000000..6003944 --- /dev/null +++ b/templates/layouts/layout.html @@ -0,0 +1,229 @@ + + + + + + {{ model.title }} - {{ model.NAME_COMPANY_SHORT }} + + + + + + + + + + + + + + {% block page_head %}{% endblock %} + + + +
+
+ +
+
+ + +
+ {% block page_body %}{% endblock %} +
+ + +
+
+ + + +
+
+ + + + diff --git a/templates/pages/core/_contact.html b/templates/pages/core/_contact.html new file mode 100644 index 0000000..05f1e57 --- /dev/null +++ b/templates/pages/core/_contact.html @@ -0,0 +1,77 @@ +{% extends 'layouts/layout.html' %} + +{% block page_head %} + +{% endblock %} + +{% block page_nav_links %} + {# + Command + Contact Details + #} +{% endblock %} + +{% block page_body %} + + {% set form = model.form_contact %} +
+
+

Contact Us

+

Please fill in the form below and we'll get back to you as soon as possible.

+ +
+ {{ form.csrf_token }} + +
+ +
+ {{ form.email(class="form-input", required=True) }} +
+ + +
+ {{ form.contact_name(class="form-input", required=True) }} +
+ + +
+ {{ form.company_name(class="form-input", required=True) }} +
+ + +
+ {{ form.message(class="form-input", required=True) }} +
+
+ + +
+
+ {{ form.altcha.label }} + +
+

This CAPTCHA mechanism is fully GDPR-compliant with no cookies, no fingerprinting, no tracking, and runs in the background so you don't need to do anything!

+
+
+ {{ model.form_contact.submit() }} +
+
+ +
+

How we use your information

+

If you opt in to marketing communications, we will also use your email address to send you updates about our services, ERPNext features, and relevant industry news. You can unsubscribe from these communications at any time.

+

We retain command submissions for customer service purposes and retain marketing consent records as required by law. For details about how long we keep your information, please see our data retention schedule.

+

For full details about how we handle your personal data, please read our Privacy Policy.

+
+
+
+{% endblock %} \ No newline at end of file diff --git a/templates/pages/core/_contact_success.html b/templates/pages/core/_contact_success.html new file mode 100644 index 0000000..0e36586 --- /dev/null +++ b/templates/pages/core/_contact_success.html @@ -0,0 +1,22 @@ +{% extends 'layouts/layout.html' %} + +{% block page_head %} + +{% endblock %} + +{% block page_nav_links %} +{% endblock %} + +{% block page_body %} + + {% set form = model.form_contact %} +
+
+

Message Received

+

Thanks for contacting us! We've received your message and will respond within 48 hours.

+
+
+ + +{% endblock %} \ No newline at end of file diff --git a/templates/pages/core/_home.html b/templates/pages/core/_home.html new file mode 100644 index 0000000..45f6961 --- /dev/null +++ b/templates/pages/core/_home.html @@ -0,0 +1,119 @@ + + +{% extends 'layouts/layout.html' %} + +{% block page_head %} + + +{% endblock %} + +{% block page_nav_links %} + Services + Testimonial + Pricing + Contact Us +{% endblock %} + +{% block page_body %} +
+
+
+

Transform Your Business with Modern ERP Solutions

+

UK-based ERPNext specialist providing integrated ERP and e-commerce solutions. 5+ years experience implementing systems for builders merchants and automotive companies.

+ Book Consultation +
+
+
+ +
+
+

Our Services

+

Comprehensive ERP solutions tailored to your business needs

+ +
+
+

Implementation Services

+

Full ERPNext implementation including setup, configuration, and training. We ensure a smooth transition to your new ERP system.

+
+ +
+

Integration & Migration

+

Seamlessly migrate your existing data and integrate ERPNext with your current business applications and workflows.

+
+ +
+

Hosting Services

+

Secure, reliable cloud hosting with regular backups and maintenance to keep your ERP system running smoothly.

+
+ +
+

Custom Extensions

+

Tailored app development and customizations to extend ERPNext functionality according to your specific requirements.

+
+
+
+
+ + {# +
+
+

Client Success Story

+

See how we've helped other businesses succeed

+ +
+

"The ERPNext implementation has revolutionized our operations. The integrated e-commerce system has streamlined our entire sales process, and the team's support has been exceptional throughout our journey."

+

- 4 Shires Builders Merchants

+
+
+
+ #} + +
+
+

Simple, Transparent Pricing

+

Enterprise-grade solutions at SMB-friendly prices

+ +
+

Implementation

+
From £10,000
+

One-time setup fee based on business size

+
    +
  • ✓ Full ERP & e-commerce setup
  • +
  • ✓ Product catalogue configuration
  • +
  • ✓ Staff training
  • +
  • ✓ Data migration
  • +
+ +

Monthly Support & Hosting

+
£200
+

12-month minimum term, billed annually at £2,400

+
    +
  • ✓ Unlimited support tickets
  • +
  • ✓ Cloud hosting (99.9% uptime)
  • +
  • ✓ Regular maintenance and system updates
  • +
+ + Get Custom Quote +
+
+
+ +
+
+

Ready to Transform Your Business?

+

Contact us today to discuss your ERP needs

+ Book Consultation +
+
+ + + + +{% endblock %} \ No newline at end of file diff --git a/templates/pages/legal/_accessibility_statement.html b/templates/pages/legal/_accessibility_statement.html new file mode 100644 index 0000000..086f6dd --- /dev/null +++ b/templates/pages/legal/_accessibility_statement.html @@ -0,0 +1,205 @@ +{% extends 'layouts/layout.html' %} + +{% block title %}{{ model.title }}{% endblock %} + +{% block page_body %} + + + +
+

Accessibility statement for {{ model.NAME_COMPANY }}

+ +

This accessibility statement applies to the public website of {{ model.NAME_COMPANY }}.

+ +

This website is run by {{ model.NAME_COMPANY }}. We want as many people as possible to be able to use this website. For example, that means you should be able to: +

    +
  • Zoom in up to 400% without the text spilling off the screen
  • +
  • Navigate most of the website using just a keyboard or speech recognition software
  • +
  • Listen to most of the website using a screen reader (including the most recent versions of NVDA and TalkBack)
  • +
  • We've also made the website text as simple as possible to understand.
  • + + AbilityNet has advice on making your device easier to use if you have a disability. +

    + +

    How accessible this website is

    + +

    We know some parts of this website are not fully accessible: +

      +
    • you cannot modify the line height or spacing of text
    • +
    +

    + +

    Feedback and contact information

    +

    If you find any problems not listed on this page or think we’re not meeting accessibility requirements, contact: {{ model.app.MAIL_CONTACT_PUBLIC }} or complete our Contact Us form. + + If you need information on this website in a different format like accessible PDF, large print, easy read, audio recording or braille: +

    + {% set block_id = 'button_get_in_touch' %} + {% include 'components/common/buttons/_buttons_save_cancel.html' %} +

    + We’ll consider your request and get back to you in 7 days. + + +

    + +

    Enforcement procedure

    +

    The Equality and Human Rights Commission (EHRC) is responsible for enforcing the Public Sector Bodies (Websites and Mobile Applications) (No. 2) Accessibility Regulations 2018 (the ‘accessibility regulations’). If you’re not happy with how we respond to your complaint, contact the Equality Advisory and Support Service (EASS). +

    + +
    + +

    Technical information about this website’s accessibility

    + +

    {{ model.NAME_COMPANY }} is committed to making its website accessible, in accordance with the Public Sector Bodies (Websites and Mobile Applications) (No. 2) Accessibility Regulations 2018. +

    + +

    Compliance status

    +

    The website has been tested against the Web Content Accessibility Guidelines (WCAG) 2.2 AA standard. +

    + +

    + + (a) This website is fully compliant with the Web Content Accessibility Guidelines version 2.2 AA standard. + +

    + + + + + +
    +

    Preparation of this accessibility statement

    + +

    This statement was prepared on 30/04/2024. It was last reviewed on 30/04/2024. + + This website was last tested on 30/04/2024 against the WCAG 2.2 AA standard. +

    + +

    The test was carried out by {{ model.NAME_COMPANY }}. All pages were tested using automated testing tools by our website team. A further audit of the website was carried out to the WCAG 2.2 AA standard.

    + +

    You can read the full accessibility test report {{ model.URL_HOST }}{{ model.HASH_PAGE_ACCESSIBILITY_REPORT }}.

    +
+ + + +{% endblock %} \ No newline at end of file diff --git a/templates/pages/legal/_license.html b/templates/pages/legal/_license.html new file mode 100644 index 0000000..95fb915 --- /dev/null +++ b/templates/pages/legal/_license.html @@ -0,0 +1,40 @@ +{% extends 'layouts/layout.html' %} + +{% block title %}{{ model.title }}{% endblock %} + +{% block page_body %} + + + + +
+

Copyright © 2024 Precision And Research Technology Systems Limited +

+

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +

+ +

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +

+ +

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +

+
+ + + + +{% endblock %} \ No newline at end of file diff --git a/templates/pages/legal/_privacy_policy.html b/templates/pages/legal/_privacy_policy.html new file mode 100644 index 0000000..47d2b66 --- /dev/null +++ b/templates/pages/legal/_privacy_policy.html @@ -0,0 +1,99 @@ +{% extends 'layouts/layout.html' %} + +{% block title %}{{ model.title }}{% endblock %} + +{% block page_body %} + + + + +
+

Generated privacy notice - general business

+

Precision and Research Technology Systems Ltd customer privacy notice

+

This privacy notice tells you what to expect us to do with your personal information.

+

Our contact details

+

Email

+

{{ model.get_mail_contact_public() }}

+

What information we collect, use, and why

+

We collect or use the following information to provide services and goods, including delivery:

+
    +
  • Names and contact details
  • +
+ +

Lawful bases

+

Our lawful bases for collecting or using personal information to provide services and goods are:

+
    +
  • Legitimate interest:
  • +
      +
    • + We collect the user's name and email address alongside a message they send on our 'Contact Us' form in order to respond to their request. Alternatively, the user has the option to contact us directly by email. +
    • +
    +
+ +

Where we get personal information from

+
    +
  • People directly
  • +
+ +

How long we keep information

+

For information on how long we keep personal information, see our retention schedule at https://www.partsltd.co.uk/retention-schedule

+ +

Who we share information with

+

Data processors

+

Zume

+

This data processor does the following activities for us: They host our web and email server, including emails with personal data in body and database storage for database that holds user data.

+ +

Sharing information outside the UK

+

Where necessary, we may transfer personal information outside of the UK. When doing so, we comply with the UK GDPR, making sure appropriate safeguards are in place. Please contact us for more information.

+

Where necessary, our data processors may share personal information outside of the UK. When doing so, they comply with the UK GDPR, making sure appropriate safeguards are in place. Please contact us for more information.

+ +

Your data protection rights

+

Under data protection law, you have rights including:

+
    +
  • Your right of access - You have the right to ask us for copies of your personal data.
  • +
  • Your right to rectification - You have the right to ask us to rectify personal data you think is inaccurate. You also have the right to ask us to complete information you think is incomplete.
  • +
  • Your right to erasure - You have the right to ask us to erase your personal data in certain circumstances.
  • +
  • Your right to restriction of processing - You have the right to ask us to restrict the processing of your personal data in certain circumstances.
  • +
  • Your right to object to processing - You have the right to object to the processing of your personal data in certain circumstances.
  • +
  • Your right to data portability - You have the right to ask that we transfer the personal data you gave us to another organisation, or to you, in certain circumstances.
  • +
  • Your right to withdraw consent – When we use consent as our lawful basis you have the right to withdraw your consent.
  • +
+

You don’t usually need to pay a fee to exercise your rights. If you make a request, we have one calendar month to respond to you.

+

To make a data protection rights request, please contact us using the contact details at the top of this privacy notice.

+ +

How to complain

+

If you have any concerns about our use of your personal data, you can make a complaint to us using the contact details at the top of this privacy notice.

+

If you remain unhappy with how we’ve used your data after raising a complaint with us, you can also complain to the ICO.

+ +

The ICO’s address:

+

Information Commissioner’s Office

+

Wycliffe House

+

Water Lane

+

Wilmslow

+

Cheshire

+

SK9 5AF

+

Helpline number: 0303 123 1113

+

Website: https://www.ico.org.uk/make-a-complaint

+

Last updated

+

1 May 2024

+
+ + + + +{% endblock %} \ No newline at end of file diff --git a/templates/pages/legal/_retention_schedule.html b/templates/pages/legal/_retention_schedule.html new file mode 100644 index 0000000..51a7f36 --- /dev/null +++ b/templates/pages/legal/_retention_schedule.html @@ -0,0 +1,1966 @@ +{% extends 'layouts/layout.html' %} + +{% block title %}{{ model.title }}{% endblock %} + +{% block page_body %} + + + + +
+

Retention periods for {{ model.NAME_COMPANY }}

+

Accounting records

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
CategoryRecord typeDescription of UseRetention period
Bank account recordsCheques and associated recordsCheque book / butts for all accounts2 years
Cancelled cheques 2 years
Dishonoured cheques2 years
Fresh cheques6 years
Paid / presented cheques 6 years
Stoppage of cheque payment notices2 years
Record of cheques opened books2 years
Cheque registers 2 years
Record of cheques drawn for payment6 years
Bank depositsBank deposit books / slips / butts2 years
Bank deposit summary sheets + Summaries of daily banking + Cheques schedules + 2 years
Register of cheques lodged for collection2 years
Bank reconciliationsReconciliation files / sheets 2 years
Daily list of paid cheques2 years
Unpaid cheque records2 years
Bank statementsBank statements, periodic reconciliations2 years
Bank certificates of balance2 years
Electronic banking and electronic funds transferCash transactions + Payment instructions + Deposits and/or withdrawals + Disposal action in line wiht paper records
Audit trailsRetain for the same period as the base transaction record
Expenditure recordsCash books / sheetsExpenditure sheets6 years
Cash books / sheets6 years
Petty cash recordsPetty cash records / books / sheets 2 years
Petty cash receipts2 years
Postal cash book/sheets + Postage/courier account/cash records + Register of postage expenditure + Postage paid record + Postage books sheets + 2 years
Summary cash books 2 years
CreditorsCreditors’ history records + Lists/reports + 6 years
StatementsStatements of accounts outstanding + Outstanding orders + 2 years
Statements of accounts – rendered / payable2 years
Subsidiary records Copies of extracts and expenditure dissections1 year
Credit note books2 years
Credit notes2 years
Debit note books2 years
VouchersVouchers – claims for payment, purchase orders, requisition for goods and services, accounts payable, invoices and so on6 years
Wages / salaries vouchers6 years
Copies of vouchers1 year
Voucher registers2 years
Voucher registration cards and payment cards6 years
Voucher summaries1 year
Advice/schedule of vouchers despatched + Delivery advice1 year
Costing recordsCost cards 2 years
Costing records, dissection sheets and so on2 years
Ledger recordsGeneral and subsidiary ledgersGeneral and subsidiary ledgers produced for the purposes of preparing certified financial statements or published information6 years
Cash books / sheets6 years
Other ledgers (such as contracts, costs, purchases)2 years
Related journalsAudit sheets – ledger posting2 years
JournalsJournals – prime records for the raising of charges6 years
Journals – routine adjustments2 years
Trial balances and reconciliations/td> + Year-end balances, reconciliations and variations to support ledger balances and published accounts6 years
Receipts and revenue recordsBooks / buttsReceipt books/butts + Office copies of receipts – cashiers’, cash + register, fines and costs, sale of + publications, general receipt books/butts/ + records6 years
Postal remittance books/records6 years
Receipt books/records for imposts (such as stamp duty, VAT receipt books)6 years
Irregular remittance books2 years
Cash registersCopies of forms6 years
Reconciliation sheets6 years
Audit rolls2 years
Summaries / analysis records2 years
Reading books / sheets2 years
Cashiers’ recordsHandover books2 years
Revenue records Revenue cash books / sheets / records + Receipt cash books / sheets6 years
Daily revenue dissections 1 year
Debtors’ records and invoicesPeriodical revenue dissections1 year
Copies of invoices/debit notes rendered on debtors (such as invoices paid/unpaid, registers of invoices, debtors ledgers)6 years
Source documents/records used for raising of invoices/debit notes6 years
Debits and refundsCopies of invoices and copies of source documents2 years
Records relating to unrecoverable revenue, debts and overpayments (such as register of debts written off, register of refunds)6 years
Salaries and related recordsSalary recordsEmployee pay histories + Note that the last three years’ records must be kept for leavers, in either the personnel or finance records system, for the calculation of pension entitlement6 years
Salary rates registerWhen superceded
Salary ledger card/records6 years
Copies of salaries/wages payroll sheets2 years
Stores recordsStores recordsGoods inwards books/records6 years
Delivery dockets 2 years
Stock / stores control cards / sheets / records2 years
Stock / stores issue registers / records2 years
Stocktaking sheets/records, including inventories, stock reconciliations, stock take reports2 years
Purchase order recordsPurchase order books / records6 years
Railway / courier consignment books / records2 years
Travel warrants2 years
Requisition recordsRequisition records2 years
Other accountable financial recordsAsset registersAssets / equipment registers / recordsSix years after asset or last one in the register is disposed of
Depreciation registersRecords relating to the calculation of annual depreciationSix years after asset or last one in the register is disposed of
Financial statementsStatements/summaries prepared for inclusion in quarterly/annual reports6 years
Periodic financial statements prepared for management on a regular basisDestroy when cumulated into quarterly/annual reports
Ad hoc statements1 year
+ +

Central expenditure records

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
CategoryRecord typeDescription of UseRetention period
Estimates records (including revised and supplementary) where detailed justification is provided and which are submitted to the Treasury6 years
Estimates submissions from regional or local offices2 years
Calculations and costings for annual estimates2 years
Expenditure scrutinies2 years
Records relating to bids from the Civil Contingencies Fund 6 years
Spending reviewsOne year after the cycle to which the records relate
Records relating to dealings with the + Public Accounts Committee and the Select + Committee on Expenditure6 years
Expenditure and revenue returnsOne year after the year to which the returns relate
Financial statements prepared for annual reportsOne year after publication of the report
Financial statements prepared for managementOne year after completion of annual financial report
Grant funding records Six years after action completed/grant made
Financial authorities or delegationsSix years after authority or delegation is superseded
Policy and strategy records (including investment policy) Second review
Treasury Directives and Circulars Until superseded
Asset registersSix years after item / asset is disposed of
Land registers Twelve years after disposal
Depreciation recordsSix years after item / asset is disposed of
Audit investigations (external) Six years after action completed
Financial records relating to capital works projectsSix years after action/project is completed
Investment recordsTwo years after investments are liquidated or matured
Stocktaking records2 years after audit
Unclaimed monies records6 years after audit
Records relating to serious matters of: +
    +
  • theft
  • +
  • fraud
  • +
  • misappropriation
  • +
  • irrecoverable debts and overpayments
  • +
  • write-offs
  • +
  • recovery of debt
  • +
  • wavering of debt
  • +
+ (where external action has been taken) +
Ten years after action / investigation is completed
Records relating to minor matters of: +
    +
  • theft
  • +
  • fraud
  • +
  • misappropriation
  • +
  • irrecoverable debts and overpayments
  • +
  • write-offs
  • +
  • recovery of debt
  • +
  • wavering of debt
  • +
+ (where matter was resolved internally) +
Six years after audit
Procedure manuals 2 years after superceded
+ +

Comlaints records

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
CategoryRecord typeDescription of UseRetention period
Policy statementsWhen superseded
System handbook / guideWhen superseded
Minutes of meetings of Complaints Committee, Service Standards Team and others10 years
Surveys3 years
Case recordsEnquiries3 years
Investigations10 years
Statistical reports5 years
Reports on particular complaints or on categories of complaints3 years
PrecedentsReview after 10 years
Register of complaints10 years
ReviewsCorrespondence and papers10 years
Reports3 years
+ +

Contractual records

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
CategoryRecord typeDescription of UseRetention period
Policy mattersPolicy on contracts, normally contained in a separate registered file seriesFirst and second review
Initial proposalEnd user requirement6 years
List of approved suppliersAn active document – updated regularly
Statements of interestOne year from date of last paper
Draft specificationDestroy when specification has been agreed
Agreed specificationSix years from end of contract
Evaluation criteriaSix years from end of contract
Invitation to tenderSix years from end of contract
TenderingUnsuccessful tender documentOne year after date of last paper
Successful tender documentSix years from award of contract
Background information supplied by departmentOne year after date of last paper
Interview panel – report and notes of proceedingsOne year from end of contract
Commissioning letterOne year from end of contract
Signed contract6 years from end of contract
Contract operation and monitoringReports from contractors2 years from end of contract
Schedules of works2 years from end of contract
Bills of quantity (building contracts)16 years
Surveys and inspections + a. equipment and supplies + b. buildingsa. Two years from date of last + paper + b. Second review
Records of complaints6 years from end of contract
Disputes over payment6 years from end of contract
Final accounts6 years from end of contract
Minutes and papers of meetingsSecond review
Amendments to contractsChanges to requirements6 years from end of contract
Forms of variation6 years from end of contract
Extensions to contract6 years from end of contract
+ +

Employee personnel records

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
CategoryRecord typeDescription of UseRetention period
Employment and careerWritten particulars of employment + Contracts of employment, including theCertificate of Qualification or its equivalent and including the Senior Civil Service + Changes to terms and conditions, including change of hours lettersUntil age 100
Job History - consolidated record of whole career and location details (paper or electronic)Until age 100
Current address detailsSix years after employment has ended
Record of location of overseas serviceUntil age 100
Variation of hours - calculation formula for individualDestroy after use
Promotion, temporary promotion and / or substitution documentation Destroy after summary noted
Working Time Directive opt out formsThree years after the opt-out has been rescinded or has ceased to apply
Record of previous service datesUntil age 100
Previous service supporting papersDestroy after records noted as appropriate
Qualifications/references6 years
Transfer documents (OGD E18) Destroy after summary noted and actioned
Annual/Assessment reports or summary of performance marks where an open reporting system operates5 years
Annual/Assessment reports for the last five years of service or summary of performance marks where an open reporting system operatesUntil age 72
Training history6 years
Travel and subsistence - claims and authorisation6 years
Employment and careerAnnual leave records (dependent on departmental practice)2 years
Job applications – internal1 year
Recruitment, appointment and/or promotion board selection papers1 year
Building society references6 months
HealthHealth DeclarationUntil age 100
Health referrals, including: + Medical reports from doctors and consultants + Correspondence with the appointed medical + adviser to the PCSPS (currently BMI Health + Services and, previous to that body, the + Occupational Health and Safety Agency Ltd, + the Civil Service Occupational Health Service + or the Medical Advisory Service (MAS)) + Until age 100
Papers relating to any injury on dutyUntil age 100
Medical reports of those exposed to a + substance hazardous to health, including: + Lead (Control of Lead at Work Regulations + 1980) 40 years from date at which entry was + made + Asbestos (Control of Asbestos at Work + Regulations 1996) 40 years after last record + Compressed Air (Work in Compressed Air + Regulations 1996) 40 years from date of last + entry + Radiation (Ionising Radiation Regulations + 1985)50 years from date of last entry
Medical/Self Certificates – unrelated to industrial injury4 years
PersonalWelfare papersDestroy after minimum of six years after last + action
SecuritySecurity personnel files Five years after leaving (if at normal retirement age) or ten years after leaving (if before normal retirement age)
Pay and pensionBank details - current Six years after employment has ended
Death Benefit Nomination and Revocation + Forms Until age 100
Death certificatesReturn original to provider + Retain copy until age 100
Decree AbsolutesReturn original to provider + Retain copy until age 100
Housing advanceUntil age 100
Marriage certificate and documentation relating to civil registrationReturn original to provider + Retain copy until age 100
Unpaid leave periods (such as maternity leave)Until age 100
Statutory maternity pay documents6 years
Other maternity pay documentation18 months
Overpayment documentation6 years after repayment or write-off
Personal payroll history, including record of + pay, performance pay, overtime pay, + allowances, pay enhancements, other taxable + allowances, payment for untaken leave, + reduced pay, no pay, maternity leaveUntil age 100
Pensions estimates and awardsUntil age 100
Record of: + Full name and date of birth + National Insurance number + Pensionable pay at leaving + Reckonable service for pension purposes (and + actual service where this is different, together + with reasons for the difference) + Reason for leaving and new employer’s name + (where known) + Amount and destination of any transfer value + paid + Amount of any refund of PCSPS contributions + Amount and date of any Contributions + Equivalent Premium paid + All other papers relating to pensionability not + listed above (such as papers about + pensionability of other employment (including + war service); extension of service papers; + papers about widow’s, widower’s, children’s + and other dependant’s pensions; + correspondence with the Cabinet Office, other + departments and pension administrators, or the + officer and his/her representatives (MPs, + unions or others) about pension mattersUntil age 100
Resignation, termination and/or retirement + lettersUntil age 100
Added yearsUntil age 100
Additional Voluntary Contributions (AVC)Until age 100
Payroll input forms6 years
Bonus nominations6 years
Complete sick absence record showing dates and causes of sick leaveUntil age 72
Statutory Sick Pay (SSP) formsFor last 4 to 6 years
Papers relating to disciplinary action which has resulted in any changes to terms and conditions of service, salary, performance pay or allowancesUntil age 72
Authorisation for deputising, substitution allowance and/or overtime/travel time claim6 years
Advances for: + Season tickets + Car parking + Bicycles + Christmas/holidays + Housing6 years after repayment
+ + + +

Employee personnel records

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
CategoryRecord typeDescription of UseRetention period
ReportsAudit reports (including interim), where these have included the examination of long-term contracts6 years
Report papers used in the course of a fraud investigation6 years after legal proceedings have been completed
Other audit reports (including interim)3 years
UndertakingsTerms of reference3 years
Programmes / plans / strategiesOne year after the last date of the plan
Correspondence3 years
Record keepingMinutes of meetings and related papers, including those of the Audit Committee3 years
Working papers3 years
Other recordsInternal Audit guidesWhen superseded
Manuals and guides relating to departmental proceduresWhen superseded
Local auditing standardsWhen superseded
DisposalAnnual reports to Accounting Officers3 years
+ +

Project records

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
CategoryRecord typeDescription of UseRetention period
Project proposalsapproved10 years after completion of project
rejected or deferred5 years after completion of project
Project Initiation Documents (PIDs)PIDs and supporting documentation (including business cases)Small projects: + 10 years after completion of project + Major projects: + 25 years after completion of project +
Feasibility studiesreportsSmall projects: + 10 years after issue + Major projects: + 25 years after completion of project +
-draft reportsSmall projects: + 2 years after last paper + Major projects: + 25 years after completion of project +
working papersSmall projects: + 2 years after last paper + Major projects: + 25 years after completion of project +
correspondenceSmall projects: + 2 years after last paper + Major projects: + 25 years after completion of project +
Plans and specifications (such as statements of requirements, operational requirements, technical plans, resource plans)provisional / proposed5 years after completion of project
final10 years after completion of project
variations10 years after completion of project
Contracts and agreementscontracts under sealSee 'Contractual records' above.
other contractsSee 'Contractual records' above.
title deedsSee 'Contractual records' above.
correspondenceSee 'Contractual records' above.
Contractorsapproved nominations1 year after issue
rejected nominations1 year after issue
approved listwhen new list is issued
removals/suspensions6 years after the end of the project
Tender boardsrecord sets of papersat the end of the project
other copies1 year after date of last paper
working papers2 years after date of last paper
minutes of meetings5 years after date of last paper
Maps, plans, drawings and photographsmaster setSMall projects: + 10 years after completion of project + Major projects: + 25 years after completion of project
working copiesSmall projects: + at the end of the project + Major projects: + 25 years after completion of project
other copiesSmall projects: + 5 years after date of last paper + Major projects: + 25 years after completion of project
Financial documentsFinancial documents (including + investment appraisals)6 years after completion of project
Equipment and suppliesEquipment and supplies6 years after completion of project
Land recordsallocationwhen land released for other purposes
procurement / disposal12 years after date of disposal
Human resourcesSee 'Personal records' above.
Project boards, Assessment meetings, etc.minutesSmall projects: + 5 years after date of last paper + Major projects: + 25 years after completion of project
correspondenceSmall projects: + 5 years after date of last paper + Major projects: + 25 years after completion of project
Reports (such as stage assessments, quality reviews, highlight reports, GANTT charts)interim5 years after issue
final25 years after completion of project
evaluation25 years after completion of project
draftat the end of the project
Product descriptions5 years after completion of project
Project operating manuals5 years after completion of project
Miscellaneous recordsCopies of documentation from other projects; information on products, equipment or machinery; training courses; correspondence2 years after completion of project
+ +

Inquiry records

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
CategoryRecord typeDescription of UseRetention period
InquiriesEvidence of steps taken to secure the attendance of witnesses7 years from the final report
Schedules of witnesses7 years from the final report
Research gathered by the inquiry team 7 years from the final report
Financial records7 years from the final report
Cost solicitor’s records7 years from the final report
Parliamentary questions7 years from the final report
All other data related to the inquiryPermanent
+ +

Public inquiry records

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
CategoryRecord typeDescription of UseRetention period
Customer dataEnquiries6 years from end of contract
Contracted servicesInitial proposal6 years from end of contract
Signed contracts and ammendments6 years from end of contract
Reports from third party services contracted6 years from end of contract
+
+ + + + +{% endblock %} + diff --git a/templates/pages/legal/accessibility_report.html b/templates/pages/legal/accessibility_report.html new file mode 100644 index 0000000..527d424 --- /dev/null +++ b/templates/pages/legal/accessibility_report.html @@ -0,0 +1,60 @@ +public-website-of-precision-and-research-technology-systems-limited-report.html

Report

About the Evaluation

Report Creator
Lord Edward Middleton-Smith
Evaluation Commissioner
Lord Edward Middleton-Smith
Evaluation date
Tue Apr 30 2024

Executive Summary

Not provided

Scope of the Evaluation

Website name
Public Website of Precision And Research Technology Systems Limited
Scope of the website
'All web content of the public mobile and desktop website of Precision And Research Technology Systems Limited located at https://www.partsltd.co.uk/
WCAG Version
2.2
Conformance target
AA
Accessibility support baseline
Google Chrome with NVDA, FireFox with NVDA, Ecosia mobile browser with TalkBack.
Additional evaluation requirements
Not provided

Detailed Audit Results

Summary

Reported on 55 of 55 WCAG 2.2 AA + Success Criteria.

  • 41 Passed
  • 0 Failed
  • 0 Cannot tell
  • 14 Not present
  • 0 Not checked

All Results

1 Perceivable

1.1 Text Alternatives
Success Criterion Result Observations
1.1.1: Non-text Content

Result: Passed

Observations:

All user input controls have descriptive names and v2 Google reCaptcha used with text label to identify to user that they must check the box to prove they are not a bot.

+
1.2 Time-based Media
Success Criterion Result Observations
1.2.1: Audio-only and Video-only (Prerecorded)

Result: Not present

1.2.2: Captions (Prerecorded)

Result: Not present

1.2.3: Audio Description or Media Alternative (Prerecorded)

Result: Not present

1.2.4: Captions (Live)

Result: Not present

1.2.5: Audio Description (Prerecorded)

Result: Not present

1.3 Adaptable
Success Criterion Result Observations
1.3.1: Info and Relationships

Result: Passed

Observations:

Elements change in response to zoom and viewport dimensions properly. Aria-label provided for all images.

+
1.3.2: Meaningful Sequence

Result: Passed

Observations:

Flow layout keeps associated sections together but allows dynamic structure depending on size of elements relative to screen.

+
1.3.3: Sensory Characteristics

Result: Passed

Observations:

Content reads properly as raw text in default order. Aria-label provided for all images and names for all form input components.

+
1.3.4: Orientation

Result: Passed

Observations:

Orientation of content is not locked.

+
1.3.5: Identify Input Purpose

Result: Passed

Observations:

Appropriate visible labels used alongside name attributes for form input elements.

+
1.4 Distinguishable
Success Criterion Result Observations
1.4.1: Use of Color

Result: Passed

Observations:

Colour only used to convey meaning for text hyperlinks, which have alt-text attributes to identify their purpose and presence.

+
1.4.2: Audio Control

Result: Not present

1.4.3: Contrast (Minimum)

Result: Passed

Observations:

Webpage text contrast assessed with tool at this website: https://accessibleweb.com/color-contrast-checker/

+
1.4.4: Resize text

Result: Passed

Observations:

All webpages can be scaled to up to 500% while maintaining structure and visible components.

+
1.4.5: Images of Text

Result: Not present

1.4.10: Reflow

Result: Passed

Observations:

Flex layout forces only vertical scrolling at required viewport dimensions.

+
1.4.11: Non-text Contrast

Result: Passed

Observations:

Strong borders used for form input components.

+
1.4.12: Text Spacing

Result: Passed

Observations:

Content becomes vertically scrollable as necessary.

+
1.4.13: Content on Hover or Focus

Result: Passed

Observations:

Hamburger menu button for navigation overlay used. The button remains stationary with no elements above it, throughout use of navigation.

+

2 Operable

2.1 Keyboard Accessible
Success Criterion Result Observations
2.1.1: Keyboard

Result: Passed

Observations:

Tab indices set to enable correct transition around page by keyboard. Other keyboard shortcuts not changed.

+
2.1.2: No Keyboard Trap

Result: Passed

Observations:

Tab indices set to enable correct transition around page by keyboard.

+
2.1.4: Character Key Shortcuts

Result: Passed

Observations:

Tab indices set to enable correct transition around page by keyboard. Other keyboard shortcuts not changed, and can be set by user's device settings.

+
2.2 Enough Time
Success Criterion Result Observations
2.2.1: Timing Adjustable

Result: Not present

Observations:

No session time limits imposed on user.

+
2.2.2: Pause, Stop, Hide

Result: Not present

2.3 Seizures and Physical Reactions
Success Criterion Result Observations
2.3.1: Three Flashes or Below Threshold

Result: Passed

2.4 Navigable
Success Criterion Result Observations
2.4.1: Bypass Blocks

Result: Not present

2.4.2: Page Titled

Result: Passed

Observations:

Descriptive titles used on all webpages.

+
2.4.3: Focus Order

Result: Passed

Observations:

Keyboard tab indices set for logical navigation around pages.

+
2.4.4: Link Purpose (In Context)

Result: Passed

Observations:

Descriptive aria-label provided for all text hyperlinks.

+
2.4.5: Multiple Ways

Result: Passed

Observations:

Navigation on all webpages and company logo links to home page.

+
2.4.6: Headings and Labels

Result: Passed

2.4.7: Focus Visible

Result: Passed

2.4.11: Focus Not Obscured (Minimum)

Result: Passed

2.5 Input Modalities
Success Criterion Result Observations
2.5.1: Pointer Gestures

Result: Not present

2.5.2: Pointer Cancellation

Result: Passed

Observations:

Up event used to trigger events across website.

+
2.5.3: Label in Name

Result: Passed

Observations:

Input label for attributes used to associate with input elements. +Aria-label attributes used for text hyperlinks.

+
2.5.4: Motion Actuation

Result: Not present

2.5.7: Dragging Movements

Result: Not present

2.5.8: Target Size (Minimum)

Result: Passed

Observations:

Minimum control dimension is 27 CSS pixels.

+

3 Understandable

3.1 Readable
Success Criterion Result Observations
3.1.1: Language of Page

Result: Passed

Observations:

English - Great Britain on all pages.

+
3.1.2: Language of Parts

Result: Passed

Observations:

No language changes across website.

+
3.2 Predictable
Success Criterion Result Observations
3.2.1: On Focus

Result: Passed

Observations:

No change of context initiated except by button click to navigate to submit a form and/or navigate to a new page.

+
3.2.2: On Input

Result: Passed

Observations:

No change of context initiated except by button click to navigate to submit a form and/or navigate to a new page.

+
3.2.3: Consistent Navigation

Result: Passed

Observations:

Navigation component and mechanisms shared across all pages.

+
3.2.4: Consistent Identification

Result: Passed

Observations:

Classes and CSS styles used to group collections of elements by purpose and functionality.

+
3.2.6: Consistent Help

Result: Passed

Observations:

Contact us button provided in a consistent format.

+
3.3 Input Assistance
Success Criterion Result Observations
3.3.1: Error Identification

Result: Passed

Observations:

Each input element has an associated error display label which are triggered when input validation is not met.

+
3.3.2: Labels or Instructions

Result: Passed

Observations:

Each user input has a descriptive label.

+
3.3.3: Error Suggestion

Result: Passed

Observations:

Text description of incomplete required fields is provided. Description of what caused error is issued when it involves simple regular expression validation.

+
3.3.4: Error Prevention (Legal, Financial, Data)

Result: Not present

3.3.7: Redundant Entry

Result: Passed

Observations:

No redundant data entry required. User's browser cache stores form data for rapid re-entry on crash or any other occasion.

+
3.3.8: Accessible Authentication (Minimum)

Result: Passed

Observations:

Alternative sign in methods provided, including recovery by code by phone and email.

+

4 Robust

4.1 Compatible
Success Criterion Result Observations
4.1.2: Name, Role, Value

Result: Passed

Observations:

Aria-label attribute maintained for all images and text hyperlinks. Label for attribute used to associate input elements with descriptive labels.

+
4.1.3: Status Messages

Result: Passed

Observations:

Success feedback provided on form submission, with descriptive errors on failure.

+

Sample of Audited Web Pages

  1. Home - https://www.partsltd.co.uk/
  2. Contact us - https://www.partsltd.co.uk/contact
  3. Services - https://www.partsltd.co.uk/services
  4. -

Web Technology

HTML,CSS,JavaScript,python Flask

Recording of Evaluation Specifics

Not provided

\ No newline at end of file diff --git a/templates/pages/user/_user.html b/templates/pages/user/_user.html new file mode 100644 index 0000000..5b0f028 --- /dev/null +++ b/templates/pages/user/_user.html @@ -0,0 +1,56 @@ +{% extends 'layouts/layout.html' %} + +{% block page_body %} + + + {% set user = model.users[0] %} +
+
+
+
+ + +
+
+
+
+ + +
+
+
+
+ + +
+
+
+
+ + {% set currency = user.currency_default %} + {% include 'components/store/_preview_DDL_currency.html' %} +
+
+
+
+ +
+ {{ user.region_default.name }} +
+
+
+
+
+ + +
+
+
+
+ + {% include 'components/common/temporary/_overlay_confirm.html' %} + {% include 'components/common/temporary/_overlay_error.html' %} + + +{% endblock %} \ No newline at end of file diff --git a/todo.txt b/todo.txt new file mode 100644 index 0000000..672ef30 --- /dev/null +++ b/todo.txt @@ -0,0 +1,4 @@ + +Dark mode / light mode + +git commit -m "Feat: \n 1. Contact Us page form submission success page created. \n 2. Contact Us page styling and CAPTCHA text content. \n 3. Removal of ERP, Google CAPTCHA, and ALTCHA API code and left over comments in JavaScript, Python." \ No newline at end of file diff --git a/webpack.config.js b/webpack.config.js new file mode 100644 index 0000000..a792af4 --- /dev/null +++ b/webpack.config.js @@ -0,0 +1,93 @@ +const path = require('path'); +const glob = require('glob'); +const MiniCssExtractPlugin = require('mini-css-extract-plugin'); + +module.exports = { + entry: { + main: [ + path.resolve(__dirname, 'static/js/app.js'), + path.resolve(__dirname, 'static/css/main.css'), + path.resolve(__dirname, 'static/css/components/button.css'), + path.resolve(__dirname, 'static/css/layouts/header.css'), + path.resolve(__dirname, 'static/css/layouts/footer.css'), + path.resolve(__dirname, 'static/css/lib/reset.css'), + path.resolve(__dirname, 'static/css/lib/typography.css'), + path.resolve(__dirname, 'static/css/lib/utils.css'), + path.resolve(__dirname, 'static/css/lib/variables.css'), + path.resolve(__dirname, 'static/css/themes/light.css'), + // ...glob.sync(path.resolve(__dirname, 'static/css/main/** /*.css')) // Include CSS files for the main page + ], + // Core + core_home: [ + path.resolve(__dirname, 'static/css/sections/core.css'), + path.resolve(__dirname, 'static/css/pages/core/home.css') + ], + core_contact: [ + path.resolve(__dirname, 'static/css/sections/core.css'), + path.resolve(__dirname, 'static/css/pages/core/contact.css') + ], + // Legal + /* + legal_accessibility_report: [ + path.resolve(__dirname, 'static/js/pages/legal/accessibility_report.js'), + path.resolve(__dirname, 'static/css/sections/core.css'), + path.resolve(__dirname, 'static/css/pages/legal/accessibility_report.css') + ], + */ + legal_accessibility_statement: [ + path.resolve(__dirname, 'static/css/sections/legal.css'), + path.resolve(__dirname, 'static/css/pages/legal/accessibility_statement.css') + ], + legal_retention_schedule: [ + path.resolve(__dirname, 'static/css/sections/legal.css'), + path.resolve(__dirname, 'static/css/pages/legal/retention_schedule.css') + ], + legal_license: [ + path.resolve(__dirname, 'static/css/sections/legal.css'), + path.resolve(__dirname, 'static/css/pages/legal/license.css') + ], + legal_privacy_policy: [ + path.resolve(__dirname, 'static/css/sections/legal.css'), + path.resolve(__dirname, 'static/css/pages/legal/privacy_policy.css') + ], + }, + output: { + filename: 'js/[name].bundle.js', + path: path.resolve(__dirname, 'static/dist'), + chunkFilename: '[name].chunk.js', // Non-entry chunk filename + }, + module: { + rules: [ + { + test: /\.css$/, + use: [ + MiniCssExtractPlugin.loader, + 'css-loader', + ], + }, + { + test: /\.js$/, + exclude: path.resolve(__dirname, 'templates'), // Exclude templates folder + use: { + loader: 'babel-loader', + }, + }, + ], + }, + plugins: [ + new MiniCssExtractPlugin({ + filename: 'css/[name].bundle.css', + }), + ], + resolve: { + extensions: ['.js', '.json', '.wasm'] + }, + optimization: { + splitChunks: { + chunks: 'all' + }, + minimize: false, + }, + mode: 'development', + devtool: 'source-map', +}; \ No newline at end of file