Proyectos de Subversion LeadersLinked - Antes de SPA

Rev

Rev 944 | Rev 947 | 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');
943 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
  }
1 www 123
  useEffect(() => {
124
    clearErrors();
868 steven 125
    hideDuplicatedModal();
1 www 126
  }, [isOpen]);
127
 
128
  const handleShowConfirmModal = () => {
129
    setShowConfirmModal(!showConfirmModal);
130
  };
131
 
132
  const handleModalAccept = () => {
133
    setShowConfirmModal(false);
134
    setValue("description", "");
135
    setValue("file", "");
136
    openShareModal(postUrl, modalType, feedType);
137
    clearErrors();
138
  };
139
 
140
  const handleModalCancel = () => {
141
    setShowConfirmModal(false);
142
    closeShareModal();
143
    setModalType(lastModalType);
144
    openShareModal(postUrl, lastModalType, feedType);
145
  };
146
 
147
  const onSubmit = async (data, e) => {
148
    setLoading(true);
149
    const currentFormData = new FormData();
150
    for (let input in data) {
151
      currentFormData.append(input, data[input]);
152
       (`${input}:${data[input]}`);
153
    }
154
    await axios.post(postUrl, currentFormData).then((response) => {
155
      const data = response.data;
156
      const newFeed = data.data;
157
       (data);
158
      if (data.success) {
159
        closeShareModal();
160
        // reset data
161
        e.target.reset();
162
        setValue("description", "");
163
        setValue("file", "");
164
        clearErrors();
165
        addNotification({
166
          style: "success",
167
          msg: "La publicación ha sido compartida",
168
        });
169
        // if (modalType !== shareModalTypes.SHARE) {
170
          addFeed(newFeed);
171
        // }
172
      } else {
173
        if (data.data.description || data.data.file || data.data.share_width) {
174
          Object.entries(data.data).map(([key, value]) => {
175
            setError(key, { type: "required", message: value });
176
          });
177
        } else {
178
          addNotification({
179
            style: "danger",
180
            msg: "Ha ocurrido un error",
181
          });
182
        }
183
      }
184
    });
185
 
186
    setLoading(false);
187
  };
188
 
189
  const onUploadedHandler = (files) => {
190
    setValue("file", files);
191
    clearErrors("file");
192
  };
193
 
194
  const dropZoneRender = () => {
195
    if (
196
      modalType !== shareModalTypes.POST &&
197
      modalType !== shareModalTypes.SHARE
198
    ) {
199
      return (
200
        <DropzoneComponent
201
          modalType={modalType}
202
          onUploaded={onUploadedHandler}
203
          settedFile={getValues("file")}
204
          recomendationText={recomendationText()}
205
        />
206
      );
207
    }
208
  };
209
 
210
  const SharedWithSelectRender = () => {
211
    if (feedType === feedTypes.DASHBOARD) {
212
      return (
213
        <React.Fragment>
214
          <select
215
            // value={formData.shared_with}
216
            name="shared_with"
217
            id="shared_with"
218
            className="form-control"
219
            // onChange={(e) => onInputChangeHandler(e)}
220
            ref={register({
221
              required: "El campo es requerido",
222
            })}
223
            defaultValue="p"
224
          >
225
            <option disabled="disabled" value="" style={{ display: "none" }}>
226
              Compartir con
227
            </option>
228
            <option value="p">Público</option>
229
            <option value="c">Conexiones</option>
230
          </select>
231
          {errors.shared_with && (
232
            <FormErrorFeedback>{errors.shared_with.message}</FormErrorFeedback>
233
          )}
234
        </React.Fragment>
235
      );
236
    }
237
  };
238
 
