Add "my files" using resources #3792
parent
b090544ba6
commit
fcabbcc1ef
@ -0,0 +1,75 @@ |
|||||||
|
<template> |
||||||
|
<q-form> |
||||||
|
<q-input |
||||||
|
id="item_title" |
||||||
|
v-model="item.title" |
||||||
|
:placeholder="$t('Title')" |
||||||
|
:error="v$.item.title.$error" |
||||||
|
@input="v$.item.title.$touch()" |
||||||
|
@blur="v$.item.title.$touch()" |
||||||
|
:error-message="titleErrors" |
||||||
|
/> |
||||||
|
<slot></slot> |
||||||
|
</q-form> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script> |
||||||
|
import has from 'lodash/has'; |
||||||
|
import useVuelidate from '@vuelidate/core'; |
||||||
|
import { required } from '@vuelidate/validators'; |
||||||
|
|
||||||
|
export default { |
||||||
|
name: 'PersonalFileForm', |
||||||
|
setup () { |
||||||
|
return { v$: useVuelidate() } |
||||||
|
}, |
||||||
|
props: { |
||||||
|
values: { |
||||||
|
type: Object, |
||||||
|
required: true |
||||||
|
}, |
||||||
|
errors: { |
||||||
|
type: Object, |
||||||
|
default: () => {} |
||||||
|
}, |
||||||
|
initialValues: { |
||||||
|
type: Object, |
||||||
|
default: () => {} |
||||||
|
}, |
||||||
|
}, |
||||||
|
data() { |
||||||
|
return { |
||||||
|
title: null, |
||||||
|
parentResourceNodeId: null, |
||||||
|
}; |
||||||
|
}, |
||||||
|
computed: { |
||||||
|
item() { |
||||||
|
return this.initialValues || this.values; |
||||||
|
}, |
||||||
|
titleErrors() { |
||||||
|
const errors = []; |
||||||
|
if (!this.v$.item.title.$dirty) return errors; |
||||||
|
has(this.violations, 'title') && errors.push(this.violations.title); |
||||||
|
|
||||||
|
if (this.v$.item.title.required) { |
||||||
|
return this.$t('Field is required') |
||||||
|
} |
||||||
|
|
||||||
|
return errors; |
||||||
|
}, |
||||||
|
violations() { |
||||||
|
return this.errors || {}; |
||||||
|
} |
||||||
|
}, |
||||||
|
validations: { |
||||||
|
item: { |
||||||
|
title: { |
||||||
|
required, |
||||||
|
}, |
||||||
|
parentResourceNodeId: { |
||||||
|
}, |
||||||
|
} |
||||||
|
} |
||||||
|
}; |
||||||
|
</script> |
@ -0,0 +1,126 @@ |
|||||||
|
<template> |
||||||
|
<q-form> |
||||||
|
<div class="input-group mb-3"> |
||||||
|
<div class="custom-file"> |
||||||
|
<input |
||||||
|
id="file_upload" |
||||||
|
type="file" |
||||||
|
class="custom-file-input" |
||||||
|
ref="fileList" |
||||||
|
multiple |
||||||
|
placeholder="File upload" |
||||||
|
@change="selectFile" |
||||||
|
/> |
||||||
|
<label |
||||||
|
class="custom-file-label" |
||||||
|
for="file_upload" |
||||||
|
aria-describedby="File upload"> |
||||||
|
Choose file |
||||||
|
</label> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
|
||||||
|
<div class="field"> |
||||||
|
<div |
||||||
|
v-for="(file, index) in files" |
||||||
|
:key="index" |
||||||
|
:class="{ error : file.invalidMessage}" |
||||||
|
> |
||||||
|
<div> |
||||||
|
{{ file.name }} |
||||||
|
<span v-if="file.invalidMessage"> |
||||||
|
- {{ file.invalidMessage }} |
||||||
|
</span> |
||||||
|
<span> |
||||||
|
<a @click.prevent="files.splice(index, 1)" |
||||||
|
class="delete" |
||||||
|
> |
||||||
|
<FontAwesomeIcon icon="trash" /> |
||||||
|
</a> |
||||||
|
</span> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</q-form> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script> |
||||||
|
import has from 'lodash/has'; |
||||||
|
import map from 'lodash/map'; |
||||||
|
import useVuelidate from '@vuelidate/core'; |
||||||
|
|
||||||
|
export default { |
||||||
|
name: 'PersonalFileFormUpload', |
||||||
|
setup () { |
||||||
|
return { v$: useVuelidate() } |
||||||
|
}, |
||||||
|
props: { |
||||||
|
values: { |
||||||
|
type: Array, |
||||||
|
required: true |
||||||
|
}, |
||||||
|
parentResourceNodeId: { |
||||||
|
type: Number |
||||||
|
}, |
||||||
|
resourceLinkList: { |
||||||
|
type: String, |
||||||
|
}, |
||||||
|
errors: { |
||||||
|
type: Object, |
||||||
|
default: () => {} |
||||||
|
}, |
||||||
|
processFiles: { |
||||||
|
type: Function, |
||||||
|
required: false |
||||||
|
}, |
||||||
|
}, |
||||||
|
data() { |
||||||
|
return { |
||||||
|
fileList:[], |
||||||
|
files: [], |
||||||
|
}; |
||||||
|
}, |
||||||
|
computed: { |
||||||
|
titleErrors() { |
||||||
|
const errors = []; |
||||||
|
if (!this.$v.item.title.$dirty) return errors; |
||||||
|
has(this.violations, 'title') && errors.push(this.violations.title); |
||||||
|
!this.$v.item.title.required && errors.push(this.$t('Field is required')); |
||||||
|
|
||||||
|
return errors; |
||||||
|
}, |
||||||
|
violations() { |
||||||
|
return this.errors || {}; |
||||||
|
} |
||||||
|
}, |
||||||
|
methods: { |
||||||
|
selectFile() { |
||||||
|
const files = this.$refs.fileList.files; |
||||||
|
|
||||||
|
this.files = [ |
||||||
|
...this.files, |
||||||
|
...map(files, file => ({ |
||||||
|
name: file.name, |
||||||
|
size: file.size, |
||||||
|
type: file.type, |
||||||
|
filetype: 'file', |
||||||
|
parentResourceNodeId: this.parentResourceNodeId, |
||||||
|
resourceLinkList: this.resourceLinkList, |
||||||
|
uploadFile: file, |
||||||
|
invalidMessage: this.validate(file), |
||||||
|
})) |
||||||
|
] |
||||||
|
}, |
||||||
|
validate(file) { |
||||||
|
if (file) { |
||||||
|
return ''; |
||||||
|
} |
||||||
|
|
||||||
|
return 'error'; |
||||||
|
} |
||||||
|
}, |
||||||
|
validations: { |
||||||
|
files: {} |
||||||
|
} |
||||||
|
}; |
||||||
|
</script> |
@ -0,0 +1,9 @@ |
|||||||
|
<template> |
||||||
|
<router-view></router-view> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script> |
||||||
|
export default { |
||||||
|
name: 'PersonalFileLayout' |
||||||
|
} |
||||||
|
</script> |
@ -0,0 +1,68 @@ |
|||||||
|
<template> |
||||||
|
<div v-if="item && item['resourceLinkListFromEntity']"> |
||||||
|
<ul> |
||||||
|
<li |
||||||
|
v-for="link in item['resourceLinkListFromEntity']" |
||||||
|
> |
||||||
|
<div v-if="link['course']"> |
||||||
|
{{ $t('Course') }}: {{ link.course.resourceNode.title }} |
||||||
|
</div> |
||||||
|
|
||||||
|
<div v-if="link['session']"> |
||||||
|
{{ $t('Session') }}: {{ link.session.name }} |
||||||
|
</div> |
||||||
|
|
||||||
|
<div v-if="link['group']"> |
||||||
|
{{ $t('Group') }}: {{ link.session.resourceNode.title }} |
||||||
|
</div> |
||||||
|
|
||||||
|
<q-separator /> |
||||||
|
|
||||||
|
<q-select |
||||||
|
filled |
||||||
|
v-model="link.visibility" |
||||||
|
:options="visibilityList" |
||||||
|
label="Status" |
||||||
|
emit-value |
||||||
|
map-options |
||||||
|
/> |
||||||
|
</li> |
||||||
|
</ul> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script> |
||||||
|
import has from 'lodash/has'; |
||||||
|
import useVuelidate from '@vuelidate/core'; |
||||||
|
import { required } from '@vuelidate/validators'; |
||||||
|
|
||||||
|
export default { |
||||||
|
name: 'ResourceLinkForm', |
||||||
|
setup () { |
||||||
|
const visibilityList = [ |
||||||
|
{value: 2, label: 'Published'}, |
||||||
|
{value: 0, label: 'Draft'}, |
||||||
|
]; |
||||||
|
return {v$: useVuelidate(), visibilityList}; |
||||||
|
}, |
||||||
|
props: { |
||||||
|
values: { |
||||||
|
type: Object, |
||||||
|
required: true |
||||||
|
}, |
||||||
|
errors: { |
||||||
|
type: Object, |
||||||
|
default: () => {} |
||||||
|
}, |
||||||
|
initialValues: { |
||||||
|
type: Object, |
||||||
|
default: () => {} |
||||||
|
}, |
||||||
|
}, |
||||||
|
computed: { |
||||||
|
item() { |
||||||
|
return this.initialValues || this.values; |
||||||
|
}, |
||||||
|
}, |
||||||
|
}; |
||||||
|
</script> |
@ -0,0 +1,42 @@ |
|||||||
|
export default { |
||||||
|
path: '/resources/personal_files', |
||||||
|
meta: { requiresAuth: true }, |
||||||
|
name: 'personal_files', |
||||||
|
component: () => import('../views/personalfile/Home.vue'), |
||||||
|
children: [ |
||||||
|
{ |
||||||
|
name: 'personal_files', |
||||||
|
path: ':node/', |
||||||
|
component: () => import('../components/personalfile/Layout.vue'), |
||||||
|
redirect: { name: 'PersonalFileList' }, |
||||||
|
children: [ |
||||||
|
{ |
||||||
|
name: 'PersonalFileList', |
||||||
|
path: '', |
||||||
|
component: () => import('../views/personalfile/List.vue') |
||||||
|
}, |
||||||
|
{ |
||||||
|
name: 'PersonalFileCreate', |
||||||
|
path: 'new', |
||||||
|
component: () => import('../views/personalfile/Create.vue') |
||||||
|
}, |
||||||
|
{ |
||||||
|
name: 'PersonalFileUploadFile', |
||||||
|
path: 'upload', |
||||||
|
component: () => import('../views/personalfile/Upload.vue') |
||||||
|
}, |
||||||
|
{ |
||||||
|
name: 'PersonalFileUpdate', |
||||||
|
//path: ':id/edit',
|
||||||
|
path: 'edit_file', |
||||||
|
component: () => import('../views/personalfile/Update.vue') |
||||||
|
}, |
||||||
|
{ |
||||||
|
name: 'PersonalFileShow', |
||||||
|
path: 'show', |
||||||
|
component: () => import('../views/personalfile/Show.vue') |
||||||
|
} |
||||||
|
] |
||||||
|
}, |
||||||
|
] |
||||||
|
}; |
@ -0,0 +1,3 @@ |
|||||||
|
import makeService from './api'; |
||||||
|
|
||||||
|
export default makeService('personal_files'); |
@ -0,0 +1,63 @@ |
|||||||
|
<template> |
||||||
|
<div> |
||||||
|
<Toolbar |
||||||
|
:handle-submit="onSendForm" |
||||||
|
:handle-reset="resetForm" |
||||||
|
/> |
||||||
|
|
||||||
|
<DocumentsForm |
||||||
|
ref="createForm" |
||||||
|
:values="item" |
||||||
|
:errors="violations" |
||||||
|
/> |
||||||
|
<Loading :visible="isLoading" /> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script> |
||||||
|
import { mapActions } from 'vuex'; |
||||||
|
import { createHelpers } from 'vuex-map-fields'; |
||||||
|
import DocumentsForm from '../../components/personalfile/Form.vue'; |
||||||
|
import Loading from '../../components/Loading.vue'; |
||||||
|
import Toolbar from '../../components/Toolbar.vue'; |
||||||
|
import CreateMixin from '../../mixins/CreateMixin'; |
||||||
|
|
||||||
|
const servicePrefix = 'PersonalFile'; |
||||||
|
|
||||||
|
const { mapFields } = createHelpers({ |
||||||
|
getterType: 'personal_file/getField', |
||||||
|
mutationType: 'personal_file/updateField' |
||||||
|
}); |
||||||
|
|
||||||
|
export default { |
||||||
|
name: 'PersonalFileCreate', |
||||||
|
servicePrefix, |
||||||
|
components: { |
||||||
|
Loading, |
||||||
|
Toolbar, |
||||||
|
DocumentsForm |
||||||
|
}, |
||||||
|
mixins: [CreateMixin], |
||||||
|
data() { |
||||||
|
return { |
||||||
|
item: {}, |
||||||
|
type: 'folder' |
||||||
|
}; |
||||||
|
}, |
||||||
|
computed: { |
||||||
|
...mapFields(['error', 'isLoading', 'created', 'violations']) |
||||||
|
}, |
||||||
|
created() { |
||||||
|
this.item.parentResourceNodeId = this.$route.params.node; |
||||||
|
this.item.resourceLinkList = JSON.stringify([{ |
||||||
|
gid: this.$route.query.gid, |
||||||
|
sid: this.$route.query.sid, |
||||||
|
c_id: this.$route.query.cid, |
||||||
|
visibility: 2, // visible by default |
||||||
|
}]); |
||||||
|
}, |
||||||
|
methods: { |
||||||
|
...mapActions('personalfile', ['create', 'reset']) |
||||||
|
} |
||||||
|
}; |
||||||
|
</script> |
@ -0,0 +1,43 @@ |
|||||||
|
<template> |
||||||
|
<router-view></router-view> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script> |
||||||
|
import { mapActions, mapGetters } from 'vuex'; |
||||||
|
import Loading from '../../components/Loading.vue'; |
||||||
|
import ShowMixin from '../../mixins/ShowMixin'; |
||||||
|
import Toolbar from '../../components/Toolbar.vue'; |
||||||
|
import isEmpty from "lodash/isEmpty"; |
||||||
|
const servicePrefix = 'PersonalFile'; |
||||||
|
|
||||||
|
export default { |
||||||
|
name: 'PersonalFileHome', |
||||||
|
servicePrefix, |
||||||
|
components: { |
||||||
|
Loading, |
||||||
|
Toolbar |
||||||
|
}, |
||||||
|
created() { |
||||||
|
console.log('CREATED HOME'); |
||||||
|
let resourceNodeId = this.currentUser.resourceNode['id']; |
||||||
|
|
||||||
|
console.log(resourceNodeId); |
||||||
|
this.$router |
||||||
|
.push({ name: `${this.$options.servicePrefix}List`, params: { node: resourceNodeId },}) |
||||||
|
.catch(() => {}); |
||||||
|
|
||||||
|
}, |
||||||
|
computed: { |
||||||
|
// From crud.js list function |
||||||
|
...mapGetters('resourcenode', { |
||||||
|
resourceNode: 'getResourceNode' |
||||||
|
}), |
||||||
|
...mapGetters({ |
||||||
|
'isAuthenticated': 'security/isAuthenticated', |
||||||
|
'isAdmin': 'security/isAdmin', |
||||||
|
'currentUser': 'security/getUser', |
||||||
|
}), |
||||||
|
} |
||||||
|
|
||||||
|
}; |
||||||
|
</script> |
@ -0,0 +1,363 @@ |
|||||||
|
<template> |
||||||
|
<div v-if="isAuthenticated" class="q-card"> |
||||||
|
<div class="p-4 flex flex-row gap-1 mb-2"> |
||||||
|
<div class="flex flex-row gap-2" > |
||||||
|
<Button label="New folder" icon="fa fa-folder-plus" class="btn btn-primary" @click="openNew" /> |
||||||
|
<Button label="Upload" icon="fa fa-file-upload" class="btn btn-primary" @click="uploadDocumentHandler()" /> |
||||||
|
<Button label="Delete" icon="pi pi-trash" class="btn btn-danger " @click="confirmDeleteMultiple" :disabled="!selectedItems || !selectedItems.length" /> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
<DataTable |
||||||
|
class="p-datatable-sm" |
||||||
|
:value="items" |
||||||
|
v-model:selection="selectedItems" |
||||||
|
dataKey="iid" |
||||||
|
v-model:filters="filters" |
||||||
|
filterDisplay="menu" |
||||||
|
:lazy="true" |
||||||
|
:paginator="true" |
||||||
|
:rows="10" |
||||||
|
:totalRecords="totalItems" |
||||||
|
:loading="isLoading" |
||||||
|
@page="onPage($event)" |
||||||
|
@sort="sortingChanged($event)" |
||||||
|
paginatorTemplate="CurrentPageReport FirstPageLink PrevPageLink PageLinks NextPageLink LastPageLink RowsPerPageDropdown" |
||||||
|
:rowsPerPageOptions="[5, 10, 20, 50]" |
||||||
|
responsiveLayout="scroll" |
||||||
|
currentPageReportTemplate="Showing {first} to {last} of {totalRecords}" |
||||||
|
:globalFilterFields="['resourceNode.title', 'resourceNode.updatedAt']"> |
||||||
|
|
||||||
|
<span v-if="isCurrentTeacher"> |
||||||
|
<Column selectionMode="multiple" style="width: 3rem" :exportable="false"></Column> |
||||||
|
</span> |
||||||
|
|
||||||
|
<Column field="resourceNode.title" :header="$t('Title')" :sortable="true"> |
||||||
|
<template #body="slotProps"> |
||||||
|
<div v-if="slotProps.data && slotProps.data.resourceNode && slotProps.data.resourceNode.resourceFile"> |
||||||
|
<ResourceFileLink :resource="slotProps.data" /> |
||||||
|
</div> |
||||||
|
<div v-else> |
||||||
|
<a |
||||||
|
v-if="slotProps.data" |
||||||
|
@click="handleClick(slotProps.data)" |
||||||
|
class="cursor-pointer " > |
||||||
|
<FontAwesomeIcon |
||||||
|
icon="folder" |
||||||
|
size="lg" |
||||||
|
/> |
||||||
|
{{ slotProps.data.resourceNode.title }} |
||||||
|
</a> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
</Column> |
||||||
|
|
||||||
|
<Column field="resourceNode.resourceFile.size" :header="$t('Size')" :sortable="true"> |
||||||
|
<template #body="slotProps"> |
||||||
|
{{ |
||||||
|
slotProps.data.resourceNode.resourceFile ? $filters.prettyBytes(slotProps.data.resourceNode.resourceFile.size) : '' |
||||||
|
}} |
||||||
|
</template> |
||||||
|
</Column> |
||||||
|
|
||||||
|
<Column field="resourceNode.updatedAt" :header="$t('Modified')" :sortable="true"> |
||||||
|
<template #body="slotProps"> |
||||||
|
{{$luxonDateTime.fromISO(slotProps.data.resourceNode.updatedAt).toRelative() }} |
||||||
|
</template> |
||||||
|
</Column> |
||||||
|
|
||||||
|
<Column :exportable="false"> |
||||||
|
<template #body="slotProps"> |
||||||
|
<div class="flex flex-row gap-2"> |
||||||
|
<Button icon="fa fa-info-circle" class="btn btn-primary " @click="showHandler(slotProps.data)" /> |
||||||
|
<Button v-if="isAuthenticated" icon="pi pi-pencil" class="btn btn-primary p-mr-2" @click="editHandler(slotProps.data)" /> |
||||||
|
<Button v-if="isAuthenticated" icon="pi pi-trash" class="btn btn-danger" @click="confirmDeleteItem(slotProps.data)" /> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
</Column> |
||||||
|
|
||||||
|
<!-- <template #paginatorLeft>--> |
||||||
|
<!-- <Button type="button" icon="pi pi-refresh" class="p-button-text" />--> |
||||||
|
<!-- </template>--> |
||||||
|
<!-- <template #paginatorRight>--> |
||||||
|
<!-- <Button type="button" icon="pi pi-cloud" class="p-button-text" />--> |
||||||
|
<!-- </template>--> |
||||||
|
</DataTable> |
||||||
|
|
||||||
|
<Dialog v-model:visible="itemDialog" :style="{width: '450px'}" :header="$t('New folder')" :modal="true" class="p-fluid"> |
||||||
|
<div class="p-field"> |
||||||
|
<label for="name">{{ $t('Name') }}</label> |
||||||
|
<InputText |
||||||
|
autocomplete="off" |
||||||
|
id="title" |
||||||
|
v-model.trim="item.title" |
||||||
|
required="true" |
||||||
|
autofocus |
||||||
|
:class="{'p-invalid': submitted && !item.title}" |
||||||
|
/> |
||||||
|
<small class="p-error" v-if="submitted && !item.title">$t('Title is required')</small> |
||||||
|
</div> |
||||||
|
|
||||||
|
<template #footer> |
||||||
|
<Button label="Cancel" icon="pi pi-times" class="p-button-text" @click="hideDialog"/> |
||||||
|
<Button label="Save" icon="pi pi-check" class="p-button-text" @click="saveItem" /> |
||||||
|
</template> |
||||||
|
</Dialog> |
||||||
|
|
||||||
|
<Dialog v-model:visible="deleteItemDialog" :style="{width: '450px'}" header="Confirm" :modal="true"> |
||||||
|
<div class="confirmation-content"> |
||||||
|
<i class="pi pi-exclamation-triangle p-mr-3" style="font-size: 2rem" /> |
||||||
|
<span v-if="item">Are you sure you want to delete <b>{{item.title}}</b>?</span> |
||||||
|
</div> |
||||||
|
<template #footer> |
||||||
|
<Button label="No" icon="pi pi-times" class="p-button-text" @click="deleteItemDialog = false"/> |
||||||
|
<Button label="Yes" icon="pi pi-check" class="p-button-text" @click="deleteItemButton" /> |
||||||
|
</template> |
||||||
|
</Dialog> |
||||||
|
|
||||||
|
<Dialog v-model:visible="deleteMultipleDialog" :style="{width: '450px'}" header="Confirm" :modal="true"> |
||||||
|
<div class="confirmation-content"> |
||||||
|
<i class="pi pi-exclamation-triangle p-mr-3" style="font-size: 2rem" /> |
||||||
|
<span v-if="item">Are you sure you want to delete the selected items?</span> |
||||||
|
</div> |
||||||
|
<template #footer> |
||||||
|
<Button label="No" icon="pi pi-times" class="p-button-text" @click="deleteMultipleDialog = false"/> |
||||||
|
<Button label="Yes" icon="pi pi-check" class="p-button-text" @click="deleteMultipleItems" /> |
||||||
|
</template> |
||||||
|
</Dialog> |
||||||
|
|
||||||
|
</template> |
||||||
|
|
||||||
|
<script> |
||||||
|
import { mapActions, mapGetters } from 'vuex'; |
||||||
|
import { mapFields } from 'vuex-map-fields'; |
||||||
|
import ListMixin from '../../mixins/ListMixin'; |
||||||
|
import ActionCell from '../../components/ActionCell.vue'; |
||||||
|
//import Toolbar from '../../components/Toolbar.vue'; |
||||||
|
import ResourceFileIcon from '../../components/documents/ResourceFileIcon.vue'; |
||||||
|
import ResourceFileLink from '../../components/documents/ResourceFileLink.vue'; |
||||||
|
|
||||||
|
import { useRoute } from 'vue-router' |
||||||
|
import DataFilter from '../../components/DataFilter'; |
||||||
|
//import DocumentsFilterForm from '../../components/personalfile/Filter'; |
||||||
|
import { ref, reactive, onMounted, computed } from 'vue'; |
||||||
|
import { useStore } from 'vuex'; |
||||||
|
import isEmpty from 'lodash/isEmpty'; |
||||||
|
import moment from "moment"; |
||||||
|
|
||||||
|
export default { |
||||||
|
name: 'PersonalFileList', |
||||||
|
servicePrefix: 'PersonalFile', |
||||||
|
components: { |
||||||
|
//8Toolbar, |
||||||
|
ActionCell, |
||||||
|
ResourceFileIcon, |
||||||
|
ResourceFileLink, |
||||||
|
//DocumentsFilterForm, |
||||||
|
DataFilter |
||||||
|
}, |
||||||
|
mixins: [ListMixin], |
||||||
|
data() { |
||||||
|
return { |
||||||
|
sortBy: 'title', |
||||||
|
sortDesc: false, |
||||||
|
columnsQua: [ |
||||||
|
{align: 'left', name: 'resourceNode.title', label: this.$i18n.t('Title'), field: 'resourceNode.title', sortable: true}, |
||||||
|
{align: 'left', name: 'resourceNode.updatedAt', label: this.$i18n.t('Modified'), field: 'resourceNode.updatedAt', sortable: true}, |
||||||
|
{name: 'resourceNode.resourceFile.size', label: this.$i18n.t('Size'), field: 'resourceNode.resourceFile.size', sortable: true}, |
||||||
|
{name: 'action', label: this.$i18n.t('Actions'), field: 'action', sortable: false} |
||||||
|
], |
||||||
|
columns: [ |
||||||
|
{ label: this.$i18n.t('Title'), field: 'title', name: 'title', sortable: true}, |
||||||
|
{ label: this.$i18n.t('Modified'), field: 'resourceNode.updatedAt', name: 'updatedAt', sortable: true}, |
||||||
|
{ label: this.$i18n.t('Size'), field: 'resourceNode.resourceFile.size', name: 'size', sortable: true}, |
||||||
|
{ label: this.$i18n.t('Actions'), name: 'action', sortable: false} |
||||||
|
], |
||||||
|
pageOptions: [10, 20, 50, this.$i18n.t('All')], |
||||||
|
selected: [], |
||||||
|
isBusy: false, |
||||||
|
options: [], |
||||||
|
selectedItems: [], |
||||||
|
// prime vue |
||||||
|
itemDialog: false, |
||||||
|
deleteItemDialog: false, |
||||||
|
deleteMultipleDialog: false, |
||||||
|
item: {}, |
||||||
|
filters: {}, |
||||||
|
submitted: false, |
||||||
|
}; |
||||||
|
}, |
||||||
|
created() { |
||||||
|
console.log('CREATED'); |
||||||
|
let resourceNodeId = this.currentUser.resourceNode['id']; |
||||||
|
if (isEmpty(this.$route.params.node)) { |
||||||
|
this.$route.params.node = resourceNodeId; |
||||||
|
} |
||||||
|
//this.item.parentResourceNodeId = this.$route.params.node; |
||||||
|
this.filters['resourceNode.parent'] = resourceNodeId; |
||||||
|
}, |
||||||
|
mounted() { |
||||||
|
const route = useRoute() |
||||||
|
/*let nodeId = route.params['node']; |
||||||
|
if (!isEmpty(nodeId)) { |
||||||
|
this.findResourceNode('/api/resource_nodes/' + nodeId); |
||||||
|
}*/ |
||||||
|
console.log(this.options); |
||||||
|
this.onUpdateOptions(this.options); |
||||||
|
}, |
||||||
|
computed: { |
||||||
|
// From crud.js list function |
||||||
|
...mapGetters('resourcenode', { |
||||||
|
resourceNode: 'getResourceNode' |
||||||
|
}), |
||||||
|
...mapGetters({ |
||||||
|
'isAuthenticated': 'security/isAuthenticated', |
||||||
|
'isAdmin': 'security/isAdmin', |
||||||
|
'currentUser': 'security/getUser', |
||||||
|
}), |
||||||
|
|
||||||
|
...mapGetters('personalfile', { |
||||||
|
items: 'list', |
||||||
|
}), |
||||||
|
|
||||||
|
//...getters |
||||||
|
|
||||||
|
// From ListMixin |
||||||
|
...mapFields('personalfile', { |
||||||
|
deletedItem: 'deleted', |
||||||
|
error: 'error', |
||||||
|
isLoading: 'isLoading', |
||||||
|
resetList: 'resetList', |
||||||
|
totalItems: 'totalItems', |
||||||
|
view: 'view' |
||||||
|
}), |
||||||
|
}, |
||||||
|
methods: { |
||||||
|
// prime |
||||||
|
onPage(event) { |
||||||
|
console.log(event); |
||||||
|
console.log(event.page); |
||||||
|
console.log(event.sortField); |
||||||
|
console.log(event.sortOrder); |
||||||
|
|
||||||
|
this.options.itemsPerPage = event.rows; |
||||||
|
this.options.page = event.page + 1; |
||||||
|
this.options.sortBy = event.sortField; |
||||||
|
this.options.sortDesc = event.sortOrder === -1; |
||||||
|
|
||||||
|
this.onUpdateOptions(this.options); |
||||||
|
}, |
||||||
|
sortingChanged(event) { |
||||||
|
console.log('sortingChanged'); |
||||||
|
console.log(event); |
||||||
|
this.options.sortBy = event.sortField; |
||||||
|
this.options.sortDesc = event.sortOrder === -1; |
||||||
|
|
||||||
|
this.onUpdateOptions(this.options); |
||||||
|
// ctx.sortBy ==> Field key for sorting by (or null for no sorting) |
||||||
|
// ctx.sortDesc ==> true if sorting descending, false otherwise |
||||||
|
}, |
||||||
|
|
||||||
|
openNew() { |
||||||
|
this.item = {}; |
||||||
|
this.submitted = false; |
||||||
|
this.itemDialog = true; |
||||||
|
}, |
||||||
|
hideDialog() { |
||||||
|
this.itemDialog = false; |
||||||
|
this.submitted = false; |
||||||
|
}, |
||||||
|
saveItem() { |
||||||
|
this.submitted = true; |
||||||
|
|
||||||
|
if (this.item.title.trim()) { |
||||||
|
if (this.item.id) { |
||||||
|
} else { |
||||||
|
let resourceNodeId = this.currentUser.resourceNode['id']; |
||||||
|
if (!isEmpty(this.$route.params.node)) { |
||||||
|
resourceNodeId = this.$route.params.node; |
||||||
|
} |
||||||
|
|
||||||
|
this.item.parentResourceNodeId = resourceNodeId; |
||||||
|
this.item.resourceLinkList = JSON.stringify([{ |
||||||
|
gid: 0, |
||||||
|
sid: 0, |
||||||
|
c_id: 0, |
||||||
|
visibility: 2, // visible by default |
||||||
|
}]); |
||||||
|
|
||||||
|
this.create(this.item); |
||||||
|
this.showMessage('Saved'); |
||||||
|
} |
||||||
|
|
||||||
|
this.itemDialog = false; |
||||||
|
this.item = {}; |
||||||
|
} |
||||||
|
}, |
||||||
|
editItem(item) { |
||||||
|
this.item = {...item}; |
||||||
|
this.itemDialog = true; |
||||||
|
}, |
||||||
|
confirmDeleteItem(item) { |
||||||
|
this.item = item; |
||||||
|
this.deleteItemDialog = true; |
||||||
|
}, |
||||||
|
confirmDeleteMultiple() { |
||||||
|
this.deleteMultipleDialog = true; |
||||||
|
}, |
||||||
|
deleteMultipleItems() { |
||||||
|
console.log('deleteMultipleItems'); |
||||||
|
console.log(this.selectedItems); |
||||||
|
this.deleteMultipleAction(this.selectedItems); |
||||||
|
this.onRequest({ |
||||||
|
pagination: this.pagination, |
||||||
|
}); |
||||||
|
this.deleteMultipleDialog = false; |
||||||
|
this.selectedItems = null; |
||||||
|
//this.$toast.add({severity:'success', summary: 'Successful', detail: 'Products Deleted', life: 3000});*/ |
||||||
|
}, |
||||||
|
deleteItemButton() { |
||||||
|
console.log('deleteItem'); |
||||||
|
this.deleteItem(this.item); |
||||||
|
//this.items = this.items.filter(val => val.iid !== this.item.iid); |
||||||
|
this.deleteItemDialog = false; |
||||||
|
this.item = {}; |
||||||
|
this.onUpdateOptions(this.options); |
||||||
|
}, |
||||||
|
onRowSelected(items) { |
||||||
|
this.selected = items |
||||||
|
}, |
||||||
|
selectAllRows() { |
||||||
|
this.$refs.selectableTable.selectAllRows() |
||||||
|
}, |
||||||
|
clearSelected() { |
||||||
|
this.$refs.selectableTable.clearSelected() |
||||||
|
}, |
||||||
|
async deleteSelected() { |
||||||
|
console.log('deleteSelected'); |
||||||
|
/*for (let i = 0; i < this.selected.length; i++) { |
||||||
|
let item = this.selected[i]; |
||||||
|
//this.deleteHandler(item); |
||||||
|
this.deleteItem(item); |
||||||
|
}*/ |
||||||
|
|
||||||
|
this.deleteMultipleAction(this.selected); |
||||||
|
this.onRequest({ |
||||||
|
pagination: this.pagination, |
||||||
|
}); |
||||||
|
console.log('end -- deleteSelected'); |
||||||
|
}, |
||||||
|
//...actions, |
||||||
|
// From ListMixin |
||||||
|
...mapActions('personalfile', { |
||||||
|
getPage: 'fetchAll', |
||||||
|
create: 'create', |
||||||
|
deleteItem: 'del', |
||||||
|
deleteMultipleAction: 'delMultiple' |
||||||
|
}), |
||||||
|
...mapActions('resourcenode', { |
||||||
|
findResourceNode: 'findResourceNode', |
||||||
|
}), |
||||||
|
} |
||||||
|
}; |
||||||
|
</script> |
@ -0,0 +1,193 @@ |
|||||||
|
<template> |
||||||
|
<div> |
||||||
|
<Toolbar |
||||||
|
v-if="item && isCurrentTeacher" |
||||||
|
:handle-edit="editHandler" |
||||||
|
:handle-delete="del" |
||||||
|
> |
||||||
|
<template slot="left"> |
||||||
|
<!-- <v-toolbar-title v-if="item">--> |
||||||
|
<!-- {{--> |
||||||
|
<!-- `${$options.servicePrefix} ${item['@id']}`--> |
||||||
|
<!-- }}--> |
||||||
|
<!-- </v-toolbar-title>--> |
||||||
|
</template> |
||||||
|
</Toolbar> |
||||||
|
|
||||||
|
<p class="text-lg" v-if="item"> |
||||||
|
{{ item['title'] }} |
||||||
|
</p> |
||||||
|
|
||||||
|
<div v-if="item" class="flex flex-row"> |
||||||
|
<div class="w-1/2"> |
||||||
|
<div class ="flex justify-center" v-if="item['resourceNode']['resourceFile']"> |
||||||
|
<div class="w-64"> |
||||||
|
<q-img |
||||||
|
spinner-color="primary" |
||||||
|
v-if="item['resourceNode']['resourceFile']['image']" |
||||||
|
:src="item['contentUrl'] + '&w=300'" |
||||||
|
/> |
||||||
|
<span v-else-if="item['resourceNode']['resourceFile']['video']"> |
||||||
|
<video controls> |
||||||
|
<source :src="item['contentUrl']" /> |
||||||
|
</video> |
||||||
|
</span> |
||||||
|
<span v-else> |
||||||
|
<q-btn |
||||||
|
class="btn btn-primary" |
||||||
|
:to="item['downloadUrl']" |
||||||
|
> |
||||||
|
<FontAwesomeIcon icon="file-download" /> |
||||||
|
{{ $t('Download file') }} |
||||||
|
</q-btn> |
||||||
|
</span> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
<div class ="flex justify-center" v-else> |
||||||
|
<FontAwesomeIcon |
||||||
|
icon="folder" |
||||||
|
size="7x" |
||||||
|
/> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
|
||||||
|
<span class="w-1/2"> |
||||||
|
<q-markup-table> |
||||||
|
<tbody> |
||||||
|
<tr> |
||||||
|
<td><strong>{{ $t('Author') }}</strong></td> |
||||||
|
<td> |
||||||
|
{{ item['resourceNode'].creator.username }} |
||||||
|
</td> |
||||||
|
<td></td> |
||||||
|
<td /> |
||||||
|
</tr> |
||||||
|
<tr> |
||||||
|
<td><strong>{{ $t('Comment') }}</strong></td> |
||||||
|
<td> |
||||||
|
{{ item['comment'] }} |
||||||
|
</td> |
||||||
|
</tr> |
||||||
|
<tr> |
||||||
|
<td><strong>{{ $t('Created at') }}</strong></td> |
||||||
|
<td> |
||||||
|
{{ item['resourceNode'] ? $luxonDateTime.fromISO(item['resourceNode'].createdAt).toRelative() : ''}} |
||||||
|
</td> |
||||||
|
<td /> |
||||||
|
</tr> |
||||||
|
<tr> |
||||||
|
<td><strong>{{ $t('Updated at') }}</strong></td> |
||||||
|
<td> |
||||||
|
{{ item['resourceNode'] ? $luxonDateTime.fromISO(item['resourceNode'].updatedAt).toRelative() : ''}} |
||||||
|
</td> |
||||||
|
<td /> |
||||||
|
</tr> |
||||||
|
<tr v-if="item['resourceNode']['resourceFile']"> |
||||||
|
<td><strong>{{ $t('File') }}</strong></td> |
||||||
|
<td> |
||||||
|
<div> |
||||||
|
<a |
||||||
|
class="btn btn-primary" |
||||||
|
:href="item['downloadUrl']" |
||||||
|
> |
||||||
|
<FontAwesomeIcon icon="file-download" /> |
||||||
|
{{ $t('Download file') }} |
||||||
|
</a> |
||||||
|
</div> |
||||||
|
</td> |
||||||
|
<td /> |
||||||
|
</tr> |
||||||
|
</tbody> |
||||||
|
</q-markup-table> |
||||||
|
|
||||||
|
<hr /> |
||||||
|
|
||||||
|
<span v-if="item['resourceLinkListFromEntity']"> |
||||||
|
<h2>{{ $t('Shared') }}</h2> |
||||||
|
<span |
||||||
|
v-for="link in item['resourceLinkListFromEntity']" |
||||||
|
> |
||||||
|
<q-markup-table> |
||||||
|
<tbody> |
||||||
|
<tr> |
||||||
|
<td> |
||||||
|
{{ $t('Status') }} |
||||||
|
</td> |
||||||
|
<td> |
||||||
|
{{ link.visibilityName }} |
||||||
|
</td> |
||||||
|
</tr> |
||||||
|
|
||||||
|
<tr v-if="link['course']"> |
||||||
|
<td> |
||||||
|
{{ $t('Course') }} |
||||||
|
</td> |
||||||
|
<td> |
||||||
|
{{ link.course.resourceNode.title }} |
||||||
|
</td> |
||||||
|
</tr> |
||||||
|
|
||||||
|
<tr v-if="link['session']"> |
||||||
|
<td> |
||||||
|
{{ $t('Session') }} |
||||||
|
</td> |
||||||
|
<td> |
||||||
|
{{ link.session.name }} |
||||||
|
</td> |
||||||
|
</tr> |
||||||
|
|
||||||
|
<tr v-if="link['group']"> |
||||||
|
<td> |
||||||
|
{{ $t('Group') }} |
||||||
|
</td> |
||||||
|
<td> |
||||||
|
{{ link.group.resourceNode.title }} |
||||||
|
</td> |
||||||
|
</tr> |
||||||
|
</tbody> |
||||||
|
</q-markup-table> |
||||||
|
</span> |
||||||
|
</span> |
||||||
|
</span> |
||||||
|
</div> |
||||||
|
|
||||||
|
<Loading :visible="isLoading" /> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script> |
||||||
|
import { mapActions, mapGetters } from 'vuex'; |
||||||
|
import { mapFields } from 'vuex-map-fields'; |
||||||
|
import Loading from '../../components/Loading.vue'; |
||||||
|
import ShowMixin from '../../mixins/ShowMixin'; |
||||||
|
import Toolbar from '../../components/Toolbar.vue'; |
||||||
|
const servicePrefix = 'PersonalFile'; |
||||||
|
|
||||||
|
export default { |
||||||
|
name: 'PersonalFileShow', |
||||||
|
components: { |
||||||
|
Loading, |
||||||
|
Toolbar |
||||||
|
}, |
||||||
|
mixins: [ShowMixin], |
||||||
|
computed: { |
||||||
|
...mapFields('personalfile', { |
||||||
|
isLoading: 'isLoading' |
||||||
|
}), |
||||||
|
...mapGetters('personalfile', ['find']), |
||||||
|
...mapGetters({ |
||||||
|
'isAuthenticated': 'security/isAuthenticated', |
||||||
|
'isAdmin': 'security/isAdmin', |
||||||
|
'isCurrentTeacher': 'security/isCurrentTeacher', |
||||||
|
}), |
||||||
|
}, |
||||||
|
methods: { |
||||||
|
...mapActions('personalfile', { |
||||||
|
deleteItem: 'del', |
||||||
|
reset: 'resetShow', |
||||||
|
retrieve: 'loadWithQuery' |
||||||
|
}), |
||||||
|
}, |
||||||
|
servicePrefix |
||||||
|
}; |
||||||
|
</script> |
@ -0,0 +1,68 @@ |
|||||||
|
<template> |
||||||
|
<div v-if="!isLoading && item && isCurrentTeacher"> |
||||||
|
<!-- :handle-delete="del"--> |
||||||
|
<Toolbar |
||||||
|
:handle-submit="onSendForm" |
||||||
|
:handle-reset="resetForm" |
||||||
|
/> |
||||||
|
<DocumentsForm |
||||||
|
ref="updateForm" |
||||||
|
:values="item" |
||||||
|
:errors="violations" |
||||||
|
> |
||||||
|
<ResourceLinkForm |
||||||
|
v-if="item && !isLoading" |
||||||
|
ref="resourceLinkForm" |
||||||
|
:values="item" |
||||||
|
/> |
||||||
|
</DocumentsForm> |
||||||
|
<Loading :visible="isLoading || deleteLoading" /> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script> |
||||||
|
import { mapActions, mapGetters } from 'vuex'; |
||||||
|
import { mapFields } from 'vuex-map-fields'; |
||||||
|
import DocumentsForm from '../../components/personalfile/Form.vue'; |
||||||
|
import ResourceLinkForm from '../../components/personalfile/ResourceLinkForm.vue'; |
||||||
|
import Loading from '../../components/Loading.vue'; |
||||||
|
import Toolbar from '../../components/Toolbar.vue'; |
||||||
|
import UpdateMixin from '../../mixins/UpdateMixin'; |
||||||
|
|
||||||
|
const servicePrefix = 'PersonalFile'; |
||||||
|
|
||||||
|
export default { |
||||||
|
name: 'PersonalFileUpdate', |
||||||
|
servicePrefix, |
||||||
|
components: { |
||||||
|
Loading, |
||||||
|
Toolbar, |
||||||
|
DocumentsForm, |
||||||
|
ResourceLinkForm |
||||||
|
}, |
||||||
|
mixins: [UpdateMixin], |
||||||
|
computed: { |
||||||
|
...mapFields('personalfile', { |
||||||
|
deleteLoading: 'isLoading', |
||||||
|
isLoading: 'isLoading', |
||||||
|
error: 'error', |
||||||
|
updated: 'updated', |
||||||
|
violations: 'violations' |
||||||
|
}), |
||||||
|
...mapGetters('personalfile', ['find']), |
||||||
|
...mapGetters({ |
||||||
|
'isCurrentTeacher': 'security/isCurrentTeacher', |
||||||
|
}), |
||||||
|
}, |
||||||
|
methods: { |
||||||
|
...mapActions('personalfile', { |
||||||
|
createReset: 'resetCreate', |
||||||
|
deleteItem: 'del', |
||||||
|
delReset: 'resetDelete', |
||||||
|
retrieve: 'load', |
||||||
|
update: 'update', |
||||||
|
updateReset: 'resetUpdate' |
||||||
|
}) |
||||||
|
} |
||||||
|
}; |
||||||
|
</script> |
@ -0,0 +1,138 @@ |
|||||||
|
<template> |
||||||
|
<div> |
||||||
|
<DocumentsForm |
||||||
|
ref="createForm" |
||||||
|
:values="files" |
||||||
|
:parentResourceNodeId="parentResourceNodeId" |
||||||
|
:resourceLinkList="resourceLinkList" |
||||||
|
:errors="violations" |
||||||
|
:process-files="processFiles" |
||||||
|
/> |
||||||
|
|
||||||
|
<Toolbar |
||||||
|
:handle-submit="onUploadForm" |
||||||
|
/> |
||||||
|
<Loading :visible="isLoading" /> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script> |
||||||
|
import {mapActions, mapGetters} from 'vuex'; |
||||||
|
import { createHelpers } from 'vuex-map-fields'; |
||||||
|
import DocumentsForm from '../../components/personalfile/FormUpload.vue'; |
||||||
|
import Loading from '../../components/Loading.vue'; |
||||||
|
import Toolbar from '../../components/Toolbar.vue'; |
||||||
|
import UploadMixin from '../../mixins/UploadMixin'; |
||||||
|
import { ref, onMounted } from 'vue' |
||||||
|
import isEmpty from 'lodash/isEmpty'; |
||||||
|
|
||||||
|
const servicePrefix = 'PersonalFile'; |
||||||
|
|
||||||
|
const { mapFields } = createHelpers({ |
||||||
|
getterType: 'personalfile/getField', |
||||||
|
mutationType: 'personalfile/updateField' |
||||||
|
}); |
||||||
|
|
||||||
|
export default { |
||||||
|
name: 'PersonalFileUploadFile', |
||||||
|
servicePrefix, |
||||||
|
components: { |
||||||
|
Loading, |
||||||
|
Toolbar, |
||||||
|
DocumentsForm |
||||||
|
}, |
||||||
|
setup() { |
||||||
|
const createForm = ref(null); |
||||||
|
|
||||||
|
return { |
||||||
|
createForm |
||||||
|
} |
||||||
|
}, |
||||||
|
mixins: [UploadMixin], |
||||||
|
data() { |
||||||
|
return { |
||||||
|
files : [], |
||||||
|
parentResourceNodeId: 0, |
||||||
|
resourceLinkList: '', |
||||||
|
}; |
||||||
|
}, |
||||||
|
computed: { |
||||||
|
...mapFields(['error', 'isLoading', 'created', 'violations']), |
||||||
|
...mapGetters({ |
||||||
|
'isAuthenticated': 'security/isAuthenticated', |
||||||
|
'isAdmin': 'security/isAdmin', |
||||||
|
'currentUser': 'security/getUser', |
||||||
|
}), |
||||||
|
}, |
||||||
|
created() { |
||||||
|
console.log('created'); |
||||||
|
let nodeId = this.$route.params.node; |
||||||
|
if (isEmpty(nodeId)) { |
||||||
|
nodeId = this.currentUser.resourceNode['id'] |
||||||
|
} |
||||||
|
|
||||||
|
console.log(nodeId) |
||||||
|
this.parentResourceNodeId = Number(nodeId); |
||||||
|
this.resourceLinkList = JSON.stringify([{ |
||||||
|
gid: this.$route.query.gid, |
||||||
|
sid: this.$route.query.sid, |
||||||
|
c_id: this.$route.query.cid, |
||||||
|
visibility: 2, |
||||||
|
}]); |
||||||
|
this.files = []; |
||||||
|
}, |
||||||
|
methods: { |
||||||
|
async processFiles(files) { |
||||||
|
/*this.files = [ |
||||||
|
...this.files, |
||||||
|
...map(files, file => ({ |
||||||
|
title: file.name, |
||||||
|
name: file.name, |
||||||
|
size: file.size, |
||||||
|
type: file.type, |
||||||
|
filetype: 'file', |
||||||
|
parentResourceNodeId: this.parentResourceNodeId, |
||||||
|
resourceLinkList: this.resourceLinkList, |
||||||
|
uploadFile: file, |
||||||
|
invalidMessage: this.validate(file), |
||||||
|
})) |
||||||
|
];*/ |
||||||
|
|
||||||
|
return new Promise((resolve) => { |
||||||
|
for (let i = 0; i < files.length; i++) { |
||||||
|
files[i].title = files[i].name; |
||||||
|
files[i].parentResourceNodeId = this.parentResourceNodeId; |
||||||
|
files[i].resourceLinkList = this.resourceLinkList; |
||||||
|
files[i].uploadFile = files[i]; |
||||||
|
this.createFile(files[i]); |
||||||
|
} |
||||||
|
|
||||||
|
resolve(files); |
||||||
|
/*console.log(file); |
||||||
|
file.title = file.name; |
||||||
|
file.parentResourceNodeId = this.parentResourceNodeId; |
||||||
|
file.resourceLinkList = this.resourceLinkList; |
||||||
|
file.uploadFile = file; |
||||||
|
this.create(file); |
||||||
|
resolve(file);*/ |
||||||
|
|
||||||
|
|
||||||
|
/*for (let i = 0; i < this.files.length; i++) { |
||||||
|
this.create(this.files[i]); |
||||||
|
} |
||||||
|
resolve(true);*/ |
||||||
|
}).then(() => { |
||||||
|
this.files = []; |
||||||
|
}); |
||||||
|
}, |
||||||
|
validate(file) { |
||||||
|
if (file) { |
||||||
|
return ''; |
||||||
|
} |
||||||
|
|
||||||
|
return 'error'; |
||||||
|
}, |
||||||
|
...mapActions('personalfile', ['uploadMany', 'create', 'createFile']) |
||||||
|
} |
||||||
|
}; |
||||||
|
</script> |
@ -0,0 +1,23 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
declare(strict_types=1); |
||||||
|
|
||||||
|
/* For licensing terms, see /license.txt */ |
||||||
|
|
||||||
|
namespace Chamilo\CoreBundle\Controller\Api; |
||||||
|
|
||||||
|
use Chamilo\CoreBundle\Entity\PersonalFile; |
||||||
|
use Symfony\Component\HttpFoundation\Request; |
||||||
|
|
||||||
|
class CreatePersonalFileAction extends BaseResourceFileAction |
||||||
|
{ |
||||||
|
public function __invoke(Request $request): PersonalFile |
||||||
|
{ |
||||||
|
error_log('CreatePersonalFileAction __invoke'); |
||||||
|
|
||||||
|
$document = new PersonalFile(); |
||||||
|
$this->handleCreateRequest($document, $request); |
||||||
|
|
||||||
|
return $document; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,25 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
declare(strict_types=1); |
||||||
|
|
||||||
|
/* For licensing terms, see /license.txt */ |
||||||
|
|
||||||
|
namespace Chamilo\CoreBundle\Controller\Api; |
||||||
|
|
||||||
|
use Chamilo\CoreBundle\Entity\PersonalFile; |
||||||
|
use Chamilo\CourseBundle\Repository\CDocumentRepository; |
||||||
|
use Symfony\Component\HttpFoundation\Request; |
||||||
|
|
||||||
|
class UpdatePersonalFileAction extends BaseResourceFileAction |
||||||
|
{ |
||||||
|
public function __invoke(PersonalFile $document, Request $request, CDocumentRepository $repo): PersonalFile |
||||||
|
{ |
||||||
|
error_log('UpdatePersonalFileAction __invoke'); |
||||||
|
|
||||||
|
$this->handleUpdateRequest($document, $repo, $request); |
||||||
|
|
||||||
|
error_log('Finish update resource node file action'); |
||||||
|
|
||||||
|
return $document; |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue