feat: zenmode + toggle left, right & header panes

This commit is contained in:
liyasthomas
2021-07-21 15:25:46 +05:30
parent 22772ac10f
commit 04cd5b0981
13 changed files with 135 additions and 263 deletions

View File

@@ -47,6 +47,7 @@
</Splitpanes>
</Pane>
<Pane
v-if="RIGHT_SIDEBAR"
max-size="30"
size="25"
min-size="20"
@@ -108,13 +109,20 @@
</template>
<script>
import { defineComponent } from "@nuxtjs/composition-api"
import { Splitpanes, Pane } from "splitpanes"
import Paho from "paho-mqtt"
import debounce from "~/helpers/utils/debounce"
import { logHoppRequestRunToAnalytics } from "~/helpers/fb/analytics"
import { useSetting } from "~/newstore/settings"
export default {
export default defineComponent({
components: { Splitpanes, Pane },
setup() {
return {
RIGHT_SIDEBAR: useSetting("RIGHT_SIDEBAR"),
}
},
data() {
return {
url: "wss://test.mosquitto.org:8081",
@@ -322,5 +330,5 @@ export default {
})
},
},
}
})
</script>

View File

@@ -67,6 +67,7 @@
</Splitpanes>
</Pane>
<Pane
v-if="RIGHT_SIDEBAR"
max-size="30"
size="25"
min-size="20"
@@ -134,14 +135,21 @@
</template>
<script>
import { defineComponent } from "@nuxtjs/composition-api"
import { Splitpanes, Pane } from "splitpanes"
import { io as Client } from "socket.io-client"
import wildcard from "socketio-wildcard"
import debounce from "~/helpers/utils/debounce"
import { logHoppRequestRunToAnalytics } from "~/helpers/fb/analytics"
import { useSetting } from "~/newstore/settings"
export default {
export default defineComponent({
components: { Splitpanes, Pane },
setup() {
return {
RIGHT_SIDEBAR: useSetting("RIGHT_SIDEBAR"),
}
},
data() {
return {
url: "wss://main-daxrc78qyb411dls-gtw.qovery.io",
@@ -317,5 +325,5 @@ export default {
}
},
},
}
})
</script>

View File

@@ -138,6 +138,7 @@
</Splitpanes>
</Pane>
<Pane
v-if="RIGHT_SIDEBAR"
max-size="30"
size="25"
min-size="20"
@@ -176,14 +177,20 @@
</Splitpanes>
</template>
<script>
<script lang="ts">
import { defineComponent } from "@nuxtjs/composition-api"
import { Splitpanes, Pane } from "splitpanes"
import { logHoppRequestRunToAnalytics } from "~/helpers/fb/analytics"
import debounce from "~/helpers/utils/debounce"
import "splitpanes/dist/splitpanes.css"
export default {
import { useSetting } from "~/newstore/settings"
export default defineComponent({
components: { Splitpanes, Pane },
setup() {
return {
RIGHT_SIDEBAR: useSetting("RIGHT_SIDEBAR"),
}
},
data() {
return {
connectionState: false,
@@ -387,5 +394,5 @@ export default {
})
},
},
}
})
</script>

View File

@@ -348,5 +348,6 @@
"profile": "Profile",
"are_you_sure_logout": "Are you sure you want to logout?",
"telemetry": "Telemetry",
"shortcuts_indicator": "Shortcuts indicator"
"shortcuts_indicator": "Shortcuts indicator",
"zen_mode": "Zen mode"
}

View File

