tududi/backend/models/project.js
Chris e80847b01f
Fix project name overflow and add 6-word validation limit (#972)
* Fix project name overflow and add validation

This commit addresses issue #971 by implementing both UI fixes and
validation to prevent excessively long project names.

Changes:
1. Add word-break and line-clamp to ProjectBanner.tsx to handle
   overflow gracefully with line-clamp-3 for names
2. Add frontend validation in ProjectModal.tsx limiting names to
   6 words maximum
3. Add backend validation in project.js model with custom wordCount
   validator
4. Show user-friendly error messages when validation fails

This ensures project names remain concise and UI-friendly while
preventing the extreme overflow cases that were possible before.

Fixes #971

* Add overflow-hidden to make line-clamp work properly

The line-clamp utility requires explicit overflow-hidden to function
correctly. Without it, the text continues to display in full rather
than being truncated with ellipsis.

* Fix line-clamp using inline CSS styles

Tailwind's line-clamp utilities weren't working, so switched to using
inline styles with the standard CSS approach:
- display: -webkit-box
- -webkit-line-clamp: 3
- -webkit-box-orient: vertical

This ensures the text truncation works reliably across browsers.

* Use Tailwind line-clamp utilities (already defined in CSS)

The project already has line-clamp-1/2/3 utilities properly defined
in tailwind.css with all the necessary webkit properties. Simplified
the component to use these existing utilities instead of inline styles.

* Add dedicated CSS classes with !important for line-clamp

Created custom project-name-clamp and project-desc-clamp classes
with !important flags to ensure they override any conflicting styles.
This should finally fix the text truncation issue.

* Use component-scoped styles for line-clamp

Adding inline style tag in the component to ensure the line-clamp
CSS is definitely loaded and applied. This bypasses any potential
issues with external CSS compilation or loading order.

* Change project name line-clamp from 3 to 2 lines

Limiting project name display to 2 lines with ellipsis for better
visual density and cleaner appearance.

* Increase line-height for project name in banner

Added line-height: 1.3 to project name for better readability
and visual spacing between lines.
2026-03-24 17:36:24 +02:00

118 lines
3.4 KiB
JavaScript

const { DataTypes } = require('sequelize');
const { uid } = require('../utils/uid');
module.exports = (sequelize) => {
const Project = sequelize.define(
'Project',
{
id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
uid: {
type: DataTypes.STRING,
allowNull: false,
unique: true,
defaultValue: () => uid(),
},
name: {
type: DataTypes.STRING,
allowNull: false,
validate: {
notEmpty: {
msg: 'Project name is required',
},
wordCount(value) {
const MAX_WORDS = 6;
const wordCount = value
.trim()
.split(/\s+/)
.filter((word) => word.length > 0).length;
if (wordCount > MAX_WORDS) {
throw new Error(
`Project name must be ${MAX_WORDS} words or less`
);
}
},
},
},
description: {
type: DataTypes.TEXT,
allowNull: true,
},
pin_to_sidebar: {
type: DataTypes.BOOLEAN,
allowNull: false,
defaultValue: false,
},
priority: {
type: DataTypes.INTEGER,
allowNull: true,
validate: {
min: 0,
max: 2,
},
},
due_date_at: {
type: DataTypes.DATE,
allowNull: true,
},
user_id: {
type: DataTypes.INTEGER,
allowNull: false,
references: {
model: 'users',
key: 'id',
},
},
area_id: {
type: DataTypes.INTEGER,
allowNull: true,
references: {
model: 'areas',
key: 'id',
},
},
image_url: {
type: DataTypes.TEXT,
allowNull: true,
},
task_show_completed: {
type: DataTypes.BOOLEAN,
allowNull: true,
defaultValue: false,
},
task_sort_order: {
type: DataTypes.STRING,
allowNull: true,
defaultValue: 'created_at:desc',
},
status: {
type: DataTypes.ENUM(
'not_started',
'in_progress',
'done',
'waiting',
'cancelled',
'planned'
),
allowNull: false,
defaultValue: 'not_started',
},
},
{
tableName: 'projects',
indexes: [
{
fields: ['user_id'],
},
{
fields: ['area_id'],
},
],
}
);
return Project;
};