Proyectos de Subversion LeadersLinked - Antes de SPA

Rev

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