feat: added toggle Button to Frontend
This commit is contained in:
@@ -7,7 +7,7 @@ export type FormDataEntry = {
|
|||||||
value: string | Blob;
|
value: string | Blob;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type HoppEnvPair = { key: string; value: string };
|
export type HoppEnvPair = { key: string; value: string; secret: boolean };
|
||||||
|
|
||||||
export type HoppEnvs = {
|
export type HoppEnvs = {
|
||||||
global: HoppEnvPair[];
|
global: HoppEnvPair[];
|
||||||
|
|||||||
@@ -48,7 +48,8 @@
|
|||||||
"turn_off": "Ausschalten",
|
"turn_off": "Ausschalten",
|
||||||
"turn_on": "Einschalten",
|
"turn_on": "Einschalten",
|
||||||
"undo": "Rückgängig machen",
|
"undo": "Rückgängig machen",
|
||||||
"yes": "Ja"
|
"yes": "Ja",
|
||||||
|
"secret": "Als Secret speichern"
|
||||||
},
|
},
|
||||||
"add": {
|
"add": {
|
||||||
"new": "Neue hinzufügen",
|
"new": "Neue hinzufügen",
|
||||||
@@ -880,4 +881,4 @@
|
|||||||
"team": "Team Workspace",
|
"team": "Team Workspace",
|
||||||
"title": "Workspaces"
|
"title": "Workspaces"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -48,7 +48,8 @@
|
|||||||
"turn_off": "Turn off",
|
"turn_off": "Turn off",
|
||||||
"turn_on": "Turn on",
|
"turn_on": "Turn on",
|
||||||
"undo": "Undo",
|
"undo": "Undo",
|
||||||
"yes": "Yes"
|
"yes": "Yes",
|
||||||
|
"secret": "Save as secret"
|
||||||
},
|
},
|
||||||
"add": {
|
"add": {
|
||||||
"new": "Add new",
|
"new": "Add new",
|
||||||
|
|||||||
@@ -143,7 +143,6 @@ declare module 'vue' {
|
|||||||
IconLucideAlertTriangle: typeof import('~icons/lucide/alert-triangle')['default']
|
IconLucideAlertTriangle: typeof import('~icons/lucide/alert-triangle')['default']
|
||||||
IconLucideArrowLeft: typeof import('~icons/lucide/arrow-left')['default']
|
IconLucideArrowLeft: typeof import('~icons/lucide/arrow-left')['default']
|
||||||
IconLucideArrowUpRight: typeof import('~icons/lucide/arrow-up-right')['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']
|
IconLucideCheckCircle: typeof import('~icons/lucide/check-circle')['default']
|
||||||
IconLucideChevronRight: typeof import('~icons/lucide/chevron-right')['default']
|
IconLucideChevronRight: typeof import('~icons/lucide/chevron-right')['default']
|
||||||
IconLucideGlobe: typeof import('~icons/lucide/globe')['default']
|
IconLucideGlobe: typeof import('~icons/lucide/globe')['default']
|
||||||
|
|||||||
@@ -71,6 +71,16 @@
|
|||||||
@click="removeEnvironmentVariable(index)"
|
@click="removeEnvironmentVariable(index)"
|
||||||
/>
|
/>
|
||||||
</div>
|
</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>
|
</div>
|
||||||
<HoppSmartPlaceholder
|
<HoppSmartPlaceholder
|
||||||
v-if="vars.length === 0"
|
v-if="vars.length === 0"
|
||||||
@@ -110,6 +120,7 @@ import IconTrash2 from "~icons/lucide/trash-2"
|
|||||||
import IconDone from "~icons/lucide/check"
|
import IconDone from "~icons/lucide/check"
|
||||||
import IconPlus from "~icons/lucide/plus"
|
import IconPlus from "~icons/lucide/plus"
|
||||||
import IconTrash from "~icons/lucide/trash"
|
import IconTrash from "~icons/lucide/trash"
|
||||||
|
import IconLock from "~icons/lucide/lock"
|
||||||
import { clone } from "lodash-es"
|
import { clone } from "lodash-es"
|
||||||
import { computed, ref, watch } from "vue"
|
import { computed, ref, watch } from "vue"
|
||||||
import * as E from "fp-ts/Either"
|
import * as E from "fp-ts/Either"
|
||||||
@@ -140,6 +151,7 @@ type EnvironmentVariable = {
|
|||||||
env: {
|
env: {
|
||||||
key: string
|
key: string
|
||||||
value: string
|
value: string
|
||||||
|
secret: boolean
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -172,7 +184,7 @@ const idTicker = ref(0)
|
|||||||
|
|
||||||
const editingName = ref<string | null>(null)
|
const editingName = ref<string | null>(null)
|
||||||
const vars = ref<EnvironmentVariable[]>([
|
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>(
|
const clearIcon = refAutoReset<typeof IconTrash2 | typeof IconDone>(
|
||||||
@@ -262,6 +274,7 @@ const addEnvironmentVariable = () => {
|
|||||||
env: {
|
env: {
|
||||||
key: "",
|
key: "",
|
||||||
value: "",
|
value: "",
|
||||||
|
secret: false,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -270,6 +283,10 @@ const removeEnvironmentVariable = (index: number) => {
|
|||||||
vars.value.splice(index, 1)
|
vars.value.splice(index, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const toggleEnvironmentSecret = (index: number) => {
|
||||||
|
vars.value[index].env.secret = !vars.value[index].env.secret
|
||||||
|
}
|
||||||
|
|
||||||
const saveEnvironment = () => {
|
const saveEnvironment = () => {
|
||||||
if (!editingName.value) {
|
if (!editingName.value) {
|
||||||
toast.error(`${t("environment.invalid_name")}`)
|
toast.error(`${t("environment.invalid_name")}`)
|
||||||
|
|||||||
@@ -74,6 +74,16 @@
|
|||||||
@click="removeEnvironmentVariable(index)"
|
@click="removeEnvironmentVariable(index)"
|
||||||
/>
|
/>
|
||||||
</div>
|
</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>
|
</div>
|
||||||
<HoppSmartPlaceholder
|
<HoppSmartPlaceholder
|
||||||
v-if="vars.length === 0"
|
v-if="vars.length === 0"
|
||||||
@@ -139,6 +149,7 @@ import IconTrash from "~icons/lucide/trash"
|
|||||||
import IconTrash2 from "~icons/lucide/trash-2"
|
import IconTrash2 from "~icons/lucide/trash-2"
|
||||||
import IconDone from "~icons/lucide/check"
|
import IconDone from "~icons/lucide/check"
|
||||||
import IconPlus from "~icons/lucide/plus"
|
import IconPlus from "~icons/lucide/plus"
|
||||||
|
import IconLock from "~icons/lucide/lock"
|
||||||
import { platform } from "~/platform"
|
import { platform } from "~/platform"
|
||||||
|
|
||||||
type EnvironmentVariable = {
|
type EnvironmentVariable = {
|
||||||
@@ -146,6 +157,7 @@ type EnvironmentVariable = {
|
|||||||
env: {
|
env: {
|
||||||
key: string
|
key: string
|
||||||
value: string
|
value: string
|
||||||
|
secret: boolean
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -182,7 +194,7 @@ const idTicker = ref(0)
|
|||||||
|
|
||||||
const editingName = ref<string | null>(null)
|
const editingName = ref<string | null>(null)
|
||||||
const vars = ref<EnvironmentVariable[]>([
|
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>(
|
const clearIcon = refAutoReset<typeof IconTrash2 | typeof IconDone>(
|
||||||
@@ -220,7 +232,7 @@ watch(
|
|||||||
editingName.value = null
|
editingName.value = null
|
||||||
vars.value = pipe(
|
vars.value = pipe(
|
||||||
props.envVars() ?? [],
|
props.envVars() ?? [],
|
||||||
A.map((e: { key: string; value: string }) => ({
|
A.map((e: { key: string; value: string; secret: boolean }) => ({
|
||||||
id: idTicker.value++,
|
id: idTicker.value++,
|
||||||
env: clone(e),
|
env: clone(e),
|
||||||
}))
|
}))
|
||||||
@@ -229,7 +241,7 @@ watch(
|
|||||||
editingName.value = props.editingEnvironment.environment.name ?? null
|
editingName.value = props.editingEnvironment.environment.name ?? null
|
||||||
vars.value = pipe(
|
vars.value = pipe(
|
||||||
props.editingEnvironment.environment.variables ?? [],
|
props.editingEnvironment.environment.variables ?? [],
|
||||||
A.map((e: { key: string; value: string }) => ({
|
A.map((e: { key: string; value: string; secret: boolean }) => ({
|
||||||
id: idTicker.value++,
|
id: idTicker.value++,
|
||||||
env: clone(e),
|
env: clone(e),
|
||||||
}))
|
}))
|
||||||
@@ -251,6 +263,7 @@ const addEnvironmentVariable = () => {
|
|||||||
env: {
|
env: {
|
||||||
key: "",
|
key: "",
|
||||||
value: "",
|
value: "",
|
||||||
|
secret: false,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -259,6 +272,10 @@ const removeEnvironmentVariable = (index: number) => {
|
|||||||
vars.value.splice(index, 1)
|
vars.value.splice(index, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const toggleEnvironmentSecret = (index: number) => {
|
||||||
|
vars.value[index].env.secret = !vars.value[index].env.secret
|
||||||
|
}
|
||||||
|
|
||||||
const isLoading = ref(false)
|
const isLoading = ref(false)
|
||||||
|
|
||||||
const saveEnvironment = async () => {
|
const saveEnvironment = async () => {
|
||||||
|
|||||||
@@ -279,6 +279,7 @@ const globalEnvVars = useReadonlyStream(globalEnv$, []) as Ref<
|
|||||||
Array<{
|
Array<{
|
||||||
key: string
|
key: string
|
||||||
value: string
|
value: string
|
||||||
|
secret: boolean
|
||||||
}>
|
}>
|
||||||
>
|
>
|
||||||
|
|
||||||
|
|||||||
@@ -48,6 +48,7 @@ type Props = {
|
|||||||
env: {
|
env: {
|
||||||
key: string
|
key: string
|
||||||
value: string
|
value: string
|
||||||
|
secret: boolean
|
||||||
previousValue?: string
|
previousValue?: string
|
||||||
}
|
}
|
||||||
status: Status
|
status: Status
|
||||||
|
|||||||
@@ -72,7 +72,9 @@ const props = withDefaults(
|
|||||||
modelValue?: string
|
modelValue?: string
|
||||||
placeholder?: string
|
placeholder?: string
|
||||||
styles?: string
|
styles?: string
|
||||||
envs?: { key: string; value: string; source: string }[] | null
|
envs?:
|
||||||
|
| { key: string; value: string; secret: boolean; source: string }[]
|
||||||
|
| null
|
||||||
focus?: boolean
|
focus?: boolean
|
||||||
selectTextOnMount?: boolean
|
selectTextOnMount?: boolean
|
||||||
environmentHighlights?: boolean
|
environmentHighlights?: boolean
|
||||||
@@ -320,6 +322,7 @@ const envVars = computed(() =>
|
|||||||
? props.envs.map((x) => ({
|
? props.envs.map((x) => ({
|
||||||
key: x.key,
|
key: x.key,
|
||||||
value: x.value,
|
value: x.value,
|
||||||
|
secret: x.secret,
|
||||||
sourceEnv: x.source,
|
sourceEnv: x.source,
|
||||||
}))
|
}))
|
||||||
: aggregateEnvs.value
|
: aggregateEnvs.value
|
||||||
|
|||||||
@@ -66,7 +66,10 @@ const cursorTooltipField = (aggregateEnvs: AggregateEnvironment[]) =>
|
|||||||
|
|
||||||
const envName = tooltipEnv?.sourceEnv ?? "Choose an Environment"
|
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)
|
const result = parseTemplateStringE(envValue, aggregateEnvs)
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
"!name": "pw-pre",
|
"!name": "pw-pre",
|
||||||
"pw": {
|
"pw": {
|
||||||
"env": {
|
"env": {
|
||||||
"set": "fn(key: string, value: string)",
|
"set": "fn(key: string, value: string, secret: boolean)",
|
||||||
"get": "fn(key: string) -> string",
|
"get": "fn(key: string) -> string",
|
||||||
"getResolve": "fn(key: string) -> string",
|
"getResolve": "fn(key: string) -> string",
|
||||||
"resolve": "fn(value: string) -> string"
|
"resolve": "fn(value: string) -> string"
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
"body": "?"
|
"body": "?"
|
||||||
},
|
},
|
||||||
"env": {
|
"env": {
|
||||||
"set": "fn(key: string, value: string)",
|
"set": "fn(key: string, value: string, secret:boolean)",
|
||||||
"get": "fn(key: string) -> string",
|
"get": "fn(key: string) -> string",
|
||||||
"getResolve": "fn(key: string) -> string",
|
"getResolve": "fn(key: string) -> string",
|
||||||
"resolve": "fn(value: string) -> string"
|
"resolve": "fn(value: string) -> string"
|
||||||
|
|||||||
@@ -186,14 +186,19 @@ const dispatchers = defineDispatchers({
|
|||||||
},
|
},
|
||||||
addEnvironmentVariable(
|
addEnvironmentVariable(
|
||||||
{ environments }: EnvironmentStore,
|
{ environments }: EnvironmentStore,
|
||||||
{ envIndex, key, value }: { envIndex: number; key: string; value: string }
|
{
|
||||||
|
envIndex,
|
||||||
|
key,
|
||||||
|
value,
|
||||||
|
secret,
|
||||||
|
}: { envIndex: number; key: string; value: string; secret: boolean }
|
||||||
) {
|
) {
|
||||||
return {
|
return {
|
||||||
environments: environments.map((env, index) =>
|
environments: environments.map((env, index) =>
|
||||||
index === envIndex
|
index === envIndex
|
||||||
? {
|
? {
|
||||||
...env,
|
...env,
|
||||||
variables: [...env.variables, { key, value }],
|
variables: [...env.variables, { key, value, secret }],
|
||||||
}
|
}
|
||||||
: env
|
: env
|
||||||
),
|
),
|
||||||
@@ -221,7 +226,10 @@ const dispatchers = defineDispatchers({
|
|||||||
{
|
{
|
||||||
envIndex,
|
envIndex,
|
||||||
vars,
|
vars,
|
||||||
}: { envIndex: number; vars: { key: string; value: string }[] }
|
}: {
|
||||||
|
envIndex: number
|
||||||
|
vars: { key: string; value: string; secret: boolean }[]
|
||||||
|
}
|
||||||
) {
|
) {
|
||||||
return {
|
return {
|
||||||
environments: environments.map((env, index) =>
|
environments: environments.map((env, index) =>
|
||||||
@@ -241,11 +249,13 @@ const dispatchers = defineDispatchers({
|
|||||||
variableIndex,
|
variableIndex,
|
||||||
updatedKey,
|
updatedKey,
|
||||||
updatedValue,
|
updatedValue,
|
||||||
|
updatedSecret,
|
||||||
}: {
|
}: {
|
||||||
envIndex: number
|
envIndex: number
|
||||||
variableIndex: number
|
variableIndex: number
|
||||||
updatedKey: string
|
updatedKey: string
|
||||||
updatedValue: string
|
updatedValue: string
|
||||||
|
updatedSecret: boolean
|
||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
return {
|
return {
|
||||||
@@ -255,7 +265,11 @@ const dispatchers = defineDispatchers({
|
|||||||
...env,
|
...env,
|
||||||
variables: env.variables.map((v, vIndex) =>
|
variables: env.variables.map((v, vIndex) =>
|
||||||
vIndex === variableIndex
|
vIndex === variableIndex
|
||||||
? { key: updatedKey, value: updatedValue }
|
? {
|
||||||
|
key: updatedKey,
|
||||||
|
value: updatedValue,
|
||||||
|
secret: updatedSecret,
|
||||||
|
}
|
||||||
: v
|
: v
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
@@ -359,6 +373,7 @@ export const currentEnvironment$: Observable<Environment | undefined> =
|
|||||||
export type AggregateEnvironment = {
|
export type AggregateEnvironment = {
|
||||||
key: string
|
key: string
|
||||||
value: string
|
value: string
|
||||||
|
secret: boolean
|
||||||
sourceEnv: string
|
sourceEnv: string
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -373,11 +388,11 @@ export const aggregateEnvs$: Observable<AggregateEnvironment[]> = combineLatest(
|
|||||||
map(([selectedEnv, globalVars]) => {
|
map(([selectedEnv, globalVars]) => {
|
||||||
const results: AggregateEnvironment[] = []
|
const results: AggregateEnvironment[] = []
|
||||||
|
|
||||||
selectedEnv?.variables.forEach(({ key, value }) =>
|
selectedEnv?.variables.forEach(({ key, value, secret }) =>
|
||||||
results.push({ key, value, sourceEnv: selectedEnv.name })
|
results.push({ key, value, secret, sourceEnv: selectedEnv.name })
|
||||||
)
|
)
|
||||||
globalVars.forEach(({ key, value }) =>
|
globalVars.forEach(({ key, value, secret }) =>
|
||||||
results.push({ key, value, sourceEnv: "Global" })
|
results.push({ key, value, secret, sourceEnv: "Global" })
|
||||||
)
|
)
|
||||||
|
|
||||||
return results
|
return results
|
||||||
@@ -593,7 +608,7 @@ export function updateEnvironment(envIndex: number, updatedEnv: Environment) {
|
|||||||
|
|
||||||
export function setEnvironmentVariables(
|
export function setEnvironmentVariables(
|
||||||
envIndex: number,
|
envIndex: number,
|
||||||
vars: { key: string; value: string }[]
|
vars: { key: string; value: string; secret: boolean }[]
|
||||||
) {
|
) {
|
||||||
environmentsStore.dispatch({
|
environmentsStore.dispatch({
|
||||||
dispatcher: "setEnvironmentVariables",
|
dispatcher: "setEnvironmentVariables",
|
||||||
@@ -606,7 +621,7 @@ export function setEnvironmentVariables(
|
|||||||
|
|
||||||
export function addEnvironmentVariable(
|
export function addEnvironmentVariable(
|
||||||
envIndex: number,
|
envIndex: number,
|
||||||
{ key, value }: { key: string; value: string }
|
{ key, value, secret }: { key: string; value: string; secret: boolean }
|
||||||
) {
|
) {
|
||||||
environmentsStore.dispatch({
|
environmentsStore.dispatch({
|
||||||
dispatcher: "addEnvironmentVariable",
|
dispatcher: "addEnvironmentVariable",
|
||||||
@@ -614,6 +629,7 @@ export function addEnvironmentVariable(
|
|||||||
envIndex,
|
envIndex,
|
||||||
key,
|
key,
|
||||||
value,
|
value,
|
||||||
|
secret,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -634,7 +650,7 @@ export function removeEnvironmentVariable(
|
|||||||
export function updateEnvironmentVariable(
|
export function updateEnvironmentVariable(
|
||||||
envIndex: number,
|
envIndex: number,
|
||||||
variableIndex: number,
|
variableIndex: number,
|
||||||
{ key, value }: { key: string; value: string }
|
{ key, value, secret }: { key: string; value: string; secret: boolean }
|
||||||
) {
|
) {
|
||||||
environmentsStore.dispatch({
|
environmentsStore.dispatch({
|
||||||
dispatcher: "updateEnvironmentVariable",
|
dispatcher: "updateEnvironmentVariable",
|
||||||
@@ -643,6 +659,7 @@ export function updateEnvironmentVariable(
|
|||||||
variableIndex,
|
variableIndex,
|
||||||
updatedKey: key,
|
updatedKey: key,
|
||||||
updatedValue: value,
|
updatedValue: value,
|
||||||
|
updatedSecret: secret,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ export type Environment = {
|
|||||||
variables: {
|
variables: {
|
||||||
key: string
|
key: string
|
||||||
value: string
|
value: string
|
||||||
|
secret: boolean
|
||||||
}[]
|
}[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -50,6 +50,7 @@ export function getEnv(envName: string, envs: TestResult["envs"]) {
|
|||||||
export function setEnv(
|
export function setEnv(
|
||||||
envName: string,
|
envName: string,
|
||||||
envValue: string,
|
envValue: string,
|
||||||
|
envSecret: boolean,
|
||||||
envs: TestResult["envs"]
|
envs: TestResult["envs"]
|
||||||
): TestResult["envs"] {
|
): TestResult["envs"] {
|
||||||
const indexInSelected = envs.selected.findIndex((x) => x.key === envName)
|
const indexInSelected = envs.selected.findIndex((x) => x.key === envName)
|
||||||
@@ -80,6 +81,7 @@ export function setEnv(
|
|||||||
envs.selected.push({
|
envs.selected.push({
|
||||||
key: envName,
|
key: envName,
|
||||||
value: envValue,
|
value: envValue,
|
||||||
|
secret: envSecret,
|
||||||
})
|
})
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
Reference in New Issue
Block a user