Merge branch 'main' of github.com:ghostfolio/ghostfolio
All checks were successful
Docker image CD / build_and_push (push) Successful in 21m12s

This commit is contained in:
sudacode 2025-02-08 18:00:07 -08:00
commit bbcef36abe
5 changed files with 75 additions and 58 deletions

View File

@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added
- Extended the tags selector component by a `readonly` attribute
- Added global styles to the _Storybook_ setup
## 2.138.0 - 2025-02-08

View File

@ -366,33 +366,12 @@
</mat-tab>
</mat-tab-group>
<div
class="row"
[ngClass]="{
'd-none': !data.hasPermissionToUpdateOrder
}"
>
<div class="col">
<gf-tags-selector
[tags]="activityForm.get('tags')?.value"
[tagsAvailable]="tagsAvailable"
(tagsChanged)="onTagsChanged($event)"
/>
</div>
</div>
@if (!data.hasPermissionToUpdateOrder && tagsAvailable?.length > 0) {
<div class="row">
<div class="col">
<div class="h5" i18n>Tags</div>
<mat-chip-listbox>
@for (tag of tags; track tag) {
<mat-chip-option disabled>{{ tag.name }}</mat-chip-option>
}
</mat-chip-listbox>
</div>
</div>
}
<gf-tags-selector
[readonly]="!data.hasPermissionToUpdateOrder"
[tags]="activityForm.get('tags')?.value"
[tagsAvailable]="tagsAvailable"
(tagsChanged)="onTagsChanged($event)"
/>
@if (
dataSource?.data.length > 0 &&

View File

@ -1,32 +1,49 @@
<mat-form-field appearance="outline" class="w-100 without-hint">
<mat-label i18n>Tags</mat-label>
<mat-chip-grid #tagsChipList>
@for (tag of tagsSelected(); track tag.id) {
<mat-chip-row
matChipRemove
[removable]="true"
(removed)="onRemoveTag(tag)"
>
{{ tag.name }}
<ion-icon matChipTrailingIcon name="close-outline" />
</mat-chip-row>
<div class="row">
<div class="col">
@if (readonly) {
<div class="h5" i18n>Tags</div>
@if (tags?.length > 0) {
<mat-chip-listbox>
@for (tag of tags; track tag) {
<mat-chip-option disabled>{{ tag.name }}</mat-chip-option>
}
</mat-chip-listbox>
} @else {
<div>-</div>
}
} @else {
<mat-form-field appearance="outline" class="w-100 without-hint">
<mat-label i18n>Tags</mat-label>
<mat-chip-grid #tagsChipList>
@for (tag of tagsSelected(); track tag.id) {
<mat-chip-row
matChipRemove
[removable]="true"
(removed)="onRemoveTag(tag)"
>
{{ tag.name }}
<ion-icon matChipTrailingIcon name="close-outline" />
</mat-chip-row>
}
<input
#tagInput
[formControl]="tagInputControl"
[matAutocomplete]="autocompleteTags"
[matChipInputFor]="tagsChipList"
[matChipInputSeparatorKeyCodes]="separatorKeysCodes"
/>
</mat-chip-grid>
<mat-autocomplete
#autocompleteTags="matAutocomplete"
(optionSelected)="onAddTag($event)"
>
@for (tag of filteredOptions | async; track tag.id) {
<mat-option [value]="tag.id">
{{ tag.name }}
</mat-option>
}
</mat-autocomplete>
</mat-form-field>
}
<input
#tagInput
[formControl]="tagInputControl"
[matAutocomplete]="autocompleteTags"
[matChipInputFor]="tagsChipList"
[matChipInputSeparatorKeyCodes]="separatorKeysCodes"
/>
</mat-chip-grid>
<mat-autocomplete
#autocompleteTags="matAutocomplete"
(optionSelected)="onAddTag($event)"
>
@for (tag of filteredOptions | async; track tag.id) {
<mat-option [value]="tag.id">
{{ tag.name }}
</mat-option>
}
</mat-autocomplete>
</mat-form-field>
</div>
</div>

View File

@ -47,6 +47,25 @@ export const Default: Story = {
}
};
export const Readonly: Story = {
args: {
readonly: true,
tags: [
{
id: 'EMERGENCY_FUND',
name: 'Emergency Fund',
userId: null
},
{
id: 'RETIREMENT_FUND',
name: 'Retirement Fund',
userId: null
}
],
tagsAvailable: OPTIONS
}
};
export const WithoutValue: Story = {
args: {
tags: [],

View File

@ -42,6 +42,7 @@ import { BehaviorSubject, Subject, takeUntil } from 'rxjs';
templateUrl: 'tags-selector.component.html'
})
export class GfTagsSelectorComponent implements OnInit, OnChanges, OnDestroy {
@Input() readonly = false;
@Input() tags: Tag[];
@Input() tagsAvailable: Tag[];