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
Léo-Paul Géneau
gitlab-ce
Commits
f564cbb2
Commit
f564cbb2
authored
Apr 03, 2017
by
Bryce Johnson
Committed by
Alfredo Sumaran
Apr 03, 2017
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Make file templates easy to use and discover
parent
ca6a7f1e
Changes
31
Show whitespace changes
Inline
Side-by-side
Showing
31 changed files
with
832 additions
and
217 deletions
+832
-217
app/assets/javascripts/blob/file_template_mediator.js
app/assets/javascripts/blob/file_template_mediator.js
+241
-0
app/assets/javascripts/blob/file_template_selector.js
app/assets/javascripts/blob/file_template_selector.js
+60
-0
app/assets/javascripts/blob/template_selector.js
app/assets/javascripts/blob/template_selector.js
+0
-0
app/assets/javascripts/blob/template_selectors/blob_ci_yaml_selector.js
...ascripts/blob/template_selectors/blob_ci_yaml_selector.js
+0
-9
app/assets/javascripts/blob/template_selectors/blob_ci_yaml_selectors.js
...scripts/blob/template_selectors/blob_ci_yaml_selectors.js
+0
-23
app/assets/javascripts/blob/template_selectors/blob_dockerfile_selector.js
...ripts/blob/template_selectors/blob_dockerfile_selector.js
+0
-9
app/assets/javascripts/blob/template_selectors/blob_dockerfile_selectors.js
...ipts/blob/template_selectors/blob_dockerfile_selectors.js
+0
-23
app/assets/javascripts/blob/template_selectors/blob_gitignore_selector.js
...cripts/blob/template_selectors/blob_gitignore_selector.js
+0
-9
app/assets/javascripts/blob/template_selectors/blob_gitignore_selectors.js
...ripts/blob/template_selectors/blob_gitignore_selectors.js
+0
-23
app/assets/javascripts/blob/template_selectors/blob_license_selector.js
...ascripts/blob/template_selectors/blob_license_selector.js
+0
-13
app/assets/javascripts/blob/template_selectors/blob_license_selectors.js
...scripts/blob/template_selectors/blob_license_selectors.js
+0
-24
app/assets/javascripts/blob/template_selectors/ci_yaml_selector.js
...s/javascripts/blob/template_selectors/ci_yaml_selector.js
+32
-0
app/assets/javascripts/blob/template_selectors/dockerfile_selector.js
...avascripts/blob/template_selectors/dockerfile_selector.js
+32
-0
app/assets/javascripts/blob/template_selectors/gitignore_selector.js
...javascripts/blob/template_selectors/gitignore_selector.js
+31
-0
app/assets/javascripts/blob/template_selectors/license_selector.js
...s/javascripts/blob/template_selectors/license_selector.js
+38
-0
app/assets/javascripts/blob/template_selectors/type_selector.js
...sets/javascripts/blob/template_selectors/type_selector.js
+25
-0
app/assets/javascripts/blob_edit/blob_bundle.js
app/assets/javascripts/blob_edit/blob_bundle.js
+2
-1
app/assets/javascripts/blob_edit/edit_blob.js
app/assets/javascripts/blob_edit/edit_blob.js
+11
-27
app/assets/javascripts/templates/issuable_template_selector.js
...ssets/javascripts/templates/issuable_template_selector.js
+1
-1
app/assets/stylesheets/pages/editor.scss
app/assets/stylesheets/pages/editor.scss
+113
-29
app/views/projects/blob/_editor.html.haml
app/views/projects/blob/_editor.html.haml
+7
-13
app/views/projects/blob/_template_selectors.html.haml
app/views/projects/blob/_template_selectors.html.haml
+17
-0
app/views/projects/blob/edit.html.haml
app/views/projects/blob/edit.html.haml
+5
-2
app/views/projects/blob/new.html.haml
app/views/projects/blob/new.html.haml
+4
-4
changelogs/unreleased/25332-make-file-templates-easy-to-use-and-discover.yml
...ed/25332-make-file-templates-easy-to-use-and-discover.yml
+4
-0
spec/features/auto_deploy_spec.rb
spec/features/auto_deploy_spec.rb
+2
-2
spec/features/projects/blobs/user_create_spec.rb
spec/features/projects/blobs/user_create_spec.rb
+1
-1
spec/features/projects/files/project_owner_creates_license_file_spec.rb
...projects/files/project_owner_creates_license_file_spec.rb
+2
-2
spec/features/projects/files/project_owner_sees_link_to_create_license_file_in_empty_project_spec.rb
...sees_link_to_create_license_file_in_empty_project_spec.rb
+2
-2
spec/features/projects/files/template_type_dropdown_spec.rb
spec/features/projects/files/template_type_dropdown_spec.rb
+135
-0
spec/features/projects/files/undo_template_spec.rb
spec/features/projects/files/undo_template_spec.rb
+67
-0
No files found.
app/assets/javascripts/blob/file_template_mediator.js
0 → 100644
View file @
f564cbb2
/* eslint-disable class-methods-use-this */
/* global Flash */
import
FileTemplateTypeSelector
from
'
./template_selectors/type_selector
'
;
import
BlobCiYamlSelector
from
'
./template_selectors/ci_yaml_selector
'
;
import
DockerfileSelector
from
'
./template_selectors/dockerfile_selector
'
;
import
GitignoreSelector
from
'
./template_selectors/gitignore_selector
'
;
import
LicenseSelector
from
'
./template_selectors/license_selector
'
;
export
default
class
FileTemplateMediator
{
constructor
({
editor
,
currentAction
})
{
this
.
editor
=
editor
;
this
.
currentAction
=
currentAction
;
this
.
initTemplateSelectors
();
this
.
initTemplateTypeSelector
();
this
.
initDomElements
();
this
.
initDropdowns
();
this
.
initPageEvents
();
}
initTemplateSelectors
()
{
// Order dictates template type dropdown item order
this
.
templateSelectors
=
[
GitignoreSelector
,
BlobCiYamlSelector
,
DockerfileSelector
,
LicenseSelector
,
].
map
(
TemplateSelectorClass
=>
new
TemplateSelectorClass
({
mediator
:
this
}));
}
initTemplateTypeSelector
()
{
this
.
typeSelector
=
new
FileTemplateTypeSelector
({
mediator
:
this
,
dropdownData
:
this
.
templateSelectors
.
map
((
templateSelector
)
=>
{
const
cfg
=
templateSelector
.
config
;
return
{
name
:
cfg
.
name
,
key
:
cfg
.
key
,
};
}),
});
}
initDomElements
()
{
const
$templatesMenu
=
$
(
'
.template-selectors-menu
'
);
const
$undoMenu
=
$templatesMenu
.
find
(
'
.template-selectors-undo-menu
'
);
const
$fileEditor
=
$
(
'
.file-editor
'
);
this
.
$templatesMenu
=
$templatesMenu
;
this
.
$undoMenu
=
$undoMenu
;
this
.
$undoBtn
=
$undoMenu
.
find
(
'
button
'
);
this
.
$templateSelectors
=
$templatesMenu
.
find
(
'
.template-selector-dropdowns-wrap
'
);
this
.
$filenameInput
=
$fileEditor
.
find
(
'
.js-file-path-name-input
'
);
this
.
$fileContent
=
$fileEditor
.
find
(
'
#file-content
'
);
this
.
$commitForm
=
$fileEditor
.
find
(
'
form
'
);
this
.
$navLinks
=
$fileEditor
.
find
(
'
.nav-links
'
);
}
initDropdowns
()
{
if
(
this
.
currentAction
===
'
create
'
)
{
this
.
typeSelector
.
show
();
}
else
{
this
.
hideTemplateSelectorMenu
();
}
this
.
displayMatchedTemplateSelector
();
}
initPageEvents
()
{
this
.
listenForFilenameInput
();
this
.
prepFileContentForSubmit
();
this
.
listenForPreviewMode
();
}
listenForFilenameInput
()
{
this
.
$filenameInput
.
on
(
'
keyup blur
'
,
()
=>
{
this
.
displayMatchedTemplateSelector
();
});
}
prepFileContentForSubmit
()
{
this
.
$commitForm
.
submit
(()
=>
{
this
.
$fileContent
.
val
(
this
.
editor
.
getValue
());
});
}
listenForPreviewMode
()
{
this
.
$navLinks
.
on
(
'
click
'
,
'
a
'
,
(
e
)
=>
{
const
urlPieces
=
e
.
target
.
href
.
split
(
'
#
'
);
const
hash
=
urlPieces
[
1
];
if
(
hash
===
'
preview
'
)
{
this
.
hideTemplateSelectorMenu
();
}
else
if
(
hash
===
'
editor
'
)
{
this
.
showTemplateSelectorMenu
();
}
});
}
selectTemplateType
(
item
,
el
,
e
)
{
if
(
e
)
{
e
.
preventDefault
();
}
this
.
templateSelectors
.
forEach
((
selector
)
=>
{
if
(
selector
.
config
.
key
===
item
.
key
)
{
selector
.
show
();
}
else
{
selector
.
hide
();
}
});
this
.
typeSelector
.
setToggleText
(
item
.
name
);
this
.
cacheToggleText
();
}
selectTemplateFile
(
selector
,
query
,
data
)
{
selector
.
renderLoading
();
// in case undo menu is already already there
this
.
destroyUndoMenu
();
this
.
fetchFileTemplate
(
selector
.
config
.
endpoint
,
query
,
data
)
.
then
((
file
)
=>
{
this
.
showUndoMenu
();
this
.
setEditorContent
(
file
);
this
.
setFilename
(
selector
.
config
.
name
);
selector
.
renderLoaded
();
})
.
catch
(
err
=>
new
Flash
(
`An error occurred while fetching the template:
${
err
}
`
));
}
displayMatchedTemplateSelector
()
{
const
currentInput
=
this
.
getFilename
();
this
.
templateSelectors
.
forEach
((
selector
)
=>
{
const
match
=
selector
.
config
.
pattern
.
test
(
currentInput
);
if
(
match
)
{
this
.
typeSelector
.
show
();
this
.
selectTemplateType
(
selector
.
config
);
this
.
showTemplateSelectorMenu
();
}
});
}
fetchFileTemplate
(
apiCall
,
query
,
data
)
{
return
new
Promise
((
resolve
)
=>
{
const
resolveFile
=
file
=>
resolve
(
file
);
if
(
!
data
)
{
apiCall
(
query
,
resolveFile
);
}
else
{
apiCall
(
query
,
data
,
resolveFile
);
}
});
}
setEditorContent
(
file
)
{
if
(
!
file
&&
file
!==
''
)
return
;
const
newValue
=
file
.
content
||
file
;
this
.
editor
.
setValue
(
newValue
,
1
);
this
.
editor
.
focus
();
this
.
editor
.
navigateFileStart
();
}
findTemplateSelectorByKey
(
key
)
{
return
this
.
templateSelectors
.
find
(
selector
=>
selector
.
config
.
key
===
key
);
}
showUndoMenu
()
{
this
.
$undoMenu
.
removeClass
(
'
hidden
'
);
this
.
$undoBtn
.
on
(
'
click
'
,
()
=>
{
this
.
restoreFromCache
();
this
.
destroyUndoMenu
();
});
}
destroyUndoMenu
()
{
this
.
cacheFileContents
();
this
.
cacheToggleText
();
this
.
$undoMenu
.
addClass
(
'
hidden
'
);
this
.
$undoBtn
.
off
(
'
click
'
);
}
hideTemplateSelectorMenu
()
{
this
.
$templatesMenu
.
hide
();
}
showTemplateSelectorMenu
()
{
this
.
$templatesMenu
.
show
();
}
cacheToggleText
()
{
this
.
cachedToggleText
=
this
.
getTemplateSelectorToggleText
();
}
cacheFileContents
()
{
this
.
cachedContent
=
this
.
editor
.
getValue
();
this
.
cachedFilename
=
this
.
getFilename
();
}
restoreFromCache
()
{
this
.
setEditorContent
(
this
.
cachedContent
);
this
.
setFilename
(
this
.
cachedFilename
);
this
.
setTemplateSelectorToggleText
();
}
getTemplateSelectorToggleText
()
{
return
this
.
$templateSelectors
.
find
(
'
.js-template-selector-wrap:visible .dropdown-toggle-text
'
)
.
text
();
}
setTemplateSelectorToggleText
()
{
return
this
.
$templateSelectors
.
find
(
'
.js-template-selector-wrap:visible .dropdown-toggle-text
'
)
.
text
(
this
.
cachedToggleText
);
}
getTypeSelectorToggleText
()
{
return
this
.
typeSelector
.
getToggleText
();
}
getFilename
()
{
return
this
.
$filenameInput
.
val
();
}
setFilename
(
name
)
{
this
.
$filenameInput
.
val
(
name
);
}
getSelected
()
{
return
this
.
templateSelectors
.
find
(
selector
=>
selector
.
selected
);
}
}
app/assets/javascripts/blob/file_template_selector.js
0 → 100644
View file @
f564cbb2
/* global Api */
export
default
class
FileTemplateSelector
{
constructor
(
mediator
)
{
this
.
mediator
=
mediator
;
this
.
$dropdown
=
null
;
this
.
$wrapper
=
null
;
}
init
()
{
const
cfg
=
this
.
config
;
this
.
$dropdown
=
$
(
cfg
.
dropdown
);
this
.
$wrapper
=
$
(
cfg
.
wrapper
);
this
.
$loadingIcon
=
this
.
$wrapper
.
find
(
'
.fa-chevron-down
'
);
this
.
$dropdownToggleText
=
this
.
$wrapper
.
find
(
'
.dropdown-toggle-text
'
);
this
.
initDropdown
();
}
show
()
{
if
(
this
.
$dropdown
===
null
)
{
this
.
init
();
}
this
.
$wrapper
.
removeClass
(
'
hidden
'
);
}
hide
()
{
if
(
this
.
$dropdown
!==
null
)
{
this
.
$wrapper
.
addClass
(
'
hidden
'
);
}
}
getToggleText
()
{
return
this
.
$dropdownToggleText
.
text
();
}
setToggleText
(
text
)
{
this
.
$dropdownToggleText
.
text
(
text
);
}
renderLoading
()
{
this
.
$loadingIcon
.
addClass
(
'
fa-spinner fa-spin
'
)
.
removeClass
(
'
fa-chevron-down
'
);
}
renderLoaded
()
{
this
.
$loadingIcon
.
addClass
(
'
fa-chevron-down
'
)
.
removeClass
(
'
fa-spinner fa-spin
'
);
}
reportSelection
(
query
,
el
,
e
,
data
)
{
e
.
preventDefault
();
return
this
.
mediator
.
selectTemplateFile
(
this
,
query
,
data
);
}
}
app/assets/javascripts/blob/template_selector
s/template_selector
.js
→
app/assets/javascripts/blob/template_selector.js
View file @
f564cbb2
File moved
app/assets/javascripts/blob/template_selectors/blob_ci_yaml_selector.js
deleted
100644 → 0
View file @
ca6a7f1e
/* global Api */
import
TemplateSelector
from
'
./template_selector
'
;
export
default
class
BlobCiYamlSelector
extends
TemplateSelector
{
requestFile
(
query
)
{
return
Api
.
gitlabCiYml
(
query
.
name
,
(
file
,
config
)
=>
this
.
setEditorContent
(
file
,
config
));
}
}
app/assets/javascripts/blob/template_selectors/blob_ci_yaml_selectors.js
deleted
100644 → 0
View file @
ca6a7f1e
/* global Api */
import
BlobCiYamlSelector
from
'
./blob_ci_yaml_selector
'
;
export
default
class
BlobCiYamlSelectors
{
constructor
({
editor
,
$dropdowns
})
{
this
.
$dropdowns
=
$dropdowns
||
$
(
'
.js-gitlab-ci-yml-selector
'
);
this
.
initSelectors
(
editor
);
}
initSelectors
(
editor
)
{
this
.
$dropdowns
.
each
((
i
,
dropdown
)
=>
{
const
$dropdown
=
$
(
dropdown
);
return
new
BlobCiYamlSelector
({
editor
,
pattern
:
/
(
.gitlab-ci.yml
)
/
,
data
:
$dropdown
.
data
(
'
data
'
),
wrapper
:
$dropdown
.
closest
(
'
.js-gitlab-ci-yml-selector-wrap
'
),
dropdown
:
$dropdown
,
});
});
}
}
app/assets/javascripts/blob/template_selectors/blob_dockerfile_selector.js
deleted
100644 → 0
View file @
ca6a7f1e
/* global Api */
import
TemplateSelector
from
'
./template_selector
'
;
export
default
class
BlobDockerfileSelector
extends
TemplateSelector
{
requestFile
(
query
)
{
return
Api
.
dockerfileYml
(
query
.
name
,
(
file
,
config
)
=>
this
.
setEditorContent
(
file
,
config
));
}
}
app/assets/javascripts/blob/template_selectors/blob_dockerfile_selectors.js
deleted
100644 → 0
View file @
ca6a7f1e
import
BlobDockerfileSelector
from
'
./blob_dockerfile_selector
'
;
export
default
class
BlobDockerfileSelectors
{
constructor
({
editor
,
$dropdowns
})
{
this
.
editor
=
editor
;
this
.
$dropdowns
=
$dropdowns
||
$
(
'
.js-dockerfile-selector
'
);
this
.
initSelectors
();
}
initSelectors
()
{
const
editor
=
this
.
editor
;
this
.
$dropdowns
.
each
((
i
,
dropdown
)
=>
{
const
$dropdown
=
$
(
dropdown
);
return
new
BlobDockerfileSelector
({
editor
,
pattern
:
/
(
Dockerfile
)
/
,
data
:
$dropdown
.
data
(
'
data
'
),
wrapper
:
$dropdown
.
closest
(
'
.js-dockerfile-selector-wrap
'
),
dropdown
:
$dropdown
,
});
});
}
}
app/assets/javascripts/blob/template_selectors/blob_gitignore_selector.js
deleted
100644 → 0
View file @
ca6a7f1e
/* global Api */
import
TemplateSelector
from
'
./template_selector
'
;
export
default
class
BlobGitignoreSelector
extends
TemplateSelector
{
requestFile
(
query
)
{
return
Api
.
gitignoreText
(
query
.
name
,
(
file
,
config
)
=>
this
.
setEditorContent
(
file
,
config
));
}
}
app/assets/javascripts/blob/template_selectors/blob_gitignore_selectors.js
deleted
100644 → 0
View file @
ca6a7f1e
import
BlobGitignoreSelector
from
'
./blob_gitignore_selector
'
;
export
default
class
BlobGitignoreSelectors
{
constructor
({
editor
,
$dropdowns
})
{
this
.
$dropdowns
=
$dropdowns
||
$
(
'
.js-gitignore-selector
'
);
this
.
editor
=
editor
;
this
.
initSelectors
();
}
initSelectors
()
{
this
.
$dropdowns
.
each
((
i
,
dropdown
)
=>
{
const
$dropdown
=
$
(
dropdown
);
return
new
BlobGitignoreSelector
({
pattern
:
/
(
.gitignore
)
/
,
data
:
$dropdown
.
data
(
'
data
'
),
wrapper
:
$dropdown
.
closest
(
'
.js-gitignore-selector-wrap
'
),
dropdown
:
$dropdown
,
editor
:
this
.
editor
,
});
});
}
}
app/assets/javascripts/blob/template_selectors/blob_license_selector.js
deleted
100644 → 0
View file @
ca6a7f1e
/* global Api */
import
TemplateSelector
from
'
./template_selector
'
;
export
default
class
BlobLicenseSelector
extends
TemplateSelector
{
requestFile
(
query
)
{
const
data
=
{
project
:
this
.
dropdown
.
data
(
'
project
'
),
fullname
:
this
.
dropdown
.
data
(
'
fullname
'
),
};
return
Api
.
licenseText
(
query
.
id
,
data
,
(
file
,
config
)
=>
this
.
setEditorContent
(
file
,
config
));
}
}
app/assets/javascripts/blob/template_selectors/blob_license_selectors.js
deleted
100644 → 0
View file @
ca6a7f1e
/* eslint-disable no-unused-vars, no-param-reassign */
import
BlobLicenseSelector
from
'
./blob_license_selector
'
;
export
default
class
BlobLicenseSelectors
{
constructor
({
$dropdowns
,
editor
})
{
this
.
$dropdowns
=
$dropdowns
||
$
(
'
.js-license-selector
'
);
this
.
initSelectors
(
editor
);
}
initSelectors
(
editor
)
{
this
.
$dropdowns
.
each
((
i
,
dropdown
)
=>
{
const
$dropdown
=
$
(
dropdown
);
return
new
BlobLicenseSelector
({
editor
,
pattern
:
/^
(
.+
\/)?(
licen
[
sc
]
e|copying
)(
$|
\.)
/i
,
data
:
$dropdown
.
data
(
'
data
'
),
wrapper
:
$dropdown
.
closest
(
'
.js-license-selector-wrap
'
),
dropdown
:
$dropdown
,
});
});
}
}
app/assets/javascripts/blob/template_selectors/ci_yaml_selector.js
0 → 100644
View file @
f564cbb2
/* global Api */
import
FileTemplateSelector
from
'
../file_template_selector
'
;
export
default
class
BlobCiYamlSelector
extends
FileTemplateSelector
{
constructor
({
mediator
})
{
super
(
mediator
);
this
.
config
=
{
key
:
'
gitlab-ci-yaml
'
,
name
:
'
.gitlab-ci.yml
'
,
pattern
:
/
(
.gitlab-ci.yml
)
/
,
endpoint
:
Api
.
gitlabCiYml
,
dropdown
:
'
.js-gitlab-ci-yml-selector
'
,
wrapper
:
'
.js-gitlab-ci-yml-selector-wrap
'
,
};
}
initDropdown
()
{
// maybe move to super class as well
this
.
$dropdown
.
glDropdown
({
data
:
this
.
$dropdown
.
data
(
'
data
'
),
filterable
:
true
,
selectable
:
true
,
toggleLabel
:
item
=>
item
.
name
,
search
:
{
fields
:
[
'
name
'
],
},
clicked
:
(
query
,
el
,
e
)
=>
this
.
reportSelection
(
query
.
name
,
el
,
e
),
text
:
item
=>
item
.
name
,
});
}
}
app/assets/javascripts/blob/template_selectors/dockerfile_selector.js
0 → 100644
View file @
f564cbb2
/* global Api */
import FileTemplateSelector from '../file_template_selector';
export default class DockerfileSelector extends FileTemplateSelector {
constructor({ mediator }) {
super(mediator);
this.config = {
key: 'dockerfile',
name: 'Dockerfile',
pattern: /(Dockerfile)/,
endpoint: Api.dockerfileYml,
dropdown: '.js-dockerfile-selector',
wrapper: '.js-dockerfile-selector-wrap',
};
}
initDropdown() {
// maybe move to super class as well
this.$dropdown.glDropdown({
data: this.$dropdown.data('data'),
filterable: true,
selectable: true,
toggleLabel: item => item.name,
search: {
fields: ['name'],
},
clicked: (query, el, e) => this.reportSelection(query.name, el, e),
text: item => item.name,
});
}
}
app/assets/javascripts/blob/template_selectors/gitignore_selector.js
0 → 100644
View file @
f564cbb2
/* global Api */
import
FileTemplateSelector
from
'
../file_template_selector
'
;
export
default
class
BlobGitignoreSelector
extends
FileTemplateSelector
{
constructor
({
mediator
})
{
super
(
mediator
);
this
.
config
=
{
key
:
'
gitignore
'
,
name
:
'
.gitignore
'
,
pattern
:
/
(
.gitignore
)
/
,
endpoint
:
Api
.
gitignoreText
,
dropdown
:
'
.js-gitignore-selector
'
,
wrapper
:
'
.js-gitignore-selector-wrap
'
,
};
}
initDropdown
()
{
this
.
$dropdown
.
glDropdown
({
data
:
this
.
$dropdown
.
data
(
'
data
'
),
filterable
:
true
,
selectable
:
true
,
toggleLabel
:
item
=>
item
.
name
,
search
:
{
fields
:
[
'
name
'
],
},
clicked
:
(
query
,
el
,
e
)
=>
this
.
reportSelection
(
query
.
name
,
el
,
e
),
text
:
item
=>
item
.
name
,
});
}
}
app/assets/javascripts/blob/template_selectors/license_selector.js
0 → 100644
View file @
f564cbb2
/* global Api */
import
FileTemplateSelector
from
'
../file_template_selector
'
;
export
default
class
BlobLicenseSelector
extends
FileTemplateSelector
{
constructor
({
mediator
})
{
super
(
mediator
);
this
.
config
=
{
key
:
'
license
'
,
name
:
'
LICENSE
'
,
pattern
:
/^
(
.+
\/)?(
licen
[
sc
]
e|copying
)(
$|
\.)
/i
,
endpoint
:
Api
.
licenseText
,
dropdown
:
'
.js-license-selector
'
,
wrapper
:
'
.js-license-selector-wrap
'
,
};
}
initDropdown
()
{
this
.
$dropdown
.
glDropdown
({
data
:
this
.
$dropdown
.
data
(
'
data
'
),
filterable
:
true
,
selectable
:
true
,
toggleLabel
:
item
=>
item
.
name
,
search
:
{
fields
:
[
'
name
'
],
},
clicked
:
(
query
,
el
,
e
)
=>
{
const
data
=
{
project
:
this
.
$dropdown
.
data
(
'
project
'
),
fullname
:
this
.
$dropdown
.
data
(
'
fullname
'
),
};
this
.
reportSelection
(
query
.
id
,
el
,
e
,
data
);
},
text
:
item
=>
item
.
name
,
});
}
}
app/assets/javascripts/blob/template_selectors/type_selector.js
0 → 100644
View file @
f564cbb2
import
FileTemplateSelector
from
'
../file_template_selector
'
;
export
default
class
FileTemplateTypeSelector
extends
FileTemplateSelector
{
constructor
({
mediator
,
dropdownData
})
{
super
(
mediator
);
this
.
mediator
=
mediator
;
this
.
config
=
{
dropdown
:
'
.js-template-type-selector
'
,
wrapper
:
'
.js-template-type-selector-wrap
'
,
dropdownData
,
};
}
initDropdown
()
{
this
.
$dropdown
.
glDropdown
({
data
:
this
.
config
.
dropdownData
,
filterable
:
false
,
selectable
:
true
,
toggleLabel
:
item
=>
item
.
name
,
clicked
:
(
item
,
el
,
e
)
=>
this
.
mediator
.
selectTemplateType
(
item
,
el
,
e
),
text
:
item
=>
item
.
name
,
});
}
}
app/assets/javascripts/blob_edit/blob_bundle.js
View file @
f564cbb2
...
@@ -13,8 +13,9 @@ $(() => {
...
@@ -13,8 +13,9 @@ $(() => {
const
urlRoot
=
editBlobForm
.
data
(
'
relative-url-root
'
);
const
urlRoot
=
editBlobForm
.
data
(
'
relative-url-root
'
);
const
assetsPath
=
editBlobForm
.
data
(
'
assets-prefix
'
);
const
assetsPath
=
editBlobForm
.
data
(
'
assets-prefix
'
);
const
blobLanguage
=
editBlobForm
.
data
(
'
blob-language
'
);
const
blobLanguage
=
editBlobForm
.
data
(
'
blob-language
'
);
const
currentAction
=
$
(
'
.js-file-title
'
).
data
(
'
current-action
'
);
new
EditBlob
(
`
${
urlRoot
}${
assetsPath
}
`
,
blobLanguage
);
new
EditBlob
(
`
${
urlRoot
}${
assetsPath
}
`
,
blobLanguage
,
currentAction
);
new
NewCommitForm
(
editBlobForm
);
new
NewCommitForm
(
editBlobForm
);
}
}
...
...
app/assets/javascripts/blob_edit/edit_blob.js
View file @
f564cbb2
/* global ace */
/* global ace */
import
BlobLicenseSelectors
from
'
../blob/template_selectors/blob_license_selectors
'
;
import
TemplateSelectorMediator
from
'
../blob/file_template_mediator
'
;
import
BlobGitignoreSelectors
from
'
../blob/template_selectors/blob_gitignore_selectors
'
;
import
BlobCiYamlSelectors
from
'
../blob/template_selectors/blob_ci_yaml_selectors
'
;
import
BlobDockerfileSelectors
from
'
../blob/template_selectors/blob_dockerfile_selectors
'
;
export
default
class
EditBlob
{
export
default
class
EditBlob
{
constructor
(
assetsPath
,
aceMode
)
{
constructor
(
assetsPath
,
aceMode
,
currentAction
)
{
this
.
configureAceEditor
(
aceMode
,
assetsPath
);
this
.
configureAceEditor
(
aceMode
,
assetsPath
);
this
.
prepFileContentForSubmit
();
this
.
initModePanesAndLinks
();
this
.
initModePanesAndLinks
();
this
.
initSoftWrap
();
this
.
initSoftWrap
();
this
.
initFileSelectors
();
this
.
initFileSelectors
(
currentAction
);
}
}
configureAceEditor
(
aceMode
,
assetsPath
)
{
configureAceEditor
(
aceMode
,
assetsPath
)
{
...
@@ -19,6 +15,10 @@ export default class EditBlob {
...
@@ -19,6 +15,10 @@ export default class EditBlob {
ace
.
config
.
loadModule
(
'
ace/ext/searchbox
'
);
ace
.
config
.
loadModule
(
'
ace/ext/searchbox
'
);
this
.
editor
=
ace
.
edit
(
'
editor
'
);
this
.
editor
=
ace
.
edit
(
'
editor
'
);
// This prevents warnings re: automatic scrolling being logged
this
.
editor
.
$blockScrolling
=
Infinity
;
this
.
editor
.
focus
();
this
.
editor
.
focus
();
if
(
aceMode
)
{
if
(
aceMode
)
{
...
@@ -26,27 +26,11 @@ export default class EditBlob {
...
@@ -26,27 +26,11 @@ export default class EditBlob {
}
}
}
}
prepFileContentForSubmit
()
{
initFileSelectors
(
currentAction
)
{
$
(
'
form
'
).
submit
(()
=>
{
this
.
fileTemplateMediator
=
new
TemplateSelectorMediator
({
$
(
'
#file-content
'
).
val
(
this
.
editor
.
getValue
());
currentAction
,
});
}
initFileSelectors
()
{
this
.
blobTemplateSelectors
=
[
new
BlobLicenseSelectors
({
editor
:
this
.
editor
,
editor
:
this
.
editor
,
}),
});
new
BlobGitignoreSelectors
({
editor
:
this
.
editor
,
}),
new
BlobCiYamlSelectors
({
editor
:
this
.
editor
,
}),
new
BlobDockerfileSelectors
({
editor
:
this
.
editor
,
}),
];
}
}
initModePanesAndLinks
()
{
initModePanesAndLinks
()
{
...
...
app/assets/javascripts/templates/issuable_template_selector.js
View file @
f564cbb2
/* eslint-disable comma-dangle, max-len, no-useless-return, no-param-reassign, max-len */
/* eslint-disable comma-dangle, max-len, no-useless-return, no-param-reassign, max-len */
/* global Api */
/* global Api */
import
TemplateSelector
from
'
../blob/template_selector
s/template_selector
'
;
import
TemplateSelector
from
'
../blob/template_selector
'
;
((
global
)
=>
{
((
global
)
=>
{
class
IssuableTemplateSelector
extends
TemplateSelector
{
class
IssuableTemplateSelector
extends
TemplateSelector
{
...
...
app/assets/stylesheets/pages/editor.scss
View file @
f564cbb2
.file-editor
{
.file-editor
{
.nav-links
{
border-top
:
1px
solid
$border-color
;
border-right
:
1px
solid
$border-color
;
border-left
:
1px
solid
$border-color
;
border-bottom
:
none
;
border-radius
:
2px
;
background
:
$gray-normal
;
}
#editor
{
#editor
{
border
:
none
;
border
:
none
;
border-radius
:
0
;
border-radius
:
0
;
...
@@ -72,11 +81,7 @@
...
@@ -72,11 +81,7 @@
}
}
.encoding-selector
,
.encoding-selector
,
.soft-wrap-toggle
,
.soft-wrap-toggle
{
.license-selector
,
.gitignore-selector
,
.gitlab-ci-yml-selector
,
.dockerfile-selector
{
display
:
inline-block
;
display
:
inline-block
;
vertical-align
:
top
;
vertical-align
:
top
;
font-family
:
$regular_font
;
font-family
:
$regular_font
;
...
@@ -103,28 +108,9 @@
...
@@ -103,28 +108,9 @@
}
}
}
}
}
}
.gitignore-selector
,
.license-selector
,
.gitlab-ci-yml-selector
,
.dockerfile-selector
{
.dropdown
{
line-height
:
21px
;
}
.dropdown-menu-toggle
{
vertical-align
:
top
;
width
:
220px
;
}
}
.gitlab-ci-yml-selector
{
.dropdown-menu-toggle
{
width
:
250px
;
}
}
}
}
@media
(
max-width
:
$screen-xs-max
){
@media
(
max-width
:
$screen-xs-max
){
.file-editor
{
.file-editor
{
.file-title
{
.file-title
{
...
@@ -149,10 +135,7 @@
...
@@ -149,10 +135,7 @@
margin
:
3px
0
;
margin
:
3px
0
;
}
}
.encoding-selector
,
.encoding-selector
{
.license-selector
,
.gitignore-selector
,
.gitlab-ci-yml-selector
{
display
:
block
;
display
:
block
;
margin
:
3px
0
;
margin
:
3px
0
;
...
@@ -163,3 +146,104 @@
...
@@ -163,3 +146,104 @@
}
}
}
}
}
}
.blob-new-page-title
,
.blob-edit-page-title
{
margin
:
19px
0
21px
;
vertical-align
:
top
;
display
:
inline-block
;
@media
(
max-width
:
$screen-sm-max
)
{
display
:
block
;
margin
:
19px
0
12px
;
}
}
.template-selectors-menu
{
display
:
inline-block
;
vertical-align
:
top
;
margin
:
14px
0
0
16px
;
padding
:
0
0
0
14px
;
border-left
:
1px
solid
$border-color
;
@media
(
max-width
:
$screen-sm-max
)
{
display
:
block
;
width
:
100%
;
margin
:
5px
0
;
padding
:
0
;
border-left
:
none
;
}
}
.templates-selectors-label
{
display
:
inline-block
;
vertical-align
:
top
;
margin-top
:
6px
;
line-height
:
21px
;
@media
(
max-width
:
$screen-sm-max
)
{
display
:
block
;
margin
:
5px
0
;
}
}
.template-selector-dropdowns-wrap
{
display
:
inline-block
;
margin-left
:
8px
;
vertical-align
:
top
;
margin
:
5px
0
0
8px
;
@media
(
max-width
:
$screen-sm-max
)
{
display
:
block
;
width
:
100%
;
margin
:
0
0
16px
;
}
.license-selector
,
.gitignore-selector
,
.gitlab-ci-yml-selector
,
.dockerfile-selector
,
.template-type-selector
{
display
:
inline-block
;
vertical-align
:
top
;
font-family
:
$regular_font
;
margin-top
:
-5px
;
@media
(
max-width
:
$screen-sm-max
)
{
display
:
block
;
width
:
100%
;
margin
:
5px
0
;
}
.dropdown
{
line-height
:
21px
;
}
.dropdown-menu-toggle
{
width
:
250px
;
vertical-align
:
top
;
@media
(
max-width
:
$screen-sm-max
)
{
display
:
block
;
width
:
100%
;
margin
:
5px
0
;
}
}
}
}
.template-selectors-undo-menu
{
display
:
inline-block
;
margin
:
7px
0
0
10px
;
@media
(
max-width
:
$screen-sm-max
)
{
display
:
block
;
width
:
100%
;
margin
:
20px
0
;
}
button
{
margin
:
-4px
0
0
15px
;
}
}
app/views/projects/blob/_editor.html.haml
View file @
f564cbb2
-
action
=
current_action?
(
:edit
)
||
current_action?
(
:update
)
?
'edit'
:
'create'
.file-holder.file.append-bottom-default
.file-holder.file.append-bottom-default
.js-file-title.file-title.clearfix
.js-file-title.file-title.clearfix
{
data:
{
current_action:
action
}
}
.editor-ref
.editor-ref
=
icon
(
'code-fork'
)
=
icon
(
'code-fork'
)
=
ref
=
ref
%span
.editor-file-name
%span
.editor-file-name
-
if
current_action?
(
:edit
)
||
current_action?
(
:update
)
-
if
current_action?
(
:edit
)
||
current_action?
(
:update
)
=
text_field_tag
'file_path'
,
(
params
[
:file_path
]
||
@path
),
=
text_field_tag
'file_path'
,
(
params
[
:file_path
]
||
@path
),
class:
'form-control new-file-path'
class:
'form-control new-file-path
js-file-path-name-input
'
-
if
current_action?
(
:new
)
||
current_action?
(
:create
)
-
if
current_action?
(
:new
)
||
current_action?
(
:create
)
%span
.editor-file-name
%span
.editor-file-name
\/
\/
=
text_field_tag
'file_name'
,
params
[
:file_name
],
placeholder:
"File name"
,
=
text_field_tag
'file_name'
,
params
[
:file_name
],
placeholder:
"File name"
,
required:
true
,
class:
'form-control new-file-name'
required:
true
,
class:
'form-control new-file-name
js-file-path-name-input
'
.pull-right.file-buttons
.pull-right.file-buttons
.license-selector.js-license-selector-wrap.hidden
=
button_tag
class:
'soft-wrap-toggle btn'
,
type:
'button'
,
tabindex:
'-1'
do
=
dropdown_tag
(
"Choose a License template"
,
options:
{
toggle_class:
'btn js-license-selector'
,
title:
"Choose a license"
,
filter:
true
,
placeholder:
"Filter"
,
data:
{
data:
licenses_for_select
,
project:
@project
.
name
,
fullname:
@project
.
namespace
.
human_name
}
}
)
.gitignore-selector.js-gitignore-selector-wrap.hidden
=
dropdown_tag
(
"Choose a .gitignore template"
,
options:
{
toggle_class:
'btn js-gitignore-selector'
,
title:
"Choose a template"
,
filter:
true
,
placeholder:
"Filter"
,
data:
{
data:
gitignore_names
}
}
)
.gitlab-ci-yml-selector.js-gitlab-ci-yml-selector-wrap.hidden
=
dropdown_tag
(
"Choose a GitLab CI Yaml template"
,
options:
{
toggle_class:
'btn js-gitlab-ci-yml-selector'
,
title:
"Choose a template"
,
filter:
true
,
placeholder:
"Filter"
,
data:
{
data:
gitlab_ci_ymls
}
}
)
.dockerfile-selector.js-dockerfile-selector-wrap.hidden
=
dropdown_tag
(
"Choose a Dockerfile template"
,
options:
{
toggle_class:
'btn js-dockerfile-selector'
,
title:
"Choose a template"
,
filter:
true
,
placeholder:
"Filter"
,
data:
{
data:
dockerfile_names
}
}
)
=
button_tag
class:
'soft-wrap-toggle btn'
,
type:
'button'
do
%span
.no-wrap
%span
.no-wrap
=
custom_icon
(
'icon_no_wrap'
)
=
custom_icon
(
'icon_no_wrap'
)
No wrap
No wrap
...
@@ -31,7 +25,7 @@
...
@@ -31,7 +25,7 @@
=
custom_icon
(
'icon_soft_wrap'
)
=
custom_icon
(
'icon_soft_wrap'
)
Soft wrap
Soft wrap
.encoding-selector
.encoding-selector
=
select_tag
:encoding
,
options_for_select
([
"base64"
,
"text"
],
"text"
),
class:
'select2'
=
select_tag
:encoding
,
options_for_select
([
"base64"
,
"text"
],
"text"
),
class:
'select2'
,
tabindex:
'-1'
.file-editor.code
.file-editor.code
%pre
.js-edit-mode-pane
#editor
=
params
[
:content
]
||
local_assigns
[
:blob_data
]
%pre
.js-edit-mode-pane
#editor
=
params
[
:content
]
||
local_assigns
[
:blob_data
]
...
...
app/views/projects/blob/_template_selectors.html.haml
0 → 100644
View file @
f564cbb2
.template-selectors-menu
.templates-selectors-label
Template
.template-selector-dropdowns-wrap
.template-type-selector.js-template-type-selector-wrap.hidden
=
dropdown_tag
(
"Choose type"
,
options:
{
toggle_class:
'btn js-template-type-selector'
,
title:
"Choose a template type"
}
)
.license-selector.js-license-selector-wrap.js-template-selector-wrap.hidden
=
dropdown_tag
(
"Apply a License template"
,
options:
{
toggle_class:
'btn js-license-selector'
,
title:
"Apply a license"
,
filter:
true
,
placeholder:
"Filter"
,
data:
{
data:
licenses_for_select
,
project:
@project
.
name
,
fullname:
@project
.
namespace
.
human_name
}
}
)
.gitignore-selector.js-gitignore-selector-wrap.js-template-selector-wrap.hidden
=
dropdown_tag
(
"Apply a .gitignore template"
,
options:
{
toggle_class:
'btn js-gitignore-selector'
,
title:
"Apply a template"
,
filter:
true
,
placeholder:
"Filter"
,
data:
{
data:
gitignore_names
}
}
)
.gitlab-ci-yml-selector.js-gitlab-ci-yml-selector-wrap.js-template-selector-wrap.hidden
=
dropdown_tag
(
"Apply a GitLab CI Yaml template"
,
options:
{
toggle_class:
'btn js-gitlab-ci-yml-selector'
,
title:
"Apply a template"
,
filter:
true
,
placeholder:
"Filter"
,
data:
{
data:
gitlab_ci_ymls
}
}
)
.dockerfile-selector.js-dockerfile-selector-wrap.js-template-selector-wrap.hidden
=
dropdown_tag
(
"Apply a Dockerfile template"
,
options:
{
toggle_class:
'btn js-dockerfile-selector'
,
title:
"Apply a template"
,
filter:
true
,
placeholder:
"Filter"
,
data:
{
data:
dockerfile_names
}
}
)
.template-selectors-undo-menu.hidden
%span
.text-info
Template applied
%button
.btn.btn-sm.btn-info
Undo
app/views/projects/blob/edit.html.haml
View file @
f564cbb2
...
@@ -11,12 +11,15 @@
...
@@ -11,12 +11,15 @@
Someone edited the file the same time you did. Please check out
Someone edited the file the same time you did. Please check out
=
link_to
"the file"
,
namespace_project_blob_path
(
@project
.
namespace
,
@project
,
tree_join
(
@target_branch
,
@file_path
)),
target:
"_blank"
,
rel:
'noopener noreferrer'
=
link_to
"the file"
,
namespace_project_blob_path
(
@project
.
namespace
,
@project
,
tree_join
(
@target_branch
,
@file_path
)),
target:
"_blank"
,
rel:
'noopener noreferrer'
and make sure your changes will not unintentionally remove theirs.
and make sure your changes will not unintentionally remove theirs.
.editor-title-row
%h3
.page-title.blob-edit-page-title
Edit file
=
render
'template_selectors'
.file-editor
.file-editor
%ul
.nav-links.no-bottom.js-edit-mode
%ul
.nav-links.no-bottom.js-edit-mode
%li
.active
%li
.active
=
link_to
'#editor'
do
=
link_to
'#editor'
do
Edit Fil
e
Writ
e
%li
%li
=
link_to
'#preview'
,
'data-preview-url'
=>
namespace_project_preview_blob_path
(
@project
.
namespace
,
@project
,
@id
)
do
=
link_to
'#preview'
,
'data-preview-url'
=>
namespace_project_preview_blob_path
(
@project
.
namespace
,
@project
,
@id
)
do
...
...
app/views/projects/blob/new.html.haml
View file @
f564cbb2
...
@@ -2,10 +2,10 @@
...
@@ -2,10 +2,10 @@
-
content_for
:page_specific_javascripts
do
-
content_for
:page_specific_javascripts
do
=
page_specific_javascript_tag
(
'lib/ace.js'
)
=
page_specific_javascript_tag
(
'lib/ace.js'
)
=
page_specific_javascript_bundle_tag
(
'blob'
)
=
page_specific_javascript_bundle_tag
(
'blob'
)
.editor-title-row
%h3
.
page-title
%h3
.page-title.blob-new-
page-title
New F
ile
New f
ile
=
render
'template_selectors'
.file-editor
.file-editor
=
form_tag
(
namespace_project_create_blob_path
(
@project
.
namespace
,
@project
,
@id
),
method: :post
,
class:
'form-horizontal js-edit-blob-form js-new-blob-form js-quick-submit js-requires-input'
,
data:
blob_editor_paths
)
do
=
form_tag
(
namespace_project_create_blob_path
(
@project
.
namespace
,
@project
,
@id
),
method: :post
,
class:
'form-horizontal js-edit-blob-form js-new-blob-form js-quick-submit js-requires-input'
,
data:
blob_editor_paths
)
do
=
render
'projects/blob/editor'
,
ref:
@ref
=
render
'projects/blob/editor'
,
ref:
@ref
...
...
changelogs/unreleased/25332-make-file-templates-easy-to-use-and-discover.yml
0 → 100644
View file @
f564cbb2
---
title
:
Remove no-new annotation from file_template_mediator.js.
merge_request
:
!9782
author
:
spec/features/auto_deploy_spec.rb
View file @
f564cbb2
...
@@ -42,7 +42,7 @@ describe 'Auto deploy' do
...
@@ -42,7 +42,7 @@ describe 'Auto deploy' do
it
'includes OpenShift as an available template'
,
js:
true
do
it
'includes OpenShift as an available template'
,
js:
true
do
click_link
'Set up auto deploy'
click_link
'Set up auto deploy'
click_button
'
Choose
a GitLab CI Yaml template'
click_button
'
Apply
a GitLab CI Yaml template'
within
'.gitlab-ci-yml-selector'
do
within
'.gitlab-ci-yml-selector'
do
expect
(
page
).
to
have_content
(
'OpenShift'
)
expect
(
page
).
to
have_content
(
'OpenShift'
)
...
@@ -51,7 +51,7 @@ describe 'Auto deploy' do
...
@@ -51,7 +51,7 @@ describe 'Auto deploy' do
it
'creates a merge request using "auto-deploy" branch'
,
js:
true
do
it
'creates a merge request using "auto-deploy" branch'
,
js:
true
do
click_link
'Set up auto deploy'
click_link
'Set up auto deploy'
click_button
'
Choose
a GitLab CI Yaml template'
click_button
'
Apply
a GitLab CI Yaml template'
within
'.gitlab-ci-yml-selector'
do
within
'.gitlab-ci-yml-selector'
do
click_on
'OpenShift'
click_on
'OpenShift'
end
end
...
...
spec/features/projects/blobs/user_create_spec.rb
View file @
f564cbb2
...
@@ -88,7 +88,7 @@ feature 'New blob creation', feature: true, js: true do
...
@@ -88,7 +88,7 @@ feature 'New blob creation', feature: true, js: true do
scenario
'shows error message'
do
scenario
'shows error message'
do
expect
(
page
).
to
have_content
(
'Your changes could not be committed because a file with the same name already exists'
)
expect
(
page
).
to
have_content
(
'Your changes could not be committed because a file with the same name already exists'
)
expect
(
page
).
to
have_content
(
'New
F
ile'
)
expect
(
page
).
to
have_content
(
'New
f
ile'
)
expect
(
page
).
to
have_content
(
'NextFeature'
)
expect
(
page
).
to
have_content
(
'NextFeature'
)
end
end
end
end
...
...
spec/features/projects/files/project_owner_creates_license_file_spec.rb
View file @
f564cbb2
...
@@ -40,7 +40,7 @@ feature 'project owner creates a license file', feature: true, js: true do
...
@@ -40,7 +40,7 @@ feature 'project owner creates a license file', feature: true, js: true do
scenario
'project master creates a license file from the "Add license" link'
do
scenario
'project master creates a license file from the "Add license" link'
do
click_link
'Add License'
click_link
'Add License'
expect
(
page
).
to
have_content
(
'New
F
ile'
)
expect
(
page
).
to
have_content
(
'New
f
ile'
)
expect
(
current_path
).
to
eq
(
expect
(
current_path
).
to
eq
(
namespace_project_new_blob_path
(
project
.
namespace
,
project
,
'master'
))
namespace_project_new_blob_path
(
project
.
namespace
,
project
,
'master'
))
expect
(
find
(
'#file_name'
).
value
).
to
eq
(
'LICENSE'
)
expect
(
find
(
'#file_name'
).
value
).
to
eq
(
'LICENSE'
)
...
@@ -63,7 +63,7 @@ feature 'project owner creates a license file', feature: true, js: true do
...
@@ -63,7 +63,7 @@ feature 'project owner creates a license file', feature: true, js: true do
def
select_template
(
template
)
def
select_template
(
template
)
page
.
within
(
'.js-license-selector-wrap'
)
do
page
.
within
(
'.js-license-selector-wrap'
)
do
click_button
'
Choose
a License template'
click_button
'
Apply
a License template'
click_link
template
click_link
template
wait_for_ajax
wait_for_ajax
end
end
...
...
spec/features/projects/files/project_owner_sees_link_to_create_license_file_in_empty_project_spec.rb
View file @
f564cbb2
...
@@ -14,7 +14,7 @@ feature 'project owner sees a link to create a license file in empty project', f
...
@@ -14,7 +14,7 @@ feature 'project owner sees a link to create a license file in empty project', f
visit
namespace_project_path
(
project
.
namespace
,
project
)
visit
namespace_project_path
(
project
.
namespace
,
project
)
click_link
'Create empty bare repository'
click_link
'Create empty bare repository'
click_on
'LICENSE'
click_on
'LICENSE'
expect
(
page
).
to
have_content
(
'New
F
ile'
)
expect
(
page
).
to
have_content
(
'New
f
ile'
)
expect
(
current_path
).
to
eq
(
expect
(
current_path
).
to
eq
(
namespace_project_new_blob_path
(
project
.
namespace
,
project
,
'master'
))
namespace_project_new_blob_path
(
project
.
namespace
,
project
,
'master'
))
...
@@ -40,7 +40,7 @@ feature 'project owner sees a link to create a license file in empty project', f
...
@@ -40,7 +40,7 @@ feature 'project owner sees a link to create a license file in empty project', f
def
select_template
(
template
)
def
select_template
(
template
)
page
.
within
(
'.js-license-selector-wrap'
)
do
page
.
within
(
'.js-license-selector-wrap'
)
do
click_button
'
Choose
a License template'
click_button
'
Apply
a License template'
click_link
template
click_link
template
wait_for_ajax
wait_for_ajax
end
end
...
...
spec/features/projects/files/template_type_dropdown_spec.rb
0 → 100644
View file @
f564cbb2
require
'spec_helper'
feature
'Template type dropdown selector'
,
js:
true
do
let
(
:project
)
{
create
(
:project
)
}
let
(
:user
)
{
create
(
:user
)
}
before
do
project
.
team
<<
[
user
,
:master
]
login_as
user
end
context
'editing a non-matching file'
do
before
do
create_and_edit_file
(
'.random-file.js'
)
end
scenario
'not displayed'
do
check_type_selector_display
(
false
)
end
scenario
'selects every template type correctly'
do
fill_in
'file_path'
,
with:
'.gitignore'
try_selecting_all_types
end
scenario
'updates toggle value when input matches'
do
fill_in
'file_path'
,
with:
'.gitignore'
check_type_selector_toggle_text
(
'.gitignore'
)
end
end
context
'editing a matching file'
do
before
do
visit
namespace_project_edit_blob_path
(
project
.
namespace
,
project
,
File
.
join
(
project
.
default_branch
,
'LICENSE'
))
end
scenario
'displayed'
do
check_type_selector_display
(
true
)
end
scenario
'is displayed when input matches'
do
check_type_selector_display
(
true
)
end
scenario
'selects every template type correctly'
do
try_selecting_all_types
end
context
'user previews changes'
do
before
do
click_link
'Preview Changes'
end
scenario
'type selector is hidden and shown correctly'
do
check_type_selector_display
(
false
)
click_link
'Write'
check_type_selector_display
(
true
)
end
end
end
context
'creating a matching file'
do
before
do
visit
namespace_project_new_blob_path
(
project
.
namespace
,
project
,
'master'
,
file_name:
'.gitignore'
)
end
scenario
'is displayed'
do
check_type_selector_display
(
true
)
end
scenario
'toggle is set to the correct value'
do
check_type_selector_toggle_text
(
'.gitignore'
)
end
scenario
'selects every template type correctly'
do
try_selecting_all_types
end
end
context
'creating a file'
do
before
do
visit
namespace_project_new_blob_path
(
project
.
namespace
,
project
,
project
.
default_branch
)
end
scenario
'type selector is shown'
do
check_type_selector_display
(
true
)
end
scenario
'toggle is set to the proper value'
do
check_type_selector_toggle_text
(
'Choose type'
)
end
scenario
'selects every template type correctly'
do
try_selecting_all_types
end
end
end
def
check_type_selector_display
(
is_visible
)
count
=
is_visible
?
1
:
0
expect
(
page
).
to
have_css
(
'.js-template-type-selector'
,
count:
count
)
end
def
try_selecting_all_types
try_selecting_template_type
(
'LICENSE'
,
'Apply a License template'
)
try_selecting_template_type
(
'Dockerfile'
,
'Apply a Dockerfile template'
)
try_selecting_template_type
(
'.gitlab-ci.yml'
,
'Apply a GitLab CI Yaml template'
)
try_selecting_template_type
(
'.gitignore'
,
'Apply a .gitignore template'
)
end
def
try_selecting_template_type
(
template_type
,
selector_label
)
select_template_type
(
template_type
)
check_template_selector_display
(
selector_label
)
check_type_selector_toggle_text
(
template_type
)
end
def
select_template_type
(
template_type
)
find
(
'.js-template-type-selector'
).
click
find
(
'.dropdown-content li'
,
text:
template_type
).
click
end
def
check_template_selector_display
(
content
)
expect
(
page
).
to
have_content
(
content
)
end
def
check_type_selector_toggle_text
(
template_type
)
dropdown_toggle_button
=
find
(
'.template-type-selector .dropdown-toggle-text'
)
expect
(
dropdown_toggle_button
).
to
have_content
(
template_type
)
end
def
create_and_edit_file
(
file_name
)
visit
namespace_project_new_blob_path
(
project
.
namespace
,
project
,
'master'
,
file_name:
file_name
)
click_button
"Commit Changes"
visit
namespace_project_edit_blob_path
(
project
.
namespace
,
project
,
File
.
join
(
project
.
default_branch
,
file_name
))
end
spec/features/projects/files/undo_template_spec.rb
0 → 100644
View file @
f564cbb2
require
'spec_helper'
include
WaitForAjax
feature
'Template Undo Button'
,
js:
true
do
let
(
:project
)
{
create
(
:project
)
}
let
(
:user
)
{
create
(
:user
)
}
before
do
project
.
team
<<
[
user
,
:master
]
login_as
user
end
context
'editing a matching file and applying a template'
do
before
do
visit
namespace_project_edit_blob_path
(
project
.
namespace
,
project
,
File
.
join
(
project
.
default_branch
,
"LICENSE"
))
select_file_template
(
'.js-license-selector'
,
'Apache License 2.0'
)
end
scenario
'reverts template application'
do
try_template_undo
(
'http://www.apache.org/licenses/'
,
'Apply a License template'
)
end
end
context
'creating a non-matching file'
do
before
do
visit
namespace_project_new_blob_path
(
project
.
namespace
,
project
,
'master'
)
select_file_template_type
(
'LICENSE'
)
select_file_template
(
'.js-license-selector'
,
'Apache License 2.0'
)
end
scenario
'reverts template application'
do
try_template_undo
(
'http://www.apache.org/licenses/'
,
'Apply a License template'
)
end
end
end
def
try_template_undo
(
template_content
,
toggle_text
)
check_undo_button_display
check_content_reverted
(
template_content
)
check_toggle_text_set
(
toggle_text
)
end
def
check_toggle_text_set
(
neutral_toggle_text
)
expect
(
page
).
to
have_content
(
neutral_toggle_text
)
end
def
check_undo_button_display
expect
(
page
).
to
have_content
(
'Template applied'
)
expect
(
page
).
to
have_css
(
'.template-selectors-undo-menu .btn-info'
)
end
def
check_content_reverted
(
template_content
)
find
(
'.template-selectors-undo-menu .btn-info'
).
click
expect
(
page
).
not_to
have_content
(
template_content
)
expect
(
find
(
'.template-type-selector .dropdown-toggle-text'
)).
to
have_content
()
end
def
select_file_template
(
template_selector_selector
,
template_name
)
find
(
template_selector_selector
).
click
find
(
'.dropdown-content li'
,
text:
template_name
).
click
wait_for_ajax
end
def
select_file_template_type
(
template_type
)
find
(
'.js-template-type-selector'
).
click
find
(
'.dropdown-content li'
,
text:
template_type
).
click
end
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