JSFiddle - React, Tailwind, and code Playground

by Roger Sanchez

HTML

<link rel="stylesheet" href="http://netdna.bootstrapcdn.com/twitter-bootstrap/2.1.0/css/bootstrap-combined.min.css">
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.3.1/css/all.css">
<link rel="stylesheet" href="https://rawgit.com/nohros/nsPopover/master/example/nsPopover.css">
<body ng-app="ScotiApp">
  <div ng-controller="MainController as main">
    <div class="floatleft">
      <ul ui-sortable="sortableOptions" ng-model="GroupItems" class="list">

        <li id="item-{{item.value}}" ng-repeat="item in GroupItems" class="item li-item-box">
          <div id="item-box-{{item.value}}" ng-show="GroupCardType.SimpleText===item.GroupCardType" ng-if="GroupCardType.SimpleText===item.GroupCardType" class="box-text">
            <div class="form-group">
              <textarea placeholder="{{Const_Text ? Const_Text : 'Ingrese datos'}}" ng-model='txtAddText' id='item-{{item.value}}' class='editable-class input-{{item.value}}' rows="4" cols="50"></textarea>
            </div>
            <div ng-repeat='TextItem in GroupBtnItemsText'>
              <button class="btn btn-default" id="btn-text-{{TextItem.value}}" ng-click='' ns-popover="" ns-popover-template="close" ns-popover-trigger="click" ns-popover-theme="ns-popover-tooltip-theme" ns-popover-timeout="1000" ns-popover-hide-on-inside-click="false"
                ns-popover-hide-on-outside-click="true" ns-popover-hide-on-button-click="true">Nuevo boton #{{updated_info}}</button>
            </div>
            <button class="btn btn-add-new" ng-click='addBtnText()'>Agregar boton</button>
            <button class="li-item-box-close"ng-click='delBox($index)'>X</button>
          </div>

          <div id="item-{{item.value}}" ng-show="GroupCardType.Image===item.GroupCardType" ng-if="GroupCardType.Image===item.GroupCardType" class="box-image">
            <div class="form-group">
              <form action="/" enctype="multipart/form-data" method="POST">
                <div action=""...

CSS

.li-item-box-close {
  top: -13px;
  right: -29px;
  position: absolute;
}
.li-item-box {
  position: relative;
}

.list {
  list-style: none outside none;
  margin: 10px 0 30px;
}

.item {
  padding: 5px 10px;
  margin: 5px 0;
  border: 1px solid #ccc;
  border-radius: 5px;
  background-color: #fff;
  font-size: 1.1em;
  font-weight: bold;
  text-align: center;
  cursor: move;
}

/***  Extra ***/

body {
  font-family: Verdana, 'Trebuchet ms', Tahoma;
}

.logList {
  margin: 20px;
  width: 250px;
  min-height: 200px;
  padding: 5px 15px;
  border: 5px solid #000;
  border-radius: 15px;
}

.logList:before {
  content: 'log';
  padding: 0 5px;
  position: relative;
  top: -1.1em;
  background-color: #FFF;
}

.container {
  width: 600px;
  margin: auto;
}

h2 {
  text-align: center;
}

.floatleft {
  float: left;
}

.clear {
  clear: both;
}

/* BOX */

#content-post {
  flex: 0 0 380px;
  width: 380px;
  max-width: 380px;
  margin: 20px 40px;
  min-height: calc(100vh - 60px) !important;
  background: #fff;
  box-shadow: 0 2px 77px rgba(132, 146, 166, .21);
}

#content-post .post-head {
  position: relative;
  display: -webkit-box;
  display: -ms-flexbox;
  display: flex;
  -webkit-box-align: center;
  -ms-flex-align: center;
  align-items: center;
  -webkit-box-pack: center;
  -ms-flex-pack: center;
  justify-content: center;
  height: 60px;
  padding: 0 48px;
  background: #e0e6ed;
  font-size: 20px;
  font-weight: 400;
  line-height: 24px;
}

#content-post .post-body {
  padding: 20px 0;
}

#content-post .post-footer {}

/********************************************/

.editable-class {
  will-change: border-color, background-color, box-shadow;
  transition: border-color 0.15s ease 0s, background-color 0.15s ease 0s;
  background-color: rgb(241, 240, 240);
  border-top-left-radius: 15px;
  border-top-right-radius: 15px;
  padding: 0.5rem;
  margin: 0px 0px 9px;
  width: 354px;
  height: 111px;
}

.btn-add-new {
  display: block;
  width: 100%;
  position:...

JavaScript

var ScotiApp = angular.module('ScotiApp', ['nsPopover', 'ui.sortable']);

ScotiApp.constant("EnumGroupCardType", (function() {
  return {
    SimpleText: 'SimpleText',
    Image: 'Image',
    Carousel: 'Carousel'
  }
})());

ScotiApp.controller('MainController', function($scope, $timeout, EnumGroupCardType) {
  $scope.GroupItems = [];
  $scope.GroupBtnItemsText = [];
  $scope.GroupCardType = EnumGroupCardType;
  $scope.Const_Text = 'Ingrese texto';

  $scope.addBox = function(Type) {
    if ($scope.GroupItems.length < 10) {
      $scope.GroupItems.push({
        GroupCardType: Type,
        text: 'Item ' + $scope.GroupItems.length,
        value: $scope.GroupItems.length
      });
    }
  }
  $scope.delBox = function(i) {
    $scope.GroupItems.splice(i, 1);
  }

  this.items = [{
    name: "Enviar mensaje"
  }, {
    name: "Abrir hipervinculo"
  }];

  $('#example').popover();


  $scope.sortingLog = [];
  $scope.sortableOptions = {
    'ui-floating': true,
    placeholder: "item",
    connectWith: ".list",
    activate: function() {
      console.log("activate");
    },
    beforeStop: function() {
      console.log("beforeStop");
    },
    change: function() {
      console.log("change");
    },
    create: function() {
      console.log("create");
    },
    deactivate: function() {
      console.log("deactivate");
    },
    out: function() {
      console.log("out");
    },
    over: function() {
      console.log("over");
    },
    receive: function() {
      console.log("receive");
    },
    remove: function() {
      console.log("remove");
    },
    sort: function() {
      console.log("sort");
    },
    start: function() {
      console.log("start");
    },
    update: function(e, ui) {
      console.log("update");
      var logEntry = $scope.GroupItems.map(function(i) {
        return i.value;
      }).join(', ');
      $scope.sortingLog.push('Update: ' + logEntry);
    },
    stop: function(e, ui) {
      console.log("stop");
      // this...