diff --git a/README.md b/README.md index 3907417..afb14db 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,8 @@ Please read the latest update post: https://redd.it/flubzn ![screenshot](https://raw.githubusercontent.com/rmountjoy92/DashMachine/master/screenshot3.png) +![screenshot](https://raw.githubusercontent.com/rmountjoy92/DashMachine/master/screenshot4.png) + ### Features * creates a dashboard to view web pages * uses a single .ini file for configuration @@ -21,6 +23,7 @@ Please read the latest update post: https://redd.it/flubzn * user login system * 'app templates' which are sample config entries for popular self hosted apps * powerful plugin system for adding data from various sources to display on cards +* multiple card types including collections and custom cards * multiple users, access groups, access settings * tagging system @@ -58,16 +61,12 @@ Then open a web browser and go to localhost:5000 ## Default user/password ``` User: admin -Password: adminadmin +Password: admin ``` ## Updating For python, use git. For docker, just pull the latest image and recreate the container. -**Note:** if you update DashMachine and it fails to start, it's possible something is messed up -with your database file. Backup your files in the user_data folder, delete the contents and -restart DashMachine. This will reset your user table, so log in with the default user/pass. - ## Configuration The user data folder is located at DashMachine/dashmachine/user_data. This is where the config.ini, custom backgrounds/icons, and the database file live. A reference for what can go into the config.ini file can be found on the settings page of the dashmachine by clicking the info icon next to 'Config'. @@ -102,7 +101,6 @@ Bountysource faq: https://github.com/bountysource/core/wiki/Frequently-Asked-Que * Jinja2 * Materialize css * JavaScript/jQuery/jQueryUI -* Requests (python) ## FAQs 1. application does not work in iframe diff --git a/config_readme.md b/config_readme.md deleted file mode 100644 index 56f3736..0000000 --- a/config_readme.md +++ /dev/null @@ -1,119 +0,0 @@ -#### Config.ini Readme - -##### Settings -This is the configuration entry for DashMachine's settings. DashMachine will not work if -this is missing. As for all config entries, [Settings] can only appear once in the config. -If you change the config.ini file, you either have to restart the container -(or python script) or click the ‘save’ button in the config section of settings for the -config to be applied. -```ini -[Settings] -theme = light -accent = orange -background = None -roles = admin,user,public_user -home_access_groups = admin_only -settings_access_groups = admin_only -custom_app_title = DashMachine -``` - -| Variable | Required | Description | Options | -|------------------------|----------|----------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| [Settings] | Yes | Config section name. | [Settings] | -| theme | Yes | UI theme. | light, dark | -| accent | Yes | UI accent color | orange, red, pink, purple, deepPurple, indigo, blue, lightBlue,cyan, teal, green, lightGreen, lime, yellow, amber, deepOrange, brown, grey, blueGrey | -| background | Yes | Background image for the UI | /static/images/backgrounds/yourpicture.png, external link to image, None, random | -| roles | No | User roles for access groups. | comma separated string, if not defined, this is set to 'admin,user,public_user'. Note: admin, user, public_user roles are required and will be added automatically if omitted. | -| home_access_groups | No | Define which access groups can access the /home page | Groups defined in your config. If not defined, default is admin_only | -| settings_access_groups | No | Define which access groups can access the /settings page | Groups defined in your config. If not defined, default is admin_only | -| custom_app_title | No | Change the title of the app for browser tabs | string | - -##### Apps -These entries are the cards that you see one the home page, as well as the sidenav. Entries -must be unique. They are displayed in the order that they appear in config.ini -```ini -[App Name] -prefix = https:// -url = your-website.com -icon = static/images/apps/default.png -sidebar_icon = static/images/apps/default.png -description = Example description -open_in = iframe -data_sources = None -tags = Example Tag -groups = admin_only -``` - -| Variable | Required | Description | Options | -|--------------|----------|-------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------| -| [App Name] | Yes | The name of your app. | [App Name] | -| prefix | Yes | The prefix for the app's url. | web prefix, e.g. http:// or https:// | -| url | Yes | The url for your app. | web url, e.g. myapp.com | -| open_in | Yes | open the app in the current tab, an iframe or a new tab | iframe, new_tab, this_tab | -| icon | No | Icon for the dashboard. | /static/images/icons/yourpicture.png, external link to image | -| sidebar_icon | No | Icon for the sidenav. | /static/images/icons/yourpicture.png, external link to image | -| description | No | A short description for the app. | string | -| data_sources | No | Data sources to be included on the app's card.*Note: you must have a data source set up in the config above this application entry. | comma separated string | -| tags | No | Optionally specify tags for organization on /home | comma separated string | -| groups | No | Optionally the access groups that can see this app. | comma separated string | - -##### Access Groups -You can create access groups to control what user roles can access parts of the ui. Access groups are just a collection of roles, and each user has an attribute 'role'. Each -application can have an access group, if the user's role is not in the group, the app will be hidden. -Also, in the settings entry you can specify `home_access_groups` and `settings_access_groups` to control -which groups can access /home and /settings -```ini -[admin_only] -roles = admin -``` - -| Variable | Required | Description | Options | -|--------------|----------|--------------------------------------------------------------------------------|----------------------------------------------------------------------------------| -| [Group Name] | Yes | Name for access group. | [Group Name] | -| roles | Yes | A comma separated list of user roles allowed to view apps in this access group | Roles defined in your config. If not defined, defaults are admin and public_user | - -> Say we wanted to create a limited user that still has a login, but can only access `/home` and certain apps we would first create a group: ->```ini ->[users] ->roles = admin, user ->``` ->then we would change in the `[Settings]` entry: ->```ini ->home_access_groups = users ->``` ->By default here, the `user` user could access `/home`, but would see no apps. To allow access, we would add to apps: ->```ini ->groups = users ->``` ->Say we then wanted to allow some access for users without a login (`public_user`), we would add: ->```ini ->[public] ->roles = admin, user, public_user ->``` ->then we would change in the `[Settings]` entry: ->```ini ->home_access_groups = public ->``` ->By default here, the `public_user` user could access `/home`, but would see no apps. To allow access, we would add to apps: ->```ini ->groups = public ->``` - - ->It’s also important to note, when setting up roles in `[Settings]`, say we had roles set like this: ->```ini ->roles = my_people ->``` ->Dashmachine will automatically add `admin,user,public_user`, so really you would have 4 roles: `my_people,admin,user,public_user`. Also, the `admin_only` group is required and added by default if omitted. - -#### Data Source Platforms -DashMachine includes several different 'platforms' for displaying data on your dash applications. -Platforms are essentially plugins. All data source config entries require the `platform` variable, -which tells DashMachine which platform file in the platform folder to load. **Note:** you are able to -load your own platform files by placing them in the platform folder and referencing them in the config. -However currently they will be deleted if you update the application, if you would like to make them -permanent, submit a pull request for it to be added by default! - -> To add a data source to your app, add a data source config entry from one of the samples below -**above** the application entry in config.ini, then add the following to your app config entry: -`data_source = variable_name` diff --git a/dashmachine/__init__.py b/dashmachine/__init__.py index 564fe2b..921a6f6 100755 --- a/dashmachine/__init__.py +++ b/dashmachine/__init__.py @@ -19,6 +19,7 @@ api = Api(app) app.config["AVATARS_IDENTICON_BG"] = (255, 255, 255) app.config["SECRET_KEY"] = "66532a62c4048f976e22a39638b6f10e" app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///user_data/site.db" +app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False app.config["SEND_FILE_MAX_AGE_DEFAULT"] = 0 db = SQLAlchemy(app) diff --git a/dashmachine/main/models.py b/dashmachine/main/models.py index c5ea5af..013045a 100644 --- a/dashmachine/main/models.py +++ b/dashmachine/main/models.py @@ -28,6 +28,8 @@ class Apps(db.Model): data_template = db.Column(db.String()) groups = db.Column(db.String()) tags = db.Column(db.String()) + type = db.Column(db.String()) + urls = db.Column(db.String()) class DataSources(db.Model): @@ -58,3 +60,5 @@ class Groups(db.Model): class Tags(db.Model): id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String()) + icon = db.Column(db.String()) + sort_pos = db.Column(db.Integer) diff --git a/dashmachine/main/read_config.py b/dashmachine/main/read_config.py index 59c5a41..2a019a4 100644 --- a/dashmachine/main/read_config.py +++ b/dashmachine/main/read_config.py @@ -1,6 +1,13 @@ import os +import json from configparser import ConfigParser from dashmachine.main.models import Apps, Groups, DataSources, DataSourcesArgs, Tags +from dashmachine.user_system.models import User +from dashmachine.user_system.utils import ( + hash_and_cache_password, + get_cached_password, + clean_auth_cache, +) from dashmachine.settings_system.models import Settings from dashmachine.paths import user_data_folder from dashmachine import db @@ -30,6 +37,7 @@ def read_config(): Settings.query.delete() Groups.query.delete() Tags.query.delete() + User.query.delete() for section in config.sections(): @@ -61,15 +69,57 @@ def read_config(): settings.settings_access_groups = config["Settings"].get( "settings_access_groups", "admin_only" ) - settings.home_view_mode = config["Settings"].get("home_view_mode", "grid") settings.custom_app_title = config["Settings"].get( "custom_app_title", "DashMachine" ) + settings.sidebar_default = config["Settings"].get("sidebar_default", "open") + + settings.tags_expanded = config["Settings"].get("tags_expanded", "True") + db.session.add(settings) db.session.commit() + # User creation + elif "role" in config[section]: + user = User() + user.username = section + user.role = config[section]["role"] + user.sidebar_default = config[section].get("sidebar_default", None) + user.theme = config[section].get("theme", None) + user.accent = config[section].get("accent", None) + user.tags_expanded = config[section].get("tags_expanded", None) + user.password = "" + if not User.query.filter_by(role="admin").first() and user.role != "admin": + print( + f"Invalid Config: admin user not specified, or not specified first. {user.username} role set to admin" + ) + user.role = "admin" + config.set(section, "role", "admin") + config.write(open(os.path.join(user_data_folder, "config.ini"), "w")) + db.session.add(user) + db.session.commit() + new_password = config[section].get("password", None) + if new_password: + if new_password == config[section].get("confirm_password", None): + password = hash_and_cache_password(new_password, user.id) + user.password = password + db.session.merge(user) + db.session.commit() + else: + password = get_cached_password(user.id) + if password == "error": + print( + f"Invalid Config: Password for {user.username} must be specified. Using 'admin' by default" + ) + user.password = password + db.session.merge(user) + db.session.commit() + config.set(section, "password", "") + config.set(section, "confirm_password", "") + config.write(open(os.path.join(user_data_folder, "config.ini"), "w")) + # Groups creation elif "roles" in config[section]: group = Groups() @@ -98,35 +148,25 @@ def read_config(): # App creation app = Apps() app.name = section - if "prefix" in config[section]: - app.prefix = config[section]["prefix"] - else: + app.type = config[section].get("type", "app") + + app.prefix = config[section].get("prefix", None) + if app.type == "app" and not app.prefix: return {"msg": f"Invalid Config: {section} does not contain prefix."} - if "url" in config[section]: - app.url = config[section]["url"] - else: + app.url = config[section].get("url", None) + if app.type == "app" and not app.url: return {"msg": f"Invalid Config: {section} does not contain url."} - if "icon" in config[section]: - app.icon = config[section]["icon"] - else: - app.icon = None + app.icon = config[section].get("icon", None) - if "sidebar_icon" in config[section]: - app.sidebar_icon = config[section]["sidebar_icon"] - else: - app.sidebar_icon = app.icon + app.sidebar_icon = config[section].get("sidebar_icon", None) - if "description" in config[section]: - app.description = config[section]["description"] - else: - app.description = None + app.description = config[section].get("description", None) - if "open_in" in config[section]: - app.open_in = config[section]["open_in"] - else: - app.open_in = "this_tab" + app.open_in = config[section].get("open_in", "this_tab") + + app.urls = config[section].get("urls", None) if "groups" in config[section]: for group_name in config[section]["groups"].split(","): @@ -138,14 +178,18 @@ def read_config(): else: app.groups = None + # Tags creation if "tags" in config[section]: - app.tags = config[section]["tags"].title() + app.tags = config[section]["tags"] for tag in app.tags.split(","): - tag = tag.strip().title() + tag = tag.strip() if not Tags.query.filter_by(name=tag).first(): tag_db = Tags(name=tag) db.session.add(tag_db) db.session.commit() + tag_db.sort_pos = tag_db.id + db.session.merge(tag_db) + db.session.commit() else: if Tags.query.first(): app.tags = "Untagged" @@ -178,4 +222,33 @@ def read_config(): group.roles = "admin" db.session.add(group) db.session.commit() + + tags_settings = config["Settings"].get("tags", None) + if tags_settings: + tags_settings = tags_settings.replace("},{", "}%,%{").split("%,%") + + for tag_setting in tags_settings: + tag_json = json.loads(tag_setting) + tag = Tags.query.filter_by(name=tag_json.get("name", None)).first() + if tag: + icon = tag_json.get("icon", None) + if icon: + tag.icon = icon + sort_pos = tag_json.get("sort_pos", None) + if icon: + tag.sort_pos = sort_pos + db.session.merge(tag) + db.session.commit() + + clean_auth_cache() + if not User.query.first(): + user = User() + user.username = "admin" + user.role = "admin" + user.password = "" + db.session.add(user) + db.session.commit() + user.password = hash_and_cache_password("admin", user.id) + db.session.merge(user) + db.session.commit() return {"msg": "success", "settings": row2dict(settings)} diff --git a/dashmachine/main/routes.py b/dashmachine/main/routes.py index 9196844..1e6d0bc 100755 --- a/dashmachine/main/routes.py +++ b/dashmachine/main/routes.py @@ -5,13 +5,13 @@ from htmlmin.main import minify from configparser import ConfigParser from flask import render_template, url_for, redirect, request, Blueprint, jsonify from flask_login import current_user -from dashmachine.main.models import Files, Apps, DataSources, Tags -from dashmachine.main.forms import TagsForm +from dashmachine.main.models import Files, Apps, DataSources from dashmachine.main.utils import ( - public_route, check_groups, get_data_source, + mark_update_message_read, ) +from dashmachine.user_system.models import User from dashmachine.settings_system.models import Settings from dashmachine.paths import cache_folder, user_data_folder from dashmachine import app, db @@ -35,28 +35,9 @@ def response_minify(response): return response -# blocks access to all pages (except public routes) unless the user is -# signed in. -@main.before_app_request -def check_valid_login(): - - if any( - [ - request.endpoint.startswith("static"), - current_user.is_authenticated, - getattr(app.view_functions[request.endpoint], "is_public", False), - ] - ): - return - - else: - return redirect(url_for("user_system.login")) - - # ------------------------------------------------------------------------------ # /home # ------------------------------------------------------------------------------ -@public_route @main.route("/") @main.route("/home", methods=["GET"]) def home(): @@ -66,16 +47,21 @@ def home(): return render_template("main/home.html") -@public_route @main.route("/app_view?", methods=["GET"]) -def app_view(app_id): +@main.route("/app_view?", methods=["GET"]) +def app_view(app_id, url=None): settings = Settings.query.first() if not check_groups(settings.home_access_groups, current_user): return redirect(url_for("user_system.login")) - app_db = Apps.query.filter_by(id=app_id).first() - return render_template( - "main/app-view.html", url=f"{app_db.prefix}{app_db.url}", title=app_db.name - ) + + if url: + title = url + + if not url: + app_db = Apps.query.filter_by(id=app_id).first() + url = f"{app_db.prefix}{app_db.url}" + title = app_db.name + return render_template("main/app-view.html", url=url, title=title) @main.route("/load_data_source", methods=["GET"]) @@ -85,18 +71,10 @@ def load_data_source(): return data -@public_route -@main.route("/change_home_view_mode?", methods=["GET"]) -def change_home_view_mode(mode): - config = ConfigParser() - config.read(os.path.join(user_data_folder, "config.ini")) - config.set("Settings", "home_view_mode", mode) - config.write(open(os.path.join(user_data_folder, "config.ini"), "w")) - settings = Settings.query.first() - settings.home_view_mode = mode - db.session.merge(settings) - db.session.commit() - return redirect(url_for("main.home")) +@main.route("/update_message_read", methods=["GET"]) +def update_message_read(): + mark_update_message_read() + return "ok" # ------------------------------------------------------------------------------ diff --git a/dashmachine/main/utils.py b/dashmachine/main/utils.py index 419c7fd..b0fa6be 100755 --- a/dashmachine/main/utils.py +++ b/dashmachine/main/utils.py @@ -1,13 +1,17 @@ import os import importlib from shutil import copyfile -from PIL import Image, ImageOps -from dashmachine.paths import dashmachine_folder, images_folder +from PIL import Image +from markdown2 import markdown +from dashmachine.paths import ( + dashmachine_folder, + images_folder, + root_folder, + user_data_folder, +) from dashmachine.main.models import Groups from dashmachine.main.read_config import read_config -from dashmachine.settings_system.models import Settings -from dashmachine.user_system.models import User -from dashmachine.user_system.utils import add_edit_user +from dashmachine.version import version as dashmachine_version from dashmachine import db @@ -54,20 +58,6 @@ def dashmachine_init(): read_config() - user = User.query.first() - if not user: - settings = Settings.query.first() - add_edit_user( - username="admin", - password="adminadmin", - role=settings.roles.split(",")[0].strip(), - ) - - users = User.query.all() - for user in users: - if not user.role: - user.role = "admin" - def check_groups(groups, current_user): if current_user.is_anonymous: @@ -111,3 +101,35 @@ def resize_template_app_images(): image = Image.open(fp) image.thumbnail((64, 64)) image.save(fp) + + +def get_update_message_html(): + try: + with open(os.path.join(user_data_folder, ".has_read_update"), "r") as has_read: + has_read_version = has_read.read() + except FileNotFoundError: + has_read_version = None + if not has_read_version or has_read_version.strip() != dashmachine_version: + with open( + os.path.join(root_folder, "update_message.md"), "r" + ) as update_message: + md = update_message.read() + + config_html = markdown( + md, + extras=[ + "tables", + "fenced-code-blocks", + "break-on-newline", + "header-ids", + "code-friendly", + ], + ) + return config_html + else: + return "" + + +def mark_update_message_read(): + with open(os.path.join(user_data_folder, ".has_read_update"), "w") as has_read: + has_read.write(dashmachine_version) diff --git a/dashmachine/paths.py b/dashmachine/paths.py index 74cf543..7f624f1 100755 --- a/dashmachine/paths.py +++ b/dashmachine/paths.py @@ -19,6 +19,11 @@ platform_folder = os.path.join(dashmachine_folder, "platform") user_data_folder = os.path.join(dashmachine_folder, "user_data") +auth_cache = os.path.join(user_data_folder, "auth_cache") + +if not os.path.isdir(auth_cache): + os.mkdir(auth_cache) + static_folder = os.path.join(dashmachine_folder, "static") images_folder = os.path.join(static_folder, "images") diff --git a/dashmachine/platform/curl.py b/dashmachine/platform/curl.py index 5fea062..360d9d6 100644 --- a/dashmachine/platform/curl.py +++ b/dashmachine/platform/curl.py @@ -14,7 +14,7 @@ response_type = json | Variable | Required | Description | Options | |-----------------|----------|-----------------------------------------------------------------|-------------------| | [variable_name] | Yes | Name for the data source. | [variable_name] | -| plaform | Yes | Name of the platform. | curl | +| platform | Yes | Name of the platform. | curl | | resource | Yes | Url to curl | url | | value_template | Yes | Jinja template for how the returned data from api is displayed. | jinja template | | response_type | No | Response type. Use json if response is a JSON. Default is plain.| plain,json | diff --git a/dashmachine/platform/http_status.py b/dashmachine/platform/http_status.py new file mode 100644 index 0000000..21b9efc --- /dev/null +++ b/dashmachine/platform/http_status.py @@ -0,0 +1,96 @@ +""" + +##### http_status +Make a http call on a given URL and display if the service is online. +```ini +[variable_name] +platform = http_status +resource = https://your-website.com/api +method = get +authentication = basic +username = my_username +password = my_password +headers = {"Content-Type": "application/json"} +return_codes = 2xx,3xx +``` +> **Returns:** a right-aligned colored bullet point on the app card. + +| Variable | Required | Description | Options | +|-----------------|----------|-----------------------------------------------------------------|-------------------| +| [variable_name] | Yes | Name for the data source. | [variable_name] | +| platform | Yes | Name of the platform. | rest | +| resource | Yes | Url of rest api resource. | url | +| method | No | Method for the api call, default is GET | GET,HEAD,OPTIONS,TRACE| +| authentication | No | Authentication for the api call, default is None | None,basic,digest | +| username | No | Username to use for auth. | string | +| password | No | Password to use for auth. | string | +| headers | No | Request headers | json | +| return_codes | No | Acceptable http status codes, x is handled as wildcard | string | + +> **Working example:** +>```ini +>[http_status_test] +>platform = http_status +>resource = https://google.com +>return_codes = 2xx,3xx +> +>[Google] +>prefix = https:// +>url = google.com +>icon = static/images/apps/default.png +>open_in = this_tab +>data_sources = http_status_test +>``` + +""" + +from requests import Request, Session +from requests.auth import HTTPBasicAuth, HTTPDigestAuth + + +class Platform: + def __init__(self, *args, **kwargs): + # parse the user's options from the config entries + for key, value in kwargs.items(): + self.__dict__[key] = value + + # set defaults for omitted options + if not hasattr(self, "method"): + self.method = "GET" + if not hasattr(self, "authentication"): + self.authentication = None + if not hasattr(self, "headers"): + self.headers = None + if not hasattr(self, "return_codes"): + self.return_codes = "2xx,3xx" + + def process(self): + # Check if method is within allowed methods for http_status + if self.method.upper() not in ["GET", "HEAD", "OPTIONS", "TRACE"]: + raise NotImplementedError + + s = Session() + # prepare Authentication mechanism + if self.authentication: + if self.authentication.lower() == "digest": + auth = HTTPDigestAuth(self.username, self.password) + else: + auth = HTTPBasicAuth(self.username, self.password) + else: + auth = None + + # Send request + req = Request( + self.method.upper(), self.resource, headers=self.headers, auth=auth + ) + prepped = req.prepare() + resp = s.send(prepped) + + return_codes = tuple([x.replace("x", "") for x in self.return_codes.split(",")]) + + if str(resp.status_code).startswith(return_codes): + icon_class = "theme-success-text" + else: + icon_class = "theme-failure-text" + + return f"fiber_manual_record " diff --git a/dashmachine/platform/pihole.py b/dashmachine/platform/pihole.py index b4d24e0..4108553 100644 --- a/dashmachine/platform/pihole.py +++ b/dashmachine/platform/pihole.py @@ -1,3 +1,58 @@ +""" + +##### PiHole +Display information from the PiHole API +```ini +[variable_name] +platform = pihole +host = 192.168.1.101 +password = {{ PiHole password }} +value_template = {{ value_template }} +``` +> **Returns:** `value_template` as rendered string + +| Variable | Required | Description | Options | +|-----------------|----------|-----------------------------------------------------------------|-------------------| +| [variable_name] | Yes | Name for the data source. | [variable_name] | +| platform | Yes | Name of the platform. | pihole | +| host | Yes | Host of the PiHole | host | +| password | Yes | Password for the PiHole | password | +| value_template | Yes | Jinja template for how the returned data from API is displayed. | jinja template | + + +
+###### **Available fields for value_template** + +* domain_count +* queries +* blocked +* ads_percentage +* unique_domains +* forwarded +* cached +* total_clients +* unique_clients +* total_queries +* gravity_last_updated + +> **Working example:** +>```ini +> [pihole-data] +> platform = pihole +> host = 192.168.1.101 +> password = password123 +> value_template = Ads Blocked Today: {{ blocked }}
Status: {{ status }}
Queries today: {{ queries }} +> +> [PiHole] +> prefix = http:// +> url = 192.168.1.101 +> icon = static/images/apps/pihole.png +> description = A black hole for Internet advertisements +> open_in = new_tab +> data_sources = pihole-data +>``` +""" + from flask import render_template_string diff --git a/dashmachine/platform/rest.py b/dashmachine/platform/rest.py index 372617b..307f537 100644 --- a/dashmachine/platform/rest.py +++ b/dashmachine/platform/rest.py @@ -12,6 +12,8 @@ authentication = basic username = my_username password = my_password payload = {"var1": "hi", "var2": 1} +headers = {"Content-Type": "application/json"} +verify = false ``` > **Returns:** `value_template` as rendered string @@ -26,6 +28,8 @@ payload = {"var1": "hi", "var2": 1} | username | No | Username to use for auth. | string | | password | No | Password to use for auth. | string | | payload | No | Payload for post request. | json | +| headers | No | Custom headers for get or post | json | +| verify | No | Turn TLS verification on or off, default is True | true,false | > **Working example:** >```ini @@ -62,24 +66,38 @@ class Platform: self.method = "GET" if not hasattr(self, "authentication"): self.authentication = None + if not hasattr(self, "headers"): + self.headers = None + if not hasattr(self, "verify"): + self.verify = True def process(self): + if self.authentication: + if self.authentication.lower() == "digest": + auth = HTTPDigestAuth(self.username, self.password) + else: + auth = HTTPBasicAuth(self.username, self.password) + else: + auth = None + + verify = False if str(self.verify).lower() == "false" else True + if self.method.upper() == "GET": try: - value = get(self.resource).json() + value = get( + self.resource, auth=auth, headers=self.headers, verify=verify + ).json() except Exception as e: value = f"{e}" elif self.method.upper() == "POST": - if self.authentication: - if self.authentication.lower() == "digest": - auth = HTTPDigestAuth(self.username, self.password) - else: - auth = HTTPBasicAuth(self.username, self.password) - else: - auth = None - payload = json.loads(self.payload.replace("'", '"')) - value = post(self.resource, data=payload, auth=auth) + value = post( + self.resource, + data=payload, + auth=auth, + headers=self.headers, + verify=verify, + ) value_template = render_template_string(self.value_template, value=value) return value_template diff --git a/dashmachine/platform/transmission.py b/dashmachine/platform/transmission.py index 0fef512..00dc05d 100644 --- a/dashmachine/platform/transmission.py +++ b/dashmachine/platform/transmission.py @@ -1,3 +1,57 @@ +""" + +##### Transmission +Display information from the Trasnmission API +```ini +[variable_name] +platform = transmission +host = localhost +port = 9091 +user = {{ transmission Web UI username }} +password = {{ Transmission Web UI password }} +value_template = {{ value_template }} +``` +> **Returns:** `value_template` as rendered string + +| Variable | Required | Description | Options | +|-----------------|----------|-----------------------------------------------------------------|-------------------| +| [variable_name] | Yes | Name for the data source. | [variable_name] | +| platform | Yes | Name of the platform. | transmission | +| host | Yes | Host of Transmission Web UI | host | +| port | Yes | Port of Transmission Web UI | port | +| user | No | Username for Transmission Web UI | username | +| password | No | Password for Transmission Web UI | password | +| value_template | Yes | Jinja template for how the returned data from API is displayed. | jinja template | + +
+###### **Available fields for value_template** + +* downloadSpeed +* uploadSpeed +* activeTorrentCount +* pausedTorrentCount +* torrentCount + +> **Working example:** +>```ini +> [transmission-data] +> platform = transmission +> host = 192.168.1.30 +> port = 9091 +> user = admin +> password = password123 +> value_template = 🔽 {{(downloadSpeed/1024/1024)|round(2)}} MB/s
🔼 {{(uploadSpeed/1024/1024)|round(2)}} MB/s
Active: {{activeTorrentCount}}
+> +> [Transmission] +> prefix = http:// +> url = 192.168.1.30:9091 +> icon = static/images/apps/transmission.png +> description = A Fast, Easy, and Free BitTorrent Client +> open_in = new_tab +> data_sources = transmission-data +>``` +""" + import json from flask import render_template_string import transmissionrpc diff --git a/dashmachine/settings_system/models.py b/dashmachine/settings_system/models.py index ffd4acc..4c4fa29 100644 --- a/dashmachine/settings_system/models.py +++ b/dashmachine/settings_system/models.py @@ -9,5 +9,6 @@ class Settings(db.Model): roles = db.Column(db.String()) home_access_groups = db.Column(db.String()) settings_access_groups = db.Column(db.String()) - home_view_mode = db.Column(db.String()) custom_app_title = db.Column(db.String()) + sidebar_default = db.Column(db.String()) + tags_expanded = db.Column(db.String()) diff --git a/dashmachine/settings_system/routes.py b/dashmachine/settings_system/routes.py index 5635057..7b29cbb 100644 --- a/dashmachine/settings_system/routes.py +++ b/dashmachine/settings_system/routes.py @@ -4,7 +4,6 @@ from configparser import ConfigParser from flask_login import current_user from flask import render_template, request, Blueprint, jsonify, redirect, url_for from dashmachine.user_system.forms import UserForm -from dashmachine.user_system.utils import add_edit_user from dashmachine.user_system.models import User from dashmachine.main.utils import public_route, check_groups from dashmachine.main.read_config import read_config @@ -19,7 +18,6 @@ from dashmachine.paths import ( template_apps_folder, ) from dashmachine.version import version -from dashmachine import db settings_system = Blueprint("settings_system", __name__) @@ -92,55 +90,7 @@ def delete_file(): @settings_system.route("/settings/get_app_template", methods=["GET"]) def get_app_template(): - # template_app = TemplateApps.query.filter_by(name=request.args.get("name")).first() - # template = f"[{template_app.name}]
" - # for key, value in row2dict(template_app).items(): - # if key not in ["id", "name"]: - # template += f"{key} = {value}
" - fn = os.path.join(template_apps_folder, f"{request.args.get('name')}.ini") with open(fn, "r") as template_app_ini: template = template_app_ini.read().replace("\n", "
") return template - - -@settings_system.route("/settings/edit_user", methods=["POST"]) -def edit_user(): - form = UserForm() - settings_db = Settings.query.first() - form.role.choices += [(role, role) for role in settings_db.roles.split(",")] - if form.validate_on_submit(): - if form.password.data != form.confirm_password.data: - return jsonify(data={"err": "Passwords don't match"}) - err = add_edit_user( - form.username.data, - form.password.data, - user_id=form.id.data, - role=form.role.data, - ) - if err: - return jsonify(data={"err": err}) - else: - err_str = "" - for fieldName, errorMessages in form.errors.items(): - err_str += f"{fieldName}: " - for err in errorMessages: - err_str += f"{err} " - return jsonify(data={"err": err_str}) - users = User.query.all() - html = render_template("settings_system/user.html", users=users) - return jsonify(data={"err": "success", "html": html}) - - -@settings_system.route("/settings/delete_user", methods=["GET"]) -def delete_user(): - admin_users = User.query.filter_by(role="admin").all() - user = User.query.filter_by(id=request.args.get("id")).first() - if len(admin_users) < 2 and user.role == "admin": - return jsonify(data={"err": "You must have at least one admin user"}) - else: - User.query.filter_by(id=request.args.get("id")).delete() - db.session.commit() - users = User.query.all() - html = render_template("settings_system/user.html", users=users) - return jsonify(data={"err": "success", "html": html}) diff --git a/dashmachine/settings_system/utils.py b/dashmachine/settings_system/utils.py index 49baded..7a24899 100644 --- a/dashmachine/settings_system/utils.py +++ b/dashmachine/settings_system/utils.py @@ -18,19 +18,8 @@ def load_files_html(): ) -def get_config_html(): - with open(os.path.join(root_folder, "config_readme.md")) as readme_file: - md = readme_file.read() - platforms = os.listdir(platform_folder) - platforms = sorted(platforms) - for platform in platforms: - name, extension = os.path.splitext(platform) - if extension.lower() == ".py": - module = importlib.import_module(f"dashmachine.platform.{name}", ".") - if module.__doc__: - md += module.__doc__ - - config_html = markdown( +def convert_html_to_md(md): + html = markdown( md, extras=[ "tables", @@ -40,4 +29,28 @@ def get_config_html(): "code-friendly", ], ) - return config_html + return html + + +def get_config_html(): + with open(os.path.join(root_folder, "readme_settings.md")) as readme_file: + md = readme_file.read() + html = {"settings": convert_html_to_md(md)} + + with open(os.path.join(root_folder, "readme_cards.md")) as readme_file: + md = readme_file.read() + html["cards"] = convert_html_to_md(md) + + with open(os.path.join(root_folder, "readme_data_sources.md")) as readme_file: + md = readme_file.read() + platforms = os.listdir(platform_folder) + platforms = sorted(platforms) + for platform in platforms: + name, extension = os.path.splitext(platform) + if extension.lower() == ".py": + module = importlib.import_module(f"dashmachine.platform.{name}", ".") + if module.__doc__: + md += module.__doc__ + html["data_sources"] = convert_html_to_md(md) + + return html diff --git a/dashmachine/site.db b/dashmachine/site.db index 3657cdf..27af106 100644 Binary files a/dashmachine/site.db and b/dashmachine/site.db differ diff --git a/dashmachine/sources.py b/dashmachine/sources.py index 6055ccd..ade73ec 100644 --- a/dashmachine/sources.py +++ b/dashmachine/sources.py @@ -1,10 +1,11 @@ import os +import json import random from jsmin import jsmin from flask_login import current_user from dashmachine import app -from dashmachine.main.models import Apps -from dashmachine.main.utils import check_groups +from dashmachine.main.models import Apps, Tags +from dashmachine.main.utils import check_groups, get_update_message_html from dashmachine.main.forms import TagsForm from dashmachine.settings_system.models import Settings from dashmachine.paths import static_folder, backgrounds_images_folder @@ -73,24 +74,38 @@ def process_css_sources(process_bundle=None, src=None, app_global=False): return html +def tag_sort_func(e): + return e.sort_pos + + @app.context_processor def context_processor(): apps = [] + temp_tags = [] tags = [] apps_db = Apps.query.all() for app_db in apps_db: + if app_db.urls: + url_list = app_db.urls.replace("},{", "}%,%{").split("%,%") + app_db.urls_json = [] + for url in url_list: + app_db.urls_json.append(json.loads(url)) if not app_db.groups: app_db.groups = None if check_groups(app_db.groups, current_user): apps.append(app_db) if app_db.tags: - tags += app_db.tags.split(",") + temp_tags += app_db.tags.split(",") tags_form = TagsForm() - if len(tags) > 0: - tags = [tag.strip() for tag in tags] - tags = list(dict.fromkeys(tags)) - tags_form.tags.choices += [(tag, tag) for tag in tags] + if len(temp_tags) > 0: + temp_tags = list(dict.fromkeys([tag.strip() for tag in temp_tags])) + tags_form.tags.choices += [(tag, tag) for tag in temp_tags] + for tag in temp_tags: + tag_db = Tags.query.filter_by(name=tag).first() + if tag_db: + tags.append(tag_db) + tags.sort(key=tag_sort_func) settings = Settings.query.first() if settings.background == "random": if len(os.listdir(backgrounds_images_folder)) < 1: @@ -100,11 +115,14 @@ def context_processor(): f"static/images/backgrounds/" f"{random.choice(os.listdir(backgrounds_images_folder))}" ) + update_message = get_update_message_html() return dict( test_key="test", process_js_sources=process_js_sources, process_css_sources=process_css_sources, apps=apps, settings=settings, + tags=tags, tags_form=tags_form, + update_message=update_message, ) diff --git a/dashmachine/static/css/global/dashmachine.css b/dashmachine/static/css/global/dashmachine.css index 7eb485b..66c6101 100644 --- a/dashmachine/static/css/global/dashmachine.css +++ b/dashmachine/static/css/global/dashmachine.css @@ -36,6 +36,10 @@ overflow-y: scroll !important; overflow-x: hidden !important; } +.scrollbar-x { + overflow-y: scroll !important; + overflow-x: scroll !important; +} /* ELEMENT STLYES */ body { @@ -333,15 +337,27 @@ input:disabled { .navbar .navbar-light ul a { color: var(--theme-color-font); } -/*@media (min-width: 900px)*/ -/*{*/ -/* .sidenav-overlay*/ -/* {*/ -/* display: none !important;*/ +.sidenav { + background-color: var(--theme-surface); + top: unset; + overflow-y: scroll; + scrollbar-width: none; +} -/* opacity: 0 !important;*/ -/* }*/ -/*}*/ +#sidenav-mobile-toggle-btn { + position: fixed; + top: unset; + bottom: 10px; +} +.sidenav-active-rounded .sidenav li > a.active > i { + color: var(--theme-on-primary) !important; +} +.sidenav-active-rounded .sidenav li > a.active > span { + color: var(--theme-on-primary) !important; +} +.sidenav-active-rounded .sidenav li > a.active { + min-width: 3.6rem; +} /* MODALS AND CARDS */ .modal { @@ -383,7 +399,10 @@ input:disabled { border-radius: 8px; background: var(--theme-surface); } - +.card .card-reveal { + border-radius: 8px; + background: var(--theme-surface); +} /* TABS */ .tabs { @@ -461,71 +480,6 @@ input:disabled { margin-right: 5px; } -/* DATE AND TIME PICKERS */ -.datepicker-date-display { - background-color: var(--theme-primary) -} - -.datepicker-cancel { - color: var(--theme-primary) -} - -.datepicker-done { - color: var(--theme-primary) -} - -.datepicker-modal { - border-radius: 12px; - z-index: 2001 !important; -} - -.is-today { - color: var(--theme-primary) !important -} - -.is-selected { - background-color: var(--theme-primary) !important -} - -.timepicker-close { - color: var(--theme-primary) -} - -.timepicker-digital-display { - background: var(--theme-primary) -} - -.timepicker-canvas-bg, -.timepicker-canvas-bearing { - fill: var(--theme-primary); -} - -.timepicker-canvas line { - stroke: var(--theme-primary); -} - -.timepicker input[type=text]:not(.browser-default) { - border-bottom: 1px solid var(--theme-primary) !important; - box-shadow: 0 1px 0 0 var(--theme-primary) !important; -} - -.date-field, .time-field { - color: var(--theme-primary) !important; - max-width: 60px; - max-height: 20px; - margin: 0 !important; - border: 0 !important; - cursor: pointer; - font-size: 13.5px !important; - position: relative; - bottom: 6px; -} - -.date-field:focus { - color: var(--theme-primary) !important; -} - - /* "CARD FILTER" GLOBAL SEXY SEARCH BAR */ .card-filter-container { position: -webkit-sticky; @@ -572,109 +526,6 @@ input:disabled { color: var(--theme-secondary); } -/* CARD SECTIONS USED IN DEALS AND PROFILES */ -.tabs-card { - border-bottom-right-radius: 0px !important; - border-bottom-left-radius: 0px !important; - z-index: 1; - -webkit-box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.12), 0 1px 3px 0 rgba(0, 0, 0, 0.12), 0 1px 3px 0 rgba(0, 0, 0, 0); - box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.12), 0 1px 3px 0 rgba(0, 0, 0, 0.12), 0 1px 3px 0 rgba(0, 0, 0, 0); -} - -.filter-card { - border-radius: 0 0 0 0 !important; - z-index: 3; - -webkit-box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.12), 0 1px 3px 0 rgba(0, 0, 0, 0.12), 0 1px 3px 0 rgba(0, 0, 0, 0.12); - box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.12), 0 1px 3px 0 rgba(0, 0, 0, 0.12), 0 1px 3px 0 rgba(0, 0, 0, 0.12); -} - -.rows-card { - z-index: 2; - border-top-right-radius: 0px !important; - border-top-left-radius: 0px !important; - -webkit-box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.12), 0 1px 3px 0 rgba(0, 0, 0, 0.12), 0 1px 3px 0 rgba(0, 0, 0, 0.12); - box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.12), 0 1px 3px 0 rgba(0, 0, 0, 0.12), 0 1px 3px 0 rgba(0, 0, 0, 0.12); -} - -/* FEED */ -#feed-body { - min-height: calc(100vh - 220px); - max-height: calc(100vh - 220px); -} -#slide-out-right.sidenav #activity .header-search-input { - background-color: var(--theme-background); -} - -#slide-out-right.sidenav { - max-height: calc(100vh - 64px); - bottom: 0; - top: unset; - width: 380px; - z-index: 100; -} - -.slide-out-right-body { - overflow: hidden; -} - -.sidenav { - background-color: var(--theme-surface); - top: unset; - overflow-y: scroll; - scrollbar-width: none; -} - -#sidenav-mobile-toggle-btn { - position: fixed; - top: unset; - bottom: 10px; -} -.sidenav-active-rounded .sidenav li > a.active > i { - color: var(--theme-on-primary) !important; -} -.sidenav-active-rounded .sidenav li > a.active > span { - color: var(--theme-on-primary) !important; -} -.sidenav-active-rounded .sidenav li > a.active { - min-width: 3.6rem; -} - -.border-bottom-1 { - border-bottom: 1px solid var(--theme-background); -} - -#feed-rows-ul .feed-item-li { - background-color: var(--theme-surface); -} - -/* Settings collapsible */ -.settings-collapsible { - border-radius: 12px; - border: transparent; -} - -.settings-collapsible li { - background-color: var(--theme-surface-1); - border-radius: 12px; - border: transparent; -} - -.settings-collapsible .collapsible-header { - border-radius: 12px; - border: transparent; - background-color: var(--theme-surface-1); -} - -.settings-collapsible .collapsible-body { - border-radius: 12px; - border: transparent; - background-color: var(--theme-surface-1); -} - -.settings-collapsible .collection-item { - border: transparent; -} - /* MISC COMPONENTS */ .divider { margin-top: 15px; @@ -688,12 +539,6 @@ span.badge.new { float: unset; } -#breadcrumbs-wrapper { - padding-top: 0px; - padding-bottom: 10px; - background: var(--theme-background); -} - .toast { border-radius: 10px !important; } @@ -712,29 +557,6 @@ span.badge.new { max-width: 25vh; } -.task-filter-button { - margin: 5px; - font-weight: bolder; -} - -.avatar-img { - background-color: #fff; -} - -.big-icon-btn { - width: 100%; - border-radius: 20px; - padding: 15px; - background: var(--theme-surface-1); - -webkit-box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.12), 0 1px 3px 0 rgba(0, 0, 0, 0.12), 0 1px 3px 0 rgba(0, 0, 0, 0.12); - box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.12), 0 1px 3px 0 rgba(0, 0, 0, 0.12), 0 1px 3px 0 rgba(0, 0, 0, 0.12); -} - -.big-icon-btn .material-icons-outlined { - font-size: 5rem; - color: var(--theme-secondary); -} - .icon-btn, .icon-btn-warning { padding: 5px; cursor: pointer; @@ -759,19 +581,6 @@ span.badge.new { box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.12), 0 1px 3px 0 rgba(0, 0, 0, 0.12), 0 1px 3px 0 rgba(0, 0, 0, 0.12); } -.label-filter .material-icons-outlined, -.contact-filter .material-icons-outlined, -.deal-filter .material-icons-outlined, -.task-filter .material-icons-outlined { - position: relative; - top: 6px -} - -.deals-collection .deal-row-img { - height: 64px; - border-radius: 12px; -} - .progress { background-color: var(--theme-background); } @@ -780,15 +589,6 @@ span.badge.new { background-color: var(--theme-primary); } -.task-type-icon { - background: var(--theme-primary); - border-radius: 24px; - padding: 5px; - font-size: 16px; - position: relative; - right: 10px; -} - /*FAB*/ .tap-target-wave::before, .tap-target-wave::after { background-color: var(--theme-background); diff --git a/dashmachine/static/css/main/home.css b/dashmachine/static/css/main/home.css index 97ad099..5da6ba7 100644 --- a/dashmachine/static/css/main/home.css +++ b/dashmachine/static/css/main/home.css @@ -17,11 +17,16 @@ @media screen and (max-width: 992px) { .tags-select-col { top: 0; - width: calc(100vw - 45px) !important; - margin-left: 15px !important; + /*width: calc(100vw - 45px) !important;*/ + /*margin-left: 15px !important;*/ } } +.app-card .card-reveal { + position: + +} + #list-view-collection .app-a { background: rgba(var(--theme-surface-rgb), 0.8); } diff --git a/dashmachine/static/css/settings_system/settings.css b/dashmachine/static/css/settings_system/settings.css index eb92ad7..5134a24 100644 --- a/dashmachine/static/css/settings_system/settings.css +++ b/dashmachine/static/css/settings_system/settings.css @@ -28,18 +28,18 @@ background: var(--theme-surface-1); } -#config-readme h5 { +#settings-readme h5, #cards-readme h5, #data-sources-readme h5 { color: var(--theme-primary); margin-top: 5%; } -#config-readme h4 { +#settings-readme h4, #cards-readme h4, #data-sources-readme h4 { color: var(--theme-color-font-muted); margin-top: 5%; } #configini-readme { margin-top: 2% !important; } -#config-readme code { +#settings-readme code, #cards-readme code, #data-sources-readme code { -webkit-touch-callout: all; -webkit-user-select: all; -khtml-user-select: all; @@ -47,11 +47,12 @@ -ms-user-select: all; user-select: all; cursor: text; + white-space: pre-wrap; } -#config-readme th { +#settings-readme th, #cards-readme th, #data-sources-readme th { color: var(--theme-primary); } -#config-readme td { +#settings-readme td, #cards-readme td, #data-sources-readme td { -webkit-touch-callout: text !important; -webkit-user-select: text !important; -khtml-user-select: text !important; @@ -60,6 +61,6 @@ user-select: text !important; cursor: text; } -#config-readme strong { +#settings-readme strong, #cards-readme strong, #data-sources-readme strong { font-weight: 900; } \ No newline at end of file diff --git a/dashmachine/static/images/apps/glances.png b/dashmachine/static/images/apps/glances.png new file mode 100644 index 0000000..1384096 Binary files /dev/null and b/dashmachine/static/images/apps/glances.png differ diff --git a/dashmachine/static/js/global/dashmachine.js b/dashmachine/static/js/global/dashmachine.js index 9ebbf19..b95d585 100644 --- a/dashmachine/static/js/global/dashmachine.js +++ b/dashmachine/static/js/global/dashmachine.js @@ -67,6 +67,13 @@ function hide_sidenav() { localStorage.setItem('sidenav_hidden', 'true'); } +function no_sidebar() { + $("#main-sidenav").remove(); + $("#main.main-full").css('padding-left', 0); + $("#no-sidenav").removeClass('hide'); + localStorage.setItem('sidenav_hidden', 'no_sidebar'); +} + function show_sidenav(){ $("#main-sidenav").removeClass('hide'); $("#main.main-full").css('padding-left', 64); @@ -74,26 +81,80 @@ function show_sidenav(){ localStorage.setItem('sidenav_hidden', null); } -function apply_settings(settings_theme, settings_accent){ - localStorage.setItem('mode', settings_theme); - document.documentElement.setAttribute('data-theme', settings_theme); - localStorage.setItem('accent', settings_accent); - document.documentElement.setAttribute('data-accent', settings_accent); +function apply_settings(settings){ + // theme + if (settings['user_theme'] != "None" && settings['user_theme'].length > 1) { + console.log(settings['user_theme'].length) + localStorage.setItem('mode', settings['user_theme']); + document.documentElement.setAttribute('data-theme', settings['user_theme']); + } else { + localStorage.setItem('mode', settings['settings_theme']); + document.documentElement.setAttribute('data-theme', settings['settings_theme']); + } + // accent + if (settings['user_accent'] != "None" && settings['user_accent'].length > 1) { + localStorage.setItem('accent', settings['user_accent']); + document.documentElement.setAttribute('data-accent', settings['user_accent']); + } else { + localStorage.setItem('accent', settings['settings_accent']); + document.documentElement.setAttribute('data-accent', settings['settings_accent']); + } + if (settings['settings_sidebar_default'] == "closed"){ + localStorage.setItem('sidenav_hidden', 'true'); + } else if (settings['settings_sidebar_default'] == "open"){ + localStorage.setItem('sidenav_hidden', 'false'); + } else if (settings['settings_sidebar_default'] == "no_sidebar"){ + localStorage.setItem('sidenav_hidden', 'no_sidebar'); + } + if (settings['user_sidebar_default'] == "closed"){ + localStorage.setItem('sidenav_hidden', 'true'); + } else if (settings['user_sidebar_default'] == "open"){ + localStorage.setItem('sidenav_hidden', 'false'); + } else if (settings['user_sidebar_default'] == "no_sidebar"){ + localStorage.setItem('sidenav_hidden', 'no_sidebar'); + } + if (localStorage.getItem('sidenav_hidden') === 'true'){ + hide_sidenav(); + } else if (localStorage.getItem('sidenav_hidden') === 'no_sidebar'){ + no_sidebar(); + } else if (settings['user_name'].length < 1) { + no_sidebar(); + } } //-------------------------------------------------------------------------------------- // Document ready function //-------------------------------------------------------------------------------------- $(document).ready(function () { - apply_settings($("#settings-theme").val(), $("#settings-accent").val()); "use strict"; + apply_settings({ + settings_theme: $("#settings-theme").val(), + settings_accent: $("#settings-accent").val(), + settings_sidebar_default: $("#settings-sidebar_default").val(), + user_name: $("#user-name").val(), + user_theme: $("#user-theme").val(), + user_accent: $("#user-accent").val(), + user_sidebar_default: $("#user-sidebar_default").val(), + }); // INITS init_select(); - if (localStorage.getItem('sidenav_hidden') === 'true'){ - hide_sidenav(); + $("#update-message-modal").modal({ + dismissible: false + }); + if ($("#update-message-content").text().length > 1){ + $("#update-message-modal").modal('open'); } + $("#update-message-read-btn").on('click', function(e) { + $.ajax({ + url: $(this).attr('data-url'), + type: 'GET', + success: function(data){ + $("#update-message-modal").modal('close'); + } + }); + }); $("#hide-sidenav").on('click', function(e) { hide_sidenav(); diff --git a/dashmachine/static/js/global/keyboard-shortcuts.js b/dashmachine/static/js/global/keyboard-shortcuts.js deleted file mode 100644 index e69de29..0000000 diff --git a/dashmachine/static/js/main/home.js b/dashmachine/static/js/main/home.js index 7296550..e3f4574 100644 --- a/dashmachine/static/js/main/home.js +++ b/dashmachine/static/js/main/home.js @@ -1,22 +1,49 @@ var d = document.getElementById("dashboard-sidenav"); d.className += " active theme-primary"; +function get_data_source(el){ + el.html(""); + el.closest('.col').find('.data-source-loading').removeClass('hide'); + $.ajax({ + async: true, + url: el.attr('data-url'), + type: 'GET', + data: {id: el.attr('data-id')}, + success: function(data){ + el.closest('.col').find('.data-source-loading').addClass('hide'); + el.html(data); + } + }); +} + $( document ).ready(function() { $(".tooltipped").tooltip(); $("#apps-filter").on('keyup', function(e) { + $(".toggle-tag-expand-btn").each(function(e) { + if ($(this).attr("data-expanded") == 'false'){ + $(this)[0].click(); + } + }); var value = $(this).val().toLowerCase(); - $(".app-a").each(function(i, e) { - if ($(this).attr("data-name").toLowerCase().indexOf(value) > -1 - || $(this).attr("data-description").toLowerCase().indexOf(value) > -1) { + + $(".app-card").each(function(e) { + var x = 0 + $(this).find('.searchable').each(function(e) { + if ($(this).text().toLowerCase().indexOf(value) > -1) { + x = x + 1 + } + }); + if (x > 0){ $(this).removeClass('hide'); } else { $(this).addClass('hide'); } }); + $(".tag-group").each(function(i, e) { var x = 0 - $(this).find('.app-a').each(function(i, e) { + $(this).find('.app-card').each(function(i, e) { if ($(this).hasClass("hide") === false){ x = x + 1 } @@ -30,21 +57,22 @@ $( document ).ready(function() { }); $(".data-source-container").each(function(e) { - var el = $(this); - $.ajax({ - url: el.attr('data-url'), - type: 'GET', - data: {id: el.attr('data-id')}, - success: function(data){ - el.closest('.col').find('.data-source-loading').addClass('hide'); - el.html(data); - } + get_data_source($(this)); + }); + + $(".refresh-data-source-btn").on('click', function(e) { + e.preventDefault(); + $(this).closest('.app-card').find(".data-source-container").each(function(e) { + get_data_source($(this)); }); }); $("#tags-select").on('change', function(e) { var value = $(this).val(); $(".tag-group").each(function(i, e) { + if ($(this).find('.toggle-tag-expand-btn').attr("data-expanded") == "false"){ + $(this).find('.toggle-tag-expand-btn')[0].click(); + } if ($(this).attr("data-tag").indexOf(value) > -1 || value === "All tags") { $(this).removeClass('filtered'); } else { @@ -52,4 +80,53 @@ $( document ).ready(function() { } }); }); + + $(".toggle-tag-expand-btn").on('click', function(e) { + if ($(this).attr("data-expanded") == "true"){ + $(this).attr("data-expanded", "false"); + $(this).text('keyboard_arrow_down'); + $(this).closest('.tag-group').find('.tag-apps-row').addClass('hide'); + } else { + $(this).attr("data-expanded", "true"); + $(this).text('keyboard_arrow_up'); + $(this).closest('.tag-group').find('.tag-apps-row').removeClass('hide'); + } + var x = 0 + $(".toggle-tag-expand-btn").each(function(e) { + if ($(this).attr("data-expanded") == "true") { + x = x + 1 + } + }); + if (x > 0) { + $("#toggle-tag-expand-all-btn").text('unfold_less'); + } else { + $("#toggle-tag-expand-all-btn").text('unfold_more'); + } + }); + + $("#toggle-tag-expand-all-btn").on('click', function(e) { + if ($(this).text() == "unfold_more") { + $(".toggle-tag-expand-btn").each(function(e) { + $(this)[0].click(); + }); + } else { + $(".toggle-tag-expand-btn").each(function(e) { + if ($(this).attr("data-expanded") == "true"){ + $(this)[0].click(); + } + }); + } + }); + + if ($("#settings-tags_expanded").val() == "False" || $("#user-tags_expanded").val() == "False"){ + $(".toggle-tag-expand-btn").each(function(e) { + $(this)[0].click(); + }); + if ($("#user-tags_expanded").val() == "True"){ + $(".toggle-tag-expand-btn").each(function(e) { + $(this)[0].click(); + }); + } + } + }); \ No newline at end of file diff --git a/dashmachine/static/js/settings_system/settings.js b/dashmachine/static/js/settings_system/settings.js index d1f7e41..9bb0a01 100644 --- a/dashmachine/static/js/settings_system/settings.js +++ b/dashmachine/static/js/settings_system/settings.js @@ -2,7 +2,7 @@ var d = document.getElementById("settings-sidenav"); d.className += " active theme-primary"; $( document ).ready(function() { - $("#config-readme table").addClass('responsive-table'); + $("#settings-readme table").addClass('responsive-table'); initTCdrop('#images-tcdrop'); $("#user-modal").modal({ onCloseEnd: function () { diff --git a/dashmachine/static/vendors/tinymce/jquery.tinymce.min.js b/dashmachine/static/vendors/tinymce/jquery.tinymce.min.js deleted file mode 100644 index 4a69c27..0000000 --- a/dashmachine/static/vendors/tinymce/jquery.tinymce.min.js +++ /dev/null @@ -1 +0,0 @@ -!function(){var f,c,u,p,d,s=[];d="undefined"!=typeof global?global:window,p=d.jQuery;var v=function(){return d.tinymce};p.fn.tinymce=function(o){var e,t,i,l=this,r="";if(!l.length)return l;if(!o)return v()?v().get(l[0].id):null;l.css("visibility","hidden");var n=function(){var a=[],c=0;u||(m(),u=!0),l.each(function(e,t){var n,i=t.id,r=o.oninit;i||(t.id=i=v().DOM.uniqueId()),v().get(i)||(n=v().createEditor(i,o),a.push(n),n.on("init",function(){var e,t=r;l.css("visibility",""),r&&++c==a.length&&("string"==typeof t&&(e=-1===t.indexOf(".")?null:v().resolve(t.replace(/\.\w+$/,"")),t=v().resolve(t)),t.apply(e||v(),a))}))}),p.each(a,function(e,t){t.render()})};if(d.tinymce||c||!(e=o.script_url))1===c?s.push(n):n();else{c=1,t=e.substring(0,e.lastIndexOf("/")),-1!=e.indexOf(".min")&&(r=".min"),d.tinymce=d.tinyMCEPreInit||{base:t,suffix:r},-1!=e.indexOf("gzip")&&(i=o.language||"en",e=e+(/\?/.test(e)?"&":"?")+"js=true&core=true&suffix="+escape(r)+"&themes="+escape(o.theme||"modern")+"&plugins="+escape(o.plugins||"")+"&languages="+(i||""),d.tinyMCE_GZ||(d.tinyMCE_GZ={start:function(){var n=function(e){v().ScriptLoader.markDone(v().baseURI.toAbsolute(e))};n("langs/"+i+".js"),n("themes/"+o.theme+"/theme"+r+".js"),n("themes/"+o.theme+"/langs/"+i+".js"),p.each(o.plugins.split(","),function(e,t){t&&(n("plugins/"+t+"/plugin"+r+".js"),n("plugins/"+t+"/langs/"+i+".js"))})},end:function(){}}));var a=document.createElement("script");a.type="text/javascript",a.onload=a.onreadystatechange=function(e){e=e||window.event,2===c||"load"!=e.type&&!/complete|loaded/.test(a.readyState)||(v().dom.Event.domLoaded=1,c=2,o.script_loaded&&o.script_loaded(),n(),p.each(s,function(e,t){t()}))},a.src=e,document.body.appendChild(a)}return l},p.extend(p.expr[":"],{tinymce:function(e){var t;return!!(e.id&&"tinymce"in d&&(t=v().get(e.id))&&t.editorManager===v())}});var m=function(){var r=function(e){"remove"===e&&this.each(function(e,t){var n=l(t);n&&n.remove()}),this.find("span.mceEditor,div.mceEditor").each(function(e,t){var n=v().get(t.id.replace(/_parent$/,""));n&&n.remove()})},o=function(i){var e,t=this;if(null!=i)r.call(t),t.each(function(e,t){var n;(n=v().get(t.id))&&n.setContent(i)});else if(0])*>/g,""):n.getContent({save:!0}):a.apply(p(t),r)}),i}}),p.each(["append","prepend"],function(e,t){var n=s[t]=p.fn[t],r="prepend"===t;p.fn[t]=function(i){var e=this;return u(e)?i!==f?("string"==typeof i&&e.filter(":tinymce").each(function(e,t){var n=l(t);n&&n.setContent(r?i+n.getContent():n.getContent()+i)}),n.apply(e.not(":tinymce"),arguments),e):void 0:n.apply(e,arguments)}}),p.each(["remove","replaceWith","replaceAll","empty"],function(e,t){var n=s[t]=p.fn[t];p.fn[t]=function(){return r.call(this,t),n.apply(this,arguments)}}),s.attr=p.fn.attr,p.fn.attr=function(e,t){var n=this,i=arguments;if(!e||"value"!==e||!u(n))return s.attr.apply(n,i);if(t!==f)return o.call(n.filter(":tinymce"),t),s.attr.apply(n.not(":tinymce"),i),n;var r=n[0],a=l(r);return a?a.getContent({save:!0}):s.attr.apply(p(r),i)}}}(); \ No newline at end of file diff --git a/dashmachine/static/vendors/tinymce/langs/readme.md b/dashmachine/static/vendors/tinymce/langs/readme.md deleted file mode 100644 index a52bf03..0000000 --- a/dashmachine/static/vendors/tinymce/langs/readme.md +++ /dev/null @@ -1,3 +0,0 @@ -This is where language files should be placed. - -Please DO NOT translate these directly use this service: https://www.transifex.com/projects/p/tinymce/ diff --git a/dashmachine/static/vendors/tinymce/license.txt b/dashmachine/static/vendors/tinymce/license.txt deleted file mode 100644 index b17fc90..0000000 --- a/dashmachine/static/vendors/tinymce/license.txt +++ /dev/null @@ -1,504 +0,0 @@ - GNU LESSER GENERAL PUBLIC LICENSE - Version 2.1, February 1999 - - Copyright (C) 1991, 1999 Free Software Foundation, Inc. - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - -[This is the first released version of the Lesser GPL. It also counts - as the successor of the GNU Library Public License, version 2, hence - the version number 2.1.] - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -Licenses are intended to guarantee your freedom to share and change -free software--to make sure the software is free for all its users. - - This license, the Lesser General Public License, applies to some -specially designated software packages--typically libraries--of the -Free Software Foundation and other authors who decide to use it. You -can use it too, but we suggest you first think carefully about whether -this license or the ordinary General Public License is the better -strategy to use in any particular case, based on the explanations below. - - When we speak of free software, we are referring to freedom of use, -not price. Our General Public Licenses are designed to make sure that -you have the freedom to distribute copies of free software (and charge -for this service if you wish); that you receive source code or can get -it if you want it; that you can change the software and use pieces of -it in new free programs; and that you are informed that you can do -these things. - - To protect your rights, we need to make restrictions that forbid -distributors to deny you these rights or to ask you to surrender these -rights. These restrictions translate to certain responsibilities for -you if you distribute copies of the library or if you modify it. - - For example, if you distribute copies of the library, whether gratis -or for a fee, you must give the recipients all the rights that we gave -you. You must make sure that they, too, receive or can get the source -code. If you link other code with the library, you must provide -complete object files to the recipients, so that they can relink them -with the library after making changes to the library and recompiling -it. And you must show them these terms so they know their rights. - - We protect your rights with a two-step method: (1) we copyright the -library, and (2) we offer you this license, which gives you legal -permission to copy, distribute and/or modify the library. - - To protect each distributor, we want to make it very clear that -there is no warranty for the free library. Also, if the library is -modified by someone else and passed on, the recipients should know -that what they have is not the original version, so that the original -author's reputation will not be affected by problems that might be -introduced by others. - - Finally, software patents pose a constant threat to the existence of -any free program. We wish to make sure that a company cannot -effectively restrict the users of a free program by obtaining a -restrictive license from a patent holder. Therefore, we insist that -any patent license obtained for a version of the library must be -consistent with the full freedom of use specified in this license. - - Most GNU software, including some libraries, is covered by the -ordinary GNU General Public License. This license, the GNU Lesser -General Public License, applies to certain designated libraries, and -is quite different from the ordinary General Public License. We use -this license for certain libraries in order to permit linking those -libraries into non-free programs. - - When a program is linked with a library, whether statically or using -a shared library, the combination of the two is legally speaking a -combined work, a derivative of the original library. The ordinary -General Public License therefore permits such linking only if the -entire combination fits its criteria of freedom. The Lesser General -Public License permits more lax criteria for linking other code with -the library. - - We call this license the "Lesser" General Public License because it -does Less to protect the user's freedom than the ordinary General -Public License. It also provides other free software developers Less -of an advantage over competing non-free programs. These disadvantages -are the reason we use the ordinary General Public License for many -libraries. However, the Lesser license provides advantages in certain -special circumstances. - - For example, on rare occasions, there may be a special need to -encourage the widest possible use of a certain library, so that it becomes -a de-facto standard. To achieve this, non-free programs must be -allowed to use the library. A more frequent case is that a free -library does the same job as widely used non-free libraries. In this -case, there is little to gain by limiting the free library to free -software only, so we use the Lesser General Public License. - - In other cases, permission to use a particular library in non-free -programs enables a greater number of people to use a large body of -free software. For example, permission to use the GNU C Library in -non-free programs enables many more people to use the whole GNU -operating system, as well as its variant, the GNU/Linux operating -system. - - Although the Lesser General Public License is Less protective of the -users' freedom, it does ensure that the user of a program that is -linked with the Library has the freedom and the wherewithal to run -that program using a modified version of the Library. - - The precise terms and conditions for copying, distribution and -modification follow. Pay close attention to the difference between a -"work based on the library" and a "work that uses the library". The -former contains code derived from the library, whereas the latter must -be combined with the library in order to run. - - GNU LESSER GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License Agreement applies to any software library or other -program which contains a notice placed by the copyright holder or -other authorized party saying it may be distributed under the terms of -this Lesser General Public License (also called "this License"). -Each licensee is addressed as "you". - - A "library" means a collection of software functions and/or data -prepared so as to be conveniently linked with application programs -(which use some of those functions and data) to form executables. - - The "Library", below, refers to any such software library or work -which has been distributed under these terms. A "work based on the -Library" means either the Library or any derivative work under -copyright law: that is to say, a work containing the Library or a -portion of it, either verbatim or with modifications and/or translated -straightforwardly into another language. (Hereinafter, translation is -included without limitation in the term "modification".) - - "Source code" for a work means the preferred form of the work for -making modifications to it. For a library, complete source code means -all the source code for all modules it contains, plus any associated -interface definition files, plus the scripts used to control compilation -and installation of the library. - - Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running a program using the Library is not restricted, and output from -such a program is covered only if its contents constitute a work based -on the Library (independent of the use of the Library in a tool for -writing it). Whether that is true depends on what the Library does -and what the program that uses the Library does. - - 1. You may copy and distribute verbatim copies of the Library's -complete source code as you receive it, in any medium, provided that -you conspicuously and appropriately publish on each copy an -appropriate copyright notice and disclaimer of warranty; keep intact -all the notices that refer to this License and to the absence of any -warranty; and distribute a copy of this License along with the -Library. - - You may charge a fee for the physical act of transferring a copy, -and you may at your option offer warranty protection in exchange for a -fee. - - 2. You may modify your copy or copies of the Library or any portion -of it, thus forming a work based on the Library, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) The modified work must itself be a software library. - - b) You must cause the files modified to carry prominent notices - stating that you changed the files and the date of any change. - - c) You must cause the whole of the work to be licensed at no - charge to all third parties under the terms of this License. - - d) If a facility in the modified Library refers to a function or a - table of data to be supplied by an application program that uses - the facility, other than as an argument passed when the facility - is invoked, then you must make a good faith effort to ensure that, - in the event an application does not supply such function or - table, the facility still operates, and performs whatever part of - its purpose remains meaningful. - - (For example, a function in a library to compute square roots has - a purpose that is entirely well-defined independent of the - application. Therefore, Subsection 2d requires that any - application-supplied function or table used by this function must - be optional: if the application does not supply it, the square - root function must still compute square roots.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Library, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Library, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote -it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Library. - -In addition, mere aggregation of another work not based on the Library -with the Library (or with a work based on the Library) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may opt to apply the terms of the ordinary GNU General Public -License instead of this License to a given copy of the Library. To do -this, you must alter all the notices that refer to this License, so -that they refer to the ordinary GNU General Public License, version 2, -instead of to this License. (If a newer version than version 2 of the -ordinary GNU General Public License has appeared, then you can specify -that version instead if you wish.) Do not make any other change in -these notices. - - Once this change is made in a given copy, it is irreversible for -that copy, so the ordinary GNU General Public License applies to all -subsequent copies and derivative works made from that copy. - - This option is useful when you wish to copy part of the code of -the Library into a program that is not a library. - - 4. You may copy and distribute the Library (or a portion or -derivative of it, under Section 2) in object code or executable form -under the terms of Sections 1 and 2 above provided that you accompany -it with the complete corresponding machine-readable source code, which -must be distributed under the terms of Sections 1 and 2 above on a -medium customarily used for software interchange. - - If distribution of object code is made by offering access to copy -from a designated place, then offering equivalent access to copy the -source code from the same place satisfies the requirement to -distribute the source code, even though third parties are not -compelled to copy the source along with the object code. - - 5. A program that contains no derivative of any portion of the -Library, but is designed to work with the Library by being compiled or -linked with it, is called a "work that uses the Library". Such a -work, in isolation, is not a derivative work of the Library, and -therefore falls outside the scope of this License. - - However, linking a "work that uses the Library" with the Library -creates an executable that is a derivative of the Library (because it -contains portions of the Library), rather than a "work that uses the -library". The executable is therefore covered by this License. -Section 6 states terms for distribution of such executables. - - When a "work that uses the Library" uses material from a header file -that is part of the Library, the object code for the work may be a -derivative work of the Library even though the source code is not. -Whether this is true is especially significant if the work can be -linked without the Library, or if the work is itself a library. The -threshold for this to be true is not precisely defined by law. - - If such an object file uses only numerical parameters, data -structure layouts and accessors, and small macros and small inline -functions (ten lines or less in length), then the use of the object -file is unrestricted, regardless of whether it is legally a derivative -work. (Executables containing this object code plus portions of the -Library will still fall under Section 6.) - - Otherwise, if the work is a derivative of the Library, you may -distribute the object code for the work under the terms of Section 6. -Any executables containing that work also fall under Section 6, -whether or not they are linked directly with the Library itself. - - 6. As an exception to the Sections above, you may also combine or -link a "work that uses the Library" with the Library to produce a -work containing portions of the Library, and distribute that work -under terms of your choice, provided that the terms permit -modification of the work for the customer's own use and reverse -engineering for debugging such modifications. - - You must give prominent notice with each copy of the work that the -Library is used in it and that the Library and its use are covered by -this License. You must supply a copy of this License. If the work -during execution displays copyright notices, you must include the -copyright notice for the Library among them, as well as a reference -directing the user to the copy of this License. Also, you must do one -of these things: - - a) Accompany the work with the complete corresponding - machine-readable source code for the Library including whatever - changes were used in the work (which must be distributed under - Sections 1 and 2 above); and, if the work is an executable linked - with the Library, with the complete machine-readable "work that - uses the Library", as object code and/or source code, so that the - user can modify the Library and then relink to produce a modified - executable containing the modified Library. (It is understood - that the user who changes the contents of definitions files in the - Library will not necessarily be able to recompile the application - to use the modified definitions.) - - b) Use a suitable shared library mechanism for linking with the - Library. A suitable mechanism is one that (1) uses at run time a - copy of the library already present on the user's computer system, - rather than copying library functions into the executable, and (2) - will operate properly with a modified version of the library, if - the user installs one, as long as the modified version is - interface-compatible with the version that the work was made with. - - c) Accompany the work with a written offer, valid for at - least three years, to give the same user the materials - specified in Subsection 6a, above, for a charge no more - than the cost of performing this distribution. - - d) If distribution of the work is made by offering access to copy - from a designated place, offer equivalent access to copy the above - specified materials from the same place. - - e) Verify that the user has already received a copy of these - materials or that you have already sent this user a copy. - - For an executable, the required form of the "work that uses the -Library" must include any data and utility programs needed for -reproducing the executable from it. However, as a special exception, -the materials to be distributed need not include anything that is -normally distributed (in either source or binary form) with the major -components (compiler, kernel, and so on) of the operating system on -which the executable runs, unless that component itself accompanies -the executable. - - It may happen that this requirement contradicts the license -restrictions of other proprietary libraries that do not normally -accompany the operating system. Such a contradiction means you cannot -use both them and the Library together in an executable that you -distribute. - - 7. You may place library facilities that are a work based on the -Library side-by-side in a single library together with other library -facilities not covered by this License, and distribute such a combined -library, provided that the separate distribution of the work based on -the Library and of the other library facilities is otherwise -permitted, and provided that you do these two things: - - a) Accompany the combined library with a copy of the same work - based on the Library, uncombined with any other library - facilities. This must be distributed under the terms of the - Sections above. - - b) Give prominent notice with the combined library of the fact - that part of it is a work based on the Library, and explaining - where to find the accompanying uncombined form of the same work. - - 8. You may not copy, modify, sublicense, link with, or distribute -the Library except as expressly provided under this License. Any -attempt otherwise to copy, modify, sublicense, link with, or -distribute the Library is void, and will automatically terminate your -rights under this License. However, parties who have received copies, -or rights, from you under this License will not have their licenses -terminated so long as such parties remain in full compliance. - - 9. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Library or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Library (or any work based on the -Library), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Library or works based on it. - - 10. Each time you redistribute the Library (or any work based on the -Library), the recipient automatically receives a license from the -original licensor to copy, distribute, link with or modify the Library -subject to these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties with -this License. - - 11. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Library at all. For example, if a patent -license would not permit royalty-free redistribution of the Library by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Library. - -If any portion of this section is held invalid or unenforceable under any -particular circumstance, the balance of the section is intended to apply, -and the section as a whole is intended to apply in other circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 12. If the distribution and/or use of the Library is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Library under this License may add -an explicit geographical distribution limitation excluding those countries, -so that distribution is permitted only in or among countries not thus -excluded. In such case, this License incorporates the limitation as if -written in the body of this License. - - 13. The Free Software Foundation may publish revised and/or new -versions of the Lesser General Public License from time to time. -Such new versions will be similar in spirit to the present version, -but may differ in detail to address new problems or concerns. - -Each version is given a distinguishing version number. If the Library -specifies a version number of this License which applies to it and -"any later version", you have the option of following the terms and -conditions either of that version or of any later version published by -the Free Software Foundation. If the Library does not specify a -license version number, you may choose any version ever published by -the Free Software Foundation. - - 14. If you wish to incorporate parts of the Library into other free -programs whose distribution conditions are incompatible with these, -write to the author to ask for permission. For software which is -copyrighted by the Free Software Foundation, write to the Free -Software Foundation; we sometimes make exceptions for this. Our -decision will be guided by the two goals of preserving the free status -of all derivatives of our free software and of promoting the sharing -and reuse of software generally. - - NO WARRANTY - - 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO -WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. -EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR -OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY -KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE -LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME -THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN -WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY -AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU -FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR -CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE -LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING -RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A -FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF -SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH -DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Libraries - - If you develop a new library, and you want it to be of the greatest -possible use to the public, we recommend making it free software that -everyone can redistribute and change. You can do so by permitting -redistribution under these terms (or, alternatively, under the terms of the -ordinary General Public License). - - To apply these terms, attach the following notices to the library. It is -safest to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least the -"copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - -Also add information on how to contact you by electronic and paper mail. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the library, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the - library `Frob' (a library for tweaking knobs) written by James Random Hacker. - - , 1 April 1990 - Ty Coon, President of Vice - -That's all there is to it! - - diff --git a/dashmachine/static/vendors/tinymce/plugins/advlist/plugin.min.js b/dashmachine/static/vendors/tinymce/plugins/advlist/plugin.min.js deleted file mode 100644 index 122cd8f..0000000 --- a/dashmachine/static/vendors/tinymce/plugins/advlist/plugin.min.js +++ /dev/null @@ -1 +0,0 @@ -!function(){"use strict";var t=tinymce.util.Tools.resolve("tinymce.PluginManager"),a=tinymce.util.Tools.resolve("tinymce.util.Tools"),s=function(t,e,n){var r="UL"===e?"InsertUnorderedList":"InsertOrderedList";t.execCommand(r,!1,!1===n?null:{"list-style-type":n})},o=function(n){n.addCommand("ApplyUnorderedListStyle",function(t,e){s(n,"UL",e["list-style-type"])}),n.addCommand("ApplyOrderedListStyle",function(t,e){s(n,"OL",e["list-style-type"])})},e=function(t){var e=t.getParam("advlist_number_styles","default,lower-alpha,lower-greek,lower-roman,upper-alpha,upper-roman");return e?e.split(/[ ,]/):[]},n=function(t){var e=t.getParam("advlist_bullet_styles","default,circle,disc,square");return e?e.split(/[ ,]/):[]},u=function(t){return t&&/^(TH|TD)$/.test(t.nodeName)},c=function(r){return function(t){return t&&/^(OL|UL|DL)$/.test(t.nodeName)&&(n=t,(e=r).$.contains(e.getBody(),n));var e,n}},d=function(t){var e=t.dom.getParent(t.selection.getNode(),"ol,ul");return t.dom.getStyle(e,"listStyleType")||""},p=function(t){return a.map(t,function(t){return{text:t.replace(/\-/g," ").replace(/\b\w/g,function(t){return t.toUpperCase()}),data:"default"===t?"":t}})},f=function(i,l){return function(t){var o=t.control;i.on("NodeChange",function(t){var e=function(t,e){for(var n=0;nh(t)&&(r=a);var p=v(t);p&&p]*>((\xa0| |[ \t]|]*>)+?|)|
$","i").test(e)},c=function(t){var e=parseInt(r.getItem(u(t)+"time"),10)||0;return!((new Date).getTime()-e>i(t.settings.autosave_retention,"20m")&&(f(t,!1),1))},f=function(t,e){var n=u(t);r.removeItem(n+"draft"),r.removeItem(n+"time"),!1!==e&&t.fire("RemoveDraft")},l=function(t){var e=u(t);!s(t)&&t.isDirty()&&(r.setItem(e+"draft",t.getContent({format:"raw",no_events:!0})),r.setItem(e+"time",(new Date).getTime().toString()),t.fire("StoreDraft"))},m=function(t){var e=u(t);c(t)&&(t.setContent(r.getItem(e+"draft"),{format:"raw"}),t.fire("RestoreDraft"))},v=function(t,e){var n=i(t.settings.autosave_interval,"30s");e.get()||(setInterval(function(){t.removed||l(t)},n),e.set(!0))},d=function(t){t.undoManager.transact(function(){m(t),f(t)}),t.focus()};function g(r){for(var o=[],t=1;t(.*?)<\/a>/gi,"[url=$1]$2[/url]"),o(/(.*?)<\/font>/gi,"[code][color=$1]$2[/color][/code]"),o(/(.*?)<\/font>/gi,"[quote][color=$1]$2[/color][/quote]"),o(/(.*?)<\/font>/gi,"[code][color=$1]$2[/color][/code]"),o(/(.*?)<\/font>/gi,"[quote][color=$1]$2[/color][/quote]"),o(/(.*?)<\/span>/gi,"[color=$1]$2[/color]"),o(/(.*?)<\/font>/gi,"[color=$1]$2[/color]"),o(/(.*?)<\/span>/gi,"[size=$1]$2[/size]"),o(/(.*?)<\/font>/gi,"$1"),o(//gi,"[img]$1[/img]"),o(/(.*?)<\/span>/gi,"[code]$1[/code]"),o(/(.*?)<\/span>/gi,"[quote]$1[/quote]"),o(/(.*?)<\/strong>/gi,"[code][b]$1[/b][/code]"),o(/(.*?)<\/strong>/gi,"[quote][b]$1[/b][/quote]"),o(/(.*?)<\/em>/gi,"[code][i]$1[/i][/code]"),o(/(.*?)<\/em>/gi,"[quote][i]$1[/i][/quote]"),o(/(.*?)<\/u>/gi,"[code][u]$1[/u][/code]"),o(/(.*?)<\/u>/gi,"[quote][u]$1[/u][/quote]"),o(/<\/(strong|b)>/gi,"[/b]"),o(/<(strong|b)>/gi,"[b]"),o(/<\/(em|i)>/gi,"[/i]"),o(/<(em|i)>/gi,"[i]"),o(/<\/u>/gi,"[/u]"),o(/(.*?)<\/span>/gi,"[u]$1[/u]"),o(//gi,"[u]"),o(/]*>/gi,"[quote]"),o(/<\/blockquote>/gi,"[/quote]"),o(/
/gi,"\n"),o(//gi,"\n"),o(/
/gi,"\n"),o(/

/gi,""),o(/<\/p>/gi,"\n"),o(/ |\u00a0/gi," "),o(/"/gi,'"'),o(/</gi,"<"),o(/>/gi,">"),o(/&/gi,"&"),e},i=function(e){e=t.trim(e);var o=function(o,t){e=e.replace(o,t)};return o(/\n/gi,"
"),o(/\[b\]/gi,""),o(/\[\/b\]/gi,""),o(/\[i\]/gi,""),o(/\[\/i\]/gi,""),o(/\[u\]/gi,""),o(/\[\/u\]/gi,""),o(/\[url=([^\]]+)\](.*?)\[\/url\]/gi,'$2'),o(/\[url\](.*?)\[\/url\]/gi,'$1'),o(/\[img\](.*?)\[\/img\]/gi,''),o(/\[color=(.*?)\](.*?)\[\/color\]/gi,'$2'),o(/\[code\](.*?)\[\/code\]/gi,'$1 '),o(/\[quote.*?\](.*?)\[\/quote\]/gi,'$1 '),e};o.add("bbcode",function(){return{init:function(o){o.on("beforeSetContent",function(o){o.content=i(o.content)}),o.on("postProcess",function(o){o.set&&(o.content=i(o.content)),o.get&&(o.content=e(o.content))})}}})}(); \ No newline at end of file diff --git a/dashmachine/static/vendors/tinymce/plugins/charmap/plugin.min.js b/dashmachine/static/vendors/tinymce/plugins/charmap/plugin.min.js deleted file mode 100644 index 9ea3f75..0000000 --- a/dashmachine/static/vendors/tinymce/plugins/charmap/plugin.min.js +++ /dev/null @@ -1 +0,0 @@ -!function(){"use strict";var e=tinymce.util.Tools.resolve("tinymce.PluginManager"),i=function(e,t){return e.fire("insertCustomChar",{chr:t})},l=function(e,t){var a=i(e,t).chr;e.execCommand("mceInsertContent",!1,a)},a=tinymce.util.Tools.resolve("tinymce.util.Tools"),r=function(e){return e.settings.charmap},n=function(e){return e.settings.charmap_append},o=a.isArray,c=function(e){return o(e)?[].concat((t=e,a.grep(t,function(e){return o(e)&&2===e.length}))):"function"==typeof e?e():[];var t},s=function(e){return function(e,t){var a=r(e);a&&(t=c(a));var i=n(e);return i?[].concat(t).concat(c(i)):t}(e,[["160","no-break space"],["173","soft hyphen"],["34","quotation mark"],["162","cent sign"],["8364","euro sign"],["163","pound sign"],["165","yen sign"],["169","copyright sign"],["174","registered sign"],["8482","trade mark sign"],["8240","per mille sign"],["181","micro sign"],["183","middle dot"],["8226","bullet"],["8230","three dot leader"],["8242","minutes / feet"],["8243","seconds / inches"],["167","section sign"],["182","paragraph sign"],["223","sharp s / ess-zed"],["8249","single left-pointing angle quotation mark"],["8250","single right-pointing angle quotation mark"],["171","left pointing guillemet"],["187","right pointing guillemet"],["8216","left single quotation mark"],["8217","right single quotation mark"],["8220","left double quotation mark"],["8221","right double quotation mark"],["8218","single low-9 quotation mark"],["8222","double low-9 quotation mark"],["60","less-than sign"],["62","greater-than sign"],["8804","less-than or equal to"],["8805","greater-than or equal to"],["8211","en dash"],["8212","em dash"],["175","macron"],["8254","overline"],["164","currency sign"],["166","broken bar"],["168","diaeresis"],["161","inverted exclamation mark"],["191","turned question mark"],["710","circumflex accent"],["732","small tilde"],["176","degree sign"],["8722","minus sign"],["177","plus-minus sign"],["247","division sign"],["8260","fraction slash"],["215","multiplication sign"],["185","superscript one"],["178","superscript two"],["179","superscript three"],["188","fraction one quarter"],["189","fraction one half"],["190","fraction three quarters"],["402","function / florin"],["8747","integral"],["8721","n-ary sumation"],["8734","infinity"],["8730","square root"],["8764","similar to"],["8773","approximately equal to"],["8776","almost equal to"],["8800","not equal to"],["8801","identical to"],["8712","element of"],["8713","not an element of"],["8715","contains as member"],["8719","n-ary product"],["8743","logical and"],["8744","logical or"],["172","not sign"],["8745","intersection"],["8746","union"],["8706","partial differential"],["8704","for all"],["8707","there exists"],["8709","diameter"],["8711","backward difference"],["8727","asterisk operator"],["8733","proportional to"],["8736","angle"],["180","acute accent"],["184","cedilla"],["170","feminine ordinal indicator"],["186","masculine ordinal indicator"],["8224","dagger"],["8225","double dagger"],["192","A - grave"],["193","A - acute"],["194","A - circumflex"],["195","A - tilde"],["196","A - diaeresis"],["197","A - ring above"],["256","A - macron"],["198","ligature AE"],["199","C - cedilla"],["200","E - grave"],["201","E - acute"],["202","E - circumflex"],["203","E - diaeresis"],["274","E - macron"],["204","I - grave"],["205","I - acute"],["206","I - circumflex"],["207","I - diaeresis"],["298","I - macron"],["208","ETH"],["209","N - tilde"],["210","O - grave"],["211","O - acute"],["212","O - circumflex"],["213","O - tilde"],["214","O - diaeresis"],["216","O - slash"],["332","O - macron"],["338","ligature OE"],["352","S - caron"],["217","U - grave"],["218","U - acute"],["219","U - circumflex"],["220","U - diaeresis"],["362","U - macron"],["221","Y - acute"],["376","Y - diaeresis"],["562","Y - macron"],["222","THORN"],["224","a - grave"],["225","a - acute"],["226","a - circumflex"],["227","a - tilde"],["228","a - diaeresis"],["229","a - ring above"],["257","a - macron"],["230","ligature ae"],["231","c - cedilla"],["232","e - grave"],["233","e - acute"],["234","e - circumflex"],["235","e - diaeresis"],["275","e - macron"],["236","i - grave"],["237","i - acute"],["238","i - circumflex"],["239","i - diaeresis"],["299","i - macron"],["240","eth"],["241","n - tilde"],["242","o - grave"],["243","o - acute"],["244","o - circumflex"],["245","o - tilde"],["246","o - diaeresis"],["248","o slash"],["333","o macron"],["339","ligature oe"],["353","s - caron"],["249","u - grave"],["250","u - acute"],["251","u - circumflex"],["252","u - diaeresis"],["363","u - macron"],["253","y - acute"],["254","thorn"],["255","y - diaeresis"],["563","y - macron"],["913","Alpha"],["914","Beta"],["915","Gamma"],["916","Delta"],["917","Epsilon"],["918","Zeta"],["919","Eta"],["920","Theta"],["921","Iota"],["922","Kappa"],["923","Lambda"],["924","Mu"],["925","Nu"],["926","Xi"],["927","Omicron"],["928","Pi"],["929","Rho"],["931","Sigma"],["932","Tau"],["933","Upsilon"],["934","Phi"],["935","Chi"],["936","Psi"],["937","Omega"],["945","alpha"],["946","beta"],["947","gamma"],["948","delta"],["949","epsilon"],["950","zeta"],["951","eta"],["952","theta"],["953","iota"],["954","kappa"],["955","lambda"],["956","mu"],["957","nu"],["958","xi"],["959","omicron"],["960","pi"],["961","rho"],["962","final sigma"],["963","sigma"],["964","tau"],["965","upsilon"],["966","phi"],["967","chi"],["968","psi"],["969","omega"],["8501","alef symbol"],["982","pi symbol"],["8476","real part symbol"],["978","upsilon - hook symbol"],["8472","Weierstrass p"],["8465","imaginary part"],["8592","leftwards arrow"],["8593","upwards arrow"],["8594","rightwards arrow"],["8595","downwards arrow"],["8596","left right arrow"],["8629","carriage return"],["8656","leftwards double arrow"],["8657","upwards double arrow"],["8658","rightwards double arrow"],["8659","downwards double arrow"],["8660","left right double arrow"],["8756","therefore"],["8834","subset of"],["8835","superset of"],["8836","not a subset of"],["8838","subset of or equal to"],["8839","superset of or equal to"],["8853","circled plus"],["8855","circled times"],["8869","perpendicular"],["8901","dot operator"],["8968","left ceiling"],["8969","right ceiling"],["8970","left floor"],["8971","right floor"],["9001","left-pointing angle bracket"],["9002","right-pointing angle bracket"],["9674","lozenge"],["9824","black spade suit"],["9827","black club suit"],["9829","black heart suit"],["9830","black diamond suit"],["8194","en space"],["8195","em space"],["8201","thin space"],["8204","zero width non-joiner"],["8205","zero width joiner"],["8206","left-to-right mark"],["8207","right-to-left mark"]])},t=function(t){return{getCharMap:function(){return s(t)},insertChar:function(e){l(t,e)}}},u=function(e){var t,a,i,r=Math.min(e.length,25),n=Math.ceil(e.length/r);for(t='',i=0;i",a=0;a
'+s+"
"}else t+="
"}return t+=""},d=function(e){for(;e;){if("TD"===e.nodeName)return e;e=e.parentNode}},m=function(n){var o,e={type:"container",html:u(s(n)),onclick:function(e){var t=e.target;if(/^(TD|DIV)$/.test(t.nodeName)){var a=d(t).firstChild;if(a&&a.hasAttribute("data-chr")){var i=a.getAttribute("data-chr"),r=parseInt(i,10);isNaN(r)||l(n,String.fromCharCode(r)),e.ctrlKey||o.close()}}},onmouseover:function(e){var t=d(e.target);t&&t.firstChild?(o.find("#preview").text(t.firstChild.firstChild.data),o.find("#previewTitle").text(t.title)):(o.find("#preview").text(" "),o.find("#previewTitle").text(" "))}};o=n.windowManager.open({title:"Special character",spacing:10,padding:10,items:[e,{type:"container",layout:"flex",direction:"column",align:"center",spacing:5,minWidth:160,minHeight:160,items:[{type:"label",name:"preview",text:" ",style:"font-size: 40px; text-align: center",border:1,minWidth:140,minHeight:80},{type:"spacer",minHeight:20},{type:"label",name:"previewTitle",text:" ",style:"white-space: pre-wrap;",border:1,minWidth:140}]}],buttons:[{text:"Close",onclick:function(){o.close()}}]})},g=function(e){e.addCommand("mceShowCharmap",function(){m(e)})},p=function(e){e.addButton("charmap",{icon:"charmap",tooltip:"Special character",cmd:"mceShowCharmap"}),e.addMenuItem("charmap",{icon:"charmap",text:"Special character",cmd:"mceShowCharmap",context:"insert"})};e.add("charmap",function(e){return g(e),p(e),t(e)})}(); \ No newline at end of file diff --git a/dashmachine/static/vendors/tinymce/plugins/code/plugin.min.js b/dashmachine/static/vendors/tinymce/plugins/code/plugin.min.js deleted file mode 100644 index 7afcca6..0000000 --- a/dashmachine/static/vendors/tinymce/plugins/code/plugin.min.js +++ /dev/null @@ -1 +0,0 @@ -!function(){"use strict";var t=tinymce.util.Tools.resolve("tinymce.PluginManager"),n=tinymce.util.Tools.resolve("tinymce.dom.DOMUtils"),o=function(t){return t.getParam("code_dialog_width",600)},i=function(t){return t.getParam("code_dialog_height",Math.min(n.DOM.getViewPort().h-200,500))},c=function(t,n){t.focus(),t.undoManager.transact(function(){t.setContent(n)}),t.selection.setCursorLocation(),t.nodeChanged()},d=function(t){return t.getContent({source_view:!0})},e=function(n){var t=o(n),e=i(n);n.windowManager.open({title:"Source code",body:{type:"textbox",name:"code",multiline:!0,minWidth:t,minHeight:e,spellcheck:!1,style:"direction: ltr; text-align: left"},onSubmit:function(t){c(n,t.data.code)}}).find("#code").value(d(n))},u=function(t){t.addCommand("mceCodeEditor",function(){e(t)})},a=function(t){t.addButton("code",{icon:"code",tooltip:"Source code",onclick:function(){e(t)}}),t.addMenuItem("code",{icon:"code",text:"Source code",onclick:function(){e(t)}})};t.add("code",function(t){return u(t),a(t),{}})}(); \ No newline at end of file diff --git a/dashmachine/static/vendors/tinymce/plugins/codesample/css/prism.css b/dashmachine/static/vendors/tinymce/plugins/codesample/css/prism.css deleted file mode 100644 index 128237f..0000000 --- a/dashmachine/static/vendors/tinymce/plugins/codesample/css/prism.css +++ /dev/null @@ -1,138 +0,0 @@ -/* http://prismjs.com/download.html?themes=prism&languages=markup+css+clike+javascript */ -/** - * prism.js default theme for JavaScript, CSS and HTML - * Based on dabblet (http://dabblet.com) - * @author Lea Verou - */ - -code[class*="language-"], -pre[class*="language-"] { - color: black; - text-shadow: 0 1px white; - font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; - direction: ltr; - text-align: left; - white-space: pre; - word-spacing: normal; - word-break: normal; - word-wrap: normal; - line-height: 1.5; - - -moz-tab-size: 4; - -o-tab-size: 4; - tab-size: 4; - - -webkit-hyphens: none; - -moz-hyphens: none; - -ms-hyphens: none; - hyphens: none; -} - -pre[class*="language-"]::-moz-selection, pre[class*="language-"] ::-moz-selection, -code[class*="language-"]::-moz-selection, code[class*="language-"] ::-moz-selection { - text-shadow: none; - background: #b3d4fc; -} - -pre[class*="language-"]::selection, pre[class*="language-"] ::selection, -code[class*="language-"]::selection, code[class*="language-"] ::selection { - text-shadow: none; - background: #b3d4fc; -} - -@media print { - code[class*="language-"], - pre[class*="language-"] { - text-shadow: none; - } -} - -/* Code blocks */ -pre[class*="language-"] { - padding: 1em; - margin: .5em 0; - overflow: auto; -} - -:not(pre) > code[class*="language-"], -pre[class*="language-"] { - background: #f5f2f0; -} - -/* Inline code */ -:not(pre) > code[class*="language-"] { - padding: .1em; - border-radius: .3em; -} - -.token.comment, -.token.prolog, -.token.doctype, -.token.cdata { - color: slategray; -} - -.token.punctuation { - color: #999; -} - -.namespace { - opacity: .7; -} - -.token.property, -.token.tag, -.token.boolean, -.token.number, -.token.constant, -.token.symbol, -.token.deleted { - color: #905; -} - -.token.selector, -.token.attr-name, -.token.string, -.token.char, -.token.builtin, -.token.inserted { - color: #690; -} - -.token.operator, -.token.entity, -.token.url, -.language-css .token.string, -.style .token.string { - color: #a67f59; - background: hsla(0, 0%, 100%, .5); -} - -.token.atrule, -.token.attr-value, -.token.keyword { - color: #07a; -} - -.token.function { - color: #DD4A68; -} - -.token.regex, -.token.important, -.token.variable { - color: #e90; -} - -.token.important, -.token.bold { - font-weight: bold; -} -.token.italic { - font-style: italic; -} - -.token.entity { - cursor: help; -} - diff --git a/dashmachine/static/vendors/tinymce/plugins/codesample/plugin.min.js b/dashmachine/static/vendors/tinymce/plugins/codesample/plugin.min.js deleted file mode 100644 index 8f7373c..0000000 --- a/dashmachine/static/vendors/tinymce/plugins/codesample/plugin.min.js +++ /dev/null @@ -1 +0,0 @@ -!function(){"use strict";var n=function(e){var t=e,a=function(){return t};return{get:a,set:function(e){t=e},clone:function(){return n(a())}}},e=tinymce.util.Tools.resolve("tinymce.PluginManager"),i=tinymce.util.Tools.resolve("tinymce.dom.DOMUtils"),s=function(e){return e.settings.codesample_content_css},a=function(e){return e.settings.codesample_languages},o=function(e){return Math.min(i.DOM.getViewPort().w,e.getParam("codesample_dialog_width",800))},l=function(e){return Math.min(i.DOM.getViewPort().w,e.getParam("codesample_dialog_height",650))},t={},r=t,u=void 0!==t?t:"undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope?self:{},c=function(){var c=/\blang(?:uage)?-(?!\*)(\w+)\b/i,S=u.Prism={util:{encode:function(e){return e instanceof o?new o(e.type,S.util.encode(e.content),e.alias):"Array"===S.util.type(e)?e.map(S.util.encode):e.replace(/&/g,"&").replace(/e.length)break e;if(!(h instanceof n)){c.lastIndex=0;var m=c.exec(h);if(m){g&&(d=m[1].length);var b=m.index-1+d,y=b+(m=m[0].slice(d)).length,v=h.slice(0,b+1),k=h.slice(y+1),w=[f,1];v&&w.push(v);var x=new n(s,u?S.tokenize(m,u):m,p);w.push(x),k&&w.push(k),Array.prototype.splice.apply(i,w)}}}}}return i},hooks:{all:{},add:function(e,t){var a=S.hooks.all;a[e]=a[e]||[],a[e].push(t)},run:function(e,t){var a=S.hooks.all[e];if(a&&a.length)for(var n=0,i=void 0;i=a[n++];)i(t)}}},o=S.Token=function(e,t,a){this.type=e,this.content=t,this.alias=a};if(o.stringify=function(t,a,e){if("string"==typeof t)return t;if("Array"===S.util.type(t))return t.map(function(e){return o.stringify(e,a,t)}).join("");var n={type:t.type,content:o.stringify(t.content,a,e),tag:"span",classes:["token",t.type],attributes:{},language:a,parent:e};if("comment"===n.type&&(n.attributes.spellcheck="true"),t.alias){var i="Array"===S.util.type(t.alias)?t.alias:[t.alias];Array.prototype.push.apply(n.classes,i)}S.hooks.run("wrap",n);var r="";for(var s in n.attributes)r+=(r?" ":"")+s+'="'+(n.attributes[s]||"")+'"';return"<"+n.tag+' class="'+n.classes.join(" ")+'" '+r+">"+n.content+""},!u.document)return u.addEventListener&&u.addEventListener("message",function(e){var t=JSON.parse(e.data),a=t.language,n=t.code,i=t.immediateClose;u.postMessage(S.highlight(n,S.languages[a],a)),i&&u.close()},!1),u.Prism}();void 0!==r&&(r.Prism=c),c.languages.markup={comment://,prolog:/<\?[\w\W]+?\?>/,doctype://,cdata://i,tag:{pattern:/<\/?[^\s>\/=.]+(?:\s+[^\s>\/=]+(?:=(?:("|')(?:\\\1|\\?(?!\1)[\w\W])*\1|[^\s'">=]+))?)*\s*\/?>/i,inside:{tag:{pattern:/^<\/?[^\s>\/]+/i,inside:{punctuation:/^<\/?/,namespace:/^[^\s>\/:]+:/}},"attr-value":{pattern:/=(?:('|")[\w\W]*?(\1)|[^\s>]+)/i,inside:{punctuation:/[=>"']/}},punctuation:/\/?>/,"attr-name":{pattern:/[^\s>\/]+/,inside:{namespace:/^[^\s>\/:]+:/}}}},entity:/&#?[\da-z]{1,8};/i},c.hooks.add("wrap",function(e){"entity"===e.type&&(e.attributes.title=e.content.replace(/&/,"&"))}),c.languages.xml=c.languages.markup,c.languages.html=c.languages.markup,c.languages.mathml=c.languages.markup,c.languages.svg=c.languages.markup,c.languages.css={comment:/\/\*[\w\W]*?\*\//,atrule:{pattern:/@[\w-]+?.*?(;|(?=\s*\{))/i,inside:{rule:/@[\w-]+/}},url:/url\((?:(["'])(\\(?:\r\n|[\w\W])|(?!\1)[^\\\r\n])*\1|.*?)\)/i,selector:/[^\{\}\s][^\{\};]*?(?=\s*\{)/,string:/("|')(\\(?:\r\n|[\w\W])|(?!\1)[^\\\r\n])*\1/,property:/(\b|\B)[\w-]+(?=\s*:)/i,important:/\B!important\b/i,"function":/[-a-z0-9]+(?=\()/i,punctuation:/[(){};:]/},c.languages.css.atrule.inside.rest=c.util.clone(c.languages.css),c.languages.markup&&(c.languages.insertBefore("markup","tag",{style:{pattern:/[\w\W]*?<\/style>/i,inside:{tag:{pattern:/|<\/style>/i,inside:c.languages.markup.tag.inside},rest:c.languages.css},alias:"language-css"}}),c.languages.insertBefore("inside","attr-value",{"style-attr":{pattern:/\s*style=("|').*?\1/i,inside:{"attr-name":{pattern:/^\s*style/i,inside:c.languages.markup.tag.inside},punctuation:/^\s*=\s*['"]|['"]\s*$/,"attr-value":{pattern:/.+/i,inside:c.languages.css}},alias:"language-css"}},c.languages.markup.tag)),c.languages.clike={comment:[{pattern:/(^|[^\\])\/\*[\w\W]*?\*\//,lookbehind:!0},{pattern:/(^|[^\\:])\/\/.*/,lookbehind:!0}],string:/(["'])(\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,"class-name":{pattern:/((?:\b(?:class|interface|extends|implements|trait|instanceof|new)\s+)|(?:catch\s+\())[a-z0-9_\.\\]+/i,lookbehind:!0,inside:{punctuation:/(\.|\\)/}},keyword:/\b(if|else|while|do|for|return|in|instanceof|function|new|try|throw|catch|finally|null|break|continue)\b/,"boolean":/\b(true|false)\b/,"function":/[a-z0-9_]+(?=\()/i,number:/\b-?(?:0x[\da-f]+|\d*\.?\d+(?:e[+-]?\d+)?)\b/i,operator:/--?|\+\+?|!=?=?|<=?|>=?|==?=?|&&?|\|\|?|\?|\*|\/|~|\^|%/,punctuation:/[{}[\];(),.:]/},c.languages.javascript=c.languages.extend("clike",{keyword:/\b(as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|false|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|true|try|typeof|var|void|while|with|yield)\b/,number:/\b-?(0x[\dA-Fa-f]+|0b[01]+|0o[0-7]+|\d*\.?\d+([Ee][+-]?\d+)?|NaN|Infinity)\b/,"function":/[_$a-zA-Z\xA0-\uFFFF][_$a-zA-Z0-9\xA0-\uFFFF]*(?=\()/i}),c.languages.insertBefore("javascript","keyword",{regex:{pattern:/(^|[^/])\/(?!\/)(\[.+?]|\\.|[^/\\\r\n])+\/[gimyu]{0,5}(?=\s*($|[\r\n,.;})]))/,lookbehind:!0}}),c.languages.insertBefore("javascript","class-name",{"template-string":{pattern:/`(?:\\`|\\?[^`])*`/,inside:{interpolation:{pattern:/\$\{[^}]+\}/,inside:{"interpolation-punctuation":{pattern:/^\$\{|\}$/,alias:"punctuation"},rest:c.languages.javascript}},string:/[\s\S]+/}}}),c.languages.markup&&c.languages.insertBefore("markup","tag",{script:{pattern:/[\w\W]*?<\/script>/i,inside:{tag:{pattern:/|<\/script>/i,inside:c.languages.markup.tag.inside},rest:c.languages.javascript},alias:"language-javascript"}}),c.languages.js=c.languages.javascript,c.languages.c=c.languages.extend("clike",{keyword:/\b(asm|typeof|inline|auto|break|case|char|const|continue|default|do|double|else|enum|extern|float|for|goto|if|int|long|register|return|short|signed|sizeof|static|struct|switch|typedef|union|unsigned|void|volatile|while)\b/,operator:/\-[>-]?|\+\+?|!=?|<>?=?|==?|&&?|\|?\||[~^%?*\/]/,number:/\b-?(?:0x[\da-f]+|\d*\.?\d+(?:e[+-]?\d+)?)[ful]*\b/i}),c.languages.insertBefore("c","string",{macro:{pattern:/(^\s*)#\s*[a-z]+([^\r\n\\]|\\.|\\(?:\r\n?|\n))*/im,lookbehind:!0,alias:"property",inside:{string:{pattern:/(#\s*include\s*)(<.+?>|("|')(\\?.)+?\3)/,lookbehind:!0}}}}),delete c.languages.c["class-name"],delete c.languages.c["boolean"],c.languages.csharp=c.languages.extend("clike",{keyword:/\b(abstract|as|async|await|base|bool|break|byte|case|catch|char|checked|class|const|continue|decimal|default|delegate|do|double|else|enum|event|explicit|extern|false|finally|fixed|float|for|foreach|goto|if|implicit|in|int|interface|internal|is|lock|long|namespace|new|null|object|operator|out|override|params|private|protected|public|readonly|ref|return|sbyte|sealed|short|sizeof|stackalloc|static|string|struct|switch|this|throw|true|try|typeof|uint|ulong|unchecked|unsafe|ushort|using|virtual|void|volatile|while|add|alias|ascending|async|await|descending|dynamic|from|get|global|group|into|join|let|orderby|partial|remove|select|set|value|var|where|yield)\b/,string:[/@("|')(\1\1|\\\1|\\?(?!\1)[\s\S])*\1/,/("|')(\\?.)*?\1/],number:/\b-?(0x[\da-f]+|\d*\.?\d+)\b/i}),c.languages.insertBefore("csharp","keyword",{preprocessor:{pattern:/(^\s*)#.*/m,lookbehind:!0}}),c.languages.cpp=c.languages.extend("c",{keyword:/\b(alignas|alignof|asm|auto|bool|break|case|catch|char|char16_t|char32_t|class|compl|const|constexpr|const_cast|continue|decltype|default|delete|do|double|dynamic_cast|else|enum|explicit|export|extern|float|for|friend|goto|if|inline|int|long|mutable|namespace|new|noexcept|nullptr|operator|private|protected|public|register|reinterpret_cast|return|short|signed|sizeof|static|static_assert|static_cast|struct|switch|template|this|thread_local|throw|try|typedef|typeid|typename|union|unsigned|using|virtual|void|volatile|wchar_t|while)\b/,"boolean":/\b(true|false)\b/,operator:/[-+]{1,2}|!=?|<{1,2}=?|>{1,2}=?|\->|:{1,2}|={1,2}|\^|~|%|&{1,2}|\|?\||\?|\*|\/|\b(and|and_eq|bitand|bitor|not|not_eq|or|or_eq|xor|xor_eq)\b/}),c.languages.insertBefore("cpp","keyword",{"class-name":{pattern:/(class\s+)[a-z0-9_]+/i,lookbehind:!0}}),c.languages.java=c.languages.extend("clike",{keyword:/\b(abstract|continue|for|new|switch|assert|default|goto|package|synchronized|boolean|do|if|private|this|break|double|implements|protected|throw|byte|else|import|public|throws|case|enum|instanceof|return|transient|catch|extends|int|short|try|char|final|interface|static|void|class|finally|long|strictfp|volatile|const|float|native|super|while)\b/,number:/\b0b[01]+\b|\b0x[\da-f]*\.?[\da-fp\-]+\b|\b\d*\.?\d+(?:e[+-]?\d+)?[df]?\b/i,operator:{pattern:/(^|[^.])(?:\+[+=]?|-[-=]?|!=?|<>?>?=?|==?|&[&=]?|\|[|=]?|\*=?|\/=?|%=?|\^=?|[?:~])/m,lookbehind:!0}}),c.languages.php=c.languages.extend("clike",{keyword:/\b(and|or|xor|array|as|break|case|cfunction|class|const|continue|declare|default|die|do|else|elseif|enddeclare|endfor|endforeach|endif|endswitch|endwhile|extends|for|foreach|function|include|include_once|global|if|new|return|static|switch|use|require|require_once|var|while|abstract|interface|public|implements|private|protected|parent|throw|null|echo|print|trait|namespace|final|yield|goto|instanceof|finally|try|catch)\b/i,constant:/\b[A-Z0-9_]{2,}\b/,comment:{pattern:/(^|[^\\])(?:\/\*[\w\W]*?\*\/|\/\/.*)/,lookbehind:!0}}),c.languages.insertBefore("php","class-name",{"shell-comment":{pattern:/(^|[^\\])#.*/,lookbehind:!0,alias:"comment"}}),c.languages.insertBefore("php","keyword",{delimiter:/\?>|<\?(?:php)?/i,variable:/\$\w+\b/i,"package":{pattern:/(\\|namespace\s+|use\s+)[\w\\]+/,lookbehind:!0,inside:{punctuation:/\\/}}}),c.languages.insertBefore("php","operator",{property:{pattern:/(->)[\w]+/,lookbehind:!0}}),c.languages.markup&&(c.hooks.add("before-highlight",function(t){"php"===t.language&&(t.tokenStack=[],t.backupCode=t.code,t.code=t.code.replace(/(?:<\?php|<\?)[\w\W]*?(?:\?>)/gi,function(e){return t.tokenStack.push(e),"{{{PHP"+t.tokenStack.length+"}}}"}))}),c.hooks.add("before-insert",function(e){"php"===e.language&&(e.code=e.backupCode,delete e.backupCode)}),c.hooks.add("after-highlight",function(e){if("php"===e.language){for(var t=0,a=void 0;a=e.tokenStack[t];t++)e.highlightedCode=e.highlightedCode.replace("{{{PHP"+(t+1)+"}}}",c.highlight(a,e.grammar,"php").replace(/\$/g,"$$$$"));e.element.innerHTML=e.highlightedCode}}),c.hooks.add("wrap",function(e){"php"===e.language&&"markup"===e.type&&(e.content=e.content.replace(/(\{\{\{PHP[0-9]+\}\}\})/g,'$1'))}),c.languages.insertBefore("php","comment",{markup:{pattern:/<[^?]\/?(.*?)>/,inside:c.languages.markup},php:/\{\{\{PHP[0-9]+\}\}\}/})),c.languages.python={comment:{pattern:/(^|[^\\])#.*/,lookbehind:!0},string:/"""[\s\S]+?"""|'''[\s\S]+?'''|("|')(?:\\?.)*?\1/,"function":{pattern:/((?:^|\s)def[ \t]+)[a-zA-Z_][a-zA-Z0-9_]*(?=\()/g,lookbehind:!0},"class-name":{pattern:/(\bclass\s+)[a-z0-9_]+/i,lookbehind:!0},keyword:/\b(?:as|assert|async|await|break|class|continue|def|del|elif|else|except|exec|finally|for|from|global|if|import|in|is|lambda|pass|print|raise|return|try|while|with|yield)\b/,"boolean":/\b(?:True|False)\b/,number:/\b-?(?:0[bo])?(?:(?:\d|0x[\da-f])[\da-f]*\.?\d*|\.\d+)(?:e[+-]?\d+)?j?\b/i,operator:/[-+%=]=?|!=|\*\*?=?|\/\/?=?|<[<=>]?|>[=>]?|[&|^~]|\b(?:or|and|not)\b/,punctuation:/[{}[\];(),.:]/},function(e){e.languages.ruby=e.languages.extend("clike",{comment:/#(?!\{[^\r\n]*?\}).*/,keyword:/\b(alias|and|BEGIN|begin|break|case|class|def|define_method|defined|do|each|else|elsif|END|end|ensure|false|for|if|in|module|new|next|nil|not|or|raise|redo|require|rescue|retry|return|self|super|then|throw|true|undef|unless|until|when|while|yield)\b/});var t={pattern:/#\{[^}]+\}/,inside:{delimiter:{pattern:/^#\{|\}$/,alias:"tag"},rest:e.util.clone(e.languages.ruby)}};e.languages.insertBefore("ruby","keyword",{regex:[{pattern:/%r([^a-zA-Z0-9\s\{\(\[<])(?:[^\\]|\\[\s\S])*?\1[gim]{0,3}/,inside:{interpolation:t}},{pattern:/%r\((?:[^()\\]|\\[\s\S])*\)[gim]{0,3}/,inside:{interpolation:t}},{pattern:/%r\{(?:[^#{}\\]|#(?:\{[^}]+\})?|\\[\s\S])*\}[gim]{0,3}/,inside:{interpolation:t}},{pattern:/%r\[(?:[^\[\]\\]|\\[\s\S])*\][gim]{0,3}/,inside:{interpolation:t}},{pattern:/%r<(?:[^<>\\]|\\[\s\S])*>[gim]{0,3}/,inside:{interpolation:t}},{pattern:/(^|[^/])\/(?!\/)(\[.+?]|\\.|[^/\r\n])+\/[gim]{0,3}(?=\s*($|[\r\n,.;})]))/,lookbehind:!0}],variable:/[@$]+[a-zA-Z_][a-zA-Z_0-9]*(?:[?!]|\b)/,symbol:/:[a-zA-Z_][a-zA-Z_0-9]*(?:[?!]|\b)/}),e.languages.insertBefore("ruby","number",{builtin:/\b(Array|Bignum|Binding|Class|Continuation|Dir|Exception|FalseClass|File|Stat|File|Fixnum|Fload|Hash|Integer|IO|MatchData|Method|Module|NilClass|Numeric|Object|Proc|Range|Regexp|String|Struct|TMS|Symbol|ThreadGroup|Thread|Time|TrueClass)\b/,constant:/\b[A-Z][a-zA-Z_0-9]*(?:[?!]|\b)/}),e.languages.ruby.string=[{pattern:/%[qQiIwWxs]?([^a-zA-Z0-9\s\{\(\[<])(?:[^\\]|\\[\s\S])*?\1/,inside:{interpolation:t}},{pattern:/%[qQiIwWxs]?\((?:[^()\\]|\\[\s\S])*\)/,inside:{interpolation:t}},{pattern:/%[qQiIwWxs]?\{(?:[^#{}\\]|#(?:\{[^}]+\})?|\\[\s\S])*\}/,inside:{interpolation:t}},{pattern:/%[qQiIwWxs]?\[(?:[^\[\]\\]|\\[\s\S])*\]/,inside:{interpolation:t}},{pattern:/%[qQiIwWxs]?<(?:[^<>\\]|\\[\s\S])*>/,inside:{interpolation:t}},{pattern:/("|')(#\{[^}]+\}|\\(?:\r?\n|\r)|\\?.)*?\1/,inside:{interpolation:t}}]}(c);var g={isCodeSample:function(e){return e&&"PRE"===e.nodeName&&-1!==e.className.indexOf("language-")},trimArg:function(a){return function(e,t){return a(t)}}},d=function(e){var t=e.selection.getNode();return g.isCodeSample(t)?t:null},p=d,f=function(t,a,n){t.undoManager.transact(function(){var e=d(t);n=i.DOM.encode(n),e?(t.dom.setAttrib(e,"class","language-"+a),e.innerHTML=n,c.highlightElement(e),t.selection.select(e)):(t.insertContent('

'+n+"
"),t.selection.select(t.$("#__new").removeAttr("id")[0]))})},h=function(e){var t=d(e);return t?t.textContent:""},m=function(e){var t=a(e);return t||[{text:"HTML/XML",value:"markup"},{text:"JavaScript",value:"javascript"},{text:"CSS",value:"css"},{text:"PHP",value:"php"},{text:"Ruby",value:"ruby"},{text:"Python",value:"python"},{text:"Java",value:"java"},{text:"C",value:"c"},{text:"C#",value:"csharp"},{text:"C++",value:"cpp"}]},b=function(e){var t,a=p(e);return a&&(t=a.className.match(/language-(\w+)/))?t[1]:""},y=function(t){var e=o(t),a=l(t),n=b(t),i=m(t),r=h(t);t.windowManager.open({title:"Insert/Edit code sample",minWidth:e,minHeight:a,layout:"flex",direction:"column",align:"stretch",body:[{type:"listbox",name:"language",label:"Language",maxWidth:200,value:n,values:i},{type:"textbox",name:"code",multiline:!0,spellcheck:!1,ariaLabel:"Code view",flex:1,style:"direction: ltr; text-align: left",classes:"monospace",value:r,autofocus:!0}],onSubmit:function(e){f(t,e.data.language,e.data.code)}})},v=function(t){t.addCommand("codesample",function(){var e=t.selection.getNode();t.selection.isCollapsed()||g.isCodeSample(e)?y(t):t.formatter.toggle("code")})},k=function(a){var i=a.$;a.on("PreProcess",function(e){i("pre[contenteditable=false]",e.node).filter(g.trimArg(g.isCodeSample)).each(function(e,t){var a=i(t),n=t.textContent;a.attr("class",i.trim(a.attr("class"))),a.removeAttr("contentEditable"),a.empty().append(i("").each(function(){this.textContent=n}))})}),a.on("SetContent",function(){var e=i("pre").filter(g.trimArg(g.isCodeSample)).filter(function(e,t){return"false"!==t.contentEditable});e.length&&a.undoManager.transact(function(){e.each(function(e,t){i(t).find("br").each(function(e,t){t.parentNode.replaceChild(a.getDoc().createTextNode("\n"),t)}),t.contentEditable=!1,t.innerHTML=a.dom.encode(t.textContent),c.highlightElement(t),t.className=i.trim(t.className)})})})},w=function(e,t,a,n){var i,r=s(e);e.inline&&a.get()||!e.inline&&n.get()||(e.inline?a.set(!0):n.set(!0),!1!==r&&(i=e.dom.create("link",{rel:"stylesheet",href:r||t+"/css/prism.css"}),e.getDoc().getElementsByTagName("head")[0].appendChild(i)))},x=function(e){e.addButton("codesample",{cmd:"codesample",title:"Insert/Edit code sample"}),e.addMenuItem("codesample",{cmd:"codesample",text:"Code sample",icon:"codesample"})},S=n(!1);e.add("codesample",function(t,e){var a=n(!1);k(t),x(t),v(t),t.on("init",function(){w(t,e,S,a)}),t.on("dblclick",function(e){g.isCodeSample(e.target)&&y(t)})})}(); \ No newline at end of file diff --git a/dashmachine/static/vendors/tinymce/plugins/colorpicker/plugin.min.js b/dashmachine/static/vendors/tinymce/plugins/colorpicker/plugin.min.js deleted file mode 100644 index 10317a5..0000000 --- a/dashmachine/static/vendors/tinymce/plugins/colorpicker/plugin.min.js +++ /dev/null @@ -1 +0,0 @@ -!function(){"use strict";var e=tinymce.util.Tools.resolve("tinymce.PluginManager"),l=tinymce.util.Tools.resolve("tinymce.util.Color"),a=function(e,n){e.find("#preview")[0].getEl().style.background=n},o=function(e,n){var i=l(n),t=i.toRgb();e.fromJSON({r:t.r,g:t.g,b:t.b,hex:i.toHex().substr(1)}),a(e,i.toHex())},t=function(e,n,i){var t=e.windowManager.open({title:"Color",items:{type:"container",layout:"flex",direction:"row",align:"stretch",padding:5,spacing:10,items:[{type:"colorpicker",value:i,onchange:function(){var e=this.rgb();t&&(t.find("#r").value(e.r),t.find("#g").value(e.g),t.find("#b").value(e.b),t.find("#hex").value(this.value().substr(1)),a(t,this.value()))}},{type:"form",padding:0,labelGap:5,defaults:{type:"textbox",size:7,value:"0",flex:1,spellcheck:!1,onchange:function(){var e,n,i=t.find("colorpicker")[0];if(e=this.name(),n=this.value(),"hex"===e)return o(t,n="#"+n),void i.value(n);n={r:t.find("#r").value(),g:t.find("#g").value(),b:t.find("#b").value()},i.value(n),o(t,n)}},items:[{name:"r",label:"R",autofocus:1},{name:"g",label:"G"},{name:"b",label:"B"},{name:"hex",label:"#",value:"000000"},{name:"preview",type:"container",border:1}]}]},onSubmit:function(){n("#"+t.toJSON().hex)}});o(t,i)};e.add("colorpicker",function(i){i.settings.color_picker_callback||(i.settings.color_picker_callback=function(e,n){t(i,e,n)})})}(); \ No newline at end of file diff --git a/dashmachine/static/vendors/tinymce/plugins/contextmenu/plugin.min.js b/dashmachine/static/vendors/tinymce/plugins/contextmenu/plugin.min.js deleted file mode 100644 index a2e2c75..0000000 --- a/dashmachine/static/vendors/tinymce/plugins/contextmenu/plugin.min.js +++ /dev/null @@ -1 +0,0 @@ -!function(){"use strict";var o=function(t){var n=t,e=function(){return n};return{get:e,set:function(t){n=t},clone:function(){return o(e())}}},t=tinymce.util.Tools.resolve("tinymce.PluginManager"),i=function(t){return{isContextMenuVisible:function(){return t.get()}}},r=function(t){return t.settings.contextmenu_never_use_native},u=function(t){return t.getParam("contextmenu","link openlink image inserttable | cell row column deletetable")},l=tinymce.util.Tools.resolve("tinymce.dom.DOMUtils"),s=function(t){return l.DOM.select(t.settings.ui_container)[0]},a=function(t,n){return{x:t,y:n}},f=function(t,n,e){return a(t.x+n,t.y+e)},m=function(t,n){if(t&&"static"!==l.DOM.getStyle(t,"position",!0)){var e=l.DOM.getPos(t),o=e.x-t.scrollLeft,i=e.y-t.scrollTop;return f(n,-o,-i)}return f(n,0,0)},c=function(t,n){if(t.inline)return m(s(t),a((u=n).pageX,u.pageY));var e,o,i,r,u,c=(e=t.getContentAreaContainer(),o=a((r=n).clientX,r.clientY),i=l.DOM.getPos(e),f(o,i.x,i.y));return m(s(t),c)},g=tinymce.util.Tools.resolve("tinymce.ui.Factory"),v=tinymce.util.Tools.resolve("tinymce.util.Tools"),y=function(t,n,e,o){null===o.get()?o.set(function(e,n){var t,o,i=[];o=u(e),v.each(o.split(/[ ,]/),function(t){var n=e.menuItems[t];"|"===t&&(n={text:t}),n&&(n.shortcut="",i.push(n))});for(var r=0;r'}),o+=""}),o+=""},o=function(a,t){var e=i(t);a.addButton("emoticons",{type:"panelbutton",panel:{role:"application",autohide:!0,html:e,onclick:function(t){var e,i,o,n=a.dom.getParent(t.target,"a");n&&(e=a,i=n.getAttribute("data-mce-url"),o=n.getAttribute("data-mce-alt"),e.insertContent(e.dom.createHTML("img",{src:i,alt:o})),this.hide())}},tooltip:"Emoticons"})};t.add("emoticons",function(t,e){o(t,e)})}(); \ No newline at end of file diff --git a/dashmachine/static/vendors/tinymce/plugins/fullpage/plugin.min.js b/dashmachine/static/vendors/tinymce/plugins/fullpage/plugin.min.js deleted file mode 100644 index de5221a..0000000 --- a/dashmachine/static/vendors/tinymce/plugins/fullpage/plugin.min.js +++ /dev/null @@ -1 +0,0 @@ -!function(){"use strict";var l=function(e){var t=e,n=function(){return t};return{get:n,set:function(e){t=e},clone:function(){return l(n())}}},e=tinymce.util.Tools.resolve("tinymce.PluginManager"),g=tinymce.util.Tools.resolve("tinymce.util.Tools"),t=tinymce.util.Tools.resolve("tinymce.html.DomParser"),f=tinymce.util.Tools.resolve("tinymce.html.Node"),m=tinymce.util.Tools.resolve("tinymce.html.Serializer"),h=function(e){return e.getParam("fullpage_hide_in_source_view")},r=function(e){return e.getParam("fullpage_default_xml_pi")},o=function(e){return e.getParam("fullpage_default_encoding")},a=function(e){return e.getParam("fullpage_default_font_family")},c=function(e){return e.getParam("fullpage_default_font_size")},s=function(e){return e.getParam("fullpage_default_text_color")},u=function(e){return e.getParam("fullpage_default_title")},d=function(e){return e.getParam("fullpage_default_doctype","")},p=function(e){return t({validate:!1,root_name:"#document"}).parse(e)},y=p,v=function(e,t){var n,l,i=p(t),r={};function o(e,t){return e.attr(t)||""}return r.fontface=a(e),r.fontsize=c(e),7===(n=i.firstChild).type&&(r.xml_pi=!0,(l=/encoding="([^"]+)"/.exec(n.value))&&(r.docencoding=l[1])),(n=i.getAll("#doctype")[0])&&(r.doctype=""),(n=i.getAll("title")[0])&&n.firstChild&&(r.title=n.firstChild.value),g.each(i.getAll("meta"),function(e){var t,n=e.attr("name"),l=e.attr("http-equiv");n?r[n.toLowerCase()]=e.attr("content"):"Content-Type"===l&&(t=/charset\s*=\s*(.*)\s*/gi.exec(e.attr("content")))&&(r.docencoding=t[1])}),(n=i.getAll("html")[0])&&(r.langcode=o(n,"lang")||o(n,"xml:lang")),r.stylesheets=[],g.each(i.getAll("link"),function(e){"stylesheet"===e.attr("rel")&&r.stylesheets.push(e.attr("href"))}),(n=i.getAll("body")[0])&&(r.langdir=o(n,"dir"),r.style=o(n,"style"),r.visited_color=o(n,"vlink"),r.link_color=o(n,"link"),r.active_color=o(n,"alink")),r},_=function(e,r,t){var o,n,l,a,i,c=e.dom;function s(e,t,n){e.attr(t,n||undefined)}function u(e){n.firstChild?n.insert(e,n.firstChild):n.append(e)}o=p(t),(n=o.getAll("head")[0])||(a=o.getAll("html")[0],n=new f("head",1),a.firstChild?a.insert(n,a.firstChild,!0):a.append(n)),a=o.firstChild,r.xml_pi?(i='version="1.0"',r.docencoding&&(i+=' encoding="'+r.docencoding+'"'),7!==a.type&&(a=new f("xml",7),o.insert(a,o.firstChild,!0)),a.value=i):a&&7===a.type&&a.remove(),a=o.getAll("#doctype")[0],r.doctype?(a||(a=new f("#doctype",10),r.xml_pi?o.insert(a,o.firstChild):u(a)),a.value=r.doctype.substring(9,r.doctype.length-1)):a&&a.remove(),a=null,g.each(o.getAll("meta"),function(e){"Content-Type"===e.attr("http-equiv")&&(a=e)}),r.docencoding?(a||((a=new f("meta",1)).attr("http-equiv","Content-Type"),a.shortEnded=!0,u(a)),a.attr("content","text/html; charset="+r.docencoding)):a&&a.remove(),a=o.getAll("title")[0],r.title?(a?a.empty():u(a=new f("title",1)),a.append(new f("#text",3)).value=r.title):a&&a.remove(),g.each("keywords,description,author,copyright,robots".split(","),function(e){var t,n,l=o.getAll("meta"),i=r[e];for(t=0;t"))},n=function(n,l){var i=v(n,l.get());n.windowManager.open({title:"Document properties",data:i,defaults:{type:"textbox",size:40},body:[{name:"title",label:"Title"},{name:"keywords",label:"Keywords"},{name:"description",label:"Description"},{name:"robots",label:"Robots"},{name:"author",label:"Author"},{name:"docencoding",label:"Encoding"}],onSubmit:function(e){var t=_(n,g.extend(i,e.data),l.get());l.set(t)}})},i=function(e,t){e.addCommand("mceFullPageProperties",function(){n(e,t)})},b=function(e,t){return g.each(e,function(e){t=t.replace(e,function(e){return"\x3c!--mce:protected "+escape(e)+"--\x3e"})}),t},x=function(e){return e.replace(//g,function(e,t){return unescape(t)})},k=g.each,C=function(e){return e.replace(/<\/?[A-Z]+/g,function(e){return e.toLowerCase()})},A=function(e){var t,n="",l="";if(r(e)){var i=o(e);n+='\n'}return n+=d(e),n+="\n\n\n",(t=u(e))&&(n+=""+t+"\n"),(t=o(e))&&(n+='\n'),(t=a(e))&&(l+="font-family: "+t+";"),(t=c(e))&&(l+="font-size: "+t+";"),(t=s(e))&&(l+="color: "+t+";"),n+="\n\n"},w=function(r,o,a){r.on("BeforeSetContent",function(e){!function(e,t,n,l){var i,r,o,a,c,s="",u=e.dom;if(!(l.selection||(o=b(e.settings.protect,l.content),"raw"===l.format&&t.get()||l.source_view&&h(e)))){0!==o.length||l.source_view||(o=g.trim(t.get())+"\n"+g.trim(o)+"\n"+g.trim(n.get())),-1!==(i=(o=o.replace(/<(\/?)BODY/gi,"<$1body")).indexOf("",i),t.set(C(o.substring(0,i+1))),-1===(r=o.indexOf("\n")),a=y(t.get()),k(a.getAll("style"),function(e){e.firstChild&&(s+=e.firstChild.value)}),(c=a.getAll("body")[0])&&u.setAttribs(e.getBody(),{style:c.attr("style")||"",dir:c.attr("dir")||"",vLink:c.attr("vlink")||"",link:c.attr("link")||"",aLink:c.attr("alink")||""}),u.remove("fullpage_styles");var d=e.getDoc().getElementsByTagName("head")[0];s&&(u.add(d,"style",{id:"fullpage_styles"},s),(c=u.get("fullpage_styles")).styleSheet&&(c.styleSheet.cssText=s));var f={};g.each(d.getElementsByTagName("link"),function(e){"stylesheet"===e.rel&&e.getAttribute("data-mce-fullpage")&&(f[e.href]=e)}),g.each(a.getAll("link"),function(e){var t=e.attr("href");if(!t)return!0;f[t]||"stylesheet"!==e.attr("rel")||u.add(d,"link",{rel:"stylesheet",text:"text/css",href:t,"data-mce-fullpage":"1"}),delete f[t]}),g.each(f,function(e){e.parentNode.removeChild(e)})}}(r,o,a,e)}),r.on("GetContent",function(e){var t,n,l,i;t=r,n=o.get(),l=a.get(),(i=e).selection||i.source_view&&h(t)||(i.content=x(g.trim(n)+"\n"+g.trim(i.content)+"\n"+g.trim(l)))})},P=function(e){e.addButton("fullpage",{title:"Document properties",cmd:"mceFullPageProperties"}),e.addMenuItem("fullpage",{text:"Document properties",cmd:"mceFullPageProperties",context:"file"})};e.add("fullpage",function(e){var t=l(""),n=l("");i(e,t),P(e),w(e,t,n)})}(); \ No newline at end of file diff --git a/dashmachine/static/vendors/tinymce/plugins/fullscreen/plugin.min.js b/dashmachine/static/vendors/tinymce/plugins/fullscreen/plugin.min.js deleted file mode 100644 index cd4eb5e..0000000 --- a/dashmachine/static/vendors/tinymce/plugins/fullscreen/plugin.min.js +++ /dev/null @@ -1 +0,0 @@ -!function(){"use strict";var i=function(e){var n=e,t=function(){return n};return{get:t,set:function(e){n=e},clone:function(){return i(t())}}},e=tinymce.util.Tools.resolve("tinymce.PluginManager"),t=function(e){return{isFullscreen:function(){return null!==e.get()}}},n=tinymce.util.Tools.resolve("tinymce.dom.DOMUtils"),m=function(e,n){e.fire("FullscreenStateChanged",{state:n})},g=n.DOM,r=function(e,n){var t,r,l,i,o,c,s=document.body,u=document.documentElement,d=n.get(),a=function(){var e,n,t,i;g.setStyle(l,"height",(t=window,i=document.body,i.offsetWidth&&(e=i.offsetWidth,n=i.offsetHeight),t.innerWidth&&t.innerHeight&&(e=t.innerWidth,n=t.innerHeight),{w:e,h:n}).h-(r.clientHeight-l.clientHeight))},h=function(){g.unbind(window,"resize",a)};if(t=(r=e.getContainer()).style,i=(l=e.getContentAreaContainer().firstChild).style,d)i.width=d.iframeWidth,i.height=d.iframeHeight,d.containerWidth&&(t.width=d.containerWidth),d.containerHeight&&(t.height=d.containerHeight),g.removeClass(s,"mce-fullscreen"),g.removeClass(u,"mce-fullscreen"),g.removeClass(r,"mce-fullscreen"),o=d.scrollPos,window.scrollTo(o.x,o.y),g.unbind(window,"resize",d.resizeHandler),e.off("remove",d.removeHandler),n.set(null),m(e,!1);else{var f={scrollPos:(c=g.getViewPort(),{x:c.x,y:c.y}),containerWidth:t.width,containerHeight:t.height,iframeWidth:i.width,iframeHeight:i.height,resizeHandler:a,removeHandler:h};i.width=i.height="100%",t.width=t.height="",g.addClass(s,"mce-fullscreen"),g.addClass(u,"mce-fullscreen"),g.addClass(r,"mce-fullscreen"),g.bind(window,"resize",a),e.on("remove",h),a(),n.set(f),m(e,!0)}},l=function(e,n){e.addCommand("mceFullScreen",function(){r(e,n)})},o=function(t){return function(e){var n=e.control;t.on("FullscreenStateChanged",function(e){n.active(e.state)})}},c=function(e){e.addMenuItem("fullscreen",{text:"Fullscreen",shortcut:"Ctrl+Shift+F",selectable:!0,cmd:"mceFullScreen",onPostRender:o(e),context:"view"}),e.addButton("fullscreen",{active:!1,tooltip:"Fullscreen",cmd:"mceFullScreen",onPostRender:o(e)})};e.add("fullscreen",function(e){var n=i(null);return e.settings.inline||(l(e,n),c(e),e.addShortcut("Ctrl+Shift+F","","mceFullScreen")),t(n)})}(); \ No newline at end of file diff --git a/dashmachine/static/vendors/tinymce/plugins/help/img/logo.png b/dashmachine/static/vendors/tinymce/plugins/help/img/logo.png deleted file mode 100644 index ebd7eb1..0000000 Binary files a/dashmachine/static/vendors/tinymce/plugins/help/img/logo.png and /dev/null differ diff --git a/dashmachine/static/vendors/tinymce/plugins/help/plugin.min.js b/dashmachine/static/vendors/tinymce/plugins/help/plugin.min.js deleted file mode 100644 index a598b6c..0000000 --- a/dashmachine/static/vendors/tinymce/plugins/help/plugin.min.js +++ /dev/null @@ -1 +0,0 @@ -!function(){"use strict";var e=tinymce.util.Tools.resolve("tinymce.PluginManager"),t=function(e){return function(){return e}};function c(r){for(var o=[],e=1;e'+C.translate(e.action)+""+e.shortcut+"";var t}).join("");return{title:"Handy Shortcuts",type:"container",style:"overflow-y: auto; overflow-x: hidden; max-height: 250px",items:[{type:"container",html:'
"+e+"
'+C.translate("Action")+""+C.translate("Shortcut")+"
"}]}},P=Object.keys,_=[{key:"advlist",name:"Advanced List"},{key:"anchor",name:"Anchor"},{key:"autolink",name:"Autolink"},{key:"autoresize",name:"Autoresize"},{key:"autosave",name:"Autosave"},{key:"bbcode",name:"BBCode"},{key:"charmap",name:"Character Map"},{key:"code",name:"Code"},{key:"codesample",name:"Code Sample"},{key:"colorpicker",name:"Color Picker"},{key:"compat3x",name:"3.x Compatibility"},{key:"contextmenu",name:"Context Menu"},{key:"directionality",name:"Directionality"},{key:"emoticons",name:"Emoticons"},{key:"fullpage",name:"Full Page"},{key:"fullscreen",name:"Full Screen"},{key:"help",name:"Help"},{key:"hr",name:"Horizontal Rule"},{key:"image",name:"Image"},{key:"imagetools",name:"Image Tools"},{key:"importcss",name:"Import CSS"},{key:"insertdatetime",name:"Insert Date/Time"},{key:"legacyoutput",name:"Legacy Output"},{key:"link",name:"Link"},{key:"lists",name:"Lists"},{key:"media",name:"Media"},{key:"nonbreaking",name:"Nonbreaking"},{key:"noneditable",name:"Noneditable"},{key:"pagebreak",name:"Page Break"},{key:"paste",name:"Paste"},{key:"preview",name:"Preview"},{key:"print",name:"Print"},{key:"save",name:"Save"},{key:"searchreplace",name:"Search and Replace"},{key:"spellchecker",name:"Spell Checker"},{key:"tabfocus",name:"Tab Focus"},{key:"table",name:"Table"},{key:"template",name:"Template"},{key:"textcolor",name:"Text Color"},{key:"textpattern",name:"Text Pattern"},{key:"toc",name:"Table of Contents"},{key:"visualblocks",name:"Visual Blocks"},{key:"visualchars",name:"Visual Characters"},{key:"wordcount",name:"Word Count"}],H=c(function(e,o){return e.replace(/\$\{([^{}]*)\}/g,function(e,t){var n,r=o[t];return"string"==(n=typeof r)||"number"===n?r.toString():e})},'${name}'),F=function(t,n){return function(e,t){for(var n=0,r=e.length;n"+F(t,e)+""}),i=a.length,l=a.join("");return"

