Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft: Experiment form using React #1455

Draft
wants to merge 89 commits into
base: develop
Choose a base branch
from
Draft

Conversation

drikusroor
Copy link
Contributor

No description provided.

@drikusroor drikusroor self-assigned this Jan 6, 2025
Comment on lines +29 to +34
class ExperimentViewSet(viewsets.ModelViewSet):
queryset = Experiment.objects.all()
serializer_class = ExperimentSerializer
permission_classes = [permissions.IsAuthenticated]


Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This creates GET, GET(id), POST, PUT & DELETE endpoints for the experiment (and its relations as defined in the serializers)

Comment on lines +68 to +72
@api_view(["GET"])
def playlists(request):
"""Return a list of all playlists"""
playlists = [{"id": playlist.id, "name": playlist.name} for playlist in Playlist.objects.all()]
return Response(playlists)
Copy link
Contributor Author

@drikusroor drikusroor Jan 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is used by the experiment form in react to be able to show all playlists and pick one from a multi select input

Comment on lines +221 to +225
@api_view(["GET"])
def block_rules(request):
"""Return a list of available block rules"""
rules = [{"id": rule_id, "name": rule_class.__name__} for rule_id, rule_class in BLOCK_RULES.items()]
return Response(rules)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is used by the experiment form to display all rules in a select input

Comment on lines +44 to +45
path("api/token/", TokenObtainPairView.as_view(), name="token_obtain_pair"),
path("api/token/refresh/", TokenRefreshView.as_view(), name="token_refresh"),
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is used by the experiment form react application to obtain a JWT token that is used to authenticate the user in Rest API requests

fields = ["id", "index", "dashboard", "randomize", "blocks"]


class ExperimentSerializer(serializers.ModelSerializer):
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the weak part about this setup (for now) I think. It seems to be a bit convoluted but I do think it should be able to simplify it. It's like this right now because I had to deal with different scenarios like many to many relationships, or just FKs, do the related objects have PKs already or not, and so on. Maybe a good step is just to create and save an empty experiment before you get to the form. Then at least the experiment already exists and we can remove the create method in here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we load this file and the built JS + CSS files, I think we can integrate it into the Django admin interface quite easily and maybe even remove the whole JWT mumbo jumbo.

Comment on lines 17 to 42
const [jwt, setJwt] = useState<string | null>(localStorage.getItem('jwt'));

const handleLogin = (newJwt: string) => {
localStorage.setItem('jwt', newJwt);
setJwt(newJwt);
};

const handleLogout = () => {
localStorage.removeItem('jwt');
setJwt(null);
};

if (!jwt) {
return <Login onLogin={handleLogin} />;
} else {
try {
const payload = JSON.parse(atob(jwt.split('.')[1]));
if (payload.exp && Date.now() >= payload.exp * 1000) {
handleLogout();
return <Login onLogin={handleLogin} />;
}
} catch (error) {
handleLogout();
return <Login onLogin={handleLogin} />;
}
}
Copy link
Contributor Author

@drikusroor drikusroor Jan 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So this is just a fairly simple way of checking if we are logged in using the JWT token in the local storage and redirect to the login page if not logged in or the JWT has expired (valid for 60 minutes right now, see the Django settings). If we build in the refresh token mechanism it'll be valid for 1 day.

@drikusroor drikusroor force-pushed the feat/custom-react-forms branch from 9e4c89c to efd5a61 Compare January 7, 2025 14:20
@drikusroor drikusroor force-pushed the feat/custom-react-forms branch from efa2132 to 940ffde Compare January 7, 2025 15:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant