Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
5 changes: 5 additions & 0 deletions .changeset/nasty-cherries-double.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@alauda/ui": patch
---

feat: optimize tags input
6 changes: 5 additions & 1 deletion .github/workflows/release-beta.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ on:
jobs:
release_beta:
name: Release Beta
permissions:
contents: read
id-token: write
runs-on: ubuntu-latest
steps:
- name: Checkout Repo
Expand All @@ -17,6 +20,7 @@ jobs:
with:
node-version: 20
cache: yarn
registry-url: 'https://registry.npmjs.org'

- name: Install dependencies
run: yarn --frozen-lockfile
Expand All @@ -25,7 +29,7 @@ jobs:
run: sh scripts/release.sh
env:
PUBLISH_VERSION: beta
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

- name: Sync Cnpm
run: npx cnpm sync @alauda/ui
6 changes: 5 additions & 1 deletion .github/workflows/release-prod.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ on:
jobs:
release_prod:
name: Release Prod
permissions:
contents: write
id-token: write
runs-on: ubuntu-latest
steps:
- name: Checkout Repo
Expand All @@ -20,6 +23,7 @@ jobs:
with:
node-version: 20
cache: yarn
registry-url: 'https://registry.npmjs.org'

- name: Install dependencies
run: yarn --frozen-lockfile
Expand All @@ -33,7 +37,7 @@ jobs:
run: sh scripts/release.sh
env:
PUBLISH_VERSION: ${{ github.event.inputs.version }}
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

- name: Sync Cnpm
run: npx cnpm sync @alauda/ui
6 changes: 5 additions & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ jobs:
release:
name: Release
runs-on: ubuntu-latest
permissions:
contents: write
id-token: write
steps:
- name: Checkout Repo
uses: actions/checkout@v3
Expand All @@ -21,6 +24,7 @@ jobs:
with:
node-version: 20
cache: yarn
registry-url: 'https://registry.npmjs.org'

- name: Install Dependencies
run: yarn --frozen-lockfile
Expand All @@ -35,7 +39,7 @@ jobs:
publish: yarn release
env:
GITHUB_TOKEN: ${{ secrets.GH_TOKEN }}
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

- name: Sync Cnpm
run: npx cnpm sync @alauda/ui
16 changes: 15 additions & 1 deletion jest.setup.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,18 @@
import 'jest-preset-angular/setup-jest';
import { setupZoneTestEnv } from 'jest-preset-angular/setup-env/zone';

setupZoneTestEnv();

// Suppress CSS parsing errors from JSDOM (e.g., @layer rules not supported)
const originalConsoleError = console.error;
console.error = (...args: any[]) => {
if (
typeof args[0] === 'string' &&
args[0].includes('Could not parse CSS stylesheet')
) {
return;
}
originalConsoleError.call(console, ...args);
};

