Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Abstract attachments into new components #330

Closed
wants to merge 65 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
65 commits
Select commit Hold shift + click to select a range
7faed7b
initial commit
susanm74 May 15, 2023
32886dd
- created AttachmentsList and AttachmentsUploader and updated Attachm…
susanm74 May 15, 2023
30391a2
- removed attachments list update from handleAttachmentsAdded fn
susanm74 May 15, 2023
ec0496e
- test
susanm74 May 15, 2023
694b67a
- reverted trivial test post yarn install
susanm74 May 15, 2023
5422a15
- removed unused import in Attachments
susanm74 May 15, 2023
dea50e4
Merge branch 'main' into sl-new-attachments-components
susanm74 May 16, 2023
b59ea88
- removed unused inner components class
susanm74 May 16, 2023
4720541
- added lots of console logs
susanm74 May 16, 2023
15196ea
- removed extra custom event fire from Attachments updated
susanm74 May 16, 2023
a6b8e50
- removed unused import
susanm74 May 16, 2023
19e8688
- removed extra console logs
susanm74 May 16, 2023
42bb4ca
- removed upload_endpoint from Attachments
susanm74 May 16, 2023
237b9de
- created temba-image-picker
susanm74 May 18, 2023
15c47f3
- added example divs to attachments tab for spacing in between demo c…
susanm74 May 19, 2023
3f12704
- added custom width for attachments drop zone container
susanm74 May 22, 2023
3c2b017
- replace Compose2 with AttachmentsDropZone, AttachmentsList, and Att…
susanm74 May 22, 2023
d7362ea
- removed delete icon directly next to img
susanm74 May 22, 2023
634e23d
- cleaned up demo page to use image and trash can icons for upload an…
susanm74 May 23, 2023
02e5827
- commented out failing tests marked with todo's to fix (all related …
susanm74 May 23, 2023
75bfd58
- updated ImagePicker image render to remove the check for an error a…
susanm74 May 23, 2023
01e4826
Debugging help
ericnewcomer May 24, 2023
0821a2d
- removed extra console logs
susanm74 May 24, 2023
fff7c23
- removed extra quotes surrounding element event handlers ex. @click=…
susanm74 May 24, 2023
9ff67fa
Merge branch 'main' into sl-new-attachments-components
ericnewcomer May 24, 2023
bc5aa9c
- added back compose component to the window's customElements
susanm74 May 25, 2023
f086a31
- added new 'upload started' custom event
susanm74 May 27, 2023
9de8542
- added helpText to AttachmentsPicker, Compose2, and ImagePicker
susanm74 May 27, 2023
1ce7cab
- AttachmentsPicker - commented out redundant base class props
susanm74 May 31, 2023
0409599
- AttachmentsUploader - updated inspectFiles to create an array of pr…
susanm74 May 31, 2023
4b01db8
- moved ImageType enum into attachments util file
susanm74 Jun 1, 2023
ec4a3bf
- parent/child proof of concept
susanm74 Jun 5, 2023
6b630f2
- added case switch to getImageDimensions and getDropZoneWidth
susanm74 Jun 5, 2023
2c386cb
Merge branch 'main' into sl-new-attachments-components
susanm74 Jun 6, 2023
d073aae
- AttachmentsList - got rid of extra check for undefined in updated fn
susanm74 Jun 6, 2023
49300f3
- updated compose unit tests - everything passing, yay!
susanm74 Jun 6, 2023
ed2c815
- demo - re-ordered tabs and components within tabs
susanm74 Jun 6, 2023
e3bd1e0
- AttachmentsList - removed some whitespace and some extra requestUpd…
susanm74 Jun 6, 2023
0b833b5
- vsg.js - re-commented console log
susanm74 Jun 6, 2023
418f3d2
- more cleanup of whitespace and comments
susanm74 Jun 6, 2023
a552f1c
- updated image picker temp hack spoof image url
susanm74 Jun 7, 2023
a62c7aa
- removed all parent/child-related components to relocate into their …
susanm74 Jun 7, 2023
e46d9a9
- demo index - based on property updates
susanm74 Jun 7, 2023
deec29e
- AttachmentsPicker - removed clearing out of currentAttachments and …
susanm74 Jun 7, 2023
c3011e6
- minor updates to comments
susanm74 Jun 7, 2023
f27e158
- demo index - added compose2 examples to compose tab
susanm74 Jun 8, 2023
6193c37
- minor cleanup to comments
susanm74 Jun 8, 2023
c3e3602
- added initial AttachmentsPicker unit testing
susanm74 Jun 9, 2023
a9dd17f
- demo index - removed extra compose2 components
susanm74 Jun 9, 2023
eed5175
- updated attachment picker and image picker unit tests incl. screens…
susanm74 Jun 21, 2023
a84a56e
- added attachments drop zone unit tests - 2 drag and drop unit tests…
susanm74 Jun 21, 2023
f641160
- simplified screenshot names
susanm74 Jun 21, 2023
288e4e0
- added attachments list unit tests
susanm74 Jun 21, 2023
4b79fc0
- updated attachments list unit tests to add screenshots for before v…
susanm74 Jun 21, 2023
d7533eb
- removed unused import
susanm74 Jun 21, 2023
fa3cbf1
- removed extra comments
susanm74 Jun 22, 2023
63c2cda
- resolving merge conflicts
susanm74 Jun 22, 2023
3862e8a
- resolving merge conflicts again
susanm74 Jun 22, 2023
cae9af5
- updating svg fingerprint
susanm74 Jun 22, 2023
d1eaf24
Merge branch 'main' into sl-new-attachments-components
susanm74 Jun 22, 2023
7e4f4f9
- removed remaining refs to 'this.values'
susanm74 Jun 22, 2023
96884bf
Merge branch 'main' into sl-new-attachments-components
susanm74 Jun 23, 2023
0197815
- renamed dropWidth to dropZoneWidth
susanm74 Jun 23, 2023
30cc9ec
Merge branch 'main' into sl-new-attachments-components
ericnewcomer Jun 23, 2023
c698985
Merge branch 'main' into sl-new-attachments-components
susanm74 Jun 29, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 19 additions & 1 deletion demo/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -349,7 +349,25 @@
</div>
<div class="example">
<temba-compose chatbox attachments counter button></temba-compose>
</div>
</div>
</temba-tab>

<temba-tab name="attachments" icon="paperclip">
<div class="example">
<temba-attachments-picker></temba-attachments-picker>
</div>
<div class="example">
<temba-attachments-picker uploadLabel="Upload Attachments"></temba-attachments-picker>
</div>
<div class="example">
<temba-image-picker></temba-image-picker>
</div>
<div class="example">
<temba-image-picker uploadLabel="Upload Avatar" imageRadius="50%"></temba-image-picker>
</div>
<div class="example">
<temba-image-picker uploadLabel="Upload Logo" imageWidth="200" imageHeight="100"></temba-image-picker>
</div>
</temba-tab>

</temba-tabs>
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added screenshots/truth/image-picker/failure-file.png
Binary file added screenshots/truth/image-picker/success-file.png
132 changes: 132 additions & 0 deletions src/attachments/AttachmentsDropZone.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
import { TemplateResult, html, css } from 'lit';
import { FormElement } from '../FormElement';
import { property } from 'lit/decorators.js';
import { CustomEventType } from '../interfaces';
import { getClasses } from '../utils';

export class AttachmentsDropZone extends FormElement {
static get styles() {
return css`
.container {
display: flex;
flex-direction: column;
justify-content: space-between;
position: relative;

border-radius: var(--curvature-widget);
background: var(--color-widget-bg);
border: 1px solid var(--color-widget-border);
transition: all ease-in-out var(--transition-speed);
box-shadow: var(--widget-box-shadow);
caret-color: var(--input-caret);
padding: var(--temba-textinput-padding);
}

.container:focus-within {
border-color: var(--color-focus);
background: var(--color-widget-bg-focused);
box-shadow: var(--widget-box-shadow-focused);
}

.drop-mask {
opacity: 0;
pointer-events: none;
position: absolute;
z-index: 1;
height: 100%;
width: 100%;
bottom: 0;
right: 0;
background: rgba(210, 243, 184, 0.8);
border-radius: var(--curvature-widget);
margin: -0.5em;
padding: 0.5em;
transition: opacity ease-in-out var(--transition-speed);
display: flex;
align-items: center;
text-align: center;
}

.highlight .drop-mask {
opacity: 1;
}

.drop-mask > div {
margin: auto;
border-radius: var(--curvature-widget);
font-weight: 400;
color: rgba(0, 0, 0, 0.5);
}
`;
}

@property({ type: Number })
dropZoneWidth = 0; //accepts pixels

@property({ type: String })
uploadLabel = '';

@property({ type: Boolean })
pendingDrop = false;

public constructor() {
super();
}

private handleContainerClicked(evt: Event): void {
this.fireCustomEvent(CustomEventType.ContainerClicked);
}

private handleDragEnter(evt: DragEvent): void {
this.highlight(evt);
}

private handleDragOver(evt: DragEvent): void {
this.highlight(evt);
}

private handleDragLeave(evt: DragEvent): void {
this.unhighlight(evt);
}

private handleDragDropped(evt: DragEvent): void {
this.unhighlight(evt);
this.fireCustomEvent(CustomEventType.DragDropped, { de: evt });
}

private preventDefaults(evt: Event): void {
evt.preventDefault();
evt.stopPropagation();
}

private highlight(evt: DragEvent): void {
this.pendingDrop = true;
this.preventDefaults(evt);
}

private unhighlight(evt: DragEvent): void {
this.pendingDrop = false;
this.preventDefaults(evt);
}

public render(): TemplateResult {
return html`
<div
class=${getClasses({ container: true, highlight: this.pendingDrop })}
@click=${this.handleContainerClicked}
@dragenter=${this.handleDragEnter}
@dragover=${this.handleDragOver}
@dragleave=${this.handleDragLeave}
@drop=${this.handleDragDropped}
style="width:${this.dropZoneWidth > 0
? this.dropZoneWidth + 'px'
: 'auto'}"
>
<div class="drop-mask">
<div>${this.uploadLabel}</div>
</div>
<slot></slot>
</div>
`;
}
}
162 changes: 162 additions & 0 deletions src/attachments/AttachmentsList.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
import { TemplateResult, html, css } from 'lit';
import { FormElement } from '../FormElement';
import { property } from 'lit/decorators.js';
import { Icon } from '../vectoricon';
import { CustomEventType } from '../interfaces';
import { formatFileSize, formatFileType, truncate } from '../utils';
import { Attachment } from './attachments';

