Ghost/ghost/admin/app/components/gh-member-label-input-labs.js
Rishabh a895bafb53 Added label editing feature in filtering dropdown
refs https://github.com/TryGhost/Team/issues/966

With introduction of members filtering, the current way of editing member labels needed an upgrade. This change updates the member label input component to include editing option which allows triggering label edit modal directly from the filtering menu when working with labels. The long term idea is to make this a consistent global pattern with labels dropdown, extending to member details screen as well.
2021-08-12 17:51:18 +05:30

96 lines
2.9 KiB
JavaScript

import Component from '@glimmer/component';
import {action} from '@ember/object';
import {inject as service} from '@ember/service';
import {tracked} from '@glimmer/tracking';
export default class GhMemberLabelInputLabs extends Component {
@service store;
@tracked selectedLabels = [];
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');
this.selectedLabels = this.args.labels || [];
}
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.selectedLabels = newLabels;
this.args.onChange(newLabels);
}
@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);
}
}