소스 검색

updated project view set

Dimitri Korsch 3 년 전
부모
커밋
b7c460379e

+ 1 - 0
backend/pycs_api/models/base.py

@@ -12,4 +12,5 @@ class BaseModel(models.Model):
         "id",
         "name",
     ]
+    read_only_fields = []
 

+ 24 - 2
backend/pycs_api/models/project.py

@@ -1,8 +1,10 @@
 import uuid
+import logging
 
 from django.conf import settings
 from django.contrib.auth.models import User
 from django.db import models
+from django.dispatch import receiver
 
 from pycs_api.models import base
 from pycs_api.models.label_provider import LabelProvider
@@ -50,9 +52,29 @@ class Project(base.BaseModel):
     serializer_fields = base.BaseModel.serializer_fields + [
         "description",
         "created",
-        "model_id",
-        "label_provider_id",
+        "model",
+        "label_provider",
         "data_folder",
         "root_folder",
     ]
+    read_only_fields = base.BaseModel.read_only_fields + [
+        "created",
+        "data_folder",
+        "root_folder",
+    ]
+
+@receiver(models.signals.pre_save, sender=Project)
+def project_pre_save(sender, instance, **kwargs):
+    is_external = instance.data_folder != ''
+
+    logging.info(f"Using external folder: {'yes' if is_external else 'no'}")
+    instance.external_data = is_external
+
+    if not is_external:
+        logging.info("Setting data folder")
+        instance.data_folder = instance.root_folder + "/data"
+
+
 
+    # TODO: copy model to root_folder / "model"
+    # TODO: create temp folder root_folder / "temp"

+ 7 - 3
backend/pycs_api/serializers.py

@@ -2,20 +2,24 @@
 from rest_framework import serializers
 from pycs_api import models
 
-class ModelSerializer(serializers.HyperlinkedModelSerializer):
+class BaseSerializer(serializers.ModelSerializer):
+    pass
+
+class ModelSerializer(BaseSerializer):
 
     class Meta:
         model = models.Model
         fields = models.Model.serializer_fields
 
-class LabelProviderSerializer(serializers.HyperlinkedModelSerializer):
+class LabelProviderSerializer(BaseSerializer):
 
     class Meta:
         model = models.LabelProvider
         fields = models.LabelProvider.serializer_fields
 
-class ProjectSerializer(serializers.HyperlinkedModelSerializer):
+class ProjectSerializer(BaseSerializer):
 
     class Meta:
         model = models.Project
         fields = models.Project.serializer_fields
+        read_only_fields = models.Project.read_only_fields

+ 1 - 1
backend/pycs_api/views/__init__.py

@@ -30,4 +30,4 @@ class TokenRefreshView(BaseTokenRefreshView):
 router = routers.DefaultRouter()
 router.register(r'model', ModelViewSet)
 router.register(r'label-provider', LabelProviderViewSet)
-router.register(r'project', ProjectViewSet)
+router.register(r'project', ProjectViewSet, "project")

+ 6 - 1
backend/pycs_api/views/base.py

@@ -2,6 +2,7 @@ from django import http
 from django import views
 from rest_framework import permissions
 from rest_framework import viewsets
+from rest_framework.response import Response
 
 class JsonResponseView(views.View):
 
@@ -11,5 +12,9 @@ class JsonResponseView(views.View):
 
 
 class BaseViewSet(viewsets.ModelViewSet):
-    permission_classes = []#permissions.IsAuthenticated]
+    permission_classes = [permissions.IsAuthenticated]
 
+
+    def new_response(self, obj, **kwargs):
+        serializer = self.get_serializer(obj, **kwargs)
+        return Response(serializer.data)

+ 6 - 82
backend/pycs_api/views/project.py

@@ -1,4 +1,5 @@
-from django.views.decorators.http import require_POST
+from django.shortcuts import get_object_or_404
+
 from rest_framework import status
 from rest_framework.decorators import permission_classes
 from rest_framework.response import Response
@@ -10,87 +11,10 @@ from pycs_api.views.base import BaseViewSet
 
 class ProjectViewSet(BaseViewSet):
 
-    queryset = Project.objects.all().order_by("id")
     serializer_class = ProjectSerializer
 
