Skip to content

Commit

Permalink
Merge pull request #151 from razee-io/table_to_grid_columns
Browse files Browse the repository at this point in the history
replacing the external applications table with bootstrap grid rows and columns
  • Loading branch information
mckaymic authored Sep 27, 2019
2 parents 59225fe + ec26968 commit 70dfbd2
Show file tree
Hide file tree
Showing 4 changed files with 187 additions and 107 deletions.
216 changes: 118 additions & 98 deletions imports/ui/components/externalApplications/component.html
Original file line number Diff line number Diff line change
Expand Up @@ -24,110 +24,130 @@ <h4 class="card-header text-muted">External applications

<div class="card-body">
<form id="app-table" class="needs-validation" novalidate>
<div class="table-responsive">
<table class="table table-sm table-hover">
<thead>
<tr>
<th class="pl-2">Name</th>
<th>URL</th>
<th>Name Match (regex)</th>
<th>Kind Match (regex)</th>
<th>Action</th>
</tr>
</thead>
<tbody>
{{#unless externalApps}}
<tr class="app-item">
<td class="align-middle pl-2"><span>No applications have been defined</span></td>
<td class="align-middle"><span class="text-muted">https://company.example.com/{{|kind}}/{{|metadata.labels.app}}</span></td>
<td class="align-middle"><span class="text-muted">my-resource</span></td>
<td class="align-middle"><span class="text-muted">Deployment</span></td>
<td></td>
</tr>

<div class="container-fluid">
<!-- on small screens this header row will be hidden -->
<div class="d-none d-lg-block row-header">
<div class="row">
<div class="col-lg-2">Name</div>
<div class="col-lg-4">URL</div>
<div class="col-lg-2">Name Match(regex)</div>
<div class="col-lg-2">Kind Match(regex)</div>
<div class="col-lg-2">Action</div>
</div>
</div>
{{#unless externalApps}}
{{#unless showNewAppRow}}
<div class="row">
<div class="col">No applications have been defined</div>
</div>
{{/unless}}
{{#each app in externalApps}}
{{#if editMode app.name }}
<tr class="app-item-edit" data-name="{{app.name}}" data-id="{{app._id}}">
<td class="cursor-pointer pl-2">
<input type="text" name="appName" value="{{app.name}}" class="form-control" required autofocus/>
<div class="invalid-feedback"> Please enter a unique name </div>
</td>
<td class="cursor-pointer">
<input type="text" name="appLink" value="{{app.url}}" class="form-control" required/>
<div class="invalid-feedback"> Please enter a url </div>
</td>
<td class="cursor-pointer">
<input type="text" name="nameMatch" value="{{app.nameMatch}}" class="form-control"/>
</td>
<td class="cursor-pointer">
<input type="text" name="kindMatch" value="{{app.kindMatch}}" class="form-control"/>
</td>
<td>
<button class="btn btn-primary rounded-0 js-update-app" type="submit">Save</button>
<button class="btn btn-warning rounded-0 js-cancel-edit">Cancel</button>
</td>
</tr>
{{else}}
<tr class="app-item" data-name={{app.name}}>
<td tabindex="0" class="cursor-pointer app-edit align-middle pl-2"><span>{{app.name}}</span></td>
<td tabindex="0" class="cursor-pointer app-edit align-middle"><span>{{app.url}}</span></td>
<td tabindex="0" class="cursor-pointer app-edit align-middle"><span>{{app.nameMatch}}</span></td>
<td tabindex="0" class="cursor-pointer app-edit align-middle"><span>{{app.kindMatch}}</span></td>
<td>
<button class="btn btn-danger rounded-0 js-app-remove {{buttonStatus}}" data-name="{{app.name}}" alt="remove this app from RazeeDash"> Remove </button>
<div class="modal js-delete-app-modal" tabindex="-1" role="dialog">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Remove "{{app.name}}"</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<p>Are you sure you want to remove the application link for <strong>"{{app.name}}"</strong>?</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-link" data-dismiss="modal">Cancel</button>
<button type="button" class="btn btn-primary js-delete-app-confirm">Delete</button>
</div>
</div>
</div>
</div>
</td>
</tr>
{{/if}}
{{/each}}
<!-- New app -->
{{#if showNewAppRow }}
<tr class="app-item-new">
<td class="cursor-pointer pl-2">
<input type="text" name="appName" class="form-control" required autofocus/>
{{/unless}}
{{#each app in externalApps}}
{{#if editMode app.name }}
<div class="row app-item-edit" data-name="{{app.name}}" data-id="{{app._id}}">
<div class="col-lg-2">
<div class="d-block d-lg-none row-header-sm">Name</div>
<input type="text" name="appName" value="{{app.name}}" class="form-control" required autofocus/>
<div class="invalid-feedback"> Please enter a unique name </div>
</td>
<td class="cursor-pointer">
<input type="text" name="appLink" placeholder="https://company.site.com/{{|kind}}/{{|metadata.labels.app}}" class="form-control " required/>
</div>
<div class="col-lg-4">
<div class="d-block d-lg-none row-header-sm">URL</div>
<input type="text" name="appLink" value="{{app.url}}" class="form-control" required/>
<div class="invalid-feedback"> Please enter a url </div>
</td>
<td class="cursor-pointer">
<input type="text" name="nameMatch" placeholder="my-resource" class="form-control"/>
</td>
<td class="cursor-pointer">
<input type="text" name="kindMatch" placeholder="Deployment" class="form-control"/>
</td>
<td>
<button class="btn btn-primary rounded-0 js-add-app">Save</button>
<button class="btn btn-warning rounded-0 js-cancel-add">Cancel</button>
</td>
</tr>
</div>
<div class="col-lg-2">
<div class="d-block d-lg-none row-header-sm">Name Match(regex)</div>
<input type="text" name="nameMatch" value="{{app.nameMatch}}" class="form-control"/>
</div>
<div class="col-lg-2">
<div class="d-block d-lg-none row-header-sm">Kind Match(regex)</div>
<input type="text" name="kindMatch" value="{{app.kindMatch}}" class="form-control"/>
</div>
<div class="col-lg-2 action-col">
<div class="d-block d-lg-none row-header-sm">Action</div>
<button class="btn btn-primary rounded-0 js-update-app" type="submit">Save</button>
<button class="btn btn-warning rounded-0 js-cancel-edit">Cancel</button>
</div>
</div>
{{else}}
<div class="row app-item" data-name={{app.name}}>
<div class="col-lg-2">
<div class="d-block d-lg-none row-header-sm">Name</div>
<div class="app-edit">{{app.name}}</div>
</div>
<div class="col-lg-4">
<div class="d-block d-lg-none row-header-sm">URL</div>
<div class="app-edit">{{app.url}}</div>
</div>
<div class="col-lg-2">
<div class="d-block d-lg-none row-header-sm">Name Match(regex)</div>
<div class="app-edit">{{app.nameMatch}}</div>
</div>
<div class="col-lg-2">
<div class="d-block d-lg-none row-header-sm">Kind Match(regex)</div>
<div class="app-edit">{{app.kindMatch}}</div>
</div>
<div class="col-lg-2 action-col">
<div class="d-block d-lg-none row-header-sm">Action</div>
<button class="btn btn-danger rounded-0 js-app-remove {{buttonStatus}}" data-name="{{app.name}}" alt="remove this app from RazeeDash"> Remove </button>
<div class="modal js-delete-app-modal action-col" tabindex="-1" role="dialog">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Remove "{{app.name}}"</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<p>Are you sure you want to remove the application link for <strong>"{{app.name}}"</strong>?</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-link" data-dismiss="modal">Cancel</button>
<button type="button" class="btn btn-primary js-delete-app-confirm">Delete</button>
</div>
</div>
</div>
</div>
</div>
</div>
{{/if}}
</tbody>
</table>
{{/each}}
{{#if showNewAppRow }}
<div class="row app-item-new">
<div class="col-lg-2">
<div class="d-block d-lg-none row-header-sm">Name</div>
<input type="text" name="appName" class="form-control" required autofocus/>
<div class="invalid-feedback"> Please enter a unique name </div>
</div>
<div class="col-lg-4">
<div class="d-block d-lg-none row-header-sm">URL</div>
<input type="text" name="appLink" placeholder="https://company.site.com/{{|kind}}/{{|metadata.labels.app}}" class="form-control" required/>
<div class="invalid-feedback"> Please enter a url </div>
</div>
<div class="col-lg-2">
<div class="d-block d-lg-none row-header-sm">Name Match(regex)</div>
<input type="text" name="nameMatch" placeholder="my-resource" class="form-control"/>
</div>
<div class="col-lg-2">
<div class="d-block d-lg-none row-header-sm">Kind Match(regex)</div>
<input type="text" name="kindMatch" placeholder="Deployment" class="form-control"/>
</div>
<div class="col-lg-2 action-col">
<div class="d-block d-lg-none row-header-sm">Action</div>
<button class="btn btn-primary rounded-0 js-add-app">Save</button>
<button class="btn btn-warning rounded-0 js-cancel-add">Cancel</button>
</div>
</div>
{{/if}}
</div>
</form>
<div>
<button class="ml-1 mt-2 btn btn-primary js-create-app" type="submit">Add</button>
</div>
{{#unless showNewAppRow}}
<div>
<button class="mt-2 btn btn-primary js-create-app" type="submit">Add</button>
</div>
{{/unless}}
</div>
</div>
</template>
65 changes: 61 additions & 4 deletions imports/ui/components/externalApplications/component.scss
Original file line number Diff line number Diff line change
@@ -1,8 +1,65 @@
.cursor-pointer {

$grey:#ced4da;

.app-edit {
min-height: 37px;
cursor: pointer;
overflow-x: scroll;
}
#app-table .container-fluid {
padding-left: 0px;
}
.app-item {
line-height: 2.5;
margin-bottom: 2px;
&:hover {
background-color: rgba(0,0,0,.075);
}
}
.app-item-edit {
margin-bottom: 2px;
}
.row-header {
line-height: 2.1;
border-bottom: solid 1px $grey;
border-top: solid 1px $grey;
font-weight: 600;
margin-bottom: 8px;
}
.row-header-sm {
border: none;
font-weight: 600;
}

// prevents the left border from being cut off when the input field is focused
td.app-edit:focus {
outline-offset: -5px;
@media (max-width: 991px) {
.app-item {
line-height: 3.5;
&:hover {
background-color: inherit;
}
}
.app-item-new {
line-height: 3.5;
}
.action-col {
border-bottom: solid 1px $grey;
padding-bottom: 10px;
}
.app-item-edit {
line-height: 3.5;
}
.form-control {
height: 39px;
}
.app-edit {
display: block;
width: 100%;
height: 39px;
padding: 0.375rem 0.75rem;
font-size: 0.875rem;
font-weight: 400;
line-height: 1.9;
border: 1px solid $grey;
border-radius: 0px;
}
}
6 changes: 3 additions & 3 deletions imports/ui/components/externalApplications/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ Template.ManageExternalApps.events({
},
'click .js-update-app'(e) {
e.preventDefault();
const appId = $(e.target).closest('tr').data('id');
const appId = $(e.target).closest('.app-item-edit').data('id');
const updatedName = $(e.target).closest('.app-item-edit').find('input[name="appName"]').val();
const updatedLink = $(e.target).closest('.app-item-edit').find('input[name="appLink"]').val();
const updatedNameMatch = $(e.target).closest('.app-item-edit').find('input[name="nameMatch"]').val();
Expand Down Expand Up @@ -176,9 +176,9 @@ Template.ManageExternalApps.events({
clickedItem.set(null);
editMode.set(false);
},
'click td.app-edit, keypress td.app-edit'(e) {
'click .app-edit, keypress .app-edit'(e) {
e.preventDefault();
const clickedRow = $(e.target).closest('tr').data('name');
const clickedRow = $(e.target).closest('.app-item').data('name');
clickedItem.set(clickedRow);
editMode.set(true);
return false;
Expand Down
7 changes: 5 additions & 2 deletions imports/ui/pages/resources/resourcesSingle.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -197,9 +197,13 @@ export class ResourcesSingle_default extends React.Component{
KindResourceTagName = resourceKinds[kind];
}

const apps = this.props.externalApplications;

return (
<div>
<ExternalApps {...this.props} />
{ apps && apps.length > 0 &&
<ExternalApps {...this.props} />
}
<ResourceKindAttrTable {...this.props} />

{KindResourceTagName &&
Expand All @@ -215,7 +219,6 @@ export class ResourcesSingle_default extends React.Component{
class ExternalApps extends React.Component{
renderLinks(applications) {

console.log(JSON.parse(this.props.resource.data));
const resourceName = _.get(this.props.resource, 'searchableData.name', this.props.selfLink);
const resourceKind = this.props.resource.searchableData.kind;

Expand Down

0 comments on commit 70dfbd2

Please sign in to comment.