Skip to content

Commit

Permalink
Feature/mrsimpson#23 title first message to new request (RocketChat#149)
Browse files Browse the repository at this point in the history
* Request title and first message while creating new request
* Make titles of inputs and placeholders more consistent
* Fix display issues:

- Dropdown overlapped by input field
- In English, the width of the creation dialog was not 100%, thus input fields within too narrow

* Minor corrections with respect to error handling:

- Refactor error display to an own template
- Show error if selected expertise on request creation is invalid (not chosen from the dropdown)
- Fix positioning of "at" on members selection if invalid
  • Loading branch information
vickyokrm authored and mrsimpson committed Nov 16, 2017
1 parent bbcb41c commit 484b04c
Show file tree
Hide file tree
Showing 11 changed files with 245 additions and 54 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ <h1 class="create-channel__title">{{_ "Expertises"}}</h1>
<div class="create-channel__inputs">
<div class="rc-input {{#if invalidChannel}}rc-input--error{{/if}}">
<label class="rc-input__label">
<div class="rc-input__title">{{_ "Expertise_title"}}</div>
<div class="rc-input__title">{{_ "Name"}}</div>
<div class="rc-input__wrapper">
<div class="rc-input__icon">
{{> icon block="rc-input__icon-svg" icon="flag" }}
Expand All @@ -17,17 +17,12 @@ <h1 class="create-channel__title">{{_ "Expertises"}}</h1>
</div>
</label>
{{#if inUse}}
<div class="rc-input__error">
<div class="rc-input__error-icon">
{{> icon block="rc-input__error-icon" icon="warning" classes="rc-input__error-icon-svg"}}
</div>
<div class="rc-input__error-message">{{_ "Channel_already_exist_static"}}</div>
</div>
{{> AssistifyCreateInputError text="Channel_already_exist_static"}}
{{/if}}
</div>
<div class="rc-input">
<label class="rc-input__label">
<div class="rc-input__title">{{_ "Choose_experts"}}</div>
<div class="rc-input__title">{{_ "Experts"}}</div>
<div class="rc-input__wrapper">
<div class="rc-input__icon">
{{> icon block="rc-input__icon-svg" icon="at"}}
Expand All @@ -36,18 +31,13 @@ <h1 class="create-channel__title">{{_ "Expertises"}}</h1>
{{#each user in selectedUsers}}
{{> tag user}}
{{/each}}
<input type="text" class="rc-tags__input {{#if invalidMembers}}rc-input--error{{/if}}" placeholder="{{_ "Experts"}}"
<input type="text" class="rc-tags__input {{#if invalidMembers}}rc-input--error{{/if}}" placeholder="{{_ "Choose_experts"}}"
name="experts" autocomplete="off"/>
</div>
{{#if invalidMembers}}
<div class="rc-input__error">
<div class="rc-input__error-icon">
{{> icon block="rc-input__error-icon" icon="warning" classes="rc-input__error-icon-svg"}}
</div>
<div class="rc-input__error-message">{{_ "Expertise_needs_experts"}}</div>
</div>
{{/if}}
</div>
{{#if invalidMembers}}
{{> AssistifyCreateInputError text="Expertise_needs_experts"}}
{{/if}}
{{#with config}}
{{#if autocomplete 'isShowing'}}
<div class="fadeInDown">
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<template name="AssistifyCreateInputError">
<div class="rc-input__error">
<div class="rc-input__error-icon">
{{> icon block="rc-input__error-icon" icon="warning" classes="rc-input__error-icon-svg"}}
</div>
<div class="rc-input__error-message">{{_ text}}</div>
</div>
</template>
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,23 @@ <h1 class="create-channel__title">{{_ "Requests"}}</h1>
<div class="create-channel__inputs">
<div class="rc-input">
<label class="rc-input__label">
<div class="rc-input__title">{{_ "New_request_for_expertise"}}</div>
<div class="rc-input__title">{{_ "Expertise"}}</div>
<div class="rc-input__wrapper">
<div class="rc-input__icon">
<svg class="rc-icon rc-input__icon-svg rc-input__icon-svg--lock" aria-hidden="true">
<use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#icon-lock"></use>
</svg>
</div>
<input name="expertise" type="text" class="rc-input__element" id="expertise-search" placeholder="Expertise" autocomplete=off value={{expertise}}>
<input name="expertise" type="text" class="rc-input__element" id="expertise-search"
placeholder={{_ "New_request_for_expertise"}} autocomplete=off value={{expertise}}>
</div>
{{#unless autocomplete 'isShowing'}}
{{#if expertise}}
{{#unless validExpertise}}
{{> AssistifyCreateInputError text="Expertise_does_not_exist"}}
{{/unless}}
{{/if}}
{{/unless}}
{{#with config}}
{{#if autocomplete 'isShowing'}}
<div class="fadeInDown">
Expand All @@ -25,10 +33,43 @@ <h1 class="create-channel__title">{{_ "Requests"}}</h1>
</div>
{{/if}}
{{/with}}
<input class="rc-button rc-button--primary js-save-request" type="submit" data-button="create"
value="{{_ "Create"}}" {{createIsDisabled}}>
</label>

</div>
<div class="rc-input {{#if requestTitleError}}rc-input--error{{/if}}">
<label class="rc-input__label">
<div class="rc-input__title">{{_ "Name"}}</div>
<div class="rc-input__wrapper">
<div class="rc-input__icon">
<svg class="rc-icon rc-input__icon-svg rc-input__icon-svg--flag" aria-hidden="true">
<use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#icon-flag"></use>
</svg>
</div>
<input name="request_title" type="text" class="rc-input__element" id="request_title"
placeholder={{_ "New_request_title"}} autocomplete="off">
</div>
</label>
{{#if requestTitleInUse}}
{{> AssistifyCreateInputError text="Request_already_exists"}}
{{/if}}
{{#if invalidTitle}}
{{> AssistifyCreateInputError text="Request_no_special_char"}}
{{/if}}
</div>
<div class="rc-input">
<label class="rc-input__label">
<div class="rc-input__title">{{_ "Your_question"}}</div>
<div class="rc-input__wrapper">
<div class="rc-input__icon">
{{> icon block="rc-input__icon-svg" icon="send"}}
</div>
<input name="first_question" type="text" class="rc-input__element" id="first_question"
placeholder={{_ "New_request_first_question"}} autocomplete="off">
</div>
</label>
</div>
<div class="rc-input">
<input class="rc-button rc-button--primary js-save-request" type="submit" data-button="create"
value="{{_ "Create"}}" {{createIsDisabled}}>
</div>
</div>
</form>
Expand All @@ -37,5 +78,5 @@ <h1 class="create-channel__title">{{_ "Requests"}}</h1>
<template name="AssistifyCreateRequestAutocomplete">
<li class="rc-popup-list__item">
<span class="rc-popup-list__item-name">{{{modifier item.name}}}</span>
</li>
</li>
</template>
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,22 @@
import {RocketChat} from 'meteor/rocketchat:lib';
import {FlowRouter} from 'meteor/kadira:flow-router';
import {ReactiveVar} from 'meteor/reactive-var';
import toastr from 'toastr';

const validateRequestName = (name) => {
if (RocketChat.settings.get('UI_Allow_room_names_with_special_chars')) {
return true;
} else {
const reg = new RegExp(`^${ RocketChat.settings.get('UTF8_Names_Validation') }$`);
return name.length === 0 || reg.test(name);
}
};

const acEvents = {
'click .rc-popup-list__item'(e, t) {
t.ac.onItemClick(this, e);
},
'keydown [name="expertise"]'(e, t) {
if ([8, 46].includes(e.keyCode) && e.target.value === '') {
const users = t.selectedUsers;
const usersArr = users.get();
usersArr.pop();
return users.set(usersArr);
}

t.ac.onKeyDown(e);
},
'keyup [name="expertise"]'(e, t) {
Expand All @@ -28,6 +31,7 @@ const acEvents = {
}
};


Template.AssistifyCreateRequest.helpers({
autocomplete(key) {
const instance = Template.instance();
Expand Down Expand Up @@ -57,14 +61,47 @@ Template.AssistifyCreateRequest.helpers({
createIsDisabled() {
const instance = Template.instance();

if (instance.validExpertise.get()) {
return '';
} else {
return 'disabled';
if (!instance.requestTitle.get()) {
if (instance.validExpertise.get()) {
return '';
} else {
return 'disabled';
}
} else if (instance.requestTitle.get()) {
if (instance.validExpertise.get() && !instance.requestTitleInUse.get() && !instance.invalidTitle.get()) {
return '';
} else {
return 'disabled';
}
}
},
invalidTitle() {
const instance = Template.instance();
return instance.invalidTitle.get();
},
requestTitleInUse() {
const instance = Template.instance();
return instance.requestTitleInUse.get();
},
validExpertise() {
const instance = Template.instance();
return instance.validExpertise.get();
},
expertise() {
const instance = Template.instance();
return instance.expertise.get();
},
requestTitleError() {
const instance = Template.instance();
return instance.invalidTitle.get() || instance.requestTitleInUse.get();
}
// noSplCharAllowed() {
// const instance = Template.instance();
// return instance.noSplCharAllowed.get();
// }
});


Template.AssistifyCreateRequest.events({
...acEvents,
'input #expertise-search'(e, t) {
Expand All @@ -73,20 +110,62 @@ Template.AssistifyCreateRequest.events({
const length = input.value.length;
document.activeElement === input && e && /input/i.test(e.type) && (input.selectionEnd = position + input.value.length - length);
if (input.value) {
t.delaySetExpertise(input.value);
t.checkExpertise(input.value);
t.expertise.set(input.value);
} else {
t.validExpertise.set(false);
t.delaySetExpertise(false);
t.expertise.set('');
}
if (t.expertise.get() && t.requestTitle.get()) {
const requestName = `${ t.expertise.get() }-${ t.requestTitle.get() }`;
t.invalidTitle.set(!validateRequestName(requestName));
t.requestTitleInUse.set(undefined);
t.checkRequestName(requestName);
}
},
'input #request_title'(e, t) {
const input = e.target;
//const length = input.value.length;
if (input.value !== t.requestTitle.get()) {
t.requestTitle.set(input.value);
} else {
t.requestTitle.set(false);
}

if (t.expertise.get() && input.value) {
const requestName = `${ input.value }`;
t.invalidTitle.set(!validateRequestName(requestName));
if (RocketChat.settings.get('UI_Allow_room_names_with_special_chars')) {
t.checkRequestDisplayName(requestName);
} else {
t.checkRequestName(requestName);
}
// t.invalidTitle.set(!validateRequestName(requestName));
// t.checkRequestName(requestName);
t.requestTitleInUse.set(undefined);
} else if (!input.value) {
t.invalidTitle.set(false);
t.requestTitleInUse.set(undefined);
}

},
'input #first_question'(e, t) {
const input = e.target;
//const length = input.value.length;
if (input.value) {
t.openingQuestion.set(input.value);
} else {
t.openingQuestion.set(false);
}
},
'submit create-channel__content, click .js-save-request'(event, instance) {
event.preventDefault();
const expertise = instance.expertise.get();

const requestTitle = instance.requestTitle.get();
const openingQuestion = instance.openingQuestion.get();
if (expertise) {
instance.errorMessage.set(null);
Meteor.call('createRequest', '', expertise, (err, result) => {
Meteor.call('createRequest', requestTitle, expertise, openingQuestion, (err, result) => {
if (err) {
console.log(err);
switch (err.error) {
Expand All @@ -99,11 +178,17 @@ Template.AssistifyCreateRequest.events({
case 'error-archived-duplicate-name':
toastr.error(TAPi18n.__('Duplicate_archived_channel_name', name));
return;
case 'error-invalid-room-name':
console.log('room name slug error');
// toastr.error(TAPi18n.__('Duplicate_archived_channel_name', name));
toastr.error(TAPi18n.__('Invalid_room_name', err.details.channel_name));
return;
default:
return handleError(err);
}
}

console.log('Room Created');
toastr.success(TAPi18n.__('New_request_created'));
const roomCreated = RocketChat.models.Rooms.findOne({_id: result.rid});
FlowRouter.go('request', {name: roomCreated.name}, FlowRouter.current().queryParams);
});
Expand Down Expand Up @@ -133,8 +218,34 @@ Template.AssistifyCreateRequest.onCreated(function() {
instance.expertise = new ReactiveVar(''); //the value of the text field
instance.validExpertise = new ReactiveVar(false);
instance.errorMessage = new ReactiveVar(null);

this.checkExpertise = _.debounce((expertise) => {
instance.requestTitle = new ReactiveVar('');
instance.openingQuestion = new ReactiveVar('');
instance.requestTitleInUse = new ReactiveVar(undefined);
instance.invalidTitle = new ReactiveVar(false);
instance.error = new ReactiveVar(null);
instance.checkRequestName = _.debounce((name) => {
if (validateRequestName(name)) {
return Meteor.call('roomNameExists', name, (error, result) => {
if (error) {
return;
}
instance.requestTitleInUse.set(result);
});
}
instance.requestTitleInUse.set(undefined);
}, 500);
instance.checkRequestDisplayName = _.debounce((name) => {
if (validateRequestName(name)) {
return Meteor.call('roomDisplayNameExists', name, (error, result) => {
if (error) {
return;
}
instance.requestTitleInUse.set(result);
});
}
instance.requestTitleInUse.set(undefined);
}, 500);
instance.checkExpertise = _.debounce((expertise) => {
return Meteor.call('assistify:isValidExpertise', expertise, (error, result) => {
if (error) {
instance.validExpertise.set(false);
Expand All @@ -143,6 +254,9 @@ Template.AssistifyCreateRequest.onCreated(function() {
}
});
}, 500);
instance.delaySetExpertise = _.debounce((expertise) => {
instance.expertise.set(expertise);
}, 200);

// instance.clearForm = function() {
// instance.requestRoomName.set('');
Expand Down
1 change: 1 addition & 0 deletions packages/assistify-help-request/package.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ Package.onUse(function(api) {
api.addFiles('client/views/creationDialog/AssistifyCreateRequest.js', 'client');
api.addFiles('client/views/creationDialog/AssistifyCreateExpertise.html', 'client');
api.addFiles('client/views/creationDialog/AssistifyCreateExpertise.js', 'client');
api.addFiles('client/views/creationDialog/AssistifyCreateInputError.html', 'client');
api.addFiles('client/views/sideNav/requests.html', 'client');
api.addFiles('client/views/sideNav/requests.js', 'client');
api.addFiles('client/views/sideNav/expertise.html', 'client');
Expand Down
Loading

0 comments on commit 484b04c

Please sign in to comment.