Giter Club home page Giter Club logo

skybrud.umbraco.feedback's Introduction

Feedback-modul til Umbraco 7

Indholdsfortegnelse

Brug i frontend

Her et eksempel, der tager udgangspunkt i DC intranet's løsning.

Felterne name, email og comment er som udgangspunkt alle valgfri, men kan konfigureres til, at skulle udfyldes. Feltet rating angives til aliaset for den ønskede rating (se mere under ratings). Standard ratings i modulet er Positive (alias: positive) og Negative (alias: negative).

$.ajax({
    url: '/umbraco/Feedback/Frontend/PostFeedback',
    method: 'POST',
    data: {
        siteId: $('body').data('siteid'),
        pageId: $('body').data('pageid'),
        name: 'Filip Bech Bruun-Larsen',
        email: '[email protected]',
        rating: 'positive',
        comment: 'Ham Bjerner er faktisk ret flink'
    }
}).done(function(r){

    console.log( JSON.stringify(r, null, '  ') );

}).error(function(r){

    console.log( JSON.stringify(r, null, '  ') );

});

Såfremt ovenstående AJAX-kald bliver gennemført, vil serveren svare tilbage noget i stil med følgende:

{ "meta": { "code": 200 }, "data": 26 }

Det vigtigste her er koden, hvor 200 betyder gennemført. Værdien under data er kommentarens ID, men værdien bruges pt. ikke til noget, og data vil måske blive ændret i fremtiden til at returnere noget andet.

Tilsvarende hvis noget går galt, vil serveren svare tilbage noget i stil med:

{ "meta": { "code": 500, "error": "Øv!" }, "data": null }

Værdien i error vil være en fejlbeskrivelse, som gerne må vises til brugeren.

Plugins

Konfigurationen af Feedback-modulet sker gennem kode, hvor man i så fald kan lave en klasse, der implementerer interfacet IFeedbackPlugin (eller blot nedarver fra den abstrakte klasse FeedbackPlugin).

Et custom plugin kan registreres som følgende:

#!C
namespace MySite {
    
    public class Startup : ApplicationEventHandler {

        protected override void ApplicationStarted(UmbracoApplicationBase umbraco, ApplicationContext application) {

            // Register an instance of the feedback plugin
            FeedbackModule.Instance.AddPlugin(new MySiteFeedbackPlugin());
        
        }

    }

}

Teknisk set behøver man ikke tilføje sit plugin over startup, men det giver nok mest mening.

GetUsers

Feedback-modulet holdet styr på en liste over de brugere, der må kunne vælges som ansvarlig på den enkelte feedback-kommentar. Listen over brugere er dog som udgangspunkt tom, og det er derfor nødvendigt, at definere dette via et custom plugin og metoden GetUsers.

Tanken er, at en bruger kan komme fra en eller flere datakilder, som så illustreres via interfacet IFeedbackUser (eller den abstrakte klasse FeedbackUser). I langt de fleste tilfælde er vi blot interesseret i, at hente en liste over de brugere, der er oprettet i Umbraco. Så i et konkret eksempel kunne GetUsers metoden implementeres som nedenstående:

#!C
public override IFeedbackUser[] GetUsers() {
            
    // Attempt to get the dictionary from the items object (the dictionary is kept in the items during the current page cycle)
    var users = HttpContext.Current.Items["IntranetFeedbackUsers"] as Dictionary<int, IFeedbackUser>;

    // Check whether we already have a dictionary in memory
    if (users == null) {
                
        // Get a reference to the user service
        IUserService service = UmbracoContext.Current.Application.Services.UserService;

        int total;

        // Populate the dictionary with users from the database
        users = (
            from IUser user in service.GetAll(0, Int32.MaxValue, out total)
            where !user.Email.EndsWith("@skybrud.dk") && !user.Email.EndsWith("@umbraco.com") && !user.Email.EndsWith("@codemonkeys.dk")
            select (IFeedbackUser) new FeedbackUser {
                Id = user.Id,
                Email = user.Email,
                Name = user.Name,
                Language = user.Language
            }
        ).ToDictionary(x => x.Id, x => x);

        // Add the dictionary to the items object for later retrieval
        HttpContext.Current.Items["IntranetFeedbackUsers"] = users;
            
    }

    // Return the users as an array
    return users.Values.ToArray();
        
}

Bemærk at brugere med en emailadresse, der ender på @skybrud.dk, @umbraco.com eller @codemonkeys.dk i dette eksempel vil blive ekskluderet fra listen.

OnEntrySubmitting

Via metoden OnEntrySubmitting kan vi ændre kommentarer idet de oprettes - altså svarende til inden de bliver skrevet ned i databasen. Dette kunne eksempelvis være at automatisk tilknytte en bruger/redaktør til en kommentar alt efter hvem der er ansvarlig for det site eller den side, hvortil kommentaren gives.

Som eksempel har vi på Danish Crown's internet følgende implementation af OnEntrySubmitting-metoden:

