Skip to content

Commit efc09c4

Browse files
Added search functionality and 6 unit tests
2 parents 4aa0a41 + 09b4429 commit efc09c4

File tree

189 files changed

+1668
-701
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

189 files changed

+1668
-701
lines changed

Gemfile

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,11 +65,12 @@ group :test do
6565
gem 'selenium-webdriver', '~> 3.142.7'
6666
# Easy installation and use of chromedriver to run system tests with Chrome
6767
gem 'chromedriver-helper', '~> 2.1.1'
68+
gem 'test-unit'
6869
end
6970

7071
gem 'docusign_admin', '~> 1.1.0'
7172
gem 'docusign_click', '~> 1.2.2'
72-
gem 'docusign_esign', '~> 3.19.0'
73+
gem 'docusign_esign', '~> 3.20.0'
7374
gem 'docusign_monitor', '~> 1.1.0'
7475
gem 'docusign_rooms', '~> 1.2.0.rc1'
7576
gem 'omniauth-oauth2', '~> 1.7.1'
@@ -78,3 +79,5 @@ gem 'omniauth-rails_csrf_protection'
7879
# Windows does not include zoneinfo files, so bundle the tzinfo-data gem
7980
gem 'tzinfo-data', '~> 1.2022.1', '>= 1.2022.1'
8081
gem 'wdm', '>= 0.1.0', platforms: %i[mingw mswin x64_mingw]
82+
83+
gem "matrix", "~> 0.4.2"

Gemfile.lock

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ GEM
108108
json (~> 2.1, >= 2.1.0)
109109
jwt (~> 2.2, >= 2.2.1)
110110
typhoeus (~> 1.0, >= 1.0.1)
111-
docusign_esign (3.19.0)
111+
docusign_esign (3.20.0)
112112
addressable (~> 2.7, >= 2.7.0)
113113
json (~> 2.1, >= 2.1.0)
114114
jwt (~> 2.2, >= 2.2.1)
@@ -147,12 +147,13 @@ GEM
147147
listen (3.7.1)
148148
rb-fsevent (~> 0.10, >= 0.10.3)
149149
rb-inotify (~> 0.9, >= 0.9.10)
150-
loofah (2.19.0)
150+
loofah (2.19.1)
151151
crass (~> 1.0.2)
152152
nokogiri (>= 1.5.9)
153153
mail (2.7.1)
154154
mini_mime (>= 0.1.1)
155155
marcel (1.0.2)
156+
matrix (0.4.2)
156157
method_source (0.9.2)
157158
mini_mime (1.1.2)
158159
minitest (5.16.3)
@@ -167,9 +168,11 @@ GEM
167168
net-smtp (0.3.2)
168169
net-protocol
169170
nio4r (2.5.8)
170-
nokogiri (1.13.8-x64-mingw-ucrt)
171+
nokogiri (1.13.10-x64-mingw-ucrt)
171172
racc (~> 1.4)
172-
nokogiri (1.13.8-x86_64-darwin)
173+
nokogiri (1.13.10-x86_64-darwin)
174+
racc (~> 1.4)
175+
nokogiri (1.13.10-x86_64-linux)
173176
racc (~> 1.4)
174177
oauth2 (2.0.9)
175178
faraday (>= 0.17.3, < 3.0)
@@ -191,6 +194,7 @@ GEM
191194
parallel (1.22.1)
192195
parser (3.1.2.1)
193196
ast (~> 2.4.1)
197+
power_assert (2.0.1)
194198
pry (0.12.2)
195199
coderay (~> 1.1.0)
196200
method_source (~> 0.9.0)
@@ -201,7 +205,7 @@ GEM
201205
public_suffix (5.0.0)
202206
puma (5.6.5)
203207
nio4r (~> 2.0)
204-
racc (1.6.0)
208+
racc (1.6.1)
205209
rack (2.2.4)
206210
rack-protection (3.0.2)
207211
rack
@@ -224,8 +228,8 @@ GEM
224228
rails-dom-testing (2.0.3)
225229
activesupport (>= 4.2.0)
226230
nokogiri (>= 1.6)
227-
rails-html-sanitizer (1.4.3)
228-
loofah (~> 2.3)
231+
rails-html-sanitizer (1.4.4)
232+
loofah (~> 2.19, >= 2.19.1)
229233
railties (7.0.4)
230234
actionpack (= 7.0.4)
231235
activesupport (= 7.0.4)
@@ -283,6 +287,8 @@ GEM
283287
activesupport (>= 5.2)
284288
sprockets (>= 3.0.0)
285289
sqlite3 (1.4.4)
290+
test-unit (3.5.3)
291+
power_assert
286292
thor (1.2.1)
287293
tilt (2.0.11)
288294
timeout (0.3.0)
@@ -314,6 +320,7 @@ GEM
314320
PLATFORMS
315321
x64-mingw-ucrt
316322
x86_64-darwin-21
323+
x86_64-linux
317324

