app/views/promethee/_edit.html.erb
<%
@disable_page_attributes = false
@disable_page_attributes ||= disable_page_attributes
promethee_data = Promethee::Data::Master.new master_data
preview_url ||= promethee_preview_path
back_url ||= nil
logo = File.read "#{__dir__}/../../assets/images/icon-promethee.svg"
%>
<script type="text/javascript">
angular
.module('uid', [])
.factory('uidService', function () {
// Option 3 : https://stackoverflow.com/a/27747377
return {
generate: function () {
var arr = new Uint8Array(10 / 2),
hexArr = [],
i;
(window.crypto || window.msCrypto).getRandomValues(arr);
for (i = 0; i < arr.length; i += 1) {
hexArr[i] = ('0' + arr[i].toString(16)).substr(-2);
}
return hexArr.join('');
}
};
});
</script>
<script type="text/javascript">
var promethee = angular
.module('Promethee', ['summernote', 'ngAnimate', 'ngFileUpload', 'ui.sortable', 'colorpicker.module', 'uid'], ['$rootScopeProvider', function($rootScopeProvider) {
$rootScopeProvider.digestTtl(30);
}])
.value('definitions', [])
.value('presets', []);
</script>
<% promethee_util_partials.each do |partial| %>
<%= render partial %>
<% end %>
<% promethee_preset_partials.each do |partial| %>
<%= render partial %>
<% end %>
<script type="text/javascript">
promethee.controller('PrometheeController', ['$scope', 'summernoteConfig', 'presets', '$filter', function($scope, summernoteConfig, presets, $filter) {
$scope.generateIdentifier = function() {
// https://stackoverflow.com/questions/105034/create-guid-uuid-in-javascript
function s4() {
return Math.floor((1 + Math.random()) * 0x10000)
.toString(16)
.substring(1);
}
return s4() + s4() + '-' + s4() + '-' + s4() + '-' + s4() + '-' + s4() + s4() + s4();
}
$scope.data = <%= promethee_data.to_json.html_safe %>;
// Data (TODO use standard method createComponentFromDefinition)
if (typeof $scope.data !== 'object' || $scope.data === null || $scope.data.type !== 'page') {
$scope.data = {
id: $scope.generateIdentifier(),
type: 'page',
attributes: {
title: {
searchable: true,
translatable: true,
type: 'string',
value: 'New page'
},
description: {
searchable: true,
translatable: true,
type: 'text',
value: ''
},
thumbnail: {
searchable: false,
translatable: false,
type: 'blob',
value: {
id: undefined,
name: ''
}
},
stylesheets: {
searchable: false,
translatable: false,
type: 'string',
value: ''
},
javascripts: {
searchable: false,
translatable: false,
type: 'string',
value: ''
}
},
children: []
};
}
$scope.promethee = {
data: $scope.data,
definitions: [],
presets: presets,
inspected: $scope.data,
mode: 'move',
preview: 'desktop',
fullscreen: true
};
$scope.findDefinitionByType = function(type) {
return $filter('filter')($scope.promethee.definitions, {'data':{'type':type}})[0];
}
$scope.addComponentByType = function(type, target, index = -1) {
var definition = $scope.findDefinitionByType(type);
$scope.addComponent(definition, target, index);
}
$scope.addComponent = function(definition, target, index = -1) {
var component = $scope.createComponentFromDefinition(definition);
if (index === -1) {
target.push(component);
} else {
target.splice(index, 0, component);
}
}
$scope.createComponentFromDefinition = function(definition) {
var component = angular.copy(definition.data);
component.id = $scope.generateIdentifier();
return component;
}
$scope.inspect = function(component, event) {
if(event.target.closest('.promethee-edit__component') === event.currentTarget) {
$scope.promethee.inspected = component;
}
}
$scope.enablePreview = function() {
if (this.promethee.mode === 'preview') return;
this.promethee.mode = 'preview';
this.sendPreviewData('preview');
}
$scope.sendPreviewData = function(target) {
var form = document.createElement('form');
document.body.appendChild(form);
form.method = 'POST';
form.action = "<%= preview_url %>";
form.target = target;
var input = document.createElement('input');
input.type = 'text';
input.value = JSON.stringify($scope.promethee.data);
input.name = 'data';
form.appendChild(input);
<% if defined?(preview_layout) %>
var layoutInput = document.createElement('input');
layoutInput.type = 'text';
layoutInput.value = "<%= preview_layout %>";
layoutInput.name = 'preview_layout';
form.appendChild(layoutInput);
<% end %>
form.submit();
document.body.removeChild(form);
}
$scope.remove = function(component, components) {
var index = components.indexOf(component);
components.splice(index, 1);
this.promethee.inspected = null;
}
$scope.submit = function() {
window.warnBeforeUnload.unlock();
$('#promethee').closest('form').submit();
};
$scope.$watch('promethee.data', function(new_val, old_val) {
if (old_val != new_val) {
window.warnBeforeUnload.lock();
}
}, true);
$scope.summernoteConfig = summernoteConfig;
}]);
</script>
<div class="promethee-loader">
<div class="promethee-loader__inner"><%= image_tag 'loader.gif' %></div>
</div>
<div id="promethee"
ng-app="Promethee"
ng-controller="PrometheeController as prometheeController"
ng-init="component = promethee.data"
class="ng-cloak">
<% promethee_template_partials.each do |partial| %>
<%= render partial %>
<% end %>
<div class="promethee-edit" ng-show="promethee.fullscreen">
<input type="hidden" name="page[data]" id="page_data" value="{{promethee.data}}" />
<div class="upload__modal" ng-show="upload.running">
</div>
<nav class="navbar navbar-default promethee-edit__navbar px-0 py-0" ng-class="{'navbar-fixed-top': promethee.fullscreen }">
<div class="container-fluid">
<div class="navbar-header promethee-edit__icon">
<div class="navbar-brand"><%= logo.html_safe %></div>
</div>
<div id="navbar">
<ul class="nav navbar-nav navbar-right ml-auto">
<li class="nav-item" ng-click="promethee.mode = 'move'" ng-class="{active: promethee.mode == 'move'}">
<a class="nav-link" href="#" title="Edit"><%= icon('fa', 'pencil') %></a>
</li>
<li class="nav-item" ng-class="{active: promethee.mode == 'preview'}">
<a class="nav-link" href="#" title="Preview" ng-click="enablePreview()" data-toggle="dropdown"><%= icon('fa', 'eye') %></a>
<ul class="dropdown-menu" ng-show="promethee.mode == 'preview'">
<li ng-click="promethee.preview = 'desktop'"
class="nav-item"
ng-class="{active: promethee.preview == 'desktop'}">
<a class="promethee-previewmode promethee-previewmode__desktop nav-link" href="#" title="Desktop"><i class="fa fa-desktop"></i></a>
</li>
<li ng-click="promethee.preview = 'tablet'"
class="nav-item"
ng-class="{active: promethee.preview == 'tablet'}">
<a class="promethee-previewmode promethee-previewmode__tablet nav-link" href="#" title="Tablet"><i class="fa fa-tablet"></i></a>
</li>
<li ng-click="promethee.preview = 'mobile'"
class="nav-item"
ng-class="{active: promethee.preview == 'mobile'}">
<a class="promethee-previewmode promethee-previewmode__mobile nav-link" href="#" title="Mobile"><i class="fa fa-mobile"></i></a>
</li>
</ul>
</li>
<li class="nav-item" ng-click="submit()">
<a class="nav-link" href="#" title="Save"><%= icon('fa', 'save') %></a>
</li>
<% if back_url.present? %>
<li class="nav-item">
<a class="nav-link" href="<%= back_url %>" title="Close"><%= icon('fa', 'close') %></a>
</li>
<% else %>
<li class="nav-item" ng-click="promethee.fullscreen = false">
<a class="nav-link" href="#" title="Close"><%= icon('fa', 'close') %></a>
</li>
<% end %>
</ul>
</div>
</div>
</nav>
<% promethee_component_partials.each do |partial| %>
<%= render partial %>
<% end %>
<%= render 'promethee/edit/move' %>
<%= render 'promethee/edit/preview' %>
</div>
</div>