% layout 'yancy';
% content_for head => begin
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.3/vue.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/marked/0.3.7/marked.min.js"></script>
<style>
.data-table tbody tr:nth-child( even ) > div {
height: 0;
overflow: hidden;
}
.data-table tbody tr:nth-child( odd ).open + tr td {
padding-bottom: 0.75em;
}
.data-table tbody tr:nth-child( odd ).open + tr > div {
height: auto;
}
.data-table tbody tr:nth-child( even ) td {
padding: 0;
border: 0;
}
.data-table textarea, .add-item textarea {
width: 100%;
}
.add-item {
margin-top: 0.75em;
}
.yes-no input {
display: none;
}
.markdownEditor {
height: 50vh;
border: 1px solid #ccc;
border-radius: .25em;
}
.markdownEditor textarea, .markdownEditor div {
display: inline-block;
width: 49%;
height: 100%;
vertical-align: top;
box-sizing: border-box;
padding: 0 20px;
overflow: scroll;
}
.markdownEditor textarea {
border: none;
border-right: 1px solid #ccc;
resize: none;
outline: none;
background-color: #f6f6f6;
font-size: 14px;
font-family: 'Monaco', courier, monospace;
padding: 20px;
}
/* Fix Bootstrap 4 problem: https://github.com/twbs/bootstrap/issues/23454 */
.is-invalid + .invalid-feedback {
display: block;
}
</style>
% end
<main id="app" class="container-fluid" style="margin-top: 10px">
<div v-show="error && error.fetchSpec" class="alert alert-danger" role="alert">
<h4 class="alert-heading">Error Fetching API Spec</h4>
<p>Error from server: {{ error.fetchSpec }}</p>
<p class="mb-0">Please fix the error and reload the page.</p>
</div>
<div class="row">
<div class="col-md-2">
<div class="list-group">
<!-- collection list -->
<a v-for="( val, key ) in collections" href="#"
@click.prevent="currentCollection = key"
class="list-group-item list-group-item-action"
:class="currentCollection == key ? 'active' : ''"
>
{{ key }}
</a>
</div>
</div>
<div v-show="currentCollection" class="col-md-10">
<!-- current collection -->
<h2>{{ currentCollection }}</h2>
<div v-show="error && error.fetchPage" class="alert alert-danger" role="alert">
<h4 class="alert-heading">Error Fetching Data</h4>
<p class="mb-0">Error from server: {{ error.fetchPage }}</p>
</div>
<div v-show="info && info.addItem" class="alert alert-success alert-dismissable" role="alert">
<button type="button" @click="info.addItem = false" class="close" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
Item Added
</div>
<div v-show="info && info.saveItem" class="alert alert-success alert-dismissable" role="alert">
<button type="button" @click="info.saveItem = false" class="close" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
Item Saved
</div>
<button @click="fetchPage()" class="btn btn-primary">Refresh</button>
<button @click="showAddItem()" class="btn btn-default">Add Item</button>
<div v-if="addingItem" class="add-item">
<div v-show="error && error.addItem" class="alert alert-danger" role="alert">
<h4 class="alert-heading">Error Adding Item</h4>
<p class="mb-0">Error from server: {{ error.addItem }}</p>
</div>
<item-form v-model="newItem"
:schema="operations['add'].schema"
@close="cancelAddItem" @input="addItem"
:error="formError"
/>
</div>
<table style="margin-top: 0.5em; width: 100%" class="table data-table">
<thead class="thead-light">
<tr>
<!-- <th><input type="checkbox"></th> -->
<th></th>
<th v-for="( col, i ) in columns">{{col}}</th>
</tr>
</thead>
<tbody>
<template v-for="( row, i ) in rows">
<tr :class="openedRow == i ? 'open' : ''">
<!-- <td style="width: 2em"><input type="checkbox"></td> -->
<td style="width: 4em">
<a href="#" @click.prevent="toggleRow(i)">
<i class="fa fa-pencil-square-o" aria-hidden="true"></i>
</a>
<a href="#" @click.prevent="confirmDeleteItem(i)">
<i class="fa fa-trash-o" aria-hidden="true"></i>
</a>
</td>
<td v-for="col in columns">
{{ row[col] }}
</td>
</tr>
<tr>
<td :colspan="2 + columns.length">
<div v-if="openedRow == i" v-show="error && error.saveItem" class="alert alert-danger" role="alert">
<h4 class="alert-heading">Error Saving Item</h4>
<p class="mb-0">Error from server: {{ error.saveItem }}</p>
</div>
<item-form v-if="openedRow == i" v-model="rows[i]"
:schema="operations['set'].schema"
@close="toggleRow(i)" @input="saveItem(i)"
:error="formError"
/>
</td>
</tr>
</template>
</tbody>
</table>
<p v-if="rows.length == 0">
No items found.
<a href="#" @click.prevent="showAddItem()">Create an item</a>.
</p>
<nav aria-label="List page navigation">
<ul class="pagination">
<li class="page-item" :class="currentPage == 0 ? 'disabled' : ''">
<a class="page-link" href="#" aria-label="Previous"
@click.prevent="currentPage--"
>
<span aria-hidden="true">«</span>
<span class="sr-only">Previous</span>
</a>
</li>
<li v-for="page in totalPages" class="page-item"
:class="page == currentPage + 1 ? 'active': ''"
>
<a class="page-link" href="#" @click.prevent="currentPage = page - 1">
{{ page }}
</a>
</li>
<li class="page-item" :class="currentPage >= totalPages - 1 ? 'disabled' : ''">
<a class="page-link" href="#" aria-label="Next"
@click.prevent="currentPage++"
>
<span aria-hidden="true">»</span>
<span class="sr-only">Next</span>
</a>
</li>
</ul>
</nav>
</div>
</div>
<div id="confirmDelete" class="modal" tabindex="-1" role="dialog">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Confirm Delete</h5>
</div>
<div class="modal-body">
<p>Are you sure you want to delete this item?</p>
</div>
<div class="modal-footer">
<button @click.prevent="deleteItem()" type="button" class="btn btn-danger">Delete</button>
<button @click.prevent="cancelDeleteItem()" type="button" class="btn btn-secondary">Cancel</button>
</div>
</div>
</main>
<template id="item-form">
<div>
<form @submit.prevent="save()">
<div class="pull-right" style="margin-bottom: 4px">
<label class="btn btn-secondary">Show Raw <input type="checkbox" v-model="showRaw" /></label>
</div>
<button class="btn btn-primary">Save</button>
<button type="button" @click="cancel()" class="btn btn-danger">Cancel</button>
<div v-if="!showRaw">
<div v-for="( conf, field ) in properties" class="form-group" style="clear: both">
<label :for="'field-' + field + '-' + _uid">
{{ conf.title || field }} {{ isRequired( field ) ? '*' : '' }}
</label>
<edit-field v-model="$data._value[field]"
:example="example[field]" :schema="conf"
:required="isRequired( field )" :valid="!error[field]"
/></edit-field>
<div v-show="error[field]" class="invalid-feedback">Error: {{ error[ field ] }}</div>
</div>
</div>
<div v-if="showRaw && rawError" class="alert alert-danger" role="alert" style="clear: both">
<h4 class="alert-heading">Error Parsing JSON</h4>
<p class="mb-0">{{ rawError.message }}</p>
</div>
<textarea v-if="showRaw" rows="10" v-model="rawValue" @change="updateRaw"></textarea>
</form>
</div>
</template>
<template id="edit-field">
<div :class="!valid ? 'is-invalid' : ''">
<input v-if="fieldType != 'select' && fieldType != 'checkbox' && fieldType != 'markdown'"
:type="fieldType" :pattern="pattern" :required="required"
:minlength="minlength" :maxlength="maxlength"
:min="min" :max="max"
:readonly="readonly"
:placeholder="example"
v-model="$data._value" @change="input" class="form-control"
:class="!valid ? 'is-invalid' : ''"
/>
<select v-if="fieldType == 'select'"
:required="required" :disabled="readonly"
v-model="$data._value" @change="input"
class="custom-select"
:class="!valid ? 'is-invalid' : ''"
>
<option v-if="!required" :value="undefined">- empty -</option>
<option v-for="val in schema.enum">{{val}}</option>
</select>
<div v-if="fieldType == 'checkbox'"
class="btn-group yes-no"
>
<label class="btn btn-xs" :class="value ? 'btn-success active' : 'btn-outline-success'"
@click="readonly || ( $data._value = true )"
>
<input type="radio" :name="_uid"
v-model="$data._value" @change="input" :value="true"
> Yes
</label>
<label class="btn btn-xs" :class="value ? 'btn-outline-danger' : 'btn-danger active'"
@click="readonly || ( $data._value = false )"
>
<input type="radio" :name="_uid"
v-model="$data._value" @change="input" :value="false"
> No
</label>
</div>
<div v-if="fieldType == 'markdown'" class="markdownEditor">
<textarea v-model="$data._value" @change="input"></textarea>
<div v-html="html"></div>
</div>
</div>
</template>
<script>var specUrl = '<%= url_for("yancy.api") %>';</script>
<script src="/yancy.js"></script>