Source code for tendril.frontend.blueprints.entityhub.views

# -*- coding: utf-8 -*-
# Copyright (C) 2015 Chintalagiri Shashank
#
# This file is part of Tendril.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program 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 Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
"""
This file is part of tendril
See the COPYING, README, and INSTALL files for more information
"""

import json

from future.utils import viewitems
from flask import render_template
from flask import abort, flash
from flask import jsonify
from flask_user import login_required

from . import entityhub as blueprint
from .forms import CreateSnoSeriesForm

from tendril.conventions import status
from tendril.entityhub.modules import get_prototype_lib
from tendril.entityhub.modules import CardPrototype
from tendril.entityhub.modules import CablePrototype

from tendril.entityhub.modules import get_pcb_lib
from tendril.entityhub.modules import get_project_lib

# TODO Consider migration of the next section of imports
# to a prototype like structure
from tendril.entityhub import products as ehproducts
from tendril.entityhub import serialnos as ehserialnos
from tendril.entityhub.db.controller import SeriesNotFound

from tendril.dox.gedaproject import get_img_list
from tendril.dox.gedaproject import get_pcbpricing_data

from tendril.inventory.electronics import get_inventory_stage
from tendril.utils.fsutils import Crumb
from tendril.utils.types.currency import BASE_CURRENCY_SYMBOL


