rss-reader

Форк
0
/
view.js 
167 строк · 5.5 Кб
1
import onChange from 'on-change';
2

3
const initialInputState = (input, button) => {
4
  button.disabled = false;
5
  input.disabled = false;
6
  input.value = '';
7
  input.focus();
8
};
9

10
const renderState = (input, button, value) => {
11
  if (value === 'processing') {
12
    const oldFeedback = document.querySelector('.feedback');
13
    if (oldFeedback) oldFeedback.remove();
14
    button.disabled = true;
15
    input.disabled = true;
16
    input.classList.remove('is-invalid');
17
    input.classList.remove('is-valid');
18
  }
19
  if (value === 'processed') {
20
    input.classList.add('is-valid');
21
    initialInputState(input, button);
22
  }
23
  if (value === 'failed') {
24
    input.classList.add('is-invalid');
25
    initialInputState(input, button);
26
  }
27
};
28

29
const renderFeedback = (state, i18next, rssForm, value) => {
30
  const oldFeedback = rssForm.parentElement.querySelector('.feedback');
31
  if (oldFeedback) oldFeedback.remove();
32
  const newFeedback = document.createElement('p');
33
  newFeedback.classList.add('feedback', 'm-0', 'position-absolute', 'small');
34
  let newTextContent;
35
  if (value === 'waiting') {
36
    newTextContent = i18next.t('feedback.uploadingRss');
37
    newFeedback.classList.add('text-white-50');
38
  }
39
  if (value === 'valid') {
40
    newTextContent = i18next.t('feedback.uploadedRss');
41
    newFeedback.classList.add('text-success');
42
  }
43
  if (value === 'invalid') {
44
    const errorMessage = state.formState.errors.at(-1);
45
    newTextContent = i18next.t(errorMessage);
46
    newFeedback.classList.add('text-danger');
47
  }
48
  newFeedback.textContent = newTextContent;
49
  rssForm.parentElement.append(newFeedback);
50
};
51

52
const renderFeeds = (feeds, value) => {
53
  let card;
54
  if (feeds.querySelector('.card')) {
55
    card = feeds.querySelector('.card');
56
  } else {
57
    card = document.createElement('div');
58
    card.classList.add('card', 'border-0');
59
    card.innerHTML = `<div class="card-body"><h2 class="card-title h4">Фиды</h2></div>
60
    <ul class="list-group border-0 rounded-0"></ul>`;
61
    feeds.append(card);
62
  }
63
  const listGroup = feeds.querySelector('.list-group');
64
  listGroup.innerHTML = '';
65
  value.forEach((feed) => {
66
    const li = document.createElement('li');
67
    li.classList.add('list-group-item', 'border-0', 'border-end-0');
68
    const h3 = document.createElement('h3');
69
    h3.classList.add('h6', 'm-0');
70
    h3.textContent = feed.title;
71
    const p = document.createElement('p');
72
    p.classList.add('m-0', 'small', 'text-black-50');
73
    p.textContent = feed.description;
74
    li.append(h3);
75
    li.append(p);
76
    listGroup.prepend(li);
77
  });
78
};
79

80
const renderPosts = (posts, value, prevValue) => {
81
  let newPosts;
82
  if (prevValue === undefined) {
83
    newPosts = value;
84
  } else if (prevValue !== undefined) {
85
    const isObjInPrevValue = (newPost) => prevValue.some((prevPost) => prevPost.id === newPost.id);
86
    newPosts = value.filter((newPost) => !isObjInPrevValue(newPost));
87
  }
88
  let card;
89
  if (posts.querySelector('.card')) {
90
    card = posts.querySelector('.card');
91
  } else {
92
    card = document.createElement('div');
93
    card.classList.add('card', 'border-0');
94
    card.innerHTML = `<div class="card-body"><h2 class="card-title h4">Посты</h2></div>
95
<ul class="list-group border-0 rounded-0"></ul>`;
96
    posts.append(card);
97
  }
98
  const listGroup = posts.querySelector('.list-group');
99
  newPosts.forEach((post) => {
100
    const li = document.createElement('li');
101
    li.classList.add('list-group-item', 'd-flex', 'justify-content-between', 'align-items-start', 'border-0', 'border-end-0');
102
    const link = document.createElement('a');
103
    link.href = post.link;
104
    link.classList.add('fw-bold');
105
    link.setAttribute('data-id', post.id);
106
    link.target = '_blank';
107
    link.rel = 'noopener noreferrer';
108
    link.textContent = post.title;
109
    const button = document.createElement('button');
110
    button.type = 'button';
111
    button.classList.add('btn', 'btn-outline-primary', 'btn-sm');
112
    button.setAttribute('data-id', post.id);
113
    button.setAttribute('data-bs-toggle', 'modal');
114
    button.setAttribute('data-bs-target', '#modal');
115
    button.textContent = 'Просмотр';
116
    li.append(link);
117
    li.append(button);
118
    listGroup.prepend(li);
119
  });
120
};
121

122
const renderViewedLink = (value, prevValue) => {
123
  const findNewId = () => Array.from(new Set([...value].filter((item) => !prevValue.has(item))))[0];
124
  const newId = findNewId();
125
  const link = document.querySelector(`a[data-id="${newId}"]`);
126
  link.classList.remove('fw-bold');
127
  link.classList.add('fw-normal', 'link-secondary');
128
};
129

130
const renderModal = (modal, value) => {
131
  const modalTitle = modal.querySelector('.modal-title');
132
  const modalBody = modal.querySelector('.modal-body');
133
  const read = modal.querySelector('.modal-footer').querySelector('a');
134
  modalTitle.textContent = value.title;
135
  modalBody.textContent = value.description;
136
  read.href = value.link;
137
};
138

139
const render = (state, i18next, elements) => (path, value, prevValue) => {
140
  const {
141
    rssForm, button, input, modal, feeds, posts,
142
  } = elements;
143
  switch (path) {
144
    case 'state':
145
      renderState(input, button, value);
146
      break;
147
    case 'formState.isValid':
148
      renderFeedback(state, i18next, rssForm, value);
149
      break;
150
    case 'data.feeds':
151
      renderFeeds(feeds, value);
152
      break;
153
    case 'data.posts':
154
      renderPosts(posts, value, prevValue);
155
      break;
156
    case 'uiState.viewedPostsId':
157
      renderViewedLink(value, prevValue);
158
      break;
159
    case 'uiState.vievedPost':
160
      renderModal(modal, value);
161
      break;
162
    default:
163
      break;
164
  }
165
};
166

167
export default (state, i18next, elements) => onChange(state, render(state, i18next, elements));
168

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.