Skip to content

Commit dfbdd1b

Browse files
committed
Added some kudos emoji test data and implemented basic emoji support on public kudos
1 parent 6888c15 commit dfbdd1b

File tree

4 files changed

+105
-17
lines changed

4 files changed

+105
-17
lines changed

server/src/main/resources/db/dev/R__Load_testing_data.sql

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1776,7 +1776,7 @@ VALUES
17761776
INSERT INTO kudos
17771777
(id, message, senderid, teamid, datecreated, dateapproved, publiclyvisible)
17781778
VALUES
1779-
('39dfd281-d0af-4016-848b-8156dfef2b93', PGP_SYM_ENCRYPT('Kudos to Revolver Ocelot!', '${aeskey}'), 'e4b2fe52-1915-4544-83c5-21b8f871f6db', null, '2023-12-01', '2023-12-02', true);
1779+
('39dfd281-d0af-4016-848b-8156dfef2b93', PGP_SYM_ENCRYPT('Kudos to Revolver Ocelot! Test :bowtie::smile::simple_smile::laughing::blush::smiley::relaxed::smirk::heart_eyes::kissing_heart::kissing_closed_eyes::flushed::relieved::laughing::grin::wink::stuck_out_tongue_winking_eye::stuck_out_tongue_closed_eyes::grinning::kissing::kissing_smiling_eyes::stuck_out_tongue::sleeping::worried::frowning::anguished::open_mouth::grimacing::confused::hushed::expressionless::unamused::sweat_smile::sweat::disappointed_relieved::weary::pensive::disappointed::confounded::fearful::cold_sweat::persevere::cry::sob::joy::astonished::scream::tired_face::angry::rage::triumph::sleepy::yum::mask::sunglasses::dizzy_face::imp::smiling_imp::neutral_face::no_mouth::innocent::alien::yellow_heart::blue_heart::purple_heart::heart::green_heart::broken_heart::heartbeat::heartpulse::two_hearts::revolving_hearts::cupid::sparkling_heart::sparkles::star::star2::dizzy::boom::boom::anger::exclamation::question::grey_exclamation::grey_question::zzz::dash::sweat_drops::notes::musical_note::fire::hankey::hankey::hankey::+1::+1::-1::-1::ok_hand::facepunch::facepunch::fist::v::wave::hand::hand::open_hands::point_up::point_down::point_left::point_right::raised_hands::pray::point_up_2::clap::muscle::runner::runner::man_and_woman_holding_hands::family::two_men_holding_hands::two_women_holding_hands::dancer::dancers::ok_woman::no_good::information_desk_person::raising_hand::bride_with_veil::person_with_pouting_face::person_frowning::bow::couplekiss::couple_with_heart::massage::haircut::nail_care::boy::girl::woman::man::baby::older_woman::older_man::person_with_blond_hair::man_with_gua_pi_mao::man_with_turban::construction_worker::cop::angel::princess::smiley_cat::smile_cat::heart_eyes_cat::kissing_cat::smirk_cat::scream_cat::crying_cat_face::joy_cat::pouting_cat::japanese_ogre::japanese_goblin::see_no_evil::hear_no_evil::speak_no_evil::guardsman::skull::feet::lips::kiss::droplet::ear::eyes::nose::tongue::love_letter::bust_in_silhouette::busts_in_silhouette::speech_balloon::thought_balloon::trollface::sunny::umbrella::cloud::snowflake::snowman::zap::cyclone::foggy::ocean::cat::dog::mouse::hamster::rabbit::wolf::frog::tiger::koala::bear::pig::pig_nose::cow::boar::monkey_face::monkey::horse::racehorse::camel::sheep::elephant::panda_face::snake::bird::baby_chick::hatched_chick::hatching_chick::chicken::penguin::turtle::bug::bee::ant::beetle::snail::octopus::tropical_fish::fish::whale::whale2::dolphin::cow2::ram::rat::water_buffalo::tiger2::rabbit2::dragon::goat::rooster::dog2::pig2::mouse2::ox::dragon_face::blowfish::crocodile::dromedary_camel::leopard::cat2::poodle::feet::bouquet::cherry_blossom::tulip::four_leaf_clover::rose::sunflower::hibiscus::maple_leaf::leaves::fallen_leaf::herb::mushroom::cactus::palm_tree::evergreen_tree::deciduous_tree::chestnut::seedling::blossom::ear_of_rice::shell::globe_with_meridians::sun_with_face::full_moon_with_face::new_moon_with_face::new_moon::waxing_crescent_moon::first_quarter_moon::moon::full_moon::waning_gibbous_moon::last_quarter_moon::waning_crescent_moon::last_quarter_moon_with_face::first_quarter_moon_with_face::crescent_moon::earth_africa::earth_americas::earth_asia::volcano::milky_way::partly_sunny::squirrel::bamboo::gift_heart::dolls::school_satchel::mortar_board::flags::fireworks::sparkler::wind_chime::rice_scene::jack_o_lantern::ghost::santa::christmas_tree::gift::bell::no_bell::tanabata_tree::tada::confetti_ball::balloon::crystal_ball::cd::dvd::floppy_disk::camera::video_camera::movie_camera::computer::tv::iphone::phone::phone::telephone_receiver::pager::fax::minidisc::vhs::sound::speaker::mute::loudspeaker::mega::hourglass::hourglass_flowing_sand::alarm_clock::watch::radio::satellite::loop::mag::mag_right::unlock::lock::lock_with_ink_pen::closed_lock_with_key::key::bulb::flashlight::high_brightness::low_brightness::electric_plug::battery::calling::email::mailbox::postbox::bath::bathtub::shower::toilet::wrench::nut_and_bolt::hammer::seat::moneybag::yen::dollar::pound::euro::credit_card::money_with_wings::e-mail::inbox_tray::outbox_tray::email::incoming_envelope::postal_horn::mailbox_closed::mailbox_with_mail::mailbox_with_no_mail::package::door::smoking::bomb::gun::hocho::pill::syringe::page_facing_up::page_with_curl::bookmark_tabs::bar_chart::chart_with_upwards_trend::chart_with_downwards_trend::scroll::clipboard::calendar::date::card_index::file_folder::open_file_folder::scissors::pushpin::paperclip::black_nib::pencil2::straight_ruler::triangular_ruler::closed_book::green_book::blue_book::orange_book::notebook::notebook_with_decorative_cover::ledger::books::bookmark::name_badge::microscope::telescope::newspaper::football::basketball::soccer::baseball::tennis::8ball::rugby_football::bowling::golf::mountain_bicyclist::bicyclist::horse_racing::snowboarder::swimmer::surfer::ski::spades::hearts::clubs::diamonds::gem::ring::trophy::musical_score::musical_keyboard::violin::space_invader::video_game::black_joker::flower_playing_cards::game_die::dart::mahjong::clapper::memo::memo::book::art::microphone::headphones::trumpet::saxophone::guitar::mans_shoe::sandal::high_heel::lipstick::boot::shirt::shirt::necktie::womans_clothes::dress::running_shirt_with_sash::jeans::kimono::bikini::ribbon::tophat::crown::womans_hat::mans_shoe::closed_umbrella::briefcase::handbag::pouch::purse::eyeglasses::fishing_pole_and_fish::coffee::tea::sake::baby_bottle::beer::beers::cocktail::tropical_drink::wine_glass::fork_and_knife::pizza::hamburger::fries::poultry_leg::meat_on_bone::spaghetti::curry::fried_shrimp::bento::sushi::fish_cake::rice_ball::rice_cracker::rice::ramen::stew::oden::dango::egg::bread::doughnut::custard::icecream::ice_cream::shaved_ice::birthday::cake::cookie::chocolate_bar::candy::lollipop::honey_pot::apple::green_apple::tangerine::lemon::cherries::grapes::watermelon::strawberry::peach::melon::banana::pear::pineapple::sweet_potato::eggplant::tomato::corn::house::house_with_garden::school::office::post_office::hospital::bank::convenience_store::love_hotel::hotel::wedding::church::department_store::european_post_office::city_sunrise::city_sunset::japanese_castle::european_castle::tent::factory::tokyo_tower::japan::mount_fuji::sunrise_over_mountains::sunrise::stars::statue_of_liberty::bridge_at_night::carousel_horse::rainbow::ferris_wheel::fountain::roller_coaster::ship::speedboat::boat::boat::rowboat::anchor::rocket::airplane::helicopter::steam_locomotive::tram::mountain_railway::bike::aerial_tramway::suspension_railway::mountain_cableway::tractor::blue_car::oncoming_automobile::car::car::taxi::oncoming_taxi::articulated_lorry::bus::oncoming_bus::rotating_light::police_car::oncoming_police_car::fire_engine::ambulance::minibus::truck::train::station::train2::bullettrain_front::bullettrain_side::light_rail::monorail::railway_car::trolleybus::ticket::fuelpump::vertical_traffic_light::traffic_light::warning::construction::beginner::atm::slot_machine::busstop::barber::hotsprings::checkered_flag::crossed_flags::izakaya_lantern::moyai::circus_tent::performing_arts::round_pushpin::triangular_flag_on_post::jp::kr::cn::us::fr::es::it::ru::gb::gb::de::one::two::three::four::five::six::seven::eight::nine::keycap_ten::1234::zero::hash::symbols::arrow_backward::arrow_down::arrow_forward::arrow_left::capital_abcd::abcd::abc::arrow_lower_left::arrow_lower_right::arrow_right::arrow_up::arrow_upper_left::arrow_upper_right::arrow_double_down::arrow_double_up::arrow_down_small::arrow_heading_down::arrow_heading_up::leftwards_arrow_with_hook::arrow_right_hook::left_right_arrow::arrow_up_down::arrow_up_small::arrows_clockwise::arrows_counterclockwise::rewind::fast_forward::information_source::ok::twisted_rightwards_arrows::repeat::repeat_one::new::top::up::cool::free::ng::cinema::koko::signal_strength::u5272::u5408::u55b6::u6307::u6708::u6709::u6e80::u7121::u7533::u7a7a::u7981::sa::restroom::mens::womens::baby_symbol::no_smoking::parking::wheelchair::metro::baggage_claim::accept::wc::potable_water::put_litter_in_its_place::secret::congratulations::m::passport_control::left_luggage::customs::ideograph_advantage::cl::sos::id::no_entry_sign::underage::no_mobile_phones::do_not_litter::non-potable_water::no_bicycles::no_pedestrians::children_crossing::no_entry::eight_spoked_asterisk::sparkle::eight_pointed_black_star::heart_decoration::vs::vibration_mode::mobile_phone_off::chart::currency_exchange::aries::taurus::gemini::cancer::leo::virgo::libra::scorpius::sagittarius::capricorn::aquarius::pisces::ophiuchus::six_pointed_star::negative_squared_cross_mark::a::b::ab::o2::diamond_shape_with_a_dot_inside::recycle::end::back::on::soon::clock1::clock130::clock10::clock1030::clock11::clock1130::clock12::clock1230::clock2::clock230::clock3::clock330::clock4::clock430::clock5::clock530::clock6::clock630::clock7::clock730::clock8::clock830::clock9::clock930::heavy_dollar_sign::copyright::registered::tm::x::exclamation::bangbang::interrobang::o::heavy_multiplication_x::heavy_plus_sign::heavy_minus_sign::heavy_division_sign::white_flower::100::heavy_check_mark::ballot_box_with_check::radio_button::link::curly_loop::wavy_dash::part_alternation_mark::trident::black_small_square::white_small_square::black_medium_small_square::white_medium_small_square::black_medium_square::white_medium_square::black_large_square::white_large_square::white_check_mark::black_square_button::white_square_button::black_circle::white_circle::red_circle::large_blue_circle::large_blue_diamond::large_orange_diamond::small_blue_diamond::small_orange_diamond::small_red_triangle::small_red_triangle_down::shipit: <https://zombo.com/|Welcome...>', '${aeskey}'), 'e4b2fe52-1915-4544-83c5-21b8f871f6db', null, '2025-04-01', '2025-04-02', true);
17801780

17811781
INSERT INTO kudos_recipient
17821782
(id, kudosid, memberid)

web-ui/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
"date-fns": "^2.24.0",
2626
"dayjs": "^1.11.11",
2727
"dompurify": "^3.2.4",
28+
"emoji-picker-react": "^4.12.2",
2829
"fuse.js": "^6.4.6",
2930
"html-react-parser": "^5.1.12",
3031
"isomorphic-fetch": "^3.0.0",

web-ui/src/components/kudos/PublicKudosCard.jsx

Lines changed: 91 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,14 @@
1-
import React, { useCallback, useContext, useState } from 'react';
1+
import React, { useCallback, useContext } from 'react';
22
import PropTypes from 'prop-types';
33
import {
44
Card,
55
CardHeader,
66
CardContent,
7-
Divider,
87
Typography,
98
Avatar,
109
Chip,
11-
Button,
1210
AvatarGroup,
1311
Tooltip,
14-
Dialog,
15-
DialogTitle,
16-
DialogContent,
17-
DialogContentText,
18-
DialogActions,
19-
TextField,
2012
Link
2113
} from '@mui/material';
2214
import {
@@ -26,14 +18,11 @@ import {
2618
import { AppContext } from '../../context/AppContext';
2719
import { getAvatarURL } from '../../api/api';
2820
import DateFnsUtils from '@date-io/date-fns';
29-
import CheckIcon from '@mui/icons-material/Check';
30-
import CloseIcon from '@mui/icons-material/Close';
3121
import TeamIcon from '@mui/icons-material/Groups';
32-
33-
import { approveKudos, deleteKudos } from '../../api/kudos';
34-
import { UPDATE_TOAST } from '../../context/actions';
22+
import { Emoji, EmojiStyle } from 'emoji-picker-react';
3523

3624
import './PublicKudosCard.css';
25+
import emojis from 'emoji-picker-react/src/data/emojis.json';
3726

3827
const dateUtils = new DateFnsUtils();
3928

@@ -49,6 +38,26 @@ const propTypes = {
4938
}).isRequired
5039
};
5140

