Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gitlab-ce
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
1
Merge Requests
1
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
gitlab-ce
Commits
17a35da6
Commit
17a35da6
authored
Oct 30, 2017
by
Filipa Lacerda
Committed by
Phil Hughes
Oct 30, 2017
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Ee 38869 importer status - Remove code from global namespace
parent
3dc544f4
Changes
13
Show whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
306 additions
and
477 deletions
+306
-477
app/assets/javascripts/boards/components/board_sidebar.js
app/assets/javascripts/boards/components/board_sidebar.js
+1
-1
app/assets/javascripts/dispatcher.js
app/assets/javascripts/dispatcher.js
+3
-3
app/assets/javascripts/importer_status.js
app/assets/javascripts/importer_status.js
+71
-73
app/assets/javascripts/init_issuable_sidebar.js
app/assets/javascripts/init_issuable_sidebar.js
+1
-1
app/assets/javascripts/issuable_bulk_update_actions.js
app/assets/javascripts/issuable_bulk_update_actions.js
+0
-1
app/assets/javascripts/issuable_bulk_update_sidebar.js
app/assets/javascripts/issuable_bulk_update_sidebar.js
+4
-0
app/assets/javascripts/issuable_context.js
app/assets/javascripts/issuable_context.js
+56
-57
app/assets/javascripts/issuable_form.js
app/assets/javascripts/issuable_form.js
+97
-100
app/assets/javascripts/issuable_index.js
app/assets/javascripts/issuable_index.js
+36
-165
app/assets/javascripts/main.js
app/assets/javascripts/main.js
+2
-3
spec/javascripts/issuable_context_spec.js
spec/javascripts/issuable_context_spec.js
+1
-2
spec/javascripts/issuable_spec.js
spec/javascripts/issuable_spec.js
+33
-69
spec/javascripts/labels_issue_sidebar_spec.js
spec/javascripts/labels_issue_sidebar_spec.js
+1
-2
No files found.
app/assets/javascripts/boards/components/board_sidebar.js
View file @
17a35da6
/* eslint-disable comma-dangle, space-before-function-paren, no-new */
/* global IssuableContext */
/* global MilestoneSelect */
/* global LabelsSelect */
/* global Sidebar */
...
...
@@ -11,6 +10,7 @@ import AssigneeTitle from '../../sidebar/components/assignees/assignee_title';
import
Assignees
from
'
../../sidebar/components/assignees/assignees
'
;
import
DueDateSelectors
from
'
../../due_date_select
'
;
import
'
./sidebar/remove_issue
'
;
import
IssuableContext
from
'
../../issuable_context
'
;
const
Store
=
gl
.
issueBoards
.
BoardsStore
;
...
...
app/assets/javascripts/dispatcher.js
View file @
17a35da6
/* eslint-disable func-names, space-before-function-paren, no-var, prefer-arrow-callback, wrap-iife, no-shadow, consistent-return, one-var, one-var-declaration-per-line, camelcase, default-case, no-new, quotes, no-duplicate-case, no-case-declarations, no-fallthrough, max-len */
/* global ProjectSelect */
/* global IssuableIndex */
import
IssuableIndex
from
'
./issuable_index
'
;
/* global Milestone */
/* global IssuableForm */
import
IssuableForm
from
'
./issuable_form
'
;
/* global LabelsSelect */
/* global MilestoneSelect */
/* global NewBranchForm */
...
...
@@ -197,7 +197,7 @@ import initGroupAnalytics from './init_group_analytics';
filteredSearchManager
.
setup
();
}
const
pagePrefix
=
page
===
'
projects:merge_requests:index
'
?
'
merge_request_
'
:
'
issue_
'
;
IssuableIndex
.
init
(
pagePrefix
);
new
IssuableIndex
(
pagePrefix
);
shortcut_handler
=
new
ShortcutsNavigation
();
new
UsersSelect
();
...
...
app/assets/javascripts/importer_status.js
View file @
17a35da6
/* eslint-disable func-names, space-before-function-paren, wrap-iife, camelcase, no-var, one-var, one-var-declaration-per-line, prefer-template, quotes, object-shorthand, comma-dangle, no-unused-vars, prefer-arrow-callback, no-else-return, vars-on-top, no-new, max-len */
(
function
()
{
window
.
ImporterStatus
=
(
function
()
{
function
ImporterStatus
(
jobs_url
,
import_url
)
{
this
.
jobs_url
=
jobs_url
;
this
.
import_url
=
import_url
;
class
ImporterStatus
{
constructor
(
jobsUrl
,
importUrl
)
{
this
.
jobsUrl
=
jobsUrl
;
this
.
importUrl
=
importUrl
;
this
.
initStatusPage
();
this
.
setAutoUpdate
();
}
ImporterStatus
.
prototype
.
initStatusPage
=
function
()
{
$
(
'
.js-add-to-import
'
).
off
(
'
click
'
).
on
(
'
click
'
,
(
function
(
_this
)
{
return
function
(
e
)
{
var
$btn
,
$namespace_input
,
$target_field
,
$tr
,
id
,
target_namespace
,
newName
;
$btn
=
$
(
e
.
currentTarget
);
$tr
=
$btn
.
closest
(
'
tr
'
);
$target_f
ield
=
$tr
.
find
(
'
.import-target
'
);
$namespace_input
=
$target_f
ield
.
find
(
'
.js-select-namespace option:selected
'
);
id
=
$tr
.
attr
(
'
id
'
).
replace
(
'
repo_
'
,
''
);
target_namespace
=
null
;
newName
=
null
;
if
(
$namespace_i
nput
.
length
>
0
)
{
target_namespace
=
$namespace_i
nput
[
0
].
innerHTML
;
newName
=
$target_f
ield
.
find
(
'
#path
'
).
prop
(
'
value
'
);
$target_field
.
empty
().
append
(
target_namespace
+
"
/
"
+
newName
);
initStatusPage
()
{
$
(
'
.js-add-to-import
'
)
.
off
(
'
click
'
)
.
on
(
'
click
'
,
(
event
)
=>
{
const
$btn
=
$
(
event
.
currentTarget
);
const
$tr
=
$btn
.
closest
(
'
tr
'
);
const
$targetF
ield
=
$tr
.
find
(
'
.import-target
'
);
const
$namespaceInput
=
$targetF
ield
.
find
(
'
.js-select-namespace option:selected
'
);
const
id
=
$tr
.
attr
(
'
id
'
).
replace
(
'
repo_
'
,
''
);
let
targetNamespace
;
let
newName
;
if
(
$namespaceI
nput
.
length
>
0
)
{
targetNamespace
=
$namespaceI
nput
[
0
].
innerHTML
;
newName
=
$targetF
ield
.
find
(
'
#path
'
).
prop
(
'
value
'
);
$targetField
.
empty
().
append
(
`
${
targetNamespace
}
/
${
newName
}
`
);
}
$btn
.
disable
().
addClass
(
'
is-loading
'
);
return
$
.
post
(
_this
.
import_url
,
{
return
$
.
post
(
this
.
importUrl
,
{
repo_id
:
id
,
target_namespace
:
target_n
amespace
,
new_name
:
newName
target_namespace
:
targetN
amespace
,
new_name
:
newName
,
},
{
dataType
:
'
script
'
dataType
:
'
script
'
,
});
});
};
})(
this
));
return
$
(
'
.js-import-all
'
).
off
(
'
click
'
).
on
(
'
click
'
,
function
(
e
)
{
var
$btn
;
$btn
=
$
(
this
);
$
(
'
.js-import-all
'
)
.
off
(
'
click
'
)
.
on
(
'
click
'
,
function
onClickImportAll
()
{
const
$btn
=
$
(
this
);
$btn
.
disable
().
addClass
(
'
is-loading
'
);
return
$
(
'
.js-add-to-import
'
).
each
(
function
()
{
return
$
(
'
.js-add-to-import
'
).
each
(
function
triggerAddImport
()
{
return
$
(
this
).
trigger
(
'
click
'
);
});
});
};
ImporterStatus
.
prototype
.
setAutoUpdate
=
function
()
{
return
setInterval
(((
function
(
_this
)
{
return
function
()
{
return
$
.
get
(
_this
.
jobs_url
,
function
(
data
)
{
return
$
.
each
(
data
,
function
(
i
,
job
)
{
var
job_item
,
status_field
;
job_item
=
$
(
"
#project_
"
+
job
.
id
);
status_field
=
job_item
.
find
(
"
.job-status
"
);
if
(
job
.
import_status
===
'
finished
'
)
{
job_item
.
removeClass
(
"
active
"
).
addClass
(
"
success
"
);
return
status_field
.
html
(
'
<span><i class="fa fa-check"></i> done</span>
'
);
}
else
if
(
job
.
import_status
===
'
scheduled
'
)
{
return
status_field
.
html
(
"
<i class='fa fa-spinner fa-spin'></i> scheduled
"
);
}
else
if
(
job
.
import_status
===
'
started
'
)
{
return
status_field
.
html
(
"
<i class='fa fa-spinner fa-spin'></i> started
"
);
}
else
{
return
status_field
.
html
(
job
.
import_status
);
}
});
});
};
})(
this
)),
4000
);
};
return
ImporterStatus
;
})();
setAutoUpdate
()
{
return
setInterval
(()
=>
$
.
get
(
this
.
jobsUrl
,
data
=>
$
.
each
(
data
,
(
i
,
job
)
=>
{
const
jobItem
=
$
(
`#project_
${
job
.
id
}
`
);
const
statusField
=
jobItem
.
find
(
'
.job-status
'
);
$
(
function
()
{
if
(
$
(
'
.js-importer-status
'
).
length
)
{
var
jobsImportPath
=
$
(
'
.js-importer-status
'
).
data
(
'
jobs-import-path
'
);
var
importPath
=
$
(
'
.js-importer-status
'
).
data
(
'
import-path
'
);
const
spinner
=
'
<i class="fa fa-spinner fa-spin"></i>
'
;
new
window
.
ImporterStatus
(
jobsImportPath
,
importPath
);
switch
(
job
.
import_status
)
{
case
'
finished
'
:
jobItem
.
removeClass
(
'
active
'
).
addClass
(
'
success
'
);
statusField
.
html
(
'
<span><i class="fa fa-check"></i> done</span>
'
);
break
;
case
'
scheduled
'
:
statusField
.
html
(
`
${
spinner
}
scheduled`
);
break
;
case
'
started
'
:
statusField
.
html
(
`
${
spinner
}
started`
);
break
;
default
:
statusField
.
html
(
job
.
import_status
);
break
;
}
});
}).
call
(
window
);
})),
4000
);
}
}
// eslint-disable-next-line consistent-return
export
default
function
initImporterStatus
()
{
const
importerStatus
=
document
.
querySelector
(
'
.js-importer-status
'
);
if
(
importerStatus
)
{
const
data
=
importerStatus
.
dataset
;
return
new
ImporterStatus
(
data
.
jobsImportPath
,
data
.
importPath
);
}
}
app/assets/javascripts/init_issuable_sidebar.js
View file @
17a35da6
...
...
@@ -2,7 +2,7 @@
/* global MilestoneSelect */
/* global LabelsSelect */
/* global WeightSelect */
/* global IssuableContext */
import
IssuableContext
from
'
./issuable_context
'
;
/* global Sidebar */
import
DueDateSelectors
from
'
./due_date_select
'
;
...
...
app/assets/javascripts/issuable_bulk_update_actions.js
View file @
17a35da6
/* eslint-disable comma-dangle, quotes, consistent-return, func-names, array-callback-return, space-before-function-paren, prefer-arrow-callback, max-len, no-unused-expressions, no-sequences, no-underscore-dangle, no-unused-vars, no-param-reassign */
/* global IssuableIndex */
import
_
from
'
underscore
'
;
import
Flash
from
'
./flash
'
;
...
...
app/assets/javascripts/issuable_bulk_update_sidebar.js
View file @
17a35da6
...
...
@@ -5,6 +5,10 @@
/* global SubscriptionSelect */
import
IssuableBulkUpdateActions
from
'
./issuable_bulk_update_actions
'
;
import
'
./milestone_select
'
;
import
'
./issue_status_select
'
;
import
'
./subscription_select
'
;
import
'
./labels_select
'
;
const
HIDDEN_CLASS
=
'
hidden
'
;
const
DISABLED_CONTENT_CLASS
=
'
disabled-content
'
;
...
...
app/assets/javascripts/issuable_context.js
View file @
17a35da6
/* eslint-disable func-names, space-before-function-paren, wrap-iife, no-new, comma-dangle, quotes, prefer-arrow-callback, consistent-return, one-var, no-var, one-var-declaration-per-line, no-underscore-dangle, max-len */
import
Cookies
from
'
js-cookie
'
;
import
bp
from
'
./breakpoints
'
;
import
UsersSelect
from
'
./users_select
'
;
const
PARTICIPANTS_ROW_COUNT
=
7
;
(
function
()
{
this
.
IssuableContext
=
(
function
()
{
function
IssuableContext
(
currentUser
)
{
export
default
class
IssuableContext
{
constructor
(
currentUser
)
{
this
.
initParticipants
();
new
UsersSelect
(
currentUser
);
this
.
userSelect
=
new
UsersSelect
(
currentUser
);
$
(
'
select.select2
'
).
select2
({
width
:
'
resolve
'
,
dropdownAutoWidth
:
true
dropdownAutoWidth
:
true
,
});
$
(
"
.issuable-sidebar .inline-update
"
).
on
(
"
change
"
,
"
select
"
,
function
()
{
$
(
'
.issuable-sidebar .inline-update
'
).
on
(
'
change
'
,
'
select
'
,
function
onClickSelect
()
{
return
$
(
this
).
submit
();
});
$
(
"
.issuable-sidebar .inline-update
"
).
on
(
"
change
"
,
"
.js-assignee
"
,
function
()
{
$
(
'
.issuable-sidebar .inline-update
'
).
on
(
'
change
'
,
'
.js-assignee
'
,
function
onClickAssignee
()
{
return
$
(
this
).
submit
();
});
$
(
document
).
off
(
'
click
'
,
'
.issuable-sidebar .dropdown-content a
'
).
on
(
'
click
'
,
'
.issuable-sidebar .dropdown-content a
'
,
function
(
e
)
{
return
e
.
preventDefault
();
});
$
(
document
).
off
(
'
click
'
,
'
.edit-link
'
).
on
(
'
click
'
,
'
.edit-link
'
,
function
(
e
)
{
var
$block
,
$selectbox
;
$
(
document
)
.
off
(
'
click
'
,
'
.issuable-sidebar .dropdown-content a
'
)
.
on
(
'
click
'
,
'
.issuable-sidebar .dropdown-content a
'
,
e
=>
e
.
preventDefault
());
$
(
document
)
.
off
(
'
click
'
,
'
.edit-link
'
)
.
on
(
'
click
'
,
'
.edit-link
'
,
function
onClickEdit
(
e
)
{
e
.
preventDefault
();
$block
=
$
(
this
).
parents
(
'
.block
'
);
$selectbox
=
$block
.
find
(
'
.selectbox
'
);
const
$block
=
$
(
this
).
parents
(
'
.block
'
);
const
$selectbox
=
$block
.
find
(
'
.selectbox
'
);
if
(
$selectbox
.
is
(
'
:visible
'
))
{
$selectbox
.
hide
();
$block
.
find
(
'
.value
'
).
show
();
...
...
@@ -35,31 +37,31 @@ const PARTICIPANTS_ROW_COUNT = 7;
$selectbox
.
show
();
$block
.
find
(
'
.value
'
).
hide
();
}
if
(
$selectbox
.
is
(
'
:visible
'
))
{
return
setTimeout
(
function
()
{
return
$block
.
find
(
'
.dropdown-menu-toggle
'
).
trigger
(
'
click
'
);
},
0
);
setTimeout
(()
=>
$block
.
find
(
'
.dropdown-menu-toggle
'
).
trigger
(
'
click
'
),
0
);
}
});
window
.
addEventListener
(
'
beforeunload
'
,
function
()
{
window
.
addEventListener
(
'
beforeunload
'
,
()
=>
{
// collapsed_gutter cookie hides the sidebar
var
bpBreakpoint
=
bp
.
getBreakpointSize
();
const
bpBreakpoint
=
bp
.
getBreakpointSize
();
if
(
bpBreakpoint
===
'
xs
'
||
bpBreakpoint
===
'
sm
'
)
{
Cookies
.
set
(
'
collapsed_gutter
'
,
true
);
}
});
}
IssuableContext
.
prototype
.
initParticipants
=
function
()
{
initParticipants
()
{
$
(
document
).
on
(
'
click
'
,
'
.js-participants-more
'
,
this
.
toggleHiddenParticipants
);
return
$
(
'
.js-participants-author
'
).
each
(
function
(
i
)
{
return
$
(
'
.js-participants-author
'
).
each
(
function
forEachAuthor
(
i
)
{
if
(
i
>=
PARTICIPANTS_ROW_COUNT
)
{
return
$
(
this
).
addClass
(
'
js-participants-hidden
'
).
hide
();
$
(
this
).
addClass
(
'
js-participants-hidden
'
).
hide
();
}
});
};
}
IssuableContext
.
prototype
.
toggleHiddenParticipants
=
function
()
{
toggleHiddenParticipants
()
{
const
currentText
=
$
(
this
).
text
().
trim
();
const
lessText
=
$
(
this
).
data
(
'
less-text
'
);
const
originalText
=
$
(
this
).
data
(
'
original-text
'
);
...
...
@@ -73,8 +75,5 @@ const PARTICIPANTS_ROW_COUNT = 7;
}
$
(
'
.js-participants-hidden
'
).
toggle
();
};
return
IssuableContext
;
})();
}).
call
(
window
);
}
}
app/assets/javascripts/issuable_form.js
View file @
17a35da6
/* eslint-disable func-names,
space-before-function-paren, no-var, prefer-rest-params, wrap-iife, no-use-before-define, no-useless-escape, no-new, quotes
, object-shorthand, no-unused-vars, comma-dangle, no-alert, consistent-return, no-else-return, prefer-template, one-var, one-var-declaration-per-line, curly, max-len */
/* eslint-disable func-names,
prefer-rest-params, wrap-iife, no-use-before-define, no-useless-escape, no-new
, object-shorthand, no-unused-vars, comma-dangle, no-alert, consistent-return, no-else-return, prefer-template, one-var, one-var-declaration-per-line, curly, max-len */
/* global GitLab */
import
Pikaday
from
'
pikaday
'
;
...
...
@@ -9,77 +9,77 @@ import ZenMode from './zen_mode';
import
{
parsePikadayDate
,
pikadayToString
}
from
'
./lib/utils/datefix
'
;
import
groupsSelect
from
'
./groups_select
'
;
(
function
()
{
this
.
IssuableForm
=
(
function
()
{
IssuableForm
.
prototype
.
wipRegex
=
/^
\s
*
(\[
WIP
\]\s
*|WIP:
\s
*|WIP
\s
+
)
+
\s
*/i
;
function
IssuableForm
(
form
)
{
var
$issuableDueDate
,
calendar
;
export
default
class
IssuableForm
{
constructor
(
form
)
{
this
.
form
=
form
;
this
.
toggleWip
=
this
.
toggleWip
.
bind
(
this
);
this
.
renderWipExplanation
=
this
.
renderWipExplanation
.
bind
(
this
);
this
.
resetAutosave
=
this
.
resetAutosave
.
bind
(
this
);
this
.
handleSubmit
=
this
.
handleSubmit
.
bind
(
this
);
this
.
wipRegex
=
/^
\s
*
(\[
WIP
\]\s
*|WIP:
\s
*|WIP
\s
+
)
+
\s
*/i
;
new
GfmAutoComplete
(
gl
.
GfmAutoComplete
&&
gl
.
GfmAutoComplete
.
dataSources
).
setup
();
new
UsersSelect
();
groupsSelect
();
new
ZenMode
();
this
.
titleField
=
this
.
form
.
find
(
"
input[name*='[title]']
"
);
this
.
descriptionField
=
this
.
form
.
find
(
"
textarea[name*='[description]']
"
);
this
.
titleField
=
this
.
form
.
find
(
'
input[name*="[title]"]
'
);
this
.
descriptionField
=
this
.
form
.
find
(
'
textarea[name*="[description]"]
'
);
if
(
!
(
this
.
titleField
.
length
&&
this
.
descriptionField
.
length
))
{
return
;
}
this
.
initAutosave
();
this
.
form
.
on
(
"
submit
"
,
this
.
handleSubmit
);
this
.
form
.
on
(
"
click
"
,
"
.btn-cancel
"
,
this
.
resetAutosave
);
this
.
form
.
on
(
'
submit
'
,
this
.
handleSubmit
);
this
.
form
.
on
(
'
click
'
,
'
.btn-cancel
'
,
this
.
resetAutosave
);
this
.
initWip
();
$issuableDueDate
=
$
(
'
#issuable-due-date
'
);
const
$issuableDueDate
=
$
(
'
#issuable-due-date
'
);
if
(
$issuableDueDate
.
length
)
{
calendar
=
new
Pikaday
({
const
calendar
=
new
Pikaday
({
field
:
$issuableDueDate
.
get
(
0
),
theme
:
'
gitlab-theme animate-picker
'
,
format
:
'
yyyy-mm-dd
'
,
container
:
$issuableDueDate
.
parent
().
get
(
0
),
parse
:
dateString
=>
parsePikadayDate
(
dateString
),
toString
:
date
=>
pikadayToString
(
date
),
onSelect
:
function
(
dateText
)
{
$issuableDueDate
.
val
(
calendar
.
toString
(
dateText
));
}
onSelect
:
dateText
=>
$issuableDueDate
.
val
(
calendar
.
toString
(
dateText
)),
});
calendar
.
setDate
(
parsePikadayDate
(
$issuableDueDate
.
val
()));
}
}
IssuableForm
.
prototype
.
initAutosave
=
function
()
{
new
Autosave
(
this
.
titleField
,
[
document
.
location
.
pathname
,
document
.
location
.
search
,
"
title
"
]);
return
new
Autosave
(
this
.
descriptionField
,
[
document
.
location
.
pathname
,
document
.
location
.
search
,
"
description
"
]);
};
initAutosave
()
{
new
Autosave
(
this
.
titleField
,
[
document
.
location
.
pathname
,
document
.
location
.
search
,
'
title
'
]);
return
new
Autosave
(
this
.
descriptionField
,
[
document
.
location
.
pathname
,
document
.
location
.
search
,
'
description
'
]);
}
IssuableForm
.
prototype
.
handleSubmit
=
function
()
{
handleSubmit
()
{
return
this
.
resetAutosave
();
};
}
IssuableForm
.
prototype
.
resetAutosave
=
function
()
{
this
.
titleField
.
data
(
"
autosave
"
).
reset
();
return
this
.
descriptionField
.
data
(
"
autosave
"
).
reset
();
};
resetAutosave
()
{
this
.
titleField
.
data
(
'
autosave
'
).
reset
();
return
this
.
descriptionField
.
data
(
'
autosave
'
).
reset
();
}
IssuableForm
.
prototype
.
initWip
=
function
()
{
this
.
$wipExplanation
=
this
.
form
.
find
(
"
.js-wip-explanation
"
);
this
.
$noWipExplanation
=
this
.
form
.
find
(
"
.js-no-wip-explanation
"
);
initWip
()
{
this
.
$wipExplanation
=
this
.
form
.
find
(
'
.js-wip-explanation
'
);
this
.
$noWipExplanation
=
this
.
form
.
find
(
'
.js-no-wip-explanation
'
);
if
(
!
(
this
.
$wipExplanation
.
length
&&
this
.
$noWipExplanation
.
length
))
{
return
;
}
this
.
form
.
on
(
"
click
"
,
"
.js-toggle-wip
"
,
this
.
toggleWip
);
this
.
titleField
.
on
(
"
keyup blur
"
,
this
.
renderWipExplanation
);
this
.
form
.
on
(
'
click
'
,
'
.js-toggle-wip
'
,
this
.
toggleWip
);
this
.
titleField
.
on
(
'
keyup blur
'
,
this
.
renderWipExplanation
);
return
this
.
renderWipExplanation
();
};
}
IssuableForm
.
prototype
.
workInProgress
=
function
()
{
workInProgress
()
{
return
this
.
wipRegex
.
test
(
this
.
titleField
.
val
());
};
}
IssuableForm
.
prototype
.
renderWipExplanation
=
func
tion
()
{
renderWipExplana
tion
()
{
if
(
this
.
workInProgress
())
{
this
.
$wipExplanation
.
show
();
return
this
.
$noWipExplanation
.
hide
();
...
...
@@ -87,9 +87,9 @@ import groupsSelect from './groups_select';
this
.
$wipExplanation
.
hide
();
return
this
.
$noWipExplanation
.
show
();
}
};
}
IssuableForm
.
prototype
.
toggleWip
=
function
(
event
)
{
toggleWip
(
event
)
{
event
.
preventDefault
();
if
(
this
.
workInProgress
())
{
this
.
removeWip
();
...
...
@@ -97,16 +97,13 @@ import groupsSelect from './groups_select';
this
.
addWip
();
}
return
this
.
renderWipExplanation
();
};
IssuableForm
.
prototype
.
removeWip
=
function
()
{
return
this
.
titleField
.
val
(
this
.
titleField
.
val
().
replace
(
this
.
wipRegex
,
""
));
};
}
IssuableForm
.
prototype
.
addWip
=
function
()
{
return
this
.
titleField
.
val
(
"
WIP:
"
+
(
this
.
titleField
.
val
()
));
};
removeWip
()
{
return
this
.
titleField
.
val
(
this
.
titleField
.
val
().
replace
(
this
.
wipRegex
,
''
));
}
return
IssuableForm
;
})();
}).
call
(
window
);
addWip
()
{
this
.
titleField
.
val
(
`WIP:
${(
this
.
titleField
.
val
())}
`
);
}
}
app/assets/javascripts/issuable_index.js
View file @
17a35da6
/* eslint-disable no-param-reassign, func-names, no-var, camelcase, no-unused-vars, object-shorthand, space-before-function-paren, no-return-assign, comma-dangle, consistent-return, one-var, one-var-declaration-per-line, quotes, prefer-template, prefer-arrow-callback, wrap-iife, max-len */
/* global IssuableIndex */
import
_
from
'
underscore
'
;
import
IssuableBulkUpdateSidebar
from
'
./issuable_bulk_update_sidebar
'
;
import
IssuableBulkUpdateActions
from
'
./issuable_bulk_update_actions
'
;
((
global
)
=>
{
var
issuable_created
;
issuable_created
=
false
;
global
.
IssuableIndex
=
{
init
:
function
(
pagePrefix
)
{
IssuableIndex
.
initTemplates
();
IssuableIndex
.
initSearch
();
IssuableIndex
.
initBulkUpdate
(
pagePrefix
);
IssuableIndex
.
initResetFilters
();
export
default
class
IssuableIndex
{
constructor
(
pagePrefix
)
{
this
.
initBulkUpdate
(
pagePrefix
);
IssuableIndex
.
resetIncomingEmailToken
();
IssuableIndex
.
initLabelFilterRemove
();
},
initTemplates
:
function
()
{
return
IssuableIndex
.
labelRow
=
_
.
template
(
'
<% _.each(labels, function(label){ %> <span class="label-row btn-group" role="group" aria-label="<%- label.title %>" style="color: <%- label.text_color %>;"> <a href="#" class="btn btn-transparent has-tooltip" style="background-color: <%- label.color %>;" title="<%- label.description %>" data-container="body"> <%- label.title %> </a> <button type="button" class="btn btn-transparent label-remove js-label-filter-remove" style="background-color: <%- label.color %>;" data-label="<%- label.title %>"> <i class="fa fa-times"></i> </button> </span> <% }); %>
'
);
},
initSearch
:
function
()
{
const
$searchInput
=
$
(
'
#issuable_search
'
);
IssuableIndex
.
initSearchState
(
$searchInput
);
// `immediate` param set to false debounces on the `trailing` edge, lets user finish typing
const
debouncedExecSearch
=
_
.
debounce
(
IssuableIndex
.
executeSearch
,
1000
,
false
);
$searchInput
.
off
(
'
keyup
'
).
on
(
'
keyup
'
,
debouncedExecSearch
);
// ensures existing filters are preserved when manually submitted
$
(
'
#issuable_search_form
'
).
on
(
'
submit
'
,
(
e
)
=>
{
e
.
preventDefault
();
debouncedExecSearch
(
e
);
});
},
initSearchState
:
function
(
$searchInput
)
{
const
currentSearchVal
=
$searchInput
.
val
();
IssuableIndex
.
searchState
=
{
elem
:
$searchInput
,
current
:
currentSearchVal
};
IssuableIndex
.
maybeFocusOnSearch
();
},
accessSearchPristine
:
function
(
set
)
{
// store reference to previous value to prevent search on non-mutating keyup
const
state
=
IssuableIndex
.
searchState
;
const
currentSearchVal
=
state
.
elem
.
val
();
if
(
set
)
{
state
.
current
=
currentSearchVal
;
}
else
{
return
state
.
current
===
currentSearchVal
;
}
},
maybeFocusOnSearch
:
function
()
{
const
currentSearchVal
=
IssuableIndex
.
searchState
.
current
;
if
(
currentSearchVal
&&
currentSearchVal
!==
''
)
{
const
queryLength
=
currentSearchVal
.
length
;
const
$searchInput
=
IssuableIndex
.
searchState
.
elem
;
/* The following ensures that the cursor is initially placed at
* the end of search input when focus is applied. It accounts
* for differences in browser implementations of `setSelectionRange`
* and cursor placement for elements in focus.
*/
$searchInput
.
focus
();
if
(
$searchInput
.
setSelectionRange
)
{
$searchInput
.
setSelectionRange
(
queryLength
,
queryLength
);
}
else
{
$searchInput
.
val
(
currentSearchVal
);
}
}
},
executeSearch
:
function
(
e
)
{
const
$search
=
$
(
'
#issuable_search
'
);
const
$searchName
=
$search
.
attr
(
'
name
'
);
const
$searchValue
=
$search
.
val
();
const
$filtersForm
=
$
(
'
.js-filter-form
'
);
const
$input
=
$
(
`input[name='
${
$searchName
}
']`
,
$filtersForm
);
const
isPristine
=
IssuableIndex
.
accessSearchPristine
();
if
(
isPristine
)
{
return
;
}
if
(
!
$input
.
length
)
{
$filtersForm
.
append
(
`<input type='hidden' name='
${
$searchName
}
' value='
${
_
.
escape
(
$searchValue
)}
'/>`
);
}
else
{
$input
.
val
(
$searchValue
);
}
IssuableIndex
.
filterResults
(
$filtersForm
);
},
initLabelFilterRemove
:
function
()
{
return
$
(
document
).
off
(
'
click
'
,
'
.js-label-filter-remove
'
).
on
(
'
click
'
,
'
.js-label-filter-remove
'
,
function
(
e
)
{
var
$button
;
$button
=
$
(
this
);
// Remove the label input box
$
(
'
input[name="label_name[]"]
'
).
filter
(
function
()
{
return
this
.
value
===
$button
.
data
(
'
label
'
);
}).
remove
();
// Submit the form to get new data
IssuableIndex
.
filterResults
(
$
(
'
.filter-form
'
));
});
},
filterResults
:
(
function
(
_this
)
{
return
function
(
form
)
{
var
formAction
,
formData
,
issuesUrl
;
formData
=
form
.
serializeArray
();
formData
=
formData
.
filter
(
function
(
data
)
{
return
data
.
value
!==
''
;
});
formData
=
$
.
param
(
formData
);
formAction
=
form
.
attr
(
'
action
'
);
issuesUrl
=
formAction
;
issuesUrl
+=
""
+
(
formAction
.
indexOf
(
'
?
'
)
===
-
1
?
'
?
'
:
'
&
'
);
issuesUrl
+=
formData
;
return
gl
.
utils
.
visitUrl
(
issuesUrl
);
};
})(
this
),
initResetFilters
:
function
()
{
$
(
'
.reset-filters
'
).
on
(
'
click
'
,
function
(
e
)
{
e
.
preventDefault
();
const
target
=
e
.
target
;
const
$form
=
$
(
target
).
parents
(
'
.js-filter-form
'
);
const
baseIssuesUrl
=
target
.
href
;
$form
.
attr
(
'
action
'
,
baseIssuesUrl
);
gl
.
utils
.
visitUrl
(
baseIssuesUrl
);
});
},
initBulkUpdate
:
function
(
pagePrefix
)
{
initBulkUpdate
(
pagePrefix
)
{
const
userCanBulkUpdate
=
$
(
'
.issues-bulk-update
'
).
length
>
0
;
const
alreadyInitialized
=
!!
this
.
bulkUpdateSidebar
;
...
...
@@ -146,26 +17,26 @@ import IssuableBulkUpdateActions from './issuable_bulk_update_actions';
this
.
bulkUpdateSidebar
=
new
IssuableBulkUpdateSidebar
();
}
},
resetIncomingEmailToken
:
function
()
{
$
(
'
.incoming-email-token-reset
'
).
on
(
'
click
'
,
function
(
e
)
{
}
static
resetIncomingEmailToken
()
{
$
(
'
.incoming-email-token-reset
'
).
on
(
'
click
'
,
(
e
)
=>
{
e
.
preventDefault
();
$
.
ajax
({
type
:
'
PUT
'
,
url
:
$
(
'
.incoming-email-token-reset
'
).
attr
(
'
href
'
),
dataType
:
'
json
'
,
success
:
function
(
response
)
{
success
(
response
)
{
$
(
'
#issue_email
'
).
val
(
response
.
new_issue_address
).
focus
();
},
beforeSend
:
function
()
{
beforeSend
()
{
$
(
'
.incoming-email-token-reset
'
).
text
(
'
resetting...
'
);
},
complete
:
function
()
{
complete
()
{
$
(
'
.incoming-email-token-reset
'
).
text
(
'
reset it
'
);
}
},
});
});
}
};
})(
window
);
}
app/assets/javascripts/main.js
View file @
17a35da6
...
...
@@ -57,9 +57,7 @@ import './gl_field_error';
import
'
./gl_field_errors
'
;
import
'
./gl_form
'
;
import
'
./header
'
;
import
'
./importer_status
'
;
import
'
./issuable_index
'
;
import
'
./issuable_context
'
;
import
initImporterStatus
from
'
./importer_status
'
;
import
'
./issuable_form
'
;
import
'
./issue
'
;
import
'
./issue_status_select
'
;
...
...
@@ -149,6 +147,7 @@ $(function () {
var
fitSidebarForSize
;
initBreadcrumbs
();
initImporterStatus
();
// Set the default path for all cookies to GitLab's root directory
Cookies
.
defaults
.
path
=
gon
.
relative_url_root
||
'
/
'
;
...
...
spec/javascripts/issuable_context_spec.js
View file @
17a35da6
/* global IssuableContext */
import
'
~/issuable_context
'
;
import
$
from
'
jquery
'
;
import
IssuableContext
from
'
~/issuable_context
'
;
describe
(
'
IssuableContext
'
,
()
=>
{
describe
(
'
toggleHiddenParticipants
'
,
()
=>
{
...
...
spec/javascripts/issuable_spec.js
View file @
17a35da6
/* global IssuableIndex */
import
IssuableIndex
from
'
~/issuable_index
'
;
import
'
~/lib/utils/url_utility
'
;
import
'
~/issuable_index
'
;
(()
=>
{
const
BASE_URL
=
'
/user/project/issues?scope=all&state=closed
'
;
const
DEFAULT_PARAMS
=
'
&utf8=%E2%9C%93
'
;
function
updateForm
(
formValues
,
form
)
{
$
.
each
(
formValues
,
(
id
,
value
)
=>
{
$
(
`#
${
id
}
`
,
form
).
val
(
value
);
describe
(
'
Issuable
'
,
()
=>
{
let
Issuable
;
describe
(
'
initBulkUpdate
'
,
()
=>
{
it
(
'
should not set bulkUpdateSidebar
'
,
()
=>
{
Issuable
=
new
IssuableIndex
(
'
issue_
'
);
expect
(
Issuable
.
bulkUpdateSidebar
).
not
.
toBeDefined
();
});
}
function
resetForm
(
form
)
{
$
(
'
input[name!="utf8"]
'
,
form
).
each
((
index
,
input
)
=>
{
input
.
setAttribute
(
'
value
'
,
''
);
});
}
it
(
'
should set bulkUpdateSidebar
'
,
()
=>
{
const
element
=
document
.
createElement
(
'
div
'
);
element
.
classList
.
add
(
'
issues-bulk-update
'
);
document
.
body
.
appendChild
(
element
);
describe
(
'
Issuable
'
,
()
=>
{
preloadFixtures
(
'
static/issuable_filter.html.raw
'
);
beforeEach
(()
=>
{
loadFixtures
(
'
static/issuable_filter.html.raw
'
);
IssuableIndex
.
init
();
Issuable
=
new
IssuableIndex
(
'
issue_
'
);
expect
(
Issuable
.
bulkUpdateSidebar
).
toBeDefined
();
});
it
(
'
should be defined
'
,
()
=>
{
expect
(
window
.
IssuableIndex
).
toBeDefined
();
});
describe
(
'
filtering
'
,
()
=>
{
let
$filtersForm
;
describe
(
'
resetIncomingEmailToken
'
,
()
=>
{
beforeEach
(()
=>
{
$filtersForm
=
$
(
'
.js-filter-form
'
);
loadFixtures
(
'
static/issuable_filter.html.raw
'
);
resetForm
(
$filtersForm
);
});
it
(
'
should contain only the default parameters
'
,
()
=>
{
spyOn
(
gl
.
utils
,
'
visitUrl
'
);
const
element
=
document
.
createElement
(
'
a
'
);
element
.
classList
.
add
(
'
incoming-email-token-reset
'
);
element
.
setAttribute
(
'
href
'
,
'
foo
'
);
document
.
body
.
appendChild
(
element
);
IssuableIndex
.
filterResults
(
$filtersForm
);
const
input
=
document
.
createElement
(
'
input
'
);
input
.
setAttribute
(
'
id
'
,
'
issue_email
'
);
document
.
body
.
appendChild
(
input
);
expect
(
gl
.
utils
.
visitUrl
).
toHaveBeenCalledWith
(
BASE_URL
+
DEFAULT_PARAMS
);
Issuable
=
new
IssuableIndex
(
'
issue_
'
);
});
it
(
'
should filter for the phrase "broken"
'
,
()
=>
{
spyOn
(
gl
.
utils
,
'
visitUrl
'
);
it
(
'
should send request to reset email token
'
,
()
=>
{
spyOn
(
jQuery
,
'
ajax
'
).
and
.
callThrough
();
document
.
querySelector
(
'
.incoming-email-token-reset
'
).
click
();
updateForm
({
search
:
'
broken
'
},
$filtersForm
);
IssuableIndex
.
filterResults
(
$filtersForm
);
const
params
=
`
${
DEFAULT_PARAMS
}
&search=broken`
;
expect
(
gl
.
utils
.
visitUrl
).
toHaveBeenCalledWith
(
BASE_URL
+
params
);
});
it
(
'
should keep query parameters after modifying filter
'
,
()
=>
{
spyOn
(
gl
.
utils
,
'
visitUrl
'
);
// initial filter
updateForm
({
milestone_title
:
'
v1.0
'
},
$filtersForm
);
IssuableIndex
.
filterResults
(
$filtersForm
);
let
params
=
`
${
DEFAULT_PARAMS
}
&milestone_title=v1.0`
;
expect
(
gl
.
utils
.
visitUrl
).
toHaveBeenCalledWith
(
BASE_URL
+
params
);
// update filter
updateForm
({
label_name
:
'
Frontend
'
},
$filtersForm
);
IssuableIndex
.
filterResults
(
$filtersForm
);
params
=
`
${
DEFAULT_PARAMS
}
&milestone_title=v1.0&label_name=Frontend`
;
expect
(
gl
.
utils
.
visitUrl
).
toHaveBeenCalledWith
(
BASE_URL
+
params
);
expect
(
jQuery
.
ajax
).
toHaveBeenCalled
();
expect
(
jQuery
.
ajax
.
calls
.
argsFor
(
0
)[
0
].
url
).
toEqual
(
'
foo
'
);
});
});
});
})();
});
spec/javascripts/labels_issue_sidebar_spec.js
View file @
17a35da6
/* eslint-disable no-new */
/* global IssuableContext */
import
IssuableContext
from
'
~/issuable_context
'
;
/* global LabelsSelect */
import
'
~/gl_dropdown
'
;
import
'
select2
'
;
import
'
~/api
'
;
import
'
~/create_label
'
;
import
'
~/issuable_context
'
;
import
'
~/users_select
'
;
import
'
~/labels_select
'
;
...
...
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