Kanka Search Upgrades

Adds the ability to look for user and campaign settings in Kanka’s search field for faster access.

  1. // ==UserScript==
  2. // @name Kanka Search Upgrades
  3. // @namespace http://tampermonkey.net/
  4. // @version 9
  5. // @license MIT
  6. // @description Adds the ability to look for user and campaign settings in Kanka’s search field for faster access.
  7. // @author Salvatos
  8. // @match https://*.kanka.io/*
  9. // @icon https://www.google.com/s2/favicons?domain=kanka.io
  10. // @grant GM_addStyle
  11. // @run-at document-end
  12. // ==/UserScript==
  13.  
  14. // PREFERENCES
  15. const requireSettingsSwitch = true; // Set to false to always show matching settings, or true to require the character below to trigger settings search
  16. const settingsSwitch = "#"; // If the above is true, settings search only happens when your query starts with this character (must be a single character)
  17.  
  18. GM_addStyle(`
  19. #content-search-prompt {
  20. }
  21. #content-search-prompt:hover {
  22. }
  23. #content-search-prompt a {
  24. color: var(--search-cursor-text) !important;
  25. }
  26. #matched-settings a {
  27. display: inline;
  28. color: var(--link-text) !important;
  29. padding: 0;
  30. font-size: 13px;
  31. text-decoration: underline;
  32. }
  33. `);
  34.  
  35. // Prepare base URLs for this campaign/user
  36. const campaignPath = location.pathname.split("/", 3);
  37. const campaignId = campaignPath[2];
  38. let campaign = location.origin + "/w/" + campaignId;
  39. let settings = location.origin + "/settings";
  40.  
  41. // Define settings pages (no need to add words from the title to the keywords)
  42. const settingsPages = [
  43. // User settings
  44. {
  45. title: "User settings",
  46. keywords: "personal preferences",
  47. url: `${settings}/appearance`
  48. },
  49. {
  50. title: "User-preferred theme",
  51. keywords: "dark light midnight",
  52. url: `${settings}/appearance`
  53. },
  54. {
  55. title: "Pagination",
  56. keywords: "page results per",
  57. url: `${settings}/appearance`
  58. },
  59. {
  60. title: "Date format",
  61. keywords: "",
  62. url: `${settings}/appearance`
  63. },
  64. {
  65. title: "Campaign switcher sorting order",
  66. keywords: "list",
  67. url: `${settings}/appearance`
  68. },
  69. {
  70. title: "New entity workflow",
  71. keywords: "create creation",
  72. url: `${settings}/appearance`
  73. },
  74. {
  75. title: "Text editor",
  76. keywords: "summernote tinymce",
  77. url: `${settings}/appearance`
  78. },
  79. {
  80. title: "Entity list layout",
  81. keywords: "default grid table entities",
  82. url: `${settings}/appearance`
  83. },
  84. {
  85. title: "Entity list nesting (user)",
  86. keywords: "default flat nested entities tree view",
  87. url: `${settings}/appearance`
  88. },
  89. {
  90. title: "Advanced mentions",
  91. keywords: "",
  92. url: `${settings}/appearance`
  93. },
  94. {
  95. title: "Notifications",
  96. keywords: "updates news subscriptions",
  97. url: `${settings}/newsletter`
  98. },
  99. {
  100. title: "Profile",
  101. keywords: "privacy name username avatar picture",
  102. url: `${settings}/profile`
  103. },
  104. {
  105. title: "Subscription",
  106. keywords: "tier level subscribe upgrade downgrade kobold owlbear elemental wyvern patreon",
  107. url: `${settings}/subscription`
  108. },
  109. {
  110. title: "Boosters",
  111. keywords: "boosted campaigns boost superboost superboosted premium",
  112. url: `${settings}/boosters`
  113. },
  114. {
  115. title: "Premium campaigns",
  116. keywords: "boost campaigns premium",
  117. url: `${settings}/premium`
  118. },
  119. {
  120. title: "Payment method",
  121. keywords: "credit card paypal currency",
  122. url: `${settings}/billing/payment-method`
  123. },
  124. {
  125. title: "Billing",
  126. keywords: "invoices history",
  127. url: `${settings}/billing/history`
  128. },
  129. {
  130. title: "App integration",
  131. keywords: "sync discord",
  132. url: `${settings}/apps`
  133. },
  134. {
  135. title: "API",
  136. keywords: "key token",
  137. url: `${settings}/api`
  138. },
  139. // Campaign
  140. {
  141. title: "Campaign overview and settings",
  142. keywords: "edit delete settings",
  143. url: `${campaign}/overview`
  144. },
  145. // Main settings form
  146. {
  147. title: "Basic campaign configuration",
  148. keywords: "name description image picture settings",
  149. url: `${campaign}/edit#tab_form-entry`
  150. },
  151. {
  152. title: "Vanity URL",
  153. keywords: "custom personalized address domain",
  154. url: `${campaign}/edit#tab_form-entry`
  155. },
  156. {
  157. title: "Campaign visibility",
  158. keywords: "public private",
  159. url: `${campaign}/edit#tab_form-public`
  160. },
  161. {
  162. title: "Campaign language",
  163. keywords: "language locale",
  164. url: `${campaign}/edit#tab_form-public`
  165. },
  166. {
  167. title: "Game system",
  168. keywords: "rpg",
  169. url: `${campaign}/edit#tab_form-public`
  170. },
  171. {
  172. title: "Campaign-enforced theme",
  173. keywords: "light dark midnight",
  174. url: `${campaign}/edit#tab_form-ui`
  175. },
  176. {
  177. title: "Member list visibility",
  178. keywords: "users members privacy",
  179. url: `${campaign}/edit#tab_form-ui`
  180. },
  181. {
  182. title: "Entity history log visibility",
  183. keywords: "",
  184. url: `${campaign}/edit#tab_form-ui`
  185. },
  186. {
  187. title: "Entity image in tooltips",
  188. keywords: "",
  189. url: `${campaign}/edit#tab_form-ui`
  190. },
  191. {
  192. title: "Default entity connections display",
  193. keywords: "explorer list relations",
  194. url: `${campaign}/edit#tab_form-ui`
  195. },
  196. {
  197. title: "Default filtering of entity descendants",
  198. keywords: "sublist direct indirect hierarchy children child",
  199. url: `${campaign}/edit#tab_form-ui`
  200. },
  201. {
  202. title: "Entity list layout (campaign)",
  203. keywords: "default flat nested entities tree view",
  204. url: `${campaign}/edit#tab_form-ui`
  205. },
  206. {
  207. title: "New posts collapsed by default",
  208. keywords: "",
  209. url: `${campaign}/edit#tab_form-ui`
  210. },
  211. {
  212. title: "Default permissions for new entities and elements",
  213. keywords: "visibility entity",
  214. url: `${campaign}/edit#tab_form-permission`
  215. },
  216. {
  217. title: "Dashboard header text and image",
  218. keywords: "",
  219. url: `${campaign}/edit#tab_form-dashboard`
  220. },
  221. // Other campaign options
  222. {
  223. title: "Export campaign",
  224. keywords: "JSON",
  225. url: `${campaign}/campaign-export`
  226. },
  227. {
  228. title: "Recover deleted entities",
  229. keywords: "recovery restore archive",
  230. url: `${campaign}/recovery`
  231. },
  232. {
  233. title: "Achievements",
  234. keywords: "campaign stats",
  235. url: `${campaign}/achievements`
  236. },
  237. {
  238. title: "Member list",
  239. keywords: "members users invite",
  240. url: `${campaign}/campaign_users`
  241. },
  242. {
  243. title: "Campaign membership applications",
  244. keywords: "public open request join",
  245. url: `${campaign}/campaign_submissions`
  246. },
  247. {
  248. title: "User roles",
  249. keywords: "groups permissions players",
  250. url: `${campaign}/campaign_roles`
  251. },
  252. {
  253. title: "Modules (entity types)",
  254. keywords: "features enable disable rename icons categories",
  255. url: `${campaign}/modules`
  256. },
  257. {
  258. title: "Marketplace plugins",
  259. keywords: "enable disable themes character sheets content packs",
  260. url: `${campaign}/plugins`
  261. },
  262. {
  263. title: "Default entity thumbnails",
  264. keywords: "images icons fallback",
  265. url: `${campaign}/default-images`
  266. },
  267. {
  268. title: "Theming (campaign styles)",
  269. keywords: "theme css style sheet customize appearance skin look",
  270. url: `${campaign}/campaign_styles`
  271. },
  272. {
  273. title: "Theme builder (color palette)",
  274. keywords: "theme builder css colors colours palette customize skin",
  275. url: `${campaign}/theme-builder`
  276. },
  277. {
  278. title: "Sidebar setup",
  279. keywords: "custom names links menu navigation order icons",
  280. url: `${campaign}/sidebar-setup`
  281. },
  282. {
  283. title: "Bookmarks",
  284. keywords: "custom quick links menu shortcuts",
  285. url: `${campaign}/bookmarks`
  286. },
  287. {
  288. title: "Campaign stats",
  289. keywords: "facts info count number",
  290. url: `${campaign}/stats`
  291. }
  292. ];
  293.  
  294. // On input, update link
  295. $("#entity-lookup").on("input", updSugg);
  296.  
  297. function updSugg() {
  298. let searchtext = $("#entity-lookup").val();
  299.  
  300. // Create a container for the dropdown
  301. if ($("#content-search-prompt").length == 0) {
  302. $(".search-recent .grow")[0].insertAdjacentHTML("afterbegin", "<div id='content-search-prompt' class='italic m-2 rounded p-1 hover:lookup-entity'></div>");
  303. }
  304.  
  305. // Look for matching settings pages if desired, as indicated by the first character or preferences
  306. if (requireSettingsSwitch === false || searchtext.substr(0,1) === settingsSwitch) {
  307. searchtext = searchtext.substr(1);
  308. // match anything in title:
  309. let titleMatches = settingsPages.filter(element => element.title.toLowerCase().match(searchtext.toLowerCase()));
  310. // match anything in keywords:
  311. let keywordMatches = settingsPages.filter(element => element.keywords.toLowerCase().match(searchtext.toLowerCase()));
  312. // match whole words only in keywords:
  313. //let keywordMatches = settingsPages.filter(element => element.keywords.toLowerCase().split(" ").includes(searchtext.toLowerCase()));
  314. // combine and remove duplicates:
  315. let allMatches = Array.from(new Set(titleMatches.concat(keywordMatches)));
  316.  
  317. // Make links for matches
  318. if (allMatches.length > 0) {
  319. let listOfPages = `<div id='matched-settings' class=''>Your search matches the following settings:<ul>`;
  320. allMatches.forEach(function (item) {
  321. listOfPages += `<li><a href='${item.url}'>${item.title}</a></li>`;
  322. });
  323. // Remove last separator and close div
  324. listOfPages = listOfPages.substring(0, listOfPages.length -3) + `</ul></div>`;
  325.  
  326. // Insert or refresh suggestions
  327. $("#content-search-prompt").html(listOfPages);
  328. }
  329. else {
  330. // If we showed results previously but no longer match anyhing, remove the previous suggestions
  331. try {
  332. $("#matched-settings").remove();
  333. }
  334. catch (e) {
  335. }
  336. }
  337. }
  338. else {
  339. // If we showed results previously but no longer match anyhing, remove the previous suggestions
  340. try {
  341. $("#matched-settings").remove();
  342. }
  343. catch (e) {
  344. }
  345. }
  346. }