318325
DEPENDENCIES
319326
bootsnap (~> 1.7.3)
@@ -322,12 +329,13 @@ DEPENDENCIES
322329
chromedriver-helper (~> 2.1.1)
323330
coffee-rails (~> 5.0.0)
324331
docusign_admin (~> 1.1.0)
325-
docusign_click (~> 1.2.0)
326-
docusign_esign (~> 3.19.0)
332+
docusign_click (~> 1.2.2)
333+
docusign_esign (~> 3.20.0)
327334
docusign_monitor (~> 1.1.0)
328335
docusign_rooms (~> 1.2.0.rc1)
329336
jbuilder (~> 2.11.5)
330337
listen (~> 3.7.1)
338+
matrix (~> 0.4.2)
331339
omniauth-oauth2 (~> 1.7.1)
332340
omniauth-rails_csrf_protection
333341
pry-nav (~> 0.3.0)
@@ -340,6 +348,7 @@ DEPENDENCIES
340348
spring (~> 2.1.0)
341349
spring-watcher-listen (~> 2.0.1)
342350
sqlite3 (~> 1.4.4)
351+
test-unit
343352
turbolinks (~> 5.2.1)
344353
tzinfo-data (~> 1.2022.1, >= 1.2022.1)
345354
uglifier (~> 4.2.0)

app/assets/javascripts/search.js

