Add file creation and file upload from ckeditor

pull/3346/head
Julio Montoya 5 years ago
parent 95d679d00b
commit 83f4f457c0
  1. 4
      assets/vue/App.vue
  2. 2
      assets/vue/components/Toolbar.vue
  3. 36
      assets/vue/components/documents/FormNewDocument.vue
  4. 105
      assets/vue/components/documents/UploadAdapter.js
  5. 5
      assets/vue/main.js
  6. 4
      package.json
  7. 5
      webpack.config.js
  8. 72
      yarn.lock

@ -274,12 +274,12 @@
</div>
</v-app-bar>
<v-content>
<v-main>
<Breadcrumb layout-class="pl-3 py-3"/>
<router-view></router-view>
<div id="legacy_content" v-html="legacy_content">
</div>
</v-content>
</v-main>
<v-footer color="indigo" app>
<span class="white--text">&copy; 2020</span>

@ -53,7 +53,7 @@
</v-btn>
<v-btn v-if="handleAddDocument" color="primary" rounded @click="addDocument">
<v-icon left>mdi-cloud-upload</v-icon>New document
<v-icon left>mdi-file-plus-outline</v-icon>New document
</v-btn>
<v-btn v-if="handleUploadDocument" color="primary" rounded @click="uploadDocument">

