diff --git a/src/styles/_homepage.sass b/src/styles/_homepage.sass index 80cbba11..b0cd746a 100644 --- a/src/styles/_homepage.sass +++ b/src/styles/_homepage.sass @@ -126,11 +126,8 @@ size: 1.2em weight: 400 display: inline-block - padding: 15px 20px 10px 20px - border-bottom: 3px solid transparent + padding: 10px 10px - &:hover - border-color: $color-success a color: $color-success text-decoration: none diff --git a/src/styles/_organizations.sass b/src/styles/_organizations.sass new file mode 100644 index 00000000..c2998c27 --- /dev/null +++ b/src/styles/_organizations.sass @@ -0,0 +1,35 @@ +body.organizations + ul#sub-nav-tabs__list + align-items: center + display: flex + + li.result + padding: 10px 20px + li.create + margin-left: auto + + + #side + .box + +container-box + padding: 10px 20px + margin: 20px 10px + + #item-details + .organization + label + display: block + margin-top: 10px + + .input-group, + textarea, + input + width: 100% + + input + font-size: 1.1em + + + .org-admin + #admin-name + padding: 10px 0 diff --git a/src/styles/_project-dashboard.sass b/src/styles/_project-dashboard.sass index 3182112c..bfc35051 100644 --- a/src/styles/_project-dashboard.sass +++ b/src/styles/_project-dashboard.sass @@ -8,28 +8,18 @@ section#sub-nav-tabs.home, section#sub-nav-tabs.projects - background-color: $color-background-light + background-color: white border-bottom: thin solid $color-background-dark li.nav-tabs__list-tab padding: 15px 20px 10px 20px - &:hover - border-color: rgba($color-primary, .4) - &.active - border-color: $color-primary - color: $color-primary-dark - a, i - color: $color-primary-dark - - span - color: $color-text-dark-secondary - section#home background-color: $color-background-dark section.nav-tabs__tab display: none + background-color: $color-background-light &.active display: block diff --git a/src/styles/_project.sass b/src/styles/_project.sass index a0b91af3..df08e174 100644 --- a/src/styles/_project.sass +++ b/src/styles/_project.sass @@ -1212,6 +1212,9 @@ section.node-preview.group .node-details-meta-list display: inline-block + > li + padding: 0 5px + .node-details-meta-actions display: inline-block diff --git a/src/styles/base.sass b/src/styles/base.sass index 3c8c06b7..7b695a00 100644 --- a/src/styles/base.sass +++ b/src/styles/base.sass @@ -1090,8 +1090,8 @@ button, .btn #cloud-search, .tt-hint + +text-overflow-ellipsis background-color: transparent - width: 100% outline: none border: thin solid transparent border-bottom: 3px solid transparent @@ -1103,7 +1103,6 @@ button, .btn padding: 0 20px 0 40px min-height: 32px color: white - +text-overflow-ellipsis transition: border 100ms ease-in-out &:focus diff --git a/src/styles/main.sass b/src/styles/main.sass index 9ed450cb..48b1d748 100644 --- a/src/styles/main.sass +++ b/src/styles/main.sass @@ -14,6 +14,7 @@ @import _services @import _stats @import _search +@import _organizations /* services, about, etc */ @import _pages diff --git a/src/templates/_macros/_menu.pug b/src/templates/_macros/_menu.pug index 8ad0a4d2..6fa73729 100644 --- a/src/templates/_macros/_menu.pug +++ b/src/templates/_macros/_menu.pug @@ -62,6 +62,7 @@ li(class="dropdown") title="My Projects") i.pi-star | My Projects + | {% if current_user.has_organizations() %} li a.navbar-item( @@ -70,20 +71,24 @@ li(class="dropdown") i.pi-users | My Organizations | {% endif %} + li a.navbar-item( href="{{ url_for('settings.profile') }}" title="Settings") i.pi-cog | Settings + li a.navbar-item( href="{{ url_for('settings.billing') }}" title="Billing") i.pi-credit-card | Subscription + li.divider(role="separator") | {% endif %} + li a.navbar-item( href="{{ url_for('users.logout') }}") diff --git a/src/templates/_macros/_navigation.pug b/src/templates/_macros/_navigation.pug index b222035f..ac60fd46 100644 --- a/src/templates/_macros/_navigation.pug +++ b/src/templates/_macros/_navigation.pug @@ -5,11 +5,23 @@ section#nav-tabs li.nav-tabs__list-tab( class="{% if title == 'homepage' %}active{% endif %}") a(href="{{ url_for('main.homepage') }}") Activity - li.nav-tabs__list-tab( - class="{% if title == 'dashboard' %}active{% endif %}") - a(href="{{ url_for('projects.index') }}") My Projects + li.nav-tabs__list-tab( class="{% if title == 'home' %}active{% endif %}") a(href="{{ url_for('projects.home_project') }}") Home + li.nav-tabs__list-tab( + class="{% if title == 'dashboard' %}active{% endif %}") + a(href="{{ url_for('projects.index') }}") My Projects + + | {% if current_user.has_organizations() %} + li.nav-tabs__list-tab( + class="{% if title == 'organizations' %}active{% endif %}") + a( + href="{{ url_for('pillar.web.organizations.index') }}", + title="My Organizations") + | My Organizations + | {% endif %} + + | {% endmacro %} diff --git a/src/templates/organizations/index.pug b/src/templates/organizations/index.pug index a3d29055..3b20b951 100644 --- a/src/templates/organizations/index.pug +++ b/src/templates/organizations/index.pug @@ -1,59 +1,74 @@ | {% extends 'layout.html' %} -| {% block bodyattrs %}{{ super() }} data-context='organizations'{% endblock %} +| {% 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 %} -#app-main - #col_main.organization-index - #col_main-content - .col_header.item-list-header - i.pi-cloud - | Your organizations +.dashboard-container + section#main + | {{ navigation_tabs(title) }} - .item-list.col-scrollable - .table - .table-head - .table-row - .table-cell.item-name - span.collapser(title="Collapse name column") Name - .table-cell.item-priority - span.collapser(title="Collapse priority column") Members - .table-cell.item-priority - span.collapser(title="Collapse priority column") Pending Members + section#projects - .table-body - | {% for organization in organizations['_items'] %} - | {% set link_url = url_for('pillar.web.organizations.view_embed', organization_id=organization._id) %} - .table-row(id="organization-{{ organization._id }}") - .table-cell.item-name - a(data-organization-id="{{ organization._id }}", - href="{{ link_url }}", - class="organization-link") - span(class="organization-name-{{ organization._id }}") {{ organization.name }} - .table-cell.item-members - a(data-organization-id="{{ organization._id }}", - href="{{ link_url }}", - class="organization-link") - span(class="organization-projects-{{ organization._id }}") {{ organization.members|hide_none|count }} - .table-cell.item-pending-members - a(data-organization-id="{{ organization._id }}", - href="{{ link_url }}", - class="organization-link") - span(class="organization-projects-{{ organization._id }}") {{ organization.unknown_members|hide_none|count }} - | {% endfor %} + | {% if can_create_organization %} + section#sub-nav-tabs.projects + ul#sub-nav-tabs__list + li.result#create_organization_result_panel + li.create + button.btn.btn-success(onclick='createNewOrganization(this)') + i.pi-plus + | Create Organization + | {% endif %} - #item-action-panel - | {% if can_create_organization %} - button.btn(onclick='createNewOrganization(this)') Create new organization - #create_organization_result_panel + section.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 %} - #col_right - .col_header - span.header_text - #item-details.col-scrollable - .item-details-empty - | Select an organization + section#side + section.box + #item-details + | {% endblock %} @@ -102,7 +117,6 @@ script. $.get(item_url, function(item_data) { statusBarClear(); $('#item-details').html(item_data); - $('#col_right .col_header span.header_text').text('Organization details'); current_item .removeClass(clean_classes) @@ -143,6 +157,7 @@ script. {% if open_organization_id %} $(function() { item_open('{{ open_organization_id }}', false); }); {% endif %} + {% if can_create_organization %} function createNewOrganization(button) { $(button) diff --git a/src/templates/organizations/view_embed.pug b/src/templates/organizations/view_embed.pug index 7e51bb14..55557ee6 100644 --- a/src/templates/organizations/view_embed.pug +++ b/src/templates/organizations/view_embed.pug @@ -29,15 +29,16 @@ type="text", placeholder="Organization's location", value="{{ organization.location | hide_none }}") + | {% if can_super_edit %} - .input-group.text-danger + .input-group label(for='org-seat-count-field') Seat count input.item-location.input-transparent#org-seat-count-field( name="seat_count", type="text", placeholder="Seat count", value="{{ organization.seat_count | hide_none }}") - .input-group.text-danger + .input-group label(for='org-roles-field') Roles input.item-location.input-transparent#org-roles-field( name="org_roles", @@ -45,8 +46,9 @@ placeholder="Organization roles", value="{{ organization.org_roles | hide_none | sort | join(' ') }}") | {% endif %} - .input-group - label.item-admin-user Org admin + + .input-group.org-admin + label.item-admin-user Organization Administrator p#admin-name a(href='javascript:showAdminPicker()', title='Click to choose another administrator') {{ admin_user.full_name }} p#admin-picker @@ -55,12 +57,13 @@ type='text', placeholder='Search for a new administrator') a(href='javascript:hideAdminPicker()') - i.pi-cancel.text-danger + span.text-danger Cancel script $('#admin-picker').hide(); + .input-group - button#item-save.btn.btn-default.btn-block(type='submit') + button#item-save.btn.btn-success.btn-block(type='submit') i.pi-check - | Save Organization + | Save Changes | {% else %} p.item-name {{ organization.name | hide_none }} | {% if organization.description %} @@ -76,98 +79,111 @@ p.item-admin-user Organization administrator: {{ admin_user.full_name }} | {% endif %} - h4 Properties - .table.item-properties - .table-body - .table-row.properties-last-updated - .table-cell Last Updated - .table-cell(title='Unable to edit, set by Organization') - | {{ organization._updated | hide_none | pretty_date_time }} - .table-row.properties-seat-count - .table-cell Seat Count - .table-cell(title='Unable to edit, determined by subscription') - | {{ organization.seat_count }} ({{ seats_used }} used) - .table-row.properties-org-roles - .table-cell User roles - .table-cell(title='Unable to edit, determined by subscription') - | {{ organization.org_roles | hide_none | sort | join(', ') }} +hr +h4 Properties +.table.item-properties + .table-body + .table-row.properties-last-updated + .table-cell Last Updated + .table-cell(title='Unable to edit, set by Organization') + | {{ organization._updated | hide_none | pretty_date_time }} + .table-row.properties-seat-count + .table-cell Seat Count + .table-cell(title='Unable to edit, determined by subscription') + | {{ organization.seat_count }} ({{ seats_used }} used) + .table-row.properties-org-roles + .table-cell User roles + .table-cell(title='Unable to edit, determined by subscription') + | {{ organization.org_roles | hide_none | sort | join(', ') }} + +hr + +h4 Organization members .members - h4 Organization members - | {% if can_edit %} - .sharing-users-search - .form-group - input#user-select.form-control( - name='contacts', - type='text', - placeholder='Add member by name') - | {% endif %} - ul.sharing-users-list - | {% for member in members %} - li.sharing-users-item( - data-user-id="{{ member['_id'] }}", - class="{% if current_user.objectid == member['_id'] %}self{% endif %}") - .sharing-users-avatar - img(src="{{ member['avatar'] }}") - .sharing-users-details - span.sharing-users-name - | {{ member['full_name'] }} - | {% if current_user.objectid == member['_id'] %} - small (You) - | {% endif %} - | {% if organization['admin_uid'] == member['_id'] %} - small (admin) - | {% endif %} - span.sharing-users-extra {{ member['username'] }} - .sharing-users-action - | {% if can_edit or current_user.objectid == member['_id'] %} - | {% if current_user.objectid == member['_id'] %} - button.user-remove(title="Leave as member of this organization") - i.pi-trash - | {% else %} - button.user-remove(title="Remove this user from this organization") - i.pi-trash - | {% endif %} + + | {% if can_edit %} + .sharing-users-search + .form-group + input#user-select.form-control( + name='contacts', + type='text', + placeholder='Add member by name') + | {% endif %} + + ul.sharing-users-list + | {% for member in members %} + li.sharing-users-item( + data-user-id="{{ member['_id'] }}", + class="{% if current_user.objectid == member['_id'] %}self{% endif %}") + .sharing-users-avatar + img(src="{{ member['avatar'] }}") + .sharing-users-details + span.sharing-users-name + | {{ member['full_name'] }} + | {% if current_user.objectid == member['_id'] %} + small (You) | {% endif %} - | {% else %} - li - p.small No members yet - | {% endfor %} - | {% if organization.unknown_members %} - h5 Pending members (i.e. without Blender Cloud account) - ul.sharing-users-list.unknown-members - | {% for email in organization.unknown_members %} - li.sharing-users-item.unknown-member(data-user-email='{{ email }}') - .sharing-users-avatar - img(src="{{ email | gravatar }}") - .sharing-users-details - span.sharing-users-email {{ email }} - .sharing-users-action - | {% if can_edit %} - button.user-remove(title="Remove this user from this organization") - i.pi-trash + | {% if organization['admin_uid'] == member['_id'] %} + small (admin) | {% endif %} - | {% endfor %} - | {% endif %} - | {% if can_edit %} - h5 Batch-add members by email address - form#batch_add_form(onsubmit="return batchAddUsers()") - .input-group - textarea.item-description.input-transparent( - name="emails", - type="text", - rows=1, - placeholder="Email addresses, separated by space/enter") - .input-group - button.btn.btn-default.btn-block(type='submit') - i.pi-check - | Add members - | {% endif %} + span.sharing-users-extra {{ member['username'] }} + .sharing-users-action + | {% if can_edit or current_user.objectid == member['_id'] %} + | {% if current_user.objectid == member['_id'] %} + button.user-remove(title="Leave as member of this organization") + i.pi-trash + | {% else %} + button.user-remove(title="Remove this user from this organization") + i.pi-trash + | {% endif %} + | {% endif %} + | {% else %} + li + p.text-warning No members yet + | {% endfor %} + + | {% if organization.unknown_members %} + hr + + p Pending Members (i.e. without Blender Cloud account) + ul.sharing-users-list.unknown-members + | {% for email in organization.unknown_members %} + li.sharing-users-item.unknown-member(data-user-email='{{ email }}') + .sharing-users-avatar + img(src="{{ email | gravatar }}") + .sharing-users-details + span.sharing-users-email {{ email }} + .sharing-users-action + | {% if can_edit %} + button.user-remove(title="Remove this user from this organization") + i.pi-trash + | {% endif %} + | {% endfor %} + | {% endif %} + + | {% if can_edit %} + br + + p Batch-add members by email address: + form#batch_add_form(onsubmit="return batchAddUsers()") + .input-group + textarea.item-description( + name="emails", + type="text", + rows=1, + placeholder="Enter the email addresses separated by space or a new line") + + .input-group + button.btn.btn-info.btn-block(type='submit') + i.pi-plus + | Add Members + | {% endif %} .action-result-panel +| {% if config.DEBUG %} #item-view-feed - | {% if config.DEBUG %} .debug-info a.debug-info-toggle(role='button', data-toggle='collapse', @@ -179,7 +195,7 @@ #debug-content-organization.collapse pre. {{ organization.to_dict() | pprint }} - | {% endif %} +| {% endif %} | {% block footer_scripts %} diff --git a/src/templates/projects/index_dashboard.pug b/src/templates/projects/index_dashboard.pug index 97553be4..ec8c4359 100644 --- a/src/templates/projects/index_dashboard.pug +++ b/src/templates/projects/index_dashboard.pug @@ -42,7 +42,7 @@ meta(name="twitter:image", content="{{ url_for('static', filename='assets/img/ba | {% if current_user.has_cap('subscriber') %} li.create( data-url="{{ url_for('projects.create') }}") - a#project-create( + a.btn.btn-success#project-create( href="{{ url_for('projects.create') }}") i.pi-plus | Create Project