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
0
Merge Requests
0
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
Boxiang Sun
gitlab-ce
Commits
d9262b79
Commit
d9262b79
authored
Apr 16, 2018
by
Phil Hughes
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
created constants file
added specs for ide.vue Mousetrap binds
parent
8a076c1b
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
175 additions
and
89 deletions
+175
-89
app/assets/javascripts/ide/components/file_finder/index.vue
app/assets/javascripts/ide/components/file_finder/index.vue
+22
-17
app/assets/javascripts/ide/components/file_finder/item.vue
app/assets/javascripts/ide/components/file_finder/item.vue
+5
-3
app/assets/javascripts/ide/components/ide.vue
app/assets/javascripts/ide/components/ide.vue
+70
-65
app/assets/javascripts/ide/constants.js
app/assets/javascripts/ide/constants.js
+8
-0
spec/javascripts/ide/components/file_finder/index_spec.js
spec/javascripts/ide/components/file_finder/index_spec.js
+5
-4
spec/javascripts/ide/components/ide_spec.js
spec/javascripts/ide/components/ide_spec.js
+65
-0
No files found.
app/assets/javascripts/ide/components/file_finder/index.vue
View file @
d9262b79
...
@@ -4,8 +4,15 @@ import fuzzaldrinPlus from 'fuzzaldrin-plus';
...
@@ -4,8 +4,15 @@ import fuzzaldrinPlus from 'fuzzaldrin-plus';
import
VirtualList
from
'
vue-virtual-scroll-list
'
;
import
VirtualList
from
'
vue-virtual-scroll-list
'
;
import
Item
from
'
./item.vue
'
;
import
Item
from
'
./item.vue
'
;
import
router
from
'
../../ide_router
'
;
import
router
from
'
../../ide_router
'
;
import
{
const
MAX_RESULTS
=
40
;
MAX_FILE_FINDER_RESULTS
,
FILE_FINDER_ROW_HEIGHT
,
FILE_FINDER_EMPTY_ROW_HEIGHT
,
UP_KEY_CODE
,
DOWN_KEY_CODE
,
ENTER_KEY_CODE
,
ESC_KEY_CODE
,
}
from
'
../../constants
'
;
export
default
{
export
default
{
components
:
{
components
:
{
...
@@ -25,12 +32,14 @@ export default {
...
@@ -25,12 +32,14 @@ export default {
filteredBlobs
()
{
filteredBlobs
()
{
const
searchText
=
this
.
searchText
.
trim
();
const
searchText
=
this
.
searchText
.
trim
();
if
(
searchText
===
''
)
return
this
.
allBlobs
.
slice
(
0
,
MAX_RESULTS
);
if
(
searchText
===
''
)
{
return
this
.
allBlobs
.
slice
(
0
,
MAX_FILE_FINDER_RESULTS
);
}
return
fuzzaldrinPlus
return
fuzzaldrinPlus
.
filter
(
this
.
allBlobs
,
searchText
,
{
.
filter
(
this
.
allBlobs
,
searchText
,
{
key
:
'
path
'
,
key
:
'
path
'
,
maxResults
:
MAX_RESULTS
,
maxResults
:
MAX_
FILE_FINDER_
RESULTS
,
})
})
.
sort
((
a
,
b
)
=>
b
.
lastOpenedAt
-
a
.
lastOpenedAt
);
.
sort
((
a
,
b
)
=>
b
.
lastOpenedAt
-
a
.
lastOpenedAt
);
},
},
...
@@ -38,12 +47,10 @@ export default {
...
@@ -38,12 +47,10 @@ export default {
return
this
.
filteredBlobs
.
length
;
return
this
.
filteredBlobs
.
length
;
},
},
listShowCount
()
{
listShowCount
()
{
if
(
!
this
.
filteredBlobsLength
)
return
1
;
return
this
.
filteredBlobsLength
?
Math
.
min
(
this
.
filteredBlobsLength
,
5
)
:
1
;
return
this
.
filteredBlobsLength
>
5
?
5
:
this
.
filteredBlobsLength
;
},
},
listHeight
()
{
listHeight
()
{
return
this
.
filteredBlobsLength
?
55
:
33
;
return
this
.
filteredBlobsLength
?
FILE_FINDER_ROW_HEIGHT
:
FILE_FINDER_EMPTY_ROW_HEIGHT
;
},
},
showClearInputButton
()
{
showClearInputButton
()
{
return
this
.
searchText
.
trim
()
!==
''
;
return
this
.
searchText
.
trim
()
!==
''
;
...
@@ -57,7 +64,9 @@ export default {
...
@@ -57,7 +64,9 @@ export default {
}
else
{
}
else
{
this
.
focusedIndex
=
0
;
this
.
focusedIndex
=
0
;
this
.
$refs
.
searchInput
.
focus
();
if
(
this
.
$refs
.
searchInput
)
{
this
.
$refs
.
searchInput
.
focus
();
}
}
}
});
});
},
},
...
@@ -85,8 +94,7 @@ export default {
...
@@ -85,8 +94,7 @@ export default {
},
},
onKeydown
(
e
)
{
onKeydown
(
e
)
{
switch
(
e
.
keyCode
)
{
switch
(
e
.
keyCode
)
{
case
38
:
case
UP_KEY_CODE
:
// UP
e
.
preventDefault
();
e
.
preventDefault
();
this
.
mouseOver
=
false
;
this
.
mouseOver
=
false
;
if
(
this
.
focusedIndex
>
0
)
{
if
(
this
.
focusedIndex
>
0
)
{
...
@@ -95,8 +103,7 @@ export default {
...
@@ -95,8 +103,7 @@ export default {
this
.
focusedIndex
=
this
.
filteredBlobsLength
-
1
;
this
.
focusedIndex
=
this
.
filteredBlobsLength
-
1
;
}
}
break
;
break
;
case
40
:
case
DOWN_KEY_CODE
:
// DOWN
e
.
preventDefault
();
e
.
preventDefault
();
this
.
mouseOver
=
false
;
this
.
mouseOver
=
false
;
if
(
this
.
focusedIndex
<
this
.
filteredBlobsLength
-
1
)
{
if
(
this
.
focusedIndex
<
this
.
filteredBlobsLength
-
1
)
{
...
@@ -111,12 +118,10 @@ export default {
...
@@ -111,12 +118,10 @@ export default {
},
},
onKeyup
(
e
)
{
onKeyup
(
e
)
{
switch
(
e
.
keyCode
)
{
switch
(
e
.
keyCode
)
{
case
13
:
case
ENTER_KEY_CODE
:
// ENTER
this
.
openFile
(
this
.
filteredBlobs
[
this
.
focusedIndex
]);
this
.
openFile
(
this
.
filteredBlobs
[
this
.
focusedIndex
]);
break
;
break
;
case
27
:
case
ESC_KEY_CODE
:
// ESC
this
.
toggleFileFinder
(
false
);
this
.
toggleFileFinder
(
false
);
break
;
break
;
default
:
default
:
...
...
app/assets/javascripts/ide/components/file_finder/item.vue
View file @
d9262b79
...
@@ -30,9 +30,11 @@ export default {
...
@@ -30,9 +30,11 @@ export default {
},
},
computed
:
{
computed
:
{
pathWithEllipsis
()
{
pathWithEllipsis
()
{
return
this
.
file
.
path
.
length
<
MAX_PATH_LENGTH
const
path
=
this
.
file
.
path
;
?
this
.
file
.
path
:
`...
${
this
.
file
.
path
.
substr
(
this
.
file
.
path
.
length
-
MAX_PATH_LENGTH
)}
`
;
return
path
.
length
<
MAX_PATH_LENGTH
?
path
:
`...
${
path
.
substr
(
path
.
length
-
MAX_PATH_LENGTH
)}
`
;
},
},
nameSearchTextOccurences
()
{
nameSearchTextOccurences
()
{
return
fuzzaldrinPlus
.
match
(
this
.
file
.
name
,
this
.
searchText
);
return
fuzzaldrinPlus
.
match
(
this
.
file
.
name
,
this
.
searchText
);
...
...
app/assets/javascripts/ide/components/ide.vue
View file @
d9262b79
<
script
>
<
script
>
import
{
mapActions
,
mapState
,
mapGetters
}
from
'
vuex
'
;
import
{
mapActions
,
mapState
,
mapGetters
}
from
'
vuex
'
;
import
Mousetrap
from
'
mousetrap
'
;
import
Mousetrap
from
'
mousetrap
'
;
import
ideSidebar
from
'
./ide_side_bar.vue
'
;
import
ideSidebar
from
'
./ide_side_bar.vue
'
;
import
ideContextbar
from
'
./ide_context_bar.vue
'
;
import
ideContextbar
from
'
./ide_context_bar.vue
'
;
import
repoTabs
from
'
./repo_tabs.vue
'
;
import
repoTabs
from
'
./repo_tabs.vue
'
;
import
ideStatusBar
from
'
./ide_status_bar.vue
'
;
import
ideStatusBar
from
'
./ide_status_bar.vue
'
;
import
repoEditor
from
'
./repo_editor.vue
'
;
import
repoEditor
from
'
./repo_editor.vue
'
;
import
FindFile
from
'
./file_finder/index.vue
'
;
import
FindFile
from
'
./file_finder/index.vue
'
;
export
default
{
const
originalStopCallback
=
Mousetrap
.
stopCallback
;
components
:
{
ideSidebar
,
export
default
{
ideContextbar
,
components
:
{
repoTabs
,
ideSidebar
,
ideStatusBar
,
ideContextbar
,
repoEditor
,
repoTabs
,
FindFile
,
ideStatusBar
,
},
repoEditor
,
props
:
{
FindFile
,
emptyStateSvgPath
:
{
type
:
String
,
required
:
true
,
},
},
noChangesStateSvgPath
:
{
props
:
{
type
:
String
,
emptyStateSvgPath
:
{
required
:
true
,
type
:
String
,
required
:
true
,
},
noChangesStateSvgPath
:
{
type
:
String
,
required
:
true
,
},
committedStateSvgPath
:
{
type
:
String
,
required
:
true
,
},
},
},
committedStateSvgPath
:
{
computed
:
{
type
:
String
,
...
mapState
([
required
:
true
,
'
changedFiles
'
,
'
openFiles
'
,
'
viewer
'
,
'
currentMergeRequestId
'
,
'
fileFindVisible
'
,
]),
...
mapGetters
([
'
activeFile
'
,
'
hasChanges
'
]),
},
},
},
mounted
()
{
computed
:
{
const
returnValue
=
'
Are you sure you want to lose unsaved changes?
'
;
...
mapState
([
window
.
onbeforeunload
=
e
=>
{
'
changedFiles
'
,
if
(
!
this
.
changedFiles
.
length
)
return
undefined
;
'
openFiles
'
,
'
viewer
'
,
'
currentMergeRequestId
'
,
'
fileFindVisible
'
,
]),
...
mapGetters
([
'
activeFile
'
,
'
hasChanges
'
]),
},
mounted
()
{
const
returnValue
=
'
Are you sure you want to lose unsaved changes?
'
;
window
.
onbeforeunload
=
e
=>
{
if
(
!
this
.
changedFiles
.
length
)
return
undefined
;
Object
.
assign
(
e
,
{
Object
.
assign
(
e
,
{
returnValue
,
returnValue
,
});
});
return
returnValue
;
return
returnValue
;
};
};
Mousetrap
.
bind
([
'
t
'
,
'
command+p
'
,
'
ctrl+p
'
],
e
=>
{
if
(
e
.
preventDefault
)
{
e
.
preventDefault
();
}
Mousetrap
.
bind
([
'
t
'
,
'
command+p
'
,
'
ctrl+p
'
],
e
=>
{
this
.
toggleFileFinder
(
!
this
.
fileFindVisible
);
e
.
preventDefault
();
});
this
.
toggleFileFinder
(
!
this
.
fileFindVisible
);
});
const
originalStopCallback
=
Mousetrap
.
stopCallback
;
Mousetrap
.
stopCallback
=
(
e
,
el
,
combo
)
=>
this
.
mousetrapStopCallback
(
e
,
el
,
combo
);
Mousetrap
.
stopCallback
=
(
e
,
el
,
combo
)
=>
{
},
if
(
combo
===
'
t
'
&&
el
.
classList
.
contains
(
'
dropdown-input-field
'
))
{
methods
:
{
return
true
;
...
mapActions
([
'
toggleFileFinder
'
]),
}
else
if
(
combo
===
'
command+p
'
||
combo
===
'
ctrl+p
'
)
{
mousetrapStopCallback
(
e
,
el
,
combo
)
{
return
false
;
if
(
combo
===
'
t
'
&&
el
.
classList
.
contains
(
'
dropdown-input-field
'
))
{
}
return
true
;
}
else
if
(
combo
===
'
command+p
'
||
combo
===
'
ctrl+p
'
)
{
return
false
;
}
return
originalStopCallback
(
e
,
el
,
combo
);
return
originalStopCallback
(
e
,
el
,
combo
);
};
},
},
},
methods
:
{
};
...
mapActions
([
'
toggleFileFinder
'
]),
},
};
</
script
>
</
script
>
<
template
>
<
template
>
...
...
app/assets/javascripts/ide/constants.js
0 → 100644
View file @
d9262b79
// Fuzzy file finder
export
const
MAX_FILE_FINDER_RESULTS
=
40
;
export
const
FILE_FINDER_ROW_HEIGHT
=
55
;
export
const
FILE_FINDER_EMPTY_ROW_HEIGHT
=
33
;
export
const
UP_KEY_CODE
=
38
;
export
const
DOWN_KEY_CODE
=
40
;
export
const
ENTER_KEY_CODE
=
13
;
export
const
ESC_KEY_CODE
=
27
;
spec/javascripts/ide/components/file_finder/index_spec.js
View file @
d9262b79
import
Vue
from
'
vue
'
;
import
Vue
from
'
vue
'
;
import
store
from
'
~/ide/stores
'
;
import
store
from
'
~/ide/stores
'
;
import
FindFileComponent
from
'
~/ide/components/file_finder/index.vue
'
;
import
FindFileComponent
from
'
~/ide/components/file_finder/index.vue
'
;
import
{
UP_KEY_CODE
,
DOWN_KEY_CODE
,
ENTER_KEY_CODE
,
ESC_KEY_CODE
}
from
'
~/ide/constants
'
;
import
router
from
'
~/ide/ide_router
'
;
import
router
from
'
~/ide/ide_router
'
;
import
{
file
,
resetStore
}
from
'
../../helpers
'
;
import
{
file
,
resetStore
}
from
'
../../helpers
'
;
import
{
mountComponentWithStore
}
from
'
../../../helpers/vue_mount_component_helper
'
;
import
{
mountComponentWithStore
}
from
'
../../../helpers/vue_mount_component_helper
'
;
...
@@ -214,7 +215,7 @@ describe('IDE File finder item spec', () => {
...
@@ -214,7 +215,7 @@ describe('IDE File finder item spec', () => {
describe
(
'
onKeyup
'
,
()
=>
{
describe
(
'
onKeyup
'
,
()
=>
{
it
(
'
opens file on enter key
'
,
done
=>
{
it
(
'
opens file on enter key
'
,
done
=>
{
const
event
=
new
CustomEvent
(
'
keyup
'
);
const
event
=
new
CustomEvent
(
'
keyup
'
);
event
.
keyCode
=
13
;
event
.
keyCode
=
ENTER_KEY_CODE
;
spyOn
(
vm
,
'
openFile
'
);
spyOn
(
vm
,
'
openFile
'
);
...
@@ -229,7 +230,7 @@ describe('IDE File finder item spec', () => {
...
@@ -229,7 +230,7 @@ describe('IDE File finder item spec', () => {
it
(
'
closes file finder on esc key
'
,
done
=>
{
it
(
'
closes file finder on esc key
'
,
done
=>
{
const
event
=
new
CustomEvent
(
'
keyup
'
);
const
event
=
new
CustomEvent
(
'
keyup
'
);
event
.
keyCode
=
27
;
event
.
keyCode
=
ESC_KEY_CODE
;
spyOn
(
vm
,
'
toggleFileFinder
'
);
spyOn
(
vm
,
'
toggleFileFinder
'
);
...
@@ -252,7 +253,7 @@ describe('IDE File finder item spec', () => {
...
@@ -252,7 +253,7 @@ describe('IDE File finder item spec', () => {
describe
(
'
up key
'
,
()
=>
{
describe
(
'
up key
'
,
()
=>
{
const
event
=
new
CustomEvent
(
'
keydown
'
);
const
event
=
new
CustomEvent
(
'
keydown
'
);
event
.
keyCode
=
38
;
event
.
keyCode
=
UP_KEY_CODE
;
it
(
'
resets to last index when at top
'
,
()
=>
{
it
(
'
resets to last index when at top
'
,
()
=>
{
el
.
dispatchEvent
(
event
);
el
.
dispatchEvent
(
event
);
...
@@ -271,7 +272,7 @@ describe('IDE File finder item spec', () => {
...
@@ -271,7 +272,7 @@ describe('IDE File finder item spec', () => {
describe
(
'
down key
'
,
()
=>
{
describe
(
'
down key
'
,
()
=>
{
const
event
=
new
CustomEvent
(
'
keydown
'
);
const
event
=
new
CustomEvent
(
'
keydown
'
);
event
.
keyCode
=
40
;
event
.
keyCode
=
DOWN_KEY_CODE
;
it
(
'
resets to first index when at bottom
'
,
()
=>
{
it
(
'
resets to first index when at bottom
'
,
()
=>
{
vm
.
focusedIndex
=
1
;
vm
.
focusedIndex
=
1
;
...
...
spec/javascripts/ide/components/ide_spec.js
View file @
d9262b79
import
Vue
from
'
vue
'
;
import
Vue
from
'
vue
'
;
import
Mousetrap
from
'
mousetrap
'
;
import
store
from
'
~/ide/stores
'
;
import
store
from
'
~/ide/stores
'
;
import
ide
from
'
~/ide/components/ide.vue
'
;
import
ide
from
'
~/ide/components/ide.vue
'
;
import
{
createComponentWithStore
}
from
'
spec/helpers/vue_mount_component_helper
'
;
import
{
createComponentWithStore
}
from
'
spec/helpers/vue_mount_component_helper
'
;
...
@@ -38,4 +39,68 @@ describe('ide component', () => {
...
@@ -38,4 +39,68 @@ describe('ide component', () => {
done
();
done
();
});
});
});
});
describe
(
'
file finder
'
,
()
=>
{
beforeEach
(
done
=>
{
spyOn
(
vm
,
'
toggleFileFinder
'
);
vm
.
$store
.
state
.
fileFindVisible
=
true
;
vm
.
$nextTick
(
done
);
});
it
(
'
calls toggleFileFinder on `t` key press
'
,
done
=>
{
Mousetrap
.
trigger
(
'
t
'
);
vm
.
$nextTick
()
.
then
(()
=>
{
expect
(
vm
.
toggleFileFinder
).
toHaveBeenCalled
();
})
.
then
(
done
)
.
catch
(
done
.
fail
);
});
it
(
'
calls toggleFileFinder on `command+p` key press
'
,
done
=>
{
Mousetrap
.
trigger
(
'
command+p
'
);
vm
.
$nextTick
()
.
then
(()
=>
{
expect
(
vm
.
toggleFileFinder
).
toHaveBeenCalled
();
})
.
then
(
done
)
.
catch
(
done
.
fail
);
});
it
(
'
calls toggleFileFinder on `ctrl+p` key press
'
,
done
=>
{
Mousetrap
.
trigger
(
'
ctrl+p
'
);
vm
.
$nextTick
()
.
then
(()
=>
{
expect
(
vm
.
toggleFileFinder
).
toHaveBeenCalled
();
})
.
then
(
done
)
.
catch
(
done
.
fail
);
});
it
(
'
always allows `command+p` to trigger toggleFileFinder
'
,
()
=>
{
expect
(
vm
.
mousetrapStopCallback
(
null
,
vm
.
$el
.
querySelector
(
'
.dropdown-input-field
'
),
'
command+p
'
),
).
toBe
(
false
);
});
it
(
'
always allows `ctrl+p` to trigger toggleFileFinder
'
,
()
=>
{
expect
(
vm
.
mousetrapStopCallback
(
null
,
vm
.
$el
.
querySelector
(
'
.dropdown-input-field
'
),
'
ctrl+p
'
),
).
toBe
(
false
);
});
it
(
'
onlys handles `t` when focused in input-field
'
,
()
=>
{
expect
(
vm
.
mousetrapStopCallback
(
null
,
vm
.
$el
.
querySelector
(
'
.dropdown-input-field
'
),
'
t
'
),
).
toBe
(
true
);
});
});
});
});
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