SAVE
This commit is contained in:
parent
3aa27efa36
commit
2e59823caa
|
@ -85,7 +85,8 @@
|
||||||
"deleteFailed": "Failed to delete drawing.",
|
"deleteFailed": "Failed to delete drawing.",
|
||||||
"loadUsersFailed": "Failed to load users.",
|
"loadUsersFailed": "Failed to load users.",
|
||||||
"userNotSelected": "Please select a user to share with.",
|
"userNotSelected": "Please select a user to share with.",
|
||||||
"shareFailed": "Failed to share drawing."
|
"shareFailed": "Failed to share drawing.",
|
||||||
|
"unshareFailed": "Failed to unshare drawing."
|
||||||
},
|
},
|
||||||
"shareModal": {
|
"shareModal": {
|
||||||
"title": "Share Drawing",
|
"title": "Share Drawing",
|
||||||
|
@ -94,7 +95,11 @@
|
||||||
"cancelButton": "Cancel",
|
"cancelButton": "Cancel",
|
||||||
"noUsersFound": "No users available to share with or match your search.",
|
"noUsersFound": "No users available to share with or match your search.",
|
||||||
"loadingUsers": "Loading users...",
|
"loadingUsers": "Loading users...",
|
||||||
"sharingButton": "Sharing..."
|
"sharingButton": "Sharing...",
|
||||||
|
"shareTab": "Share",
|
||||||
|
"manageSharesTab": "Manage Access",
|
||||||
|
"noSharedUsers": "This drawing is not shared with anyone yet.",
|
||||||
|
"unsharingButton": "Removing access..."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"editor": {
|
"editor": {
|
||||||
|
|
|
@ -85,7 +85,8 @@
|
||||||
"deleteFailed": "Error al eliminar el dibujo.",
|
"deleteFailed": "Error al eliminar el dibujo.",
|
||||||
"loadUsersFailed": "Error al cargar usuarios.",
|
"loadUsersFailed": "Error al cargar usuarios.",
|
||||||
"userNotSelected": "Por favor, selecciona un usuario para compartir.",
|
"userNotSelected": "Por favor, selecciona un usuario para compartir.",
|
||||||
"shareFailed": "Error al compartir el dibujo."
|
"shareFailed": "Error al compartir el dibujo.",
|
||||||
|
"unshareFailed": "Error al dejar de compartir el dibujo."
|
||||||
},
|
},
|
||||||
"shareModal": {
|
"shareModal": {
|
||||||
"title": "Compartir Dibujo",
|
"title": "Compartir Dibujo",
|
||||||
|
@ -94,7 +95,11 @@
|
||||||
"cancelButton": "Cancelar",
|
"cancelButton": "Cancelar",
|
||||||
"noUsersFound": "No hay usuarios disponibles para compartir o que coincidan con tu búsqueda.",
|
"noUsersFound": "No hay usuarios disponibles para compartir o que coincidan con tu búsqueda.",
|
||||||
"loadingUsers": "Cargando usuarios...",
|
"loadingUsers": "Cargando usuarios...",
|
||||||
"sharingButton": "Compartiendo..."
|
"sharingButton": "Compartiendo...",
|
||||||
|
"shareTab": "Compartir",
|
||||||
|
"manageSharesTab": "Gestionar Accesos",
|
||||||
|
"noSharedUsers": "Este dibujo no está compartido con nadie todavía.",
|
||||||
|
"unsharingButton": "Eliminando acceso..."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"editor": {
|
"editor": {
|
||||||
|
|
|
@ -1,417 +1,488 @@
|
||||||
.cardContainer {
|
.cardContainer {
|
||||||
border: 1px solid #e0e0e0;
|
background-color: var(--card-bg, #ffffff);
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
background-color: #ffffff;
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||||
padding: 1rem;
|
overflow: hidden;
|
||||||
transition: box-shadow 0.2s ease-in-out, transform 0.2s ease-in-out, background-color 0.3s ease, border-color 0.3s ease;
|
transition: transform 0.2s ease, box-shadow 0.2s ease;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
:global(.dark) .cardContainer {
|
:global(.dark) .cardContainer {
|
||||||
background-color: #1e1e1e;
|
--card-bg: #1e1e1e;
|
||||||
border-color: #333;
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
|
||||||
}
|
}
|
||||||
|
|
||||||
.cardContainer:hover {
|
.cardContainer:hover {
|
||||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
|
|
||||||
transform: translateY(-2px);
|
transform: translateY(-2px);
|
||||||
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
||||||
}
|
}
|
||||||
|
|
||||||
:global(.dark) .cardContainer:hover {
|
:global(.dark) .cardContainer:hover {
|
||||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.4);
|
||||||
}
|
}
|
||||||
|
|
||||||
.titleContainer {
|
.titleContainer {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
margin-bottom: 0.75rem;
|
padding: 1rem;
|
||||||
|
border-bottom: 1px solid var(--border-color, #eaeaea);
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(.dark) .titleContainer {
|
||||||
|
--border-color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cardTitle {
|
||||||
|
margin: 0;
|
||||||
|
font-size: 1.2rem;
|
||||||
|
font-weight: 600;
|
||||||
|
color: var(--text-primary, #333);
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(.dark) .cardTitle {
|
||||||
|
--text-primary: #e0e0e0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.titleLink {
|
.titleLink {
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
color: inherit;
|
color: inherit;
|
||||||
flex-grow: 1;
|
flex: 1;
|
||||||
margin-right: 0.5rem;
|
min-width: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.cardTitle {
|
.cardContent {
|
||||||
font-size: 1.2rem;
|
padding: 1rem;
|
||||||
font-weight: 600;
|
flex: 1;
|
||||||
color: #333;
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cardDate {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
word-break: break-word;
|
|
||||||
}
|
|
||||||
|
|
||||||
:global(.dark) .cardTitle {
|
|
||||||
color: #e0e0e0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.editButton {
|
|
||||||
background: none;
|
|
||||||
border: none;
|
|
||||||
padding: 0.25rem;
|
|
||||||
cursor: pointer;
|
|
||||||
color: #555;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
border-radius: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.editButton:hover {
|
|
||||||
color: #000;
|
|
||||||
background-color: #f0f0f0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.actionButtonsContainer {
|
|
||||||
display: flex;
|
|
||||||
gap: 0.25rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.iconButton {
|
|
||||||
background: none;
|
|
||||||
border: none;
|
|
||||||
padding: 0.25rem;
|
|
||||||
cursor: pointer;
|
|
||||||
color: #555;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
border-radius: 4px;
|
|
||||||
transition: background-color 0.2s ease, color 0.2s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
:global(.dark) .iconButton {
|
|
||||||
color: #aaa;
|
|
||||||
}
|
|
||||||
|
|
||||||
.iconButton:hover {
|
|
||||||
color: #000;
|
|
||||||
background-color: #f0f0f0;
|
|
||||||
}
|
|
||||||
|
|
||||||
:global(.dark) .iconButton:hover {
|
|
||||||
color: #fff;
|
|
||||||
background-color: #333;
|
|
||||||
}
|
|
||||||
|
|
||||||
.deleteButton:hover {
|
|
||||||
color: #d9534f;
|
|
||||||
}
|
|
||||||
|
|
||||||
:global(.dark) .deleteButton:hover {
|
|
||||||
color: #ff7875;
|
|
||||||
}
|
|
||||||
|
|
||||||
.inlineEditForm {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 0.5rem;
|
|
||||||
margin-bottom: 0.75rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.inlineInput {
|
|
||||||
padding: 0.5rem 0.7rem;
|
|
||||||
border: 1px solid #ccc;
|
|
||||||
border-radius: 4px;
|
|
||||||
font-size: 1rem;
|
|
||||||
flex-grow: 1;
|
|
||||||
background-color: #fff;
|
|
||||||
color: #333;
|
|
||||||
}
|
|
||||||
|
|
||||||
:global(.dark) .inlineInput {
|
|
||||||
background-color: #2a2a2a;
|
|
||||||
border-color: #444;
|
|
||||||
color: #e0e0e0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.inlineInput:focus {
|
|
||||||
outline: none;
|
|
||||||
border-color: #0070f3;
|
|
||||||
box-shadow: 0 0 0 2px rgba(0, 112, 243, 0.2);
|
|
||||||
}
|
|
||||||
|
|
||||||
:global(.dark) .inlineInput:focus {
|
|
||||||
border-color: #0070f3;
|
|
||||||
box-shadow: 0 0 0 2px rgba(0, 112, 243, 0.3);
|
|
||||||
}
|
|
||||||
|
|
||||||
.formActionButton {
|
|
||||||
padding: 0.5rem 0.9rem;
|
|
||||||
border: none;
|
|
||||||
border-radius: 4px;
|
|
||||||
font-size: 0.85rem;
|
font-size: 0.85rem;
|
||||||
font-weight: 500;
|
color: var(--text-secondary, #666);
|
||||||
cursor: pointer;
|
|
||||||
transition: background-color 0.2s ease-in-out, color 0.2s ease-in-out, transform 0.1s ease;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.formActionButton:active {
|
:global(.dark) .cardDate {
|
||||||
transform: translateY(1px);
|
--text-secondary: #aaa;
|
||||||
}
|
|
||||||
|
|
||||||
.confirmButton {
|
|
||||||
background-color: #28a745;
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
.confirmButton:hover {
|
|
||||||
background-color: #218838;
|
|
||||||
}
|
|
||||||
|
|
||||||
.cancelButton {
|
|
||||||
background-color: #6c757d;
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
.cancelButton:hover {
|
|
||||||
background-color: #5a6268;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.cardLinkUnderTitle {
|
.cardLinkUnderTitle {
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
color: inherit;
|
color: inherit;
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|
||||||
.cardContent {
|
.actionButtonsContainer {
|
||||||
margin-top: auto;
|
display: flex;
|
||||||
|
gap: 0.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.cardDate {
|
.iconButton {
|
||||||
font-size: 0.8rem;
|
background: none;
|
||||||
color: #777;
|
border: none;
|
||||||
margin-top: 0.5rem;
|
cursor: pointer;
|
||||||
}
|
|
||||||
|
|
||||||
:global(.dark) .cardDate {
|
|
||||||
color: #aaa;
|
|
||||||
}
|
|
||||||
|
|
||||||
.renameErrorText {
|
|
||||||
color: #d9534f;
|
|
||||||
font-size: 0.8rem;
|
|
||||||
margin-bottom: 0.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
:global(.dark) .renameErrorText {
|
|
||||||
color: #ff7875;
|
|
||||||
}
|
|
||||||
|
|
||||||
.thumbnailPlaceholder {
|
|
||||||
width: 100%;
|
|
||||||
height: 150px;
|
|
||||||
background-color: #f0f0f0;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
color: #999;
|
padding: 0.25rem;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
margin-bottom: 12px;
|
color: var(--icon-color, #666);
|
||||||
|
transition: background-color 0.2s ease, color 0.2s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
:global(.dark) .thumbnailPlaceholder {
|
:global(.dark) .iconButton {
|
||||||
background-color: #2a2a2a;
|
--icon-color: #aaa;
|
||||||
color: #aaa;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.cardActions {
|
.iconButton:hover {
|
||||||
margin-top: 16px;
|
background-color: var(--icon-hover-bg, rgba(0, 0, 0, 0.05));
|
||||||
display: flex;
|
color: var(--icon-hover-color, #333);
|
||||||
justify-content: flex-end;
|
}
|
||||||
|
|
||||||
|
:global(.dark) .iconButton:hover {
|
||||||
|
--icon-hover-bg: rgba(255, 255, 255, 0.1);
|
||||||
|
--icon-hover-color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.deleteButton:hover {
|
||||||
|
color: var(--delete-color, #e53935);
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(.dark) .deleteButton:hover {
|
||||||
|
--delete-color: #f44336;
|
||||||
|
}
|
||||||
|
|
||||||
|
.inlineEditForm {
|
||||||
|
padding: 0.75rem;
|
||||||
|
width: 100%;
|
||||||
|
border-bottom: 1px solid var(--border-color, #eaeaea);
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(.dark) .inlineEditForm {
|
||||||
|
--border-color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.inlineInput {
|
||||||
|
width: 100%;
|
||||||
|
padding: 0.5rem;
|
||||||
|
border: 1px solid var(--input-border, #ccc);
|
||||||
|
border-radius: 4px;
|
||||||
|
font-size: 1rem;
|
||||||
|
background-color: var(--input-bg, #fff);
|
||||||
|
color: var(--input-color, #333);
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(.dark) .inlineInput {
|
||||||
|
--input-border: #555;
|
||||||
|
--input-bg: #2a2a2a;
|
||||||
|
--input-color: #e0e0e0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.inlineInput:focus {
|
||||||
|
outline: none;
|
||||||
|
border-color: var(--input-focus-border, #0070f3);
|
||||||
|
box-shadow: 0 0 0 2px var(--input-focus-shadow, rgba(0, 112, 243, 0.2));
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(.dark) .inlineInput:focus {
|
||||||
|
--input-focus-border: #0070f3;
|
||||||
|
--input-focus-shadow: rgba(0, 112, 243, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.renameErrorText {
|
||||||
|
color: var(--error-color, #ff4d4f);
|
||||||
|
font-size: 0.85rem;
|
||||||
|
margin: 0.5rem 0;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(.dark) .renameErrorText {
|
||||||
|
--error-color: #ff7875;
|
||||||
}
|
}
|
||||||
|
|
||||||
.modalErrorText {
|
.modalErrorText {
|
||||||
color: #d9534f;
|
color: var(--error-color, #ff4d4f);
|
||||||
font-size: 0.9rem;
|
font-size: 0.9rem;
|
||||||
margin: 0.5rem 0;
|
margin: 1rem 0;
|
||||||
padding: 0.5rem;
|
padding: 0.5rem;
|
||||||
background-color: rgba(217, 83, 79, 0.1);
|
background-color: var(--error-bg, rgba(255, 77, 79, 0.1));
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
:global(.dark) .modalErrorText {
|
:global(.dark) .modalErrorText {
|
||||||
color: #ff7875;
|
--error-color: #ff7875;
|
||||||
background-color: rgba(255, 120, 117, 0.15);
|
--error-bg: rgba(255, 77, 79, 0.2);
|
||||||
}
|
}
|
||||||
|
|
||||||
.modalFooter {
|
.modalFooter {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: flex-end;
|
justify-content: flex-end;
|
||||||
gap: 0.75rem;
|
gap: 0.75rem;
|
||||||
margin-top: 1rem;
|
margin-top: 1.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.modalButtonCancel {
|
.modalButtonCancel {
|
||||||
padding: 0.6rem 1.2rem;
|
padding: 0.5rem 1rem;
|
||||||
border-radius: 6px;
|
background-color: var(--cancel-btn-bg, #f5f5f5);
|
||||||
font-weight: 500;
|
color: var(--cancel-btn-color, #333);
|
||||||
|
border: 1px solid var(--cancel-btn-border, #d9d9d9);
|
||||||
|
border-radius: 4px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
background-color: #f8f9fa;
|
font-size: 0.9rem;
|
||||||
color: #333;
|
transition: all 0.2s;
|
||||||
border: 1px solid #ced4da;
|
|
||||||
transition: background-color 0.2s ease, border-color 0.2s ease;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
:global(.dark) .modalButtonCancel {
|
:global(.dark) .modalButtonCancel {
|
||||||
background-color: #333;
|
--cancel-btn-bg: #333;
|
||||||
color: #e0e0e0;
|
--cancel-btn-color: #e0e0e0;
|
||||||
border-color: #555;
|
--cancel-btn-border: #444;
|
||||||
}
|
}
|
||||||
|
|
||||||
.modalButtonCancel:hover {
|
.modalButtonCancel:hover {
|
||||||
background-color: #e2e6ea;
|
background-color: var(--cancel-btn-hover-bg, #e6e6e6);
|
||||||
border-color: #dae0e5;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
:global(.dark) .modalButtonCancel:hover {
|
:global(.dark) .modalButtonCancel:hover {
|
||||||
background-color: #444;
|
--cancel-btn-hover-bg: #444;
|
||||||
border-color: #666;
|
}
|
||||||
|
|
||||||
|
.modalButtonCancel:disabled {
|
||||||
|
opacity: 0.6;
|
||||||
|
cursor: not-allowed;
|
||||||
}
|
}
|
||||||
|
|
||||||
.modalButtonConfirm {
|
.modalButtonConfirm {
|
||||||
padding: 0.6rem 1.2rem;
|
padding: 0.5rem 1rem;
|
||||||
border-radius: 6px;
|
background-color: var(--confirm-btn-bg, #1890ff);
|
||||||
font-weight: 500;
|
|
||||||
cursor: pointer;
|
|
||||||
background-color: #d9534f;
|
|
||||||
color: white;
|
color: white;
|
||||||
border: 1px solid #d9534f;
|
border: none;
|
||||||
transition: background-color 0.2s ease, border-color 0.2s ease;
|
border-radius: 4px;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
transition: all 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modalButtonConfirm.delete {
|
||||||
|
--confirm-btn-bg: #ff4d4f;
|
||||||
}
|
}
|
||||||
|
|
||||||
.modalButtonConfirm:hover {
|
.modalButtonConfirm:hover {
|
||||||
background-color: #c9302c;
|
background-color: var(--confirm-btn-hover-bg, #40a9ff);
|
||||||
border-color: #ac2925;
|
}
|
||||||
|
|
||||||
|
.modalButtonConfirm.delete:hover {
|
||||||
|
--confirm-btn-hover-bg: #ff7875;
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(.dark) .modalButtonConfirm:hover {
|
||||||
|
filter: brightness(1.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.modalButtonConfirm:disabled {
|
||||||
|
opacity: 0.6;
|
||||||
|
cursor: not-allowed;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Share modal */
|
|
||||||
.shareModalContent {
|
.shareModalContent {
|
||||||
display: flex;
|
margin-bottom: 1rem;
|
||||||
flex-direction: column;
|
|
||||||
gap: 1rem;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.shareSearchInput {
|
.shareSearchInput {
|
||||||
padding: 0.75rem;
|
|
||||||
border: 1px solid #ced4da;
|
|
||||||
border-radius: 6px;
|
|
||||||
font-size: 0.95rem;
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
transition: border-color 0.2s ease, box-shadow 0.2s ease;
|
padding: 0.75rem;
|
||||||
|
border: 1px solid var(--input-border, #d9d9d9);
|
||||||
|
border-radius: 4px;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
background-color: var(--input-bg, #fff);
|
||||||
|
color: var(--input-color, #333);
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(.dark) .shareSearchInput {
|
||||||
|
--input-border: #444;
|
||||||
|
--input-bg: #2a2a2a;
|
||||||
|
--input-color: #e0e0e0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.shareSearchInput:focus {
|
.shareSearchInput:focus {
|
||||||
outline: none;
|
outline: none;
|
||||||
border-color: #0070f3;
|
border-color: var(--input-focus-border, #1890ff);
|
||||||
box-shadow: 0 0 0 2px rgba(0, 112, 243, 0.2);
|
box-shadow: 0 0 0 2px var(--input-focus-shadow, rgba(24, 144, 255, 0.2));
|
||||||
}
|
|
||||||
|
|
||||||
:global(.dark) .shareSearchInput {
|
|
||||||
background-color: #2a2a2a;
|
|
||||||
border-color: #444;
|
|
||||||
color: #e0e0e0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
:global(.dark) .shareSearchInput:focus {
|
:global(.dark) .shareSearchInput:focus {
|
||||||
border-color: #0070f3;
|
--input-focus-border: #1890ff;
|
||||||
box-shadow: 0 0 0 2px rgba(0, 112, 243, 0.3);
|
--input-focus-shadow: rgba(24, 144, 255, 0.3);
|
||||||
}
|
}
|
||||||
|
|
||||||
.shareSearchInput:disabled {
|
.shareSearchInput:disabled {
|
||||||
background-color: #f8f9fa;
|
background-color: var(--input-disabled-bg, #f5f5f5);
|
||||||
cursor: not-allowed;
|
cursor: not-allowed;
|
||||||
opacity: 0.7;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
:global(.dark) .shareSearchInput:disabled {
|
:global(.dark) .shareSearchInput:disabled {
|
||||||
background-color: #333;
|
--input-disabled-bg: #333;
|
||||||
}
|
}
|
||||||
|
|
||||||
.userListShare {
|
.userListShare {
|
||||||
list-style: none;
|
list-style: none;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
max-height: 250px;
|
max-height: 200px;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
border: 1px solid #ced4da;
|
border: 1px solid var(--list-border, #d9d9d9);
|
||||||
border-radius: 6px;
|
border-radius: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
:global(.dark) .userListShare {
|
:global(.dark) .userListShare {
|
||||||
border-color: #444;
|
--list-border: #444;
|
||||||
}
|
}
|
||||||
|
|
||||||
.userListItemShare {
|
.userListItemShare {
|
||||||
padding: 0.75rem 1rem;
|
padding: 0.75rem;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: background-color 0.2s ease;
|
border-bottom: 1px solid var(--item-border, #f0f0f0);
|
||||||
border-bottom: 1px solid #eeeeee;
|
background-color: var(--item-bg, #fff);
|
||||||
|
color: var(--item-color, #333);
|
||||||
|
transition: background-color 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(.dark) .userListItemShare {
|
||||||
|
--item-border: #333;
|
||||||
|
--item-bg: #2a2a2a;
|
||||||
|
--item-color: #e0e0e0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.userListItemShare:last-child {
|
.userListItemShare:last-child {
|
||||||
border-bottom: none;
|
border-bottom: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
:global(.dark) .userListItemShare {
|
|
||||||
border-bottom-color: #333;
|
|
||||||
}
|
|
||||||
|
|
||||||
.userListItemShare:hover {
|
.userListItemShare:hover {
|
||||||
background-color: #f8f9fa;
|
background-color: var(--item-hover-bg, #f5f5f5);
|
||||||
}
|
}
|
||||||
|
|
||||||
:global(.dark) .userListItemShare:hover {
|
:global(.dark) .userListItemShare:hover {
|
||||||
background-color: #333;
|
--item-hover-bg: #333;
|
||||||
}
|
}
|
||||||
|
|
||||||
.selectedUser {
|
.userListItemShare.selectedUser {
|
||||||
background-color: #e8f0fe;
|
background-color: var(--selected-bg, #e6f7ff);
|
||||||
|
color: var(--selected-color, #1890ff);
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(.dark) .userListItemShare.selectedUser {
|
||||||
|
--selected-bg: rgba(24, 144, 255, 0.2);
|
||||||
|
--selected-color: #1890ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.userListItemShare.disabledItem {
|
||||||
|
opacity: 0.7;
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tabsContainer {
|
||||||
|
display: flex;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
border-bottom: 1px solid var(--tabs-border, #d9d9d9);
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(.dark) .tabsContainer {
|
||||||
|
--tabs-border: #444;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tabButton {
|
||||||
|
padding: 0.75rem 1.5rem;
|
||||||
|
background: none;
|
||||||
|
border: none;
|
||||||
|
border-bottom: 2px solid transparent;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 0.95rem;
|
||||||
|
color: var(--tab-color, #666);
|
||||||
|
transition: all 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(.dark) .tabButton {
|
||||||
|
--tab-color: #aaa;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tabButton:hover {
|
||||||
|
color: var(--tab-hover-color, #1890ff);
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(.dark) .tabButton:hover {
|
||||||
|
--tab-hover-color: #40a9ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tabButton.activeTab {
|
||||||
|
color: var(--active-tab-color, #1890ff);
|
||||||
|
border-bottom: 2px solid var(--active-tab-border, #1890ff);
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
|
|
||||||
.selectedUser:hover {
|
:global(.dark) .tabButton.activeTab {
|
||||||
background-color: #d8e5fd;
|
--active-tab-color: #1890ff;
|
||||||
|
--active-tab-border: #1890ff;
|
||||||
}
|
}
|
||||||
|
|
||||||
:global(.dark) .selectedUser {
|
.userListManage {
|
||||||
background-color: #1a3a6c;
|
list-style: none;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
max-height: 200px;
|
||||||
|
overflow-y: auto;
|
||||||
|
border: 1px solid var(--list-border, #d9d9d9);
|
||||||
|
border-radius: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
:global(.dark) .selectedUser:hover {
|
:global(.dark) .userListManage {
|
||||||
background-color: #254b85;
|
--list-border: #444;
|
||||||
}
|
}
|
||||||
|
|
||||||
.disabledItem {
|
.userListItemManage {
|
||||||
|
padding: 0.75rem;
|
||||||
|
border-bottom: 1px solid var(--item-border, #f0f0f0);
|
||||||
|
background-color: var(--item-bg, #fff);
|
||||||
|
color: var(--item-color, #333);
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(.dark) .userListItemManage {
|
||||||
|
--item-border: #333;
|
||||||
|
--item-bg: #2a2a2a;
|
||||||
|
--item-color: #e0e0e0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.userListItemManage:last-child {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.userInfo {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.unshareButton {
|
||||||
|
background: none;
|
||||||
|
border: none;
|
||||||
|
cursor: pointer;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 0.4rem;
|
||||||
|
border-radius: 4px;
|
||||||
|
color: var(--unshare-color, #666);
|
||||||
|
transition: all 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(.dark) .unshareButton {
|
||||||
|
--unshare-color: #aaa;
|
||||||
|
}
|
||||||
|
|
||||||
|
.unshareButton:hover {
|
||||||
|
background-color: var(--unshare-hover-bg, rgba(255, 77, 79, 0.1));
|
||||||
|
color: var(--unshare-hover-color, #ff4d4f);
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(.dark) .unshareButton:hover {
|
||||||
|
--unshare-hover-bg: rgba(255, 77, 79, 0.2);
|
||||||
|
--unshare-hover-color: #ff7875;
|
||||||
|
}
|
||||||
|
|
||||||
|
.unshareButton.disabledButton {
|
||||||
opacity: 0.6;
|
opacity: 0.6;
|
||||||
cursor: not-allowed;
|
cursor: not-allowed;
|
||||||
}
|
}
|
||||||
|
|
||||||
.disabledItem:hover {
|
@media (max-width: 768px) {
|
||||||
background-color: inherit;
|
.userListShare, .userListManage {
|
||||||
|
max-height: 150px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tabButton {
|
||||||
|
padding: 0.6rem 1rem;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
:global(.dark) .disabledItem:hover {
|
@media (max-width: 480px) {
|
||||||
background-color: inherit;
|
.userListItemManage {
|
||||||
}
|
padding: 0.6rem;
|
||||||
|
font-size: 0.9rem;
|
||||||
/* Estilo para botones deshabilitados */
|
}
|
||||||
.modalButtonConfirm:disabled,
|
|
||||||
.modalButtonCancel:disabled {
|
.tabButton {
|
||||||
opacity: 0.6;
|
padding: 0.5rem 0.75rem;
|
||||||
cursor: not-allowed;
|
font-size: 0.85rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.modalButtonConfirm:disabled:hover,
|
|
||||||
.modalButtonCancel:disabled:hover {
|
|
||||||
background-color: inherit;
|
|
||||||
border-color: inherit;
|
|
||||||
}
|
|
||||||
|
|
||||||
:global(.dark) .modalButtonConfirm:disabled:hover,
|
|
||||||
:global(.dark) .modalButtonCancel:disabled:hover {
|
|
||||||
background-color: inherit;
|
|
||||||
border-color: inherit;
|
|
||||||
}
|
}
|
|
@ -8,6 +8,7 @@ import {
|
||||||
deleteDrawing as apiDeleteDrawing,
|
deleteDrawing as apiDeleteDrawing,
|
||||||
getUsers as apiGetUsers,
|
getUsers as apiGetUsers,
|
||||||
shareDrawingWithUser as apiShareDrawing,
|
shareDrawingWithUser as apiShareDrawing,
|
||||||
|
unshareDrawingWithUser as apiUnshareDrawing,
|
||||||
} from '@/lib/api';
|
} from '@/lib/api';
|
||||||
import { IUser } from '@/models/User';
|
import { IUser } from '@/models/User';
|
||||||
import styles from './DrawingCard.module.css';
|
import styles from './DrawingCard.module.css';
|
||||||
|
@ -42,11 +43,14 @@ export default function DrawingCard({
|
||||||
// States for the share modal
|
// States for the share modal
|
||||||
const [showShareModal, setShowShareModal] = useState(false);
|
const [showShareModal, setShowShareModal] = useState(false);
|
||||||
const [usersForSharing, setUsersForSharing] = useState<IUser[]>([]);
|
const [usersForSharing, setUsersForSharing] = useState<IUser[]>([]);
|
||||||
|
const [sharedWithUsers, setSharedWithUsers] = useState<IUser[]>([]);
|
||||||
const [shareSearchTerm, setShareSearchTerm] = useState('');
|
const [shareSearchTerm, setShareSearchTerm] = useState('');
|
||||||
const [selectedUserIdToShare, setSelectedUserIdToShare] = useState<string | null>(null);
|
const [selectedUserIdToShare, setSelectedUserIdToShare] = useState<string | null>(null);
|
||||||
const [shareError, setShareError] = useState<string | null>(null);
|
const [shareError, setShareError] = useState<string | null>(null);
|
||||||
const [isLoadingUsers, setIsLoadingUsers] = useState(false);
|
const [isLoadingUsers, setIsLoadingUsers] = useState(false);
|
||||||
const [isSharing, setIsSharing] = useState(false);
|
const [isSharing, setIsSharing] = useState(false);
|
||||||
|
const [isUnsharing, setIsUnsharing] = useState(false);
|
||||||
|
const [activeTab, setActiveTab] = useState<'share' | 'manage'>('share');
|
||||||
|
|
||||||
const handleCancelEdit = useCallback(() => {
|
const handleCancelEdit = useCallback(() => {
|
||||||
setIsEditing(false);
|
setIsEditing(false);
|
||||||
|
@ -164,19 +168,37 @@ export default function DrawingCard({
|
||||||
setShareError(null);
|
setShareError(null);
|
||||||
setSelectedUserIdToShare(null);
|
setSelectedUserIdToShare(null);
|
||||||
setShareSearchTerm('');
|
setShareSearchTerm('');
|
||||||
if (usersForSharing.length === 0) { // Load users only if they haven't been loaded before
|
setActiveTab('share');
|
||||||
setIsLoadingUsers(true);
|
setIsLoadingUsers(true);
|
||||||
|
|
||||||
|
try {
|
||||||
const response = await apiGetUsers();
|
const response = await apiGetUsers();
|
||||||
setIsLoadingUsers(false);
|
|
||||||
if (response.data) {
|
if (response.data) {
|
||||||
// Filter out the owner and already shared users
|
// Get all users
|
||||||
const filteredUsers = response.data.filter(
|
const allUsers = response.data;
|
||||||
(user) => user._id !== drawing.owner_id && !drawing.shared_with.includes(user._id as string)
|
|
||||||
|
// Filter users that already have access
|
||||||
|
const sharedWithUserIds = drawing.shared_with || [];
|
||||||
|
const usersWithAccess = allUsers.filter(user =>
|
||||||
|
sharedWithUserIds.includes(user._id as string)
|
||||||
);
|
);
|
||||||
setUsersForSharing(filteredUsers);
|
|
||||||
|
// Filter users that don't have access yet (excluding the owner)
|
||||||
|
const usersWithoutAccess = allUsers.filter(user =>
|
||||||
|
user._id !== drawing.owner_id &&
|
||||||
|
!sharedWithUserIds.includes(user._id as string)
|
||||||
|
);
|
||||||
|
|
||||||
|
setSharedWithUsers(usersWithAccess);
|
||||||
|
setUsersForSharing(usersWithoutAccess);
|
||||||
} else {
|
} else {
|
||||||
setShareError(response.error || t('drawingCard.errors.loadUsersFailed') || "Failed to load users.");
|
setShareError(response.error || t('drawingCard.errors.loadUsersFailed') || "Failed to load users.");
|
||||||
}
|
}
|
||||||
|
} catch (err) {
|
||||||
|
setShareError(t('drawingCard.errors.loadUsersFailed') || "Failed to load users.");
|
||||||
|
console.error("Load users error:", err);
|
||||||
|
} finally {
|
||||||
|
setIsLoadingUsers(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -194,17 +216,61 @@ export default function DrawingCard({
|
||||||
}
|
}
|
||||||
setIsSharing(true);
|
setIsSharing(true);
|
||||||
setShareError(null);
|
setShareError(null);
|
||||||
const response = await apiShareDrawing(drawing._id, selectedUserIdToShare);
|
|
||||||
setIsSharing(false);
|
try {
|
||||||
if (response.data) {
|
const response = await apiShareDrawing(drawing._id, selectedUserIdToShare);
|
||||||
setShowShareModal(false);
|
if (response.data) {
|
||||||
if (onDrawingShared) {
|
// Find the user that was shared with
|
||||||
onDrawingShared(response.data);
|
const sharedUser = usersForSharing.find(user => user._id === selectedUserIdToShare);
|
||||||
|
if (sharedUser) {
|
||||||
|
// Add to shared users list
|
||||||
|
setSharedWithUsers(prev => [...prev, sharedUser]);
|
||||||
|
// Remove from available users list
|
||||||
|
setUsersForSharing(prev => prev.filter(user => user._id !== selectedUserIdToShare));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (onDrawingShared) {
|
||||||
|
onDrawingShared(response.data);
|
||||||
|
}
|
||||||
|
setSelectedUserIdToShare(null);
|
||||||
|
} else {
|
||||||
|
setShareError(response.error || t('drawingCard.errors.shareFailed') || "Failed to share drawing.");
|
||||||
}
|
}
|
||||||
setUsersForSharing(prevUsers => prevUsers.filter(u => u._id !== selectedUserIdToShare));
|
} catch (err) {
|
||||||
setSelectedUserIdToShare(null);
|
setShareError(t('drawingCard.errors.shareFailed') || "Failed to share drawing.");
|
||||||
} else {
|
console.error("Share error:", err);
|
||||||
setShareError(response.error || t('drawingCard.errors.shareFailed') || "Failed to share drawing.");
|
} finally {
|
||||||
|
setIsSharing(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleUnshareDrawing = async (userId: string) => {
|
||||||
|
setIsUnsharing(true);
|
||||||
|
setShareError(null);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await apiUnshareDrawing(drawing._id, userId);
|
||||||
|
if (response.data) {
|
||||||
|
// Find the user that was unshared
|
||||||
|
const unsharedUser = sharedWithUsers.find(user => user._id === userId);
|
||||||
|
if (unsharedUser) {
|
||||||
|
// Remove from shared users list
|
||||||
|
setSharedWithUsers(prev => prev.filter(user => user._id !== userId));
|
||||||
|
// Add to available users list
|
||||||
|
setUsersForSharing(prev => [...prev, unsharedUser]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (onDrawingShared) {
|
||||||
|
onDrawingShared(response.data);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
setShareError(response.error || t('drawingCard.errors.unshareFailed') || "Failed to unshare drawing.");
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
setShareError(t('drawingCard.errors.unshareFailed') || "Failed to unshare drawing.");
|
||||||
|
console.error("Unshare error:", err);
|
||||||
|
} finally {
|
||||||
|
setIsUnsharing(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -213,6 +279,11 @@ export default function DrawingCard({
|
||||||
user.email.toLowerCase().includes(shareSearchTerm.toLowerCase())
|
user.email.toLowerCase().includes(shareSearchTerm.toLowerCase())
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const filteredSharedWithUsers = sharedWithUsers.filter((user) =>
|
||||||
|
user.username.toLowerCase().includes(shareSearchTerm.toLowerCase()) ||
|
||||||
|
user.email.toLowerCase().includes(shareSearchTerm.toLowerCase())
|
||||||
|
);
|
||||||
|
|
||||||
const modalTitle = i18nCardIsLoading
|
const modalTitle = i18nCardIsLoading
|
||||||
? "Confirm Deletion"
|
? "Confirm Deletion"
|
||||||
: t('drawingCard.confirmDelete.title') || "Confirm Deletion";
|
: t('drawingCard.confirmDelete.title') || "Confirm Deletion";
|
||||||
|
@ -251,6 +322,15 @@ export default function DrawingCard({
|
||||||
const shareModalNoUsersFoundText = i18nCardIsLoading
|
const shareModalNoUsersFoundText = i18nCardIsLoading
|
||||||
? "No users available to share with or match your search."
|
? "No users available to share with or match your search."
|
||||||
: t('drawingCard.shareModal.noUsersFound') || "No users available to share with or match your search.";
|
: t('drawingCard.shareModal.noUsersFound') || "No users available to share with or match your search.";
|
||||||
|
const manageSharesTabText = i18nCardIsLoading
|
||||||
|
? "Manage Shares"
|
||||||
|
: t('drawingCard.shareModal.manageSharesTab') || "Manage Shares";
|
||||||
|
const shareTabText = i18nCardIsLoading
|
||||||
|
? "Share"
|
||||||
|
: t('drawingCard.shareModal.shareTab') || "Share";
|
||||||
|
const noSharedUsersText = i18nCardIsLoading
|
||||||
|
? "This drawing is not shared with anyone yet."
|
||||||
|
: t('drawingCard.shareModal.noSharedUsers') || "This drawing is not shared with anyone yet.";
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
@ -322,50 +402,101 @@ export default function DrawingCard({
|
||||||
title={shareModalTitle}
|
title={shareModalTitle}
|
||||||
>
|
>
|
||||||
<div className={styles.shareModalContent}>
|
<div className={styles.shareModalContent}>
|
||||||
|
<div className={styles.tabsContainer}>
|
||||||
|
<button
|
||||||
|
className={`${styles.tabButton} ${activeTab === 'share' ? styles.activeTab : ''}`}
|
||||||
|
onClick={() => setActiveTab('share')}
|
||||||
|
>
|
||||||
|
{shareTabText}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
className={`${styles.tabButton} ${activeTab === 'manage' ? styles.activeTab : ''}`}
|
||||||
|
onClick={() => setActiveTab('manage')}
|
||||||
|
>
|
||||||
|
{manageSharesTabText}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
placeholder={shareModalSearchPlaceholder}
|
placeholder={shareModalSearchPlaceholder}
|
||||||
value={shareSearchTerm}
|
value={shareSearchTerm}
|
||||||
onChange={(e) => setShareSearchTerm(e.target.value)}
|
onChange={(e) => setShareSearchTerm(e.target.value)}
|
||||||
className={styles.shareSearchInput}
|
className={styles.shareSearchInput}
|
||||||
disabled={isLoadingUsers || isSharing}
|
disabled={isLoadingUsers || isSharing || isUnsharing}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{isLoadingUsers && <p>{t('drawingCard.shareModal.loadingUsers') || 'Loading users...'}</p>}
|
{isLoadingUsers && <p>{t('drawingCard.shareModal.loadingUsers') || 'Loading users...'}</p>}
|
||||||
{shareError && <p className={styles.modalErrorText}>{shareError}</p>}
|
{shareError && <p className={styles.modalErrorText}>{shareError}</p>}
|
||||||
|
|
||||||
{!isLoadingUsers && filteredUsersForSharing.length === 0 && (
|
{activeTab === 'share' && !isLoadingUsers && (
|
||||||
<p>{shareModalNoUsersFoundText}</p>
|
<>
|
||||||
)}
|
{filteredUsersForSharing.length === 0 && (
|
||||||
|
<p>{shareModalNoUsersFoundText}</p>
|
||||||
|
)}
|
||||||
|
|
||||||
{!isLoadingUsers && filteredUsersForSharing.length > 0 && (
|
{filteredUsersForSharing.length > 0 && (
|
||||||
<ul className={styles.userListShare}>
|
<ul className={styles.userListShare}>
|
||||||
{filteredUsersForSharing.map((user) => (
|
{filteredUsersForSharing.map((user) => (
|
||||||
<li
|
<li
|
||||||
key={user._id as string}
|
key={user._id as string}
|
||||||
onClick={() => !isSharing && setSelectedUserIdToShare(user._id as string)}
|
onClick={() => !isSharing && setSelectedUserIdToShare(user._id as string)}
|
||||||
className={`${styles.userListItemShare} ${selectedUserIdToShare === user._id ? styles.selectedUser : ''} ${isSharing ? styles.disabledItem : ''}`}
|
className={`${styles.userListItemShare} ${selectedUserIdToShare === user._id ? styles.selectedUser : ''} ${isSharing ? styles.disabledItem : ''}`}
|
||||||
>
|
>
|
||||||
{user.username} ({user.email})
|
{user.username} ({user.email})
|
||||||
</li>
|
</li>
|
||||||
))}
|
))}
|
||||||
</ul>
|
</ul>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{activeTab === 'manage' && !isLoadingUsers && (
|
||||||
|
<>
|
||||||
|
{filteredSharedWithUsers.length === 0 && (
|
||||||
|
<p>{noSharedUsersText}</p>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{filteredSharedWithUsers.length > 0 && (
|
||||||
|
<ul className={styles.userListManage}>
|
||||||
|
{filteredSharedWithUsers.map((user) => (
|
||||||
|
<li key={user._id as string} className={styles.userListItemManage}>
|
||||||
|
<span className={styles.userInfo}>
|
||||||
|
{user.username} ({user.email})
|
||||||
|
</span>
|
||||||
|
<button
|
||||||
|
onClick={() => !isUnsharing && handleUnshareDrawing(user._id as string)}
|
||||||
|
className={`${styles.unshareButton} ${isUnsharing ? styles.disabledButton : ''}`}
|
||||||
|
disabled={isUnsharing}
|
||||||
|
>
|
||||||
|
<Icon name="user-x" size={16} />
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className={styles.modalFooter}>
|
<div className={styles.modalFooter}>
|
||||||
<button
|
<button
|
||||||
onClick={handleCloseShareModal}
|
onClick={handleCloseShareModal}
|
||||||
className={styles.modalButtonCancel}
|
className={styles.modalButtonCancel}
|
||||||
disabled={isSharing}
|
disabled={isSharing || isUnsharing}
|
||||||
>
|
>
|
||||||
{shareModalCancelButtonText}
|
{shareModalCancelButtonText}
|
||||||
</button>
|
</button>
|
||||||
<button
|
|
||||||
onClick={handleConfirmShare}
|
{activeTab === 'share' && (
|
||||||
className={styles.modalButtonConfirm}
|
<button
|
||||||
disabled={!selectedUserIdToShare || isLoadingUsers || isSharing}
|
onClick={handleConfirmShare}
|
||||||
>
|
className={styles.modalButtonConfirm}
|
||||||
{isSharing ? (t('drawingCard.shareModal.sharingButton') || 'Sharing...') : shareModalConfirmButtonText}
|
disabled={!selectedUserIdToShare || isLoadingUsers || isSharing}
|
||||||
</button>
|
>
|
||||||
|
{isSharing ? (t('drawingCard.shareModal.sharingButton') || 'Sharing...') : shareModalConfirmButtonText}
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</Modal>
|
</Modal>
|
||||||
</>
|
</>
|
||||||
|
|
Loading…
Reference in New Issue
Block a user