pass on fa user search
This commit is contained in:
@@ -5,10 +5,7 @@ class Domain::Fa::ApiController < ApplicationController
|
||||
def search_users
|
||||
name = params[:name]
|
||||
limit = (params[:limit] || 10).to_i.clamp(0, 15)
|
||||
users = relevant = users_for_name(name).
|
||||
map do |id, name, url_name|
|
||||
{ id: id, name: name, url_name: url_name }
|
||||
end
|
||||
users = users_for_name(name)
|
||||
if !Rails.env.production? && name == "error"
|
||||
render status: 500, json: { error: "an error!" }
|
||||
else
|
||||
@@ -360,166 +357,26 @@ class Domain::Fa::ApiController < ApplicationController
|
||||
end
|
||||
|
||||
def users_for_name(name)
|
||||
return USERS if Rails.env.development?
|
||||
|
||||
Domain::Fa::User.where([
|
||||
"(name ilike :name) OR (url_name ilike :name)",
|
||||
{ name: "#{ReduxApplicationRecord.sanitize_sql_like(name)}%" },
|
||||
]).order(name: :asc).
|
||||
limit(limit).
|
||||
pluck(:id, :name, :url_name)
|
||||
end
|
||||
]).
|
||||
includes(:avatar).
|
||||
select(:id, :state, :state_detail, :log_entry_detail, :name, :url_name).
|
||||
order(name: :asc).
|
||||
limit(10).
|
||||
map do |user|
|
||||
thumb = nil
|
||||
if user.avatar&.log_entry
|
||||
thumb = log_entries_path(user.avatar.log_entry, thumb: true)
|
||||
end
|
||||
|
||||
USERS = [
|
||||
[102661, "Twee", "twee"],
|
||||
[102836, "Kobrin", "kobrin"],
|
||||
[106292, "manadspaniel", "manadspaniel"],
|
||||
[121171, "Sakura_the_wolf", "sakurathewolf"],
|
||||
[123481, "Kai~skunk", "kai~skunk"],
|
||||
[131219, "Luna.Moonflower", "luna.moonflower"],
|
||||
[132018, "HeyImDaddy", "heyimdaddy"],
|
||||
[132032, "frankenbunny", "frankenbunny"],
|
||||
[154415, "Gh0stlyFurry", "gh0stlyfurry"],
|
||||
[158837, "4r_da_Sqauw", "4rdasqauw"],
|
||||
[173905, "ZombieUnicorn", "zombieunicorn"],
|
||||
[181599, "space_fruit", "spacefruit"],
|
||||
[182869, "Ragd360", "ragd360"],
|
||||
[185649, "IBluefoxI", "ibluefoxi"],
|
||||
[188437, "Yuricupcakes", "yuricupcakes"],
|
||||
[190487, "lingaring", "lingaring"],
|
||||
[197704, "Rayneier", "rayneier"],
|
||||
[201974, "Clow", "clow"],
|
||||
[208562, "rdraft", "rdraft"],
|
||||
[215738, "Kaori_Keia", "kaorikeia"],
|
||||
[22036, "tiddys", "tiddys"],
|
||||
[223999, "SwampPossum", "swamppossum"],
|
||||
[22841, "k-inukai", "k-inukai"],
|
||||
[232171, "IPfix_da_Firefox", "ipfixdafirefox"],
|
||||
[235933, "VisibleSuicide", "visiblesuicide"],
|
||||
[258806, "Wizmas", "wizmas"],
|
||||
[273285, "furrything", "furrything"],
|
||||
[273634, "AngieTheOtter", "angietheotter"],
|
||||
[282615, "catsrulekg", "catsrulekg"],
|
||||
[285410, "Icyskills", "icyskills"],
|
||||
[291374, "autumnfoxfur", "autumnfoxfur"],
|
||||
[293860, "katamarulte", "katamarulte"],
|
||||
[306985, "RadioactiveF0X", "radioactivef0x"],
|
||||
[319368, "Soren123", "soren123"],
|
||||
[349997, "kuroneko---sama", "kuroneko---sama"],
|
||||
[350090, "SkylesFawkx", "skylesfawkx"],
|
||||
[355982, "Shirilee", "shirilee"],
|
||||
[358587, "Shosta", "shosta"],
|
||||
[363811, "WhiteKIBA", "whitekiba"],
|
||||
[374231, "starswillscream", "starswillscream"],
|
||||
[379724, "dub-c", "dub-c"],
|
||||
[386887, "Kirei-Uchiha", "kirei-uchiha"],
|
||||
[407214, "MagicOFManga", "magicofmanga"],
|
||||
[412404, "PoppyPath", "poppypath"],
|
||||
[412923, "Sebastian_teh_Dober", "sebastiantehdober"],
|
||||
[416072, "declinedkitty", "declinedkitty"],
|
||||
[418580, "X-MXNE666", "x-mxne666"],
|
||||
[418660, "Peelpeelpeel1", "peelpeelpeel1"],
|
||||
[419237, "Fennixthepawlicker", "fennixthepawlicker"],
|
||||
[431318, "GregorianBurns", "gregorianburns"],
|
||||
[436280, "fionnaidh", "fionnaidh"],
|
||||
[43684, "MLBat-Darkheart", "mlbat-darkheart"],
|
||||
[437721, "White_Dragon_sisu", "whitedragonsisu"],
|
||||
[441002, "someSkylah", "someskylah"],
|
||||
[441268, "Eviscerator", "eviscerator"],
|
||||
[442275, "HumanistFurs", "humanistfurs"],
|
||||
[445549, "Ayrich", "ayrich"],
|
||||
[448023, "NastyCalamari", "nastycalamari"],
|
||||
[455220, "analfurs", "analfurs"],
|
||||
[459851, "TotallySafe", "totallysafe"],
|
||||
[464719, "Shadowfur13", "shadowfur13"],
|
||||
[46619, "CandyShop", "candyshop"],
|
||||
[466695, "ElFurroKawaii", "elfurrokawaii"],
|
||||
[467565, "Brygaht", "brygaht"],
|
||||
[472867, "Mitryll", "mitryll"],
|
||||
[479071, "Shamanroach", "shamanroach"],
|
||||
[497090, "!BlakeTheGamer", "blakethegamer"],
|
||||
[507923, "Guro-Jans", "guro-jans"],
|
||||
[520548, "Elseano", "elseano"],
|
||||
[530399, "PUMPKINLIGHTTHEKITSUNE", "pumpkinlightthekitsune"],
|
||||
[531212, "Ulti_199", "ulti199"],
|
||||
[532461, "DozyDoe", "dozydoe"],
|
||||
[537220, "fentible", "fentible"],
|
||||
[539148, "StealthyIntheDark", "stealthyinthedark"],
|
||||
[545990, "odinokiy", "odinokiy"],
|
||||
[552205, "Namorria", "namorria"],
|
||||
[557322, "Katana2", "katana2"],
|
||||
[56360, "t0rrid", "t0rrid"],
|
||||
[570571, "Zoralth8745", "zoralth8745"],
|
||||
[570771, "Swagging", "swagging"],
|
||||
[574502, "AMeanCow", "ameancow"],
|
||||
[576501, "CaptianYeti", "captianyeti"],
|
||||
[578205, "cyphurel", "cyphurel"],
|
||||
[580442, "rraw", "rraw"],
|
||||
[584446, "HelveluxDragon", "helveluxdragon"],
|
||||
[592829, "clownshoes", "clownshoes"],
|
||||
[594599, "AxisthewoIf", "axisthewoif"],
|
||||
[597726, "GypsyCavarow", "gypsycavarow"],
|
||||
[598375, "Cloud_Heart_Saber", "cloudheartsaber"],
|
||||
[608812, "MidnightMapleMoon", "midnightmaplemoon"],
|
||||
[608859, "pasteldad", "pasteldad"],
|
||||
[609253, "mezzoforte2", "mezzoforte2"],
|
||||
[616675, "Lil_Naz", "lilnaz"],
|
||||
[617918, "tristian", "tristian"],
|
||||
[629272, "esenya_valenok", "esenyavalenok"],
|
||||
[637893, "Ink-EyesBae", "ink-eyesbae"],
|
||||
[638713, "NavigatorTP", "navigatortp"],
|
||||
[642236, "-EdenArcane-", "-edenarcane-"],
|
||||
[660560, "Nevera66", "nevera66"],
|
||||
[678313, "mog17", "mog17"],
|
||||
[694556, "veroaid", "veroaid"],
|
||||
[695130, "Furry_Writers", "furrywriters"],
|
||||
[697418, "Lazywerewolf", "lazywerewolf"],
|
||||
[711410, "Seas1de", "seas1de"],
|
||||
[713084, "fuzzmuffin23", "fuzzmuffin23"],
|
||||
[713759, "alp_Rik", "alprik"],
|
||||
[716200, "RequiemDreamer", "requiemdreamer"],
|
||||
[718333, "KhorneSoup", "khornesoup"],
|
||||
[73267, "splendidguy44", "splendidguy44"],
|
||||
[738005, "aurokhan", "aurokhan"],
|
||||
[742214, "velin.art", "velin.art"],
|
||||
[742375, "vampiretigress", "vampiretigress"],
|
||||
[752692, "FlairMalin", "flairmalin"],
|
||||
[756325, "Thorn_Mochag", "thornmochag"],
|
||||
[75693, "numbsoul", "numbsoul"],
|
||||
[758113, "leetf0x", "leetf0x"],
|
||||
[758475, "Naspyta", "naspyta"],
|
||||
[763834, "dankkushlove420", "dankkushlove420"],
|
||||
[773150, "Fokatuh", "fokatuh"],
|
||||
[777382, "Yorrick67", "yorrick67"],
|
||||
[783391, "lovebigtits94", "lovebigtits94"],
|
||||
[790219, "ValiantBadger", "valiantbadger"],
|
||||
[793308, "promqueen192", "promqueen192"],
|
||||
[794155, "Sola_the_Solgaleo", "solathesolgaleo"],
|
||||
[802477, "kempo2k", "kempo2k"],
|
||||
[804770, "vinv", "vinv"],
|
||||
[808277, "AzartAlien", "azartalien"],
|
||||
[819527, "curiosity6678", "curiosity6678"],
|
||||
[820429, "GrayGrim", "graygrim"],
|
||||
[822085, "rRICHr", "rrichr"],
|
||||
[835929, "Kovuska", "kovuska"],
|
||||
[836315, "knotthatbun", "knotthatbun"],
|
||||
[836547, "1223223", "1223223"],
|
||||
[841669, "DisheveledSloth", "disheveledsloth"],
|
||||
[84257, "Naktian-Furs", "naktian-furs"],
|
||||
[844032, "Fluffy_kozlik", "fluffykozlik"],
|
||||
[854728, "pierre_dunn", "pierredunn"],
|
||||
[856538, "onlyheretosponser", "onlyheretosponser"],
|
||||
[861416, "tailsthefoxrules123", "tailsthefoxrules123"],
|
||||
[862656, "EVXFY", "evxfy"],
|
||||
[865110, "LowkeyArt", "lowkeyart"],
|
||||
[873049, "Tedy", "tedy"],
|
||||
[875191, "JamesTec666", "jamestec666"],
|
||||
[875416, "Obscurum", "obscurum"],
|
||||
[879928, "Solious6233", "solious6233"],
|
||||
[882664, "princepixelbunny", "princepixelbunny"],
|
||||
[887058, "Pyrote", "pyrote"],
|
||||
[90246, "sonupi", "sonupi"],
|
||||
[92111, "zevialexander", "zevialexander"],
|
||||
[92831, "foxmacro", "foxmacro"],
|
||||
]
|
||||
{
|
||||
id: user.id,
|
||||
name: user.name,
|
||||
url_name: user.url_name,
|
||||
thumb: thumb,
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -6,8 +6,8 @@ import ListItem from "./ListItem";
|
||||
import Trie, { TrieNode } from "../lib/Trie";
|
||||
|
||||
// staging
|
||||
const HOST = "http://scraper.local:3001";
|
||||
// const HOST = "";
|
||||
// const HOST = "http://scraper.local:3001";
|
||||
const HOST = "";
|
||||
const COMMON_LIST_ELEM_CLASSES = `
|
||||
w-full p-2 pl-8
|
||||
text-xl font-light
|
||||
@@ -39,43 +39,19 @@ type TrieNodeType = TrieNode<TrieValue>;
|
||||
export default function UserSearchBar({ isServerRendered }: PropTypes) {
|
||||
isServerRendered = !!isServerRendered;
|
||||
const [userName, setUserName] = useState("");
|
||||
const [items, setUserList] = useState<ServerResponse["users"]>([]);
|
||||
const [userList, setUserList] = useState<ServerResponse["users"]>([]);
|
||||
const [selectedIdx, setSelectedIdx] = useState<number | null>(null);
|
||||
const [errorMessage, setErrorMessage] = useState<string | null>(null);
|
||||
const [pendingRequest, setPendingRequest] = useState<AbortController | null>(
|
||||
null
|
||||
);
|
||||
const [typingSettled, setTypingSettled] = useState(true);
|
||||
const [trie, setTrie] = useState<TrieType | null>(null);
|
||||
const inputRef = useRef(null);
|
||||
|
||||
const [isFocused, setIsFocused] = useState(
|
||||
isServerRendered ? false : document.activeElement == inputRef.current
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
const controller = new AbortController();
|
||||
async function loadUserTrie() {
|
||||
try {
|
||||
let req = await fetch(`${HOST}/api/fa/load_users`, {
|
||||
signal: controller.signal,
|
||||
});
|
||||
if (req.status != 200) {
|
||||
setErrorMessage(`error loading users: ${await req.body}`);
|
||||
} else {
|
||||
let trieSerialized = await req.json();
|
||||
const trie: TrieType = new Trie(trieSerialized);
|
||||
setErrorMessage("loaded trie");
|
||||
setTrie(trie);
|
||||
}
|
||||
} catch (err) {
|
||||
console.log("error loading user trie: ", err);
|
||||
}
|
||||
}
|
||||
loadUserTrie();
|
||||
return () => controller.abort();
|
||||
}, []);
|
||||
|
||||
const clearResults = useCallback(() => {
|
||||
setUserList([]);
|
||||
setErrorMessage(null);
|
||||
@@ -84,123 +60,65 @@ export default function UserSearchBar({ isServerRendered }: PropTypes) {
|
||||
|
||||
const cancelPendingRequest = useCallback(async () => {
|
||||
if (pendingRequest) {
|
||||
clearResults();
|
||||
setPendingRequest(null);
|
||||
pendingRequest.abort();
|
||||
}
|
||||
}, [pendingRequest, userName]);
|
||||
}, [pendingRequest]);
|
||||
|
||||
const searchForUserDebounced = useCallback(
|
||||
debounce(async (userName) => {
|
||||
setTypingSettled(true);
|
||||
setUserName(userName);
|
||||
}, 250),
|
||||
[]
|
||||
const sendSearchRequest = useCallback(
|
||||
(userName) => {
|
||||
cancelPendingRequest();
|
||||
|
||||
const controller = new AbortController();
|
||||
setPendingRequest(controller);
|
||||
|
||||
async function sendRequest() {
|
||||
try {
|
||||
let req = await fetch(
|
||||
`${HOST}/api/fa/search_users?name=${userName}`,
|
||||
{
|
||||
signal: controller.signal,
|
||||
}
|
||||
);
|
||||
if (req.status != 200) {
|
||||
setErrorMessage(`error loading users: ${await req.body}`);
|
||||
} else {
|
||||
let gotUserList = await req.json();
|
||||
setPendingRequest(null);
|
||||
setUserList(gotUserList.users);
|
||||
}
|
||||
} catch (err) {
|
||||
console.log("error loading user trie: ", err);
|
||||
setPendingRequest(null);
|
||||
setErrorMessage("error loading users");
|
||||
}
|
||||
}
|
||||
sendRequest();
|
||||
|
||||
return () => controller.abort();
|
||||
},
|
||||
[cancelPendingRequest]
|
||||
);
|
||||
|
||||
const searchForUser = useCallback(
|
||||
(userName: string) => {
|
||||
// setTypingSettled(false);
|
||||
// cancelPendingRequest();
|
||||
if (trie == null) {
|
||||
return;
|
||||
} else if (isEmpty(userName)) {
|
||||
setUserName(userName);
|
||||
if (isEmpty(userName)) {
|
||||
clearResults();
|
||||
setUserName("");
|
||||
} else {
|
||||
const { node } = trie.nodeForPrefix(userName);
|
||||
if (node) {
|
||||
const users = nodeToList(node, 5).map((node) => ({
|
||||
name: `${node.value[1]} (${node.value[0]})`,
|
||||
}));
|
||||
console.log("Set users", users);
|
||||
setUserList(users);
|
||||
}
|
||||
sendSearchRequest(userName);
|
||||
}
|
||||
},
|
||||
[cancelPendingRequest, trie]
|
||||
[clearResults, sendSearchRequest]
|
||||
);
|
||||
|
||||
function nodeToList(node: TrieNodeType, limit: number): TrieNodeType[] {
|
||||
const list = [];
|
||||
nodeToListImpl(list, node, limit);
|
||||
return list;
|
||||
}
|
||||
|
||||
function nodeToListImpl(
|
||||
listOut: TrieNodeType[],
|
||||
node: TrieNodeType,
|
||||
limit: number
|
||||
) {
|
||||
if (listOut.length >= limit) return;
|
||||
|
||||
if (node.terminal) {
|
||||
listOut.push(node);
|
||||
if (listOut.length >= limit) return;
|
||||
}
|
||||
|
||||
for (const [childKey, child] of node.children.entries()) {
|
||||
nodeToListImpl(listOut, child, limit);
|
||||
if (listOut.length >= limit) return;
|
||||
}
|
||||
}
|
||||
|
||||
// useEffect(() => {
|
||||
// if (isEmpty(userName)) {
|
||||
// return;
|
||||
// }
|
||||
// if (trie == null) {
|
||||
// return;
|
||||
// }
|
||||
|
||||
// const node = trie.nodeForPrefix(userName);
|
||||
// setUserList([{ name: `node ${node}` }]);
|
||||
|
||||
// // const controller = new AbortController();
|
||||
// // setPendingRequest(controller);
|
||||
// // async function doFetch() {
|
||||
// // try {
|
||||
// // let response = await fetch(
|
||||
// // `${HOST}/api/fa/search_users?name=${encodeURIComponent(userName)}`,
|
||||
// // {
|
||||
// // signal: controller.signal,
|
||||
// // }
|
||||
// // );
|
||||
// // await handleServerResponse(response);
|
||||
// // } catch (error) {
|
||||
// // if (error.name == "AbortError") {
|
||||
// // return;
|
||||
// // }
|
||||
// // clearResults();
|
||||
// // setErrorMessage(error.toString());
|
||||
// // } finally {
|
||||
// // setPendingRequest(null);
|
||||
// // }
|
||||
// // }
|
||||
// // doFetch();
|
||||
|
||||
// return () => {
|
||||
// cancelPendingRequest();
|
||||
// };
|
||||
// }, [userName, trie]);
|
||||
|
||||
// const handleServerResponse = useCallback(async (response) => {
|
||||
// clearResults();
|
||||
// const contentType: string = response.headers.get("Content-Type");
|
||||
// if (response.status == 200) {
|
||||
// const { users }: ServerResponse = await response.json();
|
||||
// setUserList(users);
|
||||
// } else if (
|
||||
// !isEmpty(contentType) &&
|
||||
// contentType.startsWith("application/json")
|
||||
// ) {
|
||||
// const { error } = await response.json();
|
||||
// setErrorMessage(`${response.status}: ${error}`);
|
||||
// } else {
|
||||
// const text = await response.text();
|
||||
// setErrorMessage(`${response.status}: ${text}`);
|
||||
// }
|
||||
// }, []);
|
||||
const searchForUserDebounced = useCallback(
|
||||
debounce(async (userName) => {
|
||||
setTypingSettled(true);
|
||||
searchForUser(userName);
|
||||
}, 250),
|
||||
[setTypingSettled, searchForUser]
|
||||
);
|
||||
|
||||
function onSearchInputKeyDown(event) {
|
||||
const { code, shiftKey } = event;
|
||||
@@ -220,7 +138,10 @@ export default function UserSearchBar({ isServerRendered }: PropTypes) {
|
||||
break;
|
||||
case "Enter":
|
||||
if (selectedIdx != null) {
|
||||
setUserName(items[selectedIdx].name);
|
||||
const user = userList[selectedIdx];
|
||||
console.log("selecting user: ", user);
|
||||
setUserName(user.name);
|
||||
inputRef.current.value = user.name;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@@ -239,13 +160,13 @@ export default function UserSearchBar({ isServerRendered }: PropTypes) {
|
||||
}
|
||||
|
||||
function setNewIdxTruncated(newIdx) {
|
||||
if (items.length == 0) {
|
||||
if (userList.length == 0) {
|
||||
newIdx = null;
|
||||
} else {
|
||||
if (newIdx >= items.length) {
|
||||
if (newIdx >= userList.length) {
|
||||
newIdx = 0;
|
||||
} else if (newIdx < 0) {
|
||||
newIdx = items.length - 1;
|
||||
newIdx = userList.length - 1;
|
||||
}
|
||||
}
|
||||
setSelectedIdx(newIdx);
|
||||
@@ -257,9 +178,8 @@ export default function UserSearchBar({ isServerRendered }: PropTypes) {
|
||||
!isEmpty(userName) &&
|
||||
pendingRequest == null &&
|
||||
typingSettled &&
|
||||
items.length == 0;
|
||||
const itemsShown =
|
||||
isFocused && items.length > 0 && typingSettled && pendingRequest == null;
|
||||
userList.length == 0;
|
||||
const itemsShown = isFocused && userList.length > 0;
|
||||
const anyShown = infoShown || errorShown || itemsShown;
|
||||
|
||||
function UserSearchBarItems() {
|
||||
@@ -268,7 +188,7 @@ export default function UserSearchBar({ isServerRendered }: PropTypes) {
|
||||
{errorShown ? (
|
||||
<ListItem
|
||||
key="error"
|
||||
isLast={!infoShown && items.length == 0}
|
||||
isLast={!infoShown && userList.length == 0}
|
||||
selected={false}
|
||||
style="error"
|
||||
value={errorMessage}
|
||||
@@ -284,10 +204,10 @@ export default function UserSearchBar({ isServerRendered }: PropTypes) {
|
||||
/>
|
||||
) : null}
|
||||
{itemsShown
|
||||
? items.map(({ name }, idx) => (
|
||||
? userList.map(({ name }, idx) => (
|
||||
<ListItem
|
||||
key={"name-" + name}
|
||||
isLast={idx == items.length - 1}
|
||||
isLast={idx == userList.length - 1}
|
||||
selected={idx == selectedIdx}
|
||||
style="item"
|
||||
value={name}
|
||||
@@ -325,8 +245,14 @@ export default function UserSearchBar({ isServerRendered }: PropTypes) {
|
||||
].join(" ")}
|
||||
placeholder={"Enter Username"}
|
||||
defaultValue={userName}
|
||||
onChange={(v) => searchForUser(v.target.value)}
|
||||
onKeyDown={(v) => onSearchInputKeyDown(v)}
|
||||
onChange={(v) => {
|
||||
setTypingSettled(false);
|
||||
searchForUserDebounced(v.target.value);
|
||||
}}
|
||||
onKeyDown={(v) => {
|
||||
setIsFocused(true);
|
||||
onSearchInputKeyDown(v);
|
||||
}}
|
||||
onFocus={() => setIsFocused(true)}
|
||||
onBlur={() => setIsFocused(false)}
|
||||
ref={inputRef}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
function buildUsersTrie(users) {
|
||||
const rootNode = new trie();
|
||||
users.forEach(([id, name, urlName]) => {
|
||||
rootNode.insert(name.toLowerCase(), [id, name, urlName]);
|
||||
users.forEach(([id, name]) => {
|
||||
rootNode.insert(name.toLowerCase(), [id, name]);
|
||||
});
|
||||
return JSON.stringify(rootNode.serialize());
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
<header class="bg-slate-100 border-slate-200 border-b-2">
|
||||
<div class="mx-auto max-w-5xl py-6 px-6 sm:px-8 flex items-baseline">
|
||||
<h1 class="text-4xl sm:text-5xl font-bold text-slate-900">
|
||||
<%= @site_title %>
|
||||
<%= link_to @site_title, root_path %>
|
||||
</h1>
|
||||
<div class="flex-grow"></div>
|
||||
<h2 class="text-1xl sm:text-2xl italic font-bold text-slate-500">
|
||||
|
||||
@@ -39,10 +39,7 @@ Rails.application.routes.draw do
|
||||
end
|
||||
end
|
||||
|
||||
# Defines the root path route ("/")
|
||||
# root "articles#index"
|
||||
resources :blobs, only: [:show], slug: :sha256
|
||||
|
||||
resources :log_entries, only: [:index, :show] do
|
||||
get :contents, on: :member
|
||||
get :stats, on: :collection
|
||||
|
||||
@@ -13,7 +13,7 @@ class CreateIndexGoodJobsJobsOnPriorityCreatedAtWhenUnfinished < ActiveRecord::M
|
||||
end
|
||||
|
||||
add_index :good_jobs, [:priority, :created_at], order: { priority: "DESC NULLS LAST", created_at: :asc },
|
||||
where: "finished_at IS NULL", name: :index_good_jobs_jobs_on_priority_created_at_when_unfinished,
|
||||
algorithm: :concurrently
|
||||
where: "finished_at IS NULL", name: :index_good_jobs_jobs_on_priority_created_at_when_unfinished,
|
||||
algorithm: :concurrently
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user