Proyectos de Subversion LeadersLinked - Antes de SPA

Rev

Rev 1009 | Rev 1019 | Ir a la última revisión | | Comparar con el anterior | Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 www 1
import React, { useState, useEffect } from "react";
2
import { connect } from "react-redux";
3
import { Button, Modal } from "react-bootstrap";
4
import { useForm } from "react-hook-form";
5
import styled from "styled-components";
6
import FormErrorFeedback from "../../../shared/form-error-feedback/FormErrorFeedback";
7
import Spinner from "../../../shared/loading-spinner/Spinner";
8
import { addNotification } from "../../../redux/notification/notification.actions";
9
import {
10
  closeShareModal,
11
  openShareModal,
12
  setModalType,
13
} from "../../../redux/share-modal/shareModal.actions";
1005 steven 14
import { addFeed, fetchFeeds } from "../../../redux/feed/feed.actions";
1 www 15
import DropzoneComponent from "../../../shared/dropzone/DropzoneComponent";
16
import { shareModalTypes } from "../../../redux/share-modal/shareModal.types";
17
import { feedTypes } from "../../../redux/feed/feed.types";
1018 stevensc 18
import { CKEditor } from "ckeditor4-react";
19
import { axios } from "../../../utils";
20
import { CKEditor } from "ckeditor4-react";
21
import { axios } from "../../../utils";
1 www 22
import ConfirmModal from "../../../shared/confirm-modal/ConfirmModal";
23
 
24
const StyledSpinnerContainer = styled.div`
25
  position: absolute;
26
  left: 0;
27
  top: 0;
28
  width: 100%;
29
  height: 100%;
30
  background: rgba(255, 255, 255, 0.4);
31
  display: flex;
32
  justify-content: center;
33
  align-items: center;
34
  z-index: 300;
35
`;
36
 
