Skip to content
Snippets Groups Projects
Commit 4fc0a5b2 authored by Sameer Al-Sakran's avatar Sameer Al-Sakran
Browse files

Merge pull request #437 from metabase/new_db_admin

New db admin - (WIP)
parents 276b6d65 51509c12
No related branches found
No related tags found
No related merge requests found
Showing
with 378 additions and 345 deletions
...@@ -171,34 +171,108 @@ DatabasesControllers.controller('DatabaseEdit', ['$scope', '$routeParams', '$loc ...@@ -171,34 +171,108 @@ DatabasesControllers.controller('DatabaseEdit', ['$scope', '$routeParams', '$loc
} }
]); ]);
DatabasesControllers.controller('DatabaseMasterDetail', ['$scope', '$route', '$routeParams',
DatabasesControllers.controller('DatabaseTables', ['$scope', '$routeParams', '$location', 'Metabase', function($scope, $route, $routeParams) {
function($scope, $routeParams, $location, Metabase) { $scope.pane = 'settings';
Metabase.db_get({ // mildly hacky way to prevent reloading controllers as the URL changes
'dbId': $routeParams.databaseId var lastRoute = $route.current;
}, function(database) { $scope.$on('$locationChangeSuccess', function (event) {
$scope.database = database; if ($route.current.$$route.controller === 'DatabaseMasterDetail') {
}, function(error) { var params = $route.current.params;
console.log('error loading database', error); $route.current = lastRoute;
if (error.status == 404) { angular.forEach(params, function(value, key) {
$location.path('/admin/databases/'); $route.current.params[key] = value;
$routeParams[key] = value;
});
} }
}); });
Metabase.db_tables({ $scope.routeParams = $routeParams;
'dbId': $routeParams.databaseId $scope.$watch('routeParams', function() {
}, function(tables) { $scope.pane = $routeParams.mode;
$scope.tables = tables; }, true);
}, function(error) { }
]);
}); DatabasesControllers.controller('DatabaseTables', ['$scope', '$routeParams', '$location', '$q', 'Metabase',
function($scope, $routeParams, $location, $q, Metabase) {
$scope.tableFields = {};
$scope.routeParams = $routeParams;
$scope.$watch('routeParams', function() {
loadData();
}, true);
function loadData() {
return loadDatabase()
.then(function() {
return updateTable();
})
.catch(function(error) {
console.log('error loading data', error);
if (error.status == 404) {
$location.path('/admin/databases');
}
});
}
function loadDatabase() {
if ($scope.$parent.database && $scope.$parent.database.id == $routeParams.databaseId) {
return $q.all([]); // just return an empty promise if we already loaded this db
} else {
return $q.all([
Metabase.db_get({ 'dbId': $routeParams.databaseId }).$promise
.then(function(database) {
$scope.$parent.database = database;
}),
Metabase.db_tables({ 'dbId': $routeParams.databaseId }).$promise
.then(function(tables) {
$scope.tables = tables;
return $q.all(tables.map(function(table) {
return Metabase.table_query_metadata({ 'tableId': table.id }).$promise
.then(function(result) {
$scope.tableFields[table.id] = result;
});
}));
})
]);
}
}
function updateTable() {
if ($routeParams.tableId !== undefined) {
$scope.$parent.table = $scope.tables.filter(function(t) { return $routeParams.tableId == t.id; })[0];
if (!$scope.$parent.table) {
$location.path('/admin/databases/'+$routeParams.databaseId+'/tables');
}
}
}
} }
]); ]);
DatabasesControllers.controller('DatabaseTable', ['$scope', '$routeParams', '$location', 'Metabase', 'ForeignKey', DatabasesControllers.controller('DatabaseTable', ['$scope', '$routeParams', '$location', 'Metabase', 'ForeignKey',
function($scope, $routeParams, $location, Metabase, ForeignKey) { function($scope, $routeParams, $location, Metabase, ForeignKey) {
$scope.routeParams = $routeParams;
$scope.$watch('routeParams', function() {
loadData();
}, true);
function loadData() {
Metabase.table_query_metadata({
'tableId': $routeParams.tableId
}, function(result) {
$scope.table = result;
$scope.getIdFields();
$scope.decorateWithTargets();
}, function(error) {
console.log(error);
if (error.status == 404) {
$location.path('/');
}
});
}
$scope.getIdFields = function() { $scope.getIdFields = function() {
// fetch the ID fields // fetch the ID fields
...@@ -332,13 +406,11 @@ DatabasesControllers.controller('DatabaseTable', ['$scope', '$routeParams', '$lo ...@@ -332,13 +406,11 @@ DatabasesControllers.controller('DatabaseTable', ['$scope', '$routeParams', '$lo
}; };
$scope.fields = [];
$scope.dragControlListeners = { $scope.dragControlListeners = {
containment: '.EntityGroup', containment: '.EntityGroup',
orderChanged: function(event) { orderChanged: function(event) {
// Change order here // Change order here
var new_order = _.map($scope.fields, function(field) { var new_order = _.map($scope.table.fields, function(field) {
return field.id; return field.id;
}); });
Metabase.table_reorder_fields({ Metabase.table_reorder_fields({
...@@ -347,21 +419,6 @@ DatabasesControllers.controller('DatabaseTable', ['$scope', '$routeParams', '$lo ...@@ -347,21 +419,6 @@ DatabasesControllers.controller('DatabaseTable', ['$scope', '$routeParams', '$lo
}); });
} }
}; };
Metabase.table_query_metadata({
'tableId': $routeParams.tableId
}, function(result) {
$scope.table = result;
$scope.fields = $scope.table.fields;
$scope.getIdFields();
$scope.decorateWithTargets();
}, function(error) {
console.log(error);
if (error.status == 404) {
$location.path('/');
}
});
} }
]); ]);
......
...@@ -5,7 +5,7 @@ var AdminDatabases = angular.module('corvusadmin.databases', [ ...@@ -5,7 +5,7 @@ var AdminDatabases = angular.module('corvusadmin.databases', [
]); ]);
AdminDatabases.config(['$routeProvider', function ($routeProvider) { AdminDatabases.config(['$routeProvider', function ($routeProvider) {
$routeProvider.when('/:orgSlug/admin/databases/', { $routeProvider.when('/:orgSlug/admin/databases', {
templateUrl: '/app/admin/databases/partials/database_list.html', templateUrl: '/app/admin/databases/partials/database_list.html',
controller: 'DatabaseList' controller: 'DatabaseList'
}); });
...@@ -13,20 +13,17 @@ AdminDatabases.config(['$routeProvider', function ($routeProvider) { ...@@ -13,20 +13,17 @@ AdminDatabases.config(['$routeProvider', function ($routeProvider) {
templateUrl: '/app/admin/databases/partials/database_edit.html', templateUrl: '/app/admin/databases/partials/database_edit.html',
controller: 'DatabaseEdit' controller: 'DatabaseEdit'
}); });
$routeProvider.when('/:orgSlug/admin/databases/:databaseId', { $routeProvider.when('/:orgSlug/admin/databases/:databaseId', {
templateUrl: '/app/admin/databases/partials/database_edit.html', redirectTo: '/:orgSlug/admin/databases/:databaseId/tables'
controller: 'DatabaseEdit'
}); });
$routeProvider.when('/:orgSlug/admin/databases/:databaseId/tables/', { $routeProvider.when('/:orgSlug/admin/databases/:databaseId/:mode', {
templateUrl: '/app/admin/databases/partials/database_tables.html', templateUrl: '/app/admin/databases/partials/database_master_detail.html',
controller: 'DatabaseTables' controller: 'DatabaseMasterDetail'
}); });
$routeProvider.when('/:orgSlug/admin/databases/table/:tableId', { $routeProvider.when('/:orgSlug/admin/databases/:databaseId/:mode/:tableId', {
templateUrl: '/app/admin/databases/partials/database_table.html', templateUrl: '/app/admin/databases/partials/database_master_detail.html',
controller: 'DatabaseTable' controller: 'DatabaseMasterDetail'
});
$routeProvider.when('/:orgSlug/admin/databases/field/:fieldId', {
templateUrl: '/app/admin/databases/partials/database_table_field.html',
controller: 'DatabaseTableField'
}); });
}]); }]);
...@@ -6,36 +6,6 @@ ...@@ -6,36 +6,6 @@
<h2 class="Breadcrumb Breadcrumb--page" ng-if="database.id">{{database.name}}</h2> <h2 class="Breadcrumb Breadcrumb--page" ng-if="database.id">{{database.name}}</h2>
</section> </section>
<section class="Grid Grid--gutters Grid--full"> <section class="Grid Grid--gutters Grid--full" ng-include="'/app/admin/databases/partials/database_edit_pane.html'" >
<div class="Grid-cell Cell--2of3">
<form class="Form-new bordered rounded shadowed" name="form" novalidate>
<!-- Form -->
<div ng-include="'/app/admin/databases/partials/database_edit_forms.html'"></div>
<!-- Bottom Actions -->
<div class="Form-actions">
<button class="Button" ng-class="{'Button--primary': form.$valid}" ng-click="save(database, details)" ng-disabled="!form.$valid">
Save
</button>
<mb-form-message></mb-form-message>
</div>
</form>
</div>
<!-- Sidebar Actions -->
<div class="Grid-cell Cell--1of3" ng-if="database.id">
<div class="Actions">
<h3>Actions</h3>
<div class="Actions-group">
<button class="Button" mb-action-button="sync" success-text="Sync triggered!" failed-text="Failed to sync" active-text="Starting ...">Sync</button>
</div>
<div class="Actions-group Actions--dangerZone">
<label class="Actions-groupLabel block">Danger Zone:</label>
<!-- TODO: this doesn't do anything because its unclear if its really safe to delete dbs -->
<button class="Button Button--danger">Remove this database</button>
</div>
</div>
</div>
</section> </section>
</div> </div>
<div class="Grid-cell Cell--2of3">
<form class="Form-new bordered rounded shadowed" name="form" novalidate>
<!-- Form -->
<div ng-include="'/app/admin/databases/partials/database_edit_forms.html'"></div>
<!-- Bottom Actions -->
<div class="Form-actions">
<button class="Button" ng-class="{'Button--primary': form.$valid}" ng-click="save(database, details)" ng-disabled="!form.$valid">
Save
</button>
<mb-form-message></mb-form-message>
</div>
</form>
</div>
<!-- Sidebar Actions -->
<div class="Grid-cell Cell--1of3" ng-if="database.id">
<div class="Actions bordered rounded shadowed">
<h3>Actions</h3>
<div class="Actions-group">
<button class="Button" mb-action-button="sync" success-text="Sync triggered!" failed-text="Failed to sync" active-text="Starting ...">Sync</button>
</div>
<div class="Actions-group Actions--dangerZone">
<label class="Actions-groupLabel block">Danger Zone:</label>
<!-- TODO: this doesn't do anything because its unclear if its really safe to delete dbs -->
<button class="Button Button--danger">Remove this database</button>
</div>
</div>
</div>
...@@ -22,14 +22,13 @@ ...@@ -22,14 +22,13 @@
</tr> </tr>
<tr ng-repeat="database in databases"> <tr ng-repeat="database in databases">
<td> <td>
<a class="text-bold link" cv-org-href="/admin/databases/{{database.id}}">{{database.name}}</a> <a class="text-bold link" cv-org-href="/admin/databases/{{database.id}}/tables">{{database.name}}</a>
</td> </td>
<td> <td>
{{database.engine}} {{database.engine}}
</td> </td>
<td class="Table-actions"> <td class="Table-actions">
<!-- TODO: sync now button? --> <!-- TODO: sync now button? -->
<a class="Button" cv-org-href="/admin/databases/{{database.id}}/tables/">Tables</a>
<button class="Button Button--danger" ng-click="delete(database.id)" delete-confirm>Delete</button> <button class="Button Button--danger" ng-click="delete(database.id)" delete-confirm>Delete</button>
</td> </td>
</tr> </tr>
......
<div class="wrapper full-height flex flex-column">
<section class="my3 clearfix">
<div class="py2 float-right">
<div class="Button-group Button-group--blue text-uppercase text-bold">
<a class="Button AdminHoverItem" ng-class="{ 'Button--active': pane == 'tables' }" cv-org-href="/admin/databases/{{database.id}}/tables/{{table.id}}">Data</a>
<a class="Button AdminHoverItem" ng-class="{ 'Button--active': pane == 'settings' }" cv-org-href="/admin/databases/{{database.id}}/settings">Connection Details</a>
</div>
</div>
<h3 class="py2">{{database.name}}</h2>
</section>
<section class="DatabaseTablesAdmin Grid bordered rounded shadowed flex-full mb4" ng-show="pane == 'tables'">
<div class="DatabaseTablesAdminSidebar relative Grid-cell Cell--1of3 border-right" ng-controller="DatabaseTables" ng-include="'/app/admin/databases/partials/database_table_list.html'">
</div>
<div class="DatabaseTableAdmin relative Grid-cell" ng-controller="DatabaseTable" ng-if="table" ng-include="'/app/admin/databases/partials/database_table_detail.html'">
</div>
<div class="Grid-cell flex layout-centered relative" ng-if="!table">
<h2 class="text-grey-3">Select any table to see its schema and add or edit metadata.</h2>
</div>
</section>
<section ng-show="pane == 'settings'" ng-controller="DatabaseEdit">
<div class="Grid Grid--gutters Grid--full" ng-include="'/app/admin/databases/partials/database_edit_pane.html'" >
</div>
</section>
</div>
<svg width="0" height="0">
<defs>
<pattern id="dragger" width=".50" height=".08">
<rect width="2px" height="2px" fill="#cacaca">
</pattern>
</defs>
</svg>
<div class="wrapper">
<section class="Breadcrumbs">
<a class="Breadcrumb Breadcrumb--path" cv-org-href="/admin/databases/">Databases</a>
<cv-chevron-right-icon class="Breadcrumb-divider" width="12px" height="12px"></cv-chevron-right-icon>
<a class="Breadcrumb Breadcrumb--path" cv-org-href="/admin/databases/{{table.db.id}}/tables/">{{table.db.name}}</a>
<cv-chevron-right-icon class="Breadcrumb-divider" width="12px" height="12px"></cv-chevron-right-icon>
<h2 class="Breadcrumb Breadcrumb--page">{{table.name}}</h2>
</section>
<section>
<div class="pb2 clearfix" ng-if="table">
<div class="clearfix">
<div class="text-grey-3 float-right" ng-if="table.entity_name">
<p class="text-right">actual table name: {{table.name}}</p>
<p class="py1 text-right clearfix">
<a class="link float-right" ng-click="syncMetadata()">Sync Metadata</a>
</p>
</div>
<div class="float-left">
<h2 class="inline-block">
<a class="text-brand" href="#" ng-class="{EditedEntity: table.entity_name}" editable-text="table.entity_name" onaftersave="inlineSave()">
<span ng-if="table.entity_name">{{table.entity_name}}</span>
<span ng-if="!table.entity_name">{{table.name}}</span>
</a>
</h2>
<label class="Select mx2 inline-block">
<select ng-class="{CustomTypeApplied: table.entity_type }" ng-model="table.entity_type" ng-change="inlineSave()" ng-options="ent_type.id as ent_type.name for ent_type in utils.table_entity_types">
</select>
</label>
<div class="text-grey-4 mt1">
<a e-class="full" href="#" ng-class="{EditedEntity: table.description }" editable-text="table.description" onaftersave="inlineSave()">
{{table.description}}
<span ng-if="!table.description">Add a description ...</span>
</a>
</div>
</div>
</div>
</div>
<div class="DragBoundary mt2 border-bottom">
<ul as-sortable="dragControlListeners" ng-model="fields">
<li class="border-top py2 relative text-grey-3" ng-repeat="field in table.fields" as-sortable-item>
<div class="Drag-handle" title="Reorder" as-sortable-item-handle>
<svg width="9" height="36">
<rect class="Dragger" fill="url(#dragger)" width="6" height="42">
</svg>
</div>
<div class="ml3 mr1 clearfix">
<div class="float-right">
<span class="EntityOriginalType float-left">{{field.base_type}}</span>
</div>
<div>
<input ng-model="field.preview_display" type="checkbox" ng-change="inlineSaveField($index)">
<h3 class="text-bold inline-block">
<a class="link mr1" cv-org-href="/admin/databases/field/{{field.id}}">{{field.name}}</a>
</h3>
<label class="Select mx1">
<select ng-class="{CustomTypeApplied: field.field_type }" ng-model="field.field_type" ng-change="inlineSaveField($index)" ng-options="spec_type.id as spec_type.name for spec_type in utils.field_field_types">
</select>
</label>
<label class="Select mx1">
<select ng-class="{CustomTypeApplied: field.special_type }" ng-model="field.special_type" ng-change="inlineSpecialTypeChange($index)" ng-options="spec_type.id as spec_type.name for spec_type in utils.field_special_types">
</select>
</label>
<label class="Select mx1" ng-if="field.special_type=='fk'">
<select ng-model="field.target_id" ng-change="inlineChangeFKTarget($index)" ng-options="idf.id as idf.displayName for idf in idfields">
<option value="" disabled selected>Target Field</option>
</select>
</label>
</div>
<div class="pt1 full">
<a e-class="full" href="#" ng-class="{EditedEntity: field.description }" editable-text="field.description" onaftersave="inlineSaveField($index)">
{{field.description}}
<span ng-if="!field.description">Add a description...</span>
</a>
</div>
</div>
</li>
</ul>
</div>
</section>
</div>
\ No newline at end of file
<div class="TableField py4 pr4">
<label class="Select Select--small float-right">
<select ng-class="{CustomTypeApplied: table.entity_type, 'Select--unselected': !table.entity_type }" ng-model="table.entity_type" ng-change="inlineSave()" ng-options="ent_type.id as ent_type.name for ent_type in utils.table_entity_types"></select>
</label>
<div>
<span class="h2 text-bold" editable-text="table.entity_name" e-form="tableNameForm" onaftersave="inlineSave()">
{{table.entity_name || table.name}}
</span>
<span class="h5" ng-click="tableNameForm.$show()" ng-hide="tableNameForm.$visible">
Rename
</span>
</div>
<div class="mt2 full">
<a e-class="full" href="#" editable-text="table.description" onaftersave="console.log('nyi', $index)">
{{table.description || "Add a description..."}}
</a>
</div>
</div>
<div class="TableFieldList" mb-scroll-shadow>
<ul as-sortable="dragControlListeners" ng-model="table.fields">
<li class="TableField AdminHoverItem py2 pr4 relative" ng-repeat="field in table.fields track by field.id" as-sortable-item>
<div class="Drag-handle" title="Reorder" as-sortable-item-handle>
<svg width="9" height="36">
<rect class="Dragger" fill="url(#dragger)" width="6" height="42">
</svg>
</div>
<div class="Grid">
<div class="Grid-cell">
<input ng-model="field.preview_display" type="checkbox" ng-change="inlineSaveField($index)">
<h3 class="TableField-name inline-block">
{{field.name}}
</h3>
<span class="EntityOriginalType inline-block">{{field.base_type}}</span>
<div class="full">
<a e-class="full" href="#" ng-class="{EditedEntity: field.description }" editable-text="field.description" onaftersave="inlineSaveField($index)">
{{field.description || "Add a description..."}}
</a>
</div>
</div>
<div class="Grid Grid-cell Cell--1of3 py1 flex align-start">
<label class="Grid-cell mx2 Select Select--small Select--blue">
<select ng-model="field.field_type" ng-change="inlineSaveField($index)" ng-options="spec_type.id as spec_type.name for spec_type in utils.field_field_types">
</select>
</label>
<div class="Grid-cell flex flex-column">
<label class="Select flex-full Select--small Select--purple">
<select ng-model="field.special_type" ng-change="inlineSpecialTypeChange($index)" ng-options="spec_type.id as spec_type.name for spec_type in utils.field_special_types">
</select>
</label>
<label class="Select Select--small mt1" ng-if="field.special_type=='fk'">
<select ng-model="field.target_id" ng-change="inlineChangeFKTarget($index)" ng-options="idf.id as idf.displayName for idf in idfields">
<option value="" disabled selected>Target Field</option>
</select>
</label>
</div>
</div>
</div>
</li>
</ul>
</div>
<div class="wrapper">
<section class="Breadcrumbs">
<a class="Breadcrumb Breadcrumb--path" cv-org-href="/admin/databases/">Databases</a>
<cv-chevron-right-icon class="Breadcrumb-divider" width="12px" height="12px"></cv-chevron-right-icon>
<a class="Breadcrumb Breadcrumb--path" cv-org-href="/admin/databases/{{field.table.db.id}}/tables/">{{field.table.db.name}}</a>
<cv-chevron-right-icon class="Breadcrumb-divider" width="12px" height="12px"></cv-chevron-right-icon>
<a class="Breadcrumb Breadcrumb--path" cv-org-href="/admin/databases/table/{{field.table.id}}">{{field.table.name}}</a>
<cv-chevron-right-icon class="Breadcrumb-divider" width="12px" height="12px"></cv-chevron-right-icon>
<h2 class="Breadcrumb Breadcrumb--page">{{field.name}}</h2>
</section>
<section>
<div>
<h3>Information</h3>
<b>Data Type:</b> {{field.base_type}} <br/>
<b>User Assigned Type:</b> <a href="#" editable-select="field.special_type" onaftersave="inlineSave()" e-ng-options="spec_type.id as spec_type.name for spec_type in utils.field_special_types">{{utils.fieldSpecialType(field.special_type)}}</a> <br/>
<b>Display in preview:</b> <a href="#" editable-select="field.preview_display" onaftersave="inlineSave()" e-ng-options="spec_type.id as spec_type.name for spec_type in utils.boolean_types">{{field.preview_display && "Yes" || "No"}}</a> <br/>
<b>Description:</b> <a href="#" editable-textarea="field.description" e-rows="4" e-cols="50" onaftersave="inlineSave()">{{field.description}}<span ng-if="!field.description">Description</span></a> <br/>
<div ng-if="fks">
<b>Relationships:</b><br>
<table class="Table">
<thead>
<tr>
<th>Destination Table</th>
<th>Destination Field</th>
<th>Relationship Type</th>
<th>Delete</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="fk in fks">
<td>{{fk.destination.table.name}}</td>
<td>{{fk.destination.name}}</td>
<td>{{fk.relationship}}</td>
<td> <a class="Button Button--remove" href="#" ng-click="deleteRelationship(fk.id)" delete-confirm>x</a></td>
</tr>
</tbody>
</table>
</div>
<hr />
<cv-comments type="field" id="field.id" title="Notes"></cv-comments>
</div>
<div>
<h3>Summary</h3>
<table class="table table-striped">
<thead>
<tr>
<th>Characteristic</th>
<th>Value</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="item in field_summary">
<td>{{item[0]}}</td>
<td>{{item[1]}}</td>
</tr>
</tbody>
</table>
<div class="border-top py2 clearfix">
<div class="py2">
<input class="Button Button--primary float-right" type="button" value="Update Mapped Values" role="button" ng-click="updateMappedValues()" />
<h3>Valid Values</h3>
</div>
<table class="Table">
<thead>
<tr>
<th>Value</th>
<th>Remapped Value</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="value in field_values.values">
<td>{{value || "Empty Field"}}</td>
<td> <input class="input" ng-model="field_values.human_readable_values[value]"> </td>
</tr>
</tbody>
</table>
</div>
</div>
</section>
</div>
<div class="border-bottom py1">
<cv-search-icon class="ml2 text-grey-2" width="18" height="18"></cv-search-icon>
<input class="Form-input Form-input--medium mx1" type="text" placeholder="Search for a table name" value="" ng-model="tableSearchText" autofocus>
</div>
<div class="DatabaseList" mb-scroll-shadow>
<ul class="p2">
<li class="flex flex-column layout-centered full-height text-grey-3" ng-show="!tables">
<cv-loading-icon class="text-brand"></cv-loading-icon>
<h3>Loading ...</h3>
</li>
<li class="DatabaseListItem AdminHoverItem rounded py1 px2 text-grey-4" ng-class="{ 'DatabaseListItem--active': t.id == table.id }" ng-repeat="t in tables | filter:tableSearchText">
<a class="link link--nohover text-current" cv-org-href="/admin/databases/{{database.id}}/tables/{{t.id}}">
<h4>{{t.name}}</h4>
</a>
</li>
</ul>
</div>
<div class="wrapper">
<section class="Breadcrumbs">
<a class="Breadcrumb Breadcrumb--path" cv-org-href="/admin/databases/">Databases</a>
<cv-chevron-right-icon class="Breadcrumb-divider" width="12px" height="12px"></cv-chevron-right-icon>
<h2 class="Breadcrumb Breadcrumb--page">{{database.name}}</h2>
<cv-chevron-right-icon class="Breadcrumb-divider" width="12px" height="12px"></cv-chevron-right-icon>
<h2 class="Breadcrumb Breadcrumb--page">Tables</h2>
</section>
<section>
<table class="ContentTable">
<thead>
<tr>
<th>Table</th>
<th>Rows</th>
</tr>
</thead>
<tbody>
<tr ng-show="!tables">
<td colspan=4>
<cv-loading-icon></cv-loading-icon>
<h3>Loading ...</h3>
</td>
</tr>
<tr ng-repeat="table in tables">
<td>
<a class="text-bold link" cv-org-href="/admin/databases/table/{{table.id}}">{{table.name}}</a>
</td>
<td>
{{table.rows}}
</td>
</tr>
</tbody>
</table>
</section>
</div>
<section class="wrapper">
<div ng-repeat="db in databases">
<div class="py2 clearfix">
<div class="float-right">
<a class="Button Button--primary" ng-click="syncDatabase(db.id)">Re-Sync Database</a>
</div>
<h2>{{db.name}}</h2>
</div>
<ul class="bg-white bordered rounded shadowed">
<li class="p2 border-bottom" ng-repeat="table in db.tables">
<h4>
<a class="EntityListItem link" ng-class="{ EditedEntity: table.entity_name, EditedEntityMarker: table.entity_name }" cv-org-href="/admin/datasets/{{table.id}}">
<span class="ModifiedEntity">{{table.entity_name}}</span>
<span ng-if="!table.entity_name">{{table.name}}</span>
</a>
</h4>
</li>
</ul>
</div>
</section>
...@@ -70,6 +70,7 @@ ...@@ -70,6 +70,7 @@
border-bottom: none; border-bottom: none;
border-right: none; border-right: none;
border-radius: 0; border-radius: 0;
box-shadow: none;
} }
.Button-group .Button--active { .Button-group .Button--active {
...@@ -81,6 +82,19 @@ ...@@ -81,6 +82,19 @@
border-left: none; border-left: none;
} }
.Button-group--blue {
border-color: rgb(194,216,242);
}
.Button-group--blue .Button {
color: rgb(147,155,178);
}
.Button-group--blue .Button--active {
background-color: rgb(227,238,250);
color: rgb(74,144,226);
}
.Button:disabled { .Button:disabled {
opacity: 0.5; opacity: 0.5;
cursor: not-allowed; cursor: not-allowed;
......
...@@ -2,6 +2,8 @@ ...@@ -2,6 +2,8 @@
--form-padding: 1em; --form-padding: 1em;
--form-input-placeholder-color: #C0C0C0; --form-input-placeholder-color: #C0C0C0;
--form-input-size: 1.571rem; --form-input-size: 1.571rem;
--form-input-size-medium: 1.25rem;
--form-input-size-small: 1.0rem;
--form-label-color: #949494; --form-label-color: #949494;
--form-offset: 2.4rem; --form-offset: 2.4rem;
...@@ -54,6 +56,14 @@ ...@@ -54,6 +56,14 @@
font-family: var(--default-font-family); font-family: var(--default-font-family);
} }
.Form-input--medium {
font-size: var(--form-input-size-medium);
}
.Form-input--small {
font-size: var(--form-input-size-small);
}
.Form-input:focus { .Form-input:focus {
outline: none; outline: none;
} }
......
<svg viewBox="0 0 66 85" ng-attr-width="{{width}}" ng-attr-height="{{height}}"> <svg viewBox="0 0 66 85" ng-attr-width="{{width}}" ng-attr-height="{{height}}" fill="currentcolor">
<g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd"> <path d="M46.8253288,70.4935014 C49.5764899,70.4935014 51.8067467,68.1774705 51.8067467,65.3205017 C51.8067467,62.4635329 49.5764899,60.147502 46.8253288,60.147502 C44.0741676,60.147502 41.8439108,62.4635329 41.8439108,65.3205017 C41.8439108,68.1774705 44.0741676,70.4935014 46.8253288,70.4935014 Z M32.8773585,84.9779005 C35.6285197,84.9779005 37.8587764,82.6618697 37.8587764,79.8049008 C37.8587764,76.947932 35.6285197,74.6319011 32.8773585,74.6319011 C30.1261973,74.6319011 27.8959405,76.947932 27.8959405,79.8049008 C27.8959405,82.6618697 30.1261973,84.9779005 32.8773585,84.9779005 Z M32.8773585,70.4935014 C35.6285197,70.4935014 37.8587764,68.1774705 37.8587764,65.3205017 C37.8587764,62.4635329 35.6285197,60.147502 32.8773585,60.147502 C30.1261973,60.147502 27.8959405,62.4635329 27.8959405,65.3205017 C27.8959405,68.1774705 30.1261973,70.4935014 32.8773585,70.4935014 Z M18.9293882,70.4935014 C21.6805494,70.4935014 23.9108062,68.1774705 23.9108062,65.3205017 C23.9108062,62.4635329 21.6805494,60.147502 18.9293882,60.147502 C16.1782271,60.147502 13.9479703,62.4635329 13.9479703,65.3205017 C13.9479703,68.1774705 16.1782271,70.4935014 18.9293882,70.4935014 Z M46.8253288,56.0091023 C49.5764899,56.0091023 51.8067467,53.6930714 51.8067467,50.8361026 C51.8067467,47.9791337 49.5764899,45.6631029 46.8253288,45.6631029 C44.0741676,45.6631029 41.8439108,47.9791337 41.8439108,50.8361026 C41.8439108,53.6930714 44.0741676,56.0091023 46.8253288,56.0091023 Z M18.9293882,56.0091023 C21.6805494,56.0091023 23.9108062,53.6930714 23.9108062,50.8361026 C23.9108062,47.9791337 21.6805494,45.6631029 18.9293882,45.6631029 C16.1782271,45.6631029 13.9479703,47.9791337 13.9479703,50.8361026 C13.9479703,53.6930714 16.1782271,56.0091023 18.9293882,56.0091023 Z M46.8253288,26.8995984 C49.5764899,26.8995984 51.8067467,24.5835675 51.8067467,21.7265987 C51.8067467,18.8696299 49.5764899,16.553599 46.8253288,16.553599 C44.0741676,16.553599 41.8439108,18.8696299 41.8439108,21.7265987 C41.8439108,24.5835675 44.0741676,26.8995984 46.8253288,26.8995984 Z M32.8773585,41.5247031 C35.6285197,41.5247031 37.8587764,39.2086723 37.8587764,36.3517034 C37.8587764,33.4947346 35.6285197,31.1787037 32.8773585,31.1787037 C30.1261973,31.1787037 27.8959405,33.4947346 27.8959405,36.3517034 C27.8959405,39.2086723 30.1261973,41.5247031 32.8773585,41.5247031 Z M32.8773585,10.3459994 C35.6285197,10.3459994 37.8587764,8.02996853 37.8587764,5.17299969 C37.8587764,2.31603085 35.6285197,0 32.8773585,0 C30.1261973,0 27.8959405,2.31603085 27.8959405,5.17299969 C27.8959405,8.02996853 30.1261973,10.3459994 32.8773585,10.3459994 Z M32.8773585,26.8995984 C35.6285197,26.8995984 37.8587764,24.5835675 37.8587764,21.7265987 C37.8587764,18.8696299 35.6285197,16.553599 32.8773585,16.553599 C30.1261973,16.553599 27.8959405,18.8696299 27.8959405,21.7265987 C27.8959405,24.5835675 30.1261973,26.8995984 32.8773585,26.8995984 Z M18.9293882,26.8995984 C21.6805494,26.8995984 23.9108062,24.5835675 23.9108062,21.7265987 C23.9108062,18.8696299 21.6805494,16.553599 18.9293882,16.553599 C16.1782271,16.553599 13.9479703,18.8696299 13.9479703,21.7265987 C13.9479703,24.5835675 16.1782271,26.8995984 18.9293882,26.8995984 Z" opacity="0.2"></path>
<g id="logo"fill="#4990E2"> <path d="M60.773299,70.4935014 C63.5244602,70.4935014 65.754717,68.1774705 65.754717,65.3205017 C65.754717,62.4635329 63.5244602,60.147502 60.773299,60.147502 C58.0221379,60.147502 55.7918811,62.4635329 55.7918811,65.3205017 C55.7918811,68.1774705 58.0221379,70.4935014 60.773299,70.4935014 Z M4.98141795,70.3527958 C7.73257912,70.3527958 9.96283591,68.0367649 9.96283591,65.1797961 C9.96283591,62.3228273 7.73257912,60.0067964 4.98141795,60.0067964 C2.23025679,60.0067964 0,62.3228273 0,65.1797961 C0,68.0367649 2.23025679,70.3527958 4.98141795,70.3527958 Z M60.773299,56.0091023 C63.5244602,56.0091023 65.754717,53.6930714 65.754717,50.8361026 C65.754717,47.9791337 63.5244602,45.6631029 60.773299,45.6631029 C58.0221379,45.6631029 55.7918811,47.9791337 55.7918811,50.8361026 C55.7918811,53.6930714 58.0221379,56.0091023 60.773299,56.0091023 Z M32.8773585,56.0091023 C35.6285197,56.0091023 37.8587764,53.6930714 37.8587764,50.8361026 C37.8587764,47.9791337 35.6285197,45.6631029 32.8773585,45.6631029 C30.1261973,45.6631029 27.8959405,47.9791337 27.8959405,50.8361026 C27.8959405,53.6930714 30.1261973,56.0091023 32.8773585,56.0091023 Z M4.98141795,55.8683967 C7.73257912,55.8683967 9.96283591,53.5523658 9.96283591,50.695397 C9.96283591,47.8384281 7.73257912,45.5223973 4.98141795,45.5223973 C2.23025679,45.5223973 0,47.8384281 0,50.695397 C0,53.5523658 2.23025679,55.8683967 4.98141795,55.8683967 Z M60.773299,41.5247031 C63.5244602,41.5247031 65.754717,39.2086723 65.754717,36.3517034 C65.754717,33.4947346 63.5244602,31.1787037 60.773299,31.1787037 C58.0221379,31.1787037 55.7918811,33.4947346 55.7918811,36.3517034 C55.7918811,39.2086723 58.0221379,41.5247031 60.773299,41.5247031 Z M46.8253288,41.5247031 C49.5764899,41.5247031 51.8067467,39.2086723 51.8067467,36.3517034 C51.8067467,33.4947346 49.5764899,31.1787037 46.8253288,31.1787037 C44.0741676,31.1787037 41.8439108,33.4947346 41.8439108,36.3517034 C41.8439108,39.2086723 44.0741676,41.5247031 46.8253288,41.5247031 Z M60.773299,26.8995984 C63.5244602,26.8995984 65.754717,24.5835675 65.754717,21.7265987 C65.754717,18.8696299 63.5244602,16.553599 60.773299,16.553599 C58.0221379,16.553599 55.7918811,18.8696299 55.7918811,21.7265987 C55.7918811,24.5835675 58.0221379,26.8995984 60.773299,26.8995984 Z M18.9293882,41.5247031 C21.6805494,41.5247031 23.9108062,39.2086723 23.9108062,36.3517034 C23.9108062,33.4947346 21.6805494,31.1787037 18.9293882,31.1787037 C16.1782271,31.1787037 13.9479703,33.4947346 13.9479703,36.3517034 C13.9479703,39.2086723 16.1782271,41.5247031 18.9293882,41.5247031 Z M4.98141795,41.3839975 C7.73257912,41.3839975 9.96283591,39.0679667 9.96283591,36.2109978 C9.96283591,33.354029 7.73257912,31.0379981 4.98141795,31.0379981 C2.23025679,31.0379981 0,33.354029 0,36.2109978 C0,39.0679667 2.23025679,41.3839975 4.98141795,41.3839975 Z M4.98141795,26.8995984 C7.73257912,26.8995984 9.96283591,24.5835675 9.96283591,21.7265987 C9.96283591,18.8696299 7.73257912,16.553599 4.98141795,16.553599 C2.23025679,16.553599 0,18.8696299 0,21.7265987 C0,24.5835675 2.23025679,26.8995984 4.98141795,26.8995984 Z"></path>
<path d="M46.8253288,70.4935014 C49.5764899,70.4935014 51.8067467,68.1774705 51.8067467,65.3205017 C51.8067467,62.4635329 49.5764899,60.147502 46.8253288,60.147502 C44.0741676,60.147502 41.8439108,62.4635329 41.8439108,65.3205017 C41.8439108,68.1774705 44.0741676,70.4935014 46.8253288,70.4935014 Z M32.8773585,84.9779005 C35.6285197,84.9779005 37.8587764,82.6618697 37.8587764,79.8049008 C37.8587764,76.947932 35.6285197,74.6319011 32.8773585,74.6319011 C30.1261973,74.6319011 27.8959405,76.947932 27.8959405,79.8049008 C27.8959405,82.6618697 30.1261973,84.9779005 32.8773585,84.9779005 Z M32.8773585,70.4935014 C35.6285197,70.4935014 37.8587764,68.1774705 37.8587764,65.3205017 C37.8587764,62.4635329 35.6285197,60.147502 32.8773585,60.147502 C30.1261973,60.147502 27.8959405,62.4635329 27.8959405,65.3205017 C27.8959405,68.1774705 30.1261973,70.4935014 32.8773585,70.4935014 Z M18.9293882,70.4935014 C21.6805494,70.4935014 23.9108062,68.1774705 23.9108062,65.3205017 C23.9108062,62.4635329 21.6805494,60.147502 18.9293882,60.147502 C16.1782271,60.147502 13.9479703,62.4635329 13.9479703,65.3205017 C13.9479703,68.1774705 16.1782271,70.4935014 18.9293882,70.4935014 Z M46.8253288,56.0091023 C49.5764899,56.0091023 51.8067467,53.6930714 51.8067467,50.8361026 C51.8067467,47.9791337 49.5764899,45.6631029 46.8253288,45.6631029 C44.0741676,45.6631029 41.8439108,47.9791337 41.8439108,50.8361026 C41.8439108,53.6930714 44.0741676,56.0091023 46.8253288,56.0091023 Z M18.9293882,56.0091023 C21.6805494,56.0091023 23.9108062,53.6930714 23.9108062,50.8361026 C23.9108062,47.9791337 21.6805494,45.6631029 18.9293882,45.6631029 C16.1782271,45.6631029 13.9479703,47.9791337 13.9479703,50.8361026 C13.9479703,53.6930714 16.1782271,56.0091023 18.9293882,56.0091023 Z M46.8253288,26.8995984 C49.5764899,26.8995984 51.8067467,24.5835675 51.8067467,21.7265987 C51.8067467,18.8696299 49.5764899,16.553599 46.8253288,16.553599 C44.0741676,16.553599 41.8439108,18.8696299 41.8439108,21.7265987 C41.8439108,24.5835675 44.0741676,26.8995984 46.8253288,26.8995984 Z M32.8773585,41.5247031 C35.6285197,41.5247031 37.8587764,39.2086723 37.8587764,36.3517034 C37.8587764,33.4947346 35.6285197,31.1787037 32.8773585,31.1787037 C30.1261973,31.1787037 27.8959405,33.4947346 27.8959405,36.3517034 C27.8959405,39.2086723 30.1261973,41.5247031 32.8773585,41.5247031 Z M32.8773585,10.3459994 C35.6285197,10.3459994 37.8587764,8.02996853 37.8587764,5.17299969 C37.8587764,2.31603085 35.6285197,0 32.8773585,0 C30.1261973,0 27.8959405,2.31603085 27.8959405,5.17299969 C27.8959405,8.02996853 30.1261973,10.3459994 32.8773585,10.3459994 Z M32.8773585,26.8995984 C35.6285197,26.8995984 37.8587764,24.5835675 37.8587764,21.7265987 C37.8587764,18.8696299 35.6285197,16.553599 32.8773585,16.553599 C30.1261973,16.553599 27.8959405,18.8696299 27.8959405,21.7265987 C27.8959405,24.5835675 30.1261973,26.8995984 32.8773585,26.8995984 Z M18.9293882,26.8995984 C21.6805494,26.8995984 23.9108062,24.5835675 23.9108062,21.7265987 C23.9108062,18.8696299 21.6805494,16.553599 18.9293882,16.553599 C16.1782271,16.553599 13.9479703,18.8696299 13.9479703,21.7265987 C13.9479703,24.5835675 16.1782271,26.8995984 18.9293882,26.8995984 Z" id="Oval-14" opacity="0.2"></path>
<path d="M60.773299,70.4935014 C63.5244602,70.4935014 65.754717,68.1774705 65.754717,65.3205017 C65.754717,62.4635329 63.5244602,60.147502 60.773299,60.147502 C58.0221379,60.147502 55.7918811,62.4635329 55.7918811,65.3205017 C55.7918811,68.1774705 58.0221379,70.4935014 60.773299,70.4935014 Z M4.98141795,70.3527958 C7.73257912,70.3527958 9.96283591,68.0367649 9.96283591,65.1797961 C9.96283591,62.3228273 7.73257912,60.0067964 4.98141795,60.0067964 C2.23025679,60.0067964 0,62.3228273 0,65.1797961 C0,68.0367649 2.23025679,70.3527958 4.98141795,70.3527958 Z M60.773299,56.0091023 C63.5244602,56.0091023 65.754717,53.6930714 65.754717,50.8361026 C65.754717,47.9791337 63.5244602,45.6631029 60.773299,45.6631029 C58.0221379,45.6631029 55.7918811,47.9791337 55.7918811,50.8361026 C55.7918811,53.6930714 58.0221379,56.0091023 60.773299,56.0091023 Z M32.8773585,56.0091023 C35.6285197,56.0091023 37.8587764,53.6930714 37.8587764,50.8361026 C37.8587764,47.9791337 35.6285197,45.6631029 32.8773585,45.6631029 C30.1261973,45.6631029 27.8959405,47.9791337 27.8959405,50.8361026 C27.8959405,53.6930714 30.1261973,56.0091023 32.8773585,56.0091023 Z M4.98141795,55.8683967 C7.73257912,55.8683967 9.96283591,53.5523658 9.96283591,50.695397 C9.96283591,47.8384281 7.73257912,45.5223973 4.98141795,45.5223973 C2.23025679,45.5223973 0,47.8384281 0,50.695397 C0,53.5523658 2.23025679,55.8683967 4.98141795,55.8683967 Z M60.773299,41.5247031 C63.5244602,41.5247031 65.754717,39.2086723 65.754717,36.3517034 C65.754717,33.4947346 63.5244602,31.1787037 60.773299,31.1787037 C58.0221379,31.1787037 55.7918811,33.4947346 55.7918811,36.3517034 C55.7918811,39.2086723 58.0221379,41.5247031 60.773299,41.5247031 Z M46.8253288,41.5247031 C49.5764899,41.5247031 51.8067467,39.2086723 51.8067467,36.3517034 C51.8067467,33.4947346 49.5764899,31.1787037 46.8253288,31.1787037 C44.0741676,31.1787037 41.8439108,33.4947346 41.8439108,36.3517034 C41.8439108,39.2086723 44.0741676,41.5247031 46.8253288,41.5247031 Z M60.773299,26.8995984 C63.5244602,26.8995984 65.754717,24.5835675 65.754717,21.7265987 C65.754717,18.8696299 63.5244602,16.553599 60.773299,16.553599 C58.0221379,16.553599 55.7918811,18.8696299 55.7918811,21.7265987 C55.7918811,24.5835675 58.0221379,26.8995984 60.773299,26.8995984 Z M18.9293882,41.5247031 C21.6805494,41.5247031 23.9108062,39.2086723 23.9108062,36.3517034 C23.9108062,33.4947346 21.6805494,31.1787037 18.9293882,31.1787037 C16.1782271,31.1787037 13.9479703,33.4947346 13.9479703,36.3517034 C13.9479703,39.2086723 16.1782271,41.5247031 18.9293882,41.5247031 Z M4.98141795,41.3839975 C7.73257912,41.3839975 9.96283591,39.0679667 9.96283591,36.2109978 C9.96283591,33.354029 7.73257912,31.0379981 4.98141795,31.0379981 C2.23025679,31.0379981 0,33.354029 0,36.2109978 C0,39.0679667 2.23025679,41.3839975 4.98141795,41.3839975 Z M4.98141795,26.8995984 C7.73257912,26.8995984 9.96283591,24.5835675 9.96283591,21.7265987 C9.96283591,18.8696299 7.73257912,16.553599 4.98141795,16.553599 C2.23025679,16.553599 0,18.8696299 0,21.7265987 C0,24.5835675 2.23025679,26.8995984 4.98141795,26.8995984 Z" id="Oval-14" sketch:type="MSShapeGroup"></path>
</g>
</g>
</svg> </svg>
...@@ -17,10 +17,8 @@ ...@@ -17,10 +17,8 @@
.Select:after { .Select:after {
content: ''; content: '';
position: absolute; position: absolute;
top: 50%; top: 50%;
right: 1rem; right: 0;
width: 0; width: 0;
height: 0; height: 0;
pointer-events: none; /* no clicks since arrow is just for appearance */ pointer-events: none; /* no clicks since arrow is just for appearance */
...@@ -60,6 +58,43 @@ ...@@ -60,6 +58,43 @@
box-shadow: 0 1px 2px rgba(0, 0, 0, .12); box-shadow: 0 1px 2px rgba(0, 0, 0, .12);
} }
.Select--blue select {
color: rgb(78,146,223);
border-color: rgb(195,216,241);
background-color: rgb(227,238,249);
}
.Select--blue:after {
border-top: .3rem solid rgb(78,146,223);
}
.Select--blue:before {
border-bottom: .3rem solid rgb(78,146,223);
}
.Select--purple select {
color: rgb(168,138,195);
border-color: rgb(203,186,219);
background-color: rgb(231,223,239);
}
.Select--purple:after {
border-top: .3rem solid rgb(168,138,195);
}
.Select--purple:before {
border-bottom: .3rem solid rgb(168,138,195);
}
.Select--small select {
padding: 0.25rem 1.5rem 0.25rem 0.5rem;
font-size: 0.7em;
line-height: 1.5em;
}
.Select--small:after {
margin-top: -.1rem;
right: 0.5em;
}
.Select--small:before {
border-bottom: none;
}
.Select select:focus { .Select select:focus {
outline: none; outline: none;
} }
...@@ -37,6 +37,12 @@ ...@@ -37,6 +37,12 @@
display: none; display: none;
} }
/* utility to get a simple common hover state for admin items */
.AdminHoverItem:hover {
background-color: #F3F8FD;
transition: background .2s linear;
}
.UserNick { .UserNick {
border-width: 1px; border-width: 1px;
border-style: solid; border-style: solid;
...@@ -130,6 +136,7 @@ ...@@ -130,6 +136,7 @@
padding: 1em; padding: 1em;
} }
/* TODO: remove this and apply AdminHoverItem to content rows */
.ContentTable tbody tr:hover { .ContentTable tbody tr:hover {
background-color: rgba(74, 144, 226, 0.04); background-color: rgba(74, 144, 226, 0.04);
} }
...@@ -139,7 +146,62 @@ ...@@ -139,7 +146,62 @@
transition: opacity .2s linear; transition: opacity .2s linear;
} }
.DatabaseList,
.TableFieldList {
padding-bottom: 3em;
position: absolute;
left: 0;
right: 0;
height: 100%;
overflow-y: scroll;
}
.DatabaseListItem .h4 {
line-height: 0.8em;
}
.DatabaseListItem.DatabaseListItem--active {
background-color: rgb(227,238,250);
color: rgb(74,144,226);
}
/* TODO: this is for the ace editor and should be handled without an ID */ /* TODO: this is for the ace editor and should be handled without an ID */
#id_sql { #id_sql {
height: 200px; height: 200px;
} }
.DatabaseTablesAdmin {
overflow: hidden;
}
.TableField {
border-bottom: 1px solid #F0F0F0;
padding-left: 3em;
}
.TableField-name {
color: #676C72;
}
.DatabaseTablesAdmin .editable-click {
font-size: 0.8em;
border-bottom: none;
font-style: normal;
}
.DatabaseTablesAdmin .editable-click:hover, .DatabaseTablesAdmin .editable-empty:hover {
color: inherit !important;
font-style: normal;
}
.DatabaseTablesAdmin .editable-empty {
font-style: normal;
}
.Select--unselected {
border-style: dotted !important;
}
.ScrollShadow {
border-top: 1px solid rgba(0, 0, 0, .05);
box-shadow: 0 -1px 0 rgba(0, 0, 0, .12);
}
:root { :root {
--default-font-family: "Lato"; --default-font-family: "Lato";
--default-font-size: 1em; --default-font-size: 1em;
--default-font-color: #727479;
} }
html { html {
...@@ -10,8 +11,8 @@ html { ...@@ -10,8 +11,8 @@ html {
body { body {
font-family: var(--default-font-family), "Helvetica Neue", Helvetica, sans-serif; font-family: var(--default-font-family), "Helvetica Neue", Helvetica, sans-serif;
font-size: var(--default-font-size); font-size: var(--default-font-size);
color: var(--default-font-color);
margin: 0; margin: 0;
box-sizing: border-box;
height: 100%; /* ensure the entire page will fill the window */ height: 100%; /* ensure the entire page will fill the window */
display: flex; display: flex;
flex-direction: column; flex-direction: column;
......
/* set main elements to box-sizing border-box for more reliable box model calc */ /* set main elements to box-sizing border-box for more reliable box model calc */
body,
div, div,
nav, nav,
article, article,
......
...@@ -208,7 +208,6 @@ ...@@ -208,7 +208,6 @@
} }
} }
.Grid-cell.Cell--1of3 { .Grid-cell.Cell--1of3 {
flex: 0 0 33.3333%; flex: 0 0 33.3333%;
} }
......
:root { :root {
--default-header-margin: 0.5em; --default-header-margin: 0.5em;
--default-header-text-color: #727479;
} }
h1, h1, .h1,
.h1, h2, .h2,
h2, h3, .h3,
.h2, h4, .h4,
h3, h5, .h5,
.h3, h6, .h6 {
h4,
.h4,
h5,
.h5,
h6,
.h6 {
margin-top: var(--default-header-margin); margin-top: var(--default-header-margin);
margin-bottom: var(--default-header-margin); margin-bottom: var(--default-header-margin);
color: var(--default-header-text-color);
} }
.h1 { font-size: 2em; } .h1 { font-size: 2em; }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment