JSFiddle - React, Tailwind, and code Playground

by Romel Herrera

HTML

<script src="https://code.jquery.com/jquery-1.11.3.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.5/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.5/angular-messages.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/danialfarid-angular-file-upload/7.2.0/ng-file-upload-shim.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/danialfarid-angular-file-upload/7.2.0/ng-file-upload.js"></script>
<section ng-app="publications" ng-controller="PublicationsController" style="padding: 10px">
    <div class="panel panel-default">
        <div class="panel-heading">
             <h3 class="panel-title">New Publication</h3>

        </div>
        <div class="panel-body">
            <form name="publicationForm" novalidate="" ng-submit="submit()">
                <button class="btn btn-primary" type="submit"><span class="glyphicon glyphicon-ok" aria-hidden="true"></span> Publish</button>
                <hr>
                <div class="form-group">
                    <label class="control-label"><span class="glyphicon glyphicon-bookmark"></span> Title <sup style="color: red;">*</sup>

                    </label>
                    <input type="text" name="title" ng-model="model.title" required minlength="7" class="form-control" placeholder="">
                    <div data-ng-messages="publicationForm.$submitted && publicationForm.title.$error" class="help-block">
                        <div data-ng-message="required">- The <b>title</b> is required.</div>
                        <div data-ng-message="minlength">- The <b>title</b> must be at least 7 characters long.</div>
                    </div>
                </div>
                <hr class="hr-xs">
             ...

CSS

.alert-xs {
    padding: 1px 5px;
    font-size: 12px;
    line-height: 1.5;
    border-radius: 3px;
}
/* FileUpload START */
 .file-name {
    white-space: nowrap;
    //font-weight: bold;
    width: 300px;
    margin-bottom: 2px;
}
.file-name:not(:hover) {
    overflow: hidden;
    text-overflow: ellipsis;
}
.remove-button {
    padding-top: 10px;
}
.img-preview {
    height:100px;
    max-height: 250px;
    max-width: 250px;
    margin-bottom: 5px;
}
.file-input {
    visibility: hidden;
    position: absolute;
    top: 0;
    left: 0;
    height: 0;
    width: 0;
}
/* FileUpload END */
 .hr-xs {
    margin-top: 10px;
    margin-bottom: 10px;
}

JavaScript

'use strict';


angular.module('publications', ['ngMessages', 'ngFileUpload'])
    .controller('PublicationsController', ['$scope', '$filter', '$log', function ($scope, $filter, $log) {

    $scope.model = {
        files: []
    };

    $scope.submit = function () {
        if ($scope.publicationForm.$valid) {
            $log.info('Submit the form');
        } else {
            $log.info('something missing')
        }
    };

    $scope.inQueue = function () {
        var queue = 0;
        angular.forEach($scope.model.files, function (value) {
            if (!angular.isDefined(value.inServer) && !angular.isDefined(value.$error)) {
                queue += 1;
            }
        });
        return queue;
    };

    $scope.removeAllQueueFiles = function () {
        // TODO remove only the queue and the invalids files, kept the those they are on the server
        angular.copy([], $scope.model.files);
    };

    $scope.removeFile = function (fileIndex) {
        $scope.model.files = $filter('filter')($scope.model.files, function(value, index) { return index !== fileIndex;});        
    };

}])
/**
 * AngularJS byte format filter
 * Source: https://gist.github.com/thomseddon/3511330
 */
.filter('bytes', [function () {
    return function (bytes, precision) {
        if (isNaN(parseFloat(bytes)) || !isFinite(bytes)) {
            return '-';
        }
        if (typeof precision === 'undefined') {
            precision = 1;
        }
        var units = ['bytes', 'kB', 'MB', 'GB', 'TB', 'PB'],
            number = Math.floor(Math.log(bytes) / Math.log(1024));
        return (bytes / Math.pow(1024, Math.floor(number))).toFixed(precision) + ' ' + units[number];
    };
}]);