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
f3433d8a
Commit
f3433d8a
authored
Dec 03, 2017
by
Eric Eastwood
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Backport changes from refactor sidebar weight block Vue and move to Issue Boards
See
https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/3566
parent
e0f84130
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
249 additions
and
131 deletions
+249
-131
issue.js
app/assets/javascripts/boards/models/issue.js
+5
-0
gl_dropdown.js
app/assets/javascripts/gl_dropdown.js
+2
-1
right_sidebar.js
app/assets/javascripts/right_sidebar.js
+3
-3
mount_sidebar.js
app/assets/javascripts/sidebar/mount_sidebar.js
+104
-0
sidebar_bundle.js
app/assets/javascripts/sidebar/sidebar_bundle.js
+2
-100
sidebar_mediator.js
app/assets/javascripts/sidebar/sidebar_mediator.js
+21
-13
sidebar_store.js
app/assets/javascripts/sidebar/stores/sidebar_store.js
+5
-0
issue_spec.js
spec/javascripts/boards/issue_spec.js
+6
-0
mock_data.js
spec/javascripts/sidebar/mock_data.js
+72
-10
sidebar_mediator_spec.js
spec/javascripts/sidebar/sidebar_mediator_spec.js
+23
-4
sidebar_store_spec.js
spec/javascripts/sidebar/sidebar_store_spec.js
+6
-0
No files found.
app/assets/javascripts/boards/models/issue.js
View file @
f3433d8a
...
...
@@ -20,6 +20,7 @@ class ListIssue {
this
.
isFetching
=
{
subscriptions
:
true
,
};
this
.
isLoading
=
{};
this
.
sidebarInfoEndpoint
=
obj
.
issue_sidebar_endpoint
;
this
.
toggleSubscriptionEndpoint
=
obj
.
toggle_subscription_endpoint
;
...
...
@@ -86,6 +87,10 @@ class ListIssue {
this
.
isFetching
[
key
]
=
value
;
}
setLoadingState
(
key
,
value
)
{
this
.
isLoading
[
key
]
=
value
;
}
update
(
url
)
{
const
data
=
{
issue
:
{
...
...
app/assets/javascripts/gl_dropdown.js
View file @
f3433d8a
...
...
@@ -514,10 +514,11 @@ GitLabDropdown = (function() {
const
dropdownToggle
=
this
.
dropdown
.
find
(
'.dropdown-menu-toggle'
);
const
hasFilterBulkUpdate
=
dropdownToggle
.
hasClass
(
'js-filter-bulk-update'
);
const
shouldRefreshOnOpen
=
dropdownToggle
.
hasClass
(
'js-gl-dropdown-refresh-on-open'
);
const
hasMultiSelect
=
dropdownToggle
.
hasClass
(
'js-multiselect'
);
// Makes indeterminate items effective
if
(
this
.
fullData
&&
hasFilterBulkUpdate
)
{
if
(
this
.
fullData
&&
(
shouldRefreshOnOpen
||
hasFilterBulkUpdate
)
)
{
this
.
parseData
(
this
.
fullData
);
}
...
...
app/assets/javascripts/right_sidebar.js
View file @
f3433d8a
...
...
@@ -15,7 +15,7 @@ import Cookies from 'js-cookie';
Sidebar
.
prototype
.
removeListeners
=
function
()
{
this
.
sidebar
.
off
(
'click'
,
'.sidebar-collapsed-icon'
);
$
(
'.dropdown'
)
.
off
(
'hidden.gl.dropdown'
);
this
.
sidebar
.
off
(
'hidden.gl.dropdown'
);
$
(
'.dropdown'
).
off
(
'loading.gl.dropdown'
);
$
(
'.dropdown'
).
off
(
'loaded.gl.dropdown'
);
$
(
document
).
off
(
'click'
,
'.js-sidebar-toggle'
);
...
...
@@ -25,7 +25,7 @@ import Cookies from 'js-cookie';
const
$document
=
$
(
document
);
this
.
sidebar
.
on
(
'click'
,
'.sidebar-collapsed-icon'
,
this
,
this
.
sidebarCollapseClicked
);
$
(
'.dropdown'
)
.
on
(
'hidden.gl.dropdown'
,
this
,
this
.
onSidebarDropdownHidden
);
this
.
sidebar
.
on
(
'hidden.gl.dropdown'
,
this
,
this
.
onSidebarDropdownHidden
);
$
(
'.dropdown'
).
on
(
'loading.gl.dropdown'
,
this
.
sidebarDropdownLoading
);
$
(
'.dropdown'
).
on
(
'loaded.gl.dropdown'
,
this
.
sidebarDropdownLoaded
);
...
...
@@ -180,7 +180,7 @@ import Cookies from 'js-cookie';
var
$block
,
sidebar
;
sidebar
=
e
.
data
;
e
.
preventDefault
();
$block
=
$
(
this
).
closest
(
'.block'
);
$block
=
$
(
e
.
target
).
closest
(
'.block'
);
return
sidebar
.
sidebarDropdownHidden
(
$block
);
};
...
...
app/assets/javascripts/sidebar/mount_sidebar.js
0 → 100644
View file @
f3433d8a
import
Vue
from
'vue'
;
import
SidebarTimeTracking
from
'./components/time_tracking/sidebar_time_tracking'
;
import
SidebarAssignees
from
'./components/assignees/sidebar_assignees'
;
import
ConfidentialIssueSidebar
from
'./components/confidential/confidential_issue_sidebar.vue'
;
import
SidebarMoveIssue
from
'./lib/sidebar_move_issue'
;
import
LockIssueSidebar
from
'./components/lock/lock_issue_sidebar.vue'
;
import
sidebarParticipants
from
'./components/participants/sidebar_participants.vue'
;
import
sidebarSubscriptions
from
'./components/subscriptions/sidebar_subscriptions.vue'
;
import
Translate
from
'../vue_shared/translate'
;
Vue
.
use
(
Translate
);
function
mountConfidentialComponent
(
mediator
)
{
const
el
=
document
.
getElementById
(
'js-confidential-entry-point'
);
if
(
!
el
)
return
;
const
dataNode
=
document
.
getElementById
(
'js-confidential-issue-data'
);
const
initialData
=
JSON
.
parse
(
dataNode
.
innerHTML
);
const
ConfidentialComp
=
Vue
.
extend
(
ConfidentialIssueSidebar
);
new
ConfidentialComp
({
propsData
:
{
isConfidential
:
initialData
.
is_confidential
,
isEditable
:
initialData
.
is_editable
,
service
:
mediator
.
service
,
},
}).
$mount
(
el
);
}
function
mountLockComponent
(
mediator
)
{
const
el
=
document
.
getElementById
(
'js-lock-entry-point'
);
if
(
!
el
)
return
;
const
dataNode
=
document
.
getElementById
(
'js-lock-issue-data'
);
const
initialData
=
JSON
.
parse
(
dataNode
.
innerHTML
);
const
LockComp
=
Vue
.
extend
(
LockIssueSidebar
);
new
LockComp
({
propsData
:
{
isLocked
:
initialData
.
is_locked
,
isEditable
:
initialData
.
is_editable
,
mediator
,
issuableType
:
gl
.
utils
.
isInIssuePage
()
?
'issue'
:
'merge_request'
,
},
}).
$mount
(
el
);
}
function
mountParticipantsComponent
()
{
const
el
=
document
.
querySelector
(
'.js-sidebar-participants-entry-point'
);
if
(
!
el
)
return
;
// eslint-disable-next-line no-new
new
Vue
({
el
,
components
:
{
sidebarParticipants
,
},
render
:
createElement
=>
createElement
(
'sidebar-participants'
,
{}),
});
}
function
mountSubscriptionsComponent
()
{
const
el
=
document
.
querySelector
(
'.js-sidebar-subscriptions-entry-point'
);
if
(
!
el
)
return
;
// eslint-disable-next-line no-new
new
Vue
({
el
,
components
:
{
sidebarSubscriptions
,
},
render
:
createElement
=>
createElement
(
'sidebar-subscriptions'
,
{}),
});
}
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
);
}
mountConfidentialComponent
(
mediator
);
mountLockComponent
(
mediator
);
mountParticipantsComponent
();
mountSubscriptionsComponent
();
new
SidebarMoveIssue
(
mediator
,
$
(
'.js-move-issue'
),
$
(
'.js-move-issue-confirmation-button'
),
).
init
();
new
Vue
(
SidebarTimeTracking
).
$mount
(
'#issuable-time-tracker'
);
}
export
default
mount
;
app/assets/javascripts/sidebar/sidebar_bundle.js
View file @
f3433d8a
import
Vue
from
'vue'
;
import
SidebarTimeTracking
from
'./components/time_tracking/sidebar_time_tracking'
;
import
SidebarAssignees
from
'./components/assignees/sidebar_assignees'
;
import
ConfidentialIssueSidebar
from
'./components/confidential/confidential_issue_sidebar.vue'
;
import
SidebarMoveIssue
from
'./lib/sidebar_move_issue'
;
import
LockIssueSidebar
from
'./components/lock/lock_issue_sidebar.vue'
;
import
sidebarParticipants
from
'./components/participants/sidebar_participants.vue'
;
import
sidebarSubscriptions
from
'./components/subscriptions/sidebar_subscriptions.vue'
;
import
Translate
from
'../vue_shared/translate'
;
import
Mediator
from
'./sidebar_mediator'
;
Vue
.
use
(
Translate
);
function
mountConfidentialComponent
(
mediator
)
{
const
el
=
document
.
getElementById
(
'js-confidential-entry-point'
);
if
(
!
el
)
return
;
const
dataNode
=
document
.
getElementById
(
'js-confidential-issue-data'
);
const
initialData
=
JSON
.
parse
(
dataNode
.
innerHTML
);
const
ConfidentialComp
=
Vue
.
extend
(
ConfidentialIssueSidebar
);
new
ConfidentialComp
({
propsData
:
{
isConfidential
:
initialData
.
is_confidential
,
isEditable
:
initialData
.
is_editable
,
service
:
mediator
.
service
,
},
}).
$mount
(
el
);
}
function
mountLockComponent
(
mediator
)
{
const
el
=
document
.
getElementById
(
'js-lock-entry-point'
);
if
(
!
el
)
return
;
const
dataNode
=
document
.
getElementById
(
'js-lock-issue-data'
);
const
initialData
=
JSON
.
parse
(
dataNode
.
innerHTML
);
const
LockComp
=
Vue
.
extend
(
LockIssueSidebar
);
new
LockComp
({
propsData
:
{
isLocked
:
initialData
.
is_locked
,
isEditable
:
initialData
.
is_editable
,
mediator
,
issuableType
:
gl
.
utils
.
isInIssuePage
()
?
'issue'
:
'merge_request'
,
},
}).
$mount
(
el
);
}
function
mountParticipantsComponent
()
{
const
el
=
document
.
querySelector
(
'.js-sidebar-participants-entry-point'
);
if
(
!
el
)
return
;
// eslint-disable-next-line no-new
new
Vue
({
el
,
components
:
{
sidebarParticipants
,
},
render
:
createElement
=>
createElement
(
'sidebar-participants'
,
{}),
});
}
function
mountSubscriptionsComponent
()
{
const
el
=
document
.
querySelector
(
'.js-sidebar-subscriptions-entry-point'
);
if
(
!
el
)
return
;
// eslint-disable-next-line no-new
new
Vue
({
el
,
components
:
{
sidebarSubscriptions
,
},
render
:
createElement
=>
createElement
(
'sidebar-subscriptions'
,
{}),
});
}
import
mountSidebar
from
'./mount_sidebar'
;
function
domContentLoaded
()
{
const
sidebarOptions
=
JSON
.
parse
(
document
.
querySelector
(
'.js-sidebar-options'
).
innerHTML
);
const
mediator
=
new
Mediator
(
sidebarOptions
);
mediator
.
fetch
();
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
);
}
mountConfidentialComponent
(
mediator
);
mountLockComponent
(
mediator
);
mountParticipantsComponent
();
mountSubscriptionsComponent
();
new
SidebarMoveIssue
(
mediator
,
$
(
'.js-move-issue'
),
$
(
'.js-move-issue-confirmation-button'
),
).
init
();
new
Vue
(
SidebarTimeTracking
).
$mount
(
'#issuable-time-tracker'
);
mountSidebar
(
mediator
);
}
document
.
addEventListener
(
'DOMContentLoaded'
,
domContentLoaded
);
...
...
app/assets/javascripts/sidebar/sidebar_mediator.js
View file @
f3433d8a
...
...
@@ -5,19 +5,23 @@ import Store from './stores/sidebar_store';
export
default
class
SidebarMediator
{
constructor
(
options
)
{
if
(
!
SidebarMediator
.
singleton
)
{
this
.
store
=
new
Store
(
options
);
this
.
service
=
new
Service
({
endpoint
:
options
.
endpoint
,
toggleSubscriptionEndpoint
:
options
.
toggleSubscriptionEndpoint
,
moveIssueEndpoint
:
options
.
moveIssueEndpoint
,
projectsAutocompleteEndpoint
:
options
.
projectsAutocompleteEndpoint
,
});
SidebarMediator
.
singleton
=
this
;
this
.
initSingleton
(
options
);
}
return
SidebarMediator
.
singleton
;
}
initSingleton
(
options
)
{
this
.
store
=
new
Store
(
options
);
this
.
service
=
new
Service
({
endpoint
:
options
.
endpoint
,
toggleSubscriptionEndpoint
:
options
.
toggleSubscriptionEndpoint
,
moveIssueEndpoint
:
options
.
moveIssueEndpoint
,
projectsAutocompleteEndpoint
:
options
.
projectsAutocompleteEndpoint
,
});
SidebarMediator
.
singleton
=
this
;
}
assignYourself
()
{
this
.
store
.
addAssignee
(
this
.
store
.
currentUser
);
}
...
...
@@ -35,17 +39,21 @@ export default class SidebarMediator {
}
fetch
()
{
this
.
service
.
get
()
return
this
.
service
.
get
()
.
then
(
response
=>
response
.
json
())
.
then
((
data
)
=>
{
this
.
store
.
setAssigneeData
(
data
);
this
.
store
.
setTimeTrackingData
(
data
);
this
.
store
.
setParticipantsData
(
data
);
this
.
store
.
setSubscriptionsData
(
data
);
this
.
processFetchedData
(
data
);
})
.
catch
(()
=>
new
Flash
(
'Error occurred when fetching sidebar data'
));
}
processFetchedData
(
data
)
{
this
.
store
.
setAssigneeData
(
data
);
this
.
store
.
setTimeTrackingData
(
data
);
this
.
store
.
setParticipantsData
(
data
);
this
.
store
.
setSubscriptionsData
(
data
);
}
toggleSubscription
()
{
this
.
store
.
setFetchingState
(
'subscriptions'
,
true
);
return
this
.
service
.
toggleSubscription
()
...
...
app/assets/javascripts/sidebar/stores/sidebar_store.js
View file @
f3433d8a
...
...
@@ -15,6 +15,7 @@ export default class SidebarStore {
participants
:
true
,
subscriptions
:
true
,
};
this
.
isLoading
=
{};
this
.
autocompleteProjects
=
[];
this
.
moveToProjectId
=
0
;
this
.
isLockDialogOpen
=
false
;
...
...
@@ -55,6 +56,10 @@ export default class SidebarStore {
this
.
isFetching
[
key
]
=
value
;
}
setLoadingState
(
key
,
value
)
{
this
.
isLoading
[
key
]
=
value
;
}
addAssignee
(
assignee
)
{
if
(
!
this
.
findAssignee
(
assignee
))
{
this
.
assignees
.
push
(
assignee
);
...
...
spec/javascripts/boards/issue_spec.js
View file @
f3433d8a
...
...
@@ -146,6 +146,12 @@ describe('Issue model', () => {
expect
(
issue
.
isFetching
.
subscriptions
).
toBe
(
false
);
});
it
(
'sets loading state'
,
()
=>
{
issue
.
setLoadingState
(
'foo'
,
true
);
expect
(
issue
.
isLoading
.
foo
).
toBe
(
true
);
});
describe
(
'update'
,
()
=>
{
it
(
'passes assignee ids when there are assignees'
,
(
done
)
=>
{
spyOn
(
Vue
.
http
,
'patch'
).
and
.
callFake
((
url
,
data
)
=>
{
...
...
spec/javascripts/sidebar/mock_data.js
View file @
f3433d8a
/* eslint-disable quote-props*/
const
sidebarMockData
=
{
const
RESPONSE_MAP
=
{
'GET'
:
{
'/gitlab-org/gitlab-shell/issues/5.json'
:
{
id
:
45
,
...
...
@@ -66,6 +66,65 @@ const sidebarMockData = {
},
labels
:
[],
},
'/gitlab-org/gitlab-shell/issues/5.json?serializer=sidebar'
:
{
assignees
:
[
{
name
:
'User 0'
,
username
:
'user0'
,
id
:
22
,
state
:
'active'
,
avatar_url
:
'http: //www.gravatar.com/avatar/52e4ce24a915fb7e51e1ad3b57f4b00a?s=80
\
u0026d=identicon'
,
web_url
:
'http: //localhost:3001/user0'
,
},
{
name
:
'Marguerite Bartell'
,
username
:
'tajuana'
,
id
:
18
,
state
:
'active'
,
avatar_url
:
'http: //www.gravatar.com/avatar/4852a41fb41616bf8f140d3701673f53?s=80
\
u0026d=identicon'
,
web_url
:
'http: //localhost:3001/tajuana'
,
},
{
name
:
'Laureen Ritchie'
,
username
:
'michaele.will'
,
id
:
16
,
state
:
'active'
,
avatar_url
:
'http: //www.gravatar.com/avatar/e301827eb03be955c9c172cb9a8e4e8a?s=80
\
u0026d=identicon'
,
web_url
:
'http: //localhost:3001/michaele.will'
,
},
],
human_time_estimate
:
null
,
human_total_time_spent
:
null
,
participants
:
[
{
name
:
'User 0'
,
username
:
'user0'
,
id
:
22
,
state
:
'active'
,
avatar_url
:
'http: //www.gravatar.com/avatar/52e4ce24a915fb7e51e1ad3b57f4b00a?s=80
\
u0026d=identicon'
,
web_url
:
'http: //localhost:3001/user0'
,
},
{
name
:
'Marguerite Bartell'
,
username
:
'tajuana'
,
id
:
18
,
state
:
'active'
,
avatar_url
:
'http: //www.gravatar.com/avatar/4852a41fb41616bf8f140d3701673f53?s=80
\
u0026d=identicon'
,
web_url
:
'http: //localhost:3001/tajuana'
,
},
{
name
:
'Laureen Ritchie'
,
username
:
'michaele.will'
,
id
:
16
,
state
:
'active'
,
avatar_url
:
'http: //www.gravatar.com/avatar/e301827eb03be955c9c172cb9a8e4e8a?s=80
\
u0026d=identicon'
,
web_url
:
'http: //localhost:3001/michaele.will'
,
},
],
subscribed
:
true
,
time_estimate
:
0
,
total_time_spent
:
0
,
},
'/autocomplete/projects?project_id=15'
:
[
{
'id'
:
0
,
...
...
@@ -113,9 +172,10 @@ const sidebarMockData = {
},
};
export
default
{
const
mockData
=
{
responseMap
:
RESPONSE_MAP
,
mediator
:
{
endpoint
:
'/gitlab-org/gitlab-shell/issues/5.json'
,
endpoint
:
'/gitlab-org/gitlab-shell/issues/5.json
?serializer=sidebar
'
,
toggleSubscriptionEndpoint
:
'/gitlab-org/gitlab-shell/issues/5/toggle_subscription'
,
moveIssueEndpoint
:
'/gitlab-org/gitlab-shell/issues/5/move'
,
projectsAutocompleteEndpoint
:
'/autocomplete/projects?project_id=15'
,
...
...
@@ -141,12 +201,14 @@ export default {
name
:
'Administrator'
,
username
:
'root'
,
},
};
sidebarMockInterceptor
(
request
,
next
)
{
const
body
=
sidebarMockData
[
request
.
method
.
toUpperCase
()][
request
.
url
];
mockData
.
sidebarMockInterceptor
=
function
(
request
,
next
)
{
const
body
=
this
.
responseMap
[
request
.
method
.
toUpperCase
()][
request
.
url
];
next
(
request
.
respondWith
(
JSON
.
stringify
(
body
),
{
status
:
200
,
}));
},
};
next
(
request
.
respondWith
(
JSON
.
stringify
(
body
),
{
status
:
200
,
}));
}.
bind
(
mockData
);
export
default
mockData
;
spec/javascripts/sidebar/sidebar_mediator_spec.js
View file @
f3433d8a
...
...
@@ -33,10 +33,29 @@ describe('Sidebar mediator', () => {
.
catch
(
done
.
fail
);
});
it
(
'fetches the data'
,
()
=>
{
spyOn
(
this
.
mediator
.
service
,
'get'
).
and
.
callThrough
();
this
.
mediator
.
fetch
();
expect
(
this
.
mediator
.
service
.
get
).
toHaveBeenCalled
();
it
(
'fetches the data'
,
(
done
)
=>
{
const
mockData
=
Mock
.
responseMap
.
GET
[
'/gitlab-org/gitlab-shell/issues/5.json?serializer=sidebar'
];
spyOn
(
this
.
mediator
,
'processFetchedData'
).
and
.
callThrough
();
this
.
mediator
.
fetch
()
.
then
(()
=>
{
expect
(
this
.
mediator
.
processFetchedData
).
toHaveBeenCalledWith
(
mockData
);
})
.
then
(
done
)
.
catch
(
done
.
fail
);
});
it
(
'processes fetched data'
,
()
=>
{
const
mockData
=
Mock
.
responseMap
.
GET
[
'/gitlab-org/gitlab-shell/issues/5.json?serializer=sidebar'
];
this
.
mediator
.
processFetchedData
(
mockData
);
expect
(
this
.
mediator
.
store
.
assignees
).
toEqual
(
mockData
.
assignees
);
expect
(
this
.
mediator
.
store
.
humanTimeEstimate
).
toEqual
(
mockData
.
human_time_estimate
);
expect
(
this
.
mediator
.
store
.
humanTotalTimeSpent
).
toEqual
(
mockData
.
human_total_time_spent
);
expect
(
this
.
mediator
.
store
.
participants
).
toEqual
(
mockData
.
participants
);
expect
(
this
.
mediator
.
store
.
subscribed
).
toEqual
(
mockData
.
subscribed
);
expect
(
this
.
mediator
.
store
.
timeEstimate
).
toEqual
(
mockData
.
time_estimate
);
expect
(
this
.
mediator
.
store
.
totalTimeSpent
).
toEqual
(
mockData
.
total_time_spent
);
});
it
(
'sets moveToProjectId'
,
()
=>
{
...
...
spec/javascripts/sidebar/sidebar_store_spec.js
View file @
f3433d8a
...
...
@@ -120,6 +120,12 @@ describe('Sidebar store', () => {
expect
(
this
.
store
.
isFetching
.
participants
).
toEqual
(
false
);
});
it
(
'sets loading state'
,
()
=>
{
this
.
store
.
setLoadingState
(
'assignees'
,
true
);
expect
(
this
.
store
.
isLoading
.
assignees
).
toEqual
(
true
);
});
it
(
'set time tracking data'
,
()
=>
{
this
.
store
.
setTimeTrackingData
(
Mock
.
time
);
expect
(
this
.
store
.
timeEstimate
).
toEqual
(
Mock
.
time
.
time_estimate
);
...
...
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