├── repository ├── TMM-Core.package │ ├── StugDemo.class │ │ ├── README.md │ │ ├── class │ │ │ ├── runLocal.st │ │ │ ├── descriptionStore.st │ │ │ ├── descriptionSchool.st │ │ │ ├── descriptionStartDate.st │ │ │ ├── descriptionStartTime.st │ │ │ ├── descriptionPrice.st │ │ │ ├── demoHelloWorld.st │ │ │ ├── demoHelloWorld5.st │ │ │ ├── demoMongo.st │ │ │ ├── demoMustache1.st │ │ │ ├── demoVoyageMagritte.st │ │ │ ├── demoTemplates.st │ │ │ ├── demoParameters.st │ │ │ ├── demoMustache2List.st │ │ │ ├── demoMustache3List.st │ │ │ ├── demoMustache4Nesting.st │ │ │ └── demoResponseTransformers.st │ │ ├── properties.json │ │ └── methodProperties.json │ ├── TMMFlower.class │ │ ├── README.md │ │ ├── instance │ │ │ ├── name.st │ │ │ ├── description.st │ │ │ ├── name..st │ │ │ ├── asAddDictionary.st │ │ │ ├── asViewDictionary.st │ │ │ ├── description..st │ │ │ ├── asSearchResultDictionaryWIthRank..st │ │ │ ├── copyValuesFrom..st │ │ │ ├── descriptionName.st │ │ │ ├── descriptionDescription.st │ │ │ ├── descriptionLogoFileName.st │ │ │ ├── printOn..st │ │ │ ├── asEditDictionary.st │ │ │ └── asDictionary.st │ │ ├── class │ │ │ ├── isVoyageRoot.st │ │ │ ├── listHeadings.st │ │ │ ├── descriptionContainer.st │ │ │ ├── htmlInputFieldsOn..st │ │ │ ├── makeIndex.st │ │ │ ├── htmlTableOn..st │ │ │ ├── makeSamples.st │ │ │ ├── moustacheList.st │ │ │ ├── htmlTableHeadOn..st │ │ │ ├── submitButtonOn..st │ │ │ ├── moustacheView.st │ │ │ ├── moustacheAdd.st │ │ │ ├── moustacheEdit.st │ │ │ ├── htmlTableBodyOn..st │ │ │ ├── htmlInputFieldOn.description..st │ │ │ └── moustacheListZ.st │ │ ├── properties.json │ │ └── methodProperties.json │ ├── TMMUser.class │ │ ├── README.md │ │ ├── class │ │ │ ├── isVoyageRoot.st │ │ │ ├── listHeadings.st │ │ │ ├── googleUserId..st │ │ │ ├── facebookUserId..st │ │ │ ├── twitterUserId..st │ │ │ ├── descriptionContainer.st │ │ │ ├── findLocalUserId..st │ │ │ ├── userId.providerName..st │ │ │ ├── findGoogleUserId..st │ │ │ └── findUserId.providerName..st │ │ ├── instance │ │ │ ├── userId.st │ │ │ ├── passwordHash.st │ │ │ ├── providerName.st │ │ │ ├── userId..st │ │ │ ├── asEditDictionary.st │ │ │ ├── asViewDictionary.st │ │ │ ├── passwordHash..st │ │ │ ├── providerName..st │ │ │ ├── ownerQueryString.st │ │ │ ├── isSuperuser.st │ │ │ ├── descriptionUserId.st │ │ │ ├── descriptionProviderName.st │ │ │ ├── asSelectTagDictionary.st │ │ │ ├── printOn..st │ │ │ └── asDictionary.st │ │ ├── properties.json │ │ └── methodProperties.json │ ├── properties.json │ ├── TMMDomainObject.class │ │ ├── README.md │ │ ├── instance │ │ │ ├── toString..st │ │ │ └── voyageIdHexString.st │ │ ├── class │ │ │ ├── listHeadings.st │ │ │ ├── templateFieldNamePrefix.st │ │ │ ├── htmlInputFieldsOn..st │ │ │ ├── findByVoyageId..st │ │ │ ├── htmlTableOn..st │ │ │ ├── mustacheList.st │ │ │ ├── htmlTableHeadOn..st │ │ │ ├── submitButtonOn..st │ │ │ ├── mustacheView.st │ │ │ ├── mustacheAdd.st │ │ │ ├── mustacheEdit.st │ │ │ ├── htmlInputFieldOn.description..st │ │ │ └── htmlTableBodyOn..st │ │ ├── properties.json │ │ └── methodProperties.json │ ├── monticello.meta │ │ ├── initializers.st │ │ ├── package │ │ ├── categories.st │ │ └── version │ ├── TeaRequest.extension │ │ ├── properties.json │ │ ├── instance │ │ │ └── znRequest.st │ │ └── methodProperties.json │ ├── TMMFlowerStore.class │ │ ├── instance │ │ │ ├── server.st │ │ │ ├── ssoData.st │ │ │ ├── start.st │ │ │ ├── server..st │ │ │ ├── ssoData..st │ │ │ ├── staticFilePath.st │ │ │ ├── flower.st │ │ │ ├── staticFilePath..st │ │ │ ├── ssoDataAt..st │ │ │ ├── ssoLogout..st │ │ │ ├── isOAuth2Callback..st │ │ │ ├── ssoDataAt.put..st │ │ │ ├── actionRegisterGet..st │ │ │ ├── loggedInUserId..st │ │ │ ├── generateInvalidCallbackRequest.st │ │ │ ├── initializeOn..st │ │ │ ├── twitterSessionFor.put..st │ │ │ ├── twitterOAuth1Service.st │ │ │ ├── actionLogoutGet..st │ │ │ ├── twitterSessionFor.ifAbsent..st │ │ │ ├── addRouteHome.st │ │ │ ├── output.addAll..st │ │ │ ├── actionFlowerView..st │ │ │ ├── serveStaticFilesFrom..st │ │ │ ├── ssoGoogle..st │ │ │ ├── googleSessionFor..st │ │ │ ├── userFromRequest..st │ │ │ ├── ssoFacebook..st │ │ │ ├── addRouteRestart.st │ │ │ ├── facebookSessionFor..st │ │ │ ├── templateContents..st │ │ │ ├── findUserOrNil..st │ │ │ ├── addRouteUserEdit.st │ │ │ ├── findFlowerOrNil..st │ │ │ ├── image.st │ │ │ ├── retrieve.using..st │ │ │ ├── bytesForImageFileName..st │ │ │ ├── actionFlowerList..st │ │ │ ├── actionUserEditForm..st │ │ │ ├── addRouteUpload.st │ │ │ ├── actionLoginGet..st │ │ │ ├── actionUserView..st │ │ │ ├── addRouteUser.st │ │ │ ├── partialsWithTemplateContents..st │ │ │ ├── actionFlowerAddForm..st │ │ │ ├── partialsWithTemplateNamed..st │ │ │ ├── ssoGoogleCallback..st │ │ │ ├── ssoTwitter..st │ │ │ ├── ssoFacebookCallback..st │ │ │ ├── addRoutes.st │ │ │ ├── ssoGoogleData..st │ │ │ ├── addRouteSearch.st │ │ │ ├── ssoFacebookData..st │ │ │ ├── recommendedList.st │ │ │ ├── html.st │ │ │ ├── actionFlowerEdit..st │ │ │ ├── formForImageEntity..st │ │ │ ├── teapotListBlock.st │ │ │ ├── handleGetRequest..st │ │ │ ├── addRouteLoginFacebook.st │ │ │ ├── mustacheNamed..st │ │ │ ├── mustacheAddFor..st │ │ │ ├── mustacheEditFor..st │ │ │ ├── mustacheListFor..st │ │ │ ├── mustacheViewFor..st │ │ │ ├── addRouteLoginGoogle.st │ │ │ ├── addRouteLoginTwitter.st │ │ │ ├── actionFlowerAdd..st │ │ │ ├── actionUserEdit..st │ │ │ ├── ssoTwitterData..st │ │ │ ├── loggedInUser..st │ │ │ ├── actionObectList..st │ │ │ ├── addRouteLogin.st │ │ │ ├── actionLoginPost..st │ │ │ ├── handleQuery..st │ │ │ ├── actionRegisterPost..st │ │ │ ├── ssoTwitterCallback..st │ │ │ ├── addRouteFlower.st │ │ │ ├── addRouteObject.st │ │ │ ├── handlePostRequest..st │ │ │ └── headerList..st │ │ ├── class │ │ │ ├── googleKey.st │ │ │ ├── facebookKey.st │ │ │ ├── twitterKey.st │ │ │ ├── googleSecret.st │ │ │ ├── defaultUrlPrefix.st │ │ │ ├── facebookSecret.st │ │ │ ├── twitterSecret.st │ │ │ ├── clearConfig.st │ │ │ ├── config.st │ │ │ ├── defaultStaticFilePath.st │ │ │ ├── resetMongoDescriptionCache.st │ │ │ ├── buildConfig.st │ │ │ ├── setUpMongo.st │ │ │ ├── runScheme.host.portno.serverPortno.staticFilePath..st │ │ │ └── runLocal.st │ │ ├── properties.json │ │ ├── README.md │ │ └── methodProperties.json │ ├── VOMongoContainer.extension │ │ ├── properties.json │ │ ├── instance │ │ │ └── validateKind..st │ │ └── methodProperties.json │ └── .filetree ├── BaselineOfTMM.package │ ├── BaselineOfTMM.class │ │ ├── README.md │ │ ├── methodProperties.json │ │ ├── instance │ │ │ └── baseline..st │ │ └── properties.json │ ├── properties.json │ ├── monticello.meta │ │ ├── initializers.st │ │ ├── package │ │ ├── categories.st │ │ └── version │ └── .filetree └── .filetree ├── files ├── shtml │ ├── debug.shtml │ ├── page.shtml │ ├── footer.shtml │ ├── user.shtml │ ├── htmlhead.shtml │ ├── user-edit.shtml │ ├── flower-list.shtml │ ├── home.shtml │ ├── register.shtml │ ├── header.shtml │ └── login.shtml ├── img │ ├── gplus.png │ ├── twitter.png │ ├── facebook.png │ ├── 64x64.svg │ └── 242x200.svg └── css │ └── tmm.css ├── .filetree ├── config-sample.json ├── LICENSE.md ├── README.md └── ConfigurationOfTMM.st /repository/TMM-Core.package/StugDemo.class/README.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlower.class/README.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMUser.class/README.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /files/shtml/debug.shtml: -------------------------------------------------------------------------------- 1 |
2 | {{debug}}
3 | 
4 | -------------------------------------------------------------------------------- /repository/TMM-Core.package/properties.json: -------------------------------------------------------------------------------- 1 | { 2 | } 3 | -------------------------------------------------------------------------------- /repository/BaselineOfTMM.package/BaselineOfTMM.class/README.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /repository/BaselineOfTMM.package/properties.json: -------------------------------------------------------------------------------- 1 | { 2 | } 3 | -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMDomainObject.class/README.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /repository/TMM-Core.package/monticello.meta/initializers.st: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /repository/BaselineOfTMM.package/monticello.meta/initializers.st: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /repository/TMM-Core.package/monticello.meta/package: -------------------------------------------------------------------------------- 1 | (name 'TMM-Core') -------------------------------------------------------------------------------- /repository/BaselineOfTMM.package/monticello.meta/package: -------------------------------------------------------------------------------- 1 | (name 'BaselineOfTMM') -------------------------------------------------------------------------------- /.filetree: -------------------------------------------------------------------------------- 1 | {"packageExtension" : ".package", 2 | "propertyFileExtension" : ".json" } -------------------------------------------------------------------------------- /files/img/gplus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yannij/TMM/HEAD/files/img/gplus.png -------------------------------------------------------------------------------- /files/img/twitter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yannij/TMM/HEAD/files/img/twitter.png -------------------------------------------------------------------------------- /files/img/facebook.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yannij/TMM/HEAD/files/img/facebook.png -------------------------------------------------------------------------------- /repository/.filetree: -------------------------------------------------------------------------------- 1 | {"packageExtension" : ".package", 2 | "propertyFileExtension" : ".json" } -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlower.class/instance/name.st: -------------------------------------------------------------------------------- 1 | accessing 2 | name 3 | ^ name -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlower.class/class/isVoyageRoot.st: -------------------------------------------------------------------------------- 1 | testing 2 | isVoyageRoot 3 | ^true -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMUser.class/class/isVoyageRoot.st: -------------------------------------------------------------------------------- 1 | testing 2 | isVoyageRoot 3 | 4 | ^true -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMUser.class/instance/userId.st: -------------------------------------------------------------------------------- 1 | accessing 2 | userId 3 | 4 | ^ userId -------------------------------------------------------------------------------- /repository/TMM-Core.package/TeaRequest.extension/properties.json: -------------------------------------------------------------------------------- 1 | { 2 | "name" : "TeaRequest" } 3 | -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlowerStore.class/instance/server.st: -------------------------------------------------------------------------------- 1 | accessing 2 | server 3 | 4 | ^ server -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlowerStore.class/instance/ssoData.st: -------------------------------------------------------------------------------- 1 | accessing 2 | ssoData 3 | ^ ssoData -------------------------------------------------------------------------------- /repository/TMM-Core.package/monticello.meta/categories.st: -------------------------------------------------------------------------------- 1 | SystemOrganization addCategory: #'TMM-Core'! 2 | -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlower.class/instance/description.st: -------------------------------------------------------------------------------- 1 | accessing 2 | description 3 | ^ description -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlower.class/instance/name..st: -------------------------------------------------------------------------------- 1 | accessing 2 | name: anObject 3 | name := anObject -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMUser.class/instance/passwordHash.st: -------------------------------------------------------------------------------- 1 | accessing 2 | passwordHash 3 | ^ passwordHash -------------------------------------------------------------------------------- /repository/TMM-Core.package/VOMongoContainer.extension/properties.json: -------------------------------------------------------------------------------- 1 | { 2 | "name" : "VOMongoContainer" } 3 | -------------------------------------------------------------------------------- /repository/BaselineOfTMM.package/monticello.meta/categories.st: -------------------------------------------------------------------------------- 1 | SystemOrganization addCategory: #BaselineOfTMM! 2 | -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMUser.class/instance/providerName.st: -------------------------------------------------------------------------------- 1 | accessing 2 | providerName 3 | 4 | ^ providerName -------------------------------------------------------------------------------- /repository/TMM-Core.package/TeaRequest.extension/instance/znRequest.st: -------------------------------------------------------------------------------- 1 | *TMM-Core 2 | znRequest 3 | 4 | ^ znRequest -------------------------------------------------------------------------------- /repository/TMM-Core.package/VOMongoContainer.extension/instance/validateKind..st: -------------------------------------------------------------------------------- 1 | *TMM-Core 2 | validateKind: anObject -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlowerStore.class/instance/start.st: -------------------------------------------------------------------------------- 1 | initialize 2 | start 3 | 4 | self server start 5 | -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMUser.class/instance/userId..st: -------------------------------------------------------------------------------- 1 | accessing 2 | userId: anObject 3 | 4 | userId := anObject -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlowerStore.class/class/googleKey.st: -------------------------------------------------------------------------------- 1 | config 2 | googleKey 3 | 4 | ^self config at: 'google.key' -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlowerStore.class/instance/server..st: -------------------------------------------------------------------------------- 1 | accessing 2 | server: anObject 3 | 4 | server := anObject -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlowerStore.class/instance/ssoData..st: -------------------------------------------------------------------------------- 1 | accessing 2 | ssoData: anObject 3 | ssoData := anObject -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlowerStore.class/instance/staticFilePath.st: -------------------------------------------------------------------------------- 1 | accessing 2 | staticFilePath 3 | ^ staticFilePath -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMDomainObject.class/instance/toString..st: -------------------------------------------------------------------------------- 1 | printing 2 | toString: anOject 3 | 4 | ^self printString -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlower.class/instance/asAddDictionary.st: -------------------------------------------------------------------------------- 1 | converting 2 | asAddDictionary 3 | 4 | ^self asDictionary -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlower.class/instance/asViewDictionary.st: -------------------------------------------------------------------------------- 1 | converting 2 | asViewDictionary 3 | 4 | ^self asDictionary -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlower.class/instance/description..st: -------------------------------------------------------------------------------- 1 | accessing 2 | description: anObject 3 | description := anObject -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlowerStore.class/class/facebookKey.st: -------------------------------------------------------------------------------- 1 | config 2 | facebookKey 3 | 4 | ^self config at: 'facebook.key' -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlowerStore.class/class/twitterKey.st: -------------------------------------------------------------------------------- 1 | config 2 | twitterKey 3 | 4 | ^self config at: 'twitter.key' -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlowerStore.class/instance/flower.st: -------------------------------------------------------------------------------- 1 | route - upload 2 | flower 3 | 4 | ^TMMFlower selectAll first -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMUser.class/instance/asEditDictionary.st: -------------------------------------------------------------------------------- 1 | converting 2 | asEditDictionary 3 | 4 | ^self asDictionary -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMUser.class/instance/asViewDictionary.st: -------------------------------------------------------------------------------- 1 | converting 2 | asViewDictionary 3 | 4 | ^self asDictionary -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMUser.class/instance/passwordHash..st: -------------------------------------------------------------------------------- 1 | accessing 2 | passwordHash: anObject 3 | passwordHash := anObject -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlowerStore.class/class/googleSecret.st: -------------------------------------------------------------------------------- 1 | config 2 | googleSecret 3 | 4 | ^self config at: 'google.secret' -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMDomainObject.class/class/listHeadings.st: -------------------------------------------------------------------------------- 1 | mustache html 2 | listHeadings 3 | 4 | self subclassResponsibility -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlowerStore.class/class/defaultUrlPrefix.st: -------------------------------------------------------------------------------- 1 | config 2 | defaultUrlPrefix 3 | 4 | ^self config at: 'urlPrefix' -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlowerStore.class/class/facebookSecret.st: -------------------------------------------------------------------------------- 1 | config 2 | facebookSecret 3 | 4 | ^self config at: 'facebook.secret' -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlowerStore.class/class/twitterSecret.st: -------------------------------------------------------------------------------- 1 | config 2 | twitterSecret 3 | 4 | ^self config at: 'twitter.secret' -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMUser.class/instance/providerName..st: -------------------------------------------------------------------------------- 1 | accessing 2 | providerName: anObject 3 | 4 | providerName := anObject -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlowerStore.class/instance/staticFilePath..st: -------------------------------------------------------------------------------- 1 | accessing 2 | staticFilePath: anObject 3 | staticFilePath := anObject -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMUser.class/class/listHeadings.st: -------------------------------------------------------------------------------- 1 | mustache html 2 | listHeadings 3 | 4 | ^#( 5 | 'User ID' 6 | 'Provider Name' 7 | ) -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMUser.class/instance/ownerQueryString.st: -------------------------------------------------------------------------------- 1 | accessing 2 | ownerQueryString 3 | 4 | ^ self providerName, ':', self userId -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlowerStore.class/class/clearConfig.st: -------------------------------------------------------------------------------- 1 | config 2 | clearConfig 3 | " 4 | self clearConfig 5 | " 6 | 7 | Config := nil -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlowerStore.class/instance/ssoDataAt..st: -------------------------------------------------------------------------------- 1 | accessing 2 | ssoDataAt: aKey 3 | 4 | ^ self ssoData at: aKey ifAbsent: [ nil ] -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMUser.class/instance/isSuperuser.st: -------------------------------------------------------------------------------- 1 | testing 2 | isSuperuser 3 | 4 | ^ userId = (TMMFlowerStore config at: 'superuser') -------------------------------------------------------------------------------- /repository/TMM-Core.package/StugDemo.class/class/runLocal.st: -------------------------------------------------------------------------------- 1 | 9 Flower Store 2 | runLocal 3 | " 4 | TMMFlowerStore runLocal. 5 | Teapot stopAll. 6 | " 7 | -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMDomainObject.class/instance/voyageIdHexString.st: -------------------------------------------------------------------------------- 1 | printing 2 | voyageIdHexString 3 | 4 | ^self voyageId value printStringHex -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlowerStore.class/class/config.st: -------------------------------------------------------------------------------- 1 | config 2 | config 3 | 4 | Config isNil ifTrue: [ Config := self buildConfig ]. 5 | ^Config -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlowerStore.class/class/defaultStaticFilePath.st: -------------------------------------------------------------------------------- 1 | config 2 | defaultStaticFilePath 3 | 4 | ^self config at: 'staticFilePath' -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlowerStore.class/instance/ssoLogout..st: -------------------------------------------------------------------------------- 1 | sso 2 | ssoLogout: request 3 | 4 | request session removeAttribute: 'twitter-session' -------------------------------------------------------------------------------- /repository/TMM-Core.package/.filetree: -------------------------------------------------------------------------------- 1 | { 2 | "noMethodMetaData" : true, 3 | "separateMethodMetaAndSource" : false, 4 | "useCypressPropertiesFile" : true } 5 | -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlowerStore.class/instance/isOAuth2Callback..st: -------------------------------------------------------------------------------- 1 | sso 2 | isOAuth2Callback: aRequest 3 | 4 | ^aRequest uri queryKeys includes: 'code' -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlowerStore.class/instance/ssoDataAt.put..st: -------------------------------------------------------------------------------- 1 | accessing 2 | ssoDataAt: aKey put: aValue 3 | 4 | ^ self ssoData at: aKey put: aValue -------------------------------------------------------------------------------- /repository/BaselineOfTMM.package/.filetree: -------------------------------------------------------------------------------- 1 | { 2 | "noMethodMetaData" : true, 3 | "separateMethodMetaAndSource" : false, 4 | "useCypressPropertiesFile" : true } 5 | -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlower.class/class/listHeadings.st: -------------------------------------------------------------------------------- 1 | mustache html 2 | listHeadings 3 | 4 | ^#( 5 | 'Name' 6 | 'Description' 7 | 'Logo File Name' 8 | ) -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlowerStore.class/instance/actionRegisterGet..st: -------------------------------------------------------------------------------- 1 | route - login 2 | actionRegisterGet: req 3 | 4 | ^(self headerList: req) 5 | yourself -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMDomainObject.class/class/templateFieldNamePrefix.st: -------------------------------------------------------------------------------- 1 | mustache html 2 | templateFieldNamePrefix 3 | 4 | ^self magritteDescription collectionName -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlower.class/instance/asSearchResultDictionaryWIthRank..st: -------------------------------------------------------------------------------- 1 | converting 2 | asSearchResultDictionaryWIthRank: anIndex 3 | 4 | ^self asEditDictionary -------------------------------------------------------------------------------- /repository/TMM-Core.package/TeaRequest.extension/methodProperties.json: -------------------------------------------------------------------------------- 1 | { 2 | "class" : { 3 | }, 4 | "instance" : { 5 | "znRequest" : "YanniChiu 1/18/2015 22:42" } } 6 | -------------------------------------------------------------------------------- /repository/BaselineOfTMM.package/BaselineOfTMM.class/methodProperties.json: -------------------------------------------------------------------------------- 1 | { 2 | "class" : { 3 | }, 4 | "instance" : { 5 | "baseline:" : "YanniChiu 4/26/2015 17:31" } } 6 | -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlowerStore.class/instance/loggedInUserId..st: -------------------------------------------------------------------------------- 1 | route - login 2 | loggedInUserId: req 3 | 4 | ^ req znRequest session attributeAt: 'userid' ifAbsent: [ nil ] -------------------------------------------------------------------------------- /repository/TMM-Core.package/VOMongoContainer.extension/methodProperties.json: -------------------------------------------------------------------------------- 1 | { 2 | "class" : { 3 | }, 4 | "instance" : { 5 | "validateKind:" : "YanniChiu 9/17/2013 22:09" } } 6 | -------------------------------------------------------------------------------- /repository/BaselineOfTMM.package/BaselineOfTMM.class/instance/baseline..st: -------------------------------------------------------------------------------- 1 | accessing 2 | baseline: spec 3 | 4 | spec 5 | for: #pharo 6 | do: [ 7 | spec package: 'TMM-Core' ]. -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlowerStore.class/instance/generateInvalidCallbackRequest.st: -------------------------------------------------------------------------------- 1 | sso 2 | generateInvalidCallbackRequest 3 | 4 | self error: 'TODO generateInvalidCallbackRequest' -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMUser.class/class/googleUserId..st: -------------------------------------------------------------------------------- 1 | instance creation 2 | googleUserId: aUserId 3 | 4 | ^ self new 5 | providerName: 'google'; 6 | userId: aUserId; 7 | yourself -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMUser.class/class/facebookUserId..st: -------------------------------------------------------------------------------- 1 | instance creation 2 | facebookUserId: aUserId 3 | 4 | ^ self new 5 | providerName: 'facebook'; 6 | userId: aUserId; 7 | yourself -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMUser.class/class/twitterUserId..st: -------------------------------------------------------------------------------- 1 | instance creation 2 | twitterUserId: aUserId 3 | 4 | ^ self new 5 | providerName: 'twitter'; 6 | userId: aUserId; 7 | yourself -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlowerStore.class/instance/initializeOn..st: -------------------------------------------------------------------------------- 1 | initialize 2 | initializeOn: aConfiguration 3 | 4 | server := Teapot configure: aConfiguration. 5 | ssoData := Dictionary new. 6 | -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlowerStore.class/instance/twitterSessionFor.put..st: -------------------------------------------------------------------------------- 1 | sso 2 | twitterSessionFor: aRequest put: anObject 3 | 4 | ^ aRequest session attributeAt: 'twitter-session' put: anObject -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlowerStore.class/instance/twitterOAuth1Service.st: -------------------------------------------------------------------------------- 1 | sso 2 | twitterOAuth1Service 3 | 4 | ^ ZnOAuth1Service new 5 | providerAccount: (self ssoDataAt: 'twitter') ; 6 | yourself -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlowerStore.class/instance/actionLogoutGet..st: -------------------------------------------------------------------------------- 1 | route - login 2 | actionLogoutGet: req 3 | 4 | req znRequest session removeAttribute: 'userid'. 5 | ^self ssoLogout: req znRequest 6 | -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlowerStore.class/instance/twitterSessionFor.ifAbsent..st: -------------------------------------------------------------------------------- 1 | sso 2 | twitterSessionFor: aRequest ifAbsent: aBlock 3 | 4 | ^ aRequest session attributeAt: 'twitter-session' ifAbsent: aBlock -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlowerStore.class/instance/addRouteHome.st: -------------------------------------------------------------------------------- 1 | route - main 2 | addRouteHome 3 | 4 | self server 5 | GET: '/' -> [:req | self headerList: req ]; 6 | output: (self mustacheNamed: 'home'). 7 | -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMUser.class/class/descriptionContainer.st: -------------------------------------------------------------------------------- 1 | magritte 2 | descriptionContainer 3 | 4 | ^VOMongoContainer new 5 | collectionName: 'user'; 6 | kind: TMMUser; 7 | yourself -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlower.class/class/descriptionContainer.st: -------------------------------------------------------------------------------- 1 | magritte 2 | descriptionContainer 3 | 4 | ^VOMongoContainer new 5 | collectionName: 'flower'; 6 | kind: TMMFlower; 7 | yourself -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlower.class/instance/copyValuesFrom..st: -------------------------------------------------------------------------------- 1 | converting 2 | copyValuesFrom: req 3 | 4 | self 5 | name: (req at: 'flowerName'); 6 | description: (req at: 'flowerDescription'); 7 | yourself. 8 | -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlowerStore.class/instance/output.addAll..st: -------------------------------------------------------------------------------- 1 | utility 2 | output: req addAll: aDictionary 3 | 4 | ^Dictionary new 5 | addAll: (self headerList: req); 6 | addAll: aDictionary; 7 | yourself -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMUser.class/class/findLocalUserId..st: -------------------------------------------------------------------------------- 1 | instance creation 2 | findLocalUserId: aUserId 3 | 4 | ^ TMMUser selectOne: { 5 | 'providerName' -> 'local'. 6 | 'userId' -> aUserId 7 | } asDictionary -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMUser.class/class/userId.providerName..st: -------------------------------------------------------------------------------- 1 | instance creation 2 | userId: aUserId providerName: providerName 3 | 4 | ^ self new 5 | providerName: providerName; 6 | userId: aUserId; 7 | yourself -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlower.class/class/htmlInputFieldsOn..st: -------------------------------------------------------------------------------- 1 | template 2 | htmlInputFieldsOn: anXmlWriter 3 | 4 | self basicNew magritteDescription do: [ :each | 5 | self htmlInputFieldOn: anXmlWriter description: each ] -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlowerStore.class/instance/actionFlowerView..st: -------------------------------------------------------------------------------- 1 | route - flower 2 | actionFlowerView: req 3 | | model | 4 | 5 | model := self findFlowerOrNil: req. 6 | ^self output: req addAll: model asViewDictionary -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMUser.class/class/findGoogleUserId..st: -------------------------------------------------------------------------------- 1 | instance creation 2 | findGoogleUserId: aUserId 3 | 4 | ^ TMMUser selectOne: { 5 | 'providerName' -> 'google'. 6 | 'userId' -> aUserId 7 | } asDictionary -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlower.class/class/makeIndex.st: -------------------------------------------------------------------------------- 1 | example data 2 | makeIndex 3 | " 4 | db.Flower.ensureIndex( { name: ""text"", description: ""text"" } ) 5 | 6 | db.Flower.find( { $text: { $search: ""test5"" } } ) 7 | " -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlower.class/instance/descriptionName.st: -------------------------------------------------------------------------------- 1 | magritte 2 | descriptionName 3 | 4 | ^ MAStringDescription new 5 | accessor: #name; 6 | label: 'Name'; 7 | priority: 100; 8 | yourself -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlowerStore.class/instance/serveStaticFilesFrom..st: -------------------------------------------------------------------------------- 1 | initialize 2 | serveStaticFilesFrom: aLocalFilePath 3 | 4 | self staticFilePath: aLocalFilePath. 5 | self server serveStatic: '/' from: aLocalFilePath. 6 | -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlowerStore.class/instance/ssoGoogle..st: -------------------------------------------------------------------------------- 1 | sso 2 | ssoGoogle: request 3 | 4 | | googleSession | 5 | 6 | googleSession := self googleSessionFor: request. 7 | 8 | ^ googleSession authenticationUrl asString -------------------------------------------------------------------------------- /repository/TMM-Core.package/StugDemo.class/class/descriptionStore.st: -------------------------------------------------------------------------------- 1 | code snippits 2 | descriptionStore 3 | 4 | ^VOMongoToOneDescription new 5 | attributeName: 'store'; 6 | accessor: #store; 7 | "beLazy;" 8 | yourself -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMDomainObject.class/class/htmlInputFieldsOn..st: -------------------------------------------------------------------------------- 1 | mustache html 2 | htmlInputFieldsOn: anXmlWriter 3 | 4 | self basicNew magritteDescription do: [ :each | 5 | self htmlInputFieldOn: anXmlWriter description: each ] -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlowerStore.class/instance/googleSessionFor..st: -------------------------------------------------------------------------------- 1 | sso 2 | googleSessionFor: aRequest 3 | ^ aRequest session 4 | attributeAt: 'google-session' 5 | ifAbsentPut: [ ZnOAuth2Session google: (self ssoDataAt: 'google') ] -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlowerStore.class/instance/userFromRequest..st: -------------------------------------------------------------------------------- 1 | route - user 2 | userFromRequest: req 3 | | voyageId model | 4 | 5 | voyageId := req at: 'userVoyageId'. 6 | model := TMMUser findByVoyageId: voyageId. 7 | ^ model -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMUser.class/instance/descriptionUserId.st: -------------------------------------------------------------------------------- 1 | magritte 2 | descriptionUserId 3 | 4 | ^ MAStringDescription new 5 | accessor: #userId; 6 | label: 'User ID'; 7 | priority: 100; 8 | yourself -------------------------------------------------------------------------------- /repository/BaselineOfTMM.package/monticello.meta/version: -------------------------------------------------------------------------------- 1 | (name 'BaselineOfTMM-YanniChiu.1' message 'Initial version' id 'ed2d9129-3a89-47eb-acb2-c3fc227ca75e' date '26 April 2015' time '5:38:13.071777 pm' author 'YanniChiu' ancestors () stepChildren ()) -------------------------------------------------------------------------------- /repository/TMM-Core.package/StugDemo.class/class/descriptionSchool.st: -------------------------------------------------------------------------------- 1 | code snippits 2 | descriptionSchool 3 | 4 | ^VOMongoToOneDescription new 5 | attributeName: 'school'; 6 | accessor: #school; 7 | "beLazy;" 8 | yourself -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlowerStore.class/instance/ssoFacebook..st: -------------------------------------------------------------------------------- 1 | sso 2 | ssoFacebook: request 3 | 4 | | facebookSession | 5 | 6 | facebookSession := self facebookSessionFor: request. 7 | 8 | ^ facebookSession authenticationUrl asString -------------------------------------------------------------------------------- /repository/TMM-Core.package/StugDemo.class/class/descriptionStartDate.st: -------------------------------------------------------------------------------- 1 | code snippits 2 | descriptionStartDate 3 | 4 | ^ MADateDescription new 5 | accessor: #startDate; 6 | label: 'Start Date'; 7 | priority: 210; 8 | yourself -------------------------------------------------------------------------------- /repository/TMM-Core.package/StugDemo.class/class/descriptionStartTime.st: -------------------------------------------------------------------------------- 1 | code snippits 2 | descriptionStartTime 3 | 4 | ^ MATimeDescription new 5 | accessor: #startTime; 6 | label: 'Start Time'; 7 | priority: 215; 8 | yourself -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlowerStore.class/instance/addRouteRestart.st: -------------------------------------------------------------------------------- 1 | route - main 2 | addRouteRestart 3 | 4 | self server 5 | GET: '/restart' -> [:req | Smalltalk snapshot: false andQuit: true]; 6 | output: (self mustacheNamed: 'home'). 7 | -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlowerStore.class/instance/facebookSessionFor..st: -------------------------------------------------------------------------------- 1 | sso 2 | facebookSessionFor: aRequest 3 | ^ aRequest session 4 | attributeAt: 'facebook-session' 5 | ifAbsentPut: [ ZnOAuth2Session facebook: (self ssoDataAt: 'facebook') ] -------------------------------------------------------------------------------- /repository/TMM-Core.package/StugDemo.class/class/descriptionPrice.st: -------------------------------------------------------------------------------- 1 | code snippits 2 | descriptionPrice 3 | 4 | ^ MANumberDescription new 5 | accessor: #price; 6 | label: 'Price '; 7 | priority: 200; 8 | bePositive; 9 | yourself -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlower.class/instance/descriptionDescription.st: -------------------------------------------------------------------------------- 1 | magritte 2 | descriptionDescription 3 | 4 | ^ MAMemoDescription new 5 | accessor: #description; 6 | label: 'Description'; 7 | priority: 110; 8 | yourself -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMUser.class/class/findUserId.providerName..st: -------------------------------------------------------------------------------- 1 | instance creation 2 | findUserId: aUserId providerName: providerName 3 | 4 | ^ TMMUser selectOne: { 5 | 'providerName' -> providerName. 6 | 'userId' -> aUserId 7 | } asDictionary -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlowerStore.class/instance/templateContents..st: -------------------------------------------------------------------------------- 1 | utility 2 | templateContents: aTemplateName 3 | 4 | ^ self staticFilePath asFileReference / 'shtml' / (aTemplateName, '.shtml' ) 5 | readStreamDo: [ :stream | stream contents ]. 6 | -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMUser.class/instance/descriptionProviderName.st: -------------------------------------------------------------------------------- 1 | magritte 2 | descriptionProviderName 3 | 4 | ^ MAStringDescription new 5 | accessor: #providerName; 6 | label: 'Provider Name'; 7 | priority: 110; 8 | yourself -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlower.class/instance/descriptionLogoFileName.st: -------------------------------------------------------------------------------- 1 | magritte 2 | descriptionLogoFileName 3 | 4 | ^ MAStringDescription new 5 | accessor: #logoFileName; 6 | label: 'Logo File Name'; 7 | priority: 120; 8 | yourself -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMDomainObject.class/class/findByVoyageId..st: -------------------------------------------------------------------------------- 1 | mongo query 2 | findByVoyageId: aVoyageId 3 | | id model | 4 | 5 | id := Integer readFrom: aVoyageId base: 16. 6 | model := self selectOne: { '_id' -> (OID value: id) } asDictionary. 7 | 8 | ^model -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlowerStore.class/instance/findUserOrNil..st: -------------------------------------------------------------------------------- 1 | route - user 2 | findUserOrNil: req 3 | | voyageId | 4 | 5 | voyageId := Integer readFrom: (req at: #voyageId) base: 16. 6 | ^ TMMUser selectOne: { '_id' -> (OID value: voyageId) } asDictionary 7 | -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlowerStore.class/instance/addRouteUserEdit.st: -------------------------------------------------------------------------------- 1 | route - user 2 | addRouteUserEdit 3 | 4 | self server 5 | GET: '/user-edit/' -> [:req | 6 | self actionUserEditForm: req ]; 7 | output: (self mustacheNamed: 'user-edit'); 8 | yourself -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlowerStore.class/class/resetMongoDescriptionCache.st: -------------------------------------------------------------------------------- 1 | mongo 2 | resetMongoDescriptionCache 3 | " 4 | self resetMongoDescriptionCache 5 | " 6 | 7 | VOMongoRepository resetDescriptionOf: TMMFlower. 8 | VOMongoRepository resetDescriptionOf: TMMUser. 9 | -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlowerStore.class/instance/findFlowerOrNil..st: -------------------------------------------------------------------------------- 1 | route - flower 2 | findFlowerOrNil: req 3 | | voyageId | 4 | 5 | voyageId := Integer readFrom: (req at: #voyageId) base: 16. 6 | ^ TMMFlower selectOne: { '_id' -> (OID value: voyageId) } asDictionary 7 | -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlowerStore.class/class/buildConfig.st: -------------------------------------------------------------------------------- 1 | config 2 | buildConfig 3 | " 4 | self buildConfig 5 | 6 | Example: 7 | See class comment because double quotes are needed 8 | " 9 | 10 | ^NeoJSONReader fromString: ('config.json' asFileReference contents) -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlowerStore.class/instance/image.st: -------------------------------------------------------------------------------- 1 | route - upload 2 | image 3 | | fileName | 4 | 5 | fileName := 'like.png'. 6 | logoFileName ifNotNil: [ fileName := logoFileName ]. 7 | ^ image := ZnEntity with: (self bytesForImageFileName: fileName) type: 'image/png' 8 | -------------------------------------------------------------------------------- /repository/TMM-Core.package/StugDemo.class/class/demoHelloWorld.st: -------------------------------------------------------------------------------- 1 | 1 Hello World 2 | demoHelloWorld 3 | " 4 | http://smalltalkhub.com/#!/~zeroflag/Teapot 5 | 6 | Teapot stopAll. self demoHelloWorld 7 | " 8 | 9 | Teapot on 10 | GET: '/welcome' -> 'Hello World!'; 11 | start. 12 | -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlowerStore.class/class/setUpMongo.st: -------------------------------------------------------------------------------- 1 | mongo 2 | setUpMongo 3 | " 4 | self setUpMongo 5 | " 6 | | repo | 7 | 8 | repo := VOMongoRepository 9 | host: VOMongoRepository defaultHost 10 | database: 'tmm'. 11 | 12 | VORepository setRepository: repo. 13 | -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlowerStore.class/instance/retrieve.using..st: -------------------------------------------------------------------------------- 1 | utility 2 | retrieve: aModelClass using: req 3 | | id model | 4 | 5 | id := Integer readFrom: (req at: #voyageId) base: 16. 6 | model := aModelClass selectOne: { '_id' -> (OID value: id) } asDictionary. 7 | 8 | ^model -------------------------------------------------------------------------------- /files/shtml/page.shtml: -------------------------------------------------------------------------------- 1 | 2 | 3 | {{> htmlhead }} 4 | 5 |
6 | {{> header }} 7 | {{> content }} 8 |
9 | {{> footer }} 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlowerStore.class/instance/bytesForImageFileName..st: -------------------------------------------------------------------------------- 1 | route - upload 2 | bytesForImageFileName: aString 3 | | imageType fileContents | 4 | 5 | imageType := 'png'. 6 | fileContents := aString asFileReference binaryReadStreamDo: [:stream | stream contents ]. 7 | ^ fileContents -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMUser.class/instance/asSelectTagDictionary.st: -------------------------------------------------------------------------------- 1 | converting 2 | asSelectTagDictionary 3 | | voyageId | 4 | 5 | voyageId := self voyageId value printStringHex. 6 | 7 | ^ Dictionary new 8 | at: 'userVoyageId' put: voyageId; 9 | at: 'userId' put: self userId; 10 | yourself -------------------------------------------------------------------------------- /repository/TMM-Core.package/StugDemo.class/class/demoHelloWorld5.st: -------------------------------------------------------------------------------- 1 | 1 Hello World 2 | demoHelloWorld5 3 | " 4 | Teapot stopAll. self demoHelloWorld5 5 | " 6 | 7 | 1701 to: 1706 do: [ :port | 8 | (Teapot configure: { #port -> port }) 9 | GET: '/' -> ('Hello ', port asString); 10 | start. 11 | ] 12 | -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlower.class/instance/printOn..st: -------------------------------------------------------------------------------- 1 | printing 2 | printOn: aStream 3 | 4 | super printOn: aStream. 5 | 6 | aStream 7 | nextPut: $(; 8 | nextPutAll: self name printString; 9 | nextPutAll: ', '; 10 | nextPutAll: self description printString; 11 | nextPut: $); 12 | yourself -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlower.class/class/htmlTableOn..st: -------------------------------------------------------------------------------- 1 | template 2 | htmlTableOn: anXmlWriter 3 | 4 | anXmlWriter 5 | tag: 'table' 6 | attributes: {'class'->'report table table-striped table-condensed table-hover'} 7 | with: [ 8 | self htmlTableHeadOn: anXmlWriter. 9 | self htmlTableBodyOn: anXmlWriter] -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMUser.class/instance/printOn..st: -------------------------------------------------------------------------------- 1 | printing 2 | printOn: aStream 3 | 4 | super printOn: aStream. 5 | 6 | aStream 7 | nextPut: $(; 8 | nextPutAll: self providerName printString; 9 | nextPutAll: ', '; 10 | nextPutAll: self userId printString; 11 | nextPut: $); 12 | yourself -------------------------------------------------------------------------------- /repository/TMM-Core.package/StugDemo.class/properties.json: -------------------------------------------------------------------------------- 1 | { 2 | "category" : "TMM-Core", 3 | "classinstvars" : [ 4 | ], 5 | "classvars" : [ 6 | ], 7 | "commentStamp" : "", 8 | "instvars" : [ 9 | ], 10 | "name" : "StugDemo", 11 | "pools" : [ 12 | ], 13 | "super" : "Object", 14 | "type" : "normal" } 15 | -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMDomainObject.class/class/htmlTableOn..st: -------------------------------------------------------------------------------- 1 | mustache html 2 | htmlTableOn: anXmlWriter 3 | 4 | anXmlWriter 5 | tag: 'table' 6 | attributes: {'class'->'report table table-striped table-condensed table-hover'} 7 | with: [ 8 | self htmlTableHeadOn: anXmlWriter. 9 | self htmlTableBodyOn: anXmlWriter] -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlowerStore.class/instance/actionFlowerList..st: -------------------------------------------------------------------------------- 1 | route - flower 2 | actionFlowerList: req 3 | | result | 4 | 5 | result := Dictionary new. 6 | 7 | result 8 | at: 'list' 9 | put: (TMMFlower selectAll collect: [:model | model asViewDictionary]). 10 | 11 | ^self output: req addAll: result -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlower.class/instance/asEditDictionary.st: -------------------------------------------------------------------------------- 1 | converting 2 | asEditDictionary 3 | | result | 4 | 5 | result := self asDictionary. 6 | result 7 | at: 'editUrl' put: '/flower-edit/', self voyageIdHexString; 8 | at: 'viewUrl' put: '/flower/', self voyageIdHexString; 9 | yourself. 10 | 11 | ^result -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMDomainObject.class/properties.json: -------------------------------------------------------------------------------- 1 | { 2 | "category" : "TMM-Core", 3 | "classinstvars" : [ 4 | ], 5 | "classvars" : [ 6 | ], 7 | "commentStamp" : "", 8 | "instvars" : [ 9 | ], 10 | "name" : "TMMDomainObject", 11 | "pools" : [ 12 | ], 13 | "super" : "Object", 14 | "type" : "normal" } 15 | -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlower.class/instance/asDictionary.st: -------------------------------------------------------------------------------- 1 | converting 2 | asDictionary 3 | | result | 4 | 5 | result := Dictionary new. 6 | result 7 | at: 'voyageId' put: self voyageIdHexString; 8 | at: 'flowerName' put: self name; 9 | at: 'flowerDescription' put: self description; 10 | yourself. 11 | 12 | ^result -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlowerStore.class/instance/actionUserEditForm..st: -------------------------------------------------------------------------------- 1 | route - user 2 | actionUserEditForm: req 3 | | result | 4 | 5 | result := Dictionary new. 6 | result 7 | at: 'users' 8 | put: (TMMUser selectAll collect: [:each | each asSelectTagDictionary]); 9 | yourself. 10 | 11 | ^self output: req addAll: result -------------------------------------------------------------------------------- /repository/BaselineOfTMM.package/BaselineOfTMM.class/properties.json: -------------------------------------------------------------------------------- 1 | { 2 | "category" : "BaselineOfTMM", 3 | "classinstvars" : [ 4 | ], 5 | "classvars" : [ 6 | ], 7 | "commentStamp" : "", 8 | "instvars" : [ 9 | ], 10 | "name" : "BaselineOfTMM", 11 | "pools" : [ 12 | ], 13 | "super" : "BaselineOf", 14 | "type" : "normal" } 15 | -------------------------------------------------------------------------------- /repository/TMM-Core.package/StugDemo.class/class/demoMongo.st: -------------------------------------------------------------------------------- 1 | 7 MongoDB 2 | demoMongo 3 | " 4 | TMMFlower selectAll. 5 | TMMUser selectAll. 6 | 7 | demo from image: 8 | - update/save 9 | - new/save 10 | - delete 11 | - queries - see FlowerStore 12 | - by ID 13 | - by full text search 14 | 15 | demo from bash: 16 | - find 17 | - ??? 18 | " -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlowerStore.class/instance/addRouteUpload.st: -------------------------------------------------------------------------------- 1 | route - upload 2 | addRouteUpload 3 | 4 | self server 5 | GET: '/upload' -> [:req | self handleGetRequest: req]; 6 | output: [ :object | object]; 7 | POST: '/upload' -> [:req | self handlePostRequest: req]; 8 | output: [ :object | object]; 9 | yourself 10 | -------------------------------------------------------------------------------- /config-sample.json: -------------------------------------------------------------------------------- 1 | { 2 | "google.key": "zzzzzzzz.apps.googleusercontent.com", 3 | "google.secret": "secret", 4 | "facebook.key": "zzzzzzzzz", 5 | "facebook.secret": "secret", 6 | "twitter.key": "zzzzzzzzz", 7 | "twitter.secret": "secret", 8 | 9 | "superuser": "fubar", 10 | "urlPrefix": "http://fubar.zzz/", 11 | "staticFilePath": "files" 12 | } 13 | -------------------------------------------------------------------------------- /files/shtml/footer.shtml: -------------------------------------------------------------------------------- 1 | 8 | -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlowerStore.class/instance/actionLoginGet..st: -------------------------------------------------------------------------------- 1 | route - login 2 | actionLoginGet: req 3 | 4 | ^(self headerList: req) 5 | at: 'googleOauth2Url' put: (self ssoGoogle: req znRequest); 6 | at: 'facebookOauth2Url' put: (self ssoFacebook: req znRequest); 7 | at: 'twitterOauth1Url' put: (self ssoTwitter: req znRequest); 8 | yourself -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlowerStore.class/instance/actionUserView..st: -------------------------------------------------------------------------------- 1 | route - user 2 | actionUserView: req 3 | | result user | 4 | 5 | result := Dictionary new. 6 | user := self loggedInUser: req. 7 | user isNil ifTrue: [ 8 | ^self output: req addAll: result]. 9 | 10 | result := user asViewDictionary. 11 | 12 | ^self output: req addAll: result -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlowerStore.class/instance/addRouteUser.st: -------------------------------------------------------------------------------- 1 | route - user 2 | addRouteUser 3 | 4 | self server 5 | GET: '/user/' -> [:req | 6 | self actionUserView: req]; 7 | output: (self mustacheNamed: 'user'); 8 | POST: '/user' -> [:req | 9 | self actionUserEdit: req]; 10 | output: (self mustacheNamed: 'user'); 11 | yourself -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlower.class/class/makeSamples.st: -------------------------------------------------------------------------------- 1 | example data 2 | makeSamples 3 | " 4 | self makeSamples. 5 | self selectAll. 6 | " 7 | (self new name: 'rose'; description: 'yada yada'; yourself) save. 8 | (self new name: 'violet'; description: 'yada'; yourself) save. 9 | (self new name: 'flock'; description: 'yada yada yada'; yourself) save. 10 | -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlowerStore.class/instance/partialsWithTemplateContents..st: -------------------------------------------------------------------------------- 1 | utility 2 | partialsWithTemplateContents: templateContents 3 | 4 | ^ { 5 | 'htmlhead' -> (self templateContents: 'htmlhead'). 6 | 'header' -> (self templateContents: 'header'). 7 | 'content' -> templateContents. 8 | 'footer' -> (self templateContents: 'footer'). 9 | } asDictionary -------------------------------------------------------------------------------- /repository/TMM-Core.package/StugDemo.class/class/demoMustache1.st: -------------------------------------------------------------------------------- 1 | 5 Mustache 2 | demoMustache1 3 | " 4 | self demoMustache1 5 | " 6 | | templateString context | 7 | 8 | templateString := '{{phrase}} {{name}}!'. 9 | 10 | context := {'phrase' -> 'Hello'. 'name' -> 'World'} asDictionary. 11 | 12 | ^(MustacheTemplate on: templateString) value: context 13 | -------------------------------------------------------------------------------- /files/shtml/user.shtml: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |
5 |
6 | {{userId}}
7 |
 8 | {{info}}
 9 | 
10 |
11 |
12 |
13 |
14 |
15 |
16 | -------------------------------------------------------------------------------- /repository/TMM-Core.package/StugDemo.class/class/demoVoyageMagritte.st: -------------------------------------------------------------------------------- 1 | 6 Voyage/Magritte 2 | demoVoyageMagritte 3 | " 4 | TMMFlower selectAll. 5 | 6 | TMMFlower basicNew magritteDescription collect: [:each | each label ]. 7 | 8 | TMMFlower basicNew magritteDescription 9 | inject: OrderedCollection new 10 | into: [:value :each | value add: each label; yourself ]. 11 | 12 | " -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlower.class/properties.json: -------------------------------------------------------------------------------- 1 | { 2 | "category" : "TMM-Core", 3 | "classinstvars" : [ 4 | ], 5 | "classvars" : [ 6 | ], 7 | "commentStamp" : "", 8 | "instvars" : [ 9 | "name", 10 | "description", 11 | "price" ], 12 | "name" : "TMMFlower", 13 | "pools" : [ 14 | ], 15 | "super" : "TMMDomainObject", 16 | "type" : "normal" } 17 | -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlowerStore.class/instance/actionFlowerAddForm..st: -------------------------------------------------------------------------------- 1 | route - flower 2 | actionFlowerAddForm: req 3 | | result user | 4 | 5 | result := Dictionary new. 6 | user := self loggedInUser: req. 7 | user isNil ifTrue: [ 8 | ^self output: req addAll: result]. 9 | 10 | result := TMMFlower new asAddDictionary. 11 | 12 | ^self output: req addAll: result -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlowerStore.class/instance/partialsWithTemplateNamed..st: -------------------------------------------------------------------------------- 1 | utility 2 | partialsWithTemplateNamed: templateName 3 | 4 | ^ { 5 | 'htmlhead' -> (self templateContents: 'htmlhead'). 6 | 'header' -> (self templateContents: 'header'). 7 | 'content' -> (self templateContents: templateName). 8 | 'footer' -> (self templateContents: 'footer'). 9 | } asDictionary -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMUser.class/instance/asDictionary.st: -------------------------------------------------------------------------------- 1 | converting 2 | asDictionary 3 | | result | 4 | 5 | result := Dictionary new. 6 | result 7 | at: 'voyageId' put: self voyageId value printStringHex; 8 | at: 'userId' put: self userId; 9 | at: 'userUserId' put: self userId; 10 | at: 'userProviderName' put: self providerName; 11 | yourself. 12 | 13 | ^result -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMUser.class/properties.json: -------------------------------------------------------------------------------- 1 | { 2 | "category" : "TMM-Core", 3 | "classinstvars" : [ 4 | ], 5 | "classvars" : [ 6 | ], 7 | "commentStamp" : "", 8 | "instvars" : [ 9 | "userId", 10 | "providerName", 11 | "passwordHash" ], 12 | "name" : "TMMUser", 13 | "pools" : [ 14 | ], 15 | "super" : "TMMDomainObject", 16 | "type" : "normal" } 17 | -------------------------------------------------------------------------------- /repository/TMM-Core.package/StugDemo.class/class/demoTemplates.st: -------------------------------------------------------------------------------- 1 | 4 Templates 2 | demoTemplates 3 | " 4 | Teapot stopAll. self demoTemplates. 5 | " 6 | 7 | Teapot on 8 | GET: '/greet' -> {'phrase' -> 'Hello'. 'name' -> 'World'}; 9 | output: (TeaOutput mustacheHtml: '{{phrase}} {{name}}!'); 10 | start. 11 | 12 | " 13 | ZnEasy get: 'http://localhost:1701/greet'. 14 | " -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlowerStore.class/instance/ssoGoogleCallback..st: -------------------------------------------------------------------------------- 1 | sso 2 | ssoGoogleCallback: request 3 | | googleSession | 4 | 5 | (self isOAuth2Callback: request) 6 | ifFalse: [ ^ self generateInvalidCallbackRequest ]. 7 | 8 | googleSession := self googleSessionFor: request. 9 | googleSession handleAuthenticationCallback: request uri query. 10 | 11 | ^ ZnResponse redirect: 'sso-google-data' -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlowerStore.class/instance/ssoTwitter..st: -------------------------------------------------------------------------------- 1 | sso 2 | ssoTwitter: request 3 | 4 | | oauthService requestToken | 5 | 6 | oauthService := self twitterOAuth1Service. 7 | 8 | requestToken := oauthService getRequestTokenFor: request server url / 'sso-twitter-callback'. 9 | self twitterSessionFor: request put: requestToken. 10 | 11 | ^ (oauthService loginUrlFor: requestToken) asString -------------------------------------------------------------------------------- /files/img/64x64.svg: -------------------------------------------------------------------------------- 1 | 64x64 -------------------------------------------------------------------------------- /repository/TMM-Core.package/StugDemo.class/class/demoParameters.st: -------------------------------------------------------------------------------- 1 | 2 Parameters 2 | demoParameters 3 | " 4 | Teapot stopAll. self demoParameters. 5 | " 6 | 7 | Teapot on 8 | GET: '/hi' -> 'Bonjour!'; 9 | GET: '/hi/' -> [:req | 'Hello ', (req at: #user)]; 10 | start. 11 | " 12 | (ZnEasy get: 'http://localhost:1701/hi') entity string. 13 | (ZnEasy get: 'http://localhost:1701/hi/user1234') entity string. 14 | " -------------------------------------------------------------------------------- /files/img/242x200.svg: -------------------------------------------------------------------------------- 1 | 242x200 -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlowerStore.class/instance/ssoFacebookCallback..st: -------------------------------------------------------------------------------- 1 | sso 2 | ssoFacebookCallback: request 3 | | facebookSession | 4 | 5 | (self isOAuth2Callback: request) 6 | ifFalse: [ ^ self generateInvalidCallbackRequest ]. 7 | 8 | facebookSession := self facebookSessionFor: request. 9 | facebookSession handleAuthenticationCallback: request uri query. 10 | 11 | ^ ZnResponse redirect: 'sso-facebook-data' -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlowerStore.class/instance/addRoutes.st: -------------------------------------------------------------------------------- 1 | route - main 2 | addRoutes 3 | 4 | self addRouteHome. 5 | self addRouteSearch. 6 | self addRouteFlower. 7 | self addRouteObject. 8 | self addRouteLogin. 9 | self addRouteLoginGoogle. 10 | self addRouteLoginFacebook. 11 | self addRouteLoginTwitter. 12 | self addRouteUser. 13 | self addRouteUserEdit. 14 | self addRouteUpload. 15 | self addRouteRestart. 16 | -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlowerStore.class/instance/ssoGoogleData..st: -------------------------------------------------------------------------------- 1 | sso 2 | ssoGoogleData: request 3 | | googleSession userData | 4 | 5 | googleSession := self googleSessionFor: request. 6 | userData := googleSession getUserData. 7 | 8 | request session 9 | attributeAt: 'providerName' put: 'google'; 10 | attributeAt: 'userid' put: (userData at: 'email'); 11 | yourself. 12 | 13 | ^ NeoJSONWriter toStringPretty: userData -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlowerStore.class/instance/addRouteSearch.st: -------------------------------------------------------------------------------- 1 | route - flower 2 | addRouteSearch 3 | 4 | self server 5 | GET: '/search' -> [:req | self handleQuery: req]; 6 | output: (self mustacheListFor: TMMFlower); 7 | GET: '/search/' -> [:req | self handleQuery: req]; 8 | output: (self mustacheListFor: TMMFlower); 9 | POST: '/search' -> [:req | self handleQuery: req]; 10 | output: (self mustacheListFor: TMMFlower) -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlowerStore.class/instance/ssoFacebookData..st: -------------------------------------------------------------------------------- 1 | sso 2 | ssoFacebookData: request 3 | | facebookSession userData | 4 | 5 | facebookSession := self facebookSessionFor: request. 6 | userData := facebookSession getUserData. 7 | 8 | request session 9 | attributeAt: 'providerName' put: 'facebook'; 10 | attributeAt: 'userid' put: (userData at: 'email'); 11 | yourself. 12 | 13 | ^ NeoJSONWriter toStringPretty: userData -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlower.class/class/moustacheList.st: -------------------------------------------------------------------------------- 1 | template 2 | moustacheList 3 | | writer | 4 | 5 | writer := XMLWriter new. 6 | writer enablePrettyPrinting. 7 | writer 8 | tag: 'div' 9 | attributes: {'class'->'container'. 'style'->'display:table'} 10 | with: [ 11 | writer 12 | tag: 'div' 13 | attributes: {'class'->'col-lg-12 col-md-12'} 14 | with: [ 15 | self htmlTableOn: writer]]. 16 | 17 | ^writer contents -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlowerStore.class/instance/recommendedList.st: -------------------------------------------------------------------------------- 1 | route - main 2 | recommendedList 3 | 4 | ^ { 5 | '242x200.svg'->'Flower 1'. 6 | '242x200.svg'->'Flower 2'. 7 | '242x200.svg'->'Flower 3'. 8 | } collect: [ :each | 9 | { 10 | (Association key: 'heading' value: each value). 11 | (Association key: 'img' value: each key). 12 | (Association key: 'href' value: '/search/', each value) 13 | } asDictionary. 14 | ] -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlowerStore.class/properties.json: -------------------------------------------------------------------------------- 1 | { 2 | "category" : "TMM-Core", 3 | "classinstvars" : [ 4 | ], 5 | "classvars" : [ 6 | "Config" ], 7 | "commentStamp" : "YanniChiu 4/24/2015 23:30", 8 | "instvars" : [ 9 | "server", 10 | "staticFilePath", 11 | "ssoData", 12 | "image", 13 | "logoFileName" ], 14 | "name" : "TMMFlowerStore", 15 | "pools" : [ 16 | ], 17 | "super" : "Object", 18 | "type" : "normal" } 19 | -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMDomainObject.class/class/mustacheList.st: -------------------------------------------------------------------------------- 1 | mustache html 2 | mustacheList 3 | | writer | 4 | 5 | writer := XMLWriter new. 6 | writer enablePrettyPrinting. 7 | writer 8 | tag: 'div' 9 | attributes: {'class'->'container'. 'style'->'display:table'} 10 | with: [ 11 | writer 12 | tag: 'div' 13 | attributes: {'class'->'col-lg-12 col-md-12'} 14 | with: [ 15 | self htmlTableOn: writer]]. 16 | 17 | ^writer contents -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlowerStore.class/instance/html.st: -------------------------------------------------------------------------------- 1 | route - upload 2 | html 3 | ^ 'Image 4 | 5 |

Image

6 | 7 |
8 |
9 |

Change the image:

10 | 11 | 12 | 13 |
14 | ' -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMDomainObject.class/class/htmlTableHeadOn..st: -------------------------------------------------------------------------------- 1 | mustache html 2 | htmlTableHeadOn: anXmlWriter 3 | 4 | anXmlWriter 5 | tag: 'thead' 6 | with: [ 7 | anXmlWriter 8 | tag: 'tr' 9 | with: [ 10 | self listHeadings do: [:each | 11 | anXmlWriter 12 | tag: 'th' 13 | with: [anXmlWriter string: each]]. 14 | anXmlWriter tag: 'th' with: [anXmlWriter raw: ' ']. 15 | anXmlWriter tag: 'th' with: [anXmlWriter raw: ' ']]] -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlower.class/class/htmlTableHeadOn..st: -------------------------------------------------------------------------------- 1 | template 2 | htmlTableHeadOn: anXmlWriter 3 | 4 | anXmlWriter 5 | tag: 'thead' 6 | with: [ 7 | anXmlWriter 8 | tag: 'tr' 9 | with: [ 10 | self listHeadings do: [:each | 11 | anXmlWriter 12 | tag: 'th' 13 | with: [anXmlWriter string: each]]. 14 | anXmlWriter tag: 'th' with: [anXmlWriter raw: ' ']. 15 | anXmlWriter tag: 'th' with: [anXmlWriter raw: ' ']]] -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlowerStore.class/instance/actionFlowerEdit..st: -------------------------------------------------------------------------------- 1 | route - flower 2 | actionFlowerEdit: req 3 | | result model | 4 | 5 | result := Dictionary new. 6 | 7 | "user := self loggedInUser: req. 8 | user isNil ifTrue: [ 9 | ^self output: req addAll: result]." 10 | 11 | model := self findFlowerOrNil: req. 12 | (model notNil) ifTrue: [ 13 | model copyValuesFrom: req. 14 | model save. 15 | result := model asViewDictionary]. 16 | 17 | ^self output: req addAll: result -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlowerStore.class/instance/formForImageEntity..st: -------------------------------------------------------------------------------- 1 | route - upload 2 | formForImageEntity: imageEntity 3 | "Parse the actual bytes of imageEntity and return a Form." 4 | 5 | | imageType parserClassName parserClass parser | 6 | imageType := imageEntity contentType sub. 7 | parserClassName := imageType asUppercase, #ReadWriter. 8 | parserClass := Smalltalk globals at: parserClassName asSymbol. 9 | parser := parserClass on: imageEntity readStream. 10 | ^ parser nextImage -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlower.class/class/submitButtonOn..st: -------------------------------------------------------------------------------- 1 | template 2 | submitButtonOn: anXmlWriter 3 | 4 | anXmlWriter 5 | tag: 'div' 6 | attributes: {'class'->'form-group'} 7 | with: [ 8 | anXmlWriter 9 | tag: 'div' 10 | attributes: {'class'->'col-sm-offset-2 col-sm-10'} 11 | with: [ 12 | anXmlWriter 13 | tag: 'button' 14 | attributes: {'type'->'submit'. 'class'->'btn btn-default'. 'name'->'btn-save'} 15 | with: [ 16 | anXmlWriter string: 'Save']]] -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMDomainObject.class/class/submitButtonOn..st: -------------------------------------------------------------------------------- 1 | mustache html 2 | submitButtonOn: anXmlWriter 3 | 4 | anXmlWriter 5 | tag: 'div' 6 | attributes: {'class'->'form-group'} 7 | with: [ 8 | anXmlWriter 9 | tag: 'div' 10 | attributes: {'class'->'col-sm-offset-2 col-sm-10'} 11 | with: [ 12 | anXmlWriter 13 | tag: 'button' 14 | attributes: {'type'->'submit'. 'class'->'btn btn-default'. 'name'->'btn-save'} 15 | with: [ 16 | anXmlWriter string: 'Save']]] -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlowerStore.class/README.md: -------------------------------------------------------------------------------- 1 | A TMVMFlowerStore class is demonstration of the TMVM framework stack. 2 | 3 | Here is a sample "config.json" file: 4 | ==== 5 | { 6 | "google.key": "zzzzzzzz.apps.googleusercontent.com", 7 | "google.secret": "secret", 8 | "facebook.key": "zzzzzzzzz", 9 | "facebook.secret": "secret", 10 | "twitter.key": "zzzzzzzzz", 11 | "twitter.secret": "secret", 12 | 13 | "superuser": "fubar", 14 | "urlPrefix": "http://fubar.zzz/", 15 | "staticFilePath": "files" 16 | } 17 | ==== -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlowerStore.class/instance/teapotListBlock.st: -------------------------------------------------------------------------------- 1 | utility 2 | teapotListBlock 3 | 4 | ^ [ :teaRequest | | model objectClass | 5 | model := teaRequest body. 6 | objectClass := Smalltalk classNamed: (model at: 'objectClass'). 7 | ZnResponse ok: (ZnStringEntity 8 | with: (((Smalltalk at: #MustacheTemplate) on: (self templateContents: 'page')) 9 | value: model 10 | partials: (self partialsWithTemplateContents: objectClass mustacheList)) 11 | type: ZnMimeType textHtml) ] 12 | -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlowerStore.class/instance/handleGetRequest..st: -------------------------------------------------------------------------------- 1 | route - upload 2 | handleGetRequest: request 3 | "GET /image - Serve an HTML page showing our image and a form to upload a new one. 4 | GET /image?raw=true - Serve the last image directly" 5 | 6 | ^ (request uri queryAt: #raw ifAbsent: [ nil ]) 7 | ifNil: [ 8 | ZnResponse ok: (ZnEntity html: ((MustacheTemplate on: self html) value: {'voyageId' -> self flower voyageIdHexString} asDictionary)) ] 9 | ifNotNil: [ 10 | ZnResponse ok: self image ] -------------------------------------------------------------------------------- /repository/TMM-Core.package/StugDemo.class/class/demoMustache2List.st: -------------------------------------------------------------------------------- 1 | 5 Mustache 2 | demoMustache2List 3 | " 4 | self demoMustache2List 5 | " 6 | | templateString context | 7 | 8 | templateString := 'A list of numbers 9 | {{# list }} 10 | Number: {{ number }} 11 | {{/ list }} 12 | '. 13 | 14 | context := { 15 | 'label' -> 'fine'. 16 | 'list' -> { 17 | { 'number' -> 1 } asDictionary. 18 | { 'number' -> 2 } asDictionary. 19 | } 20 | } asDictionary. 21 | 22 | ^(MustacheTemplate on: templateString) value: context 23 | -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlower.class/class/moustacheView.st: -------------------------------------------------------------------------------- 1 | template 2 | moustacheView 3 | | writer | 4 | 5 | writer := XMLWriter new. 6 | writer enablePrettyPrinting. 7 | writer 8 | tag: 'div' 9 | attributes: {'class'->'container'". 'style'->'display:table'"} 10 | with: [ 11 | writer raw: '

View

'. 12 | writer 13 | tag: 'form' 14 | attributes: {'class'->'form-horizontal'. 'method'->'post'. 'action'->'/flower-edit/{{flowerId}}'} 15 | with: [ 16 | self htmlInputFieldsOn: writer]]. 17 | 18 | ^writer contents -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlowerStore.class/instance/addRouteLoginFacebook.st: -------------------------------------------------------------------------------- 1 | route - login 2 | addRouteLoginFacebook 3 | 4 | self server 5 | GET: '/sso-facebook-callback' -> [:req | 6 | self ssoFacebookCallback: req znRequest]; 7 | output: [ZnResponse redirect: 'sso-facebook-data']; 8 | GET: '/sso-facebook-data' -> [:req | 9 | | data | 10 | data := self ssoFacebookData: req znRequest. 11 | (self headerList: req) 12 | at: 'debug' put: data; 13 | yourself ]; 14 | output: (self mustacheNamed: 'debug'); 15 | yourself. 16 | -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlowerStore.class/instance/mustacheNamed..st: -------------------------------------------------------------------------------- 1 | utility 2 | mustacheNamed: templateName 3 | 4 | ^ [ :teaRequest | | object model | 5 | object := teaRequest body. 6 | model := (object respondsTo: #asDictionary) 7 | ifTrue: [ object asDictionary ] 8 | ifFalse: [ object ]. 9 | ZnResponse ok: (ZnStringEntity 10 | with: (((Smalltalk at: #MustacheTemplate) on: (self templateContents: 'page')) 11 | value: model 12 | partials: (self partialsWithTemplateNamed: templateName)) 13 | type: ZnMimeType textHtml) ] 14 | -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlowerStore.class/instance/mustacheAddFor..st: -------------------------------------------------------------------------------- 1 | utility 2 | mustacheAddFor: aClass 3 | 4 | ^ [ :teaRequest | | object model | 5 | object := teaRequest body. 6 | model := (object respondsTo: #asDictionary) 7 | ifTrue: [ object asDictionary ] 8 | ifFalse: [ object ]. 9 | ZnResponse ok: (ZnStringEntity 10 | with: (((Smalltalk at: #MustacheTemplate) on: (self templateContents: 'page')) 11 | value: model 12 | partials: (self partialsWithTemplateContents: aClass mustacheAdd)) 13 | type: ZnMimeType textHtml) ] 14 | -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlowerStore.class/instance/mustacheEditFor..st: -------------------------------------------------------------------------------- 1 | utility 2 | mustacheEditFor: aClass 3 | 4 | ^ [ :teaRequest | | object model | 5 | object := teaRequest body. 6 | model := (object respondsTo: #asDictionary) 7 | ifTrue: [ object asDictionary ] 8 | ifFalse: [ object ]. 9 | ZnResponse ok: (ZnStringEntity 10 | with: (((Smalltalk at: #MustacheTemplate) on: (self templateContents: 'page')) 11 | value: model 12 | partials: (self partialsWithTemplateContents: aClass mustacheEdit)) 13 | type: ZnMimeType textHtml) ] 14 | -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlowerStore.class/instance/mustacheListFor..st: -------------------------------------------------------------------------------- 1 | utility 2 | mustacheListFor: aClass 3 | 4 | ^ [ :teaRequest | | object model | 5 | object := teaRequest body. 6 | model := (object respondsTo: #asDictionary) 7 | ifTrue: [ object asDictionary ] 8 | ifFalse: [ object ]. 9 | ZnResponse ok: (ZnStringEntity 10 | with: (((Smalltalk at: #MustacheTemplate) on: (self templateContents: 'page')) 11 | value: model 12 | partials: (self partialsWithTemplateContents: aClass mustacheList)) 13 | type: ZnMimeType textHtml) ] 14 | -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlowerStore.class/instance/mustacheViewFor..st: -------------------------------------------------------------------------------- 1 | utility 2 | mustacheViewFor: aClass 3 | 4 | ^ [ :teaRequest | | object model | 5 | object := teaRequest body. 6 | model := (object respondsTo: #asDictionary) 7 | ifTrue: [ object asDictionary ] 8 | ifFalse: [ object ]. 9 | ZnResponse ok: (ZnStringEntity 10 | with: (((Smalltalk at: #MustacheTemplate) on: (self templateContents: 'page')) 11 | value: model 12 | partials: (self partialsWithTemplateContents: aClass mustacheView)) 13 | type: ZnMimeType textHtml) ] 14 | -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlowerStore.class/instance/addRouteLoginGoogle.st: -------------------------------------------------------------------------------- 1 | route - login 2 | addRouteLoginGoogle 3 | 4 | self server 5 | GET: '/sso-google-callback' -> [:req | 6 | self ssoGoogleCallback: req znRequest]; 7 | output: [ZnResponse redirect: 'sso-google-data']; 8 | GET: '/sso-google-data' -> [:req | 9 | | data | 10 | data := self ssoGoogleData: req znRequest. 11 | self loggedInUser: req. 12 | (self headerList: req) 13 | at: 'debug' put: data; 14 | yourself ]; 15 | output: (self mustacheNamed: 'debug'); 16 | yourself. 17 | -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlowerStore.class/instance/addRouteLoginTwitter.st: -------------------------------------------------------------------------------- 1 | route - login 2 | addRouteLoginTwitter 3 | 4 | self server 5 | GET: '/sso-twitter-callback' -> [:req | 6 | self ssoTwitterCallback: req znRequest]; 7 | output: [ZnResponse redirect: 'sso-twitter-data']; 8 | GET: '/sso-twitter-data' -> [:req | 9 | | data | 10 | data := self ssoTwitterData: req znRequest. 11 | self loggedInUser: req. 12 | (self headerList: req) 13 | at: 'debug' put: data; 14 | yourself ]; 15 | output: (self mustacheNamed: 'debug'); 16 | yourself. 17 | -------------------------------------------------------------------------------- /files/css/tmm.css: -------------------------------------------------------------------------------- 1 | @charset "UTF-8"; 2 | /* CSS Document */ 3 | 4 | html, body { 5 | min-height: 100%; 6 | height: 100%; 7 | } 8 | 9 | body { 10 | font-size: 16px; 11 | padding-top: 70px; 12 | display: table; 13 | width: 100%; 14 | } 15 | 16 | #wrap { 17 | display:table; 18 | height: 100%; 19 | width:100%; 20 | } 21 | 22 | #footer { 23 | height: 30px; 24 | background-color:#290C31; 25 | font-size:11px; 26 | vertical-align:middle; 27 | display:table-row; 28 | color:#999; 29 | } 30 | 31 | form.login{ 32 | background:#F2EEF2; 33 | border:1px solid #ddd; 34 | } 35 | -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMDomainObject.class/class/mustacheView.st: -------------------------------------------------------------------------------- 1 | mustache html 2 | mustacheView 3 | | writer | 4 | 5 | writer := XMLWriter new. 6 | writer enablePrettyPrinting. 7 | writer 8 | tag: 'div' 9 | attributes: {'class'->'container'". 'style'->'display:table'"} 10 | with: [ 11 | writer raw: '

View

'. 12 | writer 13 | tag: 'form' 14 | attributes: {'class'->'form-horizontal'. 'method'->'post'. 'action'->('/', self templateFieldNamePrefix, '-edit/{{voyageId}}')} 15 | with: [ 16 | self htmlInputFieldsOn: writer]]. 17 | 18 | ^writer contents -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlower.class/class/moustacheAdd.st: -------------------------------------------------------------------------------- 1 | template 2 | moustacheAdd 3 | | writer | 4 | 5 | writer := XMLWriter new. 6 | writer enablePrettyPrinting. 7 | writer 8 | tag: 'div' 9 | attributes: {'class'->'container'". 'style'->'display:table'"} 10 | with: [ 11 | writer raw: '

Add

'. 12 | writer 13 | tag: 'form' 14 | attributes: {'class'->'form-horizontal'. 'method'->'post'. 'action'->'/flower-edit/{{flowerId}}'} 15 | with: [ 16 | self htmlInputFieldsOn: writer. 17 | self submitButtonOn: writer]]. 18 | 19 | ^writer contents -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlower.class/class/moustacheEdit.st: -------------------------------------------------------------------------------- 1 | template 2 | moustacheEdit 3 | | writer | 4 | 5 | writer := XMLWriter new. 6 | writer enablePrettyPrinting. 7 | writer 8 | tag: 'div' 9 | attributes: {'class'->'container'". 'style'->'display:table'"} 10 | with: [ 11 | writer raw: '

Edit

'. 12 | writer 13 | tag: 'form' 14 | attributes: {'class'->'form-horizontal'. 'method'->'post'. 'action'->'/flower-edit/{{flowerId}}'} 15 | with: [ 16 | self htmlInputFieldsOn: writer. 17 | self submitButtonOn: writer]]. 18 | 19 | ^writer contents -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlowerStore.class/instance/actionFlowerAdd..st: -------------------------------------------------------------------------------- 1 | route - flower 2 | actionFlowerAdd: req 3 | | result btn user | 4 | 5 | result := Dictionary new. 6 | 7 | user := self loggedInUser: req. 8 | user isNil ifTrue: [ 9 | ^self output: req addAll: result]. 10 | 11 | btn := (req at: 'btn-save' ifAbsent: [nil]). 12 | (btn notNil and: [(req at: 'className' ifAbsent: ['']) notEmpty]) ifTrue: [ 13 | | model | 14 | model := TMMFlower new. 15 | model copyValuesFrom: req. 16 | model save. 17 | result := model asViewDictionary]. 18 | 19 | ^self output: req addAll: result -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlowerStore.class/instance/actionUserEdit..st: -------------------------------------------------------------------------------- 1 | route - user 2 | actionUserEdit: req 3 | | result btn loggedInUser | 4 | 5 | result := Dictionary new. 6 | 7 | loggedInUser := self loggedInUser: req. 8 | (loggedInUser isNil or: [ loggedInUser isSuperuser not ]) ifTrue: [ 9 | ^self output: req addAll: result]. 10 | 11 | btn := (req at: 'btn-save' ifAbsent: [nil]). 12 | btn notNil ifTrue: [ 13 | | user | 14 | user := self userFromRequest: req. 15 | user notNil ifTrue: [ 16 | user save. 17 | result := user asViewDictionary]]. 18 | 19 | ^self output: req addAll: result -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMDomainObject.class/class/mustacheAdd.st: -------------------------------------------------------------------------------- 1 | mustache html 2 | mustacheAdd 3 | | writer | 4 | 5 | writer := XMLWriter new. 6 | writer enablePrettyPrinting. 7 | writer 8 | tag: 'div' 9 | attributes: {'class'->'container'". 'style'->'display:table'"} 10 | with: [ 11 | writer raw: '

Add

'. 12 | writer 13 | tag: 'form' 14 | attributes: {'class'->'form-horizontal'. 'method'->'post'. 'action'->('/', self templateFieldNamePrefix, '-edit/{{voyageId}}')} 15 | with: [ 16 | self htmlInputFieldsOn: writer. 17 | self submitButtonOn: writer]]. 18 | 19 | ^writer contents -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMDomainObject.class/class/mustacheEdit.st: -------------------------------------------------------------------------------- 1 | mustache html 2 | mustacheEdit 3 | | writer | 4 | 5 | writer := XMLWriter new. 6 | writer enablePrettyPrinting. 7 | writer 8 | tag: 'div' 9 | attributes: {'class'->'container'". 'style'->'display:table'"} 10 | with: [ 11 | writer raw: '

Edit

'. 12 | writer 13 | tag: 'form' 14 | attributes: {'class'->'form-horizontal'. 'method'->'post'. 'action'->('/', self templateFieldNamePrefix, '-edit/{{voyageId}}')} 15 | with: [ 16 | self htmlInputFieldsOn: writer. 17 | self submitButtonOn: writer]]. 18 | 19 | ^writer contents -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlowerStore.class/instance/ssoTwitterData..st: -------------------------------------------------------------------------------- 1 | sso 2 | ssoTwitterData: request 3 | | accessToken userData | 4 | 5 | accessToken := self twitterSessionFor: request 6 | ifAbsent: [ ^ self generateInvalidCallbackRequest ]. 7 | 8 | userData := ZnOAuth1TwitterUserAccess new 9 | oauth1Service: self twitterOAuth1Service ; 10 | accessToken: accessToken ; 11 | accountVerifyCredentials. 12 | 13 | request session 14 | attributeAt: 'providerName' put: 'twitter'; 15 | attributeAt: 'userid' put: (userData at: 'screen_name'); 16 | yourself. 17 | 18 | ^ NeoJSONWriter toStringPretty: userData -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlowerStore.class/instance/loggedInUser..st: -------------------------------------------------------------------------------- 1 | route - login 2 | loggedInUser: req 3 | | session userId providerName | 4 | 5 | session := req znRequest session. 6 | userId := session attributeAt: 'userid' ifAbsent: [ nil ]. 7 | providerName := session attributeAt: 'providerName' ifAbsent: [ nil ]. 8 | 9 | ^(userId notNil and: [providerName notNil]) 10 | ifTrue: [ 11 | | user | 12 | user := TMMUser findUserId: userId providerName: providerName. 13 | "user isNil ifTrue: [ 14 | user := TMVMUser userId: userId providerName: providerName. 15 | user save]." 16 | user] 17 | ifFalse: [ nil ] -------------------------------------------------------------------------------- /repository/TMM-Core.package/StugDemo.class/class/demoMustache3List.st: -------------------------------------------------------------------------------- 1 | 5 Mustache 2 | demoMustache3List 3 | " 4 | self demoMustache3List 5 | " 6 | | templateString packageNames context | 7 | 8 | templateString := '{{label}} Names: 9 | {{# list }} 10 | Name: {{ packageName }}{{/ list }} 11 | '. 12 | 13 | packageNames := (RPackageOrganizer default packages 14 | collect: [ :each | each name ]) asSortedCollection. 15 | 16 | context := { 17 | 'label' -> 'Package'. 18 | 'list' -> (packageNames collect: [ :each | { 'packageName' -> each } asDictionary]) 19 | } asDictionary. 20 | 21 | ^(MustacheTemplate on: templateString) value: context 22 | -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlowerStore.class/instance/actionObectList..st: -------------------------------------------------------------------------------- 1 | route - flower 2 | actionObectList: req 3 | | result objectName metaData objectClass | 4 | 5 | objectName := req at: 'objectName'. 6 | metaData := (TMMDomainObject allSubclasses collect: [:each | each magritteDescription ]) 7 | detect: [ :each | each collectionName = objectName ] ifNone: [ nil ]. 8 | objectClass := metaData kind. 9 | 10 | result := Dictionary new. 11 | result at: 'objectClass' put: objectClass name. 12 | 13 | result 14 | at: 'list' 15 | put: (objectClass selectAll collect: [:model | model asViewDictionary]). 16 | 17 | ^self output: req addAll: result -------------------------------------------------------------------------------- /repository/TMM-Core.package/StugDemo.class/class/demoMustache4Nesting.st: -------------------------------------------------------------------------------- 1 | 5 Mustache 2 | demoMustache4Nesting 3 | " 4 | Called 'partials' in Mustache. 5 | 6 | self demoMustache4Nesting 7 | " 8 | | templateString userTemplateString | 9 | 10 | templateString := '

Names

11 | {{# names }} 12 | {{> user }} 13 | {{/ names }}'. 14 | 15 | userTemplateString := '{{name}}'. 16 | 17 | ^(MustacheTemplate on: templateString) 18 | value: { 19 | 'names' -> { 20 | { 'name' -> 'Username' } asDictionary. 21 | { 'name' -> 'Alias' } asDictionary 22 | } } asDictionary 23 | partials: {'user' -> userTemplateString} asDictionary. 24 | 25 | -------------------------------------------------------------------------------- /repository/TMM-Core.package/monticello.meta/version: -------------------------------------------------------------------------------- 1 | (name 'TMM-Core-YanniChiu.3' message 'Push-up to abstract superclass, the code for generating the html template.' id '890af538-a240-45cd-a669-ca4be7ce55f0' date '1 May 2015' time '1:52:56.620382 am' author 'YanniChiu' ancestors ((name 'TMM-Core-YanniChiu.2' message 'Add local user/password registration' id '50cdf0e8-d3ee-42cb-bf40-de3e424bc73a' date '27 April 2015' time '12:43:25.503815 am' author 'YanniChiu' ancestors ((name 'TMM-Core-YanniChiu.1' message 'Initial release' id '2071a13d-ae00-48fd-bff2-c4d01557e4c2' date '26 April 2015' time '10:46:24.627142 am' author 'YanniChiu' ancestors () stepChildren ())) stepChildren ())) stepChildren ()) -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlowerStore.class/class/runScheme.host.portno.serverPortno.staticFilePath..st: -------------------------------------------------------------------------------- 1 | instance creation 2 | runScheme: aScheme host: aHostname portno: aPortno serverPortno: aListeningPortno staticFilePath: aFilePath 3 | " 4 | self runScheme: 'http' host: 'localhost' portno: 80 serverPortno: 9990 staticFilePath: '/home/git/www/tmm' 5 | " 6 | | url | 7 | 8 | Teapot stopAll. 9 | 10 | url := ZnUrl new 11 | scheme: aScheme; 12 | host: aHostname; 13 | port: aPortno; 14 | yourself. 15 | 16 | ^self new 17 | initializeOn: { #port -> aListeningPortno. #serverUrl -> url }; 18 | serveStaticFilesFrom: aFilePath; 19 | addRoutes; 20 | start; 21 | yourself -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlowerStore.class/instance/addRouteLogin.st: -------------------------------------------------------------------------------- 1 | route - login 2 | addRouteLogin 3 | 4 | self server 5 | GET: '/login' -> [:req | self actionLoginGet: req ]; 6 | output: (self mustacheNamed: 'login'); 7 | POST: '/login' -> [:req | self actionLoginPost: req ]; 8 | output: (self mustacheNamed: 'debug'); 9 | 10 | GET: '/logout' -> [:req | self actionLogoutGet: req]; 11 | output: [ZnResponse redirect: '/']; 12 | 13 | GET: '/register' -> [:req | self actionRegisterGet: req ]; 14 | output: (self mustacheNamed: 'register'); 15 | POST: '/register' -> [:req | self actionRegisterPost: req ]; 16 | output: (self mustacheNamed: 'debug'); 17 | 18 | yourself. 19 | -------------------------------------------------------------------------------- /repository/TMM-Core.package/StugDemo.class/class/demoResponseTransformers.st: -------------------------------------------------------------------------------- 1 | 3 Response Transformers 2 | demoResponseTransformers 3 | " 4 | Teapot stopAll. self demoResponseTransformers. 5 | " 6 | 7 | Teapot on 8 | GET: '/hello' -> '

hello

'; output: #html; 9 | GET: '/jsonlist' -> #(1 2 3 4); output: #json; 10 | GET: '/sometext' -> 'this is text plain'; output: #text; 11 | GET: '/download' -> ['foobar.txt' asFileReference readStream]; output: #stream; 12 | start. 13 | 14 | " 15 | ZnEasy get: 'http://localhost:1701/hello'. 16 | (ZnEasy get: 'http://localhost:1701/jsonlist') entity string. 17 | ZnEasy get: 'http://localhost:1701/sometext'. 18 | ZnEasy get: 'http://localhost:1701/download'. 19 | " -------------------------------------------------------------------------------- /files/shtml/htmlhead.shtml: -------------------------------------------------------------------------------- 1 | 2 | FlowerStore 3 | 4 | 5 | 6 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlowerStore.class/instance/actionLoginPost..st: -------------------------------------------------------------------------------- 1 | route - login 2 | actionLoginPost: req 3 | | email password user message | 4 | 5 | email := (req at: 'email'). 6 | user := TMMUser findLocalUserId: email. 7 | 8 | message := 'Login failed'. 9 | 10 | user notNil ifTrue: [ 11 | password := (req at: 'password'). 12 | user passwordHash asByteArray = (MD5 hashMessage: password) ifTrue: [ 13 | message := 'Welcome back ', email. 14 | req session 15 | attributeAt: 'providerName' put: 'local'; 16 | attributeAt: 'userid' put: email; 17 | attributeAt: 'profileImageUrl' put: 'picture'; 18 | yourself. 19 | ] 20 | ]. 21 | 22 | ^(self headerList: req) 23 | at: 'debug' put: message; 24 | yourself -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlower.class/class/htmlTableBodyOn..st: -------------------------------------------------------------------------------- 1 | template 2 | htmlTableBodyOn: anXmlWriter 3 | 4 | anXmlWriter 5 | tag: 'tbody' 6 | with: [ 7 | anXmlWriter raw: '{{# list}}'. 8 | anXmlWriter 9 | tag: 'tr' 10 | with: [ 11 | self listHeadings do: [:each | 12 | anXmlWriter 13 | tag: 'td' 14 | with: [anXmlWriter string: '{{flower', each, '}}']]. 15 | anXmlWriter tag: 'td' with: [ 16 | anXmlWriter raw: '']. 17 | anXmlWriter tag: 'td' with: [ 18 | anXmlWriter raw: '']]. 19 | anXmlWriter raw: '{{/ list}}'. 20 | ] -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlowerStore.class/instance/handleQuery..st: -------------------------------------------------------------------------------- 1 | route - flower 2 | handleQuery: req 3 | | query result | 4 | 5 | query := req at: #query ifAbsent: ['']. 6 | result := query isEmpty 7 | ifTrue: [TMMFlower selectAll] 8 | ifFalse: [ 9 | TMMFlower selectMany: { 10 | '$or' -> { 11 | {'name' -> { '$regex' -> query. '$options' -> 'i' } asDictionary } asDictionary. 12 | {'description' -> { '$regex' -> query. '$options' -> 'i' } asDictionary} asDictionary 13 | } 14 | } asDictionary 15 | ]. 16 | 17 | ^self output: req addAll: { 18 | 'query' -> query. 19 | 'searchResultSize' -> result size. 20 | 'list' -> (result withIndexCollect: [:each :index | each asSearchResultDictionaryWIthRank: index - 1])} asDictionary -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlowerStore.class/instance/actionRegisterPost..st: -------------------------------------------------------------------------------- 1 | route - login 2 | actionRegisterPost: req 3 | | email password password2 message user | 4 | 5 | email := (req at: 'email'). 6 | password := (req at: 'password'). 7 | password2 := (req at: 'password2'). 8 | 9 | message := 'Passwords did not match.'. 10 | 11 | password = password2 ifTrue: [ 12 | user := TMMUser findLocalUserId: email. 13 | user isNil ifTrue: [ 14 | user := TMMUser userId: email providerName: 'local'. 15 | user passwordHash: (MD5 hashMessage: password). 16 | user save. 17 | message := 'Welcome ', email. 18 | ] 19 | ifFalse: [ 20 | message := email, ' already registered'. 21 | ]. 22 | ]. 23 | 24 | ^(self headerList: req) 25 | at: 'debug' put: message; 26 | yourself -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlowerStore.class/instance/ssoTwitterCallback..st: -------------------------------------------------------------------------------- 1 | sso 2 | ssoTwitterCallback: request 3 | 4 | | requestToken oauthToken oauthVerifier accessToken | 5 | 6 | requestToken := self twitterSessionFor: request 7 | ifAbsent: [ ^ self generateInvalidCallbackRequest ]. 8 | 9 | oauthToken := request uri queryAt: 'oauth_token'. 10 | oauthVerifier := request uri queryAt: 'oauth_verifier'. 11 | 12 | (oauthToken isNil or: [ oauthVerifier isNil]) 13 | ifTrue: [ ^ self generateInvalidCallbackRequest ]. 14 | 15 | oauthToken = requestToken value 16 | ifFalse: [ ^ self generateInvalidCallbackRequest ]. 17 | 18 | accessToken := self twitterOAuth1Service getAccessToken: requestToken verifier: oauthVerifier. 19 | self twitterSessionFor: request put: accessToken. 20 | 21 | ^ ZnResponse redirect: 'sso-twitter-data' -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlowerStore.class/instance/addRouteFlower.st: -------------------------------------------------------------------------------- 1 | route - flower 2 | addRouteFlower 3 | 4 | self server 5 | GET: '/flower-list' -> [:req | 6 | self actionFlowerList: req]; 7 | output: (self mustacheNamed: 'flower-list'); 8 | 9 | GET: '/flower/' -> [:req | 10 | self actionFlowerView: req]; 11 | output: (self mustacheViewFor: TMMFlower); 12 | 13 | GET: '/flower-edit/' -> [:req | 14 | self actionFlowerView: req]; 15 | output: (self mustacheEditFor: TMMFlower); 16 | POST: '/flower-edit/' -> [:req | 17 | self actionFlowerEdit: req]; 18 | output: (self mustacheViewFor: TMMFlower); 19 | 20 | GET: '/flower-add' -> [:req | 21 | self actionFlowerAddForm: req]; 22 | output: (self mustacheAddFor: TMMFlower); 23 | POST: '/flower-add' -> [:req | 24 | self actionFlowerAdd: req]; 25 | output: (self mustacheViewFor: TMMFlower); 26 | 27 | yourself -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlowerStore.class/instance/addRouteObject.st: -------------------------------------------------------------------------------- 1 | route - main 2 | addRouteObject 3 | 4 | self server 5 | GET: '/l/' -> [:req | 6 | self actionObectList: req]; 7 | output: self teapotListBlock; 8 | 9 | GET: '/o//' -> [:req | 10 | self actionFlowerView: req]; 11 | output: (self mustacheViewFor: TMMFlower); 12 | 13 | GET: '/e//' -> [:req | 14 | self actionFlowerView: req]; 15 | output: (self mustacheEditFor: TMMFlower); 16 | POST: '/e//' -> [:req | 17 | self actionFlowerEdit: req]; 18 | output: (self mustacheViewFor: TMMFlower); 19 | 20 | GET: '/a/' -> [:req | 21 | self actionFlowerAddForm: req]; 22 | output: (self mustacheAddFor: TMMFlower); 23 | POST: '/a/' -> [:req | 24 | self actionFlowerAdd: req]; 25 | output: (self mustacheViewFor: TMMFlower); 26 | 27 | yourself -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMDomainObject.class/methodProperties.json: -------------------------------------------------------------------------------- 1 | { 2 | "class" : { 3 | "findByVoyageId:" : "YanniChiu 1/27/2015 00:09", 4 | "htmlInputFieldOn:description:" : "YanniChiu 4/28/2015 01:08", 5 | "htmlInputFieldsOn:" : "YanniChiu 4/28/2015 00:02", 6 | "htmlTableBodyOn:" : "YanniChiu 5/1/2015 01:45", 7 | "htmlTableHeadOn:" : "YanniChiu 4/29/2015 01:16", 8 | "htmlTableOn:" : "YanniChiu 4/28/2015 00:02", 9 | "listHeadings" : "YanniChiu 4/28/2015 01:12", 10 | "mustacheAdd" : "YanniChiu 4/28/2015 01:17", 11 | "mustacheEdit" : "YanniChiu 4/28/2015 01:17", 12 | "mustacheList" : "YanniChiu 4/28/2015 00:06", 13 | "mustacheView" : "YanniChiu 4/28/2015 01:17", 14 | "submitButtonOn:" : "YanniChiu 4/28/2015 00:02", 15 | "templateFieldNamePrefix" : "YanniChiu 4/28/2015 01:10" }, 16 | "instance" : { 17 | "toString:" : "YanniChiu 9/24/2013 01:00", 18 | "voyageIdHexString" : "YanniChiu 3/7/2015 21:18" } } 19 | -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlower.class/class/htmlInputFieldOn.description..st: -------------------------------------------------------------------------------- 1 | template 2 | htmlInputFieldOn: anXmlWriter description: magritteDescription 3 | | attributeName inputName inputValue | 4 | 5 | attributeName := magritteDescription accessor readSelector asString capitalized. 6 | inputName := 'flower', attributeName. 7 | inputValue := '{{', inputName, '}}'. 8 | 9 | anXmlWriter 10 | tag: 'div' 11 | attributes: {'class'->'form-group'} 12 | with: [ 13 | anXmlWriter 14 | tag: 'label' 15 | attributes: {'for'->inputName. 'class'->'col-sm-2 control-label'} 16 | with: [ 17 | anXmlWriter string: magritteDescription label]. 18 | anXmlWriter 19 | tag: 'div' 20 | attributes: {'class'->'col-sm-10'} 21 | with: [ 22 | anXmlWriter 23 | tag: 'input' 24 | attributes: {'id'->inputName. 'name'->inputName. 'class'->'form-control'. 'value'->inputValue} 25 | with: [] 26 | ] 27 | ] -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMDomainObject.class/class/htmlInputFieldOn.description..st: -------------------------------------------------------------------------------- 1 | mustache html 2 | htmlInputFieldOn: anXmlWriter description: magritteDescription 3 | | attributeName inputName inputValue | 4 | 5 | attributeName := magritteDescription accessor readSelector asString capitalized. 6 | inputName := self templateFieldNamePrefix, attributeName. 7 | inputValue := '{{', inputName, '}}'. 8 | 9 | anXmlWriter 10 | tag: 'div' 11 | attributes: {'class'->'form-group'} 12 | with: [ 13 | anXmlWriter 14 | tag: 'label' 15 | attributes: {'for'->inputName. 'class'->'col-sm-2 control-label'} 16 | with: [ 17 | anXmlWriter string: magritteDescription label]. 18 | anXmlWriter 19 | tag: 'div' 20 | attributes: {'class'->'col-sm-10'} 21 | with: [ 22 | anXmlWriter 23 | tag: 'input' 24 | attributes: {'id'->inputName. 'name'->inputName. 'class'->'form-control'. 'value'->inputValue} 25 | with: [] 26 | ] 27 | ] -------------------------------------------------------------------------------- /files/shtml/user-edit.shtml: -------------------------------------------------------------------------------- 1 |
2 |
3 | 4 |
5 | 6 |
7 | 12 |
13 |
14 |
15 |
16 | 17 |
18 |
19 |
20 |
21 |
22 | 25 | -------------------------------------------------------------------------------- /repository/TMM-Core.package/StugDemo.class/methodProperties.json: -------------------------------------------------------------------------------- 1 | { 2 | "class" : { 3 | "demoHelloWorld" : "YanniChiu 3/8/2015 22:53", 4 | "demoHelloWorld5" : "YanniChiu 3/8/2015 22:54", 5 | "demoMongo" : "YanniChiu 4/25/2015 10:06", 6 | "demoMustache1" : "YanniChiu 3/8/2015 22:03", 7 | "demoMustache2List" : "YanniChiu 3/8/2015 22:01", 8 | "demoMustache3List" : "YanniChiu 3/8/2015 22:14", 9 | "demoMustache4Nesting" : "YanniChiu 3/8/2015 22:21", 10 | "demoParameters" : "YanniChiu 3/8/2015 22:54", 11 | "demoResponseTransformers" : "YanniChiu 3/8/2015 19:57", 12 | "demoTemplates" : "YanniChiu 3/8/2015 20:07", 13 | "demoVoyageMagritte" : "YanniChiu 4/25/2015 10:03", 14 | "descriptionPrice" : "YanniChiu 3/7/2015 22:04", 15 | "descriptionSchool" : "YanniChiu 3/7/2015 22:04", 16 | "descriptionStartDate" : "YanniChiu 3/7/2015 22:03", 17 | "descriptionStartTime" : "YanniChiu 3/7/2015 22:04", 18 | "descriptionStore" : "YanniChiu 4/21/2015 00:18", 19 | "runLocal" : "YanniChiu 4/25/2015 10:06" }, 20 | "instance" : { 21 | } } 22 | -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlowerStore.class/instance/handlePostRequest..st: -------------------------------------------------------------------------------- 1 | route - upload 2 | handlePostRequest: request 3 | "POST /image - change the image and show the result. 4 | Do full error checking before accepting the newly uploaded image" 5 | 6 | | part newImage badRequest reference | 7 | 8 | badRequest := [ ^ ZnResponse badRequest: request ]. 9 | (request hasEntity and: [ request contentType matches: ZnMimeType multiPartFormData ]) 10 | ifFalse: badRequest. 11 | part := request entity 12 | partNamed: #file 13 | ifNone: badRequest. 14 | newImage := part entity. 15 | (newImage notNil and: [ newImage contentType matches: 'image/*' asZnMimeType ]) 16 | ifFalse: badRequest. 17 | [ self formForImageEntity: newImage ] on: Error do: badRequest. 18 | "image := newImage." 19 | logoFileName := part fileName. 20 | reference := FileSystem workingDirectory / logoFileName. 21 | reference writeStreamDo: [ :ws | ws nextPutAll: newImage bytes ]. 22 | "mimetype: part contentType." 23 | 24 | ^ ZnResponse redirect: #upload 25 | -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMDomainObject.class/class/htmlTableBodyOn..st: -------------------------------------------------------------------------------- 1 | mustache html 2 | htmlTableBodyOn: anXmlWriter 3 | 4 | anXmlWriter 5 | tag: 'tbody' 6 | with: [ 7 | anXmlWriter raw: '{{# list}}'. 8 | anXmlWriter 9 | tag: 'tr' 10 | with: [ 11 | self listHeadings do: [:each | 12 | | description getter | 13 | 14 | description := self basicNew magritteDescription detect: [:d | d label = each ] ifNone: [ nil ]. 15 | getter := description accessor readSelector asString. 16 | getter := (getter copyFrom: 1 to: 1) asUppercase, (getter copyFrom: 2 to: getter size). 17 | getter := self templateFieldNamePrefix, getter. 18 | anXmlWriter 19 | tag: 'td' 20 | with: [anXmlWriter string: '{{', getter, '}}']]. 21 | anXmlWriter tag: 'td' with: [ 22 | anXmlWriter raw: '']. 23 | anXmlWriter tag: 'td' with: [ 24 | anXmlWriter raw: '']]. 25 | anXmlWriter raw: '{{/ list}}'. 26 | ] -------------------------------------------------------------------------------- /files/shtml/flower-list.shtml: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | {{# list }} 15 | 16 | 19 | 22 | 25 | 28 | 29 | {{/ list }} 30 | 31 |
NameDescription  
17 | {{flowerName}} 18 | 20 | {{flowerDescription}} 21 | 23 | 24 | 26 | 27 |
32 |
33 | 34 |
35 | 36 | -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlower.class/methodProperties.json: -------------------------------------------------------------------------------- 1 | { 2 | "class" : { 3 | "descriptionContainer" : "YanniChiu 4/25/2015 21:59", 4 | "isVoyageRoot" : "YanniChiu 8/13/2013 01:06", 5 | "listHeadings" : "YanniChiu 4/28/2015 01:12", 6 | "makeIndex" : "YanniChiu 3/2/2015 00:13", 7 | "makeSamples" : "YanniChiu 3/2/2015 00:12" }, 8 | "instance" : { 9 | "asAddDictionary" : "YanniChiu 2/28/2015 17:23", 10 | "asDictionary" : "YanniChiu 4/28/2015 01:16", 11 | "asEditDictionary" : "YanniChiu 3/7/2015 21:53", 12 | "asSearchResultDictionaryWIthRank:" : "YanniChiu 3/7/2015 21:21", 13 | "asViewDictionary" : "YanniChiu 2/28/2015 17:24", 14 | "copyValuesFrom:" : "YanniChiu 3/8/2015 00:11", 15 | "description" : "YanniChiu 8/13/2013 01:06", 16 | "description:" : "YanniChiu 8/13/2013 01:06", 17 | "descriptionDescription" : "YanniChiu 12/28/2014 15:32", 18 | "descriptionLogoFileName" : "YanniChiu 3/12/2015 00:47", 19 | "descriptionName" : "YanniChiu 12/28/2014 15:33", 20 | "name" : "YanniChiu 8/13/2013 01:06", 21 | "name:" : "YanniChiu 8/13/2013 01:06", 22 | "printOn:" : "YanniChiu 4/29/2015 00:40" } } 23 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Yanni K. Chiu 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlowerStore.class/class/runLocal.st: -------------------------------------------------------------------------------- 1 | instance creation 2 | runLocal 3 | " 4 | self runLocal. 5 | Teapot stopAll. 6 | " 7 | | server | 8 | 9 | server := TMMFlowerStore 10 | runScheme: 'http' 11 | host: 'localhost' 12 | portno: 1701 13 | serverPortno: 1701 14 | staticFilePath: self defaultStaticFilePath.. 15 | 16 | "https://developers.google.com/console/help/new/#generatingoauth2" 17 | server 18 | ssoDataAt: 'google' 19 | put: (ZnOAuth2ConsumerData 20 | key: self googleKey 21 | secret: self googleSecret 22 | redirectUrl: self defaultUrlPrefix, 'sso-google-callback'). 23 | 24 | "Have NOT been successful at getting facebook credentials" 25 | server 26 | ssoDataAt: 'facebook' 27 | put: (ZnOAuth2ConsumerData 28 | key: self facebookKey 29 | secret: self facebookSecret 30 | redirectUrl: self defaultUrlPrefix, 'sso-facebook-callback'). 31 | 32 | "get secret token at: https://apps.twitter.com/" 33 | server 34 | ssoDataAt: 'twitter' 35 | put: (ZnOAuth1ConsumerData newForTwitterAuthentication 36 | consumer: self twitterKey; 37 | consumerSecret: self twitterSecret 38 | ). 39 | 40 | ^ server -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlower.class/class/moustacheListZ.st: -------------------------------------------------------------------------------- 1 | template 2 | moustacheListZ 3 | 4 | ^' 5 |
6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | {{# list }} 19 | 20 | 23 | 26 | 29 | 32 | 33 | {{/ list }} 34 | 35 |
NameDescription  
21 | {{flowerName}} 22 | 24 | {{flowerDescription}} 25 | 27 | 28 | 30 | 31 |
36 |
37 | 38 |
39 | ' -------------------------------------------------------------------------------- /files/shtml/home.shtml: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 | {{# list }} 5 | 11 | {{/ list }} 12 |
13 | 14 |
15 | 16 |
17 | 18 |
19 |
20 |

Recommended for you


21 | 22 |
23 | {{# recommended }} 24 |
25 |
26 | {{mg}} 27 |
28 |

{{heading}}

29 |

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

30 |

Button Button

31 |
32 |
33 |
34 | {{/ recommended }} 35 |
36 | 37 |
38 |
39 |
40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlowerStore.class/instance/headerList..st: -------------------------------------------------------------------------------- 1 | route - main 2 | headerList: req 3 | | list result ssoUserId user | 4 | 5 | list := { 6 | '64x64.svg'->'rose'. 7 | '64x64.svg'->'violet'. 8 | '64x64.svg'->'tulip'. 9 | '64x64.svg'->'orchid'. 10 | } collect: [ :each | 11 | { 12 | (Association key: 'heading' value: each value). 13 | (Association key: 'img' value: each key). 14 | (Association key: 'href' value: '/search/', each value) 15 | } asDictionary. 16 | ]. 17 | 18 | result := { 19 | 'headerHomeUrl' -> '/'. 20 | 'headerSearchUrl' -> '/search'. 21 | 'navItemFindUrl' -> '/search'. 22 | 'navItemListUrl' -> '/class-add'. 23 | 'list' -> list. 24 | 'recommended' -> self recommendedList 25 | } asDictionary. 26 | 27 | ssoUserId := self loggedInUserId: req. 28 | ssoUserId notNil ifTrue: [ 29 | result at: 'logInOrOutUrl' put: '/logout'. 30 | result at: 'logInOrOutText' put: 'LOG OUT'. 31 | result at: 'loggedInUser' put: ' (', ssoUserId, ')'. 32 | user := self loggedInUser: req. 33 | (user notNil and: [ user isSuperuser ]) ifTrue: [ 34 | result at: 'isSuperuser?' put: true] 35 | ] 36 | ifFalse: [ 37 | result at: 'logInOrOutUrl' put: '/login'. 38 | result at: 'logInOrOutText' put: 'LOG IN'. 39 | result at: 'loggedInUser' put: ''. 40 | ]. 41 | 42 | ^result -------------------------------------------------------------------------------- /files/shtml/register.shtml: -------------------------------------------------------------------------------- 1 |
2 | 3 | 41 | 42 |
43 | -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMUser.class/methodProperties.json: -------------------------------------------------------------------------------- 1 | { 2 | "class" : { 3 | "descriptionContainer" : "YanniChiu 4/25/2015 21:59", 4 | "facebookUserId:" : "YanniChiu 1/26/2015 22:40", 5 | "findGoogleUserId:" : "YanniChiu 4/25/2015 10:02", 6 | "findLocalUserId:" : "YanniChiu 4/27/2015 00:04", 7 | "findUserId:providerName:" : "YanniChiu 4/25/2015 10:02", 8 | "googleUserId:" : "YanniChiu 1/26/2015 22:40", 9 | "isVoyageRoot" : "YanniChiu 4/21/2015 00:35", 10 | "listHeadings" : "YanniChiu 4/29/2015 01:13", 11 | "twitterUserId:" : "YanniChiu 1/26/2015 22:40", 12 | "userId:providerName:" : "YanniChiu 1/26/2015 23:02" }, 13 | "instance" : { 14 | "asDictionary" : "YanniChiu 4/29/2015 01:54", 15 | "asEditDictionary" : "YanniChiu 1/31/2015 22:09", 16 | "asSelectTagDictionary" : "YanniChiu 1/31/2015 22:57", 17 | "asViewDictionary" : "YanniChiu 3/1/2015 20:01", 18 | "descriptionProviderName" : "YanniChiu 1/26/2015 22:25", 19 | "descriptionUserId" : "YanniChiu 1/26/2015 22:25", 20 | "isSuperuser" : "YanniChiu 4/25/2015 08:22", 21 | "ownerQueryString" : "YanniChiu 1/26/2015 00:46", 22 | "passwordHash" : "YanniChiu 4/25/2015 21:36", 23 | "passwordHash:" : "YanniChiu 4/25/2015 21:36", 24 | "printOn:" : "YanniChiu 4/29/2015 00:41", 25 | "providerName" : "YanniChiu 1/26/2015 00:35", 26 | "providerName:" : "YanniChiu 1/26/2015 00:35", 27 | "userId" : "YanniChiu 1/26/2015 00:11", 28 | "userId:" : "YanniChiu 1/26/2015 00:11" } } 29 | -------------------------------------------------------------------------------- /files/shtml/header.shtml: -------------------------------------------------------------------------------- 1 | 45 | 46 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | #TMM 2 | *TMM (Teapot, Mustache, Mongo) is a simple to use Web/CRUD framework built on Pharo Smalltalk.* 3 | 4 | The main elements of the framework are: 5 | * Teapot - a micro web framework] 6 | * Mustache - a popular templating engine 7 | * Mongo - a key/value store (a.k.a. noSQL database) 8 | * Voyage - a small persistence framework for "mapping" to an object database 9 | * Magritte3 - a meta data framework 10 | * Zinc SSO - a single-sign-on framework 11 | 12 | Some useful links: 13 | * [Teapot - Pharo repository](http://smalltalkhub.com/#!/~zeroflag/Teapot) 14 | * [Mustache - Pharo repository](http://smalltalkhub.com/#!/~NorbertHartl/Mustache) 15 | * [Mustache blog post](http://norbert.hartl.name/blog/2013/10/03/mustache-templates-for-smalltalk/) 16 | * [Mustache website](https://mustache.github.io/) 17 | * [Voyage/MongoDB blog post](http://tulipemoutarde.be/2012/05/24/mongodb-with-voyage-in-pharo.html) 18 | * [Voyage - Pharo repository](http://smalltalkhub.com/#!/~estebanlm/Voyage) 19 | * [MongoDB website](https://www.mongodb.org/) 20 | * [Zinc SSO documentation](https://github.com/svenvc/docs/blob/master/zinc/zinc-sso-paper.md) 21 | 22 | 23 | ## Installing 24 | 25 | The current version of **TMM** has been tested in 26 | Pharo4.0 27 | 28 | ### Pharo 29 | To install in **Pharo**: 30 | 31 | ``` 32 | CodeImporter evaluateString: 33 | 'https://raw.githubusercontent.com/yannij/TMM/master/ConfigurationOfTMM.st' asUrl retrieveContents. 34 | ``` 35 | 36 | ```Smalltalk 37 | ((Smalltalk at: #ConfigurationOfTMM) project version: #'stable') load. 38 | ``` 39 | 40 | ## Configure 41 | 42 | Find the config-sample.json file in the git filetree. Copy the file to the image directory, and name it "config.json". Edit the value of "staticFilePath" - point it at the "files" directory in the git filetree. 43 | 44 | ## Run 45 | 46 | After MongoDB is running, set up the demo repository using: 47 | ``` 48 | TMMFlowerStore setUpMongo. 49 | ``` 50 | 51 | Start the web server using: 52 | ``` 53 | TMMFlowerStore runLocal. 54 | ``` 55 | 56 | From a web browser, go to: 57 | 58 | http://localhost:1701. 59 | 60 | ## TO DO 61 | https://github.com/yannij/TMM/wiki 62 | -------------------------------------------------------------------------------- /files/shtml/login.shtml: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 |
5 | 6 | 56 |
57 | 58 |
59 |
60 | -------------------------------------------------------------------------------- /ConfigurationOfTMM.st: -------------------------------------------------------------------------------- 1 | Object subclass: #ConfigurationOfTMM instanceVariableNames: 'project' classVariableNames: 'LastVersionLoad' poolDictionaries: '' category: 'ConfigurationOfTMM'! !ConfigurationOfTMM methodsFor: 'baselines' stamp: 'YanniChiu 4/26/2015 21:28'! baseline1: spec spec for: #common do: [ spec blessing: #baseline; repository: 'github://yannij/TMM:master/repository'; project: 'VoyageMongo' with: [ spec className: 'ConfigurationOfVoyageMongo'; version: #stable; repository: 'http://smalltalkhub.com/mc/Pharo/MetaRepoForPharo40/main ' ]; project: 'Mustache' with: [ spec className: 'ConfigurationOfMustache'; version: #stable; repository: 'http://smalltalkhub.com/mc/Pharo/MetaRepoForPharo40/main ' ]; project: 'Teapot' with: [ spec className: 'ConfigurationOfTeapot'; version: #stable; repository: 'http://smalltalkhub.com/mc/Pharo/MetaRepoForPharo40/main ' ]; project: 'ZincSSO' with: [ spec className: 'ConfigurationOfZincHTTPComponents'; version: #stable; loads: #('SSO'); repository: 'http://mc.stfx.eu/ZincHTTPComponents' ]; package: 'TMM-Core' with: [ spec requires: #( 'VoyageMongo' 'Mustache' 'Teapot' 'ZincSSO' ) ]; group: 'default' with: #('TMM-Core'); group: 'Core' with: #('TMM-Core')]! ! !ConfigurationOfTMM methodsFor: 'symbolic versions' stamp: 'YanniChiu 5/1/2015 01:56'! stable: spec spec for: #common version: '3'. ! ! !ConfigurationOfTMM methodsFor: 'symbolic versions' stamp: 'YanniChiu 4/27/2015 22:29'! development: spec spec for: #common version: '3'. ! ! !ConfigurationOfTMM methodsFor: 'versions' stamp: 'YanniChiu 5/1/2015 01:56'! version2: spec spec for: #common do: [ spec blessing: #stable; package: 'TMM-Core' with: 'TMM-Core-YanniChiu.2' ]! ! !ConfigurationOfTMM methodsFor: 'versions' stamp: 'YanniChiu 4/27/2015 01:01'! version1: spec spec for: #common do: [ spec blessing: #stable; package: 'TMM-Core' with: 'TMM-Core-YanniChiu.2' ]! ! !ConfigurationOfTMM methodsFor: 'versions' stamp: 'YanniChiu 5/1/2015 01:55'! version3: spec spec for: #common do: [ spec blessing: #stable; package: 'TMM-Core' with: 'TMM-Core-YanniChiu.3' ]! ! !ConfigurationOfTMM methodsFor: 'accessing' stamp: 'YanniChiu 4/26/2015 16:34'! project ^ project ifNil: [ | constructor | "Bootstrap Metacello if it is not already loaded" (self class baseConfigurationClassIfAbsent: []) ensureMetacello. "Construct Metacello project" constructor := (Smalltalk at: #MetacelloVersionConstructor) on: self. project := constructor project. project loadType: #linear. "change to #atomic if desired" project ]! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! ConfigurationOfTMM class instanceVariableNames: ''! !ConfigurationOfTMM class methodsFor: 'accessing' stamp: 'YanniChiu 4/26/2015 16:39'! project ^self new project! ! !ConfigurationOfTMM class methodsFor: 'loading' stamp: 'YanniChiu 4/26/2015 16:39'! loadBleedingEdge "Load the latest versions of the mcz files defined for this project. It is not likely that the #bleedingEdge has been tested." "self loadBleedingEdge" ^(self project version: #bleedingEdge) load! ! !ConfigurationOfTMM class methodsFor: 'loading' stamp: 'YanniChiu 4/26/2015 16:39'! load "Load the #stable version defined for this platform. The #stable version is the version that is recommended to be used on this platform." "self load" ^(self project version: #stable) load! ! !ConfigurationOfTMM class methodsFor: 'loading' stamp: 'YanniChiu 4/26/2015 16:40'! loadDevelopment "Load the #development version defined for this platform. The #development version will change over time and is not expected to be stable." "self loadDevelopment" ^(self project version: #development) load! ! !ConfigurationOfTMM class methodsFor: 'private' stamp: 'YanniChiu 4/26/2015 16:41'! ensureMetacelloBaseConfiguration Smalltalk at: #MetacelloBaseConfiguration ifAbsent: [ | repository version | repository := MCHttpRepository location: 'http://seaside.gemstone.com/ss/metacello' user: '' password: ''. repository versionReaderForFileNamed: 'Metacello-Base-DaleHenrichs.2.mcz' do: [ :reader | version := reader version. version load. version workingCopy repositoryGroup addRepository: repository ] ]! ! !ConfigurationOfTMM class methodsFor: 'private' stamp: 'YanniChiu 4/26/2015 16:40'! baseConfigurationClassIfAbsent: aBlock ^Smalltalk at: #MetacelloBaseConfiguration ifAbsent: [ self ensureMetacelloBaseConfiguration. Smalltalk at: #MetacelloBaseConfiguration ifAbsent: aBlock ]. ! ! !ConfigurationOfTMM class methodsFor: 'private' stamp: 'YanniChiu 4/26/2015 16:41'! ensureMetacello (self baseConfigurationClassIfAbsent: []) ensureMetacello! ! !ConfigurationOfTMM class methodsFor: 'metacello tool support' stamp: 'YanniChiu 4/26/2015 16:40'! isMetacelloConfig "Answer true and the Metacello tools will operate on you" ^true! ! -------------------------------------------------------------------------------- /repository/TMM-Core.package/TMMFlowerStore.class/methodProperties.json: -------------------------------------------------------------------------------- 1 | { 2 | "class" : { 3 | "buildConfig" : "YanniChiu 4/21/2015 00:39", 4 | "clearConfig" : "YanniChiu 4/21/2015 00:42", 5 | "config" : "YanniChiu 4/21/2015 00:40", 6 | "defaultStaticFilePath" : "YanniChiu 4/21/2015 00:28", 7 | "defaultUrlPrefix" : "YanniChiu 4/21/2015 00:28", 8 | "facebookKey" : "YanniChiu 4/21/2015 00:28", 9 | "facebookSecret" : "YanniChiu 4/21/2015 00:29", 10 | "googleKey" : "YanniChiu 4/21/2015 00:29", 11 | "googleSecret" : "YanniChiu 4/21/2015 00:29", 12 | "resetMongoDescriptionCache" : "YanniChiu 4/25/2015 20:30", 13 | "runLocal" : "YanniChiu 4/25/2015 08:22", 14 | "runScheme:host:portno:serverPortno:staticFilePath:" : "YanniChiu 4/25/2015 21:40", 15 | "setUpMongo" : "YanniChiu 4/25/2015 21:24", 16 | "twitterKey" : "YanniChiu 4/21/2015 00:29", 17 | "twitterSecret" : "YanniChiu 4/21/2015 00:30" }, 18 | "instance" : { 19 | "actionFlowerAdd:" : "YanniChiu 4/25/2015 10:02", 20 | "actionFlowerAddForm:" : "YanniChiu 4/25/2015 10:02", 21 | "actionFlowerEdit:" : "YanniChiu 3/8/2015 00:14", 22 | "actionFlowerList:" : "YanniChiu 4/25/2015 10:02", 23 | "actionFlowerView:" : "YanniChiu 3/7/2015 19:03", 24 | "actionLoginGet:" : "YanniChiu 4/26/2015 23:58", 25 | "actionLoginPost:" : "YanniChiu 4/27/2015 00:35", 26 | "actionLogoutGet:" : "YanniChiu 4/27/2015 00:00", 27 | "actionObectList:" : "YanniChiu 4/29/2015 01:08", 28 | "actionRegisterGet:" : "YanniChiu 4/27/2015 00:00", 29 | "actionRegisterPost:" : "YanniChiu 4/27/2015 00:38", 30 | "actionUserEdit:" : "YanniChiu 3/1/2015 19:55", 31 | "actionUserEditForm:" : "YanniChiu 4/25/2015 10:02", 32 | "actionUserView:" : "YanniChiu 1/31/2015 22:37", 33 | "addRouteFlower" : "YanniChiu 4/25/2015 10:02", 34 | "addRouteHome" : "YanniChiu 1/19/2015 23:36", 35 | "addRouteLogin" : "YanniChiu 4/27/2015 00:02", 36 | "addRouteLoginFacebook" : "YanniChiu 1/23/2015 21:31", 37 | "addRouteLoginGoogle" : "YanniChiu 3/1/2015 20:10", 38 | "addRouteLoginTwitter" : "YanniChiu 3/1/2015 23:33", 39 | "addRouteObject" : "YanniChiu 4/29/2015 01:03", 40 | "addRouteRestart" : "YanniChiu 1/17/2015 00:27", 41 | "addRouteSearch" : "YanniChiu 4/25/2015 10:02", 42 | "addRouteUpload" : "YanniChiu 3/30/2015 23:37", 43 | "addRouteUser" : "YanniChiu 1/31/2015 22:12", 44 | "addRouteUserEdit" : "YanniChiu 1/31/2015 22:13", 45 | "addRoutes" : "YanniChiu 4/28/2015 01:24", 46 | "bytesForImageFileName:" : "YanniChiu 3/12/2015 01:12", 47 | "facebookSessionFor:" : "YanniChiu 1/23/2015 21:38", 48 | "findFlowerOrNil:" : "YanniChiu 4/25/2015 10:02", 49 | "findUserOrNil:" : "YanniChiu 4/25/2015 10:02", 50 | "flower" : "YanniChiu 4/25/2015 10:02", 51 | "formForImageEntity:" : "YanniChiu 3/10/2015 22:38", 52 | "generateInvalidCallbackRequest" : "YanniChiu 1/22/2015 01:42", 53 | "googleSessionFor:" : "YanniChiu 1/22/2015 00:21", 54 | "handleGetRequest:" : "YanniChiu 3/30/2015 22:56", 55 | "handlePostRequest:" : "YanniChiu 3/13/2015 00:08", 56 | "handleQuery:" : "YanniChiu 4/25/2015 10:02", 57 | "headerList:" : "YanniChiu 4/25/2015 23:28", 58 | "html" : "YanniChiu 3/30/2015 23:38", 59 | "image" : "YanniChiu 3/13/2015 00:44", 60 | "initializeOn:" : "YanniChiu 1/22/2015 00:06", 61 | "isOAuth2Callback:" : "YanniChiu 1/21/2015 00:52", 62 | "loggedInUser:" : "YanniChiu 4/25/2015 10:02", 63 | "loggedInUserId:" : "YanniChiu 1/25/2015 23:53", 64 | "mustacheAddFor:" : "YanniChiu 4/28/2015 00:05", 65 | "mustacheEditFor:" : "YanniChiu 4/28/2015 00:05", 66 | "mustacheListFor:" : "YanniChiu 4/28/2015 00:06", 67 | "mustacheNamed:" : "YanniChiu 4/25/2015 00:30", 68 | "mustacheViewFor:" : "YanniChiu 4/28/2015 00:06", 69 | "output:addAll:" : "YanniChiu 1/19/2015 23:39", 70 | "partialsWithTemplateContents:" : "YanniChiu 3/2/2015 01:14", 71 | "partialsWithTemplateNamed:" : "YanniChiu 1/18/2015 00:17", 72 | "recommendedList" : "YanniChiu 4/25/2015 23:14", 73 | "retrieve:using:" : "YanniChiu 1/8/2015 01:09", 74 | "serveStaticFilesFrom:" : "YanniChiu 2/28/2015 00:50", 75 | "server" : "YanniChiu 9/13/2014 21:38", 76 | "server:" : "YanniChiu 9/13/2014 21:38", 77 | "ssoData" : "YanniChiu 1/22/2015 00:13", 78 | "ssoData:" : "YanniChiu 1/22/2015 00:13", 79 | "ssoDataAt:" : "YanniChiu 1/22/2015 00:14", 80 | "ssoDataAt:put:" : "YanniChiu 1/22/2015 00:15", 81 | "ssoFacebook:" : "YanniChiu 1/23/2015 21:20", 82 | "ssoFacebookCallback:" : "YanniChiu 1/23/2015 21:22", 83 | "ssoFacebookData:" : "YanniChiu 1/26/2015 00:41", 84 | "ssoGoogle:" : "YanniChiu 1/21/2015 00:49", 85 | "ssoGoogleCallback:" : "YanniChiu 1/21/2015 23:37", 86 | "ssoGoogleData:" : "YanniChiu 1/26/2015 00:42", 87 | "ssoLogout:" : "YanniChiu 1/19/2015 23:53", 88 | "ssoTwitter:" : "YanniChiu 1/22/2015 01:22", 89 | "ssoTwitterCallback:" : "YanniChiu 1/18/2015 23:11", 90 | "ssoTwitterData:" : "YanniChiu 1/26/2015 00:42", 91 | "start" : "YanniChiu 12/2/2014 00:07", 92 | "staticFilePath" : "YanniChiu 12/2/2014 00:01", 93 | "staticFilePath:" : "YanniChiu 12/2/2014 00:01", 94 | "teapotListBlock" : "YanniChiu 5/1/2015 01:46", 95 | "templateContents:" : "YanniChiu 1/17/2015 00:00", 96 | "twitterOAuth1Service" : "YanniChiu 1/22/2015 00:15", 97 | "twitterSessionFor:ifAbsent:" : "YanniChiu 1/18/2015 23:19", 98 | "twitterSessionFor:put:" : "YanniChiu 1/18/2015 23:21", 99 | "userFromRequest:" : "YanniChiu 4/25/2015 10:02" } } 100 | --------------------------------------------------------------------------------