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">
   <p ng-model="GroupCardType">
   xD
  Reusable variable: {{GroupCardType.SimpleText}}
      <br>Reusable variable singleton: {{singleton.varReuse}}
   </p>
    <div class="floatleft">
      <ul ui-sortable="sortableOptions" ng-model="GroupItems" class="list">
     
        <li ng-repeat="item in GroupItems" class="item">
          <div id="item-{{item.value}}" ng-show="GroupCardType.SimpleText===item.GroupCardType" ng-if="TextValue===item.GroupCardType" class="box-text">
            <div class="form-group">
              <textarea placeholder="{{txtAddText ? txtAddText : 'Ingrese datos'}}" ng-model='txtAddText' id='item-{{item.value}}' class='editable-class input-{{item.value}}' rows="4" cols="50"></textarea>
            </div>
            <div ng-repeat='item in GroupTextItems'>
              <button class="btn btn-default" id="btn-text-{{item.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 ng-click='delText(item.value)'>DEL</button>
          </div>

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

CSS

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

.item {
  /*width: 200px;*/
  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: relative;
  box-sizing: border-box;
  color: #8492a6;
  border: 2px dashed #e0e6ed;
 ...

JavaScript

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

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

ScotiApp.asd("constantService",{attr:"this is first contant"});

ScotiApp.service('ReuseService', function() {
  return {
    varReuse: 'xDDDDDD',
    imReuseFunction: function(val) {
      this.varReuse = val;
    }
  }
  });
    
ScotiApp.controller('MainController', function($scope, $timeout, GroupCardType) {
  $scope.GroupItems = [];
  $scope.GroupTextItems = [];
  
  $scope.GroupCardType = GroupCardType;

/*
  $scope.GroupCardType.SimpleText = 'SimpleText';
  $scope.GroupCardType.Image = 'Image';
  $scope.GroupCardType.Carousel = 'Carousel';
*/

  $scope.btntitle = "";

  $scope.newitem = '';
  $scope.txtAddText = 'Ingrese texto';

  $scope.addBtnText = function() {
    if ($scope.GroupTextItems.length < 3) {
      $scope.GroupTextItems.push($scope.BtnTextItems.length);
    }
  }

  var i = 1;

  $scope.addText = function() {
    if ($scope.GroupItems.length < 10) {
      $scope.GroupItems.push({
        GroupCardType: 'SimpleText',
        text: 'Item ' + i,
        value: i
      });
      i++;
    }
  }
  
  $scope.addImage = function() {
    if ($scope.GroupItems.length < 10) {
       $scope.BoxItems.push({
        GroupCardType: 'Image',
        text: 'Item ' + i,
        value: i
      });
      i++;
    }
  }
  $scope.addCard = function() {
     if ($scope.GroupItems.length < 10) {
         $scope.GroupItems.push({
          GroupCardType: 'Carousel',
          text: 'Item ' + i,
          value: i
        });
      i++;
    }
  }

  $scope.delGroupText = function(i) {
    $scope.GroupItems.splice(i, 1);
  }
  $scope.delGroupImage = function(i) {
    $scope.GroupItems.splice(i, 1);
  }
  $scope.delGroupCard = function(i) {
    $scope.GroupItems.splice(i, 1);
  }




  this.items = [{
    name: "Enviar mensaje"
  }, {
 ...