Base environments fully working

This commit is contained in:
Gregory Schier
2023-11-02 18:43:39 -07:00
parent 1cd6e0af06
commit 68ea718c77
9 changed files with 57 additions and 33 deletions

View File

@@ -93,8 +93,11 @@ async fn actually_send_ephemeral_request(
let start = std::time::Instant::now(); let start = std::time::Instant::now();
let environment = models::get_environment(environment_id, pool).await.ok(); let environment = models::get_environment(environment_id, pool).await.ok();
let environment_ref = environment.as_ref(); let environment_ref = environment.as_ref();
let workspace = models::get_workspace(&request.workspace_id, pool)
.await
.expect("Failed to get workspace");
let mut url_string = render::render(&request.url, environment.as_ref()); let mut url_string = render::render(&request.url, &workspace, environment.as_ref());
if !url_string.starts_with("http://") && !url_string.starts_with("https://") { if !url_string.starts_with("http://") && !url_string.starts_with("https://") {
url_string = format!("http://{}", url_string); url_string = format!("http://{}", url_string);
@@ -119,8 +122,8 @@ async fn actually_send_ephemeral_request(
continue; continue;
} }
let name = render::render(&h.name, environment_ref); let name = render::render(&h.name, &workspace, environment_ref);
let value = render::render(&h.value, environment_ref); let value = render::render(&h.value, &workspace, environment_ref);
let header_name = match HeaderName::from_bytes(name.as_bytes()) { let header_name = match HeaderName::from_bytes(name.as_bytes()) {
Ok(n) => n, Ok(n) => n,
@@ -155,8 +158,8 @@ async fn actually_send_ephemeral_request(
.unwrap_or(empty_value) .unwrap_or(empty_value)
.as_str() .as_str()
.unwrap_or(""); .unwrap_or("");
let username = render::render(raw_username, environment_ref); let username = render::render(raw_username, &workspace, environment_ref);
let password = render::render(raw_password, environment_ref); let password = render::render(raw_password, &workspace, environment_ref);
let auth = format!("{username}:{password}"); let auth = format!("{username}:{password}");
let encoded = base64::engine::general_purpose::STANDARD_NO_PAD.encode(auth); let encoded = base64::engine::general_purpose::STANDARD_NO_PAD.encode(auth);
@@ -166,7 +169,7 @@ async fn actually_send_ephemeral_request(
); );
} else if b == "bearer" { } else if b == "bearer" {
let raw_token = a.get("token").unwrap_or(empty_value).as_str().unwrap_or(""); let raw_token = a.get("token").unwrap_or(empty_value).as_str().unwrap_or("");
let token = render::render(raw_token, environment_ref); let token = render::render(raw_token, &workspace, environment_ref);
headers.insert( headers.insert(
"Authorization", "Authorization",
HeaderValue::from_str(&format!("Bearer {token}")).unwrap(), HeaderValue::from_str(&format!("Bearer {token}")).unwrap(),
@@ -180,7 +183,7 @@ async fn actually_send_ephemeral_request(
let sendable_req_result = match (request.body, request.body_type) { let sendable_req_result = match (request.body, request.body_type) {
(Some(raw_body), Some(_)) => { (Some(raw_body), Some(_)) => {
let body = render::render(&raw_body, environment_ref); let body = render::render(&raw_body, &workspace, environment_ref);
builder.body(body).build() builder.body(body).build()
} }
_ => builder.build(), _ => builder.build(),

View File

@@ -1,24 +1,27 @@
use crate::models::Environment; use crate::models::{Environment, Workspace};
use std::collections::HashMap; use std::collections::HashMap;
use tauri::regex::Regex; use tauri::regex::Regex;
pub fn render(template: &str, environment: Option<&Environment>) -> String { pub fn render(template: &str, workspace: &Workspace, environment: Option<&Environment>) -> String {
match environment {
Some(environment) => render_with_environment(template, environment),
None => template.to_string(),
}
}
fn render_with_environment(template: &str, environment: &Environment) -> String {
let mut map = HashMap::new(); let mut map = HashMap::new();
let variables = &environment.variables.0; let workspace_variables = &workspace.variables.0;
for variable in variables { for variable in workspace_variables {
if !variable.enabled { if !variable.enabled || variable.value.is_empty() {
continue; continue;
} }
map.insert(variable.name.as_str(), variable.value.as_str()); map.insert(variable.name.as_str(), variable.value.as_str());
} }
if let Some(e) = environment {
let environment_variables = &e.variables.0;
for variable in environment_variables {
if !variable.enabled || variable.value.is_empty() {
continue;
}
map.insert(variable.name.as_str(), variable.value.as_str());
}
}
Regex::new(r"\$\{\[\s*([^]\s]+)\s*]}") Regex::new(r"\$\{\[\s*([^]\s]+)\s*]}")
.expect("Failed to create regex") .expect("Failed to create regex")
.replace_all(template, |caps: &tauri::regex::Captures| { .replace_all(template, |caps: &tauri::regex::Captures| {

View File

@@ -52,7 +52,11 @@ export const EnvironmentActionsDropdown = memo(function EnvironmentActionsDropdo
label: e.name, label: e.name,
rightSlot: e.id === activeEnvironment?.id ? <Icon icon="check" /> : undefined, rightSlot: e.id === activeEnvironment?.id ? <Icon icon="check" /> : undefined,
onSelect: async () => { onSelect: async () => {
routes.setEnvironment(e); if (e.id !== activeEnvironment?.id) {
routes.setEnvironment(e);
} else {
routes.setEnvironment(null);
}
}, },
}), }),
[activeEnvironment?.id], [activeEnvironment?.id],

View File

@@ -51,7 +51,7 @@ export const EnvironmentEditDialog = function ({ initialEnvironment }: Props) {
justify="start" justify="start"
className={classNames( className={classNames(
'w-full', 'w-full',
'text-gray-600 hocus:text-gray-800', 'text-gray-600 hocus:text-gray-800 !ring-0',
selectedEnvironment == null && 'bg-highlightSecondary !text-gray-900', selectedEnvironment == null && 'bg-highlightSecondary !text-gray-900',
)} )}
onClick={() => { onClick={() => {

View File

@@ -32,7 +32,7 @@ export function Overlay({
return ( return (
<Portal name={portalName}> <Portal name={portalName}>
{open && ( {open && (
<FocusTrap> <FocusTrap>
<motion.div <motion.div
className={classNames('fixed inset-0', zIndexes[zIndex])} className={classNames('fixed inset-0', zIndexes[zIndex])}
initial={{ opacity: 0 }} initial={{ opacity: 0 }}

View File

@@ -13,6 +13,7 @@ import { baseExtensions, getLanguageExtension, multiLineExtensions } from './ext
import type { GenericCompletionConfig } from './genericCompletion'; import type { GenericCompletionConfig } from './genericCompletion';
import { singleLineExt } from './singleLine'; import { singleLineExt } from './singleLine';
import { useActiveEnvironment } from '../../../hooks/useActiveEnvironment'; import { useActiveEnvironment } from '../../../hooks/useActiveEnvironment';
import { useActiveWorkspace } from '../../../hooks/useActiveWorkspace';
// Export some things so all the code-split parts are in this file // Export some things so all the code-split parts are in this file
export { buildClientSchema, getIntrospectionQuery } from 'graphql/utilities'; export { buildClientSchema, getIntrospectionQuery } from 'graphql/utilities';
@@ -72,7 +73,9 @@ const _Editor = forwardRef<EditorView | undefined, EditorProps>(function Editor(
ref, ref,
) { ) {
const e = useActiveEnvironment(); const e = useActiveEnvironment();
const w = useActiveWorkspace();
const environment = autocompleteVariables ? e : null; const environment = autocompleteVariables ? e : null;
const workspace = autocompleteVariables ? w : null;
const cm = useRef<{ view: EditorView; languageCompartment: Compartment } | null>(null); const cm = useRef<{ view: EditorView; languageCompartment: Compartment } | null>(null);
useImperativeHandle(ref, () => cm.current?.view); useImperativeHandle(ref, () => cm.current?.view);
@@ -124,9 +127,15 @@ const _Editor = forwardRef<EditorView | undefined, EditorProps>(function Editor(
useEffect(() => { useEffect(() => {
if (cm.current === null) return; if (cm.current === null) return;
const { view, languageCompartment } = cm.current; const { view, languageCompartment } = cm.current;
const ext = getLanguageExtension({ contentType, environment, useTemplating, autocomplete }); const ext = getLanguageExtension({
contentType,
environment,
workspace,
useTemplating,
autocomplete,
});
view.dispatch({ effects: languageCompartment.reconfigure(ext) }); view.dispatch({ effects: languageCompartment.reconfigure(ext) });
}, [contentType, autocomplete, useTemplating, environment]); }, [contentType, autocomplete, useTemplating, environment, workspace]);
useEffect(() => { useEffect(() => {
if (cm.current === null) return; if (cm.current === null) return;
@@ -152,6 +161,7 @@ const _Editor = forwardRef<EditorView | undefined, EditorProps>(function Editor(
useTemplating, useTemplating,
autocomplete, autocomplete,
environment, environment,
workspace,
}); });
const state = EditorState.create({ const state = EditorState.create({
@@ -271,7 +281,7 @@ function getExtensions({
EditorView.domEventHandlers({ EditorView.domEventHandlers({
focus: () => onFocus.current?.(), focus: () => onFocus.current?.(),
blur: () => onBlur.current?.(), blur: () => onBlur.current?.(),
keydown: e => onKeyDown.current?.(e), keydown: (e) => onKeyDown.current?.(e),
}), }),
// Handle onChange // Handle onChange

View File

@@ -36,7 +36,7 @@ import type { EditorProps } from './index';
import { text } from './text/extension'; import { text } from './text/extension';
import { twig } from './twig/extension'; import { twig } from './twig/extension';
import { url } from './url/extension'; import { url } from './url/extension';
import type { Environment } from '../../../lib/models'; import type { Environment, Workspace } from '../../../lib/models';
export const myHighlightStyle = HighlightStyle.define([ export const myHighlightStyle = HighlightStyle.define([
{ {
@@ -96,8 +96,9 @@ export function getLanguageExtension({
contentType, contentType,
useTemplating = false, useTemplating = false,
environment, environment,
workspace,
autocomplete, autocomplete,
}: { environment: Environment | null } & Pick< }: { environment: Environment | null; workspace: Workspace | null } & Pick<
EditorProps, EditorProps,
'contentType' | 'useTemplating' | 'autocomplete' 'contentType' | 'useTemplating' | 'autocomplete'
>) { >) {
@@ -110,7 +111,7 @@ export function getLanguageExtension({
return base; return base;
} }
return twig(base, environment, autocomplete); return twig(base, environment, workspace, autocomplete);
} }
export const baseExtensions = [ export const baseExtensions = [

View File

@@ -7,14 +7,17 @@ import { placeholders } from './placeholder';
import { textLanguageName } from '../text/extension'; import { textLanguageName } from '../text/extension';
import { twigCompletion } from './completion'; import { twigCompletion } from './completion';
import { parser as twigParser } from './twig'; import { parser as twigParser } from './twig';
import type { Environment } from '../../../../lib/models'; import type { Environment, Workspace } from '../../../../lib/models';
export function twig( export function twig(
base: LanguageSupport, base: LanguageSupport,
environment: Environment | null, environment: Environment | null,
workspace: Workspace | null,
autocomplete?: GenericCompletionConfig, autocomplete?: GenericCompletionConfig,
) { ) {
const variables = environment?.variables.filter(v => v.enabled) ?? []; const variables =
[...(workspace?.variables ?? []), ...(environment?.variables ?? [])].filter((v) => v.enabled) ??
[];
const completions = twigCompletion({ options: variables }); const completions = twigCompletion({ options: variables });
const language = mixLanguage(base); const language = mixLanguage(base);

View File

@@ -53,18 +53,18 @@ export function useAppRoutes() {
}, [nav]); }, [nav]);
const setEnvironment = useCallback( const setEnvironment = useCallback(
({ id: environmentId }: Environment) => { (environment: Environment | null) => {
if (workspaceId == null) { if (workspaceId == null) {
navigate('workspaces'); navigate('workspaces');
} else if (requestId == null) { } else if (requestId == null) {
navigate('workspace', { navigate('workspace', {
workspaceId: workspaceId, workspaceId: workspaceId,
environmentId: environmentId ?? null, environmentId: environment == null ? undefined : environment.id,
}); });
} else { } else {
navigate('request', { navigate('request', {
workspaceId, workspaceId,
environmentId: environmentId ?? null, environmentId: environment == null ? undefined : environment.id,
requestId, requestId,
}); });
} }