Commit 3909c6c0 authored by Jacob Schatz's avatar Jacob Schatz

Adds new ruby help for dropdowns for branches

parent 71d08bfb
...@@ -206,7 +206,7 @@ GitLabDropdown = (function() { ...@@ -206,7 +206,7 @@ GitLabDropdown = (function() {
CURSOR_SELECT_SCROLL_PADDING = 5; CURSOR_SELECT_SCROLL_PADDING = 5;
FILTER_INPUT = '.dropdown-input .dropdown-input-field'; FILTER_INPUT = '.dropdown-input .dropdown-input-field:not(.dropdown-no-filter)';
function GitLabDropdown(el1, options) { function GitLabDropdown(el1, options) {
var searchFields, selector, self; var searchFields, selector, self;
......
...@@ -77,7 +77,6 @@ import Cookies from 'js-cookie'; ...@@ -77,7 +77,6 @@ import Cookies from 'js-cookie';
}, },
dataType: "json" dataType: "json"
}).done(function(refs) { }).done(function(refs) {
console.log(refs);
return callback(refs); return callback(refs);
}); });
}, },
...@@ -118,9 +117,15 @@ import Cookies from 'js-cookie'; ...@@ -118,9 +117,15 @@ import Cookies from 'js-cookie';
e.preventDefault(); e.preventDefault();
if ($('input[name="ref"]').length) { if ($('input[name="ref"]').length) {
var $form = $dropdown.closest('form'); var $form = $dropdown.closest('form');
var $visit = $dropdown.data('visit');
var shouldVisit = typeof $visit === 'undefined' ? true : $visit;
var action = $form.attr('action'); var action = $form.attr('action');
var divider = action.indexOf('?') === -1 ? '?' : '&'; var divider = action.indexOf('?') === -1 ? '?' : '&';
gl.utils.visitUrl(action + '' + divider + '' + $form.serialize()); if(shouldVisit){
gl.utils.visitUrl(action + '' + divider + '' + $form.serialize());
}
} }
} }
}); });
......
...@@ -10,7 +10,8 @@ import RepoTabs from './repo_tabs.vue'; ...@@ -10,7 +10,8 @@ import RepoTabs from './repo_tabs.vue';
import RepoFileButtons from './repo_file_buttons.vue'; import RepoFileButtons from './repo_file_buttons.vue';
import RepoBinaryViewer from './repo_binary_viewer.vue'; import RepoBinaryViewer from './repo_binary_viewer.vue';
import { repoEditorLoader } from './repo_editor'; import { repoEditorLoader } from './repo_editor';
import RepoMiniMixin from './repo_mini_mixin'; import RepoMixin from './repo_mixin';
import PopupDialog from '../vue_shared/components/popup_dialog.vue'
function initRepo() { function initRepo() {
const repo = document.getElementById('repo'); const repo = document.getElementById('repo');
...@@ -37,9 +38,10 @@ function initRepo() { ...@@ -37,9 +38,10 @@ function initRepo() {
<repo-binary-viewer/> <repo-binary-viewer/>
</div> </div>
<repo-commit-section/> <repo-commit-section/>
<popup-dialog :open="dialog.open" kind="warning" title="Are you sure?" body="Are you sure you want to discard your changes?" @toggle="dialogToggled" @submit="dialogSubmitted"></popup-dialog>
</div> </div>
`, `,
mixins: [RepoMiniMixin], mixins: [RepoMixin],
components: { components: {
'repo-sidebar': RepoSidebar, 'repo-sidebar': RepoSidebar,
'repo-tabs': RepoTabs, 'repo-tabs': RepoTabs,
...@@ -47,7 +49,19 @@ function initRepo() { ...@@ -47,7 +49,19 @@ function initRepo() {
'repo-binary-viewer': RepoBinaryViewer, 'repo-binary-viewer': RepoBinaryViewer,
'repo-editor': repoEditorLoader, 'repo-editor': repoEditorLoader,
'repo-commit-section': RepoCommitSection, 'repo-commit-section': RepoCommitSection,
'popup-dialog': PopupDialog,
}, },
methods: {
dialogToggled(toggle) {
this.dialog.open = toggle;
},
dialogSubmitted(status) {
this.dialog.open = false;
this.dialog.status = status;
}
}
}); });
const editButton = document.getElementById('editable-mode'); const editButton = document.getElementById('editable-mode');
......
...@@ -2,10 +2,13 @@ ...@@ -2,10 +2,13 @@
/* global Flash */ /* global Flash */
import Store from './repo_store'; import Store from './repo_store';
import Api from '../api'; import Api from '../api';
import RepoMixin from './repo_mixin'
const RepoCommitSection = { const RepoCommitSection = {
data: () => Store, data: () => Store,
mixins: [RepoMixin],
methods: { methods: {
makeCommit() { makeCommit() {
// see https://docs.gitlab.com/ce/api/commits.html#create-a-commit-with-multiple-files-and-actions // see https://docs.gitlab.com/ce/api/commits.html#create-a-commit-with-multiple-files-and-actions
...@@ -38,14 +41,6 @@ const RepoCommitSection = { ...@@ -38,14 +41,6 @@ const RepoCommitSection = {
}, Store.tempPrivateToken); }, Store.tempPrivateToken);
}, },
}, },
computed: {
changedFiles() {
const changedFileList = this.openedFiles
.filter(file => file.changed);
return changedFileList;
},
},
}; };
export default RepoCommitSection; export default RepoCommitSection;
......
import Vue from 'vue'; import Vue from 'vue';
import Store from './repo_store'; import Store from './repo_store';
import RepoMixin from './repo_mixin'
export default class RepoEditButton { export default class RepoEditButton {
constructor(el) { constructor(el) {
...@@ -9,10 +10,11 @@ export default class RepoEditButton { ...@@ -9,10 +10,11 @@ export default class RepoEditButton {
initVue(el) { initVue(el) {
this.vue = new Vue({ this.vue = new Vue({
el, el,
mixins: [RepoMixin],
data: () => Store, data: () => Store,
computed: { computed: {
buttonLabel() { buttonLabel() {
return this.editMode ? 'Read-only mode' : 'Edit mode'; return this.editMode ? 'Cancel edit' : 'Edit';
}, },
buttonIcon() { buttonIcon() {
...@@ -21,9 +23,25 @@ export default class RepoEditButton { ...@@ -21,9 +23,25 @@ export default class RepoEditButton {
}, },
methods: { methods: {
editClicked() { editClicked() {
console.log('thiscf', this.changedFiles)
if(this.changedFiles.length) {
this.dialog.open = true;
return;
}
this.editMode = !this.editMode; this.editMode = !this.editMode;
}, },
}, },
watch: {
dialog: {
handler(obj) {
if(obj.status) {
obj.status = false;
}
},
deep: true,
}
}
}); });
} }
} }
...@@ -65,7 +65,6 @@ const RepoEditor = { ...@@ -65,7 +65,6 @@ const RepoEditor = {
}, },
editMode() { editMode() {
console.log('edit mode changed')
const readOnly = !this.editMode; const readOnly = !this.editMode;
Store.readOnly = readOnly; Store.readOnly = readOnly;
......
<script> <script>
import Store from './repo_store'; import Store from './repo_store';
import Helper from './repo_helper'; import Helper from './repo_helper';
import RepoMiniMixin from './repo_mini_mixin'; import RepoMixin from './repo_mixin';
const RepoFileButtons = { const RepoFileButtons = {
data: () => Store, data: () => Store,
mixins: [RepoMiniMixin], mixins: [RepoMixin],
computed: { computed: {
editableBorder() { editableBorder() {
......
...@@ -135,7 +135,6 @@ const RepoHelper = { ...@@ -135,7 +135,6 @@ const RepoHelper = {
getContent(treeOrFile, cb) { getContent(treeOrFile, cb) {
let file = treeOrFile; let file = treeOrFile;
console.log('file',file)
// const loadingData = RepoHelper.setLoading(true); // const loadingData = RepoHelper.setLoading(true);
return Service.getContent() return Service.getContent()
.then((response) => { .then((response) => {
......
import Store from './repo_store'; import Store from './repo_store';
const RepoMiniMixin = { const RepoMixin = {
computed: { computed: {
isMini() { isMini() {
return !!Store.openedFiles.length; return !!Store.openedFiles.length;
}, },
changedFiles() {
const changedFileList = this.openedFiles
.filter(file => file.changed);
return changedFileList;
},
}, },
}; };
export default RepoMiniMixin; export default RepoMixin;
...@@ -6,10 +6,10 @@ import RepoPreviousDirectory from './repo_prev_directory.vue'; ...@@ -6,10 +6,10 @@ import RepoPreviousDirectory from './repo_prev_directory.vue';
import RepoFileOptions from './repo_file_options.vue'; import RepoFileOptions from './repo_file_options.vue';
import RepoFile from './repo_file.vue'; import RepoFile from './repo_file.vue';
import RepoLoadingFile from './repo_loading_file.vue'; import RepoLoadingFile from './repo_loading_file.vue';
import RepoMiniMixin from './repo_mini_mixin'; import RepoMixin from './repo_mixin';
const RepoSidebar = { const RepoSidebar = {
mixins: [RepoMiniMixin], mixins: [RepoMixin],
components: { components: {
'repo-file-options': RepoFileOptions, 'repo-file-options': RepoFileOptions,
'repo-previous-directory': RepoPreviousDirectory, 'repo-previous-directory': RepoPreviousDirectory,
......
...@@ -29,6 +29,11 @@ const RepoStore = { ...@@ -29,6 +29,11 @@ const RepoStore = {
tempPrivateToken: '', tempPrivateToken: '',
submitCommitsLoading: false, submitCommitsLoading: false,
binaryLoaded:false, binaryLoaded:false,
dialog: {
open: false,
title: '',
status: false,
},
activeFile: RepoHelper.getDefaultActiveFile(), activeFile: RepoHelper.getDefaultActiveFile(),
activeFileIndex: 0, activeFileIndex: 0,
activeLine: 0, activeLine: 0,
...@@ -143,7 +148,6 @@ const RepoStore = { ...@@ -143,7 +148,6 @@ const RepoStore = {
// now activate the right tab based on what you closed. // now activate the right tab based on what you closed.
if(RepoStore.openedFiles.length === 0) { if(RepoStore.openedFiles.length === 0) {
console.log('open 0')
RepoStore.activeFile = {}; RepoStore.activeFile = {};
return; return;
} }
......
...@@ -2,10 +2,10 @@ ...@@ -2,10 +2,10 @@
import Vue from 'vue'; import Vue from 'vue';
import Store from './repo_store'; import Store from './repo_store';
import RepoTab from './repo_tab.vue'; import RepoTab from './repo_tab.vue';
import RepoMiniMixin from './repo_mini_mixin'; import RepoMixin from './repo_mixin';
const RepoTabs = { const RepoTabs = {
mixins: [RepoMiniMixin], mixins: [RepoMixin],
components: { components: {
'repo-tab': RepoTab, 'repo-tab': RepoTab,
......
<script>
const PopupDialog = {
name: 'popup-dialog',
props: {
open: Boolean,
title: String,
body: String,
kind: {
type: String,
default: 'primary',
},
closeButtonLabel: {
type: String,
default: 'Cancel',
},
primaryButtonLabel: {
type: String,
default: 'Save changes',
},
},
computed: {
typeOfClass() {
const className = `btn-${this.kind}`;
let returnObj = {};
returnObj[className] = true;
return returnObj;
}
},
methods: {
close() {
this.$emit('toggle', false);
},
yesClick() {
this.$emit('submit', true);
},
noClick() {
this.$emit('submit', false);
}
}
};
export default PopupDialog;
</script>
<template>
<div class="modal popup-dialog" tabindex="-1" v-show="open" role="dialog">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" @click="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title">{{this.title}}</h4>
</div>
<div class="modal-body">
<p>{{this.body}}</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal" @click="noClick">{{closeButtonLabel}}</button>
<button type="button" class="btn" :class="typeOfClass" @click="yesClick">{{primaryButtonLabel}}</button>
</div>
</div>
</div>
</div>
</template>
\ No newline at end of file
...@@ -7,6 +7,22 @@ ...@@ -7,6 +7,22 @@
transition: opacity .5s; transition: opacity .5s;
} }
.modal.popup-dialog {
display: block;
@media (min-width: 992px) {
.modal-dialog {
width: 600px;
margin: 30px auto;
}
}
}
.project-refs-form, .project-refs-target-form {
display: inline-block;
}
.fade-enter, .fade-enter,
.fade-leave-to /* .fade-leave-active in <2.1.8 */ { .fade-leave-to /* .fade-leave-active in <2.1.8 */ {
opacity: 0; opacity: 0;
...@@ -55,7 +71,6 @@ ...@@ -55,7 +71,6 @@
} }
#tabs { #tabs {
height: 61px;
border-bottom: 1px solid $white-normal; border-bottom: 1px solid $white-normal;
padding-left: 0; padding-left: 0;
margin-bottom: 0; margin-bottom: 0;
...@@ -65,14 +80,6 @@ ...@@ -65,14 +80,6 @@
overflow-y: hidden; overflow-y: hidden;
overflow-x: auto; overflow-x: auto;
&.overflown {
height: 61px;
li {
padding: 20px 18px;
}
}
li { li {
animation: swipeRightAppear ease-in 0.1s; animation: swipeRightAppear ease-in 0.1s;
animation-iteration-count: 1; animation-iteration-count: 1;
...@@ -80,9 +87,10 @@ ...@@ -80,9 +87,10 @@
list-style-type: none; list-style-type: none;
background: $gray-normal; background: $gray-normal;
display: inline-block; display: inline-block;
padding: 20px 18px; padding: 10px 18px;
border-right: 1px solid $border-color; border-right: 1px solid $border-color;
white-space: nowrap; white-space: nowrap;
border-radius: 3px 3px 0 0;
&.active { &.active {
background: $white-light; background: $white-light;
......
...@@ -220,13 +220,29 @@ class ProjectsController < Projects::ApplicationController ...@@ -220,13 +220,29 @@ class ProjectsController < Projects::ApplicationController
end end
def refs def refs
branches = BranchesFinder.new(@repository, params).execute.map(&:name) find_refs = params['find']
find_branches = true
find_tags = true
find_commits = true
if !find_refs.nil?
find_branches = find_refs.include? 'branches'
find_tags = find_refs.include? 'tags'
find_commits = find_refs.include? 'commits'
end
options = { branches = []
s_('RefSwitcher|Branches') => branches.take(100) options = {}
}
if find_branches
branches = BranchesFinder.new(@repository, params).execute.map(&:name)
options = {
s_('RefSwitcher|Branches') => branches.take(100)
}
end
unless @repository.tag_count.zero? if @repository.tag_count.nonzero? && find_tags
tags = TagsFinder.new(@repository, params).execute.map(&:name) tags = TagsFinder.new(@repository, params).execute.map(&:name)
options[s_('RefSwitcher|Tags')] = tags.take(100) options[s_('RefSwitcher|Tags')] = tags.take(100)
...@@ -234,7 +250,7 @@ class ProjectsController < Projects::ApplicationController ...@@ -234,7 +250,7 @@ class ProjectsController < Projects::ApplicationController
# If reference is commit id - we should add it to branch/tag selectbox # If reference is commit id - we should add it to branch/tag selectbox
ref = Addressable::URI.unescape(params[:ref]) ref = Addressable::URI.unescape(params[:ref])
if ref && options.flatten(2).exclude?(ref) && ref =~ /\A[0-9a-zA-Z]{6,52}\z/ if ref && options.flatten(2).exclude?(ref) && ref =~ /\A[0-9a-zA-Z]{6,52}\z/ && find_commits
options['Commits'] = [ref] options['Commits'] = [ref]
end end
......
...@@ -48,11 +48,11 @@ module DropdownsHelper ...@@ -48,11 +48,11 @@ module DropdownsHelper
end end
end end
def dropdown_title(title, back: false) def dropdown_title(title, options: {})
content_tag :div, class: "dropdown-title" do content_tag :div, class: "dropdown-title" do
title_output = "" title_output = ""
if back if options.fetch(:back, false)
title_output << content_tag(:button, class: "dropdown-title-button dropdown-menu-back", aria: { label: "Go back" }, type: "button") do title_output << content_tag(:button, class: "dropdown-title-button dropdown-menu-back", aria: { label: "Go back" }, type: "button") do
icon('arrow-left') icon('arrow-left')
end end
...@@ -60,14 +60,25 @@ module DropdownsHelper ...@@ -60,14 +60,25 @@ module DropdownsHelper
title_output << content_tag(:span, title) title_output << content_tag(:span, title)
title_output << content_tag(:button, class: "dropdown-title-button dropdown-menu-close", aria: { label: "Close" }, type: "button") do if options.fetch(:close, true)
icon('times', class: 'dropdown-menu-close-icon') title_output << content_tag(:button, class: "dropdown-title-button dropdown-menu-close", aria: { label: "Close" }, type: "button") do
icon('times', class: 'dropdown-menu-close-icon')
end
end end
title_output.html_safe title_output.html_safe
end end
end end
def dropdown_input(placeholder, input_id: nil)
content_tag :div, class: "dropdown-input" do
filter_output = search_field_tag input_id, nil, class: "dropdown-input-field dropdown-no-filter", placeholder: placeholder, autocomplete: 'off'
filter_output << icon('times', class: "dropdown-input-clear js-dropdown-input-clear", role: "button")
filter_output.html_safe
end
end
def dropdown_filter(placeholder, search_id: nil) def dropdown_filter(placeholder, search_id: nil)
content_tag :div, class: "dropdown-input" do content_tag :div, class: "dropdown-input" do
filter_output = search_field_tag search_id, nil, class: "dropdown-input-field", placeholder: placeholder, autocomplete: 'off' filter_output = search_field_tag search_id, nil, class: "dropdown-input-field", placeholder: placeholder, autocomplete: 'off'
......
.tree-ref-container .tree-ref-container
.tree-ref-holder .tree-ref-holder
= render 'shared/ref_switcher', destination: 'tree', path: @path = render 'shared/ref_switcher', destination: 'tree', path: @path
=icon('long-arrow-right', title: 'to target branch')
= render 'shared/target_switcher', destination: 'tree', path: @path
.tree-controls .tree-controls
%a.btn.btn-default#editable-mode{ "href"=>"#", "@click.prevent" => "editClicked", "v-cloak" => 1, "v-if" => "isCommitable" } %a.btn.btn-default#editable-mode{ "href"=>"#", "@click.prevent" => "editClicked", "v-cloak" => 1, "v-if" => "isCommitable" }
......
- dropdown_toggle_text = @ref || @project.default_branch
= form_tag nil, method: :get, class: "project-refs-target-form" do
= hidden_field_tag :destination, destination
- if defined?(path)
= hidden_field_tag :path, path
- @options && @options.each do |key, value|
= hidden_field_tag key, value, id: nil
.dropdown
= dropdown_toggle dropdown_toggle_text, { toggle: "dropdown", selected: dropdown_toggle_text, ref: @ref, refs_url: refs_project_path(@project, find: ['branches']), field_name: 'ref', submit_form_on_click: true, visit: false }, { toggle_class: "js-project-refs-dropdown" }
%ul.dropdown-menu.dropdown-menu-selectable.git-revision-dropdown{ class: ("dropdown-menu-align-right" if local_assigns[:align_right]) }
%li
= dropdown_title _("Create a new branch")
%li
= dropdown_input _("Create a new branch")
%li
= dropdown_title _("Select existing branch"), {close: false}
%li
= dropdown_filter _("Search branches and tags")
= dropdown_content
= dropdown_loading
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment