mirror of
https://github.com/LC044/WeChatMsg
synced 2024-11-09 09:31:18 +08:00
mainwindows文件修正
This commit is contained in:
parent
01f16c1168
commit
64c1cb7c49
141
resource/datasets/__init__.py
Normal file
141
resource/datasets/__init__.py
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
import difflib
|
||||||
|
import os
|
||||||
|
import typing
|
||||||
|
import urllib.request
|
||||||
|
|
||||||
|
import simplejson as json
|
||||||
|
|
||||||
|
|
||||||
|
class FuzzyDict(dict):
|
||||||
|
"""Provides a dictionary that performs fuzzy lookup"""
|
||||||
|
|
||||||
|
def __init__(self, cutoff: float = 0.6):
|
||||||
|
"""Construct a new FuzzyDict instance
|
||||||
|
|
||||||
|
items is an dictionary to copy items from (optional)
|
||||||
|
cutoff is the match ratio below which matches should not be considered
|
||||||
|
cutoff needs to be a float between 0 and 1 (where zero is no match
|
||||||
|
and 1 is a perfect match)"""
|
||||||
|
super(FuzzyDict, self).__init__()
|
||||||
|
self.cutoff = cutoff
|
||||||
|
|
||||||
|
# short wrapper around some super (dict) methods
|
||||||
|
self._dict_contains = lambda key: super(FuzzyDict, self).__contains__(key)
|
||||||
|
self._dict_getitem = lambda key: super(FuzzyDict, self).__getitem__(key)
|
||||||
|
|
||||||
|
def _search(self, lookfor: typing.Any, stop_on_first: bool = False):
|
||||||
|
"""Returns the value whose key best matches lookfor
|
||||||
|
|
||||||
|
if stop_on_first is True then the method returns as soon
|
||||||
|
as it finds the first item
|
||||||
|
"""
|
||||||
|
|
||||||
|
# if the item is in the dictionary then just return it
|
||||||
|
if self._dict_contains(lookfor):
|
||||||
|
return True, lookfor, self._dict_getitem(lookfor), 1
|
||||||
|
|
||||||
|
# set up the fuzzy matching tool
|
||||||
|
ratio_calc = difflib.SequenceMatcher()
|
||||||
|
ratio_calc.set_seq1(lookfor)
|
||||||
|
|
||||||
|
# test each key in the dictionary
|
||||||
|
best_ratio = 0
|
||||||
|
best_match = None
|
||||||
|
best_key = None
|
||||||
|
for key in self:
|
||||||
|
# if the current key is not a string
|
||||||
|
# then we just skip it
|
||||||
|
try:
|
||||||
|
# set up the SequenceMatcher with other text
|
||||||
|
ratio_calc.set_seq2(key)
|
||||||
|
except TypeError:
|
||||||
|
continue
|
||||||
|
|
||||||
|
# we get an error here if the item to look for is not a
|
||||||
|
# string - if it cannot be fuzzy matched and we are here
|
||||||
|
# this it is definitely not in the dictionary
|
||||||
|
try:
|
||||||
|
# calculate the match value
|
||||||
|
ratio = ratio_calc.ratio()
|
||||||
|
except TypeError:
|
||||||
|
break
|
||||||
|
|
||||||
|
# if this is the best ratio so far - save it and the value
|
||||||
|
if ratio > best_ratio:
|
||||||
|
best_ratio = ratio
|
||||||
|
best_key = key
|
||||||
|
best_match = self._dict_getitem(key)
|
||||||
|
|
||||||
|
if stop_on_first and ratio >= self.cutoff:
|
||||||
|
break
|
||||||
|
|
||||||
|
return best_ratio >= self.cutoff, best_key, best_match, best_ratio
|
||||||
|
|
||||||
|
def __contains__(self, item: typing.Any):
|
||||||
|
if self._search(item, True)[0]:
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
def __getitem__(self, lookfor: typing.Any):
|
||||||
|
matched, key, item, ratio = self._search(lookfor)
|
||||||
|
|
||||||
|
if not matched:
|
||||||
|
raise KeyError(
|
||||||
|
"'%s'. closest match: '%s' with ratio %.3f"
|
||||||
|
% (str(lookfor), str(key), ratio)
|
||||||
|
)
|
||||||
|
|
||||||
|
return item
|
||||||
|
|
||||||
|
|
||||||
|
__HERE = os.path.abspath(os.path.dirname(__file__))
|
||||||
|
with open(os.path.join(__HERE, "map_filename.json"), "r", encoding="utf8") as f:
|
||||||
|
FILENAMES: FuzzyDict = FuzzyDict()
|
||||||
|
for k, v in json.load(f).items():
|
||||||
|
FILENAMES[k] = v
|
||||||
|
|
||||||
|
with open(os.path.join(__HERE, "city_coordinates.json"), "r", encoding="utf8") as f:
|
||||||
|
COORDINATES: FuzzyDict = FuzzyDict()
|
||||||
|
for k, v in json.load(f).items():
|
||||||
|
COORDINATES[k] = v
|
||||||
|
|
||||||
|
EXTRA = {}
|
||||||
|
|
||||||
|
|
||||||
|
def register_url(asset_url: str):
|
||||||
|
if asset_url:
|
||||||
|
registry = asset_url + "/registry.json"
|
||||||
|
try:
|
||||||
|
contents = urllib.request.urlopen(registry).read()
|
||||||
|
contents = json.loads(contents)
|
||||||
|
except Exception as e:
|
||||||
|
raise e
|
||||||
|
files = {}
|
||||||
|
pinyin_names = set()
|
||||||
|
for name, pinyin in contents["PINYIN_MAP"].items():
|
||||||
|
file_name = contents["FILE_MAP"][pinyin]
|
||||||
|
files[name] = [file_name, "js"]
|
||||||
|
pinyin_names.add(pinyin)
|
||||||
|
|
||||||
|
for key, file_name in contents["FILE_MAP"].items():
|
||||||
|
if key not in pinyin_names:
|
||||||
|
# English names
|
||||||
|
files[key] = [file_name, "js"]
|
||||||
|
|
||||||
|
js_folder_name = contents["JS_FOLDER"]
|
||||||
|
if js_folder_name == "/":
|
||||||
|
js_file_prefix = f"{asset_url}/"
|
||||||
|
else:
|
||||||
|
js_file_prefix = f"{asset_url}/{js_folder_name}/"
|
||||||
|
EXTRA[js_file_prefix] = files
|
||||||
|
|
||||||
|
|
||||||
|
def register_files(asset_files: dict):
|
||||||
|
if asset_files:
|
||||||
|
FILENAMES.update(asset_files)
|
||||||
|
|
||||||
|
|
||||||
|
def register_coords(coords: dict):
|
||||||
|
if coords:
|
||||||
|
COORDINATES.update(coords)
|
15006
resource/datasets/city_coordinates.json
Normal file
15006
resource/datasets/city_coordinates.json
Normal file
File diff suppressed because it is too large
Load Diff
218
resource/datasets/countries_regions_db.json
Normal file
218
resource/datasets/countries_regions_db.json
Normal file
@ -0,0 +1,218 @@
|
|||||||
|
{
|
||||||
|
"蒲隆地": "BI",
|
||||||
|
"圣卢西亚": "LC",
|
||||||
|
"巴巴多斯": "BB",
|
||||||
|
"安道尔": "AD",
|
||||||
|
"利比里亚": "LR",
|
||||||
|
"吉尔吉斯斯坦": "KG",
|
||||||
|
"阿曼": "OM",
|
||||||
|
"利比亚": "LY",
|
||||||
|
"根西": "GG",
|
||||||
|
"南非": "ZA",
|
||||||
|
"阿塞拜疆": "AZ",
|
||||||
|
"巴拉圭": "PY",
|
||||||
|
"匈牙利": "HU",
|
||||||
|
"巴勒斯坦": "PS",
|
||||||
|
"泰国": "TH",
|
||||||
|
"黎巴嫩": "LB",
|
||||||
|
"英属维尔京群岛": "VG",
|
||||||
|
"特立尼达和多巴哥": "TT",
|
||||||
|
"巴基斯坦": "PK",
|
||||||
|
"加拿大": "CA",
|
||||||
|
"保加利亚": "BG",
|
||||||
|
"马来西亚": "MY",
|
||||||
|
"叙利亚": "SY",
|
||||||
|
"毛里塔尼亚": "MR",
|
||||||
|
"白俄罗斯": "BY",
|
||||||
|
"秘鲁": "PE",
|
||||||
|
"摩洛哥": "MA",
|
||||||
|
"莱索托": "LS",
|
||||||
|
"法罗群岛": "FO",
|
||||||
|
"圣基茨和尼维斯": "KN",
|
||||||
|
"阿根廷": "AR",
|
||||||
|
"委内瑞拉": "VE",
|
||||||
|
"塞舌尔": "SC",
|
||||||
|
"英属印度洋领地": "IO",
|
||||||
|
"瓦努阿图": "VU",
|
||||||
|
"纳米比亚": "NA",
|
||||||
|
"马拉维": "MW",
|
||||||
|
"克罗地亚": "HR",
|
||||||
|
"玻利维亚": "BO",
|
||||||
|
"塞内加尔": "SN",
|
||||||
|
"希腊": "GR",
|
||||||
|
"蒙古": "MN",
|
||||||
|
"东帝汶": "TL",
|
||||||
|
"新加坡": "SG",
|
||||||
|
"意大利": "IT",
|
||||||
|
"皮特凱恩群島": "PN",
|
||||||
|
"芬兰": "FI",
|
||||||
|
"圭亚那": "GY",
|
||||||
|
"福克兰群岛": "FK",
|
||||||
|
"毛里求斯": "MU",
|
||||||
|
"马其顿": "MK",
|
||||||
|
"新西兰": "NZ",
|
||||||
|
"波斯尼亚-黑塞哥维那": "BA",
|
||||||
|
"吐瓦鲁": "TV",
|
||||||
|
"以色列": "IL",
|
||||||
|
"塞尔维亚": "RS",
|
||||||
|
"密克罗尼西亚联邦": "FM",
|
||||||
|
"斯洛文尼亚": "SI",
|
||||||
|
"阿富汗": "AF",
|
||||||
|
"科威特": "KW",
|
||||||
|
"英国": "GB",
|
||||||
|
"汤加": "TO",
|
||||||
|
"贝宁": "BJ",
|
||||||
|
"撒拉威阿拉伯民主共和国": "",
|
||||||
|
"海地": "HT",
|
||||||
|
"格鲁吉亚": "GE",
|
||||||
|
"安提瓜和巴布达": "AG",
|
||||||
|
"刚果金": "CD",
|
||||||
|
"澳大利亚": "AU",
|
||||||
|
"史瓦济兰": "SZ",
|
||||||
|
"马达加斯加": "MG",
|
||||||
|
"哥伦比亚": "CO",
|
||||||
|
"多米尼加共和国": "DO",
|
||||||
|
"爱沙尼亚": "EE",
|
||||||
|
"哥斯达黎加": "CR",
|
||||||
|
"塞浦路斯": "CY",
|
||||||
|
"沙特阿拉伯": "SA",
|
||||||
|
"南苏丹": "SS",
|
||||||
|
"荷兰": "NL",
|
||||||
|
"圣马力诺": "SM",
|
||||||
|
"罗马尼亚": "RO",
|
||||||
|
"智利": "CL",
|
||||||
|
"几内亚比索": "GW",
|
||||||
|
"尼加拉瓜": "NI",
|
||||||
|
"特克斯和凯科斯群岛": "TC",
|
||||||
|
"珊瑚海群岛领地": "",
|
||||||
|
"泽西": "JE",
|
||||||
|
"奥地利": "AT",
|
||||||
|
"蒙特塞拉特": "MS",
|
||||||
|
"纽埃": "NU",
|
||||||
|
"圣文森特和格林纳丁斯": "VC",
|
||||||
|
"伯利兹": "BZ",
|
||||||
|
"斯洛伐克": "SK",
|
||||||
|
"哈萨克斯坦": "KZ",
|
||||||
|
"直布罗陀": "GI",
|
||||||
|
"柬埔寨": "KH",
|
||||||
|
"立陶宛": "LT",
|
||||||
|
"中非共和国": "CF",
|
||||||
|
"瑞典": "SE",
|
||||||
|
"爱尔兰": "IE",
|
||||||
|
"赤道几内亚": "GQ",
|
||||||
|
"亚美尼亚": "AM",
|
||||||
|
"捷克": "CZ",
|
||||||
|
"冈比亚": "GM",
|
||||||
|
"格陵兰": "GL",
|
||||||
|
"科索沃": "",
|
||||||
|
"印度": "IN",
|
||||||
|
"多哥": "TG",
|
||||||
|
"挪威": "NO",
|
||||||
|
"土耳其": "TR",
|
||||||
|
"拉脱维亚": "LV",
|
||||||
|
"佛得角": "CV",
|
||||||
|
"乌兹别克斯坦": "UZ",
|
||||||
|
"肯尼亚": "KE",
|
||||||
|
"博茨瓦纳": "BW",
|
||||||
|
"加蓬": "GA",
|
||||||
|
"塔吉克斯坦": "TJ",
|
||||||
|
"尼日尔": "NE",
|
||||||
|
"布基纳法索": "BF",
|
||||||
|
"安圭拉": "AI",
|
||||||
|
"老挝": "LA",
|
||||||
|
"阿尔巴尼亚": "AL",
|
||||||
|
"厄瓜多尔": "EC",
|
||||||
|
"葡萄牙": "PT",
|
||||||
|
"乍得": "TD",
|
||||||
|
"南乔治亚和南桑威奇群岛": "GS",
|
||||||
|
"几内亚": "GN",
|
||||||
|
"冰岛": "IS",
|
||||||
|
"托克劳": "TK",
|
||||||
|
"摩纳哥": "MC",
|
||||||
|
"埃及": "EG",
|
||||||
|
"马绍尔群岛": "MH",
|
||||||
|
"巴拿马": "PA",
|
||||||
|
"巴林": "BH",
|
||||||
|
"苏里南": "SR",
|
||||||
|
"帕劳": "PW",
|
||||||
|
"尼日利亚": "NG",
|
||||||
|
"加纳": "GH",
|
||||||
|
"牙买加": "JM",
|
||||||
|
"巴哈马": "BS",
|
||||||
|
"波兰": "PL",
|
||||||
|
"土库曼": "TM",
|
||||||
|
"古巴": "CU",
|
||||||
|
"吉布提": "DJ",
|
||||||
|
"马恩岛": "IM",
|
||||||
|
"巴布亚新几内亚": "PG",
|
||||||
|
"文莱": "BN",
|
||||||
|
"摩尔多瓦": "MD",
|
||||||
|
"开曼群岛": "KY",
|
||||||
|
"安哥拉": "AO",
|
||||||
|
"乌克兰": "UA",
|
||||||
|
"喀麦隆": "CM",
|
||||||
|
"萨尔瓦多": "SV",
|
||||||
|
"萨摩亚": "WS",
|
||||||
|
"黑山": "ME",
|
||||||
|
"孟加拉国": "BD",
|
||||||
|
"韩国": "KR",
|
||||||
|
"苏丹": "SD",
|
||||||
|
"厄立特里亚": "ER",
|
||||||
|
"库克群岛": "CK",
|
||||||
|
"马里": "ML",
|
||||||
|
"伊朗": "IR",
|
||||||
|
"伊拉克": "IQ",
|
||||||
|
"日本": "JP",
|
||||||
|
"突尼斯": "TN",
|
||||||
|
"津巴布韦": "ZW",
|
||||||
|
"菲律宾": "PH",
|
||||||
|
"约旦": "JO",
|
||||||
|
"埃塞俄比亚": "ET",
|
||||||
|
"德国": "DE",
|
||||||
|
"巴西": "BR",
|
||||||
|
"卢旺达": "RW",
|
||||||
|
"洪都拉斯": "HN",
|
||||||
|
"梵蒂冈": "VA",
|
||||||
|
"基里巴斯": "KI",
|
||||||
|
"阿拉伯联合酋长国": "AE",
|
||||||
|
"墨西哥": "MX",
|
||||||
|
"塞拉利昂": "SL",
|
||||||
|
"所罗门群岛": "SB",
|
||||||
|
"斯里兰卡": "LK",
|
||||||
|
"俄罗斯": "RU",
|
||||||
|
"法国": "FR",
|
||||||
|
"危地马拉": "GT",
|
||||||
|
"越南": "VN",
|
||||||
|
"坦桑尼亚": "TZ",
|
||||||
|
"比利时": "BE",
|
||||||
|
"丹麦": "DK",
|
||||||
|
"索马里": "SO",
|
||||||
|
"美国": "US",
|
||||||
|
"马尔代夫": "MV",
|
||||||
|
"列支敦士登": "LI",
|
||||||
|
"科摩罗": "KM",
|
||||||
|
"百慕达群岛": "BM",
|
||||||
|
"不丹": "BT",
|
||||||
|
"朝鲜": "KP",
|
||||||
|
"莫桑比克": "MZ",
|
||||||
|
"印度尼西亚, 印尼": "ID",
|
||||||
|
"也门": "YE",
|
||||||
|
"刚果-布拉柴维尔": "CG",
|
||||||
|
"乌拉圭": "UY",
|
||||||
|
"圣赫勒拿-阿森松和特里斯坦-达库尼亚": "SH",
|
||||||
|
"尼泊尔": "NP",
|
||||||
|
"多米尼克": "DM",
|
||||||
|
"马耳他": "MT",
|
||||||
|
"阿尔及利亚": "DZ",
|
||||||
|
"卡塔尔": "QA",
|
||||||
|
"赞比亚": "ZM",
|
||||||
|
"缅甸": "MM",
|
||||||
|
"卢森堡": "LU",
|
||||||
|
"斐济": "FJ",
|
||||||
|
"西班牙": "ES",
|
||||||
|
"乌干达": "UG",
|
||||||
|
"中国": "CN",
|
||||||
|
"中国香港": "HK",
|
||||||
|
"中国台湾": "TW",
|
||||||
|
"china": "CN"
|
||||||
|
}
|
2550
resource/datasets/map_filename.json
Normal file
2550
resource/datasets/map_filename.json
Normal file
File diff suppressed because it is too large
Load Diff
1
resource/render/__init__.py
Normal file
1
resource/render/__init__.py
Normal file
@ -0,0 +1 @@
|
|||||||
|
from .snapshot import make_snapshot
|
62
resource/render/display.py
Normal file
62
resource/render/display.py
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
from ..types import Optional, Sequence, Union
|
||||||
|
|
||||||
|
|
||||||
|
class HTML:
|
||||||
|
def __init__(self, data: Optional[str] = None):
|
||||||
|
self.data = data
|
||||||
|
|
||||||
|
def _repr_html_(self):
|
||||||
|
return self.data
|
||||||
|
|
||||||
|
def __html__(self):
|
||||||
|
return self._repr_html_()
|
||||||
|
|
||||||
|
|
||||||
|
_lib_t1 = """new Promise(function(resolve, reject) {
|
||||||
|
var script = document.createElement("script");
|
||||||
|
script.onload = resolve;
|
||||||
|
script.onerror = reject;
|
||||||
|
script.src = "%s";
|
||||||
|
document.head.appendChild(script);
|
||||||
|
}).then(() => {
|
||||||
|
"""
|
||||||
|
|
||||||
|
_lib_t2 = """
|
||||||
|
});"""
|
||||||
|
|
||||||
|
_css_t = """var link = document.createElement("link");
|
||||||
|
link.ref = "stylesheet";
|
||||||
|
link.type = "text/css";
|
||||||
|
link.href = "%s";
|
||||||
|
document.head.appendChild(link);
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
class Javascript:
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
data: Optional[str] = None,
|
||||||
|
lib: Optional[Union[str, Sequence]] = None,
|
||||||
|
css: Optional[Union[str, Sequence]] = None,
|
||||||
|
):
|
||||||
|
if isinstance(lib, str):
|
||||||
|
lib = [lib]
|
||||||
|
elif lib is None:
|
||||||
|
lib = []
|
||||||
|
if isinstance(css, str):
|
||||||
|
css = [css]
|
||||||
|
elif css is None:
|
||||||
|
css = []
|
||||||
|
self.lib = lib
|
||||||
|
self.css = css
|
||||||
|
self.data = data or ""
|
||||||
|
|
||||||
|
def _repr_javascript_(self):
|
||||||
|
r = ""
|
||||||
|
for c in self.css:
|
||||||
|
r += _css_t % c
|
||||||
|
for d in self.lib:
|
||||||
|
r += _lib_t1 % d
|
||||||
|
r += self.data
|
||||||
|
r += _lib_t2 * len(self.lib)
|
||||||
|
return r
|
121
resource/render/engine.py
Normal file
121
resource/render/engine.py
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
import os
|
||||||
|
|
||||||
|
try:
|
||||||
|
from collections.abc import Iterable
|
||||||
|
except ImportError:
|
||||||
|
from collections import Iterable
|
||||||
|
|
||||||
|
from jinja2 import Environment
|
||||||
|
|
||||||
|
from ..commons import utils
|
||||||
|
from ..datasets import EXTRA, FILENAMES
|
||||||
|
from ..globals import CurrentConfig, NotebookType
|
||||||
|
from ..types import Any, Optional
|
||||||
|
from .display import HTML, Javascript
|
||||||
|
|
||||||
|
|
||||||
|
def write_utf8_html_file(file_name: str, html_content: str):
|
||||||
|
with open(file_name, "w+", encoding="utf-8") as html_file:
|
||||||
|
html_file.write(html_content)
|
||||||
|
|
||||||
|
|
||||||
|
class RenderEngine:
|
||||||
|
def __init__(self, env: Optional[Environment] = None):
|
||||||
|
self.env = env or CurrentConfig.GLOBAL_ENV
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def generate_js_link(chart: Any) -> Any:
|
||||||
|
if not chart.js_host:
|
||||||
|
chart.js_host = CurrentConfig.ONLINE_HOST
|
||||||
|
links = []
|
||||||
|
for dep in chart.js_dependencies.items:
|
||||||
|
# TODO: if?
|
||||||
|
if dep.startswith("https://api.map.baidu.com"):
|
||||||
|
links.append(dep)
|
||||||
|
if dep in FILENAMES:
|
||||||
|
f, ext = FILENAMES[dep]
|
||||||
|
links.append("{}{}.{}".format(chart.js_host, f, ext))
|
||||||
|
else:
|
||||||
|
for url, files in EXTRA.items():
|
||||||
|
if dep in files:
|
||||||
|
f, ext = files[dep]
|
||||||
|
links.append("{}{}.{}".format(url, f, ext))
|
||||||
|
break
|
||||||
|
chart.dependencies = links
|
||||||
|
return chart
|
||||||
|
|
||||||
|
def render_chart_to_file(self, template_name: str, chart: Any, path: str, **kwargs):
|
||||||
|
"""
|
||||||
|
Render a chart or page to local html files.
|
||||||
|
|
||||||
|
:param chart: A Chart or Page object
|
||||||
|
:param path: The destination file which the html code write to
|
||||||
|
:param template_name: The name of template file.
|
||||||
|
"""
|
||||||
|
tpl = self.env.get_template(template_name)
|
||||||
|
html = utils.replace_placeholder(
|
||||||
|
tpl.render(chart=self.generate_js_link(chart), **kwargs)
|
||||||
|
)
|
||||||
|
write_utf8_html_file(path, html)
|
||||||
|
|
||||||
|
def render_chart_to_template(self, template_name: str, chart: Any, **kwargs) -> str:
|
||||||
|
tpl = self.env.get_template(template_name)
|
||||||
|
return utils.replace_placeholder(
|
||||||
|
tpl.render(chart=self.generate_js_link(chart), **kwargs)
|
||||||
|
)
|
||||||
|
|
||||||
|
def render_chart_to_notebook(self, template_name: str, **kwargs) -> str:
|
||||||
|
tpl = self.env.get_template(template_name)
|
||||||
|
return utils.replace_placeholder(tpl.render(**kwargs))
|
||||||
|
|
||||||
|
|
||||||
|
def render(
|
||||||
|
chart, path: str, template_name: str, env: Optional[Environment], **kwargs
|
||||||
|
) -> str:
|
||||||
|
RenderEngine(env).render_chart_to_file(
|
||||||
|
template_name=template_name, chart=chart, path=path, **kwargs
|
||||||
|
)
|
||||||
|
return os.path.abspath(path)
|
||||||
|
|
||||||
|
|
||||||
|
def render_embed(
|
||||||
|
chart, template_name: str, env: Optional[Environment], **kwargs
|
||||||
|
) -> str:
|
||||||
|
return RenderEngine(env).render_chart_to_template(
|
||||||
|
template_name=template_name, chart=chart, **kwargs
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def render_notebook(self, notebook_template, lab_template):
|
||||||
|
instance = self if isinstance(self, Iterable) else (self,)
|
||||||
|
if CurrentConfig.NOTEBOOK_TYPE == NotebookType.JUPYTER_NOTEBOOK:
|
||||||
|
require_config = utils.produce_require_dict(self.js_dependencies, self.js_host)
|
||||||
|
return HTML(
|
||||||
|
RenderEngine().render_chart_to_notebook(
|
||||||
|
template_name=notebook_template,
|
||||||
|
charts=instance,
|
||||||
|
config_items=require_config["config_items"],
|
||||||
|
libraries=require_config["libraries"],
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
if CurrentConfig.NOTEBOOK_TYPE == NotebookType.JUPYTER_LAB:
|
||||||
|
return HTML(
|
||||||
|
RenderEngine().render_chart_to_notebook(
|
||||||
|
template_name=lab_template, charts=instance
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
if CurrentConfig.NOTEBOOK_TYPE == NotebookType.NTERACT:
|
||||||
|
return HTML(self.render_embed())
|
||||||
|
|
||||||
|
if CurrentConfig.NOTEBOOK_TYPE == NotebookType.ZEPPELIN:
|
||||||
|
print("%html " + self.render_embed())
|
||||||
|
|
||||||
|
|
||||||
|
def load_javascript(chart):
|
||||||
|
scripts = []
|
||||||
|
for dep in chart.js_dependencies.items:
|
||||||
|
f, ext = FILENAMES[dep]
|
||||||
|
scripts.append("{}{}.{}".format(CurrentConfig.ONLINE_HOST, f, ext))
|
||||||
|
return Javascript(lib=scripts)
|
99
resource/render/snapshot.py
Normal file
99
resource/render/snapshot.py
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
import base64
|
||||||
|
import codecs
|
||||||
|
import logging
|
||||||
|
import os
|
||||||
|
from io import BytesIO
|
||||||
|
|
||||||
|
from ..types import Any
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
PNG_FORMAT = "png"
|
||||||
|
JPG_FORMAT = "jpeg"
|
||||||
|
GIF_FORMAT = "gif"
|
||||||
|
PDF_FORMAT = "pdf"
|
||||||
|
SVG_FORMAT = "svg"
|
||||||
|
EPS_FORMAT = "eps"
|
||||||
|
B64_FORMAT = "base64"
|
||||||
|
|
||||||
|
|
||||||
|
def make_snapshot(
|
||||||
|
engine: Any,
|
||||||
|
file_name: str,
|
||||||
|
output_name: str,
|
||||||
|
delay: float = 2,
|
||||||
|
pixel_ratio: int = 2,
|
||||||
|
is_remove_html: bool = False,
|
||||||
|
**kwargs,
|
||||||
|
):
|
||||||
|
logger.info("Generating file ...")
|
||||||
|
file_type = output_name.split(".")[-1]
|
||||||
|
|
||||||
|
content = engine.make_snapshot(
|
||||||
|
html_path=file_name,
|
||||||
|
file_type=file_type,
|
||||||
|
delay=delay,
|
||||||
|
pixel_ratio=pixel_ratio,
|
||||||
|
**kwargs,
|
||||||
|
)
|
||||||
|
if file_type in [SVG_FORMAT, B64_FORMAT]:
|
||||||
|
save_as_text(content, output_name)
|
||||||
|
else:
|
||||||
|
# pdf, gif, png, jpeg
|
||||||
|
content_array = content.split(",")
|
||||||
|
if len(content_array) != 2:
|
||||||
|
raise OSError(content_array)
|
||||||
|
|
||||||
|
image_data = decode_base64(content_array[1])
|
||||||
|
|
||||||
|
if file_type in [PDF_FORMAT, GIF_FORMAT, EPS_FORMAT]:
|
||||||
|
save_as(image_data, output_name, file_type)
|
||||||
|
elif file_type in [PNG_FORMAT, JPG_FORMAT]:
|
||||||
|
save_as_png(image_data, output_name)
|
||||||
|
else:
|
||||||
|
raise TypeError(f"Not supported file type '{file_type}'")
|
||||||
|
|
||||||
|
if "/" not in output_name:
|
||||||
|
output_name = os.path.join(os.getcwd(), output_name)
|
||||||
|
|
||||||
|
if is_remove_html and not file_name.startswith("http"):
|
||||||
|
os.unlink(file_name)
|
||||||
|
logger.info(f"File saved in {output_name}")
|
||||||
|
|
||||||
|
|
||||||
|
def decode_base64(data: str) -> bytes:
|
||||||
|
"""Decode base64, padding being optional.
|
||||||
|
|
||||||
|
:param data: Base64 data as an ASCII byte string
|
||||||
|
:returns: The decoded byte string.
|
||||||
|
"""
|
||||||
|
missing_padding = len(data) % 4
|
||||||
|
if missing_padding != 0:
|
||||||
|
data += "=" * (4 - missing_padding)
|
||||||
|
return base64.decodebytes(data.encode("utf-8"))
|
||||||
|
|
||||||
|
|
||||||
|
def save_as_png(image_data: bytes, output_name: str):
|
||||||
|
with open(output_name, "wb") as f:
|
||||||
|
f.write(image_data)
|
||||||
|
|
||||||
|
|
||||||
|
def save_as_text(image_data: str, output_name: str):
|
||||||
|
with codecs.open(output_name, "w", encoding="utf-8") as f:
|
||||||
|
f.write(image_data)
|
||||||
|
|
||||||
|
|
||||||
|
def save_as(image_data: bytes, output_name: str, file_type: str):
|
||||||
|
try:
|
||||||
|
from PIL import Image
|
||||||
|
|
||||||
|
m = Image.open(BytesIO(image_data))
|
||||||
|
m.load()
|
||||||
|
color = (255, 255, 255)
|
||||||
|
b = Image.new("RGB", m.size, color)
|
||||||
|
# BUG for Mac:
|
||||||
|
# b.paste(m, mask=m.split()[3])
|
||||||
|
b.paste(m)
|
||||||
|
b.save(output_name, file_type, quality=100)
|
||||||
|
except ModuleNotFoundError:
|
||||||
|
raise Exception(f"Please install PIL for {file_type} image type")
|
13
resource/render/templates/components.html
Normal file
13
resource/render/templates/components.html
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
{% import 'macro' as macro %}
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>{{ chart.page_title }}</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
{{ macro.gen_components_content(chart) }}
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
231
resource/render/templates/macro
Normal file
231
resource/render/templates/macro
Normal file
@ -0,0 +1,231 @@
|
|||||||
|
{%- macro render_chart_content(c) -%}
|
||||||
|
<div id="{{ c.chart_id }}" class="chart-container" style="width:{{ c.width }}; height:{{ c.height }}; {{ c.horizontal_center }}"></div>
|
||||||
|
{% if c._geo_json_name and c._geo_json %}
|
||||||
|
<script>
|
||||||
|
(function (root, factory) {
|
||||||
|
if (typeof define === 'function' && define.amd) {
|
||||||
|
// AMD. Register as an anonymous module.
|
||||||
|
define(['exports', 'echarts'], factory);
|
||||||
|
} else if (typeof exports === 'object' && typeof exports.nodeName !== 'string') {
|
||||||
|
// CommonJS
|
||||||
|
factory(exports, require('echarts'));
|
||||||
|
} else {
|
||||||
|
// Browser globals
|
||||||
|
factory({}, root.echarts);
|
||||||
|
}
|
||||||
|
}(this, function (exports, echarts) {
|
||||||
|
var log = function (msg) {
|
||||||
|
if (typeof console !== 'undefined') {
|
||||||
|
console && console.error && console.error(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!echarts) {
|
||||||
|
log('ECharts is not Loaded');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!echarts.registerMap) {
|
||||||
|
log('ECharts Map is not loaded')
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
echarts.registerMap('{{ c._geo_json_name }}', {{ c._geo_json }});
|
||||||
|
}));
|
||||||
|
</script>
|
||||||
|
{% endif %}
|
||||||
|
<script>
|
||||||
|
{% if c._is_tab_chart %}
|
||||||
|
document.getElementById('{{ c.chart_id }}').style.width = document.getElementById('{{ c.chart_id }}').parentNode.clientWidth + 'px';
|
||||||
|
{% endif %}
|
||||||
|
var chart_{{ c.chart_id }} = echarts.init(
|
||||||
|
document.getElementById('{{ c.chart_id }}'), '{{ c.theme }}', {renderer: '{{ c.renderer }}'});
|
||||||
|
{% for js in c.js_functions.items %}
|
||||||
|
{{ js }}
|
||||||
|
{% endfor %}
|
||||||
|
var option_{{ c.chart_id }} = {{ c.json_contents }};
|
||||||
|
chart_{{ c.chart_id }}.setOption(option_{{ c.chart_id }});
|
||||||
|
{% if c._is_geo_chart %}
|
||||||
|
var bmap = chart_{{ c.chart_id }}.getModel().getComponent('bmap').getBMap();
|
||||||
|
{% if c.bmap_js_functions %}
|
||||||
|
{% for fn in c.bmap_js_functions.items %}
|
||||||
|
{{ fn }}
|
||||||
|
{% endfor %}
|
||||||
|
{% endif %}
|
||||||
|
{% endif %}
|
||||||
|
{% if c.width.endswith('%') %}
|
||||||
|
window.addEventListener('resize', function(){
|
||||||
|
chart_{{ c.chart_id }}.resize();
|
||||||
|
})
|
||||||
|
{% endif %}
|
||||||
|
</script>
|
||||||
|
{%- endmacro %}
|
||||||
|
|
||||||
|
{%- macro render_notebook_charts(charts, libraries) -%}
|
||||||
|
<script>
|
||||||
|
require([{{ libraries | join(', ') }}], function(echarts) {
|
||||||
|
{% for c in charts %}
|
||||||
|
{% if c._component_type not in ("table", "image") %}
|
||||||
|
var chart_{{ c.chart_id }} = echarts.init(
|
||||||
|
document.getElementById('{{ c.chart_id }}'), '{{ c.theme }}', {renderer: '{{ c.renderer }}'});
|
||||||
|
{% for js in c.js_functions.items %}
|
||||||
|
{{ js }}
|
||||||
|
{% endfor %}
|
||||||
|
var option_{{ c.chart_id }} = {{ c.json_contents }};
|
||||||
|
chart_{{ c.chart_id }}.setOption(option_{{ c.chart_id }});
|
||||||
|
{% if c._is_geo_chart %}
|
||||||
|
var bmap = chart_{{ c.chart_id }}.getModel().getComponent('bmap').getBMap();
|
||||||
|
bmap.addControl(new BMap.MapTypeControl());
|
||||||
|
{% endif %}
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
{%- endmacro %}
|
||||||
|
|
||||||
|
{%- macro render_chart_dependencies(c) -%}
|
||||||
|
{% for dep in c.dependencies %}
|
||||||
|
<script type="text/javascript" src="{{ dep }}"></script>
|
||||||
|
{% endfor %}
|
||||||
|
{%- endmacro %}
|
||||||
|
|
||||||
|
{%- macro render_chart_css(c) -%}
|
||||||
|
{% for dep in c.css_libs %}
|
||||||
|
<link rel="stylesheet" href="{{ dep }}">
|
||||||
|
{% endfor %}
|
||||||
|
{%- endmacro %}
|
||||||
|
|
||||||
|
{%- macro display_tablinks(chart) -%}
|
||||||
|
<div class="tab">
|
||||||
|
{% for c in chart %}
|
||||||
|
<button class="tablinks" onclick="showChart(event, '{{ c.chart_id }}')">{{ c.tab_name }}</button>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
{%- endmacro %}
|
||||||
|
|
||||||
|
{%- macro switch_tabs() -%}
|
||||||
|
<script>
|
||||||
|
(function() {
|
||||||
|
containers = document.getElementsByClassName("chart-container");
|
||||||
|
if(containers.length > 0) {
|
||||||
|
containers[0].style.display = "block";
|
||||||
|
}
|
||||||
|
})()
|
||||||
|
|
||||||
|
function showChart(evt, chartID) {
|
||||||
|
let containers = document.getElementsByClassName("chart-container");
|
||||||
|
for (let i = 0; i < containers.length; i++) {
|
||||||
|
containers[i].style.display = "none";
|
||||||
|
}
|
||||||
|
|
||||||
|
let tablinks = document.getElementsByClassName("tablinks");
|
||||||
|
for (let i = 0; i < tablinks.length; i++) {
|
||||||
|
tablinks[i].className = "tablinks";
|
||||||
|
}
|
||||||
|
|
||||||
|
document.getElementById(chartID).style.display = "block";
|
||||||
|
evt.currentTarget.className += " active";
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
{%- endmacro %}
|
||||||
|
|
||||||
|
{%- macro generate_tab_css() %}
|
||||||
|
<style>
|
||||||
|
.tab {
|
||||||
|
overflow: hidden;
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
background-color: #f1f1f1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab button {
|
||||||
|
background-color: inherit;
|
||||||
|
float: left;
|
||||||
|
border: none;
|
||||||
|
outline: none;
|
||||||
|
cursor: pointer;
|
||||||
|
padding: 12px 16px;
|
||||||
|
transition: 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab button:hover {
|
||||||
|
background-color: #ddd;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab button.active {
|
||||||
|
background-color: #ccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chart-container {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chart-container:nth-child(n+2) {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
{%- endmacro %}
|
||||||
|
|
||||||
|
{%- macro gen_components_content(chart) %}
|
||||||
|
{% if chart._component_type == "table" %}
|
||||||
|
<style>
|
||||||
|
.fl-table {
|
||||||
|
margin: 20px;
|
||||||
|
border-radius: 5px;
|
||||||
|
font-size: 12px;
|
||||||
|
border: none;
|
||||||
|
border-collapse: collapse;
|
||||||
|
max-width: 100%;
|
||||||
|
white-space: nowrap;
|
||||||
|
word-break: keep-all;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fl-table th {
|
||||||
|
text-align: left;
|
||||||
|
font-size: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fl-table tr {
|
||||||
|
display: table-row;
|
||||||
|
vertical-align: inherit;
|
||||||
|
border-color: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fl-table tr:hover td {
|
||||||
|
background: #00d1b2;
|
||||||
|
color: #F8F8F8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fl-table td, .fl-table th {
|
||||||
|
border-style: none;
|
||||||
|
border-top: 1px solid #dbdbdb;
|
||||||
|
border-left: 1px solid #dbdbdb;
|
||||||
|
border-bottom: 3px solid #dbdbdb;
|
||||||
|
border-right: 1px solid #dbdbdb;
|
||||||
|
padding: .5em .55em;
|
||||||
|
font-size: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fl-table td {
|
||||||
|
border-style: none;
|
||||||
|
font-size: 15px;
|
||||||
|
vertical-align: center;
|
||||||
|
border-bottom: 1px solid #dbdbdb;
|
||||||
|
border-left: 1px solid #dbdbdb;
|
||||||
|
border-right: 1px solid #dbdbdb;
|
||||||
|
height: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fl-table tr:nth-child(even) {
|
||||||
|
background: #F8F8F8;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<div id="{{ chart.chart_id }}" class="chart-container" style="">
|
||||||
|
<p class="title" {{ chart.title_opts.title_style }}> {{ chart.title_opts.title }}</p>
|
||||||
|
<p class="subtitle" {{ chart.title_opts.subtitle_style }}> {{ chart.title_opts.subtitle }}</p>
|
||||||
|
{{ chart.html_content }}
|
||||||
|
</div>
|
||||||
|
{% elif chart._component_type == "image" %}
|
||||||
|
<div id="{{ chart.chart_id }}" class="chart-container" style="">
|
||||||
|
<p class="title" {{ chart.title_opts.title_style }}> {{ chart.title_opts.title }}</p>
|
||||||
|
<p class="subtitle" {{ chart.title_opts.subtitle_style }}> {{ chart.title_opts.subtitle }}</p>
|
||||||
|
<img {{ chart.html_content }}/>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
{%- endmacro %}
|
5
resource/render/templates/nb_components.html
Normal file
5
resource/render/templates/nb_components.html
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
{% import 'macro' as macro %}
|
||||||
|
|
||||||
|
{% for chart in charts %}
|
||||||
|
{{ macro.gen_components_content(chart) }}
|
||||||
|
{% endfor %}
|
49
resource/render/templates/nb_jupyter_globe.html
Normal file
49
resource/render/templates/nb_jupyter_globe.html
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
<script>
|
||||||
|
require.config({
|
||||||
|
paths: {
|
||||||
|
{{ config_items | join(', ') }}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{% for chart in charts %}
|
||||||
|
<div id="{{ chart.chart_id }}" style="width:{{ chart.width }}; height:{{ chart.height }};"></div>
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
|
||||||
|
<script>
|
||||||
|
require([{{ libraries | join(', ') }}], function(echarts) {
|
||||||
|
{% for c in charts %}
|
||||||
|
var canvas_{{ c.chart_id }} = document.createElement('canvas');
|
||||||
|
var mapChart_{{ c.chart_id }} = echarts.init(
|
||||||
|
canvas_{{ c.chart_id }}, '{{ c.theme }}', {width: 4096, height: 2048, renderer: '{{ c.renderer }}'});
|
||||||
|
var mapOption_{{ c.chart_id }} = {{ c.json_contents }};
|
||||||
|
mapChart_{{ c.chart_id }}.setOption(mapOption_{{ c.chart_id }});
|
||||||
|
var chart_{{ c.chart_id }} = echarts.init(
|
||||||
|
document.getElementById('{{ c.chart_id }}'), '{{ c.theme }}', {renderer: '{{ c.renderer }}'});
|
||||||
|
{% for js in c.js_functions.items %}
|
||||||
|
{{ js }}
|
||||||
|
{% endfor %}
|
||||||
|
var option_{{ c.chart_id }} = {
|
||||||
|
"globe": {
|
||||||
|
"show": true,
|
||||||
|
"baseTexture": mapChart_{{ c.chart_id }},
|
||||||
|
shading: 'lambert',
|
||||||
|
light: {
|
||||||
|
ambient: {
|
||||||
|
intensity: 0.6
|
||||||
|
},
|
||||||
|
main: {
|
||||||
|
intensity: 0.2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}};
|
||||||
|
chart_{{ c.chart_id }}.setOption(option_{{ c.chart_id }});
|
||||||
|
{% endfor %}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
</script>
|
16
resource/render/templates/nb_jupyter_lab.html
Normal file
16
resource/render/templates/nb_jupyter_lab.html
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
{% import 'macro' as macro %}
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
{% for chart in charts %}
|
||||||
|
{% if chart._component_type in ("table", "image") %}
|
||||||
|
{{ macro.gen_components_content(chart) }}
|
||||||
|
{% else %}
|
||||||
|
{{ macro.render_chart_content(chart) }}
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
</body>
|
||||||
|
</html>
|
20
resource/render/templates/nb_jupyter_lab_tab.html
Normal file
20
resource/render/templates/nb_jupyter_lab_tab.html
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
{% import 'macro' as macro %}
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
{{ macro.generate_tab_css() }}
|
||||||
|
{{ macro.display_tablinks(charts) }}
|
||||||
|
|
||||||
|
{% for chart in charts %}
|
||||||
|
{% if chart._component_type in ("table", "image") %}
|
||||||
|
{{ macro.gen_components_content(chart) }}
|
||||||
|
{% else %}
|
||||||
|
{{ macro.render_chart_content(chart) }}
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
{{ macro.switch_tabs() }}
|
||||||
|
</body>
|
||||||
|
</html>
|
21
resource/render/templates/nb_jupyter_notebook.html
Normal file
21
resource/render/templates/nb_jupyter_notebook.html
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
{% import 'macro' as macro %}
|
||||||
|
|
||||||
|
<script>
|
||||||
|
require.config({
|
||||||
|
paths: {
|
||||||
|
{{ config_items | join(', ') }}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{% for chart in charts %}
|
||||||
|
{% if chart._component_type in ("table", "image") %}
|
||||||
|
{{ macro.gen_components_content(chart) }}
|
||||||
|
{% else %}
|
||||||
|
<div id="{{ chart.chart_id }}" style="width:{{ chart.width }}; height:{{ chart.height }};"></div>
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
{{ macro.render_notebook_charts(charts, libraries) }}
|
26
resource/render/templates/nb_jupyter_notebook_tab.html
Normal file
26
resource/render/templates/nb_jupyter_notebook_tab.html
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
{% import 'macro' as macro %}
|
||||||
|
|
||||||
|
<script>
|
||||||
|
require.config({
|
||||||
|
paths: {
|
||||||
|
{{ config_items | join(', ') }}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{{ macro.generate_tab_css() }}
|
||||||
|
{{ macro.display_tablinks(charts) }}
|
||||||
|
|
||||||
|
{% for chart in charts %}
|
||||||
|
{% if chart._component_type in ("table", "image") %}
|
||||||
|
{{ macro.gen_components_content(chart) }}
|
||||||
|
{% else %}
|
||||||
|
<div id="{{ chart.chart_id }}" class="chart-container"
|
||||||
|
style="width:{{ chart.width }}; height:{{ chart.height }};"></div>
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
{{ macro.render_notebook_charts(charts, libraries) }}
|
||||||
|
{{ macro.switch_tabs() }}
|
13
resource/render/templates/nb_nteract.html
Normal file
13
resource/render/templates/nb_nteract.html
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
{% import 'macro' as macro %}
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
{{ macro.render_chart_dependencies(chart) }}
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
{% for c in chart %}
|
||||||
|
{{ macro.render_chart_content(c) }}
|
||||||
|
{% endfor %}
|
||||||
|
</body>
|
||||||
|
</html>
|
12
resource/render/templates/simple_chart.html
Normal file
12
resource/render/templates/simple_chart.html
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
{% import 'macro' as macro %}
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>{{ chart.page_title }}</title>
|
||||||
|
{{ macro.render_chart_dependencies(chart) }}
|
||||||
|
</head>
|
||||||
|
<body {% if chart.fill_bg %}style="background-color: {{ chart.bg_color }}" {% endif %}>
|
||||||
|
{{ macro.render_chart_content(chart) }}
|
||||||
|
</body>
|
||||||
|
</html>
|
42
resource/render/templates/simple_globe.html
Normal file
42
resource/render/templates/simple_globe.html
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
{% import 'macro' as macro %}
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>{{ chart.page_title }}</title>
|
||||||
|
{{ macro.render_chart_dependencies(chart) }}
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="{{ chart.chart_id }}" style="width:{{ chart.width }}; height:{{ chart.height }};"></div>
|
||||||
|
<script>
|
||||||
|
var canvas_{{ chart.chart_id }} = document.createElement('canvas');
|
||||||
|
var mapChart_{{ chart.chart_id }} = echarts.init(
|
||||||
|
canvas_{{ chart.chart_id }}, '{{ chart.theme }}', {width: 4096, height: 2048, renderer: '{{ chart.renderer }}'});
|
||||||
|
{% for js in chart.js_functions.items %}
|
||||||
|
{{ js }}
|
||||||
|
{% endfor %}
|
||||||
|
var mapOption_{{ chart.chart_id }} = {{ chart.json_contents }};
|
||||||
|
mapChart_{{ chart.chart_id }}.setOption(mapOption_{{ chart.chart_id }});
|
||||||
|
|
||||||
|
var chart_{{ chart.chart_id }} = echarts.init(
|
||||||
|
document.getElementById('{{ chart.chart_id }}'), '{{ chart.theme }}', {renderer: '{{ chart.renderer }}'});
|
||||||
|
var options_{{ chart.chart_id }} = {
|
||||||
|
"globe": {
|
||||||
|
"show": true,
|
||||||
|
"baseTexture": mapChart_{{ chart.chart_id }},
|
||||||
|
shading: 'lambert',
|
||||||
|
light: {
|
||||||
|
ambient: {
|
||||||
|
intensity: 0.6
|
||||||
|
},
|
||||||
|
main: {
|
||||||
|
intensity: 0.2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}};
|
||||||
|
chart_{{ chart.chart_id }}.setOption(options_{{ chart.chart_id }});
|
||||||
|
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
34
resource/render/templates/simple_page.html
Normal file
34
resource/render/templates/simple_page.html
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
{% import 'macro' as macro %}
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>{{ chart.page_title }}</title>
|
||||||
|
{{ macro.render_chart_dependencies(chart) }}
|
||||||
|
{{ macro.render_chart_css(chart) }}
|
||||||
|
</head>
|
||||||
|
<body {% if chart.page_border_color !='' %}style="background-color: {{ chart.page_border_color }}" {% endif %}>
|
||||||
|
<style>.box { {{ chart.layout }} } </style>
|
||||||
|
{% if chart.download_button %}
|
||||||
|
<button onclick="downloadCfg()">Save Config</button>
|
||||||
|
{% endif %}
|
||||||
|
<div class="box">
|
||||||
|
{% for c in chart %}
|
||||||
|
{% if c._component_type in ("table", "image") %}
|
||||||
|
{{ macro.gen_components_content(c) }}
|
||||||
|
{% else %}
|
||||||
|
{{ macro.render_chart_content(c) }}
|
||||||
|
{% endif %}
|
||||||
|
{% for _ in range(chart.page_interval) %}
|
||||||
|
{% if chart.remove_br is false %}<br/>{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
<script>
|
||||||
|
{% for js in chart.js_functions.items %}
|
||||||
|
{{ js }}
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
36
resource/render/templates/simple_tab.html
Normal file
36
resource/render/templates/simple_tab.html
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
{% import 'macro' as macro %}
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>{{ chart.page_title }}</title>
|
||||||
|
{{ macro.render_chart_dependencies(chart) }}
|
||||||
|
{{ macro.render_chart_css(chart) }}
|
||||||
|
</head>
|
||||||
|
<body {% if chart.bg_color !='' %}style="background-color: {{ chart.bg_color }}" {% endif %}>
|
||||||
|
{% if chart.use_custom_tab_css is not true %}
|
||||||
|
{{ macro.generate_tab_css() }}
|
||||||
|
{% else %}
|
||||||
|
<style>{{ chart.tab_custom_css }}</style>
|
||||||
|
{% endif %}
|
||||||
|
{{ macro.display_tablinks(chart) }}
|
||||||
|
|
||||||
|
<div class="box">
|
||||||
|
{% for c in chart %}
|
||||||
|
{% if c._component_type in ("table", "image") %}
|
||||||
|
{{ macro.gen_components_content(c) }}
|
||||||
|
{% else %}
|
||||||
|
{{ macro.render_chart_content(c) }}
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
{% for js in chart.js_functions.items %}
|
||||||
|
{{ js }}
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
{{ macro.switch_tabs() }}
|
||||||
|
</body>
|
||||||
|
</html>
|
Loading…
Reference in New Issue
Block a user