fix: inputfield to readonly + asterisk if secret

This commit is contained in:
Daniel Maurer
2023-07-26 15:59:36 +02:00
committed by nivedin
parent e0eb8af6f5
commit f530fc2853
5 changed files with 109 additions and 34 deletions

View File

@@ -133,24 +133,6 @@ declare module 'vue' {
HttpTestResultReport: typeof import('./components/http/TestResultReport.vue')['default']
HttpTests: typeof import('./components/http/Tests.vue')['default']
HttpURLEncodedParams: typeof import('./components/http/URLEncodedParams.vue')['default']
IconLucideActivity: typeof import('~icons/lucide/activity')['default']
IconLucideAlertTriangle: typeof import('~icons/lucide/alert-triangle')['default']
IconLucideArrowLeft: typeof import('~icons/lucide/arrow-left')['default']
IconLucideArrowUpRight: typeof import('~icons/lucide/arrow-up-right')['default']
IconLucideCheckCircle: typeof import('~icons/lucide/check-circle')['default']
IconLucideChevronRight: typeof import('~icons/lucide/chevron-right')['default']
IconLucideGlobe: typeof import('~icons/lucide/globe')['default']
IconLucideHelpCircle: typeof import('~icons/lucide/help-circle')['default']
IconLucideInbox: typeof import('~icons/lucide/inbox')['default']
IconLucideInfo: typeof import('~icons/lucide/info')['default']
IconLucideLayers: typeof import('~icons/lucide/layers')['default']
IconLucideListEnd: typeof import('~icons/lucide/list-end')['default']
IconLucideMinus: typeof import('~icons/lucide/minus')['default']
IconLucideRss: typeof import('~icons/lucide/rss')['default']
IconLucideSearch: typeof import('~icons/lucide/search')['default']
IconLucideUsers: typeof import('~icons/lucide/users')['default']
IconLucideVerified: typeof import('~icons/lucide/verified')['default']
InterceptorsExtensionSubtitle: typeof import('./components/interceptors/ExtensionSubtitle.vue')['default']
LensesHeadersRenderer: typeof import('./components/lenses/HeadersRenderer.vue')['default']
LensesHeadersRendererEntry: typeof import('./components/lenses/HeadersRendererEntry.vue')['default']
LensesRenderersAudioLensRenderer: typeof import('./components/lenses/renderers/AudioLensRenderer.vue')['default']

View File

@@ -60,6 +60,7 @@
:placeholder="`${t('count.value', { count: index + 1 })}`"
:envs="liveEnvs"
:name="'value' + index"
:secret="env.secret"
/>
<div class="flex">
<HoppButtonSecondary
@@ -215,6 +216,8 @@ const workingEnv = computed(() => {
}
})
const oldEnvironments = ref<Environment | null>(workingEnv.value)
const envList = useReadonlyStream(environments$, []) || props.envVars()
const evnExpandError = computed(() => {
@@ -246,6 +249,21 @@ const liveEnvs = computed(() => {
}
})
watch(liveEnvs, (newLiveEnv, oldLiveEnv) => {
for (let i = 0; i < newLiveEnv.length; i++) {
const newVar = newLiveEnv[i]
const oldVar = oldLiveEnv[i]
if (!newVar.secret && newVar.value !== oldVar.value) {
const _oldEnvironments = oldEnvironments.value
if (_oldEnvironments) {
_oldEnvironments.variables[i].value = newVar.value
}
oldEnvironments.value = _oldEnvironments
}
}
})
watch(
() => props.show,
(show) => {
@@ -292,7 +310,14 @@ const saveEnvironment = () => {
toast.error(`${t("environment.invalid_name")}`)
return
}
const _vars = vars.value
for (let i = 0; i < vars.value.length; i++) {
const value = oldEnvironments.value?.variables[i].value
if (value) {
_vars[i].env.value = value
}
}
vars.value = _vars
const filterdVariables = pipe(
vars.value,
A.filterMap(

View File

@@ -63,6 +63,7 @@
:envs="liveEnvs"
:name="'value' + index"
:readonly="isViewer"
:secret="env.secret"
/>
<div v-if="!isViewer" class="flex">
<HoppButtonSecondary
@@ -197,6 +198,7 @@ const vars = ref<EnvironmentVariable[]>([
{ id: idTicker.value++, env: { key: "", value: "", secret: false } },
])
const oldEnvironments = ref(props.envVars())
const clearIcon = refAutoReset<typeof IconTrash2 | typeof IconDone>(
IconTrash2,
1000
@@ -224,6 +226,21 @@ const liveEnvs = computed(() => {
}
})
watch(liveEnvs, (newLiveEnv, oldLiveEnv) => {
for (let i = 0; i < newLiveEnv.length; i++) {
const newVar = newLiveEnv[i]
const oldVar = oldLiveEnv[i]
if (!newVar.secret && newVar.value !== oldVar.value) {
const _oldEnvironments = oldEnvironments.value
if (_oldEnvironments) {
_oldEnvironments[i].value = newVar.value
}
oldEnvironments.value = _oldEnvironments
}
}
})
watch(
() => props.show,
(show) => {
@@ -286,6 +303,15 @@ const saveEnvironment = async () => {
return
}
const _vars = vars.value
for (let i = 0; i < vars.value.length; i++) {
const value = oldEnvironments.value[i].value
if (value) {
_vars[i].env.value = value
}
}
vars.value = _vars
const filterdVariables = pipe(
vars.value,
A.filterMap(

View File

@@ -55,7 +55,12 @@ import {
keymap,
tooltips,
} from "@codemirror/view"
import { EditorSelection, EditorState, Extension } from "@codemirror/state"
import {
EditorSelection,
EditorState,
Extension,
StateEffect,
} from "@codemirror/state"
import { clone } from "lodash-es"
import { history, historyKeymap } from "@codemirror/commands"
import { inputTheme } from "~/helpers/editor/themes/baseTheme"
@@ -81,6 +86,8 @@ const props = withDefaults(
readonly?: boolean
autoCompleteSource?: string[]
inspectionResults?: InspectorResult[] | undefined
defaultValue?: string
secret?: boolean
}>(),
{
modelValue: "",
@@ -93,6 +100,8 @@ const props = withDefaults(
autoCompleteSource: undefined,
inspectionResult: undefined,
inspectionResults: undefined,
defaultValue: "",
secret: false,
}
)
@@ -106,6 +115,8 @@ const emit = defineEmits<{
(e: "click", ev: any): void
}>()
const ASTERISK = "******"
const cachedValue = ref(props.modelValue)
const view = ref<EditorView>()
@@ -265,6 +276,23 @@ watch(
}
)
const prevModelValue = ref(props.modelValue)
watch(
() => props.secret,
(newValue, oldValue) => {
if (newValue !== oldValue) {
let visibleValue = ASTERISK
if (!newValue) {
visibleValue = prevModelValue.value
} else {
prevModelValue.value = props.modelValue
}
emit("update:modelValue", visibleValue)
updateEditorViewTheme(newValue)
}
}
)
/**
* Used to scroll the active suggestion into view
*/
@@ -286,7 +314,6 @@ watch(
() => props.modelValue,
(newVal) => {
const singleLinedText = newVal.replaceAll("\n", "")
const currDoc = view.value?.state.doc
.toJSON()
.join(view.value.state.lineBreak)
@@ -357,6 +384,14 @@ function handleTextSelection() {
}
}
}
const updateEditorViewTheme = (readonly: boolean) => {
if (view.value) {
const extensions: Extension = getExtensions(readonly)
view.value.dispatch({
effects: [StateEffect.reconfigure.of(extensions)],
})
}
}
const initView = (el: any) => {
// Debounce to prevent double click from selecting the word
@@ -367,17 +402,31 @@ const initView = (el: any) => {
el.addEventListener("mouseup", debounceFn)
el.addEventListener("keyup", debounceFn)
if (props.secret) {
emit("update:modelValue", ASTERISK)
}
const extensions: Extension = getExtensions(props.readonly || props.secret)
view.value = new EditorView({
parent: el,
state: EditorState.create({
doc: props.modelValue,
extensions,
}),
})
}
const getExtensions = (readonly: boolean): Extension => {
const extensions: Extension = [
EditorView.contentAttributes.of({ "aria-label": props.placeholder }),
EditorView.contentAttributes.of({ "data-enable-grammarly": "false" }),
EditorView.updateListener.of((update) => {
if (props.readonly) {
if (readonly) {
update.view.contentDOM.inputMode = "none"
}
}),
EditorState.changeFilter.of(() => !props.readonly),
EditorState.changeFilter.of(() => !readonly),
inputTheme,
props.readonly
readonly
? EditorView.theme({
".cm-content": {
caretColor: "var(--secondary-dark-color)",
@@ -409,7 +458,7 @@ const initView = (el: any) => {
ViewPlugin.fromClass(
class {
update(update: ViewUpdate) {
if (props.readonly) return
if (readonly) return
if (update.docChanged) {
const prevValue = clone(cachedValue.value)
@@ -448,14 +497,7 @@ const initView = (el: any) => {
history(),
keymap.of([...historyKeymap]),
]
view.value = new EditorView({
parent: el,
state: EditorState.create({
doc: props.modelValue,
extensions,
}),
})
return extensions
}
const triggerTextSelection = () => {

View File

@@ -68,7 +68,7 @@ const cursorTooltipField = (aggregateEnvs: AggregateEnvironment[]) =>
let envValue = tooltipEnv?.value ?? "Not found"
if (tooltipEnv?.secret) {
envValue = "*".repeat(envValue.length)
envValue = "******"
}
const result = parseTemplateStringE(envValue, aggregateEnvs)