@blueprint.route('/modules.json')
@login_required
[docs]def modules_list(): prototypes = get_prototype_lib() moduls = sorted(prototypes.keys()) return jsonify({'modules': moduls})
@blueprint.route('/modules/<modulename>') @blueprint.route('/modules/') @login_required
[docs]def modules(modulename=None): if modulename is None: stage = {} return render_template('entityhub_modules.html', stage=stage, pagetitle="Modules") else: # Find appropriate module and redirect to page pass
@blueprint.route('/cables/<cblname>') @blueprint.route('/cables/') @login_required
[docs]def cables(cblname=None): prototypes = get_prototype_lib() if cblname is None: stage_cables = [v for k, v in viewitems(prototypes) if isinstance(v, CablePrototype)] stage_cables.sort(key=lambda x: (x.status, x.ident)) series = {} for cable in stage_cables: if cable.configs.snoseries not in series.keys(): series[cable.configs.snoseries] = 1 else: series[cable.configs.snoseries] += 1 stage = {'series': series, 'cables': stage_cables, 'crumbroot': '/entityhub', 'breadcrumbs': [Crumb(name="Entity Hub", path=""), Crumb(name="Modules", path="modules/"), Crumb(name="Cables", path="cables/")] } return render_template('entityhub_cables.html', stage=stage, pagetitle="Cables") else: prototype = prototypes[cblname] stage = {'prototype': prototype, 'inclusion': ehproducts.get_module_inclusion(cblname), 'crumbroot': '/entityhub', 'breadcrumbs': [Crumb(name="Entity Hub", path=""), Crumb(name="Modules", path="modules/"), Crumb(name="Cables", path="cables/"), Crumb(name=cblname, path="cables/"+cblname)] } return render_template('entityhub_cable_detail.html', stage=stage, pagetitle=cblname + " Cable Details")
@blueprint.route('/cards/<cardname>') @blueprint.route('/cards/') @login_required
[docs]def cards(cardname=None): prototypes = get_prototype_lib() if cardname is None: stage_cards = [v for k, v in viewitems(prototypes) if isinstance(v, CardPrototype)] stage_cards.sort(key=lambda x: (x.status, x.ident)) series = {} tstatuses = {str(x): 0 for x in status.get_known_statuses()} for card in stage_cards: if card.configs.snoseries not in series.keys(): series[card.configs.snoseries] = 1 else: series[card.configs.snoseries] += 1 tstatuses[str(card.status)] += 1 statuses = [(x, tstatuses[str(x)]) for x in status.get_known_statuses()] stage = {'statuses': statuses, 'series': series, 'cards': stage_cards, 'crumbroot': '/entityhub', 'breadcrumbs': [Crumb(name="Entity Hub", path=""), Crumb(name="Modules", path="modules/"), Crumb(name="Cards", path="cards/")] } return render_template('entityhub_cards.html', stage=stage, pagetitle="Cards") else: prototype = prototypes[cardname] stage = {'prototype': prototype, 'inclusion': ehproducts.get_module_inclusion(cardname), 'crumbroot': '/entityhub', 'breadcrumbs': [Crumb(name="Entity Hub", path=""), Crumb(name="Modules", path="modules/"), Crumb(name="Cards", path="cards/"), Crumb(name=cardname, path="cards/"+cardname)] } return render_template('entityhub_card_detail.html', stage=stage, pagetitle=cardname + " Card Details")
[docs]def get_pcb_costing_chart(projectfolder): data = get_pcbpricing_data(projectfolder) if not data: return None # TODO Interactive guideline and legend would be nice to have. # Keys : dterm datasets = {} for qty in sorted(data['pricing'].keys()): p = data['pricing'][qty] for dterm in p.keys(): if dterm not in datasets.keys(): datasets[dterm] = [] datasets[dterm].append({'x': qty, 'y': p[dterm]}) data = [] for k, v in viewitems(datasets): data.append({ 'values': v, 'key': "{0} days".format(k), 'type': 'line', 'yAxis': '1', }) mdata = datasets[10] data.append({ 'values': [{'x': a['x'], 'y': a['x'] * a['y']} for a in mdata], 'key': 'Total @10', 'type': 'line', 'yAxis': '2', }) lstage = {'data': data, 'csymbol': BASE_CURRENCY_SYMBOL} return lstage
[docs]def _get_configurations_stage(prototype): prototype_lib = get_prototype_lib() cobjs = [prototype_lib[x] for x in prototype.configs.configuration_names] cobjs.sort(key=lambda y: y.indicative_cost) configurations_costing_data = json.dumps( [{ 'key': "Sourcing Errors", 'values': [ {'label': x.ident, 'value': (2 ** x.sourcing_errors.terrors) * (-1)} for x in cobjs ], 'color': '#d67777', }, { 'key': "Indicative Costing", 'values': [ {'label': x.ident, 'value': x.indicative_cost.native_value} for x in cobjs ], 'color': '#4f99b4', }] ) return {'configurations': cobjs, 'configurations_costing': configurations_costing_data, 'native_currency_symbol': BASE_CURRENCY_SYMBOL, }
@blueprint.route('/pcbs/<pcbname>') @blueprint.route('/pcbs/') @login_required
[docs]def pcbs(pcbname=None): pcblib = get_pcb_lib() if pcbname is None: stage_pcbs = [v for k, v in viewitems(pcblib)] stage = {'pcbs': sorted([x for x in stage_pcbs], key=lambda y: (y.status, y.ident)), 'crumbroot': '/entityhub', 'breadcrumbs': [Crumb(name="Entity Hub", path=""), Crumb(name="Bare PCBs", path="pcbs/")]} return render_template('entityhub_pcbs.html', stage=stage, pagetitle="Bare PCBs") else: prototype = pcblib[pcbname] stage = {'prototype': prototype, 'imgs': get_img_list(prototype.projfolder), 'costing': get_pcb_costing_chart(prototype.projfolder), 'crumbroot': '/entityhub', 'breadcrumbs': [Crumb(name="Entity Hub", path=""), Crumb(name="Bare PCBs", path="pcbs/"), Crumb(name=pcbname, path="pcbs/" + pcbname)]} ident = 'PCB ' + pcbname stage.update(get_inventory_stage(ident)) return render_template('entityhub_pcb_detail.html', stage=stage, pagetitle="PCB Detail {0}".format(pcbname))
@blueprint.route('/projects/<projectname>') @blueprint.route('/projects/') @login_required
[docs]def projects(projectname=None): projectlib = get_project_lib() if projectname is None: stage_projects = projectlib stage = {'projects': stage_projects, 'crumbroot': '/entityhub', 'breadcrumbs': [Crumb(name="Entity Hub", path=""), Crumb(name="EDA Projects", path="projects/")] } return render_template('entityhub_projects.html', stage=stage, pagetitle="EDA Projects") else: prototype = projectlib[projectname] stage = {'prototype': prototype, 'crumbroot': '/entityhub', 'breadcrumbs': [Crumb(name="Entity Hub", path=""), Crumb(name="EDA Projects", path="projects/"), Crumb(name=projectname, path="projects/" + projectname)]} stage.update(_get_configurations_stage(prototype)) return render_template('entityhub_project_detail.html', stage=stage, pagetitle="Project Details {0}".format(projectname))
@blueprint.route('/products/<productname>') @blueprint.route('/products/') @login_required
[docs]def products(productname=None): if productname is None: stage_products = sorted(ehproducts.productlib, key=lambda x: (x.info.status, x.name)) lines = {} ptypes = {} tstatuses = {str(x): 0 for x in status.get_known_statuses()} for product in stage_products: if product.info.ptype not in ptypes.keys(): ptypes[product.info.ptype] = 1 else: ptypes[product.info.ptype] += 1 if product.info.line not in lines.keys(): lines[product.info.line] = 1 else: lines[product.info.line] += 1 tstatuses[str(product.status)] += 1 statuses = [(x, tstatuses[str(x)]) for x in status.get_known_statuses()] stage = {'statuses': statuses, 'lines': lines, 'ptypes': ptypes, 'products': stage_products, 'crumbroot': '/entityhub', 'breadcrumbs': [Crumb(name="Entity Hub", path=""), Crumb(name="Products", path="products/")] } return render_template('entityhub_products.html', stage=stage, pagetitle="Products") else: stage = {'product': ehproducts.get_product_by_ident(productname), 'crumbroot': '/entityhub', 'breadcrumbs': [Crumb(name="Entity Hub", path=""), Crumb(name="Products", path="products/"), Crumb(name=productname, path="pcbs/" + productname)], # noqa } return render_template('entityhub_product_detail.html', stage=stage, pagetitle="Product Detail {0}".format(productname))
@blueprint.route('/snoseries/<series>') @blueprint.route('/snoseries/', methods=('GET', 'POST')) @login_required
[docs]def snoseries(series=None): if series is None: form = CreateSnoSeriesForm() if form.validate_on_submit(): try: ehserialnos.controller.get_series_obj(series=form.series.data) alert = 'Did not create series {0}. ' \ 'Already exists.'.format(form.series.data) flash(alert, 'alert') except SeriesNotFound: ehserialnos.create_serial_series( form.series.data, form.start_seed.data, form.description.data ) alert = 'Created serial series {0}.'.format(form.series.data) flash(alert, 'success') stage_snoseries = sorted(ehserialnos.get_all_series(), key=lambda x: x.series) stage = {'series': stage_snoseries, 'crumbroot': '/entityhub', 'form': form, 'breadcrumbs': [Crumb(name="Entity Hub", path=""), Crumb(name="Serial Series", path="snoseries/")] } return render_template('entityhub_snoseries.html', stage=stage, pagetitle="Serial Series") else: abort(404)
# else: # stage = {'series': ehproducts.get_product_by_ident(productname), # 'crumbroot': '/entityhub', # 'breadcrumbs': [Crumb(name="Entity Hub", path=""), # Crumb(name="Products", path="products/"), # Crumb(name=productname, path="pcbs/" + productname)], # noqa # } # return render_template('entityhub_product_detail.html', stage=stage, # pagetitle="Products") @blueprint.route('/') @login_required
[docs]def main(): stage = {} return render_template('entityhub_main.html', stage=stage, pagetitle='Entity Hub')