Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(topic): encode ref in case it has question marks or other problem… #1932

Merged
merged 3 commits into from
Jun 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions sefaria/model/trend.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@
import time
from datetime import datetime, date, timedelta

from py import process

from . import abstract as abst
from . import user_profile
from . import text
Expand Down
5 changes: 3 additions & 2 deletions static/js/BookPage.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {
AdminToolHeader,
CategoryChooser,
TitleVariants,
CategoryHeader, requestWithCallBack
CategoryHeader
} from './Misc';
import {ContentText} from "./ContentText";
import {validateMarkdownLinks} from "./AdminEditor";
Expand Down Expand Up @@ -1293,7 +1293,8 @@ const EditTextInfo = function({initTitle, close}) {
const deleteObj = () => {
setSavingStatus(true);
const url = `/api/v2/index/${enTitle}`;
requestWithCallBack({url, type: "DELETE", redirect: () => window.location.href = `/texts`});
Sefaria.adminEditorApiRequest(url, null, null, "DELETE")
.then(() => window.location.href = '/texts');
}
const renderCollectiveTitle = () => {
if (!creatingCollectiveTitle) {
Expand Down
13 changes: 9 additions & 4 deletions static/js/CategoryEditor.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import {CategoryChooser, InterfaceText, ToggleSet} from "./Misc";
import Sefaria from "./sefaria/sefaria";
import $ from "./sefaria/sefariaJquery";
import {AdminEditor} from "./AdminEditor";
import {requestWithCallBack, AdminToolHeader} from "./Misc";
import {AdminToolHeader} from "./Misc";
import React, {useState, useRef} from "react";

const displayOptionForSources = (child) => {
Expand Down Expand Up @@ -84,7 +84,9 @@ const ReorderEditor = ({close, type="", postURL="", redirect="", origItems = []}
else if (type === 'sources') {
postCategoryData = {sources: tocItems};
}
requestWithCallBack({url: postURL, data: postCategoryData, setSavingStatus, redirect: () => window.location.href = redirect})
Sefaria.adminEditorApiRequest(postURL, null, postCategoryData)
.then(() => window.location.href = redirect)
.finally(() => setSavingStatus(false));
}
return <div className="editTextInfo">
<div className="static">
Expand Down Expand Up @@ -187,7 +189,9 @@ const CategoryEditor = ({origData={}, close, origPath=[]}) => {
if (urlParams.length > 0) {
url += `?${urlParams.join('&')}`;
}
requestWithCallBack({url, data: postCategoryData, setSavingStatus, redirect: () => window.location.href = "/texts/"+fullPath});
Sefaria.adminEditorApiRequest(url, null, postCategoryData)
.then(() => window.location.href = "/texts/"+fullPath)
.finally(() => setSavingStatus(false));
}


Expand All @@ -197,7 +201,8 @@ const CategoryEditor = ({origData={}, close, origPath=[]}) => {
return;
}
const url = `/api/category/${origPath.concat(origData.origEn).join("/")}`;
requestWithCallBack({url, type: "DELETE", redirect: () => window.location.href = `/texts`});
Sefaria.adminEditorApiRequest(url, null, null, "DELETE")
.then(() => window.location.href = `/texts`);
}
const primaryOptions = [
{name: "true", content: Sefaria._("True"), role: "radio", ariaLabel: Sefaria._("Set Primary Status to True") },
Expand Down
26 changes: 1 addition & 25 deletions static/js/Misc.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -1045,29 +1045,6 @@ class ToggleOption extends Component {
}
}

//style={this.props.style}

const requestWithCallBack = ({url, setSavingStatus, redirect, type="POST", data={}, redirect_params}) => {
let ajaxPayload = {url, type};
if (type === "POST") {
ajaxPayload.data = {json: JSON.stringify(data)};
}
$.ajax({
...ajaxPayload,
success: function(result) {
if ("error" in result) {
if (setSavingStatus) {
setSavingStatus(false);
}
alert(result.error);
} else {
redirect();
}
}
}).fail(function() {
alert(Sefaria._("Something went wrong. Sorry!"));
});
}

const TopicToCategorySlug = function(topic, category=null) {
//helper function for AdminEditor
Expand Down Expand Up @@ -1676,7 +1653,7 @@ const TopicPictureUploader = ({slug, callback, old_filename, caption}) => {
const deleteImage = () => {
const old_filename_wout_url = old_filename.split("/").slice(-1);
const url = `${Sefaria.apiHost}/api/topics/images/${slug}?old_filename=${old_filename_wout_url}`;
requestWithCallBack({url, type: "DELETE", redirect: () => alert("Deleted image.")});
Sefaria.adminEditorApiRequest(url, null, null, "DELETE").then(() => alert("Deleted image."));
callback("");
fileInput.current.value = "";
}
Expand Down Expand Up @@ -3385,7 +3362,6 @@ export {
AdminToolHeader,
CategoryChooser,
TitleVariants,
requestWithCallBack,
OnInView,
TopicPictureUploader,
ImageWithCaption
Expand Down
21 changes: 14 additions & 7 deletions static/js/SourceEditor.jsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import Sefaria from "./sefaria/sefaria";
import $ from "./sefaria/sefariaJquery";
import {AdminEditor} from "./AdminEditor";
import {requestWithCallBack, Autocompleter, InterfaceText} from "./Misc";
import {Autocompleter, InterfaceText} from "./Misc";
import React, {useState} from "react";
import {useRef} from "react";

Expand Down Expand Up @@ -46,10 +46,16 @@ const SourceEditor = ({topic, close, origData={}}) => {
const save = async function () {
setSavingStatus(true);
let refInUrl = isNew ? displayRef : origData.ref;
let url = `/api/ref-topic-links/${Sefaria.normRef(refInUrl)}`;
let postData = {"topic": topic, "is_new": isNew, 'new_ref': displayRef, 'interface_lang': Sefaria.interfaceLang};
postData['description'] = {"title": data.enTitle, "prompt": data.prompt, "ai_context": data.ai_context, "review_state": "edited"};
requestWithCallBack({url, data: postData, setSavingStatus, redirect: () => window.location.href = "/topics/"+topic});
const payload = {
new_ref: displayRef,
topic,
is_new: isNew,
interface_lang: Sefaria.interfaceLang,
description: {"title": data.enTitle, "prompt": data.prompt, "ai_context": data.ai_context, "review_state": "edited"},
}
Sefaria.postRefTopicLink(refInUrl, payload)
.then(() => window.location.href = `/topics/${topic}`)
.finally(() => setSavingStatus(false));
}

const handleChange = (x) => {
Expand Down Expand Up @@ -86,8 +92,9 @@ const SourceEditor = ({topic, close, origData={}}) => {
}

const deleteTopicSource = function() {
const url = `/api/ref-topic-links/${origData.ref}?topic=${topic}&interface_lang=${Sefaria.interfaceLang}`;
requestWithCallBack({url, type: "DELETE", redirect: () => window.location.href = `/topics/${topic}`});
const url = `/api/ref-topic-links/${Sefaria.normRef(origData.ref)}?topic=${topic}&interface_lang=${Sefaria.interfaceLang}`;
Sefaria.adminEditorApiRequest(url, null, null, "DELETE")
.then(() => window.location.href = `/topics/${topic}`);
}
const previousTitleItemRef = useRef(data.enTitle ? "Previous Title" : null); //use useRef to make value null even if component re-renders
const previousPromptItemRef = useRef(data.prompt ? "Previous Prompt" : null);
Expand Down
4 changes: 2 additions & 2 deletions static/js/Story.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -170,14 +170,14 @@ const ReviewStateIndicatorLang = ({reviewState, markReviewed}) => {
}

const markReviewedPostRequest = (lang, topic, topicLink) => {
const postData = {
const payload = {
"topic": topic,
"is_new": false,
'new_ref': topicLink.ref,
'interface_lang': lang === 'en' ? 'english' : 'hebrew',
'description' : {...topicLink.descriptions[lang], 'review_state': 'reviewed'}
};
return Sefaria.postToApi(`/api/ref-topic-links/${topicLink.ref}`, {}, postData);
return Sefaria.postRefTopicLink(topicLink.ref, payload);
}

const useReviewState = (topic, topicLink) => {
Expand Down
8 changes: 5 additions & 3 deletions static/js/TopicEditor.jsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import Sefaria from "./sefaria/sefaria";
import {InterfaceText, requestWithCallBack, TopicPictureUploader} from "./Misc";
import {InterfaceText, TopicPictureUploader} from "./Misc";
import $ from "./sefaria/sefariaJquery";
import {AdminEditor} from "./AdminEditor";
import {Reorder} from "./CategoryEditor";
Expand Down Expand Up @@ -109,7 +109,9 @@ const TopicEditor = ({origData, onCreateSuccess, close, origWasCat}) => {
const saveReorderedSubtopics = function () {
const url = `/api/topic/reorder`;
const postCategoryData = {topics: sortedSubtopics};
requestWithCallBack({url, data: postCategoryData, setSavingStatus, redirect: () => window.location.href = "/topics"});
Sefaria.adminEditorApiRequest(url, null, postCategoryData)
.then(() => window.location.href = "/topics")
.finally(() => setSavingStatus(false));
}

const prepData = () => {
Expand Down Expand Up @@ -189,7 +191,7 @@ const TopicEditor = ({origData, onCreateSuccess, close, origWasCat}) => {

const deleteObj = function() {
const url = `/api/topic/delete/${data.origSlug}`;
requestWithCallBack({url, type: "DELETE", redirect: () => window.location.href = "/topics"});
Sefaria.adminEditorApiRequest(url, null, null, "DELETE").then(() => window.location.href = "/topics");
}
let items = ["Title", "Hebrew Title", "English Description", "Hebrew Description", "Category Menu", "English Alternate Titles", "Hebrew Alternate Titles",];
if (isCategory) {
Expand Down
4 changes: 2 additions & 2 deletions static/js/TopicPage.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -344,7 +344,7 @@ const generatePrompts = async(topicSlug, linksToGenerate) => {
});
const payload = {ref_topic_links: linksToGenerate};
try {
await Sefaria.postToApi(`/api/topics/generate-prompts/${topicSlug}`, {}, payload);
await Sefaria.apiRequestWithBody(`/api/topics/generate-prompts/${topicSlug}`, {}, payload);
const refValues = linksToGenerate.map(item => item.ref).join(", ");
alert("The following prompts are generating: " + refValues);
} catch (error) {
Expand All @@ -359,7 +359,7 @@ const publishPrompts = async (topicSlug, linksToPublish) => {
ref.descriptions[lang]["published"] = true;
});
try {
const response = await Sefaria.postToApi(`/api/ref-topic-links/bulk`, {}, linksToPublish);
const response = await Sefaria.apiRequestWithBody(`/api/ref-topic-links/bulk`, {}, linksToPublish);
const refValues = response.map(item => item.anchorRef).join(", ");
const shouldRefresh = confirm("The following prompts have been published: " + refValues + ". Refresh page to see results?");
if (shouldRefresh) {
Expand Down
18 changes: 6 additions & 12 deletions static/js/TopicSearch.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -68,27 +68,21 @@ class TopicSearch extends Component {
const srefs = this.props.srefs;
const update = this.props.update;
const reset = this.reset;
$.post("/api/ref-topic-links/" + Sefaria.normRef(this.props.srefs), {"json": postJSON}, async function (data) {
if (data.error) {
alert(data.error);
} else {
Sefaria.postRefTopicLink(Sefaria.normRef(this.props.srefs), postJSON).then(async () => {
const sectionRef = await Sefaria.getRef(Sefaria.normRef(srefs)).sectionRef;
srefs.map(sref => {
if (!Sefaria._refTopicLinks[sref]) {
Sefaria._refTopicLinks[sref] = [];
}
Sefaria._refTopicLinks[sref].push(data);
if (!Sefaria._refTopicLinks[sref]) {
Sefaria._refTopicLinks[sref] = [];
}
Sefaria._refTopicLinks[sref].push(data);
});
if (!Sefaria._refTopicLinks[sectionRef]) {
Sefaria._refTopicLinks[sectionRef] = [];
Sefaria._refTopicLinks[sectionRef] = [];
}
Sefaria._refTopicLinks[sectionRef].push(data);
update();
reset();
alert("Topic added.");
}
}).fail(function (xhr, status, errorThrown) {
alert("Unfortunately, there may have been an error saving this topic information: " + errorThrown);
});
}

Expand Down
37 changes: 31 additions & 6 deletions static/js/sefaria/sefaria.js
Original file line number Diff line number Diff line change
Expand Up @@ -623,27 +623,52 @@ Sefaria = extend(Sefaria, {
firstName: firstName,
lastName: lastName,
};
return await Sefaria.postToApi(`/api/subscribe/${email}`, null, payload);
return await Sefaria.apiRequestWithBody(`/api/subscribe/${email}`, null, payload);
},
subscribeSteinsaltzNewsletter: async function(firstName, lastName, email) {
const payload = {firstName, lastName};
return await Sefaria.postToApi(`/api/subscribe/steinsaltz/${email}`, null, payload);
return await Sefaria.apiRequestWithBody(`/api/subscribe/steinsaltz/${email}`, null, payload);
},

postToApi: async function(url, urlParams, payload) {
postRefTopicLink: function(refInUrl, payload) {
const url = `/api/ref-topic-links/${Sefaria.normRef(refInUrl)}`;
// payload will need to be refactored once /api/ref-topic-links takes a more standard input
return Sefaria.adminEditorApiRequest(url, null, payload);
},
adminEditorApiRequest: async function(url, urlParams, payload, method="POST") {
/**
* Wraps apiRequestWithBody() with basic alerting if response has an error
*/
let result;
try {
result = await Sefaria.apiRequestWithBody(url, urlParams, payload, method);
} catch (e) {
alert(Sefaria._("Something went wrong. Sorry!"));
throw e;
}
if (result.error) {
alert(result.error);
throw result.error;
} else {
return result;
}
},
apiRequestWithBody: async function(url, urlParams, payload, method="POST") {
/**
* Generic function for performing an API request with a payload. Payload and urlParams are optional and will not be used if falsy.
*/
let apiUrl = this.apiHost + url;
if (urlParams) {
apiUrl += '?' + new URLSearchParams(urlParams).toString();
}
const response = await fetch(apiUrl, {
method: "POST",
method,
mode: 'same-origin',
headers: {
'X-CSRFToken': Cookies.get('csrftoken'),
'Content-Type': 'application/json'
},
credentials: 'same-origin',
body: JSON.stringify(payload)
body: payload && JSON.stringify(payload)
});

if (!response.ok) {
Expand Down
Loading