Skip to content

Commit

Permalink
feat: rss flow
Browse files Browse the repository at this point in the history
  • Loading branch information
mikhailmogilnikov committed Jan 9, 2024
1 parent a7cf3ef commit e9bb00b
Show file tree
Hide file tree
Showing 10 changed files with 247 additions and 49 deletions.
26 changes: 18 additions & 8 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,10 @@
"dependencies": {
"@popperjs/core": "^2.11.8",
"ajv": "^8.12.0",
"axios": "^1.6.5",
"bootstrap": "^5.3.2",
"i18next": "^23.7.16",
"lodash": "^4.17.21",
"npm-check-updates": "^16.6.2",
"on-change": "^5.0.0",
"yup": "^1.3.3"
Expand Down
34 changes: 2 additions & 32 deletions src/init.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
import * as yup from 'yup';
import view from './scripts/view.js';
import strings from './utils/strings.js';
import { normalizeUrl } from './scripts/utilities.js';
import domElements from './utils/domElements.js';

const schema = yup.string().required('this is a required field').url();
import controller from './scripts/controller.js';

export default (locales) => {
const state = {
Expand All @@ -15,31 +11,5 @@ export default (locales) => {

const watchedState = view(state, locales);

domElements.form.submit.addEventListener('click', (e) => {
e.preventDefault();

const normalizedValue = normalizeUrl(domElements.form.input.value);

if (state.feedList.includes(normalizedValue)) {
watchedState.formState = strings.formStates.invalid;
watchedState.feedback = strings.feedback.exists;
} else {
schema
.validate(normalizedValue)
.then(() => {
watchedState.formState = strings.formStates.sending;

watchedState.feedList.push(domElements.form.input?.value);
watchedState.feedback = strings.feedback.loaded;
watchedState.formState = strings.formStates.init;

domElements.form.input.value = '';
domElements.form.input?.focus();
})
.catch(() => {
watchedState.formState = strings.formStates.invalid;
watchedState.feedback = strings.feedback.invalidValidation;
});
}
});
controller(state, watchedState);
};
66 changes: 66 additions & 0 deletions src/scripts/controller.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/* eslint-disable no-param-reassign */

import * as yup from 'yup';
import axios from 'axios';
import domElements from '../utils/domElements.js';
import strings from '../utils/strings.js';
import { normalizeUrl, parseRss, parseXML } from './utilities.js';

const schema = yup.string().required('this is a required field').url();

const request = (watchedState, normalizedValue) => {
axios
.get(
`https://allorigins.hexlet.app/get?disableCache=true&url=${encodeURIComponent(
normalizedValue,
)}`,
)
.then((response) => {
try {
const rssDocument = parseXML(response);
parseRss(rssDocument);

watchedState.feedList.push(domElements.form.input?.value);
watchedState.feedback = strings.feedback.loaded;
watchedState.formState = strings.formStates.init;

domElements.form.input.value = '';
domElements.form.input?.focus();
} catch {
watchedState.formState = strings.formStates.invalid;
watchedState.feedback = strings.feedback.invalidRss;
domElements.form.input?.focus();
}
})
.catch((error) => {
console.log(error);
watchedState.formState = strings.formStates.invalid;
watchedState.feedback = strings.feedback.networkError;
domElements.form.input?.focus();
});
};

export default (state, watchedState) => {
domElements.form.submit.addEventListener('click', (e) => {
e.preventDefault();

const normalizedValue = normalizeUrl(domElements.form.input.value);

if (state.feedList.includes(normalizedValue)) {
watchedState.formState = strings.formStates.invalid;
watchedState.feedback = strings.feedback.exists;
} else {
schema
.validate(normalizedValue)
.then(() => {
watchedState.formState = strings.formStates.sending;
request(watchedState, normalizedValue);
})
.catch(() => {
watchedState.formState = strings.formStates.invalid;
watchedState.feedback = strings.feedback.invalidValidation;
domElements.form.input?.focus();
});
}
});
};
43 changes: 41 additions & 2 deletions src/scripts/utilities.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,44 @@
import _ from 'lodash';
import parsedData from '../utils/parsedData.js';

const normalizeUrl = (url) => url.trim().toLowerCase();

const normalizeError = (error) => error.toString().split(': ')[1];
const parseXML = (response) => {
const parser = new DOMParser();
const xmlDoc = parser.parseFromString(response.data.contents, 'text/xml');

const isRSS = xmlDoc.querySelector('rss') !== null;

if (!isRSS) {
throw new Error('not a RSS document');
}

return parser.parseFromString(response.data.contents, 'text/xml');
};

const parseRss = (rssDocument) => {
const items = rssDocument.querySelectorAll('item');
items.forEach((item) => {
const title = item.querySelector('title');
const description = item.querySelector('description');
const link = item.querySelector('link');

parsedData.posts.push({
id: _.uniqueId('item_'),
title: title.textContent,
description: description.textContent,
link: link.textContent,
});
});

const feedTitle = rssDocument.querySelector('title');
const feedDesc = rssDocument.querySelector('description');

parsedData.feed.push({
id: _.uniqueId('feed_'),
title: feedTitle.textContent,
description: feedDesc.textContent,
});
};

export { normalizeUrl, normalizeError };
export { normalizeUrl, parseXML, parseRss };
Loading

0 comments on commit e9bb00b

Please sign in to comment.