Skip to content

Instantly share code, notes, and snippets.

@MaxMorais
Last active July 20, 2017 00:23
Show Gist options
  • Save MaxMorais/54513362fd7698a9841b2079a31070a4 to your computer and use it in GitHub Desktop.
Save MaxMorais/54513362fd7698a9841b2079a31070a4 to your computer and use it in GitHub Desktop.
[
{
"_type": "div",
"_class": "installation-process-step",
"#text": "Installation Progress: Step 2 of 5"
},
{
"_type": "div",
"_class": "clear"
},
{
"_type": "div",
"_class": "text-center",
"#text": "Database Configuration"
},
{
"_type": "div",
"_class": "clear"
},
{
"_type": "div",
"_class": "explanation text-medium dump-down-most",
"#text": "Books will automatically configure your database. Before proceeding, create your database and database user.<br>If you need assistance, check the README.md file for step by step database and database user creation instructions."
},
{
"_type": "form",
"method": "POST",
"children": [
{
"_type": "hidden",
"type": "type",
"name": "install-step",
"value": "2"
},
{
"_type": "div",
"_class": "explanation form text-medium bump-down-most",
"children": [
{
"_type": "div",
"_class": "text-medium",
"#text": "Please enter your MySQL database details."
},
{
"_type": "div",
"_class": "left-right-row dump-down-more",
"children": [
{
"_type": "span",
"_class": "left",
"#text": "Database Type"
},
{
"_type": "span",
"_class": "right",
"children": [
{
"_type": "select",
"name": "type"
}
]
}
]
},
{
"_type": "div",
"_class": "left-right-row bump-down-more",
"children": [
{
"_type": "span",
"_class": "left",
"#text": "Hostname"
},
{
"_type": "span",
"_class": "right",
"children": [
{
"_type": "input",
"type": "text",
"name": "database_hostname",
"placeholder": "i.e. localhost or 192.168.0.1:1337"
}
]
}
]
},
{
"_type": "div",
"_class": "left-right-row bump-down-more",
"children": [
{
"_type": "span",
"_class": "left",
"#text": "Database Name"
},
{
"_type": "span",
"_class": "right",
"children": [
{
"_type": "input",
"type": "text",
"name": "database_database",
"placeholder": "i.e. beans"
}
]
}
]
},
{
"_type": "div",
"_class": "left-right-row bump-down-more",
"children": [
{
"_type": "span",
"_class": "left",
"#text": "Username"
},
{
"_type": "span",
"_class": "right",
"children": [
{
"_type": "input",
"type": "text",
"name": "database_username"
}
]
}
]
},
{
"_type": "div",
"_class": "left-right-row bump-down-more",
"children": [
{
"_type": "span",
"_class": "left",
"#text": "Password"
},
{
"_type": "span",
"_class": "right",
"children": [
{
"_type": "input",
"type": "password",
"name": "database_password"
}
]
}
]
}
]
},
{
"_type": "div",
"_class": "explanation text-small bump-down-most",
"children": [
{
"_type": "span",
"_class": "text-bold",
"#text": "Database Creation:"
}
],
"#text": "The README.md file has a section titled &quot;MySQL&quote; that provides instructions on how to create a database and user account for Books."
},
{
"_type": "div",
"_class": "explanation text-center dump-down-most",
"children": [
{
"_type": "a",
"href": "#",
"class": "button process-step",
"onclick": "callback_process_step_clicked",
"#text": "Verify Database Information"
}
]
}
]
}
]
[
{
"_type": "div",
"_class": "intallation-process-step",
"#text": "Installation Progress: Getting Started"
},
{
"_type": "div",
"_class": "clear"
},
{
"_type": "h3",
"_class": "text-center",
"#text": "Thanks for choosing Books!"
},
{
"_type": "div",
"_class": "clear"
},
{
"_type": "div",
"_class": "explanation text-medium bump-down-most"
},
{
"_type": "div",
"_class": "explanation text-medium bump-down-most",
"children": [
{
"_type": "div",
"_class": "text-center text-bold",
"#text": "Important!"
},
{
"_type": "div",
"_class": "text-center",
"#text": "Have the following information available before starting the installation."
},
{
"_type": "br"
},
{
"_type": "ul",
"children": [
{
"_type": "li",
"#text": "Empty MySQL database user credentials"
},
{
"_type": "li",
"#text": "SMTP (email) connection information"
},
{
"_type": "li",
"#text": "File Access to the directory that Books will be located."
}
]
}
]
},
{
"_type": "div",
"_class": "explanation text-medium bump-down-most",
"children": [
{
"_type": "div",
"_class": "text-large text-center",
"#text": "Ready to go?"
},
{
"_type": "div",
"_class": "text-center",
"children": [
{
"_type": "a",
"_class": "button",
"href": "/install/check",
"#text": "Start Installation",
"onclick": "callback_button_click"
}
]
}
]
}
]
#-*- coding: utf-8 -*-
from __future__ import unicode_literals
from remi import gui
class JSONView(gui.Widget):
def __init__(self, *args, **kwargs):
super(JSONView, self).__init__(*args, **kwargs)
self.build_element(self.layout, self)
@property
def layout(self):
path = os.path.join(
os.path.dirname(__file__),
self.__class__.__name__ + '.json'
)
if os.path.exists(path):
with open(path, 'rb') as f:
content = json.load(f)
return content
return [{
"_type": "div",
"#text": "No layout file found at {0}".format(path)
}]
def build_element(self, element, parent):
for d in element:
# Verify if the element is an String, if yes check for the implementation handler
if isinstance(d, basestring):
if d.startswith('fn:'):
if hasattr(self, d[3:]):
fn = getattr(self, d[3:])
if callable(fn):
fn(d)
continue
# Verify if the element type have they own implementation handler
if "_type" in d:
fn = "_build_{0}_element".format(d["_type"])
if hasattr(self, fn):
fn = getattr(self, fn)
if callable(fn):
fn(d, parent)
continue
children = d.pop("children", []) # extract the children
class_names = d.pop("_class", "").split(" ") # extract the css classes
style = d.pop("style", {}) # extract the element style
events = [
(k, d.pop(k))
for k in d.keys() if k.startswith('on')
]
text = d.pop("#text", False) # extract the element text
# Build the widget constructor args
kwargs = {
k: d.pop(k).strip()
for k in ["_type", "id"] if k in d
}
# If the element has a class, append the first class as default class
if class_names:
kwargs['_class'] = class_names.pop(0)
# Build the widget
el = gui.Widget(**kwargs)
# Append any aditional class to the element
for class_name in class_names:
el.add_class(class_name)
# After the extraction of the common elements in the object
# any remaining value will be threat as an attribute
for k, v in d.items():
el.attributes[k] = v
# Append the element style
for s, v in style.items():
el.style[s] = v
# Append the element children
if children:
self.build_element(children, el)
# Append the text to the element at the last position
if text:
el.add_child("text", text)
# assign any input with a name
if kwargs.get("_type") == "input" and "name" in el.attributes:
attr = self._build_attribute_name(el.attributes['name'])
setattr(self, attr, el)
elif hasattr(self, 'as_attribute'):
if "_class" in kwargs and "." + kwargs["_class"] in self.as_attribute:
attr = self._build_attribute_name(kwargs["_class"])
setattr(self, attr, el)
elif "id" in kwargs and "#" + kwargs["id"] in self.as_attribute:
attr = self._build_attribute_name(kwargs["id"])
setattr(self, attr, el)
parent.append(el)
# attach any event listener
for event, callback in events:
setattr(self, event, self._build_event_handler(event))
setattr(self, 'set_{0}_listener'.format(event),
self._build_event_listener);
if hasattr(self, callback):
callback = getattr(self, listener)
else:
callback = self._build_event_callback(callback, event)
listener = getattr(self, 'set_{0}_listener'.format(event))
listener(callback)
def _build_attribute_name(self, s):
attr = str(s).lower().replace(" ", "_").replace("-", "")
if attr[0].isdigit():
attr = "_" + attr
if hasattr(self, attr):
count = 1
while hasattr(self, "{0}_{1}".format(attr, count)):
count += 1
attr = "{0}_{1}".format(attr, count)
return attr
@staticmethod
def _build_event_handler(event_name):
def handler(self, event):
print type(event)
print event
self.eventManager.propagate(event_name, (event,))
return handler
@staticmethod
def _build_event_callback(event_name, callback):
def callback(self, event):
fn = getattr(self, callback, None)
if callable(fn):
fn(event)
else:
print("""You must implement a callback in the class for the event `{event_name}` as:
def {callback}(self, event): ...
""".format(
event_name=event_name,
callback=callback
)
@staticmethod
def _build_event_listener(event_name):
def listener(self, callback, *userdata):
js = """
function pathSelector = function(node){
if (!node || !node.outerHTML) { return null; }
var path, name, parent, domSiblings, sibling, i, j;
while (node.parentElement){
name = node.localName;
if (!name) { break; }
name = name.toLowerCase();
parent = node.parentElement;
domSiblings = [];
if (parent.children && parent.children.length > 0){
j = parent.children.length;
for (; i < j; i++){
sibling = parent.children[i];
if (sibling.localName && sibling.localName.toLowerCase){
if (sibling.localName.toLowerCase() === name){
domSiblings.push(sibling);
}
}
}
}
if (domSiblings.length > 1){
name += ':eq(' + domSiblinds.indexOf(node) + ')';
}
path = name + (path ? '>' + path : '');
node = parent;
}
return path;
}
var params = {
'event': {
'eventName': e.toString(),
'altKey': e.altKey,
'bubbles': e.bubbles,
'button': e.button,
'buttons': e.buttons,
'cancelBubble': e.cancelBubble,
'cancelable': e.cancelable,
'clientY': e.clientY,
'clientX': e.clientX,
'composed': e.composed,
'ctrlKey': e.ctrlKey,
'currentTarget': e.currentTarget ? '#' + e.currentTarget.id : null,
'defaultPrevented': e.defaultPrevented,
'detail': e.detail,
'eventPhase': e.eventPhase,
'fromElement': e.fromElement ? '#' + e.fromElement.id : null,
'isTrusted': e.isTrusted,
'layerX': e.layerX,
'layerY': e.layerY,
'metaKey': e.metaKey,
'movementX': e.movementX,
'movementY': e.movementY,
'offsetX': e.offsetX,
'offsetY': e.offsetY,
'pageX': e.pageX,
'pageY': e.pageY,
'path': pathToSelector(e.path && e.path.length ? e.path[0] : null),
'relatedTarget': e.relatedTarget ? '#' + e.relatedTarget.id : null,
'returnValue': e.returnValue,
'screenX': e.screenX,
'screenY': e.screenY,
'shiftKey': e.shiftKey,
'sourceCapabilities: e.sourceCapabilities ? e.sourceCapabilities() : null,
'target': e.target ? '#' + e.target.id : null,
'timeStamp': e.timeStamp,
'toElement': e.toElement ? '#' + e.toElement.id : null,
'type': e.type,
'view': e.view ? e.view.toString() : null,
'which': e.which,
'x': e.x,
'y': e.y
}
};
sendCallbackParam('{id}', '{event}', param);
event.stopPropagation();
event.preventDefault();
return false;
""".format(
id=self.identifier,
event_name
)
self.attributes[event_name] = ''.join([l.strip() for l in js.splitlines()])
self.eventManager.register_listener(event_name, callback, *userdata)
#-*- coding: utf-8 -*-
from __future__ import unicode_literals
from remi_json_view import JSONView
class InstallIndexView( JSONView ):
as_attribute = [
".button"
]
def __init__(self):
super(InstallIndexView, self).__init__(_class="content")
def callback_button_click(self, event):
pass
class InstallDatabaseView( JSONView ):
as_attribute = [
".button"
]
def __init__(self):
super(InstallIndexView, self).__init__(_class="content")
def callback_process_step_clicked(self, event):
pass
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment