Extension { #name : #LeDatabase } { #category : #'*MiniDocs' } LeDatabase >> addPageCopy: aLePage [ | page | page := LePage new. page title: ('Copy of ', aLePage title,' (id: ', (page uid asString copyFrom: 1 to: 8), ')'). aLePage children do: [ :snippet | | newSnippet | newSnippet := snippet class new. newSnippet className = 'LeTextSnippet' ifTrue: [ newSnippet string: snippet contentAsString ]. newSnippet className = 'LePharoSnippet' ifTrue: [ newSnippet code: snippet contentAsString ]. newSnippet uid: LeUID new. page addSnippet: newSnippet. newSnippet database: self. self registerSnippet: newSnippet ]. self addPage: page. ^ page ] { #category : #'*MiniDocs' } LeDatabase >> addPageFromMarkdeep: markdeepDocTree withRemote: externalDocLocation [ | remoteMetadata divSnippets snippets page | divSnippets := (markdeepDocTree xpath: '//div[@st-class]') asOrderedCollection collect: [ :xmlElement | xmlElement postCopy ]. snippets := divSnippets collect: [ :xmlElement | (xmlElement attributes at: 'st-class') = 'LeTextSnippet' ifTrue: [ LeTextSnippet new contentFrom: xmlElement ] ifFalse: [ (xmlElement attributes at: 'st-class') = 'LePharoSnippet' ifTrue: [ LePharoSnippet new contentFrom: xmlElement ] ] ]. remoteMetadata := Markdeep new metadataFromXML: markdeepDocTree. page := LePage new title: (remoteMetadata at: 'title'); basicUid: (UUID fromString36: (remoteMetadata at: 'id')); createTime: (LeTime new time: (remoteMetadata at: 'created') asDateAndTime); editTime: (LeTime new time: (remoteMetadata at: 'modified') asDateAndTime); latestEditTime: (LeTime new time: (remoteMetadata at: 'modified') asDateAndTime); createEmail: (remoteMetadata at: 'creator'); editEmail: (remoteMetadata at: 'modifier'). snippets do: [ :snippet | page addSnippet: snippet ]. page children do: [ :snippet | (self hasBlockUID: snippet uid) ifTrue: [ | existingPage | existingPage := self pages detect: [ :pageTemp | pageTemp includesSnippetUid: snippet uid ]. self importErrorForLocal: existingPage withRemote: externalDocLocation. ^ self ] ifFalse: [ snippet database: self. self registerSnippet: snippet ] ]. self addPage: page. ^ page ] { #category : #'*MiniDocs' } LeDatabase >> addPageFromMarkdeepUrl: aString [ | page | page := self detectLocalPageForRemote: aString. page ifNotNil: [ :arg | self importErrorForLocal: page withRemote: aString. ^ self ]. ^ self addPageFromMarkdeep: (self docTreeForLink: aString) withRemote: aString ] { #category : #'*MiniDocs' } LeDatabase >> detectLocalPageForRemote: markdeepDocUrl [ | markdeepHelper id remoteMetadata docTree | markdeepHelper := Markdeep new. docTree := self docTreeForLink: markdeepDocUrl. remoteMetadata := markdeepHelper metadataFromXML: docTree. id := remoteMetadata at: 'id' ifAbsent: [ nil ]. ^ self pageWithID: id ifAbsent: [ ^ nil ]. ] { #category : #'*MiniDocs' } LeDatabase >> docTreeForLink: aString [ ^ (XMLHTMLParser on: aString asUrl retrieveContents) parseDocument ] { #category : #'*MiniDocs' } LeDatabase >> errorCardFor: error [ | keepButton overwriteButton backupButton errorMessageUI localPage errorKey | errorKey := error keys first. localPage := self pageWithID: errorKey. keepButton := BrButton new aptitude: BrGlamorousButtonWithIconAndLabelAptitude; label: 'Keep existing local page'; icon: BrGlamorousVectorIcons cancel; margin: (BlInsets left: 10); action: [ :aButton | aButton phlow spawnObject: localPage. self errors removeKey: errorKey ]. overwriteButton := BrButton new aptitude: BrGlamorousButtonWithIconAndLabelAptitude; label: 'Overwrite with remote page'; icon: BrGlamorousVectorIcons edit; action: [ :aButton | self removePage: localPage. aButton phlow spawnObject: (self addPageFromMarkdeepUrl: (error at: errorKey at: 'remote')). self errors removeKey: errorKey ]; margin: (BlInsets left: 10). backupButton := BrButton new aptitude: BrGlamorousButtonWithIconAndLabelAptitude; label: 'Backup local page'; icon: BrGlamorousVectorIcons changes; action: [ :aButton | ]; margin: (BlInsets left: 10). errorMessageUI := BrEditor new aptitude: BrGlamorousRegularEditorAptitude new ; text: (error at: errorKey at: 'message'); vFitContent. ^ { errorMessageUI. keepButton. overwriteButton. backupButton } ] { #category : #'*MiniDocs' } LeDatabase >> errors [ ^ self optionAt: 'errors' ifAbsentPut: [ Dictionary new ] ] { #category : #'*MiniDocs' } LeDatabase >> gtViewErrorDetailsOn: aView [ ^ aView explicit title: 'Errors' translated; priority: 5; stencil: [ | container | container := BlElement new layout: BlFlowLayout new; constraintsDo: [ :c | c vertical fitContent. c horizontal matchParent ]; padding: (BlInsets all: 10). container addChildren: (self errorCardFor: self errors) ]. ] { #category : #'*MiniDocs' } LeDatabase >> importErrorForLocal: page withRemote: externalDocLocation [ | message id error | id := page uidString. message := String streamContents: [ :stream | stream nextPutAll: 'IMPORTATION ERROR: A page with '; nextPut: Character lf; nextPutAll: ' id: ' , id; nextPut: Character lf; nextPutAll: ' title: ' , page contentAsString; nextPut: Character lf; nextPut: Character lf; nextPutAll: 'already exists in this database and includes overlapping contents'; nextPut: Character lf; nextPutAll: 'with the page you are trying to import from: '; nextPut: Character lf; nextPutAll: externalDocLocation; nextPut: Character lf; nextPut: Character lf; nextPutAll: 'Please choose one of the following options to addres the issue: ' ]. error := Dictionary new at: 'remote' put: externalDocLocation; at: 'message' put: message ; yourself. self errors at: id put: error ] { #category : #'*MiniDocs' } LeDatabase >> options [ ^ options ]