Merge pull request #5587 from aignatov-bio/ai-sci-8540-update-top-navigation

Refactor top navigation [SCI-8540]
This commit is contained in:
aignatov-bio 2023-06-13 14:13:25 +02:00 committed by GitHub
commit 0a122b6416
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
17 changed files with 88 additions and 92 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 991 B

After

Width:  |  Height:  |  Size: 843 B

View file

@ -1,3 +1,5 @@
@import "tailwind/inputs";
@tailwind base;
@tailwind components;
@tailwind utilities;

View file

@ -11,7 +11,7 @@ body.navigator-collapsed {
--left-navigation-width: 192px;
--navbar-height: calc(var(--top-navigation-height) + var(--breadcrumbs-navigation-height));
--navigator-navigation-width: 240px;
--top-navigation-height: 52px;
--top-navigation-height: 72px;
display: grid;
grid-template-areas: "left top top"
"left breadcrumbs breadcrumbs"

View file

@ -7,7 +7,7 @@
display: flex;
flex-direction: column;
height: 100%;
padding: 2rem 1rem;
padding: 1.5rem 1rem;
width: 100%;
.sci--layout--menu-item {

View file

@ -8,11 +8,11 @@
.sci--navigation--top-menu-container {
align-items: center;
background-color: $color-white;
box-shadow: $flyout-shadow;
border-bottom: 1px solid var(--sn-sleepy-grey);
display: flex;
gap: .5em;
gap: 1rem;
height: 100%;
padding: 0 2em;
padding: 0 1rem;
.sci--navigation--top-menu-logo {
a {
@ -28,40 +28,11 @@
}
}
.sci--navigation--top-menu-teams {
height: 36px;
margin-left: 2em;
width: 220px;
}
.sci--navigation--top-menu-search {
margin-left: auto;
margin-right: 1em;
width: 240px;
input {
border-color: $color-alto;
}
.sn-icon {
color: $color-silver-chalice;
}
width: 300px;
}
.sci--navigation--top-menu-user {
align-items: center;
cursor: pointer;
display: flex;
gap: 1em;
margin-left: .75em;
span {
max-width: 200px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.avatar {
border-radius: 50%;
}

View file

@ -1,15 +1,17 @@
.sn-select {
border: 1px solid;
border-color: var(--sn-grey);
border-radius: 4px;
align-items: center;
border: $border-default;
border-color: var(--sn-light-grey);
border-radius: $border-radius-default;
box-sizing: border-box;
cursor: pointer;
padding: .5em;
display: flex;
padding: .5rem .625rem .5rem 1rem;
position: relative;
&.sn-select--blank {
.sn-select__value {
color: var(--sn-grey);
font-style: italic;
}
}
@ -26,11 +28,11 @@
.sn-select__value {
all: unset;
display: inline-block;
flex-grow: 1;
line-height: 1.625rem;
overflow: hidden;
padding-right: 1.5em;
text-overflow: ellipsis;
white-space: nowrap;
width: calc(100% - 1.5em);
}
&:hover {
@ -51,12 +53,6 @@
display: none;
}
.sn-select__caret {
position: absolute;
right: 1em;
top: 1.1em;
}
.sn-select__search-input {
background: transparent;
border: 0;
@ -75,10 +71,6 @@
display: block;
}
.sn-select__caret {
transform: rotate(180deg);
}
.sn-select__options {
background: var(--sn-white);
border-bottom-left-radius: 4px;
@ -88,15 +80,15 @@
left: 0;
max-height: 300px;
overflow: hidden;
overflow-y: scroll;
top: 2.5em;
top: 2.5rem;
width: 100%;
z-index: 9999;
}
.sn-select__option {
padding: .5em;
line-height: 1.75rem;
overflow: hidden;
padding: .5rem 1rem;
text-overflow: ellipsis;
white-space: nowrap;
width: calc(100%);
@ -108,8 +100,7 @@
}
.sn-select__option:hover {
background: var(--sn-blue);
color: var(--sn-white);
background: var(--sn-super-light-grey);
}
}
}

View file

@ -19,10 +19,6 @@
transition: .3s;
user-select: none;
img {
padding-bottom: 3px;
}
&:hover {
text-decoration: none;
}

View file

@ -0,0 +1,27 @@
@layer components {
.sci-input-container-v2 {
@apply relative h-[2.75rem] flex items-center;
}
.sci-input-container-v2 input {
@apply w-full h-full bg-transparent p-0.5 border rounded outline-none absolute top-0;
border-color: var(--sn-sleepy-grey);
}
.sci-input-container-v2 input::placeholder {
color: var(--sn-sleepy-grey);
}
.sci-input-container-v2 input:focus {
border-color: var(--sn-science-blue);
}
.sci-input-container-v2 .sn-icon {
@apply m-2;
color: var(--sn-black)
}
.sci-input-container-v2.left-icon input {
@apply pl-10;
}
}

View file

@ -6,6 +6,7 @@ class NavigationsController < ApplicationController
def top_menu
render json: {
root_url: root_path,
team_switch_url: switch_users_settings_teams_path,
current_team: current_team&.id,
search_url: search_path,
teams: teams,
@ -25,11 +26,10 @@ class NavigationsController < ApplicationController
def teams
current_user.teams.order(:name).map do |t|
{
label: t.name,
value: t.id,
params: { switch_url: switch_users_settings_team_path(t) }
}
[
t.id,
t.name
]
end
end

View file

@ -132,7 +132,7 @@ module Users
end
def switch
team = current_user.teams.find_by(id: params[:id])
team = current_user.teams.find_by(id: params[:team_id])
if team && current_user.update(current_team_id: team.id)
flash[:success] = t('users.settings.changed_team_flash',

View file

@ -1,19 +1,19 @@
<template>
<div class="sci--navigation--top-menu-container">
<div v-if="currentTeam" class="sci--navigation--top-menu-teams">
<DropdownSelector
:selectedValue="currentTeam"
:options="teams"
:disableSearch="true"
:selectorId="`sciNavigationTeamSelector`"
:labelHTML="true"
@dropdown:changed="switchTeam"
/>
</div>
<div v-if="user" class="sci--navigation--top-menu-search left-icon sci-input-container" :class="{'disabled' : !currentTeam}">
<input type="text" class="sci-input-field" :placeholder="i18n.t('nav.search')" @change="searchValue"/>
<div v-if="user" class="sci--navigation--top-menu-search left-icon sci-input-container-v2" :class="{'disabled' : !currentTeam}">
<input type="text" :placeholder="i18n.t('nav.search')" @change="searchValue"/>
<i class="sn-icon sn-icon-search"></i>
</div>
<div v-if="currentTeam" class="mr-auto w-64">
<Select
:value="currentTeam"
:options="teams"
:placeholder="'test'"
:noOptionsPlaceholder="'test'"
v-bind:disabled="false"
@change="switchTeam"
></Select>
</div>
<div v-if="user" class="dropdown">
<button class="btn btn-light icon-btn" data-toggle="dropdown">
<i class="sn-icon sn-icon-help"></i>
@ -60,9 +60,8 @@
@close="notificationsOpened = false" />
</div>
<div v-if="user" class="dropdown">
<div class="sci--navigation--top-menu-user" data-toggle="dropdown">
<span>{{ i18n.t('nav.user_greeting', { full_name: user.name })}}</span>
<img class="avatar" :src="user.avatar_url">
<div class="sci--navigation--top-menu-user btn btn-light icon-btn" data-toggle="dropdown">
<img class="avatar w-6 h-6" :src="user.avatar_url">
</div>
<div class="dropdown-menu dropdown-menu-right top-menu-user-dropdown">
<li v-for="(item, i) in userMenu" :key="i">
@ -83,12 +82,14 @@
<script>
import NotificationsFlyout from './notifications/notifications_flyout.vue'
import DropdownSelector from '../shared/dropdown_selector.vue'
import Select from "../shared/select.vue";
export default {
name: 'TopMenuContainer',
components: {
DropdownSelector,
NotificationsFlyout
NotificationsFlyout,
Select
},
props: {
url: String,
@ -98,6 +99,7 @@
data() {
return {
rootUrl: null,
teamSwitchUrl: null,
currentTeam: null,
teams: null,
searchUrl: null,
@ -127,6 +129,7 @@
fetchData() {
$.get(this.url, (result) => {
this.rootUrl = result.root_url;
this.teamSwitchUrl = result.team_switch_url;
this.currentTeam = result.current_team;
this.teams = result.teams;
this.searchUrl = result.search_url;
@ -139,11 +142,11 @@
switchTeam(team) {
if (this.currentTeam == team) return;
let newTeam = this.teams.find(e => e.value == team);
let newTeam = this.teams.find(e => e[0] == team);
if (!newTeam) return;
$.post(newTeam.params.switch_url, (result) => {
$.post(this.teamSwitchUrl, {team_id: team}, (result) => {
this.currentTeam = result.currentTeam
dropdownSelector.selectValues('#sciNavigationTeamSelector', this.currentTeam);
$('body').attr('data-current-team-id', this.currentTeam);

View file

@ -4,9 +4,13 @@
<button ref="focusElement" class="sn-select__value">
<span>{{ valueLabel || (placeholder || i18n.t('general.select')) }}</span>
</button>
<span class="sn-select__caret caret"></span>
<i class="sn-icon" :class="{ 'sn-icon-down': !isOpen, 'sn-icon-up': isOpen}"></i>
</slot>
<div ref="optionsContainer" class="sn-select__options" :style="optionPositionStyle">
<perfect-scrollbar
ref="optionsContainer"
:style="optionPositionStyle"
class="sn-select__options scroll-container"
>
<template v-if="options.length">
<div
v-for="option in options"
@ -22,12 +26,13 @@
>
{{ this.noOptionsPlaceholder }}
</div>
</template>
</div>
</template>
</perfect-scrollbar>
</div>
</template>
<script>
import PerfectScrollbar from 'vue2-perfect-scrollbar';
export default {
name: 'Select',
props: {
@ -38,6 +43,7 @@
noOptionsPlaceholder: { type: String },
disabled: { type: Boolean, default: false }
},
comments: { PerfectScrollbar },
data() {
return {
isOpen: false,

View file

@ -13,7 +13,7 @@
>
<input ref="focusElement" v-model="query" type="text" class="sn-select__search-input" :placeholder="searchPlaceholder" />
<span class="sn-select__value">{{ valueLabel || (placeholder || i18n.t('general.select')) }}</span>
<span class="sn-select__caret caret"></span>
<i class="sn-icon" :class="{ 'sn-icon-down': !isOpen, 'sn-icon-up': isOpen}"></i>
</Select>
</template>

View file

@ -143,7 +143,7 @@ Rails.application.routes.draw do
namespace :users do
namespace :settings do
resources :teams, only: [] do
member do
collection do
post :switch
end
end

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 991 B

After

Width:  |  Height:  |  Size: 1.4 KiB