The first milestone finishes the contacts. For that you need almost everything from the modules before it at once: a rule in the core (modules 1.6 and 2.3), a table with a migration (2.4), a page without script (2.5), a permission decision (2.6) and tests on every level (2.7). Hardly anything is new. What’s new is that everything has to fit together in one piece.
The lesson follows the split from lesson 2.11.1:
| Pull request | Branch | Brings | Where in this lesson |
|---|---|---|---|
| 1 | feature/m1-company-model |
companies as entries of their own | section “Pull request 1” |
| 2 | feature/m1-company-migration |
the company texts become companies | section “Pull request 2” |
| 3 | feature/m1-tags |
tags | exercise 1 |
| 4 | feature/m1-search |
search, filter and pages | section “Pull request 4” |
| 5 | feature/m1-delete |
deleting after a confirmation, for management only | exercise 2 |
The acceptance criteria are in your issues from lesson 2.11.1. The test names in this lesson are the ones from the solution there.
Where the Kladde stands
In K1 the company was a text on the contact, and in most Kladdes it still is: a column Company in the table Contacts. That causes
familiar problems. “Kranich Construction”, “kranich construction” and “Kranich Construction” with two spaces are three different texts, and
a list of all contacts of one company finds only the ones written exactly the same.
The examples in this lesson start from this state:
ContactinKladde.CorehasId,Name,Email(the value objectEmailAddress) and the textCompany.- The contact list
/contactssearches and pages through the page’s address, withqfor the search text andpagefor the page (lesson 2.5.4). The filter script from lesson 2.5.11 wraps form and list as a custom element. DELETE /api/contacts/{id}has been reserved for management since lesson 2.6.3.- The roles are called
OfficeandManagementand have been constants since lesson 2.6.3:KladdeRoles.OfficeandKladdeRoles.ManagementinKladde.Web.Auth.
The solutions of modules 2.4 to 2.6 are built further along or differently in a few places. Then carry the steps over like this:
- Tags have been in the table
ContactTagssince lesson 2.4.6, one row per word. That stays; pull request 3 brings only the new rule. In the search,c.Tags.Contains(tag)then becomesdb.ContactTags.Any(t => t.ContactId == c.Id && t.Tag == tag), and the projection reads the tags of a row as in lesson 2.4.9. - The email address is mapped by lesson 2.4.6 with a value converter; the examples here use a complex type with the same column
Email. With the value converter, the search compares the whole address, likeContactDirectoryin lesson 2.4.9; then leave the converter as it is, because the unique indexUX_Contacts_Emailsits on its column. - Search and pages
ContactDirectoryhas had since lessons 2.4.9 and 2.5.4. Pull request 4 then extends that service with company and tag instead of putting a second one beside it. The page in pull request 4 shows only what is added for company and tag; the custom element of the filter script and the live region from lesson 2.5.11 stay in your page. - The confirmation for deleting at
/contacts/{id}/deletehas existed since exercise 3 of lesson 2.6.3, there with the policyKladdePolicies.Management. Exercise 2 adds what it still lacks. - A contact’s number is assigned in the solutions by the Kladde itself (
ValueGeneratedNever, lesson 2.4.6), not by the database.
If your files, classes or folders are named differently, keep your names and carry the steps over.