JSFiddle - React, Tailwind, and code Playground

by Muhammad Ali

HTML

<body>
  <!-- side pane -->
  <div class="sidepane col-sm-2 col-md-2 col-lg-2">
    <div class="form">
      <h3>Form</h3>

      <input type="file" class="form-control" placeholder="Upload Your Images" name="upload">
      <button id="submit" class="btn btn-default">upload</button>
      <!-- Upload Form here -->
    </div>
    <hr />
    <div class="assets">
      <h3>Assets</h3>
      <div class="text">
        <h4>Text</h4>
        <input id="customText" type="text">
        <button id="addText" class="btn btn-default">Add Text</button>
        <p></p>
      </div>
      <div class="image">
        <h4>Images</h4>
        <ul class="list-unstyled">
          <!-- List of images here -->
          <!-- <li><img src="images/sample.jpeg" class="img-rounded" /></li> -->
        </ul>
      </div>
    </div>
  </div>
  <!-- canvas -->
  <div class="canvas col-sm-8 col-md-8 col-lg-8">
    <div class="block">
      <!-- Add images and texts to here -->
    </div>
  </div>

  <script src="https://code.jquery.com/jquery-3.0.0.min.js">
    $('#addText').click(function() {
      var value = $('#customText').val();
      $('canvas').append('<p>' + value + '</p>');
    });

  </script>
</body>

CSS

* {
  margin: 0;
  padding: 0;
}

html,
body {
  width: 100%;
  height: 100%;
}

.sidepane {
  height: 100%;
  background: #E8E8EA;
}

.sidepane .form {
  height: 80px;
  margin: 10px 0;
}

.sidepane .assets {
  width: 100%;
}

#assetText {
  font-size: 24px;
}

.assets .text,
.assets .image {
  margin: 10px 0;
}

.assets .image ul li {
  width: 50px;
  height: 50px;
  margin-right: 5px;
  float: left;
  overflow: hidden;
}

.assets .image ul li img {
  width: 100%;
  height: 100%;
}

.canvas .block {
  position: relative;
  width: 600px;
  height: 600px;
  margin: 10px;
  border: 1px solid;
  box-shadow: 0px 0px 5px black;
}

.item {
  border: 1px solid transparent;
  position: absolute;
}

.item.selected {
  border-color: blue;
}

JavaScript

'use strict'

const express = require('express');
const multer = require('multer');
const fs = require('fs');
const junk = require('junk');
let app = express();

app.use(express.static('./'));

// define file name and destination to save
let storage = multer.diskStorage({
  destination: (req, file, cb) => {
    cb(null, __dirname + '/images')
  },
  filename: (req, file, cb) => {
    let ext = file.originalname.split('.');
    ext = ext[ext.length - 1];
    cb(null, 'uploads-' + Date.now() + '.' + ext);
  }
});

// define what file type to accept
let filter = (req, file, cb) => {
  if (file.mimetype == 'image/jpeg' || file.mimetype == 'image/png') {
    cb(null, true);
  } else {
    cb('Failed: format not supported');
  }
}

// set multer config
let upload = multer({
  storage: storage,
  fileFilter: filter
}).single('upload');

/* ===============================
  ROUTE
 ============================== */

// route for file upload
app.post('/uploads', (req, res) => {
  upload(req, res, err => {
    if (err) {
      console.log(err)
      res.status(400).json({
        message: err
      });
    } else {
      res.status(200).json({
        file: req.protocol + '://' + req.get('host') + '/images/' + req.file.filename
      })
    }
  })
})

app.get('/images', (req, res) => {
  let file_path = req.protocol + '://' + req.get('host') + '/images/';
  let files = fs.readdirSync('./images/');
  files = files
    .filter(junk.not) // remove .DS_STORE etc
    .map(f => file_path + f); // map with url path
  res.json(files);
});

// general route
app.get('/', (req, res) => {
  res.sendFile(__dirname + '/index.html');
})

var server = app.listen(8000, _ => {
  console.log('server started. listening to 8000');
})