Skip to content

Commit 1404463

Browse files
authored
Merge pull request #1617 from DNNCommunity/dev
TASK: Sync dev to master
2 parents bb392b8 + 54ef53b commit 1404463

File tree

158 files changed

+7620
-1387
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

158 files changed

+7620
-1387
lines changed

.github/copilot-instructions.md

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
2+
<!-- modeled on https://github.com/FritzAndFriends/SharpSite/pull/333 -->
3+
4+
You are a senior .NET developer, experienced in C#, JavaScript, HTML, ASP.NET Framework 4.8, CSS, and SQL.
5+
You understand the priciples of DNN (DotNetNuke) and how to develop DNN modules.
6+
You use Visual Studio Enterprise for running, debugging, and testing DNN (DotNetNuke) modules.
7+
8+
## Code Style and Structure
9+
- Write idiomatic and efficient C# code.
10+
- Follow .NET conventions.
11+
- Follow DNN module development best practices.
12+
- Always follow DNN's StyleCop rules for C# and JavaScript.
13+
- Always use StyleCop to add file header license to all C# files.
14+
- Always put using directives inside the namespace, sorted alphabetically and grouped by system and third-party libraries.
15+
- Always put a blank link between system and third-party libraries using directives.
16+
- Use Razor syntax when possible for component-based UI development.
17+
- Async/await should be used where applicable to ensure non-blocking UI operations.
18+
- Classes should always be internal unless they are intended to be public APIs.
19+
- Always add using directives for namespaces that are used in the file, and remove unused using directives.
20+
- Never use 'Active Forums' in code, always use 'DNN Community Forums' instead.
21+
22+
## Naming Conventions
23+
- Follow PascalCase for component names, method names, and public members.
24+
- Use underscore prefix and then PascalCase for private fields.
25+
- Use camelCase for local variables.
26+
- Prefix interface names with "I" (e.g., IUserService).
27+
28+
## .NET Specific Guidelines
29+
- Leverage DNN Dependency Injection for services when possible.
30+
- DNN modules should be developed using DNN version 9.11 and compatible with .NET Framework 4.8.
31+
- Always use the latest stable version of .NET libraries and packages compatible with DNN.
32+
- Use NuGet packages for third-party libraries, ensuring they are compatible with DNN and .NET Framework 4.8.
33+
- Use C# compatible with .NET Framework 4.8, avoiding features exclusive to .NET Core or .NET 5+.
34+
35+
## Error Handling and Validation
36+
- Implement proper error handling for Web API calls.
37+
38+
## DNN Entities, Controllers, and Services
39+
- Always create and use DNN-style entities (e.g., ForumUserInfo, ForumPostInfo) for data representation.
40+
- Always create and use DNN-style services (e.g., IForumService, IUserService) for business logic.
41+
- Always create controllers in Controllers folder, and use the appropriate namespaces, such as DotNetNuke.Modules.ActiveForums.Controllers.
42+
- Always create controllers that inherit from DotNetNuke.Modules.ActiveForums.Controllers.RepositoryControllerBase for the appropriate entity.
43+
- Always create controllers as internal classes, unless they are intended to be public APIs.
44+
- Always create an entity class for each DNN entity, such as ForumUserInfo, ForumPostInfo, etc., in the Entities folder, and use namespace DotNetNuke.Modules.ActiveForums.Entities.
45+
- Entity classes should use DNN DAL2 PetaPoco standards, and include TableName and PrimaryKey attributes, for example:
46+
[TableName("activeforums_Content")]
47+
[PrimaryKey("ContentId", AutoIncrement = true)]
48+
- Always map entity's DateUpdated and DateCreated properties, ensuring they are stored in UTC format.
49+
- Always add using DotNetNuke.ComponentModel.DataAnnotations; to the entity class files.
50+
51+
## SQL DataProvider and Database Access
52+
- Use DNN's built-in DataProvider pattern for database access.
53+
- Create SQL scripts for database migrations and updates, ensuring they are compatible with DNN's upgrade process.
54+
- Always use GETUTCDATE() for date and time storage in the database.
55+
- Always add DateCreated and DataModified to all tables.
56+
- Always default DateCreated to GETUTCDATE() and DateUpdated to GETUTCDATE() on insert and update operations.
57+
- Database object names should be in camelCase.
58+
- Always prefix database object names with activeforums_ to avoid conflicts with other modules.
59+
- Always prefix database objects (tables, views, stored procedures) with the {databaseOwner}{objectQualifier} prefixes to ensure compatibility with DNN's multi-tenant architecture.
60+
- Examples : {databaseOwner}[{objectQualifier}activeforums_ForumPosts] for ForumPosts table, IX_{objectQualifier}activeforums_Content_ModuleId for an index.
61+
- Always add an auto-incrementing identity as primary key to all tables, using the naming convention PK_{objectQualifier}activeforums_{TableName} (e.g., PK_activeforums_ForumPosts).
62+
- Always add indexes to frequently queried columns, using the naming convention IX_{objectQualifier}activeforums_{TableName}_{ColumnName} (e.g., IX_activeforums_ForumPosts_ModuleId).
63+
- Always use NOT EXISTS check when creating tables and adding columns ot existing tables.
64+
- Always use EXISTS check with DROP statements when creating indexes.
65+
- Always use parameterized queries to prevent SQL injection attacks.
66+
- Always create a matching entity class when creating a new table, such as ForumUserInfo, ForumPostInfo, etc., in the Entities folder.
67+
- When adding a new SqlDataProvider, always offer to update the DNN manifest file (DnnCommunityForums.dnn) to reference the new version, ensuring it is compatible with DNN's upgrade process.
68+
69+
## Caching Strategies
70+
- Implement in-memory caching for all Controllers and services to improve performance and reduce database load.
71+
- Caching should use methods in Cache.cs, such as ContentCacheRetrieve, ContentCacheStore, and ContentCacheRemove for content, and SettingsCache, SettingsCacheRetrieve, and SettingsCacheStore for settings.
72+
73+
## API Design and Integration
74+
- Use HttpClient or other appropriate services to communicate with external APIs or your own backend.
75+
- Implement error handling for API calls using try-catch and provide proper user feedback in the UI.
76+
77+
## Testing and Debugging in Visual Studio
78+
- Create unit tests for all public and internal methods using NUnit.
79+
- Use Moq for mocking dependencies during tests, leveraging TestBase.cs for shared test setup.
80+
- Create unit tests in DnnCommunityForumsTests project for testing DNN module functionality.
81+
82+
## Security and Authentication
83+
- All user properties should be accesed using ForumUserInfo and then DNN UserInfo.
84+
- Use HTTPS for all web communication and ensure proper CORS policies are implemented.
85+
86+
## API Documentation
87+
- Ensure XML documentation for models and API methods for enhancing sufficient documentation.

