mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-12-30 14:22:07 +03:00
7d0298c7a8
refs https://github.com/TryGhost/Team/issues/1320 - added a tracked `labels` property in `<ModalImportMembers::CsvFileMapping>` and passed it through to `<GhMembersLabelInput>` so that it has a list of labels that can be added to - fixed error from sorting labels if one doesn't have a name - added acceptance test for selecting labels in the members import flow
109 lines
3.3 KiB
JavaScript
109 lines
3.3 KiB
JavaScript
import Component from '@glimmer/component';
|
|
import {action} from '@ember/object';
|
|
import {inject as service} from '@ember/service';
|
|
|
|
export default class GhMemberLabelInput extends Component {
|
|
@service store;
|
|
|
|
get availableLabels() {
|
|
return this._availableLabels.toArray().sort((labelA, labelB) => {
|
|
return (labelA.name || '').localeCompare((labelB.name || ''), undefined, {ignorePunctuation: true});
|
|
});
|
|
}
|
|
|
|
get availableLabelNames() {
|
|
return this.availableLabels.map(label => label.name.toLowerCase());
|
|
}
|
|
|
|
constructor(...args) {
|
|
super(...args);
|
|
// perform a background query to fetch all users and set `availableLabels`
|
|
// to a live-query that will be immediately populated with what's in the
|
|
// store and be updated when the above query returns
|
|
this.store.query('label', {limit: 'all'});
|
|
this._availableLabels = this.store.peekAll('label');
|
|
}
|
|
|
|
get selectedLabels() {
|
|
if (typeof this.args.labels === 'object') {
|
|
if (this.args.labels?.length && typeof this.args.labels[0] === 'string') {
|
|
return this.args.labels.map((d) => {
|
|
return this.availableLabels.find(label => label.slug === d);
|
|
}) || [];
|
|
}
|
|
return this.args.labels || [];
|
|
}
|
|
return [];
|
|
}
|
|
|
|
willDestroy() {
|
|
super.willDestroy?.(...arguments);
|
|
this._availableLabels.forEach((label) => {
|
|
if (label.get('isNew')) {
|
|
this.store.deleteRecord(label);
|
|
}
|
|
});
|
|
}
|
|
|
|
@action
|
|
hideCreateOptionOnMatchingLabel(term) {
|
|
return !this.availableLabelNames.includes(term.toLowerCase());
|
|
}
|
|
|
|
@action
|
|
updateLabels(newLabels) {
|
|
let currentLabels = this.selectedLabels;
|
|
|
|
// destroy new+unsaved labels that are no longer selected
|
|
currentLabels.forEach(function (label) {
|
|
if (!newLabels.includes(label) && label.get('isNew')) {
|
|
label.destroyRecord();
|
|
}
|
|
});
|
|
|
|
// update labels
|
|
this.args.onChange(newLabels);
|
|
}
|
|
|
|
@action
|
|
editLabel(label, event) {
|
|
event.stopPropagation();
|
|
this.args.onLabelEdit?.(label.slug);
|
|
}
|
|
|
|
@action
|
|
createLabel(labelName) {
|
|
let currentLabels = this.selectedLabels;
|
|
let currentLabelNames = currentLabels.map(label => label.get('name').toLowerCase());
|
|
let labelToAdd;
|
|
|
|
labelName = labelName.trim();
|
|
|
|
// abort if label is already selected
|
|
if (currentLabelNames.includes(labelName.toLowerCase())) {
|
|
return;
|
|
}
|
|
|
|
// find existing label if there is one
|
|
labelToAdd = this._findLabelByName(labelName);
|
|
|
|
// create new label if no match
|
|
if (!labelToAdd) {
|
|
labelToAdd = this.store.createRecord('label', {
|
|
name: labelName
|
|
});
|
|
}
|
|
|
|
// push label onto member relationship
|
|
currentLabels.pushObject(labelToAdd);
|
|
this.args.onChange(currentLabels);
|
|
}
|
|
|
|
_findLabelByName(name) {
|
|
let withMatchingName = function (label) {
|
|
return label.name.toLowerCase() === name.toLowerCase();
|
|
};
|
|
return this.availableLabels.find(withMatchingName);
|
|
}
|
|
}
|