Finished up mattermost team creation
This commit is contained in:
parent
479cdc2cac
commit
173e27d62a
9 changed files with 289 additions and 15 deletions
48
app/assets/javascripts/behaviors/bind_in_out.js.es6
Normal file
48
app/assets/javascripts/behaviors/bind_in_out.js.es6
Normal file
|
@ -0,0 +1,48 @@
|
|||
class BindInOut {
|
||||
constructor(bindIn, bindOut) {
|
||||
this.in = bindIn;
|
||||
this.out = bindOut;
|
||||
|
||||
this.eventWrapper = {};
|
||||
this.eventType = /(INPUT|TEXTAREA)/.test(bindIn.tagName) ? 'keyup' : 'change';
|
||||
}
|
||||
|
||||
addEvents() {
|
||||
this.eventWrapper.updateOut = this.updateOut.bind(this);
|
||||
|
||||
this.in.addEventListener(this.eventType, this.eventWrapper.updateOut);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
updateOut() {
|
||||
this.out.textContent = this.in.value;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
removeEvents() {
|
||||
this.in.removeEventListener(this.eventType, this.eventWrapper.updateOut);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
static initAll() {
|
||||
const ins = document.querySelectorAll('*[data-bind-in]');
|
||||
|
||||
return [].map.call(ins, anIn => BindInOut.init(anIn));
|
||||
}
|
||||
|
||||
static init(anIn, anOut) {
|
||||
const out = anOut || document.querySelector(`*[data-bind-out="${anIn.dataset.bindIn}"]`);
|
||||
const bindInOut = new BindInOut(anIn, out);
|
||||
|
||||
return bindInOut.addEvents().updateOut();
|
||||
}
|
||||
}
|
||||
|
||||
const global = window.gl || (window.gl = {});
|
||||
|
||||
global.BindInOut = BindInOut;
|
||||
|
||||
module.exports = BindInOut;
|
|
@ -22,7 +22,6 @@
|
|||
// %div.js-toggle-content
|
||||
//
|
||||
$('body').on('click', '.js-toggle-button', function(e) {
|
||||
e.preventDefault();
|
||||
toggleContainer($(this).closest('.js-toggle-container'));
|
||||
});
|
||||
|
||||
|
|
|
@ -216,6 +216,7 @@ const ShortcutsBlob = require('./shortcuts_blob');
|
|||
case 'admin:groups:edit':
|
||||
case 'admin:groups:new':
|
||||
new GroupAvatar();
|
||||
gl.BindInOut.initAll();
|
||||
break;
|
||||
case 'projects:tree:show':
|
||||
shortcut_handler = new ShortcutsNavigation();
|
||||
|
|
|
@ -81,7 +81,6 @@ class GroupsController < Groups::ApplicationController
|
|||
end
|
||||
|
||||
def update
|
||||
byebug
|
||||
if Groups::UpdateService.new(@group, current_user, group_params).execute
|
||||
redirect_to edit_group_path(@group), notice: "Group '#{@group.name}' was successfully updated."
|
||||
else
|
||||
|
@ -143,7 +142,7 @@ class GroupsController < Groups::ApplicationController
|
|||
:request_access_enabled,
|
||||
:share_with_group_lock,
|
||||
:visibility_level,
|
||||
:parent_id
|
||||
:parent_id,
|
||||
:create_chat_team,
|
||||
:chat_team_name
|
||||
]
|
||||
|
|
|
@ -4,15 +4,13 @@
|
|||
= custom_icon('icon_mattermost')
|
||||
Mattermost
|
||||
.col-sm-10
|
||||
.checkbox
|
||||
.checkbox.js-toggle-container
|
||||
= f.label :create_chat_team do
|
||||
= f.check_box(:create_chat_team, { checked: @group.chat_team }, 'true', 'false')
|
||||
Link the group to a new Mattermost team
|
||||
|
||||
.form-group
|
||||
= f.label :chat_team, class: 'control-label' do
|
||||
Chat Team name
|
||||
.col-sm-10
|
||||
= f.text_field :chat_team, placeholder: @group.chat_team, class: 'form-control mattermost-team-name'
|
||||
%small
|
||||
Leave blank to match your group name
|
||||
.js-toggle-button= f.check_box(:create_chat_team, { checked: true }, 'true', 'false')
|
||||
Create a Mattermost team for this group
|
||||
%br
|
||||
%small.light.js-toggle-content
|
||||
Team URL:
|
||||
= Settings.mattermost.host
|
||||
%span> /
|
||||
%span{ "data-bind-out" => "create_chat_team"}
|
||||
|
|
|
@ -18,7 +18,8 @@
|
|||
= f.text_field :path, placeholder: 'open-source', class: 'form-control',
|
||||
autofocus: local_assigns[:autofocus] || false, required: true,
|
||||
pattern: Gitlab::Regex::NAMESPACE_REGEX_STR_SIMPLE,
|
||||
title: 'Please choose a group name with no special characters.'
|
||||
title: 'Please choose a group name with no special characters.',
|
||||
"data-bind-in" => "#{'create_chat_team' if Gitlab.config.mattermost.enabled}"
|
||||
- if parent
|
||||
= f.hidden_field :parent_id, value: parent.id
|
||||
|
||||
|
|
|
@ -43,6 +43,43 @@ feature 'Group', feature: true do
|
|||
expect(page).to have_namespace_error_message
|
||||
end
|
||||
end
|
||||
|
||||
describe 'Mattermost team creation' do
|
||||
before do
|
||||
Settings.mattermost['enabled'] = mattermost_enabled
|
||||
visit new_group_path
|
||||
end
|
||||
|
||||
context 'Mattermost enabled' do
|
||||
let(:mattermost_enabled) { true }
|
||||
|
||||
it 'displays a team creation checkbox' do
|
||||
expect(page).to have_selector('#group_create_chat_team')
|
||||
end
|
||||
|
||||
it 'checks the checkbox by default' do
|
||||
expect(find('#group_create_chat_team')['checked']).to eq(true)
|
||||
end
|
||||
|
||||
it 'updates the team URL on graph path update', :js do
|
||||
out_span = find('span[data-bind-out="create_chat_team"]')
|
||||
|
||||
expect(out_span.text).to be_empty
|
||||
|
||||
fill_in('group_path', with: 'test-group')
|
||||
|
||||
expect(out_span.text).to eq('test-group')
|
||||
end
|
||||
end
|
||||
|
||||
context 'Mattermost disabled' do
|
||||
let(:mattermost_enabled) { false }
|
||||
|
||||
it 'doesnt show a team creation checkbox if Mattermost not enabled' do
|
||||
expect(page).not_to have_selector('#group_create_chat_team')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'create a nested group' do
|
||||
|
|
189
spec/javascripts/behaviors/bind_in_out_spec.js.es6
Normal file
189
spec/javascripts/behaviors/bind_in_out_spec.js.es6
Normal file
|
@ -0,0 +1,189 @@
|
|||
const BindInOut = require('~/behaviors/bind_in_out');
|
||||
const ClassSpecHelper = require('../helpers/class_spec_helper');
|
||||
|
||||
describe('BindInOut', function () {
|
||||
describe('.constructor', function () {
|
||||
beforeEach(function () {
|
||||
this.in = {};
|
||||
this.out = {};
|
||||
|
||||
this.bindInOut = new BindInOut(this.in, this.out);
|
||||
});
|
||||
|
||||
it('should set .in', function () {
|
||||
expect(this.bindInOut.in).toBe(this.in);
|
||||
});
|
||||
|
||||
it('should set .out', function () {
|
||||
expect(this.bindInOut.out).toBe(this.out);
|
||||
});
|
||||
|
||||
it('should set .eventWrapper', function () {
|
||||
expect(this.bindInOut.eventWrapper).toEqual({});
|
||||
});
|
||||
|
||||
describe('if .in is an input', function () {
|
||||
beforeEach(function () {
|
||||
this.bindInOut = new BindInOut({ tagName: 'INPUT' });
|
||||
});
|
||||
|
||||
it('should set .eventType to keyup ', function () {
|
||||
expect(this.bindInOut.eventType).toEqual('keyup');
|
||||
});
|
||||
});
|
||||
|
||||
describe('if .in is a textarea', function () {
|
||||
beforeEach(function () {
|
||||
this.bindInOut = new BindInOut({ tagName: 'TEXTAREA' });
|
||||
});
|
||||
|
||||
it('should set .eventType to keyup ', function () {
|
||||
expect(this.bindInOut.eventType).toEqual('keyup');
|
||||
});
|
||||
});
|
||||
|
||||
describe('if .in is not an input or textarea', function () {
|
||||
beforeEach(function () {
|
||||
this.bindInOut = new BindInOut({ tagName: 'SELECT' });
|
||||
});
|
||||
|
||||
it('should set .eventType to change ', function () {
|
||||
expect(this.bindInOut.eventType).toEqual('change');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('.addEvents', function () {
|
||||
beforeEach(function () {
|
||||
this.in = jasmine.createSpyObj('in', ['addEventListener']);
|
||||
|
||||
this.bindInOut = new BindInOut(this.in);
|
||||
|
||||
this.addEvents = this.bindInOut.addEvents();
|
||||
});
|
||||
|
||||
it('should set .eventWrapper.updateOut', function () {
|
||||
expect(this.bindInOut.eventWrapper.updateOut).toEqual(jasmine.any(Function));
|
||||
});
|
||||
|
||||
it('should call .addEventListener', function () {
|
||||
expect(this.in.addEventListener)
|
||||
.toHaveBeenCalledWith(
|
||||
this.bindInOut.eventType,
|
||||
this.bindInOut.eventWrapper.updateOut,
|
||||
);
|
||||
});
|
||||
|
||||
it('should return the instance', function () {
|
||||
expect(this.addEvents).toBe(this.bindInOut);
|
||||
});
|
||||
});
|
||||
|
||||
describe('.updateOut', function () {
|
||||
beforeEach(function () {
|
||||
this.in = { value: 'the-value' };
|
||||
this.out = { textContent: 'not-the-value' };
|
||||
|
||||
this.bindInOut = new BindInOut(this.in, this.out);
|
||||
|
||||
this.updateOut = this.bindInOut.updateOut();
|
||||
});
|
||||
|
||||
it('should set .out.textContent to .in.value', function () {
|
||||
expect(this.out.textContent).toBe(this.in.value);
|
||||
});
|
||||
|
||||
it('should return the instance', function () {
|
||||
expect(this.updateOut).toBe(this.bindInOut);
|
||||
});
|
||||
});
|
||||
|
||||
describe('.removeEvents', function () {
|
||||
beforeEach(function () {
|
||||
this.in = jasmine.createSpyObj('in', ['removeEventListener']);
|
||||
this.updateOut = () => {};
|
||||
|
||||
this.bindInOut = new BindInOut(this.in);
|
||||
this.bindInOut.eventWrapper.updateOut = this.updateOut;
|
||||
|
||||
this.removeEvents = this.bindInOut.removeEvents();
|
||||
});
|
||||
|
||||
it('should call .removeEventListener', function () {
|
||||
expect(this.in.removeEventListener)
|
||||
.toHaveBeenCalledWith(
|
||||
this.bindInOut.eventType,
|
||||
this.updateOut,
|
||||
);
|
||||
});
|
||||
|
||||
it('should return the instance', function () {
|
||||
expect(this.removeEvents).toBe(this.bindInOut);
|
||||
});
|
||||
});
|
||||
|
||||
describe('.initAll', function () {
|
||||
beforeEach(function () {
|
||||
this.ins = [0, 1, 2];
|
||||
this.instances = [];
|
||||
|
||||
spyOn(document, 'querySelectorAll').and.returnValue(this.ins);
|
||||
spyOn(Array.prototype, 'map').and.callThrough();
|
||||
spyOn(BindInOut, 'init');
|
||||
|
||||
this.initAll = BindInOut.initAll();
|
||||
});
|
||||
|
||||
ClassSpecHelper.itShouldBeAStaticMethod(BindInOut, 'initAll');
|
||||
|
||||
it('should call .querySelectorAll', function () {
|
||||
expect(document.querySelectorAll).toHaveBeenCalledWith('*[data-bind-in]');
|
||||
});
|
||||
|
||||
it('should call .map', function () {
|
||||
expect(Array.prototype.map).toHaveBeenCalledWith(jasmine.any(Function));
|
||||
});
|
||||
|
||||
it('should call .init for each element', function () {
|
||||
expect(BindInOut.init.calls.count()).toEqual(3);
|
||||
});
|
||||
|
||||
it('should return an array of instances', function () {
|
||||
expect(this.initAll).toEqual(jasmine.any(Array));
|
||||
});
|
||||
});
|
||||
|
||||
describe('.init', function () {
|
||||
beforeEach(function () {
|
||||
spyOn(BindInOut.prototype, 'addEvents').and.callFake(function () { return this; });
|
||||
spyOn(BindInOut.prototype, 'updateOut').and.callFake(function () { return this; });
|
||||
|
||||
this.init = BindInOut.init({}, {});
|
||||
});
|
||||
|
||||
ClassSpecHelper.itShouldBeAStaticMethod(BindInOut, 'init');
|
||||
|
||||
it('should call .addEvents', function () {
|
||||
expect(BindInOut.prototype.addEvents).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should call .updateOut', function () {
|
||||
expect(BindInOut.prototype.updateOut).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
describe('if no anOut is provided', function () {
|
||||
beforeEach(function () {
|
||||
this.anIn = { dataset: { bindIn: 'the-data-bind-in' } };
|
||||
|
||||
spyOn(document, 'querySelector');
|
||||
|
||||
BindInOut.init(this.anIn);
|
||||
});
|
||||
|
||||
it('should call .querySelector', function () {
|
||||
expect(document.querySelector)
|
||||
.toHaveBeenCalledWith(`*[data-bind-out="${this.anIn.dataset.bindIn}"]`);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -7,3 +7,5 @@ class ClassSpecHelper {
|
|||
}
|
||||
|
||||
window.ClassSpecHelper = ClassSpecHelper;
|
||||
|
||||
module.exports = ClassSpecHelper;
|
||||
|
|
Loading…
Reference in a new issue