mirror of
https://github.com/ceph/ceph
synced 2025-01-01 00:22:25 +00:00
mgr/dashboard_v2: Add table component
The current implementation isn't finished yet, but it's a start. The ngx-datatable is used as the core of the table component. You can use the table to show data in a table. You can search, paginate, sort, refresh the table contents. Multi selection is possible, the details of the selected items will be given to the specified detail component. What will be fixed soon? * Enable the usage of buttons in the table header * Enable details inline not beneath the table * Pagination to use a input field to switch pages * The columns to show can be checked and predefined * The selection made by the user will be saved in the local storage Signed-off-by: Stephan Müller <smueller@suse.com> Signed-off-by: Tiago Melo <tmelo@suse.com>
This commit is contained in:
parent
06066f0dda
commit
41c50f4c52
@ -22,6 +22,7 @@
|
||||
"@angular/platform-browser-dynamic": "^5.0.0",
|
||||
"@angular/router": "^5.0.0",
|
||||
"awesome-bootstrap-checkbox": "0.3.7",
|
||||
"@swimlane/ngx-datatable": "^11.1.7",
|
||||
"bootstrap": "^3.3.7",
|
||||
"core-js": "^2.4.1",
|
||||
"font-awesome": "4.7.0",
|
||||
|
@ -0,0 +1,14 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { TableComponent } from './table/table.component';
|
||||
import { NgxDatatableModule } from '@swimlane/ngx-datatable';
|
||||
import { TableDetailsDirective } from './table/table-details.directive';
|
||||
import {FormsModule} from '@angular/forms';
|
||||
|
||||
@NgModule({
|
||||
entryComponents: [],
|
||||
imports: [CommonModule, NgxDatatableModule, FormsModule],
|
||||
declarations: [TableComponent, TableDetailsDirective],
|
||||
exports: [TableComponent, NgxDatatableModule]
|
||||
})
|
||||
export class ComponentsModule {}
|
@ -0,0 +1,8 @@
|
||||
import { TableDetailsDirective } from './table-details.directive';
|
||||
|
||||
describe('TableDetailsDirective', () => {
|
||||
it('should create an instance', () => {
|
||||
const directive = new TableDetailsDirective(null);
|
||||
expect(directive).toBeTruthy();
|
||||
});
|
||||
});
|
@ -0,0 +1,11 @@
|
||||
import {Directive, Input, ViewContainerRef} from '@angular/core';
|
||||
|
||||
@Directive({
|
||||
selector: '[cdTableDetails]'
|
||||
})
|
||||
export class TableDetailsDirective {
|
||||
@Input() selected?: any[];
|
||||
|
||||
constructor(public viewContainerRef: ViewContainerRef) { }
|
||||
|
||||
}
|
@ -0,0 +1,68 @@
|
||||
<div class="dataTables_wrapper">
|
||||
<div class="dataTables_header clearfix"
|
||||
*ngIf="header">
|
||||
<!-- actions -->
|
||||
<div class="oadatatableactions">
|
||||
<ng-content select="table-actions"></ng-content>
|
||||
</div>
|
||||
<!-- end actions -->
|
||||
|
||||
<!-- search -->
|
||||
<div class="input-group">
|
||||
<span class="input-group-addon">
|
||||
<i class="glyphicon glyphicon-search"></i>
|
||||
</span>
|
||||
<input
|
||||
class="form-control"
|
||||
type="text"
|
||||
[(ngModel)]="search"
|
||||
(keyup)='updateFilter($event)'>
|
||||
<span class="input-group-btn">
|
||||
<button type="button"
|
||||
class="btn btn-default clear-input tc_clearInputBtn"
|
||||
(click)="updateFilter()">
|
||||
<i class="icon-prepend fa fa-remove"></i>
|
||||
</button>
|
||||
</span>
|
||||
</div>
|
||||
<!-- end search -->
|
||||
|
||||
<!-- pagination limit -->
|
||||
<div class="dataTables_length widget-toolbar">
|
||||
<input type="number"
|
||||
min="1"
|
||||
max="9999"
|
||||
[value]="limit"
|
||||
(click)="setLimit($event)"
|
||||
(keyup)="setLimit($event)"
|
||||
(blur)="setLimit($event)">
|
||||
</div>
|
||||
<!-- end pagination limit-->
|
||||
|
||||
<!-- refresh button -->
|
||||
<div class="widget-toolbar tc_refreshBtn">
|
||||
<a (click)="reloadData()">
|
||||
<i class="fa fa-lg fa-refresh"></i>
|
||||
</a>
|
||||
</div>
|
||||
<!-- end refresh button -->
|
||||
</div>
|
||||
<ngx-datatable #table
|
||||
class="bootstrap oadatatable"
|
||||
[cssClasses]="paginationClasses"
|
||||
[selectionType]="selectable"
|
||||
[selected]="selected"
|
||||
(select)="toggleExpandRow($event)"
|
||||
[columns]="columns"
|
||||
[columnMode]="'force'"
|
||||
[rows]="rows"
|
||||
[footerHeight]="'auto'"
|
||||
[limit]="limit"
|
||||
[loadingIndicator]="true"
|
||||
[rowHeight]="'auto'">
|
||||
<!-- Row Detail Template -->
|
||||
<ngx-datatable-row-detail (toggle)="updateDetailView($event)">
|
||||
</ngx-datatable-row-detail>
|
||||
</ngx-datatable>
|
||||
</div>
|
||||
<ng-template cdTableDetails></ng-template>
|
@ -0,0 +1,71 @@
|
||||
.dataTables_wrapper {
|
||||
margin-bottom: 25px;
|
||||
.separator {
|
||||
height: 30px;
|
||||
border-left: 1px solid rgba(0,0,0,.09);
|
||||
padding-left: 5px;
|
||||
margin-left: 5px;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
}
|
||||
.widget-toolbar {
|
||||
display: inline-block;
|
||||
float: right;
|
||||
width: auto;
|
||||
height: 30px;
|
||||
line-height: 28px;
|
||||
position: relative;
|
||||
border-left: 1px solid rgba(0,0,0,.09);
|
||||
cursor: pointer;
|
||||
padding: 0 8px;
|
||||
text-align: center;
|
||||
}
|
||||
.dropdown-menu {
|
||||
white-space: nowrap;
|
||||
& > li {
|
||||
cursor: pointer;
|
||||
& > label {
|
||||
width: 100%;
|
||||
margin-bottom: 0;
|
||||
padding-left: 20px;
|
||||
padding-right: 20px;
|
||||
cursor: pointer;
|
||||
&:hover {
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
& > input {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
th.oadatatablecheckbox {
|
||||
width: 16px;
|
||||
}
|
||||
}
|
||||
.dataTables_header {
|
||||
background-color: #f6f6f6;
|
||||
border: 1px solid #d1d1d1;
|
||||
border-bottom: none;
|
||||
padding: 5px;
|
||||
position: relative;
|
||||
.oadatatableactions {
|
||||
display: inline-block;
|
||||
}
|
||||
.input-group {
|
||||
float: right;
|
||||
border-left: 1px solid rgba(0,0,0,.09);
|
||||
padding-left: 8px;
|
||||
width: 40%;
|
||||
max-width: 350px;
|
||||
.form-control {
|
||||
height: 30px;
|
||||
}
|
||||
.clear-input {
|
||||
height: 30px;
|
||||
i {
|
||||
vertical-align: text-top;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,87 @@
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { TableComponent } from './table.component';
|
||||
import {NgxDatatableModule, TableColumn} from '@swimlane/ngx-datatable';
|
||||
import {FormsModule} from '@angular/forms';
|
||||
|
||||
describe('TableComponent', () => {
|
||||
let component: TableComponent;
|
||||
let fixture: ComponentFixture<TableComponent>;
|
||||
const columns: TableColumn[] = [];
|
||||
const createFakeData = (n) => {
|
||||
const data = [];
|
||||
for (let i = 0; i < n; i++) {
|
||||
data.push({
|
||||
a: i,
|
||||
b: i * i,
|
||||
c: -(i % 10)
|
||||
});
|
||||
}
|
||||
return data;
|
||||
};
|
||||
|
||||
beforeEach(
|
||||
async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [TableComponent],
|
||||
imports: [NgxDatatableModule, FormsModule]
|
||||
}).compileComponents();
|
||||
})
|
||||
);
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(TableComponent);
|
||||
component = fixture.componentInstance;
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
component.data = createFakeData(100);
|
||||
component.useData();
|
||||
component.columns = [
|
||||
{prop: 'a'},
|
||||
{prop: 'b'},
|
||||
{prop: 'c'}
|
||||
];
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should have rows', () => {
|
||||
expect(component.data.length).toBe(100);
|
||||
expect(component.rows.length).toBe(component.data.length);
|
||||
});
|
||||
|
||||
it('should have an int in setLimit parsing a string', () => {
|
||||
expect(component.limit).toBe(10);
|
||||
expect(component.limit).toEqual(jasmine.any(Number));
|
||||
|
||||
const e = {target: {value: '1'}};
|
||||
component.setLimit(e);
|
||||
expect(component.limit).toBe(1);
|
||||
expect(component.limit).toEqual(jasmine.any(Number));
|
||||
e.target.value = '-20';
|
||||
component.setLimit(e);
|
||||
expect(component.limit).toBe(1);
|
||||
});
|
||||
|
||||
it('should search for 13', () => {
|
||||
component.search = '13';
|
||||
expect(component.rows.length).toBe(100);
|
||||
component.updateFilter(true);
|
||||
expect(component.rows[0].a).toBe(13);
|
||||
expect(component.rows[1].b).toBe(1369);
|
||||
expect(component.rows[2].b).toBe(3136);
|
||||
expect(component.rows.length).toBe(3);
|
||||
});
|
||||
|
||||
it('should restore full table after search', () => {
|
||||
component.search = '13';
|
||||
expect(component.rows.length).toBe(100);
|
||||
component.updateFilter(true);
|
||||
expect(component.rows.length).toBe(3);
|
||||
component.updateFilter();
|
||||
expect(component.rows.length).toBe(100);
|
||||
});
|
||||
});
|
@ -0,0 +1,98 @@
|
||||
import {
|
||||
Component, EventEmitter, OnInit, Input, Output, ViewChild, OnChanges, ComponentFactoryResolver, Type
|
||||
} from '@angular/core';
|
||||
import {DatatableComponent, TableColumn} from '@swimlane/ngx-datatable';
|
||||
import {TableDetailsDirective} from './table-details.directive';
|
||||
|
||||
@Component({
|
||||
selector: 'cd-table',
|
||||
templateUrl: './table.component.html',
|
||||
styleUrls: ['./table.component.scss']
|
||||
})
|
||||
export class TableComponent implements OnInit, OnChanges {
|
||||
@ViewChild(DatatableComponent) table: DatatableComponent;
|
||||
@ViewChild(TableDetailsDirective) detailTemplate: TableDetailsDirective;
|
||||
|
||||
@Input() data: any[]; // This is the array with the items to be shown
|
||||
@Input() columns: TableColumn[]; // each item -> { prop: 'attribute name', name: 'display name' }
|
||||
@Input() detailsComponent?: string; // name of the component fe 'TableDetailsComponent'
|
||||
@Input() header? = true;
|
||||
|
||||
@Output() fetchData = new EventEmitter(); // Should be the function that will update the input data
|
||||
|
||||
selectable: String = undefined;
|
||||
search = '';
|
||||
rows = [];
|
||||
selected = [];
|
||||
paginationClasses = {
|
||||
pagerLeftArrow: 'i fa fa-angle-double-left',
|
||||
pagerRightArrow: 'i fa fa-angle-double-right',
|
||||
pagerPrevious: 'i fa fa-angle-left',
|
||||
pagerNext: 'i fa fa-angle-right'
|
||||
};
|
||||
limit = 10;
|
||||
|
||||
constructor(private componentFactoryResolver: ComponentFactoryResolver) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.reloadData();
|
||||
if (this.detailsComponent) {
|
||||
this.selectable = 'multi';
|
||||
}
|
||||
}
|
||||
|
||||
ngOnChanges(changes) {
|
||||
this.useData();
|
||||
}
|
||||
|
||||
setLimit(e) {
|
||||
const value = parseInt(e.target.value, 10);
|
||||
if (value > 0) {
|
||||
this.limit = value;
|
||||
}
|
||||
}
|
||||
|
||||
reloadData() {
|
||||
this.fetchData.emit();
|
||||
}
|
||||
|
||||
useData() {
|
||||
this.rows = [...this.data];
|
||||
}
|
||||
|
||||
toggleExpandRow() {
|
||||
if (this.selected.length > 0) {
|
||||
this.table.rowDetail.toggleExpandRow(this.selected[0]);
|
||||
}
|
||||
}
|
||||
|
||||
updateDetailView() {
|
||||
if (!this.detailsComponent) {
|
||||
return;
|
||||
}
|
||||
const factories = Array.from(this.componentFactoryResolver['_factories'].keys());
|
||||
const factoryClass = <Type<any>>factories.find((x: any) => x.name === this.detailsComponent);
|
||||
this.detailTemplate.viewContainerRef.clear();
|
||||
const cmpRef = this.detailTemplate.viewContainerRef.createComponent(
|
||||
this.componentFactoryResolver.resolveComponentFactory(factoryClass)
|
||||
);
|
||||
cmpRef.instance.selected = this.selected;
|
||||
}
|
||||
|
||||
updateFilter(event?) {
|
||||
if (!event) {
|
||||
this.search = '';
|
||||
}
|
||||
const val = this.search.toLowerCase();
|
||||
const columns = this.columns;
|
||||
// update the rows
|
||||
this.rows = this.data.filter(function (d) {
|
||||
return columns.filter((c) => {
|
||||
return (typeof d[c.prop] === 'string' || typeof d[c.prop] === 'number')
|
||||
&& (d[c.prop] + '').toLowerCase().indexOf(val) !== -1;
|
||||
}).length > 0;
|
||||
});
|
||||
// Whenever the filter changes, always go back to the first page
|
||||
this.table.offset = 0;
|
||||
}
|
||||
}
|
@ -5,11 +5,13 @@ import { AuthStorageService } from './services/auth-storage.service';
|
||||
import { AuthGuardService } from './services/auth-guard.service';
|
||||
import { PipesModule } from './pipes/pipes.module';
|
||||
import { HostService } from './services/host.service';
|
||||
import { ComponentsModule } from './components/components.module';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonModule,
|
||||
PipesModule
|
||||
PipesModule,
|
||||
ComponentsModule
|
||||
],
|
||||
declarations: [],
|
||||
providers: [
|
||||
|
@ -1 +1,10 @@
|
||||
$oa-color-blue: #288cea;
|
||||
$oa-color-light-blue: #afd9ee;
|
||||
$bg-color-light-blue: #d9edf7;
|
||||
$border-color: 1px solid #d1d1d1;
|
||||
@mixin table-cell {
|
||||
padding: 5px;
|
||||
border: none;
|
||||
border-left: $border-color;
|
||||
border-bottom: $border-color;
|
||||
}
|
||||
|
@ -605,7 +605,7 @@ ul.task-queue-pagination {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.panel-openattic {
|
||||
border: 1px solid #d1d1d1;
|
||||
border: $border-color;
|
||||
border-top: 0;
|
||||
border-radius: 0;
|
||||
}
|
||||
@ -622,131 +622,113 @@ ul.task-queue-pagination {
|
||||
}
|
||||
.panel-openattic>.panel-body {
|
||||
background: #ffffff;
|
||||
border-top: 1px solid #d1d1d1;
|
||||
border-top: $border-color;
|
||||
padding: 10px 15px;
|
||||
}
|
||||
.panel-openattic>.panel-footer {
|
||||
background: #ffffff;
|
||||
border-top: 1px solid #d1d1d1;
|
||||
border-top: $border-color;
|
||||
}
|
||||
|
||||
/* Table */
|
||||
table.datatable {
|
||||
/* Table
|
||||
* Has to be here because the table component uses ngx-datatable component in
|
||||
* the template and styles are not inherited by nested components.
|
||||
*/
|
||||
.ngx-datatable.oadatatable {
|
||||
border: $border-color;
|
||||
margin-bottom: 0;
|
||||
max-width: none!important
|
||||
}
|
||||
table.dataTable thead .sorting_asc,
|
||||
table.dataTable thead .sorting_desc {
|
||||
color: $oa-color-blue;
|
||||
}
|
||||
table.dataTable thead .sorting,
|
||||
table.dataTable thead .sorting_asc,
|
||||
table.dataTable thead .sorting_desc {
|
||||
cursor: pointer;
|
||||
}
|
||||
table.datatable thead .sorting:after,
|
||||
table.datatable thead .sorting_asc:after,
|
||||
table.datatable thead .sorting_desc:after {
|
||||
font-family: FontAwesome;
|
||||
font-weight: 400;
|
||||
height: 9px;
|
||||
left: 10px;
|
||||
line-height: 12px;
|
||||
position: relative;
|
||||
vertical-align: baseline;
|
||||
width: 12px;
|
||||
}
|
||||
table.datatable thead .sorting:after {
|
||||
content: "\f0dc";
|
||||
}
|
||||
table.datatable thead .sorting_asc:after {
|
||||
content: "\f160";
|
||||
}
|
||||
table.datatable thead .sorting_desc:after {
|
||||
content: "\f161";
|
||||
}
|
||||
.table>tbody>tr>td,
|
||||
.table>tbody>tr>th,
|
||||
.table>tfoot>tr>td,
|
||||
.table>tfoot>tr>th,
|
||||
.table>thead>tr>td,
|
||||
.table>thead>tr>th {
|
||||
padding: 5px;
|
||||
}
|
||||
.table>tbody>tr>td>input,
|
||||
.table>tbody>tr>th>input,
|
||||
.table>tfoot>tr>td>input,
|
||||
.table>tfoot>tr>th>input,
|
||||
.table>thead>tr>td>input,
|
||||
.table>thead>tr>th>input {
|
||||
display: block;
|
||||
}
|
||||
.table>thead {
|
||||
background-clip: padding-box;
|
||||
background-color: #f9f9f9;
|
||||
background-image: -webkit-linear-gradient(top,#fafafa 0,#ededed 100%);
|
||||
background-image: -o-linear-gradient(top,#fafafa 0,#ededed 100%);
|
||||
background-image: linear-gradient(to bottom,#fafafa 0,#ededed 100%);
|
||||
background-repeat: repeat-x;
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffafafa', endColorstr='#ffededed', GradientType=0);
|
||||
}
|
||||
|
||||
.table.header-text-center>thead>tr>th {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.table-bordered {
|
||||
border: none;
|
||||
border-top: 1px solid #d1d1d1;
|
||||
border-right: 1px solid #d1d1d1;
|
||||
}
|
||||
|
||||
.table-bordered>tbody>tr>td,
|
||||
.table-bordered>tbody>tr>th,
|
||||
.table-bordered>tfoot>tr>td,
|
||||
.table-bordered>tfoot>tr>th,
|
||||
.table-bordered>thead>tr>td,
|
||||
.table-bordered>thead>tr>th {
|
||||
border: none;
|
||||
border-left: 1px solid #d1d1d1;
|
||||
border-bottom: 1px solid #d1d1d1;
|
||||
}
|
||||
.table-striped>tbody>tr:nth-of-type(odd) {
|
||||
background-color: #ffffff;
|
||||
}
|
||||
.table-striped>tbody>tr:nth-of-type(even) {
|
||||
background-color: #f6f6f6;
|
||||
}
|
||||
.table-responsive {
|
||||
overflow-x: auto;
|
||||
margin-bottom: 0;
|
||||
min-height: .01%;
|
||||
}
|
||||
|
||||
.table-no-background>thead {
|
||||
background: none;
|
||||
}
|
||||
.table-no-background>thead>tr>th {
|
||||
border-bottom: 1px solid #ddd;
|
||||
}
|
||||
.table-no-background>tbody>tr>td {
|
||||
height: 50px;
|
||||
vertical-align: middle;
|
||||
border-top: 0px;
|
||||
border-bottom: 1px solid #ddd;
|
||||
}
|
||||
|
||||
.table-transparent>thead {
|
||||
background: none;
|
||||
}
|
||||
.table-transparent>thead>tr>th {
|
||||
border-bottom: 0px;
|
||||
}
|
||||
.table-transparent>tbody>tr>td {
|
||||
height: 50px;
|
||||
vertical-align: middle;
|
||||
border-top: 0px;
|
||||
border-bottom: 0px;
|
||||
max-width: none!important;
|
||||
.datatable-header {
|
||||
background-clip: padding-box;
|
||||
background-color: #f9f9f9;
|
||||
background-image: -webkit-linear-gradient(top,#fafafa 0,#ededed 100%);
|
||||
background-image: -o-linear-gradient(top,#fafafa 0,#ededed 100%);
|
||||
background-image: linear-gradient(to bottom,#fafafa 0,#ededed 100%);
|
||||
background-repeat: repeat-x;
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffafafa', endColorstr='#ffededed', GradientType=0);
|
||||
.sort-asc, .sort-desc {
|
||||
color: $oa-color-blue;
|
||||
}
|
||||
.datatable-header-cell{
|
||||
@include table-cell;
|
||||
text-align: center;
|
||||
.datatable-header-cell-label {
|
||||
&:after {
|
||||
font-family: FontAwesome;
|
||||
font-weight: 400;
|
||||
height: 9px;
|
||||
left: 10px;
|
||||
line-height: 12px;
|
||||
position: relative;
|
||||
vertical-align: baseline;
|
||||
width: 12px;
|
||||
}
|
||||
}
|
||||
&.sortable {
|
||||
.datatable-header-cell-label:after {
|
||||
content: " \f0dc";
|
||||
}
|
||||
&.sort-active {
|
||||
&.sort-asc .datatable-header-cell-label:after {
|
||||
content: " \f160";
|
||||
}
|
||||
&.sort-desc .datatable-header-cell-label:after {
|
||||
content: " \f161";
|
||||
}
|
||||
}
|
||||
}
|
||||
&:first-child {
|
||||
border-left: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
.datatable-body {
|
||||
.datatable-body-row {
|
||||
&.datatable-row-even {
|
||||
background-color: #ffffff;
|
||||
}
|
||||
&.datatable-row-odd {
|
||||
background-color: #f6f6f6;
|
||||
}
|
||||
&:hover {
|
||||
background-color: $oa-color-light-blue;
|
||||
}
|
||||
&.active, &.active:hover {
|
||||
background-color: $bg-color-light-blue;
|
||||
}
|
||||
.datatable-body-cell{
|
||||
@include table-cell;
|
||||
&:first-child {
|
||||
border-left: none;
|
||||
}
|
||||
.datatable-body-cell-label {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.datatable-footer {
|
||||
.selected-count .page-count {
|
||||
padding-left: 5px;
|
||||
}
|
||||
.datatable-pager .pager {
|
||||
margin-right: 5px;
|
||||
.pages {
|
||||
& > a, & > span {
|
||||
display: inline-block;
|
||||
padding: 5px 10px;
|
||||
margin-bottom: 5px;
|
||||
border: none;
|
||||
}
|
||||
a:hover {
|
||||
background-color: $oa-color-light-blue;
|
||||
}
|
||||
&.active > a {
|
||||
background-color: $bg-color-light-blue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Typo */
|
||||
@ -812,157 +794,6 @@ h6{
|
||||
color: $oa-color-blue;
|
||||
}
|
||||
|
||||
/* Datatables */
|
||||
.dataTables_wrapper {
|
||||
margin-bottom: 25px;
|
||||
}
|
||||
.dataTables_wrapper .separator {
|
||||
height: 30px;
|
||||
border-left: 1px solid rgba(0,0,0,.09);
|
||||
padding-left: 5px;
|
||||
margin-left: 5px;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
}
|
||||
.dataTables_wrapper .widget-toolbar {
|
||||
display: inline-block;
|
||||
float: right;
|
||||
width: auto;
|
||||
height: 30px;
|
||||
line-height: 28px;
|
||||
position: relative;
|
||||
border-left: 1px solid rgba(0,0,0,.09);
|
||||
cursor: pointer;
|
||||
padding: 0 8px;
|
||||
text-align: center;
|
||||
}
|
||||
.dataTables_wrapper .dropdown-menu {
|
||||
white-space: nowrap;
|
||||
}
|
||||
.dataTables_wrapper .dropdown-menu>li {
|
||||
cursor: pointer;
|
||||
}
|
||||
.dataTables_wrapper .dropdown-menu>li>label {
|
||||
width: 100%;
|
||||
margin-bottom: 0;
|
||||
padding-left: 20px;
|
||||
padding-right: 20px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.dataTables_wrapper .dropdown-menu>li>label:hover {
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
.dataTables_wrapper .dropdown-menu>li>label>input {
|
||||
cursor: pointer;
|
||||
}
|
||||
.dataTables_wrapper th.oadatatablecheckbox {
|
||||
width: 16px;
|
||||
}
|
||||
.dataTables_header {
|
||||
background-color: #f6f6f6;
|
||||
border: 1px solid #d1d1d1;
|
||||
border-bottom: none;
|
||||
padding: 5px;
|
||||
position: relative;
|
||||
}
|
||||
.dataTables_header .oadatatableactions {
|
||||
display: inline-block;
|
||||
}
|
||||
.dataTables_header .input-group {
|
||||
float: right;
|
||||
border-left: 1px solid rgba(0,0,0,.09);
|
||||
padding-left: 8px;
|
||||
width: 40%;
|
||||
max-width: 350px;
|
||||
}
|
||||
.dataTables_header .input-group .input-group-addon {
|
||||
}
|
||||
.dataTables_header .input-group .form-control {
|
||||
height: 30px;
|
||||
}
|
||||
.dataTables_header .input-group .clear-input {
|
||||
height: 30px;
|
||||
}
|
||||
.dataTables_header .input-group .clear-input i {
|
||||
vertical-align: text-top;
|
||||
}
|
||||
.dataTables_no-match {
|
||||
border: 1px solid #d1d1d1;
|
||||
padding: 10px 0;
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
font-style: italic;
|
||||
}
|
||||
.dataTables_content .progress {
|
||||
max-height: 16px;
|
||||
}
|
||||
.dataTables_content .progress span {
|
||||
line-height: 16px;
|
||||
}
|
||||
.dataTables_footer {
|
||||
background-color: #ffffff;
|
||||
border: 1px solid #d1d1d1;
|
||||
border-top: none;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
.dataTables_footer .dataTables_info {
|
||||
float: left;
|
||||
padding-top: 6px;
|
||||
padding-left: 5px;
|
||||
font-style: italic;
|
||||
}
|
||||
.dataTables_paginate {
|
||||
background: #fafafa;
|
||||
float: right;
|
||||
margin: 0;
|
||||
}
|
||||
.dataTables_paginate .pagination {
|
||||
float: left;
|
||||
margin: 0;
|
||||
}
|
||||
.dataTables_paginate .pagination.paginate-input {
|
||||
line-height: 1em;
|
||||
padding: 0.3em 0.5em;
|
||||
}
|
||||
.dataTables_paginate .pagination>li.disabled>span {
|
||||
background: #f5f5f5;
|
||||
border-left-color: #ececec;
|
||||
border-right-color: #ececec;
|
||||
}
|
||||
.dataTables_paginate .pagination>li.disabled>span,
|
||||
.dataTables_paginate .pagination>li>span:focus,
|
||||
.dataTables_paginate .pagination>li>span:hover {
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
|
||||
}
|
||||
.dataTables_paginate .pagination>li>span {
|
||||
border-color: #fff #e1e1e1 #f4f4f4;
|
||||
border-width: 0 1px;
|
||||
font-size: 1.2em;
|
||||
font-weight: 400;
|
||||
padding: 4px;
|
||||
text-align: center;
|
||||
width: 31px;
|
||||
}
|
||||
.dataTables_paginate .pagination .last>span {
|
||||
border-right: 0;
|
||||
}
|
||||
.oadatatable div.overlay, div.oa-overlay {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 10;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
background-color: rgba(30, 30, 30, 0.2);
|
||||
}
|
||||
.oadatatable div.overlay-content, div.oa-overlay-content {
|
||||
margin: 200px auto;
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
background-color: rgba(30, 30, 30, 0);
|
||||
}
|
||||
|
||||
/* Feedback */
|
||||
#feedback .feedback-button {
|
||||
position: fixed;
|
||||
|
Loading…
Reference in New Issue
Block a user