mirror of
https://github.com/shlinkio/shlink-web-client.git
synced 2024-12-23 01:20:24 +03:00
Update to react-tag-autocomplete 7
This commit is contained in:
parent
5e2dce8f3f
commit
94ba244ae1
8 changed files with 39 additions and 41 deletions
3
.github/workflows/ci.yml
vendored
3
.github/workflows/ci.yml
vendored
|
@ -11,6 +11,5 @@ jobs:
|
||||||
ci:
|
ci:
|
||||||
uses: shlinkio/github-actions/.github/workflows/web-app-ci.yml@main
|
uses: shlinkio/github-actions/.github/workflows/web-app-ci.yml@main
|
||||||
with:
|
with:
|
||||||
node-version: 20.2
|
node-version: 20.5
|
||||||
publish-coverage: true
|
publish-coverage: true
|
||||||
force-install: true
|
|
||||||
|
|
6
.github/workflows/deploy-preview.yml
vendored
6
.github/workflows/deploy-preview.yml
vendored
|
@ -5,7 +5,7 @@ on:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
deploy:
|
deploy:
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-22.04
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
|
@ -16,10 +16,10 @@ jobs:
|
||||||
- name: Use node.js
|
- name: Use node.js
|
||||||
uses: actions/setup-node@v3
|
uses: actions/setup-node@v3
|
||||||
with:
|
with:
|
||||||
node-version: 20.2
|
node-version: 20.5
|
||||||
- name: Build
|
- name: Build
|
||||||
run: |
|
run: |
|
||||||
npm ci --force && \
|
npm ci && \
|
||||||
node ./scripts/set-homepage.js /shlink-web-client/${GITHUB_HEAD_REF#refs/heads/} && \
|
node ./scripts/set-homepage.js /shlink-web-client/${GITHUB_HEAD_REF#refs/heads/} && \
|
||||||
npm run build
|
npm run build
|
||||||
- name: Deploy preview
|
- name: Deploy preview
|
||||||
|
|
6
.github/workflows/publish-release.yml
vendored
6
.github/workflows/publish-release.yml
vendored
|
@ -7,16 +7,16 @@ on:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-22.04
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
- name: Use node.js
|
- name: Use node.js
|
||||||
uses: actions/setup-node@v3
|
uses: actions/setup-node@v3
|
||||||
with:
|
with:
|
||||||
node-version: 20.2
|
node-version: 20.5
|
||||||
- name: Generate release assets
|
- name: Generate release assets
|
||||||
run: npm ci --force && VERSION=${GITHUB_REF#refs/tags/v} npm run build:dist
|
run: npm ci && VERSION=${GITHUB_REF#refs/tags/v} npm run build:dist
|
||||||
- name: Publish release with assets
|
- name: Publish release with assets
|
||||||
uses: docker://antonyurchenko/git-release:latest
|
uses: docker://antonyurchenko/git-release:latest
|
||||||
env:
|
env:
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
FROM node:20.2-alpine as node
|
FROM node:20.5-alpine as node
|
||||||
COPY . /shlink-web-client
|
COPY . /shlink-web-client
|
||||||
ARG VERSION="latest"
|
ARG VERSION="latest"
|
||||||
ENV VERSION ${VERSION}
|
ENV VERSION ${VERSION}
|
||||||
RUN cd /shlink-web-client && npm ci --force && npm run build
|
RUN cd /shlink-web-client && npm ci && npm run build
|
||||||
|
|
||||||
FROM nginx:1.23-alpine
|
FROM nginx:1.23-alpine
|
||||||
LABEL maintainer="Alejandro Celaya <alejandro@alejandrocelaya.com>"
|
LABEL maintainer="Alejandro Celaya <alejandro@alejandrocelaya.com>"
|
||||||
|
|
|
@ -3,8 +3,8 @@ version: '3'
|
||||||
services:
|
services:
|
||||||
shlink_web_client_node:
|
shlink_web_client_node:
|
||||||
container_name: shlink_web_client_node
|
container_name: shlink_web_client_node
|
||||||
image: node:20.2-alpine
|
image: node:20.5-alpine
|
||||||
command: /bin/sh -c "cd /home/shlink/www && npm install --force && npm run start"
|
command: /bin/sh -c "cd /home/shlink/www && npm install && npm run start"
|
||||||
volumes:
|
volumes:
|
||||||
- ./:/home/shlink/www
|
- ./:/home/shlink/www
|
||||||
ports:
|
ports:
|
||||||
|
|
20
package-lock.json
generated
20
package-lock.json
generated
|
@ -39,7 +39,7 @@
|
||||||
"react-redux": "^8.1.2",
|
"react-redux": "^8.1.2",
|
||||||
"react-router-dom": "^6.14.2",
|
"react-router-dom": "^6.14.2",
|
||||||
"react-swipeable": "^7.0.1",
|
"react-swipeable": "^7.0.1",
|
||||||
"react-tag-autocomplete": "^6.3.0",
|
"react-tag-autocomplete": "^7.0.0",
|
||||||
"reactstrap": "^9.2.0",
|
"reactstrap": "^9.2.0",
|
||||||
"redux-localstorage-simple": "^2.5.1",
|
"redux-localstorage-simple": "^2.5.1",
|
||||||
"uuid": "^9.0.0",
|
"uuid": "^9.0.0",
|
||||||
|
@ -8900,16 +8900,14 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/react-tag-autocomplete": {
|
"node_modules/react-tag-autocomplete": {
|
||||||
"version": "6.3.0",
|
"version": "7.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/react-tag-autocomplete/-/react-tag-autocomplete-6.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/react-tag-autocomplete/-/react-tag-autocomplete-7.0.0.tgz",
|
||||||
"integrity": "sha512-MUBVUFh5eOqshUm5NM20qp7zXk8TzSiKO4GoktlFzBLIOLs356npaMKtL02bm0nFV2f1zInUrXn1fq6+i5YX0w==",
|
"integrity": "sha512-PFxT7fpMB8Au+S9cJYAGRVTnacZpeXybc5SkpTCyuJHmUN1Bt8gHb9vZi3f+aX/eDX44x2WIwYiqfRBi2E5AMg==",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 10.0.0"
|
"node": ">= 16.12.0"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"prop-types": "^15.5.0",
|
"react": "^18.0.0"
|
||||||
"react": "^16.5.0 || ^17.0.0",
|
|
||||||
"react-dom": "^16.5.0 || ^17.0.0"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/react-transition-group": {
|
"node_modules/react-transition-group": {
|
||||||
|
@ -17211,9 +17209,9 @@
|
||||||
"requires": {}
|
"requires": {}
|
||||||
},
|
},
|
||||||
"react-tag-autocomplete": {
|
"react-tag-autocomplete": {
|
||||||
"version": "6.3.0",
|
"version": "7.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/react-tag-autocomplete/-/react-tag-autocomplete-6.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/react-tag-autocomplete/-/react-tag-autocomplete-7.0.0.tgz",
|
||||||
"integrity": "sha512-MUBVUFh5eOqshUm5NM20qp7zXk8TzSiKO4GoktlFzBLIOLs356npaMKtL02bm0nFV2f1zInUrXn1fq6+i5YX0w==",
|
"integrity": "sha512-PFxT7fpMB8Au+S9cJYAGRVTnacZpeXybc5SkpTCyuJHmUN1Bt8gHb9vZi3f+aX/eDX44x2WIwYiqfRBi2E5AMg==",
|
||||||
"requires": {}
|
"requires": {}
|
||||||
},
|
},
|
||||||
"react-transition-group": {
|
"react-transition-group": {
|
||||||
|
|
|
@ -55,7 +55,7 @@
|
||||||
"react-redux": "^8.1.2",
|
"react-redux": "^8.1.2",
|
||||||
"react-router-dom": "^6.14.2",
|
"react-router-dom": "^6.14.2",
|
||||||
"react-swipeable": "^7.0.1",
|
"react-swipeable": "^7.0.1",
|
||||||
"react-tag-autocomplete": "^6.3.0",
|
"react-tag-autocomplete": "^7.0.0",
|
||||||
"reactstrap": "^9.2.0",
|
"reactstrap": "^9.2.0",
|
||||||
"redux-localstorage-simple": "^2.5.1",
|
"redux-localstorage-simple": "^2.5.1",
|
||||||
"uuid": "^9.0.0",
|
"uuid": "^9.0.0",
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { useEffect } from 'react';
|
import { useEffect } from 'react';
|
||||||
import type { SuggestionComponentProps, TagComponentProps } from 'react-tag-autocomplete';
|
import type { OptionRendererProps, TagRendererProps, TagSuggestion } from 'react-tag-autocomplete';
|
||||||
import ReactTags from 'react-tag-autocomplete';
|
import { ReactTags } from 'react-tag-autocomplete';
|
||||||
import type { ColorGenerator } from '../../utils/services/ColorGenerator';
|
import type { ColorGenerator } from '../../utils/services/ColorGenerator';
|
||||||
import { useSetting } from '../../utils/settings';
|
import { useSetting } from '../../utils/settings';
|
||||||
import type { TagsList } from '../reducers/tagsList';
|
import type { TagsList } from '../reducers/tagsList';
|
||||||
|
@ -19,7 +19,7 @@ interface TagsSelectorConnectProps extends TagsSelectorProps {
|
||||||
tagsList: TagsList;
|
tagsList: TagsList;
|
||||||
}
|
}
|
||||||
|
|
||||||
const toComponentTag = (tag: string) => ({ id: tag, name: tag });
|
const toTagSuggestion = (tag: string): TagSuggestion => ({ label: tag, value: tag });
|
||||||
|
|
||||||
export const TagsSelector = (colorGenerator: ColorGenerator) => (
|
export const TagsSelector = (colorGenerator: ColorGenerator) => (
|
||||||
{ selectedTags, onChange, placeholder, listTags, tagsList, allowNew = true }: TagsSelectorConnectProps,
|
{ selectedTags, onChange, placeholder, listTags, tagsList, allowNew = true }: TagsSelectorConnectProps,
|
||||||
|
@ -30,29 +30,30 @@ export const TagsSelector = (colorGenerator: ColorGenerator) => (
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const searchMode = shortUrlCreation?.tagFilteringMode ?? 'startsWith';
|
const searchMode = shortUrlCreation?.tagFilteringMode ?? 'startsWith';
|
||||||
const ReactTagsTag = ({ tag, onDelete }: TagComponentProps) =>
|
const ReactTagsTag = ({ tag, onClick: deleteTag }: TagRendererProps) => (
|
||||||
<Tag colorGenerator={colorGenerator} text={tag.name} clearable className="react-tags__tag" onClose={onDelete} />;
|
<Tag colorGenerator={colorGenerator} text={tag.label} clearable className="react-tags__tag" onClose={deleteTag} />
|
||||||
const ReactTagsSuggestion = ({ item }: SuggestionComponentProps) => (
|
);
|
||||||
|
const ReactTagsSuggestion = ({ option }: OptionRendererProps) => (
|
||||||
<>
|
<>
|
||||||
<TagBullet tag={`${item.name}`} colorGenerator={colorGenerator} />
|
<TagBullet tag={`${option.label}`} colorGenerator={colorGenerator} />
|
||||||
{item.name}
|
{option.label}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ReactTags
|
<ReactTags
|
||||||
tags={selectedTags.map(toComponentTag)}
|
selected={selectedTags.map(toTagSuggestion)}
|
||||||
tagComponent={ReactTagsTag}
|
suggestions={tagsList.tags.filter((tag) => !selectedTags.includes(tag)).map(toTagSuggestion)}
|
||||||
suggestions={tagsList.tags.filter((tag) => !selectedTags.includes(tag)).map(toComponentTag)}
|
renderTag={ReactTagsTag}
|
||||||
suggestionComponent={ReactTagsSuggestion}
|
renderOption={ReactTagsSuggestion}
|
||||||
allowNew={allowNew}
|
allowNew={allowNew}
|
||||||
addOnBlur
|
// addOnBlur TODO Implement manually
|
||||||
placeholderText={placeholder ?? 'Add tags to the URL'}
|
placeholderText={placeholder ?? 'Add tags to the URL'}
|
||||||
minQueryLength={1}
|
onShouldExpand={(value) => value.length > 1}
|
||||||
delimiters={['Enter', 'Tab', ',']}
|
delimiterKeys={['Enter', 'Tab', ',']}
|
||||||
suggestionsTransform={
|
suggestionsTransform={
|
||||||
searchMode === 'includes'
|
searchMode === 'includes'
|
||||||
? (query, suggestions) => suggestions.filter(({ name }) => name.includes(query))
|
? (query, suggestions) => suggestions.filter(({ label }) => label.includes(query))
|
||||||
: undefined
|
: undefined
|
||||||
}
|
}
|
||||||
onDelete={(removedTagIndex) => {
|
onDelete={(removedTagIndex) => {
|
||||||
|
@ -61,7 +62,7 @@ export const TagsSelector = (colorGenerator: ColorGenerator) => (
|
||||||
tagsCopy.splice(removedTagIndex, 1);
|
tagsCopy.splice(removedTagIndex, 1);
|
||||||
onChange(tagsCopy);
|
onChange(tagsCopy);
|
||||||
}}
|
}}
|
||||||
onAddition={({ name: newTag }) => onChange(
|
onAdd={({ label: newTag }) => onChange(
|
||||||
// * Avoid duplicated tags (thanks to the Set),
|
// * Avoid duplicated tags (thanks to the Set),
|
||||||
// * Split any of the new tags by comma, allowing to paste multiple comma-separated tags at once.
|
// * Split any of the new tags by comma, allowing to paste multiple comma-separated tags at once.
|
||||||
[...new Set([...selectedTags, ...newTag.toLowerCase().split(',')])],
|
[...new Set([...selectedTags, ...newTag.toLowerCase().split(',')])],
|
||||||
|
|
Loading…
Reference in a new issue