feat: added toggle Button to Frontend

This commit is contained in:
Daniel Maurer
2023-07-21 14:56:19 +02:00
committed by nivedin
parent 7beed30815
commit 7d61e69b3d
15 changed files with 87 additions and 24 deletions

View File

@@ -7,7 +7,7 @@ export type FormDataEntry = {
value: string | Blob;
};
export type HoppEnvPair = { key: string; value: string };
export type HoppEnvPair = { key: string; value: string; secret: boolean };
export type HoppEnvs = {
global: HoppEnvPair[];

View File

@@ -48,7 +48,8 @@
"turn_off": "Ausschalten",
"turn_on": "Einschalten",
"undo": "Rückgängig machen",
"yes": "Ja"
"yes": "Ja",
"secret": "Als Secret speichern"
},
"add": {
"new": "Neue hinzufügen",
@@ -880,4 +881,4 @@
"team": "Team Workspace",
"title": "Workspaces"
}
}
}

View File

@@ -48,7 +48,8 @@
"turn_off": "Turn off",
"turn_on": "Turn on",
"undo": "Undo",
"yes": "Yes"
"yes": "Yes",
"secret": "Save as secret"
},
"add": {
"new": "Add new",

View File

@@ -143,7 +143,6 @@ declare module 'vue' {
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']
IconLucideBrush: typeof import('~icons/lucide/brush')['default']
IconLucideCheckCircle: typeof import('~icons/lucide/check-circle')['default']
IconLucideChevronRight: typeof import('~icons/lucide/chevron-right')['default']
IconLucideGlobe: typeof import('~icons/lucide/globe')['default']

View File

@@ -71,6 +71,16 @@
@click="removeEnvironmentVariable(index)"
/>
</div>
<div class="flex">
<HoppButtonSecondary
id="variable"
v-tippy="{ theme: 'tooltip' }"
:title="t('action.secret')"
:icon="IconLock"
:color="env.secret ? 'red' : ''"
@click="toggleEnvironmentSecret(index)"
/>
</div>
</div>
<HoppSmartPlaceholder
v-if="vars.length === 0"
@@ -110,6 +120,7 @@ import IconTrash2 from "~icons/lucide/trash-2"
import IconDone from "~icons/lucide/check"
import IconPlus from "~icons/lucide/plus"
import IconTrash from "~icons/lucide/trash"
import IconLock from "~icons/lucide/lock"
import { clone } from "lodash-es"
import { computed, ref, watch } from "vue"
import * as E from "fp-ts/Either"
@@ -140,6 +151,7 @@ type EnvironmentVariable = {
env: {
key: string
value: string
secret: boolean
}
}
@@ -172,7 +184,7 @@ const idTicker = ref(0)
const editingName = ref<string | null>(null)
const vars = ref<EnvironmentVariable[]>([
{ id: idTicker.value++, env: { key: "", value: "" } },
{ id: idTicker.value++, env: { key: "", value: "", secret: false } },
])
const clearIcon = refAutoReset<typeof IconTrash2 | typeof IconDone>(
@@ -262,6 +274,7 @@ const addEnvironmentVariable = () => {
env: {
key: "",
value: "",
secret: false,
},
})
}
@@ -270,6 +283,10 @@ const removeEnvironmentVariable = (index: number) => {
vars.value.splice(index, 1)
}
const toggleEnvironmentSecret = (index: number) => {
vars.value[index].env.secret = !vars.value[index].env.secret
}
const saveEnvironment = () => {
if (!editingName.value) {
toast.error(`${t("environment.invalid_name")}`)

View File

@@ -74,6 +74,16 @@
@click="removeEnvironmentVariable(index)"
/>
</div>
<div class="flex">
<HoppButtonSecondary
id="variable"
v-tippy="{ theme: 'tooltip' }"
:title="t('action.secret')"
:icon="IconLock"
:color="env.secret ? 'red' : ''"
@click="toggleEnvironmentSecret(index)"
/>
</div>
</div>
<HoppSmartPlaceholder
v-if="vars.length === 0"
@@ -139,6 +149,7 @@ import IconTrash from "~icons/lucide/trash"
import IconTrash2 from "~icons/lucide/trash-2"
import IconDone from "~icons/lucide/check"
import IconPlus from "~icons/lucide/plus"
import IconLock from "~icons/lucide/lock"
import { platform } from "~/platform"
type EnvironmentVariable = {
@@ -146,6 +157,7 @@ type EnvironmentVariable = {
env: {
key: string
value: string
secret: boolean
}
}
@@ -182,7 +194,7 @@ const idTicker = ref(0)
const editingName = ref<string | null>(null)
const vars = ref<EnvironmentVariable[]>([
{ id: idTicker.value++, env: { key: "", value: "" } },
{ id: idTicker.value++, env: { key: "", value: "", secret: false } },
])
const clearIcon = refAutoReset<typeof IconTrash2 | typeof IconDone>(
@@ -220,7 +232,7 @@ watch(
editingName.value = null
vars.value = pipe(
props.envVars() ?? [],
A.map((e: { key: string; value: string }) => ({
A.map((e: { key: string; value: string; secret: boolean }) => ({
id: idTicker.value++,
env: clone(e),
}))
@@ -229,7 +241,7 @@ watch(
editingName.value = props.editingEnvironment.environment.name ?? null
vars.value = pipe(
props.editingEnvironment.environment.variables ?? [],
A.map((e: { key: string; value: string }) => ({
A.map((e: { key: string; value: string; secret: boolean }) => ({
id: idTicker.value++,
env: clone(e),
}))
@@ -251,6 +263,7 @@ const addEnvironmentVariable = () => {
env: {
key: "",
value: "",
secret: false,
},
})
}
@@ -259,6 +272,10 @@ const removeEnvironmentVariable = (index: number) => {
vars.value.splice(index, 1)
}
const toggleEnvironmentSecret = (index: number) => {
vars.value[index].env.secret = !vars.value[index].env.secret
}
const isLoading = ref(false)
const saveEnvironment = async () => {

View File

@@ -279,6 +279,7 @@ const globalEnvVars = useReadonlyStream(globalEnv$, []) as Ref<
Array<{
key: string
value: string
secret: boolean
}>
>

View File

@@ -48,6 +48,7 @@ type Props = {
env: {
key: string
value: string
secret: boolean
previousValue?: string
}
status: Status

View File

@@ -72,7 +72,9 @@ const props = withDefaults(
modelValue?: string
placeholder?: string
styles?: string
envs?: { key: string; value: string; source: string }[] | null
envs?:
| { key: string; value: string; secret: boolean; source: string }[]
| null
focus?: boolean
selectTextOnMount?: boolean
environmentHighlights?: boolean
@@ -320,6 +322,7 @@ const envVars = computed(() =>
? props.envs.map((x) => ({
key: x.key,
value: x.value,
secret: x.secret,
sourceEnv: x.source,
}))
: aggregateEnvs.value

View File

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

View File

@@ -2,7 +2,7 @@
"!name": "pw-pre",
"pw": {
"env": {
"set": "fn(key: string, value: string)",
"set": "fn(key: string, value: string, secret: boolean)",
"get": "fn(key: string) -> string",
"getResolve": "fn(key: string) -> string",
"resolve": "fn(value: string) -> string"

View File

@@ -21,7 +21,7 @@
"body": "?"
},
"env": {
"set": "fn(key: string, value: string)",
"set": "fn(key: string, value: string, secret:boolean)",
"get": "fn(key: string) -> string",
"getResolve": "fn(key: string) -> string",
"resolve": "fn(value: string) -> string"

View File

@@ -186,14 +186,19 @@ const dispatchers = defineDispatchers({
},
addEnvironmentVariable(
{ environments }: EnvironmentStore,
{ envIndex, key, value }: { envIndex: number; key: string; value: string }
{
envIndex,
key,
value,
secret,
}: { envIndex: number; key: string; value: string; secret: boolean }
) {
return {
environments: environments.map((env, index) =>
index === envIndex
? {
...env,
variables: [...env.variables, { key, value }],
variables: [...env.variables, { key, value, secret }],
}
: env
),
@@ -221,7 +226,10 @@ const dispatchers = defineDispatchers({
{
envIndex,
vars,
}: { envIndex: number; vars: { key: string; value: string }[] }
}: {
envIndex: number
vars: { key: string; value: string; secret: boolean }[]
}
) {
return {
environments: environments.map((env, index) =>
@@ -241,11 +249,13 @@ const dispatchers = defineDispatchers({
variableIndex,
updatedKey,
updatedValue,
updatedSecret,
}: {
envIndex: number
variableIndex: number
updatedKey: string
updatedValue: string
updatedSecret: boolean
}
) {
return {
@@ -255,7 +265,11 @@ const dispatchers = defineDispatchers({
...env,
variables: env.variables.map((v, vIndex) =>
vIndex === variableIndex
? { key: updatedKey, value: updatedValue }
? {
key: updatedKey,
value: updatedValue,
secret: updatedSecret,
}
: v
),
}
@@ -359,6 +373,7 @@ export const currentEnvironment$: Observable<Environment | undefined> =
export type AggregateEnvironment = {
key: string
value: string
secret: boolean
sourceEnv: string
}
@@ -373,11 +388,11 @@ export const aggregateEnvs$: Observable<AggregateEnvironment[]> = combineLatest(
map(([selectedEnv, globalVars]) => {
const results: AggregateEnvironment[] = []
selectedEnv?.variables.forEach(({ key, value }) =>
results.push({ key, value, sourceEnv: selectedEnv.name })
selectedEnv?.variables.forEach(({ key, value, secret }) =>
results.push({ key, value, secret, sourceEnv: selectedEnv.name })
)
globalVars.forEach(({ key, value }) =>
results.push({ key, value, sourceEnv: "Global" })
globalVars.forEach(({ key, value, secret }) =>
results.push({ key, value, secret, sourceEnv: "Global" })
)
return results
@@ -593,7 +608,7 @@ export function updateEnvironment(envIndex: number, updatedEnv: Environment) {
export function setEnvironmentVariables(
envIndex: number,
vars: { key: string; value: string }[]
vars: { key: string; value: string; secret: boolean }[]
) {
environmentsStore.dispatch({
dispatcher: "setEnvironmentVariables",
@@ -606,7 +621,7 @@ export function setEnvironmentVariables(
export function addEnvironmentVariable(
envIndex: number,
{ key, value }: { key: string; value: string }
{ key, value, secret }: { key: string; value: string; secret: boolean }
) {
environmentsStore.dispatch({
dispatcher: "addEnvironmentVariable",
@@ -614,6 +629,7 @@ export function addEnvironmentVariable(
envIndex,
key,
value,
secret,
},
})
}
@@ -634,7 +650,7 @@ export function removeEnvironmentVariable(
export function updateEnvironmentVariable(
envIndex: number,
variableIndex: number,
{ key, value }: { key: string; value: string }
{ key, value, secret }: { key: string; value: string; secret: boolean }
) {
environmentsStore.dispatch({
dispatcher: "updateEnvironmentVariable",
@@ -643,6 +659,7 @@ export function updateEnvironmentVariable(
variableIndex,
updatedKey: key,
updatedValue: value,
updatedSecret: secret,
},
})
}

View File

@@ -7,6 +7,7 @@ export type Environment = {
variables: {
key: string
value: string
secret: boolean
}[]
}

View File

@@ -50,6 +50,7 @@ export function getEnv(envName: string, envs: TestResult["envs"]) {
export function setEnv(
envName: string,
envValue: string,
envSecret: boolean,
envs: TestResult["envs"]
): TestResult["envs"] {
const indexInSelected = envs.selected.findIndex((x) => x.key === envName)
@@ -80,6 +81,7 @@ export function setEnv(
envs.selected.push({
key: envName,
value: envValue,
secret: envSecret,
})
return {