export class AttachmentsList extends FormElement {
static get styles() {
return css`
.attachments-list {
display: flex;
flex-direction: row;
flex-wrap: wrap;
}
.attachment-item {
background: rgba(100, 100, 100, 0.1);
border-radius: 2px;
margin: 0.3em;
display: flex;
color: var(--color-widget-text);
}
.attachment-item.error {
background: rgba(250, 0, 0, 0.1);
color: rgba(250, 0, 0, 0.75);
}
.remove-item {
cursor: pointer !important;
padding: 3px 6px;
border-right: 1px solid rgba(100, 100, 100, 0.2);
margin-top: 1px;
background: rgba(100, 100, 100, 0.05);
}
.remove-item:hover {
background: rgba(100, 100, 100, 0.1);
}
.remove-item.error:hover {
background: rgba(250, 0, 0, 0.1);
}
.remove-item.error {
background: rgba(250, 0, 0, 0.05);
color: rgba(250, 0, 0, 0.75);
}
.attachment-name {
align-self: center;
font-size: 12px;
padding: 2px 8px;
}
`;
}

@property({ type: String })
removeIcon = 'delete_small';

@property({ type: Array })
currentAttachments: Attachment[];

@property({ type: Array })
failedAttachments: Attachment[];

public constructor() {
super();
}

public firstUpdated(changes: Map<string, any>): void {
super.firstUpdated(changes);
}

public updated(changes: Map<string, any>): void {
super.updated(changes);

if (changes.has('currentAttachments') || changes.has('failedAttachments')) {
this.fireCustomEvent(CustomEventType.ContentChanged, {
currentAttachments: this.currentAttachments,
failedAttachments: this.failedAttachments,
});
}
}

private handleRemoveFileClicked(evt: Event): void {
const target = evt.target as HTMLDivElement;
const currentAttachmentToRemove = this.currentAttachments.find(
({ uuid }) => uuid === target.id
);
if (currentAttachmentToRemove) {
this.removeCurrentAttachment(currentAttachmentToRemove);
}
const failedAttachmentToRemove = this.failedAttachments.find(
({ uuid }) => uuid === target.id
);
if (failedAttachmentToRemove) {
this.removeFailedAttachment(failedAttachmentToRemove);
}
}

public removeCurrentAttachment(attachmentToRemove: any) {
this.currentAttachments = this.currentAttachments.filter(
currentAttachment => currentAttachment !== attachmentToRemove
);
}

public removeFailedAttachment(attachmentToRemove: any) {
this.failedAttachments = this.failedAttachments.filter(
(failedAttachment: any) => failedAttachment !== attachmentToRemove
);
}

public render(): TemplateResult {
return html`
${(this.currentAttachments && this.currentAttachments.length > 0) ||
(this.failedAttachments && this.failedAttachments.length > 0)
? html` <div class="attachments-list">
${this.currentAttachments.map(validAttachment => {
return html` <div class="attachment-item">
<div class="remove-item" @click=${this.handleRemoveFileClicked}>
<temba-icon
id="${validAttachment.uuid}"
name="icon.${this.removeIcon}"
></temba-icon>
</div>
<div class="attachment-name">
<span
title="${validAttachment.filename} (${formatFileSize(
validAttachment.size,
2
)}) ${validAttachment.content_type}"
>${truncate(validAttachment.filename, 25)}
(${formatFileSize(validAttachment.size, 0)})
${formatFileType(validAttachment.content_type)}</span
>
</div>
</div>`;
})}
${this.failedAttachments.map(invalidAttachment => {
return html` <div class="attachment-item error">
<div
class="remove-item error"
@click=${this.handleRemoveFileClicked}
>
<temba-icon
id="${invalidAttachment.uuid}"
name="${Icon.delete_small}"
></temba-icon>
</div>
<div class="attachment-name">
<span
title="${invalidAttachment.filename} (${formatFileSize(
0,
0
)}) - Attachment failed - ${invalidAttachment.error}"
>${truncate(invalidAttachment.filename, 25)}
(${formatFileSize(0, 0)}) - Attachment failed</span
>
</div>
</div>`;
})}
</div>`
: null}
`;
}
}
Loading