mirror of
https://github.com/thiloho/archtika.git
synced 2025-11-22 10:51:36 +01:00
Add disable attribute for no permission buttons and shorten query param names
This commit is contained in:
@@ -1,6 +1,8 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { deserialize, applyAction } from "$app/forms";
|
import { deserialize, applyAction } from "$app/forms";
|
||||||
import { textareaScrollTop, previewContent } from "$lib/runes.svelte";
|
import { textareaScrollTop, previewContent } from "$lib/runes.svelte";
|
||||||
|
import LoadingSpinner from "$lib/components/LoadingSpinner.svelte";
|
||||||
|
import { LOADING_DELAY } from "$lib/utils";
|
||||||
|
|
||||||
const {
|
const {
|
||||||
apiPrefix,
|
apiPrefix,
|
||||||
@@ -10,6 +12,8 @@
|
|||||||
}: { apiPrefix: string; label: string; name: string; content: string } = $props();
|
}: { apiPrefix: string; label: string; name: string; content: string } = $props();
|
||||||
|
|
||||||
let mainContentTextarea: HTMLTextAreaElement;
|
let mainContentTextarea: HTMLTextAreaElement;
|
||||||
|
let loadingDelay: number;
|
||||||
|
let pasting = $state(false);
|
||||||
|
|
||||||
const updateScrollPercentage = () => {
|
const updateScrollPercentage = () => {
|
||||||
const { scrollTop, scrollHeight, clientHeight } = mainContentTextarea;
|
const { scrollTop, scrollHeight, clientHeight } = mainContentTextarea;
|
||||||
@@ -28,6 +32,8 @@
|
|||||||
|
|
||||||
if (!fileObject) return;
|
if (!fileObject) return;
|
||||||
|
|
||||||
|
loadingDelay = window.setTimeout(() => (pasting = true), LOADING_DELAY);
|
||||||
|
|
||||||
const formData = new FormData();
|
const formData = new FormData();
|
||||||
formData.append("file", fileObject);
|
formData.append("file", fileObject);
|
||||||
|
|
||||||
@@ -48,20 +54,29 @@
|
|||||||
const target = event.target as HTMLTextAreaElement;
|
const target = event.target as HTMLTextAreaElement;
|
||||||
const markdownToInsert = ``;
|
const markdownToInsert = ``;
|
||||||
const cursorPosition = target.selectionStart;
|
const cursorPosition = target.selectionStart;
|
||||||
const newContent = target.value.slice(0, target.selectionStart) + markdownToInsert;
|
const newContent =
|
||||||
target.value.slice(target.selectionStart);
|
target.value.slice(0, cursorPosition) +
|
||||||
|
markdownToInsert +
|
||||||
|
target.value.slice(cursorPosition);
|
||||||
|
|
||||||
|
target.value = newContent;
|
||||||
previewContent.value = newContent;
|
previewContent.value = newContent;
|
||||||
|
|
||||||
const newCursorPosition = cursorPosition + markdownToInsert.length;
|
const newCursorPosition = cursorPosition + markdownToInsert.length;
|
||||||
target.setSelectionRange(newCursorPosition, newCursorPosition);
|
target.setSelectionRange(newCursorPosition, newCursorPosition);
|
||||||
target.focus();
|
target.focus();
|
||||||
} else {
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
window.clearTimeout(loadingDelay);
|
||||||
|
pasting = false;
|
||||||
|
return;
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
{#if pasting}
|
||||||
|
<LoadingSpinner />
|
||||||
|
{/if}
|
||||||
|
|
||||||
<label>
|
<label>
|
||||||
{label}:
|
{label}:
|
||||||
<textarea
|
<textarea
|
||||||
|
|||||||
@@ -3,11 +3,39 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if success}
|
{#if success}
|
||||||
<p class="toast success">{message}</p>
|
<p class="toast success">
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
viewBox="0 0 20 20"
|
||||||
|
fill="currentColor"
|
||||||
|
width="20"
|
||||||
|
height="20"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fill-rule="evenodd"
|
||||||
|
d="M16.704 4.153a.75.75 0 0 1 .143 1.052l-8 10.5a.75.75 0 0 1-1.127.075l-4.5-4.5a.75.75 0 0 1 1.06-1.06l3.894 3.893 7.48-9.817a.75.75 0 0 1 1.05-.143Z"
|
||||||
|
clip-rule="evenodd"
|
||||||
|
></path>
|
||||||
|
</svg>
|
||||||
|
{message}
|
||||||
|
</p>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
{#if success === false}
|
{#if success === false}
|
||||||
<p class="toast error">{message}</p>
|
<p class="toast error">
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
viewBox="0 0 20 20"
|
||||||
|
fill="currentColor"
|
||||||
|
width="20"
|
||||||
|
height="20"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M6.28 5.22a.75.75 0 0 0-1.06 1.06L8.94 10l-3.72 3.72a.75.75 0 1 0 1.06 1.06L10 11.06l3.72 3.72a.75.75 0 1 0 1.06-1.06L11.06 10l3.72-3.72a.75.75 0 0 0-1.06-1.06L10 8.94 6.28 5.22Z"
|
||||||
|
></path>
|
||||||
|
</svg>
|
||||||
|
{message}
|
||||||
|
</p>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
import type { Actions, PageServerLoad } from "./$types";
|
import type { Actions, PageServerLoad } from "./$types";
|
||||||
import { apiRequest } from "$lib/server/utils";
|
import { apiRequest } from "$lib/server/utils";
|
||||||
import { API_BASE_PREFIX } from "$lib/server/utils";
|
import { API_BASE_PREFIX } from "$lib/server/utils";
|
||||||
import type { Website } from "$lib/db-schema";
|
import type { Collab, Website } from "$lib/db-schema";
|
||||||
|
|
||||||
export const load: PageServerLoad = async ({ fetch, url, locals }) => {
|
export const load: PageServerLoad = async ({ fetch, url, locals }) => {
|
||||||
const searchQuery = url.searchParams.get("website_search_query");
|
const searchQuery = url.searchParams.get("query");
|
||||||
const filterBy = url.searchParams.get("website_filter");
|
const filterBy = url.searchParams.get("filter");
|
||||||
|
|
||||||
const params = new URLSearchParams();
|
const params = new URLSearchParams();
|
||||||
|
|
||||||
const baseFetchUrl = `${API_BASE_PREFIX}/website?select=*,collab(user_id)&collab.user_id=eq.${locals.user.id}&or=(user_id.eq.${locals.user.id},collab.not.is.null)&order=last_modified_at.desc,created_at.desc`;
|
const baseFetchUrl = `${API_BASE_PREFIX}/website?select=*,collab(user_id,permission_level)&collab.user_id=eq.${locals.user.id}&or=(user_id.eq.${locals.user.id},collab.not.is.null)&order=last_modified_at.desc,created_at.desc`;
|
||||||
|
|
||||||
if (searchQuery) {
|
if (searchQuery) {
|
||||||
params.append("title", `wfts.${searchQuery}`);
|
params.append("title", `wfts.${searchQuery}`);
|
||||||
@@ -37,7 +37,7 @@ export const load: PageServerLoad = async ({ fetch, url, locals }) => {
|
|||||||
totalWebsites.data.headers.get("content-range")?.split("/").at(-1)
|
totalWebsites.data.headers.get("content-range")?.split("/").at(-1)
|
||||||
);
|
);
|
||||||
|
|
||||||
const websites: Website[] = (
|
const websites: (Website & { collab: Collab[] })[] = (
|
||||||
await apiRequest(fetch, constructedFetchUrl, "GET", {
|
await apiRequest(fetch, constructedFetchUrl, "GET", {
|
||||||
returnData: true
|
returnData: true
|
||||||
})
|
})
|
||||||
@@ -45,7 +45,8 @@ export const load: PageServerLoad = async ({ fetch, url, locals }) => {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
totalWebsiteCount,
|
totalWebsiteCount,
|
||||||
websites
|
websites,
|
||||||
|
user: locals.user
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -55,26 +55,19 @@
|
|||||||
<form method="GET">
|
<form method="GET">
|
||||||
<label>
|
<label>
|
||||||
Search:
|
Search:
|
||||||
<input
|
<input type="text" name="query" value={$page.url.searchParams.get("query")} />
|
||||||
type="text"
|
|
||||||
name="website_search_query"
|
|
||||||
value={$page.url.searchParams.get("website_search_query")}
|
|
||||||
/>
|
|
||||||
</label>
|
</label>
|
||||||
<label>
|
<label>
|
||||||
Filter:
|
Filter:
|
||||||
<select name="website_filter">
|
<select name="filter">
|
||||||
<option value="all" selected={"all" === $page.url.searchParams.get("website_filter")}
|
<option value="all" selected={"all" === $page.url.searchParams.get("filter")}
|
||||||
>Show all</option
|
>Show all</option
|
||||||
>
|
>
|
||||||
<option
|
<option
|
||||||
value="creations"
|
value="creations"
|
||||||
selected={"creations" === $page.url.searchParams.get("website_filter")}
|
selected={"creations" === $page.url.searchParams.get("filter")}>Created by you</option
|
||||||
>Created by you</option
|
|
||||||
>
|
>
|
||||||
<option
|
<option value="shared" selected={"shared" === $page.url.searchParams.get("filter")}
|
||||||
value="shared"
|
|
||||||
selected={"shared" === $page.url.searchParams.get("website_filter")}
|
|
||||||
>Shared with you</option
|
>Shared with you</option
|
||||||
>
|
>
|
||||||
</select>
|
</select>
|
||||||
@@ -84,7 +77,7 @@
|
|||||||
</details>
|
</details>
|
||||||
|
|
||||||
<ul class="website-grid unpadded">
|
<ul class="website-grid unpadded">
|
||||||
{#each data.websites as { id, content_type, title, created_at } (id)}
|
{#each data.websites as { id, user_id, content_type, title, created_at, collab } (id)}
|
||||||
<li class="website-card">
|
<li class="website-card">
|
||||||
<p>
|
<p>
|
||||||
<strong>
|
<strong>
|
||||||
@@ -123,7 +116,11 @@
|
|||||||
/>
|
/>
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<button type="submit">Submit</button>
|
<button
|
||||||
|
type="submit"
|
||||||
|
disabled={data.user.id !== user_id && collab[0].permission_level !== 30}
|
||||||
|
>Submit</button
|
||||||
|
>
|
||||||
</form>
|
</form>
|
||||||
</Modal>
|
</Modal>
|
||||||
<Modal id="delete-website-{id}" text="Delete">
|
<Modal id="delete-website-{id}" text="Delete">
|
||||||
@@ -140,7 +137,7 @@
|
|||||||
>
|
>
|
||||||
<input type="hidden" name="id" value={id} />
|
<input type="hidden" name="id" value={id} />
|
||||||
|
|
||||||
<button type="submit">Delete website</button>
|
<button type="submit" disabled={data.user.id !== user_id}>Delete website</button>
|
||||||
</form>
|
</form>
|
||||||
</Modal>
|
</Modal>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { API_BASE_PREFIX, apiRequest } from "$lib/server/utils";
|
|||||||
import { error } from "@sveltejs/kit";
|
import { error } from "@sveltejs/kit";
|
||||||
import type { Website, Home, User } from "$lib/db-schema";
|
import type { Website, Home, User } from "$lib/db-schema";
|
||||||
|
|
||||||
export const load: LayoutServerLoad = async ({ params, fetch }) => {
|
export const load: LayoutServerLoad = async ({ locals, params, fetch }) => {
|
||||||
const websiteData = await apiRequest(
|
const websiteData = await apiRequest(
|
||||||
fetch,
|
fetch,
|
||||||
`${API_BASE_PREFIX}/website?id=eq.${params.websiteId}&select=*,user!user_id(username)`,
|
`${API_BASE_PREFIX}/website?id=eq.${params.websiteId}&select=*,user!user_id(username)`,
|
||||||
@@ -31,8 +31,27 @@ export const load: LayoutServerLoad = async ({ params, fetch }) => {
|
|||||||
})
|
})
|
||||||
).data;
|
).data;
|
||||||
|
|
||||||
|
let permissionLevel = 40;
|
||||||
|
|
||||||
|
if (website.user_id !== locals.user.id) {
|
||||||
|
permissionLevel = (
|
||||||
|
await apiRequest(
|
||||||
|
fetch,
|
||||||
|
`${API_BASE_PREFIX}/collab?select=permission_level&website_id=eq.${params.websiteId}&user_id=eq.${locals.user.id}`,
|
||||||
|
"GET",
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
Accept: "application/vnd.pgrst.object+json"
|
||||||
|
},
|
||||||
|
returnData: true
|
||||||
|
}
|
||||||
|
)
|
||||||
|
).data.permission_level;
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
website,
|
website,
|
||||||
home
|
home,
|
||||||
|
permissionLevel
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -10,7 +10,6 @@
|
|||||||
import { sending } from "$lib/runes.svelte";
|
import { sending } from "$lib/runes.svelte";
|
||||||
import MarkdownEditor from "$lib/components/MarkdownEditor.svelte";
|
import MarkdownEditor from "$lib/components/MarkdownEditor.svelte";
|
||||||
import { previewContent } from "$lib/runes.svelte";
|
import { previewContent } from "$lib/runes.svelte";
|
||||||
|
|
||||||
const { data, form }: { data: PageServerData & LayoutServerData; form: ActionData } = $props();
|
const { data, form }: { data: PageServerData & LayoutServerData; form: ActionData } = $props();
|
||||||
|
|
||||||
previewContent.value = data.home.main_content;
|
previewContent.value = data.home.main_content;
|
||||||
@@ -96,7 +95,7 @@
|
|||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<button type="submit">Submit</button>
|
<button type="submit" disabled={data.permissionLevel === 10}>Submit</button>
|
||||||
</form>
|
</form>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
@@ -143,7 +142,7 @@
|
|||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<button type="submit">Submit</button>
|
<button type="submit" disabled={data.permissionLevel === 10}>Submit</button>
|
||||||
</form>
|
</form>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
@@ -166,7 +165,7 @@
|
|||||||
content={data.home.main_content}
|
content={data.home.main_content}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<button type="submit">Submit</button>
|
<button type="submit" disabled={data.permissionLevel === 10}>Submit</button>
|
||||||
</form>
|
</form>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
@@ -183,7 +182,7 @@
|
|||||||
>
|
>
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<button type="submit">Submit</button>
|
<button type="submit" disabled={data.permissionLevel === 10}>Submit</button>
|
||||||
</form>
|
</form>
|
||||||
</section>
|
</section>
|
||||||
</WebsiteEditor>
|
</WebsiteEditor>
|
||||||
|
|||||||
@@ -4,12 +4,12 @@ import { apiRequest } from "$lib/server/utils";
|
|||||||
import type { Article, DocsCategory } from "$lib/db-schema";
|
import type { Article, DocsCategory } from "$lib/db-schema";
|
||||||
|
|
||||||
export const load: PageServerLoad = async ({ params, fetch, url, parent, locals }) => {
|
export const load: PageServerLoad = async ({ params, fetch, url, parent, locals }) => {
|
||||||
const searchQuery = url.searchParams.get("article_search_query");
|
const searchQuery = url.searchParams.get("query");
|
||||||
const filterBy = url.searchParams.get("article_filter");
|
const filterBy = url.searchParams.get("filter");
|
||||||
|
|
||||||
const { website, home } = await parent();
|
const { website, home, permissionLevel } = await parent();
|
||||||
|
|
||||||
let baseFetchUrl = `${API_BASE_PREFIX}/article?website_id=eq.${params.websiteId}&select=id,title`;
|
let baseFetchUrl = `${API_BASE_PREFIX}/article?website_id=eq.${params.websiteId}&select=id,user_id,title`;
|
||||||
if (website.content_type === "Docs") {
|
if (website.content_type === "Docs") {
|
||||||
baseFetchUrl +=
|
baseFetchUrl +=
|
||||||
",article_weight,docs_category(category_name,category_weight)&order=docs_category(category_weight).desc.nullslast,article_weight.desc.nullslast";
|
",article_weight,docs_category(category_name,category_weight)&order=docs_category(category_weight).desc.nullslast,article_weight.desc.nullslast";
|
||||||
@@ -56,7 +56,9 @@ export const load: PageServerLoad = async ({ params, fetch, url, parent, locals
|
|||||||
totalArticleCount,
|
totalArticleCount,
|
||||||
articles,
|
articles,
|
||||||
website,
|
website,
|
||||||
home
|
home,
|
||||||
|
permissionLevel,
|
||||||
|
user: locals.user
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -40,7 +40,7 @@
|
|||||||
<input type="text" name="title" pattern="\S(.*\S)?" maxlength="100" required />
|
<input type="text" name="title" pattern="\S(.*\S)?" maxlength="100" required />
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<button type="submit">Submit</button>
|
<button type="submit" disabled={data.permissionLevel === 10}>Submit</button>
|
||||||
</form>
|
</form>
|
||||||
</Modal>
|
</Modal>
|
||||||
</section>
|
</section>
|
||||||
@@ -56,26 +56,20 @@
|
|||||||
<form method="GET">
|
<form method="GET">
|
||||||
<label>
|
<label>
|
||||||
Search:
|
Search:
|
||||||
<input
|
<input type="text" name="query" value={$page.url.searchParams.get("query")} />
|
||||||
type="text"
|
|
||||||
name="article_search_query"
|
|
||||||
value={$page.url.searchParams.get("article_search_query")}
|
|
||||||
/>
|
|
||||||
</label>
|
</label>
|
||||||
<label>
|
<label>
|
||||||
Filter:
|
Filter:
|
||||||
<select name="article_filter">
|
<select name="filter">
|
||||||
<option value="all" selected={"all" === $page.url.searchParams.get("article_filter")}
|
<option value="all" selected={"all" === $page.url.searchParams.get("filter")}
|
||||||
>Show all</option
|
>Show all</option
|
||||||
>
|
>
|
||||||
<option
|
<option
|
||||||
value="creations"
|
value="creations"
|
||||||
selected={"creations" === $page.url.searchParams.get("article_filter")}
|
selected={"creations" === $page.url.searchParams.get("filter")}
|
||||||
>Created by you</option
|
>Created by you</option
|
||||||
>
|
>
|
||||||
<option
|
<option value="shared" selected={"shared" === $page.url.searchParams.get("filter")}
|
||||||
value="shared"
|
|
||||||
selected={"shared" === $page.url.searchParams.get("article_filter")}
|
|
||||||
>Created by others</option
|
>Created by others</option
|
||||||
>
|
>
|
||||||
</select>
|
</select>
|
||||||
@@ -85,7 +79,7 @@
|
|||||||
</details>
|
</details>
|
||||||
|
|
||||||
<ul class="unpadded">
|
<ul class="unpadded">
|
||||||
{#each data.articles as { id, title, article_weight, docs_category } (id)}
|
{#each data.articles as { id, user_id, title, article_weight, docs_category } (id)}
|
||||||
<li class="article-card">
|
<li class="article-card">
|
||||||
<p>
|
<p>
|
||||||
<strong>{title} {article_weight ? `(${article_weight})` : ""}</strong>
|
<strong>{title} {article_weight ? `(${article_weight})` : ""}</strong>
|
||||||
@@ -129,7 +123,12 @@
|
|||||||
>
|
>
|
||||||
<input type="hidden" name="id" value={id} />
|
<input type="hidden" name="id" value={id} />
|
||||||
|
|
||||||
<button type="submit">Delete article</button>
|
<button
|
||||||
|
type="submit"
|
||||||
|
disabled={data.permissionLevel === 10 ||
|
||||||
|
(data.permissionLevel === 20 && user_id !== data.user.id)}
|
||||||
|
>Delete article</button
|
||||||
|
>
|
||||||
</form>
|
</form>
|
||||||
</Modal>
|
</Modal>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -23,9 +23,9 @@ export const load: PageServerLoad = async ({ parent, params, fetch }) => {
|
|||||||
)
|
)
|
||||||
).data;
|
).data;
|
||||||
|
|
||||||
const { website } = await parent();
|
const { website, permissionLevel } = await parent();
|
||||||
|
|
||||||
return { website, article, categories, API_BASE_PREFIX };
|
return { website, article, categories, API_BASE_PREFIX, permissionLevel };
|
||||||
};
|
};
|
||||||
|
|
||||||
export const actions: Actions = {
|
export const actions: Actions = {
|
||||||
|
|||||||
@@ -119,7 +119,7 @@
|
|||||||
content={data.article.main_content ?? ""}
|
content={data.article.main_content ?? ""}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<button type="submit">Submit</button>
|
<button type="submit" disabled={data.permissionLevel === 10}>Submit</button>
|
||||||
</form>
|
</form>
|
||||||
</section>
|
</section>
|
||||||
</WebsiteEditor>
|
</WebsiteEditor>
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import type { Actions, PageServerLoad } from "./$types";
|
|||||||
import { API_BASE_PREFIX, apiRequest } from "$lib/server/utils";
|
import { API_BASE_PREFIX, apiRequest } from "$lib/server/utils";
|
||||||
import type { DocsCategory } from "$lib/db-schema";
|
import type { DocsCategory } from "$lib/db-schema";
|
||||||
|
|
||||||
export const load: PageServerLoad = async ({ parent, params, fetch }) => {
|
export const load: PageServerLoad = async ({ parent, params, fetch, locals }) => {
|
||||||
const categories: DocsCategory[] = (
|
const categories: DocsCategory[] = (
|
||||||
await apiRequest(
|
await apiRequest(
|
||||||
fetch,
|
fetch,
|
||||||
@@ -14,12 +14,14 @@ export const load: PageServerLoad = async ({ parent, params, fetch }) => {
|
|||||||
)
|
)
|
||||||
).data;
|
).data;
|
||||||
|
|
||||||
const { website, home } = await parent();
|
const { website, home, permissionLevel } = await parent();
|
||||||
|
|
||||||
return {
|
return {
|
||||||
categories,
|
categories,
|
||||||
website,
|
website,
|
||||||
home
|
home,
|
||||||
|
permissionLevel,
|
||||||
|
user: locals.user
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -44,7 +44,7 @@
|
|||||||
<input name="category-weight" type="number" min="0" required />
|
<input name="category-weight" type="number" min="0" required />
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<button type="submit">Submit</button>
|
<button type="submit" disabled={data.permissionLevel === 10}>Submit</button>
|
||||||
</form>
|
</form>
|
||||||
</Modal>
|
</Modal>
|
||||||
</section>
|
</section>
|
||||||
@@ -56,7 +56,7 @@
|
|||||||
</h2>
|
</h2>
|
||||||
|
|
||||||
<ul class="unpadded">
|
<ul class="unpadded">
|
||||||
{#each data.categories as { id, website_id, category_name, category_weight } (`${website_id}-${id}`)}
|
{#each data.categories as { id, website_id, user_id, category_name, category_weight } (`${website_id}-${id}`)}
|
||||||
<li class="category-card">
|
<li class="category-card">
|
||||||
<p>
|
<p>
|
||||||
<strong>{category_name} ({category_weight})</strong>
|
<strong>{category_name} ({category_weight})</strong>
|
||||||
@@ -89,7 +89,9 @@
|
|||||||
<input type="number" name="category-weight" value={category_weight} min="0" />
|
<input type="number" name="category-weight" value={category_weight} min="0" />
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<button type="submit">Update category</button>
|
<button type="submit" disabled={data.permissionLevel === 10}
|
||||||
|
>Update category</button
|
||||||
|
>
|
||||||
</form>
|
</form>
|
||||||
</Modal>
|
</Modal>
|
||||||
<Modal id="delete-category-{id}" text="Delete">
|
<Modal id="delete-category-{id}" text="Delete">
|
||||||
@@ -104,7 +106,12 @@
|
|||||||
>
|
>
|
||||||
<input type="hidden" name="category-id" value={id} />
|
<input type="hidden" name="category-id" value={id} />
|
||||||
|
|
||||||
<button type="submit">Delete category</button>
|
<button
|
||||||
|
type="submit"
|
||||||
|
disabled={data.permissionLevel === 10 ||
|
||||||
|
(data.permissionLevel === 20 && user_id !== data.user.id)}
|
||||||
|
>Delete category</button
|
||||||
|
>
|
||||||
</form>
|
</form>
|
||||||
</Modal>
|
</Modal>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import type { Actions, PageServerLoad } from "./$types";
|
|||||||
import { API_BASE_PREFIX, apiRequest } from "$lib/server/utils";
|
import { API_BASE_PREFIX, apiRequest } from "$lib/server/utils";
|
||||||
import type { Collab, User } from "$lib/db-schema";
|
import type { Collab, User } from "$lib/db-schema";
|
||||||
|
|
||||||
export const load: PageServerLoad = async ({ parent, params, fetch }) => {
|
export const load: PageServerLoad = async ({ parent, params, fetch, locals }) => {
|
||||||
const collaborators: (Collab & { user: User })[] = (
|
const collaborators: (Collab & { user: User })[] = (
|
||||||
await apiRequest(
|
await apiRequest(
|
||||||
fetch,
|
fetch,
|
||||||
@@ -14,12 +14,14 @@ export const load: PageServerLoad = async ({ parent, params, fetch }) => {
|
|||||||
)
|
)
|
||||||
).data;
|
).data;
|
||||||
|
|
||||||
const { website, home } = await parent();
|
const { website, home, permissionLevel } = await parent();
|
||||||
|
|
||||||
return {
|
return {
|
||||||
website,
|
website,
|
||||||
home,
|
home,
|
||||||
collaborators
|
collaborators,
|
||||||
|
permissionLevel,
|
||||||
|
user: locals.user
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -51,7 +51,7 @@
|
|||||||
</select>
|
</select>
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<button type="submit">Submit</button>
|
<button type="submit" disabled={[10, 20].includes(data.permissionLevel)}>Submit</button>
|
||||||
</form>
|
</form>
|
||||||
</Modal>
|
</Modal>
|
||||||
</section>
|
</section>
|
||||||
@@ -89,7 +89,11 @@
|
|||||||
</select>
|
</select>
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<button type="submit">Update collaborator</button>
|
<button
|
||||||
|
type="submit"
|
||||||
|
disabled={[10, 20].includes(data.permissionLevel) || user_id === data.user.id}
|
||||||
|
>Update collaborator</button
|
||||||
|
>
|
||||||
</form>
|
</form>
|
||||||
</Modal>
|
</Modal>
|
||||||
<Modal id="remove-collaborator-{user_id}" text="Remove">
|
<Modal id="remove-collaborator-{user_id}" text="Remove">
|
||||||
@@ -104,7 +108,11 @@
|
|||||||
>
|
>
|
||||||
<input type="hidden" name="user-id" value={user_id} />
|
<input type="hidden" name="user-id" value={user_id} />
|
||||||
|
|
||||||
<button type="submit">Remove collaborator</button>
|
<button
|
||||||
|
type="submit"
|
||||||
|
disabled={[10, 20].includes(data.permissionLevel) || user_id === data.user.id}
|
||||||
|
>Remove collaborator</button
|
||||||
|
>
|
||||||
</form>
|
</form>
|
||||||
</Modal>
|
</Modal>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -17,12 +17,13 @@ export const load: PageServerLoad = async ({ parent, fetch, params }) => {
|
|||||||
)
|
)
|
||||||
).data;
|
).data;
|
||||||
|
|
||||||
const { website } = await parent();
|
const { website, permissionLevel } = await parent();
|
||||||
|
|
||||||
return {
|
return {
|
||||||
legalInformation,
|
legalInformation,
|
||||||
website,
|
website,
|
||||||
API_BASE_PREFIX
|
API_BASE_PREFIX,
|
||||||
|
permissionLevel
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -57,5 +58,22 @@ export const actions: Actions = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return deleteLegalInformation;
|
return deleteLegalInformation;
|
||||||
|
},
|
||||||
|
pasteImage: async ({ request, fetch, params }) => {
|
||||||
|
const data = await request.formData();
|
||||||
|
const file = data.get("file") as File;
|
||||||
|
|
||||||
|
return await apiRequest(fetch, `${API_BASE_PREFIX}/rpc/upload_file`, "POST", {
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/octet-stream",
|
||||||
|
Accept: "application/vnd.pgrst.object+json",
|
||||||
|
"X-Website-Id": params.websiteId,
|
||||||
|
"X-Mimetype": file.type,
|
||||||
|
"X-Original-Filename": file.name
|
||||||
|
},
|
||||||
|
body: await file.arrayBuffer(),
|
||||||
|
successMessage: "Successfully uploaded image",
|
||||||
|
returnData: true
|
||||||
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -61,7 +61,7 @@
|
|||||||
content={data.legalInformation?.main_content ?? ""}
|
content={data.legalInformation?.main_content ?? ""}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<button type="submit">Submit</button>
|
<button type="submit" disabled={[10, 20].includes(data.permissionLevel)}>Submit</button>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
{#if data.legalInformation?.main_content}
|
{#if data.legalInformation?.main_content}
|
||||||
@@ -76,7 +76,9 @@
|
|||||||
<strong>Caution!</strong>
|
<strong>Caution!</strong>
|
||||||
This action will remove the legal information page from the website and delete all data.
|
This action will remove the legal information page from the website and delete all data.
|
||||||
</p>
|
</p>
|
||||||
<button type="submit">Delete legal information</button>
|
<button type="submit" disabled={[10, 20].includes(data.permissionLevel)}
|
||||||
|
>Delete legal information</button
|
||||||
|
>
|
||||||
</form>
|
</form>
|
||||||
</Modal>
|
</Modal>
|
||||||
{/if}
|
{/if}
|
||||||
|
|||||||
@@ -4,10 +4,10 @@ import type { ChangeLog, User, Collab } from "$lib/db-schema";
|
|||||||
import DiffMatchPatch from "diff-match-patch";
|
import DiffMatchPatch from "diff-match-patch";
|
||||||
|
|
||||||
export const load: PageServerLoad = async ({ parent, fetch, params, url }) => {
|
export const load: PageServerLoad = async ({ parent, fetch, params, url }) => {
|
||||||
const userFilter = url.searchParams.get("logs_filter_user");
|
const userFilter = url.searchParams.get("user");
|
||||||
const resourceFilter = url.searchParams.get("logs_filter_resource");
|
const resourceFilter = url.searchParams.get("resource");
|
||||||
const operationFilter = url.searchParams.get("logs_filter_operation");
|
const operationFilter = url.searchParams.get("operation");
|
||||||
const currentPage = Number.parseInt(url.searchParams.get("logs_results_page") ?? "1");
|
const currentPage = Number.parseInt(url.searchParams.get("page") ?? "1");
|
||||||
const resultOffset = (currentPage - 1) * 20;
|
const resultOffset = (currentPage - 1) * 20;
|
||||||
|
|
||||||
const searchParams = new URLSearchParams();
|
const searchParams = new URLSearchParams();
|
||||||
|
|||||||
@@ -57,8 +57,8 @@
|
|||||||
Username:
|
Username:
|
||||||
<input
|
<input
|
||||||
list="users-{data.website.id}"
|
list="users-{data.website.id}"
|
||||||
name="logs_filter_user"
|
name="user"
|
||||||
value={$page.url.searchParams.get("logs_filter_user")}
|
value={$page.url.searchParams.get("user")}
|
||||||
/>
|
/>
|
||||||
<datalist id="users-{data.website.id}">
|
<datalist id="users-{data.website.id}">
|
||||||
<option value={data.website.user.username}></option>
|
<option value={data.website.user.username}></option>
|
||||||
@@ -69,39 +69,32 @@
|
|||||||
</label>
|
</label>
|
||||||
<label>
|
<label>
|
||||||
Resource:
|
Resource:
|
||||||
<select name="logs_filter_resource">
|
<select name="resource">
|
||||||
<option value="all">Show all</option>
|
<option value="all">Show all</option>
|
||||||
{#each Object.keys(resources) as resource}
|
{#each Object.keys(resources) as resource}
|
||||||
<option
|
<option
|
||||||
value={resource}
|
value={resource}
|
||||||
selected={resource === $page.url.searchParams.get("logs_filter_resource")}
|
selected={resource === $page.url.searchParams.get("resource")}>{resource}</option
|
||||||
>{resource}</option
|
|
||||||
>
|
>
|
||||||
{/each}
|
{/each}
|
||||||
</select>
|
</select>
|
||||||
</label>
|
</label>
|
||||||
<label>
|
<label>
|
||||||
Operation:
|
Operation:
|
||||||
<select name="logs_filter_operation">
|
<select name="operation">
|
||||||
<option value="all">Show all</option>
|
<option value="all">Show all</option>
|
||||||
<option
|
<option value="insert" selected={"insert" === $page.url.searchParams.get("operation")}
|
||||||
value="insert"
|
|
||||||
selected={"insert" === $page.url.searchParams.get("logs_filter_operation")}
|
|
||||||
>Insert</option
|
>Insert</option
|
||||||
>
|
>
|
||||||
<option
|
<option value="update" selected={"update" === $page.url.searchParams.get("operation")}
|
||||||
value="update"
|
|
||||||
selected={"update" === $page.url.searchParams.get("logs_filter_operation")}
|
|
||||||
>Update</option
|
>Update</option
|
||||||
>
|
>
|
||||||
<option
|
<option value="delete" selected={"delete" === $page.url.searchParams.get("operation")}
|
||||||
value="delete"
|
|
||||||
selected={"delete" === $page.url.searchParams.get("logs_filter_operation")}
|
|
||||||
>Delete</option
|
>Delete</option
|
||||||
>
|
>
|
||||||
</select>
|
</select>
|
||||||
</label>
|
</label>
|
||||||
<input type="hidden" name="logs_results_page" value={1} />
|
<input type="hidden" name="page" value={1} />
|
||||||
<button type="submit">Submit</button>
|
<button type="submit">Submit</button>
|
||||||
</form>
|
</form>
|
||||||
</details>
|
</details>
|
||||||
@@ -112,7 +105,7 @@
|
|||||||
<th>User</th>
|
<th>User</th>
|
||||||
<th>Resource</th>
|
<th>Resource</th>
|
||||||
<th>Operation</th>
|
<th>Operation</th>
|
||||||
<th>Date and time</th>
|
<th>Date & Time</th>
|
||||||
<th>Changes</th>
|
<th>Changes</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
@@ -171,78 +164,60 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="pagination">
|
<div class="pagination">
|
||||||
{#snippet commonFilterInputs()}
|
{#snippet commonFilterInputs()}
|
||||||
<input
|
<input type="hidden" name="user" value={$page.url.searchParams.get("user")} />
|
||||||
type="hidden"
|
<input type="hidden" name="resource" value={$page.url.searchParams.get("resource")} />
|
||||||
name="logs_filter_user"
|
<input type="hidden" name="operation" value={$page.url.searchParams.get("operation")} />
|
||||||
value={$page.url.searchParams.get("logs_filter_user")}
|
|
||||||
/>
|
|
||||||
<input
|
|
||||||
type="hidden"
|
|
||||||
name="logs_filter_resource"
|
|
||||||
value={$page.url.searchParams.get("logs_filter_resource")}
|
|
||||||
/>
|
|
||||||
<input
|
|
||||||
type="hidden"
|
|
||||||
name="logs_filter_operation"
|
|
||||||
value={$page.url.searchParams.get("logs_filter_operation")}
|
|
||||||
/>
|
|
||||||
{/snippet}
|
{/snippet}
|
||||||
<p>
|
<p>
|
||||||
{$page.url.searchParams.get("logs_results_page") ?? 1} / {Math.max(
|
{$page.url.searchParams.get("page") ?? 1} / {Math.max(
|
||||||
Math.ceil(data.resultChangeLogCount / 20),
|
Math.ceil(data.resultChangeLogCount / 20),
|
||||||
1
|
1
|
||||||
)}
|
)}
|
||||||
</p>
|
</p>
|
||||||
<form method="GET">
|
<form method="GET">
|
||||||
<input type="hidden" name="logs_results_page" value={1} />
|
<input type="hidden" name="page" value={1} />
|
||||||
{@render commonFilterInputs()}
|
{@render commonFilterInputs()}
|
||||||
<button
|
<button type="submit" disabled={($page.url.searchParams.get("page") ?? "1") === "1"}
|
||||||
type="submit"
|
>First</button
|
||||||
disabled={($page.url.searchParams.get("logs_results_page") ?? "1") === "1"}>First</button
|
|
||||||
>
|
>
|
||||||
</form>
|
</form>
|
||||||
<form method="GET">
|
<form method="GET">
|
||||||
<input
|
<input
|
||||||
type="hidden"
|
type="hidden"
|
||||||
name="logs_results_page"
|
name="page"
|
||||||
value={Math.max(
|
value={Math.max(1, Number.parseInt($page.url.searchParams.get("page") ?? "1") - 1)}
|
||||||
1,
|
|
||||||
Number.parseInt($page.url.searchParams.get("logs_results_page") ?? "1") - 1
|
|
||||||
)}
|
|
||||||
/>
|
/>
|
||||||
{@render commonFilterInputs()}
|
{@render commonFilterInputs()}
|
||||||
<button
|
<button type="submit" disabled={($page.url.searchParams.get("page") ?? "1") === "1"}
|
||||||
type="submit"
|
|
||||||
disabled={($page.url.searchParams.get("logs_results_page") ?? "1") === "1"}
|
|
||||||
>Previous</button
|
>Previous</button
|
||||||
>
|
>
|
||||||
</form>
|
</form>
|
||||||
<form method="GET">
|
<form method="GET">
|
||||||
<input
|
<input
|
||||||
type="hidden"
|
type="hidden"
|
||||||
name="logs_results_page"
|
name="page"
|
||||||
value={Math.min(
|
value={Math.min(
|
||||||
Math.max(Math.ceil(data.resultChangeLogCount / 20), 1),
|
Math.max(Math.ceil(data.resultChangeLogCount / 20), 1),
|
||||||
Number.parseInt($page.url.searchParams.get("logs_results_page") ?? "1") + 1
|
Number.parseInt($page.url.searchParams.get("page") ?? "1") + 1
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
{@render commonFilterInputs()}
|
{@render commonFilterInputs()}
|
||||||
<button
|
<button
|
||||||
type="submit"
|
type="submit"
|
||||||
disabled={($page.url.searchParams.get("logs_results_page") ?? "1") ===
|
disabled={($page.url.searchParams.get("page") ?? "1") ===
|
||||||
Math.max(Math.ceil(data.resultChangeLogCount / 20), 1).toString()}>Next</button
|
Math.max(Math.ceil(data.resultChangeLogCount / 20), 1).toString()}>Next</button
|
||||||
>
|
>
|
||||||
</form>
|
</form>
|
||||||
<form method="GET">
|
<form method="GET">
|
||||||
<input
|
<input
|
||||||
type="hidden"
|
type="hidden"
|
||||||
name="logs_results_page"
|
name="page"
|
||||||
value={Math.max(Math.ceil(data.resultChangeLogCount / 20), 1)}
|
value={Math.max(Math.ceil(data.resultChangeLogCount / 20), 1)}
|
||||||
/>
|
/>
|
||||||
{@render commonFilterInputs()}
|
{@render commonFilterInputs()}
|
||||||
<button
|
<button
|
||||||
type="submit"
|
type="submit"
|
||||||
disabled={($page.url.searchParams.get("logs_results_page") ?? "1") ===
|
disabled={($page.url.searchParams.get("page") ?? "1") ===
|
||||||
Math.max(Math.ceil(data.resultChangeLogCount / 20), 1).toString()}>Last</button
|
Math.max(Math.ceil(data.resultChangeLogCount / 20), 1).toString()}>Last</button
|
||||||
>
|
>
|
||||||
</form>
|
</form>
|
||||||
@@ -262,9 +237,4 @@
|
|||||||
.pagination > form:first-of-type {
|
.pagination > form:first-of-type {
|
||||||
margin-inline-start: auto;
|
margin-inline-start: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
button:disabled {
|
|
||||||
pointer-events: none;
|
|
||||||
color: hsl(0 0% 50%);
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import { join } from "node:path";
|
|||||||
import { render } from "svelte/server";
|
import { render } from "svelte/server";
|
||||||
import type { Actions, PageServerLoad } from "./$types";
|
import type { Actions, PageServerLoad } from "./$types";
|
||||||
|
|
||||||
export const load: PageServerLoad = async ({ params, fetch }) => {
|
export const load: PageServerLoad = async ({ params, fetch, parent }) => {
|
||||||
const websiteOverview: WebsiteOverview = (
|
const websiteOverview: WebsiteOverview = (
|
||||||
await apiRequest(
|
await apiRequest(
|
||||||
fetch,
|
fetch,
|
||||||
@@ -27,10 +27,13 @@ export const load: PageServerLoad = async ({ params, fetch }) => {
|
|||||||
|
|
||||||
const { websitePreviewUrl, websiteProdUrl } = await generateStaticFiles(websiteOverview);
|
const { websitePreviewUrl, websiteProdUrl } = await generateStaticFiles(websiteOverview);
|
||||||
|
|
||||||
|
const { permissionLevel } = await parent();
|
||||||
|
|
||||||
return {
|
return {
|
||||||
websiteOverview,
|
websiteOverview,
|
||||||
websitePreviewUrl,
|
websitePreviewUrl,
|
||||||
websiteProdUrl
|
websiteProdUrl,
|
||||||
|
permissionLevel
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -36,7 +36,7 @@
|
|||||||
be published on the Internet.
|
be published on the Internet.
|
||||||
</p>
|
</p>
|
||||||
<form method="POST" action="?/publishWebsite" use:enhance={enhanceForm()}>
|
<form method="POST" action="?/publishWebsite" use:enhance={enhanceForm()}>
|
||||||
<button type="submit">Publish</button>
|
<button type="submit" disabled={[10, 20].includes(data.permissionLevel)}>Publish</button>
|
||||||
</form>
|
</form>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
@@ -73,7 +73,7 @@
|
|||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
</label>
|
</label>
|
||||||
<button type="submit">Submit</button>
|
<button type="submit" disabled={[10, 20].includes(data.permissionLevel)}>Submit</button>
|
||||||
</form>
|
</form>
|
||||||
{#if data.websiteOverview.domain_prefix?.prefix}
|
{#if data.websiteOverview.domain_prefix?.prefix}
|
||||||
<Modal id="delete-domain-prefix" text="Delete">
|
<Modal id="delete-domain-prefix" text="Delete">
|
||||||
@@ -87,7 +87,9 @@
|
|||||||
<strong>Caution!</strong>
|
<strong>Caution!</strong>
|
||||||
This action will remove the domain prefix and reset it to its initial value.
|
This action will remove the domain prefix and reset it to its initial value.
|
||||||
</p>
|
</p>
|
||||||
<button type="submit">Delete domain prefix</button>
|
<button type="submit" disabled={[10, 20].includes(data.permissionLevel)}
|
||||||
|
>Delete domain prefix</button
|
||||||
|
>
|
||||||
</form>
|
</form>
|
||||||
</Modal>
|
</Modal>
|
||||||
{/if}
|
{/if}
|
||||||
|
|||||||
@@ -105,6 +105,12 @@ label[for="toggle-theme"] svg:last-of-type {
|
|||||||
background-color: var(--bg-tertiary);
|
background-color: var(--bg-tertiary);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
button:disabled {
|
||||||
|
pointer-events: none;
|
||||||
|
opacity: 0.5;
|
||||||
|
z-index: -10;
|
||||||
|
}
|
||||||
|
|
||||||
:is(button, input, textarea, select, a, summary, pre):focus,
|
:is(button, input, textarea, select, a, summary, pre):focus,
|
||||||
:is(#toggle-mobile-preview, #toggle-sidebar):checked + label {
|
:is(#toggle-mobile-preview, #toggle-sidebar):checked + label {
|
||||||
outline: 0.125rem solid var(--color-accent);
|
outline: 0.125rem solid var(--color-accent);
|
||||||
|
|||||||
@@ -154,6 +154,10 @@ test.describe.serial("Collaborator tests", () => {
|
|||||||
|
|
||||||
test("Update website", async ({ page }) => {
|
test("Update website", async ({ page }) => {
|
||||||
await page.locator("li").filter({ hasText: "Blog" }).getByRole("button").first().click();
|
await page.locator("li").filter({ hasText: "Blog" }).getByRole("button").first().click();
|
||||||
|
const modalName = page.url().split("#")[1];
|
||||||
|
await page
|
||||||
|
.locator(`div[id="${modalName}"] button[type="submit"]`)
|
||||||
|
.evaluate((node) => node.removeAttribute("disabled"));
|
||||||
await page.getByRole("button", { name: "Submit" }).click();
|
await page.getByRole("button", { name: "Submit" }).click();
|
||||||
|
|
||||||
if ([10, 20].includes(permissionLevel)) {
|
if ([10, 20].includes(permissionLevel)) {
|
||||||
@@ -164,11 +168,18 @@ test.describe.serial("Collaborator tests", () => {
|
|||||||
});
|
});
|
||||||
test("Delete website", async ({ page }) => {
|
test("Delete website", async ({ page }) => {
|
||||||
await page.locator("li").filter({ hasText: "Blog" }).getByRole("button").nth(1).click();
|
await page.locator("li").filter({ hasText: "Blog" }).getByRole("button").nth(1).click();
|
||||||
|
const modalName = page.url().split("#")[1];
|
||||||
|
await page
|
||||||
|
.locator(`div[id="${modalName}"] button[type="submit"]`)
|
||||||
|
.evaluate((node) => node.removeAttribute("disabled"));
|
||||||
await page.getByRole("button", { name: "Delete website" }).click();
|
await page.getByRole("button", { name: "Delete website" }).click();
|
||||||
await expect(page.getByText("Insufficient permissions")).toBeVisible();
|
await expect(page.getByText("Insufficient permissions")).toBeVisible();
|
||||||
});
|
});
|
||||||
test("Update Global", async ({ page }) => {
|
test("Update Global", async ({ page }) => {
|
||||||
await page.getByRole("link", { name: "Blog" }).click();
|
await page.getByRole("link", { name: "Blog" }).click();
|
||||||
|
await page
|
||||||
|
.locator('#global button[type="submit"]')
|
||||||
|
.evaluate((node) => node.removeAttribute("disabled"));
|
||||||
await page.locator("#global").getByRole("button", { name: "Submit" }).click();
|
await page.locator("#global").getByRole("button", { name: "Submit" }).click();
|
||||||
|
|
||||||
if (permissionLevel === 10) {
|
if (permissionLevel === 10) {
|
||||||
@@ -179,6 +190,9 @@ test.describe.serial("Collaborator tests", () => {
|
|||||||
});
|
});
|
||||||
test("Update Header", async ({ page }) => {
|
test("Update Header", async ({ page }) => {
|
||||||
await page.getByRole("link", { name: "Blog" }).click();
|
await page.getByRole("link", { name: "Blog" }).click();
|
||||||
|
await page
|
||||||
|
.locator('#header button[type="submit"]')
|
||||||
|
.evaluate((node) => node.removeAttribute("disabled"));
|
||||||
await page.locator("#header").getByRole("button", { name: "Submit" }).click();
|
await page.locator("#header").getByRole("button", { name: "Submit" }).click();
|
||||||
|
|
||||||
if (permissionLevel === 10) {
|
if (permissionLevel === 10) {
|
||||||
@@ -191,6 +205,9 @@ test.describe.serial("Collaborator tests", () => {
|
|||||||
await page.getByRole("link", { name: "Blog" }).click();
|
await page.getByRole("link", { name: "Blog" }).click();
|
||||||
await page.getByLabel("Description:").click();
|
await page.getByLabel("Description:").click();
|
||||||
await page.getByLabel("Description:").fill("Description");
|
await page.getByLabel("Description:").fill("Description");
|
||||||
|
await page
|
||||||
|
.locator('#home button[type="submit"]')
|
||||||
|
.evaluate((node) => node.removeAttribute("disabled"));
|
||||||
await page.locator("#home").getByRole("button", { name: "Submit" }).click();
|
await page.locator("#home").getByRole("button", { name: "Submit" }).click();
|
||||||
|
|
||||||
if (permissionLevel === 10) {
|
if (permissionLevel === 10) {
|
||||||
@@ -201,6 +218,9 @@ test.describe.serial("Collaborator tests", () => {
|
|||||||
});
|
});
|
||||||
test("Update Footer", async ({ page }) => {
|
test("Update Footer", async ({ page }) => {
|
||||||
await page.getByRole("link", { name: "Blog" }).click();
|
await page.getByRole("link", { name: "Blog" }).click();
|
||||||
|
await page
|
||||||
|
.locator('#footer button[type="submit"]')
|
||||||
|
.evaluate((node) => node.removeAttribute("disabled"));
|
||||||
await page.locator("#footer").getByRole("button", { name: "Submit" }).click();
|
await page.locator("#footer").getByRole("button", { name: "Submit" }).click();
|
||||||
|
|
||||||
if (permissionLevel === 10) {
|
if (permissionLevel === 10) {
|
||||||
@@ -215,6 +235,9 @@ test.describe.serial("Collaborator tests", () => {
|
|||||||
await page.getByRole("button", { name: "Create article" }).click();
|
await page.getByRole("button", { name: "Create article" }).click();
|
||||||
await page.getByLabel("Title:").click();
|
await page.getByLabel("Title:").click();
|
||||||
await page.getByLabel("Title:").fill(`Article-${permissionLevel}`);
|
await page.getByLabel("Title:").fill(`Article-${permissionLevel}`);
|
||||||
|
await page
|
||||||
|
.locator('form[action="?/createArticle"] button[type="submit"]')
|
||||||
|
.evaluate((node) => node.removeAttribute("disabled"));
|
||||||
await page.getByRole("button", { name: "Submit" }).click();
|
await page.getByRole("button", { name: "Submit" }).click();
|
||||||
|
|
||||||
if (permissionLevel === 10) {
|
if (permissionLevel === 10) {
|
||||||
@@ -237,6 +260,9 @@ test.describe.serial("Collaborator tests", () => {
|
|||||||
await page.getByLabel("Author:").fill("Author");
|
await page.getByLabel("Author:").fill("Author");
|
||||||
await page.getByLabel("Main content:").click();
|
await page.getByLabel("Main content:").click();
|
||||||
await page.getByLabel("Main content:").fill("## Main content");
|
await page.getByLabel("Main content:").fill("## Main content");
|
||||||
|
await page
|
||||||
|
.locator('form button[type="submit"]')
|
||||||
|
.evaluate((node) => node.removeAttribute("disabled"));
|
||||||
await page.getByRole("button", { name: "Submit" }).click();
|
await page.getByRole("button", { name: "Submit" }).click();
|
||||||
|
|
||||||
if (permissionLevel === 10) {
|
if (permissionLevel === 10) {
|
||||||
@@ -253,6 +279,10 @@ test.describe.serial("Collaborator tests", () => {
|
|||||||
.filter({ hasText: `Article-${permissionLevel}` })
|
.filter({ hasText: `Article-${permissionLevel}` })
|
||||||
.getByRole("button")
|
.getByRole("button")
|
||||||
.click();
|
.click();
|
||||||
|
const modalName = page.url().split("#")[1];
|
||||||
|
await page
|
||||||
|
.locator(`div[id="${modalName}"] button[type="submit"]`)
|
||||||
|
.evaluate((node) => node.removeAttribute("disabled"));
|
||||||
await page.getByRole("button", { name: "Delete article" }).click();
|
await page.getByRole("button", { name: "Delete article" }).click();
|
||||||
|
|
||||||
if (permissionLevel === 10) {
|
if (permissionLevel === 10) {
|
||||||
@@ -262,6 +292,10 @@ test.describe.serial("Collaborator tests", () => {
|
|||||||
await expect(page.getByText("Successfully deleted article")).toBeVisible();
|
await expect(page.getByText("Successfully deleted article")).toBeVisible();
|
||||||
|
|
||||||
await page.locator("li").filter({ hasText: `Article-10` }).getByRole("button").click();
|
await page.locator("li").filter({ hasText: `Article-10` }).getByRole("button").click();
|
||||||
|
const modalName = page.url().split("#")[1];
|
||||||
|
await page
|
||||||
|
.locator(`div[id="${modalName}"] button[type="submit"]`)
|
||||||
|
.evaluate((node) => node.removeAttribute("disabled"));
|
||||||
await page.getByRole("button", { name: "Delete article" }).click();
|
await page.getByRole("button", { name: "Delete article" }).click();
|
||||||
|
|
||||||
if (permissionLevel === 20) {
|
if (permissionLevel === 20) {
|
||||||
@@ -277,6 +311,9 @@ test.describe.serial("Collaborator tests", () => {
|
|||||||
await page.getByRole("button", { name: "Add collaborator" }).click();
|
await page.getByRole("button", { name: "Add collaborator" }).click();
|
||||||
await page.getByLabel("Username:").click();
|
await page.getByLabel("Username:").click();
|
||||||
await page.getByLabel("Username:").fill(collabUsername4);
|
await page.getByLabel("Username:").fill(collabUsername4);
|
||||||
|
await page
|
||||||
|
.locator('form[action="?/addCollaborator"] button[type="submit"]')
|
||||||
|
.evaluate((node) => node.removeAttribute("disabled"));
|
||||||
await page.getByRole("button", { name: "Submit" }).click();
|
await page.getByRole("button", { name: "Submit" }).click();
|
||||||
|
|
||||||
if ([10, 20].includes(permissionLevel)) {
|
if ([10, 20].includes(permissionLevel)) {
|
||||||
@@ -295,6 +332,10 @@ test.describe.serial("Collaborator tests", () => {
|
|||||||
.first()
|
.first()
|
||||||
.click();
|
.click();
|
||||||
await page.getByRole("combobox").selectOption("20");
|
await page.getByRole("combobox").selectOption("20");
|
||||||
|
const modalName = page.url().split("#")[1];
|
||||||
|
await page
|
||||||
|
.locator(`div[id="${modalName}"] button[type="submit"]`)
|
||||||
|
.evaluate((node) => node.removeAttribute("disabled"));
|
||||||
await page.getByRole("button", { name: "Update collaborator" }).click();
|
await page.getByRole("button", { name: "Update collaborator" }).click();
|
||||||
|
|
||||||
if ([10, 20].includes(permissionLevel)) {
|
if ([10, 20].includes(permissionLevel)) {
|
||||||
@@ -322,6 +363,10 @@ test.describe.serial("Collaborator tests", () => {
|
|||||||
.getByRole("button")
|
.getByRole("button")
|
||||||
.nth(1)
|
.nth(1)
|
||||||
.click();
|
.click();
|
||||||
|
const modalName = page.url().split("#")[1];
|
||||||
|
await page
|
||||||
|
.locator(`div[id="${modalName}"] button[type="submit"]`)
|
||||||
|
.evaluate((node) => node.removeAttribute("disabled"));
|
||||||
await page.getByRole("button", { name: "Remove collaborator" }).click();
|
await page.getByRole("button", { name: "Remove collaborator" }).click();
|
||||||
|
|
||||||
if ([10, 20].includes(permissionLevel)) {
|
if ([10, 20].includes(permissionLevel)) {
|
||||||
@@ -344,16 +389,9 @@ test.describe.serial("Collaborator tests", () => {
|
|||||||
await page.getByRole("link", { name: "Legal information" }).click();
|
await page.getByRole("link", { name: "Legal information" }).click();
|
||||||
await page.getByLabel("Main content:").click();
|
await page.getByLabel("Main content:").click();
|
||||||
await page.getByLabel("Main content:").fill("## Content");
|
await page.getByLabel("Main content:").fill("## Content");
|
||||||
await page.getByRole("button", { name: "Submit" }).click();
|
await page
|
||||||
|
.locator('form[action="?/createUpdateLegalInformation"] button[type="submit"]')
|
||||||
if (permissionLevel === 30) {
|
.evaluate((node) => node.removeAttribute("disabled"));
|
||||||
await expect(page.getByText("Successfully created/updated legal")).toBeVisible();
|
|
||||||
} else {
|
|
||||||
await expect(page.getByText("Insufficient permissions")).toBeVisible();
|
|
||||||
}
|
|
||||||
|
|
||||||
await page.getByLabel("Main content:").click();
|
|
||||||
await page.getByLabel("Main content:").fill("## Content updated");
|
|
||||||
await page.getByRole("button", { name: "Submit" }).click();
|
await page.getByRole("button", { name: "Submit" }).click();
|
||||||
|
|
||||||
if (permissionLevel === 30) {
|
if (permissionLevel === 30) {
|
||||||
@@ -370,6 +408,9 @@ test.describe.serial("Collaborator tests", () => {
|
|||||||
.click();
|
.click();
|
||||||
await page.getByRole("link", { name: "Legal information" }).click();
|
await page.getByRole("link", { name: "Legal information" }).click();
|
||||||
await page.getByRole("button", { name: "Delete" }).click();
|
await page.getByRole("button", { name: "Delete" }).click();
|
||||||
|
await page
|
||||||
|
.locator('form[action="?/deleteLegalInformation"] button[type="submit"]')
|
||||||
|
.evaluate((node) => node.removeAttribute("disabled"));
|
||||||
await page.getByRole("button", { name: "Delete legal information" }).click();
|
await page.getByRole("button", { name: "Delete legal information" }).click();
|
||||||
|
|
||||||
if (permissionLevel === 30) {
|
if (permissionLevel === 30) {
|
||||||
@@ -386,6 +427,9 @@ test.describe.serial("Collaborator tests", () => {
|
|||||||
await page.getByLabel("Name:").nth(0).fill(`Category-${permissionLevel}`);
|
await page.getByLabel("Name:").nth(0).fill(`Category-${permissionLevel}`);
|
||||||
await page.getByRole("spinbutton", { name: "Weight:" }).click();
|
await page.getByRole("spinbutton", { name: "Weight:" }).click();
|
||||||
await page.getByRole("spinbutton", { name: "Weight:" }).fill(permissionLevel.toString());
|
await page.getByRole("spinbutton", { name: "Weight:" }).fill(permissionLevel.toString());
|
||||||
|
await page
|
||||||
|
.locator('form[action="?/createCategory"] button[type="submit"]')
|
||||||
|
.evaluate((node) => node.removeAttribute("disabled"));
|
||||||
await page.getByRole("button", { name: "Submit" }).click();
|
await page.getByRole("button", { name: "Submit" }).click();
|
||||||
|
|
||||||
if (permissionLevel === 10) {
|
if (permissionLevel === 10) {
|
||||||
@@ -407,6 +451,10 @@ test.describe.serial("Collaborator tests", () => {
|
|||||||
await page
|
await page
|
||||||
.getByRole("spinbutton", { name: "Weight:" })
|
.getByRole("spinbutton", { name: "Weight:" })
|
||||||
.fill((permissionLevel * 2).toString());
|
.fill((permissionLevel * 2).toString());
|
||||||
|
const modalName = page.url().split("#")[1];
|
||||||
|
await page
|
||||||
|
.locator(`div[id="${modalName}"] button[type="submit"]`)
|
||||||
|
.evaluate((node) => node.removeAttribute("disabled"));
|
||||||
await page.getByRole("button", { name: "Update category" }).click();
|
await page.getByRole("button", { name: "Update category" }).click();
|
||||||
|
|
||||||
if (permissionLevel === 10) {
|
if (permissionLevel === 10) {
|
||||||
@@ -424,6 +472,10 @@ test.describe.serial("Collaborator tests", () => {
|
|||||||
.getByRole("button")
|
.getByRole("button")
|
||||||
.nth(1)
|
.nth(1)
|
||||||
.click();
|
.click();
|
||||||
|
const modalName = page.url().split("#")[1];
|
||||||
|
await page
|
||||||
|
.locator(`div[id="${modalName}"] button[type="submit"]`)
|
||||||
|
.evaluate((node) => node.removeAttribute("disabled"));
|
||||||
await page.getByRole("button", { name: "Delete category" }).click();
|
await page.getByRole("button", { name: "Delete category" }).click();
|
||||||
|
|
||||||
if (permissionLevel === 10) {
|
if (permissionLevel === 10) {
|
||||||
@@ -438,6 +490,10 @@ test.describe.serial("Collaborator tests", () => {
|
|||||||
.getByRole("button")
|
.getByRole("button")
|
||||||
.nth(1)
|
.nth(1)
|
||||||
.click();
|
.click();
|
||||||
|
const modalName = page.url().split("#")[1];
|
||||||
|
await page
|
||||||
|
.locator(`div[id="${modalName}"] button[type="submit"]`)
|
||||||
|
.evaluate((node) => node.removeAttribute("disabled"));
|
||||||
await page.getByRole("button", { name: "Delete category" }).click();
|
await page.getByRole("button", { name: "Delete category" }).click();
|
||||||
|
|
||||||
if (permissionLevel === 20) {
|
if (permissionLevel === 20) {
|
||||||
@@ -450,6 +506,9 @@ test.describe.serial("Collaborator tests", () => {
|
|||||||
test("Publish website", async ({ page }) => {
|
test("Publish website", async ({ page }) => {
|
||||||
await page.getByRole("link", { name: "Blog" }).click();
|
await page.getByRole("link", { name: "Blog" }).click();
|
||||||
await page.getByRole("link", { name: "Publish" }).click();
|
await page.getByRole("link", { name: "Publish" }).click();
|
||||||
|
await page
|
||||||
|
.locator('form[action="?/publishWebsite"] button[type="submit"]')
|
||||||
|
.evaluate((node) => node.removeAttribute("disabled"));
|
||||||
await page.getByRole("button", { name: "Publish" }).click();
|
await page.getByRole("button", { name: "Publish" }).click();
|
||||||
|
|
||||||
if ([10, 20].includes(permissionLevel)) {
|
if ([10, 20].includes(permissionLevel)) {
|
||||||
@@ -468,6 +527,9 @@ test.describe.serial("Collaborator tests", () => {
|
|||||||
await page.keyboard.press(`${modifier}+A`);
|
await page.keyboard.press(`${modifier}+A`);
|
||||||
await page.keyboard.press(`Backspace`);
|
await page.keyboard.press(`Backspace`);
|
||||||
await page.getByLabel("Prefix:").fill(customPrefix2);
|
await page.getByLabel("Prefix:").fill(customPrefix2);
|
||||||
|
await page
|
||||||
|
.locator('form[action="?/createUpdateCustomDomainPrefix"] button[type="submit"]')
|
||||||
|
.evaluate((node) => node.removeAttribute("disabled"));
|
||||||
await page.getByRole("button", { name: "Submit" }).click();
|
await page.getByRole("button", { name: "Submit" }).click();
|
||||||
|
|
||||||
if ([10, 20].includes(permissionLevel)) {
|
if ([10, 20].includes(permissionLevel)) {
|
||||||
@@ -480,6 +542,9 @@ test.describe.serial("Collaborator tests", () => {
|
|||||||
await page.getByRole("link", { name: "Blog" }).click();
|
await page.getByRole("link", { name: "Blog" }).click();
|
||||||
await page.getByRole("link", { name: "Publish" }).click();
|
await page.getByRole("link", { name: "Publish" }).click();
|
||||||
await page.getByRole("button", { name: "Delete" }).click();
|
await page.getByRole("button", { name: "Delete" }).click();
|
||||||
|
await page
|
||||||
|
.locator('form[action="?/deleteCustomDomainPrefix"] button[type="submit"]')
|
||||||
|
.evaluate((node) => node.removeAttribute("disabled"));
|
||||||
await page.getByRole("button", { name: "Delete domain prefix" }).click();
|
await page.getByRole("button", { name: "Delete domain prefix" }).click();
|
||||||
|
|
||||||
if ([10, 20].includes(permissionLevel)) {
|
if ([10, 20].includes(permissionLevel)) {
|
||||||
|
|||||||
Reference in New Issue
Block a user