@@ -4,7 +4,7 @@
<Pane class="flex flex-1 overflow-auto">
<Splitpanes vertical :dbl-click-splitter="false">
<Pane
v-if="!HIDE_NAVBAR"
v-if="LEFT_SIDEBAR"
style="width: auto"
class="hide-scrollbar overflow-auto"
>
@@ -12,12 +12,12 @@
</Pane>
<Pane class="flex flex-1 overflow-auto">
<Splitpanes horizontal :dbl-click-splitter="false">
<Pane v-if="!zenMode" style="height: auto">
<Pane v-if="!ZEN_MODE" style="height: auto">
<!-- <AppAnnouncement /> -->
<AppHeader />
</Pane>
<Pane class="flex flex-1 overflow-auto">
<nuxt class="flex flex-1" :hide-right-pane="hideRightPane" />
<nuxt class="flex flex-1" :hide-right-pane="RIGHT_SIDEBAR" />
</Pane>
</Splitpanes>
</Pane>
@@ -28,32 +28,30 @@
<div>
<ButtonSecondary
v-tippy="{ theme: 'tooltip' }"
:title="HIDE_NAVBAR ? $t('show_sidebar') : $t('hide_sidebar')"
:title="LEFT_SIDEBAR ? $t('hide_sidebar') : $t('show_sidebar')"
icon="menu_open"
:class="{ 'transform rotate-180': HIDE_NAVBAR }"
@click.native="toggleSetting('HIDE_NAVBAR')"
:class="{ 'transform rotate-180': !LEFT_SIDEBAR }"
@click.native="toggleSetting('LEFT_SIDEBAR')"
/>
<ButtonSecondary
v-tippy="{ theme: 'tooltip' }"
:title="
zenMode
? `${$t('turn_off')} Zen mode`
: `${$t('turn_on')} Zen mode`
"
:icon="zenMode ? 'fullscreen_exit' : 'fullscreen'"
:title="`${ZEN_MODE ? $t('turn_off') : $t('turn_on')} ${$t(
'zen_mode'
)}`"
:icon="ZEN_MODE ? 'fullscreen_exit' : 'fullscreen'"
:class="{
'text-accent focus:text-accent hover:text-accent': zenMode,
'text-accent focus:text-accent hover:text-accent': ZEN_MODE,
}"
@click.native="zenMode = !zenMode"
@click.native="toggleSetting('ZEN_MODE')"
/>
</div>
<div>
<ButtonSecondary
v-tippy="{ theme: 'tooltip' }"
:title="hideRightPane ? $t('show_sidebar') : $t('hide_sidebar')"
:title="RIGHT_SIDEBAR ? $t('hide_sidebar') : $t('show_sidebar')"
icon="menu_open"
:class="['transform rotate-180', { ' rotate-0': hideRightPane }]"
@click.native="hideRightPane = !hideRightPane"
:class="['transform rotate-180', { 'rotate-0': !RIGHT_SIDEBAR }]"
@click.native="toggleSetting('RIGHT_SIDEBAR')"
/>
</div>
</div>
@@ -62,7 +60,8 @@
</div>
</template>
<script>
<script lang="ts">
import { defineComponent } from "@nuxtjs/composition-api"
import { Splitpanes, Pane } from "splitpanes"
import "splitpanes/dist/splitpanes.css"
import { setupLocalPersistence } from "~/newstore/localpersistence"
@@ -70,26 +69,37 @@ import { performMigrations } from "~/helpers/migrations"
import { initUserInfo } from "~/helpers/teams/BackendUserInfo"
import { registerApolloAuthUpdate } from "~/helpers/apollo"
import { initializeFirebase } from "~/helpers/fb"
import { getSettingSubject, toggleSetting } from "~/newstore/settings"
import {
defaultSettings,
getSettingSubject,
applySetting,
toggleSetting,
} from "~/newstore/settings"
import { logPageView } from "~/helpers/fb/analytics"
import type { KeysMatching } from "~/types/ts-utils"
export default {
type SettingsType = typeof defaultSettings
export default defineComponent({
components: { Splitpanes, Pane },
data() {
return {
zenMode: false,
hideRightPane: false,
HIDE_NAVBAR: null,
LEFT_SIDEBAR: null,
RIGHT_SIDEBAR: null,
ZEN_MODE: null,
}
},
subscriptions() {
return {
HIDE_NAVBAR: getSettingSubject("HIDE_NAVBAR"),
LEFT_SIDEBAR: getSettingSubject("LEFT_SIDEBAR"),
RIGHT_SIDEBAR: getSettingSubject("RIGHT_SIDEBAR"),
ZEN_MODE: getSettingSubject("ZEN_MODE"),
}
},
watch: {
zenMode(zenMode) {
this.hideNavigationPane = this.hideRightPane = zenMode
ZEN_MODE(ZEN_MODE) {
this.applySetting("LEFT_SIDEBAR", !ZEN_MODE)
this.applySetting("RIGHT_SIDEBAR", !ZEN_MODE)
},
$route(to) {
logPageView(to.fullPath)
@@ -150,9 +160,12 @@ export default {
document.removeEventListener("keydown", this._keyListener)
},
methods: {
toggleSetting(key) {
toggleSetting<K extends KeysMatching<SettingsType, boolean>>(key: K) {
toggleSetting(key)
},
applySetting<K extends keyof SettingsType>(key: K, value: SettingsType[K]) {
applySetting(key, value)
},
},
}
})
</script>

View File

@@ -45,7 +45,9 @@ export type SettingsType = {
BG_COLOR: HoppBgColor
TELEMETRY_ENABLED: boolean
SHORTCUTS_INDICATOR_ENABLED: boolean
HIDE_NAVBAR: boolean
LEFT_SIDEBAR: boolean
RIGHT_SIDEBAR: boolean
ZEN_MODE: boolean
}
export const defaultSettings: SettingsType = {
@@ -69,7 +71,9 @@ export const defaultSettings: SettingsType = {
BG_COLOR: "system",
TELEMETRY_ENABLED: true,
SHORTCUTS_INDICATOR_ENABLED: false,
HIDE_NAVBAR: false,
LEFT_SIDEBAR: true,
RIGHT_SIDEBAR: true,
ZEN_MODE: false,
}
const validKeys = Object.keys(defaultSettings)

View File

@@ -103,6 +103,7 @@
</Splitpanes>
</Pane>
<Pane
v-if="RIGHT_SIDEBAR"
max-size="30"
size="25"
min-size="20"
@@ -122,15 +123,22 @@
</template>
<script>
import { defineComponent } from "@nuxtjs/composition-api"
import { Splitpanes, Pane } from "splitpanes"
import Mustache from "mustache"
import { currentUser$ } from "~/helpers/fb/auth"
import DocsTemplate from "~/assets/md/docs.md"
import folderContents from "~/assets/md/folderContents.md"
import folderBody from "~/assets/md/folderBody.md"
import { useSetting } from "~/newstore/settings"
export default {
export default defineComponent({
components: { Splitpanes, Pane },
setup() {
return {
RIGHT_SIDEBAR: useSetting("RIGHT_SIDEBAR"),
}
},
data() {
return {
collectionJSON: "[]",
@@ -298,5 +306,5 @@ export default {
)
},
},
}
})
</script>

View File

@@ -331,6 +331,7 @@
</Splitpanes>
</Pane>
<Pane
v-if="RIGHT_SIDEBAR"
max-size="30"
size="25"
min-size="20"
@@ -478,22 +479,28 @@
</template>
<script>
import { defineComponent } from "@nuxtjs/composition-api"
import { Splitpanes, Pane } from "splitpanes"
import * as gql from "graphql"
import { commonHeaders } from "~/helpers/headers"
import { getPlatformSpecialKey } from "~/helpers/platformutils"
import { getCurrentStrategyID, sendNetworkRequest } from "~/helpers/network"
import { getSettingSubject } from "~/newstore/settings"
import { getSettingSubject, useSetting } from "~/newstore/settings"
import { addGraphqlHistoryEntry } from "~/newstore/history"
import { logHoppRequestRunToAnalytics } from "~/helpers/fb/analytics"
export default {
export default defineComponent({
components: { Splitpanes, Pane },
beforeRouteLeave(_to, _from, next) {
this.isPollingSchema = false
if (this.timeoutSubscription) clearTimeout(this.timeoutSubscription)
next()
},
setup() {
return {
RIGHT_SIDEBAR: useSetting("RIGHT_SIDEBAR"),
}
},
data() {
return {
commonHeaders,
@@ -1157,7 +1164,7 @@ export default {
this.gqlQueryString = updatedQuery
},
},
}
})
</script>
<style scoped lang="scss">

View File

@@ -31,7 +31,19 @@
<span class="select-wrapper">
<input
id="contentType"
class="bg-primary rounded-lg flex font-semibold font-mono text-xs w-full py-2 px-4 transition truncate focus:outline-none"
class="
bg-primary
rounded-lg
flex
font-semibold font-mono
text-xs
w-full
py-2
px-4
transition
truncate
focus:outline-none
"
v-model="contentType"
readonly
/>
@@ -321,6 +333,7 @@
</Splitpanes>
</Pane>
<Pane
v-if="RIGHT_SIDEBAR"
max-size="30"
size="25"
min-size="20"
@@ -462,8 +475,11 @@ import {
knownContentTypes,
isJSONContentType,
} from "~/helpers/utils/contenttypes"
import { generateCodeWithGenerator } from "~/helpers/codegen/codegen"
import { getSettingSubject, applySetting } from "~/newstore/settings"
import {
getSettingSubject,
applySetting,
useSetting,
} from "~/newstore/settings"
import { addRESTHistoryEntry } from "~/newstore/history"
import clone from "lodash/clone"
import {
@@ -476,10 +492,10 @@ import { map } from "rxjs/operators"
export default defineComponent({
components: { Splitpanes, Pane },
setup() {
return {
preRequestScript: usePreRequestScript(),
RIGHT_SIDEBAR: useSetting("RIGHT_SIDEBAR"),
}
},
data() {

View File

@@ -184,11 +184,17 @@
</div>
<div class="flex items-center">
<SmartToggle
:on="HIDE_NAVBAR"
@change="toggleSetting('HIDE_NAVBAR')"
:on="LEFT_SIDEBAR"
@change="toggleSetting('LEFT_SIDEBAR')"
>
{{ $t("navigation_sidebar") }}
{{ HIDE_NAVBAR ? $t("enabled") : $t("disabled") }}
{{ LEFT_SIDEBAR ? $t("enabled") : $t("disabled") }}
</SmartToggle>
</div>
<div class="flex items-center">
<SmartToggle :on="ZEN_MODE" @change="toggleSetting('ZEN_MODE')">
{{ $t("zen_mode") }}
{{ ZEN_MODE ? $t("enabled") : $t("disabled") }}
</SmartToggle>
</div>
</div>
@@ -340,7 +346,8 @@ export default defineComponent({
SYNC_HISTORY: useSetting("syncHistory"),
TELEMETRY_ENABLED: useSetting("TELEMETRY_ENABLED"),
SHORTCUTS_INDICATOR_ENABLED: useSetting("SHORTCUTS_INDICATOR_ENABLED"),
HIDE_NAVBAR: useSetting("HIDE_NAVBAR"),
LEFT_SIDEBAR: useSetting("LEFT_SIDEBAR"),
ZEN_MODE: useSetting("ZEN_MODE"),
currentUser: useReadonlyStream(currentUser$, currentUser$.value),
}
},
@@ -372,6 +379,10 @@ export default defineComponent({
},
},
watch: {
ZEN_MODE(ZEN_MODE) {
this.applySetting("LEFT_SIDEBAR", !ZEN_MODE)
this.applySetting("RIGHT_SIDEBAR", !ZEN_MODE)
},
proxySettings: {
deep: true,
handler({ url, key }) {

View File

@@ -9,14 +9,6 @@ export default {
gql[attribute] = value
},
setCollapsedSection({ theme }, value) {
theme.collapsedSections.includes(value)
? (theme.collapsedSections = theme.collapsedSections.filter(
(section) => section !== value
))
: theme.collapsedSections.push(value)
},
addGQLHeader({ gql }, object) {
gql.headers.push(object)
},
@@ -49,24 +41,6 @@ export default {
request.headers.splice(index, 1)
},
setKeyHeader({ request }, { index, value }) {
request.headers[index].key = value
},
setValueHeader({ request }, { index, value }) {
request.headers[index].value = value
},
setActiveHeader({ request }, { index, value }) {
if (
!Object.prototype.hasOwnProperty.call(request.headers[index], "active")
) {
Vue.set(request.headers[index], "active", value)
} else {
request.headers[index].active = value
}
},
addParams({ request }, value) {
request.params.push(value)
},
@@ -75,28 +49,6 @@ export default {
request.params.splice(index, 1)
},
setKeyParams({ request }, { index, value }) {
request.params[index].key = value
},
setValueParams({ request }, { index, value }) {
request.params[index].value = value
},
setTypeParams({ request }, { index, value }) {
request.params[index].type = value
},
setActiveParams({ request }, { index, value }) {
if (
!Object.prototype.hasOwnProperty.call(request.params[index], "active")
) {
Vue.set(request.params[index], "active", value)
} else {
request.params[index].active = value
}
},
addBodyParams({ request }, value) {
request.bodyParams.push(value)
},

View File

@@ -8,157 +8,6 @@ export const state = () => ({
})
export const mutations = {
applySetting({ settings }, setting) {
if (
setting === null ||
!(setting instanceof Array) ||
setting.length !== 2
) {
throw new Error(
"You must provide a setting (array in the form [key, value])"
)
}
const [key, value] = setting
// Do not just remove this check.
// Add your settings key to the SETTINGS_KEYS array at the
// top of the file.
// This is to ensure that application settings remain documented.
if (!SETTINGS_KEYS.includes(key)) {
throw new Error(`The settings structure does not include the key ${key}`)
}
settings[key] = value
},
removeVariables({ editingEnvironment }, value) {
editingEnvironment.variables = value
},
setEditingEnvironment(state, value) {
state.editingEnvironment = { ...value }
},
setVariableKey({ editingEnvironment }, { index, value }) {
editingEnvironment.variables[index].key = value
},
setVariableValue({ editingEnvironment }, { index, value }) {
editingEnvironment.variables[index].value = testValue(value)
},
removeVariable({ editingEnvironment }, variables) {
editingEnvironment.variables = variables
},
addVariable({ editingEnvironment }, value) {
editingEnvironment.variables.push(value)
},
replaceEnvironments(state, environments) {
state.environments = environments
},
importAddEnvironments(state, { environments, confirmation }) {
const duplicateEnvironment = environments.some((item) => {
return state.environments.some((item2) => {
return item.name.toLowerCase() === item2.name.toLowerCase()
})
})
if (duplicateEnvironment) {
this.$toast.info("Duplicate environment")
return
}
state.environments = [...state.environments, ...environments]
let index = 0
for (const environment of state.environments) {
environment.environmentIndex = index
index += 1
}
this.$toast.info(confirmation, {
icon: "folder_shared",
})
},
removeEnvironment({ environments }, environmentIndex) {
environments.splice(environmentIndex, 1)
},
saveEnvironment({ environments }, payload) {
const { environment, environmentIndex } = payload
const { name } = environment
const duplicateEnvironment =
environments.length === 1
? false
: environments.some(
(item) =>
item.environmentIndex !== environmentIndex &&
item.name.toLowerCase() === name.toLowerCase()
)
if (duplicateEnvironment) {
this.$toast.info("Duplicate environment")
return
}
environments[environmentIndex] = environment
},
replaceCollections(state, item) {
const collections = item.data
const flag = item.flag
if (flag === "rest") state.collections = collections
else state.collectionsGraphql = collections
},
importCollections(state, item) {
const collections = item.data
const flag = item.flag
if (flag === "rest")
state.collections = [...state.collections, ...collections]
else
state.collectionsGraphql = [...state.collectionsGraphql, ...collections]
let index = 0
for (const collection of collections) {
collection.collectionIndex = index
index += 1
}
},
addNewCollection({ collections, collectionsGraphql }, collection) {
const name = collection.name
const flag = collection.flag
let duplicateCollection = null
if (flag === "rest") {
duplicateCollection = collections.some(
(item) => item.name.toLowerCase() === name.toLowerCase()
)
} else {
duplicateCollection = collectionsGraphql.some(
(item) => item.name.toLowerCase() === name.toLowerCase()
)
}
if (duplicateCollection) {
this.$toast.info("Duplicate collection")
return
}
if (flag === "rest") {
collections.push({
name: "",
folders: [],
requests: [],
...collection,
})
} else {
collectionsGraphql.push({
name: "",
folders: [],
requests: [],
...collection,
})
}
},
removeCollection({ collections, collectionsGraphql }, payload) {
const { collectionIndex, flag } = payload
if (flag === "rest") collections.splice(collectionIndex, 1)
@@ -362,15 +211,6 @@ export const mutations = {
},
}
function testValue(myValue) {
try {
return JSON.parse(myValue)
} catch (ex) {
// Now we know it's a string just leave it as a string value.
return myValue
}
}
function findRequest(folderName, currentFolder, requestIndex) {
let selectedFolder, result

View File

@@ -32,9 +32,6 @@ export default () => ({
response: "",
schemaIntrospection: "",
},
theme: {
collapsedSections: [],
},
oauth2: {
tokens: [],
tokenReqs: [],