@ -11,23 +11,35 @@
@input="$v.item.title.$touch()"
@blur="$v.item.title.$touch()"
/>
<v-textarea
v-model="item.content"
:label="$t('Text')"
value=""
></v-textarea>
<ckeditor :editor="editor" v-model="item.content" :config="editorConfig">
</ckeditor>
<!-- <v-textarea-->
<!-- v-model="item.content"-->
<!-- :label="$t('Text')"-->
<!-- value=""-->
<!-- ></v-textarea>-->
</v-col>
</v-row>
</v-container>
</v-form>
</template>
<style>
.ck-editor__editable {
min-height: 400px;
}
</style>
<script>
import has from 'lodash/has';
import { validationMixin } from 'vuelidate';
import { required } from 'vuelidate/lib/validators';
import { mapActions } from 'vuex';
import { mapFields } from 'vuex-map-fields';
import ClassicEditor from '@ckeditor/ckeditor5-build-classic';
import UploadAdapter from './UploadAdapter';
export default {
name: 'DocumentsForm',
@ -53,6 +65,14 @@ export default {
title: null,
content: null,
parentResourceNodeId: null,
editor: ClassicEditor,
//editor:decoupleEditor,
editorData: '',
editorConfig: {
allowedContent: true,
extraPlugins: [this.uploader],
// The configuration of the rich-text editor.
}
};
},
computed: {
@ -83,6 +103,12 @@ export default {
}
},
methods: {
uploader(editor)
{
editor.plugins.get( 'FileRepository' ).createUploadAdapter = ( loader ) => {
return new UploadAdapter( loader );
};
},
},
validations: {
item: {

@ -0,0 +1,105 @@
import { ENTRYPOINT } from '../../config/entrypoint';
// From
// https://ckeditor.com/docs/ckeditor5/latest/framework/guides/deep-dive/upload-adapter.html
export default class MyUploadAdapter {
constructor( loader ) {
// The file loader instance to use during the upload.
this.loader = loader;
}
// Starts the upload process.
upload() {
return this.loader.file
.then( file => new Promise( ( resolve, reject ) => {
this._initRequest();
this._initListeners( resolve, reject, file );
this._sendRequest( file );
} ) );
}
// Aborts the upload process.
abort() {
if ( this.xhr ) {
this.xhr.abort();
}
}
// Initializes the XMLHttpRequest object using the URL passed to the constructor.
_initRequest() {
const xhr = this.xhr = new XMLHttpRequest();
// Note that your request may look different. It is up to you and your editor
// integration to choose the right communication channel. This example uses
// a POST request with JSON as a data structure but your configuration
// could be different.
xhr.open( 'POST', ENTRYPOINT + 'documents', true );
xhr.responseType = 'json';
}
// Initializes XMLHttpRequest listeners.
_initListeners( resolve, reject, file ) {
const xhr = this.xhr;
const loader = this.loader;
const genericErrorText = `Couldn't upload file: ${ file.name }.`;
xhr.addEventListener( 'error', () => reject( genericErrorText ) );
xhr.addEventListener( 'abort', () => reject() );
xhr.addEventListener( 'load', () => {
const response = xhr.response;
// This example assumes the XHR server's "response" object will come with
// an "error" which has its own "message" that can be passed to reject()
// in the upload promise.
//
// Your integration may handle upload errors in a different way so make sure
// it is done properly. The reject() function must be called when the upload fails.
if ( !response || response.error ) {
return reject( response && response.error ? response.error.message : genericErrorText );
}
// If the upload is successful, resolve the upload promise with an object containing
// at least the "default" URL, pointing to the image on the server.
// This URL will be used to display the image in the content. Learn more in the
// UploadAdapter#upload documentation.
resolve( {
//default: response.url
default: response.contentUrl
} );
} );
// Upload progress when it is supported. The file loader has the #uploadTotal and #uploaded
// properties which are used e.g. to display the upload progress bar in the editor
// user interface.
if ( xhr.upload ) {
xhr.upload.addEventListener( 'progress', evt => {
if ( evt.lengthComputable ) {
loader.uploadTotal = evt.total;
loader.uploaded = evt.loaded;
}
} );
}
}
// Prepares the data and sends the request.
_sendRequest( file ) {
// Prepare the form data.
const data = new FormData();
// Chamilo
data.append('filetype', 'file');
data.append('parentResourceNodeId', '4');
data.append('resourceLinkList', '{"c_id": 1, "visibility":2}');
data.append('uploadFile', file);
//data.append( 'upload', file );
// Important note: This is the right place to implement security mechanisms
// like authentication and CSRF protection. For instance, you can use
// XMLHttpRequest.setRequestHeader() to set the request headers containing
// the CSRF token generated earlier by your application.
// Send the request.
this.xhr.send( data );
}
}

@ -9,7 +9,7 @@ import resourceLinkService from './services/resourcelink';
import makeCrudModule from './store/modules/crud';
import vuetify from './plugins/vuetify' // path to vuetify export
require('@fancyapps/fancybox');
require ('@fancyapps/fancybox/dist/jquery.fancybox.css');
require('@fancyapps/fancybox/dist/jquery.fancybox.css');
import VueApollo from 'vue-apollo';
import Vuelidate from 'vuelidate';
import i18n from './i18n';
@ -25,6 +25,9 @@ Vue.use(Vuelidate);
Vue.use(VueApollo);
Vue.use(require('vue-moment'));
import CKEditor from '@ckeditor/ckeditor5-vue';
Vue.use(CKEditor);
const apolloProvider = new VueApollo({
defaultClient: apolloClient,
});

@ -6,6 +6,10 @@
"dependencies": {
"@babel/plugin-transform-runtime": "^7.9.6",
"@babel/runtime": "^7.9.6",
"@ckeditor/ckeditor5-build-classic": "^19.0.2",
"@ckeditor/ckeditor5-build-decoupled-document": "^19.0.2",
"@ckeditor/ckeditor5-upload": "^19.0.1",
"@ckeditor/ckeditor5-vue": "^1.0.1",
"@fancyapps/fancybox": "^3.5.7",
"apollo-boost": "^0.4.7",
"axios": "^0.19.2",

@ -75,12 +75,13 @@ Encore
from: './node_modules/js-cookie/src/',
pattern: /(js.cookie.js)$/,
to: 'libs/js-cookie/src/js.cookie.js'
},
}
/*,
{
from: './node_modules/mathjax/',
pattern: /(MathJax.js)$/,
to: 'libs/mathjax/MathJax.js'
},
},*/
])
// define the environment variables
.configureDefinePlugin(options => {

@ -822,6 +822,63 @@
lodash "^4.17.13"
to-fast-properties "^2.0.0"
"@ckeditor/ckeditor5-build-classic@^19.0.2":
version "19.0.2"
resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor5-build-classic/-/ckeditor5-build-classic-19.0.2.tgz#ecab0e38d3f6fa7560f6937d18f711243b20b978"
integrity sha512-yz2M9Q6jMy9zF+JiQiSoaG/m7Eu48H+Yi3FgtVGDFpLDqGUJntNsW26g3qZld5Pa4pgVPRmDcfKHzLTWAo3iRg==
"@ckeditor/ckeditor5-build-decoupled-document@^19.0.2":
version "19.0.2"
resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor5-build-decoupled-document/-/ckeditor5-build-decoupled-document-19.0.2.tgz#244efd07836e6a728ef73ce4837367e08684e901"
integrity sha512-fz33Gj9PjkadmotufWU2sN0121v1XyxhhA0OClDN4j9+d+TLt12AGflVyjXIva+/ATO/mdy5xeDWWYYXTEIrfw==
"@ckeditor/ckeditor5-core@^19.0.1":
version "19.0.1"
resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor5-core/-/ckeditor5-core-19.0.1.tgz#becf3723c69f96bcaf35880530a5cc986e145020"
integrity sha512-HKuJp7XEmg8q6o8T2pIUCQDxLlgx2vtweJeDpgreLrX4IqreE0UQtz+TUyxvtlay55UhVpBP4zrnROxrq4Prng==
dependencies:
"@ckeditor/ckeditor5-engine" "^19.0.1"
"@ckeditor/ckeditor5-utils" "^19.0.1"
lodash-es "^4.17.10"
"@ckeditor/ckeditor5-engine@^19.0.1":
version "19.0.1"
resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor5-engine/-/ckeditor5-engine-19.0.1.tgz#0c23e0d52e1468c14e66a4bcdfb3bde6d12dccf6"
integrity sha512-dBE4bSpQzGhoyZaWdDaUJyWG0ltCmpXVkv5YG/x+4s+n3vJf9KKEQcXvj/XPCrMqLaWGKTNugKYfQIEJdOzTZA==
dependencies:
"@ckeditor/ckeditor5-utils" "^19.0.1"
lodash-es "^4.17.10"
"@ckeditor/ckeditor5-ui@^19.0.1":
version "19.0.1"
resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor5-ui/-/ckeditor5-ui-19.0.1.tgz#2c1ce11e1fda5acd726cb492ffeca4dc030d82c4"
integrity sha512-b5WpNmR75NeZ/5CxXWarYUAaomcoflQVjD8M0JHppJKMrBpfuaogRXIRiqsCq+d4mUKzkrEzBcGElI2MObE5dw==
dependencies:
"@ckeditor/ckeditor5-core" "^19.0.1"
"@ckeditor/ckeditor5-utils" "^19.0.1"
lodash-es "^4.17.10"
"@ckeditor/ckeditor5-upload@^19.0.1":
version "19.0.1"
resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor5-upload/-/ckeditor5-upload-19.0.1.tgz#6a8dcd8783a8824f1d7398216a98cc0a177c9ff7"
integrity sha512-MqxP/KENO8fNUNuK5dXpfk8BSRHYi8OaNS7TYtffX6e2mhlY/Dv15zJWY7XibHEx6+UeRyhZsZ3e4nJM69faAA==
dependencies:
"@ckeditor/ckeditor5-core" "^19.0.1"
"@ckeditor/ckeditor5-ui" "^19.0.1"
"@ckeditor/ckeditor5-utils" "^19.0.1"
"@ckeditor/ckeditor5-utils@^19.0.1":
version "19.0.2"
resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor5-utils/-/ckeditor5-utils-19.0.2.tgz#72e0abf31352b74f659d29972030f89d09334e9e"
integrity sha512-ZpoCbuyzujERC5WIjT5obrUyo9m4IoAEOgTxiKOyv9Cy8IGrcW1mG01111iwY/j2pWio0rY0kGRIsQaxqcZ+Ag==
dependencies:
lodash-es "^4.17.10"
"@ckeditor/ckeditor5-vue@^1.0.1":
version "1.0.1"
resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor5-vue/-/ckeditor5-vue-1.0.1.tgz#cddb99609f61b647214b704656c08a15b6a53865"
integrity sha512-4MaQwZ04cWwqYW0732sg2aqx9ILeHIP0LSLKUuLCLR21qYONZPvxY/V/czh1DH99toaL/iwPvEoJtO2ldriPaA==
"@coreui/coreui-plugin-npm-postinstall@^1.0.2":
version "1.0.2"
resolved "https://registry.yarnpkg.com/@coreui/coreui-plugin-npm-postinstall/-/coreui-plugin-npm-postinstall-1.0.2.tgz#6daeb2ec786580d9c0849b05bc3e8d0222d5c463"
@ -948,6 +1005,11 @@
webpack-sources "^1.3.0"
yargs-parser "^18.1.3"
"@tinymce/tinymce-vue@^3.2.2":
version "3.2.2"
resolved "https://registry.yarnpkg.com/@tinymce/tinymce-vue/-/tinymce-vue-3.2.2.tgz#a16500fbeebfec4ae43f4e9fe5bd739aeb66a3d6"
integrity sha512-LNgKbdaScHHkBsq6UZsMpEL5yPY8oYTGaOX97+ArpJSw4B6KSQpKU+/GHnkytQhPgQLLob+ghejP0ifVQXuczg==
"@types/anymatch@*":
version "1.3.1"
resolved "https://registry.yarnpkg.com/@types/anymatch/-/anymatch-1.3.1.tgz#336badc1beecb9dacc38bea2cf32adf627a8421a"
@ -7259,6 +7321,11 @@ locate-path@^5.0.0:
dependencies:
p-locate "^4.1.0"
lodash-es@^4.17.10:
version "4.17.15"
resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.15.tgz#21bd96839354412f23d7a10340e5eac6ee455d78"
integrity sha512-rlrc3yU3+JNOpZ9zj5pQtxnx2THmvRykwL4Xlxoa8I9lHBlVbbyPhgyPMioxVZ4NqyxaVVtaJnzsyOidQIhyyQ==
lodash.defaults@^4.2.0:
version "4.2.0"
resolved "https://registry.yarnpkg.com/lodash.defaults/-/lodash.defaults-4.2.0.tgz#d09178716ffea4dde9e5fb7b37f6f0802274580c"
@ -10916,6 +10983,11 @@ timsort@^0.3.0:
resolved "https://registry.yarnpkg.com/timsort/-/timsort-0.3.0.tgz#405411a8e7e6339fe64db9a234de11dc31e02bd4"
integrity sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q=
tinymce@^5.3.2:
version "5.3.2"
resolved "https://registry.yarnpkg.com/tinymce/-/tinymce-5.3.2.tgz#c53622edf9c4b214bb912658762d6ea831d7d469"
integrity sha512-d8LaanlW+i/V5Ncb49gR2ncx0Tl2iWJBsepdsuT5qOlFaAPueIfc+btwwERXra7M6KDx0mOwKJaE2FBI+lHz3Q==
tmp@^0.0.33:
version "0.0.33"
resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9"

Loading…
Cancel
Save