Anonymous
Нужна помощь, чтобы создать сообщение успеха
Сообщение
Anonymous » 01 фев 2025, 20:20
Итак, я пытаюсь создать проект - rss reader, и у меня есть проблема.
После добавления нового RSS -канала у меня нет сообщения под URL -входом о нагрузке с помощью RSS. < /p>
Я перепробовал все и не могу найти проблему. Может ли кто -нибудь помочь мне с этой проблемой? < /p>
Код: Выделить всё
import i18next from 'i18next';
import { initView } from './view.js';
import { createSchema } from './validate.js';
import { fetchRss } from './rss.js';
import { parseRSS } from './parser.js';
import { checkForUpdates } from './updater.js';
export default () => {
const state = {
urls: [],
isValid: true,
error: '',
feeds: [],
posts: [],
readPostIds: [],
loading: false,
};
i18next.init({
lng: 'ru',
resources: {
ru: {
translation: {
success: 'RSS успешно загружен',
invalidUrl: 'Ссылка должна быть валидным URL',
existingUrl: 'RSS уже существует',
required: 'Не должно быть пустым',
networkError: 'Ошибка сети',
invalidRSS: 'Ресурс не содержит валидный RSS',
},
},
},
});
const watchedState = initView(state, i18next);
const form = document.querySelector('.rss-form');
form.addEventListener('submit', async (e) => {
e.preventDefault();
const formData = new FormData(e.target);
const url = formData.get('url').trim();
const schema = createSchema(watchedState.urls);
try {
if (watchedState.urls.includes(url)) {
throw new Error('existingUrl');
}
await schema.validate(url);
watchedState.loading = true;
const rssData = await fetchRss(url);
const { feed, posts } = parseRSS(rssData);
watchedState.feeds.push(feed);
watchedState.posts.push(...posts.map((post, index) => ({
...post,
id: `post-${index}`,
})));
watchedState.urls.push(url);
watchedState.isValid = true;
watchedState.error = '';
watchedState.feeds = [...watchedState.feeds];
watchedState.posts = [...watchedState.posts];
watchedState.urls = [...watchedState.urls];
if (watchedState.urls.length === 1 && !watchedState.loading) {
setTimeout(() => checkForUpdates(watchedState), 1000);
}
} catch (err) {
if (err.name === 'ValidationError') {
watchedState.error = err.message;
} else {
watchedState.error = i18next.t(err.message);
}
watchedState.isValid = false;
} finally {
watchedState.loading = false;
}
});
};
< /code>
view.js
import onChange from 'on-change';
import { Modal } from 'bootstrap';
export const initView = (state, i18next) => {
const input = document.querySelector('#url-input');
const feedback = document.querySelector('.feedback');
const feedsContainer = document.querySelector('.feeds');
const postsContainer = document.querySelector('.posts');
const modalTitle = document.querySelector('.modal-title');
const modalBody = document.querySelector('.modal-body');
const fullArticleLink = document.querySelector('.full-article');
const modalElement = document.getElementById('modal');
const modal = new Modal(modalElement);
const handlePostClick = (post) => {
if (!post.title || !post.description || !post.link) {
return;
}
modalTitle.textContent = post.title;
modalBody.innerHTML = post.description;
fullArticleLink.href = post.link;
modal.show();
};
const renderFeeds = () => {
feedsContainer.innerHTML = `
[h4]Фиды[/h4]
${state.feeds.map((feed) => `
${feed.title}
${feed.description}
`).join('')}
`;
};
const renderPosts = () => {
postsContainer.innerHTML = `
[h4]Посты[/h4]
${state.posts.map((post) => `
[url=${post.link}]
${post.title}
[/url]
Просмотр
`).join('')}
`;
document.querySelectorAll('.post-link').forEach((link) => {
link.addEventListener('click', (e) => {
const postId = e.target.dataset.postId;
if (postId && !state.readPostIds.includes(postId)) {
state.readPostIds.push(postId);
e.target.classList.add('text-muted', 'fw-normal');
e.target.classList.remove('fw-bold')
}
});
});
document.querySelectorAll('.btn-outline-primary').forEach((button) => {
button.addEventListener('click', (e) => {
e.preventDefault();
const postId = e.target.dataset.postId;
const post = state.posts.find((p) => p.id === postId);
if (post) {
handlePostClick(post);
if (!state.readPostIds.includes(postId)) {
state.readPostIds.push(postId);
const postLink = document.querySelector(`.post-link[data-post-id="${postId}"]`)
if (postLink) {
postLink.classList.add('text-muted', 'fw-normal');
postLink.classList.remove('fw-bold')
}
}
}
});
});
};
return onChange(state, (path) => {
if (path === 'isValid' || path === 'error') {
if (state.isValid) {
feedback.textContent = i18next.t('success');
feedback.classList.replace('text-danger', 'text-success');
input.classList.remove('is-invalid');
input.value = '';
input.focus();
} else {
feedback.textContent = i18next.t(state.error);
feedback.classList.replace('text-success', 'text-danger');
input.classList.add('is-invalid');
}
}
if (path === 'feeds') {
renderFeeds();
}
if (path === 'posts' || path === 'readPostIds') {
renderPosts();
}
});
};
< /code>
updater.js
import { fetchRss } from "./rss.js";
import { parseRSS } from "./parser.js"
export const checkForUpdates = async (state) => {
try {
for (const url of state.urls) {
const rssData = await fetchRss(url);
const { posts: newPosts } = parseRSS(rssData)
const existingUrl = state.posts.map((post) => post.link);
const uniqueNewPosts = newPosts.filter(
(post) => !existingUrl.includes(post.link)
);
if (uniqueNewPosts.length > 0) {
state.posts.unshift(...uniqueNewPosts);
}
}
} catch (err) {
console.log('Error', err);
} finally {
setTimeout(() => checkForUpdates(state), 5000)
}
}
Я попытался изменить состояние
Подробнее здесь:
https://stackoverflow.com/questions/794 ... ss-message
1738430423
Anonymous
Итак, я пытаюсь создать проект - rss reader, и у меня есть проблема. После добавления нового RSS -канала у меня нет сообщения под URL -входом о нагрузке с помощью RSS. < /p> Я перепробовал все и не могу найти проблему. Может ли кто -нибудь помочь мне с этой проблемой? < /p> [code]import i18next from 'i18next'; import { initView } from './view.js'; import { createSchema } from './validate.js'; import { fetchRss } from './rss.js'; import { parseRSS } from './parser.js'; import { checkForUpdates } from './updater.js'; export default () => { const state = { urls: [], isValid: true, error: '', feeds: [], posts: [], readPostIds: [], loading: false, }; i18next.init({ lng: 'ru', resources: { ru: { translation: { success: 'RSS успешно загружен', invalidUrl: 'Ссылка должна быть валидным URL', existingUrl: 'RSS уже существует', required: 'Не должно быть пустым', networkError: 'Ошибка сети', invalidRSS: 'Ресурс не содержит валидный RSS', }, }, }, }); const watchedState = initView(state, i18next); const form = document.querySelector('.rss-form'); form.addEventListener('submit', async (e) => { e.preventDefault(); const formData = new FormData(e.target); const url = formData.get('url').trim(); const schema = createSchema(watchedState.urls); try { if (watchedState.urls.includes(url)) { throw new Error('existingUrl'); } await schema.validate(url); watchedState.loading = true; const rssData = await fetchRss(url); const { feed, posts } = parseRSS(rssData); watchedState.feeds.push(feed); watchedState.posts.push(...posts.map((post, index) => ({ ...post, id: `post-${index}`, }))); watchedState.urls.push(url); watchedState.isValid = true; watchedState.error = ''; watchedState.feeds = [...watchedState.feeds]; watchedState.posts = [...watchedState.posts]; watchedState.urls = [...watchedState.urls]; if (watchedState.urls.length === 1 && !watchedState.loading) { setTimeout(() => checkForUpdates(watchedState), 1000); } } catch (err) { if (err.name === 'ValidationError') { watchedState.error = err.message; } else { watchedState.error = i18next.t(err.message); } watchedState.isValid = false; } finally { watchedState.loading = false; } }); }; < /code> view.js import onChange from 'on-change'; import { Modal } from 'bootstrap'; export const initView = (state, i18next) => { const input = document.querySelector('#url-input'); const feedback = document.querySelector('.feedback'); const feedsContainer = document.querySelector('.feeds'); const postsContainer = document.querySelector('.posts'); const modalTitle = document.querySelector('.modal-title'); const modalBody = document.querySelector('.modal-body'); const fullArticleLink = document.querySelector('.full-article'); const modalElement = document.getElementById('modal'); const modal = new Modal(modalElement); const handlePostClick = (post) => { if (!post.title || !post.description || !post.link) { return; } modalTitle.textContent = post.title; modalBody.innerHTML = post.description; fullArticleLink.href = post.link; modal.show(); }; const renderFeeds = () => { feedsContainer.innerHTML = ` [h4]Фиды[/h4] ${state.feeds.map((feed) => ` ${feed.title} ${feed.description} `).join('')} `; }; const renderPosts = () => { postsContainer.innerHTML = ` [h4]Посты[/h4] ${state.posts.map((post) => ` [url=${post.link}] ${post.title} [/url] Просмотр `).join('')} `; document.querySelectorAll('.post-link').forEach((link) => { link.addEventListener('click', (e) => { const postId = e.target.dataset.postId; if (postId && !state.readPostIds.includes(postId)) { state.readPostIds.push(postId); e.target.classList.add('text-muted', 'fw-normal'); e.target.classList.remove('fw-bold') } }); }); document.querySelectorAll('.btn-outline-primary').forEach((button) => { button.addEventListener('click', (e) => { e.preventDefault(); const postId = e.target.dataset.postId; const post = state.posts.find((p) => p.id === postId); if (post) { handlePostClick(post); if (!state.readPostIds.includes(postId)) { state.readPostIds.push(postId); const postLink = document.querySelector(`.post-link[data-post-id="${postId}"]`) if (postLink) { postLink.classList.add('text-muted', 'fw-normal'); postLink.classList.remove('fw-bold') } } } }); }); }; return onChange(state, (path) => { if (path === 'isValid' || path === 'error') { if (state.isValid) { feedback.textContent = i18next.t('success'); feedback.classList.replace('text-danger', 'text-success'); input.classList.remove('is-invalid'); input.value = ''; input.focus(); } else { feedback.textContent = i18next.t(state.error); feedback.classList.replace('text-success', 'text-danger'); input.classList.add('is-invalid'); } } if (path === 'feeds') { renderFeeds(); } if (path === 'posts' || path === 'readPostIds') { renderPosts(); } }); }; < /code> updater.js import { fetchRss } from "./rss.js"; import { parseRSS } from "./parser.js" export const checkForUpdates = async (state) => { try { for (const url of state.urls) { const rssData = await fetchRss(url); const { posts: newPosts } = parseRSS(rssData) const existingUrl = state.posts.map((post) => post.link); const uniqueNewPosts = newPosts.filter( (post) => !existingUrl.includes(post.link) ); if (uniqueNewPosts.length > 0) { state.posts.unshift(...uniqueNewPosts); } } } catch (err) { console.log('Error', err); } finally { setTimeout(() => checkForUpdates(state), 5000) } } [/code] Я попытался изменить состояние Подробнее здесь: [url]https://stackoverflow.com/questions/79405379/need-help-to-create-a-success-message[/url]