def layout(item): """ Layout for popup link """ if not item.authorized: return None if current.deployment_settings.get_ui_use_button_icons(): label = (ICON("add"), item.label) else: label = item.label # @ToDo Ensure that if we are in an inline component, these links are different for each of the 3 _id = item.attr._id or "%s_add" % item.function popup_link = A(label, _href = item.url(format = "popup"), _class = "s3_add_resource_link", _id = _id, _target = "top", _title = item.opts.info, ) tooltip = item.opts.tooltip if tooltip is not None: ttip = DIV(_class = "tooltip", _title = "%s|%s" % (item.opts.title, tooltip, ), ) else: ttip = "" return TAG[""](popup_link, ttip)
def layout(item): """ Layout for popup link """ if not item.authorized: return None if current.deployment_settings.get_ui_use_button_icons(): label = (ICON("add"), item.label) else: label = item.label popup_link = A( label, _href=item.url(format="popup"), _class="s3_add_resource_link", _id="%s_add" % item.function, _target="top", _title=item.opts.info, ) tooltip = item.opts.tooltip if tooltip is not None: ttip = DIV(_class="tooltip", _title="%s|%s" % (item.opts.title, tooltip)) else: ttip = "" return TAG[""](popup_link, ttip)
def contact_represent(value, row=None): if isinstance(value, tuple) and len(value) == 3: if not any(value): return "" name, phone, email = value output = DIV(_class="contact-repr", ) if name: output.append(SPAN( name, _class="contact-name", )) if email or phone: details = DIV(_class="contact-details") if phone: details.append( DIV( ICON("phone"), SPAN(phone, _class="contact-phone"), _class="contact-info", )) if email: details.append( DIV( ICON("mail"), SPAN(A( email, _href="mailto:%s" % email, ), _class="contact-email"), _class="contact-info", )) output.append(details) return output else: return value if value else "-"
def layout(item): """ Custom Layout Method """ # Manage flags: hide any disabled/unauthorized items if not item.authorized: enabled = False visible = False elif item.enabled is None or item.enabled: enabled = True visible = True if enabled and visible: if item.parent is None: # Main menu items = item.render_components() return DIV(items, _id="main-sub-menu", _class="icon-bar vertical three-up") else: # Menu item if item.enabled and item.authorized: attr = {"_id": item.attr._id} if item.attr._onclick: attr["_onclick"] = item.attr._onclick else: attr["_href"] = item.url() if item.selected: attr["_class"] = "active item" else: attr["_class"] = "item" icon = item.opts.icon if icon: icon = ICON(icon) else: icon = "" return A(icon, TAG["label"](item.label), **attr ) else: return None
def postp(r, output): # Call standard postp if callable(standard_postp): output = standard_postp(r, output) if r.method == "datalist": if "showadd_btn" in output: from gluon import A, SPAN, URL from s3 import ICON output["showadd_btn"] = A(ICON("plus"), SPAN(T("New guide")), _class = "add-btn no-link s3_modal", _href = URL(c="doc", f="document", args = "create.popup", vars = {"refresh": "datalist"}, ), ) return output
def __call__(self): T = current.T response = current.response s3 = response.s3 # Intro caption = T( "MapPH helps you share neighborhood needs and connects you to information from NGOs, business and government." ) # Get-started-button get_started = A(T("Get Started"), XML(" "), ICON("fa-caret-right", _class="fa"), _class="medium primary button", _href=URL( c="default", f="index", args=["docs"], vars={"name": "GetStarted"}, )) # Inject custom styles for homepage s3.stylesheets.append("../themes/MAVC/homepage.css") # Set the custom view self._view(THEME, "index.html") output = { "caption": caption, "get_started": get_started, } return output
def cms_post_list_layout(list_id, item_id, resource, rfields, record): """ dataList item renderer for Posts on the Bulletin Board. @param list_id: the HTML ID of the list @param item_id: the HTML ID of the item @param resource: the S3Resource to render @param rfields: the S3ResourceFields to render @param record: the record as dict """ record_id = record["cms_post.id"] #item_class = "thumbnail" T = current.T db = current.db s3db = current.s3db settings = current.deployment_settings permit = current.auth.s3_has_permission raw = record._row date = record["cms_post.date"] title = record["cms_post.title"] body = record["cms_post.body"] #series_id = raw["cms_post.series_id"] # Allow records to be truncated # (not yet working for HTML) body = DIV( body, _class="s3-truncate", ) #if series_id: # series = record["cms_post.series_id"] # translate = settings.get_L10n_translate_cms_series() # if translate: # series_title = T(series) # else: # series_title = series #else: # series_title = series = "" #status = record["cms_post.status_id"] author_id = raw["cms_post.created_by"] person = record["cms_post.created_by"] # @ToDo: Bulk lookup ltable = s3db.pr_person_user ptable = db.pr_person query = (ltable.user_id == author_id) & \ (ltable.pe_id == ptable.pe_id) row = db(query).select(ptable.id, limitby=(0, 1)).first() if row: person_id = row.id else: person_id = None if person: if person_id: # @ToDo: deployment_setting for controller to use? person_url = URL(c="hrm", f="person", args=[person_id]) else: person_url = "#" person = A( person, _href=person_url, ) table = db.cms_post # Toolbar if permit("update", table, record_id=record_id): edit_btn = A( ICON("edit"), SPAN( "edit", _class="show-for-sr", ), _href=URL(c="cms", f="post", args=[record_id, "update.popup"], vars={ "refresh": list_id, "record": record_id }), _class="s3_modal", #_title=T("Edit %(type)s") % dict(type=series_title), _title=T("Edit"), ) else: edit_btn = "" if permit("delete", table, record_id=record_id): delete_btn = A( ICON("delete"), SPAN( "delete", _class="show-for-sr", ), _class="dl-item-delete", _title=T("Delete"), ) else: delete_btn = "" # Bookmarks auth = current.auth user = auth.user if user: #and settings.get_cms_bookmarks(): # @ToDo: Bulk lookup (via list_fields?) ltable = s3db.cms_post_user query = (ltable.post_id == record_id) & \ (ltable.user_id == user.id) exists = db(query).select(ltable.id, limitby=(0, 1)).first() if exists: bookmark = A( ICON("bookmark"), SPAN( "remove bookmark", _class="show-for-sr", ), _class="bookmark", _title=T("Remove Bookmark"), ) else: bookmark = A( ICON("bookmark-empty"), SPAN( "bookmark", _class="show-for-sr", ), _class="bookmark", _title=T("Add Bookmark"), ) bookmark["_data-c"] = "cms" bookmark["_data-f"] = "post" bookmark["_data-i"] = record_id else: bookmark = "" # Dropdown of available documents documents = raw["doc_document.file"] if documents: if not isinstance(documents, list): documents = (documents, ) doc_list = UL( _class="dropdown-menu", _role="menu", ) retrieve = db.doc_document.file.retrieve for doc in documents: try: doc_name = retrieve(doc)[0] except (IOError, TypeError): doc_name = current.messages["NONE"] doc_url = URL(c="default", f="download", args=[doc]) doc_item = LI( A( ICON("file"), " ", doc_name, _href=doc_url, ), _role="menuitem", ) doc_list.append(doc_item) docs = DIV( A(ICON("paper-clip"), SPAN(_class="caret"), _class="btn dropdown-toggle", _href="#", **{"_data-toggle": "dropdown"}), doc_list, _class="btn-group attachments dropdown pull-right", ) else: docs = "" #divider = LI("|") #divider["_aria-hidden"] = "true" toolbar = UL( #LI(share_btn, # _class="item", # ), #LI(A(ICON("flag"), # @ToDo: Use flag-alt if not flagged & flag if already flagged (like for bookmarks) # SPAN("flag this", # _class = "show-for-sr", # ), # _href="#", # _title=T("Flag"), # ), # _class="item", # ), LI( bookmark, _class="item", ), #LI(A(I(_class="fa fa-users", # ), # SPAN("make public", # _class = "show-for-sr", # ), # _href="#", # _title=T("Make Public"), # ), # _class="item", # ), LI( edit_btn, _class="item", ), LI( delete_btn, _class="item", ), _class="controls", ) # Tags #if settings.get_cms_show_tags(): tag_list = UL(_class="left inline-list s3-tags", ) tag_list["_data-post_id"] = record_id tags = raw["cms_tag.name"] if tags: if not isinstance(tags, list): tags = [tags] for tag in tags: tag_list.append(LI(A( tag, _href="#", ), )) # Comments comment_list = UL(_class="card-post-comments") cappend = comment_list.append #if settings.get_cms_comments(): # Add existing comments (oldest 1st) # - should sort by default by ID which is equivalent to oldest first, # however they seem to come in in a random order (even if orderby set on the component) so need to be sorted manually here comments = raw["cms_comment.json_dump"] ncomments = 0 if comments: if not isinstance(comments, list): comments = [comments] comments = [json.loads(comment) for comment in comments] comments.sort(key=lambda c: c["created_on"]) for comment in comments: author = s3_auth_user_represent(comment["created_by"]) cdate = dateutil.parser.parse(comment["created_on"]) ctime = cdate.time().strftime("%H:%M") cdate = cdate.date().strftime("%b %d, %Y") comment = LI(TAG["ASIDE"](P(T("Updated %(date)s @ %(time)s by %(author)s") % \ dict(date = cdate, time = ctime, author = author, ), _class="meta", ), DIV(comment["body"], _class="desc", ), # @ToDo: Show this if more than x chars? #TAG["FOOTER"](P(A(T("More Info"), # _class="more", # ) # ), # _class="footer", # ), _class="card-post-comment", )) cappend(comment) ncomments += 1 if ncomments == 1: num_comments = "1 Comment" else: num_comments = T("%(num)s Comments") % dict(num=ncomments) if user: add_comment = A( T("Add Comment"), _class="add-comment", ) add_comment["_data-l"] = list_id add_comment["_data-i"] = record_id add_comment = P(add_comment) comment_input = LI( TAG["ASIDE"]( TEXTAREA( _class="desc", _placeholder=T("comment here"), ), TAG["FOOTER"](P(A( "Submit Comment", _class="submit", ), ), ), _class="card-post-comment", ), _class="comment-form hide", ) cappend(comment_input) else: add_comment = "" item = TAG["ASIDE"]( TAG["HEADER"]( UL( # post priority icon LI(_class="item icon", ), # post type title #LI(series_title, # _class="item primary", # ), # post status #LI(status, # _class="item secondary border status", # ), # post visibility # @ToDo: Read the visibility #LI(T("Public"), # _class="item secondary border visibility", # ), _class="status-bar-left"), toolbar, _class="status-bar", ), DIV( DIV( SPAN( "Updated ", # @ToDo: i18n TAG["TIME"](date), " by ", person, _class="meta-update", ), SPAN( num_comments, _class="meta-comments", ), _class="meta", ), H4( title, _class="title", ), DIV( body, _class="desc", ), _class="body", ), docs, TAG["FOOTER"]( DIV( tag_list, _class= "tags clearfix", # @ToDo: remove clearfix and style via CSS ), comment_list, add_comment, _class="footer", ), _class="card-post", _id=item_id, ) return item
def layout(item): """ Layout Method (Item Renderer) """ # Manage flags: hide any disabled/unauthorized items if not item.authorized: enabled = False visible = False elif item.enabled is None or item.enabled: enabled = True visible = True if enabled and visible: if item.parent is not None: if item.enabled and item.authorized: attr = {"_id": item.attr._id} if item.attr._onclick: attr["_onclick"] = item.attr._onclick else: attr["_href"] = item.url() #if item.components: # # Submenu # items = item.render_components() # # Hide submenus which have no active links # if not items and not item.link: # return None # _class = "" # if item.parent.parent is None and item.selected: # _class = "active" # section = [LI(A(ICON(item.opts.icon), # " ", # SPAN(item.label), # **attr # ), # _class = "heading %s" % _class, # ), # ] # if items: # section.append(UL(items, # _class = "menu vertical nested", # https://get.foundation/sites/docs/menu.html # )) # return section #else: # Submenu item #if item.parent.parent is None: # _class = "heading" if item.selected: _class = "active" else: _class = "" return LI( A(ICON(item.opts.icon), " ", SPAN(item.label), **attr), _class=_class, ) else: # Main menu items = item.render_components() return NAV( UL( items, _id="main-sub-menu", _class= "menu vertical icons icon-top", # https://get.foundation/sites/docs/menu.html ), ) else: return None
def layout(item): """ Layout Method (Item Renderer) """ # Manage flags: hide any disabled/unauthorized items if not item.authorized and not item.opts.always_display: item.enabled = False item.visible = False elif item.enabled is None or item.enabled: item.enabled = True item.visible = True if item.enabled and item.visible: items = item.render_components() if item.parent is not None: if item.attr._class: classes = item.attr._class.split(" ") else: classes = [] if item.parent.parent is None: # Item at the top-level? toplevel = True if item.opts.right: classes.append("menu-right") else: toplevel = False if item.components: classes.append("has-dropdown not-click") _class = " ".join(classes) # Menu item with Dropdown if item.get_first(enabled=True): _href = item.url() return LI( A(item.label, _href=_href, _id=item.attr._id), UL(items, _class="dropdown"), _class=_class, ) else: # Menu item without Drop-Down if toplevel: item_url = item.url() if item_url == URL(c="default", f="index"): classes.append("menu-home") if item.selected: classes.append("active") _class = " ".join(classes) icon = item.opts.icon if icon: label = LABEL(ICON(icon), item.label) else: label = item.label return LI( A( label, _href=item_url, _id=item.attr._id, _target=item.attr._target, ), _class=_class, ) else: # Submenu item if isinstance(item.label, dict): if "id" in item.label: return S3MainMenuDefaultLayout.checkbox_item( item) elif "name" in item.label: label = item.label["name"] else: return None else: label = item.label link = A( label, _href=item.url(), _id=item.attr._id, _target=item.attr._target, ) _class = " ".join(classes) return LI(link, _class=_class) else: # The main menu itself T = current.T settings = current.deployment_settings if item.opts.title_area: # Custom override title_area = item.opts.title_area else: # Standard: render a menu logo logo = settings.get_ui_menu_logo() if logo is None: # Render an icon logo = SPAN( settings.get_system_name_short(), _class="logo", ) elif isinstance(logo, str): # Assume image-URL logo = IMG( _src=logo, _class="logo", _alt=settings.get_system_name_short(), ) #else: # use as-is (assume HTML or T()) title_area = A( logo, _href=URL(c="default", f="index"), _title=T("Homepage"), ) # Arrange items left/right right = [] left = [] for item in items: if "menu-right" in item["_class"]: item.remove_class("menu-right") right.append(item) else: left.append(item) right.reverse() # Reverse if right-to-left if current.response.s3.rtl: right, left = left, right # Build top-bar HTML return NAV( UL( LI( title_area, _class="name", ), LI( A(SPAN(T("Menu"))), _class="toggle-topbar menu-icon", ), _class="title-area", ), SECTION( UL( right, _class="right", ), UL( left, _class="left", ), _class="top-bar-section", ), _class="top-bar", data={"topbar": " "}, ) else: return None
def layout(item): """ Layout Method (Item Renderer) """ # Manage flags: hide any disabled/unauthorized items if not item.authorized and not item.opts.always_display: item.enabled = False item.visible = False elif item.enabled is None or item.enabled: item.enabled = True item.visible = True if item.enabled and item.visible: items = item.render_components() if item.parent is None: # The menu itself number_of_links = 0 components = [] append = components.append for submenu in items: append(submenu) number_of_links += len(submenu.elements("a")) # Hide the entire menu if it doesn't contain any links if not number_of_links: return None title = H3(item.label) if item.label else "" menu = DIV( title, DIV( TAG[""](components), _class="icon-bar four-up", ), _id=item.attr._id, _class=item.attr._class, ) return menu else: # A menu item _class = item.attr._class if _class: _class = "%s item" % _class else: _class = "item" _id = item.attr._id icon = item.opts.icon if icon: label = LABEL(ICON(icon), item.label) else: label = LABEL(item.label) return A( label, _class=_class, _href=item.url(), _id=_id, ) else: return None
def __call__(self): output = {} T = current.T request = current.request response = current.response s3 = response.s3 # Check logged in and permissions auth = current.auth settings = current.deployment_settings roles = current.session.s3.roles system_roles = auth.get_system_roles() AUTHENTICATED = system_roles.AUTHENTICATED # Login/Registration forms self_registration = settings.get_security_registration_visible() registered = False login_form = None login_div = None register_form = None register_div = None # Project Links project_links = DIV(_class="title-links hide-for-small") project_description = settings.get_frontpage("project_description") if project_description: project_links.append( A( ICON("link"), T("Project Description"), _class="action-lnk", _href=project_description, _target="_blank", )) project_links.append( A( ICON("link"), T("User Manual"), _class="action-lnk", _href=URL( c="default", f="index", args=["docs"], vars={"name": "UserManual"}, ), _target="_blank", )) mailing_list = settings.get_frontpage("mailing_list") if mailing_list: project_links.append( A( ICON("link"), T("Mailing List"), _class="action-lnk", _href=mailing_list, _target="_blank", )) # Contact Form request_email = settings.get_frontpage("request_email") if request_email: from s3dal import Field from gluon.validators import IS_NOT_EMPTY from gluon.sqlhtml import SQLFORM fields = [ Field( "name", label="Your name", requires=IS_NOT_EMPTY(), ), Field( "address", label="Your e-mail address", requires=IS_NOT_EMPTY(), ), Field( "subject", label="Subject", requires=IS_NOT_EMPTY(), ), Field( "message", "text", label="Message", requires=IS_NOT_EMPTY(), ), ] from s3 import s3_mark_required labels, required = s3_mark_required(fields) s3.has_required = required response.form_label_separator = "" contact_form = SQLFORM.factory( formstyle=settings.get_ui_formstyle(), submit_button=T("Submit"), labels=labels, separator="", table_name="contact", # Dummy table name _id="mailform", *fields) if contact_form.accepts(request.post_vars, current.session, formname="contact_form", keepvalues=False, hideerror=False): # Processs Contact Form form_vars = contact_form.vars sender = "%s <%s>" % (form_vars.name, form_vars.address) result = current.msg.send_email( to=request_email, sender=sender, subject=form_vars.subject, message=form_vars.message, reply_to=form_vars.address, ) if result: response.confirmation = "Thank you for your message - we'll be in touch shortly" if s3.cdn: if s3.debug: s3.scripts.append( "http://ajax.aspnetcdn.com/ajax/jquery.validate/1.9/jquery.validate.js" ) else: s3.scripts.append( "http://ajax.aspnetcdn.com/ajax/jquery.validate/1.9/jquery.validate.min.js" ) else: if s3.debug: s3.scripts.append("/%s/static/scripts/jquery.validate.js" % request.application) else: s3.scripts.append( "/%s/static/scripts/jquery.validate.min.js" % request.application) validation_script = ''' $('#mailform').validate({ errorClass:'req', rules:{ name:{ required:true }, address: { required:true, email:true }, subject:{ required:true }, message:{ required:true } }, messages:{ name:"Enter your name", subject:"Enter a subject", message:"Enter a message", address:{ required:"Please enter a valid email address", email:"Please enter a valid email address" } }, errorPlacement:function(error,element){ error.appendTo(element.parents('div.controls')) }, submitHandler:function(form){ form.submit() } })''' s3.jquery_ready.append(validation_script) else: contact_form = "" if AUTHENTICATED not in roles: login_buttons = DIV(A(T("Login"), _id="show-login", _class="tiny secondary button"), _id="login-buttons") script = ''' $('#show-mailform').click(function(e){ e.preventDefault() $('#login_box').fadeOut(function(){$('#intro').fadeIn()}) }) $('#show-login').click(function(e){ e.preventDefault() $('#login_form').show() $('#register_form').hide() $('#intro').fadeOut(function(){$('#login_box').fadeIn()}) })''' s3.jquery_ready.append(script) # This user isn't yet logged-in if request.cookies.has_key("registered"): # This browser has logged-in before registered = True if self_registration is True: # Provide a Registration box on front page login_buttons.append( A(T("Register"), _id="show-register", _class="tiny secondary button", _style="margin-left:5px")) script = ''' $('#show-register').click(function(e){ e.preventDefault() $('#login_form').hide() $('#register_form').show() $('#intro').fadeOut(function(){$('#login_box').fadeIn()}) })''' s3.jquery_ready.append(script) register_form = auth.register() register_div = DIV(H3(T("Register")), P(XML(T("If you would like to help, then please %(sign_up_now)s") % \ dict(sign_up_now=B(T("sign-up now")))))) register_script = ''' $('#register-btn').click(function(e){ e.preventDefault() $('#login_form').fadeOut(function(){$('#register_form').fadeIn()}) }) $('#login-btn').click(function(e){ e.preventDefault() $('#register_form').fadeOut(function(){$('#login_form').fadeIn()}) })''' s3.jquery_ready.append(register_script) # Provide a login box on front page auth.messages.submit_button = T("Login") login_form = auth.login(inline=True) login_div = DIV(H3(T("Login")), P(XML(T("Registered users can %(login)s to access the system") % \ dict(login=B(T("login")))))) else: login_buttons = "" # Create output dict output = { "login_buttons": login_buttons, "self_registration": self_registration, "registered": registered, "login_div": login_div, "login_form": login_form, "register_div": register_div, "register_form": register_form, "contact_form": contact_form, "project_links": project_links, } # Count records (@todo: provide total/updated counters?) s3db = current.s3db db = current.db # Organisations table = s3db.org_organisation query = (table.deleted != True) count = table.id.count() row = db(query).select(count).first() output["total_organisations"] = row[count] # Service Locations (@todo) #table = s3db.org_service_location #query = (table.deleted != True) #count = table.id.count() #row = db(query).select(count).first() output["total_services"] = 0 #row[count] # Needs lists table = s3db.req_organisation_needs query = (table.deleted != True) count = table.id.count() row = db(query).select(count).first() output["total_needs"] = row[count] # Frontpage Feed Control if settings.frontpage.rss: s3.external_stylesheets.append( "http://www.google.com/uds/solutions/dynamicfeed/gfdynamicfeedcontrol.css" ) s3.scripts.append( "http://www.google.com/jsapi?key=notsupplied-wizard") s3.scripts.append( "http://www.google.com/uds/solutions/dynamicfeed/gfdynamicfeedcontrol.js" ) counter = 0 feeds = "" for feed in settings.frontpage.rss: counter += 1 feeds = "".join((feeds, "{title:'%s',\n" % feed["title"], "url:'%s'}" % feed["url"])) # Don't add a trailing comma for old IEs if counter != len(settings.frontpage.rss): feeds += ",\n" # feedCycleTime: milliseconds before feed is reloaded (5 minutes) feed_control = "".join((''' function LoadDynamicFeedControl(){ var feeds=[ ''', feeds, ''' ] var options={ feedCycleTime:300000, numResults:5, stacked:true, horizontal:false, title:"''', str(T("News")), '''" } new GFdynamicFeedControl(feeds,'feed-control',options) } google.load('feeds','1') google.setOnLoadCallback(LoadDynamicFeedControl)''')) s3.js_global.append(feed_control) s3.stylesheets.append("../themes/RW/homepage.css") self._view(TEMPLATE, "index.html") return output
def render_filter(cls, list_id, item_id, resource, rfields, record): """ Custom dataList item renderer for 'Saved Filters' @param list_id: the HTML ID of the list @param item_id: the HTML ID of the item @param resource: the S3Resource to render @param rfields: the S3ResourceFields to render @param record: the record as dict """ record_id = record["pr_filter.id"] item_class = "thumbnail" raw = record._row resource_name = raw["pr_filter.resource"] resource = current.s3db.resource(resource_name) T = current.T # Resource title crud_strings = current.response.s3.crud_strings.get(resource.tablename) if crud_strings: resource_name = crud_strings.title_list else: resource_name = string.capwords(resource.name, "_") # Filter title title = record["pr_filter.title"] # Filter Query and Summary URLs fstring = S3FilterString(resource, raw["pr_filter.query"]) query = fstring.represent() links = cls.summary_urls(resource, raw["pr_filter.url"], fstring.get_vars) actions = [] if links: if "map" in links: actions.append(A(ICON("globe"), _title=T("Open Map"), _href=links["map"])) if "table" in links: actions.append(A(ICON("list"), _title=T("Open Table"), _href=links["table"])) if "chart" in links: actions.append(A(ICON("list"), _title=T("Open Chart"), _href=links["chart"])) # Render the item item = DIV(DIV(DIV(actions, _class="action-bar fleft"), SPAN(T("%(resource)s Filter") % \ dict(resource=resource_name), _class="card-title"), DIV(A(ICON("delete"), _title=T("Delete this Filter"), _class="dl-item-delete"), _class="edit-bar fright"), _class="card-header"), DIV(DIV(H5(title, _id="filter-title-%s" % record_id, _class="media-heading jeditable"), DIV(query), _class="media-body"), _class="media"), _class=item_class, _id=item_id) return item
def __call__(self): T = current.T db = current.db s3db = current.s3db user = current.auth.user user_id = user.id # Huuricane Season lasts from 1/6 to 30/11 now = current.request.utcnow if 5 < now.month < 12: SEASON = T("this Season") SEASON_START = datetime.date(now.year, 6, 1) SEASON_END = None else: SEASON = T("last Season") last_year = now.year - 1 SEASON_START = datetime.date(last_year, 6, 1) SEASON_END = datetime.date(last_year, 12, 1) # Shipments stable = s3db.inv_send fields = [ "id", "send_ref", "date", "site_id", "to_site_id", "transport_type", "status", "filing_status", ] sresource = s3db.resource( "inv_send", filter=(stable.date != None), # Don't include Unsent Shipments ) srows = sresource.select( fields, as_rows=True, limit=5, orderby=~stable.date, ) rtable = s3db.inv_recv fields = [ "id", "recv_ref", "date", "site_id", "from_site_id", "transport_type", "status", "filing_status", ] rresource = s3db.resource( "inv_recv", filter=(rtable.date != None), # Don't include Unreceived Shipments ) rrows = rresource.select( fields, as_rows=True, limit=5, orderby=~rtable.date, ) rtotal = len(rrows) # Find the most recent 5 from both lists shipments = [] sappend = shipments.append rindex = 0 stotal = 0 for srow in srows: if rindex < rtotal: rrow = rrows[rindex] else: srow.type = "send" sappend(srow) if stotal == 4: break stotal += 1 continue send_date = srow.date recv_date = rrow.date if send_date > recv_date: srow.type = "send" sappend(srow) if stotal == 4: break stotal += 1 continue rrow.type = "recv" sappend(rrow) if stotal == 4: break stotal += 1 rindex += 1 if rindex < rtotal: rrow = rrows[rindex] else: srow.type = "send" sappend(srow) if stotal == 4: break stotal += 1 continue recv_date = rrow.date if send_date > recv_date: srow.type = "send" sappend(srow) if stotal == 4: break stotal += 1 continue rrow.type = "recv" sappend(rrow) if stotal == 4: break stotal += 1 rindex += 1 if rindex < rtotal: rrow = rrows[rindex] else: srow.type = "send" sappend(srow) if stotal == 4: break stotal += 1 continue recv_date = rrow.date if send_date > recv_date: srow.type = "send" sappend(srow) if stotal == 4: break stotal += 1 continue rrow.type = "recv" sappend(rrow) if stotal == 4: break stotal += 1 rindex += 1 if rindex < rtotal: rrow = rrows[rindex] else: srow.type = "send" sappend(srow) if stotal == 4: break stotal += 1 continue recv_date = rrow.date if send_date > recv_date: srow.type = "send" sappend(srow) if stotal == 4: break stotal += 1 continue rrow.type = "recv" sappend(rrow) if stotal == 4: break stotal += 1 rindex += 1 if rindex < rtotal: rrow = rrows[rindex] else: srow.type = "send" sappend(srow) if stotal == 4: break stotal += 1 continue recv_date = rrow.date if send_date > recv_date: srow.type = "send" sappend(srow) stotal += 1 break rrow.type = "recv" sappend(rrow) stotal += 1 break while stotal < 5: if rindex < rtotal: rrow = rrows[rindex] else: break rrow.type = "recv" sappend(rrow) rindex += 1 stotal += 1 date_represent = stable.date.represent status_represent = stable.status.represent site_ids = [] for row in shipments: if row.type == "send": site_ids += [ row.site_id, row.to_site_id, ] else: site_ids += [ row.site_id, row.from_site_id, ] #sites = org_SiteRepresent(show_type = False).bulk(list(set(site_ids))) sites = S3Represent(lookup="org_site").bulk(list(set(site_ids))) sites_get = sites.get transport_opts = { "Air": ICON("plane"), "Sea": ICON("ship"), "Road": ICON("truck"), "Hand": ICON("hand-grab"), } transport_opts_get = transport_opts.get filing_opts = { SHIP_DOC_PENDING: ICON("close"), SHIP_DOC_COMPLETE: ICON("check"), } filing_opts_get = filing_opts.get shipment_rows = [ DIV( DIV( T("Date"), _class="columns medium-2", ), DIV( T("in/out"), _class="columns medium-1", ), DIV( T("From"), _class="columns medium-1", ), DIV( T("To"), _class="columns medium-1", ), DIV( T("WB/GRN"), _class="columns medium-4", ), DIV( T("Trans."), _class="columns medium-1", ), DIV( T("Status"), _class="columns medium-1", ), DIV( ICON("briefcase"), _class="columns medium-1", ), _class="ship-card row", ), ] sappend = shipment_rows.append for row in shipments: if row.type == "send": in_out = ICON("arrow-right") from_site_id = row.site_id to_site_id = row.to_site_id shipment_ref = row.send_ref url = URL( c="inv", f="send", args=[row["inv_send.id"]], ) else: in_out = ICON("arrow-left") from_site_id = row.from_site_id to_site_id = row.site_id shipment_ref = row.recv_ref url = URL( c="inv", f="recv", args=[row.id], ) sappend( DIV( DIV( date_represent(row.date), _class="columns medium-2", ), DIV( in_out, _class="columns medium-1", ), DIV( sites_get(from_site_id), _class="columns medium-1", ), DIV( sites_get(to_site_id), _class="columns medium-1", ), DIV( A( shipment_ref, _href=url, ), _class="columns medium-4", ), DIV( transport_opts_get(row.transport_type), _class="columns medium-1", ), DIV( status_represent(row.status), _class="columns medium-1", ), DIV( filing_opts_get(row.filing_status), _class="columns medium-1", ), _class="ship-card row", )) shipments = DIV(*shipment_rows) # Alerts table = s3db.auth_user_notification query = (table.user_id == user_id) & \ (table.deleted == False) rows = db(query).select( table.name, table.url, orderby=~table.created_on, ) alert_rows = [] for row in rows: alert_rows.append( DIV( A( DIV(ICON("bell-o"), _class="columns medium-1"), DIV(row.name, _class="columns medium-11"), _href=row.url, _target="_blank", ), _class="alert-card row", )) alerts = DIV(*alert_rows) # Capacity # Define the Pivot Table r = s3_request("inv", "inv_item") r.customise_resource() resource = s3db.resource("inv_inv_item") report = S3Report() report.resource = resource capacity = report.widget( r, widget_id="capacity", ajaxurl=URL(c="inv", f="inv_item", args="report.json"), ) # KPI # Which Warehouses are we responsible for? wtable = s3db.inv_warehouse gtable = db.auth_group mtable = db.auth_membership query = (mtable.user_id == user_id) & \ (mtable.deleted == False) & \ (mtable.group_id == gtable.id) & \ (gtable.uuid.belongs("ORG_ADMIN", "logs_manager", "wh_operator", )) realms = db(query).select(mtable.pe_id) realms = list(set([row.pe_id for row in realms])) if None in realms: realms.remove(None) # Lookup Default Realm from s3db.pr import pr_default_realms default_realms = pr_default_realms(user.pe_id) realms = realms + default_realms from s3db.pr import pr_get_descendants child_pe_ids = pr_get_descendants(realms, entity_types=["inv_warehouse"]) warehouses = db(wtable.pe_id.belongs(realms + child_pe_ids)).select( wtable.site_id, wtable.name, wtable.free_capacity, ) wh_site_ids = [row.site_id for row in warehouses] itable = s3db.inv_inv_item fields = [ "site_id", "total_weight", "total_volume", "quantity", # extra_fields "item_pack_id$quantity", # extra_fields "item_id.weight", # extra_fields "item_id.volume", # extra_fields ] iresource = s3db.resource( "inv_inv_item", filter=(itable.site_id.belongs(wh_site_ids)), ) rows = iresource.select(fields, as_rows=True) stockpile_weight = 0 stockpile_volume = 0 for row in rows: stockpile_weight += row["inv_inv_item.total_weight"]() stockpile_volume += row["inv_inv_item.total_volume"]() fields = [ "id", "track_item.total_weight", "track_item.total_volume", "track_item.quantity", # extra_fields "track_item.item_pack_id$quantity", # extra_fields "track_item.item_id$weight", # extra_fields "track_item.item_id$volume", # extra_fields ] query = (stable.status.belongs([SHIP_STATUS_SENT, SHIP_STATUS_RECEIVED, SHIP_STATUS_RETURNING, ])) & \ (stable.date > SEASON_START) if SEASON_END: query &= (stable.date > SEASON_END) sresource = s3db.resource("inv_send", filter=query) srows = sresource.select(fields, as_rows=True) num_shipments = len(set([row["inv_send.id"] for row in srows])) shipments_weight = 0 shipments_volume = 0 for row in srows: weight = row["inv_track_item.total_weight"]() try: shipments_weight += weight except TypeError: # NONE returned: ignore pass volume = row["inv_track_item.total_volume"]() try: shipments_volume += volume except TypeError: # NONE returned: ignore pass float_represent = IS_FLOAT_AMOUNT.represent free_capacities = UL() for row in warehouses: free_capacities.append( LI("%s: %s m3" % (row.name, float_represent(row.free_capacity, precision=1)))) kpi = UL( LI("%s: %s kg" % (T("Total weight stockpiled"), float_represent(stockpile_weight, precision=1))), LI("%s: %s m3" % (T("Total volume stockpiled"), float_represent(stockpile_volume, precision=1))), LI("%s %s: %s" % (T("Number of Shipments sent"), SEASON, num_shipments)), LI("%s %s: %s kg" % (T("Total weight sent"), SEASON, float_represent(shipments_weight, precision=1))), LI("%s %s: %s m3" % (T("Total volume sent"), SEASON, float_represent(shipments_volume, precision=3))), LI("%s: %s" % (T("Number of warehouses"), len(warehouses))), LI("%s:" % T("Remaining stockpile capacities available"), free_capacities), ) # Preparedness Checklist #checklist = UL() output = { "title": T("Dashboard"), "shipments": shipments, "alerts": alerts, "capacity": capacity, "kpi": kpi, #"checklist": checklist, } # Custom view self._view(THEME, "inv_dashboard.html") return output
def layout(item): """ Layout Method (Item Renderer) """ # Manage flags: hide any disabled/unauthorized items if not item.authorized and not item.opts.always_display: item.enabled = False item.visible = False elif item.enabled is None or item.enabled: item.enabled = True item.visible = True if item.enabled and item.visible: items = item.render_components() if item.parent is not None: if item.attr._class: classes = item.attr._class.split(" ") else: classes = [] if item.parent.parent is None: # Item at the top-level? toplevel = True #if item.opts.right: # classes.append("menu-right") else: toplevel = False if item.components: # Menu item with Dropdown if item.get_first(enabled=True): classes.append( "is-dropdown-submenu-parent") # Prevent FoUC _class = " ".join(classes) return LI( A( item.label, _href=item.url(), _id=item.attr._id, ), UL( items, _class="menu", ), _class=_class, ) else: # Menu item without Drop-Down if toplevel: item_url = item.url() #if item_url == URL(c="default", f="index"): # classes.append("menu-home") if item.selected: classes.append("active") _class = " ".join(classes) icon = item.opts.icon if icon: label = LABEL(ICON(icon), item.label) else: label = item.label return LI( A( label, _href=item_url, _id=item.attr._id, _target=item.attr._target, ), _class=_class, ) else: # Submenu item if isinstance(item.label, dict): if "id" in item.label: return S3MainMenuDefaultLayout.checkbox_item( item) elif "name" in item.label: label = item.label["name"] else: return None else: label = item.label link = A( label, _href=item.url(), _id=item.attr._id, _target=item.attr._target, ) _class = " ".join(classes) return LI( link, _class=_class, ) else: # The main menu itself # Arrange items left/right #right = [] #left = [] #for item in items: # if "menu-right" in item["_class"]: # item.remove_class("menu-right") # right.append(item) # else: # left.append(item) #right.reverse() # Reverse if right-to-left #if current.response.s3.rtl: # right, left = left, right left = UL( items, _class="menu dropdown", ) left["_data-dropdown-menu"] = "" #right = UL(right, # _class = "menu dropdown", # ) #right["_data-dropdown-menu"] = "" # Build top-bar HTML return NAV( DIV( left, _class="top-bar-left", ), #DIV(right, # _class = "top-bar-right", # ), _class="top-bar", ) else: return None