summaryrefslogtreecommitdiff
path: root/cli/commands
diff options
context:
space:
mode:
authorlens <lens@neural.garden>2021-03-23 21:10:11 +0000
committerlens <lens@neural.garden>2021-03-23 21:10:11 +0000
commitcc1d0c52e104245f9f1c0d77eb24a5a33800be38 (patch)
tree02d8483dfe47803525b926a43c582dcfbf61c5db /cli/commands
parent81c673f058fda04b96baae7b2302f876479bc0a9 (diff)
parent7a3ec205e001e4c071a67ecc5c375612fa72afdc (diff)
Merge branch 'master' of asdf.us:swimmer
Diffstat (limited to 'cli/commands')
-rw-r--r--cli/commands/admin/migrate_to_mysql.py120
-rw-r--r--cli/commands/site/export.py127
-rw-r--r--cli/commands/site/populate.py79
3 files changed, 204 insertions, 122 deletions
diff --git a/cli/commands/admin/migrate_to_mysql.py b/cli/commands/admin/migrate_to_mysql.py
new file mode 100644
index 0000000..0ad9929
--- /dev/null
+++ b/cli/commands/admin/migrate_to_mysql.py
@@ -0,0 +1,120 @@
+import click
+import os
+import glob
+import time
+
+from sqlalchemy import create_engine
+from sqlalchemy.orm import sessionmaker
+from sqlalchemy.ext.declarative import declarative_base
+
+from flask_sqlalchemy import SQLAlchemy
+
+from app.settings import app_cfg
+
+@click.command('migrate_to_mysql')
+@click.pass_context
+def cli(ctx):
+ """
+ - Create connections to both databases
+ - For each table, for each row, insert from one to the other
+ """
+ mysql_session, mysql_base = make_mysql_base()
+ sqlite_session, sqlite_base = make_sqlite3_base()
+ mysql_classes = make_classes(mysql_base)
+ sqlite_classes = make_classes(sqlite_base)
+
+ for mysql_class, sqlite_class in zip(mysql_classes, sqlite_classes):
+ sqlite_objs = sqlite_session.query(sqlite_class).order_by(sqlite_class.id).all()
+ for sqlite_obj in sqlite_objs:
+ mysql_obj = mysql_class()
+ for column in sqlite_class.__table__.columns:
+ table_name, column_name = str(column).split(".")
+ # print(f"{table_name} => {column_name}")
+ # if column_name != 'id':
+ setattr(mysql_obj, column_name, getattr(sqlite_obj, column_name))
+ mysql_session.add(mysql_obj)
+ mysql_session.commit()
+
+def make_mysql_base():
+ """Make a Mysql connection"""
+ connection_url = "mysql+pymysql://{}:{}@{}/{}?charset=utf8mb4".format(
+ os.getenv("DB_USER"),
+ os.getenv("DB_PASS"),
+ os.getenv("DB_HOST"),
+ os.getenv("DB_NAME")
+ )
+ return make_base(connection_url)
+
+def make_sqlite3_base():
+ """Make a SQLite3 connection"""
+ connection_url = "sqlite:///{}".format(os.path.join(app_cfg.DIR_DATABASE, 'swimmer.sqlite3'))
+ return make_base(connection_url)
+
+def make_base(connection_url):
+ """Make a connection base from a connection URL"""
+ engine = create_engine(connection_url, encoding="utf-8", pool_recycle=3600)
+ Session = sessionmaker(bind=engine)
+ Base = declarative_base()
+ Base.metadata.bind = engine
+ db = SQLAlchemy()
+ return Session(), Base
+
+def make_classes(Base):
+ """Make classes from a base"""
+
+ from sqlalchemy import create_engine, Table, Column, Text, String, Integer, \
+ Boolean, Float, DateTime, JSON, ForeignKey
+ from sqlalchemy_utc import UtcDateTime, utcnow
+
+ class Upload(Base):
+ """Table for storing references to various media"""
+ __tablename__ = 'upload'
+ id = Column(Integer, primary_key=True)
+ graph_id = Column(Integer, ForeignKey('graph.id'), nullable=True)
+ sha256 = Column(String(256), nullable=False)
+ fn = Column(String(256), nullable=False)
+ ext = Column(String(4, convert_unicode=True), nullable=False)
+ tag = Column(String(64, convert_unicode=True), nullable=True)
+ username = Column(String(16, convert_unicode=True), nullable=False)
+ created_at = Column(UtcDateTime(), default=utcnow())
+
+ class Tile(Base):
+ """Table for storing references to tiles"""
+ __tablename__ = 'tile'
+ id = Column(Integer, primary_key=True)
+ graph_id = Column(Integer, ForeignKey('graph.id'), nullable=True)
+ page_id = Column(Integer, ForeignKey('page.id'), nullable=True)
+ target_page_id = Column(Integer, ForeignKey('page.id'), nullable=True)
+ type = Column(String(16, convert_unicode=True), nullable=False)
+ sort_order = Column(Integer, default=0)
+ settings = Column(JSON, default={}, nullable=True)
+ created_at = Column(UtcDateTime(), default=utcnow())
+ updated_at = Column(UtcDateTime(), onupdate=utcnow())
+
+ class Page(Base):
+ """Table for storing references to pages"""
+ __tablename__ = 'page'
+ id = Column(Integer, primary_key=True)
+ graph_id = Column(Integer, ForeignKey('graph.id'), nullable=True)
+ path = Column(String(64, convert_unicode=True), nullable=False)
+ title = Column(String(64, convert_unicode=True), nullable=False)
+ username = Column(String(32, convert_unicode=True), nullable=False)
+ description = Column(Text(convert_unicode=True), nullable=False)
+ settings = Column(JSON, default={}, nullable=True)
+ created_at = Column(UtcDateTime(), default=utcnow())
+ updated_at = Column(UtcDateTime(), onupdate=utcnow())
+
+ class Graph(Base):
+ """Table for storing references to graphs"""
+ __tablename__ = 'graph'
+ id = Column(Integer, primary_key=True)
+ home_page_id = Column(Integer, nullable=True)
+ path = Column(String(64, convert_unicode=True), nullable=False)
+ title = Column(String(64, convert_unicode=True), nullable=False)
+ username = Column(String(32, convert_unicode=True), nullable=False)
+ description = Column(Text(convert_unicode=True), nullable=False)
+ settings = Column(JSON, default={}, nullable=True)
+ created_at = Column(UtcDateTime(), default=utcnow())
+ updated_at = Column(UtcDateTime(), onupdate=utcnow())
+
+ return [ Graph, Page, Tile, Upload ]
diff --git a/cli/commands/site/export.py b/cli/commands/site/export.py
index 0ba6a62..78e7228 100644
--- a/cli/commands/site/export.py
+++ b/cli/commands/site/export.py
@@ -1,134 +1,17 @@
import click
from app.settings import app_cfg
-from app.utils.file_utils import load_text, write_json, write_text
-from os.path import join
-import os
+from app.site.export import export_site
@click.command('info')
@click.option('-g', '--graph', 'opt_graph_path', required=True,
help='Graph name')
@click.option('-o', '--output', 'opt_output_dir', required=True, default=app_cfg.DIR_EXPORTS,
help='Output dir')
+@click.option('-j', '--js/--no-js', 'opt_js', required=False, default=False,
+ help='Whether to rebuild the Javascript bundle')
@click.pass_context
-def cli(ctx, opt_graph_path, opt_output_dir):
+def cli(ctx, opt_graph_path, opt_output_dir, opt_build_js):
"""Export a graph"""
- # ------------------------------------------------
- # imports
-
- from app.sql.common import db, Session, Graph, Page, Tile
- from distutils.dir_util import copy_tree
-
- # ------------------------------------------------
- # generate HTML for index and all pages
-
- session = Session()
- graph = session.query(Graph).filter(Graph.path == opt_graph_path).first()
- if graph is None:
- print(f"Not a graph: {opt_graph_path}")
- return
-
- # build everything here
- graph_dir = os.path.abspath(join(opt_output_dir, graph.path))
-
- # load site index
- index_html = load_text(join(app_cfg.DIR_STATIC, 'site.html'), split=False)
- index_html = index_html.replace('SITE_PATH', '/' + graph.path)
-
- # write site JSON data
- site_data = { 'graph': sanitize_graph(graph.toSiteJSON()) }
- write_json(site_data, join(graph_dir, 'index.json'), default=str, minify=False)
-
- # import custom css
- site_css = load_text(join(app_cfg.DIR_STATIC, 'site.css'), split=False)
- site_css = site_css.replace('SITE_PATH', '/' + graph.path)
- write_text(site_css, join(graph_dir, 'site.css'))
- copy_tree(join(app_cfg.DIR_STATIC, 'fonts'), join(graph_dir, 'static/fonts'))
- copy_tree(join(app_cfg.DIR_STATIC, 'img'), join(graph_dir, 'static/img'))
-
- # write index file, redirects to homepage
- home_page = site_data['graph']['home_page']
- if home_page is None:
- print("Homepage not set! Shift-click a page on the graph to make it the homepage.")
- return
- write_text(f'<meta http-equiv="refresh" content="0; url={home_page}">', join(graph_dir, 'index.html'))
-
- index_path = ""
- for page in graph.pages:
- page_path = f'{graph.path}/{page.path}'
- if page.id == graph.home_page_id:
- index_path = page_path
- print(f'/{page_path} [index]')
- else:
- print(f'/{page_path}')
- write_index(graph, page, index_html, join(graph_dir, page.path, 'index.html'))
-
- # ------------------------------------------------
- # build javascript
-
- print("Building javascript...")
- print(f'NODE_ENV=production node ./node_modules/webpack-cli/bin/cli.js --config ./webpack.config.site.js -o {graph_dir}/bundle.js')
- os.chdir(app_cfg.DIR_PROJECT_ROOT)
- os.system(f'NODE_ENV=production node ./node_modules/webpack-cli/bin/cli.js --config ./webpack.config.site.js -o {graph_dir}/bundle.js')
-
- print("Site export complete!")
- print(f"Graph exported to: {graph_dir}")
-
-def write_index(graph, page, index_html, fp_out):
- if page is None:
- page_title = graph.title
- else:
- page_title = page.title
- index_html = index_html.replace('BUNDLE_PATH', join('/', graph.path, 'bundle.js'))
- index_html = index_html.replace('PAGE_TITLE', page_title)
- write_text(index_html, fp_out)
-
-def sanitize_graph(graph):
- page_path_lookup = {}
- page_lookup = {}
- for page in graph['pages']:
- page_path = join('/', graph['path'], page['path'])
- if page_path in page_path_lookup:
- print(f"/!\\ WARNING! Duplicate found of {page_path}")
- else:
- page_path_lookup[page['id']] = page_path
- for page in graph['pages']:
- sanitize_page(page)
- if page['id'] == 12:
- print(page)
- for tile in page['tiles']:
- if tile['target_page_id']:
- if tile['target_page_id'] == -1:
- tile['href'] = tile['settings']['external_link_url']
- elif tile['target_page_id'] > 0:
- tile['href'] = page_path_lookup[tile['target_page_id']]
- sanitize_tile(tile)
- page_path = page_path_lookup[page['id']]
- page_lookup[page_path] = page
- # print(page_lookup['/asdf/testttt'])
- graph['pages'] = page_lookup
- graph['home_page'] = page_path_lookup[graph['home_page_id']]
- return graph
-
-def sanitize_page(data):
- if 'created_at' in data:
- del data['created_at']
- if 'updated_at' in data:
- del data['updated_at']
- if 'graph_id' in data:
- del data['graph_id']
-
-def sanitize_tile(data):
- if 'created_at' in data:
- del data['created_at']
- if 'updated_at' in data:
- del data['updated_at']
- if 'username' in data:
- del data['username']
- if 'graph_id' in data:
- del data['graph_id']
- if 'page_id' in data:
- del data['page_id']
- if 'target_page_id' in data:
- del data['target_page_id']
+ export_site(opt_graph_path, opt_output_dir, opt_build_js) \ No newline at end of file
diff --git a/cli/commands/site/populate.py b/cli/commands/site/populate.py
new file mode 100644
index 0000000..b1b9691
--- /dev/null
+++ b/cli/commands/site/populate.py
@@ -0,0 +1,79 @@
+import click
+
+lines = """/static/media/last-museum/nicole-foreshew/establishing1.mp4
+/static/media/last-museum/nicole-foreshew/sequence1b.mp4
+/static/media/last-museum/nicole-foreshew/sequence2.mp4
+/static/media/last-museum/nicole-foreshew/sequence3.mp4
+/static/media/last-museum/nicole-foreshew/sequence4.mp4
+/static/media/last-museum/nicole-foreshew/sequence5.mp4""".split("\n")
+
+letters = ['a','b','c','d','e','f','g','h','i','j']
+
+@click.command('populate')
+@click.pass_context
+def cli(ctx):
+ """Populate video pages"""
+
+ import requests
+
+ def post(endpoint, data):
+ resp = requests.post(endpoint, json=data)
+ return None if resp.status_code != 200 else resp.json()
+
+ graph_id = 3
+ name = "Nicole Foreshew"
+ index = 0
+
+ for url in lines:
+ # slug = url.split("/")[5].replace(".mp4", "").lower()
+ slug = "foreshew-" + str(index) # + letters[index]
+ print(slug)
+ index += 1
+
+ page_data = {
+ "graph_id": graph_id,
+ "path": slug,
+ "title": name, # + str(index),
+ "username": "jules",
+ "description":"",
+ "settings": {
+ "x": 0.05,
+ "y": 0.05,
+ "background_color": "#000000",
+ "background_audio_id": 0,
+ "restart_audio": False
+ }
+ }
+ page_res = post("http://0.0.0.0:5000/api/v1/page/", page_data)
+ page_id = page_res['res']['id']
+
+ tile_data = {
+ "graph_id": graph_id,
+ "page_id": page_id,
+ "target_page_id": None,
+ "type": "video",
+ "settings": {
+ "x": 0,
+ "y": 0,
+ "width": 1920,
+ "height": 1080,
+ "rotation": 0,
+ "scale": 1,
+ "opacity": 1,
+ "units": False,
+ "align": "center_center",
+ "has_audio": False,
+ "audio_on_click_id": 0,
+ "audio_on_hover_id": 0,
+ "navigate_when_audio_finishes": False,
+ "video_style": "cover",
+ "url": url,
+ "external_link_url": "",
+ "cursor": "none",
+ "muted": True,
+ "loop": True,
+ "autoadvance": False
+ }
+ }
+
+ page_res = post("http://0.0.0.0:5000/api/v1/tile/", tile_data)