Dnn.CommunityForums/App_LocalResources/ControlPanel.ascx.fr-FR.resx

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1483,4 +1483,61 @@ Votre méthode de suppression est actuellement définie sur {0}. Vos sujets ser
14831483
<data name="[RESX:Tips:TemplateFileNameSuffix].Text" xml:space="preserve">
14841484
<value>Entrez une chaîne à utiliser lors de la récupération des modèles. Par exemple, si vous souhaitez disposer de fichiers de modèle distincts pour les forums modérés, entrez « modéré », puis les modèles seront récupérés à l’aide de « modéré » dans le nom de fichier, par exemple « TopicsView-moderated.ascx » plutôt que simplement « TopicsView.ascx » lorsque le modèle TopicsView est récupéré.</value>
14851485
</data>
1486+
<data name="[RESX:Description].Text" xml:space="preserve">
1487+
<value>Description</value>
1488+
</data>
1489+
<data name="[RESX:BadgeName].Text" xml:space="preserve">
1490+
<value>Insigne</value>
1491+
</data>
1492+
<data name="[RESX:SortOrder].Text" xml:space="preserve">
1493+
<value>Ordre de tri</value>
1494+
</data>
1495+
<data name="[RESX:Badges].Text" xml:space="preserve">
1496+
<value>Badges</value>
1497+
</data>
1498+
<data name="[RESX:Badge].Text" xml:space="preserve">
1499+
<value>Insigne</value>
1500+
</data>
1501+
<data name="[RESX:BadgeNew].Text" xml:space="preserve">
1502+
<value>Nouveau badge</value>
1503+
</data>
1504+
<data name="[RESX:BadgeThreshold].Text" xml:space="preserve">
1505+
<value>Seuil</value>
1506+
</data>
1507+
<data name="[RESX:BadgeMetric].Text" xml:space="preserve">
1508+
<value>Métrique</value>
1509+
</data>
1510+
<data name="[RESX:BadgeImage].Text" xml:space="preserve">
1511+
<value>Image</value>
1512+
</data>
1513+
<data name="[RESX:BadgeMetricNewUser].Text" xml:space="preserve">
1514+
<value>Nouvel utilisateur</value>
1515+
</data>
1516+
<data name="[RESX:BadgeMetricTopicsCreated].Text" xml:space="preserve">
1517+
<value>Sujets créés</value>
1518+
</data>
1519+
<data name="[RESX:BadgeMetricRepliesCreated].Text" xml:space="preserve">
1520+
<value>Réponses aux rubriques</value>
1521+
</data>
1522+
<data name="[RESX:BadgeMetricLikesReceived].Text" xml:space="preserve">
1523+
<value>J’aime reçus</value>
1524+
</data>
1525+
<data name="[RESX:BadgeMetricTopicsRead].Text" xml:space="preserve">
1526+
<value>Sujets lus</value>
1527+
</data>
1528+
<data name="[RESX:Button:UpdateBadgeUsers].Text" xml:space="preserve">
1529+
<value>Mettre à jour les utilisateurs</value>
1530+
</data>
1531+
<data name="[RESX:BadgeImageMarkup].Text" xml:space="preserve">
1532+
<value>Balisage HTML pour badge (par exemple, font-awesome)</value>
1533+
</data>
1534+
<data name="[RESX:BadgeOneTimeAward].Text" xml:space="preserve">
1535+
<value>L’utilisateur ne peut gagner un badge qu’une seule fois</value>
1536+
</data>
1537+
<data name="[RESX:BadgeIntervalDays].Text" xml:space="preserve">
1538+
<value># de jours entre l’obtention de ce badge</value>
1539+
</data>
1540+
<data name="[RESX:BadgeMetricManual].Text" xml:space="preserve">
1541+
<value>Prix du manuel</value>
1542+
</data>
14861543
</root>

