Skip to content

Commit fdd638d

Browse files
niklubnik
and
nik
authored
feat: DIA-1815: Add conditional dependencies in product tour (#6918)
Co-authored-by: nik <[email protected]>
1 parent b38000e commit fdd638d

File tree

2 files changed

+25
-2
lines changed

2 files changed

+25
-2
lines changed

label_studio/users/product_tours/serializers.py

+20-2
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,23 @@
1+
import logging
12
import pathlib
23
from functools import cached_property
34

45
import yaml
6+
from core.utils.db import fast_first
57
from rest_framework import serializers
68

7-
from .models import ProductTourInteractionData, UserProductTour
9+
from .models import ProductTourInteractionData, ProductTourState, UserProductTour
10+
11+
logger = logging.getLogger(__name__)
812

913
PRODUCT_TOURS_CONFIGS_DIR = pathlib.Path(__file__).parent / 'configs'
1014

1115

1216
class UserProductTourSerializer(serializers.ModelSerializer):
17+
# steps is a list of steps in the tour loaded from the yaml file
1318
steps = serializers.SerializerMethodField(read_only=True)
19+
# awaiting is a boolean that indicates if the tour is awaiting other tours in the list of "dependencies"
20+
awaiting = serializers.SerializerMethodField(read_only=True)
1421

1522
class Meta:
1623
model = UserProductTour
@@ -29,14 +36,25 @@ def validate_name(self, value):
2936

3037
return value
3138

39+
@cached_property
3240
def load_tour_config(self):
3341
# TODO: get product tour from yaml file. Later we move it to remote storage, e.g. S3
3442
filepath = PRODUCT_TOURS_CONFIGS_DIR / f'{self.context["name"]}.yml'
3543
with open(filepath, 'r') as f:
3644
return yaml.safe_load(f)
3745

46+
def get_awaiting(self, obj):
47+
config = self.load_tour_config
48+
dependencies = config.get('dependencies', [])
49+
for dependency in dependencies:
50+
tour = fast_first(UserProductTour.objects.filter(user=self.context['request'].user, name=dependency))
51+
if not tour or tour.state != ProductTourState.COMPLETED:
52+
logger.info(f'Tour {dependency} is not completed: skipping tour {self.context["name"]}')
53+
return True
54+
return False
55+
3856
def get_steps(self, obj):
39-
config = self.load_tour_config()
57+
config = self.load_tour_config
4058
return config.get('steps', [])
4159

4260
def validate_interaction_data(self, value):

web/libs/core/src/lib/Tour/TourProvider.tsx

+5
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,11 @@ export const TourProvider: React.FC<{
131131
return;
132132
}
133133

134+
if (response.awaiting) {
135+
console.info(`Tour "${name}" is awaiting other tours`);
136+
return;
137+
}
138+
134139
if (!response.steps?.length) {
135140
console.info(`No steps found for tour "${name}"`);
136141
return;

0 commit comments

Comments
 (0)