diff --git a/src/components/Filters.vue b/src/components/Filters.vue index 021763c143dca9c9d6e397a52dea1eb5832730de..76954fa729a82716a00624c0ce1fbec5b1c64426 100644 --- a/src/components/Filters.vue +++ b/src/components/Filters.vue @@ -2,7 +2,19 @@ <b-menu> <div> <b-menu-list label="minimum performance"> - <b-slider v-model="perfValue" lazy @change="changeTag"></b-slider> + <b-slider + v-model="perfValue" + :min="0" :max="3" + :tooltip="false" + ticks + lazy + @change="changeTag" + > + <b-slider-tick :value="0">10</b-slider-tick> + <b-slider-tick :value="1">100</b-slider-tick> + <b-slider-tick :value="2">1000</b-slider-tick> + <b-slider-tick :value="3">10000</b-slider-tick> + </b-slider> </b-menu-list> <b-menu-list v-for="tag in tags" v-bind:key="tag.name" :label="tag.name"> <div v-for="type in tag.types" v-bind:key="type" class="field"> @@ -28,7 +40,15 @@ export default { }, methods: { changeTag () { - this.$emit('setTags', this.checkboxGroup, this.perfValue) + this.$emit('setTags', this.checkboxGroup, this.convertPerf()) + }, + convertPerf () { + switch (this.perfValue) { + case 0 : return 10 + case 1 : return 100 + case 2 : return 1000 + case 3 : return 10000 + } } } } diff --git a/src/components/LayersEditor.vue b/src/components/LayersEditor.vue index 91ca175f24da6888d11a2e72ec9afe3c3e55fafa..3d4d3ee6821c1037c9e03a2a4dc26697d497e026 100644 --- a/src/components/LayersEditor.vue +++ b/src/components/LayersEditor.vue @@ -1,25 +1,29 @@ <template> <div class="layersEditor"> <h2 class="title is-6">Custom layers</h2> - <b-button class="actionButton addButton" icon-left="plus-box" type="is-success" @click="addLayer"> Add custom layer </b-button> - <b-field v-for="(layer, index) in layers" v-bind:key="layer.name" grouped> - <b-input :placeholder="'Layer ' + index + ' name'" :value="layer.name"/> + + <b-field position="is-centered"> + <b-button class="addButton" icon-left="plus-box" type="is-info" @click="addLayer" expanded> Add custom layer </b-button> + </b-field> + + <b-field v-for="(layer, index) in layers" v-bind:key="layer.name" grouped position="is-centered"> <p class="control"> - <b-upload v-model="file"> + <b-button icon-left="close-circle" type="is-danger" outlined @click="deleteLayer(layer)"/> + </p> + + <b-input :placeholder="'Layer ' + index + ' name'" v-model="layer.name"/> + + <p class="control"> + <b-upload v-model="file" accept=".py"> <a class="button is-primary"> <b-icon icon="upload"></b-icon> <span>Upload layer file</span> </a> </b-upload> - <span class="file-name" v-if="file"> - {{ file.name }} - </span> + <span class="file-name" v-if="file">{{ file.name }}</span> </p> - <p class="control"> - <b-button class="actionButton" icon-left="delete" type="is-danger" outlined/> - </p> </b-field> </div> </template> @@ -38,7 +42,8 @@ export default { methods: { addLayer () { this.layers.push({ - id: this.layers.length + id: this.layers.length, + name: null }) }, deleteLayer (layer) { diff --git a/src/components/MarkdownEditor.vue b/src/components/MarkdownEditor.vue index e0431d2f7db9d13c490e0201b0e7748bd519f505..012aeb1da4bb8edfa394e9817915d0eab0490ddf 100644 --- a/src/components/MarkdownEditor.vue +++ b/src/components/MarkdownEditor.vue @@ -1,7 +1,7 @@ <template> <div class="markdownEditor container"> <b-tabs> - <b-tab-item label="Editor" class="edit"> + <b-tab-item label="Edit" class="edit"> <b-input type="textarea" v-model="input"/> </b-tab-item> diff --git a/src/components/ModelTable.vue b/src/components/ModelTable.vue index 5728f59fcdde340e1302c808dc36b5149657fe1d..817fec6a537a2b2557da157dee4a970db9da11e1 100644 --- a/src/components/ModelTable.vue +++ b/src/components/ModelTable.vue @@ -18,6 +18,7 @@ </b-table-column> <b-table-column label="" centered> + <b-button class="actionButton" icon-left="eye" type="is-info" tag="router-link" :to="{ name: 'Model', query: { id: props.row.id } }" outlined/> <b-button class="actionButton" icon-left="pencil" type="is-warning" tag="router-link" :to="{ name: 'ModelEdit', params: {model: props.row} }" outlined/> <b-button class="actionButton" icon-left="delete" type="is-danger" @click="removePrompt(props.row.id)" outlined/> </b-table-column> @@ -83,6 +84,8 @@ export default { } </script> -<style> - +<style scoped> +.actionButton { + margin-left:8px; +} </style> diff --git a/src/components/Navbar.vue b/src/components/Navbar.vue index 36571e436fdaf1ae914e935ddb9b8f5d0efea237..11b96f9680e71a1e9ecf778c41124f4f23a915e4 100644 --- a/src/components/Navbar.vue +++ b/src/components/Navbar.vue @@ -9,7 +9,7 @@ > </b-navbar-item> </template> - <template slot="start"> + <template slot="start" v-if="!isSearch"> <b-navbar-item tag="div"> <b-field> <b-input placeholder="Search..." @@ -84,6 +84,11 @@ export default { search: '' } }, + computed: { + isSearch: function () { + return this.$route.name === 'Search' + } + }, async mounted () { const token = await localStorage.getItem('token') if (token) this.isLogged = true diff --git a/src/router/index.js b/src/router/index.js index 7c273dd945da3eaeef237f7d0091a894b1105105..0792ffa14302734c1b0328c90c9a4050c69d9296 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -39,6 +39,14 @@ const routes = [ requiresAuth: true } }, + { + path: '/modeladd', + name: 'ModelAdd', + component: () => import('../views/ModelAdd.vue'), + meta: { + requiresAuth: true + } + }, { path: '/account', name: 'Account', diff --git a/src/views/Account.vue b/src/views/Account.vue index e85efa8f7451b6fcf923c8b857fe2e3f5b9261e8..925ec119fb30f3dbe3c425a9f9ab05b81e895634 100644 --- a/src/views/Account.vue +++ b/src/views/Account.vue @@ -3,7 +3,7 @@ <div class="box"> <h1 class="title">Welcome {{account.username}}</h1> <div class="buttons"> - <b-button>Add new model</b-button> + <b-button tag="router-link" :to="{ name: 'ModelAdd' }">Add new model</b-button> <b-button>Change account details</b-button> </div> </div> diff --git a/src/views/Model.vue b/src/views/Model.vue index a9b42755b887fa6ceb894d0b319d557e6e592596..440874f39b7813f8ad7c40d80fe5d4e45818af87 100644 --- a/src/views/Model.vue +++ b/src/views/Model.vue @@ -14,7 +14,7 @@ <b-tag type="is-info">{{model.performance}}%</b-tag> </b-taglist> </div> - <div class="column"> + <div class="column infoColumn"> <h1 class="title is-4">{{model.vote}} votes <b-button size="is-small" icon-left="heart-outline" style="top:-2px"/></h1> <small>Author: </small><strong>{{model.author}}</strong> <br> @@ -24,12 +24,21 @@ <br> <br> <b-button type="is-primary" size="is-medium" icon-left="download"> - Download + Download model </b-button> + <hr> + <strong>{{model.customLayers.length}} customs layers</strong> + <br> + <template v-for="layer in model.customLayers"> + <b-button class="customLayer" type="is-primary" icon-left="download" v-bind:key="layer.name"> + Download {{layer.name}} + </b-button> + <br v-bind:key="layer.name"> + </template> </div> </div> <div class="box"> - {{model.longDescription}} + <div class="content" v-html="compiledLongDescription"></div> </div> <div class="box"> <Comments v-bind:comments="model.comments"/> @@ -41,6 +50,7 @@ <script> import Comments from '@/components/Comments.vue' +import marked from 'marked' export default { name: 'Model', @@ -54,6 +64,11 @@ export default { isLoading: true } }, + computed: { + compiledLongDescription: function () { + return marked(this.model.longDescription) + } + }, async mounted () { const id = this.$route.query.id this.model = await this.getModel(id) @@ -82,4 +97,10 @@ export default { margin-top: 50px; text-align: center; } +.customLayer { + margin-top: 8px; +} +.infoColumn { + border-left: 2px solid whitesmoke; +} </style> diff --git a/src/views/ModelAdd.vue b/src/views/ModelAdd.vue new file mode 100644 index 0000000000000000000000000000000000000000..51c35027a6083eeb48ad03ecac697d1cf9912e2d --- /dev/null +++ b/src/views/ModelAdd.vue @@ -0,0 +1,73 @@ +<template> + <div class="modelAdd container"> + <b-steps v-model="activeStep"> + <b-step-item step="1" label="Description" clickable> + <b-field label="Model name"> + <b-input maxlength="30" size="is-large"/> + </b-field> + + <b-field label="Short description"> + <b-input maxlength="200" type="textarea"/> + </b-field> + + <b-field label="Long description"> + <markdownEditor/> + </b-field> + </b-step-item> + + <b-step-item step="2" label="Tags" clickable> + <tagEditor/> + </b-step-item> + + <b-step-item step="3" label="Files" clickable> + <b-field label="Model"> + <b-upload v-model="dropFiles" drag-drop expanded> + <section class="section"> + <div class="content has-text-centered"> + <p> + <b-icon icon="upload" size="is-large"/> + </p> + <p>Drop your model here or click to upload</p> + </div> + </section> + </b-upload> + </b-field> + </b-step-item> + + <b-step-item step="4" label="Custom layers" clickable> + <layersEditor/> + </b-step-item> + + <b-step-item step="5" label="Finish" clickable> + <b-button expanded size="is-large" type="is-success">Confirm and upload</b-button> + </b-step-item> + + </b-steps> + </div> +</template> + +<script> +import markdownEditor from '@/components/MarkdownEditor.vue' +import tagEditor from '@/components/TagEditor.vue' +import layersEditor from '@/components/LayersEditor.vue' + +export default { + name: 'ModelAdd', + components: { + markdownEditor, + tagEditor, + layersEditor + }, + data () { + return { + activeStep: 0 + } + } +} +</script> + +<style scoped> +.modelAdd { + margin-top: 20px; +} +</style> diff --git a/src/views/ModelEdit.vue b/src/views/ModelEdit.vue index 76ae19728b68a5145842bbacad6cb9353e9639f6..69f30ac20d554e2cc0d2b3bbaa830f6b0d23800f 100644 --- a/src/views/ModelEdit.vue +++ b/src/views/ModelEdit.vue @@ -1,8 +1,9 @@ <template> <div class="modelEdit container"> <div class="box"> - <b-field label="Model name"> - <b-input maxlength="30" v-model="model.name"/> + <h1 class="title">Model name</h1> + <b-field> + <b-input maxlength="30" size="is-large" v-model="model.name"/> </b-field> <hr> @@ -21,20 +22,30 @@ <hr> <h1 class="title">Files</h1> + <div class="columns"> + <div class="column"> + <b-field label="Model"> + <b-upload v-model="dropFiles" drag-drop expanded> + <section class="section"> + <div class="content has-text-centered"> + <p> + <b-icon icon="upload" size="is-large"/> + </p> + <p>Drop your model here or click to upload</p> + </div> + </section> + </b-upload> + </b-field> + </div> - <b-field position="is-centered" label="Model"> - <b-upload v-model="file"> - <a class="button is-primary"> - <b-icon icon="upload"></b-icon> - <span>Upload model file</span> - </a> - </b-upload> - </b-field> + <div class="column rightColumn"> + <layersEditor v-bind:layers="model.customLayers"/> + </div> + </div> - <layersEditor v-bind:layers="model.customLayers"/> </div> <div class="box"> - <b-button type="is-warning">Abort</b-button> + <b-button >Cancel</b-button> <b-button type="is-success">Save</b-button> </div> </div> @@ -60,9 +71,6 @@ export default { } } }, - mounted () { - console.log('EDIT ' + this.model.name) - }, methods: { async saveModel () { @@ -71,6 +79,8 @@ export default { } </script> -<style> - +<style scoped> +.rightColumn { + border-left: 2px solid whitesmoke; +} </style> diff --git a/src/views/Search.vue b/src/views/Search.vue index 0010425b9efd1bb08971fa0929b7add90ce8aa63..fde2ef7051ef6c033ca520a2be7642a3b567f451 100644 --- a/src/views/Search.vue +++ b/src/views/Search.vue @@ -2,10 +2,24 @@ <div class="search container"> <div class="columns"> <div class="column"> - <h1 class="title is-6 filterTitle">Filtres</h1> + <h1 class="title is-6 filterTitle">Filters</h1> <Filters v-bind:tags="tags" v-on:setTags="setTags"/> </div> <div v-if="result" class="column is-four-fifths"> + <h1 class="title is-6 searchTitle">Search</h1> + <b-field grouped> + <b-input placeholder="Search..." + type="search" + icon="magnify" + v-model="paramSearch" + v-on:keyup.enter.native="setSearch" + expanded + /> + <b-select placeholder="Order by" icon="filter" @input="setOrder"> + <option value="vote">Most vote</option> + <option value="date">Most recent</option> + </b-select> + </b-field> <h1 class="title is-6">{{result.total}} result - page {{result.page}}</h1> <div v-for="model in result.models" v-bind:key="model.name"> <ModelCard v-bind:model="model"/> @@ -36,6 +50,7 @@ export default { result: true, paramTags: '', paramSearch: '', + paramOrder: '', paramPerf: '', resultSize: 10, page: 1, @@ -43,6 +58,8 @@ export default { } }, async mounted () { + const search = this.$route.query.n + if (search != null) this.paramSearch = search this.tags = await this.getTags() this.result = await this.getResult() this.isLoading = false @@ -52,6 +69,13 @@ export default { this.page = page this.result = await this.getResult() }, + async setSearch () { + this.result = await this.getResult() + }, + async setOrder (order) { + this.paramOrder = order + this.result = await this.getResult() + }, async setTags (tags, perfValue) { this.paramTags = tags this.paramPerf = perfValue @@ -69,16 +93,16 @@ export default { async getResult () { const url = new URL(this.$serverurl + 'search') const params = new URLSearchParams() - const nameParam = this.$route.query.n - if (nameParam != null) params.append('q', nameParam) + if (this.paramSearch != null) params.append('q', this.paramSearch) if (this.paramTags != null) params.append('tag', this.paramTags) if (this.paramPerf != null) params.append('perf', this.paramPerf) + if (this.paramOrder != null) params.append('order', this.paramOrder) params.append('size', this.resultSize) params.append('page', this.page) - console.log('get models ' + nameParam + ' + ' + this.paramPerf + ' + ' + this.paramTags) + console.log('get models ' + this.paramSearch + ' + ' + this.paramPerf + ' + ' + this.paramTags) url.search = params const response = await fetch(url) @@ -99,5 +123,10 @@ export default { .filterTitle { margin-left: 15px; + margin-bottom: 0; +} + +.searchTitle { + margin-bottom: 5px; } </style>