Proyectos de Subversion LeadersLinked - Antes de SPA

Rev

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