-    def list(self, request):
-        if request.user.is_anonymous:
-            return Response('Unauthorized',
-                status=status.HTTP_401_UNAUTHORIZED)
-
-        projects = request.user.projects.all()
-        serializer = self.get_serializer(projects, many=True)
-        return Response(serializer.data)
-
-    def create(self, request):
-        if request.user.is_anonymous:
-            return Response('Unauthorized',
-                status=status.HTTP_401_UNAUTHORIZED)
-
-        project = Project(
-            user=request.user,
-            **request.data
-        )
-
-        project.save()
-        serializer = self.get_serializer(project)
-        return Response(serializer.data)
-
-
-
-# class ProjectView(JsonResponseView):
-
-#     """
-#         serves POST and GET for '/projects/'
-
-#         staticmethods serve POST methods for
-#             '/projects/<id>/name'
-#             '/projects/<id>/description'
-#             '/projects/<id>/remove'
-#     """
-
-#     http_method_names = ["get", "post"]
-
-
-#     def get(self, request, *args, **kwargs):
-#         """ lists projects """
-#         return self.respond([
-#             dict(name="Project 1", description="Desc1", ),
-#             dict(name="Project 2", description="Desc2"),
-#         ])
-
-#     def post(self, request, *args, **kwargs):
-#         """ creates a project """
-#         return self.respond()
-
-
-#     @require_POST
-#     @classmethod
-#     def remove(cls, request, project_id: int):
-#         """ removes a project """
-#         return cls.respond()
-
-#     @require_POST
-#     @classmethod
-#     def edit_name(cls, request, project_id: int):
-#         """ edit project's name """
-#         return cls.respond()
-
-#     @require_POST
-#     @classmethod
-#     def edit_description(cls, request, project_id: int):
-#         """ edit project's description """
-#         return cls.respond()
-
-#     @require_POST
-#     @classmethod
-#     def run_external_storage(cls, request, project_id: int):
-#         """ runs external storage routine """
-#         return cls.respond()
-
-#     @require_POST
-#     @classmethod
-#     def run_label_provider(cls, request, project_id: int):
-#         """ runs label provider routine """
-#         return cls.respond()
+    def get_queryset(self):
+        return self.request.user.projects
 
+    def perform_create(self, serializer):
+        serializer.save(user=self.request.user)

+ 30 - 8
frontend/src/services/data.service.js

