rikihistory 0.4
riki history page
Requires Python: >=3.7

#Page History Feature

Implementer: 
John Besse

Python: >=3.7


#Problem

There was no way to see a record of changes made to a page in Riki system

#Solution

A history markdown file is created in parallel to the page markdown file in a content folder (e.g. content\page.md) it 
is tracking and stored with other history files in a history folder

#Requirement

A user would like a history page in order to see a record of changes made to a Riki page.

#Usage Example 1

    Input:	record_history(r'content\fakepageurl.md', 'action', 'Claude')
    Output:	'content/history\\fakepageurl_hist.md'
    Text appended to content\history\fakepageurl_hist.md: â€˜action by Claude Sat May 2 18:53:32 2020â€™

#Usage Example 2

    Input:	histurl('wiki-page')
    Output:	'history/wiki-page_hist'

#Usage Example 3

    Navigate to directory with rkhist.py
    Command Line Input: python rkhist.py -e content\fakepageurl.md moved Ted
    Output: none
    Text appended to content\history\fakepageurl_hist.md: â€˜moved by Ted Sun May 10 10:56:30 2020â€™ 


#User Manual

#In Riki sysem

    1. Call record_history() in any Riki Flask route with path of page object, desired action description, and user ID.
    2. A history page markdown file is created with provided information in content\history subfolder.

#Command line

    Run rkhist.py in its directory with -e or --entry option and 3 arguments to make a history file
        1. path: file name of page markdown file in content directory (ex: content\fakepageurl.md)
        2. action: a descripton of action performed on page (ex: edited)
        3. user: user name or ID (ex: Ted)

#Implementation Goal

To create a module that when a page is edited or moved an entry composed of the action performed and the userâ€™s name is 
written to a history markdown file via a file path derived from a Page object. 

#Implementation Details

   A public function was chosen to implement this feature so that it could be included into any Flask route API with one
    line of code in the Riki system. Markdown files with Page object formatting are used to allow history information to
     be processed with the same tools that process the wiki pages. An example is this featureâ€™s Jinja template, which is
      composed of only the URL and page parameters in two blocks. These files are also kept in a separate history folder
       to segregate them from the page files if they need to be processed differently.

   A history entry is created in a markdown file by record_history(). A new file is created if there is not one present,
    and record_history() returns this fileâ€™s path for testing purposes. It creates the files with the same methods as 
    the wiki.core.Page.save() method in Riki, so no additional modules are needed except Python time module for the time
     and date stamp. To complete an entry, the action and user name are concatenated with a time and written to the 
     markdown file. In this implementation, these calls are made in an actionâ€™s Flask route function to synchronize them
      with the actionâ€™s API call. 

   The required parameters are a markdown fileâ€™s path, an action name string, and a user name string. They are as 
   abstract as possible to allow for flexibility implementing history entries. They could be generated by any function 
   that returns a string. In Riki, the user name is generated by current_user.get_id(). The path parameter from a Page 
   object get method also allows any information in the Page to be transcribed into the history file if necessary. The 
   history markdown file is in Page object format, so they can be easily displayed through a Flask API and Jinja 
   template.

   The record_history() and histurl() functions form the basis of creating history pages. Any function that wishes to 
   create a history entry only needs one line of code to call record_history(). This keeps the overall lines of code low
    and reduces complexity. Some Riki operations that modify pages need to be performed on the history page as well to 
    maintain coherency, such as move or delete. In these cases, the respective method call is performed with the page 
    URL modified by histurl() to also update the history page. 

#Modules 


#1. Files:

#rikihistory\history.py

	contains histurl and record_history methods and doctests

#rikihistory\rkhist.py

    command line script that creates history entry with command line parameters

#rikihistory\tests\test_history.py

	Unit tests to implement the test plan

#rikihistory\README.md

	README file

#history_pydoc.html

    Pydoc file

#2. Methods:

#rikihistory.histurl(url: string): string

    This creates and returns the history file name using its associated pageâ€™s file name. This was a frequent operation
    and reduced complexity using a function.

#rikihistory.record_history(path: string, action: string, user: string): string

	This function creates or appends a history page markdown file from a Riki page mardown file located in the â€˜contentâ€™
	folder and whose path is the path parameter. Files are kept in a separate â€˜historyâ€™ subfolder in the â€˜contentâ€™ 
	folder also derived from the path parameter. It formats new history markdown files to be compatible with all Page 
	object operations in the Riki system and initiates it with a â€˜Createdâ€™ entry with user parameter and time from 
	Python time module. All other history entries are concatenated strings composed of the action and user from 
	parameters and the time. It returns the path of the markdown file modified.


#3. Tests

#test_givenRandUserName_whenHistoryRecordMade_thenUserNameInNewEntry (test 1): 

    With an edit made to the page, a new entry will have the name of the editing user.

    Specify a variable to store the user who edits the page.
    Compare the user name added to the history entry.

    A unit test was created in tests\test_history.py (lines 24-30). Mock was used to create a mock Page object with a
    path to a page in the content folder (lines 6-8). A unique user name was created by appending a random integer 
    0-1000 (lines 10, 25). A history was recorded with this information (line 26). The history file written to was read
    (lines 27-29). If the unique user was in the file (line 30), then a new record was recorded with the user parameter.

#test_givenMockPage_whenHistoryRecordMade_thenHistFilePathReturned (test 2): 

    With a history record made for a page, it will modify a history file with a file name derived from its associate 
    page in the correct directory location.

    1. Specify a variable to store the expected path with directory and file name.
    2. Compare the path returned by the record_history() function to the expected path.

    A unit test was created in tests\test_history.py (lines 41-44). Mock was used to create a mock Page object with a 
    specified path (line 43) to a page in the content folder (lines 6-8). A history record was made using the mocked 
    Page and two meaningless string parameters (line 42). If the specified path and the path returned by 
    record_history() are equal (line 44), then the file name and directory are correct because this path is used in the
    function to make the file (wiki\core.py line 95-96).

#test_givenRandAction_whenAddingRecordToExistingHistoryFile_thenActionInNewEntry (test 3): 

    Same as Test 2 but checking if the action name was used instead of user name.

    A unit test was created in Test\test_history.py (lines 32-39). It is the same as Test 2 but a random action name was
    used (line 33).

#test_givenWikiPageURL_thenReturnHistWikiPageURL (test 4): 

    With a page url, it will modify it and return the url of the pageâ€™s associated history file.

    1. Specify a variable to store the expected history page url.
    2. Compare it to the url returned by histurl().

    A unit test was created in Test\test_history.py (lines 19-22). It checks if the string generate by histurl() matches
    the expected string.

#4. Lines of Code

    54