#!C#
public override bool OnEntrySubmitting(FeedbackModule module, FeedbackEntry entry) {

    // Specifikt til DC's intranet (her tjekkes om kommentarer oprettes under et intranet site)
    if (entry.Site == null || entry.Site.DocumentTypeAlias != "SettingsContainer") return false;

    // Henter en liste over alle brugere (også fra andre plugins såfremt der er flere)
    Dictionary<int, IFeedbackUser> users = GetUsers().ToDictionary(x => x.Id, x => x);

    // Igen lidt specifikt til DC (her hentes et entry for hvem, der sidst har redigeret den pågældende side)
    ContentReminderLogEntry logEntry = ContentReminderLogEntry.GetFromNodeId(entry.PageId).FirstOrDefault(x => users.ContainsKey(x.UserId));

    if (logEntry != null) {
    
        // Såfremt vi finder en entry, assigner vi brugeren til kommentaren
        entry.AssignedTo = users[logEntry.UserId];
    
    } else {

        // På hvert intranet site har DC mulighed for, at angive en ansvarlig
        string value = entry.Site.GetPropertyValue<string>("feedbackResponsible");

        if (!String.IsNullOrWhiteSpace(value) && value.StartsWith("{") && value.EndsWith("}")) {
            try {

                // Hent den valgte brugers ID ud fra JSON-objektet
                JObject obj = JObject.Parse(value);
                int responsibleId = (int) obj.GetValue("id");

                // Assign kommentarer til brugeren såfremt brugeren findes
                if (users.ContainsKey(responsibleId)) {
                    entry.AssignedTo = users[responsibleId];
                }
            
            } catch (Exception) {

                // Ignorér exception eller gem i en log et sted

            }

        }

    }

    return true;

}

Denne metode kan også bruges til at afvise en kommentar, hvis eksempelvis emailadressen ikke er udfyldt.

OnEntrySubmitted

Tilsvarende kan man med OnEntrySubmitted-metoden fange når en kommentar er blevet gemt i databasen. Denne metode kunne eksempelvis bruges til, at udsende en mail til den rekdaktør, der er blevet assigned jvf. ovenstående metode.

#!C
public override void OnEntrySubmitted(FeedbackModule module, FeedbackEntry entry) {

     // Skip now if not assigned
    if (entry.AssignedTo == null) return;

    // Get the first name of the user
    string firstName = entry.AssignedTo.Name.Split(' ')[0];

    // Generate the body of the mail to be sent (DescribeEntry is a custom method)
    StringBuilder sb = new StringBuilder();
    sb.AppendLine("Hi " + firstName + " (" + entry.AssignedTo.Email + "),<br />");
    sb.AppendLine("<br />");
    sb.AppendLine("A new feedback entry has been submitted to which you have been assigned:<br />");
    sb.AppendLine("<br />");
    DescribeEntry(sb, entry);

    // Send the mail to the user (again a custom user)
    SendMail("DC Intra - New feedback entry", entry.AssignedTo, sb.ToString());

}

OnUserAssigned

Når en bruger efter oprettelsen assignes til en kommantar, bliver OnUserAssigned kaldt for den pågældende kommentar. Metoden har en henvisning til både den bruger, der tidligere var assigned kommentaren, og den bruger der netop er blevet assigned.

Typisk kunne man have brug for, at sende en mail til den bruger, der bliver assigned - dette kan i så fald gøres med nedenstående kode:

#!C
public override void OnUserAssigned(FeedbackModule module, FeedbackEntry entry, IFeedbackUser oldUser, IFeedbackUser newUser) {

    // Just skip now if no user was assigned
    if (newUser == null) return;

    // Skip if the new user is the same as the old user
    if (oldUser != null && oldUser.Id == newUser.Id) return;

    // Get the first name of the user
    string firstName = newUser.Name.Split(' ')[0];

    // Generate the body of the mail to be sent (DescribeEntry is a custom method)
    StringBuilder sb = new StringBuilder();
    sb.AppendLine("Hi " + firstName + " (" + newUser.Email + "),<br />");
    sb.AppendLine("<br />");
    sb.AppendLine("You have been assigned the following feedback entry:<br />");
    sb.AppendLine("<br />");
    DescribeEntry(sb, entry);

    // Send the mail to the user (again a custom user)
    SendMail("DC Intra - You were assigned to a feedback entry", entry.AssignedTo, sb.ToString());

}

OnEntryResultRender

Har vi brug for at ændre værdierne for de kommentarer, der vises i listen i backoffice, kan dette gøres via OnEntryResultRender-metoden. Et eksempel kunne her være virtuelle URL'er på DC's intranet:

#!C
public override void OnEntryResultRender(FeedbackModule module, FeedbackEntryResult result) {

    // If the page wasn't found in the Umbraco cache, we don't bother looking up the virtual URL
    if (result.Page == null) return;

    // Check for document types using URL rewriting
    switch (result.Page.Content.DocumentTypeAlias) {
        case IntranetConstants.DocumentTypes.IntranetNewsPage:
        case IntranetConstants.DocumentTypes.IntranetBlogger:
        case IntranetConstants.DocumentTypes.IntranetBlogPage:
        case IntranetConstants.DocumentTypes.IntranetActivityPage: {

            // Lookup the parent site in the Umbraco cache
            IPublishedContent site = UmbracoContext.Current.ContentCache.GetById(result.SiteId);

            if (site == null) {
                result.Page.Url = null;
            } else {

                string url = result.Page.Content.UrlWithDomain();

                int pos1 = url.IndexOf("//");
                int pos2 = pos1 >= 0 ? url.IndexOf('/', pos1 + 2) : url.IndexOf('/');

                // Calculate the virtual URL
                string domain = (pos2 > 0 ? url.Substring(0, pos2) : "");
                result.Page.Url = domain + Utils.VirtualPages.GetVirtualUrl(result.Page.Content, IntranetOverview.GetFromContent(site));

            }

            break;

        }

    }

}

Config

I forhold til konfigurationen, var det tanken, at man kunne angive denne i ~/config/SkybrudFeedback.config, men dette er endnu ikke blevet implementeret. Feedback-modulet kører derfor med en fast konfiguration.

Statuses

Konfiguration definerer tre valgmuligheder ift. til en kommentar's status. I standardkonfigurationen er der defineres disse tre:

  • New (ny)
  • In progress (inprogress)
  • Closed (closed)

En ny kommentar vil indledelsesvist blive markeret som New, mens en redaktør i backoffice efterfølgende kan ændre til en anden status - eller tilbage til New for den sags skyld.

Profiles

Konfigurationen definerer også en eller flere profiler. Feedback-modulet har en standardprofil for hele løsningen, men det er desuden muligt, at definere et profil for et givent site, som så tager over i stedet.

Ratings

Hver enkelt profil definerer en række ratings, som det er muligt for brugeren af hjemmesiden at vælge mellem, når han eller hun skal tilføje en ny kommentar. I den globale standardprofil er der defineret følgende ratings:

  • Positive (positive)
  • Negative (negative)
Konfigurationsfil

Planen var oprindeligt, at der skulle være en konfigurationsfil i løsning, som blev brugt som udgangspunkt, men at konfiguration (i hukommelsen) så senere (fx ved app start) kunne ændres fra koden. Delen med konfigurationsfilen er endnu ikke blevet implementeret, men det muligt, at ændre konfiguration fra koden.

Kodeeksempler

Ifølge standardprofilen er brugerens emailadresse obligatorisk, mens navn og selve beskeden er valgfri. Hvis du fx vil ændre standardprofilen til, at emailadresse også er valgfri, kan det eksempelvis gøres med følgende stump kode:

#!C
FeedbackConfig.Current.Profiles[0].Fields.Email = FeedbackFieldType.Optional;

Alternativt kan der tilføjes en ny profil for et givent site - dette kan gøres med nedenstående stump kode:

#!C
FeedbackConfig.Current.Profiles.Add(1234, new FeedbackProfile {
    Fields = new FeedbackProfileFields {
        Name = FeedbackFieldType.Optional,
        Email = FeedbackFieldType.Optional,
        Comment = FeedbackFieldType.Optional
    },
    Ratings = FeedbackConfig.Current.Profiles[0].Ratings
});

I eksemplet tilføjes en ny profil for sitet med id'et 1234, hvor alle tre felter (email, navn og besked) sættes til valgfri. Profilen definerer ligeledes de mulige rating, men her refereres blot de rating, der er defineret for standardprofilen.

skybrud.umbraco.feedback's People

Contributors

abjerner avatar nikcio avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

Forkers

nikcio

skybrud.umbraco.feedback's Issues

It should be possible to delete feedback before a certain date

This could be by letting the editor specify a date via the UI, and then all feedback before that date will be deleted (or archived).

Deletion at the database level could be something like this:

DELETE FROM SkybrudFeedback WHERE Created < '2019-03-01 00:00:00';

Pagination should be fixed

Right now, it seems that the pagination will show al ink for each and every page. So with 103 pages (as in the screenshot below), the pagination takes up quite a lot of space.

image

Feedback property editor: Handle filtering and sorting at the database level

Right now most of the sorting and filtering are done in C#, which means that the controller first gets all entries for a given site (which can be a lot over time), and then applies filtering and sorting.

The controller below should be updated to handle filtering and sorting at the database level, as this should be a lot faster.

https://github.com/skybrud/Skybrud.Umbraco.Feedback/blob/master/src/Skybrud.Umbraco.Feedback/Controllers/BackofficeController.cs#L73

https://github.com/skybrud/Skybrud.Umbraco.Feedback/blob/master/src/Skybrud.Umbraco.Feedback/Controllers/BackofficeController.cs#L110

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.