@@ -3,23 +3,45 @@ import api from "./api";
 class DataService {
 
   getModels() {
-    return api.get("/model/").then(
-      (response) => {
+    return api.get("/model/")
+      .then((response) => {
         return response.data;
       });
   }
 
   getLabelProviders() {
-    return api.get("/label-provider/").then(
-      (response) => {
+    return api.get("/label-provider/")
+      .then((response) => {
         return response.data;
       });
   }
 
   getProjects() {
-    return api.get("/project/").then(
-      (response) => {
+    return api.get("/project/")
+      .then((response) => {
+        return response.data;
+      });
+  }
+
+  getProject(projectId) {
+    return api.get(`/project/${projectId}`)
+      .then((response) => {
         return response.data;
+      })
+      .catch((error) =>{
+        if (error.response.status == 404)
+          return null;
+      });
+  }
+
+  deleteProject(projectId) {
+    return api.delete(`/project/${projectId}`)
+      .then(() => {
+        return true;
+      })
+      .catch((error) =>{
+        if (error.response.status == 404)
+          return false;
       });
   }
 
@@ -27,8 +49,8 @@ class DataService {
     return api.post("/project/", {
       'name': project.name,
       'description': project.description,
-      'model_id': project.model.id,
-      'label_provider_id': project.labelProvider?.id,
+      'model': project.model.id,
+      'label_provider': project.labelProvider?.id,
     }).then(
       (response) => {
         return response.data;

+ 1 - 1
frontend/src/services/setupInterceptors.js

@@ -25,7 +25,6 @@ const setup = (store) => {
       const originalConfig = err.config;
 
       if (originalConfig.url !== "/api-token/" && err.response) {
-        console.log("Access token expired!")
         // Access Token was expired
         if (err.response.status === 401 && !originalConfig._retry) {
 
@@ -41,6 +40,7 @@ const setup = (store) => {
             return api(originalConfig);
 
           } catch (_error) {
+
             return Promise.reject(_error);
           }
         }

+ 105 - 26
frontend/src/views/project/Detail.vue

@@ -17,30 +17,93 @@
             <v-row>
               <v-col>{{ project.name }}</v-col>
               <v-col class="d-flex align-end flex-column">
-                <v-btn @click="deleteProject" fab color="error"><v-icon>mdi-trash-can-outline</v-icon></v-btn>
+                <v-dialog
+                  v-model="dialog"
+                  width="500"
+                >
+                  <template v-slot:activator="{ on, attrs }">
+                    <v-btn
+                      fab
+                      color="error"
+                      v-bind="attrs"
+                      v-on="on"
+                    >
+                      <v-icon>mdi-trash-can-outline</v-icon>
+                    </v-btn>
+                  </template>
+
+                  <v-card>
+                    <v-card-title class="text-h5 grey lighten-2">
+                     Confirmation
+                    </v-card-title>
+
+                    <v-card-text>
+                      <v-container>
+                          Do you really want to delete the project "{{ project.name }}"?
+                      </v-container>
+                    </v-card-text>
+
+                    <v-divider></v-divider>
+
+                    <v-card-actions>
+                      <v-spacer></v-spacer>
+                      <v-btn
+                        color="red"
+                        text
+                        @click="deleteProj"
+                      >
+                        Yes, delete!
+                      </v-btn>
+                      <v-btn text @click="dialog=false">
+                        No
+                      </v-btn>
+                    </v-card-actions>
+                  </v-card>
+                </v-dialog>
+
               </v-col>
             </v-row>
           </v-container>
         </v-card-title>
         <v-card-text>
-          <v-container fluid>
-            <v-row>
-              <v-col>Description</v-col>
-              <v-col>{{ project.description }}</v-col>
-            </v-row>
-            <v-row>
-              <v-col>Data Folder</v-col>
-              <v-col>{{ project.data_folder }}</v-col>
-            </v-row>
-            <v-row>
-              <v-col>Model</v-col>
-              <v-col>{{ project.model_id }}</v-col>
-            </v-row>
-            <v-row>
-              <v-col>Label Provider</v-col>
-              <v-col>{{ project.label_provider_id }}</v-col>
-            </v-row>
-          </v-container >
+
+          <v-list two-line>
+            <v-list-item>
+              <v-list-item-content>
+                <v-list-item-title>Description</v-list-item-title>
+                <v-list-item-subtitle>{{ project.description }}</v-list-item-subtitle>
+              </v-list-item-content>
+            </v-list-item>
+
+            <v-list-item>
+              <v-list-item-content>
+                <v-list-item-title>Model</v-list-item-title>
+                <v-list-item-subtitle>{{ project.model }}</v-list-item-subtitle>
+              </v-list-item-content>
+            </v-list-item>
+
+            <v-list-item>
+              <v-list-item-content>
+                <v-list-item-title>Label Provider</v-list-item-title>
+                <v-list-item-subtitle>{{ project.label_provider }}</v-list-item-subtitle>
+              </v-list-item-content>
+            </v-list-item>
+            <v-divider></v-divider>
+
+            <v-list-item>
+              <v-list-item-content>
+                <v-list-item-title>Root Folder</v-list-item-title>
+                <v-list-item-subtitle>{{ project.root_folder }}</v-list-item-subtitle>
+              </v-list-item-content>
+            </v-list-item>
+
+            <v-list-item>
+              <v-list-item-content>
+                <v-list-item-title>Data Folder</v-list-item-title>
+                <v-list-item-subtitle>{{ project.data_folder }}</v-list-item-subtitle>
+              </v-list-item-content>
+            </v-list-item>
+          </v-list>
         </v-card-text>
       </div>
 
@@ -61,26 +124,42 @@
 </template>
 
 <script>
-  import { mapState } from 'vuex'
+  // import { mapState } from 'vuex'
+  import DataService from '@/services/data.service';
 
   export default {
     name: 'ShowProject',
 
+    data (){
+      return {
+        dialog: false,
+        project: null,
+      }
+    },
 
     computed: {
-      project() {
-          return this.data.projects.find(obj => obj.id == this.$route.params.id)
+
+      // ...mapState(['data']),
+      projectId() {
+        return this.$route.params.id;
       },
-      ...mapState(['data']),
     },
 
     created () {
-      this.$store.dispatch('data/getProjects');
+      DataService.getProject(this.projectId)
+        .then((project) => {
+          this.project = project;
+        })
     },
 
     methods: {
-      deleteProject (){
-        console.log("Delete project!")
+      deleteProj () {
+        DataService.deleteProject(this.projectId)
+          .then((ok) => {
+            if (ok){
+              this.$router.push({name: "projects"})
+            }
+          });
       }
     }