568 lines
36 KiB
HTML
568 lines
36 KiB
HTML
<div class="row" ng-controller="EvilPortalController">
|
|
|
|
<div class="col-md-3">
|
|
<!-- Controls Panel -->
|
|
<div class="panel panel-default">
|
|
<div class="panel-heading">
|
|
<a href="javascript:;" data-toggle="collapse" data-target="#collapseControls" class="text-muted"><h4
|
|
class="panel-title">Controls <img src="/img/throbber.gif" ng-show="throbber"/></h4></a>
|
|
</div>
|
|
<div id="collapseControls" class="panel-collapse collapse in">
|
|
<div class="panel-body">
|
|
<table style="width:100%">
|
|
<tr ng-repeat="control in controls" ng-show="control.visible">
|
|
<td style="padding-bottom: .5em;" class="text-muted">{{ control.title }}</td>
|
|
<!--<td style="text-align:right">{{ control.status }}</td>-->
|
|
<td style="text-align:right;padding-bottom: .5em;">
|
|
<button class="btn btn-default btn-sm" style="width:75px"
|
|
ng-click="handleControl(control)" ng-hide="control.throbber">{{ control.status
|
|
}}
|
|
</button>
|
|
<img src="/img/throbber.gif" ng-show="control.throbber"/>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Messages Panel -->
|
|
<div class="panel panel-default">
|
|
<div class="panel-heading">
|
|
<a href="javascript:;" data-toggle="collapse" data-target="#collapseMessages" class="text-muted"><h4
|
|
class="panel-title">Evil Portal Messages</h4></a>
|
|
</div>
|
|
<div id="collapseMessages" class="panel-collapse collapse in">
|
|
<div class="panel-body">
|
|
<p ng-show="(messages.length == 0)" class="text-muted"><i>No Messages.</i></p>
|
|
<a ng-hide="(messages.length < 2)" ng-click="messages = []" class="pull-right" href="javascript:;">Clear
|
|
All</a>
|
|
<table style="width:100%" ng-hide="(messages.length == 0)">
|
|
<tr ng-repeat="message in messages">
|
|
<td>
|
|
<fieldset>
|
|
<legend><h5><b>{{ message.title }}</b> <a ng-click="dismissMessage($index)" href="javascript:;"
|
|
class="pull-right">Dismiss</a></h5></legend>
|
|
<p class="text-muted"><i>{{ message.msg }}</i></p>
|
|
</fieldset>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="panel-group" id="accordion">
|
|
<div class="col-md-9">
|
|
<!-- Library panel -->
|
|
<div class="panel panel-default">
|
|
<div class="panel-heading">
|
|
<h5 class="panel-title"><a href="javascript:;" data-toggle="collapse" data-parent="#accordion"
|
|
data-target="#collapseLibrary" class="text-muted">Work Bench <b style="text-transform: capitalize"><i>{{ workshop.portal.title }}</i></b></a></h5>
|
|
</div>
|
|
<div id="collapseLibrary" class="panel-collapse collapse in">
|
|
<div class="panel-body">
|
|
<div class="input-group" ng-show="evilPortal.library">
|
|
|
|
<span class="input-group-btn">
|
|
<select class="form-control ng-pristine ng-valid ng-touched" style="width:80px" ng-model="newPortal.type">
|
|
<option value="basic">Basic</option>
|
|
<option value="targeted">Targeted</option>
|
|
</select>
|
|
</span>
|
|
|
|
<input type="text" class="form-control" placeholder="Portal Name" name="portalName" ng-model="newPortal.name">
|
|
|
|
<span class="input-group-btn">
|
|
<button ng-disabled="newPortal.name == ''" class="btn btn-default" type="button" ng-click="createNewPortal('internal')">Create New Portal</button>
|
|
<button ng-disabled="newPortal.name == ''" class="btn btn-default" type="button" ng-click="createNewPortal('sd')" ng-show="evilPortal.sdAvailable">Create On SD Card</button>
|
|
</span>
|
|
</div>
|
|
<hr ng-show="evilPortal.library"/>
|
|
<div ng-show="portals.length > 0 && evilPortal.library">
|
|
<div class="table-responsive">
|
|
<table class="table table-striped" align="center">
|
|
<thead>
|
|
<th>Portal Name</th>
|
|
<th>Portal Type</th>
|
|
<th>Location</th>
|
|
<th ng-show="evilPortal.sdAvailable">Move To</th>
|
|
<th>Logs</th>
|
|
<th>Activate</th>
|
|
<th>Delete</th>
|
|
</thead>
|
|
<tbody>
|
|
<tr ng-repeat="portal in portals">
|
|
<!-- Open portal work shop -->
|
|
<td><a href="javascript:;" ng-click="loadPortal(portal)" style="text-transform: capitalize"><b>{{ portal.title }}</b></a></td>
|
|
<!-- Portal type -->
|
|
<td class="text-muted" style="text-transform: capitalize">{{ portal.type }}</td>
|
|
<!-- What storage device the portal is on -->
|
|
<td class="text-muted" style="text-transform: capitalize">{{ portal.storage }}</td>
|
|
<!-- change storage -->
|
|
<td ng-show="evilPortal.sdAvailable">
|
|
<a ng-show="(portal.storage == 'internal') && !portal.active" href="javascript:;" ng-click="movePortal(portal, 'sd');">SD</a>
|
|
<a ng-show="(portal.storage == 'sd') && !portal.active" href="javascript:;" ng-click="movePortal(portal, 'internal');">Internal</a>
|
|
</td>
|
|
<td>
|
|
<a href="javascript:;" data-toggle="modal" data-target="#readLogsModal" ng-click="loadPortalLog(portal)">View</a>
|
|
</td>
|
|
<!-- activate/deactivate -->
|
|
<td>
|
|
<a ng-hide="portal.active" href="javascript:;" ng-click="activatePortal(portal)">Activate</a>
|
|
<a ng-show="portal.active" href="javascript:;" ng-click="deactivatePortal(portal)">Deactivate</a>
|
|
</td>
|
|
<!-- delete portal button -->
|
|
<td>
|
|
<a ng-hide="portal.active" data-toggle="modal" data-target="#deleteModal" ng-click="deletePortal(false, portal)">Delete</a>
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
|
|
<div ng-hide="portals.length > 0 || !evilPortal.library">
|
|
<p class="text-muted text-center"><i>No Portals in Library to Display.</i></p>
|
|
</div>
|
|
|
|
<!-- Portal Editor -->
|
|
<div ng-hide="evilPortal.library">
|
|
|
|
<!-- Editor Buttons -->
|
|
<div class="row-fluid">
|
|
<span class="pull-left">
|
|
<button type="submit" class="btn btn-default btn-sm" ng-click="evilPortal.library = true; resetWorkshop()">Back</button>
|
|
</span>
|
|
<span class="pull-right">
|
|
<button type="submit" class="btn btn-default btn-sm" data-toggle="modal" data-target="#readLogsModal" ng-click="loadPortalLog(workshop.portal)">View Log</button>
|
|
<button type="submit" class="btn btn-default btn-sm" data-toggle="modal" data-target="#fileModal" ng-click="setupNewFile()">New File</button>
|
|
<!-- Holding off on toggle commands until a future release. Still need to think through how they should work. -->
|
|
<!--<button type="submit" class="btn btn-default btn-sm" data-toggle="modal" data-target="#commandEditorModal" ng-click="loadToggleCommands()">Toggle Commands</button>-->
|
|
<button type="submit" class="btn btn-default btn-sm" data-toggle="modal" data-target="#ruleEditorModal" ng-show="workshop.portal.type == 'targeted'" ng-click="loadTargetedRules();">Target Rule Editor</button>
|
|
<button type="submit" class="btn btn-default btn-sm" ng-click="loadPortal(workshop.portal)">Refresh</button>
|
|
</span>
|
|
</div>
|
|
|
|
<br/>
|
|
<hr />
|
|
|
|
<!-- Portal Files -->
|
|
<div class="table-responsive">
|
|
<table class="table table-striped" align="center">
|
|
<thead>
|
|
<th>File Name</th>
|
|
<th>Size</th>
|
|
<th>Edit</th>
|
|
<th>Delete</th>
|
|
</thead>
|
|
<tbody>
|
|
<tr ng-repeat="file in workshop.dirContents">
|
|
<td>{{ file.name }}</td>
|
|
<td>{{ file.size }}</td>
|
|
<td><a href="javascript:;" ng-click="loadFileContent(file.path)" data-toggle="modal" data-target="#fileModal">Edit</a></td>
|
|
<td><a href="javascript:;" ng-click="workshop.deleteFile = file" data-toggle="modal" data-target="#deleteFileModal" ng-show="file.deletable">Delete</a></td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- EvilPortal White List Panel -->
|
|
<div class="panel panel-default">
|
|
<div class="panel-heading">
|
|
<h5 class="panel-title"><a href="javascript:;" data-toggle="collapse" data-parent="#accordion"
|
|
data-target="#collapseWhiteList" class="text-muted"
|
|
ng-click="getList('whiteList')">White List</a></h5>
|
|
</div>
|
|
<div id="collapseWhiteList" class="panel-collapse collapse">
|
|
<div class="panel-body">
|
|
<p class="text-muted">
|
|
<i>This is a list of clients who are allowed to connect to the internet without ever viewing the captive portal.</i>
|
|
</p>
|
|
<p>
|
|
<textarea id="whiteListPool" class="form-control" rows="15" ng-mouseup="getClickedClient('whiteListPool', 'whiteListInput');" ng-model="whiteList.clients" readonly></textarea>
|
|
</p>
|
|
<div class="input-group">
|
|
<input type="text" class="form-control" placeholder="IP Address" name="whiteListInput"
|
|
ng-model="whiteList.toManipulate">
|
|
<span class="input-group-btn">
|
|
<button class="btn btn-default" type="button" ng-click="addWhiteListClient()">Add</button>
|
|
<button class="btn btn-default" type="button" ng-click="removeClientFromList('whiteList')">Remove</button>
|
|
</span>
|
|
</div>
|
|
<br/>
|
|
<button class="btn btn-default btn-sm" type="button" ng-click="getList('whiteList')">Refresh</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- EvilPortal Authorized Clients Panel -->
|
|
<div class="panel panel-default">
|
|
<div class="panel-heading">
|
|
<h5 class="panel-title"><a href="javascript:;" data-toggle="collapse" data-parent="#accordion"
|
|
data-target="#collapseAuthorizedClients" class="text-muted"
|
|
ng-click="getList('accessList')">Authorized Clients</a></h5>
|
|
</div>
|
|
<div id="collapseAuthorizedClients" class="panel-collapse collapse">
|
|
<div class="panel-body">
|
|
<div ng-show="evilPortal.running">
|
|
<p class="text-muted">
|
|
<i>This is a list of clients who have been authorized through the captive portal.</i>
|
|
</p>
|
|
<p>
|
|
<textarea id='authorizedPool' class="form-control" rows="15" ng-mouseup="getClickedClient('authorizedPool', 'accessListInput');" ng-model="accessList.clients" readonly></textarea>
|
|
</p>
|
|
<div class="input-group">
|
|
<input type="text" class="form-control" placeholder="IP Address" name="accessListInput" ng-model="accessList.toManipulate">
|
|
<span class="input-group-btn">
|
|
<button class="btn btn-default" type="button" ng-click="authorizeClient()">Authorize</button>
|
|
<button class="btn btn-default" type="button" ng-click="removeClientFromList('accessList')">Revoke</button>
|
|
</span>
|
|
</div>
|
|
<br />
|
|
<button class="btn btn-default btn-sm" type="button" ng-click="getList('accessList')">Refresh</button>
|
|
</div>
|
|
<div ng-hide="evilPortal.running">
|
|
<p class="text-muted text-center"><i>Evil Portal must be started first.</i></p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Live Preview Panel -->
|
|
<div class="panel panel-default">
|
|
<div class="panel-heading">
|
|
<h5 class="panel-title"><a href="javascript:;" data-toggle="collapse" data-parent="#accordion"
|
|
data-target="#collapsePreview" ng-click="refreshLivePreview()"
|
|
class="text-muted">Live Preview</a></h5>
|
|
</div>
|
|
<div id="collapsePreview" class="panel-collapse collapse">
|
|
<div class="panel-body">
|
|
<div ng-show="evilPortal.running">
|
|
<iframe src="http://172.16.42.1" style="width:100%;height:300px;border:none;"
|
|
id="livePreviewIframe"></iframe>
|
|
<button type="submit" ng-click="refreshLivePreview()" class="btn btn-default btn-sm">Refresh</button>
|
|
</div>
|
|
<div ng-hide="evilPortal.running">
|
|
<p class="text-muted text-center"><i>Evil Portal must be started first.</i></p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Change Log Pannel -->
|
|
<div class="panel panel-default">
|
|
<div class="panel-heading">
|
|
<h5 class="panel-title"><a href="javascript:;" data-toggle="collapse" data-parent="#accordion"
|
|
data-target="#collapseChangelog" class="text-muted">Evil Portal Info</a></h5>
|
|
</div>
|
|
<div id="collapseChangelog" class="panel-collapse collapse">
|
|
<div class="panel-body">
|
|
<fieldset>
|
|
<legend>Disclaimer</legend>
|
|
<p><b>Evil Portal and all of its components are intended for professional use only. No one associated with this project is an anyway liable for your actions.</b></p>
|
|
</fieldset>
|
|
<fieldset>
|
|
<legend>Help</legend>
|
|
<h5>Summary</h5>
|
|
<p>Evil Portal is a captive portal program that enables you to easily create a captive portal for whatever your needs are. There are two kinds of portals Basic and Targeted.
|
|
Basic portals are just a simple page that gets served to all clients. Targeted portals allow you to serve a unique page to different clients based on a given rule.</p>
|
|
<h5>Basic Portals</h5>
|
|
<p>A Basic Portal is a one-size serves all kind of portal. These portals are designed to be a single page that all clients will land on. This is the traditional way
|
|
that captive portals work and the way Evil Portal as been doing things from the beginning.</p>
|
|
<h5>Targeted Portals</h5>
|
|
<p>A Targeted Portal allows you to serve a different page on a per-client basis based on a condition. This can be something like their mac address, user-agent, etc...
|
|
Targeted Portals give you a whole new dynamic to what Evil Portal can do, if you want clients who are connected to the SSID "Coffee Shop" to see a "Coffee Shop" branded portal
|
|
while at the same time clients with Android phones seeing an Android branded portal then this is what you want.</p>
|
|
<h5>Useful Links</h5>
|
|
<a href="https://forums.hak5.org/index.php?/topic/37874-official-evilportal/">Hak5 Forum Thread</a>
|
|
<br />
|
|
<a href="https://github.com/frozenjava/EvilPortalNano">GitHub Project</a>
|
|
</fieldset>
|
|
<fieldset>
|
|
<legend>Change Log</legend>
|
|
<ul>
|
|
<li><b>3.1</b></li>
|
|
<ul>
|
|
<li class="text-muted">Added ability to write and view logs on a per-portal basis</li>
|
|
<li class="text-muted">Created method <i>writeLog($message)</i> that writes to the portal log file</li>
|
|
<li class="text-muted">Created method <i>notify($message)</i> that sends a notification to the web ui</li>
|
|
<li class="text-muted">Added ability to download files</li>
|
|
<li class="text-muted">Tab button in file editor will now insert four spaces</li>
|
|
<li class="text-muted">Revamped the file editor modal</li>
|
|
<li class="text-muted">Showing file sizes in the portal work bench</li>
|
|
<li class="text-muted">Various quality of life improvements</li>
|
|
</ul>
|
|
<li><b>3.0</b></li>
|
|
<ul>
|
|
<li class="text-muted">Added ability to route clients to different portals based upon some identifier [ssid, mac vendor, ip, etc...]</li>
|
|
<li class="text-muted">Updated the work bench so users can choose between targeted and non-targeted portals</li>
|
|
<li class="text-muted">Created easy-to-use interface for creating targeting rules</li>
|
|
<li class="text-muted">Created some consistency throughout the UI</li>
|
|
<li class="text-muted">Added ability to create portals on an SD card and move between SD and Internal storage easily</li>
|
|
<li class="text-muted">Made white listed and authorized clients IP addresses clickable like SSIDs in PineAP</li>
|
|
<li class="text-muted">Created helper functions getClientMac, getClientSSID, getClientHostName</li>
|
|
<li class="text-muted">Sending notification when a client goes through a portal.</li>
|
|
<li class="text-muted">Various quality of life improvements</li>
|
|
</ul>
|
|
</ul>
|
|
<ul>
|
|
<li><b>2.1</b></li>
|
|
<ul>
|
|
<li class="text-muted">Removed un-needed verbosity</li>
|
|
<li class="text-muted">Made tab key indent in the editor instead of change elements</li>
|
|
<li class="text-muted">Added confirmation dialogue box when deleting a portal</li>
|
|
<li class="text-muted">Created auto-start feature</li>
|
|
<li class="text-muted">Various other quality of life updates</li>
|
|
</ul>
|
|
</ul>
|
|
<ul>
|
|
<li><b>2.0</b></li>
|
|
<ul>
|
|
<li class="text-muted">Captive Portal is now purely iptables (because F***
|
|
NoDogSplash)
|
|
</li>
|
|
</ul>
|
|
</ul>
|
|
<ul>
|
|
<li><b>1.0</b></li>
|
|
<ul>
|
|
<li class="text-muted">Initial Pineapple Nano Release</li>
|
|
</ul>
|
|
</ul>
|
|
</fieldset>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<!--</div>-->
|
|
|
|
<!-- Edit file modal -->
|
|
<div id="fileModal" class="modal fade" role="dialog">
|
|
|
|
<script type="text/javascript">
|
|
// Thanks to sud0nick on forums.hak5.org for this snippet
|
|
$(document).delegate('#evilportalEditor', 'keydown', function(e) {
|
|
var keyCode = e.keyCode || e.which;
|
|
if (keyCode == 9) {
|
|
for (var i = 0; i < 4; i++) {
|
|
// get caret position/selection
|
|
var start = this.selectionStart;
|
|
var end = this.selectionEnd;
|
|
|
|
var $this = $(this);
|
|
var value = $this.val();
|
|
|
|
// set textarea value to: text before caret + tab + text after caret
|
|
$this.val(value.substring(0, start)
|
|
+ " "
|
|
+ value.substring(end));
|
|
|
|
// put caret at right position again (add one for the tab)
|
|
this.selectionStart = this.selectionEnd = start + 1;
|
|
|
|
// prevent the focus lose
|
|
e.preventDefault();
|
|
}
|
|
}
|
|
});
|
|
|
|
</script>
|
|
<div class="modal-dialog">
|
|
<!-- Modal content-->
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<button type="button" class="close" data-dismiss="modal"
|
|
ng-click="workshop.editFile = {}">×</button>
|
|
<h4 class="modal-title" ng-show="!workshop.editFile.isNewFile">Editing File</h4>
|
|
<h4 class="modal-title" ng-show="workshop.editFile.isNewFile">Creating New File</h4>
|
|
</div>
|
|
<div class="modal-body">
|
|
<label class="control-label">File Name</label>
|
|
<input type="text" class="form-control" ng-model="workshop.editFile.name" placeholder="Notes.txt" ng-disabled="!workshop.editFile.isNewFile">
|
|
<br />
|
|
<label class="control-label pull-left">File Contents</label>
|
|
<a href="javascript:;" ng-click="workshop.editFile.content = null" class="pull-right">Clear</a>
|
|
<textarea class="form-control" rows="20" ng-model="workshop.editFile.content" placeholder="Write some text here" id="evilportalEditor"/>
|
|
<label class="control-label pull-right">File Size: {{ workshop.editFile.size }}</label>
|
|
<a href="javascript:;" class="pull-left" ng-click="download(workshop.editFile.path)">Download</a>
|
|
<br />
|
|
<!-- <script src="modules/EvilPortal/includes/js/acejs/ace.js" type="text/javascript" charset="utf-8"></script> -->
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" ng-click="saveFileContent(workshop.editFile);" class="btn btn-success pull-right" data-dismiss="modal"
|
|
ng-disabled="workshop.editFile.content == null">Save</button>
|
|
|
|
<button type="button" class="btn btn-default pull-left" data-dismiss="modal" ng-click="workshop.editFile = {}">Cancel</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<!-- Read Logs Modal -->
|
|
<div id="readLogsModal" class="modal fade" role="dialog">
|
|
<div class="modal-dialog">
|
|
|
|
<!-- Modal content -->
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<button type="button" class="close" data-dismiss="modal" ng-click="activeLog = null;">×</button>
|
|
<h4 class="modal-title">Viewing <i><b>{{ activeLog.path }}</b></i></h4>
|
|
</div>
|
|
<div class="modal-body">
|
|
<a href="javascript:;" class="pull-left" ng-click="loadLog(activeLog.path)">Refresh</a>
|
|
<a href="javascript:;" class="pull-right" ng-click="clearLog()">Clear</a>
|
|
<textarea class="form-control" rows="20" ng-model="activeLog.contents" placeholder="Nothing to show." readonly/>
|
|
<label class="control-label pull-right">Log Size: {{ activeLog.size }}</label>
|
|
<a href="javascript:;" class="pull-left" ng-click="download(activeLog.path)">Download</a>
|
|
<br />
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Delete Portal Modal -->
|
|
<div id="deleteModal" class="modal fade" role="dialog">
|
|
<div class="modal-dialog">
|
|
|
|
<!-- Modal content-->
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<button type="button" class="close" data-dismiss="modal" ng-click="portalToDelete = null; portalDeleteValidation = null">×</button>
|
|
<h4 class="modal-title">Delete Portal <i>{{ portalToDelete.title }}</i>?</h4>
|
|
</div>
|
|
<div class="modal-body">
|
|
<p>You are about to delete {{ portalToDelete.title }} on {{ portalToDelete.storage }} storage. Once you do this it can not be undone.</p>
|
|
<p><b>Type the name of the portal you are trying to delete to continue.</b></p>
|
|
<input type="text" class="form-control" placeholder="PortalName" name="portalName" ng-model="portalDeleteValidation">
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-default pull-left" data-dismiss="modal" ng-click="portalToDelete = null; portalDeleteValidation = null">Cancel</button>
|
|
<button type="button" class="btn btn-danger pull-right" data-dismiss="modal" ng-click="deletePortal(true, portalToDelete)" ng-disabled="portalDeleteValidation.toLowerCase() != portalToDelete.title.toLowerCase()">Delete</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Delete file Modal -->
|
|
<div id="deleteFileModal" class="modal fade" role="dialog">
|
|
<div class="modal-dialog">
|
|
|
|
<!-- Modal content-->
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<button type="button" class="close" data-dismiss="modal" ng-click="workshop.deleteFile = {}">×</button>
|
|
<h4 class="modal-title">Delete File <i><b>{{ workshop.deleteFile.name }}</b></i>?</h4>
|
|
</div>
|
|
<div class="modal-body">
|
|
<p>You are about to delete <b>{{ workshop.deleteFile.path }}</b>. Once you do this it can not be undone.</p>
|
|
<p><b>Are you absolutely sure you want to delete <i>{{ workshop.deleteFile.name }}</i>?</b></p>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-default pull-left" data-dismiss="modal" ng-click="workshop.deleteFile = {}">Cancel</button>
|
|
<button type="button" class="btn btn-danger pull-right" data-dismiss="modal" ng-click="deleteFile()">Delete {{ workshop.deleteFile.name }}</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Rule Editor Modal -->
|
|
<div id="ruleEditorModal" class="modal fade" role="dialog">
|
|
<div class="modal-dialog">
|
|
|
|
<!-- Modal content-->
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<button type="button" class="close" data-dismiss="modal" ng-click="">×</button>
|
|
<h4 class="modal-title">Editing Rules for {{ workshop.portal.title }}</h4>
|
|
</div>
|
|
<div class="modal-body">
|
|
<div ng-repeat="(key, data) in workshop.concreteTargetedRules.rules">
|
|
<fieldset>
|
|
<legend style="text-transform: uppercase">{{ key }}</legend>
|
|
<div ng-repeat="(specifier, values) in data">
|
|
<h5 style="text-transform: capitalize">{{ specifier }} <a href="javascript:;" data-target="#" ng-click="newTargetedRule(key, specifier);">Add Rule</a></h5>
|
|
<div class="table-responsive" ng-hide="isObjectEmpty(workshop.workingTargetedRules.rules[key][specifier])">
|
|
<table class="table table-striped" align="center">
|
|
<thead>
|
|
<th>Rule Key</th>
|
|
<th>Destination</th>
|
|
<!--<th>Commit</th>-->
|
|
<th>Remove</th>
|
|
</thead>
|
|
<tbody>
|
|
<tr ng-repeat="(i, rules) in workshop.workingTargetedRules.rules[key][specifier]">
|
|
<td><input type="text" placeholder="Key Value" ng-model="rules.key"></td>
|
|
<td><input type="text" placeholder="Destination.php" ng-model="rules.destination"></td>
|
|
<!--<td><a href="javascript:;" data-target="#" ng-click="commitPortalRule(key, specifier, i, rules.key, rules.destination)">Commit</a></td>-->
|
|
<td><button ng-click="removeTargetedRule(key, specifier, i)" class="btn btn-sm btn-danger">Remove</button></td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</fieldset>
|
|
<br />
|
|
</div>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-default pull-left" data-dismiss="modal" ng-click="">Cancel</button>
|
|
<button type="button" class="btn btn-success pull-right" data-dismiss="modal" ng-click="saveTargetedRules()" >Save</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Toggled command editor -->
|
|
<div id="commandEditorModal" class="modal fade" role="dialog">
|
|
<div class="modal-dialog">
|
|
|
|
<!-- Modal content-->
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<button type="button" class="close" data-dismiss="modal">×</button>
|
|
<h4 class="modal-title">Toggle Commands for {{ workshop.portal.title }}</h4>
|
|
</div>
|
|
<div class="modal-body">
|
|
<fieldset>
|
|
<legend>On Activation - <a ng-click="saveToggleCommands('enable')">Save</a></legend>
|
|
<div class="center-block">
|
|
<!-- For sake of getting EP 3.0 release, I'm not going to implement this just yet.
|
|
<span class="center-block">
|
|
<button type="submit" class="btn btn-link btn-sm">Enable PineAP</button>
|
|
<button type="submit" class="btn btn-link btn-sm">Enable Karma Associations</button>
|
|
<button type="submit" class="btn btn-link btn-sm">Enable Beacon Response</button>
|
|
</span>-->
|
|
</div>
|
|
<textarea style="width:100%;" rows="10" ng-model="workshop.onEnable"></textarea>
|
|
</fieldset>
|
|
<fieldset>
|
|
<legend>On Deactivation - <a ng-click="saveToggleCommands('disable')">Save</a></legend>
|
|
<div class="row-fluid">
|
|
<!-- For sake of getting EP 3.0 release, I'm not going to implement this just yet.
|
|
<span class="center-block">
|
|
<button type="submit" class="btn btn-link btn-sm">Disable PineAP</button>
|
|
<button type="submit" class="btn btn-link btn-sm">Disable Karma Associations</button>
|
|
<button type="submit" class="btn btn-link btn-sm">Disable Beacon Response</button>
|
|
</span>-->
|
|
</div>
|
|
<textarea style="width:100%;" rows="10" ng-model="workshop.onDisable"></textarea>
|
|
</fieldset>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-default pull-left" data-dismiss="modal">Cancel</button>
|
|
<button type="button" class="btn btn-success pull-right" data-dismiss="modal" ng-click="saveToggleCommands('all')">Save All</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
</div> |