diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/components/ApiAuth.vue | 46 | ||||
| -rw-r--r-- | src/components/CommentVoter.vue | 2 | ||||
| -rw-r--r-- | src/components/UploadVoter.vue | 9 | ||||
| -rw-r--r-- | src/layouts/default.vue | 6 | ||||
| -rw-r--r-- | src/pages/FetchToken.vue | 2 | ||||
| -rw-r--r-- | src/pages/UploadCreate.vue | 29 | ||||
| -rw-r--r-- | src/pages/UploadDetail.vue | 97 | ||||
| -rw-r--r-- | src/pages/UploadList.vue | 11 | ||||
| -rw-r--r-- | src/store/module-user/getters.js | 2 | ||||
| -rw-r--r-- | src/store/module-user/mutations.js | 2 |
10 files changed, 97 insertions, 109 deletions
diff --git a/src/components/ApiAuth.vue b/src/components/ApiAuth.vue index d2771c7..30c7e14 100644 --- a/src/components/ApiAuth.vue +++ b/src/components/ApiAuth.vue @@ -1,26 +1,16 @@ <template> <div> <div v-if="!$store.getters['user/loggedIn']"> - <div v-if="useLarryLogin" class="group"> - <h5>Larry Login</h5> + <div class="group"> + <h5>Parry Login</h5> <p v-if="authError" class="text-negative"> - <span v-if="typeof authError === 'object'">Email or password {{ authError['email or password'] }}</span> + <span v-if="typeof authError === 'object'">Username or password {{ authError['username or password'] }}</span> <span v-else>{{ authError }}</span> </p> <div class="group"> - <q-input @keyup.enter="larryLogin" :error="authError !== undefined" v-model="email" name="user" float-label="Email" /> - <q-input @keyup.enter="larryLogin" :error="authError !== undefined" v-model="password" name="pass" type="password" float-label="Password" /> - <q-btn color="positive" @click="larryLogin" icon="fa-sign-in">Larry login</q-btn> - </div> - <div class="text-right"> - <q-btn color="tertiary" small outline @click="useLarryLogin = false">Log in via Clonkspot</q-btn> - </div> - </div> - <div v-else class="group"> - <q-btn color="positive" @click="clonkspotLogin">Log in via Clonkspot</q-btn> - <p class="text-negative" v-if="authFailed">Oups, something went wrong. Please try again</p> - <div class="text-right"> - <q-btn color="tertiary" small outline @click="useLarryLogin = true">Log in via Larry</q-btn> + <q-input @keyup.enter="parryLogin" :error="authError !== undefined" v-model="username" name="user" float-label="Username" /> + <q-input @keyup.enter="parryLogin" :error="authError !== undefined" v-model="password" name="pass" type="password" float-label="Password" /> + <q-btn color="positive" @click="parryLogin" icon="fa-sign-in">Parry login</q-btn> </div> </div> </div> @@ -41,18 +31,17 @@ <script> import { - openURL, LocalStorage, } from 'quasar' export default { data () { return { - email: '', + username: '', password: '', authError: undefined, token: null, - useLarryLogin: false, + useParryLogin: true, authWindow: null, authFailed: false, } @@ -64,23 +53,18 @@ } }, methods: { - clonkspotLogin () { - this.authWindow = openURL(`${this.$http.defaults.baseURL}/auth/clonkspot`) - this.checkTokenLoop() - }, - larryLogin () { + parryLogin () { let that = this let params = { - user: { - email: this.email, - password: this.password, - } + username: this.username, + password: this.password, } this.authError = undefined - this.$http.post('/auth/login', params).then((response) => { - that.$store.commit('user/setAuthToken', { authToken: response.data.user.token }) - that.email = '' + this.$http.post('/auth', params).then((response) => { + that.$store.commit('user/setAuthToken', { authToken: response.data.token }) + that.username = '' that.password = '' + setTimeout(() => this.$store.commit('user/logout'), Math.max(parseInt(response.data.expires) - Math.floor(Date.now() / 1000), 0) * 1000) }).catch((error) => { if (error.response && error.response.data) { that.authError = error.response.data.errors diff --git a/src/components/CommentVoter.vue b/src/components/CommentVoter.vue index 4747571..ccb9e55 100644 --- a/src/components/CommentVoter.vue +++ b/src/components/CommentVoter.vue @@ -49,7 +49,7 @@ methods: { vote (impact) { let that = this - this.$http.post(`/uploads/${this.comment.upload}/comments/${this.comment._id}/vote`, {impact: impact}).then(response => that.$emit('voted')) + this.$http.post(`/uploads/${this.comment.upload}/comments/${this.comment.id}/vote`, {impact: impact}).then(response => that.$emit('voted')) }, }, } diff --git a/src/components/UploadVoter.vue b/src/components/UploadVoter.vue index e5d18ae..b929a45 100644 --- a/src/components/UploadVoter.vue +++ b/src/components/UploadVoter.vue @@ -45,16 +45,17 @@ }, computed: { myVote () { - if (!this.upload || !this.upload.voting || !Array.isArray(this.upload.voting.votes) || this.upload.voting.votes.length === 0) { - return undefined + if (!this.upload.voting.vote) { + let that = this + this.$http.get(`/uploads/${this.upload.id}/vote`).then((response) => { this.upload.voting.vote = response.data }) } - return this.upload.voting.votes[0] + return this.upload.voting.vote }, }, methods: { vote (impact) { let that = this - this.$http.post(`/uploads/${this.upload._id}/vote`, {impact: impact}).then(response => that.$emit('voted')) + this.$http.post(`/uploads/${this.upload.id}/vote`, {impact: impact}).then(response => that.$emit('voted')) }, }, } diff --git a/src/layouts/default.vue b/src/layouts/default.vue index e3ab151..0c7a7a7 100644 --- a/src/layouts/default.vue +++ b/src/layouts/default.vue @@ -3,8 +3,8 @@ <q-layout-header> <q-toolbar> <q-toolbar-title> - Larry UI - <div slot="subtitle">Official source of mods for OpenClonk</div> + Parry + <div slot="subtitle">Official source of mods for LegacyClonk</div> </q-toolbar-title> <q-tabs> @@ -69,7 +69,7 @@ <style> body { - background: white url('/statics/bodybg.jpg') no-repeat fixed; + background: white url('https://ccan.de/img/bg.jpg') repeat fixed; } .q-layout-header .q-toolbar { diff --git a/src/pages/FetchToken.vue b/src/pages/FetchToken.vue index 6745377..d681ca8 100644 --- a/src/pages/FetchToken.vue +++ b/src/pages/FetchToken.vue @@ -47,7 +47,7 @@ } else { let that = this - this.$http.get('/uploads', {headers: {Authorization: `Bearer ${this.routeToken}`}}).then(response => { + this.$http.get('/api/auth', {headers: {Authorization: `JWT ${this.routeToken}`}}).then(response => { that.tokenValid = true that.$store.commit('user/setAuthToken', { authToken: that.routeToken }) window.close() diff --git a/src/pages/UploadCreate.vue b/src/pages/UploadCreate.vue index 4b27725..c435a2f 100644 --- a/src/pages/UploadCreate.vue +++ b/src/pages/UploadCreate.vue @@ -43,7 +43,7 @@ </q-alert> <dropzone id="picDropzone" ref="picDropzone" - @vdropzone-success="picUploadSuccess" + @vdropzone-success="uploadSuccess" :options="picDropzoneOptions"> </dropzone> <q-stepper-navigation> @@ -61,7 +61,7 @@ </q-stepper-navigation> </q-step> <q-step name="files" title="Add files"> - <p>Now please upload your mod files (e.g. the .ocs file). You have to upload at least one file</p> + <p>Now please upload your mod files (e.g. the .c4s file). You have to upload at least one file</p> <q-alert color="warning" enter="bounceInLeft" appear> @@ -83,9 +83,9 @@ </tr> </thead> <tbody> - <tr v-for="(file, idx) of files" :key="file._id"> + <tr v-for="(file, idx) of files" :key="file.id"> <td>{{ file.filename }}</td> - <td>{{ file._id }}</td> + <td>{{ file.id }}</td> <td>{{ file.length | prettyBytes }}</td> <td>uploaded {{ file.uploadDate|moment("from") }}</td> <td><q-btn round color="negative" small icon="fa-trash" @click="deleteFile(idx)"></q-btn></td> @@ -110,13 +110,13 @@ </q-step> <q-step name="done" title="Done"> <h6 class="text-positive" v-if="savedScenario"> - Successfully saved your mod with the id {{ savedScenario._id }} + Successfully saved your mod with the id {{ savedScenario.id }} </h6> <q-stepper-navigation> <q-btn color="warning" icon="fa-refresh" @click="reset">Upload another one</q-btn> <q-btn color="primary" icon="fa-eye" - @click="$router.push({name: 'upload-detail', params: {uploadId: savedScenario._id}})"> + @click="$router.push({name: 'upload-detail', params: {uploadId: savedScenario.id}})"> Show the saved mod </q-btn> </q-stepper-navigation> @@ -167,8 +167,8 @@ return { url: `${this.$http.defaults.baseURL}/media`, paramName: 'media', - headers: { Authorization: `Bearer ${this.$store.state.user.authToken}` }, - acceptedFiles: '.ocs,.ocf,.ocd,.ocg,.ocr,.c4d,.c4g,.c4f,.c4r,.c4s,c4v', + headers: { Authorization: `JWT ${this.$store.state.user.authToken}` }, + acceptedFiles: '.ocs,.ocf,.ocd,.ocg,.ocr,.ocu,.c4d,.c4g,.c4f,.c4r,.c4s,.c4v,.c4l,.c4u', dictDefaultMessage: "<p><i class='fa fa-3x fa-cloud-upload'></i></p><p>Drop your mod files here or click to upload</p>", maxFilesize: 30, // MB } @@ -177,7 +177,7 @@ return { url: `${this.$http.defaults.baseURL}/media`, paramName: 'media', - headers: { Authorization: `Bearer ${this.$store.state.user.authToken}` }, + headers: { Authorization: `JWT ${this.$store.state.user.authToken}` }, acceptedFiles: '.png,.jpg', dictDefaultMessage: "<p><i class='fa fa-3x fa-cloud-upload'></i></p><p>Drop your image here or click to upload</p>", maxFilesize: 3, // MB @@ -195,7 +195,7 @@ if (!this.pic) { return '' } - return `${this.$http.defaults.baseURL}/media/${this.pic._id}` + return `${this.$http.defaults.baseURL}/media/${this.pic.id}` }, }, watch: { @@ -209,11 +209,7 @@ deleteFile (idx) { let file = this.files[idx] this.files.splice(idx, 1) - this.$http.delete(`${this.$http.defaults.baseURL}/media/${file._id}`) - }, - picUploadSuccess (file, response) { - this.pic = response - this.$refs.picDropzone.disable() + this.$http.delete(`${this.$http.defaults.baseURL}/media/${file.id}`) }, uploadSuccess (file, response) { this.files.push(response) @@ -238,8 +234,7 @@ let params = { title: this.title, description: this.description, - files: this.files.map(el => el._id), - pic: this.pic, + files: this.files.map(el => el.id), tags: this.tags, } this.$http.post('/uploads', params) diff --git a/src/pages/UploadDetail.vue b/src/pages/UploadDetail.vue index a26b0c2..f274eec 100644 --- a/src/pages/UploadDetail.vue +++ b/src/pages/UploadDetail.vue @@ -2,31 +2,41 @@ <div> <div v-if="upload"> <q-card> - <q-card-media v-if="upload.pic" overlay-position="top"> + <q-card-media v-if="upload.pictures.length > 0" overlay-position="top"> <q-card-title slot="overlay"> {{ upload.title }} <span slot="subtitle"> - by {{ upload.author.username }}, + by {{ upload.author.name }}, updated {{ upload.updatedAt | moment("from") }} </span> <span slot="right" class="text-white" style="margin-left: 3rem"> <q-btn @click="$router.push({name: 'upload-list'})" flat round icon="fa-times" color="negative"/> </span> </q-card-title> - <img :src="`${$http.defaults.baseURL}/media/${upload.pic._id}`"> + <q-carousel class="text-width" v-if="upload.pictures.length > 1" style="height: 300px;" arrows quick-nav infinite autoplay> + <q-carousel-slide v-for="picture in upload.pictures" :key="picture.id" :style="`background: url('${$http.defaults.baseURL}/media/${picture.id}') no-repeat; background-size: 100% auto;`"> + </q-carousel-slide> + </q-carousel> + <div v-else :style="`background: url('${$http.defaults.baseURL}/media/${upload.pictures[0].id}') no-repeat; background-size: 100% auto; height: 300px;`"> + </div> </q-card-media> <q-card-title class="bg-positive text-white" v-else> {{ upload.title }} - <span slot="subtitle" class="text-light">by {{ upload.author.username }}</span> - <span slot="right" class="text-light" style="margin-left: 3rem">updated {{ upload.updatedAt | moment("from") }}</span> + <span slot="subtitle" class="text-white">by {{ upload.author.name }}</span> + <span slot="right" class="text-white" style="margin-left: 3rem">updated {{ upload.updatedAt | moment("from") }}</span> + <span slot="right" class="text-white" style=""> + <q-btn @click="$router.push({name: 'upload-list'})" flat round icon="fa-times" color="negative"/> + </span> </q-card-title> <q-card-separator /> <q-card-actions> - <q-btn @click="openInOpenclonk" + <q-btn @click="openInLegacyClonk" color="positive" outline icon="fa-download" - label="Install mod with OpenClonk" /> + label="Install mod with LegacyClonk" + disabled + v-if="false" /> <q-btn v-if="isAuthor" outline color="negative" @@ -126,12 +136,12 @@ <em>Please log in to comment</em> </div> <div class="flex row no-wrap items-center" - v-for="comment of comments.comments" - :key="comment._id"> + v-for="comment of comments.slice().reverse()" + :key="comment.id"> <q-chat-message style="max-width: 90%" :bg-color="comment.voting.sum > 0 ? 'light-green-2' : ( comment.voting.sum === 0 ? 'grey-3' : 'red-2')" - :name="(comment.author || {}).username" + :name="(comment.author || {}).name" :text="comment.body.split('\n').filter(el => el.trim() !== '')" :stamp="$moment(comment.createdAt).format('LLLL')" /> <q-btn v-if="isAuthor" @@ -141,7 +151,7 @@ icon="fa-trash" color="negative" @click="deleteComment(comment)"/> - <comment-voter @voted="loadComments" :comment="comment"></comment-voter> + <comment-voter @voted="refresh" :comment="comment"></comment-voter> </div> </q-card-main> <q-card-separator /> @@ -163,8 +173,8 @@ </q-btn> <div class="group" v-else> <div v-for="d of upload.dependencies" - :key="d._id"> - <q-btn @click="$router.push({name: 'upload-detail', params: {uploadId: d._id}})" no-caps outline> + :key="d.id"> + <q-btn @click="$router.push({name: 'upload-detail', params: {uploadId: d.id}})" no-caps outline> {{ d.title }} </q-btn> </div> @@ -203,22 +213,22 @@ <div class="group" v-else v-for="(fid, idx) of upload.files" - :key="fid._id"> + :key="fid.id"> <q-btn loader no-caps outline icon="fa-download" color="primary" - :percentage="(downloadProgresses[fid._id] || {}).percentage" - :loading="downloadProgresses[fid._id] && downloadProgresses[fid._id].percentage < 100" - @click="(event, done) => {downloadMedia(fid._id, fid.filename, done)}" + :percentage="(downloadProgresses[fid.id] || {}).percentage" + :loading="downloadProgresses[fid.id] && downloadProgresses[fid.id].percentage < 100" + @click="(event, done) => {downloadMedia(fid.id, fid.filename, done)}" :label="`${fid.filename} (${$options.filters.prettyBytes(fid.length)})`"> <span slot="loading">Downloading...</span> </q-btn> - <span v-if="downloadProgresses[fid._id]"> + <span v-if="downloadProgresses[fid.id]"> <transition enter-active-class="animated fadeIn" leave-active-class="animated fadeOut" mode="out-in"> - <span key="sizeDownloaded" v-if="downloadProgresses[fid._id].percentage < 100"> - {{ downloadProgresses[fid._id].loaded|prettyBytes }} / {{ downloadProgresses[fid._id].total|prettyBytes }} + <span key="sizeDownloaded" v-if="downloadProgresses[fid.id].percentage < 100"> + {{ downloadProgresses[fid.id].loaded|prettyBytes }} / {{ downloadProgresses[fid.id].total|prettyBytes }} </span> <span key="downloadDone" v-else><i class="fa fa-check fa-2x text-positive"></i></span> </transition> @@ -244,7 +254,7 @@ <i class="far fa-hand-point-right"></i> Other data </q-card-title> <q-card-main> - <p>ID: {{ upload._id }}</p> + <p>ID: {{ upload.id }}</p> </q-card-main> </q-card> </div> @@ -260,7 +270,7 @@ import { openURL } from 'quasar' import UploadVoter from 'components/UploadVoter' import CommentVoter from 'components/CommentVoter' - import FileSaver from 'file-saver' + /* import FileSaver from 'file-saver' */ import VueMarkdown from 'vue-markdown' export default { @@ -275,10 +285,10 @@ return this.$route.params.uploadId }, isAuthor () { - return this.upload && this.upload.author && this.upload.author.username === this.username + return this.upload && this.upload.author && this.upload.author.name === this.name }, - username () { - return this.$store.state.user.decodedToken.username + name () { + return this.$store.state.user.decodedToken.name }, loggedIn () { return this.$store.getters['user/loggedIn'] @@ -287,8 +297,8 @@ return { url: `${this.$http.defaults.baseURL}/media`, paramName: 'media', - headers: { Authorization: `Bearer ${this.$store.state.user.authToken}` }, - acceptedFiles: '.ocs,.ocf,.ocd,.ocg,.ocr,.c4d,.c4g,.c4f,.c4r,.c4s,c4v', + headers: { Authorization: `JWT ${this.$store.state.user.authToken}` }, + acceptedFiles: '.ocs,.ocf,.ocd,.ocg,.ocr,.ocu,.c4d,.c4g,.c4f,.c4r,.c4s,c4v,.c4l.c4u', dictDefaultMessage: "<p><i class='fa fa-3x fa-cloud-upload'></i></p><p>Drop your mod files here or click to upload</p>", maxFilesize: 30, // MB } @@ -321,7 +331,7 @@ let that = this this.$http.get(`/uploads/${this.routeId}`).then(response => { that.upload = response.data - that.loadComments() + that.comments = response.data.comments }).catch((error) => { if (error.response.status === 404) { that.$router.push({name: 'upload-list'}) @@ -331,14 +341,8 @@ } }) }, - loadComments () { - let that = this - this.$http.get(`/uploads/${this.routeId}/comments`).then(response => { - that.comments = response.data - }).catch((error) => { - that.$q.notify('Failed loading comments') - console.error(error) - }) + getPictures (picture) { + return picture.map(p => `${this.$http.defaults.baseURL}/media/${p.id}`) }, uploadSuccess (file, response) { this.upload.files.push(response) @@ -347,7 +351,7 @@ }, saveUpload () { let that = this - this.$http.put(`/uploads/${this.upload._id}`, this.upload).then(response => { + this.$http.put(`/uploads/${this.upload.id}`, this.upload).then(response => { that.editDescription = false that.editTags = false that.editFiles = false @@ -366,9 +370,11 @@ outline: true, }, cancel: 'Cancel', - }).then(() => that.$http.delete(`/uploads/${upload._id}`).then(response => that.refresh())) + }).then(() => that.$http.delete(`/uploads/${upload.id}`).then(response => that.refresh())) }, downloadMedia (mediaId, filename, done) { + window.open(`${this.$http.defaults.baseURL}/media/${mediaId}?download=1`) + /* console.log({mediaId, done}) let that = this this.$set(this.downloadProgresses, mediaId, {}) @@ -386,36 +392,37 @@ FileSaver.saveAs(response.data, filename) that.downloadProgresses[mediaId].done() that.downloadProgresses[mediaId].percentage = 100 - }) + }) */ }, downloadProgress (mediaId, progressEvent) { this.downloadProgresses[mediaId].percentage = progressEvent.loaded * 100 / progressEvent.total this.downloadProgresses[mediaId].loaded = progressEvent.loaded this.downloadProgresses[mediaId].total = progressEvent.total }, - openInOpenclonk () { - openURL(`openclonk://installmod/${this.upload._id}`) + openInLegacyClonk () { + openURL(`clonk://installmod/${this.upload.id}`) }, sendComment () { let that = this this.commentSaving = true if (this.comment.length > 0) { - this.$http.post(`/uploads/${this.upload._id}/comments`, {body: this.comment}).then(() => { + this.$http.post(`/uploads/${this.upload.id}/comments`, {body: this.comment}).then(() => { that.comment = '' that.$q.notify({color: 'positive', icon: 'fa-check', message: 'Comment sent'}) - that.loadComments() this.commentSaving = false + that.refresh() }).catch((error) => { that.$q.notify('Error sending your comment') - that.loadComments() this.commentSaving = false + that.refresh() + console.log(error) console.error(error) }) } }, deleteComment (comment) { let that = this - this.$http.delete(`/uploads/${comment.upload}/comments/${comment._id}/`).then(() => that.loadComments()) + this.$http.delete(`/uploads/${comment.upload}/comments/${comment.id}/`).then(() => that.refresh()) }, } } diff --git a/src/pages/UploadList.vue b/src/pages/UploadList.vue index 733206f..423f381 100644 --- a/src/pages/UploadList.vue +++ b/src/pages/UploadList.vue @@ -17,16 +17,16 @@ :visible-columns="visibleColumns" @refresh="refresh"> <q-td slot='body-cell-title' slot-scope="props" :props='props'> - <router-link :to="{name: 'upload-detail', params: {uploadId: props.row._id}}">{{ props.value }}</router-link> + <router-link :to="{name: 'upload-detail', params: {uploadId: props.row.id}}">{{ props.value }}</router-link> </q-td> <q-td slot='body-cell-action' slot-scope="props" :props='props'> <q-btn color="primary" - v-if="$route.params.uploadId !== props.row._id" + v-if="$route.params.uploadId !== props.row.id" small outline icon="fa-info-circle" label="Show" - @click="$router.push({name: 'upload-detail', params: {uploadId: props.row._id}})" /> + @click="$router.push({name: 'upload-detail', params: {uploadId: props.row.id}})" /> </q-td> <q-td slot='body-cell-voting' slot-scope="props" :props='props'> {{ props.value.sum }} <i class="fa" :class="{'fa-caret-up text-positive': props.value.sum > 0, 'fa-caret-down text-negative': props.value.sum < 0, 'fa-sort text-dark': props.value.sum === 0}"></i> @@ -82,7 +82,7 @@ align: 'left', format: el => typeof el === 'string' && el.length > 50 ? el.slice(0, 50) + '...' : el, }, - {name: 'author', label: 'Author', field: row => row.author.username, align: 'left'}, + {name: 'author', label: 'Author', field: row => row.author.name, align: 'left'}, {name: 'voting', label: 'Voting', field: 'voting', align: 'left'}, { name: 'updatedAt', @@ -99,6 +99,7 @@ refresh (done) { let that = this this.$http.get('/uploads').then((response) => { + console.log(response.data.uploads) that.response = response that.uploads = response.data.uploads if (done) { @@ -118,7 +119,7 @@ outline: true, }, cancel: 'Cancel', - }).then(() => that.$http.delete(`/uploads/${upload._id}`).then(response => that.refresh())) + }).then(() => that.$http.delete(`/uploads/${upload.id}`).then(response => that.refresh())) }, }, } diff --git a/src/store/module-user/getters.js b/src/store/module-user/getters.js index 64241d1..3e858c3 100644 --- a/src/store/module-user/getters.js +++ b/src/store/module-user/getters.js @@ -1 +1 @@ -export const loggedIn = (state) => Boolean(state.decodedToken.username) +export const loggedIn = (state) => Boolean(state.decodedToken.name) diff --git a/src/store/module-user/mutations.js b/src/store/module-user/mutations.js index e8f4799..72b1d26 100644 --- a/src/store/module-user/mutations.js +++ b/src/store/module-user/mutations.js @@ -5,7 +5,7 @@ import { LocalStorage } from 'quasar' export const setAuthToken = (state, { authToken }) => { state.authToken = authToken state.decodedToken = jwtDecode(authToken) - axios.defaults.headers.common['Authorization'] = `Bearer ${authToken}` + axios.defaults.headers.common['Authorization'] = `JWT ${authToken}` LocalStorage.set('authToken', authToken) } |
