BigW Consortium Gitlab
Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
G
gitlab-ce
Project
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
Forest Godfrey
gitlab-ce
Commits
9c6ce2e8
Commit
9c6ce2e8
authored
Dec 11, 2017
by
Jacob Schatz
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'backport-epic-in-issue' into 'master'
Backport epic in issue See merge request gitlab-org/gitlab-ce!15799
parents
0cdc840b
bd7218f2
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
151 additions
and
82 deletions
+151
-82
sidebar_assignees.js
...scripts/sidebar/components/assignees/sidebar_assignees.js
+15
-9
sidebar_participants.vue
.../sidebar/components/participants/sidebar_participants.vue
+8
-3
sidebar_subscriptions.vue
...idebar/components/subscriptions/sidebar_subscriptions.vue
+6
-3
mount_sidebar.js
app/assets/javascripts/sidebar/mount_sidebar.js
+56
-15
sidebar_bundle.js
app/assets/javascripts/sidebar/sidebar_bundle.js
+2
-3
sidebar_mediator.js
app/assets/javascripts/sidebar/sidebar_mediator.js
+0
-1
sidebar_store.js
app/assets/javascripts/sidebar/stores/sidebar_store.js
+27
-23
sidebar.scss
app/assets/stylesheets/framework/sidebar.scss
+5
-0
issuable.scss
app/assets/stylesheets/pages/issuable.scss
+2
-1
sidebar_assignees_spec.js
spec/javascripts/sidebar/sidebar_assignees_spec.js
+24
-21
sidebar_subscriptions_spec.js
spec/javascripts/sidebar/sidebar_subscriptions_spec.js
+6
-3
No files found.
app/assets/javascripts/sidebar/components/assignees/sidebar_assignees.js
View file @
9c6ce2e8
import
Flash
from
'../../../flash'
;
import
AssigneeTitle
from
'./assignee_title'
;
import
Assignees
from
'./assignees'
;
import
Store
from
'../../stores/sidebar_store'
;
import
Mediator
from
'../../sidebar_mediator'
;
import
eventHub
from
'../../event_hub'
;
export
default
{
name
:
'SidebarAssignees'
,
data
()
{
return
{
mediator
:
new
Mediator
(),
store
:
new
Store
(),
loading
:
false
,
field
:
''
,
};
},
props
:
{
mediator
:
{
type
:
Object
,
required
:
true
,
},
field
:
{
type
:
String
,
required
:
true
,
},
signedIn
:
{
type
:
Boolean
,
required
:
false
,
default
:
false
,
},
},
components
:
{
'assignee-title'
:
AssigneeTitle
,
assignees
:
Assignees
,
...
...
@@ -61,10 +71,6 @@ export default {
eventHub
.
$off
(
'sidebar.removeAllAssignees'
,
this
.
removeAllAssignees
);
eventHub
.
$off
(
'sidebar.saveAssignees'
,
this
.
saveAssignees
);
},
beforeMount
()
{
this
.
field
=
this
.
$el
.
dataset
.
field
;
this
.
signedIn
=
typeof
this
.
$el
.
dataset
.
signedIn
!==
'undefined'
;
},
template
:
`
<div>
<assignee-title
...
...
app/assets/javascripts/sidebar/components/participants/sidebar_participants.vue
View file @
9c6ce2e8
<
script
>
import
Store
from
'../../stores/sidebar_store'
;
import
Mediator
from
'../../sidebar_mediator'
;
import
participants
from
'./participants.vue'
;
export
default
{
data
()
{
return
{
mediator
:
new
Mediator
(),
store
:
new
Store
(),
};
},
props
:
{
mediator
:
{
type
:
Object
,
required
:
true
,
},
},
components
:
{
participants
,
},
...
...
@@ -21,6 +25,7 @@ export default {
<participants
:loading=
"store.isFetching.participants"
:participants=
"store.participants"
:number-of-less-participants=
"7"
/>
:number-of-less-participants=
"7"
/>
</div>
</
template
>
app/assets/javascripts/sidebar/components/subscriptions/sidebar_subscriptions.vue
View file @
9c6ce2e8
<
script
>
import
Store
from
'../../stores/sidebar_store'
;
import
Mediator
from
'../../sidebar_mediator'
;
import
eventHub
from
'../../event_hub'
;
import
Flash
from
'../../../flash'
;
import
{
__
}
from
'../../../locale'
;
...
...
@@ -9,11 +8,15 @@ import subscriptions from './subscriptions.vue';
export
default
{
data
()
{
return
{
mediator
:
new
Mediator
(),
store
:
new
Store
(),
};
},
props
:
{
mediator
:
{
type
:
Object
,
required
:
true
,
},
},
components
:
{
subscriptions
,
},
...
...
app/assets/javascripts/sidebar/mount_sidebar.js
View file @
9c6ce2e8
...
...
@@ -10,6 +10,27 @@ import Translate from '../vue_shared/translate';
Vue
.
use
(
Translate
);
function
mountAssigneesComponent
(
mediator
)
{
const
el
=
document
.
getElementById
(
'js-vue-sidebar-assignees'
);
if
(
!
el
)
return
;
// eslint-disable-next-line no-new
new
Vue
({
el
,
components
:
{
SidebarAssignees
,
},
render
:
createElement
=>
createElement
(
'sidebar-assignees'
,
{
props
:
{
mediator
,
field
:
el
.
dataset
.
field
,
signedIn
:
el
.
hasAttribute
(
'data-signed-in'
),
},
}),
});
}
function
mountConfidentialComponent
(
mediator
)
{
const
el
=
document
.
getElementById
(
'js-confidential-entry-point'
);
...
...
@@ -49,9 +70,10 @@ function mountLockComponent(mediator) {
}).
$mount
(
el
);
}
function
mountParticipantsComponent
()
{
function
mountParticipantsComponent
(
mediator
)
{
const
el
=
document
.
querySelector
(
'.js-sidebar-participants-entry-point'
);
// eslint-disable-next-line no-new
if
(
!
el
)
return
;
// eslint-disable-next-line no-new
...
...
@@ -60,11 +82,15 @@ function mountParticipantsComponent() {
components
:
{
sidebarParticipants
,
},
render
:
createElement
=>
createElement
(
'sidebar-participants'
,
{}),
render
:
createElement
=>
createElement
(
'sidebar-participants'
,
{
props
:
{
mediator
,
},
}),
});
}
function
mountSubscriptionsComponent
()
{
function
mountSubscriptionsComponent
(
mediator
)
{
const
el
=
document
.
querySelector
(
'.js-sidebar-subscriptions-entry-point'
);
if
(
!
el
)
return
;
...
...
@@ -75,22 +101,35 @@ function mountSubscriptionsComponent() {
components
:
{
sidebarSubscriptions
,
},
render
:
createElement
=>
createElement
(
'sidebar-subscriptions'
,
{}),
render
:
createElement
=>
createElement
(
'sidebar-subscriptions'
,
{
props
:
{
mediator
,
},
}),
});
}
function
mount
(
mediator
)
{
const
sidebarAssigneesEl
=
document
.
getElementById
(
'js-vue-sidebar-assignees'
);
// Only create the sidebarAssignees vue app if it is found in the DOM
// We currently do not use sidebarAssignees for the MR page
if
(
sidebarAssigneesEl
)
{
new
Vue
(
SidebarAssignees
).
$mount
(
sidebarAssigneesEl
);
}
function
mountTimeTrackingComponent
()
{
const
el
=
document
.
getElementById
(
'issuable-time-tracker'
);
if
(
!
el
)
return
;
// eslint-disable-next-line no-new
new
Vue
({
el
,
components
:
{
SidebarTimeTracking
,
},
render
:
createElement
=>
createElement
(
'sidebar-time-tracking'
,
{}),
});
}
export
function
mountSidebar
(
mediator
)
{
mountAssigneesComponent
(
mediator
);
mountConfidentialComponent
(
mediator
);
mountLockComponent
(
mediator
);
mountParticipantsComponent
();
mountSubscriptionsComponent
();
mountParticipantsComponent
(
mediator
);
mountSubscriptionsComponent
(
mediator
);
new
SidebarMoveIssue
(
mediator
,
...
...
@@ -98,7 +137,9 @@ function mount(mediator) {
$
(
'.js-move-issue-confirmation-button'
),
).
init
();
new
Vue
(
SidebarTimeTracking
).
$mount
(
'#issuable-time-tracker'
);
mountTimeTrackingComponent
(
);
}
export
default
mount
;
export
function
getSidebarOptions
()
{
return
JSON
.
parse
(
document
.
querySelector
(
'.js-sidebar-options'
).
innerHTML
);
}
app/assets/javascripts/sidebar/sidebar_bundle.js
View file @
9c6ce2e8
import
Mediator
from
'./sidebar_mediator'
;
import
mountSidebar
from
'./mount_sidebar'
;
import
{
mountSidebar
,
getSidebarOptions
}
from
'./mount_sidebar'
;
function
domContentLoaded
()
{
const
sidebarOptions
=
JSON
.
parse
(
document
.
querySelector
(
'.js-sidebar-options'
).
innerHTML
);
const
mediator
=
new
Mediator
(
sidebarOptions
);
const
mediator
=
new
Mediator
(
getSidebarOptions
());
mediator
.
fetch
();
mountSidebar
(
mediator
);
...
...
app/assets/javascripts/sidebar/sidebar_mediator.js
View file @
9c6ce2e8
...
...
@@ -8,7 +8,6 @@ export default class SidebarMediator {
if
(
!
SidebarMediator
.
singleton
)
{
this
.
initSingleton
(
options
);
}
return
SidebarMediator
.
singleton
;
}
...
...
app/assets/javascripts/sidebar/stores/sidebar_store.js
View file @
9c6ce2e8
export
default
class
SidebarStore
{
constructor
(
store
)
{
constructor
(
options
)
{
if
(
!
SidebarStore
.
singleton
)
{
const
{
currentUser
,
rootPath
,
editable
}
=
store
;
this
.
currentUser
=
currentUser
;
this
.
rootPath
=
rootPath
;
this
.
editable
=
editable
;
this
.
timeEstimate
=
0
;
this
.
totalTimeSpent
=
0
;
this
.
humanTimeEstimate
=
''
;
this
.
humanTimeSpent
=
''
;
this
.
assignees
=
[];
this
.
isFetching
=
{
assignees
:
true
,
participants
:
true
,
subscriptions
:
true
,
};
this
.
isLoading
=
{};
this
.
autocompleteProjects
=
[];
this
.
moveToProjectId
=
0
;
this
.
isLockDialogOpen
=
false
;
this
.
participants
=
[];
this
.
subscribed
=
null
;
SidebarStore
.
singleton
=
this
;
this
.
initSingleton
(
options
);
}
return
SidebarStore
.
singleton
;
}
initSingleton
(
options
)
{
const
{
currentUser
,
rootPath
,
editable
}
=
options
;
this
.
currentUser
=
currentUser
;
this
.
rootPath
=
rootPath
;
this
.
editable
=
editable
;
this
.
timeEstimate
=
0
;
this
.
totalTimeSpent
=
0
;
this
.
humanTimeEstimate
=
''
;
this
.
humanTimeSpent
=
''
;
this
.
assignees
=
[];
this
.
isFetching
=
{
assignees
:
true
,
participants
:
true
,
subscriptions
:
true
,
};
this
.
isLoading
=
{};
this
.
autocompleteProjects
=
[];
this
.
moveToProjectId
=
0
;
this
.
isLockDialogOpen
=
false
;
this
.
participants
=
[];
this
.
subscribed
=
null
;
SidebarStore
.
singleton
=
this
;
}
setAssigneeData
(
data
)
{
this
.
isFetching
.
assignees
=
false
;
if
(
data
.
assignees
)
{
...
...
app/assets/stylesheets/framework/sidebar.scss
View file @
9c6ce2e8
...
...
@@ -50,6 +50,11 @@
&
:not
(
.disabled
)
{
cursor
:
pointer
;
}
svg
{
width
:
$gl-padding
;
height
:
$gl-padding
;
}
}
}
...
...
app/assets/stylesheets/pages/issuable.scss
View file @
9c6ce2e8
...
...
@@ -470,7 +470,8 @@
}
}
.milestone-title
span
{
.milestone-title
span
,
.collapse-truncated-title
{
@include
str-truncated
(
100%
);
display
:
block
;
margin
:
0
4px
;
...
...
spec/javascripts/sidebar/sidebar_assignees_spec.js
View file @
9c6ce2e8
...
...
@@ -4,20 +4,29 @@ import SidebarMediator from '~/sidebar/sidebar_mediator';
import
SidebarService
from
'~/sidebar/services/sidebar_service'
;
import
SidebarStore
from
'~/sidebar/stores/sidebar_store'
;
import
Mock
from
'./mock_data'
;
import
mountComponent
from
'../helpers/vue_mount_component_helper'
;
describe
(
'sidebar assignees'
,
()
=>
{
let
component
;
let
SidebarAssigneeComponent
;
let
vm
;
let
mediator
;
let
sidebarAssigneesEl
;
preloadFixtures
(
'issues/open-issue.html.raw'
);
beforeEach
(()
=>
{
Vue
.
http
.
interceptors
.
push
(
Mock
.
sidebarMockInterceptor
);
SidebarAssigneeComponent
=
Vue
.
extend
(
SidebarAssignees
);
spyOn
(
SidebarMediator
.
prototype
,
'saveAssignees'
).
and
.
callThrough
();
spyOn
(
SidebarMediator
.
prototype
,
'assignYourself'
).
and
.
callThrough
();
this
.
mediator
=
new
SidebarMediator
(
Mock
.
mediator
);
loadFixtures
(
'issues/open-issue.html.raw'
);
this
.
sidebarAssigneesEl
=
document
.
querySelector
(
'#js-vue-sidebar-assignees'
);
mediator
=
new
SidebarMediator
(
Mock
.
mediator
);
spyOn
(
mediator
,
'saveAssignees'
).
and
.
callThrough
();
spyOn
(
mediator
,
'assignYourself'
).
and
.
callThrough
();
const
SidebarAssigneeComponent
=
Vue
.
extend
(
SidebarAssignees
);
sidebarAssigneesEl
=
document
.
querySelector
(
'#js-vue-sidebar-assignees'
);
vm
=
mountComponent
(
SidebarAssigneeComponent
,
{
mediator
,
field
:
sidebarAssigneesEl
.
dataset
.
field
,
},
sidebarAssigneesEl
);
});
afterEach
(()
=>
{
...
...
@@ -28,30 +37,24 @@ describe('sidebar assignees', () => {
});
it
(
'calls the mediator when saves the assignees'
,
()
=>
{
component
=
new
SidebarAssigneeComponent
()
.
$mount
(
this
.
sidebarAssigneesEl
);
component
.
saveAssignees
();
expect
(
SidebarMediator
.
prototype
.
saveAssignees
).
toHaveBeenCalled
();
vm
.
saveAssignees
();
expect
(
mediator
.
saveAssignees
).
toHaveBeenCalled
();
});
it
(
'calls the mediator when "assignSelf" method is called'
,
()
=>
{
component
=
new
SidebarAssigneeComponent
()
.
$mount
(
this
.
sidebarAssigneesEl
);
component
.
assignSelf
();
vm
.
assignSelf
();
expect
(
SidebarMediator
.
prototype
.
assignYourself
).
toHaveBeenCalled
();
expect
(
this
.
mediator
.
store
.
assignees
.
length
).
toEqual
(
1
);
expect
(
mediator
.
assignYourself
).
toHaveBeenCalled
();
expect
(
mediator
.
store
.
assignees
.
length
).
toEqual
(
1
);
});
it
(
'hides assignees until fetched'
,
(
done
)
=>
{
component
=
new
SidebarAssigneeComponent
().
$mount
(
this
.
sidebarAssigneesEl
);
const
currentAssignee
=
this
.
sidebarAssigneesEl
.
querySelector
(
'.value'
);
const
currentAssignee
=
sidebarAssigneesEl
.
querySelector
(
'.value'
);
expect
(
currentAssignee
).
toBe
(
null
);
component
.
store
.
isFetching
.
assignees
=
false
;
vm
.
store
.
isFetching
.
assignees
=
false
;
Vue
.
nextTick
(()
=>
{
expect
(
component
.
$el
.
querySelector
(
'.value'
)).
toBeVisible
();
expect
(
vm
.
$el
.
querySelector
(
'.value'
)).
toBeVisible
();
done
();
});
});
...
...
spec/javascripts/sidebar/sidebar_subscriptions_spec.js
View file @
9c6ce2e8
...
...
@@ -26,11 +26,14 @@ describe('Sidebar Subscriptions', function () {
});
it
(
'calls the mediator toggleSubscription on event'
,
()
=>
{
spyOn
(
SidebarMediator
.
prototype
,
'toggleSubscription'
).
and
.
returnValue
(
Promise
.
resolve
());
vm
=
mountComponent
(
SidebarSubscriptions
,
{});
const
mediator
=
new
SidebarMediator
();
spyOn
(
mediator
,
'toggleSubscription'
).
and
.
returnValue
(
Promise
.
resolve
());
vm
=
mountComponent
(
SidebarSubscriptions
,
{
mediator
,
});
eventHub
.
$emit
(
'toggleSubscription'
);
expect
(
SidebarMediator
.
prototype
.
toggleSubscription
).
toHaveBeenCalled
();
expect
(
mediator
.
toggleSubscription
).
toHaveBeenCalled
();
});
});
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment