Commit 58ed0e20 authored by Benjamin Bouvier's avatar Benjamin Bouvier
Browse files

Rename Category.title to Category.label;

parent c0997450
......@@ -236,7 +236,7 @@ Budget.propTypes = {
// The list of budgets.
budgets: PropTypes.array,
// A map of categories with the id as key and the title as value.
// A map of categories with the id as key and the label as value.
categoriesNamesMap: PropTypes.object,
// The list of current operations.
......@@ -258,7 +258,7 @@ const categoriesNamesSelector = createSelector(
cats => {
let categoriesNamesMap = new Map();
for (let cat of cats) {
categoriesNamesMap.set(cat.id, cat.title);
categoriesNamesMap.set(cat.id, cat.label);
}
return categoriesNamesMap;
......
......@@ -173,7 +173,7 @@ class BudgetListItem extends React.Component {
<span className="color-block-small" style={{ backgroundColor: category.color }}>
&nbsp;
</span>{' '}
{category.title}
{category.label}
</td>
<td className="category-amount">
<div className="stacked-progress-bar">
......
......@@ -12,11 +12,11 @@ const ConfirmDeleteModal = connect(
state => {
let categoryId = get.modal(state).state;
let category = get.categoryById(state, categoryId);
let title = category ? category.title : null;
let label = category ? category.label : null;
let numOperations = get.operationIdsByCategoryId(state, categoryId).length;
return {
categoryId,
title,
label,
numOperations,
categories: get.categoriesButNone(state)
};
......@@ -50,7 +50,7 @@ const ConfirmDeleteModal = connect(
.filter(cat => cat.id !== this.props.categoryId)
.map(cat => (
<option key={cat.id} value={cat.id}>
{cat.title}
{cat.label}
</option>
));
......@@ -88,7 +88,7 @@ const ConfirmDeleteModal = connect(
const body = (
<React.Fragment>
{content}
<p>{$t('client.category.erase', { title: this.props.title })}</p>
<p>{$t('client.category.erase', { label: this.props.label })}</p>
</React.Fragment>
);
......
......@@ -36,7 +36,7 @@ const DeleteUnusedCategoriesModal = connect(
};
}
)(props => {
let listItems = props.categories.map(c => <li key={c.id}>{c.title}</li>);
let listItems = props.categories.map(c => <li key={c.id}>{c.label}</li>);
const body = (
<React.Fragment>
......
......@@ -29,7 +29,7 @@ class CategoryList extends React.Component {
function() {
// then
if (this.state.showForm) {
this.refNewCategory.current.selectTitle();
this.refNewCategory.current.selectLabel();
}
}
);
......
......@@ -52,7 +52,7 @@ class CategoryListItem extends React.Component {
};
}
refTitle = React.createRef();
refLabel = React.createRef();
isEditing() {
return typeof this.props.cat.id !== 'undefined';
......@@ -66,7 +66,7 @@ class CategoryListItem extends React.Component {
return this.handleSave(e);
} else if (e.key === 'Escape') {
if (this.isEditing()) {
e.target.value = this.props.cat.title;
e.target.value = this.props.cat.label;
} else {
this.props.onCancelCreation(e);
}
......@@ -91,24 +91,24 @@ class CategoryListItem extends React.Component {
// This might be an empty object when we're creating a new category.
let editedCategory = this.props.cat;
let title = this.refTitle.current.value.trim();
let label = this.refLabel.current.value.trim();
let color = this.state.color;
if (
!title ||
!label ||
!color ||
(color === editedCategory.color && title === editedCategory.title)
(color === editedCategory.color && label === editedCategory.label)
) {
if (this.isCreating()) {
this.props.onCancelCreation(e);
} else if (!this.title) {
this.refTitle.current.value = editedCategory.title;
} else if (!this.label) {
this.refLabel.current.value = editedCategory.label;
}
return false;
}
let newFields = {
title,
label,
color
};
......@@ -116,7 +116,7 @@ class CategoryListItem extends React.Component {
this.props.updateCategory(editedCategory, newFields);
} else {
this.props.createCategory(newFields);
this.refTitle.current.value = '';
this.refLabel.current.value = '';
this.props.onCancelCreation(e);
}
......@@ -131,8 +131,8 @@ class CategoryListItem extends React.Component {
}
};
selectTitle() {
this.refTitle.current.select();
selectLabel() {
this.refLabel.current.select();
}
render() {
......@@ -163,10 +163,10 @@ class CategoryListItem extends React.Component {
type="text"
className="form-element-block"
placeholder={$t('client.category.label')}
defaultValue={editedCategory.title}
defaultValue={editedCategory.label}
onKeyUp={this.handleKeyUp}
onBlur={this.handleBlur}
ref={this.refTitle}
ref={this.refLabel}
/>
</td>
<td>{deleteButton}</td>
......
......@@ -117,15 +117,15 @@ class BarChart extends C3Component {
for (let op of this.props.operations) {
let c = this.props.getCategoryById(op.categoryId);
map.set(c.title, map.get(c.title) || {});
let categoryDates = map.get(c.title);
map.set(c.label, map.get(c.label) || {});
let categoryDates = map.get(c.label);
let dk = this.datekey(op);
let amount = this.props.invertSign ? -op.amount : op.amount;
(categoryDates[dk] = categoryDates[dk] || []).push(amount);
dateset.set(dk, +op.budgetDate);
colorMap[c.title] = colorMap[c.title] || c.color;
colorMap[c.label] = colorMap[c.label] || c.color;
}
// Sort date in ascending order: push all pairs of (datekey, date) in
......@@ -259,8 +259,8 @@ class PieChart extends C3Component {
for (let [catId, values] of catMap) {
let c = this.props.getCategoryById(catId);
series.push([c.title].concat(values));
colorMap[c.title] = c.color;
series.push([c.label].concat(values));
colorMap[c.label] = c.color;
}
this.container = c3.generate({
......
......@@ -58,7 +58,7 @@ const OperationLine = props => {
<div className="duplicate-details">
<p>
<span className="label">{$t('client.similarity.category')}</span>
{props.categoryTitle}
{props.categoryLabel}
</p>
<p>
<span className="label">{$t('client.similarity.type')}</span>
......@@ -82,7 +82,7 @@ const DuplicateItem = props => {
rawLabel={toKeep.raw}
date={toKeep.date}
dateImport={toKeep.dateImport}
categoryTitle={toKeepCategory.title}
categoryLabel={toKeepCategory.label}
type={toKeep.type}
deletionInfo={$t('client.similarity.will_be_kept')}
/>
......@@ -93,7 +93,7 @@ const DuplicateItem = props => {
rawLabel={toRemove.raw}
date={toRemove.date}
dateImport={toRemove.dateImport}
categoryTitle={toRemoveCategory.title}
categoryLabel={toRemoveCategory.label}
type={toRemove.type}
deletionInfo={$t('client.similarity.will_be_removed')}
/>
......
......@@ -41,12 +41,12 @@ const optionsSelector = createSelector(
return [
{
value: noneCategory.id,
label: noneCategory.title
label: noneCategory.label
}
].concat(
cats
.filter(cat => cat.id !== NONE_CATEGORY_ID)
.map(cat => ({ value: cat.id, label: cat.title }))
.map(cat => ({ value: cat.id, label: cat.label }))
);
}
);
......@@ -62,7 +62,7 @@ const Export = connect(
async onCreateCategory(label) {
try {
let category = await actions.createCategory(dispatch, {
title: label,
label,
color: generateColor()
});
props.onChange(category.id);
......
......@@ -90,9 +90,9 @@ const SearchCategorySelect = connect(
let options = [
{
value: noneCategory.id,
label: noneCategory.title
label: noneCategory.label
}
].concat(categories.map(cat => ({ value: cat.id, label: cat.title })));
].concat(categories.map(cat => ({ value: cat.id, label: cat.label })));
return (
<FuzzyOrNativeSelect
......
......@@ -132,11 +132,13 @@ export class Type {
export class Category {
constructor(arg) {
this.title = assertHas(arg, 'title') && arg.title;
this.color = (maybeHas(arg, 'color') && arg.color) || stringToColor(this.title);
this.label = assertHas(arg, 'label') && arg.label;
this.color = (maybeHas(arg, 'color') && arg.color) || stringToColor(this.label);
this.id = assertHas(arg, 'id') && arg.id;
// Optional
this.parentId = arg.parentId;
}
get title() {
alert(`trying to get deprecated title property from ${new Error().stack}`);
}
}
......
......@@ -309,7 +309,7 @@ export function createAccess(bank, login, password, customFields, customLabel) {
}
export function addCategory(category) {
let error = checkExactFields(category, ['title', 'color']);
let error = checkExactFields(category, ['label', 'color']);
if (error) {
alert(`Developer error when adding a category: ${error}`);
return;
......@@ -325,7 +325,7 @@ export function addCategory(category) {
}
export function updateCategory(id, category) {
let error = checkAllowedFields(category, ['title', 'color']);
let error = checkAllowedFields(category, ['label', 'color']);
if (error) {
alert(`Developer error when updating a category: ${error}`);
return;
......
......@@ -21,7 +21,7 @@ import { CREATE_CATEGORY, UPDATE_CATEGORY, DELETE_CATEGORY } from './actions';
// Helpers
function sortCategories(items) {
let copy = items.slice();
copy.sort((a, b) => localeComparator(a.title, b.title));
copy.sort((a, b) => localeComparator(a.label, b.label));
return copy;
}
......@@ -56,7 +56,7 @@ const fail = {},
fillOutcomeHandlers(basic, fail, success);
export function create(category) {
assertHas(category, 'title', 'CreateCategory expects an object that has a title field');
assertHas(category, 'label', 'CreateCategory expects an object that has a label field');
assertHas(category, 'color', 'CreateCategory expects an object that has a color field');
return dispatch => {
......@@ -77,14 +77,14 @@ export function createDefault() {
return (dispatch, getState) => {
const defaultCategories = DefaultCategories.map(category =>
Object.assign({}, category, {
title: $t(category.title) // Translate category title
label: $t(category.label) // Translate category label.
})
);
const stateCategories = new Set(getState().categories.items.map(c => c.title));
const stateCategories = new Set(getState().categories.items.map(c => c.label));
for (let category of defaultCategories) {
// Do not re-add an already existing category
if (!stateCategories.has(category.title)) {
if (!stateCategories.has(category.label)) {
dispatch(create(category));
}
}
......@@ -93,7 +93,7 @@ export function createDefault() {
export function update(former, category) {
assert(former instanceof Category, 'UpdateCategory first arg must be a Category');
assertHas(category, 'title', 'UpdateCategory second arg must have a title field');
assertHas(category, 'label', 'UpdateCategory second arg must have a label field');
assertHas(category, 'color', 'UpdateCategory second arg must have a color field');
if (typeof category.threshold !== 'undefined') {
......@@ -216,7 +216,7 @@ export const reducer = createReducerFromMap(categoryState, reducers);
export function initialState(categories) {
const NONE_CATEGORY = new Category({
id: NONE_CATEGORY_ID,
title: $t('client.category.none'),
label: $t('client.category.none'),
color: '#000000'
});
......
......@@ -273,16 +273,16 @@ export async function import_(req, res) {
log.info('Import categories...');
let existingCategories = await Categories.all(userId);
let existingCategoriesMap = new Map();
for (let c of existingCategories) {
existingCategoriesMap.set(c.title, c);
for (let category of existingCategories) {
existingCategoriesMap.set(category.label, category);
}
let categoryMap = {};
for (let category of world.categories) {
let catId = category.id;
delete category.id;
if (existingCategoriesMap.has(category.title)) {
let existing = existingCategoriesMap.get(category.title);
if (existingCategoriesMap.has(category.label)) {
let existing = existingCategoriesMap.get(category.label);
categoryMap[catId] = existing.id;
} else {
let created = await Categories.create(userId, category);
......
......@@ -28,7 +28,7 @@ export async function create(req, res) {
try {
let { id: userId } = req.user;
let error = checkExactFields(req.body, ['title', 'color']);
let error = checkExactFields(req.body, ['label', 'color']);
if (error) {
throw new KError(`when creating a category: ${error}`, 400);
}
......@@ -44,7 +44,7 @@ export async function update(req, res) {
try {
let { id: userId } = req.user;
let error = checkAllowedFields(req.body, ['title', 'color']);
let error = checkAllowedFields(req.body, ['label', 'color']);
if (error) {
throw new KError(`when updating a category: ${error}`, 400);
}
......
......@@ -6,7 +6,7 @@ let Category = cozydb.getModel('bankcategory', {
parentId: String,
// Label of the category.
title: String,
label: String,
// Hexadecimal RGB format.
color: String,
......@@ -19,7 +19,10 @@ let Category = cozydb.getModel('bankcategory', {
threshold: {
type: Number,
default: 0
}
},
// Label of the category; replaced by label.
title: String
});
Category = promisifyModel(Category);
......
......@@ -616,7 +616,7 @@ let migrations = [
if (!budget || budget.length === 0) {
log.info(
`Migrating budget for category ${
category.title
category.label
} with period ${month}/${year}`
);
await Budgets.create(userId, {
......@@ -821,7 +821,10 @@ let migrations = [
log.error('Error while deleting enabled flag for accesses:', e.toString());
return false;
}
}
},
// m24: rename Categories.title to Categories.label.
makeRenameField(Categories, 'title', 'label')
];
export const testing = { migrations };
......
[
{
"title": "client.defaultcategories.children",
"label": "client.defaultcategories.children",
"color": "#A295D6"
},
{
"title": "client.defaultcategories.clothing",
"label": "client.defaultcategories.clothing",
"color": "#8E44AD"
},
{
"title": "client.defaultcategories.groceries",
"label": "client.defaultcategories.groceries",
"color": "#DB9320"
},
{
"title": "client.defaultcategories.health",
"label": "client.defaultcategories.health",
"color": "#D10069"
},
{
"title": "client.defaultcategories.holidays",
"label": "client.defaultcategories.holidays",
"color": "#004E00"
},
{
"title": "client.defaultcategories.housing",
"label": "client.defaultcategories.housing",
"color": "#AD8D43"
},
{
"title": "client.defaultcategories.income",
"label": "client.defaultcategories.income",
"color": "#428BCA"
},
{
"title": "client.defaultcategories.internetTVphone",
"label": "client.defaultcategories.internetTVphone",
"color": "#D1D100"
},
{
"title": "client.defaultcategories.others",
"label": "client.defaultcategories.others",
"color": ""
},
{
"title": "client.defaultcategories.parties",
"label": "client.defaultcategories.parties",
"color": "#FFF600"
},
{
"title": "client.defaultcategories.pets",
"label": "client.defaultcategories.pets",
"color": "#FF4CAB"
},
{
"title": "client.defaultcategories.savings",
"label": "client.defaultcategories.savings",
"color": "#69D100"
},
{
"title": "client.defaultcategories.sportsfunculture",
"label": "client.defaultcategories.sportsfunculture",
"color": "#A8D695"
},
{
"title": "client.defaultcategories.taxes",
"label": "client.defaultcategories.taxes",
"color": "#D9534F"
},
{
"title": "client.defaultcategories.tobacco",
"label": "client.defaultcategories.tobacco",
"color": "#777777"
},
{
"title": "client.defaultcategories.transports",
"label": "client.defaultcategories.transports",
"color": "#44AD8E"
},
{
"title": "client.defaultcategories.work",
"label": "client.defaultcategories.work",
"color": "#7F8C8D"
}
]
......@@ -47,7 +47,7 @@
"column_category_name": "Name",
"column_action": "Action",
"dont_replace": "Don't replace",
"erase": "This will erase the \"%{title}\" category. Do you confirm?",
"erase": "This will erase the \"%{label}\" category. Do you confirm?",
"no_transactions_attached": "There are no transactions attached to this category.",
"attached_transactions": "There is %{smart_count} transaction attached. It will not be deleted. |||| There are %{smart_count} transactions attached. They will not be deleted.",
"replace_with_info": "You can attach them to an existing category with the dropdown below (by default, these transactions will not have a category set anymore).",
......
......@@ -47,7 +47,7 @@
"column_category_name": "Nom",
"column_action": "Action",
"dont_replace": "Ne pas remplacer",
"erase": "Cela va supprimer la catégorie '%{title}'. Êtes-vous sûr⋅e de vouloir supprimer cette catégorie ?",
"erase": "Cela va supprimer la catégorie '%{label}'. Êtes-vous sûr⋅e de vouloir supprimer cette catégorie ?",
"no_transactions_attached": "Aucune opération n'est associée à cette catégorie.",
"attached_transactions": "%{smart_count} opération est associée à cette catégorie. Elle ne sera pas supprimée. |||| %{smart_count} opérations sont associées à cette catégorie. Elles ne seront pas supprimées.",
"replace_with_info": "Vous pouvez les réaffecter à une catégorie existante à l'aide du menu déroulant ci-dessous (sinon, ces opérations n'auront plus de catégorie).",
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment