Merge pull request #9982 from nextcloud/global-flow-rebuild
Cleanup structure
This commit is contained in:
commit
53aaa62572
27 changed files with 7874 additions and 452 deletions
|
@ -121,7 +121,8 @@
|
|||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
padding: 14px;
|
||||
opacity: .5;
|
||||
z-index: 1;
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
}
|
||||
|
|
|
@ -49,6 +49,7 @@
|
|||
#filestable {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
min-width: 500px;
|
||||
}
|
||||
|
||||
#filestable tbody tr {
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
|
||||
/* don’t require a minimum width for files table */
|
||||
#body-user #filestable {
|
||||
min-width: initial !important;
|
||||
min-width: 300px;
|
||||
}
|
||||
|
||||
table th#headerSize,
|
||||
|
|
|
@ -117,6 +117,13 @@
|
|||
* Renders this details view
|
||||
*/
|
||||
render: function() {
|
||||
// remove old instances
|
||||
if ($('#app-sidebar').length === 0) {
|
||||
this.$el.insertAfter($('#app-content'));
|
||||
} else {
|
||||
$('#app-sidebar').replaceWith(this.$el)
|
||||
}
|
||||
|
||||
var templateVars = {
|
||||
closeLabel: t('files', 'Close')
|
||||
};
|
||||
|
|
|
@ -99,11 +99,12 @@
|
|||
|
||||
/**
|
||||
* Number of files per page
|
||||
* Always show a minimum of 1
|
||||
*
|
||||
* @return {int} page size
|
||||
*/
|
||||
pageSize: function() {
|
||||
return Math.ceil(this.$container.height() / 50);
|
||||
return Math.max(Math.ceil(this.$container.height() / 50), 1);
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -274,7 +275,6 @@
|
|||
|
||||
if (_.isUndefined(options.detailsViewEnabled) || options.detailsViewEnabled) {
|
||||
this._detailsView = new OCA.Files.DetailsView();
|
||||
this._detailsView.$el.insertBefore(this.$el);
|
||||
this._detailsView.$el.addClass('disappear');
|
||||
}
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@ describe('OCA.Files.FavoritesPlugin tests', function() {
|
|||
|
||||
beforeEach(function() {
|
||||
$('#testArea').append(
|
||||
'<div id="content">' +
|
||||
'<div id="app-navigation">' +
|
||||
'<ul><li data-id="files"><a>Files</a></li>' +
|
||||
'<li data-id="sharingin"><a></a></li>' +
|
||||
|
@ -25,6 +26,7 @@ describe('OCA.Files.FavoritesPlugin tests', function() {
|
|||
'<div id="app-content-favorites" class="hidden">' +
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
'</div>'
|
||||
);
|
||||
OC.Plugins.attach('OCA.Files.App', Plugin);
|
||||
|
|
|
@ -2491,7 +2491,8 @@ describe('OCA.Files.FileList tests', function() {
|
|||
|
||||
expect($('#app-sidebar').hasClass('disappear')).toEqual(false);
|
||||
fileList.remove('One.txt');
|
||||
expect($('#app-sidebar').hasClass('disappear')).toEqual(true);
|
||||
// sidebar is removed on close before being
|
||||
expect($('#app-sidebar').length).toEqual(0);
|
||||
jQuery.fx.off = false;
|
||||
});
|
||||
it('returns the currently selected model instance when calling getModelForFile', function() {
|
||||
|
@ -2515,7 +2516,7 @@ describe('OCA.Files.FileList tests', function() {
|
|||
|
||||
expect($('#app-sidebar').hasClass('disappear')).toEqual(false);
|
||||
fileList.changeDirectory('/another');
|
||||
expect($('#app-sidebar').hasClass('disappear')).toEqual(true);
|
||||
expect($('#app-sidebar').length).toEqual(0);
|
||||
jQuery.fx.off = false;
|
||||
});
|
||||
});
|
||||
|
|
|
@ -67,7 +67,7 @@ OCA.Sharing.PublicApp = {
|
|||
$el,
|
||||
{
|
||||
id: 'files.public',
|
||||
scrollContainer: $('#content-wrapper'),
|
||||
scrollContainer: $('#app-content'),
|
||||
dragOptions: dragOptions,
|
||||
folderDropOptions: folderDropOptions,
|
||||
fileActions: fileActions,
|
||||
|
|
7453
build/package-lock.json
generated
Normal file
7453
build/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load diff
|
@ -18,13 +18,13 @@
|
|||
"jsdoc": "~3.5.5",
|
||||
"karma": "^2.0.2",
|
||||
"karma-coverage": "*",
|
||||
"karma-jasmine": "^1.1.0",
|
||||
"karma-jasmine": "^1.1.2",
|
||||
"karma-jasmine-sinon": "^1.0.4",
|
||||
"karma-junit-reporter": "*",
|
||||
"karma-phantomjs-launcher": "*",
|
||||
"karma-junit-reporter": "^1.2.0",
|
||||
"karma-phantomjs-launcher": "^1.0.4",
|
||||
"karma-viewport": "^1.0.2",
|
||||
"phantomjs-prebuilt": "*",
|
||||
"node-sass": "~4.9.0",
|
||||
"phantomjs-prebuilt": "*",
|
||||
"sinon": "<= 5.0.7"
|
||||
},
|
||||
"engine": "node >= 6.9"
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
*
|
||||
*/
|
||||
|
||||
/* BASE STYLING ---------------------------------------------------------- */
|
||||
/* BASE STYLING ------------------------------------------------------------ */
|
||||
|
||||
h2 {
|
||||
font-size: 20px;
|
||||
|
@ -64,24 +64,16 @@ kbd {
|
|||
}
|
||||
|
||||
|
||||
/* APP STYLING -------------------------------------------------------------- */
|
||||
/* APP STYLING ------------------------------------------------------------ */
|
||||
|
||||
#app {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
#content[class*='app-'] * {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
/* APP-NAVIGATION ------------------------------------------------------------*/
|
||||
|
||||
/* APP-NAVIGATION ------------------------------------------------------------ */
|
||||
/* Navigation: folder like structure */
|
||||
|
||||
#app-navigation {
|
||||
width: 250px;
|
||||
height: 100%;
|
||||
float: left;
|
||||
width: $navigation-width;
|
||||
box-sizing: border-box;
|
||||
background-color: var(--color-main-background);
|
||||
-webkit-user-select: none;
|
||||
|
@ -91,6 +83,8 @@ kbd {
|
|||
border-right: 1px solid var(--color-border);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-grow: 0;
|
||||
flex-shrink: 0;
|
||||
|
||||
/* 'New' button */
|
||||
.app-navigation-new {
|
||||
|
@ -580,57 +574,85 @@ kbd {
|
|||
}
|
||||
}
|
||||
|
||||
/* APP-CONTENT ---------------------------------------------------------------*/
|
||||
|
||||
/* CONTENT --------------------------------------------------------- */
|
||||
#content {
|
||||
/* header height */
|
||||
padding-top: $header-height;
|
||||
box-sizing: border-box;
|
||||
position: relative;
|
||||
overflow-x: hidden;
|
||||
display: flex;
|
||||
/* trick: scroll #app-content and not the body
|
||||
* to avoid double scrollbar with sidebar
|
||||
*/
|
||||
max-height: 100vh;
|
||||
}
|
||||
|
||||
/* APP-CONTENT AND WRAPPER ------------------------------------------ */
|
||||
/* Part where the content will be loaded into */
|
||||
#app-content {
|
||||
z-index: 1000;
|
||||
background-color: var(--color-main-background);
|
||||
position: relative;
|
||||
height: 100%;
|
||||
overflow-y: auto;
|
||||
min-height: calc(100vh - #{$header-height});
|
||||
flex-basis: 100vw;
|
||||
overflow: auto;
|
||||
/* no top border for first settings item */
|
||||
> .section:first-child {
|
||||
border-top: none;
|
||||
}
|
||||
&.with-app-sidebar {
|
||||
margin-right: 27%;
|
||||
|
||||
/* if app-content-list is present */
|
||||
#app-content-wrapper {
|
||||
display: flex;
|
||||
position: relative;
|
||||
align-items: start;
|
||||
.app-content-list,
|
||||
.app-content-detail {
|
||||
min-height: calc(100vh - #{$header-height});
|
||||
max-height: calc(100vh - #{$header-height});
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
/* CONTENT DETAILS AFTER LIST*/
|
||||
.app-content-detail {
|
||||
/* grow full width */
|
||||
flex-grow: 1;
|
||||
#app-navigation-toggle-back {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#app-content-wrapper {
|
||||
min-width: 100%;
|
||||
min-height: 100%;
|
||||
}
|
||||
|
||||
/* APP-SIDEBAR ----------------------------------------------------------------*/
|
||||
|
||||
/* APP-SIDEBAR ------------------------------------------------------------ */
|
||||
/*
|
||||
Sidebar: a sidebar to be used within #app-content
|
||||
have it as first element within app-content in order to shrink other
|
||||
sibling containers properly. Compare Files app for example.
|
||||
Sidebar: a sidebar to be used within #content
|
||||
#app-content will be shrinked properly
|
||||
*/
|
||||
#app-sidebar {
|
||||
position: fixed;
|
||||
top: 50px;
|
||||
right: 0;
|
||||
left: auto;
|
||||
bottom: 0;
|
||||
width: 27%;
|
||||
min-width: 300px;
|
||||
width: 27vw;
|
||||
min-width: $sidebar-min-width;
|
||||
max-width: $sidebar-max-width;
|
||||
display: block;
|
||||
position: relative;
|
||||
background: var(--color-main-background);
|
||||
border-left: 1px solid var(--color-border);
|
||||
-webkit-transition: margin-right 300ms;
|
||||
transition: margin-right 300ms;
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
visibility: visible;
|
||||
z-index: 500;
|
||||
flex-shrink: 0;
|
||||
transition: 300ms width ease-in-out,
|
||||
300ms min-width ease-in-out;
|
||||
&.disappear {
|
||||
visibility: hidden;
|
||||
width: 0;
|
||||
min-width: 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* APP-SETTINGS ---------------------------------------------------------------*/
|
||||
|
||||
/* APP-SETTINGS ------------------------------------------------------------ */
|
||||
/* settings area */
|
||||
#app-settings {
|
||||
// To the bottom w/ flex
|
||||
|
@ -650,8 +672,6 @@ kbd {
|
|||
/* restrict height of settings and make scrollable */
|
||||
max-height: 300px;
|
||||
overflow-y: auto;
|
||||
border-right: 1px solid var(--color-border);
|
||||
width: 250px;
|
||||
box-sizing: border-box;
|
||||
|
||||
/* display input fields at full width */
|
||||
|
@ -679,8 +699,6 @@ kbd {
|
|||
}
|
||||
|
||||
#app-settings-header {
|
||||
border-right: 1px solid var(--color-border);
|
||||
width: 250px;
|
||||
box-sizing: border-box;
|
||||
background-color: var(--color-main-background);
|
||||
}
|
||||
|
@ -716,7 +734,7 @@ kbd {
|
|||
}
|
||||
}
|
||||
|
||||
/* GENERAL SECTION ---------------------------------------------------------- */
|
||||
/* GENERAL SECTION ------------------------------------------------------------ */
|
||||
.section {
|
||||
display: block;
|
||||
padding: 30px;
|
||||
|
@ -753,7 +771,7 @@ kbd {
|
|||
}
|
||||
}
|
||||
|
||||
/* TABS --------------------------------------------------------------------- */
|
||||
/* TABS ------------------------------------------------------------ */
|
||||
.tabHeaders {
|
||||
display: inline-block;
|
||||
margin: 15px;
|
||||
|
@ -786,7 +804,7 @@ kbd {
|
|||
}
|
||||
}
|
||||
|
||||
/* POPOVER MENU ------------------------------------------------------------- */
|
||||
/* POPOVER MENU ------------------------------------------------------------ */
|
||||
$popoveritem-height: 38px;
|
||||
$popovericon-size: 16px;
|
||||
|
||||
|
@ -1007,23 +1025,7 @@ $popovericon-size: 16px;
|
|||
}
|
||||
}
|
||||
|
||||
/* CONTENT WRAPPER --------------------------------------------------------- */
|
||||
#app-content-wrapper {
|
||||
display: flex;
|
||||
position: relative;
|
||||
align-items: start;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
.app-content-list,
|
||||
.app-content-detail {
|
||||
min-height: 100%;
|
||||
max-height: 100%;
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
}
|
||||
}
|
||||
|
||||
/* CONTENT LIST ------------------------------------------------------------- */
|
||||
/* CONTENT LIST ------------------------------------------------------------ */
|
||||
.app-content-list {
|
||||
width: 300px;
|
||||
border-right: 1px solid var(--color-border);
|
||||
|
@ -1175,62 +1177,3 @@ $popovericon-size: 16px;
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* CONTENT ------------------------------------------------------------------ */
|
||||
.app-content-detail {
|
||||
/* grow full width */
|
||||
flex-grow: 1;
|
||||
|
||||
#app-navigation-toggle-back {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
/* MOBILE ------------------------------------------------------------------- */
|
||||
/* Mobile width < 768px */
|
||||
@media only screen and (max-width: 768px) {
|
||||
|
||||
/* full width for message list on mobile */
|
||||
.app-content-list {
|
||||
width: 100%;
|
||||
background: var(--color-main-background);
|
||||
position: relative;
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
/* overlay message detail on top of message list */
|
||||
.app-content-detail {
|
||||
background: var(--color-main-background);
|
||||
width: 100%;
|
||||
left: 0;
|
||||
height: 100%;
|
||||
top: 0;
|
||||
box-shadow: 0 0 100px rgba(100, 100, 100, .9);
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
/* Show app details page */
|
||||
#app-content.showdetails {
|
||||
#app-navigation-toggle {
|
||||
transform: translateX(-44px);
|
||||
}
|
||||
#app-navigation-toggle-back {
|
||||
position: fixed;
|
||||
display: inline-block !important;
|
||||
top: 45px;
|
||||
left: 0;
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
z-index: 149;
|
||||
background-color: rgba(255, 255, 255, .7);
|
||||
cursor: pointer;
|
||||
opacity: .6;
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
.app-content-list {
|
||||
transform: translateX(-100%);
|
||||
}
|
||||
}
|
||||
|
||||
/* end of media query */
|
||||
}
|
||||
|
|
|
@ -49,7 +49,7 @@
|
|||
left: 0;
|
||||
right: 0;
|
||||
z-index: 2000;
|
||||
height: 50px;
|
||||
height: $header-height;
|
||||
background-color: var(--color-primary);
|
||||
box-sizing: border-box;
|
||||
justify-content: space-between;
|
||||
|
@ -81,7 +81,7 @@
|
|||
max-width: 350px;
|
||||
max-height: 280px;
|
||||
right: 5px;
|
||||
top: 50px;
|
||||
top: $header-height;
|
||||
margin: 0;
|
||||
|
||||
&:not(.popovermenu) {
|
||||
|
@ -165,7 +165,7 @@
|
|||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 50px;
|
||||
width: $header-height;
|
||||
height: 100%;
|
||||
cursor: pointer;
|
||||
opacity: 0.6;
|
||||
|
@ -224,9 +224,9 @@
|
|||
/* NAVIGATION --------------------------------------------------------------- */
|
||||
nav[role='navigation'] {
|
||||
display: inline-block;
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
margin-left: -50px;
|
||||
width: $header-height;
|
||||
height: $header-height;
|
||||
margin-left: -$header-height;
|
||||
}
|
||||
|
||||
.header-left #navigation {
|
||||
|
@ -439,28 +439,21 @@ nav[role='navigation'] {
|
|||
|
||||
/* Apps menu */
|
||||
#appmenu {
|
||||
display: inline-block;
|
||||
width: auto;
|
||||
min-width: 50px;
|
||||
height: 100%;
|
||||
clear: both;
|
||||
display: inline-flex;
|
||||
min-width: $header-height;
|
||||
|
||||
li {
|
||||
float: left;
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
vertical-align: top !important;
|
||||
height: 100%;
|
||||
cursor: pointer;
|
||||
|
||||
a {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
display: flex;
|
||||
margin: 0;
|
||||
padding: 15px 15px;
|
||||
height: 20px;
|
||||
text-align: center;
|
||||
vertical-align: top !important;
|
||||
height: $header-height;
|
||||
width: $header-height;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
opacity: .6;
|
||||
}
|
||||
}
|
||||
|
@ -582,7 +575,7 @@ nav[role='navigation'] {
|
|||
|
||||
&:focus,
|
||||
&:active {
|
||||
top: 50px;
|
||||
top: $header-height;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,124 +1,147 @@
|
|||
@media only screen and (max-width: 768px) {
|
||||
|
||||
/* do not show update notification on mobile */
|
||||
#update-notification {
|
||||
display: none !important;
|
||||
/* position share dropdown */
|
||||
#dropdown {
|
||||
margin-right: 10% !important;
|
||||
width: 80% !important;
|
||||
}
|
||||
|
||||
/* fix name autocomplete not showing on mobile */
|
||||
.ui-autocomplete {
|
||||
z-index: 1000 !important;
|
||||
}
|
||||
|
||||
/* fix error display on smaller screens */
|
||||
.error-wide {
|
||||
width: 100%;
|
||||
margin-left: 0 !important;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
/* APP SIDEBAR TOGGLE and SWIPE ----------------------------------------------*/
|
||||
#app-navigation {
|
||||
transform: translateX(-250px);
|
||||
}
|
||||
.snapjs-left {
|
||||
#app-navigation {
|
||||
transform: translateX(0);
|
||||
}
|
||||
}
|
||||
|
||||
#app-content {
|
||||
margin-left: -$navigation-width;
|
||||
}
|
||||
|
||||
|
||||
/* full width for message list on mobile */
|
||||
.app-content-list {
|
||||
width: 100%;
|
||||
background: var(--color-main-background);
|
||||
position: relative;
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
/* since list and content are only displayed full window size
|
||||
* we don't ant inner scrolling
|
||||
*/
|
||||
#app-content-wrapper {
|
||||
.app-content-list,
|
||||
.app-content-detail {
|
||||
max-height: unset;
|
||||
}
|
||||
}
|
||||
|
||||
/* Show app details page */
|
||||
#app-content.showdetails {
|
||||
#app-navigation-toggle {
|
||||
transform: translateX(-44px);
|
||||
}
|
||||
#app-navigation-toggle-back {
|
||||
position: fixed;
|
||||
display: inline-block !important;
|
||||
top: 45px;
|
||||
left: 0;
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
z-index: 149;
|
||||
background-color: rgba(255, 255, 255, .7);
|
||||
cursor: pointer;
|
||||
opacity: .6;
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
.app-content-list {
|
||||
transform: translateX(-100%);
|
||||
}
|
||||
|
||||
/* end of media query */
|
||||
}
|
||||
|
||||
/* position share dropdown */
|
||||
#dropdown {
|
||||
margin-right: 10% !important;
|
||||
width: 80% !important;
|
||||
}
|
||||
|
||||
/* fix name autocomplete not showing on mobile */
|
||||
.ui-autocomplete {
|
||||
z-index: 1000 !important;
|
||||
}
|
||||
|
||||
/* fix error display on smaller screens */
|
||||
.error-wide {
|
||||
width: 100%;
|
||||
margin-left: 0 !important;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
|
||||
/* APP SIDEBAR TOGGLE and SWIPE ----------------------------------------------*/
|
||||
|
||||
#app-navigation,
|
||||
#app-content {
|
||||
position: absolute !important;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
#app-navigation {
|
||||
width: 250px !important;
|
||||
}
|
||||
|
||||
#app-content {
|
||||
width: 100% !important;
|
||||
left: 0 !important;
|
||||
background-color: var(--color-main-background);
|
||||
overflow-x: hidden !important;
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
/* allow horizontal scrollbar in settings
|
||||
/* allow horizontal scrollbar in settings
|
||||
otherwise user management is not usable on mobile */
|
||||
#body-settings #app-content {
|
||||
overflow-x: auto !important;
|
||||
}
|
||||
#body-settings #app-content {
|
||||
overflow-x: auto !important;
|
||||
}
|
||||
|
||||
#app-navigation-toggle {
|
||||
position: fixed;
|
||||
display: inline-block !important;
|
||||
top: 50px;
|
||||
left: 0;
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
z-index: 149;
|
||||
background-color: var(--color-main-background-darker);
|
||||
cursor: pointer;
|
||||
opacity: .6;
|
||||
}
|
||||
#app-navigation-toggle:hover,
|
||||
#app-navigation-toggle:focus {
|
||||
opacity: 1;
|
||||
}
|
||||
#app-navigation-toggle {
|
||||
position: fixed;
|
||||
display: inline-block !important;
|
||||
top: $header-height;
|
||||
left: 0;
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
z-index: 149;
|
||||
background-color: var(--color-main-background-darker);
|
||||
cursor: pointer;
|
||||
opacity: 0.6;
|
||||
}
|
||||
#app-navigation-toggle:hover,
|
||||
#app-navigation-toggle:focus {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
/* position controls for apps with app-navigation */
|
||||
#app-navigation+#app-content #controls {
|
||||
padding-left: 44px;
|
||||
}
|
||||
/* position controls for apps with app-navigation */
|
||||
#app-navigation + #app-content #controls {
|
||||
padding-left: 44px;
|
||||
}
|
||||
|
||||
/* .viewer-mode is when text editor, PDF viewer, etc is open */
|
||||
#body-user .app-files.viewer-mode #controls {
|
||||
padding-left: 0 !important;
|
||||
}
|
||||
.app-files.viewer-mode #app-navigation-toggle {
|
||||
display: none !important;
|
||||
}
|
||||
/* .viewer-mode is when text editor, PDF viewer, etc is open */
|
||||
#body-user .app-files.viewer-mode #controls {
|
||||
padding-left: 0 !important;
|
||||
}
|
||||
.app-files.viewer-mode #app-navigation-toggle {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
table.multiselect thead {
|
||||
left: 0 !important;
|
||||
}
|
||||
table.multiselect thead {
|
||||
left: 0 !important;
|
||||
}
|
||||
|
||||
/* prevent overflow in user management controls bar */
|
||||
#usersearchform {
|
||||
display: none;
|
||||
}
|
||||
#body-settings #controls {
|
||||
min-width: 768px !important;
|
||||
}
|
||||
|
||||
/* prevent overflow in user management controls bar */
|
||||
#usersearchform {
|
||||
display: none;
|
||||
}
|
||||
#body-settings #controls {
|
||||
min-width: 768px !important;
|
||||
}
|
||||
/* do not show dates in filepicker */
|
||||
#oc-dialog-filepicker-content .filelist .filesize,
|
||||
#oc-dialog-filepicker-content .filelist .date {
|
||||
display: none;
|
||||
}
|
||||
#oc-dialog-filepicker-content .filelist .filename {
|
||||
max-width: 80%;
|
||||
}
|
||||
|
||||
/* fix controls bar jumping when navigation is slid out */
|
||||
.snapjs-left #app-navigation-toggle,
|
||||
.snapjs-left #controls {
|
||||
top: 0;
|
||||
}
|
||||
.snapjs-left table.multiselect thead {
|
||||
top: 44px;
|
||||
}
|
||||
|
||||
/* do not show dates in filepicker */
|
||||
#oc-dialog-filepicker-content .filelist .filesize,
|
||||
#oc-dialog-filepicker-content .filelist .date {
|
||||
display: none;
|
||||
}
|
||||
#oc-dialog-filepicker-content .filelist .filename {
|
||||
max-width: 80%;
|
||||
}
|
||||
|
||||
|
||||
/* fix controls bar jumping when navigation is slid out */
|
||||
.snapjs-left #app-navigation-toggle,
|
||||
.snapjs-left #controls {
|
||||
top: 0;
|
||||
}
|
||||
.snapjs-left table.multiselect thead {
|
||||
top: 44px;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* end of media query */
|
||||
/* end of media query */
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 480px) {
|
||||
|
@ -131,7 +154,7 @@ table.multiselect thead {
|
|||
}
|
||||
/* Arrow directly child of menutoggle */
|
||||
#header .header-right > div {
|
||||
&.openedMenu{
|
||||
&.openedMenu {
|
||||
&::after {
|
||||
display: block;
|
||||
}
|
||||
|
|
|
@ -207,25 +207,6 @@ body {
|
|||
}
|
||||
}
|
||||
|
||||
#content {
|
||||
position: relative;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
.hascontrols {
|
||||
margin-top: 45px;
|
||||
}
|
||||
}
|
||||
|
||||
#content-wrapper {
|
||||
position: absolute;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
overflow-x: hidden;
|
||||
/* prevent horizontal scrollbar */
|
||||
padding-top: 50px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
/* allow horizontal scrollbar for personal and admin settings */
|
||||
|
||||
#body-settings:not(.snapjs-left) .app-settings {
|
||||
|
@ -838,7 +819,7 @@ span.ui-icon {
|
|||
}
|
||||
|
||||
.content {
|
||||
max-height: calc(100% - 50px);
|
||||
max-height: calc(100% - $header-height);
|
||||
height: 100%;
|
||||
overflow-y: auto;
|
||||
|
||||
|
|
|
@ -75,3 +75,10 @@ $color-border-dark: nc-darken($color-main-background, 14%) !default;
|
|||
$border-radius: 3px !default;
|
||||
|
||||
$font-face: 'Open Sans', Frutiger, Calibri, 'Myriad Pro', Myriad, sans-serif !default;
|
||||
|
||||
|
||||
// various structure data
|
||||
$header-height: 50px;
|
||||
$navigation-width: 300px;
|
||||
$sidebar-min-width: 300px;
|
||||
$sidebar-max-width: 500px;
|
||||
|
|
|
@ -27,9 +27,8 @@
|
|||
*/
|
||||
exports.Apps.showAppSidebar = function($el) {
|
||||
var $appSidebar = $el || $('#app-sidebar');
|
||||
$appSidebar.removeClass('disappear')
|
||||
.show('slide', { direction: 'right' }, 200);
|
||||
$('#app-content').addClass('with-app-sidebar', 200).trigger(new $.Event('appresized'));
|
||||
$appSidebar.removeClass('disappear');
|
||||
$('#content').addClass('with-app-sidebar').trigger(new $.Event('appresized'));
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -40,11 +39,8 @@
|
|||
*/
|
||||
exports.Apps.hideAppSidebar = function($el) {
|
||||
var $appSidebar = $el || $('#app-sidebar');
|
||||
$appSidebar.hide('slide', { direction: 'right' }, 100,
|
||||
function() {
|
||||
$appSidebar.addClass('disappear');
|
||||
});
|
||||
$('#app-content').removeClass('with-app-sidebar', 100).trigger(new $.Event('appresized'));
|
||||
$appSidebar.addClass('disappear');
|
||||
$('#content').removeClass('with-app-sidebar').trigger(new $.Event('appresized'));
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
describe('Apps base tests', function() {
|
||||
describe('Sidebar utility functions', function() {
|
||||
beforeEach(function() {
|
||||
$('#testArea').append('<div id="app-content">Content</div><div id="app-sidebar">The sidebar</div>');
|
||||
$('#testArea').append('<div id="content"><div id="app-content">Content</div><div id="app-sidebar">The sidebar</div></div>');
|
||||
jQuery.fx.off = true;
|
||||
});
|
||||
afterEach(function() {
|
||||
|
@ -41,7 +41,7 @@ describe('Apps base tests', function() {
|
|||
});
|
||||
it('triggers appresize event when visibility changed', function() {
|
||||
var eventStub = sinon.stub();
|
||||
$('#app-content').on('appresized', eventStub);
|
||||
$('#content').on('appresized', eventStub);
|
||||
OC.Apps.showAppSidebar();
|
||||
expect(eventStub.calledOnce).toEqual(true);
|
||||
OC.Apps.hideAppSidebar();
|
||||
|
|
|
@ -27,8 +27,7 @@
|
|||
</head>
|
||||
<body id="<?php p($_['bodyid']);?>">
|
||||
<?php include('layout.noscript.warning.php'); ?>
|
||||
<header>
|
||||
<div id="header" class="<?php p($_['header-classes']); ?>">
|
||||
<header id="header" class="<?php p($_['header-classes']); ?>">
|
||||
<div class="header-left">
|
||||
<span id="nextcloud">
|
||||
<div class="logo logo-icon svg"></div>
|
||||
|
@ -70,9 +69,7 @@
|
|||
<?php } ?>
|
||||
</div>
|
||||
<?php } ?>
|
||||
</div>
|
||||
</header>
|
||||
<div id="content-wrapper">
|
||||
</header>
|
||||
<div id="content" class="app-<?php p($_['appid']) ?>" role="main">
|
||||
<?php print_unescaped($_['content']); ?>
|
||||
</div>
|
||||
|
@ -81,7 +78,6 @@
|
|||
<p class="info"><?php print_unescaped($theme->getLongFooter()); ?></p>
|
||||
</footer>
|
||||
<?php } ?>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -28,13 +28,13 @@
|
|||
<body id="<?php p($_['bodyid']);?>">
|
||||
<?php include 'layout.noscript.warning.php'; ?>
|
||||
|
||||
<a href="#app-content" class="button primary skip-navigation skip-content"><?php p($l->t('Skip to main content')); ?></a>
|
||||
<a href="#app-navigation" class="button primary skip-navigation"><?php p($l->t('Skip to navigation of app')); ?></a>
|
||||
<a href="#app-content" class="button primary skip-navigation skip-content"><?php p($l->t('Skip to main content')); ?></a>
|
||||
<a href="#app-navigation" class="button primary skip-navigation"><?php p($l->t('Skip to navigation of app')); ?></a>
|
||||
|
||||
<div id="notification-container">
|
||||
<div id="notification"></div>
|
||||
</div>
|
||||
<header role="banner"><div id="header">
|
||||
<div id="notification-container">
|
||||
<div id="notification"></div>
|
||||
</div>
|
||||
<header role="banner" id="header">
|
||||
<div class="header-left">
|
||||
<a href="<?php print_unescaped(link_to('', 'index.php')); ?>"
|
||||
id="nextcloud">
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -21,13 +21,13 @@
|
|||
-->
|
||||
|
||||
<template>
|
||||
<div id="app">
|
||||
<div id="content" class="app-settings" :class="{ 'with-app-sidebar': currentApp}">
|
||||
<app-navigation :menu="menu" />
|
||||
<div id="app-content" class="app-settings-content" :class="{ 'with-app-sidebar': currentApp, 'icon-loading': loadingList }">
|
||||
<div id="app-content" class="app-settings-content" :class="{ 'icon-loading': loadingList }">
|
||||
<app-list :category="category" :app="currentApp" :search="searchQuery"></app-list>
|
||||
<div id="app-sidebar" v-if="id && currentApp">
|
||||
<app-details :category="category" :app="currentApp"></app-details>
|
||||
</div>
|
||||
</div>
|
||||
<div id="app-sidebar" v-if="id && currentApp">
|
||||
<app-details :category="category" :app="currentApp"></app-details>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
-->
|
||||
|
||||
<template>
|
||||
<div id="app">
|
||||
<div id="content" class="app-settings">
|
||||
<app-navigation :menu="menu">
|
||||
<template slot="settings-content">
|
||||
<div>
|
||||
|
|
|
@ -6,7 +6,7 @@ Feature: app-files
|
|||
And I see that "welcome.txt" is marked as favorite
|
||||
And I open the "Favorites" section
|
||||
And I open the details view for "welcome.txt"
|
||||
And I see that the details view for "Favorites" section is open
|
||||
And I see that the details view is open
|
||||
When I view "welcome.txt" in folder
|
||||
Then I see that the current section is "All files"
|
||||
And I see that the details view is closed
|
||||
|
@ -17,11 +17,11 @@ Feature: app-files
|
|||
And I see that "welcome.txt" is marked as favorite
|
||||
And I open the "Favorites" section
|
||||
And I open the details view for "welcome.txt"
|
||||
And I see that the details view for "Favorites" section is open
|
||||
And I see that the details view is open
|
||||
And I view "welcome.txt" in folder
|
||||
And I see that the current section is "All files"
|
||||
When I open the details view for "welcome.txt"
|
||||
Then I see that the details view for "All files" section is open
|
||||
Then I see that the details view is open
|
||||
|
||||
Scenario: rename a file with the details view open
|
||||
Given I am logged in
|
||||
|
@ -151,14 +151,14 @@ Feature: app-files
|
|||
Scenario: show the input field for tags in the details view
|
||||
Given I am logged in
|
||||
And I open the details view for "welcome.txt"
|
||||
And I see that the details view for "All files" section is open
|
||||
And I see that the details view is open
|
||||
When I open the input field for tags in the details view
|
||||
Then I see that the input field for tags in the details view is shown
|
||||
|
||||
Scenario: show the input field for tags in the details view after the sharing tab has loaded
|
||||
Given I am logged in
|
||||
And I open the details view for "welcome.txt"
|
||||
And I see that the details view for "All files" section is open
|
||||
And I see that the details view is open
|
||||
And I open the "Sharing" tab in the details view
|
||||
And I see that the "Sharing" tab in the details view is eventually loaded
|
||||
When I open the input field for tags in the details view
|
||||
|
|
|
@ -31,8 +31,8 @@ class CommentsAppContext implements Context, ActorAwareInterface {
|
|||
*/
|
||||
public static function newCommentField() {
|
||||
return Locator::forThe()->css("div.newCommentRow .message")->
|
||||
descendantOf(FilesAppContext::currentSectionDetailsView())->
|
||||
describedAs("New comment field in current section details view in Files app");
|
||||
descendantOf(FilesAppContext::detailsView())->
|
||||
describedAs("New comment field in details view in Files app");
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -40,8 +40,8 @@ class CommentsAppContext implements Context, ActorAwareInterface {
|
|||
*/
|
||||
public static function submitNewCommentButton() {
|
||||
return Locator::forThe()->css("div.newCommentRow .submit")->
|
||||
descendantOf(FilesAppContext::currentSectionDetailsView())->
|
||||
describedAs("Submit new comment button in current section details view in Files app");
|
||||
descendantOf(FilesAppContext::detailsView())->
|
||||
describedAs("Submit new comment button in details view in Files app");
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -49,8 +49,8 @@ class CommentsAppContext implements Context, ActorAwareInterface {
|
|||
*/
|
||||
public static function commentList() {
|
||||
return Locator::forThe()->css("ul.comments")->
|
||||
descendantOf(FilesAppContext::currentSectionDetailsView())->
|
||||
describedAs("Comment list in current section details view in Files app");
|
||||
descendantOf(FilesAppContext::detailsView())->
|
||||
describedAs("Comment list in details view in Files app");
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -59,7 +59,7 @@ class CommentsAppContext implements Context, ActorAwareInterface {
|
|||
public static function commentWithText($text) {
|
||||
return Locator::forThe()->xpath("//div[normalize-space() = '$text']/ancestor::li")->
|
||||
descendantOf(self::commentList())->
|
||||
describedAs("Comment with text \"$text\" in current section details view in Files app");
|
||||
describedAs("Comment with text \"$text\" in details view in Files app");
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -63,19 +63,9 @@ class FilesAppContext implements Context, ActorAwareInterface {
|
|||
/**
|
||||
* @return Locator
|
||||
*/
|
||||
public static function detailsViewForSection($section) {
|
||||
return Locator::forThe()->xpath("/preceding-sibling::*[position() = 1 and @id = 'app-sidebar']")->
|
||||
descendantOf(self::mainViewForSection($section))->
|
||||
describedAs("Details view for section $section in Files app");
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Locator
|
||||
*/
|
||||
public static function currentSectionDetailsView() {
|
||||
return Locator::forThe()->xpath("/preceding-sibling::*[position() = 1 and @id = 'app-sidebar']")->
|
||||
descendantOf(self::currentSectionMainView())->
|
||||
describedAs("Current section details view in Files app");
|
||||
public static function detailsView() {
|
||||
return Locator::forThe()->id("app-sidebar")->
|
||||
describedAs("Details view in Files app");
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -83,53 +73,53 @@ class FilesAppContext implements Context, ActorAwareInterface {
|
|||
*/
|
||||
public static function closeDetailsViewButton() {
|
||||
return Locator::forThe()->css(".icon-close")->
|
||||
descendantOf(self::currentSectionDetailsView())->
|
||||
describedAs("Close current section details view in Files app");
|
||||
descendantOf(self::detailsView())->
|
||||
describedAs("Close details view in Files app");
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Locator
|
||||
*/
|
||||
public static function fileNameInCurrentSectionDetailsView() {
|
||||
public static function fileNameInDetailsView() {
|
||||
return Locator::forThe()->css(".fileName")->
|
||||
descendantOf(self::currentSectionDetailsView())->
|
||||
describedAs("File name in current section details view in Files app");
|
||||
descendantOf(self::detailsView())->
|
||||
describedAs("File name in details view in Files app");
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Locator
|
||||
*/
|
||||
public static function fileDetailsInCurrentSectionDetailsViewWithText($fileDetailsText) {
|
||||
public static function fileDetailsInDetailsViewWithText($fileDetailsText) {
|
||||
return Locator::forThe()->xpath("//span[normalize-space() = '$fileDetailsText']")->
|
||||
descendantOf(self::fileDetailsInCurrentSectionDetailsView())->
|
||||
describedAs("File details with text \"$fileDetailsText\" in current section details view in Files app");
|
||||
descendantOf(self::fileDetailsInDetailsView())->
|
||||
describedAs("File details with text \"$fileDetailsText\" in details view in Files app");
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Locator
|
||||
*/
|
||||
private static function fileDetailsInCurrentSectionDetailsView() {
|
||||
private static function fileDetailsInDetailsView() {
|
||||
return Locator::forThe()->css(".file-details")->
|
||||
descendantOf(self::currentSectionDetailsView())->
|
||||
describedAs("File details in current section details view in Files app");
|
||||
descendantOf(self::detailsView())->
|
||||
describedAs("File details in details view in Files app");
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Locator
|
||||
*/
|
||||
public static function inputFieldForTagsInCurrentSectionDetailsView() {
|
||||
public static function inputFieldForTagsInDetailsView() {
|
||||
return Locator::forThe()->css(".systemTagsInfoView")->
|
||||
descendantOf(self::currentSectionDetailsView())->
|
||||
describedAs("Input field for tags in current section details view in Files app");
|
||||
descendantOf(self::detailsView())->
|
||||
describedAs("Input field for tags in details view in Files app");
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Locator
|
||||
*/
|
||||
public static function itemInInputFieldForTagsInCurrentSectionDetailsViewForTag($tag) {
|
||||
public static function itemInInputFieldForTagsInDetailsViewForTag($tag) {
|
||||
return Locator::forThe()->xpath("//span[normalize-space() = '$tag']")->
|
||||
descendantOf(self::inputFieldForTagsInCurrentSectionDetailsView())->
|
||||
describedAs("Item in input field for tags in current section details view for tag $tag in Files app");
|
||||
descendantOf(self::inputFieldForTagsInDetailsView())->
|
||||
describedAs("Item in input field for tags in details view for tag $tag in Files app");
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -161,37 +151,37 @@ class FilesAppContext implements Context, ActorAwareInterface {
|
|||
/**
|
||||
* @return Locator
|
||||
*/
|
||||
public static function tabHeaderInCurrentSectionDetailsViewNamed($tabHeaderName) {
|
||||
public static function tabHeaderInDetailsViewNamed($tabHeaderName) {
|
||||
return Locator::forThe()->xpath("//li[normalize-space() = '$tabHeaderName']")->
|
||||
descendantOf(self::tabHeadersInCurrentSectionDetailsView())->
|
||||
describedAs("Tab header named $tabHeaderName in current section details view in Files app");
|
||||
descendantOf(self::tabHeadersInDetailsView())->
|
||||
describedAs("Tab header named $tabHeaderName in details view in Files app");
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Locator
|
||||
*/
|
||||
private static function tabHeadersInCurrentSectionDetailsView() {
|
||||
private static function tabHeadersInDetailsView() {
|
||||
return Locator::forThe()->css(".tabHeaders")->
|
||||
descendantOf(self::currentSectionDetailsView())->
|
||||
describedAs("Tab headers in current section details view in Files app");
|
||||
descendantOf(self::detailsView())->
|
||||
describedAs("Tab headers in details view in Files app");
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Locator
|
||||
*/
|
||||
public static function tabInCurrentSectionDetailsViewNamed($tabName) {
|
||||
public static function tabInDetailsViewNamed($tabName) {
|
||||
return Locator::forThe()->xpath("//div[@id=//*[contains(concat(' ', normalize-space(@class), ' '), ' tabHeader ') and normalize-space() = '$tabName']/@data-tabid]")->
|
||||
descendantOf(self::currentSectionDetailsView())->
|
||||
describedAs("Tab named $tabName in current section details view in Files app");
|
||||
descendantOf(self::detailsView())->
|
||||
describedAs("Tab named $tabName in details view in Files app");
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Locator
|
||||
*/
|
||||
public static function loadingIconForTabInCurrentSectionDetailsViewNamed($tabName) {
|
||||
public static function loadingIconForTabInDetailsViewNamed($tabName) {
|
||||
return Locator::forThe()->css(".loading")->
|
||||
descendantOf(self::tabInCurrentSectionDetailsViewNamed($tabName))->
|
||||
describedAs("Loading icon for tab named $tabName in current section details view in Files app");
|
||||
descendantOf(self::tabInDetailsViewNamed($tabName))->
|
||||
describedAs("Loading icon for tab named $tabName in details view in Files app");
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -202,7 +192,7 @@ class FilesAppContext implements Context, ActorAwareInterface {
|
|||
// return the checkbox itself, but the element that the user interacts
|
||||
// with is the label.
|
||||
return Locator::forThe()->xpath("//label[normalize-space() = 'Share link']")->
|
||||
descendantOf(self::currentSectionDetailsView())->
|
||||
descendantOf(self::detailsView())->
|
||||
describedAs("Share link checkbox in the details view in Files app");
|
||||
}
|
||||
|
||||
|
@ -210,7 +200,7 @@ class FilesAppContext implements Context, ActorAwareInterface {
|
|||
* @return Locator
|
||||
*/
|
||||
public static function shareLinkField() {
|
||||
return Locator::forThe()->css(".linkText")->descendantOf(self::currentSectionDetailsView())->
|
||||
return Locator::forThe()->css(".linkText")->descendantOf(self::detailsView())->
|
||||
describedAs("Share link field in the details view in Files app");
|
||||
}
|
||||
|
||||
|
@ -222,7 +212,7 @@ class FilesAppContext implements Context, ActorAwareInterface {
|
|||
// that would return the radio button itself, but the element that the
|
||||
// user interacts with is the label.
|
||||
return Locator::forThe()->xpath("//label[normalize-space() = 'Allow upload and editing']")->
|
||||
descendantOf(self::currentSectionDetailsView())->
|
||||
descendantOf(self::detailsView())->
|
||||
describedAs("Allow upload and editing radio button in the details view in Files app");
|
||||
}
|
||||
|
||||
|
@ -234,7 +224,7 @@ class FilesAppContext implements Context, ActorAwareInterface {
|
|||
// would return the checkbox itself, but the element that the user
|
||||
// interacts with is the label.
|
||||
return Locator::forThe()->xpath("//label[normalize-space() = 'Password protect']")->
|
||||
descendantOf(self::currentSectionDetailsView())->
|
||||
descendantOf(self::detailsView())->
|
||||
describedAs("Password protect checkbox in the details view in Files app");
|
||||
}
|
||||
|
||||
|
@ -242,7 +232,7 @@ class FilesAppContext implements Context, ActorAwareInterface {
|
|||
* @return Locator
|
||||
*/
|
||||
public static function passwordProtectField() {
|
||||
return Locator::forThe()->css(".linkPassText")->descendantOf(self::currentSectionDetailsView())->
|
||||
return Locator::forThe()->css(".linkPassText")->descendantOf(self::detailsView())->
|
||||
describedAs("Password protect field in the details view in Files app");
|
||||
}
|
||||
|
||||
|
@ -250,7 +240,7 @@ class FilesAppContext implements Context, ActorAwareInterface {
|
|||
* @return Locator
|
||||
*/
|
||||
public static function passwordProtectWorkingIcon() {
|
||||
return Locator::forThe()->css(".linkPass .icon-loading-small")->descendantOf(self::currentSectionDetailsView())->
|
||||
return Locator::forThe()->css(".linkPass .icon-loading-small")->descendantOf(self::detailsView())->
|
||||
describedAs("Password protect working icon in the details view in Files app");
|
||||
}
|
||||
|
||||
|
@ -265,14 +255,14 @@ class FilesAppContext implements Context, ActorAwareInterface {
|
|||
* @Given I open the input field for tags in the details view
|
||||
*/
|
||||
public function iOpenTheInputFieldForTagsInTheDetailsView() {
|
||||
$this->actor->find(self::fileDetailsInCurrentSectionDetailsViewWithText("Tags"), 10)->click();
|
||||
$this->actor->find(self::fileDetailsInDetailsViewWithText("Tags"), 10)->click();
|
||||
}
|
||||
|
||||
/**
|
||||
* @Given I open the :tabName tab in the details view
|
||||
*/
|
||||
public function iOpenTheTabInTheDetailsView($tabName) {
|
||||
$this->actor->find(self::tabHeaderInCurrentSectionDetailsViewNamed($tabName), 10)->click();
|
||||
$this->actor->find(self::tabHeaderInDetailsViewNamed($tabName), 10)->click();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -347,35 +337,29 @@ class FilesAppContext implements Context, ActorAwareInterface {
|
|||
}
|
||||
|
||||
/**
|
||||
* @Then I see that the details view for :section section is open
|
||||
* @Then I see that the details view is open
|
||||
*/
|
||||
public function iSeeThatTheDetailsViewForSectionIsOpen($section) {
|
||||
PHPUnit_Framework_Assert::assertTrue(
|
||||
$this->actor->find(self::detailsViewForSection($section), 10)->isVisible());
|
||||
|
||||
$otherSections = self::sections();
|
||||
unset($otherSections[$section]);
|
||||
|
||||
$this->assertDetailsViewForSectionsAreClosed($otherSections);
|
||||
public function iSeeThatTheDetailsViewIsOpen() {
|
||||
// The sidebar always exists in the DOM, so it has to be explicitly
|
||||
// waited for it to be visible instead of relying on the implicit wait
|
||||
// made to find the element.
|
||||
if (!WaitFor::elementToBeEventuallyShown(
|
||||
$this->actor,
|
||||
self::detailsView(),
|
||||
$timeout = 10 * $this->actor->getFindTimeoutMultiplier())) {
|
||||
PHPUnit_Framework_Assert::fail("The details view is not open yet after $timeout seconds");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @Then I see that the details view is closed
|
||||
*/
|
||||
public function iSeeThatTheDetailsViewIsClosed() {
|
||||
PHPUnit_Framework_Assert::assertNotNull($this->actor->find(self::currentSectionMainView(), 10));
|
||||
|
||||
$this->assertDetailsViewForSectionsAreClosed(self::sections());
|
||||
}
|
||||
|
||||
private function assertDetailsViewForSectionsAreClosed($sections) {
|
||||
foreach ($sections as $section => $id) {
|
||||
try {
|
||||
PHPUnit_Framework_Assert::assertFalse(
|
||||
$this->actor->find(self::detailsViewForSection($section))->isVisible(),
|
||||
"Details view for section $section is open but it should be closed");
|
||||
} catch (NoSuchElementException $exception) {
|
||||
}
|
||||
if (!WaitFor::elementToBeEventuallyNotShown(
|
||||
$this->actor,
|
||||
self::detailsView(),
|
||||
$timeout = 10 * $this->actor->getFindTimeoutMultiplier())) {
|
||||
PHPUnit_Framework_Assert::fail("The details view is not closed yet after $timeout seconds");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -384,7 +368,7 @@ class FilesAppContext implements Context, ActorAwareInterface {
|
|||
*/
|
||||
public function iSeeThatTheFileNameShownInTheDetailsViewIs($fileName) {
|
||||
PHPUnit_Framework_Assert::assertEquals(
|
||||
$this->actor->find(self::fileNameInCurrentSectionDetailsView(), 10)->getText(), $fileName);
|
||||
$this->actor->find(self::fileNameInDetailsView(), 10)->getText(), $fileName);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -392,7 +376,7 @@ class FilesAppContext implements Context, ActorAwareInterface {
|
|||
*/
|
||||
public function iSeeThatTheInputFieldForTagsInTheDetailsViewIsShown() {
|
||||
PHPUnit_Framework_Assert::assertTrue(
|
||||
$this->actor->find(self::inputFieldForTagsInCurrentSectionDetailsView(), 10)->isVisible());
|
||||
$this->actor->find(self::inputFieldForTagsInDetailsView(), 10)->isVisible());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -400,7 +384,7 @@ class FilesAppContext implements Context, ActorAwareInterface {
|
|||
*/
|
||||
public function iSeeThatTheInputFieldForTagsInTheDetailsViewContainsTheTag($tag) {
|
||||
PHPUnit_Framework_Assert::assertTrue(
|
||||
$this->actor->find(self::itemInInputFieldForTagsInCurrentSectionDetailsViewForTag($tag), 10)->isVisible());
|
||||
$this->actor->find(self::itemInInputFieldForTagsInDetailsViewForTag($tag), 10)->isVisible());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -411,7 +395,7 @@ class FilesAppContext implements Context, ActorAwareInterface {
|
|||
|
||||
try {
|
||||
PHPUnit_Framework_Assert::assertFalse(
|
||||
$this->actor->find(self::itemInInputFieldForTagsInCurrentSectionDetailsViewForTag($tag))->isVisible());
|
||||
$this->actor->find(self::itemInInputFieldForTagsInDetailsViewForTag($tag))->isVisible());
|
||||
} catch (NoSuchElementException $exception) {
|
||||
}
|
||||
}
|
||||
|
@ -441,7 +425,7 @@ class FilesAppContext implements Context, ActorAwareInterface {
|
|||
public function iSeeThatTheTabInTheDetailsViewIsEventuallyLoaded($tabName) {
|
||||
if (!WaitFor::elementToBeEventuallyNotShown(
|
||||
$this->actor,
|
||||
self::loadingIconForTabInCurrentSectionDetailsViewNamed($tabName),
|
||||
self::loadingIconForTabInDetailsViewNamed($tabName),
|
||||
$timeout = 10 * $this->actor->getFindTimeoutMultiplier())) {
|
||||
PHPUnit_Framework_Assert::fail("The $tabName tab in the details view has not been loaded after $timeout seconds");
|
||||
}
|
||||
|
|
|
@ -1,23 +1,23 @@
|
|||
/**
|
||||
* ownCloud
|
||||
*
|
||||
* @author Vincent Petry
|
||||
* @copyright 2014 Vincent Petry <pvince81@owncloud.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3 of the License, or any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU AFFERO GENERAL PUBLIC LICENSE for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
* ownCloud
|
||||
*
|
||||
* @author Vincent Petry
|
||||
* @copyright 2014 Vincent Petry <pvince81@owncloud.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3 of the License, or any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU AFFERO GENERAL PUBLIC LICENSE for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* This node module is run by the karma executable to specify its configuration.
|
||||
|
@ -35,7 +35,6 @@
|
|||
|
||||
/* jshint node: true */
|
||||
module.exports = function(config) {
|
||||
|
||||
function findApps() {
|
||||
/*
|
||||
var fs = require('fs');
|
||||
|
@ -115,12 +114,7 @@ module.exports = function(config) {
|
|||
name: 'settings',
|
||||
srcFiles: [
|
||||
'settings/js/apps.js',
|
||||
'settings/js/users/deleteHandler.js',
|
||||
'core/vendor/marked/marked.min.js'
|
||||
],
|
||||
testFiles: [
|
||||
'settings/tests/js/appsSpec.js',
|
||||
'settings/tests/js/users/deleteHandlerSpec.js'
|
||||
]
|
||||
}
|
||||
];
|
||||
|
@ -130,14 +124,16 @@ module.exports = function(config) {
|
|||
// it is useful to disable coverage for debugging
|
||||
// because the coverage preprocessor will wrap the JS files somehow
|
||||
var enableCoverage = !parseInt(process.env.NOCOVERAGE, 10);
|
||||
console.log('Coverage preprocessor: ', enableCoverage?'enabled':'disabled');
|
||||
console.log(
|
||||
'Coverage preprocessor: ',
|
||||
enableCoverage ? 'enabled' : 'disabled'
|
||||
);
|
||||
|
||||
// default apps to test when none is specified (TODO: read from filesystem ?)
|
||||
var appsToTest = process.env.KARMA_TESTSUITE;
|
||||
if (appsToTest) {
|
||||
if (appsToTest) {
|
||||
appsToTest = appsToTest.split(' ');
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
appsToTest = ['core'].concat(findApps());
|
||||
}
|
||||
|
||||
|
@ -167,19 +163,19 @@ module.exports = function(config) {
|
|||
|
||||
var srcFile, i;
|
||||
// add vendor library files
|
||||
for ( i = 0; i < coreModule.vendor.length; i++ ) {
|
||||
for (i = 0; i < coreModule.vendor.length; i++) {
|
||||
srcFile = vendorPath + coreModule.vendor[i];
|
||||
files.push(srcFile);
|
||||
}
|
||||
|
||||
// add core library files
|
||||
for ( i = 0; i < coreModule.libraries.length; i++ ) {
|
||||
for (i = 0; i < coreModule.libraries.length; i++) {
|
||||
srcFile = corePath + coreModule.libraries[i];
|
||||
files.push(srcFile);
|
||||
}
|
||||
|
||||
// add core modules files
|
||||
for ( i = 0; i < coreModule.modules.length; i++ ) {
|
||||
for (i = 0; i < coreModule.modules.length; i++) {
|
||||
srcFile = corePath + coreModule.modules[i];
|
||||
files.push(srcFile);
|
||||
if (enableCoverage) {
|
||||
|
@ -197,7 +193,7 @@ module.exports = function(config) {
|
|||
|
||||
function addApp(app) {
|
||||
// if only a string was specified, expand to structure
|
||||
if (typeof(app) === 'string') {
|
||||
if (typeof app === 'string') {
|
||||
app = {
|
||||
srcFiles: 'apps/' + app + '/js/**/*.js',
|
||||
testFiles: 'apps/' + app + '/tests/js/**/*.js'
|
||||
|
@ -217,23 +213,47 @@ module.exports = function(config) {
|
|||
}
|
||||
|
||||
// add source files for apps to test
|
||||
for ( i = 0; i < appsToTest.length; i++ ) {
|
||||
for (i = 0; i < appsToTest.length; i++) {
|
||||
addApp(appsToTest[i]);
|
||||
}
|
||||
|
||||
// serve images to avoid warnings
|
||||
files.push({pattern: 'core/img/**/*', watched: false, included: false, served: true});
|
||||
files.push({pattern: 'core/css/images/*', watched: false, included: false, served: true});
|
||||
files.push({
|
||||
pattern: 'core/img/**/*',
|
||||
watched: false,
|
||||
included: false,
|
||||
served: true
|
||||
});
|
||||
files.push({
|
||||
pattern: 'core/css/images/*',
|
||||
watched: false,
|
||||
included: false,
|
||||
served: true
|
||||
});
|
||||
|
||||
// include core CSS
|
||||
files.push({pattern: 'core/css/*.css', watched: true, included: true, served: true});
|
||||
files.push({pattern: 'tests/css/*.css', watched: true, included: true, served: true});
|
||||
files.push({
|
||||
pattern: 'core/css/*.css',
|
||||
watched: true,
|
||||
included: true,
|
||||
served: true
|
||||
});
|
||||
files.push({
|
||||
pattern: 'tests/css/*.css',
|
||||
watched: true,
|
||||
included: true,
|
||||
served: true
|
||||
});
|
||||
|
||||
// Allow fonts
|
||||
files.push({pattern: 'core/fonts/*', watched: false, included: false, served: true});
|
||||
files.push({
|
||||
pattern: 'core/fonts/*',
|
||||
watched: false,
|
||||
included: false,
|
||||
served: true
|
||||
});
|
||||
|
||||
config.set({
|
||||
|
||||
// base path, that will be used to resolve files and exclude
|
||||
basePath: '..',
|
||||
|
||||
|
@ -244,9 +264,7 @@ module.exports = function(config) {
|
|||
files: files,
|
||||
|
||||
// list of files to exclude
|
||||
exclude: [
|
||||
|
||||
],
|
||||
exclude: [],
|
||||
|
||||
proxies: {
|
||||
// prevent warnings for images
|
||||
|
@ -271,7 +289,7 @@ module.exports = function(config) {
|
|||
preprocessors: preprocessors,
|
||||
|
||||
coverageReporter: {
|
||||
dir:'tests/karma-coverage',
|
||||
dir: 'tests/karma-coverage',
|
||||
reporters: [
|
||||
{ type: 'html' },
|
||||
{ type: 'cobertura' },
|
||||
|
@ -282,7 +300,6 @@ module.exports = function(config) {
|
|||
// enable / disable colors in the output (reporters and logs)
|
||||
colors: true,
|
||||
|
||||
|
||||
// level of logging
|
||||
// possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
|
||||
logLevel: config.LOG_INFO,
|
||||
|
@ -298,13 +315,30 @@ module.exports = function(config) {
|
|||
// - Safari (only Mac; has to be installed with `npm install karma-safari-launcher`)
|
||||
// - PhantomJS
|
||||
// - IE (only Windows; has to be installed with `npm install karma-ie-launcher`)
|
||||
// use PhantomJS_debug for extra local debug
|
||||
browsers: ['PhantomJS'],
|
||||
|
||||
plugins: [
|
||||
'karma-phantomjs-launcher',
|
||||
'karma-coverage',
|
||||
'karma-jasmine',
|
||||
'karma-jasmine-sinon',
|
||||
'karma-viewport',
|
||||
'karma-junit-reporter'
|
||||
],
|
||||
// you can define custom flags
|
||||
customLaunchers: {
|
||||
PhantomJS_debug: {
|
||||
base: 'PhantomJS',
|
||||
debug: true
|
||||
}
|
||||
},
|
||||
|
||||
// If browser does not capture in given timeout [ms], kill it
|
||||
captureTimeout: 60000,
|
||||
|
||||
// Continuous Integration mode
|
||||
// if true, it capture browsers, run tests and exit
|
||||
singleRun: false
|
||||
});
|
||||
});
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue