-
- {{ humanReadableParticipationStatus[selectedStatus] }}
-
-
-
-
+
-
-
+
+ {{ humanReadableParticipationStatus[selectedStatus] }}
+
+
+
+
+ {{ humanReadableParticipationStatus[state] }}
+
+
+
-
-
-
-
-
+
+
+
+
{{ title }}
{{ badge }}
-
-
+
+
From af5163e7812107df58f9a454cf3918fb7b62a06d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?In=C3=AAs=20Costa?=
<94355111+inesiscosta@users.noreply.github.com>
Date: Tue, 6 Jan 2026 20:10:05 +0000
Subject: [PATCH 5/5] feat: make company notes private and add company linkedin
Refs: #530
---
backend/src/models/company.go | 4 +-
backend/src/mongodb/company.go | 47 +++++++++++++++----
backend/src/mongodb/companyReps.go | 33 +++++++------
backend/src/mongodb/contact.go | 45 ++++++++++++++++--
backend/src/mongodb/speaker.go | 2 +-
backend/swagger/companies-id.json | 3 ++
backend/swagger/companies.json | 3 ++
backend/swagger/models/company.json | 3 ++
frontend/src/components/cards/CompanyCard.vue | 25 +++++++++-
.../components/companies/CompanyInfoForm.vue | 28 +++++++++--
.../companies/CreateCompanyForm.vue | 15 ++++++
frontend/src/dto/companies.ts | 4 +-
frontend/src/mutations/companies.ts | 5 +-
13 files changed, 177 insertions(+), 40 deletions(-)
diff --git a/backend/src/models/company.go b/backend/src/models/company.go
index bbda4947..f05d393c 100644
--- a/backend/src/models/company.go
+++ b/backend/src/models/company.go
@@ -104,6 +104,8 @@ type Company struct {
Site string `json:"site" bson:"site"`
+ LinkedIn string `json:"linkedin,omitempty" bson:"linkedin,omitempty"`
+
// Company's contacts is an array of CompanyRep _id (see models.CompanyRep).
Employers []primitive.ObjectID `json:"employers,omitempty" bson:"employers,omitempty"`
@@ -140,8 +142,6 @@ type CompanyPublic struct {
Name string `json:"name"`
- Description string `json:"description"`
-
// Company's image (public).
Image string `json:"img,omitempty"`
diff --git a/backend/src/mongodb/company.go b/backend/src/mongodb/company.go
index 8a792eb0..0d936479 100644
--- a/backend/src/mongodb/company.go
+++ b/backend/src/mongodb/company.go
@@ -7,6 +7,7 @@ import (
"fmt"
"io"
"log"
+ "strings"
"time"
"go.mongodb.org/mongo-driver/bson/primitive"
@@ -31,11 +32,26 @@ func ResetCurrentPublicCompanies() {
currentPublicCompanies = nil
}
+func formatLinkedInURL(url *string) *string {
+ if url == nil || *url == "" {
+ return url
+ }
+
+ trimmed := strings.TrimSpace(*url)
+ if strings.HasPrefix(strings.ToLower(trimmed), "http://") || strings.HasPrefix(strings.ToLower(trimmed), "https://") {
+ return &trimmed
+ }
+
+ formatted := "https://linkedin.com/company/" + strings.TrimPrefix(trimmed, "@")
+ return &formatted
+}
+
// CreateCompanyData holds data needed to create a company
type CreateCompanyData struct {
Name *string `json:"name"`
Description *string `json:"description"`
Site *string `json:"site"`
+ LinkedIn *string `json:"linkedin"`
}
// ParseBody fills the CreateCompanyData from a body
@@ -80,10 +96,17 @@ func (c *CompaniesType) CreateCompany(data CreateCompanyData) (*models.Company,
return nil, err
}
+ var linkedinValue interface{} = nil
+ formattedLinkedin := formatLinkedInURL(data.LinkedIn)
+ if formattedLinkedin != nil {
+ linkedinValue = *formattedLinkedin
+ }
+
insertResult, err := c.Collection.InsertOne(ctx, bson.M{
"name": data.Name,
"description": data.Description,
"site": data.Site,
+ "linkedin": linkedinValue,
"employers": []primitive.ObjectID{},
"participations": []models.CompanyParticipation{},
"contact": createdContact.InsertedID.(primitive.ObjectID),
@@ -325,11 +348,10 @@ func (c *CompaniesType) GetCompaniesByMembers(memberIDs []primitive.ObjectID, ev
func companyToPublic(company models.Company, eventID *int) (*models.CompanyPublic, error) {
public := models.CompanyPublic{
- ID: company.ID,
- Name: company.Name,
- Image: company.Images.Public,
- Site: company.Site,
- Description: company.Description,
+ ID: company.ID,
+ Name: company.Name,
+ Image: company.Images.Public,
+ Site: company.Site,
}
var participation *models.CompanyParticipation
@@ -860,10 +882,11 @@ func (c *CompaniesType) UpdateCompanyParticipationStatus(companyID primitive.Obj
// UpdateCompanyData is the data used to update a company, using the method UpdateCompany.
type UpdateCompanyData struct {
- Name *string
- Description *string
- Site *string
- BillingInfo *models.CompanyBillingInfo
+ Name *string `json:"name"`
+ Description *string `json:"description"`
+ Site *string `json:"site"`
+ LinkedIn *string `json:"linkedin"`
+ BillingInfo *models.CompanyBillingInfo `json:"billingInfo"`
}
// ParseBody fills the UpdateCompanyData from a body
@@ -893,6 +916,12 @@ func (c *CompaniesType) UpdateCompany(companyID primitive.ObjectID, data UpdateC
if data.Site != nil {
updateFields["site"] = *data.Site
}
+ if data.LinkedIn != nil {
+ formattedLinkedin := formatLinkedInURL(data.LinkedIn)
+ if formattedLinkedin != nil {
+ updateFields["linkedin"] = *formattedLinkedin
+ }
+ }
if data.BillingInfo != nil {
billingInfo := *data.BillingInfo
updateFields["billingInfo.name"] = billingInfo.Name
diff --git a/backend/src/mongodb/companyReps.go b/backend/src/mongodb/companyReps.go
index 2f1738b3..9efff979 100644
--- a/backend/src/mongodb/companyReps.go
+++ b/backend/src/mongodb/companyReps.go
@@ -105,23 +105,18 @@ func (c *CompanyRepsType) CreateCompanyRep(data CreateCompanyRepData) (*models.C
dataQuery["contact"] = contact.ID
} else {
- contact, err := Contacts.Collection.InsertOne(ctx, bson.M{
- "phones": []models.ContactPhone{},
- "socials": bson.M{
- "facebook": "",
- "skype": "",
- "github": "",
- "twitter": "",
- "linkedin": "",
- },
- "mails": []models.ContactMail{},
- })
-
+ // Create empty contact using CreateContact to ensure proper initialization
+ emptyContact := CreateContactData{
+ Phones: []models.ContactPhone{},
+ Socials: models.ContactSocials{},
+ Mails: []models.ContactMail{},
+ }
+ contact, err := Contacts.CreateContact(emptyContact)
if err != nil {
return nil, err
}
- dataQuery["contact"] = contact.InsertedID.(primitive.ObjectID)
+ dataQuery["contact"] = contact.ID
}
insertResult, err := c.Collection.InsertOne(ctx, dataQuery)
@@ -140,7 +135,7 @@ func (c *CompanyRepsType) CreateCompanyRep(data CreateCompanyRepData) (*models.C
return newRep, nil
}
-// UpdateCompanyRep creates a contact and adds it to a companyRep
+// UpdateCompanyRep updates a company rep and its contact
func (c *CompanyRepsType) UpdateCompanyRep(id primitive.ObjectID, data CreateCompanyRepData) (*models.CompanyRep, error) {
ctx := context.Background()
@@ -149,13 +144,17 @@ func (c *CompanyRepsType) UpdateCompanyRep(id primitive.ObjectID, data CreateCom
}
if data.Contact != nil {
- contact, err := Contacts.CreateContact(*data.Contact)
+ // Get the existing rep to find its contact ID
+ existingRep, err := c.GetCompanyRep(id)
if err != nil {
return nil, err
}
- // add contact id to the $set document
- setDoc["contact"] = contact.ID
+ // Update the existing contact instead of creating a new one
+ _, err = Contacts.UpdateContact(existingRep.Contact, *data.Contact)
+ if err != nil {
+ return nil, err
+ }
}
var updateQuery = bson.M{"$set": setDoc}
diff --git a/backend/src/mongodb/contact.go b/backend/src/mongodb/contact.go
index 79f579d5..3cd433a5 100644
--- a/backend/src/mongodb/contact.go
+++ b/backend/src/mongodb/contact.go
@@ -16,6 +16,41 @@ import (
"go.mongodb.org/mongo-driver/bson"
)
+func formatSocialURL(platform, url string) string {
+ if url == "" {
+ return ""
+ }
+
+ trimmed := strings.TrimSpace(url)
+ if strings.HasPrefix(strings.ToLower(trimmed), "http://") || strings.HasPrefix(strings.ToLower(trimmed), "https://") {
+ return trimmed
+ }
+
+ switch strings.ToLower(platform) {
+ case "linkedin":
+ return "https://linkedin.com/in/" + strings.TrimPrefix(trimmed, "@")
+ case "twitter":
+ return "https://twitter.com/" + strings.TrimPrefix(trimmed, "@")
+ case "facebook":
+ return "https://facebook.com/" + strings.TrimPrefix(trimmed, "@")
+ case "github":
+ return "https://github.com/" + strings.TrimPrefix(trimmed, "@")
+ default:
+ return trimmed
+ }
+}
+
+// formatContactSocials formats all social media links in a contact
+func formatContactSocials(socials models.ContactSocials) models.ContactSocials {
+ return models.ContactSocials{
+ LinkedIn: formatSocialURL("linkedin", socials.LinkedIn),
+ Twitter: formatSocialURL("twitter", socials.Twitter),
+ Facebook: formatSocialURL("facebook", socials.Facebook),
+ Github: formatSocialURL("github", socials.Github),
+ Skype: socials.Skype,
+ }
+}
+
// ContactsType stores importat db information on contacts
type ContactsType struct {
Collection *mongo.Collection
@@ -127,7 +162,7 @@ func (c *ContactsType) CreateContact(data CreateContactData) (*models.Contact, e
ctx := context.Background()
var insertData = bson.M{}
insertData["phones"] = data.Phones
- insertData["socials"] = data.Socials
+ insertData["socials"] = formatContactSocials(data.Socials)
insertData["mails"] = data.Mails
insertData["gender"] = data.Gender
insertData["language"] = data.Language
@@ -150,10 +185,10 @@ func (c *ContactsType) UpdateContact(contactID primitive.ObjectID, data CreateCo
ctx := context.Background()
var updateQuery = bson.M{
"$set": bson.M{
- "phones": data.Phones,
- "socials": data.Socials,
- "mails": data.Mails,
- "gender": data.Gender,
+ "phones": data.Phones,
+ "socials": formatContactSocials(data.Socials),
+ "mails": data.Mails,
+ "gender": data.Gender,
"language": data.Language,
},
}
diff --git a/backend/src/mongodb/speaker.go b/backend/src/mongodb/speaker.go
index f7c6e77b..9465258c 100644
--- a/backend/src/mongodb/speaker.go
+++ b/backend/src/mongodb/speaker.go
@@ -141,7 +141,7 @@ func (s *SpeakersType) CreateSpeaker(data CreateSpeakerData) (*models.Speaker, e
if data.Contact != nil {
contact["phones"] = data.Contact.Phones
contact["mails"] = data.Contact.Mails
- contact["socials"] = data.Contact.Socials
+ contact["socials"] = formatContactSocials(data.Contact.Socials)
}
createdContact, err := Contacts.Collection.InsertOne(ctx, contact)
diff --git a/backend/swagger/companies-id.json b/backend/swagger/companies-id.json
index 001e2a89..48b435ac 100644
--- a/backend/swagger/companies-id.json
+++ b/backend/swagger/companies-id.json
@@ -87,6 +87,9 @@
"site": {
"type": "string"
},
+ "linkedin": {
+ "type": "string"
+ },
"billingInfo": {
"type": "object",
"properties": {
diff --git a/backend/swagger/companies.json b/backend/swagger/companies.json
index dd1ad1fe..54bdd8eb 100644
--- a/backend/swagger/companies.json
+++ b/backend/swagger/companies.json
@@ -99,6 +99,9 @@
},
"site": {
"type": "string"
+ },
+ "linkedin": {
+ "type": "string"
}
}
}
diff --git a/backend/swagger/models/company.json b/backend/swagger/models/company.json
index eccbad08..b54db7a7 100644
--- a/backend/swagger/models/company.json
+++ b/backend/swagger/models/company.json
@@ -24,6 +24,9 @@
"site": {
"type": "string"
},
+ "linkedin": {
+ "type": "string"
+ },
"employers": {
"type": "array",
"items": {
diff --git a/frontend/src/components/cards/CompanyCard.vue b/frontend/src/components/cards/CompanyCard.vue
index 571a0715..93de3c2e 100644
--- a/frontend/src/components/cards/CompanyCard.vue
+++ b/frontend/src/components/cards/CompanyCard.vue
@@ -51,6 +51,7 @@
name: company.name,
description: company.description,
site: company.site,
+ linkedin: company.linkedin,
}"
:is-loading="isUpdating || isUploadingImage"
mode="edit"
@@ -112,6 +113,18 @@
{{ formatWebsite(company.site) }}
+
+