File Uploads Example

File Uploads Example

prema770prema770 Posts: 37Questions: 11Answers: 0

Hi All!
I'm building a variation on the file upload example for the Editor.

Can anyone please provide a complete working example as it is not clear to me how the data structure works.
Even just an SQL dump would be really helpful

Just wondering if it would be helpful with the examples section to include
* A zipfile of a the example including SQL dump that could be loaded on a local machine and work out of the box. Sometimes in learning - some of us! - are helped by being able to work back from something that is already working
* If a zip file is not feasible just an SQL dump could be helpful in cases like the upload example

Any comments / help much appreciated
Mike

Answers

  • rf1234rf1234 Posts: 3,000Questions: 87Answers: 421
    edited January 2020

    Ok, Mike, let me give it a try ...
    I had similar difficulties to get this started. I downloaded the example database from data tables somewhere and visualized the data model using MySQLWorkbench. That made it a little easier to understand the relevant relationships.

    But here is my own stuff.
    1st of all the data model excerpt. You basically have a table "files" that I designed the same way as it is in the data tables examples and then you have link tables to the entities that you upload files for. In my case it is proposals, contracts, offers, (help-)documents and many other things.

    The next thing is the JavaScript code:
    This is for help documents. The link table as per above is called "document_has_file" linking between "file" and "document"

    The Editor instance:

    var helpEditor = new $.fn.dataTable.Editor({
        ajax: {
            url: 'actions.php?action=tblHelp'
        },
        table: "#tblHelp",
        fields: [
                 {
                label: lang === 'de' ? 'Bezeichnung:' : 'Name:',
                name: "document.label"
            }, {
                type: "hidden",
                name: "document.type"
            }, {
                label: lang === 'de' ? 'Dokument(e):' : 'Document(s):',
                name: "file[].id",
                type: "uploadMany",
                display: function ( fileId, counter ) {
                    var fileNameExt = helpEditor.file( 'file', fileId ).name;
                    return renderFilesEditor(fileNameExt);
                },
                dragDropText: 'Drag and Drop to Upload',
                uploadText:   'Choose Document ...',
                noFileText:    'No Documents',
                processingText: 'Processing ...',
                fileReadText: 'Uploading Document'
            }
        ]
    });
    helpEditor
        .on('open', function () {
            this.set( { 'document.type': 0 } ); //help documents
        })
    

    The Data Table

    var helpTable = $('#tblHelp').DataTable({
        dom: "Bti"
        ajax: {
            url: 'actions.php?action=tblHelp'
        },
        columns: [
            {  data: "document.label" },
            {   data: null,
                render: function ( data, type, row ) {
                    return renderFilesDataTable(row.file);                  
                }
            },
            {   data: "document.update_time" }
        ],
        columnDefs: [
            // targets may be classes
            {   targets: "hiddenCols", visible: false }
        ],
        select: select,    
        buttons: [
            {  extend: "create", editor: helpEditor  },
            {  extend: "edit",   editor: helpEditor  },
            {  extend: "remove", editor: helpEditor  }
        ]
    });
    

    The two small rendering functions "renderFilesEditor" and "renderFilesDataTable" do some specific rendering which doesn't really matter here. The HTML is fairly trivial, too.

    And now the PHP:

    Editor::inst( $db, 'document' )
    ->field(
        Field::inst( 'document.type' ),
        Field::inst( 'document.label' )
            ->validator( 'Validate::notEmpty', array('message' => 'Field may not be empty.') ),
        Field::inst( 'document.update_time' )->set(Field::SET_BOTH)
                                             ->setValue( mySqlTimestamp() ),
        Field::inst( 'document.updater_id' )->set(Field::SET_BOTH)
                                            ->setValue( $_SESSION['id'] ),
        Field::inst( 'document.creator_id' )->set(Field::SET_CREATE)
                                            ->setValue( $_SESSION['id'] )            
    )
    ->join(
    Mjoin::inst( 'file' )
        ->link( 'document.id', 'document_has_file.document_id' )
        ->link( 'file.id', 'document_has_file.file_id' )
        ->fields(
            Field::inst( 'id' )
            ->upload( Upload::inst( $_SERVER['DOCUMENT_ROOT'].'/yourPath/documents/__ID__.__EXTN__' )
                    ->db( 'file', 'id', array(
                        'about'   => 'Y',  //documents
                        'name'    => Upload::DB_FILE_NAME,
                        'size'    => Upload::DB_FILE_SIZE,
                        'web_path'    => Upload::DB_WEB_PATH,
                        'system_path' => Upload::DB_SYSTEM_PATH
                    ) )
                    ->validator( function ( $file ) use ( $msg ) {
                        if ($file['size'] >= 52428800) {
                            return 'Files must be smaller than 50MB.';
                        } else {
                            return true;
                        }
                    } )
                    ->allowedExtensions( array  //php is not case sensitive here
                      ( 'pdf', 'xls', 'xlsx', 'csv', 'doc', 'docx', 'rtf', 'ppt',  
                    'pptx', 'odt', 'ods', 'odp' ), 'Please upload Pdf, MS Office or Open Office documents.' )
            ),
            Field::inst( 'web_path' )->set( false ),
            Field::inst( 'name' )->set( false )               
        )
    )
    ->where( function ( $q ) {        
        $q  ->where( 'document.type', 0 );
    } )
    ->process($_POST)
    ->json();
    

    As you can see both columns of the link table are being used in the PHP Editor instance. Editor sets the used constants as well.

    Hope this helps!

  • prema770prema770 Posts: 37Questions: 11Answers: 0

    rf1234,
    Thanks for this. Will analyse and commment. Really hefpful to see it laid out
    Mike

  • prema770prema770 Posts: 37Questions: 11Answers: 0
    edited January 2020

    rf1234 Made it with your help ! Brilliant!
    Here is a simple example for our particular use case
    - of course it requires the editor module!

    It's rough and only superficially tested but hope it helps somehow
    Includes

    • PHP
    • SQL
    • JS
    • HTML

    Mike

    DB:

    -- MySQL dump 10.13  Distrib 5.7.27, for Linux (x86_64)
    --
    -- Host: localhost    Database: gallery2
    -- ------------------------------------------------------
    -- Server version   5.7.27-0ubuntu0.18.04.1
    
    /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
    /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
    /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
    /*!40101 SET NAMES utf8 */;
    /*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
    /*!40103 SET TIME_ZONE='+00:00' */;
    /*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
    /*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
    /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
    /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
    
    --
    -- Current Database: `gallery2`
    --
    
    CREATE DATABASE /*!32312 IF NOT EXISTS*/ `gallery2` /*!40100 DEFAULT CHARACTER SET utf32 */;
    
    USE `gallery2`;
    
    --
    -- Table structure for table `files`
    --
    
    DROP TABLE IF EXISTS `files`;
    /*!40101 SET @saved_cs_client     = @@character_set_client */;
    /*!40101 SET character_set_client = utf8 */;
    CREATE TABLE `files` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `filename` text NOT NULL,
      `filesize` text NOT NULL,
      `web_path` varchar(255) NOT NULL,
      `system_path` varchar(255) NOT NULL,
      `notes` text,
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=16 DEFAULT CHARSET=utf8;
    /*!40101 SET character_set_client = @saved_cs_client */;
    
    --
    -- Dumping data for table `files`
    --
    
    LOCK TABLES `files` WRITE;
    /*!40000 ALTER TABLE `files` DISABLE KEYS */;
    INSERT INTO `files` VALUES (6,'51046087_303.jpg','58860','/gallery2/upload/6.jpg','/var/www/html/gallery2/upload/6.jpg',NULL),(7,'a-cute-koala.jpg','120179','/gallery2/upload/7.jpg','/var/www/html/gallery2/upload/7.jpg',NULL),(8,'1644768.jpg','130105','/gallery2/upload/8.jpg','/var/www/html/gallery2/upload/8.jpg',NULL),(9,'_109457629_gettyimages-452518400.jpg','14512','/gallery2/upload/9.jpg','/var/www/html/gallery2/upload/9.jpg',NULL),(10,'191217_koala.jpg','200297','/gallery2/upload/10.jpg','/var/www/html/gallery2/upload/10.jpg',NULL),(11,'51046087_303.jpg','58860','/gallery2/upload/11.jpg','/var/www/html/gallery2/upload/11.jpg',NULL),(12,'a-cute-koala.jpg','120179','/gallery2/upload/12.jpg','/var/www/html/gallery2/upload/12.jpg',NULL),(13,'image.jpeg','3111','/gallery2/upload/13.jpeg','/var/www/html/gallery2/upload/13.jpeg',NULL),(14,'largeImageSrc.adapt.740.medium.jpg','70190','/gallery2/upload/14.jpg','/var/www/html/gallery2/upload/14.jpg',NULL),(15,'108982542_07e3c4ae-e447-48e7-beb9-9242e374ed87.jpg','11865','/gallery2/upload/15.jpg','/var/www/html/gallery2/upload/15.jpg',NULL);
    /*!40000 ALTER TABLE `files` ENABLE KEYS */;
    UNLOCK TABLES;
    
    --
    -- Table structure for table `users`
    --
    
    DROP TABLE IF EXISTS `users`;
    /*!40101 SET @saved_cs_client     = @@character_set_client */;
    /*!40101 SET character_set_client = utf8 */;
    CREATE TABLE `users` (
      `id` int(10) NOT NULL AUTO_INCREMENT,
      `label` varchar(255) DEFAULT NULL,
      `description` text,
      `image_file` text,
      `practitioner_id` text,
      `image_type` varchar(255) DEFAULT NULL,
      `image_notes` text,
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=27 DEFAULT CHARSET=utf8;
    /*!40101 SET character_set_client = @saved_cs_client */;
    
    --
    -- Dumping data for table `users`
    --
    
    LOCK TABLES `users` WRITE;
    /*!40000 ALTER TABLE `users` DISABLE KEYS */;
    INSERT INTO `users` VALUES (24,'TEST ','TEST ','12','','General',''),(26,'TYERTY','ERTY','15','','General','');
    /*!40000 ALTER TABLE `users` ENABLE KEYS */;
    UNLOCK TABLES;
    /*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
    
    /*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
    /*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
    /*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
    /*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
    /*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
    /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
    /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
    
    -- Dump completed on 2020-01-16  0:01:17
    
    
    /*
     * Editor client script for DB table hdl_images
     * Created by http://editor.datatables.net/generator
     */
    
    (function($){
    
    $(document).ready(function() {
        var editor = new $.fn.dataTable.Editor( {
            ajax: 'php/upload.php',
            table: '#hdl_images',
            fields: [
                {
                    "label": "Label:",
                    "name": "label"
                },
                {
                    "label": "Description:",
                    "name": "description",
                    "type": "textarea"
                },
                {
                    "label": "File:",
                    "name": "image_file",
                    "type": "upload",
                    "display" : function ( id ) {
                        return '<img src="'+editor.file( 'files', id ).web_path+'"/>';
                    },
                    clearText: "Clear",
                    noImageText: 'No image'
                },
                {
                    "label": "practitioner_id:",
                    "name": "practitioner_id"
                },
                {
                    "label": "Image type:",
                    "name": "image_type",
                    "type": "select",
                    "options": [
                        "General",
                        "Iridology"
                    ]
                },
    
                {
                    "label": "image notes:",
                    "name": "image_notes",
    
                }                           
    
    
            ]
        } );
    
        var table = $('#hdl_images').DataTable( {
            ajax: 'php/upload.php',
            columns: [
                {
                    "data": "label"
                },
                {
                    "data": "description"
                },
                {
                    data: "image_file",
                    render: function ( file_id ) {
                        return file_id ?
                            '<img src="'+editor.file( 'files', file_id ).web_path+'"/>' :
                            null;
                    },
                    defaultContent: "No image",
                    title: "Image"
                },
    
                {
                    "data": "practitioner_id"
                },
                {
                    "data": "image_type"
                },
                {
                    "data": "image_notes"
                }
            ],
            select: true,
            lengthChange: false
        } );
    
        new $.fn.dataTable.Buttons( table, [
            { extend: "create", editor: editor },
            { extend: "edit",   editor: editor },
            { extend: "remove", editor: editor }
        ] );
    
        table.buttons().container()
            .appendTo( $('.col-md-6:eq(0)', table.table().container() ) );
    } );
    
    }(jQuery));
    
    
    ```php
    <?php
     
    /*
     * Example PHP implementation used for the index.html example
     */
     
    // DataTables PHP library
    include( "lib/DataTables.php" );
     
    // Alias Editor classes so they are easy to use
    use
        DataTables\Editor,
        DataTables\Editor\Field,
        DataTables\Editor\Format,
        DataTables\Editor\Mjoin,
        DataTables\Editor\Options,
        DataTables\Editor\Upload,
        DataTables\Editor\Validate,
        DataTables\Editor\ValidateOptions;
     
     
    // Build our Editor instance and process the data coming from _POST
    Editor::inst( $db, 'users' )
        ->fields(
            Field::inst( 'label' ),
            Field::inst( 'description' ),
    
            Field::inst( 'image_file' )
                ->setFormatter( Format::ifEmpty( null ) )
                ->upload( Upload::inst( $_SERVER['DOCUMENT_ROOT'].'/gallery2/upload/__ID__.__EXTN__' )
                    ->db( 'files', 'id', array(
                        'filename'    => Upload::DB_FILE_NAME,
                        'filesize'    => Upload::DB_FILE_SIZE,
                        'web_path'    => Upload::DB_WEB_PATH,
                        'system_path' => Upload::DB_SYSTEM_PATH
                    ) )
                    ->validator( Validate::fileSize( 500000, 'Files must be smaller that 5m' ) )
                    ->validator( Validate::fileExtensions( array( 'png', 'jpg', 'jpeg', 'gif' ), "Please upload an image" ) )
                ),
            Field::inst( 'practitioner_id' ),
            Field::inst( 'image_type' ),
            Field::inst( 'image_notes' )
    
    
        )
        ->process( $_POST )
        ->json();
    
    

    <!doctype html>
    <html>
    <head>
    <meta http-equiv="content-type" content="text/html; charset=utf-8" />

        <title>DataTables Editor - hdl_images</title>
    
        <link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/v/bs4-4.1.1/jqc-1.12.4/moment-2.18.1/dt-1.10.20/b-1.6.1/sl-1.3.1/datatables.min.css">
        <link rel="stylesheet" type="text/css" href="css/generator-base.css">
        <link rel="stylesheet" type="text/css" href="css/editor.bootstrap4.min.css">
    
        <!-- JQuery -->
        <script
        src="https://code.jquery.com/jquery-3.4.1.js"
        integrity="sha256-WpOohJOqMqqyKL9FccASB9O0KwACQJpFTUBLTYOVvVU="
        crossorigin="anonymous"></script>
    
        <!-- BS4 / Moment / Datatables -->
        <script type="text/javascript" charset="utf-8" src="https://cdn.datatables.net/v/bs4-4.1.1/jqc-1.12.4/moment-2.18.1/dt-1.10.20/b-1.6.1/sl-1.3.1/datatables.min.js"></script>
    
        <!-- Editor -->
        <script type="text/javascript" charset="utf-8" src="js/dataTables.editor.min.js"></script>
    
        <!-- BS4 -->
        <script type="text/javascript" charset="utf-8" src="js/editor.bootstrap4.min.js"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.11.0/umd/popper.min.js"></script>
    
        <!-- Images App -->
        <script type="text/javascript" charset="utf-8" src="js/table.hdl_images.js"></script>
    </head>
    <body class="bootstrap4">
        <div class="container">
    
            <h1>
                DataTables Editor <span>hdl_images</span>
            </h1>
    
            <table cellpadding="0" cellspacing="0" border="0" class="table table-striped table-bordered" id="hdl_images" width="100%">
                <thead>
                    <tr>
                        <th>Label</th>
                        <th>Description</th>
                        <th>Image</th>
                        <th>practitioner_id</th>
                        <th>image_type</th>
                        <th>image_notes</th>
                    </tr>
                </thead>
            </table>
    
        </div>
    </body>
    

    </html>
    ```

This discussion has been closed.