37
const ShareModal = (props) => {
38
  // Redux State Destructuring
39
  const {
40
    postUrl,
41
    isOpen,
42
    modalType,
43
    lastModalType,
44
    setModalType,
45
    feedType,
1007 steven 46
    fetchFeeds,
47
    currentPage,
1018 stevensc 48
    timelineUrl,
49
    feedSharedId
1 www 50
  } = props;
51
  // Redux dispatch Destructuring
52
  const { closeShareModal, addNotification, addFeed, openShareModal } = props;
53
  // states
54
  const [loading, setLoading] = useState(false);
55
  const [isCKEditorLoading, setIsCKEditorLoading] = useState(true);
56
  const [showConfirmModal, setShowConfirmModal] = useState(false);
57
 
58
  const {
59
    register,
60
    unregister,
61
    errors,
62
    handleSubmit,
63
    setValue,
64
    watch,
65
    getValues,
66
    clearErrors,
67
    setError,
68
  } = useForm({
69
    defaultValues: {
70
      description: "",
71
      share_width: "",
72
    },
73
  });
74
 
75
  useEffect(() => {
76
    register("description", {
77
      required: { value: "true", message: "El campo es requerido" },
78
    });
79
    register("posted_or_shared");
80
    if (
81
      modalType !== shareModalTypes.POST &&
82
      modalType !== shareModalTypes.SHARE
83
    ) {
84
      register("file", {
85
        required: { value: "true", message: "El campo es requerido" },
86
      });
87
    } else {
88
      if (!getValues("file")) unregister("file");
89
    }
90
  }, [modalType]);
91
 
92
  const recomendationText = () => {
93
    switch (modalType) {
94
      case shareModalTypes.IMAGE:
95
        return "Tamaño recomendado: 720x720";
96
      case shareModalTypes.FILE:
97
        return "solo documentos PDF";
98
      case shareModalTypes.VIDEO:
99
        return "Video de extensión mp4, mpeg, webm";
100
      default:
101
        return "";
102
    }
103
  };
104
  useEffect(() => {
105
    const postedOrShared = modalType === shareModalTypes.SHARE ? "s" : "p";
106
    setValue("posted_or_shared", postedOrShared);
107
    if (getValues("file") || getValues("description")) {
108
      if (modalType !== lastModalType) {
109
        closeShareModal();
110
        handleShowConfirmModal();
111
      }
112
    }
113
  }, [modalType]);
868 steven 114
  const hideDuplicatedModal = () => {
115
    setTimeout(() => {
116
      const modals = document.getElementsByClassName('modal');
1018 stevensc 117
      if (modals.length > 0 && modals[0].style.display !== 'none') {
870 steven 118
        const currentModal = modals[0];
119
        currentModal.style.display = 'none';
946 steven 120
        for (let index = 0; index < modals.length; index++) {
121
          const element = modals[index];
1018 stevensc 122
          element.removeAttribute("tabindex");
946 steven 123
        }
870 steven 124
      }
868 steven 125
    }, 3000);
126
  }
984 steven 127
 
1 www 128
  useEffect(() => {
129
    clearErrors();
868 steven 130
    hideDuplicatedModal();
1 www 131
  }, [isOpen]);
132
 
133
  const handleShowConfirmModal = () => {
134
    setShowConfirmModal(!showConfirmModal);
135
  };
136
 
137
  const handleModalAccept = () => {
138
    setShowConfirmModal(false);
139
    setValue("description", "");
140
    setValue("file", "");
141
    openShareModal(postUrl, modalType, feedType);
142
    clearErrors();
143
  };
144
 
145
  const handleModalCancel = () => {
146
    setShowConfirmModal(false);
147
    closeShareModal();
148
    setModalType(lastModalType);
149
    openShareModal(postUrl, lastModalType, feedType);
150
  };
151
 
152
  const onSubmit = async (data, e) => {
153
    setLoading(true);
154
    const currentFormData = new FormData();
155
    for (let input in data) {
156
      currentFormData.append(input, data[input]);
1018 stevensc 157
      (`${input}:${data[input]}`);
1 www 158
    }
159
    await axios.post(postUrl, currentFormData).then((response) => {
160
      const data = response.data;
161
      const newFeed = data.data;
1018 stevensc 162
      (data);
1 www 163
      if (data.success) {
164
        closeShareModal();
165
        // reset data
166
        e.target.reset();
167
        setValue("description", "");
168
        setValue("file", "");
169
        clearErrors();
170
        addNotification({
171
          style: "success",
172
          msg: "La publicación ha sido compartida",
173
        });
1018 stevensc 174
        if (feedSharedId) {
175
          addFeed(newFeed, feedSharedId);
176
        } else {
177
          addFeed(newFeed);
178
        }
1009 steven 179
        if (modalType !== shareModalTypes.SHARE) {
1008 steven 180
          console.log('>>: currentPage', currentPage, timelineUrl)
1009 steven 181
        }
1018 stevensc 182
        if (currentPage && timelineUrl) {
1009 steven 183
          fetchFeeds(timelineUrl, currentPage)
184
        }
1018 stevensc 185
 
1 www 186
      } else {
187
        if (data.data.description || data.data.file || data.data.share_width) {
188
          Object.entries(data.data).map(([key, value]) => {
189
            setError(key, { type: "required", message: value });
190
          });
191
        } else {
192
          addNotification({
193
            style: "danger",
194
            msg: "Ha ocurrido un error",
195
          });
196
        }
197
      }
198
    });
199
 
200
    setLoading(false);
201
  };
202
 
203
  const onUploadedHandler = (files) => {
204
    setValue("file", files);
205
    clearErrors("file");
206
  };
207
 
208
  const dropZoneRender = () => {
209
    if (
210
      modalType !== shareModalTypes.POST &&
211
      modalType !== shareModalTypes.SHARE
212
    ) {
213
      return (
214
        <DropzoneComponent
215
          modalType={modalType}
216
          onUploaded={onUploadedHandler}
217
          settedFile={getValues("file")}
218
          recomendationText={recomendationText()}
219
        />
220
      );
221
    }
222
  };
223
 
224
  const SharedWithSelectRender = () => {
225
    if (feedType === feedTypes.DASHBOARD) {
226
      return (
227
        <React.Fragment>
228
          <select
229
            // value={formData.shared_with}
230
            name="shared_with"
231
            id="shared_with"
232
            className="form-control"
233
            // onChange={(e) => onInputChangeHandler(e)}
234
            ref={register({
235
              required: "El campo es requerido",
236
            })}
237
            defaultValue="p"
238
          >
239
            <option disabled="disabled" value="" style={{ display: "none" }}>
240
              Compartir con
241
            </option>
242
            <option value="p">Público</option>
243
            <option value="c">Conexiones</option>
244
          </select>
245
          {errors.shared_with && (
246
            <FormErrorFeedback>{errors.shared_with.message}</FormErrorFeedback>
247
          )}
248
        </React.Fragment>
249
      );
250
    }
251
  };
252
 
253
  return (
254
    <React.Fragment>
255
      <Modal
256
        show={isOpen}
257
        onHide={closeShareModal}
943 steven 258
        autoFocus={false}
1 www 259
      >
260
        <Modal.Header closeButton>
261
          <Modal.Title>Compartir una publicación</Modal.Title>
262
        </Modal.Header>
263
        <form encType="multipart/form-data" onSubmit={handleSubmit(onSubmit)}>
264
          <Modal.Body>
265
            {SharedWithSelectRender()}
266
            <CKEditor
267
              data={watch("description")}
268
              onChange={(e) => {
269
                const text = e.editor.getData();
270
                setValue("description", text);
271
                if (errors.description && getValues(description)) {
272
                  clearErrors("description");
273
                }
274
              }}
275
              config={{
276
                startupFocus: "end",
766 steven 277
                allowedContent: false,
771 steven 278
                toolbarGroups: [
774 steven 279
                  // { name: 'document',	   groups: [ 'mode', 'document', 'doctools' ] },
775 steven 280
                  // { name: 'clipboard',   groups: [ 'undo' ] },
1018 stevensc 281
                  { name: 'editing', groups: ['find', 'selection', 'spellchecker'] },
773 steven 282
                  { name: 'forms' },
1018 stevensc 283
                  { name: 'basicstyles', groups: ['basicstyles', 'cleanup'] },
284
                  { name: 'paragraph', groups: ['list', 'indent', 'blocks', 'align', 'bidi'] },
773 steven 285
                  { name: 'links' },
286
                  { name: 'insert' },
771 steven 287
                  { name: 'styles' },
288
                  { name: 'colors' },
289
                  { name: 'tools' },
290
                  { name: 'others' },
291
                ]
292
                // removeButtons: 'Clipboard,Paste',
293
                // removePlugins: 'Clipboard,Paste'
1 www 294
              }}
295
              name="description"
296
              onBeforeLoad={() => {
297
                setIsCKEditorLoading(false);
1018 stevensc 298
                ("Ready");
299
                ("Ready");
1 www 300
              }}
301
            />
302
            {isCKEditorLoading && (
303
              <StyledSpinnerContainer>
304
                <Spinner />
305
              </StyledSpinnerContainer>
306
            )}
307
            {errors.description && (
308
              <FormErrorFeedback>
309
                {errors.description.message}
310
              </FormErrorFeedback>
311
            )}
312
 
313
            {dropZoneRender()}
314
            {errors.file && (
315
              <FormErrorFeedback>{errors.file.message}</FormErrorFeedback>
316
            )}
317
          </Modal.Body>
318
          <Modal.Footer>
319
            <Button size="sm" type="submit">Enviar</Button>
320
            <Button color="danger" size="sm" variant="danger" onClick={closeShareModal}>
321
              Cancelar
322
            </Button>
323
          </Modal.Footer>
324
        </form>
325
        {loading ? (
326
          <StyledSpinnerContainer>
327
            <Spinner />
328
          </StyledSpinnerContainer>
329
        ) : (
330
          ""
331
        )}
332
      </Modal>
333
      <ConfirmModal
334
        show={showConfirmModal}
335
        onClose={handleModalCancel}
336
        onAccept={handleModalAccept}
337
        acceptLabel="Aceptar"
338
        message="No se ha compartido tu publicación , desea descartarlo?"
339
      />
340
    </React.Fragment>
341
  );
342
};
343
 
344
const mapStateToProps = (state) => ({
345
  isOpen: state.shareModal.isOpen,
346
  postUrl: state.shareModal.postUrl,
347
  modalType: state.shareModal.modalType,
348
  lastModalType: state.shareModal.lastModalType,
349
  feedType: state.shareModal.feedType,
350
});
351
 
352
const mapDispatchToProps = {
353
  addNotification: (notification) => addNotification(notification),
354
  closeShareModal: () => closeShareModal(),
1005 steven 355
  openShareModal: (postUrl, modalType, feedType) => openShareModal(postUrl, modalType, feedType),
1 www 356
  setModalType: (modalType) => setModalType(modalType),
357
  addFeed: (feed) => addFeed(feed),
1005 steven 358
  fetchFeeds: (url, page) => fetchFeeds(url, page),
1 www 359
};
360
 
361
export default connect(mapStateToProps, mapDispatchToProps)(ShareModal);