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
75f28ea4
Commit
75f28ea4
authored
Dec 11, 2017
by
Jacob Schatz
Committed by
LUKE BENNETT
Dec 13, 2017
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Merge branch 'backport-epic-in-issue' into 'master'
Backport epic in issue See merge request gitlab-org/gitlab-ce!15799 (cherry picked from commit
9c6ce2e8
)
bd7218f2
Backport epic in issue
parent
47f916f9
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 @
75f28ea4
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 @
75f28ea4
<
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 @
75f28ea4
<
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 @
75f28ea4
...
...
@@ -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 @
75f28ea4
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 @
75f28ea4
...
...
@@ -7,7 +7,6 @@ export default class SidebarMediator {
if
(
!
SidebarMediator
.
singleton
)
{
this
.
initSingleton
(
options
);
}
return
SidebarMediator
.
singleton
;
}
...
...
app/assets/javascripts/sidebar/stores/sidebar_store.js
View file @
75f28ea4
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 @
75f28ea4
...
...
@@ -50,6 +50,11 @@
&
:not
(
.disabled
)
{
cursor
:
pointer
;
}
svg
{
width
:
$gl-padding
;
height
:
$gl-padding
;
}
}
}
...
...
app/assets/stylesheets/pages/issuable.scss
View file @
75f28ea4
...
...
@@ -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 @
75f28ea4
...
...
@@ -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 @
75f28ea4
...
...
@@ -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