feat: disable tracking request history (#4607)
Co-authored-by: jamesgeorge007 <25279263+jamesgeorge007@users.noreply.github.com>
This commit is contained in:
parent
a332fd1f69
commit
bd22c8c1a9
24 changed files with 477 additions and 6 deletions
|
|
@ -797,6 +797,7 @@
|
|||
"sync_description": "These settings are synced to cloud.",
|
||||
"sync_environments": "Environments",
|
||||
"sync_history": "History",
|
||||
"history_disabled": "History is disabled",
|
||||
"system_mode": "System",
|
||||
"telemetry": "Telemetry",
|
||||
"telemetry_helps_us": "Telemetry helps us to personalize our operations and deliver the best experience to you.",
|
||||
|
|
|
|||
|
|
@ -51,7 +51,11 @@
|
|||
<HoppButtonSecondary
|
||||
v-tippy="{ theme: 'tooltip' }"
|
||||
data-testid="clear_history"
|
||||
:disabled="history.length === 0"
|
||||
:disabled="
|
||||
history.length === 0 ||
|
||||
!isHistoryStoreEnabled ||
|
||||
isFetchingHistoryStoreStatus
|
||||
"
|
||||
:icon="IconTrash2"
|
||||
:title="t('action.clear_all')"
|
||||
@click="confirmRemove = true"
|
||||
|
|
@ -59,7 +63,10 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex flex-col">
|
||||
<div
|
||||
v-if="isHistoryStoreEnabled && !isFetchingHistoryStoreStatus"
|
||||
class="flex flex-col"
|
||||
>
|
||||
<details
|
||||
v-for="(
|
||||
filteredHistoryGroup, filteredHistoryGroupIndex
|
||||
|
|
@ -110,11 +117,18 @@
|
|||
</details>
|
||||
</div>
|
||||
<HoppSmartPlaceholder
|
||||
v-if="history.length === 0"
|
||||
v-if="!isHistoryStoreEnabled && !isFetchingHistoryStoreStatus"
|
||||
:src="`/images/states/${colorMode.value}/time.svg`"
|
||||
:alt="`${t('empty.history')}`"
|
||||
:text="t('settings.history_disabled')"
|
||||
/>
|
||||
<HoppSmartPlaceholder
|
||||
v-else-if="history.length === 0"
|
||||
:src="`/images/states/${colorMode.value}/time.svg`"
|
||||
:alt="`${t('empty.history')}`"
|
||||
:text="t('empty.history')"
|
||||
/>
|
||||
|
||||
<HoppSmartPlaceholder
|
||||
v-else-if="
|
||||
Object.keys(filteredHistoryGroups).length === 0 ||
|
||||
|
|
@ -180,6 +194,7 @@ import HistoryGraphqlCard from "./graphql/Card.vue"
|
|||
import { defineActionHandler, invokeAction } from "~/helpers/actions"
|
||||
import { useService } from "dioc/vue"
|
||||
import { RESTTabService } from "~/services/tab/rest"
|
||||
import { platform } from "~/platform"
|
||||
|
||||
type HistoryEntry = GQLHistoryEntry | RESTHistoryEntry
|
||||
|
||||
|
|
@ -205,6 +220,15 @@ const history = useReadonlyStream<RESTHistoryEntry[] | GQLHistoryEntry[]>(
|
|||
[]
|
||||
)
|
||||
|
||||
const { isHistoryStoreEnabled, isFetchingHistoryStoreStatus } =
|
||||
"requestHistoryStore" in platform.sync.history &&
|
||||
platform.sync.history.requestHistoryStore
|
||||
? platform.sync.history.requestHistoryStore
|
||||
: {
|
||||
isHistoryStoreEnabled: ref(true),
|
||||
isFetchingHistoryStoreStatus: ref(false),
|
||||
}
|
||||
|
||||
const deepCheckForRegex = (value: unknown, regExp: RegExp): boolean => {
|
||||
if (value === null || value === undefined) return false
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,10 @@
|
|||
import { Ref } from "vue"
|
||||
|
||||
export type HistoryPlatformDef = {
|
||||
initHistorySync: () => void
|
||||
requestHistoryStore?: {
|
||||
isHistoryStoreEnabled: Ref<boolean>
|
||||
isFetchingHistoryStoreStatus: Ref<boolean>
|
||||
hasErrorFetchingHistoryStoreStatus: Ref<boolean>
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import { getDefaultRESTRequest } from "~/helpers/rest/default"
|
|||
import { HoppAction, HoppActionWithArgs } from "~/helpers/actions"
|
||||
import { getDefaultGQLRequest } from "~/helpers/graphql/default"
|
||||
import { RESTTabService } from "~/services/tab/rest"
|
||||
import { PlatformDef, setPlatformDef } from "~/platform"
|
||||
|
||||
async function flushPromises() {
|
||||
return await new Promise((r) => setTimeout(r))
|
||||
|
|
@ -74,6 +75,14 @@ describe("HistorySpotlightSearcherService", () => {
|
|||
|
||||
actionsMock.invokeAction.mockReset()
|
||||
createNewTabFn.mockReset()
|
||||
|
||||
const platform = {
|
||||
sync: {
|
||||
history: {},
|
||||
},
|
||||
}
|
||||
|
||||
setPlatformDef(platform as PlatformDef)
|
||||
})
|
||||
|
||||
it("registers with the spotlight service upon initialization", async () => {
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import { useStreamStatic } from "~/composables/stream"
|
|||
import { activeActions$, invokeAction } from "~/helpers/actions"
|
||||
import { map } from "rxjs/operators"
|
||||
import { HoppRequestDocument } from "~/helpers/rest/document"
|
||||
import { platform } from "~/platform"
|
||||
|
||||
/**
|
||||
* This searcher is responsible for searching through the history.
|
||||
|
|
@ -48,6 +49,22 @@ export class HistorySpotlightSearcherService
|
|||
}
|
||||
)[0]
|
||||
|
||||
private hasHistoryPlatformDef = "requestHistoryStore" in platform.sync.history
|
||||
|
||||
private isHistoryEnabledPlatformRef =
|
||||
platform.sync.history.requestHistoryStore?.isHistoryStoreEnabled
|
||||
|
||||
private clearHistoryActionEnabledCombined = computed(() => {
|
||||
// if the platform has not defined the history store, by default we consider history is enabled
|
||||
if (!this.hasHistoryPlatformDef) return this.clearHistoryActionEnabled.value
|
||||
|
||||
// if the platform has defined the history store, we check the defined values to determine if history is enabled
|
||||
return (
|
||||
this.clearHistoryActionEnabled.value &&
|
||||
this.isHistoryEnabledPlatformRef?.value
|
||||
)
|
||||
})
|
||||
|
||||
private restHistoryEntryOpenable = useStreamStatic(
|
||||
activeActions$.pipe(
|
||||
map((actions) => actions.includes("rest.request.open"))
|
||||
|
|
@ -82,7 +99,7 @@ export class HistorySpotlightSearcherService
|
|||
})
|
||||
|
||||
const stopWatchHandle = watch(
|
||||
this.clearHistoryActionEnabled,
|
||||
this.clearHistoryActionEnabledCombined,
|
||||
(enabled) => {
|
||||
if (enabled) {
|
||||
if (minisearch.has("clear-history")) return
|
||||
|
|
|
|||
|
|
@ -0,0 +1,6 @@
|
|||
query IsUserHistoryEnabled {
|
||||
isUserHistoryEnabled {
|
||||
name
|
||||
value
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
subscription UserHistoryAllDeleted {
|
||||
userHistoryAllDeleted
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
subscription UserHistoryStoreStatusChanged {
|
||||
infraConfigUpdate(configName: USER_HISTORY_STORE_ENABLED)
|
||||
}
|
||||
|
|
@ -25,6 +25,11 @@ import {
|
|||
UserHistoryDeletedDocument,
|
||||
UserHistoryDeletedManyDocument,
|
||||
UserHistoryUpdatedDocument,
|
||||
IsUserHistoryEnabledQuery,
|
||||
IsUserHistoryEnabledQueryVariables,
|
||||
IsUserHistoryEnabledDocument,
|
||||
UserHistoryStoreStatusChangedDocument,
|
||||
UserHistoryAllDeletedDocument,
|
||||
} from "../../api/generated/graphql"
|
||||
|
||||
export const getUserHistoryEntries = () =>
|
||||
|
|
@ -33,6 +38,16 @@ export const getUserHistoryEntries = () =>
|
|||
variables: {},
|
||||
})
|
||||
|
||||
export const getUserHistoryStore = () =>
|
||||
runGQLQuery<
|
||||
IsUserHistoryEnabledQuery,
|
||||
IsUserHistoryEnabledQueryVariables,
|
||||
""
|
||||
>({
|
||||
query: IsUserHistoryEnabledDocument,
|
||||
variables: {},
|
||||
})
|
||||
|
||||
export const createUserHistory = (
|
||||
reqData: string,
|
||||
resMetadata: string,
|
||||
|
|
@ -98,3 +113,15 @@ export const runUserHistoryDeletedManySubscription = () =>
|
|||
query: UserHistoryDeletedManyDocument,
|
||||
variables: {},
|
||||
})
|
||||
|
||||
export const runUserHistoryStoreStatusChangedSubscription = () =>
|
||||
runGQLSubscription({
|
||||
query: UserHistoryStoreStatusChangedDocument,
|
||||
variables: {},
|
||||
})
|
||||
|
||||
export const runUserHistoryAllDeletedSubscription = () =>
|
||||
runGQLSubscription({
|
||||
query: UserHistoryAllDeletedDocument,
|
||||
variables: {},
|
||||
})
|
||||
|
|
|
|||
|
|
@ -18,9 +18,12 @@ import {
|
|||
import { HistoryPlatformDef } from "@hoppscotch/common/platform/history"
|
||||
import {
|
||||
getUserHistoryEntries,
|
||||
getUserHistoryStore,
|
||||
runUserHistoryAllDeletedSubscription,
|
||||
runUserHistoryCreatedSubscription,
|
||||
runUserHistoryDeletedManySubscription,
|
||||
runUserHistoryDeletedSubscription,
|
||||
runUserHistoryStoreStatusChangedSubscription,
|
||||
runUserHistoryUpdatedSubscription,
|
||||
} from "./history.api"
|
||||
|
||||
|
|
@ -29,6 +32,7 @@ import { restHistorySyncer, gqlHistorySyncer } from "./history.sync"
|
|||
import { runGQLSubscription } from "@hoppscotch/common/helpers/backend/GQLClient"
|
||||
import { runDispatchWithOutSyncing } from "@lib/sync"
|
||||
import { ReqType } from "../../api/generated/graphql"
|
||||
import { ref } from "vue"
|
||||
|
||||
function initHistorySync() {
|
||||
const currentUser$ = platformAuth.getCurrentUserStream()
|
||||
|
|
@ -38,9 +42,12 @@ function initHistorySync() {
|
|||
|
||||
gqlHistorySyncer.startStoreSync()
|
||||
|
||||
getUserHistoryStatus()
|
||||
loadHistoryEntries()
|
||||
|
||||
currentUser$.subscribe(async (user) => {
|
||||
getUserHistoryStatus()
|
||||
|
||||
if (user) {
|
||||
await loadHistoryEntries()
|
||||
}
|
||||
|
|
@ -64,12 +71,17 @@ function setupSubscriptions() {
|
|||
const userHistoryUpdatedSub = setupUserHistoryUpdatedSubscription()
|
||||
const userHistoryDeletedSub = setupUserHistoryDeletedSubscription()
|
||||
const userHistoryDeletedManySub = setupUserHistoryDeletedManySubscription()
|
||||
const userHistoryStoreStatusChangedSub =
|
||||
setupUserHistoryStoreStatusChangedSubscription()
|
||||
const userHistoryAllDeletedSub = setupUserHistoryAllDeletedSubscription()
|
||||
|
||||
subs = [
|
||||
userHistoryCreatedSub,
|
||||
userHistoryUpdatedSub,
|
||||
userHistoryDeletedSub,
|
||||
userHistoryDeletedManySub,
|
||||
userHistoryStoreStatusChangedSub,
|
||||
userHistoryAllDeletedSub,
|
||||
]
|
||||
|
||||
return () => {
|
||||
|
|
@ -109,6 +121,30 @@ async function loadHistoryEntries() {
|
|||
}
|
||||
}
|
||||
|
||||
async function getUserHistoryStatus() {
|
||||
const currentUser = platformAuth.getCurrentUser()
|
||||
|
||||
if (!currentUser) {
|
||||
isHistoryStoreEnabled.value = true
|
||||
return
|
||||
}
|
||||
|
||||
isFetchingHistoryStoreStatus.value = true
|
||||
|
||||
const res = await getUserHistoryStore()
|
||||
|
||||
if (E.isLeft(res)) {
|
||||
hasErrorFetchingHistoryStoreStatus.value = true
|
||||
isFetchingHistoryStoreStatus.value = false
|
||||
return
|
||||
}
|
||||
|
||||
isHistoryStoreEnabled.value =
|
||||
res.right.isUserHistoryEnabled.value === "ENABLE"
|
||||
|
||||
isFetchingHistoryStoreStatus.value = false
|
||||
}
|
||||
|
||||
function setupUserHistoryCreatedSubscription() {
|
||||
const [userHistoryCreated$, userHistoryCreatedSub] =
|
||||
runUserHistoryCreatedSubscription()
|
||||
|
|
@ -256,6 +292,46 @@ function setupUserHistoryDeletedManySubscription() {
|
|||
return userHistoryDeletedManySub
|
||||
}
|
||||
|
||||
function setupUserHistoryStoreStatusChangedSubscription() {
|
||||
const [userHistoryStoreStatusChanged$, userHistoryStoreStatusChangedSub] =
|
||||
runUserHistoryStoreStatusChangedSubscription()
|
||||
|
||||
userHistoryStoreStatusChanged$.subscribe((res) => {
|
||||
if (E.isRight(res)) {
|
||||
const status = res.right.infraConfigUpdate == "ENABLE" ? true : false
|
||||
|
||||
isHistoryStoreEnabled.value = status
|
||||
}
|
||||
})
|
||||
|
||||
return userHistoryStoreStatusChangedSub
|
||||
}
|
||||
|
||||
function setupUserHistoryAllDeletedSubscription() {
|
||||
const [userHistoryAllDeleted$, userHistoryAllDeletedSub] =
|
||||
runUserHistoryAllDeletedSubscription()
|
||||
|
||||
userHistoryAllDeleted$.subscribe((res) => {
|
||||
if (E.isRight(res)) {
|
||||
runDispatchWithOutSyncing(() => {
|
||||
clearRESTHistory()
|
||||
clearGraphqlHistory()
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
return userHistoryAllDeletedSub
|
||||
}
|
||||
|
||||
export const isHistoryStoreEnabled = ref(false)
|
||||
const isFetchingHistoryStoreStatus = ref(false)
|
||||
const hasErrorFetchingHistoryStoreStatus = ref(false)
|
||||
|
||||
export const def: HistoryPlatformDef = {
|
||||
initHistorySync,
|
||||
requestHistoryStore: {
|
||||
isHistoryStoreEnabled,
|
||||
isFetchingHistoryStoreStatus,
|
||||
hasErrorFetchingHistoryStoreStatus,
|
||||
},
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,6 @@
|
|||
query IsUserHistoryEnabled {
|
||||
isUserHistoryEnabled {
|
||||
name
|
||||
value
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
subscription UserHistoryAllDeleted {
|
||||
userHistoryAllDeleted
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
subscription UserHistoryStoreStatusChanged {
|
||||
infraConfigUpdate(configName: USER_HISTORY_STORE_ENABLED)
|
||||
}
|
||||
|
|
@ -25,6 +25,11 @@ import {
|
|||
UserHistoryDeletedDocument,
|
||||
UserHistoryDeletedManyDocument,
|
||||
UserHistoryUpdatedDocument,
|
||||
IsUserHistoryEnabledQuery,
|
||||
IsUserHistoryEnabledQueryVariables,
|
||||
IsUserHistoryEnabledDocument,
|
||||
UserHistoryStoreStatusChangedDocument,
|
||||
UserHistoryAllDeletedDocument,
|
||||
} from "../../api/generated/graphql"
|
||||
|
||||
export const getUserHistoryEntries = () =>
|
||||
|
|
@ -33,6 +38,16 @@ export const getUserHistoryEntries = () =>
|
|||
variables: {},
|
||||
})
|
||||
|
||||
export const getUserHistoryStore = () =>
|
||||
runGQLQuery<
|
||||
IsUserHistoryEnabledQuery,
|
||||
IsUserHistoryEnabledQueryVariables,
|
||||
""
|
||||
>({
|
||||
query: IsUserHistoryEnabledDocument,
|
||||
variables: {},
|
||||
})
|
||||
|
||||
export const createUserHistory = (
|
||||
reqData: string,
|
||||
resMetadata: string,
|
||||
|
|
@ -98,3 +113,15 @@ export const runUserHistoryDeletedManySubscription = () =>
|
|||
query: UserHistoryDeletedManyDocument,
|
||||
variables: {},
|
||||
})
|
||||
|
||||
export const runUserHistoryStoreStatusChangedSubscription = () =>
|
||||
runGQLSubscription({
|
||||
query: UserHistoryStoreStatusChangedDocument,
|
||||
variables: {},
|
||||
})
|
||||
|
||||
export const runUserHistoryAllDeletedSubscription = () =>
|
||||
runGQLSubscription({
|
||||
query: UserHistoryAllDeletedDocument,
|
||||
variables: {},
|
||||
})
|
||||
|
|
|
|||
|
|
@ -18,9 +18,12 @@ import {
|
|||
import { HistoryPlatformDef } from "@hoppscotch/common/platform/history"
|
||||
import {
|
||||
getUserHistoryEntries,
|
||||
getUserHistoryStore,
|
||||
runUserHistoryAllDeletedSubscription,
|
||||
runUserHistoryCreatedSubscription,
|
||||
runUserHistoryDeletedManySubscription,
|
||||
runUserHistoryDeletedSubscription,
|
||||
runUserHistoryStoreStatusChangedSubscription,
|
||||
runUserHistoryUpdatedSubscription,
|
||||
} from "./history.api"
|
||||
|
||||
|
|
@ -28,7 +31,8 @@ import * as E from "fp-ts/Either"
|
|||
import { restHistorySyncer, gqlHistorySyncer } from "./history.sync"
|
||||
import { runGQLSubscription } from "@hoppscotch/common/helpers/backend/GQLClient"
|
||||
import { runDispatchWithOutSyncing } from "@lib/sync"
|
||||
import { ReqType } from "../../api/generated/graphql"
|
||||
import { ReqType, ServiceStatus } from "../../api/generated/graphql"
|
||||
import { ref } from "vue"
|
||||
|
||||
function initHistorySync() {
|
||||
const currentUser$ = platformAuth.getCurrentUserStream()
|
||||
|
|
@ -38,11 +42,14 @@ function initHistorySync() {
|
|||
|
||||
gqlHistorySyncer.startStoreSync()
|
||||
|
||||
getUserHistoryStatus()
|
||||
loadHistoryEntries()
|
||||
|
||||
currentUser$.subscribe(async (user) => {
|
||||
getUserHistoryStatus()
|
||||
|
||||
if (user) {
|
||||
await loadHistoryEntries()
|
||||
loadHistoryEntries()
|
||||
}
|
||||
})
|
||||
|
||||
|
|
@ -64,12 +71,17 @@ function setupSubscriptions() {
|
|||
const userHistoryUpdatedSub = setupUserHistoryUpdatedSubscription()
|
||||
const userHistoryDeletedSub = setupUserHistoryDeletedSubscription()
|
||||
const userHistoryDeletedManySub = setupUserHistoryDeletedManySubscription()
|
||||
const userHistoryStoreStatusChangedSub =
|
||||
setupUserHistoryStoreStatusChangedSubscription()
|
||||
const userHistoryAllDeletedSub = setupUserHistoryAllDeletedSubscription()
|
||||
|
||||
subs = [
|
||||
userHistoryCreatedSub,
|
||||
userHistoryUpdatedSub,
|
||||
userHistoryDeletedSub,
|
||||
userHistoryDeletedManySub,
|
||||
userHistoryStoreStatusChangedSub,
|
||||
userHistoryAllDeletedSub,
|
||||
]
|
||||
|
||||
return () => {
|
||||
|
|
@ -109,6 +121,30 @@ async function loadHistoryEntries() {
|
|||
}
|
||||
}
|
||||
|
||||
async function getUserHistoryStatus() {
|
||||
const currentUser = platformAuth.getCurrentUser()
|
||||
|
||||
if (!currentUser) {
|
||||
isHistoryStoreEnabled.value = true
|
||||
return
|
||||
}
|
||||
|
||||
isFetchingHistoryStoreStatus.value = true
|
||||
|
||||
const res = await getUserHistoryStore()
|
||||
|
||||
if (E.isLeft(res)) {
|
||||
hasErrorFetchingHistoryStoreStatus.value = true
|
||||
isFetchingHistoryStoreStatus.value = false
|
||||
return
|
||||
}
|
||||
|
||||
isHistoryStoreEnabled.value =
|
||||
res.right.isUserHistoryEnabled.value === ServiceStatus.Enable
|
||||
|
||||
isFetchingHistoryStoreStatus.value = false
|
||||
}
|
||||
|
||||
function setupUserHistoryCreatedSubscription() {
|
||||
const [userHistoryCreated$, userHistoryCreatedSub] =
|
||||
runUserHistoryCreatedSubscription()
|
||||
|
|
@ -256,6 +292,47 @@ function setupUserHistoryDeletedManySubscription() {
|
|||
return userHistoryDeletedManySub
|
||||
}
|
||||
|
||||
function setupUserHistoryStoreStatusChangedSubscription() {
|
||||
const [userHistoryStoreStatusChanged$, userHistoryStoreStatusChangedSub] =
|
||||
runUserHistoryStoreStatusChangedSubscription()
|
||||
|
||||
userHistoryStoreStatusChanged$.subscribe((res) => {
|
||||
if (E.isRight(res)) {
|
||||
const status =
|
||||
res.right.infraConfigUpdate == ServiceStatus.Enable ? true : false
|
||||
|
||||
isHistoryStoreEnabled.value = status
|
||||
}
|
||||
})
|
||||
|
||||
return userHistoryStoreStatusChangedSub
|
||||
}
|
||||
|
||||
function setupUserHistoryAllDeletedSubscription() {
|
||||
const [userHistoryAllDeleted$, userHistoryAllDeletedSub] =
|
||||
runUserHistoryAllDeletedSubscription()
|
||||
|
||||
userHistoryAllDeleted$.subscribe((res) => {
|
||||
if (E.isRight(res)) {
|
||||
runDispatchWithOutSyncing(() => {
|
||||
clearRESTHistory()
|
||||
clearGraphqlHistory()
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
return userHistoryAllDeletedSub
|
||||
}
|
||||
|
||||
export const isHistoryStoreEnabled = ref(false)
|
||||
const isFetchingHistoryStoreStatus = ref(false)
|
||||
const hasErrorFetchingHistoryStoreStatus = ref(false)
|
||||
|
||||
export const def: HistoryPlatformDef = {
|
||||
initHistorySync,
|
||||
requestHistoryStore: {
|
||||
isHistoryStoreEnabled,
|
||||
isFetchingHistoryStoreStatus,
|
||||
hasErrorFetchingHistoryStoreStatus,
|
||||
},
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,10 +22,16 @@ import {
|
|||
} from "./history.api"
|
||||
import { ReqType } from "../../api/generated/graphql"
|
||||
|
||||
import { isHistoryStoreEnabled } from "./history.platform"
|
||||
|
||||
export const restHistoryStoreSyncDefinition: StoreSyncDefinitionOf<
|
||||
typeof restHistoryStore
|
||||
> = {
|
||||
async addEntry({ entry }) {
|
||||
if (!isHistoryStoreEnabled.value) {
|
||||
return
|
||||
}
|
||||
|
||||
const res = await createUserHistory(
|
||||
JSON.stringify(entry.request),
|
||||
JSON.stringify(entry.responseMeta),
|
||||
|
|
@ -58,6 +64,10 @@ export const gqlHistoryStoreSyncDefinition: StoreSyncDefinitionOf<
|
|||
typeof graphqlHistoryStore
|
||||
> = {
|
||||
async addEntry({ entry }) {
|
||||
if (!isHistoryStoreEnabled.value) {
|
||||
return
|
||||
}
|
||||
|
||||
const res = await createUserHistory(
|
||||
JSON.stringify(entry.request),
|
||||
JSON.stringify(entry.response),
|
||||
|
|
|
|||
|
|
@ -58,6 +58,16 @@
|
|||
"update_failure": "Failed to update smtp configurations!!",
|
||||
"user": "MAILER USER"
|
||||
},
|
||||
"history_configs": {
|
||||
"description": "Disable or enable tracking history of sent requests from the Hoppscotch app",
|
||||
"title": "History Configurations",
|
||||
"enable_history": "Enable History",
|
||||
"clear_history": "Clear existing history",
|
||||
"clear_failure": "Failed to clear history!!",
|
||||
"clear_success": "History cleared successfully.",
|
||||
"toggle_failure": "Failed to toggle history!!",
|
||||
"clear_confirm": "Are you sure you want to clear all history?"
|
||||
},
|
||||
"reset": {
|
||||
"confirm_reset": "Hoppscotch server must restart to reflect the new changes. Confirm the reset of server configurations?",
|
||||
"description": "Default configurations will be loaded as specified in the environment file",
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
<div class="flex flex-col space-y-8 divide-y divide-divider">
|
||||
<SettingsAuthProvider v-model:config="workingConfigs" />
|
||||
<SettingsSmtpConfiguration v-model:config="workingConfigs" />
|
||||
<SettingsHistoryConfiguration v-model:config="workingConfigs" />
|
||||
<SettingsDataSharing v-model:config="workingConfigs" />
|
||||
<SettingsReset />
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,104 @@
|
|||
<script lang="ts" setup>
|
||||
import { useVModel } from '@vueuse/core';
|
||||
import { computed, ref } from 'vue';
|
||||
import { useI18n } from '~/composables/i18n';
|
||||
import { ServerConfigs } from '~/helpers/configs';
|
||||
import { RevokeAllUserHistoryByAdminDocument } from '~/helpers/backend/graphql';
|
||||
import { useMutation } from '@urql/vue';
|
||||
import { useToast } from '~/composables/toast';
|
||||
|
||||
const props = defineProps<{
|
||||
config: ServerConfigs;
|
||||
}>();
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'update:config', v: ServerConfigs): void;
|
||||
}>();
|
||||
|
||||
const workingConfigs = useVModel(props, 'config', emit);
|
||||
|
||||
const t = useI18n();
|
||||
const toast = useToast();
|
||||
|
||||
// Get or set smtpConfigs from workingConfigs
|
||||
const historyConfig = computed({
|
||||
get() {
|
||||
return workingConfigs.value?.historyConfig;
|
||||
},
|
||||
set(value) {
|
||||
workingConfigs.value.historyConfig = value;
|
||||
},
|
||||
});
|
||||
|
||||
const showConfirmHistoryClearModal = ref(false);
|
||||
|
||||
// had to add this here, because useConfigHandler is too coupled with the settings page
|
||||
const { fetching: isRevoking, executeMutation: revokeAllUserHistoryByAdmin } =
|
||||
useMutation(RevokeAllUserHistoryByAdminDocument);
|
||||
|
||||
const clearAllHistory = async () => {
|
||||
const res = await revokeAllUserHistoryByAdmin({});
|
||||
|
||||
if (res.error) {
|
||||
toast.error(t('configs.history_configs.clear_failure'));
|
||||
}
|
||||
|
||||
if (res.data) {
|
||||
toast.success(t('configs.history_configs.clear_success'));
|
||||
}
|
||||
|
||||
return res;
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="grid md:grid-cols-3 gap-4 md:gap-4 pt-8">
|
||||
<div class="md:col-span-1">
|
||||
<h3 class="heading">{{ t('configs.history_configs.title') }}</h3>
|
||||
<p class="my-1 text-secondaryLight">
|
||||
{{ t('configs.history_configs.description') }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="space-y-8 sm:px-8 md:col-span-2">
|
||||
<section>
|
||||
<h4 class="font-semibold text-secondaryDark">
|
||||
{{ t('configs.history_configs.title') }}
|
||||
</h4>
|
||||
|
||||
<div class="space-y-4 py-4">
|
||||
<div class="flex items-center">
|
||||
<div class="flex justify-between w-full">
|
||||
<HoppSmartToggle
|
||||
:on="historyConfig.enabled"
|
||||
@change="historyConfig.enabled = !historyConfig.enabled"
|
||||
>
|
||||
{{ t('configs.history_configs.enable_history') }}
|
||||
</HoppSmartToggle>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<HoppButtonSecondary
|
||||
:label="t('configs.history_configs.clear_history')"
|
||||
@click="showConfirmHistoryClearModal = true"
|
||||
outline
|
||||
class="my-2"
|
||||
/>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<HoppSmartConfirmModal
|
||||
:show="showConfirmHistoryClearModal"
|
||||
:loading-state="isRevoking"
|
||||
:title="t('configs.history_configs.clear_confirm')"
|
||||
@hide-modal="showConfirmHistoryClearModal = false"
|
||||
@resolve="
|
||||
async () => {
|
||||
await clearAllHistory();
|
||||
showConfirmHistoryClearModal = false;
|
||||
}
|
||||
"
|
||||
/>
|
||||
</template>
|
||||
|
|
@ -23,6 +23,7 @@ import {
|
|||
ResetInfraConfigsDocument,
|
||||
ToggleAnalyticsCollectionDocument,
|
||||
ToggleSmtpDocument,
|
||||
ToggleUserHistoryStoreDocument,
|
||||
UpdateInfraConfigsDocument,
|
||||
} from '~/helpers/backend/graphql';
|
||||
import { ServerConfigs } from '~/helpers/configs';
|
||||
|
|
@ -55,6 +56,10 @@ const toggleDataSharingMutation = useMutation(
|
|||
);
|
||||
const toggleSMTPMutation = useMutation(ToggleSmtpDocument);
|
||||
|
||||
const toggleUserHistoryStoreMutation = useMutation(
|
||||
ToggleUserHistoryStoreDocument
|
||||
);
|
||||
|
||||
// Mutation handlers
|
||||
const {
|
||||
updateInfraConfigs,
|
||||
|
|
@ -62,6 +67,7 @@ const {
|
|||
resetInfraConfigs,
|
||||
updateDataSharingConfigs,
|
||||
toggleSMTPConfigs,
|
||||
toggleUserHistoryStore,
|
||||
} = useConfigHandler(props.workingConfigs);
|
||||
|
||||
// Call relevant mutations on component mount and initiate server restart
|
||||
|
|
@ -120,6 +126,14 @@ onMounted(async () => {
|
|||
if (!smtpResult) {
|
||||
return triggerComponentUnMount();
|
||||
}
|
||||
|
||||
const userHistoryStoreResult = await toggleUserHistoryStore(
|
||||
toggleUserHistoryStoreMutation
|
||||
);
|
||||
|
||||
if (!userHistoryStoreResult) {
|
||||
return triggerComponentUnMount();
|
||||
}
|
||||
}
|
||||
|
||||
restart.value = true;
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ import {
|
|||
ServiceStatus,
|
||||
ToggleAnalyticsCollectionMutation,
|
||||
ToggleSmtpMutation,
|
||||
ToggleUserHistoryStoreMutation,
|
||||
UpdateInfraConfigsMutation,
|
||||
} from '~/helpers/backend/graphql';
|
||||
import {
|
||||
|
|
@ -141,6 +142,14 @@ export function useConfigHandler(updatedConfigs?: ServerConfigs) {
|
|||
(x) => x.name === 'ALLOW_ANALYTICS_COLLECTION' && x.value === 'true'
|
||||
),
|
||||
},
|
||||
historyConfig: {
|
||||
name: 'history_settings',
|
||||
enabled: !!infraConfigs.value.find(
|
||||
(config) =>
|
||||
config.name === 'USER_HISTORY_STORE_ENABLED' &&
|
||||
config.value === 'ENABLE'
|
||||
),
|
||||
},
|
||||
};
|
||||
|
||||
// Cloning the current configs to working configs
|
||||
|
|
@ -384,12 +393,27 @@ export function useConfigHandler(updatedConfigs?: ServerConfigs) {
|
|||
'configs.mail_configs.toggle_failure'
|
||||
);
|
||||
|
||||
// Toggle User History Store
|
||||
const toggleUserHistoryStore = (
|
||||
toggleUserHistoryStore: UseMutationResponse<ToggleUserHistoryStoreMutation>
|
||||
) =>
|
||||
executeMutation(
|
||||
toggleUserHistoryStore,
|
||||
{
|
||||
status: updatedConfigs?.historyConfig.enabled
|
||||
? ServiceStatus.Enable
|
||||
: ServiceStatus.Disable,
|
||||
},
|
||||
'configs.user_history_store.toggle_failure'
|
||||
);
|
||||
|
||||
return {
|
||||
currentConfigs,
|
||||
workingConfigs,
|
||||
updateAuthProvider,
|
||||
updateDataSharingConfigs,
|
||||
toggleSMTPConfigs,
|
||||
toggleUserHistoryStore,
|
||||
updateInfraConfigs,
|
||||
resetInfraConfigs,
|
||||
fetchingInfraConfigs,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,3 @@
|
|||
mutation RevokeAllUserHistoryByAdmin {
|
||||
revokeAllUserHistoryByAdmin
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
mutation ToggleUserHistoryStore($status: ServiceStatus!) {
|
||||
toggleUserHistoryStore(status: $status)
|
||||
}
|
||||
|
|
@ -54,6 +54,11 @@ export type ServerConfigs = {
|
|||
};
|
||||
};
|
||||
|
||||
historyConfig: {
|
||||
name: string;
|
||||
enabled: boolean;
|
||||
};
|
||||
|
||||
dataSharingConfigs: {
|
||||
name: string;
|
||||
enabled: boolean;
|
||||
|
|
@ -195,6 +200,13 @@ const DATA_SHARING_CONFIGS: Omit<Config, 'key'>[] = [
|
|||
},
|
||||
];
|
||||
|
||||
export const HISTORY_STORE_CONFIG: Config[] = [
|
||||
{
|
||||
name: InfraConfigEnum.UserHistoryStoreEnabled,
|
||||
key: 'history_store_enabled',
|
||||
},
|
||||
];
|
||||
|
||||
export const ALL_CONFIGS = [
|
||||
GOOGLE_CONFIGS,
|
||||
MICROSOFT_CONFIGS,
|
||||
|
|
@ -202,4 +214,5 @@ export const ALL_CONFIGS = [
|
|||
MAIL_CONFIGS,
|
||||
CUSTOM_MAIL_CONFIGS,
|
||||
DATA_SHARING_CONFIGS,
|
||||
HISTORY_STORE_CONFIG,
|
||||
];
|
||||
|
|
|
|||
Loading…
Reference in a new issue