Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactoring multichain sidemenu to a selector component #692

Merged
merged 5 commits into from
Jun 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@ APP_NAME=OBE
# default network
CHAIN_NAME=telos-testnet

# enable sidebar to switch chains
#SHOW_SIDEBAR=true
# enable selector on header to switch chains
#SHOW_MULTICHAIN_SELECTOR=true

8 changes: 5 additions & 3 deletions src/boot/ual.ts
Original file line number Diff line number Diff line change
Expand Up @@ -147,12 +147,14 @@ function getMainChain() {
const authenticators: Authenticator[] = [];

export const getAuthenticators = () => {
// we initialize the authenticators inside this function on demand
if (authenticators.length === 0) {
// we initialize the authenticators inside this function on demand
// UAL is not looking at the chain when checking the localstorage for an already logged in account
// A quick fix is to add the chain in appName until we move forward with WharfKit
const mainChain = getMainChain();
authenticators.push(new Anchor([mainChain], { appName: process.env.APP_NAME })),
authenticators.push(new Anchor([mainChain], { appName: `${process.env.APP_NAME}_${mainChain.chainId}` })),
authenticators.push(new CleosAuthenticator([mainChain], {
appName: process.env.APP_NAME,
appName: `${process.env.APP_NAME}_${mainChain.chainId}`,
loginHandler,
signHandler: signHandlerForMainChain,
}));
Expand Down
113 changes: 72 additions & 41 deletions src/components/ChainsSidebar.vue → src/components/ChainsMenu.vue
Original file line number Diff line number Diff line change
@@ -1,13 +1,20 @@
<script lang="ts">
import { computed, ref, onMounted } from 'vue';
import { computed, defineComponent, onMounted, ref } from 'vue';
import ConfigManager from 'src/config/ConfigManager';
import { Chain } from 'src/types/Chain';
import { useStore } from 'src/store';
import { getAuthenticators } from 'src/boot/ual';

const configMgr = ConfigManager.get();

export default {
name: 'ChainsSidebar',
export default defineComponent({
name: 'ChainsMenu',
setup() {
const menuOpened = ref(false);
const store = useStore();
const account = computed(() => store.state.account);

const menuIcon = computed(() => menuOpened.value ? 'expand_less' : 'expand_more');
const mainnets = computed(() => sortChainsUsingName(configMgr.getMainnets()));
const testnets = computed(() => sortChainsUsingName(configMgr.getTestnets()));

Expand All @@ -21,6 +28,19 @@ export default {
return localStorage.getItem(ConfigManager.CHAIN_LOCAL_STORAGE) === chain.getName();
}

const logout = async (): Promise<void> => {
const wallet = localStorage.getItem('autoLogin');
const authenticator = getAuthenticators().find(
auth => auth.getName() === wallet,
);
try {
authenticator && (await authenticator.logout());
} catch (error) {
console.error('Authenticator logout error', error);
}
void store.dispatch('account/logout');
};

function chainSelected(chain: Chain) {
if (isSelected(chain)) {
return;
Expand All @@ -30,6 +50,11 @@ export default {
ConfigManager.CHAIN_LOCAL_STORAGE,
chain.getName(),
);

if (account.value) {
void logout();
}

location.reload();
}

Expand All @@ -43,30 +68,23 @@ export default {
});

return {
miniState: ref(true),
menuOpened,
menuIcon,
mainnets,
testnets,
chainSelected,
isSelected,
};
},
};
});
</script>

<template>

<q-drawer
show-if-above
:mini="miniState"
mini-to-overlay
:width="175"
:breakpoint="500"
bordered
@mouseover="miniState = false"
@mouseout="miniState = true"
>
<q-scroll-area class="fit">
<q-btn v-if="testnets.length > 0 || mainnets.length > 0" flat class="chain-button">
<q-icon :name="menuIcon" size="md" />
<q-menu v-model="menuOpened">
<q-list>
<div v-if="mainnets.length > 0" class="section-title">MAINNETS</div>
<q-item
v-for="(chain, index) in mainnets"
:key="`mainnet-${index}`"
Expand All @@ -79,7 +97,8 @@ export default {
<div class="q-pl-md">{{ chain.getDisplay() }}</div>
</q-item-section>
</q-item>
<q-separator class="separator"/>
<q-separator v-if="testnets.length > 0 && mainnets.length > 0" class="separator"/>
<div v-if="testnets.length > 0" class="section-title">TESTNETS</div>
<q-item
v-for="(chain, index) in testnets"
:key="`testnet-${index}`"
Expand All @@ -90,45 +109,57 @@ export default {
>
<div class="testnet-logo-container">
<img class="sidebar-logo sidebar-logo--testnet" :src="chain.getSmallLogoPath()">
<div class="testnet-text">Testnet</div>
<div class="testnet-text">TESTNET</div>
</div>
<q-item-section>
<div class="q-pl-md">{{ chain.getDisplay() }}</div>
</q-item-section>
</q-item>
</q-list>
</q-scroll-area>
</q-drawer>

</q-menu>
</q-btn>
</template>

<style lang="sass" scoped>
.chain-button
padding: 0px 4px

.q-item
&:hover, &.selected
background-color: var(--q-color-sidebar-selected)
padding-left: 4px
padding-top: 4px
&:hover, &.selected
background-color: var(--q-color-sidebar-selected)
padding-left: 16px
padding-top: 8px
width: 170px

.q-list
padding-bottom: 8px
padding-top: 8px

.separator
margin-top: .5rem
margin-bottom: .5rem
margin-left: 5px
min-height: 5px
min-width: 0
width: calc(100% - 10px)
background: var(--q-color-sidebar-selected)
margin-top: .5rem
margin-bottom: .5rem
min-height: 1px
min-width: 0
width: 100%
background: var(--q-color-sidebar-selected)

.sidebar-logo
height: auto
width: auto
max-height: 48px
max-width: 48px
object-fit: contain
height: auto
width: auto
max-height: 32px
max-width: 32px
object-fit: contain

.section-title
padding-left: 16px
padding-top: 8px
padding-bottom: 8px
font-size: 10px

.testnet-logo-container
position: relative
height: 48px
width: 48px
height: 32px
width: 32px

.testnet-text, .sidebar-logo--testnet
position: absolute
Expand All @@ -140,7 +171,7 @@ export default {

.testnet-text
color: white
font-size: 12px
font-size: 6px
width: min-content
height: min-content
padding: 0 2px
Expand Down
54 changes: 46 additions & 8 deletions src/components/Header.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { defineComponent, computed } from 'vue';
import { useQuasar } from 'quasar';
import LoginHandler from 'components/LoginHandler.vue';
import HeaderSearch from 'components/HeaderSearch.vue';
import ChainsMenu from 'components/ChainsMenu.vue';
import { getChain } from 'src/config/ConfigManager';
import { useStore } from 'src/store';

Expand All @@ -11,18 +12,21 @@ export default defineComponent({
components: {
LoginHandler,
HeaderSearch,
ChainsMenu,
},
setup() {
const $q = useQuasar();
const chain = getChain();
const store = useStore();
const account = computed(() => store.state.account.accountName);
const isLarge = computed((): boolean => $q.screen.gt.sm);
const showMultichainSelector = computed(() => process.env.SHOW_MULTICHAIN_SELECTOR === 'true');

return {
account,
isLarge: isLarge,
chain,
showMultichainSelector,
};
},
});
Expand All @@ -31,15 +35,21 @@ export default defineComponent({
<template>
<div class="header-background">
<div class="row text-center q-pt-sm justify-between q-pt-md">
<div class="logo-container col-xs-2 col-sm-2 col-md-2 col-lg-2">
<div class="logo-container col-xs-3 col-sm-2 col-md-2 col-lg-2">
<div class="q-px-xs-xs q-px-sm-xs q-px-md-md q-px-lg-md">
<a class="float-left q-ml-sm" href="/">
<img v-if="isLarge" class="logo" :src="chain.getLargeLogoPath()">
<img v-else class="logo-token" :src="chain.getSmallLogoPath()">
</a>
<div class="logo-header-container">
<div class="logo-chain-selector-container">
<a class="float-left" href="/">
<img v-if="isLarge" class="logo" :src="chain.getLargeLogoPath()">
<img v-else class="logo-token" :src="chain.getSmallLogoPath()">
</a>
<ChainsMenu v-if="showMultichainSelector"/>
</div>
<div v-if="chain.isTestnet()" class="testnet-text">TESTNET</div>
</div>
</div>
</div>
<div class="col-xs-5 col-sm-6 col-md-4 col-lg-6">
<div class="col-xs-4 col-sm-6 col-md-4 col-lg-6">
<div class="q-px-xs-xs q-px-sm-xs q-px-md-md q-px-lg-md">
<div class="row justify-center full-width">
<div class="col-12">
Expand Down Expand Up @@ -90,8 +100,23 @@ export default defineComponent({

<style lang="sass" scoped>
.q-tab
text-transform: unset
font-size: 18px
text-transform: unset
font-size: 18px

.logo-header-container
position: relative
display: flex
flex-direction: column
gap: 8px
width: fit-content

.logo-chain-selector-container
padding-left: 4px
display: flex
flex-direction: row
justify-content: space-between
a
margin-right: 4px

.logo
width: 104px
Expand All @@ -103,6 +128,17 @@ export default defineComponent({
height: 40px
object-fit: contain

.testnet-text
position: absolute
bottom: -20px
color: white
font-size: 10px
width: 100%
height: min-content
padding: 4px 8px
border-radius: 4px
background-color: rgba(white, 0.1)

.active-tab
text-decoration: none
color: var(--q-color-header-text)
Expand All @@ -115,4 +151,6 @@ export default defineComponent({
.header-background
border-bottom: 2px solid var(--q-color-header-border)
background: var(--q-color-header-background)


</style>
4 changes: 4 additions & 0 deletions src/config/BaseChain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,8 @@ export default abstract class BaseChain implements Chain {
abstract getMapDisplay(): boolean;
abstract getTheme(): Theme;
abstract getFiltersSupported(prop: string): boolean;

isTestnet(): boolean {
return false;
}
}
4 changes: 2 additions & 2 deletions src/config/ConfigManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@ export default class ConfigManager {
}

private init(): void {
const showSidebar = process.env.SHOW_SIDEBAR;
const showMultichainSelector = process.env.SHOW_MULTICHAIN_SELECTOR;
const configuredChain = process.env.CHAIN_NAME;
this.testnets = chainsConfig.testnets;
this.mainnets = chainsConfig.mainnets;
if (showSidebar) {
if (showMultichainSelector) {
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
const userConfiguredChain = this.getSelectedChain();

Expand Down
4 changes: 4 additions & 0 deletions src/config/chains/jungle/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -131,4 +131,8 @@ export default class TelosTestnet extends BaseChain {
}
return true;
}

isTestnet(): boolean {
return true;
}
}
4 changes: 4 additions & 0 deletions src/config/chains/telos-testnet/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -133,4 +133,8 @@ export default class TelosTestnet extends BaseChain {
}
return true;
}

isTestnet(): boolean {
return true;
}
}
8 changes: 0 additions & 8 deletions src/layouts/MainLayout.vue
Original file line number Diff line number Diff line change
@@ -1,19 +1,12 @@
<script lang="ts">
import AppFooter from 'components/Footer.vue';
import AppHeader from 'components/Header.vue';
import ChainsSidebar from 'components/ChainsSidebar.vue';

export default {
name: 'MainLayout',
components: {
AppHeader,
AppFooter,
ChainsSidebar,
},
setup() {
return {
showSidebar: () => process.env.SHOW_SIDEBAR === 'true',
};
},
};
</script>
Expand All @@ -24,7 +17,6 @@ export default {
<q-header>
<AppHeader/>
</q-header>
<ChainsSidebar v-if="showSidebar()"/>
<q-page-container>
<router-view/>
</q-page-container>
Expand Down
Loading