diff --git a/cloud/routes.py b/cloud/routes.py index 504b4ab..9cc0594 100644 --- a/cloud/routes.py +++ b/cloud/routes.py @@ -485,6 +485,70 @@ def project_landing(project_url): template_name=template_name) +@blueprint.route('/p//browse') +@project_view() +def project_browse(project: pillarsdk.Project): + """Project view displaying all top-level nodes. + + We render a regular project view, but we introduce an additional template + variable: browse. By doing that we prevent the regular project view + from loading and fetch via AJAX a "group" node-like view instead (see + project_browse_view_nodes). + """ + return render_template( + 'projects/view.html', + api=system_util.pillar_api(), + project=project, + node=None, + show_project=True, + browse=True, + og_picture=None, + navigation_links=[], + extension_sidebar_links=None,) + + +@blueprint.route('/p//browse/nodes') +@project_view() +def project_browse_view_nodes(project: pillarsdk.Project): + """Display top-level nodes for a Project. + + This view is always meant to be served embedded, as part of project_browse. + """ + api = system_util.pillar_api() + # Get top level nodes + projection = { + 'project': 1, + 'name': 1, + 'picture': 1, + 'node_type': 1, + 'properties.order': 1, + 'properties.status': 1, + 'user': 1, + 'properties.content_type': 1, + 'permissions.world': 1} + where = { + 'project': project['_id'], + 'parent': {'$exists': False}, + 'properties.status': 'published', + '_deleted': {'$ne': True} + } + + try: + nodes = Node.all({ + 'projection': projection, + 'where': where, + 'sort': [('properties.order', 1), ('name', 1)]}, api=api) + except pillarsdk.exceptions.ForbiddenAccess: + return render_template('errors/403_embed.html') + nodes = nodes._items + + for child in nodes: + child.picture = get_file(child.picture, api=api) + return render_template( + 'projects/browse_embed.html', + nodes=nodes) + + def project_settings(project: pillarsdk.Project, **template_args: dict): """Renders the project settings page for Blender Cloud projects. diff --git a/src/templates/projects/browse_embed.pug b/src/templates/projects/browse_embed.pug new file mode 100644 index 0000000..5ab4b21 --- /dev/null +++ b/src/templates/projects/browse_embed.pug @@ -0,0 +1,27 @@ +| {% from '_macros/_asset_list_item.html' import asset_list_item %} +include ../../../../pillar/src/templates/mixins/components +| {% block body %} +#node-container + section.d-flex + h4.p-4 Browse + + section.node-details-description.px-4. + Browse project + + section.container-fluid + | {% if nodes %} + + +card-deck(id="asset_list_explore", class="pl-4") + | {% for node in nodes %} + | {{ asset_list_item(node, current_user) }} + | {% endfor %} + | {% else %} + .list-node-children-container + .list-node-children-empty No items... yet! + | {% endif %} + + script. + // Generate GA pageview + ga('send', 'pageview', location.pathname); + +| {% endblock %} diff --git a/src/templates/projects/view.pug b/src/templates/projects/view.pug index c04d74a..5488872 100644 --- a/src/templates/projects/view.pug +++ b/src/templates/projects/view.pug @@ -240,7 +240,8 @@ link(href="{{ url_for('static_cloud', filename='assets/css/project-main.css') }} | {% endif %} #project_context | {% block project_context %} - | {% if show_project %} + | {% if show_project and not browse %} + | {# Embed the project view only if we are not exploring it. #} | {% include "projects/view_embed.html" %} | {% endif %} | {% endblock project_context %} @@ -496,6 +497,11 @@ script. } $('.project-mode-view').displayAs('inline-block'); $('.project-mode-edit').hide(); + + {% if browse %} + let url = "{{url_for('cloud.project_browse_view_nodes', project_url=project.url)}}"; + loadProjectContent(url); + {% endif %} } else { displayNode(nodeId, false); }