Object.assign(globalThis, {
ngJest: {
Expand Down
5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@
"name": "@alauda/ui",
"version": "9.1.1",
"description": "Angular UI components by Alauda Frontend Team.",
"repository": "git+https://github.com/alauda/alauda-ui.git",
"repository": {
"type": "git",
"url": "https://github.com/alauda/ui.git"
},
"author": "Alauda Frontend",
"contributors": [
"FengTianze",
Expand Down
6 changes: 2 additions & 4 deletions scripts/release.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,10 @@ PUBLISH_VERSION=$(node scripts/publish-version)
PUBLISH_BRANCH=$(node scripts/publish-branch)
NPM_TAG=$(node scripts/npm-tag)

if [ "$NPM_TOKEN" = "" ]; then
if [ "$NODE_AUTH_TOKEN" = "" ] && [ "$NPM_TOKEN" = "" ]; then
echo "NPM_TOKEN is not available on PR from forked repository!"
echo "If you're a member of Alauda, just checkout a new branch instead."
exit 0
else
npm set //registry.npmjs.org/:_authToken "$NPM_TOKEN"
fi
Comment on lines +7 to 11
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Error message should mention both token options.

The condition now checks for both NODE_AUTH_TOKEN and NPM_TOKEN, but the error message only references NPM_TOKEN. This could confuse contributors who set NODE_AUTH_TOKEN but still see the error.

Proposed fix
 if [ "$NODE_AUTH_TOKEN" = "" ] && [ "$NPM_TOKEN" = "" ]; then
-  echo "NPM_TOKEN is not available on PR from forked repository!"
+  echo "NODE_AUTH_TOKEN or NPM_TOKEN is not available on PR from forked repository!"
   echo "If you're a member of Alauda, just checkout a new branch instead."
   exit 0
 fi
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if [ "$NODE_AUTH_TOKEN" = "" ] && [ "$NPM_TOKEN" = "" ]; then
echo "NPM_TOKEN is not available on PR from forked repository!"
echo "If you're a member of Alauda, just checkout a new branch instead."
exit 0
else
npm set //registry.npmjs.org/:_authToken "$NPM_TOKEN"
fi
if [ "$NODE_AUTH_TOKEN" = "" ] && [ "$NPM_TOKEN" = "" ]; then
echo "NODE_AUTH_TOKEN or NPM_TOKEN is not available on PR from forked repository!"
echo "If you're a member of Alauda, just checkout a new branch instead."
exit 0
fi
🤖 Prompt for AI Agents
In @scripts/release.sh around lines 7 - 11, The error message in the conditional
that checks [ "$NODE_AUTH_TOKEN" = "" ] && [ "$NPM_TOKEN" = "" ] only mentions
NPM_TOKEN; update the echo(s) in that if block to clearly state that neither
NODE_AUTH_TOKEN nor NPM_TOKEN is available (for example: "Neither
NODE_AUTH_TOKEN nor NPM_TOKEN is available on PRs from forked repositories") and
keep the existing guidance line; modify the echo lines in the same if block so
the message reflects both token options.


if [ "$NPM_TAG" = "latest" ]; then
Expand All @@ -28,4 +26,4 @@ if [ "$PUBLISH_BRANCH" != "" ]; then
git push --follow-tags origin "$PUBLISH_BRANCH"
fi

npm publish ./release --tag "$NPM_TAG"
npm publish ./release --tag "$NPM_TAG" --provenance --access public
74 changes: 60 additions & 14 deletions src/input/tags-input/tags-input-form.component.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,10 @@ describe('TagsInputComponent Required Validation Behavior', () => {
let fixture: ComponentFixture<TestFormComponent>;
let testHost: TestFormComponent;
let inputEl: HTMLInputElement;
let tagComp: TagsInputComponent;

beforeEach(() => {
fixture = TestBed.createComponent(TestFormComponent);
fixture.detectChanges();
tagComp = fixture.debugElement.query(
By.directive(TagsInputComponent),
).componentInstance;
testHost = fixture.componentInstance;
const el = fixture.debugElement.query(
By.css('.aui-tags-input'),
Expand Down Expand Up @@ -64,12 +60,24 @@ describe('TagsInputComponent Required Validation Behavior', () => {

inputEl.value = 'a';
inputEl.dispatchEvent(new Event('input'));
fixture.detectChanges();
tick();

expect(testHost.form.get('tags')!.value).toEqual(['a']);

inputEl.dispatchEvent(new Event('blur'));
tick();
fixture.detectChanges();

expect(testHost.form.get('tags')!.value).toEqual(['a']);

inputEl.value = 'a';
inputEl.dispatchEvent(new Event('input'));
fixture.detectChanges();
tick();

expect(testHost.form.get('tags')!.value).toEqual(['a', 'a']);

inputEl.dispatchEvent(new Event('blur'));
tick();
fixture.detectChanges();
Expand All @@ -83,12 +91,24 @@ describe('TagsInputComponent Required Validation Behavior', () => {

inputEl.value = 'a';
inputEl.dispatchEvent(new Event('input'));
fixture.detectChanges();
tick();

expect(testHost.form.get('tags')!.value).toEqual(['a']);

inputEl.dispatchEvent(new Event('blur'));
tick();
fixture.detectChanges();

expect(testHost.form.get('tags')!.value).toEqual(['a']);

inputEl.value = 'a';
inputEl.dispatchEvent(new Event('input'));
fixture.detectChanges();
tick();

expect(testHost.form.get('tags')!.value).toEqual(['a', 'a']);

inputEl.dispatchEvent(new Event('blur'));
tick();
fixture.detectChanges();
Expand All @@ -104,6 +124,11 @@ describe('TagsInputComponent Required Validation Behavior', () => {

inputEl.value = '';
inputEl.dispatchEvent(new Event('input'));
fixture.detectChanges();
tick();

expect(testHost.form.get('tags')!.value).toEqual([]);

inputEl.dispatchEvent(new Event('blur'));
tick();
fixture.detectChanges();
Expand All @@ -117,18 +142,23 @@ describe('TagsInputComponent Required Validation Behavior', () => {

inputEl.value = '';
inputEl.dispatchEvent(new Event('input'));
fixture.detectChanges();
tick();

expect(testHost.form.get('tags')!.value).toEqual([]);

inputEl.dispatchEvent(new Event('blur'));
tick();
fixture.detectChanges();

expect(testHost.form.get('tags')!.value).toEqual(['']);
expect(testHost.form.get('tags')!.value).toEqual([]);
}));
});

describe('inputValidator behavior', () => {
it('should NOT add tag when input does NOT pass inputValidator', fakeAsync(() => {
testHost.checkFn = control => {
const value = control.value as string[];
const value = control.value as string;
if (value.includes('a')) {
return { patternB: true };
}
Expand All @@ -138,30 +168,42 @@ describe('TagsInputComponent Required Validation Behavior', () => {

inputEl.value = 'apple';
inputEl.dispatchEvent(new Event('input'));
fixture.detectChanges();
tick();

expect(testHost.form.get('tags')!.value).toEqual(['apple']);
expect(testHost.form.valid).toBeTruthy();

inputEl.dispatchEvent(new Event('blur'));
tick(0);
tick();
fixture.detectChanges();

expect(tagComp.model).toEqual([]);
expect(testHost.form.get('tags')!.value).toEqual([]);
expect(testHost.form.get('tags')!.value).toEqual(['apple']);
expect(testHost.form.valid).toBeFalsy();
}));

it('should add tag when input passes inputValidator', fakeAsync(() => {
testHost.checkFn = control => {
const value = control.value as string[];
const value = control.value as string;
if (value.includes('a')) {
return { patternB: true };
}
return null;
};
fixture.detectChanges();

inputEl.value = 'ccc';
inputEl.dispatchEvent(new Event('input'));
fixture.detectChanges();
tick();

expect(testHost.form.get('tags')!.value).toEqual(['ccc']);
expect(testHost.form.valid).toBeTruthy();

inputEl.dispatchEvent(new Event('blur'));
tick(0);
tick();
fixture.detectChanges();

expect(tagComp.model).toEqual(['ccc']);
expect(testHost.form.get('tags')!.value).toEqual(['ccc']);
expect(testHost.form.valid).toBeTruthy();
}));
Expand All @@ -175,12 +217,16 @@ describe('TagsInputComponent Required Validation Behavior', () => {

inputEl.value = 'bad';
inputEl.dispatchEvent(new Event('input'));
inputEl.dispatchEvent(new Event('blur'));
fixture.detectChanges();
tick();

expect(testHost.form.get('tags')!.value).toEqual(['bad']);

inputEl.dispatchEvent(new Event('blur'));
tick();
fixture.detectChanges();

expect(testHost.form.get('tags')!.value).toEqual([]);
expect(testHost.form.get('tags')!.value).toEqual(['bad']);
}));

it('should allow adding tag when async validator resolves to true', fakeAsync(() => {
Expand Down
27 changes: 15 additions & 12 deletions src/input/tags-input/tags-input.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,21 @@
>
{{ placeholder }}
</span>
<aui-tag
*ngFor="let tag of model; let index = index; trackBy: trackByValue"
type="info"
[title]="tag"
[size]="tagSize"
[round]="true"
[border]="true"
[closeable]="!(disabled || readonlyTags.includes(tag))"
(close)="onRemove(index)"
>
{{ tag }}
</aui-tag>
@for (item of model; let index = $index; track index) {
@if (!item.isInputting) {
<aui-tag
type="info"
[title]="item.value"
[size]="tagSize"
[round]="true"
[border]="true"
[closeable]="!(disabled || readonlyTags.includes(item.value))"
(close)="onRemove(index)"
>
{{ item.value }}
</aui-tag>
}
}
<input
#inputRef
[class]="inputClass"
Expand Down
3 changes: 3 additions & 0 deletions src/input/tags-input/tags-input.component.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ describe('TagsInputComponent', () => {

it('should push new value when press Enter', fakeAsync(() => {
inputEl.value = 'app';
inputEl.dispatchEvent(new Event('input'));
fixture.detectChanges();
tick();
inputEl.dispatchEvent(new KeyboardEvent('keydown', { key: 'Enter' }));
fixture.detectChanges();
tick(20);
Expand Down
Loading