JezK
Edit File: sc-downloads-list.cjs.entry.js.map
{"file":"sc-downloads-list.entry.cjs.js","mappings":";;;;;;;;;;;AAAA,MAAM,kBAAkB,GAAG,uTAAuT,CAAC;AACnV,8BAAe,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8ECiDA,UAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;6BAqDhB,UAAE;;;;;;;8EAMY,UAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ubA0FhB,UAAE;;;;;;;0KA8BgB,UAAE;;;;4IAQ0B,UAAE,yNAEnB,UAAE;;;;;;;;","names":[],"sources":["src/components/controllers/dashboard/sc-downloads-list/sc-downloads-list.scss?tag=sc-downloads-list&encapsulation=shadow","src/components/controllers/dashboard/sc-downloads-list/sc-downloads-list.tsx"],"sourcesContent":[":host {\n display: block;\n}\n\n.purchase {\n display: flex;\n flex-direction: column;\n gap: var(--sc-spacing-large);\n}\n\n.single-download {\n .single-download__preview {\n display: flex;\n align-items: center;\n justify-content: center;\n background: var(--sc-color-gray-200);\n border-radius: var(--sc-border-radius-small);\n height: 4rem;\n min-width: 4rem;\n width: 4rem;\n }\n}\n","import { Component, h, Prop, State, Element } from '@stencil/core';\nimport apiFetch from '../../../../functions/fetch';\nimport { __ } from '@wordpress/i18n';\nimport { addQueryArgs } from '@wordpress/url';\n\nimport { Download, Media } from '../../../../types';\nimport { onFirstVisible } from '../../../../functions/lazy';\n\n@Component({\n tag: 'sc-downloads-list',\n styleUrl: 'sc-downloads-list.scss',\n shadow: true,\n})\nexport class ScDownloadsList {\n @Element() el: HTMLScDownloadsListElement;\n @Prop() customerId: string;\n @Prop() productId: string;\n @Prop() variantId: string;\n @Prop() heading: string;\n @State() downloads: Download[];\n @State() downloading: string;\n @State() busy: boolean;\n @State() error: string;\n @State() pagination: {\n total: number;\n total_pages: number;\n } = {\n total: 0,\n total_pages: 0,\n };\n @Prop({ mutable: true }) query: any = {\n page: 1,\n per_page: 20,\n };\n\n componentWillLoad() {\n onFirstVisible(this.el, () => {\n this.fetchItems();\n });\n }\n\n async fetchItems() {\n if ((!this.productId && !this.variantId) || !this.customerId) {\n return;\n }\n try {\n this.busy = true;\n await this.getItems();\n } catch (e) {\n console.error(this.error);\n this.error = e?.message || __('Something went wrong', 'surecart');\n } finally {\n this.busy = false;\n }\n }\n\n /** Get all downloads */\n async getItems() {\n const response = (await apiFetch({\n path: addQueryArgs(`surecart/v1/downloads/`, {\n ...(this.variantId ? { variant_ids: [this.variantId] } : { product_ids: [this.productId] }),\n customer_ids: [this.customerId],\n downloadable: true,\n ...this.query,\n }),\n parse: false,\n })) as Response;\n this.pagination = {\n total: parseInt(response.headers.get('X-WP-Total')),\n total_pages: parseInt(response.headers.get('X-WP-TotalPages')),\n };\n this.downloads = (await response.json()) as Download[];\n return this.downloads;\n }\n\n nextPage() {\n this.query.page = this.query.page + 1;\n this.fetchItems();\n }\n\n prevPage() {\n this.query.page = this.query.page - 1;\n this.fetchItems();\n }\n\n async downloadItem(download) {\n if (download?.url) {\n this.downloadFile(download.url, download?.name ?? 'file');\n return;\n }\n\n const mediaId = download?.media?.id;\n if (!mediaId) return;\n\n try {\n this.downloading = mediaId;\n const media = (await apiFetch({\n path: addQueryArgs(`surecart/v1/customers/${this.customerId}/expose/${mediaId}`, {\n expose_for: 60,\n }),\n })) as Media;\n if (!media?.url) {\n throw {\n message: __('Could not download the file.', 'surecart'),\n };\n }\n this.downloadFile(media?.url, media.filename);\n } catch (e) {\n console.error(e);\n this.error = e?.message || __('Something went wrong', 'surecart');\n } finally {\n this.downloading = null;\n }\n }\n\n downloadFile(path, filename) {\n // Create a new link\n const anchor = document.createElement('a');\n anchor.href = path;\n anchor.download = filename;\n\n // Append to the DOM\n document.body.appendChild(anchor);\n\n // Trigger `click` event\n anchor.click();\n\n // To make this work on Firefox we need to wait\n // a little while before removing it.\n setTimeout(() => {\n document.body.removeChild(anchor);\n }, 0);\n }\n\n renderFileExt = download => {\n if (download?.media?.filename) {\n return download.media.filename.split?.('.')?.pop?.();\n }\n if (download?.url) {\n try {\n const url = new URL(download.url);\n if (url.pathname.includes('.')) {\n return url.pathname.split?.('.')?.pop?.();\n }\n } catch (err) {\n console.error(err);\n }\n }\n return <sc-icon name=\"file\" />;\n };\n\n renderList() {\n const downloads = (this.downloads || []).filter((d: Download) => !d.archived);\n if (this?.busy && !downloads.length) {\n return this.renderLoading();\n }\n if (!downloads.length) {\n return this.renderEmpty();\n }\n\n return (\n <sc-card no-padding>\n <sc-stacked-list>\n {downloads.map(download => {\n const media = download?.media as Media;\n return (\n <sc-stacked-list-row style={{ '--columns': '1' }}>\n <sc-flex class=\"single-download\" justifyContent=\"flex-start\" alignItems=\"center\">\n <div class=\"single-download__preview\">{this.renderFileExt(download)}</div>\n <div>\n <div>\n <strong>{media?.filename ?? download?.name ?? ''}</strong>\n </div>\n\n <sc-flex justifyContent=\"flex-start\" alignItems=\"center\" style={{ gap: '0.5em' }}>\n {media?.byte_size && <sc-format-bytes value={media.byte_size}></sc-format-bytes>}\n\n {!!media?.release_json?.version && (\n <sc-tag\n type=\"primary\"\n size=\"small\"\n style={{\n '--sc-tag-primary-background-color': '#f3e8ff',\n '--sc-tag-primary-color': '#6b21a8',\n }}\n >\n v{media?.release_json?.version}\n </sc-tag>\n )}\n </sc-flex>\n </div>\n </sc-flex>\n <sc-button\n size=\"small\"\n slot=\"suffix\"\n onClick={() => this.downloadItem(download)}\n busy={media?.id ? this.downloading == media?.id : false}\n disabled={media?.id ? this.downloading == media?.id : false}\n >\n {__('Download', 'surecart')}\n </sc-button>\n </sc-stacked-list-row>\n );\n })}\n </sc-stacked-list>\n </sc-card>\n );\n }\n\n renderLoading() {\n return (\n <sc-card no-padding style={{ '--overflow': 'hidden' }}>\n <sc-stacked-list>\n <sc-stacked-list-row style={{ '--columns': '2' }} mobile-size={0}>\n <div style={{ padding: '0.5em' }}>\n <sc-skeleton style={{ width: '30%', marginBottom: '0.75em' }}></sc-skeleton>\n <sc-skeleton style={{ width: '20%' }}></sc-skeleton>\n </div>\n </sc-stacked-list-row>\n </sc-stacked-list>\n </sc-card>\n );\n }\n\n renderEmpty() {\n return (\n <div>\n <sc-divider style={{ '--spacing': '0' }}></sc-divider>\n <slot name=\"empty\">\n <sc-empty icon=\"download\">{__(\"You don't have any downloads.\", 'surecart')}</sc-empty>\n </slot>\n </div>\n );\n }\n\n render() {\n return (\n <sc-dashboard-module class=\"purchase\" part=\"base\" heading={__('Downloads', 'surecart')}>\n <span slot=\"heading\">\n <slot name=\"heading\">{this.heading || __('Downloads', 'surecart')}</slot>\n </span>\n {this.renderList()}\n <sc-pagination\n page={this.query.page}\n perPage={this.query.per_page}\n total={this.pagination.total}\n totalPages={this.pagination.total_pages}\n totalShowing={this?.downloads?.length}\n onScNextPage={() => this.nextPage()}\n onScPrevPage={() => this.prevPage()}\n ></sc-pagination>\n {this.busy && <sc-block-ui></sc-block-ui>}\n </sc-dashboard-module>\n );\n }\n}\n"],"version":3}