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
34774260
Commit
34774260
authored
Sep 04, 2020
by
Enrique Alcántara
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch '241468-visibility-level' into 'master'
Fixing reverted !41014 See merge request gitlab-org/gitlab!41584
parents
c3afb319
19a3f70a
Changes
10
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
204 additions
and
66 deletions
+204
-66
app/assets/javascripts/snippets/components/edit.vue
app/assets/javascripts/snippets/components/edit.vue
+22
-8
app/assets/javascripts/snippets/components/snippet_visibility_edit.vue
...vascripts/snippets/components/snippet_visibility_edit.vue
+31
-19
app/assets/javascripts/snippets/constants.js
app/assets/javascripts/snippets/constants.js
+12
-0
app/assets/javascripts/snippets/index.js
app/assets/javascripts/snippets/index.js
+17
-1
app/assets/javascripts/snippets/queries/snippet_visibility.query.graphql
...scripts/snippets/queries/snippet_visibility.query.graphql
+5
-0
app/assets/javascripts/snippets/utils/blob.js
app/assets/javascripts/snippets/utils/blob.js
+15
-0
app/views/shared/snippets/_form.html.haml
app/views/shared/snippets/_form.html.haml
+2
-1
spec/frontend/snippets/components/__snapshots__/snippet_visibility_edit_spec.js.snap
...onents/__snapshots__/snippet_visibility_edit_spec.js.snap
+8
-0
spec/frontend/snippets/components/edit_spec.js
spec/frontend/snippets/components/edit_spec.js
+7
-0
spec/frontend/snippets/components/snippet_visibility_edit_spec.js
...ntend/snippets/components/snippet_visibility_edit_spec.js
+85
-37
No files found.
app/assets/javascripts/snippets/components/edit.vue
View file @
34774260
...
...
@@ -6,19 +6,21 @@ import { __, sprintf } from '~/locale';
import
TitleField
from
'
~/vue_shared/components/form/title.vue
'
;
import
{
redirectTo
,
joinPaths
}
from
'
~/lib/utils/url_utility
'
;
import
FormFooterActions
from
'
~/vue_shared/components/form/form_footer_actions.vue
'
;
import
{
SNIPPET_MARK_EDIT_APP_START
}
from
'
~/performance_constants
'
;
import
UpdateSnippetMutation
from
'
../mutations/updateSnippet.mutation.graphql
'
;
import
CreateSnippetMutation
from
'
../mutations/createSnippet.mutation.graphql
'
;
import
{
getSnippetMixin
}
from
'
../mixins/snippets
'
;
import
{
SNIPPET_VISIBILITY_PRIVATE
,
SNIPPET_CREATE_MUTATION_ERROR
,
SNIPPET_UPDATE_MUTATION_ERROR
,
SNIPPET_VISIBILITY_PRIVATE
,
}
from
'
../constants
'
;
import
defaultVisibilityQuery
from
'
../queries/snippet_visibility.query.graphql
'
;
import
SnippetBlobActionsEdit
from
'
./snippet_blob_actions_edit.vue
'
;
import
SnippetVisibilityEdit
from
'
./snippet_visibility_edit.vue
'
;
import
SnippetDescriptionEdit
from
'
./snippet_description_edit.vue
'
;
import
{
SNIPPET_MARK_EDIT_APP_START
}
from
'
~/performance_constants
'
;
export
default
{
components
:
{
...
...
@@ -31,6 +33,15 @@ export default {
GlLoadingIcon
,
},
mixins
:
[
getSnippetMixin
],
apollo
:
{
defaultVisibility
:
{
query
:
defaultVisibilityQuery
,
manual
:
true
,
result
({
data
:
{
selectedLevel
}
})
{
this
.
selectedLevelDefault
=
selectedLevel
;
},
},
},
props
:
{
markdownPreviewPath
:
{
type
:
String
,
...
...
@@ -56,6 +67,7 @@ export default {
isUpdating
:
false
,
newSnippet
:
false
,
actions
:
[],
selectedLevelDefault
:
SNIPPET_VISIBILITY_PRIVATE
,
};
},
computed
:
{
...
...
@@ -98,6 +110,13 @@ export default {
descriptionFieldId
()
{
return
`
${
this
.
isProjectSnippet
?
'
project
'
:
'
personal
'
}
_snippet_description`
;
},
newSnippetSchema
()
{
return
{
title
:
''
,
description
:
''
,
visibilityLevel
:
this
.
selectedLevelDefault
,
};
},
},
beforeCreate
()
{
performance
.
mark
(
SNIPPET_MARK_EDIT_APP_START
);
...
...
@@ -126,7 +145,7 @@ export default {
},
onNewSnippetFetched
()
{
this
.
newSnippet
=
true
;
this
.
snippet
=
this
.
$options
.
newSnippetSchema
;
this
.
snippet
=
this
.
newSnippetSchema
;
},
onExistingSnippetFetched
()
{
this
.
newSnippet
=
false
;
...
...
@@ -184,11 +203,6 @@ export default {
this
.
actions
=
actions
;
},
},
newSnippetSchema
:
{
title
:
''
,
description
:
''
,
visibilityLevel
:
SNIPPET_VISIBILITY_PRIVATE
,
},
};
</
script
>
<
template
>
...
...
app/assets/javascripts/snippets/components/snippet_visibility_edit.vue
View file @
34774260
<
script
>
import
{
GlIcon
,
GlFormGroup
,
GlFormRadio
,
GlFormRadioGroup
,
GlLink
}
from
'
@gitlab/ui
'
;
import
{
SNIPPET_VISIBILITY
,
SNIPPET_VISIBILITY_PRIVATE
,
SNIPPET_VISIBILITY_INTERNAL
,
SNIPPET_VISIBILITY_PUBLIC
,
}
from
'
~/snippets/constants
'
;
import
defaultVisibilityQuery
from
'
../queries/snippet_visibility.query.graphql
'
;
import
{
defaultSnippetVisibilityLevels
}
from
'
../utils/blob
'
;
import
{
SNIPPET_LEVELS_RESTRICTED
,
SNIPPET_LEVELS_DISABLED
}
from
'
~/snippets/constants
'
;
export
default
{
components
:
{
...
...
@@ -15,6 +12,16 @@ export default {
GlFormRadioGroup
,
GlLink
,
},
apollo
:
{
defaultVisibility
:
{
query
:
defaultVisibilityQuery
,
manual
:
true
,
result
({
data
:
{
visibilityLevels
,
multipleLevelsRestricted
}
})
{
this
.
visibilityLevels
=
defaultSnippetVisibilityLevels
(
visibilityLevels
);
this
.
multipleLevelsRestricted
=
multipleLevelsRestricted
;
},
},
},
props
:
{
helpLink
:
{
type
:
String
,
...
...
@@ -28,19 +35,17 @@ export default {
},
value
:
{
type
:
String
,
required
:
false
,
default
:
SNIPPET_VISIBILITY_PRIVATE
,
required
:
true
,
},
},
computed
:
{
visibilityOptions
()
{
return
[
SNIPPET_VISIBILITY_PRIVATE
,
SNIPPET_VISIBILITY_INTERNAL
,
SNIPPET_VISIBILITY_PUBLIC
,
].
map
(
key
=>
({
value
:
key
,
...
SNIPPET_VISIBILITY
[
key
]
}));
},
data
()
{
return
{
visibilityLevels
:
[],
multipleLevelsRestricted
:
false
,
};
},
SNIPPET_LEVELS_DISABLED
,
SNIPPET_LEVELS_RESTRICTED
,
};
</
script
>
<
template
>
...
...
@@ -51,10 +56,10 @@ export default {
><gl-icon
:size=
"12"
name=
"question"
/></gl-link>
</label>
<gl-form-group
id=
"visibility-level-setting"
>
<gl-form-radio-group
v-bind=
"$attrs"
:checked=
"value"
stacked
v-on=
"$listeners"
>
<gl-form-group
id=
"visibility-level-setting"
class=
"gl-mb-0"
>
<gl-form-radio-group
:checked=
"value"
stacked
v-bind=
"$attrs"
v-on=
"$listeners"
>
<gl-form-radio
v-for=
"option in visibility
Option
s"
v-for=
"option in visibility
Level
s"
:key=
"option.value"
:value=
"option.value"
class=
"mb-3"
...
...
@@ -71,5 +76,12 @@ export default {
</gl-form-radio>
</gl-form-radio-group>
</gl-form-group>
<div
class=
"text-muted"
data-testid=
"restricted-levels-info"
>
<
template
v-if=
"!visibilityLevels.length"
>
{{
$options
.
SNIPPET_LEVELS_DISABLED
}}
</
template
>
<
template
v-else-if=
"multipleLevelsRestricted"
>
{{
$options
.
SNIPPET_LEVELS_RESTRICTED
}}
</
template
>
</div>
</div>
</template>
app/assets/javascripts/snippets/constants.js
View file @
34774260
...
...
@@ -33,3 +33,15 @@ export const SNIPPET_BLOB_ACTION_MOVE = 'move';
export
const
SNIPPET_BLOB_ACTION_DELETE
=
'
delete
'
;
export
const
SNIPPET_MAX_BLOBS
=
10
;
export
const
SNIPPET_LEVELS_MAP
=
{
0
:
SNIPPET_VISIBILITY_PRIVATE
,
10
:
SNIPPET_VISIBILITY_INTERNAL
,
20
:
SNIPPET_VISIBILITY_PUBLIC
,
};
export
const
SNIPPET_LEVELS_RESTRICTED
=
__
(
'
Other visibility settings have been disabled by the administrator.
'
,
);
export
const
SNIPPET_LEVELS_DISABLED
=
__
(
'
Visibility settings have been disabled by the administrator.
'
,
);
app/assets/javascripts/snippets/index.js
View file @
34774260
...
...
@@ -5,6 +5,7 @@ import createDefaultClient from '~/lib/graphql';
import
SnippetsShow
from
'
./components/show.vue
'
;
import
SnippetsEdit
from
'
./components/edit.vue
'
;
import
{
SNIPPET_LEVELS_MAP
,
SNIPPET_VISIBILITY_PRIVATE
}
from
'
~/snippets/constants
'
;
Vue
.
use
(
VueApollo
);
Vue
.
use
(
Translate
);
...
...
@@ -18,13 +19,28 @@ function appFactory(el, Component) {
defaultClient
:
createDefaultClient
(),
});
const
{
visibilityLevels
=
'
[]
'
,
selectedLevel
,
multipleLevelsRestricted
,
...
restDataset
}
=
el
.
dataset
;
apolloProvider
.
clients
.
defaultClient
.
cache
.
writeData
({
data
:
{
visibilityLevels
:
JSON
.
parse
(
visibilityLevels
),
selectedLevel
:
SNIPPET_LEVELS_MAP
[
selectedLevel
]
??
SNIPPET_VISIBILITY_PRIVATE
,
multipleLevelsRestricted
:
'
multipleLevelsRestricted
'
in
el
.
dataset
,
},
});
return
new
Vue
({
el
,
apolloProvider
,
render
(
createElement
)
{
return
createElement
(
Component
,
{
props
:
{
...
el
.
d
ataset
,
...
restD
ataset
,
},
});
},
...
...
app/assets/javascripts/snippets/queries/snippet_visibility.query.graphql
0 → 100644
View file @
34774260
query
defaultSnippetVisibility
{
visibilityLevels
@client
selectedLevel
@client
multipleLevelsRestricted
@client
}
app/assets/javascripts/snippets/utils/blob.js
View file @
34774260
...
...
@@ -4,6 +4,8 @@ import {
SNIPPET_BLOB_ACTION_UPDATE
,
SNIPPET_BLOB_ACTION_MOVE
,
SNIPPET_BLOB_ACTION_DELETE
,
SNIPPET_LEVELS_MAP
,
SNIPPET_VISIBILITY
,
}
from
'
../constants
'
;
const
createLocalId
=
()
=>
uniqueId
(
'
blob_local_
'
);
...
...
@@ -64,3 +66,16 @@ export const diffAll = (blobs, origBlobs) => {
return
[...
deletedEntries
,
...
newEntries
];
};
export
const
defaultSnippetVisibilityLevels
=
arr
=>
{
if
(
Array
.
isArray
(
arr
))
{
return
arr
.
map
(
l
=>
{
const
translatedLevel
=
SNIPPET_LEVELS_MAP
[
l
];
return
{
value
:
translatedLevel
,
...
SNIPPET_VISIBILITY
[
translatedLevel
],
};
});
}
return
[];
};
app/views/shared/snippets/_form.html.haml
View file @
34774260
-
if
Feature
.
enabled?
(
:snippets_edit_vue
)
#js-snippet-edit
.snippet-form
{
data:
{
'project_path'
:
@snippet
.
project
&
.
full_path
,
'snippet-gid'
:
@snippet
.
new_record?
?
''
:
@snippet
.
to_global_id
,
'markdown-preview-path'
:
preview_markdown_path
(
parent
),
'markdown-docs-path'
:
help_page_path
(
'user/markdown'
),
'visibility-help-link'
:
help_page_path
(
"public_access/public_access"
)
}
}
-
available_visibility_levels
=
available_visibility_levels
(
@snippet
)
#js-snippet-edit
.snippet-form
{
data:
{
'project_path'
:
@snippet
.
project
&
.
full_path
,
'snippet-gid'
:
@snippet
.
new_record?
?
''
:
@snippet
.
to_global_id
,
'markdown-preview-path'
:
preview_markdown_path
(
parent
),
'markdown-docs-path'
:
help_page_path
(
'user/markdown'
),
'visibility-help-link'
:
help_page_path
(
"public_access/public_access"
),
'visibility_levels'
:
available_visibility_levels
,
'selected_level'
:
snippets_selected_visibility_level
(
available_visibility_levels
,
@snippet
.
visibility_level
),
'multiple_levels_restricted'
:
multiple_visibility_levels_restricted?
}
}
-
else
.snippet-form-holder
=
form_for
@snippet
,
url:
url
,
...
...
spec/frontend/snippets/components/__snapshots__/snippet_visibility_edit_spec.js.snap
View file @
34774260
...
...
@@ -20,6 +20,7 @@ exports[`Snippet Visibility Edit component rendering matches the snapshot 1`] =
</label>
<gl-form-group-stub
class="gl-mb-0"
id="visibility-level-setting"
>
<gl-form-radio-group-stub
...
...
@@ -90,5 +91,12 @@ exports[`Snippet Visibility Edit component rendering matches the snapshot 1`] =
</gl-form-radio-stub>
</gl-form-radio-group-stub>
</gl-form-group-stub>
<div
class="text-muted"
data-testid="restricted-levels-info"
>
<!---->
</div>
</div>
`;
spec/frontend/snippets/components/edit_spec.js
View file @
34774260
...
...
@@ -102,6 +102,13 @@ describe('Snippet Edit app', () => {
markdownDocsPath
:
'
http://docs.foo.bar
'
,
...
props
,
},
data
()
{
return
{
snippet
:
{
visibilityLevel
:
SNIPPET_VISIBILITY_PRIVATE
,
},
};
},
});
}
...
...
spec/frontend/snippets/components/snippet_visibility_edit_spec.js
View file @
34774260
import
{
GlFormRadio
,
GlIcon
,
GlFormRadioGroup
,
GlLink
}
from
'
@gitlab/ui
'
;
import
{
mount
,
shallowMount
}
from
'
@vue/test-utils
'
;
import
SnippetVisibilityEdit
from
'
~/snippets/components/snippet_visibility_edit.vue
'
;
import
{
defaultSnippetVisibilityLevels
}
from
'
~/snippets/utils/blob
'
;
import
{
SNIPPET_VISIBILITY
,
SNIPPET_VISIBILITY_PRIVATE
,
SNIPPET_VISIBILITY_INTERNAL
,
SNIPPET_VISIBILITY_PUBLIC
,
SNIPPET_LEVELS_RESTRICTED
,
SNIPPET_LEVELS_DISABLED
,
}
from
'
~/snippets/constants
'
;
describe
(
'
Snippet Visibility Edit component
'
,
()
=>
{
let
wrapper
;
const
defaultHelpLink
=
'
/foo/bar
'
;
const
defaultVisibilityLevel
=
'
private
'
;
function
createComponent
(
propsData
=
{},
deep
=
false
)
{
const
defaultVisibility
=
defaultSnippetVisibilityLevels
([
0
,
10
,
20
]);
function
createComponent
({
propsData
=
{},
visibilityLevels
=
defaultVisibility
,
multipleLevelsRestricted
=
false
,
deep
=
false
,
}
=
{})
{
const
method
=
deep
?
mount
:
shallowMount
;
const
$apollo
=
{
queries
:
{
defaultVisibility
:
{
loading
:
false
,
},
},
};
wrapper
=
method
.
call
(
this
,
SnippetVisibilityEdit
,
{
mock
:
{
$apollo
},
propsData
:
{
helpLink
:
defaultHelpLink
,
isProjectSnippet
:
false
,
value
:
defaultVisibilityLevel
,
...
propsData
,
},
data
()
{
return
{
visibilityLevels
,
multipleLevelsRestricted
,
};
},
});
}
const
findL
abel
=
()
=>
wrapper
.
find
(
'
label
'
);
const
findL
ink
=
()
=>
wrapper
.
find
(
'
label
'
).
find
(
GlLink
);
const
findRadios
=
()
=>
wrapper
.
find
(
GlFormRadioGroup
).
findAll
(
GlFormRadio
);
const
findRadiosData
=
()
=>
findRadios
().
wrappers
.
map
(
x
=>
{
...
...
@@ -47,60 +71,84 @@ describe('Snippet Visibility Edit component', () => {
expect
(
wrapper
.
element
).
toMatchSnapshot
();
});
it
(
'
renders visibility options
'
,
()
=>
{
createComponent
({},
true
);
it
(
'
renders label help link
'
,
()
=>
{
createComponent
();
expect
(
findLink
().
attributes
(
'
href
'
)).
toBe
(
defaultHelpLink
);
});
it
(
'
when helpLink is not defined, does not render label help link
'
,
()
=>
{
createComponent
({
propsData
:
{
helpLink
:
null
}
});
expect
(
findRadiosData
()).
toEqual
([
{
expect
(
findLink
().
exists
()).
toBe
(
false
);
});
describe
(
'
Visibility options
'
,
()
=>
{
const
findRestrictedInfo
=
()
=>
wrapper
.
find
(
'
[data-testid="restricted-levels-info"]
'
);
const
RESULTING_OPTIONS
=
{
0
:
{
value
:
SNIPPET_VISIBILITY_PRIVATE
,
icon
:
SNIPPET_VISIBILITY
.
private
.
icon
,
text
:
SNIPPET_VISIBILITY
.
private
.
label
,
description
:
SNIPPET_VISIBILITY
.
private
.
description
,
},
{
10
:
{
value
:
SNIPPET_VISIBILITY_INTERNAL
,
icon
:
SNIPPET_VISIBILITY
.
internal
.
icon
,
text
:
SNIPPET_VISIBILITY
.
internal
.
label
,
description
:
SNIPPET_VISIBILITY
.
internal
.
description
,
},
{
20
:
{
value
:
SNIPPET_VISIBILITY_PUBLIC
,
icon
:
SNIPPET_VISIBILITY
.
public
.
icon
,
text
:
SNIPPET_VISIBILITY
.
public
.
label
,
description
:
SNIPPET_VISIBILITY
.
public
.
description
,
},
]);
});
it
(
'
when project snippet, renders special private description
'
,
()
=>
{
createComponent
({
isProjectSnippet
:
true
},
true
);
};
expect
(
findRadiosData
()[
0
]).
toEqual
({
value
:
SNIPPET_VISIBILITY_PRIVATE
,
icon
:
SNIPPET_VISIBILITY
.
private
.
icon
,
text
:
SNIPPET_VISIBILITY
.
private
.
label
,
description
:
SNIPPET_VISIBILITY
.
private
.
description_project
,
it
.
each
`
levels | resultOptions
${
undefined
}
|
${[]}
${
''
}
|
${[]}
${[]}
|
${[]}
${[
0
]}
|
${[
RESULTING_OPTIONS
[
0
]]}
${[
0
,
10
]}
|
${[
RESULTING_OPTIONS
[
0
],
RESULTING_OPTIONS
[
10
]]}
${[
0
,
10
,
20
]}
|
${[
RESULTING_OPTIONS
[
0
],
RESULTING_OPTIONS
[
10
],
RESULTING_OPTIONS
[
20
]]}
${[
0
,
20
]}
|
${[
RESULTING_OPTIONS
[
0
],
RESULTING_OPTIONS
[
20
]]}
${[
10
,
20
]}
|
${[
RESULTING_OPTIONS
[
10
],
RESULTING_OPTIONS
[
20
]]}
`
(
'
renders correct visibility options for $levels
'
,
({
levels
,
resultOptions
})
=>
{
createComponent
({
visibilityLevels
:
defaultSnippetVisibilityLevels
(
levels
),
deep
:
true
});
expect
(
findRadiosData
()).
toEqual
(
resultOptions
);
});
});
it
(
'
renders label help link
'
,
()
=>
{
createComponent
();
expect
(
findLabel
()
.
find
(
GlLink
)
.
attributes
(
'
href
'
),
).
toBe
(
defaultHelpLink
);
});
it
.
each
`
levels | levelsRestricted | resultText
${[]}
|
${
false
}
|
${
SNIPPET_LEVELS_DISABLED
}
${[]}
|
${
true
}
|
${
SNIPPET_LEVELS_DISABLED
}
${[
0
]}
|
${
true
}
|
${
SNIPPET_LEVELS_RESTRICTED
}
${[
0
]}
|
${
false
}
|
${
''
}
${[
0
,
10
,
20
]}
|
${
false
}
|
${
''
}
`
(
'
renders correct information about restricted visibility levels for $levels
'
,
({
levels
,
levelsRestricted
,
resultText
})
=>
{
createComponent
({
visibilityLevels
:
defaultSnippetVisibilityLevels
(
levels
),
multipleLevelsRestricted
:
levelsRestricted
,
});
expect
(
findRestrictedInfo
().
text
()).
toBe
(
resultText
);
},
);
it
(
'
when helpLink is not defined, does not render label help link
'
,
()
=>
{
createComponent
({
helpLink
:
null
});
it
(
'
when project snippet, renders special private description
'
,
()
=>
{
createComponent
({
propsData
:
{
isProjectSnippet
:
true
},
deep
:
true
});
expect
(
findLabel
()
.
find
(
GlLink
)
.
exists
(),
).
toBe
(
false
);
expect
(
findRadiosData
()[
0
]).
toEqual
({
value
:
SNIPPET_VISIBILITY_PRIVATE
,
icon
:
SNIPPET_VISIBILITY
.
private
.
icon
,
text
:
SNIPPET_VISIBILITY
.
private
.
label
,
description
:
SNIPPET_VISIBILITY
.
private
.
description_project
,
});
});
});
});
...
...
@@ -108,7 +156,7 @@ describe('Snippet Visibility Edit component', () => {
it
(
'
pre-selects correct option in the list
'
,
()
=>
{
const
value
=
SNIPPET_VISIBILITY_INTERNAL
;
createComponent
({
value
});
createComponent
({
propsData
:
{
value
}
});
expect
(
wrapper
.
find
(
GlFormRadioGroup
).
attributes
(
'
checked
'
)).
toBe
(
value
);
});
...
...
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