##// END OF EJS Templates
Added mentions autocomplete into main comments form...
marcink -
r2368:5143b8df beta
parent child Browse files
Show More

The requested changes are too big and content was truncated. Show full diff

@@ -47,6 +47,7 b' from rhodecode.model.db import Changeset'
47 47 from rhodecode.model.comment import ChangesetCommentsModel
48 48 from rhodecode.model.meta import Session
49 49 from rhodecode.lib.diffs import wrapped_diff
50 from rhodecode.model.repo import RepoModel
50 51
51 52 log = logging.getLogger(__name__)
52 53
@@ -165,6 +166,9 b' class ChangesetController(BaseRepoContro'
165 166 def __before__(self):
166 167 super(ChangesetController, self).__before__()
167 168 c.affected_files_cut_off = 60
169 repo_model = RepoModel()
170 c.users_array = repo_model.get_users_js()
171 c.users_groups_array = repo_model.get_users_groups_js()
168 172
169 173 def index(self, revision):
170 174
@@ -2820,6 +2820,13 b' table.code-browser .submodule-dir {'
2820 2820 box-shadow: 0 2px 2px rgba(0, 0, 0, 0.6);
2821 2821 }
2822 2822
2823 .mentions-container{
2824 width: 100% !important;
2825 }
2826 .mentions-container .yui-ac-content{
2827 width: 90% !important;
2828 }
2829
2823 2830 .ac {
2824 2831 vertical-align: top;
2825 2832 }
@@ -988,6 +988,189 b' var MembersAutoComplete = function (user'
988 988 }
989 989
990 990
991 var MentionsAutoComplete = function (divid, cont, users_list, groups_list, group_lbl, members_lbl) {
992 var myUsers = users_list;
993 var myGroups = groups_list;
994
995 // Define a custom search function for the DataSource of users
996 var matchUsers = function (sQuery) {
997 var org_sQuery = sQuery;
998 if(this.mentionQuery == null){
999 return []
1000 }
1001 sQuery = this.mentionQuery;
1002 // Case insensitive matching
1003 var query = sQuery.toLowerCase();
1004 var i = 0;
1005 var l = myUsers.length;
1006 var matches = [];
1007
1008 // Match against each name of each contact
1009 for (; i < l; i++) {
1010 contact = myUsers[i];
1011 if ((contact.fname.toLowerCase().indexOf(query) > -1) || (contact.lname.toLowerCase().indexOf(query) > -1) || (contact.nname && (contact.nname.toLowerCase().indexOf(query) > -1))) {
1012 matches[matches.length] = contact;
1013 }
1014 }
1015 return matches
1016 };
1017
1018 //match all
1019 var matchAll = function (sQuery) {
1020 u = matchUsers(sQuery);
1021 return u
1022 };
1023
1024 // DataScheme for owner
1025 var ownerDS = new YAHOO.util.FunctionDataSource(matchUsers);
1026 ownerDS.responseSchema = {
1027 fields: ["id", "fname", "lname", "nname", "gravatar_lnk"]
1028 };
1029
1030 // Instantiate AutoComplete for mentions
1031 var ownerAC = new YAHOO.widget.AutoComplete(divid, cont, ownerDS);
1032 ownerAC.useShadow = false;
1033 ownerAC.resultTypeList = false;
1034 ownerAC.suppressInputUpdate = true;
1035
1036 // Helper highlight function for the formatter
1037 var highlightMatch = function (full, snippet, matchindex) {
1038 return full.substring(0, matchindex)
1039 + "<span class='match'>"
1040 + full.substr(matchindex, snippet.length)
1041 + "</span>" + full.substring(matchindex + snippet.length);
1042 };
1043
1044 // Custom formatter to highlight the matching letters
1045 ownerAC.formatResult = function (oResultData, sQuery, sResultMatch) {
1046 var org_sQuery = sQuery;
1047 if(this.dataSource.mentionQuery != null){
1048 sQuery = this.dataSource.mentionQuery;
1049 }
1050
1051 var query = sQuery.toLowerCase();
1052 var _gravatar = function(res, em, group){
1053 if (group !== undefined){
1054 em = '/images/icons/group.png'
1055 }
1056 tmpl = '<div class="ac-container-wrap"><img class="perm-gravatar-ac" src="{0}"/>{1}</div>'
1057 return tmpl.format(em,res)
1058 }
1059 if (oResultData.fname != undefined) {
1060 var fname = oResultData.fname,
1061 lname = oResultData.lname,
1062 nname = oResultData.nname || "",
1063 // Guard against null value
1064 fnameMatchIndex = fname.toLowerCase().indexOf(query),
1065 lnameMatchIndex = lname.toLowerCase().indexOf(query),
1066 nnameMatchIndex = nname.toLowerCase().indexOf(query),
1067 displayfname, displaylname, displaynname;
1068
1069 if (fnameMatchIndex > -1) {
1070 displayfname = highlightMatch(fname, query, fnameMatchIndex);
1071 } else {
1072 displayfname = fname;
1073 }
1074
1075 if (lnameMatchIndex > -1) {
1076 displaylname = highlightMatch(lname, query, lnameMatchIndex);
1077 } else {
1078 displaylname = lname;
1079 }
1080
1081 if (nnameMatchIndex > -1) {
1082 displaynname = "(" + highlightMatch(nname, query, nnameMatchIndex) + ")";
1083 } else {
1084 displaynname = nname ? "(" + nname + ")" : "";
1085 }
1086
1087 return _gravatar(displayfname + " " + displaylname + " " + displaynname, oResultData.gravatar_lnk);
1088 } else {
1089 return '';
1090 }
1091 };
1092
1093 if(ownerAC.itemSelectEvent){
1094 ownerAC.itemSelectEvent.subscribe(function (sType, aArgs) {
1095
1096 var myAC = aArgs[0]; // reference back to the AC instance
1097 var elLI = aArgs[1]; // reference to the selected LI element
1098 var oData = aArgs[2]; // object literal of selected item's result data
1099 //fill the autocomplete with value
1100 if (oData.nname != undefined) {
1101 //users
1102 //Replace the mention name with replaced
1103 var re = new RegExp();
1104 var org = myAC.getInputEl().value;
1105 var chunks = myAC.dataSource.chunks
1106 // replace middle chunk(the search term) with actuall match
1107 chunks[1] = chunks[1].replace('@'+myAC.dataSource.mentionQuery,
1108 '@'+oData.nname+' ');
1109 myAC.getInputEl().value = chunks.join('')
1110 YUD.get(myAC.getInputEl()).focus(); // Y U NO WORK !?
1111 } else {
1112 //groups
1113 myAC.getInputEl().value = oData.grname;
1114 YUD.get('perm_new_member_type').value = 'users_group';
1115 }
1116 });
1117 }
1118
1119 // in this keybuffer we will gather current value of search !
1120 // since we need to get this just when someone does `@` then we do the
1121 // search
1122 ownerAC.dataSource.chunks = [];
1123 ownerAC.dataSource.mentionQuery = null;
1124
1125 ownerAC.get_mention = function(msg, max_pos) {
1126 var org = msg;
1127 var re = new RegExp('(?:^@|\s@)([a-zA-Z0-9]{1}[a-zA-Z0-9\-\_\.]+)$')
1128 var chunks = [];
1129
1130
1131 // cut first chunk until curret pos
1132 var to_max = msg.substr(0, max_pos);
1133 var at_pos = Math.max(0,to_max.lastIndexOf('@')-1);
1134 var msg2 = to_max.substr(at_pos);
1135
1136 chunks.push(org.substr(0,at_pos))// prefix chunk
1137 chunks.push(msg2) // search chunk
1138 chunks.push(org.substr(max_pos)) // postfix chunk
1139
1140 // clean up msg2 for filtering and regex match
1141 var msg2 = msg2.replace(' ','').replace('\n','');
1142
1143 if(re.test(msg2)){
1144 var unam = re.exec(msg2)[1];
1145 return [unam, chunks];
1146 }
1147 return [null, null];
1148 };
1149 ownerAC.textboxKeyUpEvent.subscribe(function(type, args){
1150
1151 var ac_obj = args[0];
1152 var currentMessage = args[1];
1153 var currentCaretPosition = args[0]._elTextbox.selectionStart;
1154
1155 var unam = ownerAC.get_mention(currentMessage, currentCaretPosition);
1156 var curr_search = null;
1157 if(unam[0]){
1158 curr_search = unam[0];
1159 }
1160
1161 ownerAC.dataSource.chunks = unam[1];
1162 ownerAC.dataSource.mentionQuery = curr_search;
1163
1164 })
1165
1166 return {
1167 ownerDS: ownerDS,
1168 ownerAC: ownerAC,
1169 };
1170 }
1171
1172
1173
991 1174
992 1175 /**
993 1176 * QUICK REPO MENU
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
General Comments 0
You need to be logged in to leave comments. Login now