Dnn.CommunityForums/App_LocalResources/ControlPanel.ascx.it-IT.resx

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1480,4 +1480,61 @@ Il metodo di rimozione è attualmente impostato su {0}. I tuoi argomenti verran
14801480
<data name="[RESX:Tips:TemplateFileNameSuffix].Text" xml:space="preserve">
14811481
<value>Immettere una stringa da utilizzare per il recupero dei modelli. Ad esempio, se si desidera avere file modello separati per i forum moderati, immettere "moderato" e quindi i modelli verranno recuperati utilizzando "moderato" come parte del nome del file, ad esempio "TopicsView-moderated.ascx" anziché solo "TopicsView.ascx" quando viene recuperato il modello TopicsView.</value>
14821482
</data>
1483+
<data name="[RESX:Description].Text" xml:space="preserve">
1484+
<value>Descrizione</value>
1485+
</data>
1486+
<data name="[RESX:BadgeName].Text" xml:space="preserve">
1487+
<value>Distintivo</value>
1488+
</data>
1489+
<data name="[RESX:SortOrder].Text" xml:space="preserve">
1490+
<value>Ordinamento</value>
1491+
</data>
1492+
<data name="[RESX:Badges].Text" xml:space="preserve">
1493+
<value>Distintivi</value>
1494+
</data>
1495+
<data name="[RESX:Badge].Text" xml:space="preserve">
1496+
<value>Distintivo</value>
1497+
</data>
1498+
<data name="[RESX:BadgeNew].Text" xml:space="preserve">
1499+
<value>Nuovo distintivo</value>
1500+
</data>
1501+
<data name="[RESX:BadgeThreshold].Text" xml:space="preserve">
1502+
<value>Soglia</value>
1503+
</data>
1504+
<data name="[RESX:BadgeMetric].Text" xml:space="preserve">
1505+
<value>Metrico</value>
1506+
</data>
1507+
<data name="[RESX:BadgeImage].Text" xml:space="preserve">
1508+
<value>Immagine</value>
1509+
</data>
1510+
<data name="[RESX:BadgeMetricNewUser].Text" xml:space="preserve">
1511+
<value>Nuovo utente</value>
1512+
</data>
1513+
<data name="[RESX:BadgeMetricTopicsCreated].Text" xml:space="preserve">
1514+
<value>Argomenti creati</value>
1515+
</data>
1516+
<data name="[RESX:BadgeMetricRepliesCreated].Text" xml:space="preserve">
1517+
<value>Risposta agli argomenti</value>
1518+
</data>
1519+
<data name="[RESX:BadgeMetricLikesReceived].Text" xml:space="preserve">
1520+
<value>Mi piace ricevuti</value>
1521+
</data>
1522+
<data name="[RESX:BadgeMetricTopicsRead].Text" xml:space="preserve">
1523+
<value>Argomenti Leggi</value>
1524+
</data>
1525+
<data name="[RESX:Button:UpdateBadgeUsers].Text" xml:space="preserve">
1526+
<value>Aggiorna utenti</value>
1527+
</data>
1528+
<data name="[RESX:BadgeImageMarkup].Text" xml:space="preserve">
1529+
<value>Markup HTML per badge (ad esempio, font-awesome)</value>
1530+
</data>
1531+
<data name="[RESX:BadgeOneTimeAward].Text" xml:space="preserve">
1532+
<value>L'utente può guadagnare il badge una sola volta</value>
1533+
</data>
1534+
<data name="[RESX:BadgeIntervalDays].Text" xml:space="preserve">
1535+
<value># di giorni tra l'ottenimento di questo distintivo</value>
1536+
</data>
1537+
<data name="[RESX:BadgeMetricManual].Text" xml:space="preserve">
1538+
<value>Premio Manuale</value>
1539+
</data>
14831540
</root>

