From ffca86a9ffd0701d10f039a51f9688259eda8d52 Mon Sep 17 00:00:00 2001 From: Artyom Kazak Date: Sat, 22 Sep 2018 21:12:21 +0200 Subject: [PATCH 01/11] Add categories to the right groups (#218) * Add categories to the right groups --- front/client/components/AddCategoryDialog.vue | 5 +- front/client/service/Category.ts | 5 +- src/Guide/Api/Methods.hs | 13 +++-- src/Guide/Api/Types.hs | 11 +++- src/Guide/Handlers.hs | 2 +- src/Guide/ServerStuff.hs | 4 +- src/Guide/State.hs | 7 ++- src/Guide/Types/Edit.hs | 58 ++++++------------- src/Guide/Views.hs | 3 +- 9 files changed, 49 insertions(+), 59 deletions(-) diff --git a/front/client/components/AddCategoryDialog.vue b/front/client/components/AddCategoryDialog.vue index 0daace7..74547e2 100644 --- a/front/client/components/AddCategoryDialog.vue +++ b/front/client/components/AddCategoryDialog.vue @@ -93,7 +93,10 @@ export default class AddCategoryDialog extends Vue { } // TODO move to vuex // TODO handle errors - const createdId = await CategoryService.createCategory({ title: this.categoryName }) + const createdId = await CategoryService.createCategory({ + title: this.categoryName, + group: this.groupNameInternal + }) this.$store.dispatch('category/loadCategoryList') window.open(`http://aelve.com:4801/haskell/${createdId}`, '_blank') this.isDialogOpen = false diff --git a/front/client/service/Category.ts b/front/client/service/Category.ts index 40a81da..e6661d8 100644 --- a/front/client/service/Category.ts +++ b/front/client/service/Category.ts @@ -6,10 +6,11 @@ class CategoryService { return data } - async createCategory({ title }: ICategory): Promise { + async createCategory({ title, group }: ICategory): Promise { const { data } = await axios.post('api/category', null, { params: { - title + title, + group } }) return data diff --git a/src/Guide/Api/Methods.hs b/src/Guide/Api/Methods.hs index 562ddac..7f684c3 100644 --- a/src/Guide/Api/Methods.hs +++ b/src/Guide/Api/Methods.hs @@ -36,21 +36,22 @@ getCategory db catId = Nothing -> throwError err404 Just cat -> pure (toCCategoryFull cat) --- | Create a new category, given the title. +-- | Create a new category, given the title and the grandparent (aka group). -- -- Returns the ID of the created category (or of the existing one if the -- category with this title exists already). -createCategory :: DB -> Text -> Handler (Uid Category) -createCategory db title' = do +createCategory :: DB -> Text -> Text -> Handler (Uid Category) +createCategory db title' group' = do -- If the category exists already, don't create it cats <- view categories <$> dbQuery db GetGlobalState - let hasSameTitle cat = T.toCaseFold (cat^.title) == T.toCaseFold title' - case find hasSameTitle cats of + let isDuplicate cat = T.toCaseFold (cat^.title) == T.toCaseFold title' + && T.toCaseFold (cat^.group_) == T.toCaseFold group' + case find isDuplicate cats of Just c -> return (c^.uid) Nothing -> do catId <- randomShortUid time <- liftIO getCurrentTime - (_edit, newCategory) <- dbUpdate db (AddCategory catId title' time) + (_edit, newCategory) <- dbUpdate db (AddCategory catId title' group' time) -- TODO addEdit edit return (newCategory^.uid) diff --git a/src/Guide/Api/Types.hs b/src/Guide/Api/Types.hs index c36f690..b7fd4ea 100644 --- a/src/Guide/Api/Types.hs +++ b/src/Guide/Api/Types.hs @@ -90,11 +90,16 @@ data CategorySite route = CategorySite , _createCategory :: route :- Summary "Create a new category" :> Description "Returns the ID of the created category.\n\n\ - \If a category with the same title already exists, \ - \returns its ID instead." + \If a category with the same title already exists \ + \in the group, returns its ID instead." :> ErrorResponse 400 "'title' not provided" :> "category" - :> QueryParam' '[Required, Strict] "title" Text + :> QueryParam' '[Required, Strict, + Description "Title of the newly created category"] + "title" Text + :> QueryParam' '[Required, Strict, + Description "Group to put the category into"] + "group" Text :> Post '[JSON] (Uid Category) , _deleteCategory :: route :- diff --git a/src/Guide/Handlers.hs b/src/Guide/Handlers.hs index dee8928..01e45cf 100644 --- a/src/Guide/Handlers.hs +++ b/src/Guide/Handlers.hs @@ -274,7 +274,7 @@ addMethods = do Nothing -> do catId <- randomShortUid time <- liftIO getCurrentTime - (edit, newCategory) <- dbUpdate (AddCategory catId title' time) + (edit, newCategory) <- dbUpdate (AddCategory catId title' "Miscellaneous" time) invalidateCache' (CacheCategory catId) addEdit edit return newCategory diff --git a/src/Guide/ServerStuff.hs b/src/Guide/ServerStuff.hs index 1ac62eb..3bd6bc2 100644 --- a/src/Guide/ServerStuff.hs +++ b/src/Guide/ServerStuff.hs @@ -153,7 +153,7 @@ addEdit ed = do -- been deleted; this should change. undoEdit :: (MonadIO m, HasSpock m, SpockState m ~ ServerState) => Edit -> m (Either String ()) -undoEdit (Edit'AddCategory catId _) = do +undoEdit (Edit'AddCategory catId _ _) = do void <$> dbUpdate (DeleteCategory catId) undoEdit (Edit'AddItem _catId itemId _) = do void <$> dbUpdate (DeleteItem itemId) @@ -245,7 +245,7 @@ invalidateCacheForEdit invalidateCacheForEdit ed = do gs <- dbQuery GetGlobalState mapM_ (invalidateCache gs) $ case ed of - Edit'AddCategory catId _ -> + Edit'AddCategory catId _ _ -> [CacheCategory catId] -- Normally invalidateCache should invalidate item's category -- automatically, but in this case it's *maybe* possible that the item diff --git a/src/Guide/State.hs b/src/Guide/State.hs index a54fb08..87579ff 100644 --- a/src/Guide/State.hs +++ b/src/Guide/State.hs @@ -345,13 +345,14 @@ getTrait itemId traitId = view (itemById itemId . traitById traitId) addCategory :: Uid Category -- ^ New category's id -> Text -- ^ Title + -> Text -- ^ Group -> UTCTime -- ^ Creation time -> Acid.Update GlobalState (Edit, Category) -addCategory catId title' created' = do +addCategory catId title' group' created' = do let newCategory = Category { _categoryUid = catId, _categoryTitle = title', - _categoryGroup_ = "Miscellaneous", + _categoryGroup_ = group', _categoryEnabledSections = S.fromList [ ItemProsConsSection, ItemEcosystemSection, @@ -363,7 +364,7 @@ addCategory catId title' created' = do _categoryItems = [], _categoryItemsDeleted = [] } categories %= (newCategory :) - let edit = Edit'AddCategory catId title' + let edit = Edit'AddCategory catId title' group' return (edit, newCategory) addItem diff --git a/src/Guide/Types/Edit.hs b/src/Guide/Types/Edit.hs index 000da98..f389620 100644 --- a/src/Guide/Types/Edit.hs +++ b/src/Guide/Types/Edit.hs @@ -19,8 +19,6 @@ where import Imports --- Containers -import qualified Data.Set as S -- Network import Data.IP -- acid-state @@ -36,7 +34,8 @@ data Edit -- Add = Edit'AddCategory { editCategoryUid :: Uid Category, - editCategoryTitle :: Text } + editCategoryTitle :: Text, + editCategoryGroup :: Text } | Edit'AddItem { editCategoryUid :: Uid Category, editItemUid :: Uid Item, @@ -133,11 +132,13 @@ data Edit deriving (Eq, Show) -deriveSafeCopySimple 7 'extension ''Edit +deriveSafeCopySimple 8 'extension ''Edit -genVer ''Edit 6 [ +genVer ''Edit 7 [ -- Add - Copy 'Edit'AddCategory, + Custom "Edit'AddCategory" [ + ("editCategoryUid" , [t|Uid Category|]), + ("editCategoryTitle", [t|Text|]) ], Copy 'Edit'AddItem, Copy 'Edit'AddPro, Copy 'Edit'AddCon, @@ -146,18 +147,7 @@ genVer ''Edit 6 [ Copy 'Edit'SetCategoryGroup, Copy 'Edit'SetCategoryNotes, Copy 'Edit'SetCategoryStatus, - Custom "Edit'SetCategoryProsConsEnabled" [ - ("editCategoryUid" , [t|Uid Category|]), - ("_editCategoryProsConsEnabled" , [t|Bool|]), - ("editCategoryNewProsConsEnabled" , [t|Bool|]) ], - Custom "Edit'SetCategoryEcosystemEnabled" [ - ("editCategoryUid" , [t|Uid Category|]), - ("_editCategoryEcosystemEnabled" , [t|Bool|]), - ("editCategoryNewEcosystemEnabled", [t|Bool|]) ], - Custom "Edit'SetCategoryNotesEnabled" [ - ("editCategoryUid" , [t|Uid Category|]), - ("_editCategoryNotesEnabled" , [t|Bool|]), - ("editCategoryNewNotesEnabled" , [t|Bool|]) ], + Copy 'Edit'ChangeCategoryEnabledSections, -- Change item properties Copy 'Edit'SetItemName, Copy 'Edit'SetItemLink, @@ -176,12 +166,17 @@ genVer ''Edit 6 [ Copy 'Edit'MoveItem, Copy 'Edit'MoveTrait ] -deriveSafeCopySimple 6 'base ''Edit_v6 +deriveSafeCopySimple 7 'base ''Edit_v7 instance Migrate Edit where - type MigrateFrom Edit = Edit_v6 - migrate = $(migrateVer ''Edit 6 [ - CopyM 'Edit'AddCategory, + type MigrateFrom Edit = Edit_v7 + migrate = $(migrateVer ''Edit 7 [ + CustomM "Edit'AddCategory" [|\x -> + Edit'AddCategory + { editCategoryUid = editCategoryUid_v7 x + , editCategoryTitle = editCategoryTitle_v7 x + , editCategoryGroup = toText "Miscellaneous" + } |], CopyM 'Edit'AddItem, CopyM 'Edit'AddPro, CopyM 'Edit'AddCon, @@ -190,24 +185,7 @@ instance Migrate Edit where CopyM 'Edit'SetCategoryGroup, CopyM 'Edit'SetCategoryNotes, CopyM 'Edit'SetCategoryStatus, - CustomM "Edit'SetCategoryProsConsEnabled" [|\x -> - if editCategoryNewProsConsEnabled_v6 x - then Edit'ChangeCategoryEnabledSections (editCategoryUid_v6 x) - (S.singleton ItemProsConsSection) mempty - else Edit'ChangeCategoryEnabledSections (editCategoryUid_v6 x) - mempty (S.singleton ItemProsConsSection) |], - CustomM "Edit'SetCategoryEcosystemEnabled" [|\x -> - if editCategoryNewEcosystemEnabled_v6 x - then Edit'ChangeCategoryEnabledSections (editCategoryUid_v6 x) - (S.singleton ItemEcosystemSection) mempty - else Edit'ChangeCategoryEnabledSections (editCategoryUid_v6 x) - mempty (S.singleton ItemEcosystemSection) |], - CustomM "Edit'SetCategoryNotesEnabled" [|\x -> - if editCategoryNewNotesEnabled_v6 x - then Edit'ChangeCategoryEnabledSections (editCategoryUid_v6 x) - (S.singleton ItemNotesSection) mempty - else Edit'ChangeCategoryEnabledSections (editCategoryUid_v6 x) - mempty (S.singleton ItemNotesSection) |], + CopyM 'Edit'ChangeCategoryEnabledSections, -- Change item properties CopyM 'Edit'SetItemName, CopyM 'Edit'SetItemLink, diff --git a/src/Guide/Views.hs b/src/Guide/Views.hs index b7f2576..0ff4553 100644 --- a/src/Guide/Views.hs +++ b/src/Guide/Views.hs @@ -412,8 +412,9 @@ renderEdit globalState edit = do case edit of -- Add - Edit'AddCategory _catId title' -> p_ $ do + Edit'AddCategory _catId title' group' -> p_ $ do "added category " >> quote (toHtml title') + " to group " >> quote (toHtml group') Edit'AddItem catId _itemId name' -> p_ $ do "added item " >> printItem _itemId " (initially called " >> quote (toHtml name') >> ")" From 4b0f6407cad17cd35d02ea6ac4bedb3a5c1cb17b Mon Sep 17 00:00:00 2001 From: Artyom Kazak Date: Sat, 22 Sep 2018 21:51:21 +0200 Subject: [PATCH 02/11] Don't mark fields with (?) as "always required" --- src/Guide/Api/Utils.hs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Guide/Api/Utils.hs b/src/Guide/Api/Utils.hs index c8e001a..b388dc4 100644 --- a/src/Guide/Api/Utils.hs +++ b/src/Guide/Api/Utils.hs @@ -19,8 +19,10 @@ module Guide.Api.Utils import Imports import GHC.TypeLits +import GHC.Generics import Data.Aeson import Data.Swagger hiding (fieldLabelModifier) +import Data.Swagger.Internal.Schema import Servant import Servant.Swagger @@ -53,6 +55,9 @@ instance (KnownSymbol help, ToSchema a) => ToSchema (a ? help) where where desc = symbolVal (Proxy @help) +instance {-# OVERLAPPING #-} (KnownSymbol help, Selector s, ToSchema c) => GToSchema (S1 s (K1 i (Maybe c ? help))) where + gdeclareNamedSchema opts _ = fmap unnamed . withFieldSchema opts (Proxy2 :: Proxy2 s (K1 i (Maybe c ? help))) False + -- | A way to name branches of Swagger API. -- -- Taken from From 5b3600d7b476ff78f5a4541314269ff1d001297b Mon Sep 17 00:00:00 2001 From: Artyom Kazak Date: Sat, 22 Sep 2018 22:05:32 +0200 Subject: [PATCH 03/11] Update footer (#217) * Remove the "donate" page * Remove the "rules" page * Made by Aelve * Remove "issue tracker" * Fix the footer test --- front/client/components/AFooter.vue | 28 ++---------- src/Guide/Main.hs | 6 --- src/Guide/Views.hs | 19 ++------ src/Guide/Views/Page.hs | 15 ++----- static/donate.html | 36 --------------- static/unwritten-rules.md | 68 ----------------------------- tests/WebSpec.hs | 2 +- 7 files changed, 10 insertions(+), 164 deletions(-) delete mode 100644 static/donate.html delete mode 100644 static/unwritten-rules.md diff --git a/front/client/components/AFooter.vue b/front/client/components/AFooter.vue index 8fc3afd..77f3545 100644 --- a/front/client/components/AFooter.vue +++ b/front/client/components/AFooter.vue @@ -13,9 +13,9 @@ made by - Artyom + Aelve @@ -25,29 +25,7 @@ > source - / - - issue tracker - - - - - Rules - - - - - Donate - + on GitHub licensed under diff --git a/src/Guide/Main.hs b/src/Guide/Main.hs index 8e7f05c..533f0a0 100644 --- a/src/Guide/Main.hs +++ b/src/Guide/Main.hs @@ -279,13 +279,7 @@ guideApp waiMetrics = do s <- dbQuery GetGlobalState lucidIO $ renderAdminLinks s - -- Donation page - Spock.get "donate" $ - lucidWithConfig renderDonate - -- Static pages - Spock.get "unwritten-rules" $ lucidWithConfig $ - renderStaticMd "Unwritten rules" "unwritten-rules.md" Spock.get "markdown" $ lucidWithConfig $ renderStaticMd "Markdown" "markdown.md" Spock.get "license" $ lucidWithConfig $ diff --git a/src/Guide/Views.hs b/src/Guide/Views.hs index 0ff4553..91ed950 100644 --- a/src/Guide/Views.hs +++ b/src/Guide/Views.hs @@ -17,7 +17,6 @@ module Guide.Views renderRoot, renderAdmin, renderAdminLinks, - renderDonate, renderCategoryPage, renderHaskellRoot, @@ -605,12 +604,6 @@ renderNoScriptWarning = you won't be able to edit anything. |] --- | Render the page. -renderDonate - :: (MonadIO m, MonadReader Config m) => HtmlT m () -renderDonate = wrapPage "Donate to Artyom" $ do - toHtmlRaw =<< liftIO (readFile "static/donate.html") - -- | Render any page that is a static piece of Markdown. renderStaticMd :: (MonadIO m, MonadReader Config m) @@ -684,15 +677,9 @@ wrapPage pageTitle' page = doctypehtml_ $ do page div_ [id_ "footer"] $ do mapM_ (div_ [class_ "footer-item"]) $ - [ do "made by " - mkLink "Artyom" "https://artyom.me" - , do mkLink "source" "https://github.com/aelve/guide" - "/" - mkLink "issue tracker" "https://github.com/aelve/guide/issues" - , mkLink "rules" "/unwritten-rules" - , mkLink "donate" "/donate" - , do "licensed under " - mkLink "CC+ BY-SA 4.0" "/license" + [ "made by " >> mkLink "Aelve" "https://aelve.com" + , mkLink "source" "https://github.com/aelve/guide" >> " on GitHub" + , "licensed under " >> mkLink "CC+ BY-SA 4.0" "/license" ] -- | Render the search box. diff --git a/src/Guide/Views/Page.hs b/src/Guide/Views/Page.hs index 3e8b8da..ce73b54 100644 --- a/src/Guide/Views/Page.hs +++ b/src/Guide/Views/Page.hs @@ -179,18 +179,9 @@ footerDef -> HtmlT m () footerDef _page = do mapM_ (div_ [class_ "footer-item"]) $ - [ do - "made by " - mkLink "Artyom" "https://artyom.me" - , do - mkLink "source" "https://github.com/aelve/guide" - "/" - mkLink "issue tracker" "https://github.com/aelve/guide/issues" - , mkLink "rules" "/unwritten-rules" - , mkLink "donate" "/donate" - , do - "licensed under " - mkLink "CC+ BY-SA 4.0" "/license" + [ "made by " >> mkLink "Aelve" "https://aelve.com" + , mkLink "source" "https://github.com/aelve/guide" >> " on GitHub" + , "licensed under " >> mkLink "CC+ BY-SA 4.0" "/license" ] diff --git a/static/donate.html b/static/donate.html deleted file mode 100644 index dafc971..0000000 --- a/static/donate.html +++ /dev/null @@ -1,36 +0,0 @@ -

Donate

- -

Okay, the rules: if you donate anything, I'll spend some time working on the site this day (adding content, implementing new features, etc). Of course, I'm planning to be working on the site anyway, donations or not! However, I jump from project to project way too often (and rarely manage to finish anything), so donating money is a good way to make sure that I'd feel obligated to keep working on this one. If I find out that it doesn't work as a motivation, I'll stop accepting donations.

- -

Just in case, 1000 rub. is 14$ (or 12.5€), and you can choose any amount below 15000 rub. I'd put a Paypal button, but Paypal doesn't allow receiving money in Belarus.

- -
- -
-
-
-
- - diff --git a/static/unwritten-rules.md b/static/unwritten-rules.md deleted file mode 100644 index 91e2017..0000000 --- a/static/unwritten-rules.md +++ /dev/null @@ -1,68 +0,0 @@ -# Unwritten rules - -If you disagree with any of these “rules”, ignore them! I don't think they are right, I just think they are better than what people would be doing otherwise if they didn't have any opinions on the matter. - -[Here](/markdown) is the description of custom Markdown features we support (and you're expected to use). - -## What to include - -Sort things by importance and don't try to write *everything*. The problem is that when you see 2 columns titled “pros” and “cons”, it makes people want to try and come up with as many pros/cons as possible (well, actually I don't know about *people*, but it does happen to me all the time, so it probably happens to others too). This should be avoided at all costs. Same with items themselves (e.g. libraries) – don't list all related libraries, list all libraries that could conceivably be chosen. The test is simple: if you can't say under what conditions a person would choose A over B, and B is already on the list, don't add A. I can very well relate to the vague feeling of “but A deserves to be mentioned too”, but still, don't. - -On the other hand, there's another problem that should somehow be avoided. Let's take the section about books – RWH and LYAH are often recommended to people, but there's Haskell Programming From First Principles (that book at [haskellbook.com](http://haskellbook.com)) and it's regarded to be Totally Better Than LYAH And RWH Put Together. Even despite the fact that the former 2 are free and the latter one isn't, all 3 books still have to be mentioned – otherwise, how is the reader going to know that LYAH was omitted because it's bad and not because everyone forgot to write about it? That's the problem that comes up very often, with lists like [What I Wish I Knew When Learning Haskell](http://dev.stephendiehl.com/hask/) and [State Of The Haskell Ecosystem](https://github.com/Gabriel439/post-rfc/blob/master/sotu.md) – there are people who wouldn't trust them not because they don't trust the author's good intentions, but because they are afraid that the author simply didn't list something worth mentioning. This leads to endless Google searches and traversals of related Hackage categories (and there are way too many packages on Hackage). - -In a nutshell: - - * don't list things that aren't really distinguishable from the already listed things - * do list things that people are likely to be *considering*, even if they aren't likely to actually choose them - -## Descriptions - -Unhelpful descriptions are unhelpful. For instance, here are bad [descriptions](http://www.alternative.to/category/internet/browsers) of several browsers: - -> Opera is a web browser and internet suite developed by the Opera Software company. The browser handles common Internet-related tasks such as [...] - -> Mozilla Firefox is a free, open source, cross-platform, graphical web browser developed by the Mozilla Corporation and hundreds of volunteers. [...] - -> Google Chrome is a web-browser from Google released on September 2nd, 2008. There are three main areas on which Google intends to improve the [...] - -These aren't descriptions, these are blurbs. Who the hell cares that Chrome was released on September 2nd? Why mention hundreds of volunteers? Who on earth invented the phrase “common Internet-related tasks”? The purpose of these “descriptions” has nothing to do with trying to help the reader. - -A description should convey information that isn't conveyed elsewhere. For instance, the reason the library/book/etc was created – e.g. “this is a fork of X” suggests that there are some problems with X, and for someone they were important enough to bother to fork it. What's more interesting, it's a *stronger* signal than saying “X has such-and-such problems” explicitly. Everything has problems; not everything has forks. - -A description should also summarise the pros/cons – “use this if X; don't use this if Y”. Yes, it doesn't give any new information, but it still helps the reader. - -## Code examples - -When giving long code examples, don't do this: - -~~~~ -Here we define data types: - -~~~ hs -data X = X -data Y = Y -~~~ - -And here we define a conversion: - -~~~ hs -xToY :: X -> Y -xToY X = Y -~~~ -~~~~ - -This makes it harder to copy the code (e.g. if you want to play with it). Instead, write comments as comments, but still break code into sections: - -~~~~ -~~~ hs --- Here we define data types -data X = X -data Y = Y -~~~ - -~~~ hs --- And here we define a conversion -xToY :: X -> Y -xToY X = Y -~~~ -~~~~ diff --git a/tests/WebSpec.hs b/tests/WebSpec.hs index 3556fef..f00e134 100644 --- a/tests/WebSpec.hs +++ b/tests/WebSpec.hs @@ -71,7 +71,7 @@ mainPageTests = session "main page" $ using [chromeCaps] $ do height `shouldBeInRange` (30, 70) wd "overflows when shrunk" $ do -- and now it shall be overflowing - setWindowSize (600, 500) + setWindowSize (400, 500) footer <- select "#footer" (_, height) <- elemSize footer height `shouldBeInRange` (71, 140) From 9c3ff51a4163aa7e547f3af33f18ec2965557df4 Mon Sep 17 00:00:00 2001 From: Giyos Date: Sun, 23 Sep 2018 02:21:43 +0500 Subject: [PATCH 04/11] Article v 0.0.6 --- front/client/components/Article.vue | 52 +++++++++++++++++++++++++---- 1 file changed, 45 insertions(+), 7 deletions(-) diff --git a/front/client/components/Article.vue b/front/client/components/Article.vue index 9bd199f..e5b0e1d 100644 --- a/front/client/components/Article.vue +++ b/front/client/components/Article.vue @@ -4,12 +4,30 @@


-
- - {{ ecosystem.html }} +
+

Summary

+
+
+
+

Pros

+
    +
  • +
+
+
+

Cons

+
    +
  • +
+
+
+

Ecosystem

+
+

Notes

+
@@ -38,18 +56,38 @@ export default class ArticleItem extends Vue { get getCategoryItems() { const items = this.$store.state.categoryItem.categoryItemList.items - const parsedItems = items.map((item:any) => {return item.ecosystem.html}) - return parsedItems + return items } } From 2e94e31a091fc708872e44ebe73979cc597a5119 Mon Sep 17 00:00:00 2001 From: Giyos Date: Sun, 23 Sep 2018 19:36:05 +0500 Subject: [PATCH 05/11] Article v 0.0.7 --- front/client/App.vue | 3 + front/client/components/Article.vue | 107 +++++++++++++++++++++++++--- 2 files changed, 101 insertions(+), 9 deletions(-) diff --git a/front/client/App.vue b/front/client/App.vue index ac95c86..d763667 100644 --- a/front/client/App.vue +++ b/front/client/App.vue @@ -33,4 +33,7 @@ export default class RootComponent extends Vue {} *:after { box-sizing: border-box; } +p { + margin: 0; +} \ No newline at end of file diff --git a/front/client/components/Article.vue b/front/client/components/Article.vue index e5b0e1d..e5b987c 100644 --- a/front/client/components/Article.vue +++ b/front/client/components/Article.vue @@ -1,13 +1,27 @@