Lines changed: 266 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,266 @@
1+
const DS_SEARCH = (function () {
2+
const API_TYPES = {
3+
ESIGNATURE: "esignature",
4+
MONITOR: "monitor",
5+
CLICK: "click",
6+
ROOMS: "rooms",
7+
ADMIN: "admin",
8+
};
9+
10+
const processJSONData = function () {
11+
const json_raw = $("#api_json_data").text();
12+
const json = json_raw ? JSON.parse(json_raw) : false;
13+
14+
return json;
15+
}
16+
17+
let processCFR11Value = function () {
18+
let json_raw = $("#cfr11_data").text();
19+
20+
return json_raw;
21+
}
22+
23+
function checkIfExampleMatches(example, matches) {
24+
const name = example.ExampleName;
25+
const description = example.ExampleDescription;
26+
const pathNames = example.LinksToAPIMethod.map((a) => a.PathName);
27+
28+
for (let i = 0; i < matches.length; i++) {
29+
if (
30+
name === matches[i].value ||
31+
description === matches[i].value ||
32+
pathNames.indexOf(matches[i].value) > -1
33+
) {
34+
return true;
35+
}
36+
}
37+
38+
return false;
39+
}
40+
41+
function clearNonMatchingExamples(examples, matches) {
42+
for (let i = examples.length - 1; i >= 0; i--) {
43+
if (!checkIfExampleMatches(examples[i], matches)) {
44+
examples.splice(i, 1);
45+
}
46+
}
47+
}
48+
49+
function clearResultsAfterMatching(api, matches) {
50+
const groups = api.Groups;
51+
52+
for (let i = groups.length - 1; i >= 0; i--) {
53+
const group = groups[i];
54+
clearNonMatchingExamples(group.Examples, matches);
55+
56+
if (group.Examples.length === 0) {
57+
groups.splice(i, 1);
58+
}
59+
}
60+
}
61+
62+
const findCodeExamplesByKeywords = function(json, pattern) {
63+
const options = {
64+
isCaseSensitive: false,
65+
threshold: -0.0,
66+
includeMatches: true,
67+
ignoreLocation: true,
68+
useExtendedSearch: true,
69+
keys: [
70+
"Groups.Examples.ExampleName",
71+
"Groups.Examples.ExampleDescription",
72+
"Groups.Examples.LinksToAPIMethod.PathName",
73+
],
74+
};
75+
76+
let clearJSON = JSON.stringify(json).replace(/<\/?[^>]+(>|$)/g, "");
77+
const fuse = new Fuse(JSON.parse(clearJSON), options);
78+
79+
var searchResults = fuse.search(JSON.stringify(pattern));
80+
81+
searchResults.forEach(searchResult => {
82+
return clearResultsAfterMatching(searchResult.item, searchResult.matches)
83+
});
84+
85+
return searchResults;
86+
}
87+
88+
const getExamplesByAPIType = function (apiType, codeExamples) {
89+
let codeExamplesByAPI = codeExamples.find(
90+
(x) => x.Name.toLowerCase() === apiType
91+
);
92+
93+
if (codeExamplesByAPI != null) {
94+
return [codeExamplesByAPI];
95+
} else {
96+
return null;
97+
}
98+
};
99+
100+
const getEnteredAPIType = function (inputValue) {
101+
const inputLength = inputValue.length;
102+
103+
for (const key in API_TYPES) {
104+
if (Object.hasOwnProperty.call(API_TYPES, key)) {
105+
const apiType = API_TYPES[key];
106+
const comparedValue = apiType.substr(0, inputLength);
107+
108+
if (inputValue === comparedValue) {
109+
return apiType;
110+
}
111+
}
112+
}
113+
114+
return null;
115+
};
116+
117+
function getLinkForApiType(apiName) {
118+
switch (apiName) {
119+
case API_TYPES.ADMIN:
120+
return "aeg";
121+
case API_TYPES.CLICK:
122+
return "ceg";
123+
case API_TYPES.ROOMS:
124+
return "reg";
125+
case API_TYPES.MONITOR:
126+
return "meg";
127+
case API_TYPES.ESIGNATURE:
128+
return "eg";
129+
}
130+
}
131+
132+
let addCodeExampleToHomepage = function (codeExamples) {
133+
var cfrPart11 = processCFR11Value();
134+
135+
codeExamples.forEach(
136+
element => {
137+
let linkToCodeExample = getLinkForApiType(element.Name.toLowerCase());
138+
139+
element.Groups.forEach(
140+
group => {
141+
$("#filtered_code_examples").append("<h2>" + group.Name + "</h2>");
142+
143+
group.Examples.forEach(
144+
example => {
145+
if (!example.SkipForLanguages || !example.SkipForLanguages.toLowerCase().includes("c#")) {
146+
if (element.Name.toLowerCase() !== API_TYPES.ESIGNATURE.toLowerCase() ||
147+
((example.CFREnabled == "AllAccounts") ||
148+
((cfrPart11 == "enabled") && (example.CFREnabled == "CFROnly")) ||
149+
((cfrPart11 != "enabled") && (example.CFREnabled == "NonCFR")))) {
150+
$("#filtered_code_examples").append(
151+
"<h4 id="
152+
+ "example".concat("0".repeat(3 - example.ExampleNumber.toString().length)).concat(example.ExampleNumber) + ">"
153+
+ "<a href = "
154+
+ linkToCodeExample.concat("0".repeat(3 - example.ExampleNumber.toString().length)).concat(example.ExampleNumber)
155+
+ " >"
156+
+ example.ExampleName
157+
+ "</a ></h4 >"
158+
);
159+
160+
$("#filtered_code_examples").append("<p>" + example.ExampleDescription + "</p>");
161+
162+
$("#filtered_code_examples").append("<p>");
163+
164+
if (example.LinksToAPIMethod.length == 1) {
165+
$("#filtered_code_examples").append(processJSONData().SupportingTexts.APIMethodUsed);
166+
}
167+
else {
168+
$("#filtered_code_examples").append(processJSONData().SupportingTexts.APIMethodUsedPlural);
169+
}
170+
171+
for (let index = 0; index < example.LinksToAPIMethod.length; index++) {
172+
$("#filtered_code_examples").append(
173+
" <a target='_blank' href='"
174+
+ example.LinksToAPIMethod[index].Path
175+
+ "'>"
176+
+ example.LinksToAPIMethod[index].PathName
177+
+ "</a>"
178+
);
179+
180+
if (index + 1 === example.LinksToAPIMethod.length) {
181+
$("#filtered_code_examples").append("<span></span>");
182+
}
183+
else if (index + 1 === example.LinksToAPIMethod.length - 1) {
184+
$("#filtered_code_examples").append("<span> and </span>");
185+
}
186+
else {
187+
$("#filtered_code_examples").append("<span>, </span>");
188+
}
189+
190+
}
191+
192+
$("#filtered_code_examples").append("</p> ");
193+
}
194+
}
195+
}
196+
);
197+
}
198+
);
199+
}
200+
);
201+
}
202+
203+
const textCouldNotBeFound = function () {
204+
$("#filtered_code_examples").append(
205+
processJSONData().SupportingTexts.SearchFailed
206+
);
207+
};
208+
209+
return {
210+
processJSONData: processJSONData,
211+
getEnteredAPIType: getEnteredAPIType,
212+
getExamplesByAPIType: getExamplesByAPIType,
213+
findCodeExamplesByKeywords: findCodeExamplesByKeywords,
214+
textCouldNotBeFound: textCouldNotBeFound,
215+
addCodeExampleToHomepage: addCodeExampleToHomepage,
216+
};
217+
})();
218+
219+
const input = document.getElementById("code_example_search");
220+
const log = document.getElementById("values");
221+
222+
input.addEventListener("input", updateValue);
223+
224+
function updateValue(esearchPattern) {
225+
document.getElementById("filtered_code_examples").innerHTML = "";
226+
227+
const inputValue = esearchPattern.target.value.toLowerCase();
228+
const json = DS_SEARCH.processJSONData().APIs;
229+
230+
if (inputValue === "") {
231+
DS_SEARCH.addCodeExampleToHomepage(json);
232+
} else {
233+
const apiType = DS_SEARCH.getEnteredAPIType(inputValue);
234+
235+
if (apiType !== null) {
236+
const adminExamples = DS_SEARCH.getExamplesByAPIType(apiType, json);
237+
DS_SEARCH.addCodeExampleToHomepage(adminExamples);
238+
} else {
239+
const result = DS_SEARCH.findCodeExamplesByKeywords(json, inputValue);
240+
if (result.length < 1) {
241+
DS_SEARCH.textCouldNotBeFound();
242+
} else {
243+
result.forEach(x => {
244+
var api = json.filter(api => {
245+
return api.Name === x.item.Name;
246+
})[0];
247+
248+
x.item.Groups.forEach((group, groupIndex) => {
249+
var unfilteredGroup = api.Groups.filter(apiGroup => {
250+
return apiGroup.Name === group.Name;
251+
})[0];
252+
253+
group.Examples.forEach((example, index) => {
254+
var clearedExample = unfilteredGroup.Examples.filter(apiExample => {
255+
return apiExample.ExampleNumber === example.ExampleNumber;
256+
})[0];
257+
x.item.Groups[groupIndex].Examples[index] = clearedExample;
258+
});
259+
});
260+
261+
DS_SEARCH.addCodeExampleToHomepage([x.item]);
262+
});
263+
}
264+
}
265+
}
266+
}

0 commit comments

Comments
 (0)