239
  return (
240
    <React.Fragment>
241
      <Modal
242
        show={isOpen}
243
        onHide={closeShareModal}
943 steven 244
        autoFocus={false}
1 www 245
      >
246
        <Modal.Header closeButton>
247
          <Modal.Title>Compartir una publicación</Modal.Title>
248
        </Modal.Header>
249
        <form encType="multipart/form-data" onSubmit={handleSubmit(onSubmit)}>
250
          <Modal.Body>
251
            {SharedWithSelectRender()}
252
            <CKEditor
253
              data={watch("description")}
254
              onChange={(e) => {
255
                const text = e.editor.getData();
256
                setValue("description", text);
257
                if (errors.description && getValues(description)) {
258
                  clearErrors("description");
259
                }
260
              }}
261
              config={{
262
                startupFocus: "end",
766 steven 263
                allowedContent: false,
771 steven 264
                toolbarGroups: [
774 steven 265
                  // { name: 'document',	   groups: [ 'mode', 'document', 'doctools' ] },
775 steven 266
                  // { name: 'clipboard',   groups: [ 'undo' ] },
773 steven 267
                  { name: 'editing',     groups: [ 'find', 'selection', 'spellchecker' ] },
268
                  { name: 'forms' },
269
                  { name: 'basicstyles', groups: [ 'basicstyles', 'cleanup' ] },
270
                  { name: 'paragraph',   groups: [ 'list', 'indent', 'blocks', 'align', 'bidi' ] },
271
                  { name: 'links' },
272
                  { name: 'insert' },
771 steven 273
                  { name: 'styles' },
274
                  { name: 'colors' },
275
                  { name: 'tools' },
276
                  { name: 'others' },
277
                ]
278
                // removeButtons: 'Clipboard,Paste',
279
                // removePlugins: 'Clipboard,Paste'
1 www 280
              }}
281
              name="description"
282
              onBeforeLoad={() => {
283
                setIsCKEditorLoading(false);
284
                 ("Ready");
285
              }}
286
            />
287
            {isCKEditorLoading && (
288
              <StyledSpinnerContainer>
289
                <Spinner />
290
              </StyledSpinnerContainer>
291
            )}
292
            {errors.description && (
293
              <FormErrorFeedback>
294
                {errors.description.message}
295
              </FormErrorFeedback>
296
            )}
297
 
298
            {dropZoneRender()}
299
            {errors.file && (
300
              <FormErrorFeedback>{errors.file.message}</FormErrorFeedback>
301
            )}
302
          </Modal.Body>
303
          <Modal.Footer>
304
            <Button size="sm" type="submit">Enviar</Button>
305
            <Button color="danger" size="sm" variant="danger" onClick={closeShareModal}>
306
              Cancelar
307
            </Button>
308
          </Modal.Footer>
309
        </form>
310
        {loading ? (
311
          <StyledSpinnerContainer>
312
            <Spinner />
313
          </StyledSpinnerContainer>
314
        ) : (
315
          ""
316
        )}
317
      </Modal>
318
      <ConfirmModal
319
        show={showConfirmModal}
320
        onClose={handleModalCancel}
321
        onAccept={handleModalAccept}
322
        acceptLabel="Aceptar"
323
        message="No se ha compartido tu publicación , desea descartarlo?"
324
      />
325
    </React.Fragment>
326
  );
327
};
328
 
329
const mapStateToProps = (state) => ({
330
  isOpen: state.shareModal.isOpen,
331
  postUrl: state.shareModal.postUrl,
332
  modalType: state.shareModal.modalType,
333
  lastModalType: state.shareModal.lastModalType,
334
  feedType: state.shareModal.feedType,
335
});
336
 
337
const mapDispatchToProps = {
338
  addNotification: (notification) => addNotification(notification),
339
  closeShareModal: () => closeShareModal(),
340
  openShareModal: (postUrl, modalType, feedType) =>
341
    openShareModal(postUrl, modalType, feedType),
342
  setModalType: (modalType) => setModalType(modalType),
343
  addFeed: (feed) => addFeed(feed),
344
};
345
 
346
export default connect(mapStateToProps, mapDispatchToProps)(ShareModal);