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
Jérome Perrin
gitlab-ce
Commits
faf7865c
Commit
faf7865c
authored
Mar 07, 2017
by
Bryce Johnson
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Lightly refactor js files related to file template selectors.
parent
1af9dfb8
Changes
28
Hide whitespace changes
Inline
Side-by-side
Showing
28 changed files
with
425 additions
and
475 deletions
+425
-475
app/assets/javascripts/blob/blob_ci_yaml.js
app/assets/javascripts/blob/blob_ci_yaml.js
+0
-42
app/assets/javascripts/blob/blob_dockerfile_selector.js
app/assets/javascripts/blob/blob_dockerfile_selector.js
+0
-19
app/assets/javascripts/blob/blob_dockerfile_selectors.js
app/assets/javascripts/blob/blob_dockerfile_selectors.js
+0
-27
app/assets/javascripts/blob/blob_file_dropzone.js
app/assets/javascripts/blob/blob_file_dropzone.js
+59
-62
app/assets/javascripts/blob/blob_gitignore_selector.js
app/assets/javascripts/blob/blob_gitignore_selector.js
+0
-23
app/assets/javascripts/blob/blob_gitignore_selectors.js
app/assets/javascripts/blob/blob_gitignore_selectors.js
+0
-26
app/assets/javascripts/blob/blob_license_selector.js
app/assets/javascripts/blob/blob_license_selector.js
+0
-28
app/assets/javascripts/blob/blob_license_selectors.js
app/assets/javascripts/blob/blob_license_selectors.js
+0
-23
app/assets/javascripts/blob/template_selector.js
app/assets/javascripts/blob/template_selector.js
+0
-101
app/assets/javascripts/blob/template_selectors/blob_ci_yaml_selector.js
...ascripts/blob/template_selectors/blob_ci_yaml_selector.js
+9
-0
app/assets/javascripts/blob/template_selectors/blob_ci_yaml_selectors.js
...scripts/blob/template_selectors/blob_ci_yaml_selectors.js
+23
-0
app/assets/javascripts/blob/template_selectors/blob_dockerfile_selector.js
...ripts/blob/template_selectors/blob_dockerfile_selector.js
+9
-0
app/assets/javascripts/blob/template_selectors/blob_dockerfile_selectors.js
...ipts/blob/template_selectors/blob_dockerfile_selectors.js
+23
-0
app/assets/javascripts/blob/template_selectors/blob_gitignore_selector.js
...cripts/blob/template_selectors/blob_gitignore_selector.js
+9
-0
app/assets/javascripts/blob/template_selectors/blob_gitignore_selectors.js
...ripts/blob/template_selectors/blob_gitignore_selectors.js
+23
-0
app/assets/javascripts/blob/template_selectors/blob_license_selector.js
...ascripts/blob/template_selectors/blob_license_selector.js
+13
-0
app/assets/javascripts/blob/template_selectors/blob_license_selectors.js
...scripts/blob/template_selectors/blob_license_selectors.js
+24
-0
app/assets/javascripts/blob/template_selectors/template_selector.js
.../javascripts/blob/template_selectors/template_selector.js
+92
-0
app/assets/javascripts/blob_edit/blob_bundle.js
app/assets/javascripts/blob_edit/blob_bundle.js
+32
-0
app/assets/javascripts/blob_edit/blob_edit_bundle.js
app/assets/javascripts/blob_edit/blob_edit_bundle.js
+0
-15
app/assets/javascripts/blob_edit/edit_blob.js
app/assets/javascripts/blob_edit/edit_blob.js
+94
-83
app/assets/javascripts/main.js
app/assets/javascripts/main.js
+0
-9
app/assets/javascripts/templates/issuable_template_selector.js
...ssets/javascripts/templates/issuable_template_selector.js
+7
-7
app/views/projects/blob/_upload.html.haml
app/views/projects/blob/_upload.html.haml
+3
-6
app/views/projects/blob/edit.html.haml
app/views/projects/blob/edit.html.haml
+1
-1
app/views/projects/blob/new.html.haml
app/views/projects/blob/new.html.haml
+1
-1
config/webpack.config.js
config/webpack.config.js
+1
-1
spec/javascripts/test_bundle.js
spec/javascripts/test_bundle.js
+2
-1
No files found.
app/assets/javascripts/blob/blob_ci_yaml.js
deleted
100644 → 0
View file @
1af9dfb8
/* eslint-disable no-param-reassign, comma-dangle */
/* global Api */
require
(
'
./template_selector
'
);
((
global
)
=>
{
class
BlobCiYamlSelector
extends
gl
.
TemplateSelector
{
requestFile
(
query
)
{
return
Api
.
gitlabCiYml
(
query
.
name
,
this
.
requestFileSuccess
.
bind
(
this
));
}
requestFileSuccess
(
file
)
{
return
super
.
requestFileSuccess
(
file
);
}
}
global
.
BlobCiYamlSelector
=
BlobCiYamlSelector
;
class
BlobCiYamlSelectors
{
constructor
({
editor
,
$dropdowns
}
=
{})
{
this
.
editor
=
editor
;
this
.
$dropdowns
=
$dropdowns
||
$
(
'
.js-gitlab-ci-yml-selector
'
);
this
.
initSelectors
();
}
initSelectors
()
{
const
editor
=
this
.
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
});
});
}
}
global
.
BlobCiYamlSelectors
=
BlobCiYamlSelectors
;
})(
window
.
gl
||
(
window
.
gl
=
{}));
app/assets/javascripts/blob/blob_dockerfile_selector.js
deleted
100644 → 0
View file @
1af9dfb8
/* global Api */
require
(
'
./template_selector
'
);
(()
=>
{
const
global
=
window
.
gl
||
(
window
.
gl
=
{});
class
BlobDockerfileSelector
extends
gl
.
TemplateSelector
{
requestFile
(
query
)
{
return
Api
.
dockerfileYml
(
query
.
name
,
this
.
requestFileSuccess
.
bind
(
this
));
}
requestFileSuccess
(
file
)
{
return
super
.
requestFileSuccess
(
file
);
}
}
global
.
BlobDockerfileSelector
=
BlobDockerfileSelector
;
})();
app/assets/javascripts/blob/blob_dockerfile_selectors.js
deleted
100644 → 0
View file @
1af9dfb8
(()
=>
{
const
global
=
window
.
gl
||
(
window
.
gl
=
{});
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
gl
.
BlobDockerfileSelector
({
editor
,
pattern
:
/
(
Dockerfile
)
/
,
data
:
$dropdown
.
data
(
'
data
'
),
wrapper
:
$dropdown
.
closest
(
'
.js-dockerfile-selector-wrap
'
),
dropdown
:
$dropdown
,
});
});
}
}
global
.
BlobDockerfileSelectors
=
BlobDockerfileSelectors
;
})();
app/assets/javascripts/blob/blob_file_dropzone.js
View file @
faf7865c
/* eslint-disable func-names,
space-before-function-paren, wrap-iife, one-var, no-var, one-var-declaration-per-line, camelcase, object-shorthand, quotes, comma-dangle, prefer-arrow-callback, no-unused-vars, prefer-template, no-useless-escape, no-alert, max-len
*/
/* eslint-disable func-names,
object-shorthand, prefer-arrow-callback
*/
/* global Dropzone */
(
function
()
{
this
.
BlobFileDropzone
=
(
function
()
{
function
BlobFileDropzone
(
form
,
method
)
{
var
dropzone
,
form_dropzone
,
submitButton
;
form_dropzone
=
form
.
find
(
'
.dropzone
'
);
Dropzone
.
autoDiscover
=
false
;
dropzone
=
form_dropzone
.
dropzone
({
autoDiscover
:
false
,
autoProcessQueue
:
false
,
url
:
form
.
attr
(
'
action
'
),
// Rails uses a hidden input field for PUT
// http://stackoverflow.com/questions/21056482/how-to-set-method-put-in-form-tag-in-rails
method
:
method
,
clickable
:
true
,
uploadMultiple
:
false
,
paramName
:
"
file
"
,
maxFilesize
:
gon
.
max_file_size
||
10
,
parallelUploads
:
1
,
maxFiles
:
1
,
addRemoveLinks
:
true
,
previewsContainer
:
'
.dropzone-previews
'
,
headers
:
{
"
X-CSRF-Token
"
:
$
(
"
meta[name=
\"
csrf-token
\"
]
"
).
attr
(
"
content
"
)
},
init
:
function
()
{
this
.
on
(
'
addedfile
'
,
function
(
file
)
{
$
(
'
.dropzone-alerts
'
).
html
(
''
).
hide
();
});
this
.
on
(
'
success
'
,
function
(
header
,
response
)
{
window
.
location
.
href
=
response
.
filePath
;
});
this
.
on
(
'
maxfilesexceeded
'
,
function
(
file
)
{
this
.
removeFile
(
file
);
});
return
this
.
on
(
'
sending
'
,
function
(
file
,
xhr
,
formData
)
{
formData
.
append
(
'
target_branch
'
,
form
.
find
(
'
input[name="target_branch"]
'
).
val
());
formData
.
append
(
'
create_merge_request
'
,
form
.
find
(
'
.js-create-merge-request
'
).
val
());
formData
.
append
(
'
commit_message
'
,
form
.
find
(
'
.js-commit-message
'
).
val
());
});
},
// Override behavior of adding error underneath preview
error
:
function
(
file
,
errorMessage
)
{
var
stripped
;
stripped
=
$
(
"
<div/>
"
).
html
(
errorMessage
).
text
();
$
(
'
.dropzone-alerts
'
).
html
(
'
Error uploading file:
\
"
'
+
stripped
+
'
\
"
'
).
show
();
export
default
class
BlobFileDropzone
{
constructor
(
form
,
method
)
{
const
formDropzone
=
form
.
find
(
'
.dropzone
'
);
Dropzone
.
autoDiscover
=
false
;
const
dropzone
=
formDropzone
.
dropzone
({
autoDiscover
:
false
,
autoProcessQueue
:
false
,
url
:
form
.
attr
(
'
action
'
),
// Rails uses a hidden input field for PUT
// http://stackoverflow.com/questions/21056482/how-to-set-method-put-in-form-tag-in-rails
method
:
method
,
clickable
:
true
,
uploadMultiple
:
false
,
paramName
:
'
file
'
,
maxFilesize
:
gon
.
max_file_size
||
10
,
parallelUploads
:
1
,
maxFiles
:
1
,
addRemoveLinks
:
true
,
previewsContainer
:
'
.dropzone-previews
'
,
headers
:
{
'
X-CSRF-Token
'
:
$
(
'
meta[name="csrf-token"]
'
).
attr
(
'
content
'
),
},
init
:
function
()
{
this
.
on
(
'
addedfile
'
,
function
()
{
$
(
'
.dropzone-alerts
'
).
html
(
''
).
hide
();
});
this
.
on
(
'
success
'
,
function
(
header
,
response
)
{
window
.
location
.
href
=
response
.
filePath
;
});
this
.
on
(
'
maxfilesexceeded
'
,
function
(
file
)
{
this
.
removeFile
(
file
);
}
});
submitButton
=
form
.
find
(
'
#submit-all
'
)[
0
];
submitButton
.
addEventListener
(
'
click
'
,
function
(
e
)
{
e
.
preventDefault
();
e
.
stopPropagation
();
if
(
dropzone
[
0
].
dropzone
.
getQueuedFiles
().
length
===
0
)
{
alert
(
"
Please select a file
"
);
}
dropzone
[
0
].
dropzone
.
processQueue
();
return
false
;
});
}
});
this
.
on
(
'
sending
'
,
function
(
file
,
xhr
,
formData
)
{
formData
.
append
(
'
target_branch
'
,
form
.
find
(
'
input[name="target_branch"]
'
).
val
());
formData
.
append
(
'
create_merge_request
'
,
form
.
find
(
'
.js-create-merge-request
'
).
val
());
formData
.
append
(
'
commit_message
'
,
form
.
find
(
'
.js-commit-message
'
).
val
());
});
},
// Override behavior of adding error underneath preview
error
:
function
(
file
,
errorMessage
)
{
const
stripped
=
$
(
'
<div/>
'
).
html
(
errorMessage
).
text
();
$
(
'
.dropzone-alerts
'
).
html
(
`Error uploading file: "
${
stripped
}
"`
).
show
();
this
.
removeFile
(
file
);
},
});
return
BlobFileDropzone
;
})();
}).
call
(
window
);
const
submitButton
=
form
.
find
(
'
#submit-all
'
)[
0
];
submitButton
.
addEventListener
(
'
click
'
,
function
(
e
)
{
e
.
preventDefault
();
e
.
stopPropagation
();
if
(
dropzone
[
0
].
dropzone
.
getQueuedFiles
().
length
===
0
)
{
// eslint-disable-next-line no-alert
alert
(
'
Please select a file
'
);
}
dropzone
[
0
].
dropzone
.
processQueue
();
return
false
;
});
}
}
app/assets/javascripts/blob/blob_gitignore_selector.js
deleted
100644 → 0
View file @
1af9dfb8
/* eslint-disable func-names, space-before-function-paren, max-len, one-var, no-var, no-restricted-syntax, vars-on-top, no-use-before-define, no-param-reassign, new-cap, no-underscore-dangle, wrap-iife, prefer-rest-params */
/* global Api */
require
(
'
./template_selector
'
);
(
function
()
{
var
extend
=
function
(
child
,
parent
)
{
for
(
var
key
in
parent
)
{
if
(
hasProp
.
call
(
parent
,
key
))
child
[
key
]
=
parent
[
key
];
}
function
ctor
()
{
this
.
constructor
=
child
;
}
ctor
.
prototype
=
parent
.
prototype
;
child
.
prototype
=
new
ctor
();
child
.
__super__
=
parent
.
prototype
;
return
child
;
},
hasProp
=
{}.
hasOwnProperty
;
this
.
BlobGitignoreSelector
=
(
function
(
superClass
)
{
extend
(
BlobGitignoreSelector
,
superClass
);
function
BlobGitignoreSelector
()
{
return
BlobGitignoreSelector
.
__super__
.
constructor
.
apply
(
this
,
arguments
);
}
BlobGitignoreSelector
.
prototype
.
requestFile
=
function
(
query
)
{
return
Api
.
gitignoreText
(
query
.
name
,
this
.
requestFileSuccess
.
bind
(
this
));
};
return
BlobGitignoreSelector
;
})(
gl
.
TemplateSelector
);
}).
call
(
window
);
app/assets/javascripts/blob/blob_gitignore_selectors.js
deleted
100644 → 0
View file @
1af9dfb8
/* eslint-disable func-names, space-before-function-paren, wrap-iife, no-var, no-unused-expressions, no-cond-assign, no-sequences, comma-dangle, max-len */
/* global BlobGitignoreSelector */
(
function
()
{
this
.
BlobGitignoreSelectors
=
(
function
()
{
function
BlobGitignoreSelectors
(
opts
)
{
var
ref
;
this
.
$dropdowns
=
(
ref
=
opts
.
$dropdowns
)
!=
null
?
ref
:
$
(
'
.js-gitignore-selector
'
),
this
.
editor
=
opts
.
editor
;
this
.
$dropdowns
.
each
((
function
(
_this
)
{
return
function
(
i
,
dropdown
)
{
var
$dropdown
;
$dropdown
=
$
(
dropdown
);
return
new
BlobGitignoreSelector
({
pattern
:
/
(
.gitignore
)
/
,
data
:
$dropdown
.
data
(
'
data
'
),
wrapper
:
$dropdown
.
closest
(
'
.js-gitignore-selector-wrap
'
),
dropdown
:
$dropdown
,
editor
:
_this
.
editor
});
};
})(
this
));
}
return
BlobGitignoreSelectors
;
})();
}).
call
(
window
);
app/assets/javascripts/blob/blob_license_selector.js
deleted
100644 → 0
View file @
1af9dfb8
/* eslint-disable func-names, space-before-function-paren, max-len, one-var, no-var, no-restricted-syntax, vars-on-top, no-use-before-define, no-param-reassign, new-cap, no-underscore-dangle, wrap-iife, prefer-rest-params, comma-dangle */
/* global Api */
require
(
'
./template_selector
'
);
(
function
()
{
var
extend
=
function
(
child
,
parent
)
{
for
(
var
key
in
parent
)
{
if
(
hasProp
.
call
(
parent
,
key
))
child
[
key
]
=
parent
[
key
];
}
function
ctor
()
{
this
.
constructor
=
child
;
}
ctor
.
prototype
=
parent
.
prototype
;
child
.
prototype
=
new
ctor
();
child
.
__super__
=
parent
.
prototype
;
return
child
;
},
hasProp
=
{}.
hasOwnProperty
;
this
.
BlobLicenseSelector
=
(
function
(
superClass
)
{
extend
(
BlobLicenseSelector
,
superClass
);
function
BlobLicenseSelector
()
{
return
BlobLicenseSelector
.
__super__
.
constructor
.
apply
(
this
,
arguments
);
}
BlobLicenseSelector
.
prototype
.
requestFile
=
function
(
query
)
{
var
data
;
data
=
{
project
:
this
.
dropdown
.
data
(
'
project
'
),
fullname
:
this
.
dropdown
.
data
(
'
fullname
'
)
};
return
Api
.
licenseText
(
query
.
id
,
data
,
this
.
requestFileSuccess
.
bind
(
this
));
};
return
BlobLicenseSelector
;
})(
gl
.
TemplateSelector
);
}).
call
(
window
);
app/assets/javascripts/blob/blob_license_selectors.js
deleted
100644 → 0
View file @
1af9dfb8
/* eslint-disable no-unused-vars, no-param-reassign */
/* global BlobLicenseSelector */
((
global
)
=>
{
class
BlobLicenseSelectors
{
constructor
({
$dropdowns
,
editor
})
{
this
.
$dropdowns
=
$
(
'
.js-license-selector
'
);
this
.
editor
=
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
,
});
});
}
}
global
.
BlobLicenseSelectors
=
BlobLicenseSelectors
;
})(
window
.
gl
||
(
window
.
gl
=
{}));
app/assets/javascripts/blob/template_selector.js
deleted
100644 → 0
View file @
1af9dfb8
/* eslint-disable comma-dangle, object-shorthand, func-names, space-before-function-paren, arrow-parens, no-unused-vars, class-methods-use-this, no-var, consistent-return, no-param-reassign, max-len */
((
global
)
=>
{
class
TemplateSelector
{
constructor
({
dropdown
,
data
,
pattern
,
wrapper
,
editor
,
fileEndpoint
,
$input
}
=
{})
{
this
.
onClick
=
this
.
onClick
.
bind
(
this
);
this
.
dropdown
=
dropdown
;
this
.
data
=
data
;
this
.
pattern
=
pattern
;
this
.
wrapper
=
wrapper
;
this
.
editor
=
editor
;
this
.
fileEndpoint
=
fileEndpoint
;
this
.
$input
=
$input
||
$
(
'
#file_name
'
);
this
.
dropdownIcon
=
$
(
'
.fa-chevron-down
'
,
this
.
dropdown
);
this
.
buildDropdown
();
this
.
bindEvents
();
this
.
onFilenameUpdate
();
this
.
autosizeUpdateEvent
=
document
.
createEvent
(
'
Event
'
);
this
.
autosizeUpdateEvent
.
initEvent
(
'
autosize:update
'
,
true
,
false
);
}
buildDropdown
()
{
return
this
.
dropdown
.
glDropdown
({
data
:
this
.
data
,
filterable
:
true
,
selectable
:
true
,
toggleLabel
:
this
.
toggleLabel
,
search
:
{
fields
:
[
'
name
'
]
},
clicked
:
this
.
onClick
,
text
:
function
(
item
)
{
return
item
.
name
;
}
});
}
bindEvents
()
{
return
this
.
$input
.
on
(
'
keyup blur
'
,
(
e
)
=>
this
.
onFilenameUpdate
());
}
toggleLabel
(
item
)
{
return
item
.
name
;
}
onFilenameUpdate
()
{
var
filenameMatches
;
if
(
!
this
.
$input
.
length
)
{
return
;
}
filenameMatches
=
this
.
pattern
.
test
(
this
.
$input
.
val
().
trim
());
if
(
!
filenameMatches
)
{
this
.
wrapper
.
addClass
(
'
hidden
'
);
return
;
}
return
this
.
wrapper
.
removeClass
(
'
hidden
'
);
}
onClick
(
item
,
el
,
e
)
{
e
.
preventDefault
();
return
this
.
requestFile
(
item
);
}
requestFile
(
item
)
{
// This `requestFile` method is an abstract method that should
// be added by all subclasses.
}
// To be implemented on the extending class
// e.g.
// Api.gitignoreText item.name, @requestFileSuccess.bind(@)
requestFileSuccess
(
file
,
{
skipFocus
}
=
{})
{
if
(
!
file
)
return
;
const
oldValue
=
this
.
editor
.
getValue
();
const
newValue
=
file
.
content
;
this
.
editor
.
setValue
(
newValue
,
1
);
if
(
!
skipFocus
)
this
.
editor
.
focus
();
if
(
this
.
editor
instanceof
jQuery
)
{
this
.
editor
.
get
(
0
).
dispatchEvent
(
this
.
autosizeUpdateEvent
);
}
}
startLoadingSpinner
()
{
this
.
dropdownIcon
.
addClass
(
'
fa-spinner fa-spin
'
)
.
removeClass
(
'
fa-chevron-down
'
);
}
stopLoadingSpinner
()
{
this
.
dropdownIcon
.
addClass
(
'
fa-chevron-down
'
)
.
removeClass
(
'
fa-spinner fa-spin
'
);
}
}
global
.
TemplateSelector
=
TemplateSelector
;
})(
window
.
gl
||
(
window
.
gl
=
{}));
app/assets/javascripts/blob/template_selectors/blob_ci_yaml_selector.js
0 → 100644
View file @
faf7865c
/* 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
0 → 100644
View file @
faf7865c
/* 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
0 → 100644
View file @
faf7865c
/* 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
0 → 100644
View file @
faf7865c
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
0 → 100644
View file @
faf7865c
/* 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
0 → 100644
View file @
faf7865c
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
0 → 100644
View file @
faf7865c
/* 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
0 → 100644
View file @
faf7865c
/* 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/template_selector.js
0 → 100644
View file @
faf7865c
/* eslint-disable class-methods-use-this, no-unused-vars */
export
default
class
TemplateSelector
{
constructor
({
dropdown
,
data
,
pattern
,
wrapper
,
editor
,
$input
}
=
{})
{
this
.
pattern
=
pattern
;
this
.
editor
=
editor
;
this
.
dropdown
=
dropdown
;
this
.
$dropdownContainer
=
wrapper
;
this
.
$filenameInput
=
$input
||
$
(
'
#file_name
'
);
this
.
$dropdownIcon
=
$
(
'
.fa-chevron-down
'
,
dropdown
);
this
.
initDropdown
(
dropdown
,
data
);
this
.
listenForFilenameInput
();
this
.
renderMatchedDropdown
();
this
.
initAutosizeUpdateEvent
();
}
initDropdown
(
dropdown
,
data
)
{
return
$
(
dropdown
).
glDropdown
({
data
,
filterable
:
true
,
selectable
:
true
,
toggleLabel
:
item
=>
item
.
name
,
search
:
{
fields
:
[
'
name
'
],
},
clicked
:
(
item
,
el
,
e
)
=>
this
.
fetchFileTemplate
(
item
,
el
,
e
),
text
:
item
=>
item
.
name
,
});
}
initAutosizeUpdateEvent
()
{
this
.
autosizeUpdateEvent
=
document
.
createEvent
(
'
Event
'
);
this
.
autosizeUpdateEvent
.
initEvent
(
'
autosize:update
'
,
true
,
false
);
}
listenForFilenameInput
()
{
return
this
.
$filenameInput
.
on
(
'
keyup blur
'
,
e
=>
this
.
renderMatchedDropdown
(
e
));
}
renderMatchedDropdown
()
{
if
(
!
this
.
$filenameInput
.
length
)
{
return
null
;
}
const
filenameMatches
=
this
.
pattern
.
test
(
this
.
$filenameInput
.
val
().
trim
());
if
(
!
filenameMatches
)
{
return
this
.
$dropdownContainer
.
addClass
(
'
hidden
'
);
}
return
this
.
$dropdownContainer
.
removeClass
(
'
hidden
'
);
}
fetchFileTemplate
(
item
,
el
,
e
)
{
e
.
preventDefault
();
return
this
.
requestFile
(
item
);
}
requestFile
(
item
)
{
// This `requestFile` method is an abstract method that should
// be added by all subclasses.
}
// To be implemented on the extending class
// e.g. Api.gitlabCiYml(query.name, file => this.setEditorContent(file));
setEditorContent
(
file
,
{
skipFocus
}
=
{})
{
if
(
!
file
)
return
;
const
newValue
=
file
.
content
;
this
.
editor
.
setValue
(
newValue
,
1
);
if
(
!
skipFocus
)
this
.
editor
.
focus
();
if
(
this
.
editor
instanceof
jQuery
)
{
this
.
editor
.
get
(
0
).
dispatchEvent
(
this
.
autosizeUpdateEvent
);
}
}
startLoadingSpinner
()
{
this
.
$dropdownIcon
.
addClass
(
'
fa-spinner fa-spin
'
)
.
removeClass
(
'
fa-chevron-down
'
);
}
stopLoadingSpinner
()
{
this
.
$dropdownIcon
.
addClass
(
'
fa-chevron-down
'
)
.
removeClass
(
'
fa-spinner fa-spin
'
);
}
}
app/assets/javascripts/blob_edit/blob_bundle.js
0 → 100644
View file @
faf7865c
/* eslint-disable func-names, space-before-function-paren, prefer-arrow-callback, no-var, quotes, vars-on-top, no-unused-vars, no-new, max-len */
/* global EditBlob */
/* global NewCommitForm */
import
EditBlob
from
'
./edit_blob
'
;
import
BlobFileDropzone
from
'
../blob/blob_file_dropzone
'
;
$
(()
=>
{
const
editBlobForm
=
$
(
'
.js-edit-blob-form
'
);
const
uploadBlobForm
=
$
(
'
.js-upload-blob-form
'
);
if
(
editBlobForm
.
length
)
{
const
urlRoot
=
editBlobForm
.
data
(
'
relative-url-root
'
);
const
assetsPath
=
editBlobForm
.
data
(
'
assets-prefix
'
);
const
blobLanguage
=
editBlobForm
.
data
(
'
blob-language
'
);
new
EditBlob
(
`
${
urlRoot
}${
assetsPath
}
`
,
blobLanguage
);
new
NewCommitForm
(
editBlobForm
);
}
if
(
uploadBlobForm
.
length
)
{
const
method
=
uploadBlobForm
.
data
(
'
method
'
);
new
BlobFileDropzone
(
uploadBlobForm
,
method
);
new
NewCommitForm
(
uploadBlobForm
);
window
.
gl
.
utils
.
disableButtonIfEmptyField
(
uploadBlobForm
.
find
(
'
.js-commit-message
'
),
'
.btn-upload-file
'
,
);
}
});
app/assets/javascripts/blob_edit/blob_edit_bundle.js
deleted
100644 → 0
View file @
1af9dfb8
/* eslint-disable func-names, space-before-function-paren, prefer-arrow-callback, no-var, quotes, vars-on-top, no-unused-vars, no-new, max-len */
/* global EditBlob */
/* global NewCommitForm */
require
(
'
./edit_blob
'
);
(
function
()
{
$
(
function
()
{
var
url
=
$
(
"
.js-edit-blob-form
"
).
data
(
"
relative-url-root
"
);
url
+=
$
(
"
.js-edit-blob-form
"
).
data
(
"
assets-prefix
"
);
var
blob
=
new
EditBlob
(
url
,
$
(
'
.js-edit-blob-form
'
).
data
(
'
blob-language
'
));
new
NewCommitForm
(
$
(
'
.js-edit-blob-form
'
));
});
}).
call
(
window
);
app/assets/javascripts/blob_edit/edit_blob.js
View file @
faf7865c
/* eslint-disable func-names, space-before-function-paren, no-var, prefer-rest-params, wrap-iife, camelcase, no-param-reassign, quotes, prefer-template, no-new, comma-dangle, one-var, one-var-declaration-per-line, prefer-arrow-callback, no-else-return, no-unused-vars, max-len */
/* global ace */
/* global BlobGitignoreSelectors */
(
function
()
{
var
bind
=
function
(
fn
,
me
)
{
return
function
()
{
return
fn
.
apply
(
me
,
arguments
);
};
};
this
.
EditBlob
=
(
function
()
{
function
EditBlob
(
assets_path
,
ace_mode
)
{
if
(
ace_mode
==
null
)
{
ace_mode
=
null
;
}
this
.
editModeLinkClickHandler
=
bind
(
this
.
editModeLinkClickHandler
,
this
);
ace
.
config
.
set
(
"
modePath
"
,
assets_path
+
"
/ace
"
);
ace
.
config
.
loadModule
(
"
ace/ext/searchbox
"
);
this
.
editor
=
ace
.
edit
(
"
editor
"
);
this
.
editor
.
focus
();
if
(
ace_mode
)
{
this
.
editor
.
getSession
().
setMode
(
"
ace/mode/
"
+
ace_mode
);
}
$
(
'
form
'
).
submit
((
function
(
_this
)
{
return
function
()
{
return
$
(
"
#file-content
"
).
val
(
_this
.
editor
.
getValue
());
};
// Before a form submission, move the content from the Ace editor into the
// submitted textarea
})(
this
));
this
.
initModePanesAndLinks
();
this
.
initSoftWrap
();
new
gl
.
BlobLicenseSelectors
({
editor
:
this
.
editor
});
import
BlobLicenseSelectors
from
'
../blob/template_selectors/blob_license_selectors
'
;
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
{
constructor
(
assetsPath
,
aceMode
)
{
this
.
configureAceEditor
(
aceMode
,
assetsPath
);
this
.
prepFileContentForSubmit
();
this
.
initModePanesAndLinks
();
this
.
initSoftWrap
();
this
.
initFileSelectors
();
}
configureAceEditor
(
aceMode
,
assetsPath
)
{
ace
.
config
.
set
(
'
modePath
'
,
`
${
assetsPath
}
/ace`
);
ace
.
config
.
loadModule
(
'
ace/ext/searchbox
'
);
this
.
editor
=
ace
.
edit
(
'
editor
'
);
this
.
editor
.
focus
();
if
(
aceMode
)
{
this
.
editor
.
getSession
().
setMode
(
`ace/mode/
${
aceMode
}
`
);
}
}
prepFileContentForSubmit
()
{
$
(
'
form
'
).
submit
(()
=>
{
$
(
'
#file-content
'
).
val
(
this
.
editor
.
getValue
());
});
}
initFileSelectors
()
{
this
.
blobTemplateSelectors
=
[
new
BlobLicenseSelectors
({
editor
:
this
.
editor
,
}),
new
BlobGitignoreSelectors
({
editor
:
this
.
editor
});
new
gl
.
BlobCiYamlSelectors
({
editor
:
this
.
editor
});
new
gl
.
BlobDockerfileSelectors
({
editor
:
this
.
editor
editor
:
this
.
editor
,
}),
new
BlobCiYamlSelectors
({
editor
:
this
.
editor
,
}),
new
BlobDockerfileSelectors
({
editor
:
this
.
editor
,
}),
];
}
initModePanesAndLinks
()
{
this
.
$editModePanes
=
$
(
'
.js-edit-mode-pane
'
);
this
.
$editModeLinks
=
$
(
'
.js-edit-mode a
'
);
this
.
$editModeLinks
.
on
(
'
click
'
,
e
=>
this
.
editModeLinkClickHandler
(
e
));
}
editModeLinkClickHandler
(
e
)
{
e
.
preventDefault
();
const
currentLink
=
$
(
e
.
target
);
const
paneId
=
currentLink
.
attr
(
'
href
'
);
const
currentPane
=
this
.
$editModePanes
.
filter
(
paneId
);
this
.
$editModeLinks
.
parent
().
removeClass
(
'
active hover
'
);
currentLink
.
parent
().
addClass
(
'
active hover
'
);
this
.
$editModePanes
.
hide
();
currentPane
.
fadeIn
(
200
);
if
(
paneId
===
'
#preview
'
)
{
this
.
$toggleButton
.
hide
();
return
$
.
post
(
currentLink
.
data
(
'
preview-url
'
),
{
content
:
this
.
editor
.
getValue
(),
},
(
response
)
=>
{
currentPane
.
empty
().
append
(
response
);
return
currentPane
.
renderGFM
();
});
}
EditBlob
.
prototype
.
initModePanesAndLinks
=
function
()
{
this
.
$editModePanes
=
$
(
"
.js-edit-mode-pane
"
);
this
.
$editModeLinks
=
$
(
"
.js-edit-mode a
"
);
return
this
.
$editModeLinks
.
click
(
this
.
editModeLinkClickHandler
);
};
EditBlob
.
prototype
.
editModeLinkClickHandler
=
function
(
event
)
{
var
currentLink
,
currentPane
,
paneId
;
event
.
preventDefault
();
currentLink
=
$
(
event
.
target
);
paneId
=
currentLink
.
attr
(
"
href
"
);
currentPane
=
this
.
$editModePanes
.
filter
(
paneId
);
this
.
$editModeLinks
.
parent
().
removeClass
(
"
active hover
"
);
currentLink
.
parent
().
addClass
(
"
active hover
"
);
this
.
$editModePanes
.
hide
();
currentPane
.
fadeIn
(
200
);
if
(
paneId
===
"
#preview
"
)
{
this
.
$toggleButton
.
hide
();
return
$
.
post
(
currentLink
.
data
(
"
preview-url
"
),
{
content
:
this
.
editor
.
getValue
()
},
function
(
response
)
{
currentPane
.
empty
().
append
(
response
);
return
currentPane
.
renderGFM
();
});
}
else
{
this
.
$toggleButton
.
show
();
return
this
.
editor
.
focus
();
}
};
EditBlob
.
prototype
.
initSoftWrap
=
function
()
{
this
.
isSoftWrapped
=
false
;
this
.
$toggleButton
=
$
(
'
.soft-wrap-toggle
'
);
this
.
$toggleButton
.
on
(
'
click
'
,
this
.
toggleSoftWrap
.
bind
(
this
));
};
EditBlob
.
prototype
.
toggleSoftWrap
=
function
(
e
)
{
this
.
isSoftWrapped
=
!
this
.
isSoftWrapped
;
this
.
$toggleButton
.
toggleClass
(
'
soft-wrap-active
'
,
this
.
isSoftWrapped
);
this
.
editor
.
getSession
().
setUseWrapMode
(
this
.
isSoftWrapped
);
};
return
EditBlob
;
})();
}).
call
(
window
);
this
.
$toggleButton
.
show
();
return
this
.
editor
.
focus
();
}
initSoftWrap
()
{
this
.
isSoftWrapped
=
false
;
this
.
$toggleButton
=
$
(
'
.soft-wrap-toggle
'
);
this
.
$toggleButton
.
on
(
'
click
'
,
()
=>
this
.
toggleSoftWrap
());
}
toggleSoftWrap
()
{
this
.
isSoftWrapped
=
!
this
.
isSoftWrapped
;
this
.
$toggleButton
.
toggleClass
(
'
soft-wrap-active
'
,
this
.
isSoftWrapped
);
this
.
editor
.
getSession
().
setUseWrapMode
(
this
.
isSoftWrapped
);
}
}
app/assets/javascripts/main.js
View file @
faf7865c
...
...
@@ -49,15 +49,6 @@ import { installGlEmojiElement } from './behaviors/gl_emoji';
installGlEmojiElement
();
// blob
import
'
./blob/blob_ci_yaml
'
;
import
'
./blob/blob_dockerfile_selector
'
;
import
'
./blob/blob_dockerfile_selectors
'
;
import
'
./blob/blob_file_dropzone
'
;
import
'
./blob/blob_gitignore_selector
'
;
import
'
./blob/blob_gitignore_selectors
'
;
import
'
./blob/blob_license_selector
'
;
import
'
./blob/blob_license_selectors
'
;
import
'
./blob/template_selector
'
;
import
'
./blob/create_branch_dropdown
'
;
import
'
./blob/target_branch_dropdown
'
;
...
...
app/assets/javascripts/templates/issuable_template_selector.js
View file @
faf7865c
/* eslint-disable comma-dangle, max-len, no-useless-return, no-param-reassign, max-len */
/* global Api */
require
(
'
../blob/template_selector
'
)
;
import
TemplateSelector
from
'
../blob/template_selectors/template_selector
'
;
((
global
)
=>
{
class
IssuableTemplateSelector
extends
gl
.
TemplateSelector
{
class
IssuableTemplateSelector
extends
TemplateSelector
{
constructor
(...
args
)
{
super
(...
args
);
this
.
projectPath
=
this
.
dropdown
.
data
(
'
project-path
'
);
this
.
namespacePath
=
this
.
dropdown
.
data
(
'
namespace-path
'
);
this
.
issuableType
=
this
.
wrapp
er
.
data
(
'
issuable-type
'
);
this
.
issuableType
=
this
.
$dropdownContain
er
.
data
(
'
issuable-type
'
);
this
.
titleInput
=
$
(
`#
${
this
.
issuableType
}
_title`
);
const
initialQuery
=
{
...
...
@@ -41,16 +41,16 @@ require('../blob/template_selector');
}
setInputValueToTemplateContent
()
{
// `this.
requestFileSuccess
` sets the value of the description input field
// `this.
setEditorContent
` sets the value of the description input field
// to the content of the template selected.
if
(
this
.
titleInput
.
val
()
===
''
)
{
// If the title has not yet been set, focus the title input and
// skip focusing the description input by setting `true` as the
// `skipFocus` option to `
requestFileSuccess
`.
this
.
requestFileSuccess
(
this
.
currentTemplate
,
{
skipFocus
:
true
});
// `skipFocus` option to `
setEditorContent
`.
this
.
setEditorContent
(
this
.
currentTemplate
,
{
skipFocus
:
true
});
this
.
titleInput
.
focus
();
}
else
{
this
.
requestFileSuccess
(
this
.
currentTemplate
,
{
skipFocus
:
false
});
this
.
setEditorContent
(
this
.
currentTemplate
,
{
skipFocus
:
false
});
}
return
;
}
...
...
app/views/projects/blob/_upload.html.haml
View file @
faf7865c
...
...
@@ -5,7 +5,7 @@
%a
.close
{
href:
"#"
,
"data-dismiss"
=>
"modal"
}
×
%h3
.page-title
=
title
.modal-body
=
form_tag
form_path
,
method:
method
,
class:
'js-quick-submit js-upload-blob-form form-horizontal'
do
=
form_tag
form_path
,
method:
method
,
class:
'js-quick-submit js-upload-blob-form form-horizontal'
,
data:
{
method:
method
}
do
.dropzone
.dropzone-previews.blob-upload-dropzone-previews
%p
.dz-message.light
...
...
@@ -24,8 +24,5 @@
.inline.prepend-left-10
=
commit_in_fork_help
:javascript
gl
.
utils
.
disableButtonIfEmptyField
(
$
(
'
.js-upload-blob-form
'
).
find
(
'
.js-commit-message
'
),
'
.btn-upload-file
'
);
new
BlobFileDropzone
(
$
(
'
.js-upload-blob-form
'
),
'
#{
method
}
'
);
new
NewCommitForm
(
$
(
'
.js-upload-blob-form
'
))
-
content_for
:page_specific_javascripts
do
=
page_specific_javascript_bundle_tag
(
'blob'
)
app/views/projects/blob/edit.html.haml
View file @
faf7865c
...
...
@@ -2,7 +2,7 @@
-
page_title
"Edit"
,
@blob
.
path
,
@ref
-
content_for
:page_specific_javascripts
do
=
page_specific_javascript_tag
(
'lib/ace.js'
)
=
page_specific_javascript_bundle_tag
(
'blob
_edit
'
)
=
page_specific_javascript_bundle_tag
(
'blob'
)
=
render
"projects/commits/head"
%div
{
class:
container_class
}
...
...
app/views/projects/blob/new.html.haml
View file @
faf7865c
-
page_title
"New File"
,
@path
.
presence
,
@ref
-
content_for
:page_specific_javascripts
do
=
page_specific_javascript_tag
(
'lib/ace.js'
)
=
page_specific_javascript_bundle_tag
(
'blob
_edit
'
)
=
page_specific_javascript_bundle_tag
(
'blob'
)
%h3
.page-title
New File
...
...
config/webpack.config.js
View file @
faf7865c
...
...
@@ -21,7 +21,7 @@ var config = {
common_vue
:
[
'
vue
'
,
'
./vue_shared/common_vue.js
'
],
common_d3
:
[
'
d3
'
],
main
:
'
./main.js
'
,
blob
_edit
:
'
./blob_edit/blob_edit
_bundle.js
'
,
blob
:
'
./blob_edit/blob
_bundle.js
'
,
boards
:
'
./boards/boards_bundle.js
'
,
simulate_drag
:
'
./test_utils/simulate_drag.js
'
,
cycle_analytics
:
'
./cycle_analytics/cycle_analytics_bundle.js
'
,
...
...
spec/javascripts/test_bundle.js
View file @
faf7865c
...
...
@@ -36,7 +36,8 @@ testsContext.keys().forEach(function (path) {
if
(
process
.
env
.
BABEL_ENV
===
'
coverage
'
)
{
// exempt these files from the coverage report
const
troubleMakers
=
[
'
./blob_edit/blob_edit_bundle.js
'
,
'
./blob_edit/blob_bundle.js
'
,
'
./boards/boards_bundle.js
'
,
'
./cycle_analytics/components/stage_plan_component.js
'
,
'
./cycle_analytics/components/stage_staging_component.js
'
,
'
./cycle_analytics/components/stage_test_component.js
'
,
...
...
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