Merge branch 'refactor/ui' into feat/storybook
This commit is contained in:
@@ -103,8 +103,8 @@
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
- Choose theme: System, Light, Dark (default) and Black
|
- Choose theme: System (default), Light, Dark and Black
|
||||||
- Choose accent color: Blue, Green (default), Teal, Indigo, Purple, Orange, Pink, Red, and Yellow
|
- Choose accent color: Green (default), Teal, Blue, Indigo, Purple, Yellow, Orange, Red and Pink
|
||||||
- Toggle auto-scroll to response
|
- Toggle auto-scroll to response
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
<svg width="2500" height="2432" viewBox="0 0 256 249" xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMinYMin meet"><g fill="#161614"><path d="M127.505 0C57.095 0 0 57.085 0 127.505c0 56.336 36.534 104.13 87.196 120.99 6.372 1.18 8.712-2.766 8.712-6.134 0-3.04-.119-13.085-.173-23.739-35.473 7.713-42.958-15.044-42.958-15.044-5.8-14.738-14.157-18.656-14.157-18.656-11.568-7.914.872-7.752.872-7.752 12.804.9 19.546 13.14 19.546 13.14 11.372 19.493 29.828 13.857 37.104 10.6 1.144-8.242 4.449-13.866 8.095-17.05-28.32-3.225-58.092-14.158-58.092-63.014 0-13.92 4.981-25.295 13.138-34.224-1.324-3.212-5.688-16.18 1.235-33.743 0 0 10.707-3.427 35.073 13.07 10.17-2.826 21.078-4.242 31.914-4.29 10.836.048 21.752 1.464 31.942 4.29 24.337-16.497 35.029-13.07 35.029-13.07 6.94 17.563 2.574 30.531 1.25 33.743 8.175 8.929 13.122 20.303 13.122 34.224 0 48.972-29.828 59.756-58.22 62.912 4.573 3.957 8.648 11.717 8.648 23.612 0 17.06-.148 30.791-.148 34.991 0 3.393 2.295 7.369 8.759 6.117 50.634-16.879 87.122-64.656 87.122-120.973C255.009 57.085 197.922 0 127.505 0"/><path d="M47.755 181.634c-.28.633-1.278.823-2.185.389-.925-.416-1.445-1.28-1.145-1.916.275-.652 1.273-.834 2.196-.396.927.415 1.455 1.287 1.134 1.923M54.027 187.23c-.608.564-1.797.302-2.604-.589-.834-.889-.99-2.077-.373-2.65.627-.563 1.78-.3 2.616.59.834.899.996 2.08.36 2.65M58.33 194.39c-.782.543-2.06.034-2.849-1.1-.781-1.133-.781-2.493.017-3.038.792-.545 2.05-.055 2.85 1.07.78 1.153.78 2.513-.019 3.069M65.606 202.683c-.699.77-2.187.564-3.277-.488-1.114-1.028-1.425-2.487-.724-3.258.707-.772 2.204-.555 3.302.488 1.107 1.026 1.445 2.496.7 3.258M75.01 205.483c-.307.998-1.741 1.452-3.185 1.028-1.442-.437-2.386-1.607-2.095-2.616.3-1.005 1.74-1.478 3.195-1.024 1.44.435 2.386 1.596 2.086 2.612M85.714 206.67c.036 1.052-1.189 1.924-2.705 1.943-1.525.033-2.758-.818-2.774-1.852 0-1.062 1.197-1.926 2.721-1.951 1.516-.03 2.758.815 2.758 1.86M96.228 206.267c.182 1.026-.872 2.08-2.377 2.36-1.48.27-2.85-.363-3.039-1.38-.184-1.052.89-2.105 2.367-2.378 1.508-.262 2.857.355 3.049 1.398"/></g></svg>
|
<svg width="2500" height="2432" viewBox="0 0 256 249" xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMinYMin meet"><g fill="currentColor"><path d="M127.505 0C57.095 0 0 57.085 0 127.505c0 56.336 36.534 104.13 87.196 120.99 6.372 1.18 8.712-2.766 8.712-6.134 0-3.04-.119-13.085-.173-23.739-35.473 7.713-42.958-15.044-42.958-15.044-5.8-14.738-14.157-18.656-14.157-18.656-11.568-7.914.872-7.752.872-7.752 12.804.9 19.546 13.14 19.546 13.14 11.372 19.493 29.828 13.857 37.104 10.6 1.144-8.242 4.449-13.866 8.095-17.05-28.32-3.225-58.092-14.158-58.092-63.014 0-13.92 4.981-25.295 13.138-34.224-1.324-3.212-5.688-16.18 1.235-33.743 0 0 10.707-3.427 35.073 13.07 10.17-2.826 21.078-4.242 31.914-4.29 10.836.048 21.752 1.464 31.942 4.29 24.337-16.497 35.029-13.07 35.029-13.07 6.94 17.563 2.574 30.531 1.25 33.743 8.175 8.929 13.122 20.303 13.122 34.224 0 48.972-29.828 59.756-58.22 62.912 4.573 3.957 8.648 11.717 8.648 23.612 0 17.06-.148 30.791-.148 34.991 0 3.393 2.295 7.369 8.759 6.117 50.634-16.879 87.122-64.656 87.122-120.973C255.009 57.085 197.922 0 127.505 0"/><path d="M47.755 181.634c-.28.633-1.278.823-2.185.389-.925-.416-1.445-1.28-1.145-1.916.275-.652 1.273-.834 2.196-.396.927.415 1.455 1.287 1.134 1.923M54.027 187.23c-.608.564-1.797.302-2.604-.589-.834-.889-.99-2.077-.373-2.65.627-.563 1.78-.3 2.616.59.834.899.996 2.08.36 2.65M58.33 194.39c-.782.543-2.06.034-2.849-1.1-.781-1.133-.781-2.493.017-3.038.792-.545 2.05-.055 2.85 1.07.78 1.153.78 2.513-.019 3.069M65.606 202.683c-.699.77-2.187.564-3.277-.488-1.114-1.028-1.425-2.487-.724-3.258.707-.772 2.204-.555 3.302.488 1.107 1.026 1.445 2.496.7 3.258M75.01 205.483c-.307.998-1.741 1.452-3.185 1.028-1.442-.437-2.386-1.607-2.095-2.616.3-1.005 1.74-1.478 3.195-1.024 1.44.435 2.386 1.596 2.086 2.612M85.714 206.67c.036 1.052-1.189 1.924-2.705 1.943-1.525.033-2.758-.818-2.774-1.852 0-1.062 1.197-1.926 2.721-1.951 1.516-.03 2.758.815 2.758 1.86M96.228 206.267c.182 1.026-.872 2.08-2.377 2.36-1.48.27-2.85-.363-3.039-1.38-.184-1.052.89-2.105 2.367-2.378 1.508-.262 2.857.355 3.049 1.398"/></g></svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 2.0 KiB |
@@ -1 +1 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path d="M118.2 208.3c19.9-60.3 76.5-103.6 143.7-103.6 36.1 0 68.6 12.8 94.3 33.7L430.5 64C385.2 24.4 327 0 261.8 0 160.9 0 74 57.6 32.3 141.9l85.9 66.4z" fill="#ea4335"/><path d="M348 384.3c-23.3 15-52.8 23-86.2 23-66.9 0-123.3-43-143.4-102.9l-86.2 65.4C73.9 454.3 160.8 512 261.8 512c62.6 0 122.4-22.2 167.1-64L348 384.3z" fill="#34a853"/><path d="M428.9 448c46.8-43.7 77.2-108.7 77.2-192 0-15.1-2.3-31.4-5.8-46.5H261.8v98.9h137.3c-6.8 33.3-25 59-51.1 75.9l80.9 63.7z" fill="#4a90e2"/><path d="M118.4 304.4c-5.1-15.2-7.9-31.4-7.9-48.4 0-16.7 2.7-32.7 7.6-47.7l-85.9-66.4C15.1 176.2 5.8 214.9 5.8 256c0 40.9 9.5 79.6 26.4 113.8l86.2-65.4z" fill="#fbbc05"/></svg>
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path d="M118.2 208.3c19.9-60.3 76.5-103.6 143.7-103.6 36.1 0 68.6 12.8 94.3 33.7L430.5 64C385.2 24.4 327 0 261.8 0 160.9 0 74 57.6 32.3 141.9l85.9 66.4z" fill="currentColor"/><path d="M348 384.3c-23.3 15-52.8 23-86.2 23-66.9 0-123.3-43-143.4-102.9l-86.2 65.4C73.9 454.3 160.8 512 261.8 512c62.6 0 122.4-22.2 167.1-64L348 384.3z" fill="currentColor"/><path d="M428.9 448c46.8-43.7 77.2-108.7 77.2-192 0-15.1-2.3-31.4-5.8-46.5H261.8v98.9h137.3c-6.8 33.3-25 59-51.1 75.9l80.9 63.7z" fill="currentColor"/><path d="M118.4 304.4c-5.1-15.2-7.9-31.4-7.9-48.4 0-16.7 2.7-32.7 7.6-47.7l-85.9-66.4C15.1 176.2 5.8 214.9 5.8 256c0 40.9 9.5 79.6 26.4 113.8l86.2-65.4z" fill="currentColor"/></svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 726 B After Width: | Height: | Size: 746 B |
1
assets/icons/graphql.svg
Normal file
1
assets/icons/graphql.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" height="64" width="64" viewBox="0 0 29.999 30" fill="currentColor"><path d="M4.08 22.864l-1.1-.636L15.248.98l1.1.636z"/><path d="M2.727 20.53h24.538v1.272H2.727z"/><path d="M15.486 28.332L3.213 21.246l.636-1.1 12.273 7.086zm10.662-18.47L13.874 2.777l.636-1.1 12.273 7.086z"/><path d="M3.852 9.858l-.636-1.1L15.5 1.67l.636 1.1z"/><path d="M25.922 22.864l-12.27-21.25 1.1-.636 12.27 21.25zM3.7 7.914h1.272v14.172H3.7zm21.328 0H26.3v14.172h-1.272z"/><path d="M15.27 27.793l-.555-.962 10.675-6.163.555.962z"/><path d="M27.985 22.5a2.68 2.68 0 01-3.654.981 2.68 2.68 0 01-.981-3.654 2.68 2.68 0 013.654-.981 2.665 2.665 0 01.98 3.654M6.642 10.174a2.68 2.68 0 01-3.654.981A2.68 2.68 0 012.007 7.5a2.68 2.68 0 013.654-.981 2.68 2.68 0 01.981 3.654M2.015 22.5a2.68 2.68 0 01.981-3.654 2.68 2.68 0 013.654.981 2.68 2.68 0 01-.981 3.654c-1.287.735-2.92.3-3.654-.98m21.343-12.326a2.68 2.68 0 01.981-3.654 2.68 2.68 0 013.654.981 2.68 2.68 0 01-.981 3.654 2.68 2.68 0 01-3.654-.981M15 30a2.674 2.674 0 112.674-2.673A2.68 2.68 0 0115 30m0-24.652a2.67 2.67 0 01-2.674-2.674 2.67 2.67 0 115.347 0A2.67 2.67 0 0115 5.347"/></svg>
|
||||||
|
After Width: | Height: | Size: 1.1 KiB |
@@ -15,17 +15,10 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
::-webkit-scrollbar-thumb {
|
::-webkit-scrollbar-thumb {
|
||||||
@apply bg-divider;
|
@apply bg-divider bg-clip-content;
|
||||||
@apply rounded-full;
|
@apply rounded-full;
|
||||||
@apply border-solid;
|
@apply border-solid border-4 border-transparent;
|
||||||
@apply border-4;
|
@apply hover:(bg-dividerDark bg-clip-content);
|
||||||
@apply border-transparent;
|
|
||||||
@apply bg-clip-content;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
@apply bg-dividerDark;
|
|
||||||
@apply bg-clip-content;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
::-webkit-scrollbar {
|
::-webkit-scrollbar {
|
||||||
@@ -42,23 +35,18 @@
|
|||||||
@apply text-primary;
|
@apply text-primary;
|
||||||
}
|
}
|
||||||
|
|
||||||
::placeholder {
|
|
||||||
@apply text-secondaryLight;
|
|
||||||
@apply opacity-25;
|
|
||||||
}
|
|
||||||
|
|
||||||
html {
|
html {
|
||||||
scroll-behavior: smooth;
|
scroll-behavior: smooth;
|
||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
@apply bg-primary;
|
@apply bg-primary;
|
||||||
@apply text-secondary;
|
@apply text-secondary text-xs;
|
||||||
@apply !text-sm;
|
|
||||||
@apply font-medium;
|
@apply font-medium;
|
||||||
@apply select-none;
|
@apply select-none;
|
||||||
@apply overflow-x-hidden;
|
@apply overflow-x-hidden;
|
||||||
|
|
||||||
|
overflow: overlay;
|
||||||
-webkit-tap-highlight-color: transparent;
|
-webkit-tap-highlight-color: transparent;
|
||||||
-webkit-touch-callout: none;
|
-webkit-touch-callout: none;
|
||||||
}
|
}
|
||||||
@@ -73,7 +61,8 @@ body {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.fade-enter,
|
.fade-enter,
|
||||||
.fade-leave-to .page-enter,
|
.fade-leave-to,
|
||||||
|
.page-enter,
|
||||||
.page-leave-to,
|
.page-leave-to,
|
||||||
.layout-enter,
|
.layout-enter,
|
||||||
.layout-leave-to {
|
.layout-leave-to {
|
||||||
@@ -81,14 +70,14 @@ body {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.material-icons {
|
.material-icons {
|
||||||
font-size: 1.25rem !important;
|
font-size: 1rem !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.svg-icons {
|
.svg-icons {
|
||||||
@apply inline-flex;
|
@apply inline-flex;
|
||||||
@apply flex-shrink-0;
|
@apply flex-shrink-0;
|
||||||
@apply h-5;
|
@apply h-4;
|
||||||
@apply w-5;
|
@apply w-4;
|
||||||
}
|
}
|
||||||
|
|
||||||
a {
|
a {
|
||||||
@@ -96,27 +85,36 @@ a {
|
|||||||
@apply text-current;
|
@apply text-current;
|
||||||
@apply no-underline;
|
@apply no-underline;
|
||||||
@apply outline-none;
|
@apply outline-none;
|
||||||
@apply focus-visible:ring;
|
@apply transition;
|
||||||
@apply focus-visible:ring-inset;
|
|
||||||
@apply focus-visible:ring-accent;
|
|
||||||
|
|
||||||
&.link {
|
&.link {
|
||||||
@apply items-center;
|
@apply items-center;
|
||||||
|
@apply px-2 py-1;
|
||||||
|
@apply -mx-2 -my-1;
|
||||||
@apply text-accent;
|
@apply text-accent;
|
||||||
@apply hover:text-accent;
|
@apply hover:text-accentDark;
|
||||||
@apply focus:text-accent;
|
@apply focus-visible:(ring ring-inset ring-accent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.tippy-popper {
|
.tippy-popper {
|
||||||
.tooltip-theme {
|
.tooltip-theme {
|
||||||
@apply bg-secondary;
|
@apply bg-tooltip;
|
||||||
@apply text-primaryLight;
|
@apply text-primary text-xs;
|
||||||
@apply text-xs;
|
|
||||||
@apply font-semibold;
|
@apply font-semibold;
|
||||||
@apply px-2;
|
@apply py-1 px-2;
|
||||||
@apply px-4;
|
|
||||||
@apply shadow;
|
@apply shadow;
|
||||||
|
|
||||||
|
kbd {
|
||||||
|
@apply first:ml-2;
|
||||||
|
@apply last:-mr-1;
|
||||||
|
@apply font-sans;
|
||||||
|
@apply bg-secondaryDark;
|
||||||
|
@apply text-primaryDark;
|
||||||
|
@apply rounded;
|
||||||
|
@apply px-1;
|
||||||
|
@apply ml-1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.popover-theme {
|
.popover-theme {
|
||||||
@@ -124,59 +122,61 @@ a {
|
|||||||
@apply text-secondary;
|
@apply text-secondary;
|
||||||
@apply p-2;
|
@apply p-2;
|
||||||
@apply shadow-lg;
|
@apply shadow-lg;
|
||||||
|
@apply focus:outline-none;
|
||||||
}
|
}
|
||||||
|
|
||||||
&[x-placement^="top"] .tippy-tooltip .tippy-arrow {
|
&[x-placement^="top"] .tippy-tooltip .tippy-arrow {
|
||||||
border-top-color: var(--primary-color);
|
@apply border-t-primary;
|
||||||
}
|
}
|
||||||
|
|
||||||
&[x-placement^="bottom"] .tippy-tooltip .tippy-arrow {
|
&[x-placement^="bottom"] .tippy-tooltip .tippy-arrow {
|
||||||
border-bottom-color: var(--primary-color);
|
@apply border-b-primary;
|
||||||
}
|
}
|
||||||
|
|
||||||
&[x-placement^="left"] .tippy-tooltip .tippy-arrow {
|
&[x-placement^="left"] .tippy-tooltip .tippy-arrow {
|
||||||
border-left-color: var(--primary-color);
|
@apply border-l-primary;
|
||||||
}
|
}
|
||||||
|
|
||||||
&[x-placement^="right"] .tippy-tooltip .tippy-arrow {
|
&[x-placement^="right"] .tippy-tooltip .tippy-arrow {
|
||||||
border-right-color: var(--primary-color);
|
@apply border-r-primary;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.tippy-content > div {
|
.tippy-content > div {
|
||||||
@apply flex;
|
@apply flex flex-col;
|
||||||
@apply flex-col;
|
@apply max-h-48;
|
||||||
@apply max-h-64;
|
|
||||||
@apply overflow-y-auto;
|
|
||||||
@apply items-stretch;
|
@apply items-stretch;
|
||||||
|
@apply overflow-y-auto;
|
||||||
|
|
||||||
|
&::-webkit-scrollbar {
|
||||||
|
@apply hidden;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
hr {
|
hr {
|
||||||
@apply border-b;
|
@apply border-b border-dividerLight;
|
||||||
@apply border-dividerLight;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.heading {
|
.heading {
|
||||||
@apply font-bold;
|
@apply font-bold;
|
||||||
@apply text-secondaryDark;
|
@apply text-secondaryDark text-lg;
|
||||||
@apply text-lg;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.textarea,
|
||||||
.input,
|
.input,
|
||||||
.select {
|
.select {
|
||||||
@apply flex;
|
@apply flex flex-1;
|
||||||
@apply w-full;
|
@apply w-full;
|
||||||
@apply px-4;
|
@apply px-4 py-2;
|
||||||
@apply py-2;
|
|
||||||
@apply bg-primary;
|
@apply bg-primary;
|
||||||
@apply truncate;
|
@apply truncate;
|
||||||
@apply rounded-lg;
|
@apply rounded;
|
||||||
|
@apply text-xs;
|
||||||
@apply font-semibold;
|
@apply font-semibold;
|
||||||
@apply border-2;
|
@apply border border-divider;
|
||||||
@apply border-divider;
|
|
||||||
@apply transition;
|
@apply transition;
|
||||||
@apply focus:outline-none;
|
@apply focus:(outline-none border-accent);
|
||||||
@apply focus:border-accent;
|
@apply disabled:cursor-not-allowed;
|
||||||
}
|
}
|
||||||
|
|
||||||
.input[type="file"],
|
.input[type="file"],
|
||||||
@@ -187,12 +187,11 @@ hr {
|
|||||||
|
|
||||||
pre.ace_editor {
|
pre.ace_editor {
|
||||||
@apply font-mono;
|
@apply font-mono;
|
||||||
@apply z-0;
|
|
||||||
@apply resize-none;
|
@apply resize-none;
|
||||||
|
@apply z-0;
|
||||||
}
|
}
|
||||||
|
|
||||||
select {
|
.select {
|
||||||
@apply cursor-pointer;
|
|
||||||
@apply appearance-none;
|
@apply appearance-none;
|
||||||
|
|
||||||
&::-ms-expand {
|
&::-ms-expand {
|
||||||
@@ -203,20 +202,38 @@ select {
|
|||||||
.select-wrapper {
|
.select-wrapper {
|
||||||
@apply relative;
|
@apply relative;
|
||||||
@apply w-full;
|
@apply w-full;
|
||||||
|
@apply cursor-pointer;
|
||||||
|
|
||||||
&::after {
|
&::after {
|
||||||
@apply inline-block;
|
|
||||||
@apply absolute;
|
@apply absolute;
|
||||||
|
@apply inline-block;
|
||||||
@apply pointer-events-none;
|
@apply pointer-events-none;
|
||||||
@apply font-icon;
|
@apply font-icon;
|
||||||
@apply text-secondaryLight;
|
@apply text-secondaryLight;
|
||||||
@apply top-3;
|
@apply top-2.5;
|
||||||
@apply right-3;
|
@apply right-3;
|
||||||
|
|
||||||
content: "\e313";
|
content: "\e313";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.search-wrapper {
|
||||||
|
@apply relative;
|
||||||
|
@apply w-full;
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
@apply absolute;
|
||||||
|
@apply inline-block;
|
||||||
|
@apply pointer-events-none;
|
||||||
|
@apply font-icon;
|
||||||
|
@apply text-secondaryLight;
|
||||||
|
@apply top-2;
|
||||||
|
@apply left-3;
|
||||||
|
|
||||||
|
content: "\e8b6";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
input[type="checkbox"] {
|
input[type="checkbox"] {
|
||||||
@apply hidden;
|
@apply hidden;
|
||||||
|
|
||||||
@@ -226,9 +243,8 @@ input[type="checkbox"] {
|
|||||||
@apply cursor-pointer;
|
@apply cursor-pointer;
|
||||||
|
|
||||||
&::before {
|
&::before {
|
||||||
@apply border;
|
@apply border border-secondary;
|
||||||
@apply border-secondary;
|
@apply rounded;
|
||||||
@apply rounded-lg;
|
|
||||||
@apply inline-flex;
|
@apply inline-flex;
|
||||||
@apply items-center;
|
@apply items-center;
|
||||||
@apply justify-center;
|
@apply justify-center;
|
||||||
@@ -249,19 +265,19 @@ input[type="checkbox"] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.info-response {
|
.info-response {
|
||||||
@apply text-pink-400;
|
@apply text-pink-500;
|
||||||
}
|
}
|
||||||
|
|
||||||
.success-response {
|
.success-response {
|
||||||
@apply text-green-400;
|
@apply text-green-500;
|
||||||
}
|
}
|
||||||
|
|
||||||
.redir-response {
|
.redir-response {
|
||||||
@apply text-yellow-400;
|
@apply text-yellow-500;
|
||||||
}
|
}
|
||||||
|
|
||||||
.cl-error-response {
|
.cl-error-response {
|
||||||
@apply text-red-400;
|
@apply text-red-500;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sv-error-response {
|
.sv-error-response {
|
||||||
@@ -278,8 +294,6 @@ input[type="checkbox"] {
|
|||||||
textarea {
|
textarea {
|
||||||
@apply m-0;
|
@apply m-0;
|
||||||
@apply w-full;
|
@apply w-full;
|
||||||
|
|
||||||
line-height: 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.covers-response {
|
.covers-response {
|
||||||
@@ -292,37 +306,41 @@ input[type="checkbox"] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.toasted-container {
|
.toasted-container {
|
||||||
margin-bottom: 68px;
|
|
||||||
|
|
||||||
.toasted {
|
.toasted {
|
||||||
justify-content: space-between !important;
|
&.toasted-primary {
|
||||||
|
@apply bg-tooltip;
|
||||||
&.info {
|
@apply text-primary text-xs;
|
||||||
background-color: var(--accent-color) !important;
|
@apply justify-start;
|
||||||
color: var(--primary-color) !important;
|
@apply shadow;
|
||||||
font-weight: 700 !important;
|
@apply font-semibold;
|
||||||
}
|
|
||||||
|
|
||||||
&.bubble .action {
|
|
||||||
color: inherit !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.action {
|
.action {
|
||||||
margin-left: auto !important;
|
@apply ml-auto;
|
||||||
|
@apply transition;
|
||||||
|
@apply text-current;
|
||||||
|
@apply hover:(opacity-75 no-underline);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width: 767px) {
|
&.info {
|
||||||
main {
|
@apply !bg-accent;
|
||||||
margin-bottom: env(safe-area-inset-bottom);
|
}
|
||||||
|
|
||||||
|
&.error {
|
||||||
|
@apply !bg-red-200;
|
||||||
|
@apply !text-red-800;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.success {
|
||||||
|
@apply !bg-green-200;
|
||||||
|
@apply !text-green-800;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.splitpanes__splitter {
|
.splitpanes__splitter {
|
||||||
@apply relative;
|
@apply relative;
|
||||||
@apply bg-primaryLight;
|
@apply bg-primaryLight;
|
||||||
@apply transition;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.splitpanes--vertical > .splitpanes__splitter {
|
.splitpanes--vertical > .splitpanes__splitter {
|
||||||
@@ -338,7 +356,7 @@ input[type="checkbox"] {
|
|||||||
@apply inset-0;
|
@apply inset-0;
|
||||||
@apply bg-dividerLight;
|
@apply bg-dividerLight;
|
||||||
@apply opacity-0;
|
@apply opacity-0;
|
||||||
@apply z-1;
|
@apply z-30;
|
||||||
@apply transition;
|
@apply transition;
|
||||||
|
|
||||||
content: "";
|
content: "";
|
||||||
@@ -347,7 +365,7 @@ input[type="checkbox"] {
|
|||||||
.splitpanes__splitter::after {
|
.splitpanes__splitter::after {
|
||||||
@apply absolute;
|
@apply absolute;
|
||||||
@apply inset-0;
|
@apply inset-0;
|
||||||
@apply z-1;
|
@apply z-30;
|
||||||
@apply transition;
|
@apply transition;
|
||||||
@apply flex;
|
@apply flex;
|
||||||
@apply items-center;
|
@apply items-center;
|
||||||
@@ -379,3 +397,9 @@ input[type="checkbox"] {
|
|||||||
bottom: -2px;
|
bottom: -2px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media (max-width: 767px) {
|
||||||
|
main {
|
||||||
|
margin-bottom: env(safe-area-inset-bottom);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
@mixin baseTheme {
|
@mixin baseTheme {
|
||||||
--font-sans: "Montserrat", "sans-serif";
|
--font-sans: "Inter", "sans-serif";
|
||||||
--font-mono: "Roboto Mono", "monospace";
|
--font-mono: "Roboto Mono", "monospace";
|
||||||
--font-icon: "Material Icons";
|
--font-icon: "Material Icons";
|
||||||
}
|
}
|
||||||
@@ -8,25 +8,25 @@
|
|||||||
// Background color
|
// Background color
|
||||||
--primary-color: theme("colors.true-gray.900");
|
--primary-color: theme("colors.true-gray.900");
|
||||||
// Light Background color
|
// Light Background color
|
||||||
--primary-light-color: theme("colors.true-gray.800");
|
--primary-light-color: theme("colors.dark.600");
|
||||||
// Dark Background color
|
// Dark Background color
|
||||||
--primary-dark-color: theme("colors.dark.900");
|
--primary-dark-color: theme("colors.dark.900");
|
||||||
// Text color
|
// Text color
|
||||||
--secondary-color: theme("colors.true-gray.400");
|
--secondary-color: theme("colors.true-gray.400");
|
||||||
// Light Text color
|
// Light Text color
|
||||||
--secondary-light-color: theme("colors.true-gray.200");
|
--secondary-light-color: theme("colors.true-gray.500");
|
||||||
// Dark Text color
|
// Dark Text color
|
||||||
--secondary-dark-color: theme("colors.white");
|
--secondary-dark-color: theme("colors.true-gray.100");
|
||||||
// Border color
|
// Border color
|
||||||
--divider-color: theme("colors.true-gray.700");
|
--divider-color: theme("colors.true-gray.800");
|
||||||
// Light Border color
|
// Light Border color
|
||||||
--divider-light-color: theme("colors.true-gray.800");
|
--divider-light-color: theme("colors.dark.500");
|
||||||
// Dark Border color
|
// Dark Border color
|
||||||
--divider-dark-color: theme("colors.true-gray.600");
|
--divider-dark-color: theme("colors.dark.300");
|
||||||
// Error color
|
// Error color
|
||||||
--error-color: theme("colors.true-gray.600");
|
--error-color: theme("colors.dark.800");
|
||||||
// Tooltip color
|
// Tooltip color
|
||||||
--tooltip-color: theme("colors.true-gray.800");
|
--tooltip-color: theme("colors.true-gray.100");
|
||||||
// Editor theme
|
// Editor theme
|
||||||
--editor-theme: "merbivore_soft";
|
--editor-theme: "merbivore_soft";
|
||||||
}
|
}
|
||||||
@@ -35,25 +35,25 @@
|
|||||||
// Background color
|
// Background color
|
||||||
--primary-color: theme("colors.white");
|
--primary-color: theme("colors.white");
|
||||||
// Light Background color
|
// Light Background color
|
||||||
--primary-light-color: theme("colors.true-gray.50");
|
--primary-light-color: theme("colors.blue-gray.50");
|
||||||
// Dark Background color
|
// Dark Background color
|
||||||
--primary-dark-color: theme("colors.true-gray.100");
|
--primary-dark-color: theme("colors.blue-gray.100");
|
||||||
// Text color
|
// Text color
|
||||||
--secondary-color: theme("colors.true-gray.500");
|
--secondary-color: theme("colors.blue-gray.600");
|
||||||
// Light Text color
|
// Light Text color
|
||||||
--secondary-light-color: theme("colors.true-gray.400");
|
--secondary-light-color: theme("colors.blue-gray.500");
|
||||||
// Dark Text color
|
// Dark Text color
|
||||||
--secondary-dark-color: theme("colors.true-gray.600");
|
--secondary-dark-color: theme("colors.blue-gray.700");
|
||||||
// Border color
|
// Border color
|
||||||
--divider-color: theme("colors.true-gray.200");
|
--divider-color: theme("colors.blue-gray.200");
|
||||||
// Light Border color
|
// Light Border color
|
||||||
--divider-light-color: theme("colors.true-gray.100");
|
--divider-light-color: theme("colors.blue-gray.100");
|
||||||
// Dark Border color
|
// Dark Border color
|
||||||
--divider-dark-color: theme("colors.true-gray.300");
|
--divider-dark-color: theme("colors.blue-gray.300");
|
||||||
// Error color
|
// Error color
|
||||||
--error-color: theme("colors.true-gray.700");
|
--error-color: theme("colors.blue-gray.700");
|
||||||
// Tooltip color
|
// Tooltip color
|
||||||
--tooltip-color: theme("colors.true-gray.50");
|
--tooltip-color: theme("colors.blue-gray.800");
|
||||||
// Editor theme
|
// Editor theme
|
||||||
--editor-theme: "textmate";
|
--editor-theme: "textmate";
|
||||||
}
|
}
|
||||||
@@ -62,51 +62,36 @@
|
|||||||
// Background color
|
// Background color
|
||||||
--primary-color: theme("colors.dark.900");
|
--primary-color: theme("colors.dark.900");
|
||||||
// Light Background color
|
// Light Background color
|
||||||
--primary-light-color: theme("colors.dark.700");
|
--primary-light-color: theme("colors.true-gray.900");
|
||||||
// Dark Background color
|
// Dark Background color
|
||||||
--primary-dark-color: theme("colors.dark.800");
|
--primary-dark-color: theme("colors.dark.800");
|
||||||
// Text color
|
// Text color
|
||||||
--secondary-color: theme("colors.true-gray.400");
|
--secondary-color: theme("colors.true-gray.400");
|
||||||
// Light Text color
|
// Light Text color
|
||||||
--secondary-light-color: theme("colors.true-gray.600");
|
--secondary-light-color: theme("colors.true-gray.500");
|
||||||
// Dark Text color
|
// Dark Text color
|
||||||
--secondary-dark-color: theme("colors.true-gray.100");
|
--secondary-dark-color: theme("colors.true-gray.100");
|
||||||
// Border color
|
// Border color
|
||||||
--divider-color: theme("colors.dark.800");
|
--divider-color: theme("colors.true-gray.800");
|
||||||
// Light Border color
|
// Light Border color
|
||||||
--divider-light-color: theme("colors.dark.700");
|
--divider-light-color: theme("colors.dark.700");
|
||||||
// Dark Border color
|
// Dark Border color
|
||||||
--divider-dark-color: theme("colors.dark.600");
|
--divider-dark-color: theme("colors.dark.300");
|
||||||
// Error color
|
// Error color
|
||||||
--error-color: theme("colors.dark.800");
|
--error-color: theme("colors.dark.800");
|
||||||
// Tooltip color
|
// Tooltip color
|
||||||
--tooltip-color: theme("colors.dark.500");
|
--tooltip-color: theme("colors.true-gray.100");
|
||||||
// Editor theme
|
// Editor theme
|
||||||
--editor-theme: "vibrant_ink";
|
--editor-theme: "twilight";
|
||||||
}
|
|
||||||
|
|
||||||
@mixin blueTheme {
|
|
||||||
// Accent color
|
|
||||||
--accent-color: theme("colors.blue.400");
|
|
||||||
// Light Accent color
|
|
||||||
--accent-light-color: theme("colors.blue.200");
|
|
||||||
// Dark Accent color
|
|
||||||
--accent-dark-color: theme("colors.blue.600");
|
|
||||||
// Gradient from
|
|
||||||
--gradient-from-color: theme("colors.blue.200");
|
|
||||||
// Gradient via
|
|
||||||
--gradient-via-color: theme("colors.blue.400");
|
|
||||||
// Gradient to
|
|
||||||
--gradient-to-color: theme("colors.blue.600");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@mixin greenTheme {
|
@mixin greenTheme {
|
||||||
// Accent color
|
// Accent color
|
||||||
--accent-color: rgb(97, 207, 123);
|
--accent-color: theme("colors.green.500");
|
||||||
// Light Accent color
|
// Light Accent color
|
||||||
--accent-light-color: rgba(73, 204, 104, 1);
|
--accent-light-color: theme("colors.green.400");
|
||||||
// Dark Accent color
|
// Dark Accent color
|
||||||
--accent-dark-color: rgb(0, 71, 17);
|
--accent-dark-color: theme("colors.green.600");
|
||||||
// Gradient from
|
// Gradient from
|
||||||
--gradient-from-color: theme("colors.green.200");
|
--gradient-from-color: theme("colors.green.200");
|
||||||
// Gradient via
|
// Gradient via
|
||||||
@@ -117,12 +102,27 @@
|
|||||||
|
|
||||||
@mixin tealTheme {
|
@mixin tealTheme {
|
||||||
// Accent color
|
// Accent color
|
||||||
--accent-color: theme("colors.teal.400");
|
--accent-color: theme("colors.teal.500");
|
||||||
// Light Accent color
|
// Light Accent color
|
||||||
--accent-light-color: theme("colors.teal.200");
|
--accent-light-color: theme("colors.teal.400");
|
||||||
// Dark Accent color
|
// Dark Accent color
|
||||||
--accent-dark-color: theme("colors.teal.600");
|
--accent-dark-color: theme("colors.teal.600");
|
||||||
// Gradient from
|
// Gradient from
|
||||||
|
--gradient-from-color: theme("colors.teal.200");
|
||||||
|
// Gradient via
|
||||||
|
--gradient-via-color: theme("colors.teal.400");
|
||||||
|
// Gradient to
|
||||||
|
--gradient-to-color: theme("colors.teal.600");
|
||||||
|
}
|
||||||
|
|
||||||
|
@mixin blueTheme {
|
||||||
|
// Accent color
|
||||||
|
--accent-color: theme("colors.blue.500");
|
||||||
|
// Light Accent color
|
||||||
|
--accent-light-color: theme("colors.blue.400");
|
||||||
|
// Dark Accent color
|
||||||
|
--accent-dark-color: theme("colors.blue.600");
|
||||||
|
// Gradient from
|
||||||
--gradient-from-color: theme("colors.blue.200");
|
--gradient-from-color: theme("colors.blue.200");
|
||||||
// Gradient via
|
// Gradient via
|
||||||
--gradient-via-color: theme("colors.blue.400");
|
--gradient-via-color: theme("colors.blue.400");
|
||||||
@@ -132,92 +132,92 @@
|
|||||||
|
|
||||||
@mixin indigoTheme {
|
@mixin indigoTheme {
|
||||||
// Accent color
|
// Accent color
|
||||||
--accent-color: theme("colors.indigo.400");
|
--accent-color: theme("colors.indigo.500");
|
||||||
// Light Accent color
|
// Light Accent color
|
||||||
--accent-light-color: theme("colors.indigo.200");
|
--accent-light-color: theme("colors.indigo.400");
|
||||||
// Dark Accent color
|
// Dark Accent color
|
||||||
--accent-dark-color: theme("colors.indigo.600");
|
--accent-dark-color: theme("colors.indigo.600");
|
||||||
// Gradient from
|
// Gradient from
|
||||||
--gradient-from-color: theme("colors.blue.200");
|
--gradient-from-color: theme("colors.indigo.200");
|
||||||
// Gradient via
|
// Gradient via
|
||||||
--gradient-via-color: theme("colors.blue.400");
|
--gradient-via-color: theme("colors.indigo.400");
|
||||||
// Gradient to
|
// Gradient to
|
||||||
--gradient-to-color: theme("colors.blue.600");
|
--gradient-to-color: theme("colors.indigo.600");
|
||||||
}
|
}
|
||||||
|
|
||||||
@mixin purpleTheme {
|
@mixin purpleTheme {
|
||||||
// Accent color
|
// Accent color
|
||||||
--accent-color: theme("colors.purple.400");
|
--accent-color: theme("colors.purple.500");
|
||||||
// Light Accent color
|
// Light Accent color
|
||||||
--accent-light-color: theme("colors.purple.200");
|
--accent-light-color: theme("colors.purple.400");
|
||||||
// Dark Accent color
|
// Dark Accent color
|
||||||
--accent-dark-color: theme("colors.purple.600");
|
--accent-dark-color: theme("colors.purple.600");
|
||||||
// Gradient from
|
// Gradient from
|
||||||
--gradient-from-color: theme("colors.blue.200");
|
--gradient-from-color: theme("colors.purple.200");
|
||||||
// Gradient via
|
// Gradient via
|
||||||
--gradient-via-color: theme("colors.blue.400");
|
--gradient-via-color: theme("colors.purple.400");
|
||||||
// Gradient to
|
// Gradient to
|
||||||
--gradient-to-color: theme("colors.blue.600");
|
--gradient-to-color: theme("colors.purple.600");
|
||||||
}
|
|
||||||
|
|
||||||
@mixin orangeTheme {
|
|
||||||
// Accent color
|
|
||||||
--accent-color: theme("colors.orange.400");
|
|
||||||
// Light Accent color
|
|
||||||
--accent-light-color: theme("colors.orange.200");
|
|
||||||
// Dark Accent color
|
|
||||||
--accent-dark-color: theme("colors.orange.600");
|
|
||||||
// Gradient from
|
|
||||||
--gradient-from-color: theme("colors.blue.200");
|
|
||||||
// Gradient via
|
|
||||||
--gradient-via-color: theme("colors.blue.400");
|
|
||||||
// Gradient to
|
|
||||||
--gradient-to-color: theme("colors.blue.600");
|
|
||||||
}
|
|
||||||
|
|
||||||
@mixin pinkTheme {
|
|
||||||
// Accent color
|
|
||||||
--accent-color: theme("colors.pink.400");
|
|
||||||
// Light Accent color
|
|
||||||
--accent-light-color: theme("colors.pink.200");
|
|
||||||
// Dark Accent color
|
|
||||||
--accent-dark-color: theme("colors.pink.600");
|
|
||||||
// Gradient from
|
|
||||||
--gradient-from-color: theme("colors.blue.200");
|
|
||||||
// Gradient via
|
|
||||||
--gradient-via-color: theme("colors.blue.400");
|
|
||||||
// Gradient to
|
|
||||||
--gradient-to-color: theme("colors.blue.600");
|
|
||||||
}
|
|
||||||
|
|
||||||
@mixin redTheme {
|
|
||||||
// Accent color
|
|
||||||
--accent-color: theme("colors.red.400");
|
|
||||||
// Light Accent color
|
|
||||||
--accent-light-color: theme("colors.red.200");
|
|
||||||
// Dark Accent color
|
|
||||||
--accent-dark-color: theme("colors.red.600");
|
|
||||||
// Gradient from
|
|
||||||
--gradient-from-color: theme("colors.blue.200");
|
|
||||||
// Gradient via
|
|
||||||
--gradient-via-color: theme("colors.blue.400");
|
|
||||||
// Gradient to
|
|
||||||
--gradient-to-color: theme("colors.blue.600");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@mixin yellowTheme {
|
@mixin yellowTheme {
|
||||||
// Accent color
|
// Accent color
|
||||||
--accent-color: theme("colors.yellow.400");
|
--accent-color: theme("colors.yellow.500");
|
||||||
// Light Accent color
|
// Light Accent color
|
||||||
--accent-light-color: theme("colors.yellow.200");
|
--accent-light-color: theme("colors.yellow.400");
|
||||||
// Dark Accent color
|
// Dark Accent color
|
||||||
--accent-dark-color: theme("colors.yellow.600");
|
--accent-dark-color: theme("colors.yellow.600");
|
||||||
// Gradient from
|
// Gradient from
|
||||||
--gradient-from-color: theme("colors.blue.200");
|
--gradient-from-color: theme("colors.yellow.200");
|
||||||
// Gradient via
|
// Gradient via
|
||||||
--gradient-via-color: theme("colors.blue.400");
|
--gradient-via-color: theme("colors.yellow.400");
|
||||||
// Gradient to
|
// Gradient to
|
||||||
--gradient-to-color: theme("colors.blue.600");
|
--gradient-to-color: theme("colors.yellow.600");
|
||||||
|
}
|
||||||
|
|
||||||
|
@mixin orangeTheme {
|
||||||
|
// Accent color
|
||||||
|
--accent-color: theme("colors.orange.500");
|
||||||
|
// Light Accent color
|
||||||
|
--accent-light-color: theme("colors.orange.400");
|
||||||
|
// Dark Accent color
|
||||||
|
--accent-dark-color: theme("colors.orange.600");
|
||||||
|
// Gradient from
|
||||||
|
--gradient-from-color: theme("colors.orange.200");
|
||||||
|
// Gradient via
|
||||||
|
--gradient-via-color: theme("colors.orange.400");
|
||||||
|
// Gradient to
|
||||||
|
--gradient-to-color: theme("colors.orange.600");
|
||||||
|
}
|
||||||
|
|
||||||
|
@mixin redTheme {
|
||||||
|
// Accent color
|
||||||
|
--accent-color: theme("colors.red.500");
|
||||||
|
// Light Accent color
|
||||||
|
--accent-light-color: theme("colors.red.400");
|
||||||
|
// Dark Accent color
|
||||||
|
--accent-dark-color: theme("colors.red.600");
|
||||||
|
// Gradient from
|
||||||
|
--gradient-from-color: theme("colors.red.200");
|
||||||
|
// Gradient via
|
||||||
|
--gradient-via-color: theme("colors.red.400");
|
||||||
|
// Gradient to
|
||||||
|
--gradient-to-color: theme("colors.red.600");
|
||||||
|
}
|
||||||
|
|
||||||
|
@mixin pinkTheme {
|
||||||
|
// Accent color
|
||||||
|
--accent-color: theme("colors.pink.500");
|
||||||
|
// Light Accent color
|
||||||
|
--accent-light-color: theme("colors.pink.400");
|
||||||
|
// Dark Accent color
|
||||||
|
--accent-dark-color: theme("colors.pink.600");
|
||||||
|
// Gradient from
|
||||||
|
--gradient-from-color: theme("colors.pink.200");
|
||||||
|
// Gradient via
|
||||||
|
--gradient-via-color: theme("colors.pink.400");
|
||||||
|
// Gradient to
|
||||||
|
--gradient-to-color: theme("colors.pink.600");
|
||||||
}
|
}
|
||||||
|
|
||||||
:root {
|
:root {
|
||||||
@@ -241,27 +241,35 @@
|
|||||||
:root[data-accent="blue"] {
|
:root[data-accent="blue"] {
|
||||||
@include blueTheme;
|
@include blueTheme;
|
||||||
}
|
}
|
||||||
|
|
||||||
:root[data-accent="green"] {
|
:root[data-accent="green"] {
|
||||||
@include greenTheme;
|
@include greenTheme;
|
||||||
}
|
}
|
||||||
|
|
||||||
:root[data-accent="teal"] {
|
:root[data-accent="teal"] {
|
||||||
@include tealTheme;
|
@include tealTheme;
|
||||||
}
|
}
|
||||||
|
|
||||||
:root[data-accent="indigo"] {
|
:root[data-accent="indigo"] {
|
||||||
@include indigoTheme;
|
@include indigoTheme;
|
||||||
}
|
}
|
||||||
|
|
||||||
:root[data-accent="purple"] {
|
:root[data-accent="purple"] {
|
||||||
@include purpleTheme;
|
@include purpleTheme;
|
||||||
}
|
}
|
||||||
|
|
||||||
:root[data-accent="orange"] {
|
:root[data-accent="orange"] {
|
||||||
@include orangeTheme;
|
@include orangeTheme;
|
||||||
}
|
}
|
||||||
|
|
||||||
:root[data-accent="pink"] {
|
:root[data-accent="pink"] {
|
||||||
@include pinkTheme;
|
@include pinkTheme;
|
||||||
}
|
}
|
||||||
|
|
||||||
:root[data-accent="red"] {
|
:root[data-accent="red"] {
|
||||||
@include redTheme;
|
@include redTheme;
|
||||||
}
|
}
|
||||||
|
|
||||||
:root[data-accent="yellow"] {
|
:root[data-accent="yellow"] {
|
||||||
@include yellowTheme;
|
@include yellowTheme;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,22 +1,22 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="flex bg-primary border-b justify-between border-dividerLight">
|
<div class="bg-dividerLight border-b border-divider flex justify-between">
|
||||||
<span class="flex">
|
<span class="flex">
|
||||||
<SmartLink
|
<SmartLink
|
||||||
to="https://forms.gle/8yFiEynXB7h477Ns6"
|
to="https://forms.gle/8yFiEynXB7h477Ns6"
|
||||||
blank
|
blank
|
||||||
class="
|
class="
|
||||||
relative
|
|
||||||
flex
|
flex
|
||||||
|
py-2
|
||||||
|
px-4
|
||||||
|
transition
|
||||||
|
relative
|
||||||
items-center
|
items-center
|
||||||
justify-center
|
justify-center
|
||||||
px-4
|
|
||||||
py-3
|
|
||||||
transition
|
|
||||||
group
|
group
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
<i class="material-icons mr-4">science</i>
|
<i class="mr-4 material-icons">science</i>
|
||||||
<span class="text-secondaryDark text-xs">
|
<span class="text-secondaryDark">
|
||||||
<span class="md:hidden"> Beta Layout </span>
|
<span class="md:hidden"> Beta Layout </span>
|
||||||
<span class="hidden md:inline">
|
<span class="hidden md:inline">
|
||||||
You're currently viewing an experimental beta layout
|
You're currently viewing an experimental beta layout
|
||||||
@@ -24,17 +24,16 @@
|
|||||||
</span>
|
</span>
|
||||||
<span
|
<span
|
||||||
class="
|
class="
|
||||||
|
border-l border-divider
|
||||||
flex
|
flex
|
||||||
|
font-semibold
|
||||||
|
text-accent
|
||||||
|
ml-4
|
||||||
|
pl-4
|
||||||
|
transition
|
||||||
items-center
|
items-center
|
||||||
justify-center
|
justify-center
|
||||||
pl-4
|
|
||||||
ml-4
|
|
||||||
font-semibold
|
|
||||||
transition
|
|
||||||
border-l
|
|
||||||
group-hover:text-accentDark
|
group-hover:text-accentDark
|
||||||
border-divider
|
|
||||||
text-accent text-xs
|
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
<span class="md:hidden"> Give Feedback </span>
|
<span class="md:hidden"> Give Feedback </span>
|
||||||
@@ -43,17 +42,13 @@
|
|||||||
</SmartLink>
|
</SmartLink>
|
||||||
<SmartLink
|
<SmartLink
|
||||||
to="https://hoppscotch.io"
|
to="https://hoppscotch.io"
|
||||||
class="flex items-center justify-center transition group"
|
class="flex transition items-center justify-center group"
|
||||||
>
|
>
|
||||||
<span class="text-secondaryDark text-xs">
|
<span class="text-secondaryDark">
|
||||||
Switch back to the Hoppscotch website
|
Switch back to the Hoppscotch website
|
||||||
</span>
|
</span>
|
||||||
</SmartLink>
|
</SmartLink>
|
||||||
</span>
|
</span>
|
||||||
<ButtonSecondary
|
<ButtonSecondary icon="close" />
|
||||||
v-tippy="{ theme: 'tooltip' }"
|
|
||||||
icon="close"
|
|
||||||
:title="$t('close')"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -1,63 +0,0 @@
|
|||||||
<template>
|
|
||||||
<SmartModal v-if="show" @close="hideModal">
|
|
||||||
<template #header>
|
|
||||||
<h3 class="heading">{{ $t("extensions") }}</h3>
|
|
||||||
<div>
|
|
||||||
<ButtonSecondary icon="close" @click.native="hideModal" />
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<template #body>
|
|
||||||
<div class="flex flex-col px-2 space-y-2">
|
|
||||||
<SmartItem
|
|
||||||
to="https://addons.mozilla.org/en-US/firefox/addon/hoppscotch"
|
|
||||||
blank
|
|
||||||
svg="firefox"
|
|
||||||
label="Firefox"
|
|
||||||
:info-icon="hasFirefoxExtInstalled ? 'check_circle' : ''"
|
|
||||||
/>
|
|
||||||
<SmartItem
|
|
||||||
to="https://chrome.google.com/webstore/detail/hoppscotch-browser-extens/amknoiejhlmhancpahfcfcfhllgkpbld"
|
|
||||||
blank
|
|
||||||
svg="chrome"
|
|
||||||
label="Chrome"
|
|
||||||
:info-icon="hasChromeExtInstalled ? 'check_circle' : ''"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<template #footer>
|
|
||||||
<div class="px-2 text-secondaryLight text-xs">
|
|
||||||
{{ $t("extensions_info1") }}
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</SmartModal>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import {
|
|
||||||
hasChromeExtensionInstalled,
|
|
||||||
hasFirefoxExtensionInstalled,
|
|
||||||
} from "~/helpers/strategies/ExtensionStrategy"
|
|
||||||
|
|
||||||
export default {
|
|
||||||
props: {
|
|
||||||
show: Boolean,
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
hasChromeExtInstalled: hasChromeExtensionInstalled(),
|
|
||||||
hasFirefoxExtInstalled: hasFirefoxExtensionInstalled(),
|
|
||||||
}
|
|
||||||
},
|
|
||||||
watch: {
|
|
||||||
show() {
|
|
||||||
this.hasChromeExtInstalled = hasChromeExtensionInstalled()
|
|
||||||
this.hasFirefoxExtInstalled = hasFirefoxExtensionInstalled()
|
|
||||||
},
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
hideModal() {
|
|
||||||
this.$emit("hide-modal")
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
110
components/app/Footer.vue
Normal file
110
components/app/Footer.vue
Normal file
@@ -0,0 +1,110 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<div class="flex justify-between">
|
||||||
|
<div>
|
||||||
|
<ButtonSecondary
|
||||||
|
v-tippy="{ theme: 'tooltip' }"
|
||||||
|
:title="LEFT_SIDEBAR ? $t('hide.sidebar') : $t('show.sidebar')"
|
||||||
|
icon="menu_open"
|
||||||
|
:class="{ 'transform rotate-180': !LEFT_SIDEBAR }"
|
||||||
|
@click.native="toggleSetting('LEFT_SIDEBAR')"
|
||||||
|
/>
|
||||||
|
<ButtonSecondary
|
||||||
|
v-tippy="{ theme: 'tooltip' }"
|
||||||
|
:title="`${
|
||||||
|
ZEN_MODE ? $t('action.turn_off') : $t('action.turn_on')
|
||||||
|
} ${$t('layout.zen_mode')}`"
|
||||||
|
:icon="ZEN_MODE ? 'fullscreen_exit' : 'fullscreen'"
|
||||||
|
:class="{
|
||||||
|
'!text-accent focus:text-accent hover:text-accent': ZEN_MODE,
|
||||||
|
}"
|
||||||
|
@click.native="toggleSetting('ZEN_MODE')"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<ButtonSecondary
|
||||||
|
v-tippy="{ theme: 'tooltip' }"
|
||||||
|
icon="keyboard"
|
||||||
|
:title="$t('shortcuts')"
|
||||||
|
:shortcut="['?']"
|
||||||
|
@click.native="showShortcuts = true"
|
||||||
|
/>
|
||||||
|
<ButtonSecondary
|
||||||
|
v-if="navigatorShare"
|
||||||
|
v-tippy="{ theme: 'tooltip' }"
|
||||||
|
icon="share"
|
||||||
|
:title="$t('request.share')"
|
||||||
|
@click.native="nativeShare()"
|
||||||
|
/>
|
||||||
|
<ButtonSecondary
|
||||||
|
v-tippy="{ theme: 'tooltip' }"
|
||||||
|
:title="RIGHT_SIDEBAR ? $t('hide.sidebar') : $t('show.sidebar')"
|
||||||
|
icon="menu_open"
|
||||||
|
:class="['transform rotate-180', { 'rotate-0': !RIGHT_SIDEBAR }]"
|
||||||
|
@click.native="toggleSetting('RIGHT_SIDEBAR')"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<AppShortcuts :show="showShortcuts" @close="showShortcuts = false" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { defineComponent } from "@nuxtjs/composition-api"
|
||||||
|
import {
|
||||||
|
defaultSettings,
|
||||||
|
getSettingSubject,
|
||||||
|
applySetting,
|
||||||
|
toggleSetting,
|
||||||
|
} from "~/newstore/settings"
|
||||||
|
import type { KeysMatching } from "~/types/ts-utils"
|
||||||
|
|
||||||
|
type SettingsType = typeof defaultSettings
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
LEFT_SIDEBAR: null,
|
||||||
|
RIGHT_SIDEBAR: null,
|
||||||
|
ZEN_MODE: null,
|
||||||
|
showShortcuts: false,
|
||||||
|
navigatorShare: navigator.share,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
subscriptions() {
|
||||||
|
return {
|
||||||
|
LEFT_SIDEBAR: getSettingSubject("LEFT_SIDEBAR"),
|
||||||
|
RIGHT_SIDEBAR: getSettingSubject("RIGHT_SIDEBAR"),
|
||||||
|
ZEN_MODE: getSettingSubject("ZEN_MODE"),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
ZEN_MODE(ZEN_MODE) {
|
||||||
|
this.applySetting("LEFT_SIDEBAR", !ZEN_MODE)
|
||||||
|
// this.applySetting("RIGHT_SIDEBAR", !ZEN_MODE)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
toggleSetting<K extends KeysMatching<SettingsType, boolean>>(key: K) {
|
||||||
|
toggleSetting(key)
|
||||||
|
},
|
||||||
|
applySetting<K extends keyof SettingsType>(key: K, value: SettingsType[K]) {
|
||||||
|
applySetting(key, value)
|
||||||
|
},
|
||||||
|
nativeShare() {
|
||||||
|
if (navigator.share) {
|
||||||
|
navigator
|
||||||
|
.share({
|
||||||
|
title: "Hoppscotch",
|
||||||
|
text: "Hoppscotch • Open source API development ecosystem - Helps you create requests faster, saving precious time on development.",
|
||||||
|
url: "https://hoppscotch.io",
|
||||||
|
})
|
||||||
|
.then(() => {})
|
||||||
|
.catch(console.error)
|
||||||
|
} else {
|
||||||
|
// fallback
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
</script>
|
||||||
@@ -1,21 +1,30 @@
|
|||||||
<template>
|
<template>
|
||||||
<header class="flex items-center justify-between p-2 flex-1">
|
<header class="flex flex-1 py-2 px-4 items-center justify-between">
|
||||||
<div class="inline-flex space-x-2 items-center font-bold flex-shrink-0">
|
<div
|
||||||
<AppLogo class="h-6 mx-4" /> Hoppscotch
|
class="
|
||||||
|
font-extrabold
|
||||||
|
space-x-2
|
||||||
|
flex-shrink-0
|
||||||
|
text-sm
|
||||||
|
inline-flex
|
||||||
|
items-center
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<AppLogo />
|
||||||
</div>
|
</div>
|
||||||
<div class="inline-flex space-x-2 items-center flex-shrink-0">
|
<div class="space-x-2 flex-shrink-0 inline-flex items-center">
|
||||||
<AppGitHubStarButton class="mt-1 mr-2" />
|
<AppGitHubStarButton class="mt-1 mr-2" />
|
||||||
<TabPrimary
|
<TabPrimary
|
||||||
id="installPWA"
|
id="installPWA"
|
||||||
v-tippy="{ theme: 'tooltip' }"
|
v-tippy="{ theme: 'tooltip' }"
|
||||||
:title="$t('install_pwa')"
|
:title="$t('header.install_pwa')"
|
||||||
icon="offline_bolt"
|
icon="offline_bolt"
|
||||||
@click.native="showInstallPrompt()"
|
@click.native="showInstallPrompt()"
|
||||||
/>
|
/>
|
||||||
<span tabindex="-1">
|
<span tabindex="-1">
|
||||||
<ButtonPrimary
|
<ButtonPrimary
|
||||||
v-if="currentUser === null"
|
v-if="currentUser === null"
|
||||||
label="Get Started"
|
label="Login"
|
||||||
@click.native="showLogin = true"
|
@click.native="showLogin = true"
|
||||||
/>
|
/>
|
||||||
<tippy
|
<tippy
|
||||||
@@ -34,11 +43,11 @@
|
|||||||
:url="currentUser.photoURL"
|
:url="currentUser.photoURL"
|
||||||
:alt="currentUser.displayName"
|
:alt="currentUser.displayName"
|
||||||
:title="
|
:title="
|
||||||
(currentUser.displayName ||
|
`${currentUser.displayName || 'Name not found'}` +
|
||||||
'<label><i>Name not found</i></label>') +
|
|
||||||
'<br>' +
|
'<br>' +
|
||||||
(currentUser.email || '<label><i>Email not found</i></label>')
|
`<sub>${currentUser.email || 'Email not found'}</sub>`
|
||||||
"
|
"
|
||||||
|
:indicator="isOnLine ? 'bg-green-500' : 'bg-red-500'"
|
||||||
/>
|
/>
|
||||||
<TabPrimary
|
<TabPrimary
|
||||||
v-else
|
v-else
|
||||||
@@ -47,12 +56,6 @@
|
|||||||
icon="account_circle"
|
icon="account_circle"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
<SmartItem
|
|
||||||
to="/profile"
|
|
||||||
icon="person"
|
|
||||||
:label="$t('profile')"
|
|
||||||
@click.native="$refs.user.tippy().hide()"
|
|
||||||
/>
|
|
||||||
<SmartItem
|
<SmartItem
|
||||||
to="/settings"
|
to="/settings"
|
||||||
icon="settings"
|
icon="settings"
|
||||||
@@ -62,56 +65,8 @@
|
|||||||
<FirebaseLogout @confirm-logout="$refs.user.tippy().hide()" />
|
<FirebaseLogout @confirm-logout="$refs.user.tippy().hide()" />
|
||||||
</tippy>
|
</tippy>
|
||||||
</span>
|
</span>
|
||||||
<span tabindex="-1">
|
|
||||||
<tippy
|
|
||||||
ref="options"
|
|
||||||
interactive
|
|
||||||
tabindex="-1"
|
|
||||||
trigger="click"
|
|
||||||
theme="popover"
|
|
||||||
arrow
|
|
||||||
>
|
|
||||||
<template #trigger>
|
|
||||||
<TabPrimary
|
|
||||||
v-tippy="{ theme: 'tooltip' }"
|
|
||||||
:title="$t('more')"
|
|
||||||
icon="drag_indicator"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
<SmartItem
|
|
||||||
icon="extension"
|
|
||||||
:label="$t('extensions')"
|
|
||||||
@click.native="
|
|
||||||
showExtensions = true
|
|
||||||
$refs.options.tippy().hide()
|
|
||||||
"
|
|
||||||
/>
|
|
||||||
<SmartItem
|
|
||||||
icon="keyboard"
|
|
||||||
:label="$t('shortcuts')"
|
|
||||||
@click.native="
|
|
||||||
showShortcuts = true
|
|
||||||
$refs.options.tippy().hide()
|
|
||||||
"
|
|
||||||
/>
|
|
||||||
<SmartItem
|
|
||||||
v-if="navigatorShare"
|
|
||||||
icon="share"
|
|
||||||
:label="$t('share')"
|
|
||||||
@click.native="
|
|
||||||
nativeShare()
|
|
||||||
$refs.options.tippy().hide()
|
|
||||||
"
|
|
||||||
/>
|
|
||||||
</tippy>
|
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
<FirebaseLogin :show="showLogin" @hide-modal="showLogin = false" />
|
<FirebaseLogin :show="showLogin" @hide-modal="showLogin = false" />
|
||||||
<AppExtensions
|
|
||||||
:show="showExtensions"
|
|
||||||
@hide-modal="showExtensions = false"
|
|
||||||
/>
|
|
||||||
<AppShortcuts :show="showShortcuts" @hide-modal="showShortcuts = false" />
|
|
||||||
</header>
|
</header>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -119,7 +74,6 @@
|
|||||||
import intializePwa from "~/helpers/pwa"
|
import intializePwa from "~/helpers/pwa"
|
||||||
import { currentUser$ } from "~/helpers/fb/auth"
|
import { currentUser$ } from "~/helpers/fb/auth"
|
||||||
import { getLocalConfig, setLocalConfig } from "~/newstore/localpersistence"
|
import { getLocalConfig, setLocalConfig } from "~/newstore/localpersistence"
|
||||||
// import { hasExtensionInstalled } from "~/helpers/strategies/ExtensionStrategy"
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
data() {
|
data() {
|
||||||
@@ -129,9 +83,7 @@ export default {
|
|||||||
// prompt.
|
// prompt.
|
||||||
showInstallPrompt: null,
|
showInstallPrompt: null,
|
||||||
showLogin: false,
|
showLogin: false,
|
||||||
showExtensions: false,
|
isOnLine: navigator.onLine,
|
||||||
showShortcuts: false,
|
|
||||||
navigatorShare: navigator.share,
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
subscriptions() {
|
subscriptions() {
|
||||||
@@ -140,6 +92,13 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
async mounted() {
|
async mounted() {
|
||||||
|
window.addEventListener("online", () => {
|
||||||
|
this.isOnLine = true
|
||||||
|
})
|
||||||
|
window.addEventListener("offline", () => {
|
||||||
|
this.isOnLine = false
|
||||||
|
})
|
||||||
|
|
||||||
// Initializes the PWA code - checks if the app is installed,
|
// Initializes the PWA code - checks if the app is installed,
|
||||||
// etc.
|
// etc.
|
||||||
this.showInstallPrompt = await intializePwa()
|
this.showInstallPrompt = await intializePwa()
|
||||||
@@ -151,7 +110,7 @@ export default {
|
|||||||
theme: "toasted-primary",
|
theme: "toasted-primary",
|
||||||
action: [
|
action: [
|
||||||
{
|
{
|
||||||
text: this.$t("dismiss"),
|
text: this.$t("action.dismiss"),
|
||||||
onClick: (_, toastObject) => {
|
onClick: (_, toastObject) => {
|
||||||
setLocalConfig("cookiesAllowed", "yes")
|
setLocalConfig("cookiesAllowed", "yes")
|
||||||
toastObject.goAway(0)
|
toastObject.goAway(0)
|
||||||
@@ -161,21 +120,5 @@ export default {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
|
||||||
nativeShare() {
|
|
||||||
if (navigator.share) {
|
|
||||||
navigator
|
|
||||||
.share({
|
|
||||||
title: "Hoppscotch",
|
|
||||||
text: "Hoppscotch • Open source API development ecosystem - Helps you create requests faster, saving precious time on development.",
|
|
||||||
url: "https://hoppscotch.io",
|
|
||||||
})
|
|
||||||
.then(() => {})
|
|
||||||
.catch(console.error)
|
|
||||||
} else {
|
|
||||||
// fallback
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,19 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<svg
|
<svg class="logo" xmlns="http://www.w3.org/2000/svg" width="32" height="32">
|
||||||
class="logo fill-current"
|
<circle class="fill-current" r="8" cx="50%" cy="50%" />
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
<circle class="fill-primary" r="6" cx="50%" cy="50%" />
|
||||||
width="20"
|
|
||||||
height="20"
|
|
||||||
viewBox="0 0 612 612"
|
|
||||||
>
|
|
||||||
<g xmlns="http://www.w3.org/2000/svg">
|
|
||||||
<path
|
|
||||||
d="M4.283 208.326c-28.015 71.685 84.358 182.589 250.992 247.71 166.634 65.121 324.428 59.801 352.442-11.884 17.432-44.606-19.496-104.396-90.027-158.893-.489 22.675-4.952 44.944-13.309 66.328-3.559 9.108-11.697 21.519-30.254 28.923-10.853 4.33-24.392 6.526-40.242 6.526-40.758 0-99.372-14.662-156.792-39.22-27.484-11.755-52.967-25.125-73.694-38.665-23.871-15.594-41.229-31.196-51.592-46.373-15.399-22.551-13.289-40.954-8.807-52.421 8.368-21.412 20.275-40.884 35.185-57.777-88.789-7.765-156.47 11.143-173.902 55.746zm542.506 203.868c7.682-5.648 19.708-2.339 26.861 7.39 7.153 9.729 6.724 22.194-.958 27.842s-19.709 2.339-26.861-7.39c-7.153-9.729-6.724-22.194.958-27.842zm-297.979-5.647c3.842-9.832 16.98-13.886 29.344-9.054 12.363 4.832 19.271 16.719 15.428 26.552-3.842 9.832-16.98 13.887-29.344 9.054-12.363-4.832-19.269-16.72-15.428-26.552zM51.312 246.776c-11.854 2.301-22.937-3.422-24.754-12.782-1.817-9.361 6.321-18.813 18.174-21.114 11.854-2.301 22.937 3.422 24.754 12.782 1.817 9.36-6.319 18.813-18.174 21.114z"
|
|
||||||
/>
|
|
||||||
<path
|
|
||||||
d="M433.885 363.563c24.904 0 42.999-6.106 48.633-20.52 9.669-24.741 13.162-50.371 11.229-75.19-4.919-63.176-45.008-121.096-107.987-145.708-20.393-7.97-41.378-11.745-62.027-11.744-43.118.003-84.718 16.481-116.132 45.623-18.252 16.932-33.069 38.136-42.738 62.878-21.567 55.188 173.67 144.661 269.022 144.661z"
|
|
||||||
/>
|
|
||||||
</g>
|
|
||||||
</svg>
|
</svg>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<section :id="label.toLowerCase()">
|
<section :id="label.toLowerCase()" class="flex flex-col flex-1">
|
||||||
<slot></slot>
|
<slot></slot>
|
||||||
</section>
|
</section>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -1,44 +1,76 @@
|
|||||||
<template>
|
<template>
|
||||||
<SmartModal v-if="show" @close="hideModal">
|
<AppSlideOver :show="show" @close="close()">
|
||||||
<template #header>
|
<template #content>
|
||||||
<h3 class="heading">{{ $t("shortcuts") }}</h3>
|
|
||||||
<div>
|
|
||||||
<ButtonSecondary icon="close" @click.native="hideModal" />
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<template #body>
|
|
||||||
<div class="px-2">
|
|
||||||
<div
|
<div
|
||||||
v-for="(shortcut, index) in shortcuts"
|
|
||||||
:key="`shortcut-${index}`"
|
|
||||||
class="flex items-center"
|
|
||||||
>
|
|
||||||
<kbd
|
|
||||||
v-for="(key, keyIndex) in shortcut.keys"
|
|
||||||
:key="`shortcut-${index}-key-${keyIndex}`"
|
|
||||||
class="
|
class="
|
||||||
py-2
|
bg-primary
|
||||||
px-4
|
border-b border-dividerLight
|
||||||
m-1
|
flex
|
||||||
text-xs
|
p-2
|
||||||
border border-divider
|
top-0
|
||||||
rounded-lg
|
z-10
|
||||||
font-bold
|
items-center
|
||||||
|
sticky
|
||||||
|
justify-between
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
{{ key }}
|
<h3 class="ml-4 heading">{{ $t("shortcuts") }}</h3>
|
||||||
</kbd>
|
<div>
|
||||||
<span class="flex text-xs ml-4">
|
<ButtonSecondary to="/settings" icon="tune" />
|
||||||
|
<ButtonSecondary icon="close" @click.native="close()" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- <div class="search-wrapper">
|
||||||
|
<input
|
||||||
|
v-model="filterText"
|
||||||
|
type="search"
|
||||||
|
class="bg-primaryLight border-b border-dividerLight flex font-semibold font-mono w-full py-2 pr-2 pl-8 focus:outline-none truncate"
|
||||||
|
:placeholder="$t('search')"
|
||||||
|
/>
|
||||||
|
</div> -->
|
||||||
|
<div
|
||||||
|
class="
|
||||||
|
divide-y divide-dividerLight
|
||||||
|
flex flex-col flex-1
|
||||||
|
overflow-auto
|
||||||
|
hide-scrollbar
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
v-for="(map, mapIndex) in mappings"
|
||||||
|
:key="`map-${mapIndex}`"
|
||||||
|
class="space-y-4 py-4 px-6"
|
||||||
|
>
|
||||||
|
<h5 class="font-bold text-secondaryDark text-sm">
|
||||||
|
{{ map.section }}
|
||||||
|
</h5>
|
||||||
|
<div
|
||||||
|
v-for="(shortcut, shortcutIndex) in map.shortcuts"
|
||||||
|
:key="`map-${mapIndex}-shortcut-${shortcutIndex}`"
|
||||||
|
class="flex items-center"
|
||||||
|
>
|
||||||
|
<span class="flex flex-1 text-secondaryLight mr-4">
|
||||||
{{ shortcut.label }}
|
{{ shortcut.label }}
|
||||||
</span>
|
</span>
|
||||||
|
<span
|
||||||
|
v-for="(key, keyIndex) in shortcut.keys"
|
||||||
|
:key="`map-${mapIndex}-shortcut-${shortcutIndex}-key-${keyIndex}`"
|
||||||
|
class="shortcut-key"
|
||||||
|
>
|
||||||
|
{{ key }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</SmartModal>
|
</AppSlideOver>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { getPlatformSpecialKey } from "~/helpers/platformutils"
|
import {
|
||||||
|
getPlatformSpecialKey,
|
||||||
|
getPlatformAlternateKey,
|
||||||
|
} from "~/helpers/platformutils"
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
props: {
|
props: {
|
||||||
@@ -46,59 +78,85 @@ export default {
|
|||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
filterText: "",
|
||||||
|
mappings: [
|
||||||
|
{
|
||||||
|
section: "General",
|
||||||
shortcuts: [
|
shortcuts: [
|
||||||
{
|
{
|
||||||
keys: [this.getSpecialKey(), "G"],
|
keys: [getPlatformSpecialKey(), "G"],
|
||||||
label: this.$t("send_request"),
|
label: this.$t("shortcut.send_request"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
keys: [this.getSpecialKey(), "S"],
|
keys: [getPlatformSpecialKey(), "S"],
|
||||||
label: this.$t("save_to_collections"),
|
label: this.$t("shortcut.save_to_collections"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
keys: [this.getSpecialKey(), "K"],
|
keys: [getPlatformSpecialKey(), "K"],
|
||||||
label: this.$t("copy_request_link"),
|
label: this.$t("shortcut.copy_request_link"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
keys: [this.getSpecialKey(), "I"],
|
keys: [getPlatformSpecialKey(), "I"],
|
||||||
label: this.$t("reset_request"),
|
label: this.$t("shortcut.reset_request"),
|
||||||
|
},
|
||||||
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
keys: ["Alt", "▲"],
|
section: "Request",
|
||||||
label: this.$t("select_next_method"),
|
shortcuts: [
|
||||||
|
{
|
||||||
|
keys: [getPlatformAlternateKey(), "↑"],
|
||||||
|
label: this.$t("shortcut.next_method"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
keys: ["Alt", "▼"],
|
keys: [getPlatformAlternateKey(), "↓"],
|
||||||
label: this.$t("select_previous_method"),
|
label: this.$t("shortcut.previous_method"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
keys: ["Alt", "G"],
|
keys: [getPlatformAlternateKey(), "G"],
|
||||||
label: this.$t("select_get_method"),
|
label: this.$t("shortcut.get_method"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
keys: ["Alt", "H"],
|
keys: [getPlatformAlternateKey(), "H"],
|
||||||
label: this.$t("select_head_method"),
|
label: this.$t("shortcut.head_method"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
keys: ["Alt", "P"],
|
keys: [getPlatformAlternateKey(), "P"],
|
||||||
label: this.$t("select_post_method"),
|
label: this.$t("shortcut.post_method"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
keys: ["Alt", "U"],
|
keys: [getPlatformAlternateKey(), "U"],
|
||||||
label: this.$t("select_put_method"),
|
label: this.$t("shortcut.put_method"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
keys: ["Alt", "X"],
|
keys: [getPlatformAlternateKey(), "X"],
|
||||||
label: this.$t("select_delete_method"),
|
label: this.$t("shortcut.delete_method"),
|
||||||
|
},
|
||||||
|
],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
watch: {
|
||||||
|
$route() {
|
||||||
|
this.$emit("close")
|
||||||
|
},
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
getSpecialKey: getPlatformSpecialKey,
|
close() {
|
||||||
hideModal() {
|
this.$emit("close")
|
||||||
this.$emit("hide-modal")
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.shortcut-key {
|
||||||
|
@apply bg-dividerLight;
|
||||||
|
@apply rounded;
|
||||||
|
@apply ml-2;
|
||||||
|
@apply py-1;
|
||||||
|
@apply px-2;
|
||||||
|
@apply inline-flex;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
@@ -7,7 +7,12 @@
|
|||||||
:to="localePath(navigation.target)"
|
:to="localePath(navigation.target)"
|
||||||
class="nav-link"
|
class="nav-link"
|
||||||
>
|
>
|
||||||
<i class="material-icons">{{ navigation.icon }}</i>
|
<i v-if="navigation.icon" class="material-icons">
|
||||||
|
{{ navigation.icon }}
|
||||||
|
</i>
|
||||||
|
<div v-if="navigation.svg" class="h-4 w-4">
|
||||||
|
<SmartIcon :name="navigation.svg" class="svg-icons" />
|
||||||
|
</div>
|
||||||
<span>{{ navigation.title }}</span>
|
<span>{{ navigation.title }}</span>
|
||||||
</nuxt-link>
|
</nuxt-link>
|
||||||
</nav>
|
</nav>
|
||||||
@@ -19,12 +24,31 @@ export default {
|
|||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
primaryNavigation: [
|
primaryNavigation: [
|
||||||
{ target: "index", icon: "home", title: "Home" },
|
{
|
||||||
{ target: "realtime", icon: "language", title: "Realtime" },
|
target: "index",
|
||||||
{ target: "graphql", icon: "code", title: "GraphQL" },
|
icon: "settings_ethernet",
|
||||||
{ target: "doc", icon: "book", title: "Docs" },
|
title: this.$t("navigation.rest"),
|
||||||
{ target: "profile", icon: "person", title: "Profile" },
|
},
|
||||||
{ target: "settings", icon: "settings", title: "Settings" },
|
{
|
||||||
|
target: "graphql",
|
||||||
|
svg: "graphql",
|
||||||
|
title: this.$t("navigation.graphql"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
target: "realtime",
|
||||||
|
icon: "language",
|
||||||
|
title: this.$t("navigation.realtime"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
target: "documentation",
|
||||||
|
icon: "book",
|
||||||
|
title: this.$t("navigation.doc"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
target: "settings",
|
||||||
|
icon: "settings",
|
||||||
|
title: this.$t("navigation.settings"),
|
||||||
|
},
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -34,22 +58,20 @@ export default {
|
|||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
.nav-link {
|
.nav-link {
|
||||||
@apply p-4;
|
@apply p-4;
|
||||||
@apply flex-col;
|
@apply flex flex-col flex-1;
|
||||||
@apply flex-1;
|
|
||||||
@apply hover:bg-primaryDark;
|
|
||||||
@apply hover:text-secondaryDark;
|
|
||||||
@apply items-center;
|
@apply items-center;
|
||||||
@apply justify-center;
|
@apply justify-center;
|
||||||
@apply transition;
|
@apply transition;
|
||||||
|
@apply hover:bg-primaryDark;
|
||||||
|
@apply hover:text-secondaryDark;
|
||||||
|
|
||||||
.material-icons {
|
.material-icons,
|
||||||
@apply transition-opacity;
|
.svg-icons {
|
||||||
@apply opacity-50;
|
@apply opacity-75;
|
||||||
}
|
}
|
||||||
|
|
||||||
span {
|
span {
|
||||||
@apply mt-2;
|
@apply mt-2;
|
||||||
@apply text-xs;
|
|
||||||
@apply font-semibold;
|
@apply font-semibold;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -57,7 +79,8 @@ export default {
|
|||||||
@apply text-accent;
|
@apply text-accent;
|
||||||
@apply hover:text-accent;
|
@apply hover:text-accent;
|
||||||
|
|
||||||
.material-icons {
|
.material-icons,
|
||||||
|
.svg-icons {
|
||||||
@apply opacity-100;
|
@apply opacity-100;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
68
components/app/SlideOver.vue
Normal file
68
components/app/SlideOver.vue
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<transition v-if="show" name="fade" appear>
|
||||||
|
<div class="inset-0 transition-opacity z-20 fixed" @keydown.esc="close()">
|
||||||
|
<div
|
||||||
|
class="bg-primaryDark opacity-75 inset-0 absolute"
|
||||||
|
tabindex="0"
|
||||||
|
@click="close()"
|
||||||
|
></div>
|
||||||
|
</div>
|
||||||
|
</transition>
|
||||||
|
<aside
|
||||||
|
class="
|
||||||
|
bg-primary
|
||||||
|
flex flex-col
|
||||||
|
h-full
|
||||||
|
max-w-full
|
||||||
|
shadow-xl
|
||||||
|
transform
|
||||||
|
transition
|
||||||
|
top-0
|
||||||
|
ease-in-out
|
||||||
|
right-0
|
||||||
|
w-96
|
||||||
|
z-30
|
||||||
|
duration-300
|
||||||
|
fixed
|
||||||
|
overflow-auto
|
||||||
|
"
|
||||||
|
:class="show ? 'translate-x-0' : 'translate-x-full'"
|
||||||
|
>
|
||||||
|
<slot name="content"></slot>
|
||||||
|
</aside>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
show: {
|
||||||
|
type: Boolean,
|
||||||
|
required: true,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
show: {
|
||||||
|
immediate: true,
|
||||||
|
handler(show) {
|
||||||
|
if (process.client) {
|
||||||
|
if (show) document.body.style.setProperty("overflow", "hidden")
|
||||||
|
else document.body.style.removeProperty("overflow")
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
document.addEventListener("keydown", (e) => {
|
||||||
|
if (e.keyCode === 27 && this.show) this.close()
|
||||||
|
})
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
close() {
|
||||||
|
this.$emit("close")
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
@@ -4,28 +4,32 @@
|
|||||||
:exact="exact"
|
:exact="exact"
|
||||||
:blank="blank"
|
:blank="blank"
|
||||||
class="
|
class="
|
||||||
|
font-bold
|
||||||
|
py-2
|
||||||
|
transition
|
||||||
inline-flex
|
inline-flex
|
||||||
items-center
|
items-center
|
||||||
justify-center
|
justify-center
|
||||||
py-2
|
|
||||||
font-semibold
|
|
||||||
transition
|
|
||||||
focus:outline-none
|
focus:outline-none
|
||||||
"
|
"
|
||||||
:class="[
|
:class="[
|
||||||
color
|
color
|
||||||
? `text-${color}-800 bg-${color}-200 hover:text-${color}-900 hover:bg-${color}-300 focus:text-${color}-900 focus:bg-${color}-300`
|
? `text-${color}-800 bg-${color}-200 hover:text-${color}-900 hover:bg-${color}-300 focus:text-${color}-900 focus:bg-${color}-300`
|
||||||
: `text-white dark:text-accentDark bg-accent hover:bg-accentDark focus:bg-accentDark`,
|
: `text-primary bg-accent hover:bg-accentDark focus:bg-accentDark`,
|
||||||
label ? 'px-4' : 'px-2',
|
label ? 'px-4' : 'px-2',
|
||||||
rounded ? 'rounded-full' : 'rounded-lg',
|
rounded ? 'rounded-full' : 'rounded',
|
||||||
{ 'opacity-50 cursor-not-allowed': disabled },
|
{ 'opacity-75 cursor-not-allowed': disabled },
|
||||||
{ 'pointer-events-none': loading },
|
{ 'pointer-events-none': loading },
|
||||||
{ 'px-4 py-4 text-lg': large },
|
{ 'px-6 py-4 text-lg': large },
|
||||||
{ 'shadow-lg hover:shadow-xl': shadow },
|
{ 'shadow-lg hover:shadow-xl': shadow },
|
||||||
{
|
{
|
||||||
'text-white bg-gradient-to-tr from-gradientFrom via-gradientVia to-gradientTo':
|
'text-white bg-gradient-to-tr from-gradientFrom via-gradientVia to-gradientTo':
|
||||||
gradient,
|
gradient,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
'border border-accent hover:border-accentDark focus:border-accentDark':
|
||||||
|
outline,
|
||||||
|
},
|
||||||
]"
|
]"
|
||||||
:disabled="disabled"
|
:disabled="disabled"
|
||||||
:tabindex="loading ? '-1' : '0'"
|
:tabindex="loading ? '-1' : '0'"
|
||||||
@@ -37,27 +41,41 @@
|
|||||||
>
|
>
|
||||||
<i
|
<i
|
||||||
v-if="icon"
|
v-if="icon"
|
||||||
:class="label ? (reverse ? 'ml-2' : 'mr-2') : ''"
|
:class="[
|
||||||
class="material-icons"
|
'material-icons',
|
||||||
|
{ '!text-2xl': large },
|
||||||
|
label ? (reverse ? 'ml-2' : 'mr-2') : '',
|
||||||
|
]"
|
||||||
>
|
>
|
||||||
{{ icon }}
|
{{ icon }}
|
||||||
</i>
|
</i>
|
||||||
<SmartIcon
|
<SmartIcon
|
||||||
v-if="svg"
|
v-if="svg"
|
||||||
:name="svg"
|
:name="svg"
|
||||||
:class="label ? (reverse ? 'ml-4' : 'mr-4') : ''"
|
:class="[
|
||||||
class="svg-icons"
|
'svg-icons',
|
||||||
|
{ '!h-6 !w-6': large },
|
||||||
|
label ? (reverse ? 'ml-2' : 'mr-2') : '',
|
||||||
|
]"
|
||||||
/>
|
/>
|
||||||
{{ label }}
|
{{ label }}
|
||||||
<span v-if="shortkey" class="px-1 ml-2 rounded bg-accentLight">{{
|
<div v-if="shortcut.length && SHORTCUT_INDICATOR" class="ml-2">
|
||||||
shortkey
|
<kbd
|
||||||
}}</span>
|
v-for="(key, index) in shortcut"
|
||||||
|
:key="`key-${index}`"
|
||||||
|
class="bg-accentLight rounded ml-1 px-1 inline-flex"
|
||||||
|
>
|
||||||
|
{{ key }}
|
||||||
|
</kbd>
|
||||||
|
</div>
|
||||||
</span>
|
</span>
|
||||||
<SmartSpinner v-else />
|
<SmartSpinner v-else />
|
||||||
</SmartLink>
|
</SmartLink>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import { getSettingSubject } from "~/newstore/settings"
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
props: {
|
props: {
|
||||||
to: {
|
to: {
|
||||||
@@ -116,10 +134,24 @@ export default {
|
|||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false,
|
default: false,
|
||||||
},
|
},
|
||||||
shortkey: {
|
outline: {
|
||||||
type: String,
|
type: Boolean,
|
||||||
default: "",
|
default: false,
|
||||||
},
|
},
|
||||||
|
shortcut: {
|
||||||
|
type: Array,
|
||||||
|
default: () => [],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
SHORTCUT_INDICATOR: null,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
subscriptions() {
|
||||||
|
return {
|
||||||
|
SHORTCUT_INDICATOR: getSettingSubject("SHORTCUT_INDICATOR"),
|
||||||
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -4,22 +4,24 @@
|
|||||||
:exact="exact"
|
:exact="exact"
|
||||||
:blank="blank"
|
:blank="blank"
|
||||||
class="
|
class="
|
||||||
|
font-semibold
|
||||||
|
py-2
|
||||||
|
transition
|
||||||
inline-flex
|
inline-flex
|
||||||
items-center
|
items-center
|
||||||
justify-center
|
justify-center
|
||||||
py-2
|
|
||||||
font-semibold
|
|
||||||
transition
|
|
||||||
focus:outline-none
|
focus:outline-none
|
||||||
|
hover:bg-primaryDark
|
||||||
"
|
"
|
||||||
:class="[
|
:class="[
|
||||||
color
|
color
|
||||||
? `text-${color}-400 hover:text-${color}-600 focus:text-${color}-600`
|
? `text-${color}-500 hover:text-${color}-600 focus:text-${color}-600`
|
||||||
: 'text-secondary hover:text-secondaryDark focus:text-secondaryDark',
|
: 'text-secondary hover:text-secondaryDark focus:text-secondaryDark',
|
||||||
label ? 'px-3 rounded-lg' : 'px-2 rounded-full',
|
label ? 'px-4' : 'px-2',
|
||||||
rounded ? 'rounded-full' : 'rounded-lg',
|
rounded ? 'rounded-full' : 'rounded',
|
||||||
{ 'opacity-50 cursor-not-allowed': disabled },
|
{ 'opacity-75 cursor-not-allowed': disabled },
|
||||||
{ 'flex-row-reverse': reverse },
|
{ 'flex-row-reverse': reverse },
|
||||||
|
{ 'px-6 py-4 text-lg': large },
|
||||||
{
|
{
|
||||||
'border border-divider hover:border-dividerDark focus:border-dividerDark':
|
'border border-divider hover:border-dividerDark focus:border-dividerDark':
|
||||||
outline,
|
outline,
|
||||||
@@ -29,22 +31,46 @@
|
|||||||
>
|
>
|
||||||
<i
|
<i
|
||||||
v-if="icon"
|
v-if="icon"
|
||||||
:class="label ? (reverse ? 'ml-2' : 'mr-2') : ''"
|
:class="[
|
||||||
class="material-icons"
|
'material-icons',
|
||||||
|
{ '!text-2xl': large },
|
||||||
|
label ? (reverse ? 'ml-2' : 'mr-2') : '',
|
||||||
|
]"
|
||||||
>
|
>
|
||||||
{{ icon }}
|
{{ icon }}
|
||||||
</i>
|
</i>
|
||||||
<SmartIcon
|
<SmartIcon
|
||||||
v-if="svg"
|
v-if="svg"
|
||||||
:name="svg"
|
:name="svg"
|
||||||
:class="label ? (reverse ? 'ml-2' : 'mr-2') : ''"
|
:class="[
|
||||||
class="svg-icons"
|
'svg-icons',
|
||||||
|
{ '!h-6 !w-6': large },
|
||||||
|
label ? (reverse ? 'ml-2' : 'mr-2') : '',
|
||||||
|
]"
|
||||||
/>
|
/>
|
||||||
{{ label }}
|
{{ label }}
|
||||||
|
<div v-if="shortcut.length && SHORTCUT_INDICATOR" class="ml-2">
|
||||||
|
<kbd
|
||||||
|
v-for="(key, index) in shortcut"
|
||||||
|
:key="`key-${index}`"
|
||||||
|
class="
|
||||||
|
bg-dividerLight
|
||||||
|
rounded
|
||||||
|
text-secondaryLight
|
||||||
|
ml-1
|
||||||
|
px-1
|
||||||
|
inline-flex
|
||||||
|
"
|
||||||
|
>
|
||||||
|
{{ key }}
|
||||||
|
</kbd>
|
||||||
|
</div>
|
||||||
</SmartLink>
|
</SmartLink>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import { getSettingSubject } from "~/newstore/settings"
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
props: {
|
props: {
|
||||||
to: {
|
to: {
|
||||||
@@ -87,10 +113,28 @@ export default {
|
|||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false,
|
default: false,
|
||||||
},
|
},
|
||||||
|
large: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
outline: {
|
outline: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false,
|
default: false,
|
||||||
},
|
},
|
||||||
|
shortcut: {
|
||||||
|
type: Array,
|
||||||
|
default: () => [],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
SHORTCUT_INDICATOR: null,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
subscriptions() {
|
||||||
|
return {
|
||||||
|
SHORTCUT_INDICATOR: getSettingSubject("SHORTCUT_INDICATOR"),
|
||||||
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
<template>
|
<template>
|
||||||
<SmartModal v-if="show" @close="hideModal">
|
<SmartModal v-if="show" @close="hideModal">
|
||||||
<template #header>
|
<template #header>
|
||||||
<h3 class="heading">{{ $t("new_collection") }}</h3>
|
<h3 class="heading">{{ $t("collection.new") }}</h3>
|
||||||
<ButtonSecondary icon="close" @click.native="hideModal" />
|
<ButtonSecondary icon="close" @click.native="hideModal" />
|
||||||
</template>
|
</template>
|
||||||
<template #body>
|
<template #body>
|
||||||
<div class="px-2 flex flex-col">
|
<div class="flex flex-col px-2">
|
||||||
<label for="selectLabelAdd" class="px-4 font-semibold pb-4 text-xs">
|
<label for="selectLabelAdd" class="font-semibold px-4 pb-4">
|
||||||
{{ $t("label") }}
|
{{ $t("label") }}
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
@@ -14,7 +14,7 @@
|
|||||||
v-model="name"
|
v-model="name"
|
||||||
class="input"
|
class="input"
|
||||||
type="text"
|
type="text"
|
||||||
:placeholder="$t('my_new_collection')"
|
:placeholder="$t('collection.name')"
|
||||||
@keyup.enter="addNewCollection"
|
@keyup.enter="addNewCollection"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -7,11 +7,8 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template #body>
|
<template #body>
|
||||||
<div class="px-2 flex flex-col">
|
<div class="flex flex-col px-2">
|
||||||
<label
|
<label for="selectLabelAddFolder" class="font-semibold px-4 pb-4">
|
||||||
for="selectLabelAddFolder"
|
|
||||||
class="px-4 font-semibold pb-4 text-xs"
|
|
||||||
>
|
|
||||||
{{ $t("label") }}
|
{{ $t("label") }}
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
@@ -19,7 +16,7 @@
|
|||||||
v-model="name"
|
v-model="name"
|
||||||
class="input"
|
class="input"
|
||||||
type="text"
|
type="text"
|
||||||
:placeholder="$t('my_new_folder')"
|
:placeholder="$t('folder.new')"
|
||||||
@keyup.enter="addFolder"
|
@keyup.enter="addFolder"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -18,15 +18,15 @@
|
|||||||
type="text"
|
type="text"
|
||||||
autofocus
|
autofocus
|
||||||
class="
|
class="
|
||||||
flex
|
|
||||||
w-full
|
|
||||||
px-4
|
|
||||||
text-xs
|
|
||||||
py-3
|
|
||||||
focus:outline-none
|
|
||||||
border-b border-dividerLight
|
|
||||||
font-medium
|
|
||||||
bg-primaryLight
|
bg-primaryLight
|
||||||
|
border-b border-dividerLight
|
||||||
|
flex
|
||||||
|
font-medium
|
||||||
|
w-full
|
||||||
|
py-2
|
||||||
|
px-4
|
||||||
|
focus:outline-none
|
||||||
|
appearance-none
|
||||||
"
|
"
|
||||||
@change="updateSelectedTeam(myTeams[$event.target.value])"
|
@change="updateSelectedTeam(myTeams[$event.target.value])"
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
<template>
|
<template>
|
||||||
<SmartModal v-if="show" @close="hideModal">
|
<SmartModal v-if="show" @close="hideModal">
|
||||||
<template #header>
|
<template #header>
|
||||||
<h3 class="heading">{{ $t("edit_collection") }}</h3>
|
<h3 class="heading">{{ $t("collection.edit") }}</h3>
|
||||||
<div>
|
<div>
|
||||||
<ButtonSecondary icon="close" @click.native="hideModal" />
|
<ButtonSecondary icon="close" @click.native="hideModal" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template #body>
|
<template #body>
|
||||||
<div class="px-2 flex flex-col">
|
<div class="flex flex-col px-2">
|
||||||
<label for="selectLabelEdit" class="px-4 font-semibold pb-4 text-xs">{{
|
<label for="selectLabelEdit" class="font-semibold px-4 pb-4">{{
|
||||||
$t("label")
|
$t("label")
|
||||||
}}</label>
|
}}</label>
|
||||||
<input
|
<input
|
||||||
|
|||||||
@@ -1,18 +1,16 @@
|
|||||||
<template>
|
<template>
|
||||||
<SmartModal v-if="show" @close="$emit('hide-modal')">
|
<SmartModal v-if="show" @close="$emit('hide-modal')">
|
||||||
<template #header>
|
<template #header>
|
||||||
<h3 class="heading">{{ $t("edit_folder") }}</h3>
|
<h3 class="heading">{{ $t("folder.edit") }}</h3>
|
||||||
<div>
|
<div>
|
||||||
<ButtonSecondary icon="close" @click.native="hideModal" />
|
<ButtonSecondary icon="close" @click.native="hideModal" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template #body>
|
<template #body>
|
||||||
<div class="px-2 flex flex-col">
|
<div class="flex flex-col px-2">
|
||||||
<label
|
<label for="selectLabelEditFolder" class="font-semibold px-4 pb-4">{{
|
||||||
for="selectLabelEditFolder"
|
$t("label")
|
||||||
class="px-4 font-semibold pb-4 text-xs"
|
}}</label>
|
||||||
>{{ $t("label") }}</label
|
|
||||||
>
|
|
||||||
<input
|
<input
|
||||||
id="selectLabelEditFolder"
|
id="selectLabelEditFolder"
|
||||||
v-model="name"
|
v-model="name"
|
||||||
|
|||||||
@@ -7,10 +7,10 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template #body>
|
<template #body>
|
||||||
<div class="px-2 flex flex-col">
|
<div class="flex flex-col px-2">
|
||||||
<label for="selectLabelEditReq" class="px-4 font-semibold pb-4 text-xs">
|
<label for="selectLabelEditReq" class="font-semibold px-4 pb-4">
|
||||||
{{ $t("label") }}</label
|
{{ $t("label") }}
|
||||||
>
|
</label>
|
||||||
<input
|
<input
|
||||||
id="selectLabelEditReq"
|
id="selectLabelEditReq"
|
||||||
v-model="requestUpdateData.name"
|
v-model="requestUpdateData.name"
|
||||||
|
|||||||
@@ -33,7 +33,7 @@
|
|||||||
</template>
|
</template>
|
||||||
<SmartItem
|
<SmartItem
|
||||||
icon="assignment_returned"
|
icon="assignment_returned"
|
||||||
:label="$t('import_from_gist')"
|
:label="$t('import.from_gist')"
|
||||||
@click.native="
|
@click.native="
|
||||||
readCollectionGist
|
readCollectionGist
|
||||||
$refs.options.tippy().hide()
|
$refs.options.tippy().hide()
|
||||||
@@ -43,9 +43,9 @@
|
|||||||
v-tippy="{ theme: 'tooltip' }"
|
v-tippy="{ theme: 'tooltip' }"
|
||||||
:title="
|
:title="
|
||||||
!currentUser
|
!currentUser
|
||||||
? $t('login_with_github_to') + $t('create_secret_gist')
|
? $t('export.require_github')
|
||||||
: currentUser.provider !== 'github.com'
|
: currentUser.provider !== 'github.com'
|
||||||
? $t('login_with_github_to') + $t('create_secret_gist')
|
? $t('export.require_github')
|
||||||
: null
|
: null
|
||||||
"
|
"
|
||||||
:disabled="
|
:disabled="
|
||||||
@@ -56,7 +56,7 @@
|
|||||||
: false
|
: false
|
||||||
"
|
"
|
||||||
icon="assignment_turned_in"
|
icon="assignment_turned_in"
|
||||||
:label="$t('create_secret_gist')"
|
:label="$t('export.create_secret_gist')"
|
||||||
@click.native="
|
@click.native="
|
||||||
createCollectionGist
|
createCollectionGist
|
||||||
$refs.options.tippy().hide()
|
$refs.options.tippy().hide()
|
||||||
@@ -87,7 +87,7 @@
|
|||||||
v-tippy="{ theme: 'tooltip' }"
|
v-tippy="{ theme: 'tooltip' }"
|
||||||
:title="$t('preserve_current')"
|
:title="$t('preserve_current')"
|
||||||
icon="create_new_folder"
|
icon="create_new_folder"
|
||||||
:label="$t('import_json')"
|
:label="$t('import.json')"
|
||||||
@click.native="openDialogChooseFileToImportFrom"
|
@click.native="openDialogChooseFileToImportFrom"
|
||||||
/>
|
/>
|
||||||
<input
|
<input
|
||||||
@@ -103,20 +103,20 @@
|
|||||||
v-tippy="{ theme: 'tooltip' }"
|
v-tippy="{ theme: 'tooltip' }"
|
||||||
:title="$t('preserve_current')"
|
:title="$t('preserve_current')"
|
||||||
icon="folder_shared"
|
icon="folder_shared"
|
||||||
:label="$t('import_from_my_collections')"
|
:label="$t('import.from_my_collections')"
|
||||||
@click.native="mode = 'import_from_my_collections'"
|
@click.native="mode = 'import_from_my_collections'"
|
||||||
/>
|
/>
|
||||||
<SmartItem
|
<SmartItem
|
||||||
v-tippy="{ theme: 'tooltip' }"
|
v-tippy="{ theme: 'tooltip' }"
|
||||||
:title="$t('download_file')"
|
:title="$t('download_file')"
|
||||||
icon="drive_file_move"
|
icon="drive_file_move"
|
||||||
:label="$t('export_as_json')"
|
:label="$t('export.as_json')"
|
||||||
@click.native="exportJSON"
|
@click.native="exportJSON"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
v-if="mode == 'import_from_my_collections'"
|
v-if="mode == 'import_from_my_collections'"
|
||||||
class="flex px-2 flex-col"
|
class="flex flex-col px-2"
|
||||||
>
|
>
|
||||||
<div class="select-wrapper">
|
<div class="select-wrapper">
|
||||||
<select
|
<select
|
||||||
@@ -155,7 +155,7 @@
|
|||||||
<ButtonPrimary
|
<ButtonPrimary
|
||||||
:disabled="mySelectedCollectionID == undefined"
|
:disabled="mySelectedCollectionID == undefined"
|
||||||
icon="create_new_folder"
|
icon="create_new_folder"
|
||||||
:label="$t('import')"
|
:label="$t('import.title')"
|
||||||
@click.native="importFromMyCollections"
|
@click.native="importFromMyCollections"
|
||||||
/>
|
/>
|
||||||
</span>
|
</span>
|
||||||
@@ -213,7 +213,7 @@ export default {
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
this.$toast.success(this.$t("gist_created"), {
|
this.$toast.success(this.$t("export.gist_created"), {
|
||||||
icon: "done",
|
icon: "done",
|
||||||
})
|
})
|
||||||
window.open(res.html_url)
|
window.open(res.html_url)
|
||||||
@@ -226,7 +226,7 @@ export default {
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
async readCollectionGist() {
|
async readCollectionGist() {
|
||||||
const gist = prompt(this.$t("enter_gist_url"))
|
const gist = prompt(this.$t("import.gist_url"))
|
||||||
if (!gist) return
|
if (!gist) return
|
||||||
await this.$axios
|
await this.$axios
|
||||||
.$get(`https://api.github.com/gists/${gist.split("/").pop()}`, {
|
.$get(`https://api.github.com/gists/${gist.split("/").pop()}`, {
|
||||||
@@ -390,22 +390,22 @@ export default {
|
|||||||
},
|
},
|
||||||
exportJSON() {
|
exportJSON() {
|
||||||
this.getJSONCollection()
|
this.getJSONCollection()
|
||||||
let text = this.collectionJson
|
const dataToWrite = this.collectionJson
|
||||||
text = text.replace(/\n/g, "\r\n")
|
const file = new Blob([dataToWrite], { type: "application/json" })
|
||||||
const blob = new Blob([text], {
|
const a = document.createElement("a")
|
||||||
type: "text/json",
|
const url = URL.createObjectURL(file)
|
||||||
})
|
a.href = url
|
||||||
const anchor = document.createElement("a")
|
// TODO get uri from meta
|
||||||
anchor.download = "hoppscotch-collection.json"
|
a.download = `${url.split("/").pop().split("#")[0].split("?")[0]}`
|
||||||
anchor.href = window.URL.createObjectURL(blob)
|
document.body.appendChild(a)
|
||||||
anchor.target = "_blank"
|
a.click()
|
||||||
anchor.style.display = "none"
|
|
||||||
document.body.appendChild(anchor)
|
|
||||||
anchor.click()
|
|
||||||
document.body.removeChild(anchor)
|
|
||||||
this.$toast.success(this.$t("download_started"), {
|
this.$toast.success(this.$t("download_started"), {
|
||||||
icon: "done",
|
icon: "done",
|
||||||
})
|
})
|
||||||
|
setTimeout(() => {
|
||||||
|
document.body.removeChild(a)
|
||||||
|
URL.revokeObjectURL(url)
|
||||||
|
}, 1000)
|
||||||
},
|
},
|
||||||
fileImported() {
|
fileImported() {
|
||||||
this.$toast.info(this.$t("file_imported"), {
|
this.$toast.info(this.$t("file_imported"), {
|
||||||
@@ -413,7 +413,7 @@ export default {
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
failedImport() {
|
failedImport() {
|
||||||
this.$toast.error(this.$t("import_failed"), {
|
this.$toast.error(this.$t("import.failed"), {
|
||||||
icon: "error",
|
icon: "error",
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -5,20 +5,17 @@
|
|||||||
<ButtonSecondary icon="close" @click.native="hideModal" />
|
<ButtonSecondary icon="close" @click.native="hideModal" />
|
||||||
</template>
|
</template>
|
||||||
<template #body>
|
<template #body>
|
||||||
<div class="px-2 flex flex-col">
|
<div class="flex flex-col px-2">
|
||||||
<label for="selectLabelSaveReq" class="px-4 font-semibold pb-4 text-xs">
|
<label for="selectLabelSaveReq" class="font-semibold px-4 pb-4">
|
||||||
{{ $t("token_req_name") }}</label
|
{{ $t("request_name") }}
|
||||||
>
|
</label>
|
||||||
<input
|
<input
|
||||||
id="selectLabelSaveReq"
|
id="selectLabelSaveReq"
|
||||||
v-model="requestData.name"
|
v-model="requestName"
|
||||||
class="input"
|
class="input"
|
||||||
type="text"
|
type="text"
|
||||||
@keyup.enter="saveRequestAs"
|
|
||||||
/>
|
/>
|
||||||
<label class="px-4 pt-4 font-semibold pb-4 text-xs">
|
<label class="font-semibold px-4 pt-4 pb-4"> Select Location </label>
|
||||||
Select Location
|
|
||||||
</label>
|
|
||||||
<CollectionsGraphql
|
<CollectionsGraphql
|
||||||
v-if="mode === 'graphql'"
|
v-if="mode === 'graphql'"
|
||||||
:doc="false"
|
:doc="false"
|
||||||
@@ -47,6 +44,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import { defineComponent } from "@nuxtjs/composition-api"
|
||||||
import * as teamUtils from "~/helpers/teams/utils"
|
import * as teamUtils from "~/helpers/teams/utils"
|
||||||
import {
|
import {
|
||||||
saveRESTRequestAs,
|
saveRESTRequestAs,
|
||||||
@@ -54,20 +52,23 @@ import {
|
|||||||
editGraphqlRequest,
|
editGraphqlRequest,
|
||||||
saveGraphqlRequestAs,
|
saveGraphqlRequestAs,
|
||||||
} from "~/newstore/collections"
|
} from "~/newstore/collections"
|
||||||
|
import { getRESTRequest, useRESTRequestName } from "~/newstore/RESTSession"
|
||||||
|
|
||||||
export default {
|
export default defineComponent({
|
||||||
props: {
|
props: {
|
||||||
// mode can be either "graphql" or "rest"
|
// mode can be either "graphql" or "rest"
|
||||||
mode: { type: String, default: "rest" },
|
mode: { type: String, default: "rest" },
|
||||||
show: Boolean,
|
show: Boolean,
|
||||||
editingRequest: { type: Object, default: () => {} },
|
},
|
||||||
|
setup() {
|
||||||
|
return {
|
||||||
|
requestName: useRESTRequestName(),
|
||||||
|
}
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
defaultRequestName: "Untitled Request",
|
|
||||||
path: "Path will appear here",
|
|
||||||
requestData: {
|
requestData: {
|
||||||
name: undefined,
|
name: this.requestName,
|
||||||
collectionIndex: undefined,
|
collectionIndex: undefined,
|
||||||
folderName: undefined,
|
folderName: undefined,
|
||||||
requestIndex: undefined,
|
requestIndex: undefined,
|
||||||
@@ -102,7 +103,7 @@ export default {
|
|||||||
},
|
},
|
||||||
saveRequestAs() {
|
saveRequestAs() {
|
||||||
if (this.picked == null) {
|
if (this.picked == null) {
|
||||||
this.$toast.error(this.$t("select_collection"), {
|
this.$toast.error(this.$t("collection.select"), {
|
||||||
icon: "error",
|
icon: "error",
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
@@ -114,10 +115,7 @@ export default {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const requestUpdated = {
|
const requestUpdated = getRESTRequest()
|
||||||
...this.$props.editingRequest,
|
|
||||||
name: this.$data.requestData.name,
|
|
||||||
}
|
|
||||||
|
|
||||||
// Filter out all REST file inputs
|
// Filter out all REST file inputs
|
||||||
if (this.mode === "rest" && requestUpdated.bodyParams) {
|
if (this.mode === "rest" && requestUpdated.bodyParams) {
|
||||||
@@ -180,5 +178,5 @@ export default {
|
|||||||
this.$emit("hide-modal")
|
this.$emit("hide-modal")
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
<template>
|
<template>
|
||||||
<SmartModal v-if="show" @close="hideModal">
|
<SmartModal v-if="show" @close="hideModal">
|
||||||
<template #header>
|
<template #header>
|
||||||
<h3 class="heading">{{ $t("new_collection") }}</h3>
|
<h3 class="heading">{{ $t("collection.new") }}</h3>
|
||||||
<ButtonSecondary icon="close" @click.native="hideModal" />
|
<ButtonSecondary icon="close" @click.native="hideModal" />
|
||||||
</template>
|
</template>
|
||||||
<template #body>
|
<template #body>
|
||||||
<div class="px-2 flex flex-col">
|
<div class="flex flex-col px-2">
|
||||||
<label for="selectLabelGqlAdd" class="px-4 font-semibold pb-4 text-xs">
|
<label for="selectLabelGqlAdd" class="font-semibold px-4 pb-4">
|
||||||
{{ $t("label") }}
|
{{ $t("label") }}
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
@@ -14,7 +14,7 @@
|
|||||||
v-model="name"
|
v-model="name"
|
||||||
class="input"
|
class="input"
|
||||||
type="text"
|
type="text"
|
||||||
:placeholder="$t('my_new_collection')"
|
:placeholder="$t('collection.name')"
|
||||||
@keyup.enter="addNewCollection"
|
@keyup.enter="addNewCollection"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@@ -44,7 +44,7 @@ export default Vue.extend({
|
|||||||
methods: {
|
methods: {
|
||||||
addNewCollection() {
|
addNewCollection() {
|
||||||
if (!this.name) {
|
if (!this.name) {
|
||||||
this.$toast.info(this.$t("invalid_collection_name").toString())
|
this.$toast.info(this.$t("collection.invalid_name").toString())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,11 +7,8 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template #body>
|
<template #body>
|
||||||
<div class="px-2 flex flex-col">
|
<div class="flex flex-col px-2">
|
||||||
<label
|
<label for="selectLabelGqlAddFolder" class="font-semibold px-4 pb-4">
|
||||||
for="selectLabelGqlAddFolder"
|
|
||||||
class="px-4 font-semibold pb-4 text-xs"
|
|
||||||
>
|
|
||||||
{{ $t("label") }}
|
{{ $t("label") }}
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
@@ -19,7 +16,7 @@
|
|||||||
v-model="name"
|
v-model="name"
|
||||||
class="input"
|
class="input"
|
||||||
type="text"
|
type="text"
|
||||||
:placeholder="$t('my_new_folder')"
|
:placeholder="$t('folder.new')"
|
||||||
@keyup.enter="addFolder"
|
@keyup.enter="addFolder"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -10,32 +10,24 @@
|
|||||||
@dragend="dragging = false"
|
@dragend="dragging = false"
|
||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
class="
|
class="cursor-pointer flex w-10 justify-center items-center truncate"
|
||||||
flex
|
|
||||||
justify-center
|
|
||||||
items-center
|
|
||||||
text-xs
|
|
||||||
w-10
|
|
||||||
truncate
|
|
||||||
cursor-pointer
|
|
||||||
"
|
|
||||||
@click="toggleShowChildren()"
|
@click="toggleShowChildren()"
|
||||||
>
|
>
|
||||||
<i class="material-icons" :class="{ 'text-green-400': isSelected }">
|
<i class="material-icons" :class="{ 'text-green-500': isSelected }">
|
||||||
{{ getCollectionIcon }}
|
{{ getCollectionIcon }}
|
||||||
</i>
|
</i>
|
||||||
</span>
|
</span>
|
||||||
<span
|
<span
|
||||||
class="
|
class="
|
||||||
py-3
|
|
||||||
cursor-pointer
|
cursor-pointer
|
||||||
pr-2
|
flex
|
||||||
flex flex-1
|
|
||||||
min-w-0
|
|
||||||
text-xs
|
|
||||||
group-hover:text-secondaryDark
|
|
||||||
transition
|
|
||||||
font-semibold
|
font-semibold
|
||||||
|
flex-1
|
||||||
|
min-w-0
|
||||||
|
py-2
|
||||||
|
pr-2
|
||||||
|
transition
|
||||||
|
group-hover:text-secondaryDark
|
||||||
"
|
"
|
||||||
@click="toggleShowChildren()"
|
@click="toggleShowChildren()"
|
||||||
>
|
>
|
||||||
@@ -44,7 +36,7 @@
|
|||||||
<ButtonSecondary
|
<ButtonSecondary
|
||||||
v-tippy="{ theme: 'tooltip' }"
|
v-tippy="{ theme: 'tooltip' }"
|
||||||
icon="create_new_folder"
|
icon="create_new_folder"
|
||||||
:title="$t('new_folder')"
|
:title="$t('folder.new')"
|
||||||
class="group-hover:inline-flex hidden"
|
class="group-hover:inline-flex hidden"
|
||||||
@click.native="
|
@click.native="
|
||||||
$emit('add-folder', {
|
$emit('add-folder', {
|
||||||
@@ -69,7 +61,7 @@
|
|||||||
</template>
|
</template>
|
||||||
<SmartItem
|
<SmartItem
|
||||||
icon="create_new_folder"
|
icon="create_new_folder"
|
||||||
:label="$t('new_folder')"
|
:label="$t('folder.new')"
|
||||||
@click.native="
|
@click.native="
|
||||||
$emit('add-folder', {
|
$emit('add-folder', {
|
||||||
path: `${collectionIndex}`,
|
path: `${collectionIndex}`,
|
||||||
@@ -87,6 +79,7 @@
|
|||||||
/>
|
/>
|
||||||
<SmartItem
|
<SmartItem
|
||||||
icon="delete"
|
icon="delete"
|
||||||
|
color="red"
|
||||||
:label="$t('delete')"
|
:label="$t('delete')"
|
||||||
@click.native="
|
@click.native="
|
||||||
confirmRemove = true
|
confirmRemove = true
|
||||||
@@ -95,11 +88,11 @@
|
|||||||
/>
|
/>
|
||||||
</tippy>
|
</tippy>
|
||||||
</div>
|
</div>
|
||||||
<div v-show="showChildren || isFiltered">
|
<div v-if="showChildren || isFiltered">
|
||||||
<CollectionsGraphqlFolder
|
<CollectionsGraphqlFolder
|
||||||
v-for="(folder, index) in collection.folders"
|
v-for="(folder, index) in collection.folders"
|
||||||
:key="`folder-${index}`"
|
:key="`folder-${index}`"
|
||||||
class="ml-5 border-l border-dividerLight"
|
class="border-l border-dividerLight ml-5"
|
||||||
:picked="picked"
|
:picked="picked"
|
||||||
:saving-mode="savingMode"
|
:saving-mode="savingMode"
|
||||||
:folder="folder"
|
:folder="folder"
|
||||||
@@ -116,7 +109,7 @@
|
|||||||
<CollectionsGraphqlRequest
|
<CollectionsGraphqlRequest
|
||||||
v-for="(request, index) in collection.requests"
|
v-for="(request, index) in collection.requests"
|
||||||
:key="`request-${index}`"
|
:key="`request-${index}`"
|
||||||
class="ml-5 border-l border-dividerLight"
|
class="border-l border-dividerLight ml-5"
|
||||||
:picked="picked"
|
:picked="picked"
|
||||||
:saving-mode="savingMode"
|
:saving-mode="savingMode"
|
||||||
:request="request"
|
:request="request"
|
||||||
@@ -134,25 +127,24 @@
|
|||||||
collection.folders.length === 0 && collection.requests.length === 0
|
collection.folders.length === 0 && collection.requests.length === 0
|
||||||
"
|
"
|
||||||
class="
|
class="
|
||||||
flex
|
|
||||||
items-center
|
|
||||||
text-secondaryLight
|
|
||||||
flex-col
|
|
||||||
p-4
|
|
||||||
justify-center
|
|
||||||
ml-5
|
|
||||||
border-l border-dividerLight
|
border-l border-dividerLight
|
||||||
|
flex flex-col
|
||||||
|
text-secondaryLight
|
||||||
|
ml-5
|
||||||
|
p-4
|
||||||
|
items-center
|
||||||
|
justify-center
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
<i class="material-icons opacity-50 pb-2">folder_open</i>
|
<i class="opacity-75 pb-2 material-icons">folder_open</i>
|
||||||
<span class="text-xs text-center">
|
<span class="text-center">
|
||||||
{{ $t("collection_empty") }}
|
{{ $t("empty.collection") }}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<SmartConfirmModal
|
<SmartConfirmModal
|
||||||
:show="confirmRemove"
|
:show="confirmRemove"
|
||||||
:title="$t('are_you_sure_remove_collection')"
|
:title="$t('confirm.remove_collection')"
|
||||||
@hide-modal="confirmRemove = false"
|
@hide-modal="confirmRemove = false"
|
||||||
@resolve="removeCollection"
|
@resolve="removeCollection"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
<template>
|
<template>
|
||||||
<SmartModal v-if="show" @close="hideModal">
|
<SmartModal v-if="show" @close="hideModal">
|
||||||
<template #header>
|
<template #header>
|
||||||
<h3 class="heading">{{ $t("edit_collection") }}</h3>
|
<h3 class="heading">{{ $t("collection.edit") }}</h3>
|
||||||
<div>
|
<div>
|
||||||
<ButtonSecondary icon="close" @click.native="hideModal" />
|
<ButtonSecondary icon="close" @click.native="hideModal" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template #body>
|
<template #body>
|
||||||
<div class="px-2 flex flex-col">
|
<div class="flex flex-col px-2">
|
||||||
<label for="selectLabelGqlEdit" class="px-4 font-semibold pb-4 text-xs">
|
<label for="selectLabelGqlEdit" class="font-semibold px-4 pb-4">
|
||||||
{{ $t("label") }}
|
{{ $t("label") }}
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
@@ -48,7 +48,7 @@ export default Vue.extend({
|
|||||||
methods: {
|
methods: {
|
||||||
saveCollection() {
|
saveCollection() {
|
||||||
if (!this.name) {
|
if (!this.name) {
|
||||||
this.$toast.info(this.$t("invalid_collection_name").toString())
|
this.$toast.info(this.$t("collection.invalid_name").toString())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
const collectionUpdated = {
|
const collectionUpdated = {
|
||||||
|
|||||||
@@ -1,17 +1,14 @@
|
|||||||
<template>
|
<template>
|
||||||
<SmartModal v-if="show" @close="$emit('hide-modal')">
|
<SmartModal v-if="show" @close="$emit('hide-modal')">
|
||||||
<template #header>
|
<template #header>
|
||||||
<h3 class="heading">{{ $t("edit_folder") }}</h3>
|
<h3 class="heading">{{ $t("folder.edit") }}</h3>
|
||||||
<div>
|
<div>
|
||||||
<ButtonSecondary icon="close" @click.native="hideModal" />
|
<ButtonSecondary icon="close" @click.native="hideModal" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template #body>
|
<template #body>
|
||||||
<div class="px-2 flex flex-col">
|
<div class="flex flex-col px-2">
|
||||||
<label
|
<label for="selectLabelGqlEditFolder" class="font-semibold px-4 pb-4">
|
||||||
for="selectLabelGqlEditFolder"
|
|
||||||
class="px-4 font-semibold pb-4 text-xs"
|
|
||||||
>
|
|
||||||
{{ $t("label") }}
|
{{ $t("label") }}
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
|
|||||||
@@ -7,11 +7,8 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template #body>
|
<template #body>
|
||||||
<div class="px-2 flex flex-col">
|
<div class="flex flex-col px-2">
|
||||||
<label
|
<label for="selectLabelGqlEditReq" class="font-semibold px-4 pb-4">
|
||||||
for="selectLabelGqlEditReq"
|
|
||||||
class="px-4 font-semibold pb-4 text-xs"
|
|
||||||
>
|
|
||||||
{{ $t("label") }}
|
{{ $t("label") }}
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
|
|||||||
@@ -10,32 +10,24 @@
|
|||||||
@dragend="dragging = false"
|
@dragend="dragging = false"
|
||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
class="
|
class="cursor-pointer flex w-10 justify-center items-center truncate"
|
||||||
flex
|
|
||||||
justify-center
|
|
||||||
items-center
|
|
||||||
text-xs
|
|
||||||
w-10
|
|
||||||
truncate
|
|
||||||
cursor-pointer
|
|
||||||
"
|
|
||||||
@click="toggleShowChildren()"
|
@click="toggleShowChildren()"
|
||||||
>
|
>
|
||||||
<i class="material-icons" :class="{ 'text-green-400': isSelected }">
|
<i class="material-icons" :class="{ 'text-green-500': isSelected }">
|
||||||
{{ getCollectionIcon }}
|
{{ getCollectionIcon }}
|
||||||
</i>
|
</i>
|
||||||
</span>
|
</span>
|
||||||
<span
|
<span
|
||||||
class="
|
class="
|
||||||
py-3
|
|
||||||
cursor-pointer
|
cursor-pointer
|
||||||
pr-2
|
flex
|
||||||
flex flex-1
|
|
||||||
min-w-0
|
|
||||||
text-xs
|
|
||||||
group-hover:text-secondaryDark
|
|
||||||
transition
|
|
||||||
font-semibold
|
font-semibold
|
||||||
|
flex-1
|
||||||
|
min-w-0
|
||||||
|
py-2
|
||||||
|
pr-2
|
||||||
|
transition
|
||||||
|
group-hover:text-secondaryDark
|
||||||
"
|
"
|
||||||
@click="toggleShowChildren()"
|
@click="toggleShowChildren()"
|
||||||
>
|
>
|
||||||
@@ -46,7 +38,7 @@
|
|||||||
<ButtonSecondary
|
<ButtonSecondary
|
||||||
v-tippy="{ theme: 'tooltip' }"
|
v-tippy="{ theme: 'tooltip' }"
|
||||||
icon="create_new_folder"
|
icon="create_new_folder"
|
||||||
:title="$t('new_folder')"
|
:title="$t('folder.new')"
|
||||||
class="group-hover:inline-flex hidden"
|
class="group-hover:inline-flex hidden"
|
||||||
@click.native="$emit('add-folder', { folder, path: folderPath })"
|
@click.native="$emit('add-folder', { folder, path: folderPath })"
|
||||||
/>
|
/>
|
||||||
@@ -67,7 +59,7 @@
|
|||||||
</template>
|
</template>
|
||||||
<SmartItem
|
<SmartItem
|
||||||
icon="create_new_folder"
|
icon="create_new_folder"
|
||||||
:label="$t('new_folder')"
|
:label="$t('folder.new')"
|
||||||
@click.native="
|
@click.native="
|
||||||
$emit('add-folder', { folder, path: folderPath })
|
$emit('add-folder', { folder, path: folderPath })
|
||||||
$refs.options.tippy().hide()
|
$refs.options.tippy().hide()
|
||||||
@@ -83,6 +75,7 @@
|
|||||||
/>
|
/>
|
||||||
<SmartItem
|
<SmartItem
|
||||||
icon="delete"
|
icon="delete"
|
||||||
|
color="red"
|
||||||
:label="$t('delete')"
|
:label="$t('delete')"
|
||||||
@click.native="
|
@click.native="
|
||||||
confirmRemove = true
|
confirmRemove = true
|
||||||
@@ -91,11 +84,11 @@
|
|||||||
/>
|
/>
|
||||||
</tippy>
|
</tippy>
|
||||||
</div>
|
</div>
|
||||||
<div v-show="showChildren || isFiltered">
|
<div v-if="showChildren || isFiltered">
|
||||||
<CollectionsGraphqlFolder
|
<CollectionsGraphqlFolder
|
||||||
v-for="(subFolder, subFolderIndex) in folder.folders"
|
v-for="(subFolder, subFolderIndex) in folder.folders"
|
||||||
:key="`subFolder-${subFolderIndex}`"
|
:key="`subFolder-${subFolderIndex}`"
|
||||||
class="ml-5 border-l border-dividerLight"
|
class="border-l border-dividerLight ml-5"
|
||||||
:picked="picked"
|
:picked="picked"
|
||||||
:saving-mode="savingMode"
|
:saving-mode="savingMode"
|
||||||
:folder="subFolder"
|
:folder="subFolder"
|
||||||
@@ -112,7 +105,7 @@
|
|||||||
<CollectionsGraphqlRequest
|
<CollectionsGraphqlRequest
|
||||||
v-for="(request, index) in folder.requests"
|
v-for="(request, index) in folder.requests"
|
||||||
:key="`request-${index}`"
|
:key="`request-${index}`"
|
||||||
class="ml-5 border-l border-dividerLight"
|
class="border-l border-dividerLight ml-5"
|
||||||
:picked="picked"
|
:picked="picked"
|
||||||
:saving-mode="savingMode"
|
:saving-mode="savingMode"
|
||||||
:request="request"
|
:request="request"
|
||||||
@@ -133,25 +126,24 @@
|
|||||||
folder.requests.length === 0
|
folder.requests.length === 0
|
||||||
"
|
"
|
||||||
class="
|
class="
|
||||||
flex
|
|
||||||
items-center
|
|
||||||
text-secondaryLight
|
|
||||||
flex-col
|
|
||||||
p-4
|
|
||||||
justify-center
|
|
||||||
ml-5
|
|
||||||
border-l border-dividerLight
|
border-l border-dividerLight
|
||||||
|
flex flex-col
|
||||||
|
text-secondaryLight
|
||||||
|
ml-5
|
||||||
|
p-4
|
||||||
|
items-center
|
||||||
|
justify-center
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
<i class="material-icons opacity-50 pb-2">folder_open</i>
|
<i class="opacity-75 pb-2 material-icons">folder_open</i>
|
||||||
<span class="text-xs text-center">
|
<span class="text-center">
|
||||||
{{ $t("folder_empty") }}
|
{{ $t("empty.folder") }}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<SmartConfirmModal
|
<SmartConfirmModal
|
||||||
:show="confirmRemove"
|
:show="confirmRemove"
|
||||||
:title="$t('are_you_sure_remove_folder')"
|
:title="$t('confirm.remove_folder')"
|
||||||
@hide-modal="confirmRemove = false"
|
@hide-modal="confirmRemove = false"
|
||||||
@resolve="removeFolder"
|
@resolve="removeFolder"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
</template>
|
</template>
|
||||||
<SmartItem
|
<SmartItem
|
||||||
icon="assignment_returned"
|
icon="assignment_returned"
|
||||||
:label="$t('import_from_gist')"
|
:label="$t('import.from_gist')"
|
||||||
@click.native="
|
@click.native="
|
||||||
readCollectionGist
|
readCollectionGist
|
||||||
$refs.options.tippy().hide()
|
$refs.options.tippy().hide()
|
||||||
@@ -30,9 +30,9 @@
|
|||||||
v-tippy="{ theme: 'tooltip' }"
|
v-tippy="{ theme: 'tooltip' }"
|
||||||
:title="
|
:title="
|
||||||
!currentUser
|
!currentUser
|
||||||
? $t('login_with_github_to') + $t('create_secret_gist')
|
? $t('export.require_github')
|
||||||
: currentUser.provider !== 'github.com'
|
: currentUser.provider !== 'github.com'
|
||||||
? $t('login_with_github_to') + $t('create_secret_gist')
|
? $t('export.require_github')
|
||||||
: null
|
: null
|
||||||
"
|
"
|
||||||
:disabled="
|
:disabled="
|
||||||
@@ -43,7 +43,7 @@
|
|||||||
: false
|
: false
|
||||||
"
|
"
|
||||||
icon="assignment_turned_in"
|
icon="assignment_turned_in"
|
||||||
:label="$t('create_secret_gist')"
|
:label="$t('export.create_secret_gist')"
|
||||||
@click.native="
|
@click.native="
|
||||||
createCollectionGist
|
createCollectionGist
|
||||||
$refs.options.tippy().hide()
|
$refs.options.tippy().hide()
|
||||||
@@ -74,7 +74,7 @@
|
|||||||
v-tippy="{ theme: 'tooltip' }"
|
v-tippy="{ theme: 'tooltip' }"
|
||||||
:title="$t('preserve_current')"
|
:title="$t('preserve_current')"
|
||||||
icon="create_new_folder"
|
icon="create_new_folder"
|
||||||
:label="$t('import_json')"
|
:label="$t('import.json')"
|
||||||
@click.native="openDialogChooseFileToImportFrom"
|
@click.native="openDialogChooseFileToImportFrom"
|
||||||
/>
|
/>
|
||||||
<input
|
<input
|
||||||
@@ -89,7 +89,7 @@
|
|||||||
v-tippy="{ theme: 'tooltip' }"
|
v-tippy="{ theme: 'tooltip' }"
|
||||||
:title="$t('download_file')"
|
:title="$t('download_file')"
|
||||||
icon="drive_file_move"
|
icon="drive_file_move"
|
||||||
:label="$t('export_as_json')"
|
:label="$t('export.as_json')"
|
||||||
@click.native="exportJSON"
|
@click.native="exportJSON"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@@ -140,7 +140,7 @@ export default {
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
this.$toast.success(this.$t("gist_created"), {
|
this.$toast.success(this.$t("export.gist_created"), {
|
||||||
icon: "done",
|
icon: "done",
|
||||||
})
|
})
|
||||||
window.open(res.html_url)
|
window.open(res.html_url)
|
||||||
@@ -153,7 +153,7 @@ export default {
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
async readCollectionGist() {
|
async readCollectionGist() {
|
||||||
const gist = prompt(this.$t("enter_gist_url"))
|
const gist = prompt(this.$t("import.gist_url"))
|
||||||
if (!gist) return
|
if (!gist) return
|
||||||
await this.$axios
|
await this.$axios
|
||||||
.$get(`https://api.github.com/gists/${gist.split("/").pop()}`, {
|
.$get(`https://api.github.com/gists/${gist.split("/").pop()}`, {
|
||||||
@@ -243,22 +243,22 @@ export default {
|
|||||||
this.$refs.inputChooseFileToImportFrom.value = ""
|
this.$refs.inputChooseFileToImportFrom.value = ""
|
||||||
},
|
},
|
||||||
exportJSON() {
|
exportJSON() {
|
||||||
let text = this.collectionJson
|
const dataToWrite = this.collectionJson
|
||||||
text = text.replace(/\n/g, "\r\n")
|
const file = new Blob([dataToWrite], { type: "application/json" })
|
||||||
const blob = new Blob([text], {
|
const a = document.createElement("a")
|
||||||
type: "text/json",
|
const url = URL.createObjectURL(file)
|
||||||
})
|
a.href = url
|
||||||
const anchor = document.createElement("a")
|
// TODO get uri from meta
|
||||||
anchor.download = "hoppscotch-collection.json"
|
a.download = `${url.split("/").pop().split("#")[0].split("?")[0]}`
|
||||||
anchor.href = window.URL.createObjectURL(blob)
|
document.body.appendChild(a)
|
||||||
anchor.target = "_blank"
|
a.click()
|
||||||
anchor.style.display = "none"
|
|
||||||
document.body.appendChild(anchor)
|
|
||||||
anchor.click()
|
|
||||||
document.body.removeChild(anchor)
|
|
||||||
this.$toast.success(this.$t("download_started"), {
|
this.$toast.success(this.$t("download_started"), {
|
||||||
icon: "done",
|
icon: "done",
|
||||||
})
|
})
|
||||||
|
setTimeout(() => {
|
||||||
|
document.body.removeChild(a)
|
||||||
|
URL.revokeObjectURL(url)
|
||||||
|
}, 1000)
|
||||||
},
|
},
|
||||||
fileImported() {
|
fileImported() {
|
||||||
this.$toast.info(this.$t("file_imported"), {
|
this.$toast.info(this.$t("file_imported"), {
|
||||||
@@ -266,7 +266,7 @@ export default {
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
failedImport() {
|
failedImport() {
|
||||||
this.$toast.error(this.$t("import_failed"), {
|
this.$toast.error(this.$t("import.failed"), {
|
||||||
icon: "error",
|
icon: "error",
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -10,33 +10,32 @@
|
|||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
class="
|
class="
|
||||||
font-mono font-bold
|
cursor-pointer
|
||||||
flex
|
flex
|
||||||
|
font-mono font-bold
|
||||||
|
mx-2
|
||||||
|
w-12
|
||||||
justify-center
|
justify-center
|
||||||
items-center
|
items-center
|
||||||
text-xs
|
|
||||||
w-12
|
|
||||||
mx-2
|
|
||||||
truncate
|
truncate
|
||||||
cursor-pointer
|
|
||||||
"
|
"
|
||||||
@click="!doc ? selectRequest() : {}"
|
@click="!doc ? selectRequest() : {}"
|
||||||
>
|
>
|
||||||
<i class="material-icons" :class="{ 'text-green-400': isSelected }">
|
<i class="material-icons" :class="{ 'text-green-500': isSelected }">
|
||||||
{{ isSelected ? "check_circle" : "description" }}
|
{{ isSelected ? "check_circle" : "description" }}
|
||||||
</i>
|
</i>
|
||||||
</span>
|
</span>
|
||||||
<span
|
<span
|
||||||
class="
|
class="
|
||||||
py-3
|
|
||||||
cursor-pointer
|
cursor-pointer
|
||||||
pr-2
|
flex
|
||||||
flex flex-1
|
|
||||||
min-w-0
|
|
||||||
text-xs
|
|
||||||
group-hover:text-secondaryDark
|
|
||||||
transition
|
|
||||||
font-semibold
|
font-semibold
|
||||||
|
flex-1
|
||||||
|
min-w-0
|
||||||
|
py-2
|
||||||
|
pr-2
|
||||||
|
transition
|
||||||
|
group-hover:text-secondaryDark
|
||||||
"
|
"
|
||||||
@click="!doc ? selectRequest() : {}"
|
@click="!doc ? selectRequest() : {}"
|
||||||
>
|
>
|
||||||
@@ -79,6 +78,7 @@
|
|||||||
/>
|
/>
|
||||||
<SmartItem
|
<SmartItem
|
||||||
icon="delete"
|
icon="delete"
|
||||||
|
color="red"
|
||||||
:label="$t('delete')"
|
:label="$t('delete')"
|
||||||
@click.native="
|
@click.native="
|
||||||
confirmRemove = true
|
confirmRemove = true
|
||||||
@@ -89,7 +89,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<SmartConfirmModal
|
<SmartConfirmModal
|
||||||
:show="confirmRemove"
|
:show="confirmRemove"
|
||||||
:title="$t('are_you_sure_remove_request')"
|
:title="$t('confirm.remove_request')"
|
||||||
@hide-modal="confirmRemove = false"
|
@hide-modal="confirmRemove = false"
|
||||||
@resolve="removeRequest"
|
@resolve="removeRequest"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -1,29 +1,32 @@
|
|||||||
<template>
|
<template>
|
||||||
<AppSection
|
<AppSection
|
||||||
label="collections"
|
label="collections"
|
||||||
:class="{ 'rounded-lg border-2 border-divider': savingMode }"
|
:class="{ 'rounded border border-divider': savingMode }"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="flex flex-col sticky top-10 z-10"
|
class="flex flex-col top-8 z-10 sticky"
|
||||||
:class="{ 'bg-primary': !savingMode }"
|
:class="{ 'bg-primary': !savingMode }"
|
||||||
>
|
>
|
||||||
|
<div v-if="showCollActions" class="search-wrapper">
|
||||||
<input
|
<input
|
||||||
v-if="showCollActions"
|
|
||||||
v-model="filterText"
|
v-model="filterText"
|
||||||
type="search"
|
type="search"
|
||||||
:placeholder="$t('search')"
|
:placeholder="$t('search')"
|
||||||
class="
|
class="
|
||||||
px-4
|
|
||||||
py-3
|
|
||||||
text-xs
|
|
||||||
border-b border-dividerLight
|
|
||||||
flex flex-1
|
|
||||||
font-medium
|
|
||||||
bg-primaryLight
|
bg-primaryLight
|
||||||
|
border-b border-dividerLight
|
||||||
|
flex
|
||||||
|
font-semibold font-mono
|
||||||
|
w-full
|
||||||
|
py-2
|
||||||
|
pr-2
|
||||||
|
pl-9
|
||||||
focus:outline-none
|
focus:outline-none
|
||||||
|
truncate
|
||||||
"
|
"
|
||||||
/>
|
/>
|
||||||
<div class="border-b flex justify-between flex-1 border-dividerLight">
|
</div>
|
||||||
|
<div class="border-b border-dividerLight flex flex-1 justify-between">
|
||||||
<ButtonSecondary
|
<ButtonSecondary
|
||||||
icon="add"
|
icon="add"
|
||||||
:label="$t('new')"
|
:label="$t('new')"
|
||||||
@@ -32,7 +35,7 @@
|
|||||||
<ButtonSecondary
|
<ButtonSecondary
|
||||||
v-if="showCollActions"
|
v-if="showCollActions"
|
||||||
v-tippy="{ theme: 'tooltip' }"
|
v-tippy="{ theme: 'tooltip' }"
|
||||||
:title="$t('import_export')"
|
:title="$t('modal.import_export')"
|
||||||
icon="import_export"
|
icon="import_export"
|
||||||
@click.native="displayModalImportExport(true)"
|
@click.native="displayModalImportExport(true)"
|
||||||
/>
|
/>
|
||||||
@@ -59,19 +62,24 @@
|
|||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
v-if="collections.length === 0"
|
v-if="collections.length === 0"
|
||||||
class="flex items-center text-secondaryLight flex-col p-4 justify-center"
|
class="flex flex-col text-secondaryLight p-4 items-center justify-center"
|
||||||
>
|
>
|
||||||
<i class="material-icons opacity-50 pb-2">create_new_folder</i>
|
<i class="opacity-75 pb-2 material-icons">create_new_folder</i>
|
||||||
<span class="text-xs text-center">
|
<span class="text-center pb-4">
|
||||||
{{ $t("create_new_collection") }}
|
{{ $t("empty.collections") }}
|
||||||
</span>
|
</span>
|
||||||
|
<ButtonSecondary
|
||||||
|
:label="$t('add.new')"
|
||||||
|
outline
|
||||||
|
@click.native="displayModalAdd(true)"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
v-if="!(filteredCollections.length !== 0 || collections.length === 0)"
|
v-if="!(filteredCollections.length !== 0 || collections.length === 0)"
|
||||||
class="flex items-center text-secondaryLight flex-col p-4 justify-center"
|
class="flex flex-col text-secondaryLight p-4 items-center justify-center"
|
||||||
>
|
>
|
||||||
<i class="material-icons opacity-50 pb-2">manage_search</i>
|
<i class="opacity-75 pb-2 material-icons">manage_search</i>
|
||||||
<span class="text-xs text-center">
|
<span class="text-center">
|
||||||
{{ $t("nothing_found") }} "{{ filterText }}"
|
{{ $t("nothing_found") }} "{{ filterText }}"
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,28 +1,31 @@
|
|||||||
<template>
|
<template>
|
||||||
<AppSection
|
<AppSection
|
||||||
label="collections"
|
label="collections"
|
||||||
:class="{ 'rounded-lg border-2 border-divider': saveRequest }"
|
:class="{ 'rounded border border-divider': saveRequest }"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="flex flex-col sticky z-10 top-0 bg-primary"
|
class="bg-primary rounded-t flex flex-col top-0 z-10 sticky"
|
||||||
:class="{ '!top-10': !saveRequest && !doc }"
|
:class="{ '!top-8': !saveRequest && !doc }"
|
||||||
>
|
>
|
||||||
|
<div v-if="!saveRequest" class="search-wrapper">
|
||||||
<input
|
<input
|
||||||
v-if="!saveRequest"
|
|
||||||
v-model="filterText"
|
v-model="filterText"
|
||||||
type="search"
|
type="search"
|
||||||
:placeholder="$t('search')"
|
:placeholder="$t('search')"
|
||||||
class="
|
class="
|
||||||
px-4
|
|
||||||
py-3
|
|
||||||
text-xs
|
|
||||||
border-b border-dividerLight
|
|
||||||
flex flex-1
|
|
||||||
font-medium
|
|
||||||
bg-primaryLight
|
bg-primaryLight
|
||||||
|
border-b border-dividerLight
|
||||||
|
flex
|
||||||
|
font-semibold font-mono
|
||||||
|
w-full
|
||||||
|
py-2
|
||||||
|
pr-2
|
||||||
|
pl-9
|
||||||
focus:outline-none
|
focus:outline-none
|
||||||
|
truncate
|
||||||
"
|
"
|
||||||
/>
|
/>
|
||||||
|
</div>
|
||||||
<CollectionsChooseType
|
<CollectionsChooseType
|
||||||
:collections-type="collectionsType"
|
:collections-type="collectionsType"
|
||||||
:show="showTeamCollections"
|
:show="showTeamCollections"
|
||||||
@@ -30,7 +33,7 @@
|
|||||||
@update-collection-type="updateCollectionType"
|
@update-collection-type="updateCollectionType"
|
||||||
@update-selected-team="updateSelectedTeam"
|
@update-selected-team="updateSelectedTeam"
|
||||||
/>
|
/>
|
||||||
<div class="border-b flex justify-between flex-1 border-dividerLight">
|
<div class="border-b border-dividerLight flex flex-1 justify-between">
|
||||||
<ButtonSecondary
|
<ButtonSecondary
|
||||||
v-if="
|
v-if="
|
||||||
collectionsType.type == 'team-collections' &&
|
collectionsType.type == 'team-collections' &&
|
||||||
@@ -40,7 +43,7 @@
|
|||||||
v-tippy="{ theme: 'tooltip' }"
|
v-tippy="{ theme: 'tooltip' }"
|
||||||
disabled
|
disabled
|
||||||
icon="add"
|
icon="add"
|
||||||
:title="$t('disable_new_collection')"
|
:title="$t('team.no_access')"
|
||||||
:label="$t('new')"
|
:label="$t('new')"
|
||||||
/>
|
/>
|
||||||
<ButtonSecondary
|
<ButtonSecondary
|
||||||
@@ -57,7 +60,7 @@
|
|||||||
collectionsType.selectedTeam == undefined
|
collectionsType.selectedTeam == undefined
|
||||||
"
|
"
|
||||||
icon="import_export"
|
icon="import_export"
|
||||||
:title="$t('import_export')"
|
:title="$t('modal.import_export')"
|
||||||
@click.native="displayModalImportExport(true)"
|
@click.native="displayModalImportExport(true)"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@@ -94,19 +97,37 @@
|
|||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
v-if="collections.length === 0"
|
v-if="collections.length === 0"
|
||||||
class="flex items-center text-secondaryLight flex-col p-4 justify-center"
|
class="flex flex-col text-secondaryLight p-4 items-center justify-center"
|
||||||
>
|
>
|
||||||
<i class="material-icons opacity-50 pb-2">create_new_folder</i>
|
<i class="opacity-75 pb-2 material-icons">create_new_folder</i>
|
||||||
<span class="text-xs text-center">
|
<span class="text-center pb-4">
|
||||||
{{ $t("create_new_collection") }}
|
{{ $t("empty.collections") }}
|
||||||
</span>
|
</span>
|
||||||
|
<ButtonSecondary
|
||||||
|
v-if="
|
||||||
|
collectionsType.type == 'team-collections' &&
|
||||||
|
(collectionsType.selectedTeam == undefined ||
|
||||||
|
collectionsType.selectedTeam.myRole == 'VIEWER')
|
||||||
|
"
|
||||||
|
v-tippy="{ theme: 'tooltip' }"
|
||||||
|
disabled
|
||||||
|
:title="$t('team.no_access')"
|
||||||
|
:label="$t('add.new')"
|
||||||
|
outline
|
||||||
|
/>
|
||||||
|
<ButtonSecondary
|
||||||
|
v-else
|
||||||
|
outline
|
||||||
|
:label="$t('add.new')"
|
||||||
|
@click.native="displayModalAdd(true)"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
v-if="!(filteredCollections.length !== 0 || collections.length === 0)"
|
v-if="!(filteredCollections.length !== 0 || collections.length === 0)"
|
||||||
class="flex items-center text-secondaryLight flex-col p-4 justify-center"
|
class="flex flex-col text-secondaryLight p-4 items-center justify-center"
|
||||||
>
|
>
|
||||||
<i class="material-icons opacity-50 pb-2">manage_search</i>
|
<i class="opacity-75 pb-2 material-icons">manage_search</i>
|
||||||
<span class="text-xs text-center">
|
<span class="text-center">
|
||||||
{{ $t("nothing_found") }} "{{ filterText }}"
|
{{ $t("nothing_found") }} "{{ filterText }}"
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
@@ -292,7 +313,7 @@ export default {
|
|||||||
// Intented to be called by the CollectionAdd modal submit event
|
// Intented to be called by the CollectionAdd modal submit event
|
||||||
addNewRootCollection(name) {
|
addNewRootCollection(name) {
|
||||||
if (!name) {
|
if (!name) {
|
||||||
this.$toast.info(this.$t("invalid_collection_name"))
|
this.$toast.info(this.$t("collection.invalid_name"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (this.collectionsType.type === "my-collections") {
|
if (this.collectionsType.type === "my-collections") {
|
||||||
@@ -312,7 +333,7 @@ export default {
|
|||||||
this.collectionsType.selectedTeam.id
|
this.collectionsType.selectedTeam.id
|
||||||
)
|
)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
this.$toast.success(this.$t("collection_added"), {
|
this.$toast.success(this.$t("collection.created"), {
|
||||||
icon: "done",
|
icon: "done",
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@@ -328,7 +349,7 @@ export default {
|
|||||||
// Intented to be called by CollectionEdit modal submit event
|
// Intented to be called by CollectionEdit modal submit event
|
||||||
updateEditingCollection(newName) {
|
updateEditingCollection(newName) {
|
||||||
if (!newName) {
|
if (!newName) {
|
||||||
this.$toast.info(this.$t("invalid_collection_name"))
|
this.$toast.info(this.$t("collection.invalid_name"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (this.collectionsType.type === "my-collections") {
|
if (this.collectionsType.type === "my-collections") {
|
||||||
@@ -371,7 +392,7 @@ export default {
|
|||||||
.renameCollection(this.$apollo, name, this.editingFolder.id)
|
.renameCollection(this.$apollo, name, this.editingFolder.id)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
// Result
|
// Result
|
||||||
this.$toast.success(this.$t("folder_renamed"), {
|
this.$toast.success(this.$t("folder.renamed"), {
|
||||||
icon: "done",
|
icon: "done",
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@@ -486,7 +507,7 @@ export default {
|
|||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
// Result
|
// Result
|
||||||
this.$toast.success(this.$t("folder_added"), {
|
this.$toast.success(this.$t("folder.created"), {
|
||||||
icon: "done",
|
icon: "done",
|
||||||
})
|
})
|
||||||
this.$emit("update-team-collections")
|
this.$emit("update-team-collections")
|
||||||
|
|||||||
@@ -10,32 +10,24 @@
|
|||||||
@dragend="dragging = false"
|
@dragend="dragging = false"
|
||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
class="
|
class="cursor-pointer flex w-10 justify-center items-center truncate"
|
||||||
flex
|
|
||||||
justify-center
|
|
||||||
items-center
|
|
||||||
text-xs
|
|
||||||
w-10
|
|
||||||
truncate
|
|
||||||
cursor-pointer
|
|
||||||
"
|
|
||||||
@click="toggleShowChildren()"
|
@click="toggleShowChildren()"
|
||||||
>
|
>
|
||||||
<i class="material-icons" :class="{ 'text-green-400': isSelected }">
|
<i class="material-icons" :class="{ 'text-green-500': isSelected }">
|
||||||
{{ getCollectionIcon }}
|
{{ getCollectionIcon }}
|
||||||
</i>
|
</i>
|
||||||
</span>
|
</span>
|
||||||
<span
|
<span
|
||||||
class="
|
class="
|
||||||
py-3
|
|
||||||
cursor-pointer
|
cursor-pointer
|
||||||
pr-2
|
flex
|
||||||
flex flex-1
|
|
||||||
min-w-0
|
|
||||||
text-xs
|
|
||||||
group-hover:text-secondaryDark
|
|
||||||
transition
|
|
||||||
font-semibold
|
font-semibold
|
||||||
|
flex-1
|
||||||
|
min-w-0
|
||||||
|
py-2
|
||||||
|
pr-2
|
||||||
|
transition
|
||||||
|
group-hover:text-secondaryDark
|
||||||
"
|
"
|
||||||
@click="toggleShowChildren()"
|
@click="toggleShowChildren()"
|
||||||
>
|
>
|
||||||
@@ -44,8 +36,9 @@
|
|||||||
<ButtonSecondary
|
<ButtonSecondary
|
||||||
v-if="doc && !selected"
|
v-if="doc && !selected"
|
||||||
v-tippy="{ theme: 'tooltip' }"
|
v-tippy="{ theme: 'tooltip' }"
|
||||||
:title="$t('import')"
|
:title="$t('import.title')"
|
||||||
icon="check_box_outline_blank"
|
icon="check_box_outline_blank"
|
||||||
|
color="green"
|
||||||
@click.native="$emit('select-collection')"
|
@click.native="$emit('select-collection')"
|
||||||
/>
|
/>
|
||||||
<ButtonSecondary
|
<ButtonSecondary
|
||||||
@@ -53,12 +46,14 @@
|
|||||||
v-tippy="{ theme: 'tooltip' }"
|
v-tippy="{ theme: 'tooltip' }"
|
||||||
:title="$t('delete')"
|
:title="$t('delete')"
|
||||||
icon="check_box"
|
icon="check_box"
|
||||||
|
color="green"
|
||||||
@click.native="$emit('unselect-collection')"
|
@click.native="$emit('unselect-collection')"
|
||||||
/>
|
/>
|
||||||
<ButtonSecondary
|
<ButtonSecondary
|
||||||
|
v-if="!doc"
|
||||||
v-tippy="{ theme: 'tooltip' }"
|
v-tippy="{ theme: 'tooltip' }"
|
||||||
icon="create_new_folder"
|
icon="create_new_folder"
|
||||||
:title="$t('new_folder')"
|
:title="$t('folder.new')"
|
||||||
class="group-hover:inline-flex hidden"
|
class="group-hover:inline-flex hidden"
|
||||||
@click.native="
|
@click.native="
|
||||||
$emit('add-folder', {
|
$emit('add-folder', {
|
||||||
@@ -84,7 +79,7 @@
|
|||||||
</template>
|
</template>
|
||||||
<SmartItem
|
<SmartItem
|
||||||
icon="create_new_folder"
|
icon="create_new_folder"
|
||||||
:label="$t('new_folder')"
|
:label="$t('folder.new')"
|
||||||
@click.native="
|
@click.native="
|
||||||
$emit('add-folder', {
|
$emit('add-folder', {
|
||||||
folder: collection,
|
folder: collection,
|
||||||
@@ -103,6 +98,7 @@
|
|||||||
/>
|
/>
|
||||||
<SmartItem
|
<SmartItem
|
||||||
icon="delete"
|
icon="delete"
|
||||||
|
color="red"
|
||||||
:label="$t('delete')"
|
:label="$t('delete')"
|
||||||
@click.native="
|
@click.native="
|
||||||
confirmRemove = true
|
confirmRemove = true
|
||||||
@@ -111,11 +107,11 @@
|
|||||||
/>
|
/>
|
||||||
</tippy>
|
</tippy>
|
||||||
</div>
|
</div>
|
||||||
<div v-show="showChildren || isFiltered">
|
<div v-if="showChildren || isFiltered">
|
||||||
<CollectionsMyFolder
|
<CollectionsMyFolder
|
||||||
v-for="(folder, index) in collection.folders"
|
v-for="(folder, index) in collection.folders"
|
||||||
:key="`folder-${index}`"
|
:key="`folder-${index}`"
|
||||||
class="ml-5 border-l border-dividerLight"
|
class="border-l border-dividerLight ml-5"
|
||||||
:folder="folder"
|
:folder="folder"
|
||||||
:folder-index="index"
|
:folder-index="index"
|
||||||
:folder-path="`${collectionIndex}/${index}`"
|
:folder-path="`${collectionIndex}/${index}`"
|
||||||
@@ -134,7 +130,7 @@
|
|||||||
<CollectionsMyRequest
|
<CollectionsMyRequest
|
||||||
v-for="(request, index) in collection.requests"
|
v-for="(request, index) in collection.requests"
|
||||||
:key="`request-${index}`"
|
:key="`request-${index}`"
|
||||||
class="ml-5 border-l border-dividerLight"
|
class="border-l border-dividerLight ml-5"
|
||||||
:request="request"
|
:request="request"
|
||||||
:collection-index="collectionIndex"
|
:collection-index="collectionIndex"
|
||||||
:folder-index="-1"
|
:folder-index="-1"
|
||||||
@@ -156,25 +152,24 @@
|
|||||||
(collection.requests == undefined || collection.requests.length === 0)
|
(collection.requests == undefined || collection.requests.length === 0)
|
||||||
"
|
"
|
||||||
class="
|
class="
|
||||||
flex
|
|
||||||
items-center
|
|
||||||
text-secondaryLight
|
|
||||||
flex-col
|
|
||||||
p-4
|
|
||||||
justify-center
|
|
||||||
ml-5
|
|
||||||
border-l border-dividerLight
|
border-l border-dividerLight
|
||||||
|
flex flex-col
|
||||||
|
text-secondaryLight
|
||||||
|
ml-5
|
||||||
|
p-4
|
||||||
|
items-center
|
||||||
|
justify-center
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
<i class="material-icons opacity-50 pb-2">folder_open</i>
|
<i class="opacity-75 pb-2 material-icons">folder_open</i>
|
||||||
<span class="text-xs text-center">
|
<span class="text-center">
|
||||||
{{ $t("collection_empty") }}
|
{{ $t("empty.collection") }}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<SmartConfirmModal
|
<SmartConfirmModal
|
||||||
:show="confirmRemove"
|
:show="confirmRemove"
|
||||||
:title="$t('are_you_sure_remove_collection')"
|
:title="$t('confirm.remove_collection')"
|
||||||
@hide-modal="confirmRemove = false"
|
@hide-modal="confirmRemove = false"
|
||||||
@resolve="removeCollection"
|
@resolve="removeCollection"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -10,32 +10,24 @@
|
|||||||
@dragend="dragging = false"
|
@dragend="dragging = false"
|
||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
class="
|
class="cursor-pointer flex w-10 justify-center items-center truncate"
|
||||||
flex
|
|
||||||
justify-center
|
|
||||||
items-center
|
|
||||||
text-xs
|
|
||||||
w-10
|
|
||||||
truncate
|
|
||||||
cursor-pointer
|
|
||||||
"
|
|
||||||
@click="toggleShowChildren()"
|
@click="toggleShowChildren()"
|
||||||
>
|
>
|
||||||
<i class="material-icons" :class="{ 'text-green-400': isSelected }">
|
<i class="material-icons" :class="{ 'text-green-500': isSelected }">
|
||||||
{{ getCollectionIcon }}
|
{{ getCollectionIcon }}
|
||||||
</i>
|
</i>
|
||||||
</span>
|
</span>
|
||||||
<span
|
<span
|
||||||
class="
|
class="
|
||||||
py-3
|
|
||||||
cursor-pointer
|
cursor-pointer
|
||||||
pr-2
|
flex
|
||||||
flex flex-1
|
|
||||||
min-w-0
|
|
||||||
text-xs
|
|
||||||
group-hover:text-secondaryDark
|
|
||||||
transition
|
|
||||||
font-semibold
|
font-semibold
|
||||||
|
flex-1
|
||||||
|
min-w-0
|
||||||
|
py-2
|
||||||
|
pr-2
|
||||||
|
transition
|
||||||
|
group-hover:text-secondaryDark
|
||||||
"
|
"
|
||||||
@click="toggleShowChildren()"
|
@click="toggleShowChildren()"
|
||||||
>
|
>
|
||||||
@@ -46,7 +38,7 @@
|
|||||||
<ButtonSecondary
|
<ButtonSecondary
|
||||||
v-tippy="{ theme: 'tooltip' }"
|
v-tippy="{ theme: 'tooltip' }"
|
||||||
icon="create_new_folder"
|
icon="create_new_folder"
|
||||||
:title="$t('new_folder')"
|
:title="$t('folder.new')"
|
||||||
class="group-hover:inline-flex hidden"
|
class="group-hover:inline-flex hidden"
|
||||||
@click.native="$emit('add-folder', { folder, path: folderPath })"
|
@click.native="$emit('add-folder', { folder, path: folderPath })"
|
||||||
/>
|
/>
|
||||||
@@ -67,7 +59,7 @@
|
|||||||
</template>
|
</template>
|
||||||
<SmartItem
|
<SmartItem
|
||||||
icon="create_new_folder"
|
icon="create_new_folder"
|
||||||
:label="$t('new_folder')"
|
:label="$t('folder.new')"
|
||||||
@click.native="
|
@click.native="
|
||||||
$emit('add-folder', { folder, path: folderPath })
|
$emit('add-folder', { folder, path: folderPath })
|
||||||
$refs.options.tippy().hide()
|
$refs.options.tippy().hide()
|
||||||
@@ -88,6 +80,7 @@
|
|||||||
/>
|
/>
|
||||||
<SmartItem
|
<SmartItem
|
||||||
icon="delete"
|
icon="delete"
|
||||||
|
color="red"
|
||||||
:label="$t('delete')"
|
:label="$t('delete')"
|
||||||
@click.native="
|
@click.native="
|
||||||
confirmRemove = true
|
confirmRemove = true
|
||||||
@@ -96,11 +89,11 @@
|
|||||||
/>
|
/>
|
||||||
</tippy>
|
</tippy>
|
||||||
</div>
|
</div>
|
||||||
<div v-show="showChildren || isFiltered">
|
<div v-if="showChildren || isFiltered">
|
||||||
<CollectionsMyFolder
|
<CollectionsMyFolder
|
||||||
v-for="(subFolder, subFolderIndex) in folder.folders"
|
v-for="(subFolder, subFolderIndex) in folder.folders"
|
||||||
:key="`subFolder-${subFolderIndex}`"
|
:key="`subFolder-${subFolderIndex}`"
|
||||||
class="ml-5 border-l border-dividerLight"
|
class="border-l border-dividerLight ml-5"
|
||||||
:folder="subFolder"
|
:folder="subFolder"
|
||||||
:folder-index="subFolderIndex"
|
:folder-index="subFolderIndex"
|
||||||
:collection-index="collectionIndex"
|
:collection-index="collectionIndex"
|
||||||
@@ -119,7 +112,7 @@
|
|||||||
<CollectionsMyRequest
|
<CollectionsMyRequest
|
||||||
v-for="(request, index) in folder.requests"
|
v-for="(request, index) in folder.requests"
|
||||||
:key="`request-${index}`"
|
:key="`request-${index}`"
|
||||||
class="ml-5 border-l border-dividerLight"
|
class="border-l border-dividerLight ml-5"
|
||||||
:request="request"
|
:request="request"
|
||||||
:collection-index="collectionIndex"
|
:collection-index="collectionIndex"
|
||||||
:folder-index="folderIndex"
|
:folder-index="folderIndex"
|
||||||
@@ -142,25 +135,24 @@
|
|||||||
folder.requests.length === 0
|
folder.requests.length === 0
|
||||||
"
|
"
|
||||||
class="
|
class="
|
||||||
flex
|
|
||||||
items-center
|
|
||||||
text-secondaryLight
|
|
||||||
flex-col
|
|
||||||
p-4
|
|
||||||
justify-center
|
|
||||||
ml-5
|
|
||||||
border-l border-dividerLight
|
border-l border-dividerLight
|
||||||
|
flex flex-col
|
||||||
|
text-secondaryLight
|
||||||
|
ml-5
|
||||||
|
p-4
|
||||||
|
items-center
|
||||||
|
justify-center
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
<i class="material-icons opacity-50 pb-2">folder_open</i>
|
<i class="opacity-75 pb-2 material-icons">folder_open</i>
|
||||||
<span class="text-xs text-center">
|
<span class="text-center">
|
||||||
{{ $t("folder_empty") }}
|
{{ $t("empty.folder") }}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<SmartConfirmModal
|
<SmartConfirmModal
|
||||||
:show="confirmRemove"
|
:show="confirmRemove"
|
||||||
:title="$t('are_you_sure_remove_folder')"
|
:title="$t('confirm.remove_folder')"
|
||||||
@hide-modal="confirmRemove = false"
|
@hide-modal="confirmRemove = false"
|
||||||
@resolve="removeFolder"
|
@resolve="removeFolder"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -10,15 +10,14 @@
|
|||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
class="
|
class="
|
||||||
font-mono font-bold
|
cursor-pointer
|
||||||
flex
|
flex
|
||||||
|
font-mono font-bold
|
||||||
|
mx-2
|
||||||
|
w-12
|
||||||
justify-center
|
justify-center
|
||||||
items-center
|
items-center
|
||||||
text-xs
|
|
||||||
w-12
|
|
||||||
mx-2
|
|
||||||
truncate
|
truncate
|
||||||
cursor-pointer
|
|
||||||
"
|
"
|
||||||
:class="getRequestLabelColor(request.method)"
|
:class="getRequestLabelColor(request.method)"
|
||||||
@click="!doc ? selectRequest() : {}"
|
@click="!doc ? selectRequest() : {}"
|
||||||
@@ -26,7 +25,7 @@
|
|||||||
<i
|
<i
|
||||||
v-if="isSelected"
|
v-if="isSelected"
|
||||||
class="material-icons"
|
class="material-icons"
|
||||||
:class="{ 'text-green-400': isSelected }"
|
:class="{ 'text-green-500': isSelected }"
|
||||||
>
|
>
|
||||||
check_circle
|
check_circle
|
||||||
</i>
|
</i>
|
||||||
@@ -36,22 +35,22 @@
|
|||||||
</span>
|
</span>
|
||||||
<span
|
<span
|
||||||
class="
|
class="
|
||||||
py-3
|
|
||||||
cursor-pointer
|
cursor-pointer
|
||||||
pr-2
|
flex
|
||||||
flex flex-1
|
|
||||||
min-w-0
|
|
||||||
text-xs
|
|
||||||
group-hover:text-secondaryDark
|
|
||||||
transition
|
|
||||||
font-semibold
|
font-semibold
|
||||||
|
flex-1
|
||||||
|
min-w-0
|
||||||
|
py-2
|
||||||
|
pr-2
|
||||||
|
transition
|
||||||
|
group-hover:text-secondaryDark
|
||||||
"
|
"
|
||||||
@click="!doc ? selectRequest() : {}"
|
@click="!doc ? selectRequest() : {}"
|
||||||
>
|
>
|
||||||
<span class="truncate"> {{ request.name }} </span>
|
<span class="truncate"> {{ request.name }} </span>
|
||||||
</span>
|
</span>
|
||||||
<ButtonSecondary
|
<ButtonSecondary
|
||||||
v-if="!saveRequest"
|
v-if="!saveRequest && !doc"
|
||||||
v-tippy="{ theme: 'tooltip' }"
|
v-tippy="{ theme: 'tooltip' }"
|
||||||
icon="replay"
|
icon="replay"
|
||||||
:title="$t('restore')"
|
:title="$t('restore')"
|
||||||
@@ -90,6 +89,7 @@
|
|||||||
/>
|
/>
|
||||||
<SmartItem
|
<SmartItem
|
||||||
icon="delete"
|
icon="delete"
|
||||||
|
color="red"
|
||||||
:label="$t('delete')"
|
:label="$t('delete')"
|
||||||
@click.native="
|
@click.native="
|
||||||
confirmRemove = true
|
confirmRemove = true
|
||||||
@@ -100,7 +100,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<SmartConfirmModal
|
<SmartConfirmModal
|
||||||
:show="confirmRemove"
|
:show="confirmRemove"
|
||||||
:title="$t('are_you_sure_remove_request')"
|
:title="$t('confirm.remove_request')"
|
||||||
@hide-modal="confirmRemove = false"
|
@hide-modal="confirmRemove = false"
|
||||||
@resolve="removeRequest"
|
@resolve="removeRequest"
|
||||||
/>
|
/>
|
||||||
@@ -108,6 +108,8 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import { translateToNewRequest } from "~/helpers/types/HoppRESTRequest"
|
||||||
|
import { setRESTRequest } from "~/newstore/RESTSession"
|
||||||
export default {
|
export default {
|
||||||
props: {
|
props: {
|
||||||
request: { type: Object, default: () => {} },
|
request: { type: Object, default: () => {} },
|
||||||
@@ -126,11 +128,11 @@ export default {
|
|||||||
return {
|
return {
|
||||||
dragging: false,
|
dragging: false,
|
||||||
requestMethodLabels: {
|
requestMethodLabels: {
|
||||||
get: "text-green-400",
|
get: "text-green-500",
|
||||||
post: "text-yellow-400",
|
post: "text-yellow-500",
|
||||||
put: "text-blue-400",
|
put: "text-blue-500",
|
||||||
delete: "text-red-400",
|
delete: "text-red-500",
|
||||||
default: "text-gray-400",
|
default: "text-gray-500",
|
||||||
},
|
},
|
||||||
confirmRemove: false,
|
confirmRemove: false,
|
||||||
}
|
}
|
||||||
@@ -157,8 +159,7 @@ export default {
|
|||||||
requestIndex: this.requestIndex,
|
requestIndex: this.requestIndex,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
else
|
else setRESTRequest(translateToNewRequest(this.request))
|
||||||
this.$store.commit("postwoman/selectRequest", { request: this.request })
|
|
||||||
},
|
},
|
||||||
dragStart({ dataTransfer }) {
|
dragStart({ dataTransfer }) {
|
||||||
this.dragging = !this.dragging
|
this.dragging = !this.dragging
|
||||||
|
|||||||
@@ -2,32 +2,24 @@
|
|||||||
<div class="flex flex-col">
|
<div class="flex flex-col">
|
||||||
<div class="flex items-center group">
|
<div class="flex items-center group">
|
||||||
<span
|
<span
|
||||||
class="
|
class="cursor-pointer flex w-10 justify-center items-center truncate"
|
||||||
flex
|
|
||||||
justify-center
|
|
||||||
items-center
|
|
||||||
text-xs
|
|
||||||
w-10
|
|
||||||
truncate
|
|
||||||
cursor-pointer
|
|
||||||
"
|
|
||||||
@click="toggleShowChildren()"
|
@click="toggleShowChildren()"
|
||||||
>
|
>
|
||||||
<i class="material-icons" :class="{ 'text-green-400': isSelected }">
|
<i class="material-icons" :class="{ 'text-green-500': isSelected }">
|
||||||
{{ getCollectionIcon }}
|
{{ getCollectionIcon }}
|
||||||
</i>
|
</i>
|
||||||
</span>
|
</span>
|
||||||
<span
|
<span
|
||||||
class="
|
class="
|
||||||
py-3
|
|
||||||
cursor-pointer
|
cursor-pointer
|
||||||
pr-2
|
flex
|
||||||
flex flex-1
|
|
||||||
min-w-0
|
|
||||||
text-xs
|
|
||||||
group-hover:text-secondaryDark
|
|
||||||
transition
|
|
||||||
font-semibold
|
font-semibold
|
||||||
|
flex-1
|
||||||
|
min-w-0
|
||||||
|
py-2
|
||||||
|
pr-2
|
||||||
|
transition
|
||||||
|
group-hover:text-secondaryDark
|
||||||
"
|
"
|
||||||
@click="toggleShowChildren()"
|
@click="toggleShowChildren()"
|
||||||
>
|
>
|
||||||
@@ -36,8 +28,9 @@
|
|||||||
<ButtonSecondary
|
<ButtonSecondary
|
||||||
v-if="doc && !selected"
|
v-if="doc && !selected"
|
||||||
v-tippy="{ theme: 'tooltip' }"
|
v-tippy="{ theme: 'tooltip' }"
|
||||||
:title="$t('import')"
|
:title="$t('import.title')"
|
||||||
icon="check_box_outline_blank"
|
icon="check_box_outline_blank"
|
||||||
|
color="green"
|
||||||
@click.native="$emit('select-collection')"
|
@click.native="$emit('select-collection')"
|
||||||
/>
|
/>
|
||||||
<ButtonSecondary
|
<ButtonSecondary
|
||||||
@@ -45,13 +38,14 @@
|
|||||||
v-tippy="{ theme: 'tooltip' }"
|
v-tippy="{ theme: 'tooltip' }"
|
||||||
:title="$t('delete')"
|
:title="$t('delete')"
|
||||||
icon="check_box"
|
icon="check_box"
|
||||||
|
color="green"
|
||||||
@click.native="$emit('unselect-collection')"
|
@click.native="$emit('unselect-collection')"
|
||||||
/>
|
/>
|
||||||
<ButtonSecondary
|
<ButtonSecondary
|
||||||
v-if="collectionsType.selectedTeam.myRole !== 'VIEWER'"
|
v-if="collectionsType.selectedTeam.myRole !== 'VIEWER'"
|
||||||
v-tippy="{ theme: 'tooltip' }"
|
v-tippy="{ theme: 'tooltip' }"
|
||||||
icon="create_new_folder"
|
icon="create_new_folder"
|
||||||
:title="$t('new_folder')"
|
:title="$t('folder.new')"
|
||||||
class="group-hover:inline-flex hidden"
|
class="group-hover:inline-flex hidden"
|
||||||
@click.native="
|
@click.native="
|
||||||
$emit('add-folder', {
|
$emit('add-folder', {
|
||||||
@@ -79,7 +73,7 @@
|
|||||||
<SmartItem
|
<SmartItem
|
||||||
v-if="collectionsType.selectedTeam.myRole !== 'VIEWER'"
|
v-if="collectionsType.selectedTeam.myRole !== 'VIEWER'"
|
||||||
icon="create_new_folder"
|
icon="create_new_folder"
|
||||||
:label="$t('new_folder')"
|
:label="$t('folder.new')"
|
||||||
@click.native="
|
@click.native="
|
||||||
$emit('add-folder', {
|
$emit('add-folder', {
|
||||||
folder: collection,
|
folder: collection,
|
||||||
@@ -100,6 +94,7 @@
|
|||||||
<SmartItem
|
<SmartItem
|
||||||
v-if="collectionsType.selectedTeam.myRole !== 'VIEWER'"
|
v-if="collectionsType.selectedTeam.myRole !== 'VIEWER'"
|
||||||
icon="delete"
|
icon="delete"
|
||||||
|
color="red"
|
||||||
:label="$t('delete')"
|
:label="$t('delete')"
|
||||||
@click.native="
|
@click.native="
|
||||||
confirmRemove = true
|
confirmRemove = true
|
||||||
@@ -108,11 +103,11 @@
|
|||||||
/>
|
/>
|
||||||
</tippy>
|
</tippy>
|
||||||
</div>
|
</div>
|
||||||
<div v-show="showChildren || isFiltered">
|
<div v-if="showChildren || isFiltered">
|
||||||
<CollectionsTeamsFolder
|
<CollectionsTeamsFolder
|
||||||
v-for="(folder, index) in collection.children"
|
v-for="(folder, index) in collection.children"
|
||||||
:key="`folder-${folder}`"
|
:key="`folder-${folder}`"
|
||||||
class="ml-5 border-l border-dividerLight"
|
class="border-l border-dividerLight ml-5"
|
||||||
:folder="folder"
|
:folder="folder"
|
||||||
:folder-index="index"
|
:folder-index="index"
|
||||||
:folder-path="`${collectionIndex}/${index}`"
|
:folder-path="`${collectionIndex}/${index}`"
|
||||||
@@ -132,7 +127,7 @@
|
|||||||
<CollectionsTeamsRequest
|
<CollectionsTeamsRequest
|
||||||
v-for="(request, index) in collection.requests"
|
v-for="(request, index) in collection.requests"
|
||||||
:key="`request-${index}`"
|
:key="`request-${index}`"
|
||||||
class="ml-5 border-l border-dividerLight"
|
class="border-l border-dividerLight ml-5"
|
||||||
:request="request.request"
|
:request="request.request"
|
||||||
:collection-index="collectionIndex"
|
:collection-index="collectionIndex"
|
||||||
:folder-index="-1"
|
:folder-index="-1"
|
||||||
@@ -153,25 +148,24 @@
|
|||||||
(collection.requests == undefined || collection.requests.length === 0)
|
(collection.requests == undefined || collection.requests.length === 0)
|
||||||
"
|
"
|
||||||
class="
|
class="
|
||||||
flex
|
|
||||||
items-center
|
|
||||||
text-secondaryLight
|
|
||||||
flex-col
|
|
||||||
p-4
|
|
||||||
justify-center
|
|
||||||
ml-5
|
|
||||||
border-l border-dividerLight
|
border-l border-dividerLight
|
||||||
|
flex flex-col
|
||||||
|
text-secondaryLight
|
||||||
|
ml-5
|
||||||
|
p-4
|
||||||
|
items-center
|
||||||
|
justify-center
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
<i class="material-icons opacity-50 pb-2">folder_open</i>
|
<i class="opacity-75 pb-2 material-icons">folder_open</i>
|
||||||
<span class="text-xs text-center">
|
<span class="text-center">
|
||||||
{{ $t("collection_empty") }}
|
{{ $t("empty.collection") }}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<SmartConfirmModal
|
<SmartConfirmModal
|
||||||
:show="confirmRemove"
|
:show="confirmRemove"
|
||||||
:title="$t('are_you_sure_remove_collection')"
|
:title="$t('confirm.remove_collection')"
|
||||||
@hide-modal="confirmRemove = false"
|
@hide-modal="confirmRemove = false"
|
||||||
@resolve="removeCollection"
|
@resolve="removeCollection"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -2,32 +2,24 @@
|
|||||||
<div class="flex flex-col">
|
<div class="flex flex-col">
|
||||||
<div class="flex items-center group">
|
<div class="flex items-center group">
|
||||||
<span
|
<span
|
||||||
class="
|
class="cursor-pointer flex w-10 justify-center items-center truncate"
|
||||||
flex
|
|
||||||
justify-center
|
|
||||||
items-center
|
|
||||||
text-xs
|
|
||||||
w-10
|
|
||||||
truncate
|
|
||||||
cursor-pointer
|
|
||||||
"
|
|
||||||
@click="toggleShowChildren()"
|
@click="toggleShowChildren()"
|
||||||
>
|
>
|
||||||
<i class="material-icons" :class="{ 'text-green-400': isSelected }">
|
<i class="material-icons" :class="{ 'text-green-500': isSelected }">
|
||||||
{{ getCollectionIcon }}
|
{{ getCollectionIcon }}
|
||||||
</i>
|
</i>
|
||||||
</span>
|
</span>
|
||||||
<span
|
<span
|
||||||
class="
|
class="
|
||||||
py-3
|
|
||||||
cursor-pointer
|
cursor-pointer
|
||||||
pr-2
|
flex
|
||||||
flex flex-1
|
|
||||||
min-w-0
|
|
||||||
text-xs
|
|
||||||
group-hover:text-secondaryDark
|
|
||||||
transition
|
|
||||||
font-semibold
|
font-semibold
|
||||||
|
flex-1
|
||||||
|
min-w-0
|
||||||
|
py-2
|
||||||
|
pr-2
|
||||||
|
transition
|
||||||
|
group-hover:text-secondaryDark
|
||||||
"
|
"
|
||||||
@click="toggleShowChildren()"
|
@click="toggleShowChildren()"
|
||||||
>
|
>
|
||||||
@@ -39,7 +31,7 @@
|
|||||||
v-if="collectionsType.selectedTeam.myRole !== 'VIEWER'"
|
v-if="collectionsType.selectedTeam.myRole !== 'VIEWER'"
|
||||||
v-tippy="{ theme: 'tooltip' }"
|
v-tippy="{ theme: 'tooltip' }"
|
||||||
icon="create_new_folder"
|
icon="create_new_folder"
|
||||||
:title="$t('new_folder')"
|
:title="$t('folder.new')"
|
||||||
class="group-hover:inline-flex hidden"
|
class="group-hover:inline-flex hidden"
|
||||||
@click.native="$emit('add-folder', { folder, path: folderPath })"
|
@click.native="$emit('add-folder', { folder, path: folderPath })"
|
||||||
/>
|
/>
|
||||||
@@ -62,7 +54,7 @@
|
|||||||
<SmartItem
|
<SmartItem
|
||||||
v-if="collectionsType.selectedTeam.myRole !== 'VIEWER'"
|
v-if="collectionsType.selectedTeam.myRole !== 'VIEWER'"
|
||||||
icon="create_new_folder"
|
icon="create_new_folder"
|
||||||
:label="$t('new_folder')"
|
:label="$t('folder.new')"
|
||||||
@click.native="
|
@click.native="
|
||||||
$emit('add-folder', { folder, path: folderPath })
|
$emit('add-folder', { folder, path: folderPath })
|
||||||
$refs.options.tippy().hide()
|
$refs.options.tippy().hide()
|
||||||
@@ -85,6 +77,7 @@
|
|||||||
<SmartItem
|
<SmartItem
|
||||||
v-if="collectionsType.selectedTeam.myRole !== 'VIEWER'"
|
v-if="collectionsType.selectedTeam.myRole !== 'VIEWER'"
|
||||||
icon="delete"
|
icon="delete"
|
||||||
|
color="red"
|
||||||
:label="$t('delete')"
|
:label="$t('delete')"
|
||||||
@click.native="
|
@click.native="
|
||||||
confirmRemove = true
|
confirmRemove = true
|
||||||
@@ -93,11 +86,11 @@
|
|||||||
/>
|
/>
|
||||||
</tippy>
|
</tippy>
|
||||||
</div>
|
</div>
|
||||||
<div v-show="showChildren || isFiltered">
|
<div v-if="showChildren || isFiltered">
|
||||||
<CollectionsTeamsFolder
|
<CollectionsTeamsFolder
|
||||||
v-for="(subFolder, subFolderIndex) in folder.children"
|
v-for="(subFolder, subFolderIndex) in folder.children"
|
||||||
:key="`subFolder-${subFolderIndex}`"
|
:key="`subFolder-${subFolderIndex}`"
|
||||||
class="ml-5 border-l border-dividerLight"
|
class="border-l border-dividerLight ml-5"
|
||||||
:folder="subFolder"
|
:folder="subFolder"
|
||||||
:folder-index="subFolderIndex"
|
:folder-index="subFolderIndex"
|
||||||
:collection-index="collectionIndex"
|
:collection-index="collectionIndex"
|
||||||
@@ -117,7 +110,7 @@
|
|||||||
<CollectionsTeamsRequest
|
<CollectionsTeamsRequest
|
||||||
v-for="(request, index) in folder.requests"
|
v-for="(request, index) in folder.requests"
|
||||||
:key="`request-${index}`"
|
:key="`request-${index}`"
|
||||||
class="ml-5 border-l border-dividerLight"
|
class="border-l border-dividerLight ml-5"
|
||||||
:request="request.request"
|
:request="request.request"
|
||||||
:collection-index="collectionIndex"
|
:collection-index="collectionIndex"
|
||||||
:folder-index="folderIndex"
|
:folder-index="folderIndex"
|
||||||
@@ -137,25 +130,24 @@
|
|||||||
(folder.requests == undefined || folder.requests.length === 0)
|
(folder.requests == undefined || folder.requests.length === 0)
|
||||||
"
|
"
|
||||||
class="
|
class="
|
||||||
flex
|
|
||||||
items-center
|
|
||||||
text-secondaryLight
|
|
||||||
flex-col
|
|
||||||
p-4
|
|
||||||
justify-center
|
|
||||||
ml-5
|
|
||||||
border-l border-dividerLight
|
border-l border-dividerLight
|
||||||
|
flex flex-col
|
||||||
|
text-secondaryLight
|
||||||
|
ml-5
|
||||||
|
p-4
|
||||||
|
items-center
|
||||||
|
justify-center
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
<i class="material-icons opacity-50 pb-2">folder_open</i>
|
<i class="opacity-75 pb-2 material-icons">folder_open</i>
|
||||||
<span class="text-xs text-center">
|
<span class="text-center">
|
||||||
{{ $t("folder_empty") }}
|
{{ $t("empty.folder") }}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<SmartConfirmModal
|
<SmartConfirmModal
|
||||||
:show="confirmRemove"
|
:show="confirmRemove"
|
||||||
:title="$t('are_you_sure_remove_folder')"
|
:title="$t('confirm.remove_folder')"
|
||||||
@hide-modal="confirmRemove = false"
|
@hide-modal="confirmRemove = false"
|
||||||
@resolve="removeFolder"
|
@resolve="removeFolder"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -3,15 +3,14 @@
|
|||||||
<div class="flex items-center group">
|
<div class="flex items-center group">
|
||||||
<span
|
<span
|
||||||
class="
|
class="
|
||||||
font-mono font-bold
|
cursor-pointer
|
||||||
flex
|
flex
|
||||||
|
font-mono font-bold
|
||||||
|
mx-2
|
||||||
|
w-12
|
||||||
justify-center
|
justify-center
|
||||||
items-center
|
items-center
|
||||||
text-xs
|
|
||||||
w-12
|
|
||||||
mx-2
|
|
||||||
truncate
|
truncate
|
||||||
cursor-pointer
|
|
||||||
"
|
"
|
||||||
:class="getRequestLabelColor(request.method)"
|
:class="getRequestLabelColor(request.method)"
|
||||||
@click="!doc ? selectRequest() : {}"
|
@click="!doc ? selectRequest() : {}"
|
||||||
@@ -19,7 +18,7 @@
|
|||||||
<i
|
<i
|
||||||
v-if="isSelected"
|
v-if="isSelected"
|
||||||
class="material-icons"
|
class="material-icons"
|
||||||
:class="{ 'text-green-400': isSelected }"
|
:class="{ 'text-green-500': isSelected }"
|
||||||
>
|
>
|
||||||
check_circle
|
check_circle
|
||||||
</i>
|
</i>
|
||||||
@@ -29,22 +28,22 @@
|
|||||||
</span>
|
</span>
|
||||||
<span
|
<span
|
||||||
class="
|
class="
|
||||||
py-3
|
|
||||||
cursor-pointer
|
cursor-pointer
|
||||||
pr-2
|
flex
|
||||||
flex flex-1
|
|
||||||
min-w-0
|
|
||||||
text-xs
|
|
||||||
group-hover:text-secondaryDark
|
|
||||||
transition
|
|
||||||
font-semibold
|
font-semibold
|
||||||
|
flex-1
|
||||||
|
min-w-0
|
||||||
|
py-2
|
||||||
|
pr-2
|
||||||
|
transition
|
||||||
|
group-hover:text-secondaryDark
|
||||||
"
|
"
|
||||||
@click="!doc ? selectRequest() : {}"
|
@click="!doc ? selectRequest() : {}"
|
||||||
>
|
>
|
||||||
<span class="truncate"> {{ request.name }} </span>
|
<span class="truncate"> {{ request.name }} </span>
|
||||||
</span>
|
</span>
|
||||||
<ButtonSecondary
|
<ButtonSecondary
|
||||||
v-if="!saveRequest"
|
v-if="!saveRequest && !doc"
|
||||||
v-tippy="{ theme: 'tooltip' }"
|
v-tippy="{ theme: 'tooltip' }"
|
||||||
icon="replay"
|
icon="replay"
|
||||||
:title="$t('restore')"
|
:title="$t('restore')"
|
||||||
@@ -83,6 +82,7 @@
|
|||||||
/>
|
/>
|
||||||
<SmartItem
|
<SmartItem
|
||||||
icon="delete"
|
icon="delete"
|
||||||
|
color="red"
|
||||||
:label="$t('delete')"
|
:label="$t('delete')"
|
||||||
@click.native="
|
@click.native="
|
||||||
confirmRemove = true
|
confirmRemove = true
|
||||||
@@ -93,7 +93,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<SmartConfirmModal
|
<SmartConfirmModal
|
||||||
:show="confirmRemove"
|
:show="confirmRemove"
|
||||||
:title="$t('are_you_sure_remove_request')"
|
:title="$t('confirm.remove_request')"
|
||||||
@hide-modal="confirmRemove = false"
|
@hide-modal="confirmRemove = false"
|
||||||
@resolve="removeRequest"
|
@resolve="removeRequest"
|
||||||
/>
|
/>
|
||||||
@@ -101,6 +101,8 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import { translateToNewRequest } from "~/helpers/types/HoppRESTRequest"
|
||||||
|
import { setRESTRequest } from "~/newstore/RESTSession"
|
||||||
export default {
|
export default {
|
||||||
props: {
|
props: {
|
||||||
request: { type: Object, default: () => {} },
|
request: { type: Object, default: () => {} },
|
||||||
@@ -117,11 +119,11 @@ export default {
|
|||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
requestMethodLabels: {
|
requestMethodLabels: {
|
||||||
get: "text-green-400",
|
get: "text-green-500",
|
||||||
post: "text-yellow-400",
|
post: "text-yellow-500",
|
||||||
put: "text-blue-400",
|
put: "text-blue-500",
|
||||||
delete: "text-red-400",
|
delete: "text-red-500",
|
||||||
default: "text-gray-400",
|
default: "text-gray-500",
|
||||||
},
|
},
|
||||||
confirmRemove: false,
|
confirmRemove: false,
|
||||||
}
|
}
|
||||||
@@ -144,8 +146,7 @@ export default {
|
|||||||
requestID: this.requestIndex,
|
requestID: this.requestIndex,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
else
|
else setRESTRequest(translateToNewRequest(this.request))
|
||||||
this.$store.commit("postwoman/selectRequest", { request: this.request })
|
|
||||||
},
|
},
|
||||||
removeRequest() {
|
removeRequest() {
|
||||||
this.$emit("remove-request", {
|
this.$emit("remove-request", {
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ export default {
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style scoped lang="scss">
|
||||||
.collection {
|
.collection {
|
||||||
@apply flex flex-col flex-1;
|
@apply flex flex-col flex-1;
|
||||||
@apply justify-center;
|
@apply justify-center;
|
||||||
|
|||||||
@@ -24,13 +24,13 @@ export default {
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style scoped lang="scss">
|
||||||
.folder {
|
.folder {
|
||||||
@apply flex flex-col flex-1;
|
@apply flex flex-col flex-1;
|
||||||
@apply justify-center;
|
@apply justify-center;
|
||||||
@apply p-4;
|
@apply p-4;
|
||||||
@apply border-l border-divider;
|
|
||||||
@apply mt-4;
|
@apply mt-4;
|
||||||
|
@apply border-l border-divider;
|
||||||
|
|
||||||
.material-icons {
|
.material-icons {
|
||||||
@apply mr-4;
|
@apply mr-4;
|
||||||
|
|||||||
@@ -120,7 +120,7 @@ export default {
|
|||||||
@apply p-4;
|
@apply p-4;
|
||||||
@apply mt-4;
|
@apply mt-4;
|
||||||
@apply border border-divider;
|
@apply border border-divider;
|
||||||
@apply rounded-lg;
|
@apply rounded;
|
||||||
|
|
||||||
h4 {
|
h4 {
|
||||||
@apply mt-4;
|
@apply mt-4;
|
||||||
@@ -137,7 +137,7 @@ export default {
|
|||||||
@apply p-4;
|
@apply p-4;
|
||||||
@apply m-0;
|
@apply m-0;
|
||||||
@apply text-secondaryLight;
|
@apply text-secondaryLight;
|
||||||
@apply border-b border-dashed border-divider;
|
@apply border-b border-divider;
|
||||||
|
|
||||||
&:last-child {
|
&:last-child {
|
||||||
@apply border-b-0;
|
@apply border-b-0;
|
||||||
|
|||||||
@@ -7,8 +7,8 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template #body>
|
<template #body>
|
||||||
<div class="px-2 flex flex-col">
|
<div class="flex flex-col px-2">
|
||||||
<label for="selectLabelEnvAdd" class="px-4 font-semibold pb-4 text-xs">
|
<label for="selectLabelEnvAdd" class="font-semibold px-4 pb-4">
|
||||||
{{ $t("label") }}
|
{{ $t("label") }}
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
|
|||||||
@@ -7,8 +7,8 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template #body>
|
<template #body>
|
||||||
<div class="px-2 flex flex-col">
|
<div class="flex flex-col px-2">
|
||||||
<label for="selectLabelEnvEdit" class="px-4 font-semibold pb-4 text-xs">
|
<label for="selectLabelEnvEdit" class="font-semibold px-4 pb-4">
|
||||||
{{ $t("label") }}
|
{{ $t("label") }}
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
@@ -19,11 +19,8 @@
|
|||||||
:placeholder="editingEnvironment.name"
|
:placeholder="editingEnvironment.name"
|
||||||
@keyup.enter="saveEnvironment"
|
@keyup.enter="saveEnvironment"
|
||||||
/>
|
/>
|
||||||
<div class="flex justify-between items-center flex-1">
|
<div class="flex flex-1 justify-between items-center">
|
||||||
<label
|
<label for="variableList" class="font-semibold px-4 pt-4 pb-4">
|
||||||
for="variableList"
|
|
||||||
class="px-4 pt-4 font-semibold pb-4 text-xs"
|
|
||||||
>
|
|
||||||
{{ $t("env_variable_list") }}
|
{{ $t("env_variable_list") }}
|
||||||
</label>
|
</label>
|
||||||
<div>
|
<div>
|
||||||
@@ -36,49 +33,48 @@
|
|||||||
<ButtonSecondary
|
<ButtonSecondary
|
||||||
v-tippy="{ theme: 'tooltip' }"
|
v-tippy="{ theme: 'tooltip' }"
|
||||||
icon="add"
|
icon="add"
|
||||||
:title="$t('add_new')"
|
:title="$t('add.new')"
|
||||||
@click.native="addEnvironmentVariable"
|
@click.native="addEnvironmentVariable"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="border-2 border-divider">
|
<div class="border-divider border rounded">
|
||||||
<div
|
<div
|
||||||
v-for="(variable, index) in vars"
|
v-for="(variable, index) in vars"
|
||||||
:key="`variable-${index}`"
|
:key="`variable-${index}`"
|
||||||
class="
|
class="
|
||||||
|
divide-x divide-dividerLight
|
||||||
|
border-b border-dividerLight
|
||||||
flex
|
flex
|
||||||
border-b
|
|
||||||
divide-x
|
|
||||||
border-divider
|
|
||||||
divide-dashed divide-divider
|
|
||||||
"
|
"
|
||||||
|
:class="{ 'border-t': index == 0 }"
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
v-model="variable.key"
|
v-model="variable.key"
|
||||||
class="
|
class="
|
||||||
px-4
|
|
||||||
py-3
|
|
||||||
text-xs
|
|
||||||
flex flex-1
|
|
||||||
font-semibold
|
|
||||||
bg-primaryLight
|
bg-primaryLight
|
||||||
|
flex
|
||||||
|
font-semibold font-mono
|
||||||
|
flex-1
|
||||||
|
py-2
|
||||||
|
px-4
|
||||||
focus:outline-none
|
focus:outline-none
|
||||||
"
|
"
|
||||||
:placeholder="$t('variable_count', { count: index + 1 })"
|
:placeholder="$t('count.variable', { count: index + 1 })"
|
||||||
:name="'param' + index"
|
:name="'param' + index"
|
||||||
/>
|
/>
|
||||||
<input
|
<input
|
||||||
v-model="variable.value"
|
v-model="variable.value"
|
||||||
class="
|
class="
|
||||||
px-4
|
|
||||||
py-3
|
|
||||||
text-xs
|
|
||||||
flex flex-1
|
|
||||||
font-semibold
|
|
||||||
bg-primaryLight
|
bg-primaryLight
|
||||||
|
flex
|
||||||
|
font-semibold font-mono
|
||||||
|
flex-1
|
||||||
|
py-2
|
||||||
|
px-4
|
||||||
focus:outline-none
|
focus:outline-none
|
||||||
"
|
"
|
||||||
:placeholder="$t('value_count', { count: index + 1 })"
|
:placeholder="$t('count.value', { count: index + 1 })"
|
||||||
:name="'value' + index"
|
:name="'value' + index"
|
||||||
/>
|
/>
|
||||||
<div>
|
<div>
|
||||||
@@ -87,10 +83,31 @@
|
|||||||
v-tippy="{ theme: 'tooltip' }"
|
v-tippy="{ theme: 'tooltip' }"
|
||||||
:title="$t('delete')"
|
:title="$t('delete')"
|
||||||
icon="delete"
|
icon="delete"
|
||||||
|
color="red"
|
||||||
@click.native="removeEnvironmentVariable(index)"
|
@click.native="removeEnvironmentVariable(index)"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div
|
||||||
|
v-if="vars.length === 0"
|
||||||
|
class="
|
||||||
|
flex flex-col
|
||||||
|
text-secondaryLight
|
||||||
|
p-4
|
||||||
|
items-center
|
||||||
|
justify-center
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<i class="opacity-75 pb-2 material-icons">layers</i>
|
||||||
|
<span class="text-center pb-4">
|
||||||
|
{{ $t("empty.environments") }}
|
||||||
|
</span>
|
||||||
|
<ButtonSecondary
|
||||||
|
:label="$t('add.new')"
|
||||||
|
outline
|
||||||
|
@click.native="addEnvironmentVariable"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -1,30 +1,22 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="flex items-center group">
|
<div class="flex items-center group">
|
||||||
<span
|
<span
|
||||||
class="
|
class="cursor-pointer flex w-10 justify-center items-center truncate"
|
||||||
flex
|
|
||||||
justify-center
|
|
||||||
items-center
|
|
||||||
text-xs
|
|
||||||
w-10
|
|
||||||
truncate
|
|
||||||
cursor-pointer
|
|
||||||
"
|
|
||||||
@click="$emit('edit-environment')"
|
@click="$emit('edit-environment')"
|
||||||
>
|
>
|
||||||
<i class="material-icons">layers</i>
|
<i class="material-icons">layers</i>
|
||||||
</span>
|
</span>
|
||||||
<span
|
<span
|
||||||
class="
|
class="
|
||||||
py-3
|
|
||||||
cursor-pointer
|
cursor-pointer
|
||||||
pr-2
|
flex
|
||||||
flex flex-1
|
|
||||||
min-w-0
|
|
||||||
text-xs
|
|
||||||
group-hover:text-secondaryDark
|
|
||||||
transition
|
|
||||||
font-semibold
|
font-semibold
|
||||||
|
flex-1
|
||||||
|
min-w-0
|
||||||
|
py-2
|
||||||
|
pr-2
|
||||||
|
transition
|
||||||
|
group-hover:text-secondaryDark
|
||||||
"
|
"
|
||||||
@click="$emit('edit-environment')"
|
@click="$emit('edit-environment')"
|
||||||
>
|
>
|
||||||
@@ -32,6 +24,7 @@
|
|||||||
{{ environment.name }}
|
{{ environment.name }}
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
|
<span>
|
||||||
<tippy
|
<tippy
|
||||||
ref="options"
|
ref="options"
|
||||||
interactive
|
interactive
|
||||||
@@ -57,6 +50,7 @@
|
|||||||
/>
|
/>
|
||||||
<SmartItem
|
<SmartItem
|
||||||
icon="delete"
|
icon="delete"
|
||||||
|
color="red"
|
||||||
:label="$t('delete')"
|
:label="$t('delete')"
|
||||||
@click.native="
|
@click.native="
|
||||||
confirmRemove = true
|
confirmRemove = true
|
||||||
@@ -64,9 +58,10 @@
|
|||||||
"
|
"
|
||||||
/>
|
/>
|
||||||
</tippy>
|
</tippy>
|
||||||
|
</span>
|
||||||
<SmartConfirmModal
|
<SmartConfirmModal
|
||||||
:show="confirmRemove"
|
:show="confirmRemove"
|
||||||
:title="$t('are_you_sure_remove_environment')"
|
:title="$t('confirm.remove_environment')"
|
||||||
@hide-modal="confirmRemove = false"
|
@hide-modal="confirmRemove = false"
|
||||||
@resolve="removeEnvironment"
|
@resolve="removeEnvironment"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
</template>
|
</template>
|
||||||
<SmartItem
|
<SmartItem
|
||||||
icon="assignment_returned"
|
icon="assignment_returned"
|
||||||
:label="$t('import_from_gist')"
|
:label="$t('import.from_gist')"
|
||||||
@click.native="
|
@click.native="
|
||||||
readEnvironmentGist
|
readEnvironmentGist
|
||||||
$refs.options.tippy().hide()
|
$refs.options.tippy().hide()
|
||||||
@@ -32,9 +32,9 @@
|
|||||||
v-tippy="{ theme: 'tooltip' }"
|
v-tippy="{ theme: 'tooltip' }"
|
||||||
:title="
|
:title="
|
||||||
!currentUser
|
!currentUser
|
||||||
? $t('login_with_github_to') + $t('create_secret_gist')
|
? $t('export.require_github')
|
||||||
: currentUser.provider !== 'github.com'
|
: currentUser.provider !== 'github.com'
|
||||||
? $t('login_with_github_to') + $t('create_secret_gist')
|
? $t('export.require_github')
|
||||||
: null
|
: null
|
||||||
"
|
"
|
||||||
:disabled="
|
:disabled="
|
||||||
@@ -45,7 +45,7 @@
|
|||||||
: false
|
: false
|
||||||
"
|
"
|
||||||
icon="assignment_turned_in"
|
icon="assignment_turned_in"
|
||||||
:label="$t('create_secret_gist')"
|
:label="$t('export.create_secret_gist')"
|
||||||
@click.native="
|
@click.native="
|
||||||
createEnvironmentGist
|
createEnvironmentGist
|
||||||
$refs.options.tippy().hide()
|
$refs.options.tippy().hide()
|
||||||
@@ -76,7 +76,7 @@
|
|||||||
v-tippy="{ theme: 'tooltip' }"
|
v-tippy="{ theme: 'tooltip' }"
|
||||||
:title="$t('preserve_current')"
|
:title="$t('preserve_current')"
|
||||||
icon="create_new_folder"
|
icon="create_new_folder"
|
||||||
:label="$t('import_json')"
|
:label="$t('import.json')"
|
||||||
@click.native="openDialogChooseFileToImportFrom"
|
@click.native="openDialogChooseFileToImportFrom"
|
||||||
/>
|
/>
|
||||||
<input
|
<input
|
||||||
@@ -91,7 +91,7 @@
|
|||||||
v-tippy="{ theme: 'tooltip' }"
|
v-tippy="{ theme: 'tooltip' }"
|
||||||
:title="$t('download_file')"
|
:title="$t('download_file')"
|
||||||
icon="drive_file_move"
|
icon="drive_file_move"
|
||||||
:label="$t('export_as_json')"
|
:label="$t('export.as_json')"
|
||||||
@click.native="exportJSON"
|
@click.native="exportJSON"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@@ -142,7 +142,7 @@ export default {
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
this.$toast.success(this.$t("gist_created"), {
|
this.$toast.success(this.$t("export.gist_created"), {
|
||||||
icon: "done",
|
icon: "done",
|
||||||
})
|
})
|
||||||
window.open(res.html_url)
|
window.open(res.html_url)
|
||||||
@@ -155,7 +155,7 @@ export default {
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
async readEnvironmentGist() {
|
async readEnvironmentGist() {
|
||||||
const gist = prompt(this.$t("enter_gist_url"))
|
const gist = prompt(this.$t("import.gist_url"))
|
||||||
if (!gist) return
|
if (!gist) return
|
||||||
await this.$axios
|
await this.$axios
|
||||||
.$get(`https://api.github.com/gists/${gist.split("/").pop()}`, {
|
.$get(`https://api.github.com/gists/${gist.split("/").pop()}`, {
|
||||||
@@ -223,22 +223,22 @@ export default {
|
|||||||
this.importFromHoppscotch(environments)
|
this.importFromHoppscotch(environments)
|
||||||
},
|
},
|
||||||
exportJSON() {
|
exportJSON() {
|
||||||
let text = this.environmentJson
|
const dataToWrite = this.environmentJson
|
||||||
text = text.replace(/\n/g, "\r\n")
|
const file = new Blob([dataToWrite], { type: "application/json" })
|
||||||
const blob = new Blob([text], {
|
const a = document.createElement("a")
|
||||||
type: "text/json",
|
const url = URL.createObjectURL(file)
|
||||||
})
|
a.href = url
|
||||||
const anchor = document.createElement("a")
|
// TODO get uri from meta
|
||||||
anchor.download = "hoppscotch-environment.json"
|
a.download = `${url.split("/").pop().split("#")[0].split("?")[0]}`
|
||||||
anchor.href = window.URL.createObjectURL(blob)
|
document.body.appendChild(a)
|
||||||
anchor.target = "_blank"
|
a.click()
|
||||||
anchor.style.display = "none"
|
|
||||||
document.body.appendChild(anchor)
|
|
||||||
anchor.click()
|
|
||||||
document.body.removeChild(anchor)
|
|
||||||
this.$toast.success(this.$t("download_started"), {
|
this.$toast.success(this.$t("download_started"), {
|
||||||
icon: "done",
|
icon: "done",
|
||||||
})
|
})
|
||||||
|
setTimeout(() => {
|
||||||
|
document.body.removeChild(a)
|
||||||
|
URL.revokeObjectURL(url)
|
||||||
|
}, 1000)
|
||||||
},
|
},
|
||||||
fileImported() {
|
fileImported() {
|
||||||
this.$toast.info(this.$t("file_imported"), {
|
this.$toast.info(this.$t("file_imported"), {
|
||||||
|
|||||||
@@ -1,20 +1,20 @@
|
|||||||
<template>
|
<template>
|
||||||
<AppSection label="environments">
|
<AppSection label="environments">
|
||||||
<div class="flex flex-col sticky z-10 top-10 bg-primary">
|
<div class="bg-primary rounded-t flex flex-col top-8 z-10 sticky">
|
||||||
<div class="select-wrapper">
|
<div class="select-wrapper">
|
||||||
<select
|
<select
|
||||||
v-model="selectedEnvironmentIndex"
|
v-model="selectedEnvironmentIndex"
|
||||||
:disabled="environments.length == 0"
|
:disabled="environments.length == 0"
|
||||||
class="
|
class="
|
||||||
flex
|
|
||||||
w-full
|
|
||||||
px-4
|
|
||||||
text-xs
|
|
||||||
py-3
|
|
||||||
focus:outline-none
|
|
||||||
border-b border-dividerLight
|
|
||||||
font-medium
|
|
||||||
bg-primaryLight
|
bg-primaryLight
|
||||||
|
border-b border-dividerLight
|
||||||
|
flex
|
||||||
|
font-semibold font-mono
|
||||||
|
w-full
|
||||||
|
py-2
|
||||||
|
px-4
|
||||||
|
focus:outline-none
|
||||||
|
appearance-none
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
<option :value="-1">No environment</option>
|
<option :value="-1">No environment</option>
|
||||||
@@ -30,7 +30,7 @@
|
|||||||
</option>
|
</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div class="border-b flex justify-between flex-1 border-dividerLight">
|
<div class="border-b border-dividerLight flex flex-1 justify-between">
|
||||||
<ButtonSecondary
|
<ButtonSecondary
|
||||||
icon="add"
|
icon="add"
|
||||||
:label="$t('new')"
|
:label="$t('new')"
|
||||||
@@ -39,7 +39,7 @@
|
|||||||
<ButtonSecondary
|
<ButtonSecondary
|
||||||
v-tippy="{ theme: 'tooltip' }"
|
v-tippy="{ theme: 'tooltip' }"
|
||||||
icon="import_export"
|
icon="import_export"
|
||||||
:title="$t('import_export')"
|
:title="$t('modal.import_export')"
|
||||||
@click.native="displayModalImportExport(true)"
|
@click.native="displayModalImportExport(true)"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@@ -60,12 +60,17 @@
|
|||||||
/>
|
/>
|
||||||
<div
|
<div
|
||||||
v-if="environments.length === 0"
|
v-if="environments.length === 0"
|
||||||
class="flex items-center text-secondaryLight flex-col p-4 justify-center"
|
class="flex flex-col text-secondaryLight p-4 items-center justify-center"
|
||||||
>
|
>
|
||||||
<i class="material-icons opacity-50 pb-2">library_add</i>
|
<i class="opacity-75 pb-2 material-icons">library_add</i>
|
||||||
<span class="text-xs text-center">
|
<span class="text-center pb-4">
|
||||||
{{ $t("create_new_environment") }}
|
{{ $t("empty.environments") }}
|
||||||
</span>
|
</span>
|
||||||
|
<ButtonSecondary
|
||||||
|
:label="$t('add.new')"
|
||||||
|
outline
|
||||||
|
@click.native="displayModalAdd(true)"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-col">
|
<div class="flex flex-col">
|
||||||
<EnvironmentsEnvironment
|
<EnvironmentsEnvironment
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<SmartModal v-if="show" @close="hideModal">
|
<SmartModal v-if="show" dialog @close="hideModal">
|
||||||
<template #header>
|
<template #header>
|
||||||
<h3 class="heading">{{ $t("login_to_hoppscotch") }}</h3>
|
<h3 class="heading">{{ $t("login_to_hoppscotch") }}</h3>
|
||||||
<div>
|
<div>
|
||||||
@@ -27,17 +27,17 @@
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="mode === 'email'" class="flex flex-col space-y-2">
|
<div v-if="mode === 'email'" class="flex flex-col space-y-2">
|
||||||
<div class="flex items-center">
|
<div class="flex relative items-center">
|
||||||
<label for="email" class="flex items-center px-4">
|
<label for="email" class="flex px-4 absolute items-center">
|
||||||
<i class="material-icons opacity-75">mail</i>
|
<i class="opacity-75 material-icons">mail</i>
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
id="email"
|
id="email"
|
||||||
v-model="form.email"
|
v-model="form.email"
|
||||||
class="flex flex-1 rounded px-4 py-2 outline-none"
|
class="input !pl-12"
|
||||||
type="email"
|
type="email"
|
||||||
name="email"
|
name="email"
|
||||||
placeholder="enter your email"
|
:placeholder="$t('email')"
|
||||||
autocomplete="email"
|
autocomplete="email"
|
||||||
required
|
required
|
||||||
spellcheck="false"
|
spellcheck="false"
|
||||||
@@ -56,30 +56,34 @@
|
|||||||
"
|
"
|
||||||
type="button"
|
type="button"
|
||||||
tabindex="-1"
|
tabindex="-1"
|
||||||
:label="$t('send_magic_link')"
|
:label="$t('auth.send_magic_link')"
|
||||||
@click.native="signInWithEmail"
|
@click.native="signInWithEmail"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="mode === 'email-sent'" class="flex flex-col px-4">
|
<div v-if="mode === 'email-sent'" class="flex flex-col px-4">
|
||||||
<div class="flex justify-center max-w-md items-center flex-col">
|
<div class="flex flex-col max-w-md justify-center items-center">
|
||||||
<i class="material-icons text-accent text-4xl"> verified </i>
|
<i class="text-accent material-icons !text-4xl">
|
||||||
|
mark_email_unread
|
||||||
|
</i>
|
||||||
<h3 class="font-bold my-2 text-center text-lg">
|
<h3 class="font-bold my-2 text-center text-lg">
|
||||||
{{ $t("we_sent_magic_link") }}
|
{{ $t("auth.we_sent_magic_link") }}
|
||||||
</h3>
|
</h3>
|
||||||
<p class="text-center">
|
<p class="text-center">
|
||||||
{{ $t("we_sent_magic_link_description", { email: form.email }) }}
|
{{
|
||||||
|
$t("auth.we_sent_magic_link_description", { email: form.email })
|
||||||
|
}}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<p v-if="mode === 'sign-in'" class="text-secondaryLight text-xs">
|
<p v-if="mode === 'sign-in'" class="text-secondaryLight">
|
||||||
By signing in, you are agreeing to our
|
By signing in, you are agreeing to our
|
||||||
<SmartAnchor class="link" to="/index" label="Terms of Service" />
|
<SmartAnchor class="link" to="/index" label="Terms of Service" />
|
||||||
and
|
and
|
||||||
<SmartAnchor class="link" to="/index" label="Privacy Policy" />.
|
<SmartAnchor class="link" to="/index" label="Privacy Policy" />.
|
||||||
</p>
|
</p>
|
||||||
<p v-if="mode === 'email'" class="text-secondaryLight text-xs">
|
<p v-if="mode === 'email'" class="text-secondaryLight">
|
||||||
<SmartAnchor
|
<SmartAnchor
|
||||||
class="link"
|
class="link"
|
||||||
label="← All sign in options"
|
label="← All sign in options"
|
||||||
@@ -88,14 +92,18 @@
|
|||||||
</p>
|
</p>
|
||||||
<p
|
<p
|
||||||
v-if="mode === 'email-sent'"
|
v-if="mode === 'email-sent'"
|
||||||
class="flex flex-1 justify-between text-secondaryLight text-xs"
|
class="flex flex-1 text-secondaryLight justify-between"
|
||||||
>
|
>
|
||||||
<SmartAnchor
|
<SmartAnchor
|
||||||
class="link"
|
class="link"
|
||||||
label="← Re-enter email"
|
label="← Re-enter email"
|
||||||
@click.native="mode = 'email'"
|
@click.native="mode = 'email'"
|
||||||
/>
|
/>
|
||||||
<SmartAnchor class="link" label="Dismiss" @click.native="hideModal" />
|
<SmartAnchor
|
||||||
|
class="link"
|
||||||
|
:label="$t('action.dismiss')"
|
||||||
|
@click.native="hideModal"
|
||||||
|
/>
|
||||||
</p>
|
</p>
|
||||||
</template>
|
</template>
|
||||||
</SmartModal>
|
</SmartModal>
|
||||||
@@ -149,7 +157,7 @@ export default {
|
|||||||
const { additionalUserInfo } = await signInUserWithGoogle()
|
const { additionalUserInfo } = await signInUserWithGoogle()
|
||||||
|
|
||||||
if (additionalUserInfo.isNewUser) {
|
if (additionalUserInfo.isNewUser) {
|
||||||
this.$toast.info(`${this.$t("turn_on")} ${this.$t("sync")}`, {
|
this.$toast.info(`${this.$t("action.turn_on")} ${this.$t("sync")}`, {
|
||||||
icon: "sync",
|
icon: "sync",
|
||||||
duration: null,
|
duration: null,
|
||||||
closeOnSwipe: false,
|
closeOnSwipe: false,
|
||||||
@@ -195,7 +203,7 @@ export default {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
this.$toast.info(`${this.$t("account_exists")}`, {
|
this.$toast.info(`${this.$t("auth.account_exists")}`, {
|
||||||
icon: "vpn_key",
|
icon: "vpn_key",
|
||||||
duration: null,
|
duration: null,
|
||||||
closeOnSwipe: false,
|
closeOnSwipe: false,
|
||||||
@@ -225,7 +233,7 @@ export default {
|
|||||||
setProviderInfo(credential.providerId, credential.accessToken)
|
setProviderInfo(credential.providerId, credential.accessToken)
|
||||||
|
|
||||||
if (additionalUserInfo.isNewUser) {
|
if (additionalUserInfo.isNewUser) {
|
||||||
this.$toast.info(`${this.$t("turn_on")} ${this.$t("sync")}`, {
|
this.$toast.info(`${this.$t("action.turn_on")} ${this.$t("sync")}`, {
|
||||||
icon: "sync",
|
icon: "sync",
|
||||||
duration: null,
|
duration: null,
|
||||||
closeOnSwipe: false,
|
closeOnSwipe: false,
|
||||||
@@ -271,7 +279,7 @@ export default {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
this.$toast.info(`${this.$t("account_exists")}`, {
|
this.$toast.info(`${this.$t("auth.account_exists")}`, {
|
||||||
icon: "vpn_key",
|
icon: "vpn_key",
|
||||||
duration: null,
|
duration: null,
|
||||||
closeOnSwipe: false,
|
closeOnSwipe: false,
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
/>
|
/>
|
||||||
<SmartConfirmModal
|
<SmartConfirmModal
|
||||||
:show="confirmLogout"
|
:show="confirmLogout"
|
||||||
:title="$t('are_you_sure_logout')"
|
:title="$t('confirm.logout')"
|
||||||
@hide-modal="confirmLogout = false"
|
@hide-modal="confirmLogout = false"
|
||||||
@resolve="logout"
|
@resolve="logout"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<div
|
<div
|
||||||
class="font-semibold text-xs field-title"
|
class="font-semibold field-title"
|
||||||
:class="{ 'field-highlighted': isHighlighted }"
|
:class="{ 'field-highlighted': isHighlighted }"
|
||||||
>
|
>
|
||||||
{{ fieldName }}
|
{{ fieldName }}
|
||||||
@@ -24,31 +24,31 @@
|
|||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
v-if="gqlField.description"
|
v-if="gqlField.description"
|
||||||
class="py-2 text-xs text-secondaryLight field-desc"
|
class="text-secondaryLight py-2 field-desc"
|
||||||
>
|
>
|
||||||
{{ gqlField.description }}
|
{{ gqlField.description }}
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
v-if="gqlField.isDeprecated"
|
v-if="gqlField.isDeprecated"
|
||||||
class="
|
class="
|
||||||
inline-block
|
|
||||||
px-2
|
|
||||||
py-1
|
|
||||||
my-1
|
|
||||||
text-xs text-black
|
|
||||||
bg-yellow-200
|
|
||||||
rounded
|
rounded
|
||||||
font-semibold
|
font-semibold
|
||||||
|
bg-yellow-200
|
||||||
|
my-1
|
||||||
|
text-black
|
||||||
|
py-1
|
||||||
|
px-2
|
||||||
|
inline-block
|
||||||
field-deprecated
|
field-deprecated
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
{{ $t("deprecated") }}
|
{{ $t("deprecated") }}
|
||||||
</div>
|
</div>
|
||||||
<div v-if="fieldArgs.length > 0">
|
<div v-if="fieldArgs.length > 0">
|
||||||
<h5 class="my-2 text-xs">Arguments:</h5>
|
<h5 class="my-2">Arguments:</h5>
|
||||||
<div class="pl-4 border-l-2 border-divider">
|
<div class="border-divider border-l-2 pl-4">
|
||||||
<div v-for="(field, index) in fieldArgs" :key="`field-${index}`">
|
<div v-for="(field, index) in fieldArgs" :key="`field-${index}`">
|
||||||
<span class="font-semibold text-xs">
|
<span class="font-semibold">
|
||||||
{{ field.name }}:
|
{{ field.name }}:
|
||||||
<GraphqlTypeLink
|
<GraphqlTypeLink
|
||||||
:gql-type="field.type"
|
:gql-type="field.type"
|
||||||
@@ -57,7 +57,7 @@
|
|||||||
</span>
|
</span>
|
||||||
<div
|
<div
|
||||||
v-if="field.description"
|
v-if="field.description"
|
||||||
class="py-2 text-xs text-secondaryLight field-desc"
|
class="text-secondaryLight py-2 field-desc"
|
||||||
>
|
>
|
||||||
{{ field.description }}
|
{{ field.description }}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div :id="`type_${gqlType.name}`" class="p-4">
|
<div :id="`type_${gqlType.name}`" class="p-4">
|
||||||
<div
|
<div
|
||||||
class="font-semibold text-xs type-title"
|
class="font-semibold type-title"
|
||||||
:class="{ 'text-accent': isHighlighted }"
|
:class="{ 'text-accent': isHighlighted }"
|
||||||
>
|
>
|
||||||
<span v-if="isInput" class="text-accent">input </span>
|
<span v-if="isInput" class="text-accent">input </span>
|
||||||
@@ -9,14 +9,11 @@
|
|||||||
<span v-else-if="isEnum" class="text-accent">enum </span>
|
<span v-else-if="isEnum" class="text-accent">enum </span>
|
||||||
{{ gqlType.name }}
|
{{ gqlType.name }}
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div v-if="gqlType.description" class="text-secondaryLight py-2 type-desc">
|
||||||
v-if="gqlType.description"
|
|
||||||
class="py-2 text-xs text-secondaryLight type-desc"
|
|
||||||
>
|
|
||||||
{{ gqlType.description }}
|
{{ gqlType.description }}
|
||||||
</div>
|
</div>
|
||||||
<div v-if="interfaces.length > 0">
|
<div v-if="interfaces.length > 0">
|
||||||
<h5 class="my-2 text-xs">Interfaces:</h5>
|
<h5 class="my-2">Interfaces:</h5>
|
||||||
<div
|
<div
|
||||||
v-for="(gqlInterface, index) in interfaces"
|
v-for="(gqlInterface, index) in interfaces"
|
||||||
:key="`gqlInterface-${index}`"
|
:key="`gqlInterface-${index}`"
|
||||||
@@ -24,37 +21,37 @@
|
|||||||
<GraphqlTypeLink
|
<GraphqlTypeLink
|
||||||
:gql-type="gqlInterface"
|
:gql-type="gqlInterface"
|
||||||
:jump-type-callback="jumpTypeCallback"
|
:jump-type-callback="jumpTypeCallback"
|
||||||
class="pl-4 border-l-2 border-divider"
|
class="border-divider border-l-2 pl-4"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="children.length > 0" class="mb-2">
|
<div v-if="children.length > 0" class="mb-2">
|
||||||
<h5 class="my-2 text-xs">Children:</h5>
|
<h5 class="my-2">Children:</h5>
|
||||||
<GraphqlTypeLink
|
<GraphqlTypeLink
|
||||||
v-for="(child, index) in children"
|
v-for="(child, index) in children"
|
||||||
:key="`child-${index}`"
|
:key="`child-${index}`"
|
||||||
:gql-type="child"
|
:gql-type="child"
|
||||||
:jump-type-callback="jumpTypeCallback"
|
:jump-type-callback="jumpTypeCallback"
|
||||||
class="pl-4 border-l-2 border-divider"
|
class="border-divider border-l-2 pl-4"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="gqlType.getFields">
|
<div v-if="gqlType.getFields">
|
||||||
<h5 class="my-2 text-xs">Fields:</h5>
|
<h5 class="my-2">Fields:</h5>
|
||||||
<GraphqlField
|
<GraphqlField
|
||||||
v-for="(field, index) in gqlType.getFields()"
|
v-for="(field, index) in gqlType.getFields()"
|
||||||
:key="`field-${index}`"
|
:key="`field-${index}`"
|
||||||
class="pl-4 border-l-2 border-divider"
|
class="border-divider border-l-2 pl-4"
|
||||||
:gql-field="field"
|
:gql-field="field"
|
||||||
:is-highlighted="isFieldHighlighted({ field })"
|
:is-highlighted="isFieldHighlighted({ field })"
|
||||||
:jump-type-callback="jumpTypeCallback"
|
:jump-type-callback="jumpTypeCallback"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="isEnum">
|
<div v-if="isEnum">
|
||||||
<h5 class="my-2 text-xs">Values:</h5>
|
<h5 class="my-2">Values:</h5>
|
||||||
<div
|
<div
|
||||||
v-for="(value, index) in gqlType.getValues()"
|
v-for="(value, index) in gqlType.getValues()"
|
||||||
:key="`value-${index}`"
|
:key="`value-${index}`"
|
||||||
class="pl-4 border-l-2 border-divider"
|
class="border-divider border-l-2 pl-4"
|
||||||
v-text="value.name"
|
v-text="value.name"
|
||||||
></div>
|
></div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<span
|
<span
|
||||||
:class="isScalar ? 'text-secondaryLight' : 'cursor-pointer text-accent'"
|
:class="isScalar ? 'text-secondaryLight' : 'cursor-pointer text-accent'"
|
||||||
class="font-mono text-xs"
|
class="font-mono"
|
||||||
@click="jumpToType"
|
@click="jumpToType"
|
||||||
>
|
>
|
||||||
{{ typeString }}
|
{{ typeString }}
|
||||||
|
|||||||
@@ -3,16 +3,16 @@
|
|||||||
<div class="flex items-center">
|
<div class="flex items-center">
|
||||||
<span
|
<span
|
||||||
class="
|
class="
|
||||||
py-3
|
|
||||||
cursor-pointer
|
cursor-pointer
|
||||||
|
flex
|
||||||
|
font-semibold
|
||||||
|
flex-1
|
||||||
|
min-w-0
|
||||||
|
py-2
|
||||||
pr-2
|
pr-2
|
||||||
pl-4
|
pl-4
|
||||||
flex flex-1
|
|
||||||
min-w-0
|
|
||||||
text-xs
|
|
||||||
group-hover:text-secondaryDark
|
|
||||||
transition
|
transition
|
||||||
font-semibold
|
group-hover:text-secondaryDark
|
||||||
"
|
"
|
||||||
data-testid="restore_history_entry"
|
data-testid="restore_history_entry"
|
||||||
@click="$emit('use-entry')"
|
@click="$emit('use-entry')"
|
||||||
@@ -24,22 +24,22 @@
|
|||||||
<ButtonSecondary
|
<ButtonSecondary
|
||||||
v-tippy="{ theme: 'tooltip' }"
|
v-tippy="{ theme: 'tooltip' }"
|
||||||
icon="delete"
|
icon="delete"
|
||||||
|
color="red"
|
||||||
:title="$t('delete')"
|
:title="$t('delete')"
|
||||||
class="group-hover:inline-flex hidden"
|
class="group-hover:inline-flex hidden"
|
||||||
color="red"
|
|
||||||
data-testid="delete_history_entry"
|
data-testid="delete_history_entry"
|
||||||
@click.native="$emit('delete-entry')"
|
@click.native="$emit('delete-entry')"
|
||||||
/>
|
/>
|
||||||
<ButtonSecondary
|
<ButtonSecondary
|
||||||
v-tippy="{ theme: 'tooltip' }"
|
v-tippy="{ theme: 'tooltip' }"
|
||||||
:title="expand ? $t('hide_more') : $t('show_more')"
|
:title="expand ? $t('hide.more') : $t('show.more')"
|
||||||
:icon="expand ? 'unfold_less' : 'unfold_more'"
|
:icon="expand ? 'unfold_less' : 'unfold_more'"
|
||||||
class="group-hover:inline-flex hidden"
|
class="group-hover:inline-flex hidden"
|
||||||
@click.native="expand = !expand"
|
@click.native="expand = !expand"
|
||||||
/>
|
/>
|
||||||
<ButtonSecondary
|
<ButtonSecondary
|
||||||
v-tippy="{ theme: 'tooltip' }"
|
v-tippy="{ theme: 'tooltip' }"
|
||||||
:title="!entry.star ? $t('add_star') : $t('remove_star')"
|
:title="!entry.star ? $t('add.star') : $t('remove.star')"
|
||||||
:icon="entry.star ? 'star' : 'star_border'"
|
:icon="entry.star ? 'star' : 'star_border'"
|
||||||
color="yellow"
|
color="yellow"
|
||||||
:class="{ 'group-hover:inline-flex hidden': !entry.star }"
|
:class="{ 'group-hover:inline-flex hidden': !entry.star }"
|
||||||
@@ -51,14 +51,7 @@
|
|||||||
<span
|
<span
|
||||||
v-for="(line, index) in query"
|
v-for="(line, index) in query"
|
||||||
:key="`line-${index}`"
|
:key="`line-${index}`"
|
||||||
class="
|
class="cursor-pointer font-mono text-secondaryLight px-4 truncate"
|
||||||
text-xs
|
|
||||||
cursor-pointer
|
|
||||||
truncate
|
|
||||||
px-4
|
|
||||||
font-mono
|
|
||||||
text-secondaryLight
|
|
||||||
"
|
|
||||||
data-testid="restore_history_entry"
|
data-testid="restore_history_entry"
|
||||||
@click="$emit('use-entry')"
|
@click="$emit('use-entry')"
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -2,28 +2,32 @@
|
|||||||
<AppSection label="history">
|
<AppSection label="history">
|
||||||
<div
|
<div
|
||||||
class="
|
class="
|
||||||
flex
|
|
||||||
sticky
|
|
||||||
z-10
|
|
||||||
bg-primaryLight
|
bg-primaryLight
|
||||||
top-10
|
|
||||||
border-b border-dividerLight
|
border-b border-dividerLight
|
||||||
|
flex
|
||||||
|
top-8
|
||||||
|
z-10
|
||||||
|
sticky
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
|
<div class="search-wrapper">
|
||||||
<input
|
<input
|
||||||
v-model="filterText"
|
v-model="filterText"
|
||||||
type="search"
|
type="search"
|
||||||
class="
|
class="
|
||||||
px-4
|
|
||||||
py-3
|
|
||||||
text-xs
|
|
||||||
flex flex-1
|
|
||||||
font-medium
|
|
||||||
bg-primaryLight
|
bg-primaryLight
|
||||||
|
flex
|
||||||
|
font-semibold font-mono
|
||||||
|
w-full
|
||||||
|
py-2
|
||||||
|
pr-2
|
||||||
|
pl-9
|
||||||
focus:outline-none
|
focus:outline-none
|
||||||
|
truncate
|
||||||
"
|
"
|
||||||
:placeholder="$t('search')"
|
:placeholder="$t('search')"
|
||||||
/>
|
/>
|
||||||
|
</div>
|
||||||
<ButtonSecondary
|
<ButtonSecondary
|
||||||
v-tippy="{ theme: 'tooltip' }"
|
v-tippy="{ theme: 'tooltip' }"
|
||||||
data-testid="clear_history"
|
data-testid="clear_history"
|
||||||
@@ -56,25 +60,25 @@
|
|||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
v-if="!(filteredHistory.length !== 0 || history.length === 0)"
|
v-if="!(filteredHistory.length !== 0 || history.length === 0)"
|
||||||
class="flex items-center text-secondaryLight flex-col p-4 justify-center"
|
class="flex flex-col text-secondaryLight p-4 items-center justify-center"
|
||||||
>
|
>
|
||||||
<i class="material-icons opacity-50 pb-2">manage_search</i>
|
<i class="opacity-75 pb-2 material-icons">manage_search</i>
|
||||||
<span class="text-xs text-center">
|
<span class="text-center">
|
||||||
{{ $t("nothing_found") }} "{{ filterText }}"
|
{{ $t("nothing_found") }} "{{ filterText }}"
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
v-if="history.length === 0"
|
v-if="history.length === 0"
|
||||||
class="flex items-center text-secondaryLight flex-col p-4 justify-center"
|
class="flex flex-col text-secondaryLight p-4 items-center justify-center"
|
||||||
>
|
>
|
||||||
<i class="material-icons opacity-50 pb-2">schedule</i>
|
<i class="opacity-75 pb-2 material-icons">schedule</i>
|
||||||
<span class="text-xs text-center">
|
<span class="text-center">
|
||||||
{{ $t("history_empty") }}
|
{{ $t("empty.history") }}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<SmartConfirmModal
|
<SmartConfirmModal
|
||||||
:show="confirmRemove"
|
:show="confirmRemove"
|
||||||
:title="$t('are_you_sure_remove_history')"
|
:title="$t('confirm.remove_history')"
|
||||||
@hide-modal="confirmRemove = false"
|
@hide-modal="confirmRemove = false"
|
||||||
@resolve="clearHistory"
|
@resolve="clearHistory"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -2,15 +2,14 @@
|
|||||||
<div class="flex items-center group">
|
<div class="flex items-center group">
|
||||||
<span
|
<span
|
||||||
class="
|
class="
|
||||||
font-mono font-bold
|
cursor-pointer
|
||||||
flex
|
flex
|
||||||
|
font-mono font-bold
|
||||||
|
mx-2
|
||||||
|
w-12
|
||||||
justify-center
|
justify-center
|
||||||
items-center
|
items-center
|
||||||
text-xs
|
|
||||||
w-12
|
|
||||||
mx-2
|
|
||||||
truncate
|
truncate
|
||||||
cursor-pointer
|
|
||||||
"
|
"
|
||||||
:class="entryStatus.className"
|
:class="entryStatus.className"
|
||||||
data-testid="restore_history_entry"
|
data-testid="restore_history_entry"
|
||||||
@@ -21,15 +20,15 @@
|
|||||||
</span>
|
</span>
|
||||||
<span
|
<span
|
||||||
class="
|
class="
|
||||||
py-3
|
|
||||||
cursor-pointer
|
cursor-pointer
|
||||||
pr-2
|
flex
|
||||||
flex flex-1
|
|
||||||
min-w-0
|
|
||||||
text-xs
|
|
||||||
group-hover:text-secondaryDark
|
|
||||||
transition
|
|
||||||
font-semibold
|
font-semibold
|
||||||
|
flex-1
|
||||||
|
min-w-0
|
||||||
|
py-2
|
||||||
|
pr-2
|
||||||
|
transition
|
||||||
|
group-hover:text-secondaryDark
|
||||||
"
|
"
|
||||||
data-testid="restore_history_entry"
|
data-testid="restore_history_entry"
|
||||||
:title="duration"
|
:title="duration"
|
||||||
@@ -42,15 +41,15 @@
|
|||||||
<ButtonSecondary
|
<ButtonSecondary
|
||||||
v-tippy="{ theme: 'tooltip' }"
|
v-tippy="{ theme: 'tooltip' }"
|
||||||
icon="delete"
|
icon="delete"
|
||||||
|
color="red"
|
||||||
:title="$t('delete')"
|
:title="$t('delete')"
|
||||||
class="group-hover:inline-flex hidden"
|
class="group-hover:inline-flex hidden"
|
||||||
color="red"
|
|
||||||
data-testid="delete_history_entry"
|
data-testid="delete_history_entry"
|
||||||
@click.native="$emit('delete-entry')"
|
@click.native="$emit('delete-entry')"
|
||||||
/>
|
/>
|
||||||
<ButtonSecondary
|
<ButtonSecondary
|
||||||
v-tippy="{ theme: 'tooltip' }"
|
v-tippy="{ theme: 'tooltip' }"
|
||||||
:title="!entry.star ? $t('add_star') : $t('remove_star')"
|
:title="!entry.star ? $t('add.star') : $t('remove.star')"
|
||||||
:class="{ 'group-hover:inline-flex hidden': !entry.star }"
|
:class="{ 'group-hover:inline-flex hidden': !entry.star }"
|
||||||
:icon="entry.star ? 'star' : 'star_border'"
|
:icon="entry.star ? 'star' : 'star_border'"
|
||||||
color="yellow"
|
color="yellow"
|
||||||
|
|||||||
73
components/http/Body.vue
Normal file
73
components/http/Body.vue
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<div class="flex flex-1 py-2 items-center justify-between">
|
||||||
|
<tippy
|
||||||
|
ref="contentTypeOptions"
|
||||||
|
interactive
|
||||||
|
tabindex="-1"
|
||||||
|
trigger="click"
|
||||||
|
theme="popover"
|
||||||
|
arrow
|
||||||
|
>
|
||||||
|
<template #trigger>
|
||||||
|
<div class="flex">
|
||||||
|
<span class="select-wrapper">
|
||||||
|
<input
|
||||||
|
id="contentType"
|
||||||
|
v-model="contentType"
|
||||||
|
class="
|
||||||
|
bg-primary
|
||||||
|
rounded
|
||||||
|
flex
|
||||||
|
font-semibold font-mono
|
||||||
|
w-full
|
||||||
|
py-2
|
||||||
|
px-4
|
||||||
|
transition
|
||||||
|
truncate
|
||||||
|
focus:outline-none
|
||||||
|
"
|
||||||
|
readonly
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<SmartItem
|
||||||
|
v-for="(contentTypeItem, index) in validContentTypes"
|
||||||
|
:key="`contentTypeItem-${index}`"
|
||||||
|
:label="contentTypeItem"
|
||||||
|
@click.native="
|
||||||
|
contentType = contentTypeItem
|
||||||
|
$refs.contentTypeOptions.tippy().hide()
|
||||||
|
"
|
||||||
|
/>
|
||||||
|
</tippy>
|
||||||
|
<SmartToggle :on="rawInput" class="px-4" @change="rawInput = !rawInput">
|
||||||
|
{{ $t("raw_input") }}
|
||||||
|
</SmartToggle>
|
||||||
|
</div>
|
||||||
|
<HttpBodyParameters v-if="!rawInput" :content-type="contentType" />
|
||||||
|
<HttpRawBody v-else :content-type="contentType" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { defineComponent } from "@nuxtjs/composition-api"
|
||||||
|
import { pluckRef } from "~/helpers/utils/composables"
|
||||||
|
import { useRESTRequestBody } from "~/newstore/RESTSession"
|
||||||
|
import { knownContentTypes } from "~/helpers/utils/contenttypes"
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
setup() {
|
||||||
|
return {
|
||||||
|
contentType: pluckRef(useRESTRequestBody(), "contentType"),
|
||||||
|
rawInput: pluckRef(useRESTRequestBody(), "isRaw"),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
validContentTypes: Object.keys(knownContentTypes),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
})
|
||||||
|
</script>
|
||||||
@@ -2,20 +2,21 @@
|
|||||||
<AppSection label="bodyParameters">
|
<AppSection label="bodyParameters">
|
||||||
<div
|
<div
|
||||||
class="
|
class="
|
||||||
sticky
|
|
||||||
top-110px
|
|
||||||
z-10
|
|
||||||
bg-primary
|
bg-primary
|
||||||
|
border-b border-dividerLight
|
||||||
flex flex-1
|
flex flex-1
|
||||||
|
pl-4
|
||||||
|
top-24
|
||||||
|
z-10
|
||||||
|
sticky
|
||||||
items-center
|
items-center
|
||||||
justify-between
|
justify-between
|
||||||
pl-4
|
|
||||||
border-b border-dividerLight
|
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
<label for="reqParamList" class="font-semibold text-xs">
|
<label for="reqParamList" class="font-semibold">
|
||||||
{{ $t("request_body") }}
|
{{ $t("request_body") }}
|
||||||
</label>
|
</label>
|
||||||
|
<div class="flex">
|
||||||
<ButtonSecondary
|
<ButtonSecondary
|
||||||
v-tippy="{ theme: 'tooltip' }"
|
v-tippy="{ theme: 'tooltip' }"
|
||||||
:title="$t('clear')"
|
:title="$t('clear')"
|
||||||
@@ -23,29 +24,24 @@
|
|||||||
@click.native="clearContent('bodyParams', $event)"
|
@click.native="clearContent('bodyParams', $event)"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
<div
|
<div
|
||||||
v-for="(param, index) in bodyParams"
|
v-for="(param, index) in bodyParams"
|
||||||
:key="`param-${index}`"
|
:key="`param-${index}`"
|
||||||
class="
|
class="divide-x divide-dividerLight border-b border-dividerLight flex"
|
||||||
flex
|
|
||||||
border-b border-dashed
|
|
||||||
divide-x
|
|
||||||
border-divider
|
|
||||||
divide-dashed divide-divider
|
|
||||||
"
|
|
||||||
:class="{ 'border-t': index == 0 }"
|
:class="{ 'border-t': index == 0 }"
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
class="
|
class="
|
||||||
px-4
|
|
||||||
py-3
|
|
||||||
text-xs
|
|
||||||
flex flex-1
|
|
||||||
font-semibold
|
|
||||||
bg-primaryLight
|
bg-primaryLight
|
||||||
|
flex
|
||||||
|
font-semibold font-mono
|
||||||
|
flex-1
|
||||||
|
py-2
|
||||||
|
px-4
|
||||||
focus:outline-none
|
focus:outline-none
|
||||||
"
|
"
|
||||||
:placeholder="$t('parameter_count', { count: index + 1 })"
|
:placeholder="$t('count.parameter', { count: index + 1 })"
|
||||||
:name="'param' + index"
|
:name="'param' + index"
|
||||||
:value="param.key"
|
:value="param.key"
|
||||||
autofocus
|
autofocus
|
||||||
@@ -55,15 +51,15 @@
|
|||||||
<input
|
<input
|
||||||
v-if="!requestBodyParamIsFile(index)"
|
v-if="!requestBodyParamIsFile(index)"
|
||||||
class="
|
class="
|
||||||
px-4
|
|
||||||
py-3
|
|
||||||
text-xs
|
|
||||||
flex flex-1
|
|
||||||
font-semibold
|
|
||||||
bg-primaryLight
|
bg-primaryLight
|
||||||
|
flex
|
||||||
|
font-semibold font-mono
|
||||||
|
flex-1
|
||||||
|
py-2
|
||||||
|
px-4
|
||||||
focus:outline-none
|
focus:outline-none
|
||||||
"
|
"
|
||||||
:placeholder="$t('value_count', { count: index + 1 })"
|
:placeholder="$t('count.value', { count: index + 1 })"
|
||||||
:name="'value' + index"
|
:name="'value' + index"
|
||||||
:value="param.value"
|
:value="param.value"
|
||||||
@change="
|
@change="
|
||||||
@@ -90,9 +86,9 @@
|
|||||||
:title="
|
:title="
|
||||||
param.hasOwnProperty('active')
|
param.hasOwnProperty('active')
|
||||||
? param.active
|
? param.active
|
||||||
? $t('turn_off')
|
? $t('action.turn_off')
|
||||||
: $t('turn_on')
|
: $t('action.turn_on')
|
||||||
: $t('turn_off')
|
: $t('action.turn_off')
|
||||||
"
|
"
|
||||||
:icon="
|
:icon="
|
||||||
param.hasOwnProperty('active')
|
param.hasOwnProperty('active')
|
||||||
@@ -101,10 +97,11 @@
|
|||||||
: 'check_box_outline_blank'
|
: 'check_box_outline_blank'
|
||||||
: 'check_box'
|
: 'check_box'
|
||||||
"
|
"
|
||||||
|
color="green"
|
||||||
@click.native="toggleActive(index, param)"
|
@click.native="toggleActive(index, param)"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="contentType === 'multipart/form-data'">
|
<div>
|
||||||
<label for="attachment" class="p-0">
|
<label for="attachment" class="p-0">
|
||||||
<ButtonSecondary
|
<ButtonSecondary
|
||||||
class="w-full"
|
class="w-full"
|
||||||
@@ -126,6 +123,7 @@
|
|||||||
v-tippy="{ theme: 'tooltip' }"
|
v-tippy="{ theme: 'tooltip' }"
|
||||||
:title="$t('delete')"
|
:title="$t('delete')"
|
||||||
icon="delete"
|
icon="delete"
|
||||||
|
color="red"
|
||||||
@click.native="removeRequestBodyParam(index)"
|
@click.native="removeRequestBodyParam(index)"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -5,8 +5,8 @@
|
|||||||
<ButtonSecondary icon="close" @click.native="hideModal" />
|
<ButtonSecondary icon="close" @click.native="hideModal" />
|
||||||
</template>
|
</template>
|
||||||
<template #body>
|
<template #body>
|
||||||
<div class="px-2 flex flex-col">
|
<div class="flex flex-col px-2">
|
||||||
<label for="requestType" class="px-4 font-semibold pb-4 text-xs">
|
<label for="requestType" class="font-semibold px-4 pb-4">
|
||||||
{{ $t("choose_language") }}
|
{{ $t("choose_language") }}
|
||||||
</label>
|
</label>
|
||||||
<div class="flex flex-1">
|
<div class="flex flex-1">
|
||||||
@@ -22,20 +22,19 @@
|
|||||||
<template #trigger>
|
<template #trigger>
|
||||||
<span
|
<span
|
||||||
class="
|
class="
|
||||||
flex
|
|
||||||
w-full
|
|
||||||
px-4
|
|
||||||
text-xs
|
|
||||||
py-3
|
|
||||||
rounded-lg
|
|
||||||
font-semibold
|
|
||||||
focus:outline-none
|
|
||||||
border-b border-dividerLight
|
|
||||||
bg-primaryLight
|
bg-primaryLight
|
||||||
|
border border-dividerLight
|
||||||
|
rounded
|
||||||
cursor-pointer
|
cursor-pointer
|
||||||
|
flex
|
||||||
|
font-semibold
|
||||||
|
w-full
|
||||||
|
py-2
|
||||||
|
px-4
|
||||||
|
focus:outline-none
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
{{ codegens.find((x) => x.id === requestType).name }}
|
{{ codegens.find((x) => x.id === codegenType).name }}
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
<SmartItem
|
<SmartItem
|
||||||
@@ -43,72 +42,109 @@
|
|||||||
:key="`gen-${index}`"
|
:key="`gen-${index}`"
|
||||||
:label="gen.name"
|
:label="gen.name"
|
||||||
@click.native="
|
@click.native="
|
||||||
requestType = gen.id
|
codegenType = gen.id
|
||||||
$refs.options.tippy().hide()
|
$refs.options.tippy().hide()
|
||||||
"
|
"
|
||||||
/>
|
/>
|
||||||
</tippy>
|
</tippy>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex justify-between flex-1">
|
<div class="flex flex-1 justify-between">
|
||||||
<label
|
<label for="generatedCode" class="font-semibold px-4 pt-4 pb-4">
|
||||||
for="generatedCode"
|
|
||||||
class="px-4 pt-4 font-semibold pb-4 text-xs"
|
|
||||||
>
|
|
||||||
{{ $t("generated_code") }}
|
{{ $t("generated_code") }}
|
||||||
</label>
|
</label>
|
||||||
<ButtonSecondary
|
|
||||||
ref="copyRequestCode"
|
|
||||||
v-tippy="{ theme: 'tooltip' }"
|
|
||||||
:title="$t('copy_code')"
|
|
||||||
:icon="copyIcon"
|
|
||||||
@click.native="copyRequestCode"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
<SmartAceEditor
|
<SmartAceEditor
|
||||||
v-if="requestType"
|
v-if="codegenType"
|
||||||
ref="generatedCode"
|
ref="generatedCode"
|
||||||
:value="requestCode"
|
:value="requestCode"
|
||||||
:lang="codegens.find((x) => x.id === requestType).language"
|
:lang="codegens.find((x) => x.id === codegenType).language"
|
||||||
:options="{
|
:options="{
|
||||||
maxLines: '10',
|
maxLines: 16,
|
||||||
minLines: '10',
|
minLines: 8,
|
||||||
fontSize: '14px',
|
fontSize: '12px',
|
||||||
autoScrollEditorIntoView: true,
|
autoScrollEditorIntoView: true,
|
||||||
readOnly: true,
|
readOnly: true,
|
||||||
showPrintMargin: false,
|
showPrintMargin: false,
|
||||||
useWorker: false,
|
useWorker: false,
|
||||||
}"
|
}"
|
||||||
styles="rounded-lg"
|
styles="rounded"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
<template #footer>
|
||||||
|
<ButtonPrimary
|
||||||
|
ref="copyRequestCode"
|
||||||
|
:label="$t('action.copy')"
|
||||||
|
:icon="copyIcon"
|
||||||
|
@click.native="copyRequestCode"
|
||||||
|
/>
|
||||||
|
<ButtonSecondary
|
||||||
|
:label="$t('action.dismiss')"
|
||||||
|
@click.native="hideModal"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
</SmartModal>
|
</SmartModal>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script lang="ts">
|
||||||
|
import { defineComponent } from "@nuxtjs/composition-api"
|
||||||
import { codegens } from "~/helpers/codegen/codegen"
|
import { codegens } from "~/helpers/codegen/codegen"
|
||||||
|
import { getRESTRequest } from "~/newstore/RESTSession"
|
||||||
|
import { getEffectiveRESTRequest } from "~/helpers/utils/EffectiveURL"
|
||||||
|
import { getCurrentEnvironment } from "~/newstore/environments"
|
||||||
|
import { copyToClipboard } from "~/helpers/utils/clipboard"
|
||||||
|
|
||||||
export default {
|
export default defineComponent({
|
||||||
props: {
|
props: {
|
||||||
show: Boolean,
|
show: Boolean,
|
||||||
requestCode: { type: String, default: null },
|
|
||||||
requestTypeProp: { type: String, default: "curl" },
|
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
codegens,
|
codegens,
|
||||||
copyIcon: "content_copy",
|
copyIcon: "content_copy",
|
||||||
|
request: getRESTRequest(),
|
||||||
|
codegenType: "curl",
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
requestType: {
|
requestCode(): string {
|
||||||
get() {
|
const effectiveRequest = getEffectiveRESTRequest(
|
||||||
return this.requestTypeProp
|
this.request,
|
||||||
|
getCurrentEnvironment()
|
||||||
|
)
|
||||||
|
|
||||||
|
const urlObj = new URL(effectiveRequest.effectiveFinalURL)
|
||||||
|
const baseURL = urlObj.origin
|
||||||
|
const path = urlObj.pathname
|
||||||
|
|
||||||
|
// TODO: Solidify
|
||||||
|
return codegens
|
||||||
|
.find((x) => x.id === this.codegenType)!
|
||||||
|
.generator({
|
||||||
|
auth: "None",
|
||||||
|
httpUser: null,
|
||||||
|
httpPassword: null,
|
||||||
|
method: effectiveRequest.method,
|
||||||
|
url: baseURL,
|
||||||
|
pathName: path,
|
||||||
|
queryString: urlObj.searchParams.toString(),
|
||||||
|
bearerToken: null,
|
||||||
|
headers: effectiveRequest.effectiveFinalHeaders,
|
||||||
|
rawInput: null,
|
||||||
|
rawParams: null,
|
||||||
|
rawRequestBody: "",
|
||||||
|
contentType: effectiveRequest.effectiveFinalHeaders.find(
|
||||||
|
(x) => x.key === "content-type"
|
||||||
|
),
|
||||||
|
})
|
||||||
},
|
},
|
||||||
set(val) {
|
|
||||||
this.$emit("set-request-type", val)
|
|
||||||
},
|
},
|
||||||
|
watch: {
|
||||||
|
show(goingToShow) {
|
||||||
|
if (goingToShow) {
|
||||||
|
this.request = getRESTRequest()
|
||||||
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
@@ -119,15 +155,13 @@ export default {
|
|||||||
this.$emit("handle-import")
|
this.$emit("handle-import")
|
||||||
},
|
},
|
||||||
copyRequestCode() {
|
copyRequestCode() {
|
||||||
this.$refs.generatedCode.editor.selectAll()
|
copyToClipboard(this.requestCode)
|
||||||
this.$refs.generatedCode.editor.focus()
|
|
||||||
document.execCommand("copy")
|
|
||||||
this.copyIcon = "done"
|
this.copyIcon = "done"
|
||||||
this.$toast.success(this.$t("copied_to_clipboard"), {
|
this.$toast.success(this.$t("copied_to_clipboard").toString(), {
|
||||||
icon: "done",
|
icon: "done",
|
||||||
})
|
})
|
||||||
setTimeout(() => (this.copyIcon = "content_copy"), 1000)
|
setTimeout(() => (this.copyIcon = "content_copy"), 1000)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -2,21 +2,21 @@
|
|||||||
<AppSection label="headers">
|
<AppSection label="headers">
|
||||||
<div
|
<div
|
||||||
class="
|
class="
|
||||||
sticky
|
|
||||||
top-110px
|
|
||||||
z-10
|
|
||||||
bg-primary
|
bg-primary
|
||||||
|
border-b border-dividerLight
|
||||||
flex flex-1
|
flex flex-1
|
||||||
|
pl-4
|
||||||
|
top-24
|
||||||
|
z-10
|
||||||
|
sticky
|
||||||
items-center
|
items-center
|
||||||
justify-between
|
justify-between
|
||||||
pl-4
|
|
||||||
border-b border-dividerLight
|
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
<label for="headerList" class="font-semibold text-xs">
|
<label for="headerList" class="font-semibold">
|
||||||
{{ $t("header_list") }}
|
{{ $t("header_list") }}
|
||||||
</label>
|
</label>
|
||||||
<div>
|
<div class="flex">
|
||||||
<ButtonSecondary
|
<ButtonSecondary
|
||||||
v-tippy="{ theme: 'tooltip' }"
|
v-tippy="{ theme: 'tooltip' }"
|
||||||
:title="$t('clear')"
|
:title="$t('clear')"
|
||||||
@@ -25,7 +25,7 @@
|
|||||||
/>
|
/>
|
||||||
<ButtonSecondary
|
<ButtonSecondary
|
||||||
v-tippy="{ theme: 'tooltip' }"
|
v-tippy="{ theme: 'tooltip' }"
|
||||||
:title="$t('add_new')"
|
:title="$t('add.new')"
|
||||||
icon="add"
|
icon="add"
|
||||||
@click.native="addHeader"
|
@click.native="addHeader"
|
||||||
/>
|
/>
|
||||||
@@ -34,21 +34,24 @@
|
|||||||
<div
|
<div
|
||||||
v-for="(header, index) in headers$"
|
v-for="(header, index) in headers$"
|
||||||
:key="`header-${index}`"
|
:key="`header-${index}`"
|
||||||
class="
|
class="divide-x divide-dividerLight border-b border-dividerLight flex"
|
||||||
flex
|
|
||||||
border-b border-dashed
|
|
||||||
divide-x
|
|
||||||
border-divider
|
|
||||||
divide-dashed divide-divider
|
|
||||||
"
|
|
||||||
:class="{ 'border-t': index == 0 }"
|
:class="{ 'border-t': index == 0 }"
|
||||||
>
|
>
|
||||||
<SmartAutoComplete
|
<SmartAutoComplete
|
||||||
:placeholder="$t('header_count', { count: index + 1 })"
|
:placeholder="$t('count.header', { count: index + 1 })"
|
||||||
:source="commonHeaders"
|
:source="commonHeaders"
|
||||||
:spellcheck="false"
|
:spellcheck="false"
|
||||||
:value="header.key"
|
:value="header.key"
|
||||||
autofocus
|
autofocus
|
||||||
|
styles="
|
||||||
|
bg-primaryLight
|
||||||
|
flex
|
||||||
|
font-semibold font-mono
|
||||||
|
flex-1
|
||||||
|
py-1
|
||||||
|
px-4
|
||||||
|
focus:outline-none
|
||||||
|
"
|
||||||
@input="
|
@input="
|
||||||
updateHeader(index, {
|
updateHeader(index, {
|
||||||
key: $event,
|
key: $event,
|
||||||
@@ -57,17 +60,39 @@
|
|||||||
})
|
})
|
||||||
"
|
"
|
||||||
/>
|
/>
|
||||||
<input
|
<SmartEnvInput
|
||||||
class="
|
v-if="EXPERIMENTAL_URL_BAR_ENABLED"
|
||||||
px-4
|
v-model="header.value"
|
||||||
py-3
|
:placeholder="$t('count.value', { count: index + 1 })"
|
||||||
text-xs
|
styles="
|
||||||
flex flex-1
|
|
||||||
font-semibold
|
|
||||||
bg-primaryLight
|
bg-primaryLight
|
||||||
|
flex
|
||||||
|
font-semibold font-mono
|
||||||
|
flex-1
|
||||||
|
py-1
|
||||||
|
px-4
|
||||||
focus:outline-none
|
focus:outline-none
|
||||||
"
|
"
|
||||||
:placeholder="$t('value_count', { count: index + 1 })"
|
@change="
|
||||||
|
updateHeader(index, {
|
||||||
|
key: header.key,
|
||||||
|
value: $event.target.value,
|
||||||
|
active: header.active,
|
||||||
|
})
|
||||||
|
"
|
||||||
|
/>
|
||||||
|
<input
|
||||||
|
v-else
|
||||||
|
class="
|
||||||
|
bg-primaryLight
|
||||||
|
flex
|
||||||
|
font-semibold font-mono
|
||||||
|
flex-1
|
||||||
|
py-2
|
||||||
|
px-4
|
||||||
|
focus:outline-none
|
||||||
|
"
|
||||||
|
:placeholder="$t('count.value', { count: index + 1 })"
|
||||||
:name="'value' + index"
|
:name="'value' + index"
|
||||||
:value="header.value"
|
:value="header.value"
|
||||||
@change="
|
@change="
|
||||||
@@ -84,9 +109,9 @@
|
|||||||
:title="
|
:title="
|
||||||
header.hasOwnProperty('active')
|
header.hasOwnProperty('active')
|
||||||
? header.active
|
? header.active
|
||||||
? $t('turn_off')
|
? $t('action.turn_off')
|
||||||
: $t('turn_on')
|
: $t('action.turn_on')
|
||||||
: $t('turn_off')
|
: $t('action.turn_off')
|
||||||
"
|
"
|
||||||
:icon="
|
:icon="
|
||||||
header.hasOwnProperty('active')
|
header.hasOwnProperty('active')
|
||||||
@@ -95,6 +120,7 @@
|
|||||||
: 'check_box_outline_blank'
|
: 'check_box_outline_blank'
|
||||||
: 'check_box'
|
: 'check_box'
|
||||||
"
|
"
|
||||||
|
color="green"
|
||||||
@click.native="
|
@click.native="
|
||||||
updateHeader(index, {
|
updateHeader(index, {
|
||||||
key: header.key,
|
key: header.key,
|
||||||
@@ -109,10 +135,25 @@
|
|||||||
v-tippy="{ theme: 'tooltip' }"
|
v-tippy="{ theme: 'tooltip' }"
|
||||||
:title="$t('delete')"
|
:title="$t('delete')"
|
||||||
icon="delete"
|
icon="delete"
|
||||||
|
color="red"
|
||||||
@click.native="deleteHeader(index)"
|
@click.native="deleteHeader(index)"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div
|
||||||
|
v-if="headers$.length === 0"
|
||||||
|
class="flex flex-col text-secondaryLight p-4 items-center justify-center"
|
||||||
|
>
|
||||||
|
<i class="opacity-75 pb-2 material-icons">post_add</i>
|
||||||
|
<span class="text-center pb-4">
|
||||||
|
{{ $t("empty.headers") }}
|
||||||
|
</span>
|
||||||
|
<ButtonSecondary
|
||||||
|
outline
|
||||||
|
:label="$t('add.new')"
|
||||||
|
@click.native="addHeader"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</AppSection>
|
</AppSection>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -126,30 +167,37 @@ import {
|
|||||||
} from "~/newstore/RESTSession"
|
} from "~/newstore/RESTSession"
|
||||||
|
|
||||||
import { commonHeaders } from "~/helpers/headers"
|
import { commonHeaders } from "~/helpers/headers"
|
||||||
|
import { getSettingSubject } from "~/newstore/settings"
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
commonHeaders,
|
commonHeaders,
|
||||||
|
headers$: [],
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
subscriptions() {
|
subscriptions() {
|
||||||
return {
|
return {
|
||||||
headers$: restHeaders$,
|
headers$: restHeaders$,
|
||||||
|
EXPERIMENTAL_URL_BAR_ENABLED: getSettingSubject(
|
||||||
|
"EXPERIMENTAL_URL_BAR_ENABLED"
|
||||||
|
),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// watch: {
|
watch: {
|
||||||
// headers: {
|
headers$: {
|
||||||
// handler(newValue) {
|
handler(newValue) {
|
||||||
// if (
|
console.log("changed")
|
||||||
// newValue[newValue.length - 1]?.key !== "" ||
|
if (
|
||||||
// newValue[newValue.length - 1]?.value !== ""
|
(newValue[newValue.length - 1]?.key !== "" ||
|
||||||
// )
|
newValue[newValue.length - 1]?.value !== "") &&
|
||||||
// this.addRequestHeader()
|
newValue.length
|
||||||
// },
|
)
|
||||||
// deep: true,
|
this.addHeader()
|
||||||
// },
|
},
|
||||||
// },
|
deep: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
if (!this.headers$?.length) {
|
if (!this.headers$?.length) {
|
||||||
this.addHeader()
|
this.addHeader()
|
||||||
|
|||||||
@@ -1,41 +1,134 @@
|
|||||||
<template>
|
<template>
|
||||||
<SmartModal v-if="show" @close="hideModal">
|
<SmartModal v-if="show" @close="hideModal">
|
||||||
<template #header>
|
<template #header>
|
||||||
<h3 class="heading">{{ $t("import_curl") }}</h3>
|
<h3 class="heading">{{ $t("import.curl") }}</h3>
|
||||||
<div>
|
<div>
|
||||||
<ButtonSecondary icon="close" @click.native="hideModal" />
|
<ButtonSecondary icon="close" @click.native="hideModal" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template #body>
|
<template #body>
|
||||||
|
<div class="flex flex-col px-2">
|
||||||
<textarea
|
<textarea
|
||||||
id="import-curl"
|
id="import-curl"
|
||||||
|
v-model="curl"
|
||||||
class="textarea"
|
class="textarea"
|
||||||
autofocus
|
autofocus
|
||||||
rows="8"
|
rows="8"
|
||||||
:placeholder="$t('enter_curl')"
|
:placeholder="$t('enter_curl')"
|
||||||
></textarea>
|
></textarea>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<span>
|
<span>
|
||||||
<ButtonPrimary :label="$t('import')" @click.native="handleImport" />
|
<ButtonPrimary
|
||||||
|
:label="$t('import.title')"
|
||||||
|
@click.native="handleImport"
|
||||||
|
/>
|
||||||
<ButtonSecondary :label="$t('cancel')" @click.native="hideModal" />
|
<ButtonSecondary :label="$t('cancel')" @click.native="hideModal" />
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
</SmartModal>
|
</SmartModal>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script lang="ts">
|
||||||
export default {
|
import { defineComponent } from "@nuxtjs/composition-api"
|
||||||
|
import parseCurlCommand from "~/helpers/curlparser"
|
||||||
|
import {
|
||||||
|
HoppRESTHeader,
|
||||||
|
HoppRESTParam,
|
||||||
|
makeRESTRequest,
|
||||||
|
} from "~/helpers/types/HoppRESTRequest"
|
||||||
|
import { setRESTRequest } from "~/newstore/RESTSession"
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
props: {
|
props: {
|
||||||
show: Boolean,
|
show: Boolean,
|
||||||
},
|
},
|
||||||
|
emits: ["hide-modal"],
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
curl: "",
|
||||||
|
}
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
hideModal() {
|
hideModal() {
|
||||||
this.$emit("hide-modal")
|
this.$emit("hide-modal")
|
||||||
},
|
},
|
||||||
handleImport() {
|
handleImport() {
|
||||||
this.$emit("handle-import")
|
const text = this.curl
|
||||||
|
try {
|
||||||
|
const parsedCurl = parseCurlCommand(text)
|
||||||
|
const { origin, pathname } = new URL(
|
||||||
|
parsedCurl.url.replace(/"/g, "").replace(/'/g, "")
|
||||||
|
)
|
||||||
|
const endpoint = origin + pathname
|
||||||
|
const headers: HoppRESTHeader[] = []
|
||||||
|
const params: HoppRESTParam[] = []
|
||||||
|
if (parsedCurl.query) {
|
||||||
|
for (const key of Object.keys(parsedCurl.query)) {
|
||||||
|
const val = parsedCurl.query[key]!
|
||||||
|
|
||||||
|
if (Array.isArray(val)) {
|
||||||
|
val.forEach((value) => {
|
||||||
|
params.push({
|
||||||
|
key,
|
||||||
|
value,
|
||||||
|
active: true,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
params.push({
|
||||||
|
key,
|
||||||
|
value: val!,
|
||||||
|
active: true,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (parsedCurl.headers) {
|
||||||
|
for (const key of Object.keys(parsedCurl.headers)) {
|
||||||
|
headers.push({
|
||||||
|
key,
|
||||||
|
value: parsedCurl.headers[key],
|
||||||
|
active: true,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const method = parsedCurl.method.toUpperCase()
|
||||||
|
// let rawInput = false
|
||||||
|
// let rawParams: any | null = null
|
||||||
|
|
||||||
|
// if (parsedCurl.data) {
|
||||||
|
// rawInput = true
|
||||||
|
// rawParams = parsedCurl.data
|
||||||
|
// }
|
||||||
|
|
||||||
|
this.showCurlImportModal = false
|
||||||
|
|
||||||
|
setRESTRequest(
|
||||||
|
makeRESTRequest({
|
||||||
|
name: "Untitled request",
|
||||||
|
endpoint,
|
||||||
|
method,
|
||||||
|
params,
|
||||||
|
headers,
|
||||||
|
preRequestScript: "",
|
||||||
|
testScript: "",
|
||||||
|
body: {
|
||||||
|
contentType: "application/json",
|
||||||
|
body: "",
|
||||||
|
isRaw: false,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
)
|
||||||
|
} catch (error) {
|
||||||
|
this.showCurlImportModal = false
|
||||||
|
this.$toast.error(this.$t("curl_invalid_format").toString(), {
|
||||||
|
icon: "error",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
this.hideModal()
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -2,21 +2,21 @@
|
|||||||
<AppSection label="parameters">
|
<AppSection label="parameters">
|
||||||
<div
|
<div
|
||||||
class="
|
class="
|
||||||
sticky
|
|
||||||
top-110px
|
|
||||||
z-10
|
|
||||||
bg-primary
|
bg-primary
|
||||||
|
border-b border-dividerLight
|
||||||
flex flex-1
|
flex flex-1
|
||||||
|
pl-4
|
||||||
|
top-24
|
||||||
|
z-10
|
||||||
|
sticky
|
||||||
items-center
|
items-center
|
||||||
justify-between
|
justify-between
|
||||||
pl-4
|
|
||||||
border-b border-dividerLight
|
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
<label for="paramList" class="font-semibold text-xs">
|
<label class="font-semibold">
|
||||||
{{ $t("parameter_list") }}
|
{{ $t("parameter_list") }}
|
||||||
</label>
|
</label>
|
||||||
<div>
|
<div class="flex">
|
||||||
<ButtonSecondary
|
<ButtonSecondary
|
||||||
v-tippy="{ theme: 'tooltip' }"
|
v-tippy="{ theme: 'tooltip' }"
|
||||||
:title="$t('clear_all')"
|
:title="$t('clear_all')"
|
||||||
@@ -25,7 +25,7 @@
|
|||||||
/>
|
/>
|
||||||
<ButtonSecondary
|
<ButtonSecondary
|
||||||
v-tippy="{ theme: 'tooltip' }"
|
v-tippy="{ theme: 'tooltip' }"
|
||||||
:title="$t('add_new')"
|
:title="$t('add.new')"
|
||||||
icon="add"
|
icon="add"
|
||||||
@click.native="addParam"
|
@click.native="addParam"
|
||||||
/>
|
/>
|
||||||
@@ -34,26 +34,42 @@
|
|||||||
<div
|
<div
|
||||||
v-for="(param, index) in params$"
|
v-for="(param, index) in params$"
|
||||||
:key="`param-${index}`"
|
:key="`param-${index}`"
|
||||||
class="
|
class="divide-x divide-dividerLight border-b border-dividerLight flex"
|
||||||
flex
|
|
||||||
border-b border-dashed
|
|
||||||
divide-x
|
|
||||||
border-divider
|
|
||||||
divide-dashed divide-divider
|
|
||||||
"
|
|
||||||
:class="{ 'border-t': index == 0 }"
|
:class="{ 'border-t': index == 0 }"
|
||||||
>
|
>
|
||||||
<input
|
<SmartEnvInput
|
||||||
class="
|
v-if="EXPERIMENTAL_URL_BAR_ENABLED"
|
||||||
px-4
|
v-model="param.key"
|
||||||
py-3
|
:placeholder="$t('count.parameter', { count: index + 1 })"
|
||||||
text-xs
|
styles="
|
||||||
flex flex-1
|
|
||||||
font-semibold
|
|
||||||
bg-primaryLight
|
bg-primaryLight
|
||||||
|
flex
|
||||||
|
font-semibold font-mono
|
||||||
|
flex-1
|
||||||
|
py-1
|
||||||
|
px-4
|
||||||
focus:outline-none
|
focus:outline-none
|
||||||
"
|
"
|
||||||
:placeholder="$t('parameter_count', { count: index + 1 })"
|
@change="
|
||||||
|
updateParam(index, {
|
||||||
|
key: $event.target.value,
|
||||||
|
value: param.value,
|
||||||
|
active: param.active,
|
||||||
|
})
|
||||||
|
"
|
||||||
|
/>
|
||||||
|
<input
|
||||||
|
v-else
|
||||||
|
class="
|
||||||
|
bg-primaryLight
|
||||||
|
flex
|
||||||
|
font-semibold font-mono
|
||||||
|
flex-1
|
||||||
|
py-2
|
||||||
|
px-4
|
||||||
|
focus:outline-none
|
||||||
|
"
|
||||||
|
:placeholder="$t('count.parameter', { count: index + 1 })"
|
||||||
:name="'param' + index"
|
:name="'param' + index"
|
||||||
:value="param.key"
|
:value="param.key"
|
||||||
autofocus
|
autofocus
|
||||||
@@ -65,17 +81,39 @@
|
|||||||
})
|
})
|
||||||
"
|
"
|
||||||
/>
|
/>
|
||||||
<input
|
<SmartEnvInput
|
||||||
class="
|
v-if="EXPERIMENTAL_URL_BAR_ENABLED"
|
||||||
px-4
|
v-model="param.value"
|
||||||
py-3
|
:placeholder="$t('count.value', { count: index + 1 })"
|
||||||
text-xs
|
styles="
|
||||||
flex flex-1
|
|
||||||
font-semibold
|
|
||||||
bg-primaryLight
|
bg-primaryLight
|
||||||
|
flex
|
||||||
|
font-semibold font-mono
|
||||||
|
flex-1
|
||||||
|
py-1
|
||||||
|
px-4
|
||||||
focus:outline-none
|
focus:outline-none
|
||||||
"
|
"
|
||||||
:placeholder="$t('value_count', { count: index + 1 })"
|
@change="
|
||||||
|
updateParam(index, {
|
||||||
|
key: param.key,
|
||||||
|
value: $event.target.value,
|
||||||
|
active: param.active,
|
||||||
|
})
|
||||||
|
"
|
||||||
|
/>
|
||||||
|
<input
|
||||||
|
v-else
|
||||||
|
class="
|
||||||
|
bg-primaryLight
|
||||||
|
flex
|
||||||
|
font-semibold font-mono
|
||||||
|
flex-1
|
||||||
|
py-2
|
||||||
|
px-4
|
||||||
|
focus:outline-none
|
||||||
|
"
|
||||||
|
:placeholder="$t('count.value', { count: index + 1 })"
|
||||||
:name="'value' + index"
|
:name="'value' + index"
|
||||||
:value="param.value"
|
:value="param.value"
|
||||||
@change="
|
@change="
|
||||||
@@ -92,9 +130,9 @@
|
|||||||
:title="
|
:title="
|
||||||
param.hasOwnProperty('active')
|
param.hasOwnProperty('active')
|
||||||
? param.active
|
? param.active
|
||||||
? $t('turn_off')
|
? $t('action.turn_off')
|
||||||
: $t('turn_on')
|
: $t('action.turn_on')
|
||||||
: $t('turn_off')
|
: $t('action.turn_off')
|
||||||
"
|
"
|
||||||
:icon="
|
:icon="
|
||||||
param.hasOwnProperty('active')
|
param.hasOwnProperty('active')
|
||||||
@@ -103,6 +141,7 @@
|
|||||||
: 'check_box_outline_blank'
|
: 'check_box_outline_blank'
|
||||||
: 'check_box'
|
: 'check_box'
|
||||||
"
|
"
|
||||||
|
color="green"
|
||||||
@click.native="
|
@click.native="
|
||||||
updateParam(index, {
|
updateParam(index, {
|
||||||
key: param.key,
|
key: param.key,
|
||||||
@@ -117,10 +156,25 @@
|
|||||||
v-tippy="{ theme: 'tooltip' }"
|
v-tippy="{ theme: 'tooltip' }"
|
||||||
:title="$t('delete')"
|
:title="$t('delete')"
|
||||||
icon="delete"
|
icon="delete"
|
||||||
|
color="red"
|
||||||
@click.native="deleteParam(index)"
|
@click.native="deleteParam(index)"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div
|
||||||
|
v-if="params$.length === 0"
|
||||||
|
class="flex flex-col text-secondaryLight p-4 items-center justify-center"
|
||||||
|
>
|
||||||
|
<i class="opacity-75 pb-2 material-icons">post_add</i>
|
||||||
|
<span class="text-center pb-4">
|
||||||
|
{{ $t("empty.parameters") }}
|
||||||
|
</span>
|
||||||
|
<ButtonSecondary
|
||||||
|
:label="$t('add.new')"
|
||||||
|
outline
|
||||||
|
@click.native="addParam"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</AppSection>
|
</AppSection>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -132,6 +186,7 @@ import {
|
|||||||
deleteRESTParam,
|
deleteRESTParam,
|
||||||
deleteAllRESTParams,
|
deleteAllRESTParams,
|
||||||
} from "~/newstore/RESTSession"
|
} from "~/newstore/RESTSession"
|
||||||
|
import { getSettingSubject } from "~/newstore/settings"
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
data() {
|
data() {
|
||||||
@@ -142,20 +197,24 @@ export default {
|
|||||||
subscriptions() {
|
subscriptions() {
|
||||||
return {
|
return {
|
||||||
params$: restParams$,
|
params$: restParams$,
|
||||||
|
EXPERIMENTAL_URL_BAR_ENABLED: getSettingSubject(
|
||||||
|
"EXPERIMENTAL_URL_BAR_ENABLED"
|
||||||
|
),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// watch: {
|
watch: {
|
||||||
// params$: {
|
params$: {
|
||||||
// handler(newValue) {
|
handler(newValue) {
|
||||||
// if (
|
if (
|
||||||
// newValue[newValue.length - 1]?.key !== "" ||
|
(newValue[newValue.length - 1]?.key !== "" ||
|
||||||
// newValue[newValue.length - 1]?.value !== ""
|
newValue[newValue.length - 1]?.value !== "") &&
|
||||||
// )
|
newValue.length
|
||||||
// this.addParam()
|
)
|
||||||
// },
|
this.addParam()
|
||||||
// deep: true,
|
},
|
||||||
// },
|
deep: true,
|
||||||
// },
|
},
|
||||||
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
if (!this.params$?.length) {
|
if (!this.params$?.length) {
|
||||||
this.addParam()
|
this.addParam()
|
||||||
|
|||||||
53
components/http/PreRequestScript.vue
Normal file
53
components/http/PreRequestScript.vue
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
<template>
|
||||||
|
<AppSection label="preRequest">
|
||||||
|
<div
|
||||||
|
class="
|
||||||
|
bg-primary
|
||||||
|
border-b border-dividerLight
|
||||||
|
flex flex-1
|
||||||
|
pl-4
|
||||||
|
top-24
|
||||||
|
z-10
|
||||||
|
sticky
|
||||||
|
items-center
|
||||||
|
justify-between
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<label class="font-semibold">
|
||||||
|
{{ $t("javascript_code") }}
|
||||||
|
</label>
|
||||||
|
<ButtonSecondary
|
||||||
|
v-tippy="{ theme: 'tooltip' }"
|
||||||
|
to="https://github.com/hoppscotch/hoppscotch/wiki/Pre-Request-Scripts"
|
||||||
|
blank
|
||||||
|
:title="$t('wiki')"
|
||||||
|
icon="help_outline"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<SmartJsEditor
|
||||||
|
v-model="preRequestScript"
|
||||||
|
:options="{
|
||||||
|
maxLines: Infinity,
|
||||||
|
minLines: 16,
|
||||||
|
fontSize: '12px',
|
||||||
|
autoScrollEditorIntoView: true,
|
||||||
|
showPrintMargin: false,
|
||||||
|
useWorker: false,
|
||||||
|
}"
|
||||||
|
complete-mode="pre"
|
||||||
|
/>
|
||||||
|
</AppSection>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { defineComponent } from "@nuxtjs/composition-api"
|
||||||
|
import { usePreRequestScript } from "~/newstore/RESTSession"
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
setup() {
|
||||||
|
return {
|
||||||
|
preRequestScript: usePreRequestScript(),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
})
|
||||||
|
</script>
|
||||||
@@ -2,23 +2,23 @@
|
|||||||
<div>
|
<div>
|
||||||
<div
|
<div
|
||||||
class="
|
class="
|
||||||
sticky
|
|
||||||
top-110px
|
|
||||||
z-10
|
|
||||||
bg-primary
|
bg-primary
|
||||||
|
border-b border-dividerLight
|
||||||
flex flex-1
|
flex flex-1
|
||||||
|
pl-4
|
||||||
|
top-24
|
||||||
|
z-10
|
||||||
|
sticky
|
||||||
items-center
|
items-center
|
||||||
justify-between
|
justify-between
|
||||||
pl-4
|
|
||||||
border-b border-dividerLight
|
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
<label for="rawBody" class="font-semibold text-xs">
|
<label for="rawBody" class="font-semibold">
|
||||||
{{ $t("raw_request_body") }}
|
{{ $t("raw_request_body") }}
|
||||||
</label>
|
</label>
|
||||||
<div>
|
<div class="flex">
|
||||||
<ButtonSecondary
|
<ButtonSecondary
|
||||||
v-if="rawInput && contentType.endsWith('json')"
|
v-if="contentType.endsWith('json')"
|
||||||
ref="prettifyRequest"
|
ref="prettifyRequest"
|
||||||
v-tippy="{ theme: 'tooltip' }"
|
v-tippy="{ theme: 'tooltip' }"
|
||||||
:title="$t('prettify_body')"
|
:title="$t('prettify_body')"
|
||||||
@@ -28,7 +28,7 @@
|
|||||||
<label for="payload">
|
<label for="payload">
|
||||||
<ButtonSecondary
|
<ButtonSecondary
|
||||||
v-tippy="{ theme: 'tooltip' }"
|
v-tippy="{ theme: 'tooltip' }"
|
||||||
:title="$t('import_json')"
|
:title="$t('import.json')"
|
||||||
icon="post_add"
|
icon="post_add"
|
||||||
@click.native="$refs.payload.click()"
|
@click.native="$refs.payload.click()"
|
||||||
/>
|
/>
|
||||||
@@ -53,9 +53,9 @@
|
|||||||
v-model="rawParamsBody"
|
v-model="rawParamsBody"
|
||||||
:lang="rawInputEditorLang"
|
:lang="rawInputEditorLang"
|
||||||
:options="{
|
:options="{
|
||||||
maxLines: '16',
|
maxLines: 16,
|
||||||
minLines: '8',
|
minLines: 8,
|
||||||
fontSize: '14px',
|
fontSize: '12px',
|
||||||
autoScrollEditorIntoView: true,
|
autoScrollEditorIntoView: true,
|
||||||
showPrintMargin: false,
|
showPrintMargin: false,
|
||||||
useWorker: false,
|
useWorker: false,
|
||||||
@@ -66,43 +66,39 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import { defineComponent } from "@nuxtjs/composition-api"
|
||||||
import { getEditorLangForMimeType } from "~/helpers/editorutils"
|
import { getEditorLangForMimeType } from "~/helpers/editorutils"
|
||||||
|
import { pluckRef } from "~/helpers/utils/composables"
|
||||||
|
import { useRESTRequestBody } from "~/newstore/RESTSession"
|
||||||
|
|
||||||
export default {
|
export default defineComponent({
|
||||||
props: {
|
props: {
|
||||||
rawParams: { type: String, default: null },
|
contentType: {
|
||||||
contentType: { type: String, default: null },
|
type: String,
|
||||||
rawInput: { type: Boolean, default: false },
|
required: true,
|
||||||
},
|
},
|
||||||
data() {
|
},
|
||||||
|
setup() {
|
||||||
return {
|
return {
|
||||||
|
rawParamsBody: pluckRef(useRESTRequestBody(), "body"),
|
||||||
prettifyIcon: "photo_filter",
|
prettifyIcon: "photo_filter",
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
rawParamsBody: {
|
|
||||||
get() {
|
|
||||||
return this.rawParams
|
|
||||||
},
|
|
||||||
set(value) {
|
|
||||||
this.$emit("update-raw-body", value)
|
|
||||||
},
|
|
||||||
},
|
|
||||||
rawInputEditorLang() {
|
rawInputEditorLang() {
|
||||||
return getEditorLangForMimeType(this.contentType)
|
return getEditorLangForMimeType(this.contentType)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
clearContent(bodyParams, $event) {
|
clearContent() {
|
||||||
this.$emit("clear-content", bodyParams, $event)
|
this.rawParamsBody = ""
|
||||||
},
|
},
|
||||||
uploadPayload() {
|
uploadPayload() {
|
||||||
this.$emit("update-raw-input", true)
|
|
||||||
const file = this.$refs.payload.files[0]
|
const file = this.$refs.payload.files[0]
|
||||||
if (file !== undefined && file !== null) {
|
if (file !== undefined && file !== null) {
|
||||||
const reader = new FileReader()
|
const reader = new FileReader()
|
||||||
reader.onload = ({ target }) => {
|
reader.onload = ({ target }) => {
|
||||||
this.$emit("update-raw-body", target.result)
|
this.rawParamsBody = target.result
|
||||||
}
|
}
|
||||||
reader.readAsText(file)
|
reader.readAsText(file)
|
||||||
this.$toast.info(this.$t("file_imported"), {
|
this.$toast.info(this.$t("file_imported"), {
|
||||||
@@ -128,5 +124,5 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="sticky top-0 z-10 bg-primary flex p-4">
|
<div class="bg-primary flex p-4 top-0 z-10 sticky">
|
||||||
<div class="relative inline-flex">
|
<div class="relative inline-flex">
|
||||||
<span class="select-wrapper">
|
<span class="select-wrapper">
|
||||||
<tippy
|
<tippy
|
||||||
ref="options"
|
ref="methodOptions"
|
||||||
interactive
|
interactive
|
||||||
tabindex="-1"
|
tabindex="-1"
|
||||||
trigger="click"
|
trigger="click"
|
||||||
@@ -14,23 +14,23 @@
|
|||||||
<input
|
<input
|
||||||
id="method"
|
id="method"
|
||||||
class="
|
class="
|
||||||
flex
|
|
||||||
rounded-l-lg
|
|
||||||
bg-primaryLight
|
bg-primaryLight
|
||||||
font-mono
|
|
||||||
w-32
|
|
||||||
px-4
|
|
||||||
py-2
|
|
||||||
truncate
|
|
||||||
text-secondaryDark
|
|
||||||
font-semibold
|
|
||||||
border border-divider
|
border border-divider
|
||||||
transition
|
rounded-l
|
||||||
focus:outline-none focus:border-accent
|
|
||||||
cursor-pointer
|
cursor-pointer
|
||||||
|
flex
|
||||||
|
font-semibold font-mono
|
||||||
|
h-8
|
||||||
|
text-secondaryDark
|
||||||
|
py-1
|
||||||
|
px-4
|
||||||
|
transition
|
||||||
|
w-28
|
||||||
|
truncate
|
||||||
|
focus:outline-none focus:border-accent
|
||||||
"
|
"
|
||||||
:value="newMethod$"
|
:value="newMethod"
|
||||||
autofocus
|
readonly
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
<SmartItem
|
<SmartItem
|
||||||
@@ -38,79 +38,64 @@
|
|||||||
:key="`method-${index}`"
|
:key="`method-${index}`"
|
||||||
:label="method"
|
:label="method"
|
||||||
class="font-mono"
|
class="font-mono"
|
||||||
@click.native="
|
@click.native="onSelectMethod(method)"
|
||||||
updateMethod(method)
|
|
||||||
$refs.options.tippy().hide()
|
|
||||||
"
|
|
||||||
/>
|
/>
|
||||||
</tippy>
|
</tippy>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex-1 inline-flex">
|
<div class="flex-1 inline-flex">
|
||||||
<input
|
<SmartEnvInput
|
||||||
id="url"
|
v-if="EXPERIMENTAL_URL_BAR_ENABLED"
|
||||||
v-model="newEndpoint$"
|
v-model="newEndpoint"
|
||||||
class="
|
:placeholder="$t('url')"
|
||||||
w-full
|
styles="
|
||||||
font-mono font-semibold
|
|
||||||
truncate
|
|
||||||
text-secondaryDark
|
|
||||||
px-4
|
|
||||||
py-2
|
|
||||||
border border-divider
|
|
||||||
bg-primaryLight
|
bg-primaryLight
|
||||||
|
border border-divider
|
||||||
|
flex
|
||||||
|
font-semibold font-mono
|
||||||
|
flex-1
|
||||||
|
text-secondaryDark
|
||||||
|
py-1
|
||||||
|
px-4
|
||||||
transition
|
transition
|
||||||
|
truncate
|
||||||
|
focus:outline-none focus:border-accent
|
||||||
|
"
|
||||||
|
@enter="newSendRequest()"
|
||||||
|
/>
|
||||||
|
<input
|
||||||
|
v-else
|
||||||
|
id="url"
|
||||||
|
v-model="newEndpoint"
|
||||||
|
class="
|
||||||
|
bg-primaryLight
|
||||||
|
border border-divider
|
||||||
|
flex
|
||||||
|
font-semibold font-mono
|
||||||
|
flex-1
|
||||||
|
text-secondaryDark
|
||||||
|
py-1
|
||||||
|
px-4
|
||||||
|
transition
|
||||||
|
truncate
|
||||||
focus:outline-none focus:border-accent
|
focus:outline-none focus:border-accent
|
||||||
"
|
"
|
||||||
name="url"
|
name="url"
|
||||||
type="text"
|
type="text"
|
||||||
spellcheck="false"
|
spellcheck="false"
|
||||||
:placeholder="$t('url')"
|
:placeholder="$t('url')"
|
||||||
|
autofocus
|
||||||
@keyup.enter="newSendRequest()"
|
@keyup.enter="newSendRequest()"
|
||||||
/>
|
/>
|
||||||
<!-- <SmartUrlField v-else v-model="uri" /> -->
|
|
||||||
</div>
|
</div>
|
||||||
<div class="flex">
|
<div class="flex">
|
||||||
<span
|
<ButtonPrimary
|
||||||
id="send"
|
id="send"
|
||||||
class="
|
class="rounded-none min-w-20"
|
||||||
px-4
|
:label="!loading ? $t('send') : $t('cancel')"
|
||||||
py-2
|
@click.native="!loading ? newSendRequest() : cancelRequest()"
|
||||||
border border-accent
|
/>
|
||||||
font-mono
|
<span class="inline-flex">
|
||||||
flex
|
|
||||||
items-center
|
|
||||||
truncate
|
|
||||||
font-semibold
|
|
||||||
bg-accent
|
|
||||||
text-white
|
|
||||||
cursor-pointer
|
|
||||||
dark:text-accentDark
|
|
||||||
"
|
|
||||||
@click="newSendRequest"
|
|
||||||
>
|
|
||||||
{{ $t("send") }}
|
|
||||||
</span>
|
|
||||||
<!-- <span
|
|
||||||
v-else
|
|
||||||
id="cancel"
|
|
||||||
class="
|
|
||||||
px-4
|
|
||||||
py-2
|
|
||||||
border border-accent
|
|
||||||
font-mono
|
|
||||||
flex
|
|
||||||
items-center
|
|
||||||
truncate
|
|
||||||
font-semibold
|
|
||||||
bg-accent
|
|
||||||
text-white
|
|
||||||
cursor-pointer
|
|
||||||
"
|
|
||||||
@click="cancelRequest"
|
|
||||||
>
|
|
||||||
{{ $t("cancel") }}
|
|
||||||
</span> -->
|
|
||||||
<tippy
|
<tippy
|
||||||
ref="sendOptions"
|
ref="sendOptions"
|
||||||
interactive
|
interactive
|
||||||
@@ -120,40 +105,22 @@
|
|||||||
arrow
|
arrow
|
||||||
>
|
>
|
||||||
<template #trigger>
|
<template #trigger>
|
||||||
<span
|
<ButtonPrimary class="rounded-l-none" icon="keyboard_arrow_down" />
|
||||||
class="
|
|
||||||
px-1
|
|
||||||
py-2
|
|
||||||
border border-accent
|
|
||||||
font-mono
|
|
||||||
flex
|
|
||||||
items-center
|
|
||||||
justify-center
|
|
||||||
truncate
|
|
||||||
font-semibold
|
|
||||||
bg-accent
|
|
||||||
text-white
|
|
||||||
rounded-r-lg
|
|
||||||
dark:text-accentDark
|
|
||||||
"
|
|
||||||
>
|
|
||||||
<i class="material-icons">keyboard_arrow_down</i>
|
|
||||||
</span>
|
|
||||||
</template>
|
</template>
|
||||||
<SmartItem
|
<SmartItem
|
||||||
:label="$t('import_curl')"
|
:label="$t('import.curl')"
|
||||||
icon="import_export"
|
icon="import_export"
|
||||||
@click.native="
|
@click.native="
|
||||||
showCurlImportModal = !showCurlImportModal
|
showCurlImportModal = !showCurlImportModal
|
||||||
$refs.sendOptions.tippy().hide()
|
sendOptions.tippy().hide()
|
||||||
"
|
"
|
||||||
/>
|
/>
|
||||||
<SmartItem
|
<SmartItem
|
||||||
:label="$t('show_code')"
|
:label="$t('show.code')"
|
||||||
icon="code"
|
icon="code"
|
||||||
@click.native="
|
@click.native="
|
||||||
showCodegenModal = !showCodegenModal
|
showCodegenModal = !showCodegenModal
|
||||||
$refs.sendOptions.tippy().hide()
|
sendOptions.tippy().hide()
|
||||||
"
|
"
|
||||||
/>
|
/>
|
||||||
<SmartItem
|
<SmartItem
|
||||||
@@ -161,30 +128,20 @@
|
|||||||
:label="$t('clear_all')"
|
:label="$t('clear_all')"
|
||||||
icon="clear_all"
|
icon="clear_all"
|
||||||
@click.native="
|
@click.native="
|
||||||
clearContent('', $event)
|
clearContent()
|
||||||
$refs.sendOptions.tippy().hide()
|
sendOptions.tippy().hide()
|
||||||
"
|
"
|
||||||
/>
|
/>
|
||||||
</tippy>
|
</tippy>
|
||||||
<span
|
|
||||||
class="
|
|
||||||
ml-4
|
|
||||||
px-4
|
|
||||||
py-2
|
|
||||||
border border-divider
|
|
||||||
font-mono
|
|
||||||
flex
|
|
||||||
items-center
|
|
||||||
justify-center
|
|
||||||
truncate
|
|
||||||
font-semibold
|
|
||||||
rounded-l-lg
|
|
||||||
cursor-pointer
|
|
||||||
"
|
|
||||||
@click="newSendRequest"
|
|
||||||
>
|
|
||||||
Save
|
|
||||||
</span>
|
</span>
|
||||||
|
<ButtonSecondary
|
||||||
|
class="rounded-r-none h-8 ml-2"
|
||||||
|
:label="$t('save')"
|
||||||
|
:shortcut="[getSpecialKey(), 'S']"
|
||||||
|
outline
|
||||||
|
@click.native="showSaveRequestModal = true"
|
||||||
|
/>
|
||||||
|
<span class="inline-flex">
|
||||||
<tippy
|
<tippy
|
||||||
ref="saveOptions"
|
ref="saveOptions"
|
||||||
interactive
|
interactive
|
||||||
@@ -194,72 +151,76 @@
|
|||||||
arrow
|
arrow
|
||||||
>
|
>
|
||||||
<template #trigger>
|
<template #trigger>
|
||||||
<span
|
<ButtonSecondary
|
||||||
class="
|
icon="keyboard_arrow_down"
|
||||||
px-1
|
outline
|
||||||
py-2
|
class="rounded-l-none h-8"
|
||||||
border border-divider
|
/>
|
||||||
font-mono
|
|
||||||
flex
|
|
||||||
items-center
|
|
||||||
justify-center
|
|
||||||
truncate
|
|
||||||
font-semibold
|
|
||||||
rounded-r-lg
|
|
||||||
"
|
|
||||||
>
|
|
||||||
<i class="material-icons">keyboard_arrow_down</i>
|
|
||||||
</span>
|
|
||||||
</template>
|
</template>
|
||||||
<SmartItem :description="$t('token_req_name')" />
|
|
||||||
<input
|
<input
|
||||||
id="request-name"
|
id="request-name"
|
||||||
v-model="name"
|
v-model="requestName"
|
||||||
|
:placeholder="$t('request_name')"
|
||||||
name="request-name"
|
name="request-name"
|
||||||
type="text"
|
type="text"
|
||||||
class="input text-sm"
|
class="mb-2 input"
|
||||||
/>
|
/>
|
||||||
<SmartItem
|
<SmartItem
|
||||||
ref="copyRequest"
|
ref="copyRequest"
|
||||||
:label="$t('copy_request_link')"
|
:label="$t('request.copy_link')"
|
||||||
:icon="navigatorShare ? 'share' : 'content_copy'"
|
:icon="hasNavigatorShare ? 'share' : 'content_copy'"
|
||||||
@click.native="
|
@click.native="
|
||||||
copyRequest()
|
copyRequest()
|
||||||
$refs.saveOptions.tippy().hide()
|
saveOptions.tippy().hide()
|
||||||
"
|
"
|
||||||
/>
|
/>
|
||||||
<SmartItem
|
<SmartItem
|
||||||
ref="saveRequest"
|
ref="saveRequest"
|
||||||
:label="$t('save_to_collections')"
|
:label="$t('request.save_as')"
|
||||||
icon="create_new_folder"
|
icon="create_new_folder"
|
||||||
@click.native="
|
@click.native="
|
||||||
saveRequest()
|
showSaveRequestModal = true
|
||||||
$refs.saveOptions.tippy().hide()
|
saveOptions.tippy().hide()
|
||||||
"
|
"
|
||||||
/>
|
/>
|
||||||
</tippy>
|
</tippy>
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
<HttpImportCurl
|
||||||
|
:show="showCurlImportModal"
|
||||||
|
@hide-modal="showCurlImportModal = false"
|
||||||
|
/>
|
||||||
|
<HttpCodegenModal
|
||||||
|
:show="showCodegenModal"
|
||||||
|
@hide-modal="showCodegenModal = false"
|
||||||
|
/>
|
||||||
|
<CollectionsSaveRequest
|
||||||
|
mode="rest"
|
||||||
|
:show="showSaveRequestModal"
|
||||||
|
@hide-modal="showSaveRequestModal = false"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script lang="ts">
|
||||||
|
import { defineComponent, ref, useContext } from "@nuxtjs/composition-api"
|
||||||
import {
|
import {
|
||||||
updateRESTResponse,
|
updateRESTResponse,
|
||||||
restRequest$,
|
|
||||||
restEndpoint$,
|
restEndpoint$,
|
||||||
setRESTEndpoint,
|
setRESTEndpoint,
|
||||||
restMethod$,
|
restMethod$,
|
||||||
updateRESTMethod,
|
updateRESTMethod,
|
||||||
|
resetRESTRequest,
|
||||||
|
useRESTRequestName,
|
||||||
} from "~/newstore/RESTSession"
|
} from "~/newstore/RESTSession"
|
||||||
import { createRESTNetworkRequestStream } from "~/helpers/network"
|
import { getPlatformSpecialKey } from "~/helpers/platformutils"
|
||||||
import { currentEnvironment$ } from "~/newstore/environments"
|
import { runRESTRequest$ } from "~/helpers/RequestRunner"
|
||||||
import { getEffectiveRESTRequestStream } from "~/helpers/utils/EffectiveURL"
|
import { useStreamSubscriber, useStream } from "~/helpers/utils/composables"
|
||||||
|
import { defineActionHandler } from "~/helpers/actions"
|
||||||
|
import { copyToClipboard } from "~/helpers/utils/clipboard"
|
||||||
|
import { useSetting } from "~/newstore/settings"
|
||||||
|
|
||||||
export default {
|
const methods = [
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
newMethod$: "",
|
|
||||||
methods: [
|
|
||||||
"GET",
|
"GET",
|
||||||
"HEAD",
|
"HEAD",
|
||||||
"POST",
|
"POST",
|
||||||
@@ -270,47 +231,162 @@ export default {
|
|||||||
"TRACE",
|
"TRACE",
|
||||||
"PATCH",
|
"PATCH",
|
||||||
"CUSTOM",
|
"CUSTOM",
|
||||||
],
|
]
|
||||||
name: "",
|
|
||||||
newEndpoint$: "",
|
export default defineComponent({
|
||||||
showCurlImportModal: false,
|
setup() {
|
||||||
showCodegenModal: false,
|
const {
|
||||||
navigatorShare: navigator.share,
|
$toast,
|
||||||
effectiveStream$: null,
|
app: { i18n },
|
||||||
}
|
} = useContext()
|
||||||
},
|
const t = i18n.t.bind(i18n)
|
||||||
subscriptions() {
|
const { subscribeToStream } = useStreamSubscriber()
|
||||||
return {
|
|
||||||
newMethod$: restMethod$,
|
const newEndpoint = useStream(restEndpoint$, "", setRESTEndpoint)
|
||||||
newEndpoint$: restEndpoint$,
|
const newMethod = useStream(restMethod$, "", updateRESTMethod)
|
||||||
effectiveStream$: getEffectiveRESTRequestStream(
|
|
||||||
restRequest$,
|
const loading = ref(false)
|
||||||
currentEnvironment$
|
|
||||||
),
|
const showCurlImportModal = ref(false)
|
||||||
}
|
const showCodegenModal = ref(false)
|
||||||
},
|
const showSaveRequestModal = ref(false)
|
||||||
watch: {
|
|
||||||
newEndpoint$(newVal) {
|
const hasNavigatorShare = !!navigator.share
|
||||||
setRESTEndpoint(newVal)
|
|
||||||
},
|
// Template refs
|
||||||
},
|
//
|
||||||
mounted() {},
|
const methodOptions = ref<any | null>(null)
|
||||||
methods: {
|
const saveOptions = ref<any | null>(null)
|
||||||
updateMethod(method) {
|
const sendOptions = ref<any | null>(null)
|
||||||
updateRESTMethod(method)
|
|
||||||
},
|
const newSendRequest = () => {
|
||||||
newSendRequest() {
|
loading.value = true
|
||||||
this.$subscribeTo(
|
|
||||||
createRESTNetworkRequestStream(
|
subscribeToStream(
|
||||||
this.effectiveStream$,
|
runRESTRequest$(),
|
||||||
currentEnvironment$
|
|
||||||
),
|
|
||||||
(responseState) => {
|
(responseState) => {
|
||||||
console.log(responseState)
|
console.log(responseState)
|
||||||
|
if (loading.value) {
|
||||||
|
// Check exists because, loading can be set to false
|
||||||
|
// when cancelled
|
||||||
updateRESTResponse(responseState)
|
updateRESTResponse(responseState)
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
() => {
|
||||||
|
loading.value = false
|
||||||
|
},
|
||||||
|
() => {
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const cancelRequest = () => {
|
||||||
|
loading.value = false
|
||||||
|
updateRESTResponse(null)
|
||||||
|
}
|
||||||
|
|
||||||
|
const updateMethod = (method: string) => {
|
||||||
|
updateRESTMethod(method)
|
||||||
|
}
|
||||||
|
|
||||||
|
const onSelectMethod = (method: string) => {
|
||||||
|
updateMethod(method)
|
||||||
|
// Vue-tippy has no typescript support yet
|
||||||
|
methodOptions.value.tippy().hide()
|
||||||
|
}
|
||||||
|
|
||||||
|
const clearContent = () => {
|
||||||
|
resetRESTRequest()
|
||||||
|
}
|
||||||
|
|
||||||
|
const copyRequest = () => {
|
||||||
|
if (navigator.share) {
|
||||||
|
const time = new Date().toLocaleTimeString()
|
||||||
|
const date = new Date().toLocaleDateString()
|
||||||
|
navigator
|
||||||
|
.share({
|
||||||
|
title: "Hoppscotch",
|
||||||
|
text: `Hoppscotch • Open source API development ecosystem at ${time} on ${date}`,
|
||||||
|
url: window.location.href,
|
||||||
|
})
|
||||||
|
.then(() => {})
|
||||||
|
.catch(() => {})
|
||||||
|
} else {
|
||||||
|
copyToClipboard(window.location.href)
|
||||||
|
$toast.info(t("copied_to_clipboard").toString(), {
|
||||||
|
icon: "done",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const cycleUpMethod = () => {
|
||||||
|
const currentIndex = methods.indexOf(newMethod.value)
|
||||||
|
if (currentIndex === -1) {
|
||||||
|
// Most probs we are in CUSTOM mode
|
||||||
|
// Cycle up from CUSTOM is PATCH
|
||||||
|
updateMethod("PATCH")
|
||||||
|
} else if (currentIndex === 0) {
|
||||||
|
updateMethod("CUSTOM")
|
||||||
|
} else {
|
||||||
|
updateMethod(methods[currentIndex - 1])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const cycleDownMethod = () => {
|
||||||
|
const currentIndex = methods.indexOf(newMethod.value)
|
||||||
|
if (currentIndex === -1) {
|
||||||
|
// Most probs we are in CUSTOM mode
|
||||||
|
// Cycle down from CUSTOM is GET
|
||||||
|
updateMethod("GET")
|
||||||
|
} else if (currentIndex === methods.length - 1) {
|
||||||
|
updateMethod("GET")
|
||||||
|
} else {
|
||||||
|
updateMethod(methods[currentIndex + 1])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
defineActionHandler("request.send-cancel", () => {
|
||||||
|
if (!loading.value) newSendRequest()
|
||||||
|
else cancelRequest()
|
||||||
|
})
|
||||||
|
defineActionHandler("request.reset", clearContent)
|
||||||
|
defineActionHandler("request.copy-link", copyRequest)
|
||||||
|
defineActionHandler("request.method.next", cycleDownMethod)
|
||||||
|
defineActionHandler("request.method.prev", cycleUpMethod)
|
||||||
|
defineActionHandler(
|
||||||
|
"request.save",
|
||||||
|
() => (showSaveRequestModal.value = true)
|
||||||
|
)
|
||||||
|
defineActionHandler("request.method.get", () => updateMethod("GET"))
|
||||||
|
defineActionHandler("request.method.post", () => updateMethod("POST"))
|
||||||
|
defineActionHandler("request.method.put", () => updateMethod("PUT"))
|
||||||
|
defineActionHandler("request.method.delete", () => updateMethod("DELETE"))
|
||||||
|
defineActionHandler("request.method.head", () => updateMethod("HEAD"))
|
||||||
|
|
||||||
|
return {
|
||||||
|
newEndpoint,
|
||||||
|
newMethod,
|
||||||
|
methods,
|
||||||
|
loading,
|
||||||
|
newSendRequest,
|
||||||
|
requestName: useRESTRequestName(),
|
||||||
|
getSpecialKey: getPlatformSpecialKey,
|
||||||
|
showCurlImportModal,
|
||||||
|
showCodegenModal,
|
||||||
|
showSaveRequestModal,
|
||||||
|
hasNavigatorShare,
|
||||||
|
updateMethod,
|
||||||
|
clearContent,
|
||||||
|
copyRequest,
|
||||||
|
onSelectMethod,
|
||||||
|
|
||||||
|
EXPERIMENTAL_URL_BAR_ENABLED: useSetting("EXPERIMENTAL_URL_BAR_ENABLED"),
|
||||||
|
|
||||||
|
// Template refs
|
||||||
|
methodOptions,
|
||||||
|
sendOptions,
|
||||||
|
saveOptions,
|
||||||
|
}
|
||||||
},
|
},
|
||||||
},
|
})
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,20 +1,46 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="flex sticky top-0 z-10 bg-primary items-center p-4">
|
<div class="bg-primary flex p-4 top-0 z-10 sticky items-center">
|
||||||
<div
|
<div
|
||||||
v-if="response == null"
|
v-if="response == null"
|
||||||
class="
|
class="
|
||||||
flex flex-1
|
flex flex-col flex-1
|
||||||
items-center
|
|
||||||
text-secondaryLight
|
text-secondaryLight
|
||||||
flex-col
|
items-center
|
||||||
p-4
|
|
||||||
justify-center
|
justify-center
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
<i class="material-icons opacity-50 pb-2">send</i>
|
<div class="flex space-x-2 pb-8">
|
||||||
<span class="text-xs text-center">
|
<div class="flex flex-col space-y-4 items-end">
|
||||||
{{ $t("waiting_send_req") }}
|
<span class="flex flex-1 items-center">
|
||||||
|
{{ $t("shortcut.send_request") }}
|
||||||
</span>
|
</span>
|
||||||
|
<span class="flex flex-1 items-center">
|
||||||
|
{{ $t("shortcut.reset_request") }}
|
||||||
|
</span>
|
||||||
|
<span class="flex flex-1 items-center">
|
||||||
|
{{ $t("shortcut.show_all") }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div class="flex flex-col space-y-4">
|
||||||
|
<div class="flex">
|
||||||
|
<span class="shortcut-key">{{ getSpecialKey() }}</span>
|
||||||
|
<span class="shortcut-key">G</span>
|
||||||
|
</div>
|
||||||
|
<div class="flex">
|
||||||
|
<span class="shortcut-key">{{ getSpecialKey() }}</span>
|
||||||
|
<span class="shortcut-key">I</span>
|
||||||
|
</div>
|
||||||
|
<div class="flex">
|
||||||
|
<span class="shortcut-key">?</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<ButtonSecondary
|
||||||
|
:label="$t('documentation')"
|
||||||
|
to="https://docs.hoppscotch.io"
|
||||||
|
blank
|
||||||
|
outline
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div v-else>
|
<div v-else>
|
||||||
<i v-if="response.type === 'loading'" class="animate-spin material-icons">
|
<i v-if="response.type === 'loading'" class="animate-spin material-icons">
|
||||||
@@ -29,11 +55,11 @@
|
|||||||
<span class="text-secondaryDark"> Status: </span>
|
<span class="text-secondaryDark"> Status: </span>
|
||||||
{{ response.statusCode || $t("waiting_send_req") }}
|
{{ response.statusCode || $t("waiting_send_req") }}
|
||||||
</span>
|
</span>
|
||||||
<span v-if="response.meta.responseDuration" class="text-xs">
|
<span v-if="response.meta && response.meta.responseDuration">
|
||||||
<span class="text-secondaryDark"> Time: </span>
|
<span class="text-secondaryDark"> Time: </span>
|
||||||
{{ `${response.meta.responseDuration} ms` }}
|
{{ `${response.meta.responseDuration} ms` }}
|
||||||
</span>
|
</span>
|
||||||
<span v-if="response.meta.responseSize" class="text-xs">
|
<span v-if="response.meta && response.meta.responseSize">
|
||||||
<span class="text-secondaryDark"> Size: </span>
|
<span class="text-secondaryDark"> Size: </span>
|
||||||
{{ `${response.meta.responseSize} B` }}
|
{{ `${response.meta.responseSize} B` }}
|
||||||
</span>
|
</span>
|
||||||
@@ -44,6 +70,7 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import findStatusGroup from "~/helpers/findStatusGroup"
|
import findStatusGroup from "~/helpers/findStatusGroup"
|
||||||
|
import { getPlatformSpecialKey } from "~/helpers/platformutils"
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
props: {
|
props: {
|
||||||
@@ -57,5 +84,19 @@ export default {
|
|||||||
return findStatusGroup(this.response.statusCode)
|
return findStatusGroup(this.response.statusCode)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
methods: {
|
||||||
|
getSpecialKey: getPlatformSpecialKey,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.shortcut-key {
|
||||||
|
@apply bg-dividerLight;
|
||||||
|
@apply rounded;
|
||||||
|
@apply ml-2;
|
||||||
|
@apply py-1;
|
||||||
|
@apply px-2;
|
||||||
|
@apply inline-flex;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
63
components/http/TestResult.vue
Normal file
63
components/http/TestResult.vue
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
<template>
|
||||||
|
<div class="divide-y divide-dividerLight">
|
||||||
|
<div v-if="results.tests">
|
||||||
|
<HttpTestResult
|
||||||
|
v-for="(result, index) in results.tests"
|
||||||
|
:key="`result-${index}`"
|
||||||
|
:results="result"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<span
|
||||||
|
v-if="results.description"
|
||||||
|
class="
|
||||||
|
border-b border-dividerLight
|
||||||
|
flex
|
||||||
|
font-semibold
|
||||||
|
text-secondaryDark
|
||||||
|
py-2
|
||||||
|
px-4
|
||||||
|
items-center
|
||||||
|
"
|
||||||
|
>
|
||||||
|
{{ results.description }}
|
||||||
|
</span>
|
||||||
|
<div v-if="results.expectResults" class="divide-y divide-dividerLight">
|
||||||
|
<div
|
||||||
|
v-for="(result, index) in results.expectResults"
|
||||||
|
:key="`result-${index}`"
|
||||||
|
class="flex py-2 px-4 items-center"
|
||||||
|
>
|
||||||
|
<i
|
||||||
|
class="mr-4 material-icons"
|
||||||
|
:class="result.status === 'pass' ? 'text-green-500' : 'text-red-500'"
|
||||||
|
>
|
||||||
|
{{ result.status === "pass" ? "check" : "close" }}
|
||||||
|
</i>
|
||||||
|
<span v-if="result.message" class="font-semibold text-secondaryDark">
|
||||||
|
{{ result.message }}
|
||||||
|
</span>
|
||||||
|
<span class="text-secondaryLight">
|
||||||
|
{{
|
||||||
|
` \xA0 — \xA0test ${
|
||||||
|
result.status === "pass" ? $t("passed") : $t("failed")
|
||||||
|
}`
|
||||||
|
}}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { defineComponent, PropType } from "@nuxtjs/composition-api"
|
||||||
|
import { HoppTestResult } from "~/helpers/types/HoppTestResult"
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
props: {
|
||||||
|
results: {
|
||||||
|
type: Object as PropType<HoppTestResult>,
|
||||||
|
default: null,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
</script>
|
||||||
148
components/http/Tests.vue
Normal file
148
components/http/Tests.vue
Normal file
@@ -0,0 +1,148 @@
|
|||||||
|
<template>
|
||||||
|
<SmartTabs styles="sticky top-24 z-20">
|
||||||
|
<SmartTab id="script" :label="$t('test.script')" :selected="true">
|
||||||
|
<div
|
||||||
|
class="
|
||||||
|
bg-primary
|
||||||
|
border-b border-dividerLight
|
||||||
|
flex flex-1
|
||||||
|
pl-4
|
||||||
|
top-32
|
||||||
|
z-10
|
||||||
|
sticky
|
||||||
|
items-center
|
||||||
|
justify-between
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<label class="font-semibold">
|
||||||
|
{{ $t("javascript_code") }}
|
||||||
|
</label>
|
||||||
|
<ButtonSecondary
|
||||||
|
v-tippy="{ theme: 'tooltip' }"
|
||||||
|
to="https://github.com/hoppscotch/hoppscotch/wiki/Post-Request-Tests"
|
||||||
|
blank
|
||||||
|
:title="$t('wiki')"
|
||||||
|
icon="help_outline"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<SmartJsEditor
|
||||||
|
v-model="testScript"
|
||||||
|
:options="{
|
||||||
|
maxLines: Infinity,
|
||||||
|
minLines: 16,
|
||||||
|
fontSize: '12px',
|
||||||
|
autoScrollEditorIntoView: true,
|
||||||
|
showPrintMargin: false,
|
||||||
|
useWorker: false,
|
||||||
|
}"
|
||||||
|
complete-mode="test"
|
||||||
|
/>
|
||||||
|
</SmartTab>
|
||||||
|
<SmartTab
|
||||||
|
id="results"
|
||||||
|
:label="$t('test.results')"
|
||||||
|
:info="totalTests ? totalTests.toString() : ''"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
v-if="
|
||||||
|
testResults &&
|
||||||
|
(testResults.expectResults.length || testResults.tests.length)
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="
|
||||||
|
bg-primary
|
||||||
|
border-b border-dividerLight
|
||||||
|
flex flex-1
|
||||||
|
pl-4
|
||||||
|
top-32
|
||||||
|
z-10
|
||||||
|
sticky
|
||||||
|
items-center
|
||||||
|
justify-between
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<label class="font-semibold"> Test Report </label>
|
||||||
|
<ButtonSecondary
|
||||||
|
v-tippy="{ theme: 'tooltip' }"
|
||||||
|
:title="$t('clear')"
|
||||||
|
icon="clear_all"
|
||||||
|
@click.native="clearContent()"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="flex p-2 items-center">
|
||||||
|
<SmartProgressRing
|
||||||
|
class="text-red-500"
|
||||||
|
:radius="16"
|
||||||
|
:stroke="4"
|
||||||
|
:progress="(failedTests / totalTests) * 100"
|
||||||
|
/>
|
||||||
|
<div class="ml-2">
|
||||||
|
<span v-if="failedTests" class="font-semibold text-red-500">
|
||||||
|
{{ failedTests }} failing,
|
||||||
|
</span>
|
||||||
|
<span v-if="passedTests" class="font-semibold text-green-500">
|
||||||
|
{{ passedTests }} successful,
|
||||||
|
</span>
|
||||||
|
<span class="font-semibold"> out of {{ totalTests }} tests. </span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<HttpTestResult :results="testResults" />
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
v-else
|
||||||
|
class="
|
||||||
|
flex flex-col
|
||||||
|
text-secondaryLight
|
||||||
|
p-4
|
||||||
|
items-center
|
||||||
|
justify-center
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<i class="opacity-75 pb-2 material-icons">bug_report</i>
|
||||||
|
<span class="text-center">
|
||||||
|
{{ $t("empty.tests") }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</SmartTab>
|
||||||
|
</SmartTabs>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { defineComponent } from "@nuxtjs/composition-api"
|
||||||
|
import {
|
||||||
|
useTestScript,
|
||||||
|
restTestResults$,
|
||||||
|
setRESTTestResults,
|
||||||
|
} from "~/newstore/RESTSession"
|
||||||
|
import { useReadonlyStream } from "~/helpers/utils/composables"
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
setup() {
|
||||||
|
return {
|
||||||
|
testScript: useTestScript(),
|
||||||
|
testResults: useReadonlyStream(restTestResults$, null),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
totalTests(): number | undefined {
|
||||||
|
return this.testResults?.expectResults.length
|
||||||
|
},
|
||||||
|
failedTests(): number | undefined {
|
||||||
|
return this.testResults?.expectResults.filter(
|
||||||
|
(result: { status: string }) => result.status === "fail"
|
||||||
|
).length
|
||||||
|
},
|
||||||
|
passedTests(): number | undefined {
|
||||||
|
return this.testResults?.expectResults.filter(
|
||||||
|
(result: { status: string }) => result.status === "pass"
|
||||||
|
).length
|
||||||
|
},
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
clearContent() {
|
||||||
|
setRESTTestResults(null)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
</script>
|
||||||
@@ -49,13 +49,14 @@
|
|||||||
v-tippy="{ theme: 'tooltip' }"
|
v-tippy="{ theme: 'tooltip' }"
|
||||||
:title="$t('delete')"
|
:title="$t('delete')"
|
||||||
icon="delete"
|
icon="delete"
|
||||||
|
color="red"
|
||||||
@click.native="removeOAuthToken(index)"
|
@click.native="removeOAuthToken(index)"
|
||||||
/>
|
/>
|
||||||
</li>
|
</li>
|
||||||
</div>
|
</div>
|
||||||
</ul>
|
</ul>
|
||||||
<p v-if="tokens.length === 0">
|
<p v-if="tokens.length === 0">
|
||||||
{{ $t("empty") }}
|
{{ $t("empty.protocols") }}
|
||||||
</p>
|
</p>
|
||||||
</template>
|
</template>
|
||||||
</SmartModal>
|
</SmartModal>
|
||||||
|
|||||||
@@ -1,22 +1,26 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="flex p-4 bg-primaryLight rounded">
|
<div
|
||||||
<div class="grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-3">
|
class="
|
||||||
|
bg-primaryLight
|
||||||
|
rounded
|
||||||
|
flex
|
||||||
|
grid
|
||||||
|
p-4
|
||||||
|
gap-4
|
||||||
|
grid-cols-1
|
||||||
|
md:grid-cols-2
|
||||||
|
lg:grid-cols-3
|
||||||
|
"
|
||||||
|
>
|
||||||
<div
|
<div
|
||||||
v-for="(cta, index) in ctas"
|
v-for="(cta, index) in ctas"
|
||||||
:key="`cta-${index}`"
|
:key="`cta-${index}`"
|
||||||
class="inline-flex flex-col p-8"
|
class="flex-col p-8 inline-flex"
|
||||||
>
|
>
|
||||||
<i class="text-3xl material-icons text-accent">{{ cta.icon }}</i>
|
<i class="text-accent text-3xl material-icons">{{ cta.icon }}</i>
|
||||||
<div class="flex-grow">
|
<div class="flex-grow">
|
||||||
<h2
|
<h2
|
||||||
class="
|
class="font-semibold mt-4 text-lg text-secondaryDark mb-2 transition"
|
||||||
mt-4
|
|
||||||
mb-2
|
|
||||||
text-lg
|
|
||||||
font-semibold
|
|
||||||
transition
|
|
||||||
text-secondaryDark
|
|
||||||
"
|
|
||||||
>
|
>
|
||||||
{{ cta.title }}
|
{{ cta.title }}
|
||||||
</h2>
|
</h2>
|
||||||
@@ -32,7 +36,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
@@ -42,32 +45,32 @@ export default {
|
|||||||
ctas: [
|
ctas: [
|
||||||
{
|
{
|
||||||
icon: "layers",
|
icon: "layers",
|
||||||
title: "API Documentation",
|
title: "Feature",
|
||||||
description:
|
description:
|
||||||
"Get up and running with Kooli in as little as 10 minutes.",
|
"Get up and running with Kooli in as little as 10 minutes.",
|
||||||
link: {
|
link: {
|
||||||
title: "API reference",
|
title: "Feature",
|
||||||
target: "https://docs.kooli.tech/api",
|
target: "https://docs.hoppscotch.io/api",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: "local_library",
|
icon: "local_library",
|
||||||
title: "Guides",
|
title: "Feature",
|
||||||
description:
|
description:
|
||||||
"Explore and start integrating Kooli's products and tools.",
|
"Explore and start integrating Kooli's products and tools.",
|
||||||
link: {
|
link: {
|
||||||
title: "Guides and resources",
|
title: "Feature",
|
||||||
target: "https://docs.kooli.tech/guides",
|
target: "https://docs.hoppscotch.io/guides",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: "local_library",
|
icon: "local_library",
|
||||||
title: "Guides",
|
title: "Feature",
|
||||||
description:
|
description:
|
||||||
"Explore and start integrating Kooli's products and tools.",
|
"Explore and start integrating Kooli's products and tools.",
|
||||||
link: {
|
link: {
|
||||||
title: "Guides and resources",
|
title: "Feature",
|
||||||
target: "https://docs.kooli.tech/guides",
|
target: "https://docs.hoppscotch.io/guides",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -1,26 +1,25 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="flex flex-col p-4">
|
<div class="flex flex-col p-4">
|
||||||
<div class="flex flex-col items-center">
|
<div class="flex flex-col items-center">
|
||||||
<p class="my-4 font-semibold tracking-widest text-center text-accent">
|
<p class="font-semibold my-4 text-center text-accent tracking-widest">
|
||||||
FEATURES
|
FEATURES
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-3">
|
<div class="grid gap-4 grid-cols-1 md:grid-cols-2 lg:grid-cols-3">
|
||||||
<div
|
<div
|
||||||
v-for="(feature, index) in features"
|
v-for="(feature, index) in features"
|
||||||
:key="`feature-${index}`"
|
:key="`feature-${index}`"
|
||||||
class="inline-flex flex-col p-8"
|
class="flex-col p-8 inline-flex"
|
||||||
>
|
>
|
||||||
<i class="text-4xl material-icons text-accent">{{ feature.icon }}</i>
|
<i class="text-accent text-4xl material-icons">{{ feature.icon }}</i>
|
||||||
<div class="flex-grow">
|
<div class="flex-grow">
|
||||||
<h2
|
<h2
|
||||||
class="
|
class="
|
||||||
mt-4
|
|
||||||
mb-2
|
|
||||||
text-lg
|
|
||||||
font-semibold
|
font-semibold
|
||||||
|
mt-4
|
||||||
|
text-lg text-secondaryDark
|
||||||
|
mb-2
|
||||||
transition
|
transition
|
||||||
text-secondaryDark
|
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
{{ feature.title }}
|
{{ feature.title }}
|
||||||
@@ -47,44 +46,44 @@ export default {
|
|||||||
features: [
|
features: [
|
||||||
{
|
{
|
||||||
icon: "offline_bolt",
|
icon: "offline_bolt",
|
||||||
title: "SaaS Executives",
|
title: "Feature",
|
||||||
description:
|
description:
|
||||||
"Unblock your barriers to new markets to sell software globally, to companies of all sizes, at all different price points, and increase your revenue growth with Kooli’s SaaS Commerce Platform.",
|
"Lorem ipsum dolor, sit amet consectetur adipisicing elit. Nam vel vero quia tenetur obcaecati. Distinctio nesciunt obcaecati deserunt.",
|
||||||
link: { title: "Learn more", target: "/settings" },
|
link: { title: "Learn more", target: "/settings" },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: "stars",
|
icon: "stars",
|
||||||
title: "Product Managers",
|
title: "Feature",
|
||||||
description:
|
description:
|
||||||
"Don’t let your billing stack hold you back. Everything you need to grow your SaaS business. Subscription billing, payments, taxes and more, in one unified platform.",
|
"Lorem ipsum dolor, sit amet consectetur adipisicing elit. Nam vel vero quia tenetur obcaecati. Distinctio nesciunt obcaecati deserunt.",
|
||||||
link: { title: "Learn more", target: "/settings" },
|
link: { title: "Learn more", target: "/settings" },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: "supervised_user_circle",
|
icon: "supervised_user_circle",
|
||||||
title: "Creators",
|
title: "Feature",
|
||||||
description:
|
description:
|
||||||
"Kooli is for artists and creators: writers, designers, software developers, musicians, educators, filmmakers, and anyone in-between. If you make stuff, you can sell that stuff.",
|
"Lorem ipsum dolor, sit amet consectetur adipisicing elit. Nam vel vero quia tenetur obcaecati. Distinctio nesciunt obcaecati deserunt.",
|
||||||
link: { title: "Learn more", target: "/settings" },
|
link: { title: "Learn more", target: "/settings" },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: "build_circle",
|
icon: "build_circle",
|
||||||
title: "Developers",
|
title: "Feature",
|
||||||
description:
|
description:
|
||||||
"Focus on building, not billing. Save the blood, sweat and tears for your software development, not your billing stack, with Paddle’s subscription and commerce platform.",
|
"Lorem ipsum dolor, sit amet consectetur adipisicing elit. Nam vel vero quia tenetur obcaecati. Distinctio nesciunt obcaecati deserunt.",
|
||||||
link: { title: "Learn more", target: "/settings" },
|
link: { title: "Learn more", target: "/settings" },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: "monetization_on",
|
icon: "monetization_on",
|
||||||
title: "Finance",
|
title: "Feature",
|
||||||
description:
|
description:
|
||||||
"All your payments, subscriptions, taxes, invoices, SaaS metrics, and more in one place. Integrate your product, CRM, and accounting with only one tool, not dozens.",
|
"Lorem ipsum dolor, sit amet consectetur adipisicing elit. Nam vel vero quia tenetur obcaecati. Distinctio nesciunt obcaecati deserunt.",
|
||||||
link: { title: "Learn more", target: "/settings" },
|
link: { title: "Learn more", target: "/settings" },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: "group_work",
|
icon: "group_work",
|
||||||
title: "Enterprise",
|
title: "Feature",
|
||||||
description:
|
description:
|
||||||
"Accept payments in 135+ currencies to better serve your international customers with a single integration. No international business entity required. Fees exclude GST.",
|
"Lorem ipsum dolor, sit amet consectetur adipisicing elit. Nam vel vero quia tenetur obcaecati. Distinctio nesciunt obcaecati deserunt.",
|
||||||
link: { title: "Learn more", target: "/settings" },
|
link: { title: "Learn more", target: "/settings" },
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -1,28 +1,19 @@
|
|||||||
<template>
|
<template>
|
||||||
<footer class="flex flex-col p-4">
|
<footer class="flex flex-col p-6">
|
||||||
<nav class="grid grid-cols-2 gap-4 md:grid-cols-4">
|
<nav class="grid gap-4 grid-cols-2 md:grid-cols-4">
|
||||||
<div class="flex flex-col space-y-2">
|
<div class="flex flex-col space-y-2">
|
||||||
<span>
|
<h4 class="font-semibold my-2">Hoppscotch</h4>
|
||||||
<AppLogo class="h-8" />
|
<ul class="space-y-4">
|
||||||
</span>
|
|
||||||
<span class="font-bold"> Hoppscotch </span>
|
|
||||||
<SmartChangeLanguage />
|
|
||||||
<ul class="space-y-2">
|
|
||||||
<li>
|
<li>
|
||||||
<SmartAnchor label="Terms" to="/about/terms" class="footer-nav" />
|
<SmartChangeLanguage />
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<SmartAnchor
|
<SmartColorModePicker />
|
||||||
label="Privacy"
|
|
||||||
to="/about/privacy"
|
|
||||||
class="footer-nav"
|
|
||||||
/>
|
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<SmartColorModePicker />
|
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-col space-y-2">
|
<div class="flex flex-col space-y-2">
|
||||||
<h4 class="my-2 font-semibold">Solutions</h4>
|
<h4 class="font-semibold my-2">Solutions</h4>
|
||||||
<ul class="space-y-2">
|
<ul class="space-y-2">
|
||||||
<li
|
<li
|
||||||
v-for="(item, index) in navigation.solutions"
|
v-for="(item, index) in navigation.solutions"
|
||||||
@@ -37,7 +28,7 @@
|
|||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-col space-y-2">
|
<div class="flex flex-col space-y-2">
|
||||||
<h4 class="my-2 font-semibold">Platform</h4>
|
<h4 class="font-semibold my-2">Platform</h4>
|
||||||
<ul class="space-y-2">
|
<ul class="space-y-2">
|
||||||
<li
|
<li
|
||||||
v-for="(item, index) in navigation.platform"
|
v-for="(item, index) in navigation.platform"
|
||||||
@@ -52,7 +43,7 @@
|
|||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-col space-y-2">
|
<div class="flex flex-col space-y-2">
|
||||||
<h4 class="my-2 font-semibold">Company</h4>
|
<h4 class="font-semibold my-2">Company</h4>
|
||||||
<ul class="space-y-2">
|
<ul class="space-y-2">
|
||||||
<li
|
<li
|
||||||
v-for="(item, index) in navigation.company"
|
v-for="(item, index) in navigation.company"
|
||||||
@@ -77,72 +68,84 @@ export default {
|
|||||||
navigation: {
|
navigation: {
|
||||||
solutions: [
|
solutions: [
|
||||||
{
|
{
|
||||||
name: "SaaS",
|
name: "RESTful",
|
||||||
link: "/settings",
|
link: "/",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Products",
|
name: "WebSocket",
|
||||||
link: "/settings",
|
link: "/realtime",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Creators",
|
name: "SSE",
|
||||||
link: "/settings",
|
link: "/realtime",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Developers",
|
name: "Socket.IO",
|
||||||
link: "/settings",
|
link: "/realtime",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Finance",
|
name: "MQTT",
|
||||||
link: "/settings",
|
link: "/realtime",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Enterprise",
|
name: "GraphQL",
|
||||||
link: "/settings",
|
link: "/graphql",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
platform: [
|
platform: [
|
||||||
{
|
{
|
||||||
name: "Payments",
|
name: "API Designing",
|
||||||
link: "/settings",
|
link: "/",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Subscriptions",
|
name: "API Development",
|
||||||
link: "/settings",
|
link: "/",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "API",
|
name: "API Testing",
|
||||||
link: "https://docs.kooli.tech/api",
|
link: "/",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Guides",
|
name: "API Deployment",
|
||||||
link: "https://docs.kooli.tech/guides",
|
link: "/",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "API Documentation",
|
||||||
|
link: "/documentation",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Integrations",
|
||||||
|
link: "/",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
company: [
|
company: [
|
||||||
{
|
{
|
||||||
name: "About",
|
name: "About",
|
||||||
link: "/about",
|
link: "/",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Jobs",
|
name: "Careers",
|
||||||
link: "/about/jobs",
|
link: "/careers",
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Integrations",
|
|
||||||
link: "/about/integrations",
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Support",
|
name: "Support",
|
||||||
link: "",
|
link: "/",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Contact",
|
name: "Contact",
|
||||||
link: "/about/contact",
|
link: "/",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Blog",
|
name: "Blog",
|
||||||
link: "https://blog.kooli.tech",
|
link: "https://blog.hoppscotch.io",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Community",
|
||||||
|
link: "/",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Open Source",
|
||||||
|
link: "https://github.com/hoppscotch",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
@@ -151,11 +154,11 @@ export default {
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style scoped lang="scss">
|
||||||
.footer-nav {
|
.footer-nav {
|
||||||
&:hover,
|
@apply px-2 py-1;
|
||||||
&:focus {
|
@apply -mx-2 -my-1;
|
||||||
@apply text-secondaryDark;
|
@apply hover:text-secondaryDark;
|
||||||
}
|
@apply focus:text-secondaryDark;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,146 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div ref="globe"></div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import ThreeGlobe from "three-globe"
|
|
||||||
import * as THREE from "three"
|
|
||||||
import TrackballControls from "three-trackballcontrols"
|
|
||||||
import geojson from "~/assets/geojson/ne_110m_admin_0_countries.geojson"
|
|
||||||
import texture from "~/assets/images/texture.png"
|
|
||||||
|
|
||||||
export default {
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
globe: null,
|
|
||||||
renderer: null,
|
|
||||||
scene: null,
|
|
||||||
camera: null,
|
|
||||||
tbControls: null,
|
|
||||||
arcsData: [...Array(20).keys()].map(() => ({
|
|
||||||
startLat: (Math.random() - 0.5) * 180,
|
|
||||||
startLng: (Math.random() - 0.5) * 360,
|
|
||||||
endLat: (Math.random() - 0.5) * 180,
|
|
||||||
endLng: (Math.random() - 0.5) * 360,
|
|
||||||
color: [
|
|
||||||
["#00acee", "#aceeff", "#00ffac", "#aaef3e"][
|
|
||||||
Math.round(Math.random() * 3)
|
|
||||||
],
|
|
||||||
["#00acee", "#aceeff", "#00ffac", "#aaef3e"][
|
|
||||||
Math.round(Math.random() * 3)
|
|
||||||
],
|
|
||||||
],
|
|
||||||
})),
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
computed: {
|
|
||||||
labelsData() {
|
|
||||||
const labelsData = []
|
|
||||||
this.arcsData.forEach(
|
|
||||||
({ startLat, startLng, endLat, endLng, color }, linkIdx) =>
|
|
||||||
[
|
|
||||||
[startLat, startLng],
|
|
||||||
[endLat, endLng],
|
|
||||||
].forEach(([lat, lng], edgeIdx) =>
|
|
||||||
labelsData.push({
|
|
||||||
lat,
|
|
||||||
lng,
|
|
||||||
color: color[edgeIdx],
|
|
||||||
text: `${linkIdx} ${edgeIdx ? "tgt" : "src"}`,
|
|
||||||
})
|
|
||||||
)
|
|
||||||
)
|
|
||||||
return labelsData
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
mounted() {
|
|
||||||
this.init()
|
|
||||||
this.animate()
|
|
||||||
window.addEventListener(
|
|
||||||
"resize",
|
|
||||||
() => {
|
|
||||||
this.camera.aspect =
|
|
||||||
this.$refs.globe.clientWidth / this.$refs.globe.clientHeight
|
|
||||||
this.camera.updateProjectionMatrix()
|
|
||||||
this.renderer.setSize(
|
|
||||||
this.$refs.globe.clientWidth,
|
|
||||||
this.$refs.globe.clientHeight
|
|
||||||
)
|
|
||||||
},
|
|
||||||
false
|
|
||||||
)
|
|
||||||
},
|
|
||||||
|
|
||||||
methods: {
|
|
||||||
init() {
|
|
||||||
this.globe = new ThreeGlobe()
|
|
||||||
.globeImageUrl(texture)
|
|
||||||
.atmosphereColor("#aaaaaa")
|
|
||||||
// arcs layer
|
|
||||||
.arcsData(this.arcsData)
|
|
||||||
.arcColor("color")
|
|
||||||
.arcDashLength(1)
|
|
||||||
.arcDashGap(() => Math.random())
|
|
||||||
.arcStroke(0.6)
|
|
||||||
.arcDashInitialGap(() => Math.random() * 5)
|
|
||||||
.arcDashAnimateTime(2000)
|
|
||||||
|
|
||||||
// hex layer
|
|
||||||
.hexPolygonsData(geojson.features)
|
|
||||||
.hexPolygonResolution(3)
|
|
||||||
.hexPolygonMargin(0.5)
|
|
||||||
.hexPolygonColor(() => `#aaaaaa`)
|
|
||||||
|
|
||||||
// labels layer
|
|
||||||
.labelsData(this.labelsData)
|
|
||||||
.labelLat("lat")
|
|
||||||
.labelLng("lng")
|
|
||||||
.labelText("text")
|
|
||||||
.labelColor("color")
|
|
||||||
.labelSize(1.2)
|
|
||||||
.labelDotRadius(0.8)
|
|
||||||
|
|
||||||
// Setup renderer
|
|
||||||
this.renderer = new THREE.WebGLRenderer({
|
|
||||||
alpha: true,
|
|
||||||
})
|
|
||||||
this.renderer.setSize(
|
|
||||||
this.$refs.globe.clientWidth,
|
|
||||||
this.$refs.globe.clientHeight
|
|
||||||
)
|
|
||||||
this.$refs.globe.appendChild(this.renderer.domElement)
|
|
||||||
|
|
||||||
// Setup scene
|
|
||||||
this.scene = new THREE.Scene()
|
|
||||||
this.scene.background = null
|
|
||||||
this.scene.add(this.globe)
|
|
||||||
this.scene.add(new THREE.AmbientLight(0xffffff))
|
|
||||||
this.scene.add(new THREE.DirectionalLight(0xffffff, 0.6))
|
|
||||||
|
|
||||||
// Setup camera
|
|
||||||
this.camera = new THREE.PerspectiveCamera()
|
|
||||||
this.camera.aspect =
|
|
||||||
this.$refs.globe.clientWidth / this.$refs.globe.clientHeight
|
|
||||||
this.camera.updateProjectionMatrix()
|
|
||||||
this.camera.position.z = 300
|
|
||||||
|
|
||||||
// Add camera controls
|
|
||||||
this.tbControls = new TrackballControls(
|
|
||||||
this.camera,
|
|
||||||
this.renderer.domElement
|
|
||||||
)
|
|
||||||
this.tbControls.noZoom = true
|
|
||||||
this.tbControls.noPan = true
|
|
||||||
},
|
|
||||||
|
|
||||||
animate() {
|
|
||||||
this.renderer.render(this.scene, this.camera)
|
|
||||||
this.tbControls.update()
|
|
||||||
requestAnimationFrame(this.animate)
|
|
||||||
this.globe.rotation.y -= 0.0025
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
@@ -1,51 +1,71 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="flex p-4 relative">
|
<div class="flex flex-col p-6 relative">
|
||||||
<div class="relative my-16 z-10 max-w-3xl">
|
<div class="flex flex-col mt-16 items-center justify-center">
|
||||||
<h2
|
<h2
|
||||||
class="
|
class="
|
||||||
|
font-extrabold
|
||||||
|
text-accent text-center
|
||||||
leading-none
|
leading-none
|
||||||
tracking-tighter
|
tracking-tighter
|
||||||
font-semibold
|
text-4xl
|
||||||
text-accent text-4xl
|
md:text-6xl
|
||||||
md:text-5xl
|
lg:text-8xl
|
||||||
lg:text-6xl
|
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
Open Source
|
Open Source
|
||||||
</h2>
|
</h2>
|
||||||
<h3
|
<h3
|
||||||
class="
|
class="
|
||||||
text-3xl
|
font-extrabold
|
||||||
my-4
|
my-4
|
||||||
font-mono
|
text-center text-secondaryDark
|
||||||
text-secondaryDark
|
leading-none
|
||||||
|
tracking-tighter
|
||||||
|
text-3xl
|
||||||
md:text-4xl
|
md:text-4xl
|
||||||
lg:text-4xl
|
lg:text-5xl
|
||||||
font-semibold
|
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
API Development Ecosystem
|
API Development Ecosystem
|
||||||
</h3>
|
</h3>
|
||||||
<p class="text-lg my-4 text-secondaryLight max-w-4/5">
|
<p class="my-4 text-lg text-center max-w-2xl">
|
||||||
Millions of developers and companies build, ship, and maintain their
|
Thousands of developers and companies build, ship, and maintain their
|
||||||
APIs on Hoppscotch — the largest and most advanced development platform
|
APIs on Hoppscotch — the transparent and most flexible API development
|
||||||
in the world.
|
ecosystem in the world.
|
||||||
</p>
|
</p>
|
||||||
<div class="my-8 flex items-center">
|
<div class="flex space-x-4 my-8 justify-center items-center">
|
||||||
<ButtonPrimary
|
<ButtonPrimary
|
||||||
label="Dashboard"
|
label="Get Started"
|
||||||
icon="chevron_right"
|
icon="arrow_forward"
|
||||||
class="my-4"
|
rounded
|
||||||
large
|
|
||||||
reverse
|
reverse
|
||||||
|
large
|
||||||
|
@click.native="showLogin = true"
|
||||||
|
/>
|
||||||
|
<ButtonSecondary
|
||||||
|
to="https://github.com/hoppscotch/hoppscotch"
|
||||||
|
blank
|
||||||
|
outline
|
||||||
|
label="GitHub"
|
||||||
|
svg="github"
|
||||||
|
large
|
||||||
|
rounded
|
||||||
|
:shortcut="['30k Stars']"
|
||||||
/>
|
/>
|
||||||
<ButtonSecondary label="Dashboard" icon="chevron_right" />
|
|
||||||
<ButtonPrimary label="GitHub" svg="github" large rounded />
|
|
||||||
<AppGitHubStarButton size="large" />
|
|
||||||
</div>
|
</div>
|
||||||
|
<!-- <LandingStats /> -->
|
||||||
</div>
|
</div>
|
||||||
<div class="lg:absolute lg:inset-y-0 lg:right-0 lg:w-1/2">
|
<div class="flex flex-col items-center justify-center"></div>
|
||||||
<LandingGlobe class="h-64 w-full sm:h-72 md:h-96 lg:h-full" />
|
<FirebaseLogin :show="showLogin" @hide-modal="showLogin = false" />
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
showLogin: false,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="flex p-4 font-mono space-x-16">
|
<div class="flex font-mono space-x-16 p-6">
|
||||||
<div v-for="(stat, index) in stats" :key="`stat-${index}`">
|
<div v-for="(stat, index) in stats" :key="`stat-${index}`">
|
||||||
<span class="text-xl font-bold">
|
<span class="font-bold text-xl">
|
||||||
{{ stat.count }}<span class="text-secondaryLight">+</span>
|
{{ stat.count }}<span class="text-secondaryLight">+</span>
|
||||||
</span>
|
</span>
|
||||||
<br />
|
<br />
|
||||||
@@ -18,7 +18,7 @@ export default {
|
|||||||
return {
|
return {
|
||||||
stats: [
|
stats: [
|
||||||
{ count: "350k", audience: "Developers" },
|
{ count: "350k", audience: "Developers" },
|
||||||
{ count: "10k", audience: "Organizations" },
|
{ count: "5k", audience: "Organizations" },
|
||||||
{ count: "1m", audience: "Requests" },
|
{ count: "1m", audience: "Requests" },
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,21 +1,21 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="flex flex-col p-4 mx-4 bg-primaryLight rounded">
|
<div class="bg-primaryLight rounded flex flex-col mx-6 p-4">
|
||||||
<div class="flex flex-col items-center">
|
<div class="flex flex-col items-center">
|
||||||
<p class="my-4 font-semibold tracking-widest text-center">
|
<p class="font-semibold my-4 text-center tracking-widest">
|
||||||
EMPOWERING DEVELOPERS FROM
|
EMPOWERING DEVELOPERS FROM
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="grid grid-cols-3 gap-4 md:grid-cols-4 lg:grid-cols-6">
|
<div class="grid gap-4 grid-cols-3 md:grid-cols-4 lg:grid-cols-6">
|
||||||
<div
|
<div
|
||||||
v-for="(user, index) in users"
|
v-for="(user, index) in users"
|
||||||
:key="`user-${index}`"
|
:key="`user-${index}`"
|
||||||
class="inline-flex flex-col items-center justify-center px-4"
|
class="flex-col px-4 inline-flex items-center justify-center"
|
||||||
>
|
>
|
||||||
<img
|
<img
|
||||||
:src="`/images/users/${user.image}`"
|
:src="`/images/users/${user.image}`"
|
||||||
alt="Profile picture"
|
alt="Profile picture"
|
||||||
loading="lazy"
|
loading="lazy"
|
||||||
class="inline-flex flex-col object-contain object-center h-24 w-24"
|
class="flex-col object-contain object-center h-24 w-24 inline-flex"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="p-2 font-mono">
|
<div class="font-mono p-2">
|
||||||
<div
|
<div
|
||||||
v-for="(header, index) in headers"
|
v-for="(header, index) in headers"
|
||||||
:key="`header-${index}`"
|
:key="`header-${index}`"
|
||||||
@@ -7,27 +7,25 @@
|
|||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
class="
|
class="
|
||||||
p-2
|
|
||||||
flex
|
flex
|
||||||
min-w-0
|
|
||||||
text-xs
|
|
||||||
group-hover:text-secondaryDark
|
|
||||||
transition
|
|
||||||
font-semibold
|
font-semibold
|
||||||
|
min-w-0
|
||||||
|
p-2
|
||||||
|
transition
|
||||||
|
group-hover:text-secondaryDark
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
<span class="truncate">
|
<span class="rounded select-all truncate">
|
||||||
{{ header.key }}
|
{{ header.key }}
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
<span
|
<span
|
||||||
class="
|
class="
|
||||||
font-mono font-bold
|
|
||||||
flex
|
flex
|
||||||
|
font-mono font-bold
|
||||||
|
mx-2
|
||||||
justify-center
|
justify-center
|
||||||
items-center
|
items-center
|
||||||
text-xs
|
|
||||||
mx-2
|
|
||||||
truncate
|
truncate
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
@@ -35,16 +33,16 @@
|
|||||||
</span>
|
</span>
|
||||||
<span
|
<span
|
||||||
class="
|
class="
|
||||||
p-2
|
flex
|
||||||
flex flex-1
|
|
||||||
min-w-0
|
|
||||||
text-xs
|
|
||||||
group-hover:text-secondaryDark
|
|
||||||
transition
|
|
||||||
font-semibold
|
font-semibold
|
||||||
|
flex-1
|
||||||
|
min-w-0
|
||||||
|
p-2
|
||||||
|
transition
|
||||||
|
group-hover:text-secondaryDark
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
<span class="truncate">
|
<span class="rounded select-all truncate">
|
||||||
{{ header.value }}
|
{{ header.value }}
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<SmartTabs styles="sticky z-10 top-13">
|
<SmartTabs styles="sticky z-10 top-12">
|
||||||
<SmartTab
|
<SmartTab
|
||||||
v-for="(lens, index) in validLenses"
|
v-for="(lens, index) in validLenses"
|
||||||
:id="lens.lensName"
|
:id="lens.lensName"
|
||||||
@@ -10,10 +10,10 @@
|
|||||||
<component :is="lens.renderer" :response="response" />
|
<component :is="lens.renderer" :response="response" />
|
||||||
</SmartTab>
|
</SmartTab>
|
||||||
<SmartTab
|
<SmartTab
|
||||||
v-if="Object.keys(response.headers).length !== 0"
|
v-if="headerLength"
|
||||||
id="headers"
|
id="headers"
|
||||||
:label="$t('Headers')"
|
:label="$t('Headers')"
|
||||||
:info="Object.keys(response.headers).length.toString()"
|
:info="headerLength.toString()"
|
||||||
>
|
>
|
||||||
<LensesHeadersRenderer :headers="response.headers" />
|
<LensesHeadersRenderer :headers="response.headers" />
|
||||||
</SmartTab>
|
</SmartTab>
|
||||||
@@ -32,7 +32,14 @@ export default {
|
|||||||
response: { type: Object, default: () => {} },
|
response: { type: Object, default: () => {} },
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
headerLength() {
|
||||||
|
if (!this.response || !this.response.headers) return 0
|
||||||
|
|
||||||
|
return Object.keys(this.response.headers).length
|
||||||
|
},
|
||||||
validLenses() {
|
validLenses() {
|
||||||
|
if (!this.response) return []
|
||||||
|
|
||||||
return getSuitableLenses(this.response)
|
return getSuitableLenses(this.response)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -2,24 +2,24 @@
|
|||||||
<div>
|
<div>
|
||||||
<div
|
<div
|
||||||
class="
|
class="
|
||||||
flex flex-1
|
|
||||||
sticky
|
|
||||||
top-23
|
|
||||||
z-10
|
|
||||||
bg-primary
|
bg-primary
|
||||||
|
border-b border-dividerLight
|
||||||
|
flex flex-1
|
||||||
|
top-20
|
||||||
|
z-10
|
||||||
|
sticky
|
||||||
items-center
|
items-center
|
||||||
justify-between
|
justify-between
|
||||||
border-b border-dividerLight
|
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
<label for="body" class="px-4 font-semibold text-xs">
|
<label for="body" class="font-semibold px-4">
|
||||||
{{ $t("response_body") }}
|
{{ $t("response_body") }}
|
||||||
</label>
|
</label>
|
||||||
<div>
|
<div>
|
||||||
<ButtonSecondary
|
<ButtonSecondary
|
||||||
v-if="response.body"
|
v-if="response.body"
|
||||||
v-tippy="{ theme: 'tooltip' }"
|
v-tippy="{ theme: 'tooltip' }"
|
||||||
:title="previewEnabled ? $t('hide_preview') : $t('preview_html')"
|
:title="previewEnabled ? $t('hide.preview') : $t('preview_html')"
|
||||||
:icon="!previewEnabled ? 'visibility' : 'visibility_off'"
|
:icon="!previewEnabled ? 'visibility' : 'visibility_off'"
|
||||||
@click.native.prevent="togglePreview"
|
@click.native.prevent="togglePreview"
|
||||||
/>
|
/>
|
||||||
@@ -35,7 +35,7 @@
|
|||||||
v-if="response.body"
|
v-if="response.body"
|
||||||
ref="copyResponse"
|
ref="copyResponse"
|
||||||
v-tippy="{ theme: 'tooltip' }"
|
v-tippy="{ theme: 'tooltip' }"
|
||||||
:title="$t('copy_response')"
|
:title="$t('action.copy')"
|
||||||
:icon="copyIcon"
|
:icon="copyIcon"
|
||||||
@click.native="copyResponse"
|
@click.native="copyResponse"
|
||||||
/>
|
/>
|
||||||
@@ -47,8 +47,8 @@
|
|||||||
:lang="'html'"
|
:lang="'html'"
|
||||||
:options="{
|
:options="{
|
||||||
maxLines: Infinity,
|
maxLines: Infinity,
|
||||||
minLines: '16',
|
minLines: 16,
|
||||||
fontSize: '14px',
|
fontSize: '12px',
|
||||||
autoScrollEditorIntoView: true,
|
autoScrollEditorIntoView: true,
|
||||||
readOnly: true,
|
readOnly: true,
|
||||||
showPrintMargin: false,
|
showPrintMargin: false,
|
||||||
@@ -67,6 +67,7 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import TextContentRendererMixin from "./mixins/TextContentRendererMixin"
|
import TextContentRendererMixin from "./mixins/TextContentRendererMixin"
|
||||||
|
import { copyToClipboard } from "~/helpers/utils/clipboard"
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
mixins: [TextContentRendererMixin],
|
mixins: [TextContentRendererMixin],
|
||||||
@@ -97,18 +98,12 @@ export default {
|
|||||||
})
|
})
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
document.body.removeChild(a)
|
document.body.removeChild(a)
|
||||||
window.URL.revokeObjectURL(url)
|
URL.revokeObjectURL(url)
|
||||||
this.downloadIcon = "save_alt"
|
this.downloadIcon = "save_alt"
|
||||||
}, 1000)
|
}, 1000)
|
||||||
},
|
},
|
||||||
copyResponse() {
|
copyResponse() {
|
||||||
const aux = document.createElement("textarea")
|
copyToClipboard(this.responseBodyText)
|
||||||
const copy = this.responseBodyText
|
|
||||||
aux.innerText = copy
|
|
||||||
document.body.appendChild(aux)
|
|
||||||
aux.select()
|
|
||||||
document.execCommand("copy")
|
|
||||||
document.body.removeChild(aux)
|
|
||||||
this.copyIcon = "done"
|
this.copyIcon = "done"
|
||||||
this.$toast.success(this.$t("copied_to_clipboard"), {
|
this.$toast.success(this.$t("copied_to_clipboard"), {
|
||||||
icon: "done",
|
icon: "done",
|
||||||
|
|||||||
@@ -2,17 +2,17 @@
|
|||||||
<div>
|
<div>
|
||||||
<div
|
<div
|
||||||
class="
|
class="
|
||||||
flex flex-1
|
|
||||||
sticky
|
|
||||||
top-23
|
|
||||||
z-10
|
|
||||||
bg-primary
|
bg-primary
|
||||||
|
border-b border-dividerLight
|
||||||
|
flex flex-1
|
||||||
|
top-20
|
||||||
|
z-10
|
||||||
|
sticky
|
||||||
items-center
|
items-center
|
||||||
justify-between
|
justify-between
|
||||||
border-b border-dividerLight
|
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
<label for="body" class="px-4 font-semibold text-xs">
|
<label for="body" class="font-semibold px-4">
|
||||||
{{ $t("response_body") }}
|
{{ $t("response_body") }}
|
||||||
</label>
|
</label>
|
||||||
<div>
|
<div>
|
||||||
@@ -98,7 +98,7 @@ export default {
|
|||||||
})
|
})
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
document.body.removeChild(a)
|
document.body.removeChild(a)
|
||||||
window.URL.revokeObjectURL(url)
|
URL.revokeObjectURL(url)
|
||||||
this.downloadIcon = "save_alt"
|
this.downloadIcon = "save_alt"
|
||||||
}, 1000)
|
}, 1000)
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -2,22 +2,22 @@
|
|||||||
<div>
|
<div>
|
||||||
<div
|
<div
|
||||||
class="
|
class="
|
||||||
flex flex-1
|
|
||||||
sticky
|
|
||||||
top-23
|
|
||||||
z-10
|
|
||||||
bg-primary
|
bg-primary
|
||||||
|
border-b border-dividerLight
|
||||||
|
flex flex-1
|
||||||
|
top-20
|
||||||
|
z-10
|
||||||
|
sticky
|
||||||
items-center
|
items-center
|
||||||
justify-between
|
justify-between
|
||||||
border-b border-dividerLight
|
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
<label for="body" class="px-4 font-semibold text-xs">
|
<label for="body" class="font-semibold px-4">
|
||||||
{{ $t("response_body") }}
|
{{ $t("response_body") }}
|
||||||
</label>
|
</label>
|
||||||
<div>
|
<div>
|
||||||
<ButtonSecondary
|
<ButtonSecondary
|
||||||
v-if="response.body && canDownloadResponse"
|
v-if="response.body"
|
||||||
ref="downloadResponse"
|
ref="downloadResponse"
|
||||||
v-tippy="{ theme: 'tooltip' }"
|
v-tippy="{ theme: 'tooltip' }"
|
||||||
:title="$t('download_file')"
|
:title="$t('download_file')"
|
||||||
@@ -28,7 +28,7 @@
|
|||||||
v-if="response.body"
|
v-if="response.body"
|
||||||
ref="copyResponse"
|
ref="copyResponse"
|
||||||
v-tippy="{ theme: 'tooltip' }"
|
v-tippy="{ theme: 'tooltip' }"
|
||||||
:title="$t('copy_response')"
|
:title="$t('action.copy')"
|
||||||
:icon="copyIcon"
|
:icon="copyIcon"
|
||||||
@click.native="copyResponse"
|
@click.native="copyResponse"
|
||||||
/>
|
/>
|
||||||
@@ -41,8 +41,8 @@
|
|||||||
:provide-j-s-o-n-outline="true"
|
:provide-j-s-o-n-outline="true"
|
||||||
:options="{
|
:options="{
|
||||||
maxLines: Infinity,
|
maxLines: Infinity,
|
||||||
minLines: '16',
|
minLines: 16,
|
||||||
fontSize: '14px',
|
fontSize: '12px',
|
||||||
autoScrollEditorIntoView: true,
|
autoScrollEditorIntoView: true,
|
||||||
readOnly: true,
|
readOnly: true,
|
||||||
showPrintMargin: false,
|
showPrintMargin: false,
|
||||||
@@ -55,7 +55,7 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import TextContentRendererMixin from "./mixins/TextContentRendererMixin"
|
import TextContentRendererMixin from "./mixins/TextContentRendererMixin"
|
||||||
import { isJSONContentType } from "~/helpers/utils/contenttypes"
|
import { copyToClipboard } from "~/helpers/utils/clipboard"
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
mixins: [TextContentRendererMixin],
|
mixins: [TextContentRendererMixin],
|
||||||
@@ -82,19 +82,11 @@ export default {
|
|||||||
.split(";")[0]
|
.split(";")[0]
|
||||||
.toLowerCase()
|
.toLowerCase()
|
||||||
},
|
},
|
||||||
canDownloadResponse() {
|
|
||||||
return (
|
|
||||||
this.response &&
|
|
||||||
this.response.headers &&
|
|
||||||
this.response.headers["content-type"] &&
|
|
||||||
isJSONContentType(this.response.headers["content-type"])
|
|
||||||
)
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
downloadResponse() {
|
downloadResponse() {
|
||||||
const dataToWrite = this.responseBodyText
|
const dataToWrite = this.responseBodyText
|
||||||
const file = new Blob([dataToWrite], { type: this.responseType })
|
const file = new Blob([dataToWrite], { type: "application/json" })
|
||||||
const a = document.createElement("a")
|
const a = document.createElement("a")
|
||||||
const url = URL.createObjectURL(file)
|
const url = URL.createObjectURL(file)
|
||||||
a.href = url
|
a.href = url
|
||||||
@@ -108,18 +100,12 @@ export default {
|
|||||||
})
|
})
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
document.body.removeChild(a)
|
document.body.removeChild(a)
|
||||||
window.URL.revokeObjectURL(url)
|
URL.revokeObjectURL(url)
|
||||||
this.downloadIcon = "save_alt"
|
this.downloadIcon = "save_alt"
|
||||||
}, 1000)
|
}, 1000)
|
||||||
},
|
},
|
||||||
copyResponse() {
|
copyResponse() {
|
||||||
const aux = document.createElement("textarea")
|
copyToClipboard(this.responseBodyText)
|
||||||
const copy = this.responseBodyText
|
|
||||||
aux.innerText = copy
|
|
||||||
document.body.appendChild(aux)
|
|
||||||
aux.select()
|
|
||||||
document.execCommand("copy")
|
|
||||||
document.body.removeChild(aux)
|
|
||||||
this.copyIcon = "done"
|
this.copyIcon = "done"
|
||||||
this.$toast.success(this.$t("copied_to_clipboard"), {
|
this.$toast.success(this.$t("copied_to_clipboard"), {
|
||||||
icon: "done",
|
icon: "done",
|
||||||
|
|||||||
@@ -2,22 +2,22 @@
|
|||||||
<div>
|
<div>
|
||||||
<div
|
<div
|
||||||
class="
|
class="
|
||||||
flex flex-1
|
|
||||||
sticky
|
|
||||||
top-23
|
|
||||||
z-10
|
|
||||||
bg-primary
|
bg-primary
|
||||||
|
border-b border-dividerLight
|
||||||
|
flex flex-1
|
||||||
|
top-20
|
||||||
|
z-10
|
||||||
|
sticky
|
||||||
items-center
|
items-center
|
||||||
justify-between
|
justify-between
|
||||||
border-b border-dividerLight
|
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
<label for="body" class="px-4 font-semibold text-xs">
|
<label for="body" class="font-semibold px-4">
|
||||||
{{ $t("response_body") }}
|
{{ $t("response_body") }}
|
||||||
</label>
|
</label>
|
||||||
<div>
|
<div>
|
||||||
<ButtonSecondary
|
<ButtonSecondary
|
||||||
v-if="response.body && canDownloadResponse"
|
v-if="response.body"
|
||||||
ref="downloadResponse"
|
ref="downloadResponse"
|
||||||
v-tippy="{ theme: 'tooltip' }"
|
v-tippy="{ theme: 'tooltip' }"
|
||||||
:title="$t('download_file')"
|
:title="$t('download_file')"
|
||||||
@@ -28,7 +28,7 @@
|
|||||||
v-if="response.body"
|
v-if="response.body"
|
||||||
ref="copyResponse"
|
ref="copyResponse"
|
||||||
v-tippy="{ theme: 'tooltip' }"
|
v-tippy="{ theme: 'tooltip' }"
|
||||||
:title="$t('copy_response')"
|
:title="$t('action.copy')"
|
||||||
:icon="copyIcon"
|
:icon="copyIcon"
|
||||||
@click.native="copyResponse"
|
@click.native="copyResponse"
|
||||||
/>
|
/>
|
||||||
@@ -40,8 +40,8 @@
|
|||||||
:lang="'plain_text'"
|
:lang="'plain_text'"
|
||||||
:options="{
|
:options="{
|
||||||
maxLines: Infinity,
|
maxLines: Infinity,
|
||||||
minLines: '16',
|
minLines: 16,
|
||||||
fontSize: '14px',
|
fontSize: '12px',
|
||||||
autoScrollEditorIntoView: true,
|
autoScrollEditorIntoView: true,
|
||||||
readOnly: true,
|
readOnly: true,
|
||||||
showPrintMargin: false,
|
showPrintMargin: false,
|
||||||
@@ -54,7 +54,7 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import TextContentRendererMixin from "./mixins/TextContentRendererMixin"
|
import TextContentRendererMixin from "./mixins/TextContentRendererMixin"
|
||||||
import { isJSONContentType } from "~/helpers/utils/contenttypes"
|
import { copyToClipboard } from "~/helpers/utils/clipboard"
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
mixins: [TextContentRendererMixin],
|
mixins: [TextContentRendererMixin],
|
||||||
@@ -73,14 +73,6 @@ export default {
|
|||||||
.split(";")[0]
|
.split(";")[0]
|
||||||
.toLowerCase()
|
.toLowerCase()
|
||||||
},
|
},
|
||||||
canDownloadResponse() {
|
|
||||||
return (
|
|
||||||
this.response &&
|
|
||||||
this.response.headers &&
|
|
||||||
this.response.headers["content-type"] &&
|
|
||||||
isJSONContentType(this.response.headers["content-type"])
|
|
||||||
)
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
downloadResponse() {
|
downloadResponse() {
|
||||||
@@ -99,18 +91,12 @@ export default {
|
|||||||
})
|
})
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
document.body.removeChild(a)
|
document.body.removeChild(a)
|
||||||
window.URL.revokeObjectURL(url)
|
URL.revokeObjectURL(url)
|
||||||
this.downloadIcon = "save_alt"
|
this.downloadIcon = "save_alt"
|
||||||
}, 1000)
|
}, 1000)
|
||||||
},
|
},
|
||||||
copyResponse() {
|
copyResponse() {
|
||||||
const aux = document.createElement("textarea")
|
copyToClipboard(this.responseBodyText)
|
||||||
const copy = this.responseBodyText
|
|
||||||
aux.innerText = copy
|
|
||||||
document.body.appendChild(aux)
|
|
||||||
aux.select()
|
|
||||||
document.execCommand("copy")
|
|
||||||
document.body.removeChild(aux)
|
|
||||||
this.copyIcon = "done"
|
this.copyIcon = "done"
|
||||||
this.$toast.success(this.$t("copied_to_clipboard"), {
|
this.$toast.success(this.$t("copied_to_clipboard"), {
|
||||||
icon: "done",
|
icon: "done",
|
||||||
|
|||||||
@@ -2,17 +2,17 @@
|
|||||||
<div>
|
<div>
|
||||||
<div
|
<div
|
||||||
class="
|
class="
|
||||||
flex flex-1
|
|
||||||
sticky
|
|
||||||
top-23
|
|
||||||
z-10
|
|
||||||
bg-primary
|
bg-primary
|
||||||
|
border-b border-dividerLight
|
||||||
|
flex flex-1
|
||||||
|
top-20
|
||||||
|
z-10
|
||||||
|
sticky
|
||||||
items-center
|
items-center
|
||||||
justify-between
|
justify-between
|
||||||
border-b border-dividerLight
|
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
<label for="body" class="px-4 font-semibold text-xs">
|
<label for="body" class="font-semibold px-4">
|
||||||
{{ $t("response_body") }}
|
{{ $t("response_body") }}
|
||||||
</label>
|
</label>
|
||||||
<div>
|
<div>
|
||||||
@@ -28,7 +28,7 @@
|
|||||||
v-if="response.body"
|
v-if="response.body"
|
||||||
ref="copyResponse"
|
ref="copyResponse"
|
||||||
v-tippy="{ theme: 'tooltip' }"
|
v-tippy="{ theme: 'tooltip' }"
|
||||||
:title="$t('copy_response')"
|
:title="$t('action.copy')"
|
||||||
:icon="copyIcon"
|
:icon="copyIcon"
|
||||||
@click.native="copyResponse"
|
@click.native="copyResponse"
|
||||||
/>
|
/>
|
||||||
@@ -40,8 +40,8 @@
|
|||||||
:lang="'xml'"
|
:lang="'xml'"
|
||||||
:options="{
|
:options="{
|
||||||
maxLines: Infinity,
|
maxLines: Infinity,
|
||||||
minLines: '16',
|
minLines: 16,
|
||||||
fontSize: '14px',
|
fontSize: '12px',
|
||||||
autoScrollEditorIntoView: true,
|
autoScrollEditorIntoView: true,
|
||||||
readOnly: true,
|
readOnly: true,
|
||||||
showPrintMargin: false,
|
showPrintMargin: false,
|
||||||
@@ -54,6 +54,7 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import TextContentRendererMixin from "./mixins/TextContentRendererMixin"
|
import TextContentRendererMixin from "./mixins/TextContentRendererMixin"
|
||||||
|
import { copyToClipboard } from "~/helpers/utils/clipboard"
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
mixins: [TextContentRendererMixin],
|
mixins: [TextContentRendererMixin],
|
||||||
@@ -90,18 +91,12 @@ export default {
|
|||||||
})
|
})
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
document.body.removeChild(a)
|
document.body.removeChild(a)
|
||||||
window.URL.revokeObjectURL(url)
|
URL.revokeObjectURL(url)
|
||||||
this.downloadIcon = "save_alt"
|
this.downloadIcon = "save_alt"
|
||||||
}, 1000)
|
}, 1000)
|
||||||
},
|
},
|
||||||
copyResponse() {
|
copyResponse() {
|
||||||
const aux = document.createElement("textarea")
|
copyToClipboard(this.responseBodyText)
|
||||||
const copy = this.responseBodyText
|
|
||||||
aux.innerText = copy
|
|
||||||
document.body.appendChild(aux)
|
|
||||||
aux.select()
|
|
||||||
document.execCommand("copy")
|
|
||||||
document.body.removeChild(aux)
|
|
||||||
this.copyIcon = "done"
|
this.copyIcon = "done"
|
||||||
this.$toast.success(this.$t("copied_to_clipboard"), {
|
this.$toast.success(this.$t("copied_to_clipboard"), {
|
||||||
icon: "done",
|
icon: "done",
|
||||||
|
|||||||
@@ -1,21 +1,26 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="relative flex items-center justify-center h-5 w-5 cursor-pointer">
|
<div class="cursor-pointer flex h-5 w-5 relative items-center justify-center">
|
||||||
<img
|
<img
|
||||||
class="
|
class="
|
||||||
absolute
|
bg-primaryDark bg-primaryLight
|
||||||
object-cover object-center
|
|
||||||
transition
|
|
||||||
rounded-full
|
rounded-full
|
||||||
bg-primaryDark
|
object-cover object-center
|
||||||
h-5
|
h-5
|
||||||
|
transition
|
||||||
w-5
|
w-5
|
||||||
bg-primaryLight
|
absolute
|
||||||
"
|
"
|
||||||
:src="url"
|
:src="url"
|
||||||
:alt="alt"
|
:alt="alt"
|
||||||
loading="lazy"
|
loading="lazy"
|
||||||
/>
|
/>
|
||||||
<div class="absolute inset-0 rounded-lg shadow-inner"></div>
|
<div class="rounded-full shadow-inner inset-0 absolute"></div>
|
||||||
|
<span
|
||||||
|
:class="[
|
||||||
|
'border-primary rounded-full border-2 h-3 -top-1 -right-1 w-3 absolute',
|
||||||
|
indicator,
|
||||||
|
]"
|
||||||
|
></span>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -32,6 +37,10 @@ export default {
|
|||||||
type: String,
|
type: String,
|
||||||
default: "Profile picture",
|
default: "Profile picture",
|
||||||
},
|
},
|
||||||
|
indicator: {
|
||||||
|
type: String,
|
||||||
|
default: "bg-green-500",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,8 +1,22 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="flex flex-col">
|
<div class="flex flex-col">
|
||||||
<label for="log">{{ title }}</label>
|
<div
|
||||||
|
class="
|
||||||
|
bg-primary
|
||||||
|
border-b border-dividerLight
|
||||||
|
flex flex-1
|
||||||
|
pl-4
|
||||||
|
top-0
|
||||||
|
z-10
|
||||||
|
sticky
|
||||||
|
items-center
|
||||||
|
justify-between
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<label for="log" class="font-semibold py-2">{{ title }}</label>
|
||||||
|
</div>
|
||||||
<div ref="log" name="log" class="realtime-log">
|
<div ref="log" name="log" class="realtime-log">
|
||||||
<span v-if="log">
|
<span v-if="log" class="space-y-2">
|
||||||
<span
|
<span
|
||||||
v-for="(entry, index) in log"
|
v-for="(entry, index) in log"
|
||||||
:key="`entry-${index}`"
|
:key="`entry-${index}`"
|
||||||
@@ -51,7 +65,7 @@ export default {
|
|||||||
|
|
||||||
&,
|
&,
|
||||||
span {
|
span {
|
||||||
@apply font-mono;
|
@apply font-mono font-semibold;
|
||||||
@apply select-text;
|
@apply select-text;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,140 +1,150 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<Splitpanes :dbl-click-splitter="false" vertical>
|
||||||
<Splitpanes vertical :dbl-click-splitter="false">
|
<Pane class="hide-scrollbar !overflow-auto">
|
||||||
<Pane class="overflow-auto">
|
<Splitpanes :dbl-click-splitter="false" horizontal>
|
||||||
<Splitpanes horizontal :dbl-click-splitter="false">
|
<Pane class="hide-scrollbar !overflow-auto">
|
||||||
<Pane class="overflow-auto">
|
|
||||||
<AppSection label="request">
|
<AppSection label="request">
|
||||||
<ul>
|
<div class="bg-primary flex p-4 top-0 z-10 sticky">
|
||||||
<li>
|
<div class="flex-1 inline-flex">
|
||||||
<label for="mqtt-url">{{ $t("url") }}</label>
|
|
||||||
<input
|
<input
|
||||||
id="mqtt-url"
|
id="mqtt-url"
|
||||||
v-model="url"
|
v-model="url"
|
||||||
type="url"
|
type="url"
|
||||||
spellcheck="false"
|
spellcheck="false"
|
||||||
class="input md:rounded-bl-lg"
|
class="
|
||||||
|
bg-primaryLight
|
||||||
|
border border-divider
|
||||||
|
rounded-l
|
||||||
|
font-semibold font-mono
|
||||||
|
text-secondaryDark
|
||||||
|
w-full
|
||||||
|
py-1
|
||||||
|
px-4
|
||||||
|
transition
|
||||||
|
truncate
|
||||||
|
focus:outline-none focus:border-accent
|
||||||
|
"
|
||||||
:placeholder="$t('url')"
|
:placeholder="$t('url')"
|
||||||
/>
|
/>
|
||||||
</li>
|
<ButtonPrimary
|
||||||
<div>
|
|
||||||
<li>
|
|
||||||
<ButtonSecondary
|
|
||||||
id="connect"
|
id="connect"
|
||||||
:disabled="!validUrl"
|
:disabled="!validUrl"
|
||||||
class="
|
class="rounded-l-none w-28"
|
||||||
button
|
:label="connectionState ? $t('disconnect') : $t('connect')"
|
||||||
rounded-b-lg
|
:loading="connectingState"
|
||||||
md:rounded-bl-none md:rounded-br-lg
|
|
||||||
"
|
|
||||||
:icon="!connectionState ? 'sync' : 'sync_disabled'"
|
|
||||||
:label="
|
|
||||||
connectionState ? $t('disconnect') : $t('connect')
|
|
||||||
"
|
|
||||||
reverse
|
|
||||||
@click.native="toggleConnection"
|
@click.native="toggleConnection"
|
||||||
/>
|
/>
|
||||||
</li>
|
|
||||||
</div>
|
</div>
|
||||||
</ul>
|
</div>
|
||||||
</AppSection>
|
</AppSection>
|
||||||
</Pane>
|
</Pane>
|
||||||
<Pane class="overflow-auto">
|
<Pane class="hide-scrollbar !overflow-auto">
|
||||||
<AppSection label="response">
|
<AppSection label="response">
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
<RealtimeLog :title="$t('log')" :log="log" />
|
<RealtimeLog :title="$t('log')" :log="log" />
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</AppSection>
|
</AppSection>
|
||||||
</Pane>
|
</Pane>
|
||||||
</Splitpanes>
|
</Splitpanes>
|
||||||
</Pane>
|
</Pane>
|
||||||
<Pane max-size="35" min-size="20" class="overflow-auto">
|
<Pane
|
||||||
|
v-if="RIGHT_SIDEBAR"
|
||||||
|
max-size="35"
|
||||||
|
size="25"
|
||||||
|
min-size="20"
|
||||||
|
class="hide-scrollbar !overflow-auto"
|
||||||
|
>
|
||||||
<AppSection label="messages">
|
<AppSection label="messages">
|
||||||
<ul>
|
<div class="flex flex-col flex-1 p-4 inline-flex">
|
||||||
<li>
|
<label for="pub_topic" class="font-semibold">
|
||||||
<label for="pub_topic">{{ $t("mqtt_topic") }}</label>
|
{{ $t("mqtt.topic") }}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div class="flex px-4">
|
||||||
<input
|
<input
|
||||||
id="pub_topic"
|
id="pub_topic"
|
||||||
v-model="pub_topic"
|
v-model="pub_topic"
|
||||||
class="input"
|
class="input"
|
||||||
|
:placeholder="$t('mqtt.topic_name')"
|
||||||
type="text"
|
type="text"
|
||||||
spellcheck="false"
|
spellcheck="false"
|
||||||
/>
|
/>
|
||||||
</li>
|
</div>
|
||||||
<li>
|
<div class="bg-primary flex flex-1 p-4 items-center justify-between">
|
||||||
<label for="mqtt-message">{{ $t("message") }}</label>
|
<label for="mqtt-message" class="font-semibold">{{
|
||||||
|
$t("communication")
|
||||||
|
}}</label>
|
||||||
|
</div>
|
||||||
|
<div class="flex px-4">
|
||||||
<input
|
<input
|
||||||
id="mqtt-message"
|
id="mqtt-message"
|
||||||
v-model="msg"
|
v-model="msg"
|
||||||
|
class="input !rounded-r-none"
|
||||||
type="text"
|
type="text"
|
||||||
|
:placeholder="$t('message')"
|
||||||
spellcheck="false"
|
spellcheck="false"
|
||||||
class="input border-dashed md:border-l border-divider"
|
|
||||||
/>
|
/>
|
||||||
</li>
|
<ButtonPrimary
|
||||||
<div>
|
|
||||||
<li>
|
|
||||||
<ButtonSecondary
|
|
||||||
id="publish"
|
id="publish"
|
||||||
class="button"
|
|
||||||
name="get"
|
name="get"
|
||||||
|
class="rounded-l-none"
|
||||||
:disabled="!canpublish"
|
:disabled="!canpublish"
|
||||||
icon="send"
|
:label="$t('mqtt.publish')"
|
||||||
:label="$t('mqtt_publish')"
|
|
||||||
@click.native="publish"
|
@click.native="publish"
|
||||||
/>
|
/>
|
||||||
</li>
|
|
||||||
</div>
|
</div>
|
||||||
</ul>
|
<div
|
||||||
<ul>
|
class="
|
||||||
<li>
|
border-t border-dividerLight
|
||||||
<label for="sub_topic">{{ $t("mqtt_topic") }}</label>
|
flex flex-col flex-1
|
||||||
|
mt-4
|
||||||
|
p-4
|
||||||
|
inline-flex
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<label for="sub_topic" class="font-semibold">{{
|
||||||
|
$t("mqtt.topic")
|
||||||
|
}}</label>
|
||||||
|
</div>
|
||||||
|
<div class="flex px-4">
|
||||||
<input
|
<input
|
||||||
id="sub_topic"
|
id="sub_topic"
|
||||||
v-model="sub_topic"
|
v-model="sub_topic"
|
||||||
type="text"
|
type="text"
|
||||||
|
:placeholder="$t('mqtt.topic_name')"
|
||||||
spellcheck="false"
|
spellcheck="false"
|
||||||
class="input md:rounded-bl-lg"
|
class="input !rounded-r-none"
|
||||||
/>
|
/>
|
||||||
</li>
|
<ButtonPrimary
|
||||||
<div>
|
|
||||||
<li>
|
|
||||||
<ButtonSecondary
|
|
||||||
id="subscribe"
|
id="subscribe"
|
||||||
name="get"
|
name="get"
|
||||||
:disabled="!cansubscribe"
|
:disabled="!cansubscribe"
|
||||||
class="
|
class="rounded-l-none"
|
||||||
button
|
|
||||||
rounded-b-lg
|
|
||||||
md:rounded-bl-none md:rounded-br-lg
|
|
||||||
"
|
|
||||||
:icon="subscriptionState ? 'sync_disabled' : 'sync'"
|
|
||||||
:label="
|
:label="
|
||||||
subscriptionState
|
subscriptionState ? $t('mqtt.unsubscribe') : $t('mqtt.subscribe')
|
||||||
? $t('mqtt_unsubscribe')
|
|
||||||
: $t('mqtt_subscribe')
|
|
||||||
"
|
"
|
||||||
reverse
|
reverse
|
||||||
@click.native="toggleSubscription"
|
@click.native="toggleSubscription"
|
||||||
/>
|
/>
|
||||||
</li>
|
|
||||||
</div>
|
</div>
|
||||||
</ul>
|
|
||||||
</AppSection>
|
</AppSection>
|
||||||
</Pane>
|
</Pane>
|
||||||
</Splitpanes>
|
</Splitpanes>
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import { defineComponent } from "@nuxtjs/composition-api"
|
||||||
import { Splitpanes, Pane } from "splitpanes"
|
import { Splitpanes, Pane } from "splitpanes"
|
||||||
import Paho from "paho-mqtt"
|
import Paho from "paho-mqtt"
|
||||||
import debounce from "~/helpers/utils/debounce"
|
import debounce from "~/helpers/utils/debounce"
|
||||||
import { logHoppRequestRunToAnalytics } from "~/helpers/fb/analytics"
|
import { logHoppRequestRunToAnalytics } from "~/helpers/fb/analytics"
|
||||||
|
import { useSetting } from "~/newstore/settings"
|
||||||
|
|
||||||
export default {
|
export default defineComponent({
|
||||||
components: { Splitpanes, Pane },
|
components: { Splitpanes, Pane },
|
||||||
|
setup() {
|
||||||
|
return {
|
||||||
|
RIGHT_SIDEBAR: useSetting("RIGHT_SIDEBAR"),
|
||||||
|
}
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
url: "wss://test.mosquitto.org:8081",
|
url: "wss://test.mosquitto.org:8081",
|
||||||
@@ -144,6 +154,7 @@ export default {
|
|||||||
sub_topic: "",
|
sub_topic: "",
|
||||||
msg: "",
|
msg: "",
|
||||||
connectionState: false,
|
connectionState: false,
|
||||||
|
connectingState: false,
|
||||||
log: null,
|
log: null,
|
||||||
manualDisconnect: false,
|
manualDisconnect: false,
|
||||||
subscriptionState: false,
|
subscriptionState: false,
|
||||||
@@ -182,6 +193,7 @@ export default {
|
|||||||
if (data.url === this.url) this.isUrlValid = data.result
|
if (data.url === this.url) this.isUrlValid = data.result
|
||||||
},
|
},
|
||||||
connect() {
|
connect() {
|
||||||
|
this.connectingState = true
|
||||||
this.log = [
|
this.log = [
|
||||||
{
|
{
|
||||||
payload: this.$t("connecting_to", { name: this.url }),
|
payload: this.$t("connecting_to", { name: this.url }),
|
||||||
@@ -209,6 +221,7 @@ export default {
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
onConnectionFailure() {
|
onConnectionFailure() {
|
||||||
|
this.connectingState = false
|
||||||
this.connectionState = false
|
this.connectionState = false
|
||||||
this.log.push({
|
this.log.push({
|
||||||
payload: this.$t("error_occurred"),
|
payload: this.$t("error_occurred"),
|
||||||
@@ -218,6 +231,7 @@ export default {
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
onConnectionSuccess() {
|
onConnectionSuccess() {
|
||||||
|
this.connectingState = false
|
||||||
this.connectionState = true
|
this.connectionState = true
|
||||||
this.log.push({
|
this.log.push({
|
||||||
payload: this.$t("connected_to", { name: this.url }),
|
payload: this.$t("connected_to", { name: this.url }),
|
||||||
@@ -255,6 +269,7 @@ export default {
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
onConnectionLost() {
|
onConnectionLost() {
|
||||||
|
this.connectingState = false
|
||||||
this.connectionState = false
|
this.connectionState = false
|
||||||
if (this.manualDisconnect) {
|
if (this.manualDisconnect) {
|
||||||
this.$toast.error(this.$t("disconnected"), {
|
this.$toast.error(this.$t("disconnected"), {
|
||||||
@@ -342,5 +357,5 @@ export default {
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,167 +1,173 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<Splitpanes :dbl-click-splitter="false" vertical>
|
||||||
<Splitpanes vertical :dbl-click-splitter="false">
|
<Pane class="hide-scrollbar !overflow-auto">
|
||||||
<Pane class="overflow-auto">
|
<Splitpanes :dbl-click-splitter="false" horizontal>
|
||||||
<Splitpanes horizontal :dbl-click-splitter="false">
|
<Pane class="hide-scrollbar !overflow-auto">
|
||||||
<Pane class="overflow-auto">
|
|
||||||
<AppSection label="request">
|
<AppSection label="request">
|
||||||
<ul>
|
<div class="bg-primary flex p-4 top-0 z-10 sticky">
|
||||||
<li>
|
<div class="flex-1 inline-flex">
|
||||||
<label for="socketio-url">{{ $t("url") }}</label>
|
|
||||||
<input
|
<input
|
||||||
id="socketio-url"
|
id="socketio-url"
|
||||||
v-model="url"
|
v-model="url"
|
||||||
type="url"
|
type="url"
|
||||||
spellcheck="false"
|
spellcheck="false"
|
||||||
:class="{ error: !urlValid }"
|
:class="{ error: !urlValid }"
|
||||||
class="input md:rounded-bl-lg"
|
class="
|
||||||
|
bg-primaryLight
|
||||||
|
border border-divider
|
||||||
|
rounded-l
|
||||||
|
flex
|
||||||
|
font-semibold font-mono
|
||||||
|
flex-1
|
||||||
|
text-secondaryDark
|
||||||
|
w-full
|
||||||
|
py-1
|
||||||
|
px-4
|
||||||
|
transition
|
||||||
|
truncate
|
||||||
|
focus:outline-none focus:border-accent
|
||||||
|
"
|
||||||
:placeholder="$t('url')"
|
:placeholder="$t('url')"
|
||||||
@keyup.enter="urlValid ? toggleConnection() : null"
|
@keyup.enter="urlValid ? toggleConnection() : null"
|
||||||
/>
|
/>
|
||||||
</li>
|
|
||||||
<div>
|
|
||||||
<li>
|
|
||||||
<label for="socketio-path">{{ $t("path") }}</label>
|
|
||||||
<input
|
<input
|
||||||
id="socketio-path"
|
id="socketio-path"
|
||||||
v-model="path"
|
v-model="path"
|
||||||
class="input"
|
class="
|
||||||
|
bg-primaryLight
|
||||||
|
border border-divider
|
||||||
|
flex
|
||||||
|
font-semibold font-mono
|
||||||
|
flex-1
|
||||||
|
text-secondaryDark
|
||||||
|
w-full
|
||||||
|
py-1
|
||||||
|
px-4
|
||||||
|
transition
|
||||||
|
truncate
|
||||||
|
focus:outline-none focus:border-accent
|
||||||
|
"
|
||||||
spellcheck="false"
|
spellcheck="false"
|
||||||
/>
|
/>
|
||||||
</li>
|
<ButtonPrimary
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<li>
|
|
||||||
<ButtonSecondary
|
|
||||||
id="connect"
|
id="connect"
|
||||||
:disabled="!urlValid"
|
:disabled="!urlValid"
|
||||||
name="connect"
|
name="connect"
|
||||||
class="
|
class="rounded-l-none w-28"
|
||||||
button
|
:label="!connectionState ? $t('connect') : $t('disconnect')"
|
||||||
rounded-b-lg
|
:loading="connectingState"
|
||||||
md:rounded-bl-none md:rounded-br-lg
|
|
||||||
"
|
|
||||||
:icon="!connectionState ? 'sync' : 'sync_disabled'"
|
|
||||||
:label="
|
|
||||||
!connectionState ? $t('connect') : $t('disconnect')
|
|
||||||
"
|
|
||||||
reverse
|
|
||||||
@click.native="toggleConnection"
|
@click.native="toggleConnection"
|
||||||
/>
|
/>
|
||||||
</li>
|
|
||||||
</div>
|
</div>
|
||||||
</ul>
|
</div>
|
||||||
</AppSection>
|
</AppSection>
|
||||||
</Pane>
|
</Pane>
|
||||||
<Pane class="overflow-auto">
|
<Pane class="hide-scrollbar !overflow-auto">
|
||||||
<AppSection label="response">
|
<AppSection label="response">
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
<RealtimeLog :title="$t('log')" :log="communication.log" />
|
<RealtimeLog :title="$t('log')" :log="communication.log" />
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</AppSection>
|
</AppSection>
|
||||||
</Pane>
|
</Pane>
|
||||||
</Splitpanes>
|
</Splitpanes>
|
||||||
</Pane>
|
</Pane>
|
||||||
<Pane max-size="35" min-size="20" class="overflow-auto">
|
<Pane
|
||||||
|
v-if="RIGHT_SIDEBAR"
|
||||||
|
max-size="35"
|
||||||
|
size="25"
|
||||||
|
min-size="20"
|
||||||
|
class="hide-scrollbar !overflow-auto"
|
||||||
|
>
|
||||||
<AppSection label="messages">
|
<AppSection label="messages">
|
||||||
<ul>
|
<div class="flex flex-col flex-1 p-4 inline-flex">
|
||||||
<li>
|
<label for="events" class="font-semibold">
|
||||||
<label for="event_name">{{ $t("event_name") }}</label>
|
{{ $t("events") }}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div class="flex px-4">
|
||||||
<input
|
<input
|
||||||
id="event_name"
|
id="event_name"
|
||||||
v-model="communication.eventName"
|
v-model="communication.eventName"
|
||||||
class="input"
|
class="input"
|
||||||
name="event_name"
|
name="event_name"
|
||||||
|
:placeholder="$t('event_name')"
|
||||||
type="text"
|
type="text"
|
||||||
:readonly="!connectionState"
|
:disabled="!connectionState"
|
||||||
/>
|
/>
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
<div class="flex flex-1">
|
|
||||||
<label>{{ $t("message") }}s</label>
|
|
||||||
</div>
|
</div>
|
||||||
</li>
|
<div class="bg-primary flex flex-1 p-4 items-center justify-between">
|
||||||
</ul>
|
<label class="font-semibold">{{ $t("communication") }}</label>
|
||||||
<ul
|
<div class="flex">
|
||||||
|
<ButtonSecondary
|
||||||
|
v-tippy="{ theme: 'tooltip' }"
|
||||||
|
:title="$t('add.new')"
|
||||||
|
icon="add"
|
||||||
|
@click.native="addCommunicationInput"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="flex flex-col space-y-2 px-4">
|
||||||
|
<div
|
||||||
v-for="(input, index) of communication.inputs"
|
v-for="(input, index) of communication.inputs"
|
||||||
:key="`input-${index}`"
|
:key="`input-${index}`"
|
||||||
:class="{ 'border-t': index == 0 }"
|
|
||||||
class="
|
|
||||||
border-b border-dashed
|
|
||||||
divide-y
|
|
||||||
md:divide-x
|
|
||||||
border-divider
|
|
||||||
divide-dashed divide-divider
|
|
||||||
md:divide-y-0
|
|
||||||
"
|
|
||||||
>
|
>
|
||||||
<li>
|
<div class="flex">
|
||||||
<input
|
<input
|
||||||
v-model="communication.inputs[index]"
|
v-model="communication.inputs[index]"
|
||||||
class="input"
|
class="input !rounded-r-none"
|
||||||
name="message"
|
name="message"
|
||||||
|
:placeholder="$t('count.message', { count: index + 1 })"
|
||||||
type="text"
|
type="text"
|
||||||
:readonly="!connectionState"
|
:disabled="!connectionState"
|
||||||
@keyup.enter="connectionState ? sendMessage() : null"
|
@keyup.enter="connectionState ? sendMessage() : null"
|
||||||
/>
|
/>
|
||||||
</li>
|
|
||||||
<div v-if="index + 1 !== communication.inputs.length">
|
|
||||||
<li>
|
|
||||||
<ButtonSecondary
|
<ButtonSecondary
|
||||||
|
v-if="index + 1 !== communication.inputs.length"
|
||||||
v-tippy="{ theme: 'tooltip' }"
|
v-tippy="{ theme: 'tooltip' }"
|
||||||
:title="$t('delete')"
|
:title="$t('delete')"
|
||||||
icon="delete"
|
icon="delete"
|
||||||
|
class="rounded-l-none"
|
||||||
|
color="red"
|
||||||
|
outline
|
||||||
@click.native="removeCommunicationInput({ index })"
|
@click.native="removeCommunicationInput({ index })"
|
||||||
/>
|
/>
|
||||||
</li>
|
<ButtonPrimary
|
||||||
</div>
|
v-if="index + 1 === communication.inputs.length"
|
||||||
<div v-if="index + 1 === communication.inputs.length">
|
|
||||||
<li>
|
|
||||||
<ButtonSecondary
|
|
||||||
id="send"
|
id="send"
|
||||||
class="button"
|
|
||||||
name="send"
|
name="send"
|
||||||
:disabled="!connectionState"
|
:disabled="!connectionState"
|
||||||
icon="send"
|
class="rounded-l-none"
|
||||||
:label="$t('send')"
|
:label="$t('send')"
|
||||||
@click.native="sendMessage"
|
@click.native="sendMessage"
|
||||||
/>
|
/>
|
||||||
</li>
|
|
||||||
</div>
|
</div>
|
||||||
</ul>
|
</div>
|
||||||
<ul>
|
</div>
|
||||||
<li>
|
|
||||||
<ButtonSecondary
|
|
||||||
icon="add"
|
|
||||||
:label="$t('add_new')"
|
|
||||||
@click.native="addCommunicationInput"
|
|
||||||
/>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</AppSection>
|
</AppSection>
|
||||||
</Pane>
|
</Pane>
|
||||||
</Splitpanes>
|
</Splitpanes>
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import { defineComponent } from "@nuxtjs/composition-api"
|
||||||
import { Splitpanes, Pane } from "splitpanes"
|
import { Splitpanes, Pane } from "splitpanes"
|
||||||
import { io as Client } from "socket.io-client"
|
import { io as Client } from "socket.io-client"
|
||||||
import wildcard from "socketio-wildcard"
|
import wildcard from "socketio-wildcard"
|
||||||
import debounce from "~/helpers/utils/debounce"
|
import debounce from "~/helpers/utils/debounce"
|
||||||
import { logHoppRequestRunToAnalytics } from "~/helpers/fb/analytics"
|
import { logHoppRequestRunToAnalytics } from "~/helpers/fb/analytics"
|
||||||
|
import { useSetting } from "~/newstore/settings"
|
||||||
|
|
||||||
export default {
|
export default defineComponent({
|
||||||
components: { Splitpanes, Pane },
|
components: { Splitpanes, Pane },
|
||||||
|
setup() {
|
||||||
|
return {
|
||||||
|
RIGHT_SIDEBAR: useSetting("RIGHT_SIDEBAR"),
|
||||||
|
}
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
url: "wss://main-daxrc78qyb411dls-gtw.qovery.io",
|
url: "wss://main-daxrc78qyb411dls-gtw.qovery.io",
|
||||||
path: "/socket.io",
|
path: "/socket.io",
|
||||||
isUrlValid: true,
|
isUrlValid: true,
|
||||||
|
connectingState: false,
|
||||||
connectionState: false,
|
connectionState: false,
|
||||||
io: null,
|
io: null,
|
||||||
communication: {
|
communication: {
|
||||||
@@ -210,6 +216,7 @@ export default {
|
|||||||
else return this.disconnect()
|
else return this.disconnect()
|
||||||
},
|
},
|
||||||
connect() {
|
connect() {
|
||||||
|
this.connectingState = true
|
||||||
this.communication.log = [
|
this.communication.log = [
|
||||||
{
|
{
|
||||||
payload: this.$t("connecting_to", { name: this.url }),
|
payload: this.$t("connecting_to", { name: this.url }),
|
||||||
@@ -228,6 +235,7 @@ export default {
|
|||||||
// Add ability to listen to all events
|
// Add ability to listen to all events
|
||||||
wildcard(Client.Manager)(this.io)
|
wildcard(Client.Manager)(this.io)
|
||||||
this.io.on("connect", () => {
|
this.io.on("connect", () => {
|
||||||
|
this.connectingState = false
|
||||||
this.connectionState = true
|
this.connectionState = true
|
||||||
this.communication.log = [
|
this.communication.log = [
|
||||||
{
|
{
|
||||||
@@ -259,6 +267,7 @@ export default {
|
|||||||
this.handleError()
|
this.handleError()
|
||||||
})
|
})
|
||||||
this.io.on("disconnect", () => {
|
this.io.on("disconnect", () => {
|
||||||
|
this.connectingState = false
|
||||||
this.connectionState = false
|
this.connectionState = false
|
||||||
this.communication.log.push({
|
this.communication.log.push({
|
||||||
payload: this.$t("disconnected_from", { name: this.url }),
|
payload: this.$t("disconnected_from", { name: this.url }),
|
||||||
@@ -286,6 +295,7 @@ export default {
|
|||||||
},
|
},
|
||||||
handleError(error) {
|
handleError(error) {
|
||||||
this.disconnect()
|
this.disconnect()
|
||||||
|
this.connectingState = false
|
||||||
this.connectionState = false
|
this.connectionState = false
|
||||||
this.communication.log.push({
|
this.communication.log.push({
|
||||||
payload: this.$t("error_occurred"),
|
payload: this.$t("error_occurred"),
|
||||||
@@ -332,5 +342,5 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,43 +1,44 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<Splitpanes :dbl-click-splitter="false" horizontal>
|
||||||
<Splitpanes horizontal :dbl-click-splitter="false">
|
<Pane class="hide-scrollbar !overflow-auto">
|
||||||
<Pane class="overflow-auto">
|
|
||||||
<AppSection label="request">
|
<AppSection label="request">
|
||||||
<ul>
|
<div class="bg-primary flex p-4 top-0 z-10 sticky">
|
||||||
<li>
|
<div class="flex-1 inline-flex">
|
||||||
<label for="server">{{ $t("server") }}</label>
|
|
||||||
<input
|
<input
|
||||||
id="server"
|
id="server"
|
||||||
v-model="server"
|
v-model="server"
|
||||||
type="url"
|
type="url"
|
||||||
:class="{ error: !serverValid }"
|
:class="{ error: !serverValid }"
|
||||||
class="input md:rounded-bl-lg"
|
class="
|
||||||
|
bg-primaryLight
|
||||||
|
border border-divider
|
||||||
|
rounded-l
|
||||||
|
font-semibold font-mono
|
||||||
|
text-secondaryDark
|
||||||
|
w-full
|
||||||
|
py-1
|
||||||
|
px-4
|
||||||
|
transition
|
||||||
|
truncate
|
||||||
|
focus:outline-none focus:border-accent
|
||||||
|
"
|
||||||
:placeholder="$t('url')"
|
:placeholder="$t('url')"
|
||||||
@keyup.enter="serverValid ? toggleSSEConnection() : null"
|
@keyup.enter="serverValid ? toggleSSEConnection() : null"
|
||||||
/>
|
/>
|
||||||
</li>
|
<ButtonPrimary
|
||||||
<div>
|
|
||||||
<li>
|
|
||||||
<ButtonSecondary
|
|
||||||
id="start"
|
id="start"
|
||||||
:disabled="!serverValid"
|
:disabled="!serverValid"
|
||||||
name="start"
|
name="start"
|
||||||
class="
|
class="rounded-l-none w-22"
|
||||||
button
|
|
||||||
rounded-b-lg
|
|
||||||
md:rounded-bl-none md:rounded-br-lg
|
|
||||||
"
|
|
||||||
:icon="!connectionSSEState ? 'sync' : 'sync_disabled'"
|
|
||||||
:label="!connectionSSEState ? $t('start') : $t('stop')"
|
:label="!connectionSSEState ? $t('start') : $t('stop')"
|
||||||
reverse
|
:loading="connectingState"
|
||||||
@click.native="toggleSSEConnection"
|
@click.native="toggleSSEConnection"
|
||||||
/>
|
/>
|
||||||
</li>
|
|
||||||
</div>
|
</div>
|
||||||
</ul>
|
</div>
|
||||||
</AppSection>
|
</AppSection>
|
||||||
</Pane>
|
</Pane>
|
||||||
<Pane class="overflow-auto">
|
<Pane class="hide-scrollbar !overflow-auto">
|
||||||
<AppSection label="response">
|
<AppSection label="response">
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
@@ -48,7 +49,6 @@
|
|||||||
</AppSection>
|
</AppSection>
|
||||||
</Pane>
|
</Pane>
|
||||||
</Splitpanes>
|
</Splitpanes>
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
@@ -61,6 +61,7 @@ export default {
|
|||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
connectionSSEState: false,
|
connectionSSEState: false,
|
||||||
|
connectingState: false,
|
||||||
server: "https://express-eventsource.herokuapp.com/events",
|
server: "https://express-eventsource.herokuapp.com/events",
|
||||||
isUrlValid: true,
|
isUrlValid: true,
|
||||||
sse: null,
|
sse: null,
|
||||||
@@ -103,6 +104,7 @@ export default {
|
|||||||
else return this.stop()
|
else return this.stop()
|
||||||
},
|
},
|
||||||
start() {
|
start() {
|
||||||
|
this.connectingState = true
|
||||||
this.events.log = [
|
this.events.log = [
|
||||||
{
|
{
|
||||||
payload: this.$t("connecting_to", { name: this.server }),
|
payload: this.$t("connecting_to", { name: this.server }),
|
||||||
@@ -114,6 +116,7 @@ export default {
|
|||||||
try {
|
try {
|
||||||
this.sse = new EventSource(this.server)
|
this.sse = new EventSource(this.server)
|
||||||
this.sse.onopen = () => {
|
this.sse.onopen = () => {
|
||||||
|
this.connectingState = false
|
||||||
this.connectionSSEState = true
|
this.connectionSSEState = true
|
||||||
this.events.log = [
|
this.events.log = [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,183 +1,217 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<Splitpanes :dbl-click-splitter="false" vertical>
|
||||||
<Splitpanes vertical :dbl-click-splitter="false">
|
<Pane class="hide-scrollbar !overflow-auto">
|
||||||
<Pane class="overflow-auto">
|
<Splitpanes :dbl-click-splitter="false" horizontal>
|
||||||
<Splitpanes horizontal :dbl-click-splitter="false">
|
<Pane class="hide-scrollbar !overflow-auto">
|
||||||
<Pane class="overflow-auto">
|
|
||||||
<AppSection label="request">
|
<AppSection label="request">
|
||||||
<ul>
|
<div class="bg-primary flex p-4 top-0 z-10 sticky">
|
||||||
<li>
|
<div class="flex-1 inline-flex">
|
||||||
<label for="websocket-url">{{ $t("url") }}</label>
|
|
||||||
<input
|
<input
|
||||||
id="websocket-url"
|
id="websocket-url"
|
||||||
v-model="url"
|
v-model="url"
|
||||||
class="input"
|
class="
|
||||||
|
bg-primaryLight
|
||||||
|
border border-divider
|
||||||
|
rounded-l
|
||||||
|
font-semibold font-mono
|
||||||
|
text-secondaryDark
|
||||||
|
w-full
|
||||||
|
py-1
|
||||||
|
px-4
|
||||||
|
transition
|
||||||
|
truncate
|
||||||
|
focus:outline-none focus:border-accent
|
||||||
|
"
|
||||||
type="url"
|
type="url"
|
||||||
spellcheck="false"
|
spellcheck="false"
|
||||||
:class="{ error: !urlValid }"
|
:class="{ error: !urlValid }"
|
||||||
:placeholder="$t('url')"
|
:placeholder="$t('url')"
|
||||||
@keyup.enter="urlValid ? toggleConnection() : null"
|
@keyup.enter="urlValid ? toggleConnection() : null"
|
||||||
/>
|
/>
|
||||||
</li>
|
<ButtonPrimary
|
||||||
<div>
|
|
||||||
<li>
|
|
||||||
<ButtonSecondary
|
|
||||||
id="connect"
|
id="connect"
|
||||||
:disabled="!urlValid"
|
:disabled="!urlValid"
|
||||||
class="button"
|
class="rounded-l-none w-28"
|
||||||
name="connect"
|
name="connect"
|
||||||
:icon="!connectionState ? 'sync' : 'sync_disabled'"
|
:label="!connectionState ? $t('connect') : $t('disconnect')"
|
||||||
:label="
|
:loading="connectingState"
|
||||||
!connectionState ? $t('connect') : $t('disconnect')
|
|
||||||
"
|
|
||||||
reverse
|
|
||||||
@click.native="toggleConnection"
|
@click.native="toggleConnection"
|
||||||
/>
|
/>
|
||||||
</li>
|
|
||||||
</div>
|
</div>
|
||||||
</ul>
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
<div class="flex flex-1">
|
|
||||||
<label>{{ $t("protocols") }}</label>
|
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</AppSection>
|
||||||
</ul>
|
<div
|
||||||
<ul
|
|
||||||
v-for="(protocol, index) of protocols"
|
|
||||||
:key="`protocol-${index}`"
|
|
||||||
:class="{ 'border-t': index == 0 }"
|
|
||||||
class="
|
class="
|
||||||
border-b border-dashed
|
bg-primary
|
||||||
divide-y
|
border-b border-dividerLight
|
||||||
md:divide-x
|
flex flex-1
|
||||||
border-divider
|
pl-4
|
||||||
divide-dashed divide-divider
|
top-16
|
||||||
md:divide-y-0
|
z-10
|
||||||
|
sticky
|
||||||
|
items-center
|
||||||
|
justify-between
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
<li>
|
<label class="font-semibold">
|
||||||
|
{{ $t("websocket.protocols") }}
|
||||||
|
</label>
|
||||||
|
<div class="flex">
|
||||||
|
<ButtonSecondary
|
||||||
|
v-tippy="{ theme: 'tooltip' }"
|
||||||
|
:title="$t('clear_all')"
|
||||||
|
icon="clear_all"
|
||||||
|
@click.native="clearContent"
|
||||||
|
/>
|
||||||
|
<ButtonSecondary
|
||||||
|
v-tippy="{ theme: 'tooltip' }"
|
||||||
|
:title="$t('add.new')"
|
||||||
|
icon="add"
|
||||||
|
@click.native="addProtocol"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
v-for="(protocol, index) of protocols"
|
||||||
|
:key="`protocol-${index}`"
|
||||||
|
class="
|
||||||
|
divide-x divide-dividerLight
|
||||||
|
border-b border-dividerLight
|
||||||
|
flex
|
||||||
|
"
|
||||||
|
:class="{ 'border-t': index == 0 }"
|
||||||
|
>
|
||||||
<input
|
<input
|
||||||
v-model="protocol.value"
|
v-model="protocol.value"
|
||||||
class="input"
|
class="
|
||||||
:placeholder="$t('protocol_count', { count: index + 1 })"
|
bg-primaryLight
|
||||||
|
flex
|
||||||
|
font-semibold font-mono
|
||||||
|
flex-1
|
||||||
|
py-2
|
||||||
|
px-4
|
||||||
|
focus:outline-none
|
||||||
|
"
|
||||||
|
:placeholder="$t('count.protocol', { count: index + 1 })"
|
||||||
name="message"
|
name="message"
|
||||||
type="text"
|
type="text"
|
||||||
/>
|
/>
|
||||||
</li>
|
|
||||||
<div>
|
<div>
|
||||||
<li>
|
|
||||||
<ButtonSecondary
|
<ButtonSecondary
|
||||||
v-tippy="{ theme: 'tooltip' }"
|
v-tippy="{ theme: 'tooltip' }"
|
||||||
:title="
|
:title="
|
||||||
protocol.hasOwnProperty('active')
|
protocol.hasOwnProperty('active')
|
||||||
? protocol.active
|
? protocol.active
|
||||||
? $t('turn_off')
|
? $t('action.turn_off')
|
||||||
: $t('turn_on')
|
: $t('action.turn_on')
|
||||||
: $t('turn_off')
|
: $t('action.turn_off')
|
||||||
"
|
"
|
||||||
|
:icon="
|
||||||
|
protocol.hasOwnProperty('active')
|
||||||
|
? protocol.active
|
||||||
|
? 'check_box'
|
||||||
|
: 'check_box_outline_blank'
|
||||||
|
: 'check_box'
|
||||||
|
"
|
||||||
|
color="green"
|
||||||
@click.native="
|
@click.native="
|
||||||
protocol.active = protocol.hasOwnProperty('active')
|
protocol.active = protocol.hasOwnProperty('active')
|
||||||
? !protocol.active
|
? !protocol.active
|
||||||
: false
|
: false
|
||||||
"
|
"
|
||||||
/>
|
/>
|
||||||
<i class="material-icons">
|
|
||||||
{{
|
|
||||||
protocol.hasOwnProperty("active")
|
|
||||||
? protocol.active
|
|
||||||
? "check_box"
|
|
||||||
: "check_box_outline_blank"
|
|
||||||
: "check_box"
|
|
||||||
}}
|
|
||||||
</i>
|
|
||||||
</li>
|
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<li>
|
|
||||||
<ButtonSecondary
|
<ButtonSecondary
|
||||||
v-tippy="{ theme: 'tooltip' }"
|
v-tippy="{ theme: 'tooltip' }"
|
||||||
:title="$t('delete')"
|
:title="$t('delete')"
|
||||||
icon="delete"
|
icon="delete"
|
||||||
|
color="red"
|
||||||
@click.native="deleteProtocol({ index })"
|
@click.native="deleteProtocol({ index })"
|
||||||
/>
|
/>
|
||||||
</li>
|
|
||||||
</div>
|
</div>
|
||||||
</ul>
|
</div>
|
||||||
<ul>
|
<div
|
||||||
<li>
|
v-if="protocols.length === 0"
|
||||||
<ButtonSecondary
|
class="
|
||||||
icon="add"
|
flex flex-col
|
||||||
:label="$t('add_new')"
|
text-secondaryLight
|
||||||
@click.native="addProtocol"
|
p-4
|
||||||
/>
|
items-center
|
||||||
</li>
|
justify-center
|
||||||
</ul>
|
"
|
||||||
</AppSection>
|
>
|
||||||
|
<i class="opacity-75 pb-2 material-icons">topic</i>
|
||||||
|
<span class="text-center">
|
||||||
|
{{ $t("empty.protocols") }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
</Pane>
|
</Pane>
|
||||||
<Pane class="overflow-auto">
|
<Pane class="hide-scrollbar !overflow-auto">
|
||||||
<AppSection label="response">
|
<AppSection label="response">
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
<RealtimeLog :title="$t('log')" :log="communication.log" />
|
<RealtimeLog :title="$t('log')" :log="communication.log" />
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</AppSection>
|
</AppSection>
|
||||||
</Pane>
|
</Pane>
|
||||||
</Splitpanes>
|
</Splitpanes>
|
||||||
</Pane>
|
</Pane>
|
||||||
<Pane max-size="35" min-size="20" class="overflow-auto">
|
<Pane
|
||||||
|
v-if="RIGHT_SIDEBAR"
|
||||||
|
max-size="35"
|
||||||
|
size="25"
|
||||||
|
min-size="20"
|
||||||
|
class="hide-scrollbar !overflow-auto"
|
||||||
|
>
|
||||||
<AppSection label="messages">
|
<AppSection label="messages">
|
||||||
<ul>
|
<div class="flex flex-col flex-1 p-4 inline-flex">
|
||||||
<li>
|
<label for="websocket-message" class="font-semibold">
|
||||||
<label for="websocket-message">{{ $t("message") }}</label>
|
{{ $t("communication") }}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div class="flex px-4">
|
||||||
<input
|
<input
|
||||||
id="websocket-message"
|
id="websocket-message"
|
||||||
v-model="communication.input"
|
v-model="communication.input"
|
||||||
name="message"
|
name="message"
|
||||||
type="text"
|
type="text"
|
||||||
:readonly="!connectionState"
|
:disabled="!connectionState"
|
||||||
class="input md:rounded-bl-lg"
|
:placeholder="$t('message')"
|
||||||
|
class="input !rounded-r-none"
|
||||||
@keyup.enter="connectionState ? sendMessage() : null"
|
@keyup.enter="connectionState ? sendMessage() : null"
|
||||||
@keyup.up="connectionState ? walkHistory('up') : null"
|
@keyup.up="connectionState ? walkHistory('up') : null"
|
||||||
@keyup.down="connectionState ? walkHistory('down') : null"
|
@keyup.down="connectionState ? walkHistory('down') : null"
|
||||||
/>
|
/>
|
||||||
</li>
|
<ButtonPrimary
|
||||||
<div>
|
|
||||||
<li>
|
|
||||||
<ButtonSecondary
|
|
||||||
id="send"
|
id="send"
|
||||||
name="send"
|
name="send"
|
||||||
:disabled="!connectionState"
|
:disabled="!connectionState"
|
||||||
class="
|
class="rounded-l-none"
|
||||||
button
|
|
||||||
rounded-b-lg
|
|
||||||
md:rounded-bl-none md:rounded-br-lg
|
|
||||||
"
|
|
||||||
icon="send"
|
|
||||||
:label="$t('send')"
|
:label="$t('send')"
|
||||||
@click.native="sendMessage"
|
@click.native="sendMessage"
|
||||||
/>
|
/>
|
||||||
</li>
|
|
||||||
</div>
|
</div>
|
||||||
</ul>
|
|
||||||
</AppSection>
|
</AppSection>
|
||||||
</Pane>
|
</Pane>
|
||||||
</Splitpanes>
|
</Splitpanes>
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import { defineComponent } from "@nuxtjs/composition-api"
|
||||||
import { Splitpanes, Pane } from "splitpanes"
|
import { Splitpanes, Pane } from "splitpanes"
|
||||||
import { logHoppRequestRunToAnalytics } from "~/helpers/fb/analytics"
|
import { logHoppRequestRunToAnalytics } from "~/helpers/fb/analytics"
|
||||||
import debounce from "~/helpers/utils/debounce"
|
import debounce from "~/helpers/utils/debounce"
|
||||||
import "splitpanes/dist/splitpanes.css"
|
import "splitpanes/dist/splitpanes.css"
|
||||||
|
import { useSetting } from "~/newstore/settings"
|
||||||
export default {
|
export default defineComponent({
|
||||||
components: { Splitpanes, Pane },
|
components: { Splitpanes, Pane },
|
||||||
|
setup() {
|
||||||
|
return {
|
||||||
|
RIGHT_SIDEBAR: useSetting("RIGHT_SIDEBAR"),
|
||||||
|
}
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
connectionState: false,
|
connectionState: false,
|
||||||
|
connectingState: false,
|
||||||
url: "wss://echo.websocket.org",
|
url: "wss://echo.websocket.org",
|
||||||
isUrlValid: true,
|
isUrlValid: true,
|
||||||
socket: null,
|
socket: null,
|
||||||
@@ -222,6 +256,9 @@ export default {
|
|||||||
this.worker.terminate()
|
this.worker.terminate()
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
clearContent() {
|
||||||
|
this.protocols = []
|
||||||
|
},
|
||||||
debouncer: debounce(function () {
|
debouncer: debounce(function () {
|
||||||
this.worker.postMessage({ type: "ws", url: this.url })
|
this.worker.postMessage({ type: "ws", url: this.url })
|
||||||
}, 1000),
|
}, 1000),
|
||||||
@@ -243,8 +280,10 @@ export default {
|
|||||||
},
|
},
|
||||||
]
|
]
|
||||||
try {
|
try {
|
||||||
|
this.connectingState = true
|
||||||
this.socket = new WebSocket(this.url, this.activeProtocols)
|
this.socket = new WebSocket(this.url, this.activeProtocols)
|
||||||
this.socket.onopen = () => {
|
this.socket.onopen = () => {
|
||||||
|
this.connectingState = false
|
||||||
this.connectionState = true
|
this.connectionState = true
|
||||||
this.communication.log = [
|
this.communication.log = [
|
||||||
{
|
{
|
||||||
@@ -294,6 +333,8 @@ export default {
|
|||||||
disconnect() {
|
disconnect() {
|
||||||
if (this.socket) {
|
if (this.socket) {
|
||||||
this.socket.close()
|
this.socket.close()
|
||||||
|
this.connectionState = false
|
||||||
|
this.connectingState = false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
handleError(error) {
|
handleError(error) {
|
||||||
@@ -378,5 +419,5 @@ export default {
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,21 +1,22 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="flex">
|
<div class="flex">
|
||||||
<!-- text-blue-400 -->
|
<!-- text-green-500 -->
|
||||||
<!-- text-green-400 -->
|
<!-- text-teal-500 -->
|
||||||
<!-- text-teal-400 -->
|
<!-- text-blue-500 -->
|
||||||
<!-- text-indigo-400 -->
|
<!-- text-indigo-500 -->
|
||||||
<!-- text-purple-400 -->
|
<!-- text-purple-500 -->
|
||||||
<!-- text-orange-400 -->
|
<!-- text-yellow-500 -->
|
||||||
<!-- text-pink-400 -->
|
<!-- text-orange-500 -->
|
||||||
<!-- text-red-400 -->
|
<!-- text-red-500 -->
|
||||||
<!-- text-yellow-400 -->
|
<!-- text-pink-500 -->
|
||||||
<ButtonSecondary
|
<ButtonSecondary
|
||||||
v-for="(color, index) of accentColors"
|
v-for="(color, index) of accentColors"
|
||||||
:key="`color-${index}`"
|
:key="`color-${index}`"
|
||||||
v-tippy="{ theme: 'tooltip' }"
|
v-tippy="{ theme: 'tooltip' }"
|
||||||
:title="`${color.charAt(0).toUpperCase()}${color.slice(1)}`"
|
:title="`${color.charAt(0).toUpperCase()}${color.slice(1)}`"
|
||||||
:class="[`text-${color}-400`, { 'bg-primary': color === active }]"
|
:class="[{ 'bg-primaryLight': color === active }]"
|
||||||
icon="lens"
|
icon="lens"
|
||||||
|
:color="color"
|
||||||
@click.native="setActiveColor(color)"
|
@click.native="setActiveColor(color)"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -2,18 +2,19 @@
|
|||||||
<div class="show-if-initialized" :class="{ initialized }">
|
<div class="show-if-initialized" :class="{ initialized }">
|
||||||
<pre ref="editor" :class="styles"></pre>
|
<pre ref="editor" :class="styles"></pre>
|
||||||
<div
|
<div
|
||||||
v-if="lang == 'json'"
|
v-if="provideJSONOutline"
|
||||||
class="
|
class="
|
||||||
sticky
|
|
||||||
bottom-0
|
|
||||||
z-10
|
|
||||||
flex flex-nowrap flex-1
|
|
||||||
overflow-auto
|
|
||||||
font-mono
|
|
||||||
shadow-lg
|
|
||||||
px-4
|
|
||||||
bg-primaryLight
|
bg-primaryLight
|
||||||
border-t border-divider
|
border-t border-divider
|
||||||
|
flex flex-nowrap
|
||||||
|
font-mono
|
||||||
|
flex-1
|
||||||
|
py-1
|
||||||
|
px-4
|
||||||
|
bottom-0
|
||||||
|
z-10
|
||||||
|
sticky
|
||||||
|
overflow-auto
|
||||||
hide-scrollbar
|
hide-scrollbar
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
@@ -21,20 +22,19 @@
|
|||||||
v-for="(p, index) in currentPath"
|
v-for="(p, index) in currentPath"
|
||||||
:key="`p-${index}`"
|
:key="`p-${index}`"
|
||||||
class="
|
class="
|
||||||
inline-flex
|
|
||||||
items-center
|
|
||||||
flex-grow-0 flex-shrink-0
|
|
||||||
text-secondaryLight
|
|
||||||
hover:text-secondary
|
|
||||||
cursor-pointer
|
cursor-pointer
|
||||||
font-semibold
|
font-semibold
|
||||||
text-xs
|
flex-grow-0 flex-shrink-0
|
||||||
|
text-secondaryLight
|
||||||
|
inline-flex
|
||||||
|
items-center
|
||||||
|
hover:text-secondary
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
<span @click="onBlockClick(index)">
|
<span @click="onBlockClick(index)">
|
||||||
{{ p }}
|
{{ p }}
|
||||||
</span>
|
</span>
|
||||||
<i v-if="index + 1 !== currentPath.length" class="material-icons mx-2">
|
<i v-if="index + 1 !== currentPath.length" class="mx-2 material-icons">
|
||||||
chevron_right
|
chevron_right
|
||||||
</i>
|
</i>
|
||||||
<tippy
|
<tippy
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
color
|
color
|
||||||
? `text-${color}-500 hover:text-${color}-600 focus:text-${color}-600`
|
? `text-${color}-500 hover:text-${color}-600 focus:text-${color}-600`
|
||||||
: 'hover:text-secondaryDark focus:text-secondaryDark',
|
: 'hover:text-secondaryDark focus:text-secondaryDark',
|
||||||
{ 'opacity-50 cursor-not-allowed': disabled },
|
{ 'opacity-75 cursor-not-allowed': disabled },
|
||||||
{ 'flex-row-reverse': reverse },
|
{ 'flex-row-reverse': reverse },
|
||||||
]"
|
]"
|
||||||
:disabled="disabled"
|
:disabled="disabled"
|
||||||
|
|||||||
@@ -3,15 +3,6 @@
|
|||||||
<input
|
<input
|
||||||
ref="acInput"
|
ref="acInput"
|
||||||
v-model="text"
|
v-model="text"
|
||||||
class="
|
|
||||||
px-4
|
|
||||||
py-3
|
|
||||||
text-xs
|
|
||||||
flex flex-1
|
|
||||||
font-semibold
|
|
||||||
bg-primaryLight
|
|
||||||
focus:outline-none
|
|
||||||
"
|
|
||||||
type="text"
|
type="text"
|
||||||
:placeholder="placeholder"
|
:placeholder="placeholder"
|
||||||
:spellcheck="spellcheck"
|
:spellcheck="spellcheck"
|
||||||
@@ -197,7 +188,7 @@ export default {
|
|||||||
.autocomplete-wrapper {
|
.autocomplete-wrapper {
|
||||||
@apply relative;
|
@apply relative;
|
||||||
@apply flex;
|
@apply flex;
|
||||||
@apply flex-1;
|
@apply w-full;
|
||||||
|
|
||||||
input:focus + ul.suggestions,
|
input:focus + ul.suggestions,
|
||||||
ul.suggestions:hover {
|
ul.suggestions:hover {
|
||||||
@@ -213,15 +204,15 @@ export default {
|
|||||||
@apply z-50;
|
@apply z-50;
|
||||||
@apply shadow-lg;
|
@apply shadow-lg;
|
||||||
|
|
||||||
top: calc(100% - 8px);
|
top: calc(100% - 4px);
|
||||||
border-radius: 0 0 8px 8px;
|
border-radius: 0 0 8px 8px;
|
||||||
|
|
||||||
li {
|
li {
|
||||||
@apply w-full;
|
@apply w-full;
|
||||||
@apply block;
|
@apply block;
|
||||||
@apply py-2 px-4;
|
@apply py-2 px-4;
|
||||||
@apply text-xs;
|
@apply text-secondaryLight;
|
||||||
@apply font-mono;
|
@apply font-semibold font-mono;
|
||||||
|
|
||||||
&:last-child {
|
&:last-child {
|
||||||
border-radius: 0 0 8px 8px;
|
border-radius: 0 0 8px 8px;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<span>
|
<span class="inline-flex">
|
||||||
<tippy
|
<tippy
|
||||||
ref="language"
|
ref="language"
|
||||||
interactive
|
interactive
|
||||||
@@ -10,23 +10,26 @@
|
|||||||
:animate-fill="false"
|
:animate-fill="false"
|
||||||
>
|
>
|
||||||
<template #trigger>
|
<template #trigger>
|
||||||
<TabPrimary
|
<ButtonSecondary
|
||||||
v-tippy="{ theme: 'tooltip' }"
|
v-tippy="{ theme: 'tooltip' }"
|
||||||
:title="$t('choose_language')"
|
:title="$t('choose_language')"
|
||||||
|
class="font-medium focus:outline-none"
|
||||||
|
outline
|
||||||
:label="`${
|
:label="`${
|
||||||
$i18n.locales.find(({ code }) => code == $i18n.locale).country
|
$i18n.locales.find(({ code }) => code == $i18n.locale).name
|
||||||
} ${$i18n.locales.find(({ code }) => code == $i18n.locale).name}`"
|
}`"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
<SmartItem
|
<nuxt-link
|
||||||
v-for="(locale, index) in $i18n.locales.filter(
|
v-for="(locale, index) in $i18n.locales.filter(
|
||||||
({ code }) => code !== $i18n.locale
|
({ code }) => code !== $i18n.locale
|
||||||
)"
|
)"
|
||||||
:key="`locale-${index}`"
|
:key="`locale-${index}`"
|
||||||
:to="switchLocalePath(locale.code).toString()"
|
:to="switchLocalePath(locale.code)"
|
||||||
:label="`${locale.country} ${locale.name}`"
|
@click="$refs.language.tippy().hide()"
|
||||||
@click.native="$refs.language.tippy().hide()"
|
>
|
||||||
/>
|
<SmartItem :label="locale.name" />
|
||||||
|
</nuxt-link>
|
||||||
</tippy>
|
</tippy>
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -5,10 +5,9 @@
|
|||||||
:key="`color-${index}`"
|
:key="`color-${index}`"
|
||||||
v-tippy="{ theme: 'tooltip' }"
|
v-tippy="{ theme: 'tooltip' }"
|
||||||
:title="`${color.charAt(0).toUpperCase()}${color.slice(1)}`"
|
:title="`${color.charAt(0).toUpperCase()}${color.slice(1)}`"
|
||||||
:class="[
|
:class="{
|
||||||
{ 'bg-primary': color === activeColor },
|
'bg-primaryLight !text-accent hover:text-accent': color === active,
|
||||||
{ 'text-accent hover:text-accent': color === activeColor },
|
}"
|
||||||
]"
|
|
||||||
:icon="getIcon(color)"
|
:icon="getIcon(color)"
|
||||||
@click.native="setBGMode(color)"
|
@click.native="setBGMode(color)"
|
||||||
/>
|
/>
|
||||||
@@ -32,7 +31,7 @@ export default Vue.extend({
|
|||||||
},
|
},
|
||||||
subscriptions() {
|
subscriptions() {
|
||||||
return {
|
return {
|
||||||
activeColor: getSettingSubject("BG_COLOR"),
|
active: getSettingSubject("BG_COLOR"),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
|||||||
@@ -7,8 +7,8 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template #body>
|
<template #body>
|
||||||
<div class="px-2 flex flex-col">
|
<div class="flex flex-col px-2">
|
||||||
<label class="font-semibold text-xs">
|
<label class="font-semibold">
|
||||||
{{ title }}
|
{{ title }}
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -14,12 +14,12 @@
|
|||||||
@apply inline-flex;
|
@apply inline-flex;
|
||||||
@apply items-center;
|
@apply items-center;
|
||||||
@apply justify-center;
|
@apply justify-center;
|
||||||
@apply rounded-lg;
|
@apply rounded;
|
||||||
@apply m-1;
|
@apply m-1;
|
||||||
@apply pl-4;
|
@apply pl-4;
|
||||||
@apply bg-primaryDark;
|
@apply bg-primaryDark;
|
||||||
@apply text-secondary;
|
@apply text-secondary;
|
||||||
@apply font-mono;
|
@apply font-mono font-semibold;
|
||||||
@apply border border-divider;
|
@apply border border-divider;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,14 +5,32 @@
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="url-field-container">
|
<div class="url-field-container">
|
||||||
<div ref="editor" class="url-field" contenteditable="true"></div>
|
<div
|
||||||
|
ref="editor"
|
||||||
|
:placeholder="placeholder"
|
||||||
|
class="url-field"
|
||||||
|
:class="styles"
|
||||||
|
contenteditable="true"
|
||||||
|
@keydown.enter.prevent="$emit('enter', $event)"
|
||||||
|
@change="$emit('change', $event)"
|
||||||
|
@keyup="$emit('keyup', $event)"
|
||||||
|
@click="$emit('click', $event)"
|
||||||
|
@keydown="$emit('keydown', $event)"
|
||||||
|
></div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import { defineComponent } from "@nuxtjs/composition-api"
|
||||||
import IntervalTree from "node-interval-tree"
|
import IntervalTree from "node-interval-tree"
|
||||||
import debounce from "lodash/debounce"
|
import debounce from "lodash/debounce"
|
||||||
import isUndefined from "lodash/isUndefined"
|
import isUndefined from "lodash/isUndefined"
|
||||||
|
import { tippy } from "vue-tippy"
|
||||||
|
import {
|
||||||
|
currentEnvironment$,
|
||||||
|
getCurrentEnvironment,
|
||||||
|
} from "~/newstore/environments"
|
||||||
|
import { useReadonlyStream } from "~/helpers/utils/composables"
|
||||||
|
|
||||||
const tagsToReplace = {
|
const tagsToReplace = {
|
||||||
"&": "&",
|
"&": "&",
|
||||||
@@ -20,12 +38,30 @@ const tagsToReplace = {
|
|||||||
">": ">",
|
">": ">",
|
||||||
}
|
}
|
||||||
|
|
||||||
export default {
|
export default defineComponent({
|
||||||
props: {
|
props: {
|
||||||
value: {
|
value: {
|
||||||
type: String,
|
type: String,
|
||||||
default: "",
|
default: "",
|
||||||
},
|
},
|
||||||
|
placeholder: {
|
||||||
|
type: String,
|
||||||
|
default: "",
|
||||||
|
},
|
||||||
|
styles: {
|
||||||
|
type: String,
|
||||||
|
default: "",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
setup() {
|
||||||
|
const currentEnvironment = useReadonlyStream(
|
||||||
|
currentEnvironment$,
|
||||||
|
getCurrentEnvironment()
|
||||||
|
)
|
||||||
|
|
||||||
|
return {
|
||||||
|
currentEnvironment,
|
||||||
|
}
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
@@ -35,7 +71,8 @@ export default {
|
|||||||
highlight: [
|
highlight: [
|
||||||
{
|
{
|
||||||
text: /(<<\w+>>)/g,
|
text: /(<<\w+>>)/g,
|
||||||
style: "VAR",
|
style:
|
||||||
|
"text-white cursor-help rounded px-1 focus:outline-none mx-0.5",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
highlightEnabled: true,
|
highlightEnabled: true,
|
||||||
@@ -45,7 +82,11 @@ export default {
|
|||||||
fireOnEnabled: true,
|
fireOnEnabled: true,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
watch: {
|
watch: {
|
||||||
|
currentEnvironment() {
|
||||||
|
this.processHighlights()
|
||||||
|
},
|
||||||
highlightStyle() {
|
highlightStyle() {
|
||||||
this.processHighlights()
|
this.processHighlights()
|
||||||
},
|
},
|
||||||
@@ -70,6 +111,7 @@ export default {
|
|||||||
this.restoreSelection(this.$refs.editor, selection)
|
this.restoreSelection(this.$refs.editor, selection)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
mounted() {
|
mounted() {
|
||||||
if (this.fireOnEnabled)
|
if (this.fireOnEnabled)
|
||||||
this.$refs.editor.addEventListener(this.fireOn, this.handleChange)
|
this.$refs.editor.addEventListener(this.fireOn, this.handleChange)
|
||||||
@@ -155,14 +197,21 @@ export default {
|
|||||||
result += this.safe_tags_replace(
|
result += this.safe_tags_replace(
|
||||||
this.internalValue.substring(startingPosition, position.start)
|
this.internalValue.substring(startingPosition, position.start)
|
||||||
)
|
)
|
||||||
result +=
|
const envVar = this.internalValue
|
||||||
"<span class='" +
|
.substring(position.start, position.end + 1)
|
||||||
highlightPositions[k].style +
|
.slice(2, -2)
|
||||||
"'>" +
|
result += `<span class="${highlightPositions[k].style} ${
|
||||||
this.safe_tags_replace(
|
this.currentEnvironment.variables.find((k) => k.key === envVar)
|
||||||
|
?.value === undefined
|
||||||
|
? "bg-red-500"
|
||||||
|
: "bg-accentDark"
|
||||||
|
}" v-tippy data-tippy-content="environment: ${
|
||||||
|
this.currentEnvironment.name
|
||||||
|
} • value: ${
|
||||||
|
this.currentEnvironment.variables.find((k) => k.key === envVar)?.value
|
||||||
|
}">${this.safe_tags_replace(
|
||||||
this.internalValue.substring(position.start, position.end + 1)
|
this.internalValue.substring(position.start, position.end + 1)
|
||||||
) +
|
)}</span>`
|
||||||
"</span>"
|
|
||||||
startingPosition = position.end + 1
|
startingPosition = position.end + 1
|
||||||
}
|
}
|
||||||
if (startingPosition < this.internalValue.length)
|
if (startingPosition < this.internalValue.length)
|
||||||
@@ -177,8 +226,32 @@ export default {
|
|||||||
result += " "
|
result += " "
|
||||||
}
|
}
|
||||||
this.htmlOutput = result
|
this.htmlOutput = result
|
||||||
|
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.renderTippy()
|
||||||
|
})
|
||||||
|
|
||||||
this.$emit("input", this.internalValue)
|
this.$emit("input", this.internalValue)
|
||||||
},
|
},
|
||||||
|
renderTippy() {
|
||||||
|
const tippable = document.querySelectorAll("[v-tippy]")
|
||||||
|
tippable.forEach((t) => {
|
||||||
|
tippy(t, {
|
||||||
|
content: t.dataset["tippy-content"],
|
||||||
|
theme: "tooltip",
|
||||||
|
popperOptions: {
|
||||||
|
modifiers: {
|
||||||
|
preventOverflow: {
|
||||||
|
enabled: false,
|
||||||
|
},
|
||||||
|
hide: {
|
||||||
|
enabled: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
})
|
||||||
|
},
|
||||||
insertRange(start, end, highlightObj, intervalTree) {
|
insertRange(start, end, highlightObj, intervalTree) {
|
||||||
const overlap = intervalTree.search(start, end)
|
const overlap = intervalTree.search(start, end)
|
||||||
const maxLengthOverlap = overlap.reduce((max, o) => {
|
const maxLengthOverlap = overlap.reduce((max, o) => {
|
||||||
@@ -386,25 +459,37 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss" scoped>
|
||||||
.VAR {
|
[contenteditable="true"] {
|
||||||
@apply font-bold;
|
&:empty {
|
||||||
@apply text-accent;
|
line-height: 1.9;
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
@apply text-secondary;
|
||||||
|
@apply opacity-75;
|
||||||
|
@apply pointer-events-none;
|
||||||
|
|
||||||
|
content: attr(placeholder);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.url-field-container {
|
.url-field-container {
|
||||||
@apply inline-grid;
|
@apply inline-grid;
|
||||||
|
@apply w-full;
|
||||||
}
|
}
|
||||||
|
|
||||||
.url-field {
|
.url-field {
|
||||||
@apply border-dashed border-divider;
|
@apply flex;
|
||||||
|
@apply items-center;
|
||||||
|
@apply justify-items-start;
|
||||||
@apply whitespace-nowrap;
|
@apply whitespace-nowrap;
|
||||||
@apply overflow-x-auto;
|
@apply overflow-x-auto;
|
||||||
|
@apply overflow-y-hidden;
|
||||||
@apply resize-none;
|
@apply resize-none;
|
||||||
@apply md:border-l;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.url-field::-webkit-scrollbar {
|
.url-field::-webkit-scrollbar {
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user