41+
const parseEmojiData = () => {
42+
let shortcodeMap = {};
43+
for(const category in emojis) {
44+
if (Object.hasOwn(emojis, category)) {
45+
let emojiList = emojis[category];
46+
shortcodeMap = emojiList.reduce((acc, current) => {
47+
current?.n?.forEach(name => acc[name.replace(/\s/g, "_")] = { unified: current.u })
48+
return acc;
49+
}, shortcodeMap);
50+
}
51+
}
52+
return shortcodeMap
53+
};
54+
55+
const emojiShortcodeMap = parseEmojiData();
56+
57+
const getEmojiDataByShortcode = (shortcode) => {
58+
return emojiShortcodeMap[shortcode.toLowerCase()] || null;
59+
};
60+
5261
const KudosCard = ({ kudos }) => {
5362
const { state, dispatch } = useContext(AppContext);
5463
const csrf = selectCsrfToken(state);
@@ -174,6 +183,62 @@ const KudosCard = ({ kudos }) => {
174183
return components;
175184
};
176185

186+
const renderTextWithEmojis = useCallback((text) => {
187+
const emojiShortcodeRegex = /:([a-zA-Z0-9_+-]+):/g; // Regex to find :shortcodes:
188+
const components = [];
189+
let lastIndex = 0;
190+
let match;
191+
192+
while ((match = emojiShortcodeRegex.exec(text)) !== null) {
193+
const shortcode = match[1];
194+
const emojiData = getEmojiDataByShortcode(shortcode);
195+
const precedingText = text.slice(lastIndex, match.index);
196+
197+
// Add text before the emoji shortcode
198+
if (precedingText) {
199+
components.push(precedingText);
200+
}
201+
202+
// Add the Emoji component or the original shortcode text
203+
if (emojiData) {
204+
if (emojiData.unified) {
205+
components.push(
206+
<Emoji
207+
key={`${match.index}-${shortcode}`} // Unique key
208+
unified={emojiData.unified}
209+
size={20} // Adjust size as needed
210+
/>
211+
);
212+
} else if (emojiData.customUrl) {
213+
// Render custom emoji using emojiUrl (or as an img tag)
214+
components.push(
215+
<Emoji
216+
key={`${match.index}-${shortcode}`}
217+
emojiUrl={emojiData.customUrl}
218+
size={20}
219+
/>
220+
// Alternative: Render as an img tag directly if preferred
221+
// <img key={`${match.index}-${shortcode}`} src={emojiData.customUrl} alt={`:${shortcode}:`} style={{ width: 20, height: 20, verticalAlign: 'middle' }} />
222+
);
223+
}
224+
} else {
225+
// If shortcode not found in map, render the original text
226+
components.push(match[0]);
227+
}
228+
229+
lastIndex = emojiShortcodeRegex.lastIndex;
230+
}
231+
232+
// Add any remaining text after the last shortcode
233+
const remainingText = text.slice(lastIndex);
234+
if (remainingText) {
235+
components.push(remainingText);
236+
}
237+
238+
// If the original text had no shortcodes, return it in an array
239+
return components.length === 0 ? [text] : components;
240+
}, []);
241+
177242
const createLinks = kudos => {
178243
const lines = [];
179244
let index = 0;
@@ -193,9 +258,19 @@ const KudosCard = ({ kudos }) => {
193258
}
194259
}
195260
}
261+
262+
let finalComponents = [];
263+
for (const comp of components) {
264+
if (typeof comp === 'string') {
265+
finalComponents.push(...renderTextWithEmojis(comp)); // Spread the result
266+
} else {
267+
finalComponents.push(comp); // Keep existing non-string components
268+
}
269+
}
270+
196271
lines.push(
197-
<Typography key={kudos.id + '-' + index} variant="body1">
198-
{components}
272+
<Typography key={kudos.id + '-' + index} variant="body1" sx={{ lineHeight: '1.6' }} >
273+
{finalComponents}
199274
</Typography>
200275
);
201276
index++;

