version-0.1 #1

Merged
wamplerj merged 18 commits from version-0.1 into main 2026-07-01 13:30:08 -07:00
4 changed files with 69 additions and 30 deletions
Showing only changes of commit 5506151f19 - Show all commits

View File

@@ -319,6 +319,7 @@ interface Props {
modelValue: boolean; modelValue: boolean;
feature: FeatureResponse | null; feature: FeatureResponse | null;
featureState: FeatureStateResponse | null; featureState: FeatureStateResponse | null;
initialTab?: string;
} }
const props = defineProps<Props>(); const props = defineProps<Props>();
@@ -472,7 +473,7 @@ watch(
() => props.modelValue, () => props.modelValue,
(open) => { (open) => {
if (open) { if (open) {
activeTab.value = 'value'; activeTab.value = props.initialTab ?? 'value';
valueErrorMessage.value = null; valueErrorMessage.value = null;
settingsErrorMessage.value = null; settingsErrorMessage.value = null;
segmentsErrorMessage.value = null; segmentsErrorMessage.value = null;

View File

@@ -1,14 +1,24 @@
<template> <template>
<div data-testid="feature-value-editor"> <div data-testid="feature-value-editor">
<!-- Type selector --> <!-- Type selector -->
<v-btn-toggle <div class="d-flex mb-3" data-testid="value-mode-toggle">
v-model="detectedMode" <v-btn
density="compact" size="small"
data-testid="value-mode-toggle" :variant="detectedMode === 'text' ? 'flat' : 'outlined'"
> color="primary"
<v-btn value="text" size="small">Text</v-btn> rounded="0"
<v-btn value="json" size="small">JSON</v-btn> style="border-radius: 4px 0 0 4px"
</v-btn-toggle> @click="detectedMode = 'text'"
>Text</v-btn>
<v-btn
size="small"
:variant="detectedMode === 'json' ? 'flat' : 'outlined'"
color="primary"
rounded="0"
style="border-radius: 0 4px 4px 0; margin-left: -1px"
@click="detectedMode = 'json'"
>JSON</v-btn>
</div>
<!-- JSON mode --> <!-- JSON mode -->
<v-textarea <v-textarea
@@ -83,11 +93,3 @@ const rules = {
}; };
</script> </script>
<style scoped>
/* Materio forces square icon-toggle sizing; override for text-label toggles */
:deep(.v-btn-toggle .v-btn) {
block-size: auto !important;
inline-size: auto !important;
padding-inline: 16px !important;
}
</style>

View File

@@ -3,18 +3,26 @@
<!-- AND / OR toggle --> <!-- AND / OR toggle -->
<div class="d-flex align-center ga-2 mb-3"> <div class="d-flex align-center ga-2 mb-3">
<span class="text-body-2 font-weight-medium text-medium-emphasis">Match</span> <span class="text-body-2 font-weight-medium text-medium-emphasis">Match</span>
<v-btn-toggle <div class="d-flex" data-testid="rule-type-toggle">
:model-value="rule.type" <v-btn
density="compact" size="small"
mandatory :variant="rule.type === 'All' ? 'flat' : 'outlined'"
color="primary" color="primary"
variant="outlined" rounded="0"
data-testid="rule-type-toggle" style="border-radius: 4px 0 0 4px"
@update:model-value="onTypeChange" data-testid="rule-type-and"
> @click="onTypeChange('All')"
<v-btn value="All" size="small" data-testid="rule-type-and">ALL (AND)</v-btn> >ALL (AND)</v-btn>
<v-btn value="Any" size="small" data-testid="rule-type-or">ANY (OR)</v-btn> <v-btn
</v-btn-toggle> size="small"
:variant="rule.type === 'Any' ? 'flat' : 'outlined'"
color="primary"
rounded="0"
style="border-radius: 0 4px 4px 0; margin-left: -1px"
data-testid="rule-type-or"
@click="onTypeChange('Any')"
>ANY (OR)</v-btn>
</div>
<v-spacer /> <v-spacer />
<v-btn <v-btn
v-if="removable" v-if="removable"

View File

@@ -53,7 +53,26 @@
<!-- Name + description --> <!-- Name + description -->
<template #item.name="{ item }: { item: FeatureResponse }"> <template #item.name="{ item }: { item: FeatureResponse }">
<div> <div>
<span class="text-body-2 font-weight-medium">{{ item.name }}</span> <div class="d-flex align-center ga-1">
<span class="text-subtitle-1 font-weight-bold">{{ item.name }}</span>
<v-tooltip
v-if="(featureSegmentsMap.get(item.id) ?? []).length > 0"
text="Has segment overrides"
location="top"
>
<template #activator="{ props: tooltipProps }">
<v-btn
v-bind="tooltipProps"
icon="ri-donut-chart-fill"
size="small"
variant="text"
color="secondary"
:data-testid="`segment-override-icon-${item.id}`"
@click.stop="openDetailOnSegments(item)"
/>
</template>
</v-tooltip>
</div>
<p v-if="item.description" class="text-caption text-medium-emphasis mb-0"> <p v-if="item.description" class="text-caption text-medium-emphasis mb-0">
{{ item.description }} {{ item.description }}
</p> </p>
@@ -158,6 +177,7 @@
v-model="showDetail" v-model="showDetail"
:feature="selectedFeature" :feature="selectedFeature"
:feature-state="selectedFeatureState" :feature-state="selectedFeatureState"
:initial-tab="detailInitialTab"
@updated="onFeatureUpdated" @updated="onFeatureUpdated"
@deleted="onFeatureDeleted" @deleted="onFeatureDeleted"
@state-updated="onStateUpdated" @state-updated="onStateUpdated"
@@ -236,6 +256,7 @@ function showError(message: string): void {
const showDialog = ref(false); const showDialog = ref(false);
const showDetail = ref(false); const showDetail = ref(false);
const selectedFeature = ref<FeatureResponse | null>(null); const selectedFeature = ref<FeatureResponse | null>(null);
const detailInitialTab = ref('value');
// Delete dialog state // Delete dialog state
const showDeleteDialog = ref(false); const showDeleteDialog = ref(false);
@@ -333,6 +354,13 @@ function openCreateDialog(): void {
} }
function onRowClick(_event: Event, { item }: { item: FeatureResponse }): void { function onRowClick(_event: Event, { item }: { item: FeatureResponse }): void {
detailInitialTab.value = 'value';
selectedFeature.value = item;
showDetail.value = true;
}
function openDetailOnSegments(item: FeatureResponse): void {
detailInitialTab.value = 'segments';
selectedFeature.value = item; selectedFeature.value = item;
showDetail.value = true; showDetail.value = true;
} }