-
Notifications
You must be signed in to change notification settings - Fork 152
feat: Add bulk ZIP export (#867) #222
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
base: main
Are you sure you want to change the base?
Changes from 1 commit
4107473
fbd57d4
963a2e6
9210cb9
ebd2a2f
7b2e958
a69c569
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,4 @@ | ||
| import * as _ from 'lodash'; | ||
| import React from "react"; | ||
| import { action, computed } from "mobx"; | ||
| import { inject, observer } from "mobx-react"; | ||
|
|
@@ -20,6 +21,8 @@ import { | |
| snippetExportOptions, | ||
| SnippetOption | ||
| } from '../../../model/ui/export'; | ||
| import { ZIP_ALL_FORMAT_KEY } from '../../../model/ui/snippet-formats'; | ||
| import { ZipDownloadPanel } from '../zip-download-panel'; | ||
|
|
||
| import { ProHeaderPill, CardSalesPitch } from '../../account/pro-placeholders'; | ||
| import { | ||
|
|
@@ -135,6 +138,32 @@ const ExportHarPill = styled(observer((p: { | |
| margin-right: auto; | ||
| `; | ||
|
|
||
| // Virtual SnippetOption used as the PillSelector value when ZIP is selected. | ||
| // This is never passed to httpsnippet — it's only used for dropdown rendering. | ||
| const ZIP_SNIPPET_OPTION: SnippetOption = { | ||
| target: ZIP_ALL_FORMAT_KEY as any, | ||
| client: '' as any, | ||
| name: 'ZIP (Selected Formats)', | ||
| description: 'Download selected code snippet formats in a single ZIP archive', | ||
| link: '' | ||
| }; | ||
|
|
||
| // Build extended optGroups with ZIP at the top | ||
| const exportOptionsWithZip: _.Dictionary<SnippetOption[]> = { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You don't need to import the whole of lodash for this one type, you can just use There are probably old examples of doing that elsewhere here - they predate |
||
| 'Archive': [ZIP_SNIPPET_OPTION], | ||
| ...snippetExportOptions | ||
| }; | ||
|
|
||
| const getExportFormatKey = (option: SnippetOption): string => { | ||
| if (option === ZIP_SNIPPET_OPTION) return ZIP_ALL_FORMAT_KEY; | ||
| return getCodeSnippetFormatKey(option); | ||
| }; | ||
|
|
||
| const getExportFormatName = (option: SnippetOption): string => { | ||
| if (option === ZIP_SNIPPET_OPTION) return ZIP_SNIPPET_OPTION.name; | ||
| return getCodeSnippetFormatName(option); | ||
| }; | ||
|
|
||
| @inject('accountStore') | ||
| @inject('uiStore') | ||
| @observer | ||
|
|
@@ -143,6 +172,7 @@ export class HttpExportCard extends React.Component<ExportCardProps> { | |
| render() { | ||
| const { exchange, accountStore } = this.props; | ||
| const isPaidUser = accountStore!.user.isPaidUser(); | ||
| const isZipSelected = this.isZipSelected; | ||
|
|
||
| return <CollapsibleCard {...this.props}> | ||
| <header> | ||
|
|
@@ -153,10 +183,10 @@ export class HttpExportCard extends React.Component<ExportCardProps> { | |
|
|
||
| <PillSelector<SnippetOption> | ||
| onChange={this.setSnippetOption} | ||
| value={this.snippetOption} | ||
| optGroups={snippetExportOptions} | ||
| keyFormatter={getCodeSnippetFormatKey} | ||
| nameFormatter={getCodeSnippetFormatName} | ||
| value={this.currentDropdownValue} | ||
| optGroups={exportOptionsWithZip} | ||
| keyFormatter={getExportFormatKey} | ||
| nameFormatter={getExportFormatName} | ||
| /> | ||
|
|
||
| <CollapsibleCardHeading onCollapseToggled={this.props.onCollapseToggled}> | ||
|
|
@@ -166,10 +196,13 @@ export class HttpExportCard extends React.Component<ExportCardProps> { | |
|
|
||
| { isPaidUser ? | ||
| <div> | ||
| <ExportSnippetEditor | ||
| exchange={exchange} | ||
| exportOption={this.snippetOption} | ||
| /> | ||
| { isZipSelected | ||
| ? <ZipDownloadPanel exchanges={[exchange]} /> | ||
| : <ExportSnippetEditor | ||
| exchange={exchange} | ||
| exportOption={this.snippetOption} | ||
| /> | ||
| } | ||
| </div> | ||
| : | ||
| <CardSalesPitch source='export'> | ||
|
|
@@ -188,11 +221,29 @@ export class HttpExportCard extends React.Component<ExportCardProps> { | |
| </CollapsibleCard>; | ||
| } | ||
|
|
||
| @computed | ||
| private get isZipSelected(): boolean { | ||
| return (this.props.uiStore!.exportSnippetFormat || '') === ZIP_ALL_FORMAT_KEY; | ||
| } | ||
|
|
||
| @computed | ||
| private get currentDropdownValue(): SnippetOption { | ||
| if (this.isZipSelected) return ZIP_SNIPPET_OPTION; | ||
| return this.snippetOption; | ||
| } | ||
|
|
||
| @computed | ||
| private get snippetOption(): SnippetOption { | ||
| let exportSnippetFormat = this.props.uiStore!.exportSnippetFormat || | ||
| DEFAULT_SNIPPET_FORMAT_KEY; | ||
| return getCodeSnippetOptionFromKey(exportSnippetFormat); | ||
| // If ZIP is selected, fall back to default for the snippet option | ||
| if (exportSnippetFormat === ZIP_ALL_FORMAT_KEY) { | ||
| exportSnippetFormat = DEFAULT_SNIPPET_FORMAT_KEY; | ||
| } | ||
| // Guard: if the format key doesn't resolve (e.g. deleted/invalid key), | ||
| // fall back to the default cURL option | ||
| return getCodeSnippetOptionFromKey(exportSnippetFormat) | ||
| ?? getCodeSnippetOptionFromKey(DEFAULT_SNIPPET_FORMAT_KEY); | ||
| } | ||
|
|
||
| @action.bound | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These
anyare a bit suspicious. I think we should have some kind of better types that make this work properly, without this and witohut an extra special case functions likegetExportFormatKeythat just wrapsgetCodeSnippetFormatKeywith one extra condition. We probably want something likeexport ExportOption = ZipExportOption | SnippetOptionsomewhere with some kind of discriminated union, and then to change the various references take eitherExportOptionorSnippetOptionas appropriate, and discriminate to make all those types work correctly, withoutany.