web-ui/yarn.lock

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3181,6 +3181,13 @@ electron-to-chromium@^1.5.41:
31813181
resolved "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.55.tgz"
31823182
integrity sha512-6maZ2ASDOTBtjt9FhqYPRnbvKU5tjG0IN9SztUOWYw2AzNDNpKJYLJmlK0/En4Hs/aiWnB+JZ+gW19PIGszgKg==
31833183

3184+
emoji-picker-react@^4.12.2:
3185+
version "4.12.2"
3186+
resolved "https://registry.yarnpkg.com/emoji-picker-react/-/emoji-picker-react-4.12.2.tgz#323fbbf763daf1ffc1a9ff819966408e1ec30bab"
3187+
integrity sha512-6PDYZGlhidt+Kc0ay890IU4HLNfIR7/OxPvcNxw+nJ4HQhMKd8pnGnPn4n2vqC/arRFCNWQhgJP8rpsYKsz0GQ==
3188+
dependencies:
3189+
flairup "1.0.0"
3190+
31843191
emoji-regex@^10.3.0:
31853192
version "10.4.0"
31863193
resolved "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz"
@@ -3811,6 +3818,11 @@ find-up@^5.0.0:
38113818
locate-path "^6.0.0"
38123819
path-exists "^4.0.0"
38133820

3821+
3822+
version "1.0.0"
3823+
resolved "https://registry.yarnpkg.com/flairup/-/flairup-1.0.0.tgz#d3af0052ad02734c12d2446608a869498adb351b"
3824+
integrity sha512-IKlE+pNvL2R+kVL1kEhUYqRxVqeFnjiIvHWDMLFXNaqyUdFXQM2wte44EfMYJNHkW16X991t2Zg8apKkhv7OBA==
3825+
38143826
flat-cache@^4.0.0:
38153827
version "4.0.1"
38163828
resolved "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz"

0 commit comments

Comments
 (0)