app/views/showRecipe.scala.html (201 lines of code) (raw):
@import data.Roles
@import prism.Prism.Image
@import prism.Prism.AWSAccount
@import prism.RecipeUsage
@import views.html.helper.CSRF
@(
recipe: Recipe,
recentBakes: Iterable[Bake],
recentCopies: Map[AmiId, Seq[Image]],
accounts: Seq[AWSAccount],
usage: prism.RecipeUsage,
allRoles: Seq[RoleSummary],
debugAvailable: Boolean,
cloneForm: Form[_]
)(implicit request: RequestHeader, flash: Flash, messages: play.api.i18n.Messages)
@implicitFieldConstructor = @{ b3.inline.fieldConstructor() }
@simpleLayout("AMIgo"){
<h1>@recipe.id.value</h1>
<div class="panel panel-default">
<div class="panel-heading">Actions</div>
<div class="panel-body">
<div class="btn-toolbar">
@b3.form(routes.BakeController.startBaking(recipe.id)) {
@CSRF.formField
<button class="post btn btn-primary">Bake!</button>
}
<a href="@routes.RecipeController.editRecipe(recipe.id)" class="btn btn-default">Edit</a>
@if(debugAvailable){
@b3.form(routes.BakeController.startBaking(recipe.id, debug = true)) {
@CSRF.formField
<button class="post btn btn-warning mr-1">Bake with debug enabled</button>
}
}
<a href="@routes.RecipeController.deleteConfirm(recipe.id)" class="btn btn-danger">Delete...</a>
</div>
</div>
<div class="panel-body">
@b3.form(routes.RecipeController.cloneRecipe(recipe.id)) {
@CSRF.formField
@b3.inputWrapped( "newId", cloneForm("newId"), Symbol("placeholder") -> s"${recipe.id.value}-cloned" ) { input =>
<div class="input-group">
@input
<span class="input-group-btn">
<button type="submit" class="btn btn-default">Clone</button>
</span>
</div>
}
}
</div>
</div>
<div class="panel panel-default">
<div class="panel-heading">Description</div>
<div class="panel-body">
<p>Created @fragments.timestamp(recipe.createdAt, recipe.createdBy)</p>
<p>Modified @fragments.timestamp(recipe.modifiedAt, recipe.modifiedBy)</p>
<p>Build schedule: <code>@recipe.bakeSchedule.map(_.quartzCronExpression).getOrElse("(none)")</code></p>
<p>Request encrypted copy: @if(recipe.encryptFor.nonEmpty){ @recipe.encryptFor.map(_.accountNumber).mkString(", ") }else{ None }</p>
<p>@recipe.description</p>
@if(usage.instances.size + usage.launchConfigurations.size > 0) {
<p>This recipe is used by <a href="@routes.RecipeController.showUsages(recipe.id)">@usage.instances.size instance@if(usage.instances.size != 1){s} and @usage.launchConfigurations.size launch configuration@if(usage.launchConfigurations.size != 1){s}</a></p>
} else {
<p><b>This recipe is not used</b></p>
}
<p>
<a href="@(s"https://github.com/search?q=${helper.urlEncode(s"""org:guardian "${recipe.id}" NOT is:archived""")}&type=code")">
Search GitHub for usage
</a>
</p>
<p class="@BaseImage.eolStatusClass(recipe.baseImage)">@BaseImage.eolStatusString(recipe.baseImage)</p>
</div>
</div>
<div class="panel panel-default">
<div class="panel-heading">Base image</div>
<div class="panel-body">
<a href="@routes.BaseImageController.showBaseImage(recipe.baseImage.id)">@recipe.baseImage.id</a>
@recipe.diskSize.map{size=>
With a disk size of @size gb.
}
</div>
</div>
<div class="panel panel-default">
<div class="panel-heading">Roles</div>
<div class="panel-body">
@fragments.customisedRoles(Roles.customisedTransitiveDependency(allRoles, recipe.roles))
<h4>Inherited from base image @recipe.baseImage.id</h4>
@fragments.customisedRoles(Roles.customisedTransitiveDependency(allRoles, recipe.baseImage.builtinRoles))
</div>
</div>
<div class="panel panel-default">
<div class="panel-heading">Recent bakes</div>
<div class="panel-body">
<table class="table table-striped table-hover">
<thead>
<th>Started</th>
<th>Build number</th>
@if(recentCopies.nonEmpty) {
<th>Encrypted copy</th>
}
<th>Status</th>
<th>AMI</th>
@* Column for copy button *@
<th></th>
<th>Usages</th>
<th>AMIable</th>
</thead>
<tbody>
@for(bake <- recentBakes) {
<tr>
<td class="has-block-link">
<a class="block-link" href="@routes.BakeController.showBake(bake.recipe.id, bake.buildNumber)">
@fragments.timestamp(bake.startedAt, bake.startedBy)
</a>
</td>
<td class="has-block-link">
<a class="block-link" href="@routes.BakeController.showBake(bake.recipe.id, bake.buildNumber)">
@bake.buildNumber
</a>
</td>
@if(recentCopies.nonEmpty) {
<td class="has-block-link"></td>
}
<td class="has-block-link">
<a class="block-link" href="@routes.BakeController.showBake(bake.recipe.id, bake.buildNumber)">
@bake.status
</a>
</td>
@if(bake.amiId.isDefined) {
<td class="has-block-link">
<a class="block-link" href="@routes.BakeController.showBake(bake.recipe.id, bake.buildNumber)">
<code>@bake.amiId</code>
</a>
</td>
<td class="absolute-container has-block-link">
<button class="btn btn-primary btn-xs absolute-right copy-button" title="Copy to clipboard" data-clipboard-text="@bake.amiId">
<img src="@routes.Assets.versioned("images/clippy.svg")" width="13" alt="Copy to clipboard" title="Copy to clipboard">
</button>
</td>
@fragments.usagesColumn(recipe, RecipeUsage.amiUsages(usage, bake.amiId.get))
<td>
<a href="https://amiable.gutools.co.uk/ami?imageId=@bake.amiId" target="_blank" rel="noopener noreferrer">
<img src="@routes.Assets.versioned("images/amiable.png")" width="13" alt="View in AMIable" title="View in AMIable">
</a>
</td>
</td>
} else {
<td></td>
<td></td>
<td></td>
<td></td>
}
</tr>
@for(copy <- bake.amiId.flatMap(id => recentCopies.get(id)).getOrElse(Nil)){
<tr>
<td> </td>
<td> </td>
<td>
<ul class="list-unstyled">
<li>@defining(accounts.find(_.accountNumber == copy.ownerId)){ maybeOwnerAcc =>
@maybeOwnerAcc.map{ ownerAcc => @ownerAcc.accountName (@ownerAcc.accountNumber) }.getOrElse(copy.ownerId)
}
</li>
@copy.encrypted.map{e => <li>Encrypted tag: @e</li>}
</ul>
</td>
<td>
@copy.state.capitalize
</td>
<td>
<code>@copy.imageId</code>
</td>
<td class="absolute-container">
<button class="btn btn-primary btn-xs absolute-right copy-button" title="Copy to clipboard" data-clipboard-text="@copy.imageId">
<img src="@routes.Assets.versioned("images/clippy.svg")" width="13" alt="Copy to clipboard" title="copy to clipboard">
</button>
</td>
@fragments.usagesColumn(recipe, RecipeUsage.amiUsages(usage, copy.imageId))
<td>
<a href="https://amiable.gutools.co.uk/ami?imageId=@copy.imageId" target="_blank" rel="noopener noreferrer">
<img src="@routes.Assets.versioned("images/amiable.png")" width="13" alt="View in AMIable" title="View in AMIable">
</a>
</td>
</tr>
}
}
</tbody>
</table>
</div>
</div>
<script src="@routes.Assets.versioned("javascripts/clipboard.min.js")"></script>
<script>
var clipboard = new Clipboard('.copy-button');
clipboard.on('success', function(e) {
console.log(e);
e.trigger.classList.add('btn--success');
});
clipboard.on('error', function(e) {
console.log(e);
//TODO: Add tooltip
});
</script>
<!-- TODO listen to bake events and update the bakes list accordingly -->
}