diff --git a/config/demo-staging.json b/config/demo-staging.json index 6853960a..0ee26330 100644 --- a/config/demo-staging.json +++ b/config/demo-staging.json @@ -1,6 +1,6 @@ { "useStrict" : "use strict", - "apiUrl" : "http://api.demo.staging.ottemo.io", - "mediaPath" : "http://demo.staging.ottemo.io/media/", + "apiUrl" : "https://api.demo.staging.ottemo.io", + "mediaPath" : "https://demo.staging.ottemo.io/media/", "itemsPerPage" : "15" } \ No newline at end of file diff --git a/config/dev.json b/config/dev.json index dbec0791..bea8df88 100644 --- a/config/dev.json +++ b/config/dev.json @@ -1,6 +1,6 @@ { "useStrict" : "use strict", - "apiUrl" : "http://api.dev.ottemo.io", - "mediaPath" : "http://dev.ottemo.io/media/", + "apiUrl" : "https://api.dev.ottemo.io", + "mediaPath" : "https://dev.ottemo.io/media/", "itemsPerPage" : "15" } \ No newline at end of file diff --git a/config/kg-staging.json b/config/kg-staging.json index 9f683d98..7032393b 100644 --- a/config/kg-staging.json +++ b/config/kg-staging.json @@ -1,6 +1,6 @@ { "useStrict" : "use strict", - "apiUrl" : "http://api.kg.staging.ottemo.io", - "mediaPath" : "http://kg.staging.ottemo.io/media/", + "apiUrl" : "https://api.kg.staging.ottemo.io", + "mediaPath" : "https://kg.staging.ottemo.io/media/", "itemsPerPage" : "15" } diff --git a/config/mp-staging.json b/config/mp-staging.json index 28418235..de9169bd 100644 --- a/config/mp-staging.json +++ b/config/mp-staging.json @@ -1,6 +1,6 @@ { "useStrict" : "use strict", - "apiUrl" : "http://api.mp.staging.ottemo.io", - "mediaPath" : "http://mp.staging.ottemo.io/media/", + "apiUrl" : "https://api.mp.staging.ottemo.io", + "mediaPath" : "https://mp.staging.ottemo.io/media/", "itemsPerPage" : "15" -} \ No newline at end of file +} diff --git a/config/rk-staging.json b/config/rk-staging.json index 66113338..e1f41d4b 100644 --- a/config/rk-staging.json +++ b/config/rk-staging.json @@ -1,7 +1,7 @@ { "useStrict" : "use strict", - "apiUrl" : "http://api.rk.staging.ottemo.io", - "mediaPath" : "http://rk.staging.ottemo.io/media/", + "apiUrl" : "https://api.rk.staging.ottemo.io", + "mediaPath" : "https://rk.staging.ottemo.io/media/", "itemsPerPage" : "15" } diff --git a/config/sb-prod.json b/config/sb-prod.json new file mode 100644 index 00000000..abb3d13b --- /dev/null +++ b/config/sb-prod.json @@ -0,0 +1,6 @@ +{ + "useStrict" : "use strict", + "apiUrl" : "https://api.mystembox.com", + "mediaPath" : "https://mystembox.com/media/", + "itemsPerPage" : "15" +} \ No newline at end of file diff --git a/config/sb-staging.json b/config/sb-staging.json new file mode 100644 index 00000000..a126c26d --- /dev/null +++ b/config/sb-staging.json @@ -0,0 +1,6 @@ +{ + "useStrict" : "use strict", + "apiUrl" : "https://api.sb.staging.ottemo.io", + "mediaPath" : "https://sb.staging.ottemo.io/media/", + "itemsPerPage" : "15" +} \ No newline at end of file diff --git a/config/scs-prod.json b/config/scs-prod.json new file mode 100644 index 00000000..886eb592 --- /dev/null +++ b/config/scs-prod.json @@ -0,0 +1,6 @@ +{ + "useStrict" : "use strict", + "apiUrl" : "https://api.southcoastswords.com", + "mediaPath" : "https://southcoastswords.com/media/", + "itemsPerPage" : "15" +} \ No newline at end of file diff --git a/config/scs-staging.json b/config/scs-staging.json new file mode 100644 index 00000000..8860294c --- /dev/null +++ b/config/scs-staging.json @@ -0,0 +1,6 @@ +{ + "useStrict" : "use strict", + "apiUrl" : "https://api.scs.staging.ottemo.io", + "mediaPath" : "https://scs.staging.ottemo.io/media/", + "itemsPerPage" : "15" +} \ No newline at end of file diff --git a/deploy.sh b/deploy.sh index 5038cdd0..1e460135 100644 --- a/deploy.sh +++ b/deploy.sh @@ -23,7 +23,11 @@ if [ "$BRANCH" == 'develop' ]; then elif [ "$REMOTE_HOST" == 'demo.staging.ottemo.io' ]; then HOST=demo-staging elif [ "$REMOTE_HOST" == 'mp.staging.ottemo.io' ]; then - HOST=mp-staging + HOST=mp-staging + elif [ "$REMOTE_HOST" == 'sb.staging.ottemo.io' ]; then + HOST=sb-staging + elif [ "$REMOTE_HOST" == 'scs.staging.ottemo.io' ]; then + HOST=scs-staging fi # gulp build on remote host ssh ottemo@$REMOTE_HOST "cd $SRCDIR && npm install && gulp build --env=staging --config=${HOST}" diff --git a/package.json b/package.json index 02005906..9eb4e81e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "Dashboard", - "version": "1.1.16", + "version": "1.1.22", "description": "Ottemo Administration Tool", "main": "gulpfile.js", "repository": { diff --git a/shippable.yml b/shippable.yml index a54f28fc..6e46c45b 100644 --- a/shippable.yml +++ b/shippable.yml @@ -25,6 +25,8 @@ after_success: - REMOTE_HOST=rk.staging.ottemo.io bash deploy.sh - REMOTE_HOST=demo.staging.ottemo.io bash deploy.sh - REMOTE_HOST=mp.staging.ottemo.io bash deploy.sh + - REMOTE_HOST=sb.staging.ottemo.io bash deploy.sh + - REMOTE_HOST=scs.staging.ottemo.io bash deploy.sh - python slack_notifier.py --org $SLACK_ORG --project $PROJECT --token $SLACK_TOKEN -s notifications: diff --git a/src/app/_styles/bootstrap/_variables.scss b/src/app/_styles/bootstrap/_variables.scss index 86322bc5..fc2f5162 100755 --- a/src/app/_styles/bootstrap/_variables.scss +++ b/src/app/_styles/bootstrap/_variables.scss @@ -353,7 +353,7 @@ $container-lg: $container-large-desktop !default; //## // Basics of a navbar -$navbar-height: 60px !default; +$navbar-height: 47px !default; $navbar-margin-bottom: $line-height-computed !default; $navbar-border-radius: $border-radius-base !default; $navbar-padding-horizontal: floor(($grid-gutter-width / 2)) !default; diff --git a/src/app/_styles/components/navigation.scss b/src/app/_styles/components/navigation.scss index 5553ffae..e99b4d9f 100644 --- a/src/app/_styles/components/navigation.scss +++ b/src/app/_styles/components/navigation.scss @@ -23,24 +23,30 @@ body { width: 100%; } +// xs navbar +.navbar-default .navbar-nav { + float: right; + margin: 4px -15px; + @media (min-width: $screen-sm-min) { + margin: 0; + } +} .navbar-brand { font-size: 22px; > img { display: inline-block; - height: 20px; - vertical-align: top; - position: relative; - top: -2px; - margin-right: 10px; + margin: -2px 2px 0 0; + width: 21px; } } +// real menu, in sidebar .nav-menu { position: fixed; right: -$nav-width; top: 0; - + z-index: 1001; width: $nav-width; height: 100%; @@ -62,7 +68,6 @@ body { } &.nav-menu--active { - z-index: 20; right:0; -webkit-transition: all 0.4s ease; transition: all 0.4s ease; @@ -73,16 +78,6 @@ body { left:0; right: auto; } - - @media (min-width: $nav-break) and (min-height: 570px) { - .navbar-user { - position: absolute; - bottom: 0; - width: 100%; - border-bottom: 0; - border-top: 1px #343438 solid; - } - } } .nav-menu { @@ -91,7 +86,7 @@ body { padding: 0; } - a { + .menu-link { display: block; line-height: 1; font-size: 16px; @@ -101,32 +96,14 @@ body { padding: 15px 0px 15px 15px; border-bottom: 1px #343438 solid; position: relative; - transition: all 0.4s ease; &:hover { background: $navbar-default-link-hover-bg; color: $navbar-default-link-hover-color; - transition: all 0.4s ease; } &.active { background: $navbar-default-link-active-bg; color: $navbar-default-link-active-color; - transition: all 0.4s ease; - } - } - - - .navbar-branding { - height: 59px; - line-height: 59px; - padding: 1px 0 0 15px; - font-size: 22px; - color: #fff; - - img { - width: 20px; - margin-right: 10px; - vertical-align: baseline; } } @@ -139,6 +116,49 @@ body { right: 0; } } +.menu-item__user { + .fa { + margin-top: -5px; + margin-right: 2px; + } + .branding { + font-size: 22px; + color: #fff; + } + .fa-angle-down { + font-size: 14px; + margin-left: 3px; + color: #98978B; + } + .user-name { + margin-top: 5px; + font-size: 14px; + } +} +.user-menu-dropdown { + z-index: 1002; + margin-left: 12px; + margin-top: -10px; + border-color: #343438; + overflow: hidden; // prevent :hover bg from ruining border-radius + width: 250px; + + .menu-header { + padding: 3px 20px; + img { + float: left; + margin: 0 12px 0 0; + } + div { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + } + } + .divider { + margin: 3px 0; + } +} .nav-menu { .sub-menu { @@ -147,16 +167,11 @@ body { overflow: hidden; transition: max-height .5s; - a { + .menu-link { padding-left: 55px; } } - .open { - a { - background: $navbar-default-link-active-bg; - } - .sub-menu { - max-height: 400px; - } + .open .sub-menu { + max-height: 400px; // 8 submenu items, hopefully pretty safe } -} \ No newline at end of file +} diff --git a/src/app/_styles/components/tables.scss b/src/app/_styles/components/tables.scss index 0267d516..4afb6966 100644 --- a/src/app/_styles/components/tables.scss +++ b/src/app/_styles/components/tables.scss @@ -11,3 +11,25 @@ .th-clickable { cursor: pointer; } + +// Shadow hinting for responsive tables +// https://github.com/iKristjan/bootstrap-responsive-table-scrolling-shadows/blob/master/bootstrap-responsive-table-scrolling-shadows.css +.table-responsive { + background: + radial-gradient(farthest-side at 0% 50%, rgba(0,0,0,.2), rgba(0,0,0,0)), + radial-gradient(farthest-side at 100% 50%, rgba(0,0,0,.2), rgba(0,0,0,0)) 100% 0; + background-color: white; + background-repeat: no-repeat; + background-size: 10px 100%; + margin-bottom: 15px; +} + +.table-responsive > .table { + background: + linear-gradient(to right, white 30%, rgba(255,255,255,0)), + linear-gradient(to left, white 30%, rgba(255,255,255,0)) 100% 0; + background-size: 50px 100%; + background-repeat: no-repeat; + max-width: none; + margin-bottom: 0; +} \ No newline at end of file diff --git a/src/app/config/directives/ot-config-editor-form.directive.js b/src/app/config/directives/ot-config-editor-form.directive.js index ef32564a..15562793 100644 --- a/src/app/config/directives/ot-config-editor-form.directive.js +++ b/src/app/config/directives/ot-config-editor-form.directive.js @@ -1,94 +1,83 @@ -angular.module("coreModule") +angular.module('coreModule') -/** -* Directive used for automatic attributes editor form creation -*/ -.directive("otConfigEditorForm", [function () { +.directive('otConfigEditorForm', [function () { return { - restrict: "E", + restrict: 'E', scope: { - "parent": "=object", - "item": "=item", - "attributes": "=attributesList" + 'parent': '=object', + 'item': '=item', + 'attributes': '=attributesList' }, - templateUrl: "/views/config/directives/ot-config-editor-form.html", - controller: function ($scope) { - var updateAttributes, addTab, addFields, sortFieldsInGroups; + templateUrl: '/views/config/directives/ot-config-editor-form.html', + controller: function ($scope, _) { - $scope.tabs = {}; - $scope.click = function (id) { - if (typeof $scope.parent.selectTab === "function") { - $scope.parent.selectTab(id); - } else { - return false; - } - }; + $scope.tabs = []; + $scope.attributeGroups = {}; + $scope.click = click; - addTab = function (attr) { - if (attr.Type === "group") { - if (typeof $scope.tabs[attr.Group] === "undefined") { - $scope.tabs[attr.Group] = []; - } - $scope.tabs[attr.Group].push(attr); - } - }; + activate(); - addFields = function (attr) { - if (typeof $scope.attributeGroups[attr.Group] === "undefined") { - $scope.attributeGroups[attr.Group] = []; - } - $scope.attributeGroups[attr.Group].push(attr); - }; + /////////////////////// - sortFieldsInGroups = function () { - // var sortByLabel, tab; - // sortByLabel = function (a, b) { - // if (a.Label.toString() < b.Label.toString()) { - // return -1; - // } - // if (a.Label.toString() > b.Label.toString()) { - // return 1; - // } + function activate() { + $scope.$watchCollection('attributes', updateAttributes); + $scope.$watchCollection('item', updateAttributes); + } - // return 0; - // }; - // for (tab in $scope.attributeGroups) { - // if ($scope.attributeGroups.hasOwnProperty(tab)) { - // $scope.attributeGroups[tab].sort(sortByLabel); - // } - // } - }; + function click(id) { + if (typeof $scope.parent.selectTab === 'function') { + $scope.parent.selectTab(id); + } else { + return false; + } + } - updateAttributes = function () { - if ($scope.item === "undefined" || + function updateAttributes() { + if ($scope.item === 'undefined' || JSON.stringify({}) === JSON.stringify($scope.item)) { return true; } - var i, attr, setAttrValue; - $scope.attributeGroups = {}; - setAttrValue = function (attr) { - if (typeof $scope.item !== "undefined") { - attr.Value = $scope.item[attr.Attribute] || ""; + $scope.attributeGroups = {}; + if (typeof $scope.attributes !== 'undefined') { + for (var i = 0; i < $scope.attributes.length; i += 1) { + var attr = setAttrValue($scope.attributes[i]); + addFields(attr); } - return attr; - }; - - if (typeof $scope.attributes !== "undefined") { - for (i = 0; i < $scope.attributes.length; i += 1) { - attr = setAttrValue($scope.attributes[i]); + // only write tabs out once + if ($scope.tabs.length === 0) { + $scope.attributes.forEach(function(a){ + if (a.Type === 'group') { + addTab(a.Label, a.Group); + } + }); - addFields(attr); - addTab(attr); + // activate the first tab + $scope.click($scope.tabs[0].key); } } + } - sortFieldsInGroups(); - }; + function addTab(label, key) { + $scope.tabs.push({label:label, key:key}); + $scope.tabs = _.sortBy($scope.tabs, 'label'); + } + + function addFields(attr) { + if (typeof $scope.attributeGroups[attr.Group] === 'undefined') { + $scope.attributeGroups[attr.Group] = []; + } + $scope.attributeGroups[attr.Group].push(attr); + } + + function setAttrValue(attr) { + if (typeof $scope.item !== 'undefined') { + attr.Value = $scope.item[attr.Attribute] || ''; + } - $scope.$watchCollection("attributes", updateAttributes); - $scope.$watchCollection("item", updateAttributes); + return attr; + } } }; }]); diff --git a/src/app/config/directives/ot-config-editor-form.html b/src/app/config/directives/ot-config-editor-form.html index 9f371602..cafd2e5f 100644 --- a/src/app/config/directives/ot-config-editor-form.html +++ b/src/app/config/directives/ot-config-editor-form.html @@ -1,26 +1,47 @@ -