mirror of
https://github.com/Damillora/Shioriko.git
synced 2024-12-05 00:53:45 +00:00
Compare commits
3 Commits
31763528bf
...
e175d12ca7
Author | SHA1 | Date | |
---|---|---|---|
e175d12ca7 | |||
f2c6d852a9 | |||
19e7aea06d |
@ -152,6 +152,15 @@ func postCreate(c *gin.Context) {
|
||||
}
|
||||
|
||||
func postUpdate(c *gin.Context) {
|
||||
_, ok := c.Get("user")
|
||||
if !ok {
|
||||
c.JSON(http.StatusForbidden, models.ErrorResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
Message: "User don't exist",
|
||||
})
|
||||
c.Abort()
|
||||
}
|
||||
|
||||
id := c.Param("id")
|
||||
|
||||
var model models.PostUpdateModel
|
||||
@ -194,6 +203,15 @@ func postUpdate(c *gin.Context) {
|
||||
}
|
||||
|
||||
func postDelete(c *gin.Context) {
|
||||
_, ok := c.Get("user")
|
||||
if !ok {
|
||||
c.JSON(http.StatusForbidden, models.ErrorResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
Message: "User don't exist",
|
||||
})
|
||||
c.Abort()
|
||||
}
|
||||
|
||||
id := c.Param("id")
|
||||
|
||||
err := services.DeletePost(id)
|
||||
|
@ -3,15 +3,26 @@ package app
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/Damillora/Shioriko/pkg/middleware"
|
||||
"github.com/Damillora/Shioriko/pkg/models"
|
||||
"github.com/Damillora/Shioriko/pkg/services"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func InitializeTagRoutes(g *gin.Engine) {
|
||||
autocomplete := g.Group("/api/tag-autocomplete")
|
||||
{
|
||||
autocomplete.GET("/", tagAutocomplete)
|
||||
}
|
||||
unprotected := g.Group("/api/tag")
|
||||
{
|
||||
unprotected.GET("/", tagGet)
|
||||
unprotected.GET("/autocomplete", tagAutocomplete)
|
||||
unprotected.GET("/:tag", tagGetOne)
|
||||
}
|
||||
protected := g.Group("/api/tag").Use(middleware.AuthMiddleware())
|
||||
{
|
||||
protected.PUT("/:tag/note", tagUpdateNote)
|
||||
protected.PUT("/:tag", tagUpdate)
|
||||
}
|
||||
}
|
||||
|
||||
@ -20,7 +31,95 @@ func tagGet(c *gin.Context) {
|
||||
c.JSON(http.StatusOK, tags)
|
||||
}
|
||||
|
||||
func tagGetOne(c *gin.Context) {
|
||||
tag := c.Param("tag")
|
||||
tagObj, err := services.GetTag(tag)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, models.ErrorResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
Message: err.Error(),
|
||||
})
|
||||
c.Abort()
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, models.TagReadModel{
|
||||
TagID: tagObj.TagID,
|
||||
TagName: tagObj.TagName,
|
||||
TagType: tagObj.TagType,
|
||||
TagNote: tagObj.TagNote,
|
||||
PostCount: tagObj.PostCount,
|
||||
})
|
||||
}
|
||||
|
||||
func tagAutocomplete(c *gin.Context) {
|
||||
tags := services.GetTagAutocomplete()
|
||||
c.JSON(http.StatusOK, tags)
|
||||
}
|
||||
|
||||
func tagUpdateNote(c *gin.Context) {
|
||||
_, ok := c.Get("user")
|
||||
if !ok {
|
||||
c.JSON(http.StatusForbidden, models.ErrorResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
Message: "User don't exist",
|
||||
})
|
||||
c.Abort()
|
||||
}
|
||||
|
||||
var model models.TagNoteUpdateModel
|
||||
err := c.ShouldBindJSON(&model)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, models.ErrorResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
Message: err.Error(),
|
||||
})
|
||||
c.Abort()
|
||||
return
|
||||
}
|
||||
|
||||
tag := c.Param("tag")
|
||||
err = services.UpdateTagNotes(tag, model.Note)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, models.ErrorResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
Message: err.Error(),
|
||||
})
|
||||
c.Abort()
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, nil)
|
||||
}
|
||||
|
||||
func tagUpdate(c *gin.Context) {
|
||||
_, ok := c.Get("user")
|
||||
if !ok {
|
||||
c.JSON(http.StatusForbidden, models.ErrorResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
Message: "User don't exist",
|
||||
})
|
||||
c.Abort()
|
||||
}
|
||||
|
||||
var model models.TagUpdateModel
|
||||
err := c.ShouldBindJSON(&model)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, models.ErrorResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
Message: err.Error(),
|
||||
})
|
||||
c.Abort()
|
||||
return
|
||||
}
|
||||
|
||||
tag := c.Param("tag")
|
||||
err = services.UpdateTag(tag, model)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, models.ErrorResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
Message: err.Error(),
|
||||
})
|
||||
c.Abort()
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, nil)
|
||||
}
|
||||
|
@ -12,10 +12,12 @@ import (
|
||||
)
|
||||
|
||||
func InitializeTagTypeRoutes(g *gin.Engine) {
|
||||
|
||||
unprotected := g.Group(("/api/tagtype"))
|
||||
{
|
||||
unprotected.GET("/", tagTypeGet)
|
||||
}
|
||||
protected := g.Group("/api/tagtype").Use(middleware.AuthMiddleware())
|
||||
{
|
||||
protected.GET("/", tagTypeGet)
|
||||
protected.POST("/create", tagTypeCreate)
|
||||
protected.DELETE("/:id", tagTypeDelete)
|
||||
}
|
||||
|
@ -11,5 +11,6 @@ type Tag struct {
|
||||
UpdatedAt time.Time
|
||||
TagTypeID uint
|
||||
TagType TagType
|
||||
Note string `gorm:"type:text"`
|
||||
Posts []Post `gorm:"many2many:post_tags"`
|
||||
}
|
||||
|
@ -7,9 +7,10 @@ type UserCreateModel struct {
|
||||
}
|
||||
|
||||
type UserUpdateModel struct {
|
||||
Email string `json:"email" validate:"required,email"`
|
||||
Username string `json:"username" validate:"required"`
|
||||
Password string `json:"password"`
|
||||
Email string `json:"email" validate:"required,email"`
|
||||
Username string `json:"username" validate:"required"`
|
||||
OldPassword string `json:"oldPassword"`
|
||||
NewPassword string `json:"newPassword"`
|
||||
}
|
||||
|
||||
type TagTypeCreateModel struct {
|
||||
@ -26,6 +27,9 @@ type TagUpdateModel struct {
|
||||
TagTypeID uint `json:"tagTypeId" validate:"required"`
|
||||
}
|
||||
|
||||
type TagNoteUpdateModel struct {
|
||||
Note string `json:"note" validate:"required"`
|
||||
}
|
||||
type PostCreateModel struct {
|
||||
BlobID string `json:"blob_id" validate:"required"`
|
||||
SourceURL string `json:"source_url"`
|
||||
|
@ -10,3 +10,11 @@ type PostReadModel struct {
|
||||
Height int `json:"height"`
|
||||
Uploader string `json:"uploader"`
|
||||
}
|
||||
|
||||
type TagReadModel struct {
|
||||
TagID string `json:"tagId"`
|
||||
TagName string `json:"tagName"`
|
||||
TagType string `json:"tagType"`
|
||||
TagNote string `json:"tagNote"`
|
||||
PostCount int `json:"postCount"`
|
||||
}
|
||||
|
@ -42,6 +42,24 @@ func GetTagFilter(tagObjs []database.Tag) []models.TagListItem {
|
||||
Find(&tags, tagIds)
|
||||
return tags
|
||||
}
|
||||
|
||||
func GetTag(tagString string) (*models.TagReadModel, error) {
|
||||
tagObj, err := FindTag(tagString)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var tagModel models.TagReadModel
|
||||
|
||||
database.DB.Model(&tagObj).
|
||||
Joins("join tag_types on tag_types.id = tags.tag_type_id").
|
||||
Joins("left join post_tags on post_tags.tag_id = tags.id").
|
||||
Select("tags.id as tag_id, tags.name as tag_name, tag_types.name as tag_type, tags.note as tag_note, count(post_tags.post_id) as post_count").
|
||||
Group("tags.id, tags.name, tag_types.name, tags.note").
|
||||
First(&tagModel, "tags.id = ? ", tagObj.ID)
|
||||
|
||||
return &tagModel, nil
|
||||
}
|
||||
|
||||
func GetTagAutocomplete() []string {
|
||||
var tags []string
|
||||
result := database.DB.Model(&database.Tag{}).
|
||||
@ -134,6 +152,7 @@ func CreateOrUpdateTag(tagSyntax string) (*database.Tag, error) {
|
||||
return nil, errors.New("Malformed tag syntax")
|
||||
}
|
||||
}
|
||||
|
||||
func FindTag(tagSyntax string) (*database.Tag, error) {
|
||||
tagFields := strings.Split(tagSyntax, ":")
|
||||
var tagName string
|
||||
@ -173,3 +192,36 @@ func ParseReadTags(tags []string) ([]database.Tag, error) {
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func UpdateTagNotes(tagString string, notes string) error {
|
||||
tagObj, err := FindTag(tagString)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
tagObj.Note = notes
|
||||
|
||||
result := database.DB.Save(&tagObj)
|
||||
if result.Error != nil {
|
||||
return result.Error
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func UpdateTag(tagString string, model models.TagUpdateModel) error {
|
||||
tagObj, err := FindTag(tagString)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
tagObj.TagTypeID = model.TagTypeID
|
||||
tagObj.Name = model.Name
|
||||
|
||||
result := database.DB.Save(&tagObj)
|
||||
if result.Error != nil {
|
||||
return result.Error
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
@ -50,7 +50,12 @@ func UpdateUser(id string, model models.UserUpdateModel) (*database.User, error)
|
||||
user.Username = model.Username
|
||||
|
||||
if user.Password != "" {
|
||||
passwd, err := bcrypt.GenerateFromPassword([]byte(model.Password), bcrypt.DefaultCost)
|
||||
verifyErr := bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(model.OldPassword))
|
||||
if verifyErr != nil {
|
||||
return nil, verifyErr
|
||||
}
|
||||
|
||||
passwd, err := bcrypt.GenerateFromPassword([]byte(model.NewPassword), bcrypt.DefaultCost)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -18,6 +18,9 @@
|
||||
"svelte": "^3.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@svelte-parts/editor": "^0.0.26",
|
||||
"@tiptap/core": "^2.0.0-beta.174",
|
||||
"@tiptap/starter-kit": "^2.0.0-beta.183",
|
||||
"axios": "^0.21.1",
|
||||
"bulma": "^0.9.2",
|
||||
"node-sass": "^6.0.0",
|
||||
|
@ -3,15 +3,21 @@
|
||||
|
||||
import Navbar from "./Navbar.svelte";
|
||||
|
||||
|
||||
import Home from "./routes/Home.svelte";
|
||||
import Posts from "./routes/Posts.svelte";
|
||||
import Post from "./routes/Post.svelte";
|
||||
import Login from "./routes/Login.svelte";
|
||||
import Logout from "./routes/Logout.svelte";
|
||||
import Upload from "./routes/Upload.svelte";
|
||||
import Edit from "./routes/Edit.svelte";
|
||||
import Tags from "./routes/Tags.svelte";
|
||||
import Register from "./routes/Register.svelte";
|
||||
|
||||
import Login from "./routes/Auth/Login.svelte";
|
||||
import Logout from "./routes/Auth/Logout.svelte";
|
||||
import Register from "./routes/Auth/Register.svelte";
|
||||
|
||||
import Posts from "./routes/Post/Posts.svelte";
|
||||
import Post from "./routes/Post/Post.svelte";
|
||||
import Upload from "./routes/Post/Upload.svelte";
|
||||
|
||||
import Tags from "./routes/Tags/Tags.svelte";
|
||||
import Tag from "./routes/Tags/Tag.svelte";
|
||||
|
||||
import Profile from "./routes/User/Profile.svelte";
|
||||
|
||||
export let url = "";
|
||||
let baseURL = window.BASE_URL;
|
||||
@ -23,12 +29,13 @@
|
||||
<Route path="/" component={Home} />
|
||||
<Route path="/posts" component={Posts} />
|
||||
<Route path="/post/:id" component={Post} />
|
||||
<Route path="/post/edit/:id" component={Edit} />
|
||||
<Route path="/auth/login" component={Login} />
|
||||
<Route path="/auth/logout" component={Logout} />
|
||||
<Route path="/upload" component={Upload} />
|
||||
<Route path="/tags" component={Tags} />
|
||||
<Route path="/tags/:tag" component={Tag} />
|
||||
<Route path="/auth/register" component={Register} />
|
||||
<Route path="/user/profile" component={Profile} />
|
||||
</div>
|
||||
</Router>
|
||||
|
||||
|
@ -46,6 +46,9 @@
|
||||
{#if loggedIn}
|
||||
<div class="navbar-item">
|
||||
<div class="buttons">
|
||||
<Link to="/user/profile" class="button is-primary">
|
||||
Profile
|
||||
</Link>
|
||||
<Link to="/auth/logout" class="button is-light">
|
||||
Log out
|
||||
</Link>
|
||||
|
@ -41,8 +41,15 @@ export async function getTags() {
|
||||
const response = await axios.get(endpoint);
|
||||
return response.data;
|
||||
}
|
||||
|
||||
export async function getTag({ tag }) {
|
||||
const endpoint = url + "/api/tag/" + tag;
|
||||
const response = await axios.get(endpoint);
|
||||
return response.data;
|
||||
}
|
||||
|
||||
export async function getTagAutocomplete() {
|
||||
const endpoint = url + "/api/tag/autocomplete";
|
||||
const endpoint = url + "/api/tag-autocomplete";
|
||||
const response = await axios.get(endpoint);
|
||||
return response.data;
|
||||
}
|
||||
@ -123,6 +130,7 @@ export async function postUpdate(id, { source_url, tags }) {
|
||||
})
|
||||
return response.data;
|
||||
}
|
||||
|
||||
export async function postDelete({ id }) {
|
||||
const endpoint = url + "/api/post/" + id;
|
||||
const response = await axios({
|
||||
@ -134,4 +142,57 @@ export async function postDelete({ id }) {
|
||||
withCredentials: true,
|
||||
})
|
||||
return response.status == 200;
|
||||
}
|
||||
|
||||
export async function getUserProfile() {
|
||||
const endpoint = url + "/api/user/profile";
|
||||
const response = await axios({
|
||||
url: endpoint,
|
||||
method: "GET",
|
||||
headers: {
|
||||
'Authorization': 'Bearer ' + current_token,
|
||||
},
|
||||
withCredentials: true,
|
||||
});
|
||||
console.log(response.data);
|
||||
return response.data;
|
||||
}
|
||||
|
||||
export async function updateTagNotes(id, { note }) {
|
||||
const endpoint = url + "/api/tag/" + id + "/note";
|
||||
const response = await axios({
|
||||
url: endpoint,
|
||||
method: "PUT",
|
||||
headers: {
|
||||
'Authorization': 'Bearer ' + current_token,
|
||||
},
|
||||
withCredentials: true,
|
||||
data: {
|
||||
note
|
||||
}
|
||||
})
|
||||
return response.data;
|
||||
}
|
||||
|
||||
export async function updateTag(id, { name, tagTypeId }) {
|
||||
const endpoint = url + "/api/tag/" + id;
|
||||
const response = await axios({
|
||||
url: endpoint,
|
||||
method: "PUT",
|
||||
headers: {
|
||||
'Authorization': 'Bearer ' + current_token,
|
||||
},
|
||||
withCredentials: true,
|
||||
data: {
|
||||
name, tagTypeId
|
||||
}
|
||||
})
|
||||
return response.data;
|
||||
}
|
||||
|
||||
|
||||
export async function getTagTypes() {
|
||||
const endpoint = url + "/api/tagtype";
|
||||
const response = await axios.get(endpoint);
|
||||
return response.data;
|
||||
}
|
94
web/app/src/components/Tag/EditTagPanel.svelte
Normal file
94
web/app/src/components/Tag/EditTagPanel.svelte
Normal file
@ -0,0 +1,94 @@
|
||||
<script>
|
||||
import { onMount } from "svelte";
|
||||
|
||||
import { Link, navigate } from "svelte-routing";
|
||||
import { getTagTypes, updateTag } from "../../api";
|
||||
|
||||
export let tag;
|
||||
export let data;
|
||||
export let toggleRenameMenu;
|
||||
export let onSubmit;
|
||||
|
||||
let tagTypes = [];
|
||||
let form = {
|
||||
name: "",
|
||||
tagTypeId: 1,
|
||||
};
|
||||
|
||||
const getData = async () => {
|
||||
tagTypes = await getTagTypes();
|
||||
form.name = data.tagName;
|
||||
let tagType = tagTypes.filter((x) => x.name == data.tagType);
|
||||
form.tagTypeId = tagType[0].id;
|
||||
};
|
||||
|
||||
const onFormSubmit = async () => {
|
||||
await updateTag(tag, form);
|
||||
|
||||
navigate("/tags/"+form.name);
|
||||
|
||||
toggleRenameMenu();
|
||||
onSubmit(form.name);
|
||||
};
|
||||
|
||||
onMount(() => {
|
||||
getData();
|
||||
});
|
||||
</script>
|
||||
|
||||
<form on:submit|preventDefault={onFormSubmit}>
|
||||
<div class="panel is-warning">
|
||||
<p class="panel-heading">Edit Tag</p>
|
||||
<div class="panel-block column">
|
||||
<div class="row">
|
||||
<strong>Name:</strong>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="field">
|
||||
<div class="control">
|
||||
<input
|
||||
class="input"
|
||||
type="text"
|
||||
bind:value={form.name}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel-block column">
|
||||
<div class="row">
|
||||
<strong>Category:</strong>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="field">
|
||||
<div class="select">
|
||||
<select bind:value={form.tagTypeId}>
|
||||
{#each tagTypes as tagType}
|
||||
<option
|
||||
value={tagType.id}
|
||||
selected={form.tagTypeId === tagType.id}
|
||||
>
|
||||
{tagType.name}
|
||||
</option>
|
||||
{/each}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel-block column">
|
||||
<div class="row">
|
||||
<strong>Posts:</strong>
|
||||
</div>
|
||||
<div class="row">
|
||||
{data.postCount} (<Link to="/posts?tags={tag}">Browse</Link>)
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel-block column">
|
||||
<button class="button is-primary" type="submit">Submit</button>
|
||||
<button on:click|preventDefault={toggleRenameMenu} class="button"
|
||||
>Cancel</button
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
40
web/app/src/components/Tag/ViewTagPanel.svelte
Normal file
40
web/app/src/components/Tag/ViewTagPanel.svelte
Normal file
@ -0,0 +1,40 @@
|
||||
<script>
|
||||
import { Link } from "svelte-routing";
|
||||
import AuthCheck from "../../AuthCheck.svelte";
|
||||
|
||||
export let tag;
|
||||
export let data;
|
||||
export let toggleRenameMenu;
|
||||
</script>
|
||||
|
||||
<div class="panel is-primary">
|
||||
<p class="panel-heading">Tag</p>
|
||||
<div class="panel-block column">
|
||||
<div class="row">
|
||||
<strong>Name:</strong>
|
||||
</div>
|
||||
<div class="row">{data.tagName}</div>
|
||||
</div>
|
||||
<div class="panel-block column">
|
||||
<div class="row">
|
||||
<strong>Category:</strong>
|
||||
</div>
|
||||
<div class="row">{data.tagType}</div>
|
||||
</div>
|
||||
<div class="panel-block column">
|
||||
<div class="row">
|
||||
<strong>Posts:</strong>
|
||||
</div>
|
||||
<div class="row">
|
||||
{data.postCount} (<Link to="/posts?tags={tag}">Browse</Link>)
|
||||
</div>
|
||||
</div>
|
||||
<AuthCheck>
|
||||
<div class="panel-block column">
|
||||
<button
|
||||
on:click|preventDefault={toggleRenameMenu}
|
||||
class="button is-primary">Rename</button
|
||||
>
|
||||
</div>
|
||||
</AuthCheck>
|
||||
</div>
|
47
web/app/src/components/TagNotes/EditTagNotesPanel.svelte
Normal file
47
web/app/src/components/TagNotes/EditTagNotesPanel.svelte
Normal file
@ -0,0 +1,47 @@
|
||||
<script>
|
||||
import { onMount } from "svelte";
|
||||
import { updateTagNotes } from "../../api";
|
||||
|
||||
export let tag;
|
||||
export let data;
|
||||
export let toggleEditMenu;
|
||||
export let onSubmit;
|
||||
|
||||
let form = {
|
||||
note: "",
|
||||
};
|
||||
|
||||
const getData = async () => {
|
||||
form.note = data.tagNote;
|
||||
};
|
||||
|
||||
const onFormSubmit = async () => {
|
||||
await updateTagNotes(tag, form);
|
||||
toggleEditMenu();
|
||||
|
||||
onSubmit();
|
||||
};
|
||||
|
||||
onMount(() => {
|
||||
getData();
|
||||
});
|
||||
</script>
|
||||
|
||||
<form on:submit|preventDefault={onFormSubmit}>
|
||||
<div class="panel is-warning">
|
||||
<p class="panel-heading">Edit Notes</p>
|
||||
<div class="panel-block column">
|
||||
<textarea
|
||||
bind:value={form.note}
|
||||
class="textarea has-fixed-size"
|
||||
/>
|
||||
<div class="content" />
|
||||
</div>
|
||||
<div class="panel-block column">
|
||||
<button type="submit" class="button is-primary">Save</button>
|
||||
<button on:click|preventDefault={toggleEditMenu} class="button"
|
||||
>Cancel</button
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
29
web/app/src/components/TagNotes/ViewTagNotesPanel.svelte
Normal file
29
web/app/src/components/TagNotes/ViewTagNotesPanel.svelte
Normal file
@ -0,0 +1,29 @@
|
||||
<script>
|
||||
import AuthCheck from "../../AuthCheck.svelte";
|
||||
|
||||
export let data;
|
||||
export let toggleEditMenu;
|
||||
</script>
|
||||
|
||||
<div class="panel is-info">
|
||||
<p class="panel-heading">Notes</p>
|
||||
<div class="panel-block column">
|
||||
<div class="content pre-line">
|
||||
{data.tagNote}
|
||||
</div>
|
||||
</div>
|
||||
<AuthCheck>
|
||||
<div class="panel-block column">
|
||||
<button
|
||||
on:click|preventDefault={toggleEditMenu}
|
||||
class="button is-primary">Edit</button
|
||||
>
|
||||
</div>
|
||||
</AuthCheck>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.pre-line {
|
||||
white-space: pre-line;
|
||||
}
|
||||
</style>
|
@ -6,6 +6,7 @@
|
||||
@import '../node_modules/bulma/sass/grid/_all';
|
||||
@import '../node_modules/bulma/sass/helpers/_all';
|
||||
@import '../node_modules/bulma/sass/layout/_all';
|
||||
@import '../node_modules/bytemd/dist/index.css';
|
||||
|
||||
.tile.is-multiline {
|
||||
flex-wrap: wrap;
|
||||
|
@ -1,5 +1,5 @@
|
||||
<script>
|
||||
import { login } from "../api.js";
|
||||
import { login } from "../../api.js";
|
||||
import { navigate } from "svelte-routing";
|
||||
|
||||
let username = "";
|
@ -1,5 +1,5 @@
|
||||
<script>
|
||||
import { token } from "../stores.js";
|
||||
import { token } from "../../stores.js";
|
||||
import { navigate } from "svelte-routing";
|
||||
import { onMount } from "svelte";
|
||||
|
@ -1,5 +1,5 @@
|
||||
<script>
|
||||
import { register } from "../api.js";
|
||||
import { register } from "../../api.js";
|
||||
import { navigate } from "svelte-routing";
|
||||
|
||||
let username = "";
|
@ -1,97 +0,0 @@
|
||||
<script>
|
||||
import { getPost, postUpdate, getTagAutocomplete } from "../api.js";
|
||||
import { navigate } from "svelte-routing";
|
||||
import Tags from "svelte-tags-input";
|
||||
import { onMount } from "svelte";
|
||||
import { Link } from "svelte-routing";
|
||||
import AuthRequired from "../AuthRequired.svelte";
|
||||
|
||||
export let id;
|
||||
|
||||
let image_path = "";
|
||||
|
||||
let form = {
|
||||
source_url: "",
|
||||
tags: [],
|
||||
};
|
||||
|
||||
const getData = async () => {
|
||||
const data = await getPost({ id });
|
||||
form.source_url = data.source_url;
|
||||
form.tags = data.tags;
|
||||
image_path = data.image_path;
|
||||
};
|
||||
|
||||
const onTagChange = (value) => {
|
||||
form.tags = value.detail.tags;
|
||||
};
|
||||
|
||||
const onAutocomplete = async () => {
|
||||
const list = await getTagAutocomplete();
|
||||
return list;
|
||||
};
|
||||
|
||||
const onSubmit = async () => {
|
||||
const response = await postUpdate(id, form);
|
||||
navigate(`/post/${response.id}`);
|
||||
};
|
||||
|
||||
onMount(() => {
|
||||
getData();
|
||||
});
|
||||
</script>
|
||||
|
||||
<AuthRequired />
|
||||
|
||||
<section class="hero is-primary">
|
||||
<div class="hero-body">
|
||||
<p class="title">Edit Post: {id}</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div class="container">
|
||||
<section class="section">
|
||||
<div class="columns">
|
||||
<div class="column is-one-third box">
|
||||
<p>
|
||||
<Link class="button is-primary" to="/post/{id}">Back</Link>
|
||||
</p>
|
||||
<form on:submit|preventDefault={onSubmit}>
|
||||
<div class="field">
|
||||
<label for="source" class="label">Source URL</label>
|
||||
<div class="control">
|
||||
<input
|
||||
id="source"
|
||||
class="input"
|
||||
type="url"
|
||||
placeholder="Source URL"
|
||||
bind:value={form.source_url}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label for="tags" class="label">Tags</label>
|
||||
<div class="control" id="tags">
|
||||
<Tags
|
||||
tags={form.tags}
|
||||
addKeys={[9, 32]}
|
||||
on:tags={onTagChange}
|
||||
autoComplete={onAutocomplete}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="control">
|
||||
<button type="submit" class="button is-primary"
|
||||
>Submit</button
|
||||
>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="column">
|
||||
<figure class="image">
|
||||
<img alt={id} src={image_path} />
|
||||
</figure>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
@ -1,9 +1,9 @@
|
||||
<script>
|
||||
import { onMount } from "svelte";
|
||||
import { getPost, postDelete } from "../api.js";
|
||||
import { getPost, postDelete } from "../../api.js";
|
||||
import { navigate } from "svelte-routing";
|
||||
import EditPostPanel from "../EditPostPanel.svelte";
|
||||
import ViewPostPanel from "../ViewPostPanel.svelte";
|
||||
import EditPostPanel from "../../EditPostPanel.svelte";
|
||||
import ViewPostPanel from "../../ViewPostPanel.svelte";
|
||||
export let id;
|
||||
let post;
|
||||
const getData = async () => {
|
@ -1,12 +1,10 @@
|
||||
<script>
|
||||
import { onMount } from "svelte";
|
||||
import { getPostSearchTag, getTagAutocomplete } from "../api.js";
|
||||
import { getPostSearchTag, getTagAutocomplete } from "../../api.js";
|
||||
import { Link, navigate } from "svelte-routing";
|
||||
import TagLinkNumbered from "../TagLinkNumbered.svelte";
|
||||
import TagLinkNumbered from "../../TagLinkNumbered.svelte";
|
||||
import queryString from "query-string";
|
||||
import Tags from "svelte-tags-input";
|
||||
import { add_attribute } from "svelte/internal";
|
||||
import { paginate } from "../simple-pagination.js";
|
||||
import { paginate } from "../../simple-pagination.js";
|
||||
|
||||
export let location;
|
||||
|
@ -1,8 +1,8 @@
|
||||
<script>
|
||||
import { uploadBlob, postCreate, getTagAutocomplete } from "../api.js";
|
||||
import { uploadBlob, postCreate, getTagAutocomplete } from "../../api.js";
|
||||
import { navigate, Link } from "svelte-routing";
|
||||
import Tags from "svelte-tags-input";
|
||||
import AuthRequired from "../AuthRequired.svelte";
|
||||
import AuthRequired from "../../AuthRequired.svelte";
|
||||
|
||||
let currentProgress = 0;
|
||||
|
70
web/app/src/routes/Tags/Tag.svelte
Normal file
70
web/app/src/routes/Tags/Tag.svelte
Normal file
@ -0,0 +1,70 @@
|
||||
<script>
|
||||
import { onMount } from "svelte";
|
||||
|
||||
import { getTag } from "../../api";
|
||||
import EditTagNotesPanel from "../../components/TagNotes/EditTagNotesPanel.svelte";
|
||||
import ViewTagNotesPanel from "../../components/TagNotes/ViewTagNotesPanel.svelte";
|
||||
import ViewTagPanel from "../../components/Tag/ViewTagPanel.svelte";
|
||||
import EditTagPanel from "../../components/Tag/EditTagPanel.svelte";
|
||||
|
||||
export let tag;
|
||||
let data;
|
||||
|
||||
const getData = async () => {
|
||||
if (tag) {
|
||||
data = await getTag({ tag });
|
||||
}
|
||||
};
|
||||
|
||||
let renameMenuShown = false;
|
||||
const toggleRenameMenu = () => {
|
||||
renameMenuShown = !renameMenuShown;
|
||||
};
|
||||
|
||||
let editMenuShown = false;
|
||||
const toggleEditMenu = () => {
|
||||
editMenuShown = !editMenuShown;
|
||||
};
|
||||
|
||||
const onTagSubmit = (newName) => {
|
||||
tag = newName;
|
||||
getData();
|
||||
};
|
||||
|
||||
onMount(() => {
|
||||
getData();
|
||||
});
|
||||
</script>
|
||||
|
||||
<section class="section">
|
||||
<div class="container">
|
||||
{#if data}
|
||||
<div class="columns">
|
||||
<div class="column is-one-third">
|
||||
{#if renameMenuShown}
|
||||
<EditTagPanel
|
||||
{tag}
|
||||
{data}
|
||||
{toggleRenameMenu}
|
||||
onSubmit={onTagSubmit}
|
||||
/>
|
||||
{:else}
|
||||
<ViewTagPanel {tag} {data} {toggleRenameMenu} />
|
||||
{/if}
|
||||
</div>
|
||||
<div class="column is-two-thirds">
|
||||
{#if editMenuShown}
|
||||
<EditTagNotesPanel
|
||||
{tag}
|
||||
{data}
|
||||
{toggleEditMenu}
|
||||
onSubmit={getData}
|
||||
/>
|
||||
{:else}
|
||||
<ViewTagNotesPanel {data} {toggleEditMenu} />
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</section>
|
@ -1,5 +1,5 @@
|
||||
<script>
|
||||
import { getTags } from "../api";
|
||||
import { getTags } from "../../api";
|
||||
import { Link } from "svelte-routing";
|
||||
|
||||
let tags = [];
|
||||
@ -29,7 +29,7 @@
|
||||
{#each tags as tag}
|
||||
<tr>
|
||||
<td>
|
||||
<Link to="/posts?tags={tag.tagType}:{tag.tagName}">{tag.tagName}</Link>
|
||||
<Link to="/tags/{tag.tagName}">{tag.tagName}</Link>
|
||||
</td>
|
||||
<td>{tag.tagType}</td>
|
||||
<td>{tag.postCount}</td>
|
26
web/app/src/routes/User/Profile.svelte
Normal file
26
web/app/src/routes/User/Profile.svelte
Normal file
@ -0,0 +1,26 @@
|
||||
<script>
|
||||
import { onMount } from "svelte";
|
||||
import { getUserProfile } from "../../api.js";
|
||||
import AuthRequired from "../../AuthRequired.svelte";
|
||||
|
||||
let user;
|
||||
|
||||
const getData = async () => {
|
||||
user = await getUserProfile();
|
||||
};
|
||||
onMount(() => {
|
||||
getData();
|
||||
});
|
||||
</script>
|
||||
|
||||
<AuthRequired />
|
||||
|
||||
<section class="section">
|
||||
<div class="container">
|
||||
{#if user}
|
||||
<h1 class="title">Welcome, {user.username}</h1>
|
||||
<p>Email: {user.email}</p>
|
||||
<p>Username: {user.username}</p>
|
||||
{/if}
|
||||
</div>
|
||||
</section>
|
@ -70,6 +70,161 @@
|
||||
estree-walker "^1.0.1"
|
||||
picomatch "^2.2.2"
|
||||
|
||||
"@svelte-parts/editor@^0.0.26":
|
||||
version "0.0.26"
|
||||
resolved "https://registry.yarnpkg.com/@svelte-parts/editor/-/editor-0.0.26.tgz#321923306dc0c2734839e08e4d54f9e4e89d6ff5"
|
||||
integrity sha512-5VyzZG9RrkawjVAG5QHCqRcFY1Tn5am1W+whRH+EYVjPJTqJho5rYaTE0+f3cIpcNAkfHMd3lFyIWccoW2gBAQ==
|
||||
dependencies:
|
||||
codemirror "^5.58.2"
|
||||
|
||||
"@tiptap/core@^2.0.0-beta.174":
|
||||
version "2.0.0-beta.174"
|
||||
resolved "https://registry.yarnpkg.com/@tiptap/core/-/core-2.0.0-beta.174.tgz#cfdf16b7d7401e4b255dc69147d784f5f537b942"
|
||||
integrity sha512-APQDto40PdvagG1HTwkKlieQS4Vp6GXNe7qgV1Qo2QCgJCLyxc/fXCTghtrOx0CQb+9JT7fjSLZxbSyUFXjx7Q==
|
||||
dependencies:
|
||||
"@types/prosemirror-commands" "^1.0.4"
|
||||
"@types/prosemirror-keymap" "^1.0.4"
|
||||
"@types/prosemirror-model" "^1.16.0"
|
||||
"@types/prosemirror-schema-list" "^1.0.3"
|
||||
"@types/prosemirror-state" "^1.2.8"
|
||||
"@types/prosemirror-transform" "^1.1.5"
|
||||
"@types/prosemirror-view" "^1.23.1"
|
||||
prosemirror-commands "^1.2.1"
|
||||
prosemirror-keymap "^1.1.5"
|
||||
prosemirror-model "^1.16.1"
|
||||
prosemirror-schema-list "^1.1.6"
|
||||
prosemirror-state "^1.3.4"
|
||||
prosemirror-transform "^1.3.3"
|
||||
prosemirror-view "^1.23.6"
|
||||
|
||||
"@tiptap/extension-blockquote@^2.0.0-beta.26":
|
||||
version "2.0.0-beta.26"
|
||||
resolved "https://registry.yarnpkg.com/@tiptap/extension-blockquote/-/extension-blockquote-2.0.0-beta.26.tgz#e5ae4b7bd9376db37407a23e22080c7b11287f3b"
|
||||
integrity sha512-A6yjcYovONJfOjQFk6vDYXswaCdCtCwjL7w9VTB0R2DLTuJvvRt9DWN0IDcMrj5G+aMgDq4GUUTitv+2Y8krDg==
|
||||
|
||||
"@tiptap/extension-bold@^2.0.0-beta.26":
|
||||
version "2.0.0-beta.26"
|
||||
resolved "https://registry.yarnpkg.com/@tiptap/extension-bold/-/extension-bold-2.0.0-beta.26.tgz#aa1c7850df28cec8e0614fde437183bd4ae3e66b"
|
||||
integrity sha512-pnO0I5sEQM3pmowjMGQ74adLzvc6HqGyLyqMizaGMicPu9uTYlSdId+qckYEEgPwPMaEShtv2Vg+ZHs7KVqfcg==
|
||||
|
||||
"@tiptap/extension-bullet-list@^2.0.0-beta.26":
|
||||
version "2.0.0-beta.26"
|
||||
resolved "https://registry.yarnpkg.com/@tiptap/extension-bullet-list/-/extension-bullet-list-2.0.0-beta.26.tgz#b42126d2d984c04041b14037e8d3ec1bcf16e7ec"
|
||||
integrity sha512-1n5HV8gY1tLjPk4x48nva6SZlFHoPlRfF6pqSu9JcJxPO7FUSPxUokuz4swYNe0LRrtykfyNz44dUcxKVhoFow==
|
||||
|
||||
"@tiptap/extension-code-block@^2.0.0-beta.37":
|
||||
version "2.0.0-beta.37"
|
||||
resolved "https://registry.yarnpkg.com/@tiptap/extension-code-block/-/extension-code-block-2.0.0-beta.37.tgz#c07c007248a21d9e0434458fd05c363b7078227f"
|
||||
integrity sha512-mJAM+PHaNoKRYwM3D36lZ51/aoPxxvZNQn3UBnZ6G7l0ZJSgB3JvBEzqK6S8nNFeYIIxGwv4QF6vXe4MG9ie2g==
|
||||
dependencies:
|
||||
prosemirror-state "^1.3.4"
|
||||
|
||||
"@tiptap/extension-code@^2.0.0-beta.26":
|
||||
version "2.0.0-beta.26"
|
||||
resolved "https://registry.yarnpkg.com/@tiptap/extension-code/-/extension-code-2.0.0-beta.26.tgz#bbfa600a252ee2cded6947b56b6c4c33d998e53a"
|
||||
integrity sha512-QcFWdEFfbJ1n5UFFBD17QPPAJ3J5p/b7XV484u0shCzywO7aNPV32QeHy1z0eMoyZtCbOWf6hg/a7Ugv8IwpHw==
|
||||
|
||||
"@tiptap/extension-document@^2.0.0-beta.15":
|
||||
version "2.0.0-beta.15"
|
||||
resolved "https://registry.yarnpkg.com/@tiptap/extension-document/-/extension-document-2.0.0-beta.15.tgz#5d17a0289244a913ab2ef08e8495a1e46950711e"
|
||||
integrity sha512-ypENC+xUYD5m2t+KOKNYqyXnanXd5fxyIyhR1qeEEwwQwMXGNrO3kCH6O4mIDCpy+/WqHvVay2tV5dVsXnvY8w==
|
||||
|
||||
"@tiptap/extension-dropcursor@^2.0.0-beta.25":
|
||||
version "2.0.0-beta.25"
|
||||
resolved "https://registry.yarnpkg.com/@tiptap/extension-dropcursor/-/extension-dropcursor-2.0.0-beta.25.tgz#962f290a200259533a26194daca5a4b4a53e72d3"
|
||||
integrity sha512-GYf5s6dkZtsDy+TEkrQK6kLbfbitG4qnk02D+FlhlJMI/Nnx8rYCRJbwEHDdqrfX7XwZzULMqqqHvzxZYrEeNg==
|
||||
dependencies:
|
||||
"@types/prosemirror-dropcursor" "^1.0.3"
|
||||
prosemirror-dropcursor "^1.4.0"
|
||||
|
||||
"@tiptap/extension-gapcursor@^2.0.0-beta.34":
|
||||
version "2.0.0-beta.34"
|
||||
resolved "https://registry.yarnpkg.com/@tiptap/extension-gapcursor/-/extension-gapcursor-2.0.0-beta.34.tgz#0e4971affb1621934422dd5fc4bf2dd7a84f70f7"
|
||||
integrity sha512-Vm8vMWWQ2kJcUOLfB5CEo5pYgyudI7JeeiZvX9ScPmUmgKVYhEpt3EAICY9pUYJ41aAVH35gZLXkUtsz2f9GHw==
|
||||
dependencies:
|
||||
"@types/prosemirror-gapcursor" "^1.0.4"
|
||||
prosemirror-gapcursor "^1.2.1"
|
||||
|
||||
"@tiptap/extension-hard-break@^2.0.0-beta.30":
|
||||
version "2.0.0-beta.30"
|
||||
resolved "https://registry.yarnpkg.com/@tiptap/extension-hard-break/-/extension-hard-break-2.0.0-beta.30.tgz#165494f1194a7bad08907e6d64d349dd15851b72"
|
||||
integrity sha512-X9xj/S+CikrbIE7ccUFVwit5QHEbflnKVxod+4zPwr1cxogFbE9AyLZE2MpYdx3z9LcnTYYi9leBqFrP4T/Olw==
|
||||
|
||||
"@tiptap/extension-heading@^2.0.0-beta.26":
|
||||
version "2.0.0-beta.26"
|
||||
resolved "https://registry.yarnpkg.com/@tiptap/extension-heading/-/extension-heading-2.0.0-beta.26.tgz#112b14b4d488772bda36abbf7cb2bc8aba7c42f5"
|
||||
integrity sha512-nR6W/3rjnZH1Swo7tGBoYsmO6xMvu9MGq6jlm3WVHCB7B3CsrRvCkTwGjVIbKTaZC4bQfx5gvAUpQFvwuU+M5w==
|
||||
|
||||
"@tiptap/extension-history@^2.0.0-beta.21":
|
||||
version "2.0.0-beta.21"
|
||||
resolved "https://registry.yarnpkg.com/@tiptap/extension-history/-/extension-history-2.0.0-beta.21.tgz#5d96a17a83a7130744f0757a3275dd5b11eb1bf7"
|
||||
integrity sha512-0v8Cl30V4dsabdpspLdk+f+lMoIvLFlJN5WRxtc7RRZ5gfJVxPHwooIKdvC51brfh/oJtWFCNMRjhoz0fRaF9A==
|
||||
dependencies:
|
||||
"@types/prosemirror-history" "^1.0.3"
|
||||
prosemirror-history "^1.2.0"
|
||||
|
||||
"@tiptap/extension-horizontal-rule@^2.0.0-beta.31":
|
||||
version "2.0.0-beta.31"
|
||||
resolved "https://registry.yarnpkg.com/@tiptap/extension-horizontal-rule/-/extension-horizontal-rule-2.0.0-beta.31.tgz#efb383a6cedbbf4f2175d7d207eaeeba626faab0"
|
||||
integrity sha512-MNc4retfjRgkv3qxqGya0+/BEd1Kmn+oMsCRvE+8x3sXyKIse+vdqMuG5qUcA6np0ZD/9hh1riiQ1GQdgc23Ng==
|
||||
dependencies:
|
||||
prosemirror-state "^1.3.4"
|
||||
|
||||
"@tiptap/extension-italic@^2.0.0-beta.26":
|
||||
version "2.0.0-beta.26"
|
||||
resolved "https://registry.yarnpkg.com/@tiptap/extension-italic/-/extension-italic-2.0.0-beta.26.tgz#b00c9e32b81b1bd94eaed24bb2a22e44d5dc54a3"
|
||||
integrity sha512-vejGe2ra4K5ipFOn1U9viqF9X9nPTX8WSJpSOux+9UbKjHpANy7bz69tp66OIi/Wh5L/MMDc+luH/04qfVnpZw==
|
||||
|
||||
"@tiptap/extension-list-item@^2.0.0-beta.20":
|
||||
version "2.0.0-beta.20"
|
||||
resolved "https://registry.yarnpkg.com/@tiptap/extension-list-item/-/extension-list-item-2.0.0-beta.20.tgz#7169528b226dee4590e013bdf6e5fc6d83729b0f"
|
||||
integrity sha512-5IPEspJt38t9ROj4xLUesOVEYlTT/R9Skd9meHRxJQZX1qrzBICs5PC/WRIsnexrvTBhdxpYgCYjpvpsJBlKuQ==
|
||||
|
||||
"@tiptap/extension-ordered-list@^2.0.0-beta.27":
|
||||
version "2.0.0-beta.27"
|
||||
resolved "https://registry.yarnpkg.com/@tiptap/extension-ordered-list/-/extension-ordered-list-2.0.0-beta.27.tgz#ed48a53a9b012d578613b68375db31e8664bfdc9"
|
||||
integrity sha512-apFDeignxdZb3cA3p1HJu0zw1JgJdBYUBz1r7f99qdNybYuk3I/1MPUvlOuOgvIrBB/wydoyVDP+v9F7QN3tfQ==
|
||||
|
||||
"@tiptap/extension-paragraph@^2.0.0-beta.23":
|
||||
version "2.0.0-beta.23"
|
||||
resolved "https://registry.yarnpkg.com/@tiptap/extension-paragraph/-/extension-paragraph-2.0.0-beta.23.tgz#2ab77308519494994d7a9e5a4acd14042f45f28c"
|
||||
integrity sha512-VWAxyzecErYWk97Kv/Gkghh97zAQTcaVOisEnYYArZAlyYDaYM48qVssAC/vnRRynP2eQxb1EkppbAxE+bMHAA==
|
||||
|
||||
"@tiptap/extension-strike@^2.0.0-beta.27":
|
||||
version "2.0.0-beta.27"
|
||||
resolved "https://registry.yarnpkg.com/@tiptap/extension-strike/-/extension-strike-2.0.0-beta.27.tgz#c5187bf3c28837f95a5c0c0617d0dd31c318353d"
|
||||
integrity sha512-2dmCgtesuDdivM/54Q+Y6Tc3JbGz1SkHP6c62piuqBiYLWg3xa16zChZOhfN8szbbQlBgLT6XRTDt3c2Ux+Dug==
|
||||
|
||||
"@tiptap/extension-text@^2.0.0-beta.15":
|
||||
version "2.0.0-beta.15"
|
||||
resolved "https://registry.yarnpkg.com/@tiptap/extension-text/-/extension-text-2.0.0-beta.15.tgz#f08cff1b78f1c6996464dfba1fef8ec1e107617f"
|
||||
integrity sha512-S3j2+HyV2gsXZP8Wg/HA+YVXQsZ3nrXgBM9HmGAxB0ESOO50l7LWfip0f3qcw1oRlh5H3iLPkA6/f7clD2/TFA==
|
||||
|
||||
"@tiptap/starter-kit@^2.0.0-beta.183":
|
||||
version "2.0.0-beta.183"
|
||||
resolved "https://registry.yarnpkg.com/@tiptap/starter-kit/-/starter-kit-2.0.0-beta.183.tgz#35ff9f4b236bd321ffdd44c5061514959c1b4b9d"
|
||||
integrity sha512-Lcms6lEfFfdL1oHoATcNKfu1C8+yhuZnI5Pq+U6o2zSslfnUSDf3jgmy6nSoZrrkqvFoXjQk4dxMDFg3giw2Kg==
|
||||
dependencies:
|
||||
"@tiptap/core" "^2.0.0-beta.174"
|
||||
"@tiptap/extension-blockquote" "^2.0.0-beta.26"
|
||||
"@tiptap/extension-bold" "^2.0.0-beta.26"
|
||||
"@tiptap/extension-bullet-list" "^2.0.0-beta.26"
|
||||
"@tiptap/extension-code" "^2.0.0-beta.26"
|
||||
"@tiptap/extension-code-block" "^2.0.0-beta.37"
|
||||
"@tiptap/extension-document" "^2.0.0-beta.15"
|
||||
"@tiptap/extension-dropcursor" "^2.0.0-beta.25"
|
||||
"@tiptap/extension-gapcursor" "^2.0.0-beta.34"
|
||||
"@tiptap/extension-hard-break" "^2.0.0-beta.30"
|
||||
"@tiptap/extension-heading" "^2.0.0-beta.26"
|
||||
"@tiptap/extension-history" "^2.0.0-beta.21"
|
||||
"@tiptap/extension-horizontal-rule" "^2.0.0-beta.31"
|
||||
"@tiptap/extension-italic" "^2.0.0-beta.26"
|
||||
"@tiptap/extension-list-item" "^2.0.0-beta.20"
|
||||
"@tiptap/extension-ordered-list" "^2.0.0-beta.27"
|
||||
"@tiptap/extension-paragraph" "^2.0.0-beta.23"
|
||||
"@tiptap/extension-strike" "^2.0.0-beta.27"
|
||||
"@tiptap/extension-text" "^2.0.0-beta.15"
|
||||
|
||||
"@types/estree@*":
|
||||
version "0.0.47"
|
||||
resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.47.tgz#d7a51db20f0650efec24cd04994f523d93172ed4"
|
||||
@ -85,6 +240,94 @@
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-15.0.2.tgz#51e9c0920d1b45936ea04341aa3e2e58d339fb67"
|
||||
integrity sha512-p68+a+KoxpoB47015IeYZYRrdqMUcpbK8re/zpFB8Ld46LHC1lPEbp3EXgkEhAYEcPvjJF6ZO+869SQ0aH1dcA==
|
||||
|
||||
"@types/orderedmap@*":
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/orderedmap/-/orderedmap-1.0.0.tgz#807455a192bba52cbbb4517044bc82bdbfa8c596"
|
||||
integrity sha512-dxKo80TqYx3YtBipHwA/SdFmMMyLCnP+5mkEqN0eMjcTBzHkiiX0ES118DsjDBjvD+zeSsSU9jULTZ+frog+Gw==
|
||||
|
||||
"@types/prosemirror-commands@*", "@types/prosemirror-commands@^1.0.4":
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/@types/prosemirror-commands/-/prosemirror-commands-1.0.4.tgz#d08551415127d93ae62e7239d30db0b5e7208e22"
|
||||
integrity sha512-utDNYB3EXLjAfYIcRWJe6pn3kcQ5kG4RijbT/0Y/TFOm6yhvYS/D9eJVnijdg9LDjykapcezchxGRqFD5LcyaQ==
|
||||
dependencies:
|
||||
"@types/prosemirror-model" "*"
|
||||
"@types/prosemirror-state" "*"
|
||||
"@types/prosemirror-view" "*"
|
||||
|
||||
"@types/prosemirror-dropcursor@^1.0.3":
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/@types/prosemirror-dropcursor/-/prosemirror-dropcursor-1.0.3.tgz#49250849b8a0b86e8c29eb1ba70a463e53e46947"
|
||||
integrity sha512-b0/8njnJ4lwyHKcGuCMf3x7r1KjxyugB1R/c2iMCjplsJHSC7UY9+OysqgJR5uUXRekUSGniiLgBtac/lvH6wg==
|
||||
dependencies:
|
||||
"@types/prosemirror-state" "*"
|
||||
|
||||
"@types/prosemirror-gapcursor@^1.0.4":
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/@types/prosemirror-gapcursor/-/prosemirror-gapcursor-1.0.4.tgz#7df7d373edb33ea8da12084bfd462cf84cd69761"
|
||||
integrity sha512-9xKjFIG5947dzerFvkLWp6F53JwrUYoYwh3SgcTFEp8SbSfNNrez/PFYVZKPnoqPoaK5WtTdQTaMwpCV9rXQIg==
|
||||
dependencies:
|
||||
"@types/prosemirror-model" "*"
|
||||
"@types/prosemirror-state" "*"
|
||||
|
||||
"@types/prosemirror-history@^1.0.3":
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/@types/prosemirror-history/-/prosemirror-history-1.0.3.tgz#f1110efbe758129b5475e466ff077f0a8d9b964f"
|
||||
integrity sha512-5TloMDRavgLjOAKXp1Li8u0xcsspzbT1Cm9F2pwHOkgvQOz1jWQb2VIXO7RVNsFjLBZdIXlyfSLivro3DuMWXg==
|
||||
dependencies:
|
||||
"@types/prosemirror-model" "*"
|
||||
"@types/prosemirror-state" "*"
|
||||
|
||||
"@types/prosemirror-keymap@^1.0.4":
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/@types/prosemirror-keymap/-/prosemirror-keymap-1.0.4.tgz#f73c79810e8d0e0a20d153d84f998f02e5afbc0c"
|
||||
integrity sha512-ycevwkqUh+jEQtPwqO7sWGcm+Sybmhu8MpBsM8DlO3+YTKnXbKA6SDz/+q14q1wK3UA8lHJyfR+v+GPxfUSemg==
|
||||
dependencies:
|
||||
"@types/prosemirror-commands" "*"
|
||||
"@types/prosemirror-model" "*"
|
||||
"@types/prosemirror-state" "*"
|
||||
"@types/prosemirror-view" "*"
|
||||
|
||||
"@types/prosemirror-model@*", "@types/prosemirror-model@^1.16.0":
|
||||
version "1.16.1"
|
||||
resolved "https://registry.yarnpkg.com/@types/prosemirror-model/-/prosemirror-model-1.16.1.tgz#0ce6c80cd81b398b8a11b1bf7cf695bff3160c9a"
|
||||
integrity sha512-SrrCe2cHlYrQ9o55e2i/c3wt1yRajTTpRLvzfmB+2DWjWEbBLTByVWyjrdpKtQTxAaTeU2aeDGo1iuwl/jF27w==
|
||||
dependencies:
|
||||
"@types/orderedmap" "*"
|
||||
|
||||
"@types/prosemirror-schema-list@^1.0.3":
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/@types/prosemirror-schema-list/-/prosemirror-schema-list-1.0.3.tgz#bdf1893a7915fbdc5c49b3cac9368e96213d70de"
|
||||
integrity sha512-uWybOf+M2Ea7rlbs0yLsS4YJYNGXYtn4N+w8HCw3Vvfl6wBAROzlMt0gV/D/VW/7J/LlAjwMezuGe8xi24HzXA==
|
||||
dependencies:
|
||||
"@types/orderedmap" "*"
|
||||
"@types/prosemirror-model" "*"
|
||||
"@types/prosemirror-state" "*"
|
||||
|
||||
"@types/prosemirror-state@*", "@types/prosemirror-state@^1.2.8":
|
||||
version "1.2.8"
|
||||
resolved "https://registry.yarnpkg.com/@types/prosemirror-state/-/prosemirror-state-1.2.8.tgz#65080eeec52f63c50bf7034377f07773b4f6b2ac"
|
||||
integrity sha512-mq9uyQWcpu8jeamO6Callrdvf/e1H/aRLR2kZWSpZrPHctEsxWHBbluD/wqVjXBRIOoMHLf6ZvOkrkmGLoCHVA==
|
||||
dependencies:
|
||||
"@types/prosemirror-model" "*"
|
||||
"@types/prosemirror-transform" "*"
|
||||
"@types/prosemirror-view" "*"
|
||||
|
||||
"@types/prosemirror-transform@*", "@types/prosemirror-transform@^1.1.5":
|
||||
version "1.1.6"
|
||||
resolved "https://registry.yarnpkg.com/@types/prosemirror-transform/-/prosemirror-transform-1.1.6.tgz#4a06979f656331c46c2725039a57360cc35853af"
|
||||
integrity sha512-7HwXOWc5vZQqIfEUUVAz13lPgBqAWJTv89qEpzAtBFB6hOszFmhsvQ02Jqe2LvKauAoJDa3Qpv/dbJAmgyiTuQ==
|
||||
dependencies:
|
||||
"@types/prosemirror-model" "*"
|
||||
|
||||
"@types/prosemirror-view@*", "@types/prosemirror-view@^1.23.1":
|
||||
version "1.23.1"
|
||||
resolved "https://registry.yarnpkg.com/@types/prosemirror-view/-/prosemirror-view-1.23.1.tgz#a9a926bb6b6e6873e3a9d8caa61c32f3402629eb"
|
||||
integrity sha512-6e1B2oKUnhmZPUrsVvYjDqeVjE6jGezygjtoHsAK4ZENAxHzHqy5NT4jUvdPTWjCYeH0t2Y7pSfRPNrPIyQX4A==
|
||||
dependencies:
|
||||
"@types/prosemirror-model" "*"
|
||||
"@types/prosemirror-state" "*"
|
||||
"@types/prosemirror-transform" "*"
|
||||
|
||||
"@types/pug@^2.0.4":
|
||||
version "2.0.4"
|
||||
resolved "https://registry.yarnpkg.com/@types/pug/-/pug-2.0.4.tgz#8772fcd0418e3cd2cc171555d73007415051f4b2"
|
||||
@ -345,6 +588,11 @@ code-point-at@^1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77"
|
||||
integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=
|
||||
|
||||
codemirror@^5.58.2:
|
||||
version "5.65.2"
|
||||
resolved "https://registry.yarnpkg.com/codemirror/-/codemirror-5.65.2.tgz#5799a70cb3d706e10f60e267245e3a75205d3dd9"
|
||||
integrity sha512-SZM4Zq7XEC8Fhroqe3LxbEEX1zUPWH1wMr5zxiBuiUF64iYOUH/JI88v4tBag8MiBS8B8gRv8O1pPXGYXQ4ErA==
|
||||
|
||||
color-convert@^1.9.0:
|
||||
version "1.9.3"
|
||||
resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8"
|
||||
@ -1171,6 +1419,11 @@ once@^1.3.0:
|
||||
resolved "https://registry.yarnpkg.com/opts/-/opts-2.0.2.tgz#a17e189fbbfee171da559edd8a42423bc5993ce1"
|
||||
integrity sha512-k41FwbcLnlgnFh69f4qdUfvDQ+5vaSDnVPFI/y5XuhKRq97EnVVneO9F1ESVCdiVu4fCS2L8usX3mU331hB7pg==
|
||||
|
||||
orderedmap@^1.1.0:
|
||||
version "1.1.5"
|
||||
resolved "https://registry.yarnpkg.com/orderedmap/-/orderedmap-1.1.5.tgz#4174c90b61bd7c25294932edf789f3b5677744d0"
|
||||
integrity sha512-/fzlCGKRmfayGoI9UUXvJfc2nMZlJHW30QqEvwPvlg8tsX7jyiUSomYie6mYqx7Z9bOMGoag0H/q1PS/0PjYkg==
|
||||
|
||||
p-limit@^2.0.0:
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1"
|
||||
@ -1282,6 +1535,90 @@ process-nextick-args@~2.0.0:
|
||||
resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2"
|
||||
integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==
|
||||
|
||||
prosemirror-commands@^1.2.1:
|
||||
version "1.2.2"
|
||||
resolved "https://registry.yarnpkg.com/prosemirror-commands/-/prosemirror-commands-1.2.2.tgz#1bd167372ee20abf488aca9cece63c43fab182c9"
|
||||
integrity sha512-TX+KpWudMon06frryfpO/u7hsQv2hu8L4VSVbCpi3/7wXHBgl+35mV85qfa3RpT8xD2f3MdeoTqH0vy5JdbXPg==
|
||||
dependencies:
|
||||
prosemirror-model "^1.0.0"
|
||||
prosemirror-state "^1.0.0"
|
||||
prosemirror-transform "^1.0.0"
|
||||
|
||||
prosemirror-dropcursor@^1.4.0:
|
||||
version "1.4.0"
|
||||
resolved "https://registry.yarnpkg.com/prosemirror-dropcursor/-/prosemirror-dropcursor-1.4.0.tgz#91a859d4ee79c99b1c0ba6ee61c093b195c0d9f0"
|
||||
integrity sha512-6+YwTjmqDwlA/Dm+5wK67ezgqgjA/MhSDgaNxKUzH97SmeuWFXyLeDRxxOPZeSo7yTxcDGUCWTEjmQZsVBuMrQ==
|
||||
dependencies:
|
||||
prosemirror-state "^1.0.0"
|
||||
prosemirror-transform "^1.1.0"
|
||||
prosemirror-view "^1.1.0"
|
||||
|
||||
prosemirror-gapcursor@^1.2.1:
|
||||
version "1.2.2"
|
||||
resolved "https://registry.yarnpkg.com/prosemirror-gapcursor/-/prosemirror-gapcursor-1.2.2.tgz#7394613ba4a1601fad1f36f1cff8961968c22ffa"
|
||||
integrity sha512-7YzuRBbu9W7HGQde84kCHfIjaRLNcAdeijbgqrm/R9dsdTWkV+rrdcmic/sCc+bptiNpvjCEE+R6hrbT8zFQeQ==
|
||||
dependencies:
|
||||
prosemirror-keymap "^1.0.0"
|
||||
prosemirror-model "^1.0.0"
|
||||
prosemirror-state "^1.0.0"
|
||||
prosemirror-view "^1.0.0"
|
||||
|
||||
prosemirror-history@^1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/prosemirror-history/-/prosemirror-history-1.2.0.tgz#04cc4df8d2f7b2a46651a2780de191ada6d465ea"
|
||||
integrity sha512-B9v9xtf4fYbKxQwIr+3wtTDNLDZcmMMmGiI3TAPShnUzvo+Rmv1GiUrsQChY1meetHl7rhML2cppF3FTs7f7UQ==
|
||||
dependencies:
|
||||
prosemirror-state "^1.2.2"
|
||||
prosemirror-transform "^1.0.0"
|
||||
rope-sequence "^1.3.0"
|
||||
|
||||
prosemirror-keymap@^1.0.0, prosemirror-keymap@^1.1.5:
|
||||
version "1.1.5"
|
||||
resolved "https://registry.yarnpkg.com/prosemirror-keymap/-/prosemirror-keymap-1.1.5.tgz#b5984c7d30f5c75956c853126c54e9e624c0327b"
|
||||
integrity sha512-8SZgPH3K+GLsHL2wKuwBD9rxhsbnVBTwpHCO4VUO5GmqUQlxd/2GtBVWTsyLq4Dp3N9nGgPd3+lZFKUDuVp+Vw==
|
||||
dependencies:
|
||||
prosemirror-state "^1.0.0"
|
||||
w3c-keyname "^2.2.0"
|
||||
|
||||
prosemirror-model@^1.0.0, prosemirror-model@^1.16.0, prosemirror-model@^1.16.1:
|
||||
version "1.16.1"
|
||||
resolved "https://registry.yarnpkg.com/prosemirror-model/-/prosemirror-model-1.16.1.tgz#fb388270bc9609b66298d6a7e15d0cc1d6c61253"
|
||||
integrity sha512-r1/w0HDU40TtkXp0DyKBnFPYwd8FSlUSJmGCGFv4DeynfeSlyQF2FD0RQbVEMOe6P3PpUSXM6LZBV7W/YNZ4mA==
|
||||
dependencies:
|
||||
orderedmap "^1.1.0"
|
||||
|
||||
prosemirror-schema-list@^1.1.6:
|
||||
version "1.1.6"
|
||||
resolved "https://registry.yarnpkg.com/prosemirror-schema-list/-/prosemirror-schema-list-1.1.6.tgz#c3e13fe2f74750e4a53ff88d798dc0c4ccca6707"
|
||||
integrity sha512-aFGEdaCWmJzouZ8DwedmvSsL50JpRkqhQ6tcpThwJONVVmCgI36LJHtoQ4VGZbusMavaBhXXr33zyD2IVsTlkw==
|
||||
dependencies:
|
||||
prosemirror-model "^1.0.0"
|
||||
prosemirror-transform "^1.0.0"
|
||||
|
||||
prosemirror-state@^1.0.0, prosemirror-state@^1.2.2, prosemirror-state@^1.3.4:
|
||||
version "1.3.4"
|
||||
resolved "https://registry.yarnpkg.com/prosemirror-state/-/prosemirror-state-1.3.4.tgz#4c6b52628216e753fc901c6d2bfd84ce109e8952"
|
||||
integrity sha512-Xkkrpd1y/TQ6HKzN3agsQIGRcLckUMA9u3j207L04mt8ToRgpGeyhbVv0HI7omDORIBHjR29b7AwlATFFf2GLA==
|
||||
dependencies:
|
||||
prosemirror-model "^1.0.0"
|
||||
prosemirror-transform "^1.0.0"
|
||||
|
||||
prosemirror-transform@^1.0.0, prosemirror-transform@^1.1.0, prosemirror-transform@^1.3.3:
|
||||
version "1.4.2"
|
||||
resolved "https://registry.yarnpkg.com/prosemirror-transform/-/prosemirror-transform-1.4.2.tgz#35f56091bcab3359f1eb90e82ce9f20cc52105c1"
|
||||
integrity sha512-bcIsf3uRZhfab0xRfyyxOEh6eqSszq/hJbDbmUumFnbHBoWhB/uXbpz6vvUxfk0XiEvrZDJ+5pXRrNDc1Hu3vQ==
|
||||
dependencies:
|
||||
prosemirror-model "^1.0.0"
|
||||
|
||||
prosemirror-view@^1.0.0, prosemirror-view@^1.1.0, prosemirror-view@^1.23.6:
|
||||
version "1.23.12"
|
||||
resolved "https://registry.yarnpkg.com/prosemirror-view/-/prosemirror-view-1.23.12.tgz#196436a964abbd25a7d8efad879575e80d286ba6"
|
||||
integrity sha512-uvw9ZVz5dNDD9w1bzHkU2r4NWFlpFz85v9rCD8NAhQBau6LYhwM/crjry+C4JgeR8gy6pMXS5eJ1zhNLcK4ctQ==
|
||||
dependencies:
|
||||
prosemirror-model "^1.16.0"
|
||||
prosemirror-state "^1.0.0"
|
||||
prosemirror-transform "^1.1.0"
|
||||
|
||||
psl@^1.1.28:
|
||||
version "1.8.0"
|
||||
resolved "https://registry.yarnpkg.com/psl/-/psl-1.8.0.tgz#9326f8bcfb013adcc005fdff056acce020e51c24"
|
||||
@ -1468,6 +1805,11 @@ rollup@^2.3.4:
|
||||
optionalDependencies:
|
||||
fsevents "~2.3.1"
|
||||
|
||||
rope-sequence@^1.3.0:
|
||||
version "1.3.2"
|
||||
resolved "https://registry.yarnpkg.com/rope-sequence/-/rope-sequence-1.3.2.tgz#a19e02d72991ca71feb6b5f8a91154e48e3c098b"
|
||||
integrity sha512-ku6MFrwEVSVmXLvy3dYph3LAMNS0890K7fabn+0YIRQ2T96T9F4gkFf0vf0WW0JUraNWwGRtInEpH7yO4tbQZg==
|
||||
|
||||
sade@^1.6.0:
|
||||
version "1.7.4"
|
||||
resolved "https://registry.yarnpkg.com/sade/-/sade-1.7.4.tgz#ea681e0c65d248d2095c90578c03ca0bb1b54691"
|
||||
@ -1910,6 +2252,11 @@ verror@1.10.0:
|
||||
core-util-is "1.0.2"
|
||||
extsprintf "^1.2.0"
|
||||
|
||||
w3c-keyname@^2.2.0:
|
||||
version "2.2.4"
|
||||
resolved "https://registry.yarnpkg.com/w3c-keyname/-/w3c-keyname-2.2.4.tgz#4ade6916f6290224cdbd1db8ac49eab03d0eef6b"
|
||||
integrity sha512-tOhfEwEzFLJzf6d1ZPkYfGj+FWhIpBux9ppoP3rlclw3Z0BZv3N7b7030Z1kYth+6rDuAsXUFr+d0VE6Ed1ikw==
|
||||
|
||||
which-module@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a"
|
||||
|
Loading…
Reference in New Issue
Block a user