Dnn.CommunityForums/App_LocalResources/ControlPanel.ascx.nl-NL.resx

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1630,4 +1630,61 @@ De verwijder-methode is momenteel ingesteld op "{0}". Uw onderwerpen worden {1}
16301630
<data name="[RESX:Tips:TemplateFileNameSuffix].Text" xml:space="preserve">
16311631
<value>Voer een tekenreeks in die moet worden gebruikt bij het ophalen van sjablonen. Als u bijvoorbeeld aparte sjabloonbestanden wilt hebben voor gemodereerde forums, voert u 'gemodereerd' in, waarna sjablonen worden opgehaald met 'gemodereerd' als onderdeel van de bestandsnaam, bijvoorbeeld 'TopicsView-moderated.ascx' in plaats van alleen 'TopicsView.ascx' wanneer het TopicsView-sjabloon wordt opgehaald.</value>
16321632
</data>
1633+
<data name="[RESX:Description].Text" xml:space="preserve">
1634+
<value>Beschrijving</value>
1635+
</data>
1636+
<data name="[RESX:BadgeName].Text" xml:space="preserve">
1637+
<value>Insigne</value>
1638+
</data>
1639+
<data name="[RESX:SortOrder].Text" xml:space="preserve">
1640+
<value>Sorteervolgorde</value>
1641+
</data>
1642+
<data name="[RESX:Badges].Text" xml:space="preserve">
1643+
<value>Badges</value>
1644+
</data>
1645+
<data name="[RESX:Badge].Text" xml:space="preserve">
1646+
<value>Insigne</value>
1647+
</data>
1648+
<data name="[RESX:BadgeNew].Text" xml:space="preserve">
1649+
<value>Nieuwe badge</value>
1650+
</data>
1651+
<data name="[RESX:BadgeThreshold].Text" xml:space="preserve">
1652+
<value>Drempel</value>
1653+
</data>
1654+
<data name="[RESX:BadgeMetric].Text" xml:space="preserve">
1655+
<value>Metriek</value>
1656+
</data>
1657+
<data name="[RESX:BadgeImage].Text" xml:space="preserve">
1658+
<value>Beeld</value>
1659+
</data>
1660+
<data name="[RESX:BadgeMetricNewUser].Text" xml:space="preserve">
1661+
<value>Nieuwe gebruiker</value>
1662+
</data>
1663+
<data name="[RESX:BadgeMetricTopicsCreated].Text" xml:space="preserve">
1664+
<value>Onderwerpen gemaakt</value>
1665+
</data>
1666+
<data name="[RESX:BadgeMetricRepliesCreated].Text" xml:space="preserve">
1667+
<value>Gereageerd op onderwerpen</value>
1668+
</data>
1669+
<data name="[RESX:BadgeMetricLikesReceived].Text" xml:space="preserve">
1670+
<value>Likes ontvangen</value>
1671+
</data>
1672+
<data name="[RESX:BadgeMetricTopicsRead].Text" xml:space="preserve">
1673+
<value>Onderwerpen Lezen</value>
1674+
</data>
1675+
<data name="[RESX:Button:UpdateBadgeUsers].Text" xml:space="preserve">
1676+
<value>Gebruikers bijwerken</value>
1677+
</data>
1678+
<data name="[RESX:BadgeImageMarkup].Text" xml:space="preserve">
1679+
<value>HTML-opmaak voor badge (bijv. lettertype-geweldig)</value>
1680+
</data>
1681+
<data name="[RESX:BadgeOneTimeAward].Text" xml:space="preserve">
1682+
<value>De gebruiker kan slechts één keer een badge verdienen</value>
1683+
</data>
1684+
<data name="[RESX:BadgeIntervalDays].Text" xml:space="preserve">
1685+
<value># dagen tussen het verdienen van deze badge</value>
1686+
</data>
1687+
<data name="[RESX:BadgeMetricManual].Text" xml:space="preserve">
1688+
<value>Handleiding Award</value>
1689+
</data>
16331690
</root>

