Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gitlab-ce
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
1
Merge Requests
1
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
gitlab-ce
Commits
51c9f8b6
Commit
51c9f8b6
authored
Sep 19, 2017
by
Filipa Lacerda
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[ci skip] First iteration: port haml into vue
parent
23024a70
Changes
14
Show whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
322 additions
and
75 deletions
+322
-75
app/assets/javascripts/registry/components/app.vue
app/assets/javascripts/registry/components/app.vue
+90
-0
app/assets/javascripts/registry/components/collapsible_container.vue
...javascripts/registry/components/collapsible_container.vue
+88
-49
app/assets/javascripts/registry/constants.js
app/assets/javascripts/registry/constants.js
+13
-0
app/assets/javascripts/registry/index.js
app/assets/javascripts/registry/index.js
+25
-0
app/assets/javascripts/registry/stores/actions.js
app/assets/javascripts/registry/stores/actions.js
+7
-4
app/assets/javascripts/registry/stores/getters.js
app/assets/javascripts/registry/stores/getters.js
+2
-0
app/assets/javascripts/registry/stores/index.js
app/assets/javascripts/registry/stores/index.js
+5
-3
app/assets/javascripts/registry/stores/mutation_types.js
app/assets/javascripts/registry/stores/mutation_types.js
+3
-2
app/assets/javascripts/registry/stores/mutations.js
app/assets/javascripts/registry/stores/mutations.js
+35
-6
app/assets/javascripts/vue_shared/components/clipboard_button.vue
...ts/javascripts/vue_shared/components/clipboard_button.vue
+5
-5
app/assets/stylesheets/pages/container_registry.scss
app/assets/stylesheets/pages/container_registry.scss
+4
-0
app/controllers/projects/registry/repositories_controller.rb
app/controllers/projects/registry/repositories_controller.rb
+31
-0
app/views/projects/registry/repositories/index.html.haml
app/views/projects/registry/repositories/index.html.haml
+12
-6
config/webpack.config.js
config/webpack.config.js
+2
-0
No files found.
app/assets/javascripts/registry/components/app.vue
View file @
51c9f8b6
<
script
>
/* globals Flash */
import
{
mapGetters
,
mapActions
}
from
'
vuex
'
;
import
'
../../flash
'
;
import
loadingIcon
from
'
../../vue_shared/components/loading_icon.vue
'
;
import
store
from
'
../stores
'
;
import
collapsibleContainer
from
'
./collapsible_container.vue
'
;
import
{
errorMessages
,
errorMessagesTypes
}
from
'
../constants
'
;
export
default
{
name
:
'
registryListApp
'
,
props
:
{
endpoint
:
{
type
:
String
,
required
:
true
},
},
store
,
components
:
{
collapsibleContainer
,
loadingIcon
,
},
computed
:
{
...
mapGetters
([
'
isLoading
'
,
'
repos
'
,
]),
},
methods
:
{
...
mapActions
([
'
setMainEndpoint
'
,
'
fetchRepos
'
,
'
fetchList
'
,
'
deleteRepo
'
,
'
deleteRegistry
'
,
'
toggleIsLoading
'
,
]),
fetchRegistryList
(
repo
)
{
this
.
fetchList
(
repo
)
.
catch
(()
=>
this
.
showError
(
errorMessagesTypes
.
FETCH_REGISTRY
))
},
deleteRegistry
(
repo
,
registry
)
{
this
.
deleteRegistry
(
registry
)
.
then
(()
=>
this
.
fetchRegistry
(
repo
))
.
catch
(()
=>
this
.
showError
(
errorMessagesTypes
.
DELETE_REGISTRY
));
},
deleteRepository
(
repo
)
{
this
.
deleteRepo
(
repo
)
.
then
(()
=>
this
.
fetchRepo
())
.
catch
(()
=>
this
.
showError
(
errorMessagesTypes
.
DELETE_REPO
));
},
showError
(
message
){
Flash
(
__
(
errorMessages
[
message
]));
}
},
created
()
{
this
.
setMainEndpoint
(
this
.
endpoint
);
},
mounted
()
{
this
.
fetchRepos
()
.
catch
(()
=>
this
.
showError
(
errorMessagesTypes
.
FETCH_REPOS
));
}
};
</
script
>
<
template
>
<div>
<loading-icon
v-if=
"isLoading"
size=
"3"
/>
<collapsible-container
v-else-if=
"!isLoading && repos.length"
v-for=
"(item, index) in repos"
:key=
"index"
:repo=
"item"
@
fetchRegistryList=
"fetchRegistryList"
@
deleteRepository=
"deleteRepository"
@
deleteRegistry=
"deleteRegistry"
/>
<p
v-else-if=
"!isLoading && !repos.length"
>
{{
__
(
"
No container images stored for this project. Add one by following the instructions above
"
)
}}
</p>
</div>
</
template
>
app/assets/javascripts/registry/components/collapsible_container.vue
View file @
51c9f8b6
<
script
>
import
clipboardButton
from
'
../../vue_shared/components/clipboard_button.vue
'
;
import
loadingIcon
from
'
../../vue_shared/components/loading_icon.vue
'
;
import
tooltip
from
'
../../vue_shared/directives/tooltip
'
;
export
default
{
name
:
'
collapsibeContainerRegisty
'
,
props
:
{
title
:
{
type
:
String
,
required
:
true
,
},
clipboardContent
:
{
type
:
String
,
required
:
true
,
},
repoData
:
{
repo
:
{
type
:
Object
,
required
:
true
,
},
},
components
:
{
clipboardButton
,
loadingIcon
,
},
directives
:
{
tooltip
,
},
data
()
{
return
{
...
...
@@ -26,37 +24,73 @@
};
},
methods
:
{
itemSize
(
item
)
{
layers
(
item
)
{
const
pluralize
=
gl
.
text
.
pluralize
(
'
layer
'
,
item
.
layers
);
return
`
${
item
.
size
}
·
${
item
.
layers
}${
pluralize
}
`
;
}
}
return
`
${
item
.
layers
}
${
pluralize
}
`
;
},
toggleRepo
()
{
if
(
this
.
isOpen
===
false
)
{
// consider not fetching data the second time it is toggled? :fry:
this
.
$emit
(
'
fetchRegistryList
'
,
this
.
repo
);
}
this
.
isOpen
=
!
this
.
isOpen
;
},
handleDeleteRepository
()
{
this
.
$emit
(
'
deleteRepository
'
,
this
.
repo
)
},
handleDeleteRegistry
(
registry
)
{
this
.
$emit
(
'
deleteRegistry
'
,
this
.
repo
,
registry
);
},
},
};
</
script
>
<
template
>
<div
class=
"container-image"
>
<div
class=
"container-image-head"
>
<div
class=
"container-image-head"
>
<a
role=
"button"
@
click=
"toggleRepo"
>
<i
class=
"fa"
:class=
"
{
'chevron-lef
t': !isOpen,
'
chevron-up': isOpen,
'fa-chevron-righ
t': !isOpen,
'fa-
chevron-up': isOpen,
}"
aria-hidden="true">
</i>
{{
title
}}
{{
repo
.
name
}}
</a>
<clipboard-button
text=
"foo"
title=
"bar"
/>
<div
class=
"controls hidden-xs pull-right"
>
<button
v-if=
"repo.canDelete"
type=
"button"
class=
"btn btn-remove"
:title=
"__('Remove repository')"
v-tooltip
@
click=
"handleDeleteRepository"
>
<i
class=
"fa fa-trash"
aria-hidden=
"true"
>
</i>
</button>
</div>
<clipboard-button
:text=
""
:title=
""
/>
</div>
<loading-icon
v-if=
"repo.isLoading"
/>
<div
class=
"container-image-tags
"
:class=
"
{ hide: !isOpen }
">
v-else-if=
"!repo.isLoading && isOpen
"
class=
"container-image-tags
"
>
<table
class=
"table tags"
v-if=
"
true
"
>
<table
class=
"table tags"
v-if=
"
repo.list.length
"
>
<thead>
<tr>
<th>
{{
__
(
"
Tag
"
)
}}
</th>
...
...
@@ -71,23 +105,28 @@
v-for=
"(item, i) in repo.list"
:key=
"i"
>
<td>
{{
item
.
name
}}
{{
item
.
tag
}}
<clipboard-button
:title=
"item.
location
"
:text=
"item.
location
"
:title=
"item.
tag
"
:text=
"item.
tag
"
/>
</td>
<td>
<span
v-tooltip
:title=
"item.revision"
data-placement=
"bottom"
>
{{
item
.
shortRevision
}}
</span>
</td>
<td>
<template
v-if=
"item.size"
>
{{
itemSize
(
item
)
}}
{{
item
.
size
}}
·
{{
layers
(
item
)
}}
</
template
>
<div
v-else
class=
"light"
>
\-
...
...
@@ -103,18 +142,20 @@
</div>
</td>
<td>
<td
class=
"content"
>
<div
class=
"controls hidden-xs pull-right"
>
<button
type=
"button"
class=
"btn btn-remove"
title=
"Remove tag"
v-tooltip
@
click=
"deleteTag
(item)"
>
@
click=
"handleDeleteRegistry
(item)"
>
<i
class=
"fa fa-trash cred
"
class=
"fa fa-trash
"
aria-hidden=
"true"
>
</i>
</button>
</div>
</td>
</tr>
</tbody>
...
...
@@ -123,9 +164,7 @@
v-else
class=
"nothing-here-block"
>
{{__("No tags in Container Registry for this container image.")}}
</div>
</div>
</div>
</template>
app/assets/javascripts/registry/constants.js
0 → 100644
View file @
51c9f8b6
export
const
errorMessagesTypes
=
{
FETCH_REGISTRY
:
'
FETCH_REGISTRY
'
,
FETCH_REPOS
:
'
FETCH_REPOS
'
,
DELETE_REPO
:
'
DELETE_REPO
'
,
DELETE_REGISTRY
:
'
DELETE_REGISTRY
'
,
};
export
const
errorMessages
=
{
[
errorMessagesTypes
.
FETCH_REGISTRY
]:
'
Something went wrong while fetching the registry list.
'
,
[
errorMessagesTypes
.
FETCH_REPOS
]:
'
Something went wrong while fetching the repositories.
'
,
[
errorMessagesTypes
.
DELETE_REPO
]:
'
Something went wrong while deleting the repository.
'
,
[
errorMessagesTypes
.
DELETE_REGISTRY
]:
'
Something went wrong while deleting registry.
'
,
};
app/assets/javascripts/registry/index.js
View file @
51c9f8b6
import
Vue
from
'
vue
'
;
import
Translate
from
'
../vue_shared/translate
'
;
import
registryApp
from
'
./components/app.vue
'
;
// Vue.use(Translate);
document
.
addEventListener
(
'
DOMContentLoaded
'
,
()
=>
new
Vue
({
el
:
'
#js-vue-registry-images
'
,
components
:
{
registryApp
,
},
data
()
{
const
dataset
=
document
.
querySelector
(
this
.
$options
.
el
).
dataset
;
return
{
endpoint
:
dataset
.
endpoint
,
};
},
render
(
createElement
)
{
return
createElement
(
'
registry-app
'
,
{
props
:
{
endpoint
:
this
.
endpoint
,
},
});
},
}));
app/assets/javascripts/registry/stores/actions.js
View file @
51c9f8b6
...
...
@@ -16,13 +16,13 @@ export const fetchRepos = ({ commit, state }) => {
};
export
const
fetchList
=
({
commit
},
list
)
=>
{
commit
(
types
.
TOGGLE_
IMAGE
_LOADING
,
list
);
commit
(
types
.
TOGGLE_
REGISTRY_LIST
_LOADING
,
list
);
return
Vue
.
http
.
get
(
list
.
path
)
.
then
(
res
=>
res
.
json
())
.
then
((
response
)
=>
{
commit
(
types
.
TOGGLE_
IMAGE
_LOADING
,
list
);
commit
(
types
.
SET_
IMAGES
_LIST
,
list
,
response
);
commit
(
types
.
TOGGLE_
REGISTRY_LIST
_LOADING
,
list
);
commit
(
types
.
SET_
REGISTRY
_LIST
,
list
,
response
);
});
};
...
...
@@ -32,8 +32,11 @@ export const deleteRepo = ({ commit }, repo) => Vue.http.delete(repo.path)
commit
(
types
.
DELETE_REPO
,
repo
);
});
export
const
delete
Image
=
({
commit
},
image
)
=>
Vue
.
http
.
delete
(
image
.
path
)
export
const
delete
Registry
=
({
commit
},
image
)
=>
Vue
.
http
.
delete
(
image
.
path
)
.
then
(
res
=>
res
.
json
())
.
then
(()
=>
{
commit
(
types
.
DELETE_IMAGE
,
image
);
});
export
const
setMainEndpoint
=
({
commit
},
data
)
=>
commit
(
types
.
SET_MAIN_ENDPOINT
,
data
);
export
const
toggleIsLoading
=
({
commit
})
=>
commit
(
types
.
TOGGLE_MAIN_LOADING
);
app/assets/javascripts/registry/stores/getters.js
0 → 100644
View file @
51c9f8b6
export
const
isLoading
=
state
=>
state
.
isLoading
;
export
const
repos
=
state
=>
state
.
repos
;
\ No newline at end of file
app/assets/javascripts/registry/stores/index.js
View file @
51c9f8b6
import
Vue
from
'
vue
'
;
import
Vuex
from
'
vuex
'
;
import
actions
from
'
./actions
'
;
import
*
as
actions
from
'
./actions
'
;
import
*
as
getters
from
'
./getters
'
;
import
mutations
from
'
./mutations
'
;
Vue
.
use
(
Vuex
);
...
...
@@ -31,7 +32,8 @@ export default new Vuex.Store({
* }
*/
repos
:
[],
},
actions
,
getters
,
mutations
,
},
});
app/assets/javascripts/registry/stores/mutation_types.js
View file @
51c9f8b6
export
const
SET_MAIN_ENDPOINT
=
'
SET_MAIN_ENDPOINT
'
;
export
const
FETCH_REPOS_LIST
=
'
FETCH_REPOS_LIST
'
;
export
const
DELETE_REPO
=
'
DELETE_REPO
'
;
export
const
SET_REPOS_LIST
=
'
SET_REPOS_LIST
'
;
export
const
TOGGLE_MAIN_LOADING
=
'
TOGGLE_MAIN_LOADING
'
;
export
const
FETCH_IMAGES_LIST
=
'
FETCH_IMAGES_LIST
'
;
export
const
SET_
IMAGES_LIST
=
'
SET_IMAGES
_LIST
'
;
export
const
SET_
REGISTRY_LIST
=
'
SET_REGISTRY
_LIST
'
;
export
const
DELETE_IMAGE
=
'
DELETE_IMAGE
'
;
export
const
TOGGLE_
IMAGE_LOADING
=
'
TOGGLE_MAIN
_LOADING
'
;
export
const
TOGGLE_
REGISTRY_LIST_LOADING
=
'
TOGGLE_REGISTRY_LIST
_LOADING
'
;
app/assets/javascripts/registry/stores/mutations.js
View file @
51c9f8b6
import
*
as
types
from
'
./mutation_types
'
;
export
default
{
[
types
.
SET_MAIN_ENDPOINT
](
state
,
endpoint
)
{
Object
.
assign
(
state
,
{
endpoint
});
},
[
types
.
SET_REPOS_LIST
](
state
,
list
)
{
Object
.
assign
(
state
,
{
repos
:
list
.
map
(
el
=>
({
name
:
el
.
name
,
isLoading
:
false
,
canDelete
:
!!
el
.
destroy_path
,
destroyPath
:
el
.
destroy_path
,
isLoading
:
false
,
list
:
[],
location
:
el
.
location
,
name
:
el
.
name
,
tagsPath
:
el
.
tags_path
,
id
:
el
.
id
,
})),
});
},
...
...
@@ -17,8 +25,29 @@ export default {
Object
.
assign
(
state
,
{
isLoading
:
!
state
.
isLoading
});
},
[
types
.
SET_IMAGES_LIST
](
state
,
image
,
list
)
{
const
listToUpdate
=
state
.
repos
.
find
(
el
=>
el
.
name
===
image
.
name
);
[
types
.
SET_REGISTRY_LIST
](
state
,
repo
,
list
)
{
// mock
list
=
[
{
name
:
'
centos6
'
,
short_revision
:
'
0b6091a66
'
,
revision
:
'
0b6091a665af68bbbbb36a3e088ec3cd6f35389deebf6d4617042d56722d76fb
'
,
size
:
706
,
layers
:
19
,
created_at
:
1505828744434
,
},
{
name
:
'
centos7
'
,
short_revision
:
'
b118ab5b0
'
,
revision
:
'
b118ab5b0e90b7cb5127db31d5321ac14961d097516a8e0e72084b6cdc783b43
'
,
size
:
679
,
layers
:
19
,
created_at
:
1505828744434
,
},
];
const
listToUpdate
=
state
.
repos
.
find
(
el
=>
el
.
id
===
repo
.
id
);
listToUpdate
.
list
=
list
.
map
(
element
=>
({
tag
:
element
.
name
,
revision
:
element
.
revision
,
...
...
@@ -31,8 +60,8 @@ export default {
}));
},
[
types
.
TOGGLE_
IMAGE_LOADING
](
state
,
image
)
{
const
listToUpdate
=
state
.
repos
.
find
(
el
=>
el
.
name
===
image
.
name
);
[
types
.
TOGGLE_
REGISTRY_LIST_LOADING
](
state
,
list
)
{
const
listToUpdate
=
state
.
repos
.
find
(
el
=>
el
.
id
===
list
.
id
);
listToUpdate
.
isLoading
=
!
listToUpdate
.
isLoading
;
},
};
app/assets/javascripts/vue_shared/components/clipboard_button.vue
View file @
51c9f8b6
...
...
@@ -14,11 +14,11 @@
},
},
mounted
()
{
return
new
Clipboard
(
this
.
$refs
.
btn
,
{
text
:
()
=>
{
return
this
.
text
;
},
});
//
return new Clipboard(this.$refs.btn, {
//
text: () => {
//
return this.text;
//
},
//
});
}
};
</
script
>
...
...
app/assets/stylesheets/pages/container_registry.scss
View file @
51c9f8b6
...
...
@@ -9,6 +9,10 @@
.container-image-head
{
padding
:
0
16px
;
line-height
:
4em
;
&
:hover
{
text-decoration
:
underline
;
}
}
.table.tags
{
...
...
app/controllers/projects/registry/repositories_controller.rb
View file @
51c9f8b6
...
...
@@ -6,6 +6,37 @@ module Projects
def
index
@images
=
project
.
container_repositories
respond_to
do
|
format
|
format
.
html
format
.
json
do
# render json: @images
render
json:
[
{
name:
'gitlab-org/omnibus-gitlab/foo'
,
tags_path:
'foo'
,
destroy_path:
'bar'
,
location:
'foo'
,
id:
'134'
,
destroy_path:
'bar'
},
{
name:
'gitlab-org/omnibus-gitlab'
,
tags_path:
'foo'
,
destroy_path:
'bar'
,
location:
'foo'
,
id:
'123'
,
},
{
name:
'gitlab-org/omnibus-gitlab/bar'
,
tags_path:
'foo'
,
destroy_path:
'bar'
,
location:
'foo'
,
id:
'973'
,
}
]
end
end
end
def
destroy
...
...
app/views/projects/registry/repositories/index.html.haml
View file @
51c9f8b6
...
...
@@ -52,9 +52,15 @@
#{
escape_once
(
@project
.
container_registry_url
)
}
/optional-image-name:tag
#{
escape_once
(
@project
.
container_registry_url
)
}
/optional-name/optional-image-name:tag
-
if
@images
.
blank?
%p
.settings-message.text-center.append-bottom-default
No container images stored for this project. Add one by following the
instructions above.
-
else
=
render
partial:
'image'
,
collection:
@images
#js-vue-registry-images
{
data:
{
endpoint:
project_container_registry_index_path
(
@project
,
format: :json
)}}
=
page_specific_javascript_bundle_tag
(
'common_vue'
)
=
page_specific_javascript_bundle_tag
(
'registry_list'
)
-# - if @images.blank?
-# %p.settings-message.text-center.append-bottom-default
-# No container images stored for this project. Add one by following the
-# instructions above.
-# - else
-# = render partial: 'image', collection: @images
config/webpack.config.js
View file @
51c9f8b6
...
...
@@ -67,6 +67,7 @@ var config = {
prometheus_metrics
:
'
./prometheus_metrics
'
,
protected_branches
:
'
./protected_branches
'
,
protected_tags
:
'
./protected_tags
'
,
registry_list
:
'
./registry/index.js
'
,
repo
:
'
./repo/index.js
'
,
sidebar
:
'
./sidebar/sidebar_bundle.js
'
,
schedule_form
:
'
./pipeline_schedules/pipeline_schedule_form_bundle.js
'
,
...
...
@@ -199,6 +200,7 @@ var config = {
'
pdf_viewer
'
,
'
pipelines
'
,
'
pipelines_details
'
,
'
registry_list
'
,
'
repo
'
,
'
schedule_form
'
,
'
schedules_index
'
,
...
...
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