diff --git a/src/templates/organizations/index.pug b/src/templates/organizations/index.pug index 53c222c4..d61e9b3b 100644 --- a/src/templates/organizations/index.pug +++ b/src/templates/organizations/index.pug @@ -1,210 +1,10 @@ | {% extends 'layout.html' %} -| {% from '_macros/_navigation.html' import navigation_tabs %} - | {% set title = 'organizations' %} | {% block page_title %}Organizations{% endblock %} -| {% block og %} -meta(property="og:title", content="Dashboard") -meta(name="twitter:title", content="Blender Cloud") - -meta(property="og:url", content="https://cloud.blender.org/{{ request.path }}") -meta(property="og:type", content="website") - -meta(property="og:image", content="{{ url_for('static', filename='assets/img/backgrounds/cloud_services_oti.jpg')}}") -meta(name="twitter:image", content="{{ url_for('static', filename='assets/img/backgrounds/cloud_services_oti.jpg')}}") -| {% endblock %} - | {% block body %} -.dashboard-container - section.dashboard-main - | {{ navigation_tabs(title) }} - - section#projects - - | {% if can_create_organization %} - nav#sub-nav-tabs.projects - ul#sub-nav-tabs__list - li.result#create_organization_result_panel - li.create - button.btn.btn-outline-success(onclick='createNewOrganization(this)') - i.pi-plus - | Create Organization - | {% endif %} - - nav.nav-tabs__tab.active#own_projects - ul.projects__list - | {% if organizations %} - | {% for organization in organizations['_items'] %} - | {% set link_url = url_for('pillar.web.organizations.view_embed', organization_id=organization._id) %} - li.projects__list-item( - data-url="{{ link_url }}", - id="organization-{{ organization._id }}") - a.projects__list-thumbnail( - href="{{ link_url }}") - i.pi-users - .projects__list-details - a.title(href="{{ link_url }}") - | {{ organization.name }} - - ul.meta - li(title="Members") - | {{ organization.members|hide_none|count }} Member{{ organization.members|hide_none|count|pluralize }} - | {% if (organization.unknown_members|count) != 0 %} - | ({{ organization.unknown_members|hide_none|count }} pending) - | {% endif %} - li(title="Seats") - | {{ organization.seat_count }} Seat{{ organization.seat_count|pluralize }} - - | {% endfor %} - | {% else %} - li.projects__list-item - a.projects__list-thumbnail - i.pi-blender-cloud - .projects__list-details - span Create an Organization to get started! - | {% endif %} - - section.dashboard-secondary - section.box - #item-details - -| {% endblock %} - - -| {% block footer_scripts %} -script(src="{{ url_for('static_pillar', filename='assets/js/vendor/jquery.typeahead-0.11.1.min.js')}}") -script(src="{{ url_for('static_pillar', filename='assets/js/vendor/jquery.autocomplete-0.22.0.min.js') }}", async=true) - -script. - - /* Returns a more-or-less reasonable message given an error response object. */ - function xhrErrorResponseMessage(err) { - if (typeof err.responseJSON == 'undefined') - return err.statusText; - - if (typeof err.responseJSON._error != 'undefined' && typeof err.responseJSON._error.message != 'undefined') - return err.responseJSON._error.message; - - if (typeof err.responseJSON._message != 'undefined') - return err.responseJSON._message - - return err.statusText; - } - - /** - * Open an organization in the #item-details div. - */ - function item_open(item_id, pushState) - { - if (item_id === undefined ) { - throw new ReferenceError("item_open(" + item_id + ") called."); - } - - // Style elements starting with item_type and dash, e.g. "#job-uuid" - var clean_classes = 'active processing'; - var current_item = $('#organization-' + item_id); - - $('[id^="organization-"]').removeClass(clean_classes); - current_item - .removeClass(clean_classes) - .addClass('processing'); - - var item_url = '/o/' + item_id; - - $.get(item_url, function(item_data) { - $('#item-details').html(item_data); - - current_item - .removeClass(clean_classes) - .addClass('active'); - - }).fail(function(xhr) { - if (console) { - console.log('Error fetching organization', item_id, 'from', item_url); - console.log('XHR:', xhr); - } - - current_item.removeClass(clean_classes); - toastr.error('Failed to open organization'); - - if (xhr.status) { - $('#item-details').html(xhr.responseText); - } else { - $('#item-details').html('
Opening ' + item_type + ' failed. There possibly was ' + - 'an error connecting to the server. Please check your network connection and ' + - 'try again.
'); - } - }); - - // Determine whether we should push the new state or not. - pushState = (typeof pushState !== 'undefined') ? pushState : true; - if (!pushState) return; - - // Push the correct URL onto the history. - var push_state = {itemId: item_id}; - - window.history.pushState( - push_state, - 'Organization: ' + item_id, - item_url - ); - } - - $('li.projects__list-item').click(function(e){ - url = $(this).data('url'); - if (typeof url === 'undefined') return; - - window.location.href = url; - if (console) console.log(url); - - $(this).addClass('active'); - $(this).find('.projects__list-thumbnail i') - .removeAttr('class') - .addClass('pi-spin spin'); - }); - - - {% if open_organization_id %} - $(function() { item_open('{{ open_organization_id }}', false); }); - {% endif %} - - {% if can_create_organization %} - function createNewOrganization(button) { - $(button) - .attr('disabled', 'disabled') - .fadeTo(200, 0.1); - $('#create_organization_result_panel').html(''); - - // TODO: create a form to get the initial info from the user. - $.post( - '{{ url_for('pillar.web.organizations.create_new') }}', - { - name: 'New Organization', - seat_count: 1, - } - ) - .done(function(result) { - var $p = $('').text('organization created, reloading list.') - $('#create_organization_result_panel').html($p); - - window.location.href = result.location; - }) - .fail(function(err) { - var msg = xhrErrorResponseMessage(err); - $('#create_organization_result_panel').html('Error creating organization: ' + msg); - - $(button) - .fadeTo(1000, 1.0) - .queue(function() { - $(this) - .removeAttr('disabled') - .dequeue() - ; - }) - }) - ; - return false; - } - {% endif %} +.p-5.text-center + h2 Organizations Index + .lead. + See Blender Cloud template for reference. | {% endblock %} diff --git a/src/templates/projects/index_dashboard.pug b/src/templates/projects/index_dashboard.pug index fcc50df2..ca6d7f22 100644 --- a/src/templates/projects/index_dashboard.pug +++ b/src/templates/projects/index_dashboard.pug @@ -1,356 +1,16 @@ | {% extends 'layout.html' %} -| {% from '_macros/_navigation.html' import navigation_tabs %} - | {% set title = 'dashboard' %} -| {% block og %} -meta(property="og:title", content="Dashboard") -meta(name="twitter:title", content="Blender Cloud") - -meta(property="og:url", content="https://cloud.blender.org/{{ request.path }}") -meta(property="og:type", content="website") - -meta(property="og:image", content="{{ url_for('static', filename='assets/img/backgrounds/cloud_services_oti.jpg')}}") -meta(name="twitter:image", content="{{ url_for('static', filename='assets/img/backgrounds/cloud_services_oti.jpg')}}") -| {% endblock %} - | {% block page_title %} | {{current_user.full_name}} | {% endblock %} -| {% block css %} -| {{ super() }} -style. - .deleted-projects-toggle { - z-index: 10; - position: absolute; - right: 0; - font-size: 20px; - padding: 3px; - text-shadow: 0 0 2px white; - } - .deleted-projects-toggle .show-deleted { - color: #aaa; - } - .deleted-projects-toggle .hide-deleted { - color: #bbb; - } -| {% endblock %} - | {% block body %} -.dashboard-container - section.dashboard-main - | {{ navigation_tabs(title) }} - - section#projects - - nav#sub-nav-tabs.projects - ul#sub-nav-tabs__list - li.nav-tabs__list-tab.active(data-tab-toggle='own_projects') - | Own Projects - | {% if projects_user|length != 0 %} - span ({{ projects_user|length }}) - | {% endif %} - - li.nav-tabs__list-tab(data-tab-toggle='shared') - | Shared with me - | {% if projects_shared|length != 0 %} - span ({{ projects_shared|length }}) - | {% endif %} - - | {% if current_user.has_cap('subscriber') %} - li#project-create( - data-url="{{ url_for('projects.create') }}") - a.btn.btn-success( - href="{{ url_for('projects.create') }}") - i.pi-plus - | Create Project - | {% elif current_user.has_cap('can-renew-subscription') %} - li - a.btn.btn-outline-success(href="/renew", target="_blank") - i.pi-heart - | Renew subscription to create a project - | {% endif %} - - nav.nav-tabs__tab.active#own_projects - .deleted-projects-toggle - | {% if show_deleted_projects %} - a.hide-deleted(href="{{ request.base_url }}", title='Hide deleted projects') - i.pi-trash - | {% else %} - a.show-deleted(href="{{ request.base_url }}?deleted=1", title='Show deleted projects') - i.pi-trash - | {% endif %} - - ul.projects__list - | {% for project in projects_deleted %} - li.projects__list-item.deleted - span.projects__list-thumbnail - | {% if project.picture_square %} - img(src="{{ project.picture_square.thumbnail('s', api=api) }}") - | {% else %} - i.pi-blender-cloud - | {% endif %} - .projects__list-details - span.title {{ project.name }} - ul.meta - li.status.deleted Deleted - li.edit - a(href="javascript:undelete_project('{{ project._id }}')") Restore project - | {% else %} - | {% if show_deleted_projects %} - li.projects__list-item.deleted You have no recenly deleted projects. Deleted projects can be restored within a month after deletion. - | {% endif %} - | {% endfor %} - - | {% for project in projects_user %} - li.projects__list-item( - data-url="{{ url_for('projects.view', project_url=project.url) }}") - a.projects__list-thumbnail( - href="{{ url_for('projects.view', project_url=project.url) }}") - | {% if project.picture_square %} - img(src="{{ project.picture_square.thumbnail('s', api=api) }}") - | {% else %} - i.pi-blender-cloud - | {% endif %} - .projects__list-details - a.title(href="{{ url_for('projects.view', project_url=project.url) }}") - | {{ project.name }} - - ul.meta - li.status( - class="{{ project.is_private | yesno('private,public,') }}", - title="{{ project.is_private | yesno('Private Project,Public Project,') }}") - | {{ project.is_private | yesno('Private,Public,') }} - li.when(title="{{ project._created }}") {{ project._created | pretty_date }} - li.edit - a(href="{{ url_for('projects.edit', project_url=project.url) }}") Edit - | {% if project.status == 'pending' and current_user.has_cap('view-pending-nodes') %} - li.pending Not Published - | {% endif %} - | {% else %} - | {% if current_user.has_cap('subscriber') %} - li.projects__list-item(data-url="{{ url_for('projects.create') }}") - a.projects__list-thumbnail - i.pi-plus - .projects__list-details - a.title(href="{{ url_for('projects.create') }}") - | Create a project to get started! - | {% elif current_user.has_cap('can-renew-subscription') %} - li.projects__list-item(data-url="https://store.blender.org/renew-my-subscription.php") - a.projects__list-thumbnail - i.pi-plus - .projects__list-details - a.title(href="https://store.blender.org/renew-my-subscription.php") - | Renew your Blender Cloud subscription to create your own projects! - | {% else %} - li.projects__list-item(data-url="/join") - a.projects__list-thumbnail - i.pi-plus - .projects__list-details - a.title(href="/join") - | Join Blender Cloud to create your own projects! - | {% endif %} - | {% endfor %} - - section.nav-tabs__tab#shared(style='display: none') - ul.projects__list - | {% if projects_shared %} - | {% for project in projects_shared %} - li.projects__list-item( - data-url="{{ url_for('projects.view', project_url=project.url) }}") - a.projects__list-thumbnail( - href="{{ url_for('projects.view', project_url=project.url) }}") - | {% if project.picture_square %} - img(src="{{ project.picture_square.thumbnail('s', api=api) }}") - | {% else %} - i.pi-blender-cloud - | {% endif %} - .projects__list-details - a.title(href="{{ url_for('projects.view', project_url=project.url) }}") - | {{ project.name }} - - ul.meta - li.status( - class="{{ project.is_private | yesno('private,public,') }}", - title="{{ project.is_private | yesno('Private Project,Public Project,') }}") - | {{ project.is_private | yesno('Private,Public,') }} - li.when {{ project._created | pretty_date }} - li.who by {{ project.user.full_name }} - li.edit - a(href="{{ url_for('projects.edit', project_url=project.url) }}") Edit - | {% if project.status == 'pending' and current_user.has_cap('view-pending-nodes') %} - li.pending Not Published - | {% endif %} - - li.leave - span.user-remove-prompt - | Leave Project - - span.user-remove - | Are you sure? - span.user-remove-confirm( - user-id="{{ current_user.objectid }}", - project-url="{{url_for('projects.sharing', project_url=project.url)}}") - i.pi-check - | Yes, leave - span.user-remove-cancel - i.pi-cancel - | No, cancel - - | {% endfor %} - | {% else %} - li.projects__list-item - a.projects__list-thumbnail - i.pi-heart-broken - .projects__list-details - .title - | No projects shared with you... yet! - | {% endif %} - - section.dashboard-secondary - section.announcement - a(href="https://cloud.blender.org/blog/introducing-private-projects") - img.header( - src="{{ url_for('static', filename='assets/img/backgrounds/services_projects.jpg')}}") - .text - h5 - a.text-muted(href="https://cloud.blender.org/blog/introducing-private-projects") - | Projects - .lead - p. - Create and manage your own personal projects. - Upload assets and collaborate with other Blender Cloud members. - - a.btn.btn-link.btn-block( - href="https://cloud.blender.org/blog/introducing-private-projects") - | Learn More - i.pi-angle-right - - section.announcement.mt-3 - a(href="https://cloud.blender.org/blog/introducing-blender-sync") - img.header( - src="{{ url_for('static', filename='assets/img/blender_sync_header.jpg') }}") - .text - h5 - a.text-muted(href="https://cloud.blender.org/blog/introducing-blender-sync") - | Textures Browser & Settings Sync - - .lead - p. - Get the official Blender Cloud add-on: - - ul - li Save your Blender settings online, use them anywhere - li Browse over 800 textures & HDRIs within Blender - li Share Screenshots & Renders directly to Blender Cloud - - .row - .col-md-8 - a.btn.btn-outline-success.btn-block( - href="https://cloud.blender.org/r/downloads/blender_cloud-latest-bundle.zip") - i.pi-download - | Download Add-on v {{ config.BLENDER_CLOUD_ADDON_VERSION }} - .col-md-4 - a.btn.btn-link( - href="https://cloud.blender.org/blog/introducing-blender-sync") - | Learn More - i.pi-angle-right - +.p-5.text-center + h2 Index Dashboard + p.lead. + See Blender Cloud template for reference. | {% endblock %} - | {% block footer_scripts %} -script. - $(document).ready(function() { - - $('li.projects__list-item').click(function(e){ - url = $(this).data('url'); - if (typeof url === 'undefined') return; - - window.location.href = url; - if (console) console.log(url); - - $(this).addClass('active'); - $(this).find('.projects__list-thumbnail i') - .removeAttr('class') - .addClass('pi-spin spin'); - }); - - // Tabs behavior - var $nav_tabs_list = $('#sub-nav-tabs__list'); - var $nav_tabs = $nav_tabs_list.find('li.nav-tabs__list-tab'); - $nav_tabs.on('click', function(e){ - e.preventDefault(); - - $nav_tabs.removeClass('active'); - $(this).addClass('active'); - - $('.nav-tabs__tab').hide(); - $('#' + $(this).attr('data-tab-toggle')).show(); - }); - - // Create project - $('#project-create').on('click', function(e){ - e.preventDefault(); - - $(this).addClass('disabled'); - $('a', this).html(' Creating project...'); - - window.location.href = $(this).data('url'); - }); - - // Leave project - var $projects_list = $('ul.projects__list'); - $projects_list.find('span.user-remove-prompt').on('click', function(e){ - e.stopPropagation(); - e.preventDefault(); - - $(this).next().show(); - $(this).hide(); - }); - - $projects_list.find('span.user-remove-cancel').on('click', function(e){ - e.stopPropagation(); - e.preventDefault(); - - $(this).parent().prev().show(); - $(this).parent().hide(); - }); - - $projects_list.find('span.user-remove-confirm').on('click', function(e){ - e.stopPropagation(); - e.preventDefault(); - var parent = $(this).closest('.projects__list-item'); - - function removeUser(userId, projectUrl){ - $.post(projectUrl, {user_id: userId, action: 'remove'}) - .done(function (data) { - parent.remove(); - }); - } - - removeUser($(this).attr('user-id'), $(this).attr('project-url')); - }); - - hopToTop(); // Display jump to top button - }); - - - var patch_url = '{{ url_for('projects.patch.patch_project', project_id='PROJECTID') }}'; - function undelete_project(project_id) { - console.log('undeleting project', project_id); - $.ajax({ - url: patch_url.replace('PROJECTID', project_id), - method: 'PATCH', - data: JSON.stringify({'op': 'undelete'}), - contentType: 'application/json' - }) - .done(function(data, textStatus, jqXHR) { - location.href = jqXHR.getResponseHeader('Location'); - }) - .fail(function(err) { - toastr.error(xhrErrorResponseMessage(err), 'Undeletion failed'); - }) - } | {% endblock %} diff --git a/src/templates/projects/view.pug b/src/templates/projects/view.pug index 8151fbe6..d0b1aeb1 100644 --- a/src/templates/projects/view.pug +++ b/src/templates/projects/view.pug @@ -1,641 +1,11 @@ | {% extends 'layout.html' %} -| {% from '_macros/_add_new_menu.html' import add_new_menu %} | {% block page_title %}{{ project.name }}{% endblock%} | {% set title = 'project' %} -| {% block og %} -meta(property="og:type", content="website") - -| {% if og_picture %} -meta(property="og:image", content="{{ og_picture.thumbnail('l', api=api) }}") -meta(name="twitter:image", content="{{ og_picture.thumbnail('l', api=api) }}") -| {% elif node and node.picture %} -meta(property="og:image", content="{{ node.picture.thumbnail('l', api=api) }}") -meta(name="twitter:image", content="{{ node.picture.thumbnail('l', api=api) }}") -| {% elif project.picture_header %} -meta(property="og:image", content="{{ project.picture_header.thumbnail('l', api=api) }}") -meta(name="twitter:image", content="{{ project.picture_header.thumbnail('l', api=api) }}") -| {% endif %} - -| {% if show_project %} -meta(property="og:title", content="{{ project.name }} - Blender Cloud") -meta(name="twitter:title", content="{{ project.name }} - Blender Cloud") -meta(property="og:description", content="{{ project.summary }}") -meta(name="twitter:description", content="{{ project.summary }}") - -meta(property="og:url", content="{{ url_for('projects.view', project_url=project.url, _external=True) }}") -| {% else %} - -| {% if node %} -meta(property="og:title", content="{{ node.name }} - Blender Cloud") -meta(name="twitter:title", content="{{ node.name }} on Blender Cloud") - -| {% if node.node_type == 'post' %} - -| {% if node.properties.content %} -meta(property="og:description", content="{{ node.properties.content | truncate(180) }}") -meta(name="twitter:description", content="{{ node.properties.content | truncate(180) }}") -| {% else %} -meta(property="og:description", content="Blender Cloud, your source for open content and training") -meta(name="twitter:description", content="Blender Cloud, your source for open content and training") -| {% endif %} - -| {% else %} - -| {% if node.description %} -meta(property="og:description", content="{{ node.description | truncate(180) }}") -meta(name="twitter:description", content="{{ node.description | truncate(180) }}") -| {% else %} -meta(property="og:description", content="Blender Cloud, your source for open content and training") -meta(name="twitter:description", content="Blender Cloud, your source for open content and training") -| {% endif %} - -| {% endif %} - -meta(property="og:url", content="{{url_for('projects.view_node', project_url=project.url, node_id=node._id)}}") -| {% else %} -meta(property="og:title", content="{{ project.name }} Blog on Blender Cloud") -meta(name="twitter:title", content="{{ project.name }} Blog on Blender Cloud") -meta(property="og:description", content="{{ project.summary }}") -meta(name="twitter:description", content="{{ project.summary }}") - -meta(property="og:url", content="{{url_for('projects.view', project_url=project.url, _external=True)}}") -| {% endif %} - -| {% endif %} -| {% endblock %} - -| {% block head %} -link(href="{{ url_for('static_pillar', filename='assets/jstree/themes/default/style.min.css') }}", rel="stylesheet") -| {% if node %} -link(rel="amphtml", href="{{ url_for('nodes.view', node_id=node._id, _external=True, format='amp') }}") -| {% endif %} - -script(src="{{ url_for('static_pillar', filename='assets/js/vendor/videojs-6.2.8.min.js') }}") -script(src="{{ url_for('static_pillar', filename='assets/js/vendor/videojs-ga-0.4.2.min.js') }}") -script(src="{{ url_for('static_pillar', filename='assets/js/vendor/videojs-hotkeys-0.2.20.min.js') }}") -| {% endblock %} - -| {% block css %} -link(href="{{ url_for('static_pillar', filename='assets/css/font-pillar.css') }}", rel="stylesheet") -link(href="{{ url_for('static_pillar', filename='assets/css/project-main.css') }}", rel="stylesheet") -| {% endblock %} - | {% block body %} -#project-container - #project-side-container - #project_sidebar.bg-white - ul.project-tabs.p-0 - li.tabs-thumbnail(class="{% if project.picture_square %}image{% endif %}") - a(href="{{url_for('projects.view', project_url=project.url)}}") - #project-loading - i.pi-spin - | {% if project.picture_square %} - img(src="{{ project.picture_square.thumbnail('b', api=api) }}") - | {% else %} - i.pi-home - | {% endif %} - - li.tabs-browse( - title="Browse", - data-toggle="tooltip", - data-placement="right", - class="active") - a(href="{{url_for('projects.view', project_url=project.url, _external=True)}}") - i.pi-folder - - | {% if not project.is_private %} - | {% if current_user_is_subscriber %} - li.tabs-search( - title="Search", - data-toggle="tooltip", - data-placement="right") - a(href="{{ url_for('projects.search', project_url=project.url, _external=True)}} ") - i.pi-search - | {% else %} - li.tabs-search( - title="Search (subscribers only)", - data-toggle="tooltip", - data-placement="right") - a(href="{{ url_for('cloud.join') }}") - i.pi-search - | {% endif %} - | {% endif %} - | {{ extension_sidebar_links }} - - | {% if project.has_method('PUT') %} - li( - title="Edit Project", - data-toggle="tooltip", - data-placement="right") - a(href="{{ url_for('projects.edit', project_url=project.url) }}") - i.pi-cog - | {% endif %} - - - #project_nav(class="{{ title }}") - #project_nav-container - | {% if title != 'about' %} - #project_nav-header.bg-white - a.project-title.p-2.font-weight-bold.text-dark( - href="{{url_for('projects.view', project_url=project.url, _external=True)}}") - | {{ project.name }} - - | {% block project_tree %} - #project_tree.bg-white - | {% endblock project_tree %} - | {% endif %} - - - #project_context-container - | {% if project.has_method('PUT') %} - #project_context-header.bg-white - span#status-bar - - ul.project-edit-tools.disabled - li.dropdown - button#item_add.project-mode-view.btn.btn-sm.btn-outline-secondary.dropdown-toggle( - type="button", - data-toggle="dropdown", - aria-haspopup="true", - aria-expanded="false") - i.button-add-icon.pi-collection-plus - | New... - - ul.dropdown-menu.add_new-menu - | {{ add_new_menu(project.node_types) }} - - li.button-edit - a#item_edit.project-mode-view.btn.btn-sm.btn-outline-secondary.ml-2( - href="javascript:void(0);", - title="Edit", - data-project_id="{{project._id}}") - i.button-edit-icon.pi-edit - | Edit Project - - li.dropdown - button.dropdown-toggle.project-mode-view.btn.btn-sm.btn-outline-secondary.mx-2( - type="button", - data-toggle="dropdown", - aria-haspopup="true", - aria-expanded="false") - i.pi-more-vertical.p-0 - - ul.dropdown-menu - | {% if current_user.has_cap('admin') %} - li.dropdown-item - a#item_featured( - href="javascript:void(0);", - title="Feature on project's homepage", - data-toggle="tooltip", - data-placement="left") - i.pi-star - | Toggle Featured - - li.dropdown-item - a#item_toggle_public( - href="javascript:void(0);", - title="Make it accessible to anyone", - data-toggle="tooltip", - data-placement="left") - i.pi-lock-open - | Toggle Public - | {% endif %} - - li.dropdown-item - a#item_toggle_projheader( - href="javascript:void(0);", - title="Feature as project's header", - data-toggle="tooltip", - data-placement="left") - i.pi-star - | Toggle Project Header video - - li.dropdown-item.button-move - a#item_move( - href="javascript:void(0);", - title="Move into a folder...", - data-toggle="tooltip", - data-placement="left") - i.button-move-icon.pi-move - | Move - - li.dropdown-item.button-delete - a#item_delete( - href="javascript:void(0);", - title="Can be undone within a month", - data-toggle="tooltip", - data-placement="left") - i.pi-trash - | Delete Project - - // Edit Mode - li.button-cancel - a#item_cancel.project-mode-edit.btn.btn-outline-secondary( - href="javascript:void(0);", - title="Cancel changes") - i.button-cancel-icon.pi-cancel - | Cancel - - li.button-save - a#item_save.project-mode-edit.btn.btn-outline-success.mx-2( - href="javascript:void(0);", - title="Save changes") - i.button-save-icon.pi-check - | Save Changes - - | {% endif %} - - | {% set utm_source = request.args.get('utm_source') %} - | {% if config.UTM_LINKS and utm_source in config.UTM_LINKS %} - #utm_container - a(href="{{config.UTM_LINKS[utm_source]['link']}}") - img(src="{{config.UTM_LINKS[utm_source]['image']}}", alt="gift", class="img-responsive") - | {% endif %} - #project_context - | {% block project_context %} - | {% if show_project %} - | {% include "projects/view_embed.html" %} - | {% endif %} - | {% endblock project_context %} - - #overlay-mode-move-container - .overlay-container - .title - i.pi-angle-left - | Select the folder where you want to move it - .buttons - button#item_move_accept.move.disabled - | Select a Folder - button#item_move_cancel.cancel - i.pi-cancel - | Cancel - +.p-5.text-center + h2 Project View + .lead. + See Blender Cloud for reference. | {% endblock %} - -| {% block footer_container %}{% endblock %} - -| {% block footer_scripts_pre %} - -| {% if project.has_method('PUT') %} -| {# JS containing the Edit, Add, Featured, and Move functions #} -script(type="text/javascript", src="{{ url_for('static_pillar', filename='assets/js/project-edit.min.js') }}") -| {% endif %} - -script. - function updateToggleProjHeaderMenuItem() { - var $toggle_projheader = $('#item_toggle_projheader'); - - if (ProjectUtils.isProject()) { - $toggle_projheader.hide(); - return; - } - if (ProjectUtils.nodeType() == 'asset') { - $toggle_projheader.show(); - } else { - $toggle_projheader.hide(); - } - } - $(updateToggleProjHeaderMenuItem); - - // Function to update the interface on loadNodeContent, and edit/saving assets - function updateUi(nodeId, mode) { - - if (mode === 'view') { - $('.project-mode-view').displayAs('inline-block'); - $('.project-mode-edit').hide(); - - $("#node-edit-form").unbind("submit"); - $("#item_save").unbind("click"); - $("#item_cancel").unbind("click"); - } else if (mode === 'edit') { - $('.project-mode-view').hide(); - $('.project-mode-edit').displayAs('inline-block'); - } else { - if (console) console.log('Invalid mode:', mode); - } - - // Prevent flicker by scrolling to top. - $("#project_context-container").scrollTop(0); - - // Enable specific items under the Add New dropdown - if (ProjectUtils.nodeType() === 'group') { - addMenuEnable(['asset', 'group']); - - } else if (ProjectUtils.nodeType() === 'group_texture') { - addMenuEnable(['group_texture', 'texture']); - - } else if (ProjectUtils.nodeType() === 'group_hdri') { - addMenuEnable(['group_hdri', 'hdri']); - - } else if (!ProjectUtils.isProject()) { - addMenuEnable(false); - } - - updateToggleProjHeaderMenuItem(); - - // Set the page title on the document - var page_title = $('#node-title').text() + " - {{ project.name }} — Blender Cloud"; - DocumentTitleAPI.set_page_title(page_title); - - // TODO: Maybe remove this, now it's also in loadNodeContent(), but double-check - // it's done like that in all users of updateUi(). - $('#project-loading').removeAttr('class'); - } -| {% endblock %} - -| {% block footer_scripts %} -script(src="{{ url_for('static_pillar', filename='assets/jstree/jstree.min.js') }}") - -script. - {% if show_project %} - ProjectUtils.setProjectAttributes({projectId: "{{project._id}}", isProject: true, nodeId: ''}); - {% else %} - {% if node %} - ProjectUtils.setProjectAttributes({projectId: "{{project._id}}", isProject: false, nodeId: '{{node._id}}'}); - {% endif %} - {% endif %} - - var projectTree = document.getElementById('project_tree'); - - var urlNodeMove = "{{url_for('projects.move_node')}}"; - var urlNodeFeature = "{{url_for('projects.add_featured_node')}}"; - var urlNodeDelete = "{{url_for('projects.delete_node')}}"; - var urlNodeTogglePublic = "{{url_for('projects.toggle_node_public')}}"; - var urlNodeToggleProjHeader = "{{url_for('projects.toggle_node_project_header')}}"; - var urlProjectDelete = "{{url_for('projects.delete')}}"; - var urlProjectEdit = "{{url_for('projects.edit', project_url=project.url)}}"; - - - function loadNodeContent(url, nodeId) { - $('#project-loading').addClass('active'); - $.get(url, function(dataHtml) { - // Update the DOM injecting the generate HTML into the page - $('#project_context').html(dataHtml); - }) - .done(function(){ - updateUi(nodeId, 'view'); - }) - .fail(function(dataResponse) { - $('#project_context').html($('')); - $('#server_error').attr('src', url); - }) - .always(function(){ - $('#project-loading').removeAttr('class'); - $('.button-edit-icon').addClass('pi-edit').removeClass('pi-spin spin'); - }); - } - - - function loadProjectContent(url) { - $('#project-loading').addClass('active'); - - $.get(url, function(dataHtml) { - // Update the DOM injecting the generated HTML into the page - $('#project_context').html(dataHtml); - }) - .done(function() { - updateUi('', 'view'); - addMenuEnable(); - addMenuDisable(['texture']); - }) - .fail(function(dataResponse) { - $('#project_context').html($('')); - $('#server_error').attr('src', url); - }) - .always(function(){ - $('#project-loading').removeAttr('class'); - $('.button-edit-icon').addClass('pi-edit').removeClass('pi-spin spin'); - }); - } - - - function displayStorage(storageNodeId, path) { - var url = '/nodes/' + storageNodeId + '/view?path=' + path; - loadNodeContent(url); - } - - - function displayNode(nodeId, pushState) { - // Remove the 'n_' suffix from the id - if (nodeId.substring(0, 2) == 'n_') { - nodeId = nodeId.substr(2); - } - - var url = '/nodes/' + nodeId + '/view'; - loadNodeContent(url, nodeId); - - // Determine whether we should push the new state or not. - pushState = (typeof pushState !== 'undefined') ? pushState : true; - if (!pushState) return; - - // Push the correct URL onto the history. - var push_state = {nodeId: nodeId, url: url}; - var push_url = '{{url_for("projects.view", project_url=project.url)}}' + nodeId; - // console.log('Pushing state ', push_state, ' with URL ', push_url); - window.history.pushState( - push_state, - 'Node ' + nodeId, // TODO: use sensible title - push_url - ); - } - - function redirectToNode(nodeId) { - var generic_url = '{{ url_for("projects.view_node", project_url=project.url, node_id="theNodeId") }}'; - var node_url = generic_url.replace('theNodeId', nodeId); - - // This makes the user skip the current page when using the 'back' button, - // i.e. it works as a proper redirect. - location.replace(node_url); - } - - window.onpopstate = function(event) { - var state = event.state; - // console.log('State popped. location:', document.location, 'state:', state); - - // Deselect any selected node. We'll select the visited node (if any) later on. - var jstreeAPI = $(projectTree).jstree(true); - jstreeAPI.deselect_all(true); - - if (state == null) { - // Went back to the project. - displayProject(); - return; - } - - // Went back to a node. - loadNodeContent(state.url, state.nodeId); - - // Annoying hack because jstreeAPI.select_node() can only suppress the - // changed.jstree event, and NOT the selected_node.jstree event. - projectTree.dataset.ignoreSelectNode = true; - jstreeAPI.select_node('n_' + state.nodeId, true); - delete projectTree.dataset.ignoreSelectNode; - }; - - function displayProject() { - var url = "{{url_for('projects.view', project_url=project.url, embed=1)}}"; - loadProjectContent(url); - } - - - function getHashId() { - if (console) - console.log('getHashId() should not be used any more!'); - } - - /* Loaded once, on page load */ - function loadContent() { - - var nodeId = ProjectUtils.nodeId(); - var isProject = ProjectUtils.isProject(); - if (isProject) { - // No need to asynchronously load the project, as it's embedded by Jinja. - // displayProject() is still needed, though, when people use 'back' to go there. - if (location.hash) { - // Handle old-style /p/{url}/#node-ID links, and redirect them to the correct spot. - redirectToNode(location.hash.substr(1)); - } - $('.project-mode-view').displayAs('inline-block'); - $('.project-mode-edit').hide(); - } else { - displayNode(nodeId, false); - } - - $(projectTree).jstree({ - 'core': { - 'data': function (obj, callback) { - if(obj.id === '#') { //tree root - if (isProject) { - $.getJSON("{{url_for('projects.jstree', project_url=project.url)}}", function (jsonObject) { - callback.call(this, jsonObject['items']); - }); - } else { - $.getJSON('/nodes/' + nodeId + '/jstree', function(jsonObject) { - callback.call(this, jsonObject['items']); - }); - } - } else { //normal node - var childNodeId; - if (obj.original.type == 'group_storage') { - childNodeId = obj.original.storage_node; - $.getJSON('/nodes/' + childNodeId + '/jstree?children=1&path=' + obj.original.path, function(jsonObject) { - callback.call(this, jsonObject.children); - }); - } else { - // Remove the 'n_' suffix from the id - childNodeId = obj.id.substring(2); - $.getJSON('/nodes/' + childNodeId + '/jstree?children=1', function(jsonObject) { - callback.call(this, jsonObject.children); - }); - } - } - } - }, - "types" : { - "#": {"valid_children": ["collection"]}, - "chapter" : {"icon": "pi-folder"}, - "group" : {"icon": "pi-folder"}, - "group_texture" : {"icon": "pi-folder-texture"}, - "group_hdri" : {"icon": "pi-folder-texture", "max_children": 0}, - "group_storage" : {"icon": "pi-folder"}, - "filesystem_node" : {"icon": "pi-folder"}, - "file" : {"icon": "pi-file-archive", "max_children": 0}, - "filesystem_file" : {"icon": "pi-document", "max_children": 0}, - "image" : {"icon": "pi-image", "max_children": 0}, - "hdri" : {"icon": "pi-globe", "max_children": 0}, - "texture" : {"icon": "pi-texture", "max_children": 0}, - "video" : {"icon": "pi-film-thick", "max_children": 0}, - "blog" : {"icon": "pi-newspaper", "max_children": 0}, - "page" : {"icon": "pi-document-text", "max_children": 0}, - "default" : {"icon": "pi-document"} - }, - "plugins": ["types",] //, "state", "sort" - }); - - - var jstreeAPI = $(projectTree).jstree(true); - - $(projectTree).on("select_node.jstree", function (e, data) { - var selectedNodeId = data.node.id.substr(2); - - // Ignore events that can't be suppressed otherwise. - // This can be removed if jstreeAPI.select_node() allows suppressing - // the select_node.jstree event. - if (e.target.dataset.ignoreSelectNode === 'true') return; - - if (typeof(data.node.original.path) === 'undefined') { - var movingMode = Cookies.getJSON('bcloud_moving_node'); - - // Check if we are in the process of moving a node - if (movingMode) { - // Allow moving nodes only inside of node_type group - if (data.node.original.type != 'group' || movingMode.node_id === selectedNodeId || movingMode.node_id === ProjectUtils.parentNodeId()) { - - if (movingMode.node_type === 'texture') { - - if (data.node.original.type === 'group_texture') { - $('#item_move_accept').html('Move Here').removeClass('disabled'); - } else { - $('#item_move_accept').html('Select a Texture Folder').addClass('disabled'); - } - - } else if (movingMode.node_type === 'hdri') { - - if (data.node.original.type === 'group_hdri') { - $('#item_move_accept').html('Move Here').removeClass('disabled'); - } else { - $('#item_move_accept').html('Select an HDRi Folder').addClass('disabled'); - } - - } else { - $('#item_move_accept').html('Select a Folder').addClass('disabled'); - } - - } else { - $('#item_move_accept').html('Move Here').removeClass('disabled'); - } - } - - // Check the type of node and act accordingly - if (data.node.original.custom_view) { - window.location = data.node.a_attr.href; - } else { - var currentNodeId = ProjectUtils.nodeId(); - if (currentNodeId != selectedNodeId) { - displayNode(selectedNodeId); - } - - jstreeAPI.open_node(data.node); - } - } else { - displayStorage(data.node.original.storage_node, data.node.original.path); - jstreeAPI.toggle_node(data.node); - } - }); - }; - - {% if is_embedded_edit is not defined or is_embedded_edit %} - // Initialize the page if we are not directly editing a node (most of the time) - loadContent(); - {% endif %} - - var project_container = document.getElementById('project-container'); - - /* UI Stuff */ - $(window).on("load resize",function(){ - containerResizeY($(window).height()); - - if ($(window).width() > 480) { - project_container.style.height = (window.innerHeight - project_container.offsetTop) + "px"; - } - }); - - {% if current_user_is_subscriber %} - $(projectTree).addClass('is_subscriber'); - {% endif %} - -| {% endblock %} - -| {% block comment_scripts %} {% endblock%}