Dnn.CommunityForums/App_LocalResources/ControlPanel.ascx.resx

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1585,4 +1585,61 @@ Your removal method is currently set to {0}. Your topics will be {1} based upon
15851585
<data name="[RESX:Tips:TemplateFileNameSuffix].Text" xml:space="preserve">
15861586
<value>Enter a string to be used when retrieving templates. For example, if you want to have separate template files for moderated forums, enter 'moderated', and then templates will be retrieved using 'moderated' as part of the filename, e.g. 'TopicsView-moderated.ascx' rather than just 'TopicsView.ascx' when the TopicsView template is retrieved.</value>
15871587
</data>
1588+
<data name="[RESX:BadgeName].Text" xml:space="preserve">
1589+
<value>Badge</value>
1590+
</data>
1591+
<data name="[RESX:SortOrder].Text" xml:space="preserve">
1592+
<value>Sort Order</value>
1593+
</data>
1594+
<data name="[RESX:Badges].Text" xml:space="preserve">
1595+
<value>Badges</value>
1596+
</data>
1597+
<data name="[RESX:Badge].Text" xml:space="preserve">
1598+
<value>Badge</value>
1599+
</data>
1600+
<data name="[RESX:BadgeNew].Text" xml:space="preserve">
1601+
<value>New Badge</value>
1602+
</data>
1603+
<data name="[RESX:BadgeThreshold].Text" xml:space="preserve">
1604+
<value>Threshold</value>
1605+
</data>
1606+
<data name="[RESX:BadgeMetric].Text" xml:space="preserve">
1607+
<value>Metric</value>
1608+
</data>
1609+
<data name="[RESX:BadgeImage].Text" xml:space="preserve">
1610+
<value>Image</value>
1611+
</data>
1612+
<data name="[RESX:BadgeMetricManual].Text" xml:space="preserve">
1613+
<value>Manual Award</value>
1614+
</data>
1615+
<data name="[RESX:Description].Text" xml:space="preserve">
1616+
<value>Description</value>
1617+
</data>
1618+
<data name="[RESX:BadgeMetricNewUser].Text" xml:space="preserve">
1619+
<value>New User</value>
1620+
</data>
1621+
<data name="[RESX:BadgeMetricTopicsCreated].Text" xml:space="preserve">
1622+
<value>Topics Created</value>
1623+
</data>
1624+
<data name="[RESX:BadgeMetricRepliesCreated].Text" xml:space="preserve">
1625+
<value>Replied to Topics</value>
1626+
</data>
1627+
<data name="[RESX:BadgeMetricLikesReceived].Text" xml:space="preserve">
1628+
<value>Likes Received</value>
1629+
</data>
1630+
<data name="[RESX:BadgeMetricTopicsRead].Text" xml:space="preserve">
1631+
<value>Topics Read</value>
1632+
</data>
1633+
<data name="[RESX:Button:UpdateBadgeUsers].Text" xml:space="preserve">
1634+
<value>Update Users</value>
1635+
</data>
1636+
<data name="[RESX:BadgeImageMarkup].Text" xml:space="preserve">
1637+
<value>HTML markup for badge (e.g., font-awesome)</value>
1638+
</data>
1639+
<data name="[RESX:BadgeOneTimeAward].Text" xml:space="preserve">
1640+
<value>User can only earn badge one time</value>
1641+
</data>
1642+
<data name="[RESX:BadgeIntervalDays].Text" xml:space="preserve">
1643+
<value># of days between earning this badge</value>
1644+
</data>
15881645
</root>

0 commit comments

Comments
 (0)