Skip to content

Commit e1c0eaf

Browse files
mennokonijnMenno Konijnmartinboulais
authored
[O2B-907] Add color to tags (#1363)
* added color to tags and display them * feature/)2B-907: added color to back and frontend * fixed linter issues * implemented fixes * Display tag as colored badge * Fix runs export * Save # in color column * Fix linter and test, and add possibility to remove color * Code review --------- Co-authored-by: Menno Konijn <menno.konijn@usmedia.nl> Co-authored-by: Martin Boulais <31805063+martinboulais@users.noreply.github.com>
1 parent ec225e3 commit e1c0eaf

34 files changed

Lines changed: 326 additions & 47 deletions

lib/database/adapters/TagAdapter.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ class TagAdapter {
2929
* @param {SequelizeTag} databaseObject Object to convert.
3030
* @returns {Tag} Converted entity object.
3131
*/
32-
toEntity({ id, text, description, email, mattermost, last_edited_name, archived, archivedAt, updatedAt }) {
32+
toEntity({ id, text, description, email, mattermost, last_edited_name, archived, color, archivedAt, updatedAt }) {
3333
return {
3434
id,
3535
text,
@@ -38,6 +38,7 @@ class TagAdapter {
3838
email,
3939
mattermost,
4040
archived,
41+
color,
4142
archivedAt: archivedAt ? new Date(archivedAt).getTime() : null,
4243
updatedAt: new Date(updatedAt).getTime(),
4344
};
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
'use strict';
2+
3+
/** @type {import('sequelize-cli').Migration} */
4+
module.exports = {
5+
up: async (queryInterface, Sequelize) => queryInterface.sequelize.transaction(async () => {
6+
await queryInterface.addColumn('tags', 'color', {
7+
allowNull: true,
8+
type: Sequelize.STRING(7),
9+
default: null,
10+
validate: {
11+
len: 7,
12+
},
13+
});
14+
}),
15+
16+
down: async (queryInterface) => queryInterface.sequelize.transaction(async () => {
17+
await queryInterface.removeColumn('tags', 'color');
18+
}),
19+
};

lib/database/models/tag.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,11 @@ module.exports = (sequelize) => {
4040
allowNull: true,
4141
defaultValue: null,
4242
},
43+
color: {
44+
type: Sequelize.STRING,
45+
allowNull: true,
46+
defaultValue: null,
47+
},
4348
archived: {
4449
type: Sequelize.VIRTUAL,
4550
allowNull: true,

lib/database/models/typedefs/SequelizeTag.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,5 +23,6 @@
2323
* @property {string|null} archivedAt
2424
* @property {string} createdAt
2525
* @property {string} updatedAt
26+
* @property {string|null} color
2627
* @property {Run[]|null} runs
2728
*/

lib/domain/dtos/CreateTagDto.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
*/
1313

1414
const Joi = require('joi');
15+
const { ColorDto } = require('./common/ColorDto.js');
1516

1617
const BodyDto = Joi.object({
1718
text: Joi.string()
@@ -32,7 +33,7 @@ const BodyDto = Joi.object({
3233
.optional()
3334
.allow('', null)
3435
.email({ multiple: true }),
35-
36+
color: ColorDto.optional(),
3637
});
3738

3839
const QueryDto = Joi.object({

lib/domain/dtos/UpdateTagDto.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
const Joi = require('joi');
1515
const EntityIdDto = require('./EntityIdDto');
16+
const { ColorDto } = require('./common/ColorDto.js');
1617

1718
const BodyDto = Joi.object({
1819
description: Joi.string()
@@ -28,6 +29,7 @@ const BodyDto = Joi.object({
2829
.allow('', null)
2930
.email({ multiple: true }),
3031
archivedAt: Joi.date().allow(null).optional(),
32+
color: ColorDto.optional(),
3133
});
3234
const QueryDto = Joi.object({
3335
token: Joi.string(),

lib/domain/dtos/common/ColorDto.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/**
2+
* @license
3+
* Copyright CERN and copyright holders of ALICE O2. This software is
4+
* distributed under the terms of the GNU General Public License v3 (GPL
5+
* Version 3), copied verbatim in the file "COPYING".
6+
*
7+
* See http://alice-o2.web.cern.ch/license for full licensing information.
8+
*
9+
* In applying this license CERN does not waive the privileges and immunities
10+
* granted to it by virtue of its status as an Intergovernmental Organization
11+
* or submit itself to any jurisdiction.
12+
*/
13+
14+
const Joi = require('joi');
15+
16+
exports.ColorDto = Joi.string()
17+
.trim()
18+
.allow(null)
19+
.regex(/^#[0-9A-Fa-f]{6}$/);

lib/domain/entities/Tag.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,5 @@
2323
* @property {number|null} archivedAt
2424
* @property {number} createdAt
2525
* @property {number} updatedAt
26+
* @property {string|null} color
2627
*/

lib/public/components/Detail/detailsList.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ export const detailsList = (fields, subject, configuration) => {
4747
const { selector, emptyString = '-', attributes = {} } = configuration || {};
4848

4949
return h(
50-
`#${selector}`,
50+
`#${selector}.flex-column.g1`,
5151
attributes,
5252
Object.entries(fields).map(([key, { name, format, visible }]) => {
5353
const fieldValue = subject[key];

lib/public/components/Log/log.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import { logReplyButton } from './logReplyButton.js';
2222
import { logText } from './logText.js';
2323
import { primaryButton } from '../common/primaryButton.js';
2424
import { logDetailsButton } from './logDetailsButton.js';
25+
import { tagBadge } from '../tag/tagBadge.js';
2526

2627
/**
2728
* Provides formatting for each log field to display that field on the webpage
@@ -39,7 +40,7 @@ const logFields = (authenticationToken) => ({
3940
},
4041
tags: {
4142
name: 'Tags',
42-
format: (tags) => h('div.flex-row.flex-wrap.g1', tags.map(({ text }) => h('div.badge.white.bg-gray-light.black', text))),
43+
format: (tags) => h('div.flex-row.flex-wrap.g1', tags.map(tagBadge)),
4344
},
4445
runs: {
4546
name: 'Runs',

0 commit comments

Comments
 (0)