Browse Source

Merge branch '20-project-settings' into 'master'

Resolve "project settings"

Closes #20

See merge request troebs/pycs!13
Eric Tröbs 4 years ago
parent
commit
d7ec160cc3

+ 23 - 1
pycs/projects/ProjectManager.py

@@ -1,6 +1,7 @@
 from glob import glob
 from json import load, dump
 from os import path, mkdir
+from shutil import rmtree
 from time import time
 from uuid import uuid1
 
@@ -55,4 +56,25 @@ class ProjectManager:
         for project in to_load:
             # TODO actually load pipeline
             project['status'] = 'open'
-            project['access'] = time()
+            project['access'] = int(time())
+
+        # detect project to update
+        for i in range(len(data)):
+            if 'action' in data[i] and data[i]['action'] == 'update':
+                del data[i]['action']
+
+                prj = data[i].copy()
+                del prj['status']
+
+                with open(path.join('projects', data[i]['id'], 'project.json'), 'w') as file:
+                    dump(prj, file, indent=4)
+
+        # detect project to delete
+        for i in range(len(data)):
+            if 'action' in data[i] and data[i]['action'] == 'delete':
+                folder = path.join('projects', data[i]['id'])
+
+                del data[i]
+                rmtree(folder)
+
+                break

+ 1 - 1
webui/src/App.vue

@@ -51,7 +51,7 @@ export default {
           && !this.showProjectCreationDialog;
     },
     showProjectMainWindow: function() {
-      return this.status != null && this.status.projects.filter(x => x.status === 'open').length > 0
+      return this.status != null && this.status.projects.filter(x => ['open'].includes(x.status)).length > 0
           && !this.showProjectCreationDialog;
     }
   },

+ 42 - 0
webui/src/components/base/confirmed-button-input.vue

@@ -0,0 +1,42 @@
+<template>
+  <div @click="click">
+    <div v-if="first">
+      <slot name="first"></slot>
+    </div>
+    <div v-else>
+      <slot name="second"></slot>
+    </div>
+  </div>
+</template>
+
+<script>
+export default {
+  name: "confirmed-button-input",
+  data: function() {
+    return {
+      first: true
+    }
+  },
+  methods: {
+    click: function(event) {
+      if (this.first)
+        this.first = false;
+      else
+        this.$emit('click', event);
+    }
+  }
+}
+</script>
+
+<style scoped>
+div {
+  display: inline-block;
+}
+
+button {
+  padding: 0.67rem 1.5rem;
+  border: 1px solid rgba(0, 0, 0, 0.2);
+  border-radius: 0.75rem;
+  cursor: pointer;
+}
+</style>

+ 115 - 0
webui/src/components/projects/project-main-window-settings.vue

@@ -0,0 +1,115 @@
+<template>
+  <div class="project-main-window-settings">
+    <h1>Project Settings</h1>
+
+    <div class="content">
+      <text-input placeholder="Name"
+                  :value="name"
+                  @input="nameF"
+                  :error="nameError"
+                  @clearError="nameError = false">
+        Name
+      </text-input>
+
+      <textarea-input placeholder="Description"
+                      :value="description"
+                      @input="descriptionF"
+                      :error="descriptionError"
+                      @clearError="descriptionError = false">
+        Description
+      </textarea-input>
+
+      <confirmed-button-input @click="deleteProject">
+        <template v-slot:first>
+          <button-input>
+            Delete Project
+          </button-input>
+        </template>
+        <template v-slot:second>
+          <button-input>
+            Do you really want to delete this project?
+          </button-input>
+        </template>
+      </confirmed-button-input>
+    </div>
+  </div>
+</template>
+
+<script>
+import TextInput from "@/components/base/text-input";
+import TextareaInput from "@/components/base/textarea-input";
+import ConfirmedButtonInput from "@/components/base/confirmed-button-input";
+import ButtonInput from "@/components/base/button-input";
+
+export default {
+  name: "project-main-window-settings",
+  components: {ButtonInput, ConfirmedButtonInput, TextareaInput, TextInput},
+  props: ['status', 'socket'],
+  data: function() {
+    return {
+      project: null,
+      projectPath: null,
+      name: '',
+      nameError: false,
+      description: '',
+      descriptionError: false
+    }
+  },
+  methods: {
+    nameF: function(value) {
+      this.socket.set(this.projectPath + '/name', value);
+      this.update();
+    },
+    descriptionF: function(value) {
+      this.socket.set(this.projectPath + '/description', value);
+      this.update();
+    },
+    update: function() {
+      this.socket.set(this.projectPath + '/action', 'update');
+    },
+    deleteProject: function() {
+      this.socket.set(this.projectPath + '/action', 'delete');
+    }
+  },
+  created: function() {
+    for (let i = 0; i < this.status.projects.length; i++) {
+      if (this.status.projects[i].status === 'open') {
+        this.projectPath = 'projects/' + i;
+        this.project = this.status.projects[i];
+      }
+    }
+
+    this.name = this.project.name;
+    this.description = this.project.description;
+  }
+}
+</script>
+
+<style scoped>
+.project-main-window-settings {
+  padding: 1rem;
+}
+
+h1 {
+  margin: 0;
+  font-family: "Roboto Condensed";
+
+  text-overflow: ellipsis;
+  width: 100%;
+  white-space: nowrap;
+  overflow: hidden;
+}
+
+.content {
+  overflow: auto;
+  flex-grow: 1;
+}
+
+.content > * {
+  margin-bottom: 0.6rem;
+}
+
+/deep/ .content textarea {
+  height: 4rem;
+}
+</style>

+ 18 - 3
webui/src/components/projects/project-main-window.vue

@@ -16,26 +16,37 @@
     <div class="bottom">
       <div class="side-navigation"
            :class="{ wide: wide, narrow: !wide, active: menu }">
+        <div class="item"
+             :class="{active: activeContent === 'settings'}"
+             @click="activeContent = 'settings'">
+          Project Settings
+        </div>
+
         <div class="item" @click="socket.set(projectPath, 'save')">
-          Projekt schließen
+          Close
         </div>
       </div>
 
       <div class="content">
-        .content
+        <project-main-window-settings v-if="activeContent === 'settings'"
+                                      :status="status" :socket="socket"/>
       </div>
     </div>
   </div>
 </template>
 
 <script>
+import ProjectMainWindowSettings from "@/components/projects/project-main-window-settings";
+
 export default {
   name: "project-main-window",
+  components: {ProjectMainWindowSettings},
   props: ['status', 'socket'],
   data: function() {
     return {
       wide: true,
-      menu: false
+      menu: false,
+      activeContent: 'settings'
     }
   },
   computed: {
@@ -139,6 +150,10 @@ export default {
 }
 
 .side-navigation .item:hover {
+  background-color: #292929;
+}
+
+.side-navigation .item.active {
   background-color: #1f1f1f;
 }