"+C.translate(["Plugins installed ({0}):",i])+"

    "+l+"
"},E=function(e){return{title:"Plugins",type:"container",style:"overflow-y: auto; overflow-x: hidden;",layout:"flex",padding:10,spacing:10,items:[(t=e,{type:"container",html:'
'+M(t)+"
",flex:1}),{type:"container",html:'

'+C.translate("Premium plugins:")+'

  • PowerPaste
  • Spell Checker Pro
  • Accessibility Checker
  • Advanced Code Editor
  • Enhanced Media Embed
  • Link Checker

'+C.translate("Learn more...")+"

",flex:1}]};var t},I=tinymce.util.Tools.resolve("tinymce.EditorManager"),j=function(){var e,t,n='TinyMCE '+(e=I.majorVersion,t=I.minorVersion,0===e.indexOf("@")?"X.X.X":e+"."+t)+"";return[{type:"label",html:C.translate(["You are using {0}",n])},{type:"spacer",flex:1},{text:"Close",onclick:function(){this.parent().parent().close()}}]},L=function(e,t){return function(){e.windowManager.open({title:"Help",bodyType:"tabpanel",layout:"flex",body:[T(),E(e)],buttons:j(),onPostRender:function(){this.getEl("title").innerHTML='TinyMCE Logo'}})}},B=function(e,t){e.addCommand("mceHelp",L(e,t))},N=function(e,t){e.addButton("help",{icon:"help",onclick:L(e,t)}),e.addMenuItem("help",{text:"Help",icon:"help",context:"help",onclick:L(e,t)})};e.add("help",function(e,t){N(e,t),B(e,t),e.shortcuts.add("Alt+0","Open help dialog","mceHelp")})}(); \ No newline at end of file diff --git a/dashmachine/static/vendors/tinymce/plugins/hr/plugin.min.js b/dashmachine/static/vendors/tinymce/plugins/hr/plugin.min.js deleted file mode 100644 index 72bc2ca..0000000 --- a/dashmachine/static/vendors/tinymce/plugins/hr/plugin.min.js +++ /dev/null @@ -1 +0,0 @@ -!function(){"use strict";var n=tinymce.util.Tools.resolve("tinymce.PluginManager"),t=function(n){n.addCommand("InsertHorizontalRule",function(){n.execCommand("mceInsertContent",!1,"
")})},o=function(n){n.addButton("hr",{icon:"hr",tooltip:"Horizontal line",cmd:"InsertHorizontalRule"}),n.addMenuItem("hr",{icon:"hr",text:"Horizontal line",cmd:"InsertHorizontalRule",context:"insert"})};n.add("hr",function(n){t(n),o(n)})}(); \ No newline at end of file diff --git a/dashmachine/static/vendors/tinymce/plugins/image/plugin.min.js b/dashmachine/static/vendors/tinymce/plugins/image/plugin.min.js deleted file mode 100644 index 2bb78be..0000000 --- a/dashmachine/static/vendors/tinymce/plugins/image/plugin.min.js +++ /dev/null @@ -1 +0,0 @@ -!function(){"use strict";var i,e=tinymce.util.Tools.resolve("tinymce.PluginManager"),d=function(e){return!1!==e.settings.image_dimensions},l=function(e){return!0===e.settings.image_advtab},m=function(e){return e.getParam("image_prepend_url","")},n=function(e){return e.getParam("image_class_list")},r=function(e){return!1!==e.settings.image_description},a=function(e){return!0===e.settings.image_title},o=function(e){return!0===e.settings.image_caption},u=function(e){return e.getParam("image_list",!1)},c=function(e){return e.getParam("images_upload_url",!1)},s=function(e){return e.getParam("images_upload_handler",!1)},g=function(e){return e.getParam("images_upload_url")},f=function(e){return e.getParam("images_upload_handler")},p=function(e){return e.getParam("images_upload_base_path")},h=function(e){return e.getParam("images_upload_credentials")},v="undefined"!=typeof window?window:Function("return this;")(),b=function(e,t){return function(e,t){for(var n=t!==undefined&&null!==t?t:v,r=0;rthis.length())return null;for(var n=this.littleEndian?0:-8*(e-1),r=0,o=0;r=s.length())throw new Error("Invalid Exif data.");"ASCII"!==i?(f=s.asArray(i,c,a),l=1==a?f[0]:f,it.hasOwnProperty(o)&&"object"!=typeof l?d[o]=it[o][l]:d[o]=l):d[o]=s.STRING(c,a).replace(/\0$/,"").trim()}return d},t}(),ut=function(t){var e,n,r=[],o=0;for(e=2;e<=t.length();)if(65488<=(n=t.SHORT(e))&&n<=65495)e+=2;else{if(65498===n||65497===n)break;o=t.SHORT(e+2)+2,65505<=n&&n<=65519&&r.push({hex:n,name:"APP"+(15&n),start:e,length:o,segment:t.SEGMENT(e,o)}),e+=o}return r},ct=function(u){return k.blobToArrayBuffer(u).then(function(t){try{var e=new tt(t);if(65496===e.SHORT(0)){var n=ut(e),r=n.filter(function(t){return"APP1"===t.name}),o={};if(!r.length)return g.reject("Headers did not include required information");var i=new at(r[0].segment);return(o={tiff:i.TIFF(),exif:i.EXIF(),gps:i.GPS(),thumb:i.thumb()}).rawHeaders=n,o}return g.reject("Image was not a jpeg")}catch(a){return g.reject("Unsupported format or not an image: "+u.type+" (Exception: "+a.message+")")}})},lt=function(t,e){return Q.rotate(t,e)},st={invert:function(t){return K.invert(t)},sharpen:function(t){return K.sharpen(t)},emboss:function(t){return K.emboss(t)},brightness:function(t,e){return K.brightness(t,e)},hue:function(t,e){return K.hue(t,e)},saturate:function(t,e){return K.saturate(t,e)},contrast:function(t,e){return K.contrast(t,e)},grayscale:function(t,e){return K.grayscale(t,e)},sepia:function(t,e){return K.sepia(t,e)},colorize:function(t,e,n,r){return K.colorize(t,e,n,r)},gamma:function(t,e){return K.gamma(t,e)},exposure:function(t,e){return K.exposure(t,e)},flip:function(t,e){return Q.flip(t,e)},crop:function(t,e,n,r,o){return Q.crop(t,e,n,r,o)},resize:function(t,e,n){return Q.resize(t,e,n)},rotate:lt,exifRotate:function(e){return e.toBlob().then(ct).then(function(t){switch(t.tiff.Orientation){case 6:return lt(e,90);case 3:return lt(e,180);case 8:return lt(e,270);default:return e}},function(){return e})}},ft=function(t){return t.toBlob()},dt={blobToImageResult:function(t){return M.fromBlob(t)},fromBlobAndUrlSync:function(t,e){return M.fromBlobAndUrlSync(t,e)},imageToImageResult:function(t){return M.fromImage(t)},imageResultToBlob:function(t,e,n){return e===undefined&&n===undefined?ft(t):t.toAdjustedBlob(e,n)},imageResultToOriginalBlob:ft,imageResultToDataURL:function(t){return t.toDataURL()}},ht=function(){return S.getOrDie("URL")},pt={createObjectURL:function(t){return ht().createObjectURL(t)},revokeObjectURL:function(t){ht().revokeObjectURL(t)}},gt=tinymce.util.Tools.resolve("tinymce.util.Delay"),mt=tinymce.util.Tools.resolve("tinymce.util.Promise"),yt=tinymce.util.Tools.resolve("tinymce.util.URI"),vt=tinymce.util.Tools.resolve("tinymce.dom.DOMUtils"),bt=tinymce.util.Tools.resolve("tinymce.ui.Factory"),wt=tinymce.util.Tools.resolve("tinymce.geom.Rect"),xt=function(n){return new mt(function(t){var e=function(){n.removeEventListener("load",e),t(n)};n.complete?t(n):n.addEventListener("load",e)})},It=tinymce.util.Tools.resolve("tinymce.dom.DomQuery"),Tt=tinymce.util.Tools.resolve("tinymce.util.Observable"),Rt=tinymce.util.Tools.resolve("tinymce.util.VK"),St=0,Ot={create:function(t){return new(bt.get("Control").extend({Defaults:{classes:"imagepanel"},selection:function(t){return arguments.length?(this.state.set("rect",t),this):this.state.get("rect")},imageSize:function(){var t=this.state.get("viewRect");return{w:t.w,h:t.h}},toggleCropRect:function(t){this.state.set("cropEnabled",t)},imageSrc:function(t){var o=this,i=new Image;i.src=t,xt(i).then(function(){var t,e,n=o.state.get("viewRect");if((e=o.$el.find("img"))[0])e.replaceWith(i);else{var r=document.createElement("div");r.className="mce-imagepanel-bg",o.getEl().appendChild(r),o.getEl().appendChild(i)}t={x:0,y:0,w:i.naturalWidth,h:i.naturalHeight},o.state.set("viewRect",t),o.state.set("rect",wt.inflate(t,-20,-20)),n&&n.w===t.w&&n.h===t.h||o.zoomFit(),o.repaintImage(),o.fire("load")})},zoom:function(t){return arguments.length?(this.state.set("zoom",t),this):this.state.get("zoom")},postRender:function(){return this.imageSrc(this.settings.imageSrc),this._super()},zoomFit:function(){var t,e,n,r,o,i;t=this.$el.find("img"),e=this.getEl().clientWidth,n=this.getEl().clientHeight,r=t[0].naturalWidth,o=t[0].naturalHeight,1<=(i=Math.min((e-10)/r,(n-10)/o))&&(i=1),this.zoom(i)},repaintImage:function(){var t,e,n,r,o,i,a,u,c,l,s;s=this.getEl(),c=this.zoom(),l=this.state.get("rect"),a=this.$el.find("img"),u=this.$el.find(".mce-imagepanel-bg"),o=s.offsetWidth,i=s.offsetHeight,n=a[0].naturalWidth*c,r=a[0].naturalHeight*c,t=Math.max(0,o/2-n/2),e=Math.max(0,i/2-r/2),a.css({left:t,top:e,width:n,height:r}),u.css({left:t,top:e,width:n,height:r}),this.cropRect&&(this.cropRect.setRect({x:l.x*c+t,y:l.y*c+e,w:l.w*c,h:l.h*c}),this.cropRect.setClampRect({x:t,y:e,w:n,h:r}),this.cropRect.setViewPortRect({x:0,y:0,w:o,h:i}))},bindStates:function(){var r=this;function n(t){r.cropRect=function(l,n,s,r,o){var f,a,t,i,e="mce-",u=e+"crid-"+St++;function d(t,e){return{x:e.x-t.x,y:e.y-t.y,w:e.w,h:e.h}}function c(t,e,n,r){var o,i,a,u,c;o=e.x,i=e.y,a=e.w,u=e.h,o+=n*t.deltaX,i+=r*t.deltaY,(a+=n*t.deltaW)<20&&(a=20),(u+=r*t.deltaH)<20&&(u=20),c=l=wt.clamp({x:o,y:i,w:a,h:u},s,"move"===t.name),c=d(s,c),f.fire("updateRect",{rect:c}),g(c)}function h(e){function t(t,e){e.h<0&&(e.h=0),e.w<0&&(e.w=0),It("#"+u+"-"+t,r).css({left:e.x,top:e.y,width:e.w,height:e.h})}$.each(a,function(t){It("#"+u+"-"+t.name,r).css({left:e.w*t.xMul+e.x,top:e.h*t.yMul+e.y})}),t("top",{x:n.x,y:n.y,w:n.w,h:e.y-n.y}),t("right",{x:e.x+e.w,y:e.y,w:n.w-e.x-e.w+n.x,h:e.h}),t("bottom",{x:n.x,y:e.y+e.h,w:n.w,h:n.h-e.y-e.h+n.y}),t("left",{x:n.x,y:e.y,w:e.x-n.x,h:e.h}),t("move",e)}function p(t){h(l=t)}function g(t){var e,n;p((e=s,{x:(n=t).x+e.x,y:n.y+e.y,w:n.w,h:n.h}))}return a=[{name:"move",xMul:0,yMul:0,deltaX:1,deltaY:1,deltaW:0,deltaH:0,label:"Crop Mask"},{name:"nw",xMul:0,yMul:0,deltaX:1,deltaY:1,deltaW:-1,deltaH:-1,label:"Top Left Crop Handle"},{name:"ne",xMul:1,yMul:0,deltaX:0,deltaY:1,deltaW:1,deltaH:-1,label:"Top Right Crop Handle"},{name:"sw",xMul:0,yMul:1,deltaX:1,deltaY:0,deltaW:-1,deltaH:1,label:"Bottom Left Crop Handle"},{name:"se",xMul:1,yMul:1,deltaX:0,deltaY:0,deltaW:1,deltaH:1,label:"Bottom Right Crop Handle"}],i=["top","right","bottom","left"],It('
').appendTo(r),$.each(i,function(t){It("#"+u,r).append('