Skip to content

Commit e607f9d

Browse files
anwarulislammirarifhasanjamesgeorge007
authored
feat(common): mock server ui improvements (hoppscotch#5532)
- Update active state styles for better visibility in the mock server. - BE updates catered to improving content type handling in the mock server. - Introduced a `disableMockServerInPersonalWorkspace` platform-level feature flag. - Remove inactive keyboard shorthand nudges from the Mock server dashboard context menu. --- Co-authored-by: mirarifhasan <[email protected]> Co-authored-by: jamesgeorge007 <[email protected]>
1 parent c73e718 commit e607f9d

File tree

9 files changed

+92
-35
lines changed

9 files changed

+92
-35
lines changed

packages/hoppscotch-backend/src/mock-server/mock-server.controller.ts

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ export class MockServerController {
8787
try {
8888
const headers = JSON.parse(mockResponse.headers);
8989
Object.keys(headers).forEach((key) => {
90+
console.log('Setting header:', key, headers[key]);
9091
res.setHeader(key, headers[key]);
9192
});
9293
} catch (error) {
@@ -101,17 +102,31 @@ export class MockServerController {
101102
);
102103
}
103104

104-
// Send response
105-
const defaultContentType =
106-
typeof mockResponse.body === 'object'
107-
? 'application/json'
108-
: 'text/plain';
109-
const contentType =
110-
mockResponse.headers?.['content-type'] || defaultContentType;
105+
// Only set Content-Type if not already set
106+
if (!res.getHeader('Content-Type')) {
107+
let defaultContentType = 'text/plain';
108+
109+
// Check if body is a string and try to parse it to determine content type
110+
if (typeof mockResponse.body === 'string') {
111+
try {
112+
JSON.parse(mockResponse.body);
113+
// If parsing succeeds, it's JSON
114+
defaultContentType = 'application/json';
115+
} catch {
116+
// If parsing fails, it's plain text
117+
defaultContentType = 'text/plain';
118+
}
119+
} else if (typeof mockResponse.body === 'object') {
120+
// If it's already an object, it's JSON
121+
defaultContentType = 'application/json';
122+
}
111123

112-
res.setHeader('Content-Type', contentType);
124+
res.setHeader('Content-Type', defaultContentType);
125+
}
126+
// Security headers
113127
res.setHeader('X-Content-Type-Options', 'nosniff');
114128

129+
// Send response
115130
return res.status(mockResponse.statusCode).send(mockResponse.body);
116131
} catch (error) {
117132
console.error('Error handling mock request:', error);

packages/hoppscotch-common/src/components/collections/Collection.vue

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -136,8 +136,7 @@
136136
@keyup.t="runCollectionAction?.$el.click()"
137137
@keyup.s="sortAction?.$el.click()"
138138
@keyup.m="
139-
ENABLE_EXPERIMENTAL_MOCK_SERVERS &&
140-
mockServerAction?.$el.click()
139+
isMockServerVisible && mockServerAction?.$el.click()
141140
"
142141
@keyup.escape="hide()"
143142
>
@@ -183,7 +182,7 @@
183182
v-if="
184183
!hasNoTeamAccess &&
185184
isRootCollection &&
186-
ENABLE_EXPERIMENTAL_MOCK_SERVERS
185+
isMockServerVisible
187186
"
188187
ref="mockServerAction"
189188
:icon="IconServer"
@@ -328,7 +327,7 @@ import IconArrowUpDown from "~icons/lucide/arrow-up-down"
328327
import { CurrentSortValuesService } from "~/services/current-sort.service"
329328
import { useService } from "dioc/vue"
330329
import { useMockServerStatus } from "~/composables/mockServer"
331-
import { useSetting } from "@composables/settings"
330+
import { useMockServerVisibility } from "~/composables/mockServerVisibility"
332331
import { platform } from "~/platform"
333332
import { invokeAction } from "~/helpers/actions"
334333
@@ -464,13 +463,11 @@ const isCollectionLoading = computed(() => {
464463
})
465464
466465
// Mock Server Status
467-
const ENABLE_EXPERIMENTAL_MOCK_SERVERS = useSetting(
468-
"ENABLE_EXPERIMENTAL_MOCK_SERVERS"
469-
)
466+
const { isMockServerVisible } = useMockServerVisibility()
470467
const { getMockServerStatus } = useMockServerStatus()
471468
472469
const mockServerStatus = computed(() => {
473-
if (!ENABLE_EXPERIMENTAL_MOCK_SERVERS.value) {
470+
if (!isMockServerVisible.value) {
474471
return { exists: false, isActive: false }
475472
}
476473

packages/hoppscotch-common/src/components/http/Sidebar.vue

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@
5252
/>
5353
</HoppSmartTab>
5454
<HoppSmartTab
55-
v-if="ENABLE_EXPERIMENTAL_MOCK_SERVERS"
55+
v-if="isMockServerVisible"
5656
:id="'mock-servers'"
5757
:icon="IconServer"
5858
:label="`${t('tab.mock_servers')}`"
@@ -76,15 +76,13 @@ import IconCode from "~icons/lucide/code"
7676
import IconServer from "~icons/lucide/server"
7777
import { ref } from "vue"
7878
import { useI18n } from "@composables/i18n"
79-
import { useSetting } from "@composables/settings"
8079
import MockServerDashboard from "~/components/mockServer/MockServerDashboard.vue"
8180
import { useMockServerWorkspaceSync } from "~/composables/mockServerWorkspace"
81+
import { useMockServerVisibility } from "~/composables/mockServerVisibility"
8282
8383
const t = useI18n()
8484
85-
const ENABLE_EXPERIMENTAL_MOCK_SERVERS = useSetting(
86-
"ENABLE_EXPERIMENTAL_MOCK_SERVERS"
87-
)
85+
const { isMockServerVisible } = useMockServerVisibility()
8886
8987
type RequestOptionTabs =
9088
| "history"

packages/hoppscotch-common/src/components/mockServer/CreateMockServer.vue

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -134,16 +134,16 @@
134134
class="inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium"
135135
:class="
136136
existingMockServer?.isActive
137-
? 'bg-green-600/20 text-green-200 border border-green-900/50'
138-
: 'bg-gray-600/20 text-gray-200 border border-gray-900/50'
137+
? 'bg-green-600/20 text-green-500 border border-green-600/30'
138+
: 'text-secondary border border-secondaryLight'
139139
"
140140
>
141141
<span
142142
class="w-2 h-2 rounded-full mr-2"
143143
:class="
144144
existingMockServer?.isActive
145145
? 'bg-green-400'
146-
: 'bg-gray-400'
146+
: 'bg-secondaryLight'
147147
"
148148
></span>
149149
{{

packages/hoppscotch-common/src/components/mockServer/EditMockServer.vue

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -68,13 +68,13 @@
6868
class="inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium"
6969
:class="
7070
isActive
71-
? 'bg-green-600/20 text-green-200 border border-green-900/50'
72-
: 'bg-gray-600/20 text-gray-200 border border-gray-900/50'
71+
? 'bg-green-600/20 text-green-500 border border-green-600/30'
72+
: 'text-secondary border border-secondaryLight'
7373
"
7474
>
7575
<span
7676
class="w-2 h-2 rounded-full mr-2"
77-
:class="isActive ? 'bg-green-400' : 'bg-gray-400'"
77+
:class="isActive ? 'bg-green-400' : 'bg-secondaryLight'"
7878
></span>
7979
{{
8080
isActive

packages/hoppscotch-common/src/components/mockServer/MockServerDashboard.vue

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,6 @@
150150
? t('mock_server.stop_server')
151151
: t('mock_server.start_server')
152152
"
153-
:shortcut="['S']"
154153
@click="
155154
() => {
156155
toggleMockServer(mockServer)
@@ -162,7 +161,6 @@
162161
ref="deleteAction"
163162
:icon="IconTrash2"
164163
:label="t('action.delete')"
165-
:shortcut="['⌫']"
166164
@click="
167165
() => {
168166
deleteMockServer(mockServer)
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import { computed } from "vue"
2+
import { useSetting } from "~/composables/settings"
3+
import { platform } from "~/platform"
4+
import { useService } from "dioc/vue"
5+
import { WorkspaceService } from "~/services/workspace.service"
6+
7+
/**
8+
* Composable to determine mock server visibility based on experimental flags and platform configuration
9+
*/
10+
export function useMockServerVisibility() {
11+
const ENABLE_EXPERIMENTAL_MOCK_SERVERS = useSetting(
12+
"ENABLE_EXPERIMENTAL_MOCK_SERVERS"
13+
)
14+
15+
const workspaceService = useService(WorkspaceService)
16+
17+
/**
18+
* Check if mock servers should be visible based on experimental flag and platform configuration
19+
*/
20+
const isMockServerVisible = computed(() => {
21+
// First check if experimental mock servers are enabled
22+
if (!ENABLE_EXPERIMENTAL_MOCK_SERVERS.value) {
23+
return false
24+
}
25+
26+
// Check if platform disables mock servers in personal workspaces
27+
const disableInPersonalWorkspace =
28+
platform.platformFeatureFlags.disableMockServerInPersonalWorkspace ??
29+
false
30+
31+
// If platform disables mock servers in personal workspaces and current workspace is personal, hide mock servers
32+
if (
33+
disableInPersonalWorkspace &&
34+
workspaceService.currentWorkspace.value.type === "personal"
35+
) {
36+
return false
37+
}
38+
39+
return true
40+
})
41+
42+
return {
43+
isMockServerVisible,
44+
}
45+
}

packages/hoppscotch-common/src/composables/mockServerWorkspace.ts

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { useService } from "dioc/vue"
33
import { WorkspaceService } from "~/services/workspace.service"
44
import { setMockServers, loadMockServers } from "~/newstore/mockServers"
55
import { platform } from "~/platform"
6-
import { useSetting } from "./settings"
6+
import { useMockServerVisibility } from "./mockServerVisibility"
77

88
/**
99
* Composable to handle mock server state when workspace changes
@@ -12,22 +12,20 @@ import { useSetting } from "./settings"
1212
*/
1313
export function useMockServerWorkspaceSync() {
1414
const workspaceService = useService(WorkspaceService)
15-
const ENABLE_EXPERIMENTAL_MOCK_SERVERS = useSetting(
16-
"ENABLE_EXPERIMENTAL_MOCK_SERVERS"
17-
)
15+
const { isMockServerVisible } = useMockServerVisibility()
1816
const isAuthenticated = !!platform.auth.getCurrentUser()
1917

2018
// Initial load of mock servers for the current workspace
2119
onMounted(() => {
22-
if (!isAuthenticated || !ENABLE_EXPERIMENTAL_MOCK_SERVERS.value) return
20+
if (!isAuthenticated || !isMockServerVisible.value) return
2321
loadMockServers().catch(() => setMockServers([]))
2422
})
2523

2624
// Watch for workspace changes and clear mock servers immediately
2725
watch(
2826
() => workspaceService.currentWorkspace.value,
2927
(newWorkspace, oldWorkspace) => {
30-
if (!isAuthenticated || !ENABLE_EXPERIMENTAL_MOCK_SERVERS.value) return
28+
if (!isAuthenticated || !isMockServerVisible.value) return
3129

3230
// Clear mock servers when workspace changes to prevent stale data
3331
if (

packages/hoppscotch-common/src/platform/index.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,12 @@ export type PlatformDef = {
6666
* Whether to show the A/B testing workspace switcher click login flow or not
6767
*/
6868
workspaceSwitcherLogin?: Ref<boolean>
69+
70+
/**
71+
* Whether to disable mock servers in personal workspaces
72+
* If a value is not given, then the value is assumed to be false
73+
*/
74+
disableMockServerInPersonalWorkspace?: boolean
6975
}
7076
limits?: LimitsPlatformDef
7177
infra?: InfraPlatformDef

0 commit comments

Comments
 (0)