فهرست منبع

add upload.vue and progress.vue

tomoya 2 سال پیش
والد
کامیت
b9069ac6df

BIN
frontend/public/favicon.ico


+ 6 - 0
frontend/src/api.ts

@@ -57,4 +57,10 @@ export const api = {
     formData.append("file", file)
     return axios.post<{msg:string}>(`${apiUrl}/api/v1/utils/test-celery/file`, formData, authHeaders(token));
   },
+  async uploadPlot(token: string, title:string, file: File){
+    const formData = new FormData();
+    formData.append("title", title)
+    formData.append("upload_file", file)
+    return axios.post<{msg:string}>(`${apiUrl}/api/v1/videos`, formData, authHeaders(token));
+  }
 };

+ 8 - 1
frontend/src/interfaces/index.ts

@@ -36,4 +36,11 @@ export interface MainState {
   dashboardMiniDrawer: boolean;
   dashboardShowDrawer: boolean;
   notifications: AppNotification[];
-};
+  videos: Video[];
+};
+
+export interface Video {
+  id: number;
+  title: string;
+  progress_state: string;
+}

+ 35 - 1
frontend/src/stores/main.ts

@@ -4,7 +4,7 @@ import { api } from "@/api"
 import router from "@/router"
 import { getLocalToken, removeLocalToken, saveLocalToken } from "@/utils";
 import type { AppNotification } from '@/interfaces';
-import type { IUserProfile, IUserProfileCreate, IUserProfileUpdate, MainState } from '@/interfaces';
+import type { IUserProfile, IUserProfileCreate, IUserProfileUpdate, MainState, Video} from '@/interfaces';
 
 const defaultState: MainState = {
   isLoggedIn: null,
@@ -14,6 +14,7 @@ const defaultState: MainState = {
   dashboardMiniDrawer: false,
   dashboardShowDrawer: true,
   notifications: [],
+  videos: [],
 };
 
 export const useMainStore = defineStore("MainStoreId", {
@@ -29,6 +30,7 @@ export const useMainStore = defineStore("MainStoreId", {
         readToken: (state) => state.token,
         readIsLoggedIn: (state) => state.isLoggedIn,
         readFirstNotification: (state) => state.notifications.length > 0 && state.notifications[0], 
+        readVideos: (state) => state.videos,
     },
     
     actions:{
@@ -39,6 +41,7 @@ export const useMainStore = defineStore("MainStoreId", {
         setUserProfile(payload: IUserProfile) { this.userProfile = payload },
         setDashboardMiniDrawer(payload: boolean) { this.dashboardMiniDrawer = payload; },
         setDashboardShowDrawer(payload: boolean) { this.dashboardShowDrawer = payload; },
+        setVideos(payload: Video[]) {this.videos = payload},
         addNotification(payload: AppNotification) { this.notifications.push(payload); },
         removeNotification(payload: AppNotification) {
             if (payload) { 
@@ -225,6 +228,37 @@ export const useMainStore = defineStore("MainStoreId", {
                 });
             }
         },
+        async uploadPlot(title: string, file: File) {
+          const mainStore = useMainStore();
+          try {
+            const loadingNotification = { content: "sending", showProgress: true };
+            mainStore.addNotification(loadingNotification);
+            const response = (
+              await Promise.all([
+                api.uploadPlot(mainStore.token, title, file),
+                await new Promise<void>((resolve, _) => setTimeout(() => resolve(), 500)),
+              ])
+            );
+            mainStore.removeNotification(loadingNotification);
+            mainStore.addNotification({
+              content: "File received",
+                color: "success",
+            })
+          } catch (error) {
+            await mainStore.checkApiError(error);
+          }
+        },
+        async actionGetVideos() {
+          const mainStore = useMainStore();
+          try {
+            const response = await api.getVideos(mainStore.token)
+            if (response) {
+              this.setVideos(response.data);
+            }
+          } catch (error) {
+            await mainStore.checkApiError(error);
+          }
+        },
     }
   });
 

+ 55 - 1
frontend/src/views/main/Progress.vue

@@ -1,5 +1,59 @@
 <template>
-
+  <div>
+    <v-toolbar light>
+      <v-toolbar-title>
+        Manage Users
+      </v-toolbar-title>
+      <v-spacer></v-spacer>
+      <v-btn color="primary" to="/main/admin/users/create">Create User</v-btn>
+    </v-toolbar>
+    <v-data-table :headers="headers" :items="videos">
+      
+      <template v-slot:item.is_active="{ item }">
+        <v-icon v-if=item.columns.is_active icon="check"/>
+      </template>
+      <template v-slot:item.is_superuser="{ item }">
+        <v-icon v-if=item.columns.is_superuser icon="check"/>
+      </template>
+      <template v-slot:item.id="{ item }">
+        <v-btn flat :to="{name: 'main-admin-users-edit', params: {id: item.columns.id}}">
+          <v-icon icon="edit"/>
+          <v-tooltip location="top" activator="parent">Edit</v-tooltip>
+        </v-btn>
+      </template>
+    </v-data-table>
+  </div>
 </template>
 <script setup lang="ts">
+import { useMainStore } from '@/stores/main';
+import { storeToRefs} from 'pinia';
+import { onMounted } from 'vue';
+
+const mainStore = useMainStore();
+const mainStoreRef = storeToRefs(mainStore);
+
+const videos = mainStoreRef.readVideos;
+
+const headers = [
+  {
+    title: 'Title',
+    sortable: true,
+    key: 'title',
+    align: 'left',
+  },
+  {
+    title: 'Progress',
+    sortable: true,
+    key: 'progress',
+    align: 'left',
+  },
+  {
+    title: 'Actions',
+    key: 'id',
+  },
+];
+
+onMounted(async () =>{
+  await mainStore.actionGetVideos();
+})
 </script>

+ 50 - 1
frontend/src/views/main/Upload.vue

@@ -1,5 +1,54 @@
 <template>
-
+  <v-container fluid>
+    <v-card class="ma-3 pa-3">
+      <v-card-title primary-title>
+        <div class="headline primary--text">Make Video</div>
+      </v-card-title>
+      <v-card-text>
+          <v-form v-model="valid" ref="Form">
+            <v-text-field 
+              label="Title" v-model="title" 
+              :rules="required"
+              prepend-icon="title">
+            </v-text-field>
+            <v-file-input
+              v-model="zipFiles"
+              :rules="[v=> v.length || 'select zip file.']"
+              accept=".zip"
+              label="File input"
+              prepend-icon="folder_zip"
+            ></v-file-input>
+          </v-form>
+      </v-card-text>
+      <v-card-actions>
+        <v-spacer></v-spacer>
+        <v-btn @click="Submit" :disabled="!valid">
+              Send
+        </v-btn>
+      </v-card-actions>
+    </v-card>
+  </v-container>
 </template>
 <script setup lang="ts">
+import { ref} from 'vue';
+import { useMainStore } from '@/stores/main';
+import { required } from '@/utils';
+
+
+
+const valid = ref(true);
+const title = ref('');
+const zipFiles = ref();
+const Form = ref();
+
+
+const mainStore = useMainStore();
+
+async function Submit() {
+  await (Form as any).value.validate();
+  if (valid.value) {
+    await mainStore.uploadPlot(title.value, zipFiles.value[0]);
+    (Form as any).value.reset();
+  }
+}
 </script>